QtPlatformSupport: Add QAbstractFileIconEngine
Move the code from QtWidgets/QFileIconEngine into a new class with virtuals in QtPlatformSupport so that platforms can reuse it. Prototypically use the class in the Windows and macOS QPA plugins. Remove QPlatformTheme::fileIconPixmap() and change the type of the hint QPlatformTheme::IconPixmapSizes from QList<int> to QList<QSize> so that it fits better with the icon code. Change-Id: I580e936f3507218757565ca099272cd575b3a779 Reviewed-by: Olivier Goffart (Woboq GmbH) <ogoffart@woboq.com>bb10
parent
955b2bdfc0
commit
2cd2cba086
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
@ -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
|
||||
|
|
@ -1,3 +1,9 @@
|
|||
unix:!mac {
|
||||
include($$PWD/genericunix/genericunix.pri)
|
||||
}
|
||||
|
||||
HEADERS += \
|
||||
$$PWD/qabstractfileiconengine_p.h
|
||||
|
||||
SOURCES += \
|
||||
$$PWD/qabstractfileiconengine.cpp
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
|
|
|
|||
|
|
@ -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) {}
|
||||
|
||||
NSImage *iconImage = [[NSWorkspace sharedWorkspace] iconForFile:QCFString::toNSString(fileInfo.canonicalFilePath())];
|
||||
if (!iconImage)
|
||||
return QPixmap();
|
||||
return qt_mac_toQPixmap(iconImage, size);
|
||||
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(); }
|
||||
|
||||
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:
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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));
|
||||
}
|
||||
|
||||
/*!
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
}
|
||||
|
||||
|
|
|
|||
Loading…
Reference in New Issue