summaryrefslogtreecommitdiffstats
path: root/src/gui
diff options
context:
space:
mode:
Diffstat (limited to 'src/gui')
-rw-r--r--src/gui/image/qicon.cpp2
-rw-r--r--src/gui/image/qiconloader.cpp124
-rw-r--r--src/gui/image/qiconloader_p.h20
3 files changed, 89 insertions, 57 deletions
diff --git a/src/gui/image/qicon.cpp b/src/gui/image/qicon.cpp
index d885729cbd..1b99a5d8dc 100644
--- a/src/gui/image/qicon.cpp
+++ b/src/gui/image/qicon.cpp
@@ -1197,7 +1197,7 @@ bool QIcon::hasThemeIcon(const QString &name)
{
QIcon icon = fromTheme(name);
- return !icon.isNull();
+ return icon.name() == name;
}
diff --git a/src/gui/image/qiconloader.cpp b/src/gui/image/qiconloader.cpp
index 06491f1155..4510125816 100644
--- a/src/gui/image/qiconloader.cpp
+++ b/src/gui/image/qiconloader.cpp
@@ -172,11 +172,15 @@ QIconTheme::QIconTheme(const QString &themeName)
for ( int i = 0 ; i < iconDirs.size() ; ++i) {
QDir iconDir(iconDirs[i]);
QString themeDir = iconDir.path() + QLatin1Char('/') + themeName;
- themeIndex.setFileName(themeDir + QLatin1String("/index.theme"));
- if (themeIndex.exists()) {
- m_contentDir = themeDir;
- m_valid = true;
- break;
+ QFileInfo themeDirInfo(themeDir);
+
+ if (themeDirInfo.isDir())
+ m_contentDirs << themeDir;
+
+ if (!m_valid) {
+ themeIndex.setFileName(themeDir + QLatin1String("/index.theme"));
+ if (themeIndex.exists())
+ m_valid = true;
}
}
#ifndef QT_NO_SETTINGS
@@ -239,11 +243,11 @@ QIconTheme::QIconTheme(const QString &themeName)
#endif //QT_NO_SETTINGS
}
-QThemeIconEntries QIconLoader::findIconHelper(const QString &themeName,
- const QString &iconName,
- QStringList &visited) const
+QThemeIconInfo QIconLoader::findIconHelper(const QString &themeName,
+ const QString &iconName,
+ QStringList &visited) const
{
- QThemeIconEntries entries;
+ QThemeIconInfo info;
Q_ASSERT(!themeName.isEmpty());
QPixmap pixmap;
@@ -260,34 +264,54 @@ QThemeIconEntries QIconLoader::findIconHelper(const QString &themeName,
themeList.insert(themeName, theme);
}
- QString contentDir = theme.contentDir() + QLatin1Char('/');
+ const QStringList contentDirs = theme.contentDirs();
const QVector<QIconDirInfo> subDirs = theme.keyList();
- const QString svgext(QLatin1String(".svg"));
- const QString pngext(QLatin1String(".png"));
-
- // Add all relevant files
- for (int i = 0; i < subDirs.size() ; ++i) {
- const QIconDirInfo &dirInfo = subDirs.at(i);
- QString subdir = dirInfo.path;
- QDir currentDir(contentDir + subdir);
- if (currentDir.exists(iconName + pngext)) {
- PixmapEntry *iconEntry = new PixmapEntry;
- iconEntry->dir = dirInfo;
- iconEntry->filename = currentDir.filePath(iconName + pngext);
- // Notice we ensure that pixmap entries always come before
- // scalable to preserve search order afterwards
- entries.prepend(iconEntry);
- } else if (m_supportsSvg &&
- currentDir.exists(iconName + svgext)) {
- ScalableEntry *iconEntry = new ScalableEntry;
- iconEntry->dir = dirInfo;
- iconEntry->filename = currentDir.filePath(iconName + svgext);
- entries.append(iconEntry);
+ QString iconNameFallback = iconName;
+
+ // Iterate through all icon's fallbacks in current theme
+ while (info.entries.isEmpty()) {
+ const QString svgIconName = iconNameFallback + QLatin1String(".svg");
+ const QString pngIconName = iconNameFallback + QLatin1String(".png");
+
+ // Add all relevant files
+ for (int i = 0; i < contentDirs.size(); ++i) {
+ QString contentDir = contentDirs.at(i) + QLatin1Char('/');
+ for (int j = 0; j < subDirs.size() ; ++j) {
+ const QIconDirInfo &dirInfo = subDirs.at(j);
+ QString subdir = dirInfo.path;
+ QDir currentDir(contentDir + subdir);
+ if (currentDir.exists(pngIconName)) {
+ PixmapEntry *iconEntry = new PixmapEntry;
+ iconEntry->dir = dirInfo;
+ iconEntry->filename = currentDir.filePath(pngIconName);
+ // Notice we ensure that pixmap entries always come before
+ // scalable to preserve search order afterwards
+ info.entries.prepend(iconEntry);
+ } else if (m_supportsSvg &&
+ currentDir.exists(svgIconName)) {
+ ScalableEntry *iconEntry = new ScalableEntry;
+ iconEntry->dir = dirInfo;
+ iconEntry->filename = currentDir.filePath(svgIconName);
+ info.entries.append(iconEntry);
+ }
+ }
+ }
+
+ if (!info.entries.isEmpty()) {
+ info.iconName = iconNameFallback;
+ break;
}
+
+ // If it's possible - find next fallback for the icon
+ const int indexOfDash = iconNameFallback.lastIndexOf(QLatin1Char('-'));
+ if (indexOfDash == -1)
+ break;
+
+ iconNameFallback.truncate(indexOfDash);
}
- if (entries.isEmpty()) {
+ if (info.entries.isEmpty()) {
const QStringList parents = theme.parents();
// Search recursively through inherited themes
for (int i = 0 ; i < parents.size() ; ++i) {
@@ -295,23 +319,23 @@ QThemeIconEntries QIconLoader::findIconHelper(const QString &themeName,
const QString parentTheme = parents.at(i).trimmed();
if (!visited.contains(parentTheme)) // guard against recursion
- entries = findIconHelper(parentTheme, iconName, visited);
+ info = findIconHelper(parentTheme, iconName, visited);
- if (!entries.isEmpty()) // success
+ if (!info.entries.isEmpty()) // success
break;
}
}
- return entries;
+ return info;
}
-QThemeIconEntries QIconLoader::loadIcon(const QString &name) const
+QThemeIconInfo QIconLoader::loadIcon(const QString &name) const
{
if (!themeName().isEmpty()) {
QStringList visited;
return findIconHelper(themeName(), name, visited);
}
- return QThemeIconEntries();
+ return QThemeIconInfo();
}
@@ -325,7 +349,7 @@ QIconLoaderEngine::QIconLoaderEngine(const QString& iconName)
QIconLoaderEngine::~QIconLoaderEngine()
{
- qDeleteAll(m_entries);
+ qDeleteAll(m_info.entries);
}
QIconLoaderEngine::QIconLoaderEngine(const QIconLoaderEngine &other)
@@ -353,17 +377,19 @@ bool QIconLoaderEngine::write(QDataStream &out) const
bool QIconLoaderEngine::hasIcon() const
{
- return !(m_entries.isEmpty());
+ return !(m_info.entries.isEmpty());
}
// Lazily load the icon
void QIconLoaderEngine::ensureLoaded()
{
if (!(QIconLoader::instance()->themeKey() == m_key)) {
+ qDeleteAll(m_info.entries);
+ m_info.entries.clear();
+ m_info.iconName.clear();
- qDeleteAll(m_entries);
-
- m_entries = QIconLoader::instance()->loadIcon(m_iconName);
+ Q_ASSERT(m_info.entries.size() == 0);
+ m_info = QIconLoader::instance()->loadIcon(m_iconName);
m_key = QIconLoader::instance()->themeKey();
}
}
@@ -433,14 +459,14 @@ QIconLoaderEngineEntry *QIconLoaderEngine::entryForSize(const QSize &size)
{
int iconsize = qMin(size.width(), size.height());
- // Note that m_entries are sorted so that png-files
+ // Note that m_info.entries are sorted so that png-files
// come first
- const int numEntries = m_entries.size();
+ const int numEntries = m_info.entries.size();
// Search for exact matches first
for (int i = 0; i < numEntries; ++i) {
- QIconLoaderEngineEntry *entry = m_entries.at(i);
+ QIconLoaderEngineEntry *entry = m_info.entries.at(i);
if (directoryMatchesSize(entry->dir, iconsize)) {
return entry;
}
@@ -450,7 +476,7 @@ QIconLoaderEngineEntry *QIconLoaderEngine::entryForSize(const QSize &size)
int minimalSize = INT_MAX;
QIconLoaderEngineEntry *closestMatch = 0;
for (int i = 0; i < numEntries; ++i) {
- QIconLoaderEngineEntry *entry = m_entries.at(i);
+ QIconLoaderEngineEntry *entry = m_info.entries.at(i);
int distance = directorySizeDistance(entry->dir, iconsize);
if (distance < minimalSize) {
minimalSize = distance;
@@ -554,13 +580,13 @@ void QIconLoaderEngine::virtual_hook(int id, void *data)
{
QIconEngine::AvailableSizesArgument &arg
= *reinterpret_cast<QIconEngine::AvailableSizesArgument*>(data);
- const int N = m_entries.size();
+ const int N = m_info.entries.size();
QList<QSize> sizes;
sizes.reserve(N);
// Gets all sizes from the DirectoryInfo entries
for (int i = 0; i < N; ++i) {
- int size = m_entries.at(i)->dir.size;
+ int size = m_info.entries.at(i)->dir.size;
sizes.append(QSize(size, size));
}
arg.sizes.swap(sizes); // commit
@@ -569,7 +595,7 @@ void QIconLoaderEngine::virtual_hook(int id, void *data)
case QIconEngine::IconNameHook:
{
QString &name = *reinterpret_cast<QString*>(data);
- name = m_iconName;
+ name = m_info.iconName;
}
break;
default:
diff --git a/src/gui/image/qiconloader_p.h b/src/gui/image/qiconloader_p.h
index 50a6e6d3a7..8ee730f307 100644
--- a/src/gui/image/qiconloader_p.h
+++ b/src/gui/image/qiconloader_p.h
@@ -106,6 +106,12 @@ struct PixmapEntry : public QIconLoaderEngineEntry
typedef QList<QIconLoaderEngineEntry*> QThemeIconEntries;
+struct QThemeIconInfo
+{
+ QThemeIconEntries entries;
+ QString iconName;
+};
+
class QIconLoaderEngine : public QIconEngine
{
public:
@@ -126,7 +132,7 @@ private:
void virtual_hook(int id, void *data);
QIconLoaderEngineEntry *entryForSize(const QSize &size);
QIconLoaderEngine(const QIconLoaderEngine &other);
- QThemeIconEntries m_entries;
+ QThemeIconInfo m_info;
QString m_iconName;
uint m_key;
@@ -140,11 +146,11 @@ public:
QIconTheme() : m_valid(false) {}
QStringList parents() { return m_parents; }
QVector<QIconDirInfo> keyList() { return m_keyList; }
- QString contentDir() { return m_contentDir; }
+ QStringList contentDirs() { return m_contentDirs; }
bool isValid() { return m_valid; }
private:
- QString m_contentDir;
+ QStringList m_contentDirs;
QVector<QIconDirInfo> m_keyList;
QStringList m_parents;
bool m_valid;
@@ -154,7 +160,7 @@ class Q_GUI_EXPORT QIconLoader
{
public:
QIconLoader();
- QThemeIconEntries loadIcon(const QString &iconName) const;
+ QThemeIconInfo loadIcon(const QString &iconName) const;
uint themeKey() const { return m_themeKey; }
QString themeName() const { return m_userTheme.isEmpty() ? m_systemTheme : m_userTheme; }
@@ -169,9 +175,9 @@ public:
void ensureInitialized();
private:
- QThemeIconEntries findIconHelper(const QString &themeName,
- const QString &iconName,
- QStringList &visited) const;
+ QThemeIconInfo findIconHelper(const QString &themeName,
+ const QString &iconName,
+ QStringList &visited) const;
uint m_themeKey;
bool m_supportsSvg;
bool m_initialized;