Fix excessive memory usage by icons

* Fixes #5240
* Limit size of icons being loaded to prevent excessive memory usage in some cases
* Fix loading database icons, previous method would just overwrite the same pixmap and not actually provide caching.
This commit is contained in:
Jonathan White 2020-08-13 22:33:53 -04:00
parent e96d0429cd
commit a5208959c4
3 changed files with 18 additions and 27 deletions

View File

@ -40,9 +40,6 @@ namespace
DatabaseIcons::DatabaseIcons()
{
// Set the pixmap cache limit to 20 MB
QPixmapCache::setCacheLimit(20480);
iconList = QDir(iconDir).entryList(QDir::NoFilter, QDir::Name);
badgeList = QDir(badgeDir).entryList(QDir::NoFilter, QDir::Name);
@ -70,9 +67,7 @@ QPixmap DatabaseIcons::icon(int index, IconSize size)
auto icon = m_iconCache.value(cacheKey);
if (icon.isNull()) {
icon.addFile(iconDir + iconList[index]);
icon.addPixmap(icon.pixmap(iconSize(IconSize::Default)));
icon.addPixmap(icon.pixmap(iconSize(IconSize::Medium)));
icon.addPixmap(icon.pixmap(iconSize(IconSize::Large)));
icon.addPixmap(icon.pixmap(64));
m_iconCache.insert(cacheKey, icon);
}

View File

@ -379,11 +379,8 @@ void Metadata::addCustomIcon(const QUuid& uuid, const QImage& image)
static bool isGui = qApp->inherits("QGuiApplication");
if (isGui) {
// Generate QIcon with pre-baked resolutions
auto basePixmap = QPixmap::fromImage(image).scaled(128, 128, Qt::IgnoreAspectRatio, Qt::SmoothTransformation);
auto basePixmap = QPixmap::fromImage(image.scaled(64, 64, Qt::IgnoreAspectRatio, Qt::SmoothTransformation));
QIcon icon(basePixmap);
icon.addPixmap(icon.pixmap(databaseIcons()->iconSize(IconSize::Default)));
icon.addPixmap(icon.pixmap(databaseIcons()->iconSize(IconSize::Medium)));
icon.addPixmap(icon.pixmap(databaseIcons()->iconSize(IconSize::Large)));
m_customIcons.insert(uuid, icon);
} else {
m_customIcons.insert(uuid, QIcon());

View File

@ -164,7 +164,9 @@ QIcon Resources::icon(const QString& name, bool recolor, const QColor& overrideC
icon = QIcon::fromTheme(name);
if (getMainWindow() && recolor) {
QImage img = icon.pixmap(128, 128).toImage().convertToFormat(QImage::Format_ARGB32_Premultiplied);
const QRect rect(0, 0, 48, 48);
QImage img = icon.pixmap(rect.width(), rect.height()).toImage();
img = img.convertToFormat(QImage::Format_ARGB32_Premultiplied);
icon = {};
QPainter painter(&img);
@ -172,20 +174,19 @@ QIcon Resources::icon(const QString& name, bool recolor, const QColor& overrideC
if (!overrideColor.isValid()) {
QPalette palette = getMainWindow()->palette();
painter.fillRect(0, 0, img.width(), img.height(), palette.color(QPalette::Normal, QPalette::WindowText));
painter.fillRect(rect, palette.color(QPalette::Normal, QPalette::WindowText));
icon.addPixmap(QPixmap::fromImage(img), QIcon::Normal);
painter.fillRect(0, 0, img.width(), img.height(), palette.color(QPalette::Active, QPalette::ButtonText));
painter.fillRect(rect, palette.color(QPalette::Active, QPalette::ButtonText));
icon.addPixmap(QPixmap::fromImage(img), QIcon::Active);
painter.fillRect(
0, 0, img.width(), img.height(), palette.color(QPalette::Active, QPalette::HighlightedText));
painter.fillRect(rect, palette.color(QPalette::Active, QPalette::HighlightedText));
icon.addPixmap(QPixmap::fromImage(img), QIcon::Selected);
painter.fillRect(0, 0, img.width(), img.height(), palette.color(QPalette::Disabled, QPalette::WindowText));
painter.fillRect(rect, palette.color(QPalette::Disabled, QPalette::WindowText));
icon.addPixmap(QPixmap::fromImage(img), QIcon::Disabled);
} else {
painter.fillRect(0, 0, img.width(), img.height(), overrideColor);
painter.fillRect(rect, overrideColor);
icon.addPixmap(QPixmap::fromImage(img), QIcon::Normal);
}
@ -211,18 +212,16 @@ QIcon Resources::onOffIcon(const QString& name, bool recolor)
return icon;
}
const QSize size(48, 48);
QIcon on = Resources::icon(name + "-on", recolor);
for (const auto& size : on.availableSizes()) {
icon.addPixmap(on.pixmap(size, QIcon::Mode::Normal), QIcon::Mode::Normal, QIcon::On);
icon.addPixmap(on.pixmap(size, QIcon::Mode::Selected), QIcon::Mode::Selected, QIcon::On);
icon.addPixmap(on.pixmap(size, QIcon::Mode::Disabled), QIcon::Mode::Disabled, QIcon::On);
}
icon.addPixmap(on.pixmap(size, QIcon::Mode::Normal), QIcon::Mode::Normal, QIcon::On);
icon.addPixmap(on.pixmap(size, QIcon::Mode::Selected), QIcon::Mode::Selected, QIcon::On);
icon.addPixmap(on.pixmap(size, QIcon::Mode::Disabled), QIcon::Mode::Disabled, QIcon::On);
QIcon off = Resources::icon(name + "-off", recolor);
for (const auto& size : off.availableSizes()) {
icon.addPixmap(off.pixmap(size, QIcon::Mode::Normal), QIcon::Mode::Normal, QIcon::Off);
icon.addPixmap(off.pixmap(size, QIcon::Mode::Selected), QIcon::Mode::Selected, QIcon::Off);
icon.addPixmap(off.pixmap(size, QIcon::Mode::Disabled), QIcon::Mode::Disabled, QIcon::Off);
}
icon.addPixmap(off.pixmap(size, QIcon::Mode::Normal), QIcon::Mode::Normal, QIcon::Off);
icon.addPixmap(off.pixmap(size, QIcon::Mode::Selected), QIcon::Mode::Selected, QIcon::Off);
icon.addPixmap(off.pixmap(size, QIcon::Mode::Disabled), QIcon::Mode::Disabled, QIcon::Off);
m_iconCache.insert(cacheName, icon);