Coverage Report

Created: 2026-05-16 09:25

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/src/libreoffice/vcl/source/app/IconThemeInfo.cxx
Line
Count
Source
1
/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2
/*
3
 * This file is part of the LibreOffice project.
4
 *
5
 * This Source Code Form is subject to the terms of the Mozilla Public
6
 * License, v. 2.0. If a copy of the MPL was not distributed with this
7
 * file, You can obtain one at http://mozilla.org/MPL/2.0/.
8
 */
9
10
#include <vcl/IconThemeInfo.hxx>
11
#include <rtl/character.hxx>
12
#include <tools/gen.hxx>
13
14
#include <stdexcept>
15
#include <algorithm>
16
17
// constants for theme ids and display names. (The theme id for high contrast is used
18
// outside of this class and hence made public in IconThemeInfo.)
19
20
namespace {
21
22
constexpr OUStringLiteral HELPIMG_FAKE_THEME(u"helpimg");
23
24
OUString
25
filename_from_url(std::u16string_view url)
26
0
{
27
0
    size_t slashPosition = url.rfind( '/' );
28
0
    if (slashPosition == std::u16string_view::npos) {
29
0
        return OUString();
30
0
    }
31
0
    OUString filename( url.substr( slashPosition+1 ) );
32
0
    return filename;
33
0
}
34
35
} // end anonymous namespace
36
37
namespace vcl {
38
39
const sal_Unicode ICON_THEME_PACKAGE_PREFIX[] = u"images_";
40
41
const sal_Unicode EXTENSION_FOR_ICON_PACKAGES[] = u".zip";
42
43
IconThemeInfo::IconThemeInfo()
44
0
{
45
0
}
46
47
IconThemeInfo::IconThemeInfo(const OUString& urlToFile)
48
0
: mUrlToFile(urlToFile)
49
0
{
50
0
    OUString filename = filename_from_url(urlToFile);
51
0
    if (filename.isEmpty()) {
52
0
        throw std::runtime_error("invalid URL passed to IconThemeInfo()");
53
0
    }
54
55
0
    mThemeId = FileNameToThemeId(filename);
56
0
    mDisplayName = ThemeIdToDisplayName(mThemeId);
57
58
0
}
59
60
/*static*/ Size
61
IconThemeInfo::SizeByThemeName(std::u16string_view themeName)
62
0
{
63
0
   if (themeName == u"galaxy") { //kept for compiler because of unused parameter 'themeName'
64
0
     return Size( 26, 26 );
65
0
   }
66
0
   else {
67
0
     return Size( 24, 24 );
68
0
   }
69
0
}
70
71
/*static*/ bool
72
IconThemeInfo::UrlCanBeParsed(std::u16string_view url)
73
0
{
74
0
    OUString fname = filename_from_url(url);
75
0
    if (fname.isEmpty()) {
76
0
        return false;
77
0
    }
78
79
0
    if (!fname.startsWithIgnoreAsciiCase(ICON_THEME_PACKAGE_PREFIX)) {
80
0
        return false;
81
0
    }
82
83
0
    if (!fname.endsWithIgnoreAsciiCase(EXTENSION_FOR_ICON_PACKAGES)) {
84
0
        return false;
85
0
    }
86
87
0
    if (fname.indexOf(HELPIMG_FAKE_THEME) != -1 ) {
88
0
        return false;
89
0
    }
90
91
0
    return true;
92
0
}
93
94
/*static*/ OUString
95
IconThemeInfo::FileNameToThemeId(std::u16string_view filename)
96
0
{
97
0
    OUString r;
98
0
    size_t positionOfLastDot = filename.rfind(EXTENSION_FOR_ICON_PACKAGES);
99
0
    if (positionOfLastDot == std::u16string_view::npos) { // means index not found
100
0
        throw std::runtime_error("IconThemeInfo::FileNameToThemeId() called with invalid filename.");
101
0
    }
102
0
    size_t positionOfFirstUnderscore = filename.find(ICON_THEME_PACKAGE_PREFIX);
103
0
    if (positionOfFirstUnderscore == std::u16string_view::npos) { // means index not found. Use the whole name instead
104
0
        throw std::runtime_error("IconThemeInfo::FileNameToThemeId() called with invalid filename.");
105
0
    }
106
0
    positionOfFirstUnderscore += RTL_CONSTASCII_LENGTH(ICON_THEME_PACKAGE_PREFIX);
107
0
    r = filename.substr(positionOfFirstUnderscore, positionOfLastDot - positionOfFirstUnderscore);
108
0
    return r;
109
0
}
110
111
/*static*/ OUString
112
IconThemeInfo::ThemeIdToDisplayName(const OUString& themeId)
113
0
{
114
0
    if (themeId.isEmpty()) {
115
0
        throw std::runtime_error("IconThemeInfo::ThemeIdToDisplayName() called with invalid id.");
116
0
    }
117
118
    // Strip _svg and _dark filename "extensions"
119
0
    OUString aDisplayName = themeId;
120
121
0
    bool bIsSvg = aDisplayName.endsWith("_svg", &aDisplayName);
122
0
    bool bIsDark = aDisplayName.endsWith("_dark", &aDisplayName);
123
0
    if (!bIsSvg && bIsDark)
124
0
        bIsSvg = aDisplayName.endsWith("_svg", &aDisplayName);
125
126
    // make the first letter uppercase
127
0
    sal_Unicode firstLetter = aDisplayName[0];
128
0
    if (rtl::isAsciiLowerCase(firstLetter))
129
0
    {
130
0
        aDisplayName = OUStringChar(sal_Unicode(rtl::toAsciiUpperCase(firstLetter))) + aDisplayName.subView(1);
131
0
    }
132
133
    // replacing underscores with spaces of multi words pack name.
134
0
    aDisplayName = aDisplayName.replace('_', ' ');
135
136
0
    if (bIsSvg && bIsDark)
137
0
        aDisplayName += " (SVG + dark)";
138
0
    else if (bIsSvg)
139
0
        aDisplayName += " (SVG)";
140
0
    else if (bIsDark)
141
0
        aDisplayName += " (dark)";
142
143
0
    return aDisplayName;
144
0
}
145
146
namespace
147
{
148
    class SameTheme
149
    {
150
    private:
151
        const OUString& m_rThemeId;
152
    public:
153
0
        explicit SameTheme(const OUString &rThemeId) : m_rThemeId(rThemeId) {}
154
        bool operator()(const vcl::IconThemeInfo &rInfo)
155
0
        {
156
0
            return m_rThemeId == rInfo.GetThemeId();
157
0
        }
158
    };
159
}
160
161
/*static*/ const vcl::IconThemeInfo&
162
IconThemeInfo::FindIconThemeById(const std::vector<vcl::IconThemeInfo>& themes, const OUString& themeId)
163
0
{
164
0
    std::vector<vcl::IconThemeInfo>::const_iterator it = std::find_if(themes.begin(), themes.end(),
165
0
               SameTheme(themeId));
166
0
    if (it == themes.end())
167
0
    {
168
0
        throw std::runtime_error("Could not find theme id in theme vector.");
169
0
    }
170
0
    return *it;
171
0
}
172
173
/*static*/ bool
174
IconThemeInfo::IconThemeIsInVector(const std::vector<vcl::IconThemeInfo>& themes, const OUString& themeId)
175
0
{
176
0
    return std::any_of(themes.begin(), themes.end(), SameTheme(themeId));
177
0
}
178
179
} // end namespace vcl
180
181
/* vim:set shiftwidth=4 softtabstop=4 expandtab: */