From 7491a5600495e5e06860ee515ccc93c62a031b05 Mon Sep 17 00:00:00 2001 From: UdjinM6 Date: Tue, 13 Oct 2020 04:52:02 +0300 Subject: [PATCH 1/8] Refactor and fix `GUIUtil::updateFonts` Use QPointer-s to process deleted widgets properly, streamline the flow (less loops and map scans). --- src/qt/guiutil.cpp | 82 ++++++++++++++++++++++------------------------ 1 file changed, 40 insertions(+), 42 deletions(-) diff --git a/src/qt/guiutil.cpp b/src/qt/guiutil.cpp index 916d80405166..cca7d7058e9d 100644 --- a/src/qt/guiutil.cpp +++ b/src/qt/guiutil.cpp @@ -57,6 +57,7 @@ #include #include #include +#include #include #include // for Qt::mightBeRichText #include @@ -133,7 +134,7 @@ static QFont::Weight fontWeightNormal = defaultFontWeightNormal; static QFont::Weight fontWeightBold = defaultFontWeightBold; // Contains all widgets and its font attributes (weight, italic, size) with font changes due to GUIUtil::setFont -static std::map> mapNormalFontUpdates; +static std::map, std::tuple> mapNormalFontUpdates; // Contains a list of supported font weights for all members of GUIUtil::FontFamily static std::map> mapSupportedWeights; @@ -1543,10 +1544,31 @@ void updateFonts() return; } - static std::map mapWidgetDefaultFontSizes; + static std::map, int> mapWidgetDefaultFontSizes; static std::map mapClassDefaultFontSizes; - std::map> mapWidgetFonts; + // QPointer becomes nullptr for objects that were deleted. + // Remove them from mapDefaultFontSize and mapNormalFontUpdates + // before proceeding any further. + auto itd = mapWidgetDefaultFontSizes.begin(); + while (itd != mapWidgetDefaultFontSizes.end()) { + if (itd->first.isNull()) { + itd = mapWidgetDefaultFontSizes.erase(itd); + } else { + ++itd; + } + } + + auto itn = mapNormalFontUpdates.begin(); + while (itn != mapNormalFontUpdates.end()) { + if (itn->first.isNull()) { + itn = mapNormalFontUpdates.erase(itn); + } else { + ++itn; + } + } + + // Loop through all widgets for (QWidget* w : qApp->allWidgets()) { std::vector vecIgnore{ "QWidget", "QDialog", "QFrame", "QStackedWidget", "QDesktopWidget", "QDesktopScreenWidget", @@ -1561,49 +1583,25 @@ void updateFonts() font.setWeight(getFontWeightNormal()); font.setStyleName(qApp->font().styleName()); font.setStyle(qApp->font().style()); - // Set the font size based on the widgets default font size + the font scale - bool fAdded = false; - if (!mapWidgetDefaultFontSizes.count(w)) { - mapWidgetDefaultFontSizes.emplace(std::make_pair(w, font.pointSize() > 0 ? font.pointSize() : defaultFontSize)); - fAdded = true; - } - font.setPointSizeF(getScaledFontSize(mapWidgetDefaultFontSizes[w])); - bool fUpdateRequired = fAdded || (mapNormalFontUpdates.find(w) == mapNormalFontUpdates.end() && font != w->font()); - mapWidgetFonts.emplace(w, std::make_pair(font, fUpdateRequired)); - } - auto itn = mapNormalFontUpdates.begin(); - while (itn != mapNormalFontUpdates.end()) { - auto itw = mapWidgetFonts.find(itn->first); - if (itw != mapWidgetFonts.end()) { - int nSize = std::get<2>(itn->second); + // Set the font size based on the widgets default font size + the font scale + int pointSize = font.pointSize() > 0 ? font.pointSize() : defaultFontSize; + mapWidgetDefaultFontSizes.emplace(std::make_pair(w, pointSize)); + int pointSizeStored = mapWidgetDefaultFontSizes.at(w); + font.setPointSizeF(getScaledFontSize(pointSizeStored)); + + auto it = mapNormalFontUpdates.find(w); + if (it != mapNormalFontUpdates.end()) { + int nSize = std::get<2>(it->second); if (nSize == -1) { - nSize = mapWidgetDefaultFontSizes[itn->first]; + nSize = pointSizeStored; } - QFont&& font = getFont(std::get<0>(itn->second), std::get<1>(itn->second), nSize); - if (itn->first->font() != font) { - itw->second.first = font; - itw->second.second = true; + QFont&& fontUpd = getFont(std::get<0>(it->second), std::get<1>(it->second), nSize); + if (w->font() != fontUpd) { + w->setFont(fontUpd); } - ++itn; - } else { - itn = mapNormalFontUpdates.erase(itn); - } - } - - for (auto it : mapWidgetFonts) { - if (it.second.second) { - it.first->setFont(it.second.first); - } - } - - // Cleanup mapDefaultFontSize to remove deleted widgets - auto itd = mapWidgetDefaultFontSizes.begin(); - while (itd != mapWidgetDefaultFontSizes.end()) { - if (qApp->allWidgets().contains(itd->first)) { - ++itd; - } else { - itd = mapWidgetDefaultFontSizes.erase(itd); + } else if (w->font() != font) { + w->setFont(font); } } From f0eba2fe66982a09e099790196f206345323a800 Mon Sep 17 00:00:00 2001 From: UdjinM6 Date: Tue, 13 Oct 2020 14:04:14 +0300 Subject: [PATCH 2/8] Add some debug output --- src/qt/guiutil.cpp | 16 ++++++++++++++++ 1 file changed, 16 insertions(+) diff --git a/src/qt/guiutil.cpp b/src/qt/guiutil.cpp index cca7d7058e9d..8bf0395b33b6 100644 --- a/src/qt/guiutil.cpp +++ b/src/qt/guiutil.cpp @@ -1550,6 +1550,7 @@ void updateFonts() // QPointer becomes nullptr for objects that were deleted. // Remove them from mapDefaultFontSize and mapNormalFontUpdates // before proceeding any further. + size_t nMapSize = mapWidgetDefaultFontSizes.size(); auto itd = mapWidgetDefaultFontSizes.begin(); while (itd != mapWidgetDefaultFontSizes.end()) { if (itd->first.isNull()) { @@ -1558,7 +1559,12 @@ void updateFonts() ++itd; } } + if (nMapSize - mapWidgetDefaultFontSizes.size() > 0) { + qDebug() << __func__ << ": removed" << nMapSize - mapWidgetDefaultFontSizes.size() + << "nullptr items from mapWidgetDefaultFontSizes"; + } + nMapSize = mapNormalFontUpdates.size(); auto itn = mapNormalFontUpdates.begin(); while (itn != mapNormalFontUpdates.end()) { if (itn->first.isNull()) { @@ -1567,7 +1573,12 @@ void updateFonts() ++itn; } } + if (nMapSize - mapNormalFontUpdates.size() > 0) { + qDebug() << __func__ << ": removed" << nMapSize - mapNormalFontUpdates.size() + << "nullptr items from mapNormalFontUpdates"; + } + size_t nUpdatable{0}, nUpdated{0}; // Loop through all widgets for (QWidget* w : qApp->allWidgets()) { std::vector vecIgnore{ @@ -1578,6 +1589,7 @@ void updateFonts() if (std::find(vecIgnore.begin(), vecIgnore.end(), w->metaObject()->className()) != vecIgnore.end()) { continue; } + ++nUpdatable; QFont font = w->font(); font.setFamily(qApp->font().family()); font.setWeight(getFontWeightNormal()); @@ -1599,11 +1611,15 @@ void updateFonts() QFont&& fontUpd = getFont(std::get<0>(it->second), std::get<1>(it->second), nSize); if (w->font() != fontUpd) { w->setFont(fontUpd); + ++nUpdated; } } else if (w->font() != font) { w->setFont(font); + ++nUpdated; } } + qDebug() << __func__ << ": updated:" << nUpdated << "/" << nUpdatable + << ": total:" << qApp->allWidgets().size(); // Scale the global font for QToolTip labels, QMenu and QMessageBox instances QFont fontToolTip = qApp->font("QTipLabel"); From 491fe7d1554b5acc1e8f4b16bc5e49484f0eff63 Mon Sep 17 00:00:00 2001 From: xdustinface Date: Fri, 9 Oct 2020 13:26:56 +0100 Subject: [PATCH 3/8] qt: Rename mapNormalFontUpdates -> mapFontUpdates The "Normal" was added when we also had other maps containing font updates --- src/qt/guiutil.cpp | 24 ++++++++++++------------ 1 file changed, 12 insertions(+), 12 deletions(-) diff --git a/src/qt/guiutil.cpp b/src/qt/guiutil.cpp index 8bf0395b33b6..c8d870abc67c 100644 --- a/src/qt/guiutil.cpp +++ b/src/qt/guiutil.cpp @@ -134,7 +134,7 @@ static QFont::Weight fontWeightNormal = defaultFontWeightNormal; static QFont::Weight fontWeightBold = defaultFontWeightBold; // Contains all widgets and its font attributes (weight, italic, size) with font changes due to GUIUtil::setFont -static std::map, std::tuple> mapNormalFontUpdates; +static std::map, std::tuple> mapFontUpdates; // Contains a list of supported font weights for all members of GUIUtil::FontFamily static std::map> mapSupportedWeights; @@ -1530,7 +1530,7 @@ void setFont(const std::vector& vecWidgets, FontWeight weight, int nPo { for (auto it : vecWidgets) { auto fontAttributes = std::make_tuple(weight, fItalic, nPointSize); - auto itFontUpdate = mapNormalFontUpdates.emplace(std::make_pair(it, fontAttributes)); + auto itFontUpdate = mapFontUpdates.emplace(std::make_pair(it, fontAttributes)); if (!itFontUpdate.second) { itFontUpdate.first->second = fontAttributes; } @@ -1548,7 +1548,7 @@ void updateFonts() static std::map mapClassDefaultFontSizes; // QPointer becomes nullptr for objects that were deleted. - // Remove them from mapDefaultFontSize and mapNormalFontUpdates + // Remove them from mapDefaultFontSize and mapFontUpdates // before proceeding any further. size_t nMapSize = mapWidgetDefaultFontSizes.size(); auto itd = mapWidgetDefaultFontSizes.begin(); @@ -1564,18 +1564,18 @@ void updateFonts() << "nullptr items from mapWidgetDefaultFontSizes"; } - nMapSize = mapNormalFontUpdates.size(); - auto itn = mapNormalFontUpdates.begin(); - while (itn != mapNormalFontUpdates.end()) { + nMapSize = mapFontUpdates.size(); + auto itn = mapFontUpdates.begin(); + while (itn != mapFontUpdates.end()) { if (itn->first.isNull()) { - itn = mapNormalFontUpdates.erase(itn); + itn = mapFontUpdates.erase(itn); } else { ++itn; } } - if (nMapSize - mapNormalFontUpdates.size() > 0) { - qDebug() << __func__ << ": removed" << nMapSize - mapNormalFontUpdates.size() - << "nullptr items from mapNormalFontUpdates"; + if (nMapSize - mapFontUpdates.size() > 0) { + qDebug() << __func__ << ": removed" << nMapSize - mapFontUpdates.size() + << "nullptr items from mapFontUpdates"; } size_t nUpdatable{0}, nUpdated{0}; @@ -1602,8 +1602,8 @@ void updateFonts() int pointSizeStored = mapWidgetDefaultFontSizes.at(w); font.setPointSizeF(getScaledFontSize(pointSizeStored)); - auto it = mapNormalFontUpdates.find(w); - if (it != mapNormalFontUpdates.end()) { + auto it = mapFontUpdates.find(w); + if (it != mapFontUpdates.end()) { int nSize = std::get<2>(it->second); if (nSize == -1) { nSize = pointSizeStored; From 5c5c2d2cb16c292494775364cf74bd25e689717d Mon Sep 17 00:00:00 2001 From: xdustinface Date: Wed, 21 Oct 2020 16:09:12 +0200 Subject: [PATCH 4/8] qt: Count removed items, adjust debug logs --- src/qt/guiutil.cpp | 18 ++++++------------ 1 file changed, 6 insertions(+), 12 deletions(-) diff --git a/src/qt/guiutil.cpp b/src/qt/guiutil.cpp index c8d870abc67c..b6a3d75c7e42 100644 --- a/src/qt/guiutil.cpp +++ b/src/qt/guiutil.cpp @@ -1550,33 +1550,27 @@ void updateFonts() // QPointer becomes nullptr for objects that were deleted. // Remove them from mapDefaultFontSize and mapFontUpdates // before proceeding any further. - size_t nMapSize = mapWidgetDefaultFontSizes.size(); + size_t nRemovedDefaultFonts{0}; auto itd = mapWidgetDefaultFontSizes.begin(); while (itd != mapWidgetDefaultFontSizes.end()) { if (itd->first.isNull()) { itd = mapWidgetDefaultFontSizes.erase(itd); + ++nRemovedDefaultFonts; } else { ++itd; } } - if (nMapSize - mapWidgetDefaultFontSizes.size() > 0) { - qDebug() << __func__ << ": removed" << nMapSize - mapWidgetDefaultFontSizes.size() - << "nullptr items from mapWidgetDefaultFontSizes"; - } - nMapSize = mapFontUpdates.size(); + size_t nRemovedFontUpdates{0}; auto itn = mapFontUpdates.begin(); while (itn != mapFontUpdates.end()) { if (itn->first.isNull()) { itn = mapFontUpdates.erase(itn); + ++nRemovedFontUpdates; } else { ++itn; } } - if (nMapSize - mapFontUpdates.size() > 0) { - qDebug() << __func__ << ": removed" << nMapSize - mapFontUpdates.size() - << "nullptr items from mapFontUpdates"; - } size_t nUpdatable{0}, nUpdated{0}; // Loop through all widgets @@ -1618,8 +1612,8 @@ void updateFonts() ++nUpdated; } } - qDebug() << __func__ << ": updated:" << nUpdated << "/" << nUpdatable - << ": total:" << qApp->allWidgets().size(); + qDebug().nospace() << __func__ << " - widget counts: updated/updatable/total(" << nUpdated << "/" << nUpdatable << "/" << qApp->allWidgets().size() << ")" + << ", removed items: mapWidgetDefaultFontSizes/mapFontUpdates(" << nRemovedDefaultFonts << "/" << nRemovedFontUpdates << ")"; // Scale the global font for QToolTip labels, QMenu and QMessageBox instances QFont fontToolTip = qApp->font("QTipLabel"); From f09d911f463b5c97c1bd15e049160eafdd6108b9 Mon Sep 17 00:00:00 2001 From: xdustinface Date: Wed, 21 Oct 2020 16:47:29 +0200 Subject: [PATCH 5/8] qt: Use the emplace result for the default font size --- src/qt/guiutil.cpp | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) diff --git a/src/qt/guiutil.cpp b/src/qt/guiutil.cpp index b6a3d75c7e42..18a1ac5307c6 100644 --- a/src/qt/guiutil.cpp +++ b/src/qt/guiutil.cpp @@ -1592,15 +1592,14 @@ void updateFonts() // Set the font size based on the widgets default font size + the font scale int pointSize = font.pointSize() > 0 ? font.pointSize() : defaultFontSize; - mapWidgetDefaultFontSizes.emplace(std::make_pair(w, pointSize)); - int pointSizeStored = mapWidgetDefaultFontSizes.at(w); - font.setPointSizeF(getScaledFontSize(pointSizeStored)); + auto itDefault = mapWidgetDefaultFontSizes.emplace(std::make_pair(w, pointSize)); + font.setPointSizeF(getScaledFontSize(itDefault.first->second)); auto it = mapFontUpdates.find(w); if (it != mapFontUpdates.end()) { int nSize = std::get<2>(it->second); if (nSize == -1) { - nSize = pointSizeStored; + nSize = itDefault.first->second; } QFont&& fontUpd = getFont(std::get<0>(it->second), std::get<1>(it->second), nSize); if (w->font() != fontUpd) { From 634ccc8c9db3b9b22a6165abd0daced233321966 Mon Sep 17 00:00:00 2001 From: xdustinface Date: Thu, 22 Oct 2020 02:09:40 +0200 Subject: [PATCH 6/8] qt: Perform all widget font updates later in a seperate step --- src/qt/guiutil.cpp | 28 +++++++++++++++++++--------- 1 file changed, 19 insertions(+), 9 deletions(-) diff --git a/src/qt/guiutil.cpp b/src/qt/guiutil.cpp index 18a1ac5307c6..a75b974ec2bb 100644 --- a/src/qt/guiutil.cpp +++ b/src/qt/guiutil.cpp @@ -1573,6 +1573,7 @@ void updateFonts() } size_t nUpdatable{0}, nUpdated{0}; + std::map mapWidgetFonts; // Loop through all widgets for (QWidget* w : qApp->allWidgets()) { std::vector vecIgnore{ @@ -1584,16 +1585,17 @@ void updateFonts() continue; } ++nUpdatable; + QFont font = w->font(); + assert(font.pointSize() > 0); font.setFamily(qApp->font().family()); font.setWeight(getFontWeightNormal()); font.setStyleName(qApp->font().styleName()); font.setStyle(qApp->font().style()); - // Set the font size based on the widgets default font size + the font scale + // Insert/Get the default font size of the widget int pointSize = font.pointSize() > 0 ? font.pointSize() : defaultFontSize; auto itDefault = mapWidgetDefaultFontSizes.emplace(std::make_pair(w, pointSize)); - font.setPointSizeF(getScaledFontSize(itDefault.first->second)); auto it = mapFontUpdates.find(w); if (it != mapFontUpdates.end()) { @@ -1601,19 +1603,27 @@ void updateFonts() if (nSize == -1) { nSize = itDefault.first->second; } - QFont&& fontUpd = getFont(std::get<0>(it->second), std::get<1>(it->second), nSize); - if (w->font() != fontUpd) { - w->setFont(fontUpd); - ++nUpdated; - } - } else if (w->font() != font) { - w->setFont(font); + font = getFont(std::get<0>(it->second), std::get<1>(it->second), nSize); + } else { + font.setPointSizeF(getScaledFontSize(itDefault.first->second)); + } + + if (w->font() != font) { + auto itWidgetFont = mapWidgetFonts.emplace(w, font); + assert(itWidgetFont.second); ++nUpdated; } } qDebug().nospace() << __func__ << " - widget counts: updated/updatable/total(" << nUpdated << "/" << nUpdatable << "/" << qApp->allWidgets().size() << ")" << ", removed items: mapWidgetDefaultFontSizes/mapFontUpdates(" << nRemovedDefaultFonts << "/" << nRemovedFontUpdates << ")"; + // Perform the required font updates + // NOTE: This is done as seperate step to avoid scaling issues due to font inheritance + // hence all fonts are calculated and stored in mapWidgetFonts above. + for (auto it : mapWidgetFonts) { + it.first->setFont(it.second); + } + // Scale the global font for QToolTip labels, QMenu and QMessageBox instances QFont fontToolTip = qApp->font("QTipLabel"); QFont fontMenu = qApp->font("QMenu"); From c6bf0d35d2174315d344ccc535c7e1c73091ffa2 Mon Sep 17 00:00:00 2001 From: xdustinface Date: Thu, 22 Oct 2020 03:29:53 +0200 Subject: [PATCH 7/8] qt: Drop pointSize checks --- src/qt/guiutil.cpp | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/src/qt/guiutil.cpp b/src/qt/guiutil.cpp index a75b974ec2bb..c6e2cd235ab6 100644 --- a/src/qt/guiutil.cpp +++ b/src/qt/guiutil.cpp @@ -1594,8 +1594,7 @@ void updateFonts() font.setStyle(qApp->font().style()); // Insert/Get the default font size of the widget - int pointSize = font.pointSize() > 0 ? font.pointSize() : defaultFontSize; - auto itDefault = mapWidgetDefaultFontSizes.emplace(std::make_pair(w, pointSize)); + auto itDefault = mapWidgetDefaultFontSizes.emplace(w, font.pointSize()); auto it = mapFontUpdates.find(w); if (it != mapFontUpdates.end()) { From d06ea03e8b785af126d85c28d9d6de9556e016ee Mon Sep 17 00:00:00 2001 From: xdustinface Date: Thu, 22 Oct 2020 05:22:46 +0200 Subject: [PATCH 8/8] qt: Refactor app class font scaling --- src/qt/guiutil.cpp | 44 ++++++++++++++------------------------------ 1 file changed, 14 insertions(+), 30 deletions(-) diff --git a/src/qt/guiutil.cpp b/src/qt/guiutil.cpp index c6e2cd235ab6..bbabc210ddda 100644 --- a/src/qt/guiutil.cpp +++ b/src/qt/guiutil.cpp @@ -1545,7 +1545,6 @@ void updateFonts() } static std::map, int> mapWidgetDefaultFontSizes; - static std::map mapClassDefaultFontSizes; // QPointer becomes nullptr for objects that were deleted. // Remove them from mapDefaultFontSize and mapFontUpdates @@ -1623,35 +1622,20 @@ void updateFonts() it.first->setFont(it.second); } - // Scale the global font for QToolTip labels, QMenu and QMessageBox instances - QFont fontToolTip = qApp->font("QTipLabel"); - QFont fontMenu = qApp->font("QMenu"); - QFont fontMessageBox = qApp->font("QMessageBox"); - // Store their default font sizes before ever applying any scale to it - if (!mapClassDefaultFontSizes.count("QTipLabel")) { - mapClassDefaultFontSizes.emplace("QTipLabel", fontToolTip.pointSize()); - } - if (!mapClassDefaultFontSizes.count("QMenu")) { - mapClassDefaultFontSizes.emplace("QMenu", fontMenu.pointSize()); - } - if (!mapClassDefaultFontSizes.count("QMessageBox")) { - mapClassDefaultFontSizes.emplace("QMessageBox", fontMessageBox.pointSize()); - } - // And give them the proper scaled size based on their default sizes if required - double dSize = getScaledFontSize(mapClassDefaultFontSizes["QTipLabel"]); - if (fontToolTip.pointSizeF() != dSize) { - fontToolTip.setPointSizeF(dSize); - qApp->setFont(fontToolTip, "QTipLabel"); - } - dSize = getScaledFontSize(mapClassDefaultFontSizes["QMenu"]); - if (fontMenu.pointSizeF() != dSize) { - fontMenu.setPointSizeF(dSize); - qApp->setFont(fontMenu, "QMenu"); - } - dSize = getScaledFontSize(getScaledFontSize(mapClassDefaultFontSizes["QMessageBox"])); - if (fontMessageBox.pointSizeF() != dSize) { - fontMessageBox.setPointSizeF(dSize); - qApp->setFont(fontMessageBox, "QMessageBox"); + // Scale the global font size for the classes in the map below + static std::map mapClassFontUpdates{ + {"QTipLabel", -1}, {"QMenu", -1}, {"QMessageBox", -1} + }; + for (auto& it : mapClassFontUpdates) { + QFont fontClass = qApp->font(it.first.c_str()); + if (it.second == -1) { + it.second = fontClass.pointSize(); + } + double dSize = getScaledFontSize(it.second); + if (fontClass.pointSizeF() != dSize) { + fontClass.setPointSizeF(dSize); + qApp->setFont(fontClass, it.first.c_str()); + } } }