/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: */ |