summaryrefslogtreecommitdiffstats
path: root/src/gui/image/qiconloader.cpp
diff options
context:
space:
mode:
authorAlexander Volkov <a.volkov@rusbitech.ru>2017-12-20 16:03:42 +0300
committerAlexander Volkov <a.volkov@rusbitech.ru>2018-01-15 10:12:22 +0000
commit85aa0fd041fbaa258f089d86f227311e53f6206a (patch)
treebafaed0633d4034232af4a9d725d009e0c2a7155 /src/gui/image/qiconloader.cpp
parent537af273026eaf0a18d2151ad6928b7797d7955b (diff)
Introduce QIcon::fallbackSearchPaths()
... that will be used if an icon can't be found in the current theme. The Icon Theme Specification https://standards.freedesktop.org/icon-theme-spec/latest/ar01s05.html states that unthemed icons must be searched in the base directories, i.e. /usr/share/icons, ... But in practice unthemed icons are installed into /usr/share/pixmaps and this dir is not used as a base dir for icon themes. So it's better to explicitly specify fallback dirs to avoid needless access to the filesystem. Also some KDE application install their own unthemed icons (into /usr/share/<appname>/pics), that can't be found by QIconLoader. With this change it would be possible for them to specify dirs with unthemed icons and thus be displayed correctly in non-KDE environments. [ChangeLog][QtGui][QIcon] Added fallbackSearchPaths() that will be used to find icons missing in the current icon theme. Change-Id: I0dc55ba958b29356a3b0a2123d6b8faa24d4c91e Task-number: QTBUG-33123 Reviewed-by: Shawn Rutledge <shawn.rutledge@qt.io> Reviewed-by: Olivier Goffart (Woboq GmbH) <ogoffart@woboq.com>
Diffstat (limited to 'src/gui/image/qiconloader.cpp')
-rw-r--r--src/gui/image/qiconloader.cpp88
1 files changed, 83 insertions, 5 deletions
diff --git a/src/gui/image/qiconloader.cpp b/src/gui/image/qiconloader.cpp
index 3cb6f46bd6..1ea4f1340b 100644
--- a/src/gui/image/qiconloader.cpp
+++ b/src/gui/image/qiconloader.cpp
@@ -95,6 +95,16 @@ static inline QStringList systemIconSearchPaths()
return QStringList();
}
+static inline QStringList systemFallbackSearchPaths()
+{
+ if (const QPlatformTheme *theme = QGuiApplicationPrivate::platformTheme()) {
+ const QVariant themeHint = theme->themeHint(QPlatformTheme::IconFallbackSearchPaths);
+ if (themeHint.isValid())
+ return themeHint.toStringList();
+ }
+ return QStringList();
+}
+
extern QFactoryLoader *qt_iconEngineFactoryLoader(); // qicon.cpp
void QIconLoader::ensureInitialized()
@@ -158,6 +168,20 @@ QStringList QIconLoader::themeSearchPaths() const
return m_iconDirs;
}
+void QIconLoader::setFallbackSearchPaths(const QStringList &searchPaths)
+{
+ m_fallbackDirs = searchPaths;
+ invalidateKey();
+}
+
+QStringList QIconLoader::fallbackSearchPaths() const
+{
+ if (m_fallbackDirs.isEmpty()) {
+ m_fallbackDirs = systemFallbackSearchPaths();
+ }
+ return m_fallbackDirs;
+}
+
/*!
\internal
Helper class that reads and looks up into the icon-theme.cache generated with
@@ -481,11 +505,54 @@ QThemeIconInfo QIconLoader::findIconHelper(const QString &themeName,
return info;
}
+QThemeIconInfo QIconLoader::lookupFallbackIcon(const QString &iconName) const
+{
+ QThemeIconInfo info;
+
+ const QString pngIconName = iconName + QLatin1String(".png");
+ const QString xpmIconName = iconName + QLatin1String(".xpm");
+ const QString svgIconName = iconName + QLatin1String(".svg");
+
+ const auto searchPaths = QIcon::fallbackSearchPaths();
+ for (const QString &iconDir: searchPaths) {
+ QDir currentDir(iconDir);
+ if (currentDir.exists(pngIconName)) {
+ PixmapEntry *iconEntry = new PixmapEntry;
+ iconEntry->dir.type = QIconDirInfo::Fallback;
+ iconEntry->filename = currentDir.filePath(pngIconName);
+ info.entries.append(iconEntry);
+ break;
+ } else if (currentDir.exists(xpmIconName)) {
+ PixmapEntry *iconEntry = new PixmapEntry;
+ iconEntry->dir.type = QIconDirInfo::Fallback;
+ iconEntry->filename = currentDir.filePath(xpmIconName);
+ info.entries.append(iconEntry);
+ break;
+ } else if (m_supportsSvg &&
+ currentDir.exists(svgIconName)) {
+ ScalableEntry *iconEntry = new ScalableEntry;
+ iconEntry->dir.type = QIconDirInfo::Fallback;
+ iconEntry->filename = currentDir.filePath(svgIconName);
+ info.entries.append(iconEntry);
+ break;
+ }
+ }
+
+ if (!info.entries.isEmpty())
+ info.iconName = iconName;
+
+ return info;
+}
+
QThemeIconInfo QIconLoader::loadIcon(const QString &name) const
{
if (!themeName().isEmpty()) {
QStringList visited;
- return findIconHelper(themeName(), name, visited);
+ const QThemeIconInfo iconInfo = findIconHelper(themeName(), name, visited);
+ if (!iconInfo.entries.isEmpty())
+ return iconInfo;
+
+ return lookupFallbackIcon(name);
}
return QThemeIconInfo();
@@ -573,6 +640,8 @@ static bool directoryMatchesSize(const QIconDirInfo &dir, int iconsize, int icon
} else if (dir.type == QIconDirInfo::Threshold) {
return iconsize >= dir.size - dir.threshold &&
iconsize <= dir.size + dir.threshold;
+ } else if (dir.type == QIconDirInfo::Fallback) {
+ return true;
}
Q_ASSERT(1); // Not a valid value
@@ -603,6 +672,8 @@ static int directorySizeDistance(const QIconDirInfo &dir, int iconsize, int icon
else if (scaledIconSize > (dir.size + dir.threshold) * dir.scale)
return scaledIconSize - dir.maxSize * dir.scale;
else return 0;
+ } else if (dir.type == QIconDirInfo::Fallback) {
+ return 0;
}
Q_ASSERT(1); // Not a valid value
@@ -657,9 +728,11 @@ QSize QIconLoaderEngine::actualSize(const QSize &size, QIcon::Mode mode,
QIconLoaderEngineEntry *entry = entryForSize(m_info, size);
if (entry) {
const QIconDirInfo &dir = entry->dir;
- if (dir.type == QIconDirInfo::Scalable)
+ if (dir.type == QIconDirInfo::Scalable) {
return size;
- else {
+ } else if (dir.type == QIconDirInfo::Fallback) {
+ return QIcon(entry->filename).actualSize(size, mode, state);
+ } else {
int result = qMin<int>(dir.size, qMin(size.width(), size.height()));
return QSize(result, result);
}
@@ -745,8 +818,13 @@ void QIconLoaderEngine::virtual_hook(int id, void *data)
// Gets all sizes from the DirectoryInfo entries
for (int i = 0; i < N; ++i) {
- int size = m_info.entries.at(i)->dir.size;
- sizes.append(QSize(size, size));
+ const QIconLoaderEngineEntry *entry = m_info.entries.at(i);
+ if (entry->dir.type == QIconDirInfo::Fallback) {
+ sizes.append(QIcon(entry->filename).availableSizes());
+ } else {
+ int size = entry->dir.size;
+ sizes.append(QSize(size, size));
+ }
}
arg.sizes.swap(sizes); // commit
}