Cache null icons and remove them upon system icon theme change

Since Qt 6, qIconCache does not store null icons. In case an icon name
lookup is unsuccessful, the (expensive) lookup is repeated each time.

This patch reverts 9e7c567050, which
removes a null icon from the cache once it has been found in the cache.
In fact, that could no longer happen due to
4dc7102c84, which prevented null icons
from being cached at all. Therefore, it is also reverted by this patch.

The cache will be cleared when
- the system icon theme name changes or
- QGuiApplicationPrivate::processThemeChanged is called (e.g. due to
a change of the system's color scheme)

Fixes: QTBUG-112257
Pick-to: 6.5
Change-Id: I80cd21fa39dc31c4bae60a8e66e78d9da20e9b4b
Reviewed-by: Qt CI Bot <qt_ci_bot@qt-project.org>
Reviewed-by: Volker Hilsheimer <volker.hilsheimer@qt.io>
This commit is contained in:
Axel Spoerl 2023-04-06 16:54:00 +02:00
parent 70f9158e0f
commit 74a4f9cb05
5 changed files with 24 additions and 8 deletions

View File

@ -98,6 +98,11 @@ QIconPrivate::QIconPrivate(QIconEngine *e)
{
}
void QIconPrivate::clearIconCache()
{
qt_cleanup_icon_cache();
}
/*! \internal
Computes the displayDevicePixelRatio for a pixmap.
@ -1277,11 +1282,8 @@ void QIcon::setFallbackThemeName(const QString &name)
QIcon QIcon::fromTheme(const QString &name)
{
if (QIcon *cachedIcon = qtIconCache()->object(name)) {
if (!cachedIcon->isNull())
return *cachedIcon;
qtIconCache()->remove(name);
}
if (QIcon *cachedIcon = qtIconCache()->object(name))
return *cachedIcon;
QIcon icon;
if (QDir::isAbsolutePath(name)) {
@ -1292,8 +1294,7 @@ QIcon QIcon::fromTheme(const QString &name)
QIconEngine * const engine = (platformTheme && !hasUserTheme) ? platformTheme->createIconEngine(name)
: new QIconLoaderEngine(name);
icon = QIcon(engine);
if (!icon.isNull())
qtIconCache()->insert(name, new QIcon(icon));
qtIconCache()->insert(name, new QIcon(icon));
}
return icon;

View File

@ -42,6 +42,8 @@ public:
int serialNum;
int detach_no;
bool is_mask;
static void clearIconCache();
};

View File

@ -125,8 +125,18 @@ void QIconLoader::updateSystemTheme()
}
}
void QIconLoader::invalidateKey()
{
m_themeKey++;
QIconPrivate::clearIconCache();
}
void QIconLoader::setThemeName(const QString &themeName)
{
if (m_userTheme == themeName)
return;
m_userTheme = themeName;
invalidateKey();
}

View File

@ -158,7 +158,7 @@ public:
QIconDirInfo dirInfo(int dirindex);
static QIconLoader *instance();
void updateSystemTheme();
void invalidateKey() { m_themeKey++; }
void invalidateKey();
void ensureInitialized();
bool hasUserTheme() const { return !m_userTheme.isEmpty(); }

View File

@ -50,6 +50,7 @@
#include <qpa/qwindowsysteminterface.h>
#include <qpa/qwindowsysteminterface_p.h>
#include "private/qwindow_p.h"
#include "private/qicon_p.h"
#include "private/qcursor_p.h"
#if QT_CONFIG(opengl)
# include "private/qopenglcontext_p.h"
@ -2616,6 +2617,8 @@ void QGuiApplicationPrivate::processThemeChanged(QWindowSystemInterfacePrivate::
if (self)
self->handleThemeChanged();
QIconPrivate::clearIconCache();
QEvent themeChangeEvent(QEvent::ThemeChange);
const QWindowList windows = tce->window ? QWindowList{tce->window} : window_list;
for (auto *window : windows)