diff --git a/src/qt/guiutil.cpp b/src/qt/guiutil.cpp index 916d80405166..bbabc210ddda 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> mapFontUpdates; // Contains a list of supported font weights for all members of GUIUtil::FontFamily static std::map> mapSupportedWeights; @@ -1529,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; } @@ -1543,10 +1544,36 @@ void updateFonts() return; } - static std::map mapWidgetDefaultFontSizes; - static std::map mapClassDefaultFontSizes; - std::map> mapWidgetFonts; + static std::map, int> mapWidgetDefaultFontSizes; + // QPointer becomes nullptr for objects that were deleted. + // Remove them from mapDefaultFontSize and mapFontUpdates + // before proceeding any further. + size_t nRemovedDefaultFonts{0}; + auto itd = mapWidgetDefaultFontSizes.begin(); + while (itd != mapWidgetDefaultFontSizes.end()) { + if (itd->first.isNull()) { + itd = mapWidgetDefaultFontSizes.erase(itd); + ++nRemovedDefaultFonts; + } else { + ++itd; + } + } + + size_t nRemovedFontUpdates{0}; + auto itn = mapFontUpdates.begin(); + while (itn != mapFontUpdates.end()) { + if (itn->first.isNull()) { + itn = mapFontUpdates.erase(itn); + ++nRemovedFontUpdates; + } else { + ++itn; + } + } + + size_t nUpdatable{0}, nUpdated{0}; + std::map mapWidgetFonts; + // Loop through all widgets for (QWidget* w : qApp->allWidgets()) { std::vector vecIgnore{ "QWidget", "QDialog", "QFrame", "QStackedWidget", "QDesktopWidget", "QDesktopScreenWidget", @@ -1556,86 +1583,59 @@ void updateFonts() if (std::find(vecIgnore.begin(), vecIgnore.end(), w->metaObject()->className()) != vecIgnore.end()) { 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 - 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); + // Insert/Get the default font size of the widget + auto itDefault = mapWidgetDefaultFontSizes.emplace(w, font.pointSize()); + + auto it = mapFontUpdates.find(w); + if (it != mapFontUpdates.end()) { + int nSize = std::get<2>(it->second); if (nSize == -1) { - nSize = mapWidgetDefaultFontSizes[itn->first]; - } - 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; + nSize = itDefault.first->second; } - ++itn; + font = getFont(std::get<0>(it->second), std::get<1>(it->second), nSize); } else { - itn = mapNormalFontUpdates.erase(itn); + font.setPointSizeF(getScaledFontSize(itDefault.first->second)); } - } - for (auto it : mapWidgetFonts) { - if (it.second.second) { - it.first->setFont(it.second.first); + 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 << ")"; - // 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); - } + // 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"); - 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()); + } } }