From 86ebdc07dfd8c4df09b21ecc528dcae8d978f7e1 Mon Sep 17 00:00:00 2001 From: Friedemann Kleint Date: Thu, 11 Feb 2021 16:52:18 +0100 Subject: QAbstractFileIconProvider: Use platform theme icons Add code paths to use platform theme icons should icon themes fail. Task-number: QTBUG-66177 Change-Id: I9554637f5230b1f57faaeef6b2c04cf082271edb Reviewed-by: Volker Hilsheimer --- src/gui/image/qabstractfileiconprovider.cpp | 128 ++++++++++++++++++++++------ src/gui/image/qabstractfileiconprovider_p.h | 7 ++ src/gui/kernel/qguiapplication.cpp | 3 + src/widgets/itemviews/qfileiconprovider.cpp | 10 +-- 4 files changed, 115 insertions(+), 33 deletions(-) diff --git a/src/gui/image/qabstractfileiconprovider.cpp b/src/gui/image/qabstractfileiconprovider.cpp index 51638f69d8..dbf27d9360 100644 --- a/src/gui/image/qabstractfileiconprovider.cpp +++ b/src/gui/image/qabstractfileiconprovider.cpp @@ -40,6 +40,8 @@ #include "qabstractfileiconprovider.h" #include +#include +#include #include #include @@ -55,6 +57,103 @@ QAbstractFileIconProviderPrivate::QAbstractFileIconProviderPrivate(QAbstractFile QAbstractFileIconProviderPrivate::~QAbstractFileIconProviderPrivate() = default; +using IconTypeCache = QHash; +Q_GLOBAL_STATIC(IconTypeCache, iconTypeCache) + +void QAbstractFileIconProviderPrivate::clearIconTypeCache() +{ + iconTypeCache()->clear(); +} + +QIcon QAbstractFileIconProviderPrivate::getPlatformThemeIcon(QAbstractFileIconProvider::IconType type) const +{ + auto theme = QGuiApplicationPrivate::platformTheme(); + if (theme == nullptr) + return {}; + + auto &cache = *iconTypeCache(); + auto it = cache.find(type); + if (it == cache.end()) { + const auto sp = [&]() -> QPlatformTheme::StandardPixmap { + switch (type) { + case QAbstractFileIconProvider::Computer: + return QPlatformTheme::ComputerIcon; + case QAbstractFileIconProvider::Desktop: + return QPlatformTheme::DesktopIcon; + case QAbstractFileIconProvider::Trashcan: + return QPlatformTheme::TrashIcon; + case QAbstractFileIconProvider::Network: + return QPlatformTheme::DriveNetIcon; + case QAbstractFileIconProvider::Drive: + return QPlatformTheme::DriveHDIcon; + case QAbstractFileIconProvider::Folder: + return QPlatformTheme::DirIcon; + case QAbstractFileIconProvider::File: + break; + // no default on purpose; we want warnings when the type enum is extended + } + return QPlatformTheme::FileIcon; + }(); + + const auto sizesHint = theme->themeHint(QPlatformTheme::IconPixmapSizes); + auto sizes = sizesHint.value>(); + if (sizes.isEmpty()) + sizes.append({64, 64}); + + QIcon icon; + for (const auto &size : sizes) + icon.addPixmap(theme->standardPixmap(sp, size)); + it = cache.insert(type, icon); + } + return it.value(); +} + +QIcon QAbstractFileIconProviderPrivate::getIconThemeIcon(QAbstractFileIconProvider::IconType type) const +{ + switch (type) { + case QAbstractFileIconProvider::Computer: + return QIcon::fromTheme(QLatin1String("computer")); + case QAbstractFileIconProvider::Desktop: + return QIcon::fromTheme(QLatin1String("user-desktop")); + case QAbstractFileIconProvider::Trashcan: + return QIcon::fromTheme(QLatin1String("user-trash")); + case QAbstractFileIconProvider::Network: + return QIcon::fromTheme(QLatin1String("network-workgroup")); + case QAbstractFileIconProvider::Drive: + return QIcon::fromTheme(QLatin1String("drive-harddisk")); + case QAbstractFileIconProvider::Folder: + return QIcon::fromTheme(QLatin1String("folder")); + case QAbstractFileIconProvider::File: + return QIcon::fromTheme(QLatin1String("text-x-generic")); + // no default on purpose; we want warnings when the type enum is extended + } + return QIcon::fromTheme(QLatin1String("text-x-generic")); +} + +static inline QPlatformTheme::IconOptions toThemeIconOptions(QAbstractFileIconProvider::Options options) +{ + QPlatformTheme::IconOptions result; + if (options.testFlag(QAbstractFileIconProvider::DontUseCustomDirectoryIcons)) + result |= QPlatformTheme::DontUseCustomDirectoryIcons; + return result; +} + +QIcon QAbstractFileIconProviderPrivate::getPlatformThemeIcon(const QFileInfo &info) const +{ + if (auto theme = QGuiApplicationPrivate::platformTheme()) + return theme->fileIcon(info, toThemeIconOptions(options)); + return {}; +} + +QIcon QAbstractFileIconProviderPrivate::getIconThemeIcon(const QFileInfo &info) const +{ + if (info.isRoot()) + return getIconThemeIcon(QAbstractFileIconProvider::Drive); + if (info.isDir()) + return getIconThemeIcon(QAbstractFileIconProvider::Folder); + return QIcon::fromTheme(mimeDatabase.mimeTypeForFile(info).iconName()); +} + /*! \class QAbstractFileIconProvider @@ -139,25 +238,9 @@ QAbstractFileIconProvider::Options QAbstractFileIconProvider::options() const QIcon QAbstractFileIconProvider::icon(IconType type) const { - Q_UNUSED(type); - switch (type) { - case Computer: - return QIcon::fromTheme(QLatin1String("computer")); - case Desktop: - return QIcon::fromTheme(QLatin1String("user-desktop")); - case Trashcan: - return QIcon::fromTheme(QLatin1String("user-trash")); - case Network: - return QIcon::fromTheme(QLatin1String("network-workgroup")); - case Drive: - return QIcon::fromTheme(QLatin1String("drive-harddisk")); - case Folder: - return QIcon::fromTheme(QLatin1String("folder")); - case File: - return QIcon::fromTheme(QLatin1String("text-x-generic")); - // no default on purpose; we want warnings when the type enum is extended - } - return QIcon::fromTheme(QLatin1String("text-x-generic")); + Q_D(const QAbstractFileIconProvider); + const QIcon result = d->getIconThemeIcon(type); + return result.isNull() ? d->getPlatformThemeIcon(type) : result; } /*! @@ -170,11 +253,8 @@ QIcon QAbstractFileIconProvider::icon(IconType type) const QIcon QAbstractFileIconProvider::icon(const QFileInfo &info) const { Q_D(const QAbstractFileIconProvider); - if (info.isRoot()) - return icon(Drive); - if (info.isDir()) - return icon(Folder); - return QIcon::fromTheme(d->mimeDatabase.mimeTypeForFile(info).iconName()); + const QIcon result = d->getIconThemeIcon(info); + return result.isNull() ? d->getPlatformThemeIcon(info) : result; } /*! diff --git a/src/gui/image/qabstractfileiconprovider_p.h b/src/gui/image/qabstractfileiconprovider_p.h index 53ad4826eb..37646f77e6 100644 --- a/src/gui/image/qabstractfileiconprovider_p.h +++ b/src/gui/image/qabstractfileiconprovider_p.h @@ -65,6 +65,13 @@ public: QAbstractFileIconProviderPrivate(QAbstractFileIconProvider *q); virtual ~QAbstractFileIconProviderPrivate(); + QIcon getPlatformThemeIcon(QAbstractFileIconProvider::IconType type) const; + QIcon getIconThemeIcon(QAbstractFileIconProvider::IconType type) const; + QIcon getPlatformThemeIcon(const QFileInfo &info) const; + QIcon getIconThemeIcon(const QFileInfo &info) const; + + static void clearIconTypeCache(); + QAbstractFileIconProvider *q_ptr = nullptr; QAbstractFileIconProvider::Options options = {}; diff --git a/src/gui/kernel/qguiapplication.cpp b/src/gui/kernel/qguiapplication.cpp index 259399e029..2bb5d72bd1 100644 --- a/src/gui/kernel/qguiapplication.cpp +++ b/src/gui/kernel/qguiapplication.cpp @@ -41,6 +41,7 @@ #include "qguiapplication.h" #include "private/qguiapplication_p.h" +#include "private/qabstractfileiconprovider_p.h" #include #include "private/qevent_p.h" #include "qfont.h" @@ -4130,6 +4131,8 @@ void QGuiApplicationPrivate::notifyThemeChanged() { updatePalette(); + QAbstractFileIconProviderPrivate::clearIconTypeCache(); + if (!(applicationResourceFlags & ApplicationFontExplicitlySet)) { const auto locker = qt_scoped_lock(applicationFontMutex); clearFontUnlocked(); diff --git a/src/widgets/itemviews/qfileiconprovider.cpp b/src/widgets/itemviews/qfileiconprovider.cpp index d0bd4bc9a5..0530621cae 100644 --- a/src/widgets/itemviews/qfileiconprovider.cpp +++ b/src/widgets/itemviews/qfileiconprovider.cpp @@ -172,17 +172,9 @@ QIcon QFileIconProvider::icon(IconType type) const return QIcon(); } -static inline QPlatformTheme::IconOptions toThemeIconOptions(QFileIconProvider::Options options) -{ - QPlatformTheme::IconOptions result; - if (options & QFileIconProvider::DontUseCustomDirectoryIcons) - result |= QPlatformTheme::DontUseCustomDirectoryIcons; - return result; -} - QIcon QFileIconProviderPrivate::getIcon(const QFileInfo &fi) const { - return QGuiApplicationPrivate::platformTheme()->fileIcon(fi, toThemeIconOptions(options)); + return getPlatformThemeIcon(fi); } /*! -- cgit v1.2.3