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>bb10
parent
6c88be2af2
commit
87ff0af425
|
|
@ -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;
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
|
|
|
|||
Loading…
Reference in New Issue