fixup! refactor: speed up FaviconCache::add() again. (#1402)

This commit is contained in:
Charles Kerr 2020-09-02 19:28:36 -05:00
parent 848125d6d8
commit 0bd915c34c
5 changed files with 21 additions and 160 deletions

View File

@ -171,7 +171,10 @@ QVariant FileTreeItem::data(int column, int role) const
} }
else else
{ {
value = IconCache::get().guessMimeIcon(name()); auto& icon_cache = IconCache::get();
value = childCount() > 0 ?
icon_cache.folderIcon() :
icon_cache.guessMimeIcon(name(), icon_cache.fileIcon());
} }
} }

View File

@ -41,16 +41,16 @@ IconCache& IconCache::get()
IconCache::IconCache() : IconCache::IconCache() :
folder_icon_(QFileIconProvider().icon(QFileIconProvider::Folder)), folder_icon_(QFileIconProvider().icon(QFileIconProvider::Folder)),
file_icon_(QFileIconProvider().icon(QFileIconProvider::Folder)) file_icon_(QFileIconProvider().icon(QFileIconProvider::File))
{ {
} }
QIcon IconCache::guessMimeIcon(QString const& filename) const QIcon IconCache::guessMimeIcon(QString const& filename, QIcon fallback) const
{ {
#ifdef _WIN32
QIcon icon; QIcon icon;
#ifdef _WIN32
if (!filename.isEmpty()) if (!filename.isEmpty())
{ {
QFileInfo const file_info(filename); QFileInfo const file_info(filename);
@ -60,13 +60,18 @@ QIcon IconCache::guessMimeIcon(QString const& filename) const
addAssociatedFileIcon(file_info, SHGFI_LARGEICON, icon); addAssociatedFileIcon(file_info, SHGFI_LARGEICON, icon);
} }
return icon;
#else #else
return getMimeIcon(filename); icon = getMimeIcon(filename, fallback);
#endif #endif
if (icon.isNull())
{
icon = fallback;
}
return icon;
} }
/*** /***
@ -111,8 +116,6 @@ void IconCache::addAssociatedFileIcon(QFileInfo const& file_info, UINT icon_size
QIcon IconCache::getMimeIcon(QString const& filename) const QIcon IconCache::getMimeIcon(QString const& filename) const
{ {
// If the suffix doesn't match a mime type, treat it as a folder.
// This heuristic is fast and yields good results for torrent names.
if (suffixes_.empty()) if (suffixes_.empty())
{ {
for (auto const& type : QMimeDatabase().allMimeTypes()) for (auto const& type : QMimeDatabase().allMimeTypes())
@ -125,7 +128,7 @@ QIcon IconCache::getMimeIcon(QString const& filename) const
auto const ext = QFileInfo(filename).suffix(); auto const ext = QFileInfo(filename).suffix();
if (suffixes_.count(ext) == 0) if (suffixes_.count(ext) == 0)
{ {
return folder_icon_; return {};
} }
QIcon& icon = icon_cache_[ext]; QIcon& icon = icon_cache_[ext];
@ -145,7 +148,7 @@ QIcon IconCache::getMimeIcon(QString const& filename) const
if (icon.isNull()) if (icon.isNull())
{ {
icon = file_icon_; icon = {};
} }
} }

View File

@ -29,7 +29,7 @@ public:
QIcon folderIcon() const { return folder_icon_; } QIcon folderIcon() const { return folder_icon_; }
QIcon fileIcon() const { return file_icon_; } QIcon fileIcon() const { return file_icon_; }
QIcon guessMimeIcon(QString const& filename) const; QIcon guessMimeIcon(QString const& filename, QIcon fallback = {}) const;
protected: protected:
IconCache(); IconCache();

View File

@ -173,11 +173,11 @@ void Torrent::updateMimeIcon()
} }
else if (files.size() == 1) else if (files.size() == 1)
{ {
icon = icon_cache.guessMimeIcon(files.at(0).filename); icon = icon_cache.guessMimeIcon(files.at(0).filename, icon_cache.fileIcon());
} }
else else
{ {
icon = icon_cache.guessMimeIcon(name()); icon = icon_cache.guessMimeIcon(name(), icon_cache.folderIcon());
} }
icon_ = icon; icon_ = icon;

View File

@ -52,153 +52,8 @@ bool isSlashChar(QChar const& c)
return c == QLatin1Char('/') || c == QLatin1Char('\\'); return c == QLatin1Char('/') || c == QLatin1Char('\\');
} }
#if 0
QIcon folderIcon()
{
static QIcon icon;
if (icon.isNull())
{
icon = QFileIconProvider().icon(QFileIconProvider::Folder);
}
return icon;
}
QIcon fileIcon()
{
static QIcon icon;
if (icon.isNull())
{
icon = QFileIconProvider().icon(QFileIconProvider::File);
}
return icon;
}
#ifdef _WIN32
void addAssociatedFileIcon(QFileInfo const& file_info, UINT icon_size, QIcon& icon)
{
QString const pixmap_cache_key = QStringLiteral("tr_file_ext_") + QString::number(icon_size) + QLatin1Char('_') +
file_info.suffix();
QPixmap pixmap;
if (!QPixmapCache::find(pixmap_cache_key, &pixmap))
{
auto const filename = file_info.fileName().toStdWString();
SHFILEINFO shell_file_info;
if (::SHGetFileInfoW(filename.data(), FILE_ATTRIBUTE_NORMAL, &shell_file_info,
sizeof(shell_file_info), SHGFI_ICON | icon_size | SHGFI_USEFILEATTRIBUTES) != 0)
{
if (shell_file_info.hIcon != nullptr)
{
pixmap = QtWin::fromHICON(shell_file_info.hIcon);
::DestroyIcon(shell_file_info.hIcon);
}
}
QPixmapCache::insert(pixmap_cache_key, pixmap);
}
if (!pixmap.isNull())
{
icon.addPixmap(pixmap);
}
}
#else
std::unordered_map<QString, QIcon> icon_cache;
QIcon getMimeIcon(QString const& filename)
{
// If the suffix doesn't match a mime type, treat it as a folder.
// This heuristic is fast and yields good results for torrent names.
static std::unordered_set<QString> suffixes;
if (suffixes.empty())
{
for (auto const& type : QMimeDatabase().allMimeTypes())
{
auto const tmp = type.suffixes();
suffixes.insert(tmp.begin(), tmp.end());
}
}
QString const ext = QFileInfo(filename).suffix();
if (suffixes.count(ext) == 0)
{
return folderIcon();
}
QIcon& icon = icon_cache[ext];
if (icon.isNull()) // cache miss
{
QMimeDatabase mime_db;
QMimeType type = mime_db.mimeTypeForFile(filename, QMimeDatabase::MatchExtension);
if (icon.isNull())
{
icon = QIcon::fromTheme(type.iconName());
}
if (icon.isNull())
{
icon = QIcon::fromTheme(type.genericIconName());
}
if (icon.isNull())
{
icon = fileIcon();
}
}
return icon;
}
#endif
#endif
} // namespace } // namespace
#if 0
QIcon Utils::getFolderIcon()
{
return folderIcon();
}
QIcon Utils::getFileIcon()
{
return fileIcon();
}
QIcon Utils::guessMimeIcon(QString const& filename)
{
#ifdef _WIN32
QIcon icon;
if (!filename.isEmpty())
{
QFileInfo const file_info(filename);
addAssociatedFileIcon(file_info, SHGFI_SMALLICON, icon);
addAssociatedFileIcon(file_info, 0, icon);
addAssociatedFileIcon(file_info, SHGFI_LARGEICON, icon);
}
return icon;
#else
return getMimeIcon(filename);
#endif
}
#endif
QIcon Utils::getIconFromIndex(QModelIndex const& index) QIcon Utils::getIconFromIndex(QModelIndex const& index)
{ {
QVariant const variant = index.data(Qt::DecorationRole); QVariant const variant = index.data(Qt::DecorationRole);