qiconloader.cpp

Absolute File Name:/home/qt/qt5_coco/qt5/qtbase/src/gui/image/qiconloader.cpp
Source codeSwitch to Preprocessed file
LineSourceCount
1/****************************************************************************-
2**-
3** Copyright (C) 2016 The Qt Company Ltd.-
4** Contact: https://www.qt.io/licensing/-
5**-
6** This file is part of the QtGui module of the Qt Toolkit.-
7**-
8** $QT_BEGIN_LICENSE:LGPL$-
9** Commercial License Usage-
10** Licensees holding valid commercial Qt licenses may use this file in-
11** accordance with the commercial license agreement provided with the-
12** Software or, alternatively, in accordance with the terms contained in-
13** a written agreement between you and The Qt Company. For licensing terms-
14** and conditions see https://www.qt.io/terms-conditions. For further-
15** information use the contact form at https://www.qt.io/contact-us.-
16**-
17** GNU Lesser General Public License Usage-
18** Alternatively, this file may be used under the terms of the GNU Lesser-
19** General Public License version 3 as published by the Free Software-
20** Foundation and appearing in the file LICENSE.LGPL3 included in the-
21** packaging of this file. Please review the following information to-
22** ensure the GNU Lesser General Public License version 3 requirements-
23** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.-
24**-
25** GNU General Public License Usage-
26** Alternatively, this file may be used under the terms of the GNU-
27** General Public License version 2.0 or (at your option) the GNU General-
28** Public license version 3 or any later version approved by the KDE Free-
29** Qt Foundation. The licenses are as published by the Free Software-
30** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3-
31** included in the packaging of this file. Please review the following-
32** information to ensure the GNU General Public License requirements will-
33** be met: https://www.gnu.org/licenses/gpl-2.0.html and-
34** https://www.gnu.org/licenses/gpl-3.0.html.-
35**-
36** $QT_END_LICENSE$-
37**-
38****************************************************************************/-
39#ifndef QT_NO_ICON-
40#include <private/qiconloader_p.h>-
41-
42#include <private/qguiapplication_p.h>-
43#include <private/qicon_p.h>-
44-
45#include <QtGui/QIconEnginePlugin>-
46#include <QtGui/QPixmapCache>-
47#include <qpa/qplatformtheme.h>-
48#include <QtGui/QIconEngine>-
49#include <QtGui/QPalette>-
50#include <QtCore/QList>-
51#include <QtCore/QDir>-
52#include <QtCore/QSettings>-
53#include <QtGui/QPainter>-
54-
55#include <private/qhexstring_p.h>-
56-
57QT_BEGIN_NAMESPACE-
58-
59Q_GLOBAL_STATIC(QIconLoader, iconLoaderInstance)
never executed: end of block
never executed: guard.store(QtGlobalStatic::Destroyed);
never executed: return &holder.value;
guard.load() =...c::InitializedDescription
TRUEnever evaluated
FALSEnever evaluated
0
60-
61/* Theme to use in last resort, if the theme does not have the icon, neither the parents */-
62static QString fallbackTheme()-
63{-
64 if (const QPlatformTheme *theme = QGuiApplicationPrivate::platformTheme()) {
const QPlatfor...latformTheme()Description
TRUEnever evaluated
FALSEnever evaluated
0
65 const QVariant themeHint = theme->themeHint(QPlatformTheme::SystemIconFallbackThemeName);-
66 if (themeHint.isValid())
themeHint.isValid()Description
TRUEnever evaluated
FALSEnever evaluated
0
67 return themeHint.toString();
never executed: return themeHint.toString();
0
68 }
never executed: end of block
0
69 return QString();
never executed: return QString();
0
70}-
71-
72QIconLoader::QIconLoader() :-
73 m_themeKey(1), m_supportsSvg(false), m_initialized(false)-
74{-
75}
never executed: end of block
0
76-
77static inline QString systemThemeName()-
78{-
79 if (const QPlatformTheme *theme = QGuiApplicationPrivate::platformTheme()) {
const QPlatfor...latformTheme()Description
TRUEnever evaluated
FALSEnever evaluated
0
80 const QVariant themeHint = theme->themeHint(QPlatformTheme::SystemIconThemeName);-
81 if (themeHint.isValid())
themeHint.isValid()Description
TRUEnever evaluated
FALSEnever evaluated
0
82 return themeHint.toString();
never executed: return themeHint.toString();
0
83 }
never executed: end of block
0
84 return QString();
never executed: return QString();
0
85}-
86-
87static inline QStringList systemIconSearchPaths()-
88{-
89 if (const QPlatformTheme *theme = QGuiApplicationPrivate::platformTheme()) {
const QPlatfor...latformTheme()Description
TRUEnever evaluated
FALSEnever evaluated
0
90 const QVariant themeHint = theme->themeHint(QPlatformTheme::IconThemeSearchPaths);-
91 if (themeHint.isValid())
themeHint.isValid()Description
TRUEnever evaluated
FALSEnever evaluated
0
92 return themeHint.toStringList();
never executed: return themeHint.toStringList();
0
93 }
never executed: end of block
0
94 return QStringList();
never executed: return QStringList();
0
95}-
96-
97extern QFactoryLoader *qt_iconEngineFactoryLoader(); // qicon.cpp-
98-
99void QIconLoader::ensureInitialized()-
100{-
101 if (!m_initialized) {
!m_initializedDescription
TRUEnever evaluated
FALSEnever evaluated
0
102 m_initialized = true;-
103-
104 Q_ASSERT(qApp);-
105-
106 m_systemTheme = systemThemeName();-
107-
108 if (m_systemTheme.isEmpty())
m_systemTheme.isEmpty()Description
TRUEnever evaluated
FALSEnever evaluated
0
109 m_systemTheme = fallbackTheme();
never executed: m_systemTheme = fallbackTheme();
0
110 if (qt_iconEngineFactoryLoader()->keyMap().key(QLatin1String("svg"), -1) != -1)
qt_iconEngineF...g"), -1) != -1Description
TRUEnever evaluated
FALSEnever evaluated
0
111 m_supportsSvg = true;
never executed: m_supportsSvg = true;
0
112 }
never executed: end of block
0
113}
never executed: end of block
0
114-
115QIconLoader *QIconLoader::instance()-
116{-
117 iconLoaderInstance()->ensureInitialized();-
118 return iconLoaderInstance();
never executed: return iconLoaderInstance();
0
119}-
120-
121// Queries the system theme and invalidates existing-
122// icons if the theme has changed.-
123void QIconLoader::updateSystemTheme()-
124{-
125 // Only change if this is not explicitly set by the user-
126 if (m_userTheme.isEmpty()) {
m_userTheme.isEmpty()Description
TRUEnever evaluated
FALSEnever evaluated
0
127 QString theme = systemThemeName();-
128 if (theme.isEmpty())
theme.isEmpty()Description
TRUEnever evaluated
FALSEnever evaluated
0
129 theme = fallbackTheme();
never executed: theme = fallbackTheme();
0
130 if (theme != m_systemTheme) {
theme != m_systemThemeDescription
TRUEnever evaluated
FALSEnever evaluated
0
131 m_systemTheme = theme;-
132 invalidateKey();-
133 }
never executed: end of block
0
134 }
never executed: end of block
0
135}
never executed: end of block
0
136-
137void QIconLoader::setThemeName(const QString &themeName)-
138{-
139 m_userTheme = themeName;-
140 invalidateKey();-
141}
never executed: end of block
0
142-
143void QIconLoader::setThemeSearchPath(const QStringList &searchPaths)-
144{-
145 m_iconDirs = searchPaths;-
146 themeList.clear();-
147 invalidateKey();-
148}
never executed: end of block
0
149-
150QStringList QIconLoader::themeSearchPaths() const-
151{-
152 if (m_iconDirs.isEmpty()) {
m_iconDirs.isEmpty()Description
TRUEnever evaluated
FALSEnever evaluated
0
153 m_iconDirs = systemIconSearchPaths();-
154 // Always add resource directory as search path-
155 m_iconDirs.append(QLatin1String(":/icons"));-
156 }
never executed: end of block
0
157 return m_iconDirs;
never executed: return m_iconDirs;
0
158}-
159-
160/*!-
161 \internal-
162 Helper class that reads and looks up into the icon-theme.cache generated with-
163 gtk-update-icon-cache. If at any point we detect a corruption in the file-
164 (because the offsets point at wrong locations for example), the reader-
165 is marked as invalid.-
166*/-
167class QIconCacheGtkReader-
168{-
169public:-
170 explicit QIconCacheGtkReader(const QString &themeDir);-
171 QVector<const char *> lookup(const QString &);-
172 bool isValid() const { return m_isValid; }
never executed: return m_isValid;
0
173private:-
174 QFile m_file;-
175 const unsigned char *m_data;-
176 quint64 m_size;-
177 bool m_isValid;-
178-
179 quint16 read16(uint offset)-
180 {-
181 if (offset > m_size - 2 || (offset & 0x1)) {
offset > m_size - 2Description
TRUEnever evaluated
FALSEnever evaluated
(offset & 0x1)Description
TRUEnever evaluated
FALSEnever evaluated
0
182 m_isValid = false;-
183 return 0;
never executed: return 0;
0
184 }-
185 return m_data[offset+1] | m_data[offset] << 8;
never executed: return m_data[offset+1] | m_data[offset] << 8;
0
186 }-
187 quint32 read32(uint offset)-
188 {-
189 if (offset > m_size - 4 || (offset & 0x3)) {
offset > m_size - 4Description
TRUEnever evaluated
FALSEnever evaluated
(offset & 0x3)Description
TRUEnever evaluated
FALSEnever evaluated
0
190 m_isValid = false;-
191 return 0;
never executed: return 0;
0
192 }-
193 return m_data[offset+3] | m_data[offset+2] << 8
never executed: return m_data[offset+3] | m_data[offset+2] << 8 | m_data[offset+1] << 16 | m_data[offset] << 24;
0
194 | m_data[offset+1] << 16 | m_data[offset] << 24;
never executed: return m_data[offset+3] | m_data[offset+2] << 8 | m_data[offset+1] << 16 | m_data[offset] << 24;
0
195 }-
196};-
197-
198-
199QIconCacheGtkReader::QIconCacheGtkReader(const QString &dirName)-
200 : m_isValid(false)-
201{-
202 QFileInfo info(dirName + QLatin1Literal("/icon-theme.cache"));-
203 if (!info.exists() || info.lastModified() < QFileInfo(dirName).lastModified())
!info.exists()Description
TRUEnever evaluated
FALSEnever evaluated
info.lastModif...lastModified()Description
TRUEnever evaluated
FALSEnever evaluated
0
204 return;
never executed: return;
0
205 m_file.setFileName(info.absoluteFilePath());-
206 if (!m_file.open(QFile::ReadOnly))
!m_file.open(QFile::ReadOnly)Description
TRUEnever evaluated
FALSEnever evaluated
0
207 return;
never executed: return;
0
208 m_size = m_file.size();-
209 m_data = m_file.map(0, m_size);-
210 if (!m_data)
!m_dataDescription
TRUEnever evaluated
FALSEnever evaluated
0
211 return;
never executed: return;
0
212 if (read16(0) != 1) // VERSION_MAJOR
read16(0) != 1Description
TRUEnever evaluated
FALSEnever evaluated
0
213 return;
never executed: return;
0
214-
215 m_isValid = true;-
216-
217 // Check that all the directories are older than the cache-
218 auto lastModified = info.lastModified();-
219 quint32 dirListOffset = read32(8);-
220 quint32 dirListLen = read32(dirListOffset);-
221 for (uint i = 0; i < dirListLen; ++i) {
i < dirListLenDescription
TRUEnever evaluated
FALSEnever evaluated
0
222 quint32 offset = read32(dirListOffset + 4 + 4 * i);-
223 if (!m_isValid || offset >= m_size || lastModified < QFileInfo(dirName + QLatin1Char('/')
!m_isValidDescription
TRUEnever evaluated
FALSEnever evaluated
offset >= m_sizeDescription
TRUEnever evaluated
FALSEnever evaluated
lastModified <...lastModified()Description
TRUEnever evaluated
FALSEnever evaluated
0
224 + QString::fromUtf8(reinterpret_cast<const char*>(m_data + offset))).lastModified()) {
lastModified <...lastModified()Description
TRUEnever evaluated
FALSEnever evaluated
0
225 m_isValid = false;-
226 return;
never executed: return;
0
227 }-
228 }
never executed: end of block
0
229}
never executed: end of block
0
230-
231static quint32 icon_name_hash(const char *p)-
232{-
233 quint32 h = static_cast<signed char>(*p);-
234 for (p += 1; *p != '\0'; p++)
*p != '\0'Description
TRUEnever evaluated
FALSEnever evaluated
0
235 h = (h << 5) - h + *p;
never executed: h = (h << 5) - h + *p;
0
236 return h;
never executed: return h;
0
237}-
238-
239/*! \internal-
240 lookup the icon name and return the list of subdirectories in which an icon-
241 with this name is present. The char* are pointers to the mapped data.-
242 For example, this would return { "32x32/apps", "24x24/apps" , ... }-
243 */-
244QVector<const char *> QIconCacheGtkReader::lookup(const QString &name)-
245{-
246 QVector<const char *> ret;-
247 if (!isValid())
!isValid()Description
TRUEnever evaluated
FALSEnever evaluated
0
248 return ret;
never executed: return ret;
0
249-
250 QByteArray nameUtf8 = name.toUtf8();-
251 quint32 hash = icon_name_hash(nameUtf8);-
252-
253 quint32 hashOffset = read32(4);-
254 quint32 hashBucketCount = read32(hashOffset);-
255-
256 if (!isValid() || hashBucketCount == 0) {
!isValid()Description
TRUEnever evaluated
FALSEnever evaluated
hashBucketCount == 0Description
TRUEnever evaluated
FALSEnever evaluated
0
257 m_isValid = false;-
258 return ret;
never executed: return ret;
0
259 }-
260-
261 quint32 bucketIndex = hash % hashBucketCount;-
262 quint32 bucketOffset = read32(hashOffset + 4 + bucketIndex * 4);-
263 while (bucketOffset > 0 && bucketOffset <= m_size - 12) {
bucketOffset > 0Description
TRUEnever evaluated
FALSEnever evaluated
bucketOffset <= m_size - 12Description
TRUEnever evaluated
FALSEnever evaluated
0
264 quint32 nameOff = read32(bucketOffset + 4);-
265 if (nameOff < m_size && strcmp(reinterpret_cast<const char*>(m_data + nameOff), nameUtf8) == 0) {
nameOff < m_sizeDescription
TRUEnever evaluated
FALSEnever evaluated
strcmp(reinter...nameUtf8) == 0Description
TRUEnever evaluated
FALSEnever evaluated
0
266 quint32 dirListOffset = read32(8);-
267 quint32 dirListLen = read32(dirListOffset);-
268-
269 quint32 listOffset = read32(bucketOffset+8);-
270 quint32 listLen = read32(listOffset);-
271-
272 if (!m_isValid || listOffset + 4 + 8 * listLen > m_size) {
!m_isValidDescription
TRUEnever evaluated
FALSEnever evaluated
listOffset + 4...stLen > m_sizeDescription
TRUEnever evaluated
FALSEnever evaluated
0
273 m_isValid = false;-
274 return ret;
never executed: return ret;
0
275 }-
276-
277 ret.reserve(listLen);-
278 for (uint j = 0; j < listLen && m_isValid; ++j) {
j < listLenDescription
TRUEnever evaluated
FALSEnever evaluated
m_isValidDescription
TRUEnever evaluated
FALSEnever evaluated
0
279 quint32 dirIndex = read16(listOffset + 4 + 8 * j);-
280 quint32 o = read32(dirListOffset + 4 + dirIndex*4);-
281 if (!m_isValid || dirIndex >= dirListLen || o >= m_size) {
!m_isValidDescription
TRUEnever evaluated
FALSEnever evaluated
dirIndex >= dirListLenDescription
TRUEnever evaluated
FALSEnever evaluated
o >= m_sizeDescription
TRUEnever evaluated
FALSEnever evaluated
0
282 m_isValid = false;-
283 return ret;
never executed: return ret;
0
284 }-
285 ret.append(reinterpret_cast<const char*>(m_data) + o);-
286 }
never executed: end of block
0
287 return ret;
never executed: return ret;
0
288 }-
289 bucketOffset = read32(bucketOffset);-
290 }
never executed: end of block
0
291 return ret;
never executed: return ret;
0
292}-
293-
294QIconTheme::QIconTheme(const QString &themeName)-
295 : m_valid(false)-
296{-
297 QFile themeIndex;-
298-
299 const QStringList iconDirs = QIcon::themeSearchPaths();-
300 for ( int i = 0 ; i < iconDirs.size() ; ++i) {
i < iconDirs.size()Description
TRUEnever evaluated
FALSEnever evaluated
0
301 QDir iconDir(iconDirs[i]);-
302 QString themeDir = iconDir.path() + QLatin1Char('/') + themeName;-
303 QFileInfo themeDirInfo(themeDir);-
304-
305 if (themeDirInfo.isDir()) {
themeDirInfo.isDir()Description
TRUEnever evaluated
FALSEnever evaluated
0
306 m_contentDirs << themeDir;-
307 m_gtkCaches << QSharedPointer<QIconCacheGtkReader>::create(themeDir);-
308 }
never executed: end of block
0
309-
310 if (!m_valid) {
!m_validDescription
TRUEnever evaluated
FALSEnever evaluated
0
311 themeIndex.setFileName(themeDir + QLatin1String("/index.theme"));-
312 if (themeIndex.exists())
themeIndex.exists()Description
TRUEnever evaluated
FALSEnever evaluated
0
313 m_valid = true;
never executed: m_valid = true;
0
314 }
never executed: end of block
0
315 }
never executed: end of block
0
316#ifndef QT_NO_SETTINGS-
317 if (themeIndex.exists()) {
themeIndex.exists()Description
TRUEnever evaluated
FALSEnever evaluated
0
318 const QSettings indexReader(themeIndex.fileName(), QSettings::IniFormat);-
319 QStringListIterator keyIterator(indexReader.allKeys());-
320 while (keyIterator.hasNext()) {
keyIterator.hasNext()Description
TRUEnever evaluated
FALSEnever evaluated
0
321-
322 const QString key = keyIterator.next();-
323 if (key.endsWith(QLatin1String("/Size"))) {
key.endsWith(Q...ring("/Size"))Description
TRUEnever evaluated
FALSEnever evaluated
0
324 // Note the QSettings ini-format does not accept-
325 // slashes in key names, hence we have to cheat-
326 if (int size = indexReader.value(key).toInt()) {
int size = ind...e(key).toInt()Description
TRUEnever evaluated
FALSEnever evaluated
0
327 QString directoryKey = key.left(key.size() - 5);-
328 QIconDirInfo dirInfo(directoryKey);-
329 dirInfo.size = size;-
330 QString type = indexReader.value(directoryKey +-
331 QLatin1String("/Type")-
332 ).toString();-
333-
334 if (type == QLatin1String("Fixed"))
type == QLatin1String("Fixed")Description
TRUEnever evaluated
FALSEnever evaluated
0
335 dirInfo.type = QIconDirInfo::Fixed;
never executed: dirInfo.type = QIconDirInfo::Fixed;
0
336 else if (type == QLatin1String("Scalable"))
type == QLatin...ng("Scalable")Description
TRUEnever evaluated
FALSEnever evaluated
0
337 dirInfo.type = QIconDirInfo::Scalable;
never executed: dirInfo.type = QIconDirInfo::Scalable;
0
338 else-
339 dirInfo.type = QIconDirInfo::Threshold;
never executed: dirInfo.type = QIconDirInfo::Threshold;
0
340-
341 dirInfo.threshold = indexReader.value(directoryKey +-
342 QLatin1String("/Threshold"),-
343 2).toInt();-
344-
345 dirInfo.minSize = indexReader.value(directoryKey +-
346 QLatin1String("/MinSize"),-
347 size).toInt();-
348-
349 dirInfo.maxSize = indexReader.value(directoryKey +-
350 QLatin1String("/MaxSize"),-
351 size).toInt();-
352 m_keyList.append(dirInfo);-
353 }
never executed: end of block
0
354 }
never executed: end of block
0
355 }
never executed: end of block
0
356-
357 // Parent themes provide fallbacks for missing icons-
358 m_parents = indexReader.value(-
359 QLatin1String("Icon Theme/Inherits")).toStringList();-
360 m_parents.removeAll(QString());-
361-
362 // Ensure a default platform fallback for all themes-
363 if (m_parents.isEmpty()) {
m_parents.isEmpty()Description
TRUEnever evaluated
FALSEnever evaluated
0
364 const QString fallback = fallbackTheme();-
365 if (!fallback.isEmpty())
!fallback.isEmpty()Description
TRUEnever evaluated
FALSEnever evaluated
0
366 m_parents.append(fallback);
never executed: m_parents.append(fallback);
0
367 }
never executed: end of block
0
368-
369 // Ensure that all themes fall back to hicolor-
370 if (!m_parents.contains(QLatin1String("hicolor")))
!m_parents.con...ng("hicolor"))Description
TRUEnever evaluated
FALSEnever evaluated
0
371 m_parents.append(QLatin1String("hicolor"));
never executed: m_parents.append(QLatin1String("hicolor"));
0
372 }
never executed: end of block
0
373#endif //QT_NO_SETTINGS-
374}
never executed: end of block
0
375-
376QThemeIconInfo QIconLoader::findIconHelper(const QString &themeName,-
377 const QString &iconName,-
378 QStringList &visited) const-
379{-
380 QThemeIconInfo info;-
381 Q_ASSERT(!themeName.isEmpty());-
382-
383 // Used to protect against potential recursions-
384 visited << themeName;-
385-
386 QIconTheme theme = themeList.value(themeName);-
387 if (!theme.isValid()) {
!theme.isValid()Description
TRUEnever evaluated
FALSEnever evaluated
0
388 theme = QIconTheme(themeName);-
389 if (!theme.isValid())
!theme.isValid()Description
TRUEnever evaluated
FALSEnever evaluated
0
390 theme = QIconTheme(fallbackTheme());
never executed: theme = QIconTheme(fallbackTheme());
0
391-
392 themeList.insert(themeName, theme);-
393 }
never executed: end of block
0
394-
395 const QStringList contentDirs = theme.contentDirs();-
396-
397 QString iconNameFallback = iconName;-
398-
399 // Iterate through all icon's fallbacks in current theme-
400 while (info.entries.isEmpty()) {
info.entries.isEmpty()Description
TRUEnever evaluated
FALSEnever evaluated
0
401 const QString svgIconName = iconNameFallback + QLatin1String(".svg");-
402 const QString pngIconName = iconNameFallback + QLatin1String(".png");-
403-
404 // Add all relevant files-
405 for (int i = 0; i < contentDirs.size(); ++i) {
i < contentDirs.size()Description
TRUEnever evaluated
FALSEnever evaluated
0
406 QVector<QIconDirInfo> subDirs = theme.keyList();-
407-
408 // Try to reduce the amount of subDirs by looking in the GTK+ cache in order to save-
409 // a massive amount of file stat (especially if the icon is not there)-
410 auto cache = theme.m_gtkCaches.at(i);-
411 if (cache->isValid()) {
cache->isValid()Description
TRUEnever evaluated
FALSEnever evaluated
0
412 const auto result = cache->lookup(iconNameFallback);-
413 if (cache->isValid()) {
cache->isValid()Description
TRUEnever evaluated
FALSEnever evaluated
0
414 const QVector<QIconDirInfo> subDirsCopy = subDirs;-
415 subDirs.clear();-
416 subDirs.reserve(result.count());-
417 for (const char *s : result) {-
418 QString path = QString::fromUtf8(s);-
419 auto it = std::find_if(subDirsCopy.cbegin(), subDirsCopy.cend(),-
420 [&](const QIconDirInfo &info) {-
421 return info.path == path; } );
never executed: return info.path == path;
0
422 if (it != subDirsCopy.cend()) {
it != subDirsCopy.cend()Description
TRUEnever evaluated
FALSEnever evaluated
0
423 subDirs.append(*it);-
424 }
never executed: end of block
0
425 }
never executed: end of block
0
426 }
never executed: end of block
0
427 }
never executed: end of block
0
428-
429 QString contentDir = contentDirs.at(i) + QLatin1Char('/');-
430 for (int j = 0; j < subDirs.size() ; ++j) {
j < subDirs.size()Description
TRUEnever evaluated
FALSEnever evaluated
0
431 const QIconDirInfo &dirInfo = subDirs.at(j);-
432 QString subdir = dirInfo.path;-
433 QDir currentDir(contentDir + subdir);-
434 if (currentDir.exists(pngIconName)) {
currentDir.exists(pngIconName)Description
TRUEnever evaluated
FALSEnever evaluated
0
435 PixmapEntry *iconEntry = new PixmapEntry;-
436 iconEntry->dir = dirInfo;-
437 iconEntry->filename = currentDir.filePath(pngIconName);-
438 // Notice we ensure that pixmap entries always come before-
439 // scalable to preserve search order afterwards-
440 info.entries.prepend(iconEntry);-
441 } else if (m_supportsSvg &&
never executed: end of block
m_supportsSvgDescription
TRUEnever evaluated
FALSEnever evaluated
0
442 currentDir.exists(svgIconName)) {
currentDir.exists(svgIconName)Description
TRUEnever evaluated
FALSEnever evaluated
0
443 ScalableEntry *iconEntry = new ScalableEntry;-
444 iconEntry->dir = dirInfo;-
445 iconEntry->filename = currentDir.filePath(svgIconName);-
446 info.entries.append(iconEntry);-
447 }
never executed: end of block
0
448 }
never executed: end of block
0
449 }
never executed: end of block
0
450-
451 if (!info.entries.isEmpty()) {
!info.entries.isEmpty()Description
TRUEnever evaluated
FALSEnever evaluated
0
452 info.iconName = iconNameFallback;-
453 break;
never executed: break;
0
454 }-
455-
456 // If it's possible - find next fallback for the icon-
457 const int indexOfDash = iconNameFallback.lastIndexOf(QLatin1Char('-'));-
458 if (indexOfDash == -1)
indexOfDash == -1Description
TRUEnever evaluated
FALSEnever evaluated
0
459 break;
never executed: break;
0
460-
461 iconNameFallback.truncate(indexOfDash);-
462 }
never executed: end of block
0
463-
464 if (info.entries.isEmpty()) {
info.entries.isEmpty()Description
TRUEnever evaluated
FALSEnever evaluated
0
465 const QStringList parents = theme.parents();-
466 // Search recursively through inherited themes-
467 for (int i = 0 ; i < parents.size() ; ++i) {
i < parents.size()Description
TRUEnever evaluated
FALSEnever evaluated
0
468-
469 const QString parentTheme = parents.at(i).trimmed();-
470-
471 if (!visited.contains(parentTheme)) // guard against recursion
!visited.contains(parentTheme)Description
TRUEnever evaluated
FALSEnever evaluated
0
472 info = findIconHelper(parentTheme, iconName, visited);
never executed: info = findIconHelper(parentTheme, iconName, visited);
0
473-
474 if (!info.entries.isEmpty()) // success
!info.entries.isEmpty()Description
TRUEnever evaluated
FALSEnever evaluated
0
475 break;
never executed: break;
0
476 }
never executed: end of block
0
477 }
never executed: end of block
0
478 return info;
never executed: return info;
0
479}-
480-
481QThemeIconInfo QIconLoader::loadIcon(const QString &name) const-
482{-
483 if (!themeName().isEmpty()) {
!themeName().isEmpty()Description
TRUEnever evaluated
FALSEnever evaluated
0
484 QStringList visited;-
485 return findIconHelper(themeName(), name, visited);
never executed: return findIconHelper(themeName(), name, visited);
0
486 }-
487-
488 return QThemeIconInfo();
never executed: return QThemeIconInfo();
0
489}-
490-
491-
492// -------- Icon Loader Engine -------- //-
493-
494-
495QIconLoaderEngine::QIconLoaderEngine(const QString& iconName)-
496 : m_iconName(iconName), m_key(0)-
497{-
498}
never executed: end of block
0
499-
500QIconLoaderEngine::~QIconLoaderEngine()-
501{-
502 qDeleteAll(m_info.entries);-
503}
never executed: end of block
0
504-
505QIconLoaderEngine::QIconLoaderEngine(const QIconLoaderEngine &other)-
506 : QIconEngine(other),-
507 m_iconName(other.m_iconName),-
508 m_key(0)-
509{-
510}
never executed: end of block
0
511-
512QIconEngine *QIconLoaderEngine::clone() const-
513{-
514 return new QIconLoaderEngine(*this);
never executed: return new QIconLoaderEngine(*this);
0
515}-
516-
517bool QIconLoaderEngine::read(QDataStream &in) {-
518 in >> m_iconName;-
519 return true;
never executed: return true;
0
520}-
521-
522bool QIconLoaderEngine::write(QDataStream &out) const-
523{-
524 out << m_iconName;-
525 return true;
never executed: return true;
0
526}-
527-
528bool QIconLoaderEngine::hasIcon() const-
529{-
530 return !(m_info.entries.isEmpty());
never executed: return !(m_info.entries.isEmpty());
0
531}-
532-
533// Lazily load the icon-
534void QIconLoaderEngine::ensureLoaded()-
535{-
536 if (!(QIconLoader::instance()->themeKey() == m_key)) {
!(QIconLoader:...ey() == m_key)Description
TRUEnever evaluated
FALSEnever evaluated
0
537 qDeleteAll(m_info.entries);-
538 m_info.entries.clear();-
539 m_info.iconName.clear();-
540-
541 Q_ASSERT(m_info.entries.size() == 0);-
542 m_info = QIconLoader::instance()->loadIcon(m_iconName);-
543 m_key = QIconLoader::instance()->themeKey();-
544 }
never executed: end of block
0
545}
never executed: end of block
0
546-
547void QIconLoaderEngine::paint(QPainter *painter, const QRect &rect,-
548 QIcon::Mode mode, QIcon::State state)-
549{-
550 QSize pixmapSize = rect.size();-
551 painter->drawPixmap(rect, pixmap(pixmapSize, mode, state));-
552}
never executed: end of block
0
553-
554/*-
555 * This algorithm is defined by the freedesktop spec:-
556 * http://standards.freedesktop.org/icon-theme-spec/icon-theme-spec-latest.html-
557 */-
558static bool directoryMatchesSize(const QIconDirInfo &dir, int iconsize)-
559{-
560 if (dir.type == QIconDirInfo::Fixed) {
dir.type == QI...DirInfo::FixedDescription
TRUEnever evaluated
FALSEnever evaluated
0
561 return dir.size == iconsize;
never executed: return dir.size == iconsize;
0
562-
563 } else if (dir.type == QIconDirInfo::Scalable) {
dir.type == QI...Info::ScalableDescription
TRUEnever evaluated
FALSEnever evaluated
0
564 return iconsize <= dir.maxSize &&
never executed: return iconsize <= dir.maxSize && iconsize >= dir.minSize;
0
565 iconsize >= dir.minSize;
never executed: return iconsize <= dir.maxSize && iconsize >= dir.minSize;
0
566-
567 } else if (dir.type == QIconDirInfo::Threshold) {
dir.type == QI...nfo::ThresholdDescription
TRUEnever evaluated
FALSEnever evaluated
0
568 return iconsize >= dir.size - dir.threshold &&
never executed: return iconsize >= dir.size - dir.threshold && iconsize <= dir.size + dir.threshold;
0
569 iconsize <= dir.size + dir.threshold;
never executed: return iconsize >= dir.size - dir.threshold && iconsize <= dir.size + dir.threshold;
0
570 }-
571-
572 Q_ASSERT(1); // Not a valid value-
573 return false;
never executed: return false;
0
574}-
575-
576/*-
577 * This algorithm is defined by the freedesktop spec:-
578 * http://standards.freedesktop.org/icon-theme-spec/icon-theme-spec-latest.html-
579 */-
580static int directorySizeDistance(const QIconDirInfo &dir, int iconsize)-
581{-
582 if (dir.type == QIconDirInfo::Fixed) {
dir.type == QI...DirInfo::FixedDescription
TRUEnever evaluated
FALSEnever evaluated
0
583 return qAbs(dir.size - iconsize);
never executed: return qAbs(dir.size - iconsize);
0
584-
585 } else if (dir.type == QIconDirInfo::Scalable) {
dir.type == QI...Info::ScalableDescription
TRUEnever evaluated
FALSEnever evaluated
0
586 if (iconsize < dir.minSize)
iconsize < dir.minSizeDescription
TRUEnever evaluated
FALSEnever evaluated
0
587 return dir.minSize - iconsize;
never executed: return dir.minSize - iconsize;
0
588 else if (iconsize > dir.maxSize)
iconsize > dir.maxSizeDescription
TRUEnever evaluated
FALSEnever evaluated
0
589 return iconsize - dir.maxSize;
never executed: return iconsize - dir.maxSize;
0
590 else-
591 return 0;
never executed: return 0;
0
592-
593 } else if (dir.type == QIconDirInfo::Threshold) {
dir.type == QI...nfo::ThresholdDescription
TRUEnever evaluated
FALSEnever evaluated
0
594 if (iconsize < dir.size - dir.threshold)
iconsize < dir... dir.thresholdDescription
TRUEnever evaluated
FALSEnever evaluated
0
595 return dir.minSize - iconsize;
never executed: return dir.minSize - iconsize;
0
596 else if (iconsize > dir.size + dir.threshold)
iconsize > dir... dir.thresholdDescription
TRUEnever evaluated
FALSEnever evaluated
0
597 return iconsize - dir.maxSize;
never executed: return iconsize - dir.maxSize;
0
598 else return 0;
never executed: return 0;
0
599 }-
600-
601 Q_ASSERT(1); // Not a valid value-
602 return INT_MAX;
never executed: return 2147483647;
0
603}-
604-
605QIconLoaderEngineEntry *QIconLoaderEngine::entryForSize(const QSize &size)-
606{-
607 int iconsize = qMin(size.width(), size.height());-
608-
609 // Note that m_info.entries are sorted so that png-files-
610 // come first-
611-
612 const int numEntries = m_info.entries.size();-
613-
614 // Search for exact matches first-
615 for (int i = 0; i < numEntries; ++i) {
i < numEntriesDescription
TRUEnever evaluated
FALSEnever evaluated
0
616 QIconLoaderEngineEntry *entry = m_info.entries.at(i);-
617 if (directoryMatchesSize(entry->dir, iconsize)) {
directoryMatch...dir, iconsize)Description
TRUEnever evaluated
FALSEnever evaluated
0
618 return entry;
never executed: return entry;
0
619 }-
620 }
never executed: end of block
0
621-
622 // Find the minimum distance icon-
623 int minimalSize = INT_MAX;-
624 QIconLoaderEngineEntry *closestMatch = 0;-
625 for (int i = 0; i < numEntries; ++i) {
i < numEntriesDescription
TRUEnever evaluated
FALSEnever evaluated
0
626 QIconLoaderEngineEntry *entry = m_info.entries.at(i);-
627 int distance = directorySizeDistance(entry->dir, iconsize);-
628 if (distance < minimalSize) {
distance < minimalSizeDescription
TRUEnever evaluated
FALSEnever evaluated
0
629 minimalSize = distance;-
630 closestMatch = entry;-
631 }
never executed: end of block
0
632 }
never executed: end of block
0
633 return closestMatch;
never executed: return closestMatch;
0
634}-
635-
636/*-
637 * Returns the actual icon size. For scalable svg's this is equivalent-
638 * to the requested size. Otherwise the closest match is returned but-
639 * we can never return a bigger size than the requested size.-
640 *-
641 */-
642QSize QIconLoaderEngine::actualSize(const QSize &size, QIcon::Mode mode,-
643 QIcon::State state)-
644{-
645 ensureLoaded();-
646-
647 QIconLoaderEngineEntry *entry = entryForSize(size);-
648 if (entry) {
entryDescription
TRUEnever evaluated
FALSEnever evaluated
0
649 const QIconDirInfo &dir = entry->dir;-
650 if (dir.type == QIconDirInfo::Scalable)
dir.type == QI...Info::ScalableDescription
TRUEnever evaluated
FALSEnever evaluated
0
651 return size;
never executed: return size;
0
652 else {-
653 int result = qMin<int>(dir.size, qMin(size.width(), size.height()));-
654 return QSize(result, result);
never executed: return QSize(result, result);
0
655 }-
656 }-
657 return QIconEngine::actualSize(size, mode, state);
never executed: return QIconEngine::actualSize(size, mode, state);
0
658}-
659-
660QPixmap PixmapEntry::pixmap(const QSize &size, QIcon::Mode mode, QIcon::State state)-
661{-
662 Q_UNUSED(state);-
663-
664 // Ensure that basePixmap is lazily initialized before generating the-
665 // key, otherwise the cache key is not unique-
666 if (basePixmap.isNull())
basePixmap.isNull()Description
TRUEnever evaluated
FALSEnever evaluated
0
667 basePixmap.load(filename);
never executed: basePixmap.load(filename);
0
668-
669 QSize actualSize = basePixmap.size();-
670 if (!actualSize.isNull() && (actualSize.width() > size.width() || actualSize.height() > size.height()))
!actualSize.isNull()Description
TRUEnever evaluated
FALSEnever evaluated
actualSize.wid...> size.width()Description
TRUEnever evaluated
FALSEnever evaluated
actualSize.hei... size.height()Description
TRUEnever evaluated
FALSEnever evaluated
0
671 actualSize.scale(size, Qt::KeepAspectRatio);
never executed: actualSize.scale(size, Qt::KeepAspectRatio);
0
672-
673 QString key = QLatin1String("$qt_theme_")-
674 % HexString<qint64>(basePixmap.cacheKey())-
675 % HexString<int>(mode)-
676 % HexString<qint64>(QGuiApplication::palette().cacheKey())-
677 % HexString<int>(actualSize.width())-
678 % HexString<int>(actualSize.height());-
679-
680 QPixmap cachedPixmap;-
681 if (QPixmapCache::find(key, &cachedPixmap)) {
QPixmapCache::...&cachedPixmap)Description
TRUEnever evaluated
FALSEnever evaluated
0
682 return cachedPixmap;
never executed: return cachedPixmap;
0
683 } else {-
684 if (basePixmap.size() != actualSize)
basePixmap.siz... != actualSizeDescription
TRUEnever evaluated
FALSEnever evaluated
0
685 cachedPixmap = basePixmap.scaled(actualSize, Qt::IgnoreAspectRatio, Qt::SmoothTransformation);
never executed: cachedPixmap = basePixmap.scaled(actualSize, Qt::IgnoreAspectRatio, Qt::SmoothTransformation);
0
686 else-
687 cachedPixmap = basePixmap;
never executed: cachedPixmap = basePixmap;
0
688 if (QGuiApplication *guiApp = qobject_cast<QGuiApplication *>(qApp))
QGuiApplicatio...:instance())))Description
TRUEnever evaluated
FALSEnever evaluated
0
689 cachedPixmap = static_cast<QGuiApplicationPrivate*>(QObjectPrivate::get(guiApp))->applyQIconStyleHelper(mode, cachedPixmap);
never executed: cachedPixmap = static_cast<QGuiApplicationPrivate*>(QObjectPrivate::get(guiApp))->applyQIconStyleHelper(mode, cachedPixmap);
0
690 QPixmapCache::insert(key, cachedPixmap);-
691 }
never executed: end of block
0
692 return cachedPixmap;
never executed: return cachedPixmap;
0
693}-
694-
695QPixmap ScalableEntry::pixmap(const QSize &size, QIcon::Mode mode, QIcon::State state)-
696{-
697 if (svgIcon.isNull())
svgIcon.isNull()Description
TRUEnever evaluated
FALSEnever evaluated
0
698 svgIcon = QIcon(filename);
never executed: svgIcon = QIcon(filename);
0
699-
700 // Simply reuse svg icon engine-
701 return svgIcon.pixmap(size, mode, state);
never executed: return svgIcon.pixmap(size, mode, state);
0
702}-
703-
704QPixmap QIconLoaderEngine::pixmap(const QSize &size, QIcon::Mode mode,-
705 QIcon::State state)-
706{-
707 ensureLoaded();-
708-
709 QIconLoaderEngineEntry *entry = entryForSize(size);-
710 if (entry)
entryDescription
TRUEnever evaluated
FALSEnever evaluated
0
711 return entry->pixmap(size, mode, state);
never executed: return entry->pixmap(size, mode, state);
0
712-
713 return QPixmap();
never executed: return QPixmap();
0
714}-
715-
716QString QIconLoaderEngine::key() const-
717{-
718 return QLatin1String("QIconLoaderEngine");
never executed: return QLatin1String("QIconLoaderEngine");
0
719}-
720-
721void QIconLoaderEngine::virtual_hook(int id, void *data)-
722{-
723 ensureLoaded();-
724-
725 switch (id) {-
726 case QIconEngine::AvailableSizesHook:
never executed: case QIconEngine::AvailableSizesHook:
0
727 {-
728 QIconEngine::AvailableSizesArgument &arg-
729 = *reinterpret_cast<QIconEngine::AvailableSizesArgument*>(data);-
730 const int N = m_info.entries.size();-
731 QList<QSize> sizes;-
732 sizes.reserve(N);-
733-
734 // Gets all sizes from the DirectoryInfo entries-
735 for (int i = 0; i < N; ++i) {
i < NDescription
TRUEnever evaluated
FALSEnever evaluated
0
736 int size = m_info.entries.at(i)->dir.size;-
737 sizes.append(QSize(size, size));-
738 }
never executed: end of block
0
739 arg.sizes.swap(sizes); // commit-
740 }-
741 break;
never executed: break;
0
742 case QIconEngine::IconNameHook:
never executed: case QIconEngine::IconNameHook:
0
743 {-
744 QString &name = *reinterpret_cast<QString*>(data);-
745 name = m_info.iconName;-
746 }-
747 break;
never executed: break;
0
748 case QIconEngine::IsNullHook:
never executed: case QIconEngine::IsNullHook:
0
749 {-
750 *reinterpret_cast<bool*>(data) = m_info.entries.isEmpty();-
751 }-
752 break;
never executed: break;
0
753 default:
never executed: default:
0
754 QIconEngine::virtual_hook(id, data);-
755 }
never executed: end of block
0
756}-
757-
758QT_END_NAMESPACE-
759-
760#endif //QT_NO_ICON-
Source codeSwitch to Preprocessed file

Generated by Squish Coco Non-Commercial 4.3.0-BETA-master-30-08-2018-4cb69e9