diff --git a/src/kiconloader.cpp b/src/kiconloader.cpp --- a/src/kiconloader.cpp +++ b/src/kiconloader.cpp @@ -41,6 +41,7 @@ #include #include #include +#include #include // kdecore @@ -569,21 +570,51 @@ emit q->iconChanged(group); } +class SafePrivate : public KIconLoaderPrivate +{ + struct Proxy + { + QMutex &mutex; + KIconLoaderPrivate *d; + Proxy(QMutex &m, KIconLoaderPrivate *p) : mutex(m), d(p) + { + mutex.lock(); + } + ~Proxy() + { + mutex.unlock(); + } + KIconLoaderPrivate* operator->() + { + return d; + } + }; + QMutex mutex; +public: + using KIconLoaderPrivate::KIconLoaderPrivate; + Proxy lock() + { + return Proxy{ mutex, this }; + } +}; + +#define S_D(d) static_cast(d)->lock() + KIconLoader::KIconLoader(const QString &_appname, const QStringList &extraSearchPaths, QObject *parent) : QObject(parent) { setObjectName(_appname); - d = new KIconLoaderPrivate(this); + d = new SafePrivate(this); connect(s_globalData, SIGNAL(iconChanged(int)), SLOT(_k_refreshIcons(int))); - d->init(_appname, extraSearchPaths); + S_D(d)->init(_appname, extraSearchPaths); } void KIconLoader::reconfigure(const QString &_appname, const QStringList &extraSearchPaths) { - d->mIconCache->clear(); - d->clear(); - d->init(_appname, extraSearchPaths); + S_D(d)->mIconCache->clear(); + S_D(d)->clear(); + S_D(d)->init(_appname, extraSearchPaths); } void KIconLoaderPrivate::init(const QString &_appname, const QStringList &extraSearchPaths) @@ -672,15 +703,15 @@ QStringList KIconLoader::searchPaths() const { - return d->searchPaths; + return S_D(d)->searchPaths; } void KIconLoader::addAppDir(const QString &appname, const QString &themeBaseDir) { - d->initIconThemes(); + S_D(d)->initIconThemes(); - d->searchPaths.append(appname + QStringLiteral("/pics")); - d->addAppThemes(appname, themeBaseDir); + S_D(d)->searchPaths.append(appname + QStringLiteral("/pics")); + S_D(d)->addAppThemes(appname, themeBaseDir); } void KIconLoaderPrivate::addAppThemes(const QString &appname, const QString &themeBaseDir) @@ -808,7 +839,7 @@ void KIconLoader::drawOverlays(const QStringList &overlays, QPixmap &pixmap, KIconLoader::Group group, int state) const { - d->drawOverlays(this, group, state, pixmap, overlays); + S_D(d)->drawOverlays(this, group, state, pixmap, overlays); } QString KIconLoaderPrivate::removeIconExtension(const QString &name) const @@ -1171,7 +1202,7 @@ QString KIconLoader::iconPath(const QString &_name, int group_or_size, bool canReturnNull, qreal scale) const { - if (!d->initIconThemes()) { + if (!S_D(d)->initIconThemes()) { return QString(); } @@ -1180,19 +1211,19 @@ return _name; } - QString name = d->removeIconExtension(_name); + QString name = S_D(d)->removeIconExtension(_name); QString path; if (group_or_size == KIconLoader::User) { - path = d->locate(name + QLatin1String(".png")); + path = S_D(d)->locate(name + QLatin1String(".png")); if (path.isEmpty()) { - path = d->locate(name + QLatin1String(".svgz")); + path = S_D(d)->locate(name + QLatin1String(".svgz")); } if (path.isEmpty()) { - path = d->locate(name + QLatin1String(".svg")); + path = S_D(d)->locate(name + QLatin1String(".svg")); } if (path.isEmpty()) { - path = d->locate(name + QLatin1String(".xpm")); + path = S_D(d)->locate(name + QLatin1String(".xpm")); } return path; } @@ -1204,7 +1235,7 @@ int size; if (group_or_size >= 0) { - size = d->mpGroups[group_or_size].size; + size = S_D(d)->mpGroups[group_or_size].size; } else { size = -group_or_size; } @@ -1213,11 +1244,11 @@ if (canReturnNull) { return QString(); } else { - return d->unknownIconPath(size, scale); + return S_D(d)->unknownIconPath(size, scale); } } - path = d->findMatchingIconWithGenericFallbacks(name, size, scale); + path = S_D(d)->findMatchingIconWithGenericFallbacks(name, size, scale); if (path.isEmpty()) { // Try "User" group too. @@ -1226,7 +1257,7 @@ return path; } - return d->unknownIconPath(size, scale); + return S_D(d)->unknownIconPath(size, scale); } return path; } @@ -1240,12 +1271,12 @@ iconName[slashindex] = QLatin1Char('-'); } - if (!d->extraDesktopIconsLoaded) { + if (!S_D(d)->extraDesktopIconsLoaded) { const QPixmap pixmap = loadIcon(iconName, group, size, state, overlays, path_store, true); if (!pixmap.isNull()) { return pixmap; } - d->addExtraDesktopThemes(); + S_D(d)->addExtraDesktopThemes(); } const QPixmap pixmap = loadIcon(iconName, group, size, state, overlays, path_store, true); if (pixmap.isNull()) { @@ -1293,7 +1324,7 @@ bool absolutePath = !pathIsRelative(name); if (!absolutePath) { - name = d->removeIconExtension(name); + name = S_D(d)->removeIconExtension(name); } // Don't bother looking for an icon with no name. @@ -1303,16 +1334,16 @@ // May modify group, size, or state. This function puts them into sane // states. - d->normalizeIconMetadata(group, size, state); + S_D(d)->normalizeIconMetadata(group, size, state); // See if the image is already cached. - QString key = d->makeCacheKey(name, group, overlays, size, scale, state); + QString key = S_D(d)->makeCacheKey(name, group, overlays, size, scale, state); QPixmap pix; bool iconWasUnknown = false; QString path; - if (d->findCachedPixmapWithPath(key, pix, path)) { + if (S_D(d)->findCachedPixmapWithPath(key, pix, path)) { pix.setDevicePixelRatio(scale); if (path_store) { @@ -1324,14 +1355,14 @@ } else { // path is empty for "unknown" icons, which should be searched for // anew regularly - if (!d->shouldCheckForUnknownIcons()) { + if (!S_D(d)->shouldCheckForUnknownIcons()) { return canReturnNull ? QPixmap() : pix; } } } // Image is not cached... go find it and apply effects. - if (!d->initIconThemes()) { + if (!S_D(d)->initIconThemes()) { return QPixmap(); } @@ -1343,7 +1374,7 @@ if (absolutePath && !favIconOverlay) { path = name; } else { - path = d->findMatchingIconWithGenericFallbacks(favIconOverlay ? QStringLiteral("text-html") : name, size, scale); + path = S_D(d)->findMatchingIconWithGenericFallbacks(favIconOverlay ? QStringLiteral("text-html") : name, size, scale); } } @@ -1356,17 +1387,17 @@ // Still can't find it? Use "unknown" if we can't return null. // We keep going in the function so we can ensure this result gets cached. if (path.isEmpty() && !canReturnNull) { - path = d->unknownIconPath(size, scale); + path = S_D(d)->unknownIconPath(size, scale); iconWasUnknown = true; } QImage img; if (!path.isEmpty()) { - img = d->createIconImage(path, size, scale, static_cast(state)); + img = S_D(d)->createIconImage(path, size, scale, static_cast(state)); } if (group >= 0) { - img = d->mpEffect.apply(img, group, state); + img = S_D(d)->mpEffect.apply(img, group, state); } if (favIconOverlay) { @@ -1389,7 +1420,7 @@ // TODO: If we make a loadIcon that returns the image we can convert // drawOverlays to use the image instead of pixmaps as well so we don't // have to transfer so much to the graphics card. - d->drawOverlays(this, group, state, pix, overlays); + S_D(d)->drawOverlays(this, group, state, pix, overlays); // Don't add the path to our unknown icon to the cache, only cache the // actual image. @@ -1397,7 +1428,7 @@ path.clear(); } - d->insertCachedPixmapWithPath(key, pix, path); + S_D(d)->insertCachedPixmapWithPath(key, pix, path); if (path_store) { *path_store = path; @@ -1432,11 +1463,11 @@ QString KIconLoader::moviePath(const QString &name, KIconLoader::Group group, int size) const { - if (!d->mpGroups) { + if (!S_D(d)->mpGroups) { return QString(); } - d->initIconThemes(); + S_D(d)->initIconThemes(); if ((group < -1 || group >= KIconLoader::LastGroup) && group != KIconLoader::User) { qCDebug(KICONTHEMES) << "Illegal icon group:" << group; @@ -1449,15 +1480,15 @@ QString file = name + QStringLiteral(".mng"); if (group == KIconLoader::User) { - file = d->locate(file); + file = S_D(d)->locate(file); } else { if (size == 0) { - size = d->mpGroups[group].size; + size = S_D(d)->mpGroups[group].size; } QString path; - foreach (KIconThemeNode *themeNode, d->links) { + foreach (KIconThemeNode *themeNode, S_D(d)->links) { path = themeNode->theme->iconPath(file, size, KIconLoader::MatchExact); if (!path.isEmpty()) { break; @@ -1465,7 +1496,7 @@ } if (path.isEmpty()) { - foreach (KIconThemeNode *themeNode, d->links) { + foreach (KIconThemeNode *themeNode, S_D(d)->links) { path = themeNode->theme->iconPath(file, size, KIconLoader::MatchBest); if (!path.isEmpty()) { break; @@ -1482,11 +1513,11 @@ { QStringList lst; - if (!d->mpGroups) { + if (!S_D(d)->mpGroups) { return lst; } - d->initIconThemes(); + S_D(d)->initIconThemes(); if ((group < -1) || (group >= KIconLoader::LastGroup)) { qCDebug(KICONTHEMES) << "Illegal icon group: " << group; @@ -1499,12 +1530,12 @@ QString file = name + QStringLiteral("/0001"); if (group == KIconLoader::User) { - file = d->locate(file + QStringLiteral(".png")); + file = S_D(d)->locate(file + QStringLiteral(".png")); } else { if (size == 0) { - size = d->mpGroups[group].size; + size = S_D(d)->mpGroups[group].size; } - file = d->findMatchingIcon(file, size, 1); // FIXME scale + file = S_D(d)->findMatchingIcon(file, size, 1); // FIXME scale } if (file.isEmpty()) { return lst; @@ -1529,16 +1560,16 @@ KIconTheme *KIconLoader::theme() const { - d->initIconThemes(); - if (d->mpThemeRoot) { - return d->mpThemeRoot->theme; + S_D(d)->initIconThemes(); + if (S_D(d)->mpThemeRoot) { + return S_D(d)->mpThemeRoot->theme; } return nullptr; } int KIconLoader::currentSize(KIconLoader::Group group) const { - if (!d->mpGroups) { + if (!S_D(d)->mpGroups) { return -1; } @@ -1546,7 +1577,7 @@ qCDebug(KICONTHEMES) << "Illegal icon group:" << group; return -1; } - return d->mpGroups[group].size; + return S_D(d)->mpGroups[group].size; } QStringList KIconLoader::queryIconsByDir(const QString &iconsDir) const @@ -1564,7 +1595,7 @@ QStringList KIconLoader::queryIconsByContext(int group_or_size, KIconLoader::Context context) const { - d->initIconThemes(); + S_D(d)->initIconThemes(); QStringList result; if (group_or_size >= KIconLoader::LastGroup) { @@ -1573,12 +1604,12 @@ } int size; if (group_or_size >= 0) { - size = d->mpGroups[group_or_size].size; + size = S_D(d)->mpGroups[group_or_size].size; } else { size = -group_or_size; } - foreach (KIconThemeNode *themeNode, d->links) { + foreach (KIconThemeNode *themeNode, S_D(d)->links) { themeNode->queryIconsByContext(&result, size, context); } @@ -1593,7 +1624,7 @@ } else { name = (*it).mid(n + 1); } - name = d->removeIconExtension(name); + name = S_D(d)->removeIconExtension(name); if (!entries.contains(name)) { entries += name; res2 += *it; @@ -1605,7 +1636,7 @@ QStringList KIconLoader::queryIcons(int group_or_size, KIconLoader::Context context) const { - d->initIconThemes(); + S_D(d)->initIconThemes(); QStringList result; if (group_or_size >= KIconLoader::LastGroup) { @@ -1614,12 +1645,12 @@ } int size; if (group_or_size >= 0) { - size = d->mpGroups[group_or_size].size; + size = S_D(d)->mpGroups[group_or_size].size; } else { size = -group_or_size; } - foreach (KIconThemeNode *themeNode, d->links) { + foreach (KIconThemeNode *themeNode, S_D(d)->links) { themeNode->queryIcons(&result, size, context); } @@ -1634,7 +1665,7 @@ } else { name = (*it).mid(n + 1); } - name = d->removeIconExtension(name); + name = S_D(d)->removeIconExtension(name); if (!entries.contains(name)) { entries += name; res2 += *it; @@ -1646,9 +1677,9 @@ // used by KIconDialog to find out which contexts to offer in a combobox bool KIconLoader::hasContext(KIconLoader::Context context) const { - d->initIconThemes(); + S_D(d)->initIconThemes(); - foreach (KIconThemeNode *themeNode, d->links) + foreach (KIconThemeNode *themeNode, S_D(d)->links) if (themeNode->theme->hasContext(context)) { return true; } @@ -1657,12 +1688,12 @@ KIconEffect *KIconLoader::iconEffect() const { - return &d->mpEffect; + return &S_D(d)->mpEffect; } bool KIconLoader::alphaBlending(KIconLoader::Group group) const { - if (!d->mpGroups) { + if (!S_D(d)->mpGroups) { return false; } @@ -1794,9 +1825,9 @@ bool KIconLoader::hasIcon(const QString &name) const { - auto it = d->mIconAvailability.constFind(name); - const auto end = d->mIconAvailability.constEnd(); - if (it != end && !it.value() && !d->shouldCheckForUnknownIcons()) { + auto it = S_D(d)->mIconAvailability.constFind(name); + const auto end = S_D(d)->mIconAvailability.constEnd(); + if (it != end && !it.value() && !S_D(d)->shouldCheckForUnknownIcons()) { return false; // known to be unavailable } bool found = it != end && it.value(); @@ -1804,26 +1835,26 @@ if (!iconPath(name, KIconLoader::Desktop, KIconLoader::MatchBest).isEmpty()) { found = true; } - d->mIconAvailability.insert(name, found); // remember whether the icon is available or not + S_D(d)->mIconAvailability.insert(name, found); // remember whether the icon is available or not } return found; } void KIconLoader::setCustomPalette(const QPalette &palette) { - d->mCustomPalette = true; - d->mPalette = palette; + S_D(d)->mCustomPalette = true; + S_D(d)->mPalette = palette; } QPalette KIconLoader::customPalette() const { - return d->mPalette; + return S_D(d)->mPalette; } void KIconLoader::resetPalette() { - d->mCustomPalette = false; - d->mPalette = QPalette(); + S_D(d)->mCustomPalette = false; + S_D(d)->mPalette = QPalette(); } /*** the global icon loader ***/