diff --git a/src/platformtheme/kdeplatformtheme.h b/src/platformtheme/kdeplatformtheme.h --- a/src/platformtheme/kdeplatformtheme.h +++ b/src/platformtheme/kdeplatformtheme.h @@ -23,15 +23,20 @@ #include +#include + #include #include #include +#include + class KHintsSettings; class KFontSettingsData; class KWaylandIntegration; class X11Integration; class QIconEngine; +class QMimeDatabase; class QWindow; class AltKeyEventListener; @@ -43,6 +48,12 @@ ~KdePlatformTheme(); QVariant themeHint(ThemeHint hint) const Q_DECL_OVERRIDE; +#if QT_VERSION >= QT_VERSION_CHECK(5, 8, 0) + QIcon fileIcon(const QFileInfo &fileInfo, QPlatformTheme::IconOptions iconOptions) const Q_DECL_OVERRIDE; +#else + QPixmap fileIconPixmap(const QFileInfo &fileInfo, const QSizeF &size, + QPlatformTheme::IconOptions iconOptions) const Q_DECL_OVERRIDE; +#endif const QPalette *palette(Palette type = SystemPalette) const Q_DECL_OVERRIDE; const QFont *font(Font type) const Q_DECL_OVERRIDE; QIconEngine *createIconEngine(const QString &iconName) const Q_DECL_OVERRIDE; @@ -60,15 +71,33 @@ #endif private: + + class FileIconProvider + { + public: + FileIconProvider(); + QIcon fileIcon(const QFileInfo &fileInfo, QPlatformTheme::IconOptions iconOptions) const; + + private: + struct StandardPathItem { + QString iconName; + QStringList locations; + }; + std::vector m_standardPathItems; + QScopedPointer m_mimeDatabase; + }; + void loadSettings(); static void setWindowProperty(QWindow *window, const QByteArray &name, const QByteArray &value); + const FileIconProvider* fileIconProvider() const; KHintsSettings *m_hints; KFontSettingsData *m_fontsData; QScopedPointer m_kwaylandIntegration; QScopedPointer m_x11Integration; + mutable QScopedPointer m_fileIconProvider; }; #endif // KDEPLATFORMTHEME_H diff --git a/src/platformtheme/kdeplatformtheme.cpp b/src/platformtheme/kdeplatformtheme.cpp --- a/src/platformtheme/kdeplatformtheme.cpp +++ b/src/platformtheme/kdeplatformtheme.cpp @@ -35,9 +35,11 @@ #include #include #include +#include +#include #include +#include #include -#include #include #include #include @@ -109,6 +111,19 @@ } } +#if QT_VERSION >= QT_VERSION_CHECK(5, 8, 0) +QIcon KdePlatformTheme::fileIcon(const QFileInfo &fileInfo, QPlatformTheme::IconOptions iconOptions) const +{ + return fileIconProvider()->fileIcon(fileInfo, iconOptions); +} +#else +QPixmap KdePlatformTheme::fileIconPixmap(const QFileInfo &fileInfo, const QSizeF &size, + QPlatformTheme::IconOptions iconOptions) const +{ + return fileIconProvider()->fileIcon(fileInfo, iconOptions).pixmap(size.toSize(), QIcon::Normal); +} +#endif + const QPalette *KdePlatformTheme::palette(Palette type) const { QPalette *palette = m_hints->palette(type); @@ -368,4 +383,65 @@ } #endif +const KdePlatformTheme::FileIconProvider * KdePlatformTheme::fileIconProvider() const +{ + if (!m_fileIconProvider) { + m_fileIconProvider.reset(new FileIconProvider()); + } + + Q_ASSERT(m_fileIconProvider); + return m_fileIconProvider.data(); +} + +KdePlatformTheme::FileIconProvider::FileIconProvider() + : m_mimeDatabase(new QMimeDatabase()) +{ + const auto appendStandardPath = [this](const char* iconName, + QStandardPaths::StandardLocation location) + { + m_standardPathItems.push_back({QLatin1Literal(iconName), QStandardPaths::standardLocations(location)}); + }; + + // put home first since others might duplicate it + appendStandardPath("user-home", QStandardPaths::HomeLocation); + appendStandardPath("desktop", QStandardPaths::DesktopLocation); + appendStandardPath("folder-documents", QStandardPaths::DocumentsLocation); + appendStandardPath("folder-music", QStandardPaths::MusicLocation); + appendStandardPath("folder-videos", QStandardPaths::MoviesLocation); + appendStandardPath("folder-pictures", QStandardPaths::PicturesLocation); + appendStandardPath("folder-temp", QStandardPaths::TempLocation); + appendStandardPath("folder-downloads", QStandardPaths::DownloadLocation); +} + +QIcon KdePlatformTheme::FileIconProvider::fileIcon(const QFileInfo& fileInfo, QPlatformTheme::IconOptions iconOptions) const +{ + if (!iconOptions.testFlag(DontUseCustomDirectoryIcons) && fileInfo.isDir()) { + const QString path = fileInfo.filePath(); + for (const auto &standardPath: m_standardPathItems) { + if (standardPath.locations.contains(path)) { + QIcon icon = QIcon::fromTheme(standardPath.iconName); + if (!icon.isNull()) { + return icon; + } + // another item might contain this path as a fallback: e.g. '~' might be used as the + // fallback for QStandardPaths::DocumentsLocation, but we do not need icon "documents" + // for home directory, therefore we break loop here + break; + } + } + } + + const QMimeType mimeType = m_mimeDatabase->mimeTypeForFile(fileInfo); + if (!mimeType.isValid()) + return QIcon(); + const QString &iconName = mimeType.iconName(); + if (!iconName.isEmpty()) { + const QIcon icon = QIcon::fromTheme(iconName); + if (!icon.isNull()) + return icon; + } + const QString &genericIconName = mimeType.genericIconName(); + return genericIconName.isEmpty() ? QIcon() : QIcon::fromTheme(genericIconName); +} + #include "kdeplatformtheme.moc"