diff --git a/src/gui/image/qicon_p.h b/src/gui/image/qicon_p.h index e0fec112b5d927347901a7f59a20352b0c6182fa..8b42e770fac9b205094554830fc6b2f20e9c5f6b 100644 --- a/src/gui/image/qicon_p.h +++ b/src/gui/image/qicon_p.h @@ -99,7 +99,7 @@ inline QPixmapIconEngineEntry::QPixmapIconEngineEntry(const QString &file, const pixmap.setDevicePixelRatio(1.0); } -class QPixmapIconEngine : public QIconEngine { +class Q_GUI_EXPORT QPixmapIconEngine : public QIconEngine { public: QPixmapIconEngine(); QPixmapIconEngine(const QPixmapIconEngine &); diff --git a/src/widgets/itemviews/qfileiconprovider.cpp b/src/widgets/itemviews/qfileiconprovider.cpp index d1bd0e657e9369f789c04e1bc98e66d5fef57ed1..740bd853b7a63237ff4b90c66554110492e5db90 100644 --- a/src/widgets/itemviews/qfileiconprovider.cpp +++ b/src/widgets/itemviews/qfileiconprovider.cpp @@ -39,6 +39,7 @@ #include <qpixmapcache.h> #include <private/qfunctions_p.h> #include <private/qguiapplication_p.h> +#include <private/qicon_p.h> #include <qpa/qplatformintegration.h> #include <qpa/qplatformservices.h> #include <qpa/qplatformtheme.h> @@ -57,6 +58,88 @@ QT_BEGIN_NAMESPACE +static bool isCacheable(const QFileInfo &fi); + +class QFileIconEngine : public QPixmapIconEngine +{ +public: + QFileIconEngine(const QFileIconProvider *fip, const QFileInfo &info) + : QPixmapIconEngine(), m_fileIconProvider(fip), m_fileInfo(info) + { } + + 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; + } + + QPlatformTheme::IconOptions iconOptions; + if (m_fileIconProvider->options() & QFileIconProvider::DontUseCustomDirectoryIcons) + iconOptions |= QPlatformTheme::DontUseCustomDirectoryIcons; + + pixmap = theme->fileIconPixmap(m_fileInfo, size, iconOptions); + 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; + + 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); + foreach (const QSize &availableSize, sizes) { + if (availableSize.width() >= size.width()) + return availableSize; + } + + return sizes.last(); + } + +private: + const QFileIconProvider *m_fileIconProvider; + QFileInfo m_fileInfo; +}; + + /*! \class QFileIconProvider @@ -86,8 +169,8 @@ QT_BEGIN_NAMESPACE cause a big performance impact over network or removable drives. */ -QFileIconProviderPrivate::QFileIconProviderPrivate() : - homePath(QDir::home().absolutePath()) +QFileIconProviderPrivate::QFileIconProviderPrivate(QFileIconProvider *q) : + q_ptr(q), homePath(QDir::home().absolutePath()) { } @@ -153,7 +236,7 @@ QIcon QFileIconProviderPrivate::getIcon(QStyle::StandardPixmap name) const */ QFileIconProvider::QFileIconProvider() - : d_ptr(new QFileIconProviderPrivate) + : d_ptr(new QFileIconProviderPrivate(this)) { } @@ -238,53 +321,10 @@ static bool isCacheable(const QFileInfo &fi) QIcon QFileIconProviderPrivate::getIcon(const QFileInfo &fi) const { - QIcon retIcon; - const QPlatformTheme *theme = QGuiApplicationPrivate::platformTheme(); - if (!theme) - return retIcon; - - QList<int> sizes = theme->themeHint(QPlatformTheme::IconPixmapSizes).value<QList<int> >(); - if (sizes.isEmpty()) - return retIcon; - - const QString keyBase = QLatin1String("qt_.") + fi.suffix().toUpper(); - - bool cacheable = isCacheable(fi); - if (cacheable) { - QPixmap pixmap; - QPixmapCache::find(keyBase + QString::number(sizes.at(0)), pixmap); - if (!pixmap.isNull()) { - bool iconIsComplete = true; - retIcon.addPixmap(pixmap); - for (int i = 1; i < sizes.count(); i++) - if (QPixmapCache::find(keyBase + QString::number(sizes.at(i)), pixmap)) { - retIcon.addPixmap(pixmap); - } else { - iconIsComplete = false; - break; - } - if (iconIsComplete) - return retIcon; - } - } - - QPlatformTheme::IconOptions iconOptions; - if (options & QFileIconProvider::DontUseCustomDirectoryIcons) - iconOptions |= QPlatformTheme::DontUseCustomDirectoryIcons; - - Q_FOREACH (int size, sizes) { - QPixmap pixmap = theme->fileIconPixmap(fi, QSizeF(size, size), iconOptions); - if (!pixmap.isNull()) { - retIcon.addPixmap(pixmap); - if (cacheable) - QPixmapCache::insert(keyBase + QString::number(size), pixmap); - } - } - - return retIcon; + Q_Q(const QFileIconProvider); + return QIcon(new QFileIconEngine(q, fi)); } - /*! Returns an icon for the file described by \a info. */ diff --git a/src/widgets/itemviews/qfileiconprovider_p.h b/src/widgets/itemviews/qfileiconprovider_p.h index 213535616ce083ac4f73516c01f97a0bb44e70a4..a1fb4acbea773f13fc679bcd85e459ed19bcd60b 100644 --- a/src/widgets/itemviews/qfileiconprovider_p.h +++ b/src/widgets/itemviews/qfileiconprovider_p.h @@ -60,7 +60,7 @@ class QFileIconProviderPrivate Q_DECLARE_PUBLIC(QFileIconProvider) public: - QFileIconProviderPrivate(); + QFileIconProviderPrivate(QFileIconProvider *q); QIcon getIcon(QStyle::StandardPixmap name) const; QIcon getIcon(const QFileInfo &fi) const;