diff options
Diffstat (limited to 'src/plugins/platforms/windows/qwindowstheme.cpp')
-rw-r--r-- | src/plugins/platforms/windows/qwindowstheme.cpp | 168 |
1 files changed, 81 insertions, 87 deletions
diff --git a/src/plugins/platforms/windows/qwindowstheme.cpp b/src/plugins/platforms/windows/qwindowstheme.cpp index ff4cfe63cb..841464391d 100644 --- a/src/plugins/platforms/windows/qwindowstheme.cpp +++ b/src/plugins/platforms/windows/qwindowstheme.cpp @@ -49,17 +49,12 @@ #include "qwindowsintegration.h" #include "qt_windows.h" #include "qwindowsfontdatabase.h" -#ifdef Q_OS_WINCE -# include "qplatformfunctions_wince.h" -# include "winuser.h" -#else -# include <commctrl.h> -# include <objbase.h> -# ifndef Q_CC_MINGW -# include <commoncontrols.h> -# endif -# include <shellapi.h> +#include <commctrl.h> +#include <objbase.h> +#ifndef Q_CC_MINGW +# include <commoncontrols.h> #endif +#include <shellapi.h> #include <QtCore/QVariant> #include <QtCore/QCoreApplication> @@ -73,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> @@ -128,7 +124,6 @@ static inline QColor getSysColor(int index) return COLORREFToQColor(GetSysColor(index)); } -#ifndef QT_NO_WINCE_SHELLSDK // QTBUG-48823/Windows 10: SHGetFileInfo() (as called by item views on file system // models has been observed to trigger a WM_PAINT on the mainwindow. Suppress the // behavior by running it in a thread. @@ -170,7 +165,6 @@ static bool shGetFileInfoBackground(QWindowsThreadPoolRunner &r, } return result; } -#endif // !QT_NO_WINCE_SHELLSDK // from QStyle::standardPalette static inline QPalette standardPalette() @@ -281,14 +275,9 @@ static inline QPalette menuPalette(const QPalette &systemPalette) result.setColor(QPalette::Active, QPalette::ButtonText, menuTextColor); result.setColor(QPalette::Disabled, QPalette::WindowText, disabled); result.setColor(QPalette::Disabled, QPalette::Text, disabled); -#ifndef Q_OS_WINCE const bool isFlat = booleanSystemParametersInfo(SPI_GETFLATMENU, false); result.setColor(QPalette::Disabled, QPalette::Highlight, getSysColor(isFlat ? COLOR_MENUHILIGHT : COLOR_HIGHLIGHT)); -#else - result.setColor(QPalette::Disabled, QPalette::Highlight, - getSysColor(COLOR_HIGHLIGHT)); -#endif result.setColor(QPalette::Disabled, QPalette::HighlightedText, disabled); result.setColor(QPalette::Disabled, QPalette::Button, result.color(QPalette::Active, QPalette::Button)); @@ -314,11 +303,7 @@ static inline QPalette *menuBarPalette(const QPalette &menuPalette) QPalette *result = 0; if (booleanSystemParametersInfo(SPI_GETFLATMENU, false)) { result = new QPalette(menuPalette); -#ifndef Q_OS_WINCE const QColor menubar(getSysColor(COLOR_MENUBAR)); -#else - const QColor menubar(getSysColor(COLOR_MENU)); -#endif result->setColor(QPalette::Active, QPalette::Button, menubar); result->setColor(QPalette::Disabled, QPalette::Button, menubar); result->setColor(QPalette::Inactive, QPalette::Button, menubar); @@ -330,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)); @@ -364,7 +350,7 @@ static inline QStringList styleNames() static inline int uiEffects() { - int result = 0; + int result = QPlatformTheme::HoverEffect; if (booleanSystemParametersInfo(SPI_GETUIEFFECTS, false)) result |= QPlatformTheme::GeneralUiEffect; if (booleanSystemParametersInfo(SPI_GETMENUANIMATION, false)) @@ -389,12 +375,10 @@ QVariant QWindowsTheme::themeHint(ThemeHint hint) const return QVariant(iconThemeSearchPaths()); case StyleNames: return QVariant(styleNames()); -#ifndef Q_OS_WINCE case TextCursorWidth: return QVariant(int(dWordSystemParametersInfo(SPI_GETCARETWIDTH, 1u))); case DropShadow: return QVariant(booleanSystemParametersInfo(SPI_GETDROPSHADOW, false)); -#endif // !Q_OS_WINCE case MaximumScrollBarDragDistance: return QVariant(qRound(qreal(QWindowsContext::instance()->defaultDPI()) * 1.375)); case KeyboardScheme: @@ -402,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: @@ -445,7 +429,6 @@ void QWindowsTheme::clearFonts() void QWindowsTheme::refreshFonts() { -#ifndef Q_OS_WINCE // ALL THIS FUNCTIONALITY IS MISSING ON WINCE clearFonts(); if (!QGuiApplication::desktopSettingsAware()) return; @@ -474,7 +457,6 @@ void QWindowsTheme::refreshFonts() m_fonts[DockWidgetTitleFont] = new QFont(titleFont); m_fonts[ItemViewFont] = new QFont(iconTitleFont); m_fonts[FixedFont] = new QFont(fixedFont); -#endif // !Q_OS_WINCE } enum FileIconSize { @@ -512,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 @@ -528,12 +509,7 @@ Q_GUI_EXPORT QPixmap qt_pixmapFromWinHICON(HICON icon); static QPixmap loadIconFromShell32(int resourceId, QSizeF size) { -#ifdef Q_OS_WINCE - HMODULE hmod = LoadLibrary(L"ceshell"); -#else - HMODULE hmod = QSystemLibrary::load(L"shell32"); -#endif - if (hmod) { + if (const HMODULE hmod = QSystemLibrary::load(L"shell32")) { HICON iconHandle = static_cast<HICON>(LoadImage(hmod, MAKEINTRESOURCE(resourceId), IMAGE_ICON, int(size.width()), int(size.height()), 0)); @@ -549,7 +525,7 @@ static QPixmap loadIconFromShell32(int resourceId, QSizeF size) QPixmap QWindowsTheme::standardPixmap(StandardPixmap sp, const QSizeF &pixmapSize) const { int resourceId = -1; - int stockId = SIID_INVALID; + SHSTOCKICONID stockId = SIID_INVALID; UINT stockFlags = 0; LPCTSTR iconName = 0; switch (sp) { @@ -575,14 +551,14 @@ QPixmap QWindowsTheme::standardPixmap(StandardPixmap sp, const QSizeF &pixmapSiz break; case FileLinkIcon: stockFlags = SHGSI_LINKOVERLAY; - // Fall through + Q_FALLTHROUGH(); case FileIcon: stockId = SIID_DOCNOASSOC; resourceId = 1; break; case DirLinkIcon: stockFlags = SHGSI_LINKOVERLAY; - // Fall through + Q_FALLTHROUGH(); case DirClosedIcon: case DirIcon: stockId = SIID_FOLDER; @@ -596,7 +572,7 @@ QPixmap QWindowsTheme::standardPixmap(StandardPixmap sp, const QSizeF &pixmapSiz break; case DirLinkOpenIcon: stockFlags = SHGSI_LINKOVERLAY; - // Fall through + Q_FALLTHROUGH(); case DirOpenIcon: stockId = SIID_FOLDEROPEN; resourceId = 5; @@ -612,7 +588,6 @@ QPixmap QWindowsTheme::standardPixmap(StandardPixmap sp, const QSizeF &pixmapSiz stockId = SIID_RECYCLER; resourceId = 191; break; -#ifndef Q_OS_WINCE case MessageBoxInformation: stockId = SIID_INFO; iconName = IDI_INFORMATION; @@ -632,29 +607,22 @@ QPixmap QWindowsTheme::standardPixmap(StandardPixmap sp, const QSizeF &pixmapSiz case VistaShield: stockId = SIID_SHIELD; break; -#endif default: break; } -#ifndef Q_OS_WINCE if (stockId != SIID_INVALID) { - if (QSysInfo::WindowsVersion >= QSysInfo::WV_VISTA - && (QSysInfo::WindowsVersion & QSysInfo::WV_NT_based) - && QWindowsContext::shell32dll.sHGetStockIconInfo) { - QPixmap pixmap; - SHSTOCKICONINFO iconInfo; - memset(&iconInfo, 0, sizeof(iconInfo)); - iconInfo.cbSize = sizeof(iconInfo); - stockFlags |= (pixmapSize.width() > 16 ? SHGFI_LARGEICON : SHGFI_SMALLICON); - if (QWindowsContext::shell32dll.sHGetStockIconInfo(stockId, SHGFI_ICON | stockFlags, &iconInfo) == S_OK) { - pixmap = qt_pixmapFromWinHICON(iconInfo.hIcon); - DestroyIcon(iconInfo.hIcon); - return pixmap; - } + QPixmap pixmap; + SHSTOCKICONINFO iconInfo; + memset(&iconInfo, 0, sizeof(iconInfo)); + iconInfo.cbSize = sizeof(iconInfo); + stockFlags |= (pixmapSize.width() > 16 ? SHGFI_LARGEICON : SHGFI_SMALLICON); + if (SHGetStockIconInfo(stockId, SHGFI_ICON | stockFlags, &iconInfo) == S_OK) { + pixmap = qt_pixmapFromWinHICON(iconInfo.hIcon); + DestroyIcon(iconInfo.hIcon); + return pixmap; } } -#endif if (resourceId != -1) { QPixmap pixmap = loadIconFromShell32(resourceId, pixmapSize); @@ -729,14 +697,8 @@ static QPixmap pixmapFromShellImageList(int iImageList, const SHFILEINFO &info) // For MinGW: static const IID iID_IImageList = {0x46eb5926, 0x582e, 0x4017, {0x9f, 0xdf, 0xe8, 0x99, 0x8d, 0xaa, 0x9, 0x50}}; - if (!QWindowsContext::shell32dll.sHGetImageList) - return result; - if (iImageList == sHIL_JUMBO && QSysInfo::WindowsVersion < QSysInfo::WV_VISTA) - return result; - IImageList *imageList = 0; - HRESULT hr = QWindowsContext::shell32dll.sHGetImageList(iImageList, iID_IImageList, - reinterpret_cast<void **>(&imageList)); + HRESULT hr = SHGetImageList(iImageList, iID_IImageList, reinterpret_cast<void **>(&imageList)); if (hr != S_OK) return result; HICON hIcon; @@ -753,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. */ @@ -764,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 = @@ -778,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 @@ -794,22 +794,13 @@ QPixmap QWindowsTheme::fileIconPixmap(const QFileInfo &fileInfo, const QSizeF &s SHFILEINFO info; const unsigned int flags = -#ifndef Q_OS_WINCE SHGFI_ICON|iconSize|SHGFI_SYSICONINDEX|SHGFI_ADDOVERLAYS|SHGFI_OVERLAYINDEX; -#else - iconSize|SHGFI_SYSICONINDEX; -#endif // Q_OS_WINCE - -#if !defined(QT_NO_WINCE_SHELLSDK) 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); -#else - const bool val = false; -#endif // !QT_NO_WINCE_SHELLSDK // Even if GetFileInfo returns a valid result, hIcon can be empty in some cases if (val && info.hIcon) { @@ -848,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 |