summaryrefslogtreecommitdiffstats
path: root/src/plugins/platforms/windows/qwindowstheme.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'src/plugins/platforms/windows/qwindowstheme.cpp')
-rw-r--r--src/plugins/platforms/windows/qwindowstheme.cpp121
1 files changed, 107 insertions, 14 deletions
diff --git a/src/plugins/platforms/windows/qwindowstheme.cpp b/src/plugins/platforms/windows/qwindowstheme.cpp
index 9f6e6b18e7..49fdfc15b8 100644
--- a/src/plugins/platforms/windows/qwindowstheme.cpp
+++ b/src/plugins/platforms/windows/qwindowstheme.cpp
@@ -54,6 +54,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>
@@ -69,6 +74,12 @@
#include <qpa/qwindowsysteminterface.h>
#include <private/qsystemlibrary_p.h>
+#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)
@@ -290,8 +301,8 @@ QWindowsTheme *QWindowsTheme::m_instance = 0;
QWindowsTheme::QWindowsTheme()
{
m_instance = this;
- qFill(m_fonts, m_fonts + NFonts, static_cast<QFont *>(0));
- qFill(m_palettes, m_palettes + NPalettes, static_cast<QPalette *>(0));
+ std::fill(m_fonts, m_fonts + NFonts, static_cast<QFont *>(0));
+ std::fill(m_palettes, m_palettes + NPalettes, static_cast<QPalette *>(0));
refresh();
}
@@ -361,8 +372,15 @@ 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:
+ return QVariant(booleanSystemParametersInfo(SPI_GETSNAPTODEFBUTTON, false));
default:
break;
}
@@ -372,7 +390,7 @@ QVariant QWindowsTheme::themeHint(ThemeHint hint) const
void QWindowsTheme::clearPalettes()
{
qDeleteAll(m_palettes, m_palettes + NPalettes);
- qFill(m_palettes, m_palettes + NPalettes, static_cast<QPalette *>(0));
+ std::fill(m_palettes, m_palettes + NPalettes, static_cast<QPalette *>(0));
}
void QWindowsTheme::refreshPalettes()
@@ -393,7 +411,7 @@ void QWindowsTheme::refreshPalettes()
void QWindowsTheme::clearFonts()
{
qDeleteAll(m_fonts, m_fonts + NFonts);
- qFill(m_fonts, m_fonts + NFonts, static_cast<QFont *>(0));
+ std::fill(m_fonts, m_fonts + NFonts, static_cast<QFont *>(0));
}
void QWindowsTheme::refreshFonts()
@@ -410,6 +428,8 @@ void QWindowsTheme::refreshFonts()
const QFont messageBoxFont = QWindowsFontDatabase::LOGFONT_to_QFont(ncm.lfMessageFont);
const QFont statusFont = QWindowsFontDatabase::LOGFONT_to_QFont(ncm.lfStatusFont);
const QFont titleFont = QWindowsFontDatabase::LOGFONT_to_QFont(ncm.lfCaptionFont);
+ QFont fixedFont(QStringLiteral("Courier New"), messageBoxFont.pointSize());
+ fixedFont.setStyleHint(QFont::TypeWriter);
LOGFONT lfIconTitleFont;
SystemParametersInfo(SPI_GETICONTITLELOGFONT, sizeof(lfIconTitleFont), &lfIconTitleFont, 0);
@@ -424,6 +444,7 @@ void QWindowsTheme::refreshFonts()
m_fonts[MdiSubWindowTitleFont] = new QFont(titleFont);
m_fonts[DockWidgetTitleFont] = new QFont(titleFont);
m_fonts[ItemViewFont] = new QFont(iconTitleFont);
+ m_fonts[FixedFont] = new QFont(fixedFont);
if (QWindowsContext::verboseTheming)
qDebug() << __FUNCTION__ << '\n'
@@ -573,11 +594,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;
}
@@ -601,7 +635,40 @@ public:
void operator delete (void *) {}
};
-QPixmap QWindowsTheme::fileIconPixmap(const QFileInfo &fileInfo, const QSizeF &size) const
+// 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
{
/* We don't use the variable, but by storing it statically, we
* ensure CoInitialize is only called once. */
@@ -610,17 +677,26 @@ QPixmap QWindowsTheme::fileIconPixmap(const QFileInfo &fileInfo, const QSizeF &s
static QCache<QString, FakePointer<int> > dirIconEntryCache(1000);
static QMutex mx;
+ static int defaultFolderIIcon = 0;
+ const bool useDefaultFolderIcon = iconOptions & QPlatformTheme::DontUseCustomDirectoryIcons;
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 = **dirIconEntryCache.object(filePath);
+ 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
@@ -635,15 +711,26 @@ QPixmap QWindowsTheme::fileIconPixmap(const QFileInfo &fileInfo, const QSizeF &s
#else
iconSize|SHGFI_SYSICONINDEX;
#endif // Q_OS_WINCE
- unsigned long val = SHGetFileInfo((const wchar_t *)filePath.utf16(), 0,
- &info, sizeof(SHFILEINFO), flags);
+ unsigned long val = 0;
+ if (cacheableDirIcon && useDefaultFolderIcon) {
+ flags |= SHGFI_USEFILEATTRIBUTES;
+ val = SHGetFileInfo(L"dummy",
+ FILE_ATTRIBUTE_DIRECTORY,
+ &info, sizeof(SHFILEINFO), flags);
+ } else {
+ val = SHGetFileInfo(reinterpret_cast<const wchar_t *>(filePath.utf16()), 0,
+ &info, sizeof(SHFILEINFO), flags);
+ }
// Even if GetFileInfo returns a valid result, hIcon can be empty in some cases
if (val && info.hIcon) {
QString key;
if (cacheableDirIcon) {
+ if (useDefaultFolderIcon && !defaultFolderIIcon)
+ 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);
@@ -652,7 +739,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);