FileIconProvider: Load icons and create overlay lazily

If the icon is registered via file path, not the icon directly, we can
delay loading the icon and creating the overlay to until it is actually
needed.

Change-Id: Icfdc30ac0b717ff566a1064e4791e4bb23814958
Reviewed-by: hjk <hjk@qt.io>
This commit is contained in:
Eike Ziller
2019-11-15 14:12:26 +01:00
parent dd93820fdd
commit 349de159c9
2 changed files with 55 additions and 34 deletions

View File

@@ -27,7 +27,9 @@
#include <utils/hostosinfo.h>
#include <utils/mimetypes/mimedatabase.h>
#include <utils/optional.h>
#include <utils/qtcassert.h>
#include <utils/variant.h>
#include <QApplication>
#include <QStyle>
@@ -56,14 +58,29 @@ using namespace Utils;
retrieve icons via the icon() function.
*/
// Cache icons in a list of pairs suffix/icon which should be faster than
// hashes for small lists.
using Item = Utils::variant<QIcon, QString>; // icon or filename for the icon
namespace Core {
namespace FileIconProvider {
enum { debug = 0 };
static Utils::optional<QIcon> getIcon(QHash<QString, Item> &cache, const QString &key)
{
auto it = cache.constFind(key);
if (it == cache.constEnd())
return {};
if (const QIcon *icon = Utils::get_if<QIcon>(&*it))
return *icon;
// need to create icon from file name first
const QString *fileName = Utils::get_if<QString>(&*it);
QTC_ASSERT(fileName, return {});
const QIcon icon = QIcon(
FileIconProvider::overlayIcon(QStyle::SP_FileIcon, QIcon(*fileName), QSize(16, 16)));
cache.insert(key, icon);
return icon;
}
class FileIconProviderImplementation : public QFileIconProvider
{
public:
@@ -73,35 +90,39 @@ public:
QIcon icon(const QFileInfo &info) const override;
using QFileIconProvider::icon;
void registerIconOverlayForFilename(const QIcon &icon, const QString &filename)
void registerIconOverlayForFilename(const QString &iconFilePath, const QString &filename)
{
QTC_ASSERT(!icon.isNull() && !filename.isEmpty(), return);
const QPixmap fileIconPixmap = FileIconProvider::overlayIcon(QStyle::SP_FileIcon, icon, QSize(16, 16));
m_filenameCache.insert(filename, fileIconPixmap);
m_filenameCache.insert(filename, iconFilePath);
}
void registerIconOverlayForSuffix(const QIcon &icon, const QString &suffix)
void registerIconOverlayForSuffix(const QString &iconFilePath, const QString &suffix)
{
if (debug)
qDebug() << "FileIconProvider::registerIconOverlayForSuffix" << suffix;
QTC_ASSERT(!icon.isNull() && !suffix.isEmpty(), return);
const QPixmap fileIconPixmap = FileIconProvider::overlayIcon(QStyle::SP_FileIcon, icon, QSize(16, 16));
// replace old icon, if it exists
m_suffixCache.insert(suffix, fileIconPixmap);
m_suffixCache.insert(suffix, iconFilePath);
}
void registerIconOverlayForMimeType(const QIcon &icon, const Utils::MimeType &mimeType)
{
const QStringList suffixes = mimeType.suffixes();
for (const QString &suffix : suffixes) {
QTC_ASSERT(!icon.isNull() && !suffix.isEmpty(), return );
const QPixmap fileIconPixmap = FileIconProvider::overlayIcon(QStyle::SP_FileIcon,
icon,
QSize(16, 16));
// replace old icon, if it exists
m_suffixCache.insert(suffix, fileIconPixmap);
}
}
void registerIconOverlayForMimeType(const QString &iconFilePath, const Utils::MimeType &mimeType)
{
foreach (const QString &suffix, mimeType.suffixes())
registerIconOverlayForSuffix(icon, suffix);
registerIconOverlayForSuffix(iconFilePath, suffix);
}
// Mapping of file suffix to icon.
mutable QHash<QString, QIcon> m_suffixCache;
QHash<QString, QIcon> m_filenameCache;
mutable QHash<QString, Item> m_suffixCache;
mutable QHash<QString, Item> m_filenameCache;
};
FileIconProviderImplementation *instance()
@@ -123,15 +144,15 @@ QIcon FileIconProviderImplementation::icon(const QFileInfo &fileInfo) const
bool isDir = fileInfo.isDir();
const QString filename = !isDir ? fileInfo.fileName() : QString();
if (!filename.isEmpty()) {
auto it = m_filenameCache.constFind(filename);
if (it != m_filenameCache.constEnd())
return it.value();
const Utils::optional<QIcon> icon = getIcon(m_filenameCache, filename);
if (icon)
return *icon;
}
const QString suffix = !isDir ? fileInfo.suffix() : QString();
if (!suffix.isEmpty()) {
auto it = m_suffixCache.constFind(suffix);
if (it != m_suffixCache.constEnd())
return it.value();
const Utils::optional<QIcon> icon = getIcon(m_suffixCache, suffix);
if (icon)
return *icon;
}
// Get icon from OS (and cache it based on suffix!)
@@ -192,7 +213,7 @@ QPixmap overlayIcon(QStyle::StandardPixmap baseIcon, const QIcon &overlay, const
*/
void registerIconOverlayForSuffix(const QString &path, const QString &suffix)
{
instance()->registerIconOverlayForSuffix(QIcon(path), suffix);
instance()->registerIconOverlayForSuffix(path, suffix);
}
/*!
@@ -208,12 +229,12 @@ void registerIconOverlayForMimeType(const QIcon &icon, const QString &mimeType)
*/
void registerIconOverlayForMimeType(const QString &path, const QString &mimeType)
{
instance()->registerIconOverlayForMimeType(QIcon(path), Utils::mimeTypeForName(mimeType));
instance()->registerIconOverlayForMimeType(path, Utils::mimeTypeForName(mimeType));
}
void registerIconOverlayForFilename(const QString &path, const QString &filename)
{
instance()->registerIconOverlayForFilename(QIcon(path), filename);
instance()->registerIconOverlayForFilename(path, filename);
}
// Return a standard directory icon with the specified overlay:

View File

@@ -296,14 +296,14 @@ void CppEditorPlugin::extensionsInitialized()
if (!HostOsInfo::isMacHost() && !HostOsInfo::isWindowsHost()) {
FileIconProvider::registerIconOverlayForMimeType(
QIcon(creatorTheme()->imageFile(Theme::IconOverlayCppSource, QLatin1String(":/cppeditor/images/qt_cpp.png"))),
CppTools::Constants::CPP_SOURCE_MIMETYPE);
creatorTheme()->imageFile(Theme::IconOverlayCppSource, ":/cppeditor/images/qt_cpp.png"),
CppTools::Constants::CPP_SOURCE_MIMETYPE);
FileIconProvider::registerIconOverlayForMimeType(
QIcon(creatorTheme()->imageFile(Theme::IconOverlayCSource, QLatin1String(":/cppeditor/images/qt_c.png"))),
CppTools::Constants::C_SOURCE_MIMETYPE);
creatorTheme()->imageFile(Theme::IconOverlayCSource, ":/cppeditor/images/qt_c.png"),
CppTools::Constants::C_SOURCE_MIMETYPE);
FileIconProvider::registerIconOverlayForMimeType(
QIcon(creatorTheme()->imageFile(Theme::IconOverlayCppHeader, QLatin1String(":/cppeditor/images/qt_h.png"))),
CppTools::Constants::CPP_HEADER_MIMETYPE);
creatorTheme()->imageFile(Theme::IconOverlayCppHeader, ":/cppeditor/images/qt_h.png"),
CppTools::Constants::CPP_HEADER_MIMETYPE);
}
}