summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--src/gui/kernel/qplatformtheme.cpp10
-rw-r--r--src/gui/kernel/qplatformtheme.h3
-rw-r--r--src/platformsupport/themes/qabstractfileiconengine.cpp130
-rw-r--r--src/platformsupport/themes/qabstractfileiconengine_p.h96
-rw-r--r--src/platformsupport/themes/themes.pri6
-rw-r--r--src/plugins/platforms/cocoa/qcocoatheme.h4
-rw-r--r--src/plugins/platforms/cocoa/qcocoatheme.mm53
-rw-r--r--src/plugins/platforms/windows/qwindowstheme.cpp78
-rw-r--r--src/plugins/platforms/windows/qwindowstheme.h11
-rw-r--r--src/widgets/itemviews/qfileiconprovider.cpp134
-rw-r--r--src/widgets/styles/qcommonstyle.cpp10
11 files changed, 347 insertions, 188 deletions
diff --git a/src/gui/kernel/qplatformtheme.cpp b/src/gui/kernel/qplatformtheme.cpp
index a00c572e07..d80ab8b597 100644
--- a/src/gui/kernel/qplatformtheme.cpp
+++ b/src/gui/kernel/qplatformtheme.cpp
@@ -424,16 +424,6 @@ QIcon QPlatformTheme::fileIcon(const QFileInfo &fileInfo, QPlatformTheme::IconOp
return QIcon();
}
-QPixmap QPlatformTheme::fileIconPixmap(const QFileInfo &fileInfo, const QSizeF &size,
- QPlatformTheme::IconOptions iconOptions) const
-{
- Q_UNUSED(fileInfo);
- Q_UNUSED(size);
- Q_UNUSED(iconOptions);
- // TODO Should return QCommonStyle pixmaps?
- return QPixmap();
-}
-
QVariant QPlatformTheme::themeHint(ThemeHint hint) const
{
// For theme hints which mirror platform integration style hints, query
diff --git a/src/gui/kernel/qplatformtheme.h b/src/gui/kernel/qplatformtheme.h
index c04ebd2190..a8baca1967 100644
--- a/src/gui/kernel/qplatformtheme.h
+++ b/src/gui/kernel/qplatformtheme.h
@@ -304,9 +304,6 @@ public:
virtual QPixmap standardPixmap(StandardPixmap sp, const QSizeF &size) const;
virtual QIcon fileIcon(const QFileInfo &fileInfo,
QPlatformTheme::IconOptions iconOptions = 0) const;
- virtual QPixmap fileIconPixmap(const QFileInfo &fileInfo, const QSizeF &size,
- QPlatformTheme::IconOptions iconOptions = 0) const;
-
virtual QIconEngine *createIconEngine(const QString &iconName) const;
virtual QList<QKeySequence> keyBindings(QKeySequence::StandardKey key) const;
diff --git a/src/platformsupport/themes/qabstractfileiconengine.cpp b/src/platformsupport/themes/qabstractfileiconengine.cpp
new file mode 100644
index 0000000000..19a8eee47b
--- /dev/null
+++ b/src/platformsupport/themes/qabstractfileiconengine.cpp
@@ -0,0 +1,130 @@
+/****************************************************************************
+**
+** Copyright (C) 2016 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of the plugins of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 3 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL3 included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 3 requirements
+** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 2.0 or (at your option) the GNU General
+** Public license version 3 or any later version approved by the KDE Free
+** Qt Foundation. The licenses are as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-2.0.html and
+** https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "qabstractfileiconengine_p.h"
+
+#include <qpixmapcache.h>
+
+QT_BEGIN_NAMESPACE
+
+/*!
+ \class QAbstractFileIconEngine
+ \brief Helper base class for retrieving icons for files for usage by QFileIconProvider and related.
+
+ Reimplement availableSizes() and new virtual filePixmap() and return icons created
+ with this engine from QPlatformTheme::fileIcon().
+
+ Note: The class internally caches pixmaps for files by suffix (with the exception
+ of some files on Windows), but not for directories (since directory icons may have
+ overlay icons on Windows). You might want to cache pixmaps for directories
+ in your implementation.
+
+ \since 5.8
+ \internal
+ \sa QFileIconProvider::DontUseCustomDirectoryIcons, QPlatformTheme
+ \ingroup qpa
+*/
+QPixmap QAbstractFileIconEngine::pixmap(const QSize &size, QIcon::Mode mode,
+ QIcon::State state)
+{
+ Q_UNUSED(mode);
+ Q_UNUSED(state);
+
+ if (!size.isValid())
+ return QPixmap();
+
+ QString key = cacheKey();
+ if (key.isEmpty())
+ return filePixmap(size, mode, state);
+
+ key += QLatin1Char('_');
+ key += QString::number(size.width());
+
+ QPixmap result;
+ if (!QPixmapCache::find(key, result)) {
+ result = filePixmap(size, mode, state);
+ if (!result.isNull())
+ QPixmapCache::insert(key, result);
+ }
+
+ return result;
+}
+
+QSize QAbstractFileIconEngine::actualSize(const QSize &size, QIcon::Mode mode,
+ QIcon::State state)
+{
+ const QList<QSize> &sizes = availableSizes(mode, state);
+ const int numberSizes = sizes.length();
+ if (numberSizes == 0)
+ return QSize();
+
+ // Find the smallest available size whose area is still larger than the input
+ // size. Otherwise, use the largest area available size. (We don't assume the
+ // platform theme sizes are sorted, hence the extra logic.)
+ const int sizeArea = size.width() * size.height();
+ QSize actualSize = sizes.first();
+ int actualArea = actualSize.width() * actualSize.height();
+ for (int i = 1; i < numberSizes; ++i) {
+ const QSize &s = sizes.at(i);
+ const int a = s.width() * s.height();
+ if ((sizeArea <= a && a < actualArea) || (actualArea < sizeArea && actualArea < a)) {
+ actualSize = s;
+ actualArea = a;
+ }
+ }
+
+ if (!actualSize.isNull() && (actualSize.width() > size.width() || actualSize.height() > size.height()))
+ actualSize.scale(size, Qt::KeepAspectRatio);
+
+ return actualSize;
+}
+
+/* Reimplement to return a cache key for the entry. An empty result indicates
+ * the icon should not be cached (for example, directory icons having custom icons). */
+QString QAbstractFileIconEngine::cacheKey() const
+{
+ if (!m_fileInfo.isFile() || m_fileInfo.isSymLink() || m_fileInfo.isExecutable())
+ return QString();
+
+ const QString &suffix = m_fileInfo.suffix();
+ return QLatin1String("qt_.")
+ + (suffix.isEmpty() ? m_fileInfo.fileName() : suffix); // handle "Makefile" ;)
+}
+
+QT_END_NAMESPACE
diff --git a/src/platformsupport/themes/qabstractfileiconengine_p.h b/src/platformsupport/themes/qabstractfileiconengine_p.h
new file mode 100644
index 0000000000..ce38cf262e
--- /dev/null
+++ b/src/platformsupport/themes/qabstractfileiconengine_p.h
@@ -0,0 +1,96 @@
+/****************************************************************************
+**
+** Copyright (C) 2016 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of the plugins of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 3 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL3 included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 3 requirements
+** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 2.0 or (at your option) the GNU General
+** Public license version 3 or any later version approved by the KDE Free
+** Qt Foundation. The licenses are as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-2.0.html and
+** https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef QABSTRACTFILEICONENGINE_P_H
+#define QABSTRACTFILEICONENGINE_P_H
+
+//
+// W A R N I N G
+// -------------
+//
+// This file is not part of the Qt API. It exists purely as an
+// implementation detail. This header file may change from version to
+// version without notice, or even be removed.
+//
+// We mean it.
+//
+
+#include <QtCore/qfileinfo.h>
+#include <private/qicon_p.h>
+#include <qpa/qplatformtheme.h>
+
+QT_BEGIN_NAMESPACE
+
+class QAbstractFileIconEngine : public QPixmapIconEngine
+{
+public:
+ explicit QAbstractFileIconEngine(const QFileInfo &info, QPlatformTheme::IconOptions opts)
+ : QPixmapIconEngine(), m_fileInfo(info), m_options(opts) {}
+
+ QPixmap pixmap(const QSize &size, QIcon::Mode mode, QIcon::State) override;
+ QSize actualSize(const QSize &size, QIcon::Mode mode, QIcon::State state) override;
+
+ QFileInfo fileInfo() const { return m_fileInfo; }
+ QPlatformTheme::IconOptions options() const { return m_options; }
+
+ // Helper to convert a sequence of ints to a list of QSize
+ template <class It> static QList<QSize> toSizeList(It i1, It i2);
+
+protected:
+ virtual QPixmap filePixmap(const QSize &size, QIcon::Mode mode, QIcon::State) = 0;
+ virtual QString cacheKey() const;
+
+private:
+ const QFileInfo m_fileInfo;
+ const QPlatformTheme::IconOptions m_options;
+};
+
+template <class It>
+inline QList<QSize> QAbstractFileIconEngine::toSizeList(It i1, It i2)
+{
+ QList<QSize> result;
+ result.reserve(int(i2 - i1));
+ for ( ; i1 != i2; ++i1)
+ result.append(QSize(*i1, *i1));
+ return result;
+}
+
+QT_END_NAMESPACE
+
+#endif // QABSTRACTFILEICONENGINE_P_H
diff --git a/src/platformsupport/themes/themes.pri b/src/platformsupport/themes/themes.pri
index adee852626..552973431f 100644
--- a/src/platformsupport/themes/themes.pri
+++ b/src/platformsupport/themes/themes.pri
@@ -1,3 +1,9 @@
unix:!mac {
include($$PWD/genericunix/genericunix.pri)
}
+
+HEADERS += \
+ $$PWD/qabstractfileiconengine_p.h
+
+SOURCES += \
+ $$PWD/qabstractfileiconengine.cpp
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
diff --git a/src/widgets/itemviews/qfileiconprovider.cpp b/src/widgets/itemviews/qfileiconprovider.cpp
index 5638e438d5..8c3cf3859e 100644
--- a/src/widgets/itemviews/qfileiconprovider.cpp
+++ b/src/widgets/itemviews/qfileiconprovider.cpp
@@ -60,110 +60,6 @@
QT_BEGIN_NAMESPACE
-static bool isCacheable(const QFileInfo &fi);
-
-static QPlatformTheme::IconOptions toThemeIconOptions(QFileIconProvider::Options options)
-{
- QPlatformTheme::IconOptions result;
- if (options & QFileIconProvider::DontUseCustomDirectoryIcons)
- result |= QPlatformTheme::DontUseCustomDirectoryIcons;
- return result;
-}
-
-class QFileIconEngine : public QPixmapIconEngine
-{
-public:
- QFileIconEngine(const QFileInfo &info, QFileIconProvider::Options opts)
- : QPixmapIconEngine(), m_fileInfo(info), m_fipOpts(opts)
- { }
-
- QPixmap pixmap(const QSize &size, QIcon::Mode mode, QIcon::State state) Q_DECL_OVERRIDE
- {
- Q_UNUSED(mode);
- Q_UNUSED(state);
- QPixmap pixmap;
-
- if (!size.isValid())
- return pixmap;
-
- const QPlatformTheme *theme = QGuiApplicationPrivate::platformTheme();
- if (!theme)
- return pixmap;
-
- const QString &keyBase = QLatin1String("qt_.") + m_fileInfo.suffix().toUpper();
-
- bool cacheable = isCacheable(m_fileInfo);
- if (cacheable) {
- QPixmapCache::find(keyBase + QString::number(size.width()), pixmap);
- if (!pixmap.isNull())
- return pixmap;
- }
-
- pixmap = theme->fileIconPixmap(m_fileInfo, size, toThemeIconOptions(m_fipOpts));
- if (!pixmap.isNull()) {
- if (cacheable)
- QPixmapCache::insert(keyBase + QString::number(size.width()), pixmap);
- }
-
- return pixmap;
- }
-
- QList<QSize> availableSizes(QIcon::Mode mode = QIcon::Normal, QIcon::State state = QIcon::Off) const Q_DECL_OVERRIDE
- {
- Q_UNUSED(mode);
- Q_UNUSED(state);
- static QList<QSize> sizes;
- static QPlatformTheme *theme = 0;
- if (!theme) {
- theme = QGuiApplicationPrivate::platformTheme();
- if (!theme)
- return sizes;
-
- QList<int> themeSizes = theme->themeHint(QPlatformTheme::IconPixmapSizes).value<QList<int> >();
- if (themeSizes.isEmpty())
- return sizes;
-
- sizes.reserve(themeSizes.count());
- foreach (int size, themeSizes)
- sizes << QSize(size, size);
- }
- return sizes;
- }
-
- QSize actualSize(const QSize &size, QIcon::Mode mode, QIcon::State state) Q_DECL_OVERRIDE
- {
- const QList<QSize> &sizes = availableSizes(mode, state);
- const int numberSizes = sizes.length();
- if (numberSizes == 0)
- return QSize();
-
- // Find the smallest available size whose area is still larger than the input
- // size. Otherwise, use the largest area available size. (We don't assume the
- // platform theme sizes are sorted, hence the extra logic.)
- const int sizeArea = size.width() * size.height();
- QSize actualSize = sizes.first();
- int actualArea = actualSize.width() * actualSize.height();
- for (int i = 1; i < numberSizes; ++i) {
- const QSize &s = sizes.at(i);
- const int a = s.width() * s.height();
- if ((sizeArea <= a && a < actualArea) || (actualArea < sizeArea && actualArea < a)) {
- actualSize = s;
- actualArea = a;
- }
- }
-
- if (!actualSize.isNull() && (actualSize.width() > size.width() || actualSize.height() > size.height()))
- actualSize.scale(size, Qt::KeepAspectRatio);
-
- return actualSize;
- }
-
-private:
- QFileInfo m_fileInfo;
- QFileIconProvider::Options m_fipOpts;
-};
-
-
/*!
\class QFileIconProvider
@@ -326,35 +222,17 @@ QIcon QFileIconProvider::icon(IconType type) const
return QIcon();
}
-static bool isCacheable(const QFileInfo &fi)
+static inline QPlatformTheme::IconOptions toThemeIconOptions(QFileIconProvider::Options options)
{
- if (!fi.isFile())
- return false;
-
-#ifdef Q_OS_WIN
- // On windows it's faster to just look at the file extensions. QTBUG-13182
- const QString fileExtension = fi.suffix();
- // Will return false for .exe, .lnk and .ico extensions
- return fileExtension.compare(QLatin1String("exe"), Qt::CaseInsensitive) &&
- fileExtension.compare(QLatin1String("lnk"), Qt::CaseInsensitive) &&
- fileExtension.compare(QLatin1String("ico"), Qt::CaseInsensitive);
-#else
- return !fi.isExecutable() && !fi.isSymLink();
-#endif
+ QPlatformTheme::IconOptions result;
+ if (options & QFileIconProvider::DontUseCustomDirectoryIcons)
+ result |= QPlatformTheme::DontUseCustomDirectoryIcons;
+ return result;
}
QIcon QFileIconProviderPrivate::getIcon(const QFileInfo &fi) const
{
- const QPlatformTheme *theme = QGuiApplicationPrivate::platformTheme();
- if (!theme)
- return QIcon();
-
- QIcon themeFileIcon = theme->fileIcon(fi, toThemeIconOptions(options));
- if (!themeFileIcon.isNull())
- return themeFileIcon;
-
- QList<int> sizes = theme->themeHint(QPlatformTheme::IconPixmapSizes).value<QList<int> >();
- return sizes.isEmpty() ? QIcon() : QIcon(new QFileIconEngine(fi, options));
+ return QGuiApplicationPrivate::platformTheme()->fileIcon(fi, toThemeIconOptions(options));
}
/*!
diff --git a/src/widgets/styles/qcommonstyle.cpp b/src/widgets/styles/qcommonstyle.cpp
index 36975c5877..6cdfc061e1 100644
--- a/src/widgets/styles/qcommonstyle.cpp
+++ b/src/widgets/styles/qcommonstyle.cpp
@@ -5913,14 +5913,14 @@ QIcon QCommonStyle::standardIcon(StandardPixmap standardIcon, const QStyleOption
if (const QPlatformTheme *theme = QGuiApplicationPrivate::platformTheme()) {
QPlatformTheme::StandardPixmap sp = static_cast<QPlatformTheme::StandardPixmap>(standardIcon);
QIcon retIcon;
- QList<int> sizes = theme->themeHint(QPlatformTheme::IconPixmapSizes).value<QList<int> >();
- Q_FOREACH (int size, sizes) {
+ const QList<QSize> sizes = theme->themeHint(QPlatformTheme::IconPixmapSizes).value<QList<QSize> >();
+ for (const QSize &size : sizes) {
QPixmap mainIcon;
- const QString cacheKey = QLatin1String("qt_mac_constructQIconFromIconRef") + QString::number(standardIcon) + QString::number(size);
+ const QString cacheKey = QLatin1String("qt_mac_constructQIconFromIconRef") + QString::number(standardIcon) + QString::number(size.width());
if (standardIcon >= QStyle::SP_CustomBase) {
- mainIcon = theme->standardPixmap(sp, QSizeF(size, size));
+ mainIcon = theme->standardPixmap(sp, QSizeF(size));
} else if (QPixmapCache::find(cacheKey, mainIcon) == false) {
- mainIcon = theme->standardPixmap(sp, QSizeF(size, size));
+ mainIcon = theme->standardPixmap(sp, QSizeF(size));
QPixmapCache::insert(cacheKey, mainIcon);
}