summaryrefslogtreecommitdiffstats
path: root/src/plugins/platforms/windows
diff options
context:
space:
mode:
authorFriedemann Kleint <Friedemann.Kleint@digia.com>2013-09-06 08:43:21 +0200
committerThe Qt Project <gerrit-noreply@qt-project.org>2013-09-06 12:50:57 +0200
commit87ff0af425656d12c4766a57db60674d63ffa584 (patch)
tree63e143570bb9c7f0f94ff29939a5c2bd3054f49c /src/plugins/platforms/windows
parent6c88be2af28f979cda6bb8024a49af435e3ca3eb (diff)
Windows: Added support for large icons to QFileIconProvider.
Added code using image lists to windows theme. Initial-patch-by: Max Desyatov <max.desyatov@gmail.com> Task-number: QTBUG-4970 Change-Id: I6e82f4edec60e456d0b1759bb1771955edb94491 Reviewed-by: Oliver Wolff <oliver.wolff@digia.com>
Diffstat (limited to 'src/plugins/platforms/windows')
-rw-r--r--src/plugins/platforms/windows/qwindowscontext.cpp2
-rw-r--r--src/plugins/platforms/windows/qwindowscontext.h2
-rw-r--r--src/plugins/platforms/windows/qwindowstheme.cpp83
3 files changed, 81 insertions, 6 deletions
diff --git a/src/plugins/platforms/windows/qwindowscontext.cpp b/src/plugins/platforms/windows/qwindowscontext.cpp
index c676ca3c46..8dab1e2b1c 100644
--- a/src/plugins/platforms/windows/qwindowscontext.cpp
+++ b/src/plugins/platforms/windows/qwindowscontext.cpp
@@ -218,6 +218,7 @@ bool QWindowsUser32DLL::initTouch()
QWindowsShell32DLL::QWindowsShell32DLL()
: sHCreateItemFromParsingName(0)
, sHGetStockIconInfo(0)
+ , sHGetImageList(0)
{
}
@@ -226,6 +227,7 @@ void QWindowsShell32DLL::init()
QSystemLibrary library(QStringLiteral("shell32"));
sHCreateItemFromParsingName = (SHCreateItemFromParsingName)(library.resolve("SHCreateItemFromParsingName"));
sHGetStockIconInfo = (SHGetStockIconInfo)library.resolve("SHGetStockIconInfo");
+ sHGetImageList = (SHGetImageList)library.resolve("SHGetImageList");
}
QWindowsUser32DLL QWindowsContext::user32dll;
diff --git a/src/plugins/platforms/windows/qwindowscontext.h b/src/plugins/platforms/windows/qwindowscontext.h
index 0d3476e00f..173df58570 100644
--- a/src/plugins/platforms/windows/qwindowscontext.h
+++ b/src/plugins/platforms/windows/qwindowscontext.h
@@ -108,9 +108,11 @@ struct QWindowsShell32DLL
typedef HRESULT (WINAPI *SHCreateItemFromParsingName)(PCWSTR, IBindCtx *, const GUID&, void **);
typedef HRESULT (WINAPI *SHGetStockIconInfo)(int , int , _SHSTOCKICONINFO *);
+ typedef HRESULT (WINAPI *SHGetImageList)(int, REFIID , void **);
SHCreateItemFromParsingName sHCreateItemFromParsingName;
SHGetStockIconInfo sHGetStockIconInfo;
+ SHGetImageList sHGetImageList;
};
#endif // Q_OS_WINCE
diff --git a/src/plugins/platforms/windows/qwindowstheme.cpp b/src/plugins/platforms/windows/qwindowstheme.cpp
index 1710fd419a..498bd509fa 100644
--- a/src/plugins/platforms/windows/qwindowstheme.cpp
+++ b/src/plugins/platforms/windows/qwindowstheme.cpp
@@ -48,6 +48,11 @@
#ifdef Q_OS_WINCE
# include "qplatformfunctions_wince.h"
# include "winuser.h"
+#else
+# include <commctrl.h>
+# include <objbase.h>
+# include <commoncontrols.h>
+# include <shellapi.h>
#endif
#include <QtCore/QVariant>
@@ -65,6 +70,10 @@
#include <algorithm>
+#if defined(__IImageList_INTERFACE_DEFINED__) && defined(__IID_DEFINED__)
+# define USE_IIMAGELIST
+#endif
+
QT_BEGIN_NAMESPACE
static inline QTextStream& operator<<(QTextStream &str, const QColor &c)
@@ -357,6 +366,11 @@ QVariant QWindowsTheme::themeHint(ThemeHint hint) const
case IconPixmapSizes: {
QList<int> sizes;
sizes << 16 << 32;
+#ifdef USE_IIMAGELIST
+ sizes << 48; // sHIL_EXTRALARGE
+ if (QSysInfo::WindowsVersion >= QSysInfo::WV_VISTA)
+ sizes << 256; // SHIL_JUMBO
+#endif // USE_IIMAGELIST
return QVariant::fromValue(sizes);
}
case DialogSnapToDefaultButton:
@@ -574,11 +588,24 @@ QPixmap QWindowsTheme::standardPixmap(StandardPixmap sp, const QSizeF &size) con
return QPlatformTheme::standardPixmap(sp, size);
}
-static QString dirIconPixmapCacheKey(int iIcon, int iconSize)
+enum { // Shell image list ids
+ sHIL_EXTRALARGE = 0x2, // 48x48 or user-defined
+ sHIL_JUMBO = 0x4 // 256x256 (Vista or later)
+};
+
+static QString dirIconPixmapCacheKey(int iIcon, int iconSize, int imageListSize)
{
QString key = QLatin1String("qt_dir_") + QString::number(iIcon);
if (iconSize == SHGFI_LARGEICON)
key += QLatin1Char('l');
+ switch (imageListSize) {
+ case sHIL_EXTRALARGE:
+ key += QLatin1Char('e');
+ break;
+ case sHIL_JUMBO:
+ key += QLatin1Char('j');
+ break;
+ }
return key;
}
@@ -602,6 +629,38 @@ public:
void operator delete (void *) {}
};
+// Shell image list helper functions.
+
+static QPixmap pixmapFromShellImageList(int iImageList, const SHFILEINFO &info)
+{
+ QPixmap result;
+#ifdef USE_IIMAGELIST
+ // 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, (void **)&imageList);
+ if (hr != S_OK)
+ return result;
+ HICON hIcon;
+ hr = imageList->GetIcon(info.iIcon, ILD_TRANSPARENT, &hIcon);
+ if (hr == S_OK) {
+ result = qt_pixmapFromWinHICON(hIcon);
+ DestroyIcon(hIcon);
+ }
+ imageList->Release();
+#else
+ Q_UNUSED(iImageList)
+ Q_UNUSED(info)
+#endif // USE_IIMAGELIST
+ return result;
+}
+
QPixmap QWindowsTheme::fileIconPixmap(const QFileInfo &fileInfo, const QSizeF &size,
QPlatformTheme::IconOptions iconOptions) const
{
@@ -617,15 +676,21 @@ QPixmap QWindowsTheme::fileIconPixmap(const QFileInfo &fileInfo, const QSizeF &s
QPixmap pixmap;
const QString filePath = QDir::toNativeSeparators(fileInfo.filePath());
- int iconSize = size.width() > 16 ? SHGFI_LARGEICON : SHGFI_SMALLICON;
-
+ const int width = size.width();
+ const int iconSize = width > 16 ? SHGFI_LARGEICON : SHGFI_SMALLICON;
+ const int requestedImageListSize =
+#ifdef USE_IIMAGELIST
+ width > 48 ? sHIL_JUMBO : (width > 32 ? sHIL_EXTRALARGE : 0);
+#else
+ 0;
+#endif // !USE_IIMAGELIST
bool cacheableDirIcon = fileInfo.isDir() && !fileInfo.isRoot();
if (cacheableDirIcon) {
QMutexLocker locker(&mx);
int iIcon = (useDefaultFolderIcon && defaultFolderIIcon) ? defaultFolderIIcon
: **dirIconEntryCache.object(filePath);
if (iIcon) {
- QPixmapCache::find(dirIconPixmapCacheKey(iIcon, iconSize), pixmap);
+ QPixmapCache::find(dirIconPixmapCacheKey(iIcon, iconSize, requestedImageListSize), pixmap);
if (pixmap.isNull()) // Let's keep both caches in sync
dirIconEntryCache.remove(filePath);
else
@@ -659,7 +724,7 @@ QPixmap QWindowsTheme::fileIconPixmap(const QFileInfo &fileInfo, const QSizeF &s
defaultFolderIIcon = info.iIcon;
//using the unique icon index provided by windows save us from duplicate keys
- key = dirIconPixmapCacheKey(info.iIcon, iconSize);
+ key = dirIconPixmapCacheKey(info.iIcon, iconSize, requestedImageListSize);
QPixmapCache::find(key, pixmap);
if (!pixmap.isNull()) {
QMutexLocker locker(&mx);
@@ -668,7 +733,13 @@ QPixmap QWindowsTheme::fileIconPixmap(const QFileInfo &fileInfo, const QSizeF &s
}
if (pixmap.isNull()) {
- pixmap = qt_pixmapFromWinHICON(info.hIcon);
+ if (requestedImageListSize) {
+ pixmap = pixmapFromShellImageList(requestedImageListSize, info);
+ if (pixmap.isNull() && requestedImageListSize == sHIL_JUMBO)
+ pixmap = pixmapFromShellImageList(sHIL_EXTRALARGE, info);
+ }
+ if (pixmap.isNull())
+ pixmap = qt_pixmapFromWinHICON(info.hIcon);
if (!pixmap.isNull()) {
if (cacheableDirIcon) {
QMutexLocker locker(&mx);