From 6d9d26db654981dbd22bdb0a70dfbc48f89b2e60 Mon Sep 17 00:00:00 2001 From: Anthony Bilinski Date: Mon, 16 Apr 2018 17:16:04 -0700 Subject: [PATCH] perf(ui): cache stylesheets to reduce memory usage Issue #5078 --- src/widget/style.cpp | 34 ++++++++++++++++++++++++---------- src/widget/style.h | 5 +++-- src/widget/widget.cpp | 3 +-- 3 files changed, 28 insertions(+), 14 deletions(-) diff --git a/src/widget/style.cpp b/src/widget/style.cpp index 0a45df581..5147bb99a 100644 --- a/src/widget/style.cpp +++ b/src/widget/style.cpp @@ -92,15 +92,23 @@ QStringList Style::getThemeColorNames() QList Style::themeColorColors = {QColor(), QColor("#004aa4"), QColor("#97ba00"), QColor("#c23716"), QColor("#4617b5")}; -QString Style::getStylesheet(const QString& filename, const QFont& baseFont) -{ - QFile file(filename); - if (!file.open(QFile::ReadOnly | QFile::Text)) { - qWarning() << "Stylesheet " << filename << " not found"; - return QString(); - } +// stylesheet filename, font -> stylesheet +// QString implicit sharing deduplicates stylesheets rather than constructing a new one each time +std::map, const QString> Style::stylesheetsCache; - return resolve(file.readAll(), baseFont); +const QString Style::getStylesheet(const QString& filename, const QFont& baseFont) +{ + const std::pair cacheKey(filename, baseFont); + auto it = stylesheetsCache.find(cacheKey); + if (it != stylesheetsCache.end()) + { + // cache hit + return it->second; + } + // cache miss, new styleSheet, read it from file and add to cache + const QString newStylesheet = resolve(filename, baseFont); + stylesheetsCache.insert(std::make_pair(cacheKey, newStylesheet)); + return newStylesheet; } QColor Style::getColor(Style::ColorPalette entry) @@ -128,8 +136,15 @@ QFont Style::getFont(Style::Font font) return fonts[font]; } -QString Style::resolve(QString qss, const QFont& baseFont) +const QString Style::resolve(const QString& filename, const QFont& baseFont) { + QFile file{filename}; + if (!file.open(QFile::ReadOnly | QFile::Text)) { + qWarning() << "Stylesheet " << filename << " not found"; + return QString(""); + } + QString qss = file.readAll(); + if (dict.isEmpty()) { dict = {// colors {"@green", Style::getColor(Style::Green).name()}, @@ -162,7 +177,6 @@ QString Style::resolve(QString qss, const QFont& baseFont) for (const QString& key : dict.keys()) { qss.replace(QRegularExpression(QString("%1\\b").arg(key)), dict[key]); } - return qss; } diff --git a/src/widget/style.h b/src/widget/style.h index 013a03423..3e5f9c0a8 100644 --- a/src/widget/style.h +++ b/src/widget/style.h @@ -59,10 +59,10 @@ public: }; static QStringList getThemeColorNames(); - static QString getStylesheet(const QString& filename, const QFont& baseFont = QFont()); + static const QString getStylesheet(const QString& filename, const QFont& baseFont = QFont()); static QColor getColor(ColorPalette entry); static QFont getFont(Font font); - static QString resolve(QString qss, const QFont& baseFont = QFont()); + static const QString resolve(const QString& filename, const QFont& baseFont = QFont()); static void repolish(QWidget* w); static void setThemeColor(int color); static void setThemeColor(const QColor& color); @@ -70,6 +70,7 @@ public: static QPixmap scaleSvgImage(const QString& path, uint32_t width, uint32_t height); static QList themeColorColors; + static std::map, const QString> stylesheetsCache; signals: void themeChanged(); diff --git a/src/widget/widget.cpp b/src/widget/widget.cpp index 3df9b81c1..2fcb2480b 100644 --- a/src/widget/widget.cpp +++ b/src/widget/widget.cpp @@ -143,8 +143,7 @@ void Widget::init() connect(actionQuit, &QAction::triggered, qApp, &QApplication::quit); layout()->setContentsMargins(0, 0, 0, 0); - ui->friendList->setStyleSheet( - Style::resolve(Style::getStylesheet(":/ui/friendList/friendList.css"))); + ui->friendList->setStyleSheet(Style::getStylesheet(":/ui/friendList/friendList.css")); profilePicture = new MaskablePixmapWidget(this, QSize(40, 40), ":/img/avatar_mask.svg"); profilePicture->setPixmap(QPixmap(":/img/contact_dark.svg"));