diff options
author | Friedemann Kleint <Friedemann.Kleint@qt.io> | 2016-07-27 14:00:14 +0200 |
---|---|---|
committer | Friedemann Kleint <Friedemann.Kleint@qt.io> | 2016-08-05 08:06:21 +0000 |
commit | 2cd2cba0868efb7e8dd2d00805f1a5ceed0a1349 (patch) | |
tree | 7fff626ad15f65aeb09508559d82b94f97337714 /src/plugins/platforms | |
parent | 955b2bdfc0cb1d707f8914be230e5e00c548b6ab (diff) |
QtPlatformSupport: Add QAbstractFileIconEngine
Move the code from QtWidgets/QFileIconEngine into a new class with
virtuals in QtPlatformSupport so that platforms can reuse it.
Prototypically use the class in the Windows and macOS QPA plugins.
Remove QPlatformTheme::fileIconPixmap() and change the type
of the hint QPlatformTheme::IconPixmapSizes from QList<int>
to QList<QSize> so that it fits better with the icon code.
Change-Id: I580e936f3507218757565ca099272cd575b3a779
Reviewed-by: Olivier Goffart (Woboq GmbH) <ogoffart@woboq.com>
Diffstat (limited to 'src/plugins/platforms')
-rw-r--r-- | src/plugins/platforms/cocoa/qcocoatheme.h | 4 | ||||
-rw-r--r-- | src/plugins/platforms/cocoa/qcocoatheme.mm | 53 | ||||
-rw-r--r-- | src/plugins/platforms/windows/qwindowstheme.cpp | 78 | ||||
-rw-r--r-- | src/plugins/platforms/windows/qwindowstheme.h | 11 |
4 files changed, 104 insertions, 42 deletions
diff --git a/src/plugins/platforms/cocoa/qcocoatheme.h b/src/plugins/platforms/cocoa/qcocoatheme.h index 282e527b0b..d47e620fbb 100644 --- a/src/plugins/platforms/cocoa/qcocoatheme.h +++ b/src/plugins/platforms/cocoa/qcocoatheme.h @@ -70,9 +70,7 @@ public: const QPalette *palette(Palette type = SystemPalette) const Q_DECL_OVERRIDE; const QFont *font(Font type = SystemFont) const Q_DECL_OVERRIDE; QPixmap standardPixmap(StandardPixmap sp, const QSizeF &size) const Q_DECL_OVERRIDE; - QPixmap fileIconPixmap(const QFileInfo &fileInfo, - const QSizeF &size, - QPlatformTheme::IconOptions options = 0) const Q_DECL_OVERRIDE; + QIcon fileIcon(const QFileInfo &fileInfo, QPlatformTheme::IconOptions options = 0) const override; QVariant themeHint(ThemeHint hint) const Q_DECL_OVERRIDE; QString standardButtonText(int button) const Q_DECL_OVERRIDE; diff --git a/src/plugins/platforms/cocoa/qcocoatheme.mm b/src/plugins/platforms/cocoa/qcocoatheme.mm index 01b654af68..3a3d634f5a 100644 --- a/src/plugins/platforms/cocoa/qcocoatheme.mm +++ b/src/plugins/platforms/cocoa/qcocoatheme.mm @@ -58,6 +58,7 @@ #include <QtGui/private/qguiapplication_p.h> #include <QtGui/qpainter.h> #include <QtPlatformSupport/private/qcoretextfontdatabase_p.h> +#include <QtPlatformSupport/private/qabstractfileiconengine_p.h> #include <qpa/qplatformintegration.h> #include <qpa/qplatformnativeinterface.h> @@ -274,16 +275,41 @@ QPixmap QCocoaTheme::standardPixmap(StandardPixmap sp, const QSizeF &size) const return QPlatformTheme::standardPixmap(sp, size); } -QPixmap QCocoaTheme::fileIconPixmap(const QFileInfo &fileInfo, const QSizeF &size, - QPlatformTheme::IconOptions iconOptions) const +class QCocoaFileIconEngine : public QAbstractFileIconEngine { - Q_UNUSED(iconOptions); - QMacAutoReleasePool pool; +public: + explicit QCocoaFileIconEngine(const QFileInfo &info, + QPlatformTheme::IconOptions opts) : + QAbstractFileIconEngine(info, opts) {} + + static QList<QSize> availableIconSizes() + { + const qreal devicePixelRatio = qGuiApp->devicePixelRatio(); + const int sizes[] = { + qRound(16 * devicePixelRatio), qRound(32 * devicePixelRatio), + qRound(64 * devicePixelRatio), qRound(128 * devicePixelRatio) + }; + return QAbstractFileIconEngine::toSizeList(sizes, sizes + sizeof(sizes) / sizeof(sizes[0])); + } + + QList<QSize> availableSizes(QIcon::Mode = QIcon::Normal, QIcon::State = QIcon::Off) const override + { return QCocoaFileIconEngine::availableIconSizes(); } - NSImage *iconImage = [[NSWorkspace sharedWorkspace] iconForFile:QCFString::toNSString(fileInfo.canonicalFilePath())]; - if (!iconImage) - return QPixmap(); - return qt_mac_toQPixmap(iconImage, size); +protected: + QPixmap filePixmap(const QSize &size, QIcon::Mode, QIcon::State) override + { + QMacAutoReleasePool pool; + + NSImage *iconImage = [[NSWorkspace sharedWorkspace] iconForFile:QCFString::toNSString(fileInfo().canonicalFilePath())]; + if (!iconImage) + return QPixmap(); + return qt_mac_toQPixmap(iconImage, size); + } +}; + +QIcon QCocoaTheme::fileIcon(const QFileInfo &fileInfo, QPlatformTheme::IconOptions iconOptions) const +{ + return QIcon(new QCocoaFileIconEngine(fileInfo, iconOptions)); } QVariant QCocoaTheme::themeHint(ThemeHint hint) const @@ -298,15 +324,8 @@ QVariant QCocoaTheme::themeHint(ThemeHint hint) const case TabFocusBehavior: return QVariant([[NSApplication sharedApplication] isFullKeyboardAccessEnabled] ? int(Qt::TabFocusAllControls) : int(Qt::TabFocusTextControls | Qt::TabFocusListControls)); - case IconPixmapSizes: { - qreal devicePixelRatio = qGuiApp->devicePixelRatio(); - QList<int> sizes; - sizes << 16 * devicePixelRatio - << 32 * devicePixelRatio - << 64 * devicePixelRatio - << 128 * devicePixelRatio; - return QVariant::fromValue(sizes); - } + case IconPixmapSizes: + return QVariant::fromValue(QCocoaFileIconEngine::availableIconSizes()); case QPlatformTheme::PasswordMaskCharacter: return QVariant(QChar(kBulletUnicode)); case QPlatformTheme::UiEffects: diff --git a/src/plugins/platforms/windows/qwindowstheme.cpp b/src/plugins/platforms/windows/qwindowstheme.cpp index 2c3ffd45d9..79befc56c2 100644 --- a/src/plugins/platforms/windows/qwindowstheme.cpp +++ b/src/plugins/platforms/windows/qwindowstheme.cpp @@ -68,6 +68,7 @@ #include <QtGui/QPainter> #include <QtGui/QPixmapCache> #include <qpa/qwindowsysteminterface.h> +#include <QtPlatformSupport/private/qabstractfileiconengine_p.h> #include <private/qhighdpiscaling_p.h> #include <private/qsystemlibrary_p.h> @@ -314,6 +315,7 @@ const char *QWindowsTheme::name = "windows"; QWindowsTheme *QWindowsTheme::m_instance = 0; QWindowsTheme::QWindowsTheme() + : m_threadPoolRunner(new QWindowsThreadPoolRunner) { m_instance = this; std::fill(m_fonts, m_fonts + NFonts, static_cast<QFont *>(0)); @@ -384,7 +386,7 @@ QVariant QWindowsTheme::themeHint(ThemeHint hint) const case UiEffects: return QVariant(uiEffects()); case IconPixmapSizes: - return m_fileIconSizes; + return QVariant::fromValue(m_fileIconSizes); case DialogSnapToDefaultButton: return QVariant(booleanSystemParametersInfo(SPI_GETSNAPTODEFBUTTON, false)); case ContextMenuOnMouseRelease: @@ -492,15 +494,14 @@ void QWindowsTheme::refreshIconPixmapSizes() fileIconSizes[ExtraLargeFileIcon] = fileIconSizes[LargeFileIcon] + fileIconSizes[LargeFileIcon] / 2; fileIconSizes[JumboFileIcon] = 8 * fileIconSizes[LargeFileIcon]; // empirical, has not been observed to work - QList<int> sizes; - sizes << fileIconSizes[SmallFileIcon] << fileIconSizes[LargeFileIcon]; + #ifdef USE_IIMAGELIST - sizes << fileIconSizes[ExtraLargeFileIcon]; // sHIL_EXTRALARGE - if (QSysInfo::WindowsVersion >= QSysInfo::WV_VISTA) - sizes << fileIconSizes[JumboFileIcon]; // SHIL_JUMBO + int *availEnd = fileIconSizes + JumboFileIcon + 1; +#else + int *availEnd = fileIconSizes + LargeFileIcon + 1; #endif // USE_IIMAGELIST - qCDebug(lcQpaWindows) << __FUNCTION__ << sizes; - m_fileIconSizes = QVariant::fromValue(sizes); + m_fileIconSizes = QAbstractFileIconEngine::toSizeList(fileIconSizes, availEnd); + qCDebug(lcQpaWindows) << __FUNCTION__ << m_fileIconSizes; } // Defined in qpixmap_win.cpp @@ -714,8 +715,46 @@ static QPixmap pixmapFromShellImageList(int iImageList, const SHFILEINFO &info) return result; } -QPixmap QWindowsTheme::fileIconPixmap(const QFileInfo &fileInfo, const QSizeF &size, - QPlatformTheme::IconOptions iconOptions) const +class QWindowsFileIconEngine : public QAbstractFileIconEngine +{ +public: + explicit QWindowsFileIconEngine(const QFileInfo &info, + QPlatformTheme::IconOptions opts, + const QSharedPointer<QWindowsThreadPoolRunner> &runner) : + QAbstractFileIconEngine(info, opts), m_threadPoolRunner(runner) {} + + QList<QSize> availableSizes(QIcon::Mode = QIcon::Normal, QIcon::State = QIcon::Off) const override + { return QWindowsTheme::instance()->availableFileIconSizes(); } + +protected: + QString cacheKey() const override; + QPixmap filePixmap(const QSize &size, QIcon::Mode mode, QIcon::State) override; + +private: + const QSharedPointer<QWindowsThreadPoolRunner> m_threadPoolRunner; +}; + +QString QWindowsFileIconEngine::cacheKey() const +{ + // Cache directories unless custom or drives, which have custom icons depending on type + if ((options() & QPlatformTheme::DontUseCustomDirectoryIcons) && fileInfo().isDir() && !fileInfo().isRoot()) + return QStringLiteral("qt_/directory/"); + if (!fileInfo().isFile()) + return QString(); + // Return "" for .exe, .lnk and .ico extensions. + // It is faster to just look at the file extensions; + // avoiding slow QFileInfo::isExecutable() (QTBUG-13182) + const QString &suffix = fileInfo().suffix(); + if (!suffix.compare(QLatin1String("exe"), Qt::CaseInsensitive) + || !suffix.compare(QLatin1String("lnk"), Qt::CaseInsensitive) + || !suffix.compare(QLatin1String("ico"), Qt::CaseInsensitive)) { + return QString(); + } + return QLatin1String("qt_.") + + (suffix.isEmpty() ? fileInfo().fileName() : suffix.toUpper()); // handle "Makefile" ;) +} + +QPixmap QWindowsFileIconEngine::filePixmap(const QSize &size, QIcon::Mode, QIcon::State) { /* We don't use the variable, but by storing it statically, we * ensure CoInitialize is only called once. */ @@ -725,10 +764,10 @@ QPixmap QWindowsTheme::fileIconPixmap(const QFileInfo &fileInfo, const QSizeF &s static QCache<QString, FakePointer<int> > dirIconEntryCache(1000); static QMutex mx; static int defaultFolderIIcon = -1; - const bool useDefaultFolderIcon = iconOptions & QPlatformTheme::DontUseCustomDirectoryIcons; + const bool useDefaultFolderIcon = options() & QPlatformTheme::DontUseCustomDirectoryIcons; QPixmap pixmap; - const QString filePath = QDir::toNativeSeparators(fileInfo.filePath()); + const QString filePath = QDir::toNativeSeparators(fileInfo().filePath()); const int width = int(size.width()); const int iconSize = width > fileIconSizes[SmallFileIcon] ? SHGFI_LARGEICON : SHGFI_SMALLICON; const int requestedImageListSize = @@ -739,7 +778,7 @@ QPixmap QWindowsTheme::fileIconPixmap(const QFileInfo &fileInfo, const QSizeF &s #else 0; #endif // !USE_IIMAGELIST - bool cacheableDirIcon = fileInfo.isDir() && !fileInfo.isRoot(); + bool cacheableDirIcon = fileInfo().isDir() && !fileInfo().isRoot(); if (cacheableDirIcon) { QMutexLocker locker(&mx); int iIcon = (useDefaultFolderIcon && defaultFolderIIcon >= 0) ? defaultFolderIIcon @@ -758,9 +797,9 @@ QPixmap QWindowsTheme::fileIconPixmap(const QFileInfo &fileInfo, const QSizeF &s SHGFI_ICON|iconSize|SHGFI_SYSICONINDEX|SHGFI_ADDOVERLAYS|SHGFI_OVERLAYINDEX; const bool val = cacheableDirIcon && useDefaultFolderIcon - ? shGetFileInfoBackground(m_threadPoolRunner, L"dummy", FILE_ATTRIBUTE_DIRECTORY, + ? shGetFileInfoBackground(*m_threadPoolRunner.data(), L"dummy", FILE_ATTRIBUTE_DIRECTORY, &info, flags | SHGFI_USEFILEATTRIBUTES) - : shGetFileInfoBackground(m_threadPoolRunner, reinterpret_cast<const wchar_t *>(filePath.utf16()), 0, + : shGetFileInfoBackground(*m_threadPoolRunner.data(), reinterpret_cast<const wchar_t *>(filePath.utf16()), 0, &info, flags); // Even if GetFileInfo returns a valid result, hIcon can be empty in some cases @@ -800,9 +839,12 @@ QPixmap QWindowsTheme::fileIconPixmap(const QFileInfo &fileInfo, const QSizeF &s DestroyIcon(info.hIcon); } - if (!pixmap.isNull()) - return pixmap; - return QPlatformTheme::fileIconPixmap(fileInfo, size); + return pixmap; +} + +QIcon QWindowsTheme::fileIcon(const QFileInfo &fileInfo, QPlatformTheme::IconOptions iconOptions) const +{ + return QIcon(new QWindowsFileIconEngine(fileInfo, iconOptions, m_threadPoolRunner)); } QT_END_NAMESPACE diff --git a/src/plugins/platforms/windows/qwindowstheme.h b/src/plugins/platforms/windows/qwindowstheme.h index fa1fb4d998..0384899efa 100644 --- a/src/plugins/platforms/windows/qwindowstheme.h +++ b/src/plugins/platforms/windows/qwindowstheme.h @@ -43,6 +43,7 @@ #include "qwindowsthreadpoolrunner.h" #include <qpa/qplatformtheme.h> +#include <QtCore/QSharedPointer> #include <QtCore/QVariant> QT_BEGIN_NAMESPACE @@ -66,12 +67,14 @@ public: { return m_fonts[type]; } QPixmap standardPixmap(StandardPixmap sp, const QSizeF &size) const Q_DECL_OVERRIDE; - QPixmap fileIconPixmap(const QFileInfo &fileInfo, const QSizeF &size, - QPlatformTheme::IconOptions iconOptions = 0) const Q_DECL_OVERRIDE; + + QIcon fileIcon(const QFileInfo &fileInfo, QPlatformTheme::IconOptions iconOptions = 0) const override; void windowsThemeChanged(QWindow *window); void displayChanged() { refreshIconPixmapSizes(); } + QList<QSize> availableFileIconSizes() const { return m_fileIconSizes; } + static const char *name; private: @@ -85,8 +88,8 @@ private: static QWindowsTheme *m_instance; QPalette *m_palettes[NPalettes]; QFont *m_fonts[NFonts]; - mutable QWindowsThreadPoolRunner m_threadPoolRunner; - QVariant m_fileIconSizes; + const QSharedPointer<QWindowsThreadPoolRunner> m_threadPoolRunner; + QList<QSize> m_fileIconSizes; }; QT_END_NAMESPACE |