From 85b49b9d2a390ae59fb0c92d44f96ff9fb79113c Mon Sep 17 00:00:00 2001 From: Kittywhiskers Van Gogh <63189531+kwvg@users.noreply.github.com> Date: Wed, 24 Dec 2025 19:47:55 +0530 Subject: [PATCH 01/14] qt: add "Roboto Mono" as non-selectable font --- src/qt/appearancewidget.cpp | 5 +++-- src/qt/bitcoin.cpp | 4 ++-- src/qt/guiutil_font.cpp | 39 ++++++++++++++++++++++++++----------- src/qt/guiutil_font.h | 8 ++++++-- src/qt/optionsmodel.cpp | 2 +- 5 files changed, 40 insertions(+), 18 deletions(-) diff --git a/src/qt/appearancewidget.cpp b/src/qt/appearancewidget.cpp index 074069a8504c..300edd30e06c 100644 --- a/src/qt/appearancewidget.cpp +++ b/src/qt/appearancewidget.cpp @@ -34,7 +34,8 @@ AppearanceWidget::AppearanceWidget(QWidget* parent) : } for (size_t idx{0}; idx < GUIUtil::g_fonts_known.size(); idx++) { - ui->fontFamily->addItem(GUIUtil::g_fonts_known[idx], QVariant((uint16_t)idx)); + const auto& [font, selectable] = GUIUtil::g_fonts_known[idx]; + if (selectable) { ui->fontFamily->addItem(font, QVariant((uint16_t)idx)); } } updateWeightSlider(); @@ -154,7 +155,7 @@ void AppearanceWidget::updateTheme(const QString& theme) void AppearanceWidget::updateFontFamily(int index) { - const bool setfont_ret{GUIUtil::g_font_registry.SetFont(GUIUtil::g_fonts_known[ui->fontFamily->itemData(index).toInt()])}; + const bool setfont_ret{GUIUtil::g_font_registry.SetFont(GUIUtil::g_fonts_known[ui->fontFamily->itemData(index).toInt()].first)}; assert(setfont_ret); GUIUtil::setApplicationFont(); GUIUtil::updateFonts(); diff --git a/src/qt/bitcoin.cpp b/src/qt/bitcoin.cpp index ff001b7389c2..6f468642f74f 100644 --- a/src/qt/bitcoin.cpp +++ b/src/qt/bitcoin.cpp @@ -489,7 +489,7 @@ static void SetupUIArgs(ArgsManager& argsman) { argsman.AddArg("-choosedatadir", strprintf(QObject::tr("Choose data directory on startup (default: %u)").toStdString(), DEFAULT_CHOOSE_DATADIR), ArgsManager::ALLOW_ANY, OptionsCategory::GUI); argsman.AddArg("-custom-css-dir", "Set a directory which contains custom css files. Those will be used as stylesheets for the UI.", ArgsManager::ALLOW_ANY, OptionsCategory::GUI); - argsman.AddArg("-font-family", QObject::tr("Set the font family. Possible values: %1. (default: %2)").arg(Join(GUIUtil::g_fonts_known, ", ")).arg(GUIUtil::FontRegistry::DEFAULT_FONT).toStdString(), ArgsManager::ALLOW_ANY, OptionsCategory::GUI); + argsman.AddArg("-font-family", QObject::tr("Set the font family. Possible values: %1. (default: %2)").arg(Join(GUIUtil::getFonts(/*selectable_only=*/true), ", ")).arg(GUIUtil::FontRegistry::DEFAULT_FONT).toStdString(), ArgsManager::ALLOW_ANY, OptionsCategory::GUI); argsman.AddArg("-font-scale", QObject::tr("Set a scale factor which gets applied to the base font size. Possible range %1 (smallest fonts) to %2 (largest fonts). (default: %3)").arg(-100).arg(100).arg(GUIUtil::FontRegistry::DEFAULT_FONT_SCALE).toStdString(), ArgsManager::ALLOW_ANY, OptionsCategory::GUI); argsman.AddArg("-font-weight-bold", QObject::tr("Set the font weight for bold texts. Possible range %1 to %2 (default: %3)").arg(0).arg(8).arg(GUIUtil::weightToArg(GUIUtil::FontRegistry::TARGET_WEIGHT_BOLD)).toStdString(), ArgsManager::ALLOW_ANY, OptionsCategory::GUI); argsman.AddArg("-font-weight-normal", QObject::tr("Set the font weight for normal texts. Possible range %1 to %2 (default: %3)").arg(0).arg(8).arg(GUIUtil::weightToArg(GUIUtil::FontRegistry::TARGET_WEIGHT_NORMAL)).toStdString(), ArgsManager::ALLOW_ANY, OptionsCategory::GUI); @@ -673,7 +673,7 @@ int GuiMain(int argc, char* argv[]) // Validate/set font family if (gArgs.IsArgSet("-font-family")) { QString family = gArgs.GetArg("-font-family", GUIUtil::FontRegistry::DEFAULT_FONT.toUtf8().toStdString()).c_str(); - if (!GUIUtil::g_font_registry.RegisterFont(family) || !GUIUtil::g_font_registry.SetFont(family)) { + if (!GUIUtil::g_font_registry.RegisterFont(family, /*selectable=*/true) || !GUIUtil::g_font_registry.SetFont(family)) { QMessageBox::critical(nullptr, PACKAGE_NAME, QObject::tr("Error: Font \"%1\" could not be loaded.").arg(family)); return EXIT_FAILURE; } diff --git a/src/qt/guiutil_font.cpp b/src/qt/guiutil_font.cpp index c96517848926..6dd615dc499c 100644 --- a/src/qt/guiutil_font.cpp +++ b/src/qt/guiutil_font.cpp @@ -116,10 +116,11 @@ QString qstrprintf(const std::string& fmt, const Args&... args) } // anonymous namespace namespace GUIUtil { -// Fonts known by the client -std::vector g_fonts_known{ - OS_FONT_STR.toUtf8(), - MONTSERRAT_FONT_STR.toUtf8(), +//! Fonts known by the client +std::vector> g_fonts_known{ + {MONTSERRAT_FONT_STR.toUtf8(), true}, + {OS_FONT_STR.toUtf8(), true}, + {ROBOTO_MONO_FONT_STR.toUtf8(), false}, }; FontRegistry g_font_registry; @@ -134,12 +135,15 @@ FontInfo::FontInfo(const QString& font_name) FontInfo::~FontInfo() = default; -bool FontRegistry::RegisterFont(const QString& font, bool skip_checks) +bool FontRegistry::RegisterFont(const QString& font, bool selectable, bool skip_checks) { - const bool font_known{std::find(g_fonts_known.begin(), g_fonts_known.end(), font) != g_fonts_known.end()}; + const auto font_strs{getFonts(/*selectable_only=*/false)}; + auto font_it{std::find(font_strs.begin(), font_strs.end(), font)}; if (m_weights.count(font)) { // Font's already registered - assert(font_known); + assert(font_it != font_strs.end()); + // Overwrite selectable flag + g_fonts_known.at(std::distance(font_strs.begin(), font_it)).second = selectable; return true; } if (!skip_checks) { @@ -150,8 +154,8 @@ bool FontRegistry::RegisterFont(const QString& font, bool skip_checks) } } m_weights.emplace(font, FontInfo(font)); - if (!font_known) { - g_fonts_known.push_back(font); + if (font_it == font_strs.end()) { + g_fonts_known.emplace_back(font, selectable); } return true; } @@ -290,8 +294,8 @@ bool loadFonts() } #endif // QT_NO_DEBUG - for (const auto& fonts : g_fonts_known) { - assert(g_font_registry.RegisterFont(fonts, /*skip_checks=*/true)); + for (const auto& [fonts, selectable] : g_fonts_known) { + assert(g_font_registry.RegisterFont(fonts, selectable, /*skip_checks=*/true)); } return true; @@ -474,6 +478,10 @@ QFont getFont(const QString& font_name, const FontAttrib& font_attrib) font.setFamily(font_name); } + if (font_name == ROBOTO_MONO_FONT_STR) { + font.setStyleHint(QFont::Monospace); + } + #ifdef Q_OS_MACOS if (font_name != MONTSERRAT_FONT_STR) #endif // Q_OS_MACOS @@ -500,6 +508,15 @@ QFont getFont(const FontAttrib& font_attrib) return getFont(g_font_registry.GetFont(), font_attrib); } +std::vector getFonts(bool selectable_only) +{ + std::vector ret; + for (const auto& [font, selectable] : g_fonts_known) { + if (selectable || !selectable_only) { ret.emplace_back(font); } + } + return ret; +} + QFont getFontNormal() { return getFont({g_font_registry.GetWeightNormal()}); diff --git a/src/qt/guiutil_font.h b/src/qt/guiutil_font.h index 045149b9e9d0..9ca389412ed1 100644 --- a/src/qt/guiutil_font.h +++ b/src/qt/guiutil_font.h @@ -19,6 +19,7 @@ namespace GUIUtil { // TODO: Switch to QUtf8StringView when we switch to Qt 6 constexpr QStringView MONTSERRAT_FONT_STR{u"Montserrat"}; constexpr QStringView OS_FONT_STR{u"SystemDefault"}; +constexpr QStringView ROBOTO_MONO_FONT_STR{u"Roboto Mono"}; enum class FontWeight : uint8_t { Normal, @@ -63,7 +64,7 @@ class FontRegistry { }; public: - [[nodiscard]] bool RegisterFont(const QString& font, bool skip_checks = false); + [[nodiscard]] bool RegisterFont(const QString& font, bool selectable, bool skip_checks = false); bool IsValidWeight(const QFont::Weight& weight) const { return WeightToIdx(weight) != -1; } int WeightToIdx(const QFont::Weight& weight) const; @@ -123,7 +124,7 @@ class FontRegistry { extern FontRegistry g_font_registry; -extern std::vector g_fonts_known; +extern std::vector> g_fonts_known; /** Convert weight value from args (0-8) to QFont::Weight */ bool weightFromArg(int nArg, QFont::Weight& weight); @@ -147,6 +148,9 @@ void setFont(const std::vector& vecWidgets, const FontAttrib& font_att GUIUtil::setFont */ void updateFonts(); +/** Get list of all selectable fonts */ +std::vector getFonts(bool selectable_only); + /** Get a properly weighted QFont object with the selected font. */ QFont getFont(const QString& font_name, const FontAttrib& font_attrib); QFont getFont(const FontAttrib& font_attrib); diff --git a/src/qt/optionsmodel.cpp b/src/qt/optionsmodel.cpp index 4955ef47008d..173cde148016 100644 --- a/src/qt/optionsmodel.cpp +++ b/src/qt/optionsmodel.cpp @@ -106,7 +106,7 @@ void OptionsModel::Init(bool resetSettings) } if (GUIUtil::fontsLoaded()) { if (auto font_name = QString::fromStdString(gArgs.GetArg("-font-family", settings.value("fontFamily").toString().toStdString())); - GUIUtil::g_font_registry.RegisterFont(font_name) && GUIUtil::g_font_registry.SetFont(font_name)) { + GUIUtil::g_font_registry.RegisterFont(font_name, /*selectable=*/true) && GUIUtil::g_font_registry.SetFont(font_name)) { GUIUtil::setApplicationFont(); } } From 800cf668499fc0030d4b6831e7c93b352376a0b3 Mon Sep 17 00:00:00 2001 From: Kittywhiskers Van Gogh <63189531+kwvg@users.noreply.github.com> Date: Wed, 24 Dec 2025 16:47:09 +0530 Subject: [PATCH 02/14] qt: recognize system monospace font as non-selectable font --- src/qt/guiutil.cpp | 8 -------- src/qt/guiutil.h | 3 --- src/qt/guiutil_font.cpp | 13 ++++++++++++- src/qt/guiutil_font.h | 4 ++++ 4 files changed, 16 insertions(+), 12 deletions(-) diff --git a/src/qt/guiutil.cpp b/src/qt/guiutil.cpp index bbd2c7822416..611564f65da6 100644 --- a/src/qt/guiutil.cpp +++ b/src/qt/guiutil.cpp @@ -230,14 +230,6 @@ QString dateTimeStr(qint64 nTime) return dateTimeStr(QDateTime::fromSecsSinceEpoch((qint32)nTime)); } -QFont fixedPitchFont(bool use_embedded_font) -{ - if (use_embedded_font) { - return {"Roboto Mono"}; - } - return QFontDatabase::systemFont(QFontDatabase::FixedFont); -} - // Just some dummy data to generate a convincing random-looking (but consistent) address static const uint8_t dummydata[] = {0xeb,0x15,0x23,0x1d,0xfc,0xeb,0x60,0x92,0x58,0x86,0xb6,0x7d,0x06,0x52,0x99,0x92,0x59,0x15,0xae,0xb1,0x72,0xc0,0x66,0x47}; diff --git a/src/qt/guiutil.h b/src/qt/guiutil.h index b6a1e6becbd5..e4701677cc79 100644 --- a/src/qt/guiutil.h +++ b/src/qt/guiutil.h @@ -125,9 +125,6 @@ namespace GUIUtil QString dateTimeStr(const QDateTime &datetime); QString dateTimeStr(qint64 nTime); - // Return a monospace font - QFont fixedPitchFont(bool use_embedded_font = false); - // Set up widget for address void setupAddressWidget(QValidatedLineEdit *widget, QWidget *parent, bool fAllowURI = false); diff --git a/src/qt/guiutil_font.cpp b/src/qt/guiutil_font.cpp index 6dd615dc499c..7ebfd2726abb 100644 --- a/src/qt/guiutil_font.cpp +++ b/src/qt/guiutil_font.cpp @@ -120,6 +120,7 @@ namespace GUIUtil { std::vector> g_fonts_known{ {MONTSERRAT_FONT_STR.toUtf8(), true}, {OS_FONT_STR.toUtf8(), true}, + {OS_MONO_FONT_STR.toUtf8(), false}, {ROBOTO_MONO_FONT_STR.toUtf8(), false}, }; @@ -474,11 +475,13 @@ QFont getFont(const QString& font_name, const FontAttrib& font_attrib) #endif // Q_OS_MACOS } else if (font_name == OS_FONT_STR) { font.setFamily(g_default_font->family()); + } else if (font_name == OS_MONO_FONT_STR) { + font.setFamily(QFontDatabase::systemFont(QFontDatabase::FixedFont).family()); } else { font.setFamily(font_name); } - if (font_name == ROBOTO_MONO_FONT_STR) { + if (font_name == ROBOTO_MONO_FONT_STR || font_name == OS_MONO_FONT_STR) { font.setStyleHint(QFont::Monospace); } @@ -544,4 +547,12 @@ int FontRegistry::WeightToIdx(const QFont::Weight& weight) const } return -1; } + +QFont fixedPitchFont(bool use_embedded_font) +{ + return getFont({ + use_embedded_font ? ROBOTO_MONO_FONT_STR.toUtf8() : OS_MONO_FONT_STR.toUtf8(), + g_font_registry.GetWeightNormal() + }); +} } // namespace GUIUtil diff --git a/src/qt/guiutil_font.h b/src/qt/guiutil_font.h index 9ca389412ed1..c12f2ab2c79e 100644 --- a/src/qt/guiutil_font.h +++ b/src/qt/guiutil_font.h @@ -19,6 +19,7 @@ namespace GUIUtil { // TODO: Switch to QUtf8StringView when we switch to Qt 6 constexpr QStringView MONTSERRAT_FONT_STR{u"Montserrat"}; constexpr QStringView OS_FONT_STR{u"SystemDefault"}; +constexpr QStringView OS_MONO_FONT_STR{u"SystemMonospace"}; constexpr QStringView ROBOTO_MONO_FONT_STR{u"Roboto Mono"}; enum class FontWeight : uint8_t { @@ -160,6 +161,9 @@ QFont getFontNormal(); /** Get the default bold QFont */ QFont getFontBold(); + +/** (Bitcoin) Return a monospace font */ +QFont fixedPitchFont(bool use_embedded_font = false); } // namespace GUIUtil #endif // BITCOIN_QT_GUIUTIL_FONT_H From 6ed53d62a6b0e34a5fdddf23a3c3917c304c50e7 Mon Sep 17 00:00:00 2001 From: Kittywhiskers Van Gogh <63189531+kwvg@users.noreply.github.com> Date: Fri, 26 Dec 2025 17:45:55 +0530 Subject: [PATCH 03/14] qt: allow overriding font registry for specific widgets --- src/qt/guiutil_font.cpp | 47 ++++++++++++++++++++++++++--------------- src/qt/guiutil_font.h | 21 +++++++++++------- 2 files changed, 43 insertions(+), 25 deletions(-) diff --git a/src/qt/guiutil_font.cpp b/src/qt/guiutil_font.cpp index 7ebfd2726abb..7190a32fe5ec 100644 --- a/src/qt/guiutil_font.cpp +++ b/src/qt/guiutil_font.cpp @@ -189,7 +189,7 @@ int weightToArg(const QFont::Weight weight) void FontInfo::CalcSupportedWeights(const QString& font_name) { auto getTestWidth = [](const QString& font_name, QFont::Weight weight) -> int { - QFont font = getFont(font_name, {weight, FontRegistry::DEFAULT_FONT_SIZE, false}); + QFont font = getFont({font_name, weight, FontRegistry::DEFAULT_FONT_SIZE, false}); return TextWidth(QFontMetrics(font), ("Check the width of this text to see if the weight change has an impact!")); }; QFont::Weight prevWeight = vecWeightConsider.front(); @@ -243,6 +243,24 @@ void FontInfo::CalcDefaultWeights(const QString& font_name) } } +FontAttrib::FontAttrib(QString font, QFont::Weight weight, double point_size, bool is_italic) : + m_font{font}, + m_weight{weight}, + m_point_size{point_size}, + m_is_italic{is_italic} +{ +} + +FontAttrib::FontAttrib(QFont::Weight weight, double point_size, bool is_italic) : + m_font{g_font_registry.GetFont()}, + m_weight{weight}, + m_point_size{point_size}, + m_is_italic{is_italic} +{ +} + +FontAttrib::~FontAttrib() = default; + bool loadFonts() { // Before any font changes store the applications default font to use it as SystemDefault. @@ -407,7 +425,7 @@ void updateFonts() if (nSize == -1) { nSize = itDefault.first->second; } - font = getFont({it->second.m_weight, nSize, it->second.m_is_italic}); + font = getFont({it->second.m_font, it->second.m_weight, nSize, it->second.m_is_italic}); } else { font.setPointSizeF(g_font_registry.GetScaledFontSize(itDefault.first->second)); } @@ -444,17 +462,17 @@ void updateFonts() } } -QFont getFont(const QString& font_name, const FontAttrib& font_attrib) +QFont getFont(const FontAttrib& font_attrib) { QFont font; if (!fontsLoaded()) { return font; } - if (font_name == MONTSERRAT_FONT_STR) { + if (font_attrib.m_font == MONTSERRAT_FONT_STR) { assert(mapMontserrat.count(font_attrib.m_weight)); #ifdef Q_OS_MACOS - font.setFamily(font_name); + font.setFamily(font_attrib.m_font); font.setStyleName([&]() { std::string ret{mapMontserrat.at(font_attrib.m_weight).first}; if (font_attrib.m_is_italic) { @@ -468,25 +486,25 @@ QFont getFont(const QString& font_name, const FontAttrib& font_attrib) }()); #else if (font_attrib.m_weight == QFont::Normal || font_attrib.m_weight == QFont::Bold) { - font.setFamily(font_name); + font.setFamily(font_attrib.m_font); } else { - font.setFamily(font_name + QString{" "} + QString::fromStdString(mapMontserrat.at(font_attrib.m_weight).first)); + font.setFamily(qstrprintf("%s %s", font_attrib.m_font.toStdString(), mapMontserrat.at(font_attrib.m_weight).first)); } #endif // Q_OS_MACOS - } else if (font_name == OS_FONT_STR) { + } else if (font_attrib.m_font == OS_FONT_STR) { font.setFamily(g_default_font->family()); - } else if (font_name == OS_MONO_FONT_STR) { + } else if (font_attrib.m_font == OS_MONO_FONT_STR) { font.setFamily(QFontDatabase::systemFont(QFontDatabase::FixedFont).family()); } else { - font.setFamily(font_name); + font.setFamily(font_attrib.m_font); } - if (font_name == ROBOTO_MONO_FONT_STR || font_name == OS_MONO_FONT_STR) { + if (font_attrib.m_font == ROBOTO_MONO_FONT_STR || font_attrib.m_font == OS_MONO_FONT_STR) { font.setStyleHint(QFont::Monospace); } #ifdef Q_OS_MACOS - if (font_name != MONTSERRAT_FONT_STR) + if (font_attrib.m_font != MONTSERRAT_FONT_STR) #endif // Q_OS_MACOS { font.setWeight(font_attrib.m_weight); @@ -506,11 +524,6 @@ QFont getFont(const QString& font_name, const FontAttrib& font_attrib) return font; } -QFont getFont(const FontAttrib& font_attrib) -{ - return getFont(g_font_registry.GetFont(), font_attrib); -} - std::vector getFonts(bool selectable_only) { std::vector ret; diff --git a/src/qt/guiutil_font.h b/src/qt/guiutil_font.h index c12f2ab2c79e..f12333b67e93 100644 --- a/src/qt/guiutil_font.h +++ b/src/qt/guiutil_font.h @@ -22,17 +22,13 @@ constexpr QStringView OS_FONT_STR{u"SystemDefault"}; constexpr QStringView OS_MONO_FONT_STR{u"SystemMonospace"}; constexpr QStringView ROBOTO_MONO_FONT_STR{u"Roboto Mono"}; +extern std::vector> g_fonts_known; + enum class FontWeight : uint8_t { Normal, Bold, }; -struct FontAttrib { - QFont::Weight m_weight; - double m_point_size{-1}; - bool m_is_italic{false}; -}; - struct FontInfo { QFont::Weight m_bold; QFont::Weight m_bold_default; @@ -125,7 +121,17 @@ class FontRegistry { extern FontRegistry g_font_registry; -extern std::vector> g_fonts_known; +struct FontAttrib { + QString m_font; + QFont::Weight m_weight; + double m_point_size{-1}; + bool m_is_italic{false}; + + FontAttrib(QString font, QFont::Weight weight, double point_size = -1, bool is_italic = false); + // cppcheck-suppress noExplicitConstructor + FontAttrib(QFont::Weight weight, double point_size = -1, bool is_italic = false); + ~FontAttrib(); +}; /** Convert weight value from args (0-8) to QFont::Weight */ bool weightFromArg(int nArg, QFont::Weight& weight); @@ -153,7 +159,6 @@ void updateFonts(); std::vector getFonts(bool selectable_only); /** Get a properly weighted QFont object with the selected font. */ -QFont getFont(const QString& font_name, const FontAttrib& font_attrib); QFont getFont(const FontAttrib& font_attrib); /** Get the default normal QFont */ From 34211b6ddf2a3be82d60a47bd22cd7049867b8e0 Mon Sep 17 00:00:00 2001 From: Kittywhiskers Van Gogh <63189531+kwvg@users.noreply.github.com> Date: Fri, 2 Jan 2026 17:43:49 +0530 Subject: [PATCH 04/14] qt: apply monospace font to overview page balances and CoinJoin elements Co-authored-by: UdjinM6 --- src/qt/overviewpage.cpp | 31 ++++++++++++++++++++++++++----- src/qt/overviewpage.h | 1 + 2 files changed, 27 insertions(+), 5 deletions(-) diff --git a/src/qt/overviewpage.cpp b/src/qt/overviewpage.cpp index 8a0f4546eba4..cfc445357eac 100644 --- a/src/qt/overviewpage.cpp +++ b/src/qt/overviewpage.cpp @@ -155,10 +155,7 @@ OverviewPage::OverviewPage(QWidget* parent) : ui->labelCoinJoinHeader }, {GUIUtil::g_font_registry.GetWeightBold(), 16}); - GUIUtil::setFont({ui->labelTotalText, - ui->labelWatchTotal, - ui->labelTotal - }, {GUIUtil::g_font_registry.GetWeightBold(), 14}); + GUIUtil::setFont({ui->labelTotalText}, {GUIUtil::g_font_registry.GetWeightBold(), 14}); GUIUtil::setFont({ui->labelBalanceText, ui->labelPendingText, @@ -167,7 +164,8 @@ OverviewPage::OverviewPage(QWidget* parent) : ui->labelSpendable }, {GUIUtil::g_font_registry.GetWeightBold()}); - GUIUtil::updateFonts(); + // Calls GUIUtil::updateFonts() internally + setMonospacedFont(/*use_embedded_font=*/false); m_balances.balance = -1; @@ -304,6 +302,7 @@ void OverviewPage::setClientModel(ClientModel *model) // Show warning, for example if this is a prerelease version connect(model, &ClientModel::alertsChanged, this, &OverviewPage::updateAlerts); updateAlerts(model->getStatusBarWarnings()); + setMonospacedFont(/*use_embedded_font=*/false); // explicitly update CoinJoin frame and transaction list to reflect actual settings updateAdvancedCJUI(model->getOptionsModel()->getShowAdvancedCJUI()); } @@ -376,6 +375,28 @@ void OverviewPage::showOutOfSyncWarning(bool fShow) ui->labelTransactionsStatus->setVisible(fShow); } +void OverviewPage::setMonospacedFont(bool use_embedded_font) +{ + GUIUtil::setFont({ + ui->labelTotal, + ui->labelWatchTotal, + }, {GUIUtil::fixedPitchFont(use_embedded_font).family(), GUIUtil::g_font_registry.GetWeightBold(), 14}); + + GUIUtil::setFont({ + ui->labelAmountRounds, + ui->labelAnonymized, + ui->labelBalance, + ui->labelUnconfirmed, + ui->labelImmature, + ui->labelSubmittedDenom, + ui->labelWatchAvailable, + ui->labelWatchPending, + ui->labelWatchImmature, + }, {GUIUtil::fixedPitchFont(use_embedded_font).family(), GUIUtil::g_font_registry.GetWeightBold()}); + + GUIUtil::updateFonts(); +} + void OverviewPage::updateCoinJoinProgress() { if (!walletModel || !clientModel || clientModel->node().shutdownRequested() || !clientModel->masternodeSync().isBlockchainSynced()) return; diff --git a/src/qt/overviewpage.h b/src/qt/overviewpage.h index 5f1789f27d7a..62d9a0dbc5d5 100644 --- a/src/qt/overviewpage.h +++ b/src/qt/overviewpage.h @@ -71,6 +71,7 @@ private Q_SLOTS: void handleTransactionClicked(const QModelIndex &index); void updateAlerts(const QString &warnings); void updateWatchOnlyLabels(bool showWatchOnly); + void setMonospacedFont(bool use_embedded_font); }; #endif // BITCOIN_QT_OVERVIEWPAGE_H From 9c315c38fbadfa084b01974905ed8c7a1ff1e00d Mon Sep 17 00:00:00 2001 From: Kittywhiskers Van Gogh <63189531+kwvg@users.noreply.github.com> Date: Wed, 24 Dec 2025 20:03:49 +0530 Subject: [PATCH 05/14] qt: add monospaced font settings --- src/qt/forms/optionsdialog.ui | 100 ++++++++++++++++++++++++++++++++++ src/qt/guiutil_font.cpp | 6 +- src/qt/optionsdialog.cpp | 13 +++++ src/qt/optionsmodel.cpp | 13 +++++ src/qt/optionsmodel.h | 4 ++ src/qt/overviewpage.cpp | 3 +- 6 files changed, 137 insertions(+), 2 deletions(-) diff --git a/src/qt/forms/optionsdialog.ui b/src/qt/forms/optionsdialog.ui index 49e06646e9c3..90cfaaf08787 100644 --- a/src/qt/forms/optionsdialog.ui +++ b/src/qt/forms/optionsdialog.ui @@ -1095,6 +1095,106 @@ https://explore.transifex.com/dash/dash/ + + + + Monospaced font in the Overview tab: + + + + + + + + embedded "%1" + + + + + + + Qt::Horizontal + + + + 40 + 20 + + + + + + + + + + 111.11111111 DASH + + + + + + + 909.09090909 DASH + + + + + + + + + + + Qt::Horizontal + + + + + + + + + closest matching "%1" + + + + + + + Qt::Horizontal + + + + 40 + 20 + + + + + + + + + + 111.11111111 DASH + + + + + + + 909.09090909 DASH + + + + + + + + + + diff --git a/src/qt/guiutil_font.cpp b/src/qt/guiutil_font.cpp index 7190a32fe5ec..5671c3d4d840 100644 --- a/src/qt/guiutil_font.cpp +++ b/src/qt/guiutil_font.cpp @@ -94,8 +94,12 @@ constexpr std::array vecIgnoreClasses{ }; //! List of Qt objects to ignore when applying fonts -constexpr std::array vecIgnoreObjects{ +constexpr std::array vecIgnoreObjects{ + "embeddedFont_label_1", + "embeddedFont_label_9", "messagesWidget", + "systemFont_label_1", + "systemFont_label_9", }; //! Weights considered when testing for weights supported by a font diff --git a/src/qt/optionsdialog.cpp b/src/qt/optionsdialog.cpp index 9518d6f6ff38..1062c05cbc4b 100644 --- a/src/qt/optionsdialog.cpp +++ b/src/qt/optionsdialog.cpp @@ -217,6 +217,18 @@ OptionsDialog::OptionsDialog(QWidget *parent, bool enableWallet) : ui->minimizeToTray->setEnabled(false); } + QFont embedded_font{GUIUtil::fixedPitchFont(/*use_embedded_font=*/true)}; + ui->embeddedFont_radioButton->setText(ui->embeddedFont_radioButton->text().arg(embedded_font.family())); + ui->embeddedFont_label_1->setFont(embedded_font); + ui->embeddedFont_label_9->setFont(embedded_font); + + QFont system_font{GUIUtil::fixedPitchFont(/*use_embedded_font=*/false)}; + ui->systemFont_radioButton->setText(ui->systemFont_radioButton->text().arg(system_font.family())); + ui->systemFont_label_1->setFont(system_font); + ui->systemFont_label_9->setFont(system_font); + // Checking the embeddedFont_radioButton automatically unchecks the systemFont_radioButton. + ui->systemFont_radioButton->setChecked(true); + GUIUtil::handleCloseWindowShortcut(this); } @@ -381,6 +393,7 @@ void OptionsDialog::setMapper() mapper->addMapping(ui->lang, OptionsModel::Language); mapper->addMapping(ui->unit, OptionsModel::DisplayUnit); mapper->addMapping(ui->thirdPartyTxUrls, OptionsModel::ThirdPartyTxUrls); + mapper->addMapping(ui->embeddedFont_radioButton, OptionsModel::UseEmbeddedMonospacedFont); /* Appearance See AppearanceWidget::setModel diff --git a/src/qt/optionsmodel.cpp b/src/qt/optionsmodel.cpp index 173cde148016..bdfd42ce1a0d 100644 --- a/src/qt/optionsmodel.cpp +++ b/src/qt/optionsmodel.cpp @@ -356,6 +356,12 @@ void OptionsModel::Init(bool resetSettings) addOverriddenOption("-lang"); language = settings.value("language").toString(); + + if (!settings.contains("UseEmbeddedMonospacedFont")) { + settings.setValue("UseEmbeddedMonospacedFont", "true"); + } + m_use_embedded_monospaced_font = settings.value("UseEmbeddedMonospacedFont").toBool(); + Q_EMIT useEmbeddedMonospacedFontChanged(m_use_embedded_monospaced_font); } /** Helper function to copy contents from one QSettings to another. @@ -585,6 +591,8 @@ QVariant OptionsModel::data(const QModelIndex & index, int role) const } case Language: return settings.value("language"); + case UseEmbeddedMonospacedFont: + return m_use_embedded_monospaced_font; #ifdef ENABLE_WALLET case CoinControlFeatures: return fCoinControlFeatures; @@ -839,6 +847,11 @@ bool OptionsModel::setData(const QModelIndex & index, const QVariant & value, in setRestartRequired(true); } break; + case UseEmbeddedMonospacedFont: + m_use_embedded_monospaced_font = value.toBool(); + settings.setValue("UseEmbeddedMonospacedFont", m_use_embedded_monospaced_font); + Q_EMIT useEmbeddedMonospacedFontChanged(m_use_embedded_monospaced_font); + break; #ifdef ENABLE_WALLET case CoinControlFeatures: fCoinControlFeatures = value.toBool(); diff --git a/src/qt/optionsmodel.h b/src/qt/optionsmodel.h index 4ccf27c5e4f8..7df90fd8fa1a 100644 --- a/src/qt/optionsmodel.h +++ b/src/qt/optionsmodel.h @@ -66,6 +66,7 @@ class OptionsModel : public QAbstractListModel FontWeightNormal, // int FontWeightBold, // int Language, // QString + UseEmbeddedMonospacedFont, // bool CoinControlFeatures, // bool SubFeeFromAmount, // bool KeepChangeAddress, // bool @@ -108,6 +109,7 @@ class OptionsModel : public QAbstractListModel bool getMinimizeOnClose() const { return fMinimizeOnClose; } BitcoinUnit getDisplayUnit() const { return m_display_bitcoin_unit; } QString getThirdPartyTxUrls() const { return strThirdPartyTxUrls; } + bool getUseEmbeddedMonospacedFont() const { return m_use_embedded_monospaced_font; } bool getCoinControlFeatures() const { return fCoinControlFeatures; } bool getSubFeeFromAmount() const { return m_sub_fee_from_amount; } bool getEnablePSBTControls() const { return m_enable_psbt_controls; } @@ -138,6 +140,7 @@ class OptionsModel : public QAbstractListModel QString language; BitcoinUnit m_display_bitcoin_unit; QString strThirdPartyTxUrls; + bool m_use_embedded_monospaced_font; bool fCoinControlFeatures; bool m_sub_fee_from_amount; bool m_enable_psbt_controls; @@ -160,6 +163,7 @@ class OptionsModel : public QAbstractListModel void coinControlFeaturesChanged(bool); void keepChangeAddressChanged(bool); void showTrayIconChanged(bool); + void useEmbeddedMonospacedFontChanged(bool); }; #endif // BITCOIN_QT_OPTIONSMODEL_H diff --git a/src/qt/overviewpage.cpp b/src/qt/overviewpage.cpp index cfc445357eac..19f2bb651e0b 100644 --- a/src/qt/overviewpage.cpp +++ b/src/qt/overviewpage.cpp @@ -302,7 +302,8 @@ void OverviewPage::setClientModel(ClientModel *model) // Show warning, for example if this is a prerelease version connect(model, &ClientModel::alertsChanged, this, &OverviewPage::updateAlerts); updateAlerts(model->getStatusBarWarnings()); - setMonospacedFont(/*use_embedded_font=*/false); + connect(model->getOptionsModel(), &OptionsModel::useEmbeddedMonospacedFontChanged, this, &OverviewPage::setMonospacedFont); + setMonospacedFont(model->getOptionsModel()->getUseEmbeddedMonospacedFont()); // explicitly update CoinJoin frame and transaction list to reflect actual settings updateAdvancedCJUI(model->getOptionsModel()->getShowAdvancedCJUI()); } From eac4f52e1841f52189db3f51cbdd3ae08dd2ff35 Mon Sep 17 00:00:00 2001 From: Kittywhiskers Van Gogh <63189531+kwvg@users.noreply.github.com> Date: Thu, 28 Aug 2025 19:51:57 +0000 Subject: [PATCH 06/14] qt: adjust padding and font size of monospace font selector --- src/qt/forms/optionsdialog.ui | 12 ++++++++++++ src/qt/optionsdialog.cpp | 4 ++-- 2 files changed, 14 insertions(+), 2 deletions(-) diff --git a/src/qt/forms/optionsdialog.ui b/src/qt/forms/optionsdialog.ui index 90cfaaf08787..9afc138b412d 100644 --- a/src/qt/forms/optionsdialog.ui +++ b/src/qt/forms/optionsdialog.ui @@ -1101,6 +1101,18 @@ https://explore.transifex.com/dash/dash/ Monospaced font in the Overview tab: + + 18 + + + 18 + + + 18 + + + 18 + diff --git a/src/qt/optionsdialog.cpp b/src/qt/optionsdialog.cpp index 1062c05cbc4b..d30f522e3395 100644 --- a/src/qt/optionsdialog.cpp +++ b/src/qt/optionsdialog.cpp @@ -217,12 +217,12 @@ OptionsDialog::OptionsDialog(QWidget *parent, bool enableWallet) : ui->minimizeToTray->setEnabled(false); } - QFont embedded_font{GUIUtil::fixedPitchFont(/*use_embedded_font=*/true)}; + QFont embedded_font{GUIUtil::getFont({GUIUtil::ROBOTO_MONO_FONT_STR.toString(), GUIUtil::g_font_registry.GetWeightBold(), 10})}; ui->embeddedFont_radioButton->setText(ui->embeddedFont_radioButton->text().arg(embedded_font.family())); ui->embeddedFont_label_1->setFont(embedded_font); ui->embeddedFont_label_9->setFont(embedded_font); - QFont system_font{GUIUtil::fixedPitchFont(/*use_embedded_font=*/false)}; + QFont system_font{GUIUtil::getFont({GUIUtil::OS_MONO_FONT_STR.toString(), GUIUtil::g_font_registry.GetWeightBold(), 10})}; ui->systemFont_radioButton->setText(ui->systemFont_radioButton->text().arg(system_font.family())); ui->systemFont_label_1->setFont(system_font); ui->systemFont_label_9->setFont(system_font); From da5804e633a6436b360e41c1c7a2931d02f95e49 Mon Sep 17 00:00:00 2001 From: Kittywhiskers Van Gogh <63189531+kwvg@users.noreply.github.com> Date: Thu, 28 Aug 2025 19:53:37 +0000 Subject: [PATCH 07/14] merge bitcoin-core/gui#79: Embed monospaced font includes: - 22e0114d055b0ac6cdc47af2968b5dc742ba055a - 67f26319a0ca7e34e3db17d9330133622a40de09 continuation of 7774bdb423 from dash#6049 From 41c69e92f95a4af23f988a3bee301faa0298dc77 Mon Sep 17 00:00:00 2001 From: Kittywhiskers Van Gogh <63189531+kwvg@users.noreply.github.com> Date: Fri, 26 Dec 2025 17:31:11 +0530 Subject: [PATCH 08/14] merge bitcoin-core/gui#497: Enable users to configure their monospace font specifically --- src/qt/forms/optionsdialog.ui | 133 ++++++---------------------------- src/qt/guiutil_font.cpp | 7 +- src/qt/optionsdialog.cpp | 74 ++++++++++++++++--- src/qt/optionsmodel.cpp | 78 +++++++++++++++++--- src/qt/optionsmodel.h | 23 +++++- src/qt/overviewpage.cpp | 18 +++-- src/qt/overviewpage.h | 4 +- 7 files changed, 189 insertions(+), 148 deletions(-) diff --git a/src/qt/forms/optionsdialog.ui b/src/qt/forms/optionsdialog.ui index 9afc138b412d..04d5da99d3ff 100644 --- a/src/qt/forms/optionsdialog.ui +++ b/src/qt/forms/optionsdialog.ui @@ -1096,116 +1096,29 @@ https://explore.transifex.com/dash/dash/ - - - Monospaced font in the Overview tab: - - - - 18 - - - 18 - - - 18 - - - 18 - - - - - - - embedded "%1" - - - - - - - Qt::Horizontal - - - - 40 - 20 - - - - - - - - - - 111.11111111 DASH - - - - - - - 909.09090909 DASH - - - - - - - - - - - Qt::Horizontal - - - - - - - - - closest matching "%1" - - - - - - - Qt::Horizontal - - - - 40 - 20 - - - - - - - - - - 111.11111111 DASH - - - - - - - 909.09090909 DASH - - - - - - - - - + + + + + Font in the Overview tab: + + + moneyFont + + + + + + + + + + 111.11111111 DASH +909.09090909 DASH + + + + diff --git a/src/qt/guiutil_font.cpp b/src/qt/guiutil_font.cpp index 5671c3d4d840..0913f3ddc507 100644 --- a/src/qt/guiutil_font.cpp +++ b/src/qt/guiutil_font.cpp @@ -94,12 +94,9 @@ constexpr std::array vecIgnoreClasses{ }; //! List of Qt objects to ignore when applying fonts -constexpr std::array vecIgnoreObjects{ - "embeddedFont_label_1", - "embeddedFont_label_9", +constexpr std::array vecIgnoreObjects{ "messagesWidget", - "systemFont_label_1", - "systemFont_label_9", + "moneyFont_preview", }; //! Weights considered when testing for weights supported by a font diff --git a/src/qt/optionsdialog.cpp b/src/qt/optionsdialog.cpp index d30f522e3395..4e2cb58b6cc8 100644 --- a/src/qt/optionsdialog.cpp +++ b/src/qt/optionsdialog.cpp @@ -29,9 +29,11 @@ #include +#include #include #include #include +#include #include #include #include @@ -40,6 +42,60 @@ #include #include +int setFontChoice(QComboBox* cb, const OptionsModel::FontChoice& fc) +{ + int i; + for (i = cb->count(); --i >= 0; ) { + QVariant item_data = cb->itemData(i); + if (!item_data.canConvert()) continue; + if (item_data.value() == fc) { + break; + } + } + if (i == -1) { + // New item needed + QFont chosen_font = OptionsModel::getFontForChoice(fc); + QSignalBlocker block_currentindexchanged_signal(cb); // avoid triggering QFontDialog + cb->insertItem(0, QFontInfo(chosen_font).family(), QVariant::fromValue(fc)); + i = 0; + } + + cb->setCurrentIndex(i); + return i; +} + +void setupFontOptions(QComboBox* cb, QLabel* preview) +{ + QFont embedded_font{GUIUtil::fixedPitchFont(true)}; + QFont system_font{GUIUtil::fixedPitchFont(false)}; + cb->addItem(QObject::tr("Embedded \"%1\"").arg(QFontInfo(embedded_font).family()), QVariant::fromValue(OptionsModel::FontChoice{OptionsModel::FontChoiceAbstract::EmbeddedFont})); + cb->addItem(QObject::tr("Default system font \"%1\"").arg(QFontInfo(system_font).family()), QVariant::fromValue(OptionsModel::FontChoice{OptionsModel::FontChoiceAbstract::BestSystemFont})); + cb->addItem(QObject::tr("Custom…")); + + const auto& on_font_choice_changed = [cb, preview](int index) { + static int previous_index = -1; + QVariant item_data = cb->itemData(index); + QFont f; + if (item_data.canConvert()) { + f = OptionsModel::getFontForChoice(item_data.value()); + } else { + bool ok; + f = QFontDialog::getFont(&ok, GUIUtil::fixedPitchFont(false), cb->parentWidget()); + if (!ok) { + cb->setCurrentIndex(previous_index); + return; + } + index = setFontChoice(cb, OptionsModel::FontChoice{f}); + } + if (preview) { + preview->setFont(f); + } + previous_index = index; + }; + QObject::connect(cb, QOverload::of(&QComboBox::currentIndexChanged), on_font_choice_changed); + on_font_choice_changed(cb->currentIndex()); +} + OptionsDialog::OptionsDialog(QWidget *parent, bool enableWallet) : QDialog(parent, GUIUtil::dialog_flags), ui(new Ui::OptionsDialog), @@ -217,17 +273,7 @@ OptionsDialog::OptionsDialog(QWidget *parent, bool enableWallet) : ui->minimizeToTray->setEnabled(false); } - QFont embedded_font{GUIUtil::getFont({GUIUtil::ROBOTO_MONO_FONT_STR.toString(), GUIUtil::g_font_registry.GetWeightBold(), 10})}; - ui->embeddedFont_radioButton->setText(ui->embeddedFont_radioButton->text().arg(embedded_font.family())); - ui->embeddedFont_label_1->setFont(embedded_font); - ui->embeddedFont_label_9->setFont(embedded_font); - - QFont system_font{GUIUtil::getFont({GUIUtil::OS_MONO_FONT_STR.toString(), GUIUtil::g_font_registry.GetWeightBold(), 10})}; - ui->systemFont_radioButton->setText(ui->systemFont_radioButton->text().arg(system_font.family())); - ui->systemFont_label_1->setFont(system_font); - ui->systemFont_label_9->setFont(system_font); - // Checking the embeddedFont_radioButton automatically unchecks the systemFont_radioButton. - ui->systemFont_radioButton->setChecked(true); + setupFontOptions(ui->moneyFont, ui->moneyFont_preview); GUIUtil::handleCloseWindowShortcut(this); } @@ -280,6 +326,9 @@ void OptionsDialog::setModel(OptionsModel *_model) appearance->setModel(_model); + const auto& font_for_money = _model->data(_model->index(OptionsModel::FontForMoney, 0), Qt::EditRole).value(); + setFontChoice(ui->moneyFont, font_for_money); + updateDefaultProxyNets(); } @@ -393,7 +442,6 @@ void OptionsDialog::setMapper() mapper->addMapping(ui->lang, OptionsModel::Language); mapper->addMapping(ui->unit, OptionsModel::DisplayUnit); mapper->addMapping(ui->thirdPartyTxUrls, OptionsModel::ThirdPartyTxUrls); - mapper->addMapping(ui->embeddedFont_radioButton, OptionsModel::UseEmbeddedMonospacedFont); /* Appearance See AppearanceWidget::setModel @@ -454,6 +502,8 @@ void OptionsDialog::on_resetButton_clicked() void OptionsDialog::on_okButton_clicked() { + model->setData(model->index(OptionsModel::FontForMoney, 0), ui->moneyFont->itemData(ui->moneyFont->currentIndex())); + mapper->submit(); appearance->accept(); #ifdef ENABLE_WALLET diff --git a/src/qt/optionsmodel.cpp b/src/qt/optionsmodel.cpp index bdfd42ce1a0d..58e8550cb121 100644 --- a/src/qt/optionsmodel.cpp +++ b/src/qt/optionsmodel.cpp @@ -36,6 +36,37 @@ const char *DEFAULT_GUI_PROXY_HOST = "127.0.0.1"; static QString GetDefaultProxyAddress(); +static const QLatin1String fontchoice_str_embedded{"embedded"}; +static const QLatin1String fontchoice_str_best_system{"best_system"}; +static const QString fontchoice_str_custom_prefix{QStringLiteral("custom, ")}; + +QString OptionsModel::FontChoiceToString(const OptionsModel::FontChoice& f) +{ + if (std::holds_alternative(f)) { + if (f == UseBestSystemFont) { + return fontchoice_str_best_system; + } else { + return fontchoice_str_embedded; + } + } + return fontchoice_str_custom_prefix + std::get(f).toString(); +} + +OptionsModel::FontChoice OptionsModel::FontChoiceFromString(const QString& s) +{ + if (s == fontchoice_str_best_system) { + return FontChoiceAbstract::BestSystemFont; + } else if (s == fontchoice_str_embedded) { + return FontChoiceAbstract::EmbeddedFont; + } else if (s.startsWith(fontchoice_str_custom_prefix)) { + QFont f; + f.fromString(s.mid(fontchoice_str_custom_prefix.size())); + return f; + } else { + return FontChoiceAbstract::EmbeddedFont; // default + } +} + OptionsModel::OptionsModel(QObject *parent, bool resetSettings) : QAbstractListModel(parent) { @@ -357,11 +388,16 @@ void OptionsModel::Init(bool resetSettings) language = settings.value("language").toString(); - if (!settings.contains("UseEmbeddedMonospacedFont")) { - settings.setValue("UseEmbeddedMonospacedFont", "true"); + if (settings.contains("FontForMoney")) { + m_font_money = FontChoiceFromString(settings.value("FontForMoney").toString()); + } else if (settings.contains("UseEmbeddedMonospacedFont")) { + if (settings.value("UseEmbeddedMonospacedFont").toBool()) { + m_font_money = FontChoiceAbstract::EmbeddedFont; + } else { + m_font_money = FontChoiceAbstract::BestSystemFont; + } } - m_use_embedded_monospaced_font = settings.value("UseEmbeddedMonospacedFont").toBool(); - Q_EMIT useEmbeddedMonospacedFontChanged(m_use_embedded_monospaced_font); + Q_EMIT fontForMoneyChanged(getFontForMoney()); } /** Helper function to copy contents from one QSettings to another. @@ -478,6 +514,24 @@ void OptionsModel::SetPruneTargetGB(int prune_target_gb, bool force) SetPruneEnabled(prune, force); } +QFont OptionsModel::getFontForChoice(const FontChoice& fc) +{ + QFont f; + if (std::holds_alternative(fc)) { + f = GUIUtil::fixedPitchFont(fc != UseBestSystemFont); + f.setWeight(QFont::Bold); + } else { + f = std::get(fc); + } + f.setPointSize(10); + return f; +} + +QFont OptionsModel::getFontForMoney() const +{ + return getFontForChoice(m_font_money); +} + // read QSettings values and return them QVariant OptionsModel::data(const QModelIndex & index, int role) const { @@ -591,8 +645,8 @@ QVariant OptionsModel::data(const QModelIndex & index, int role) const } case Language: return settings.value("language"); - case UseEmbeddedMonospacedFont: - return m_use_embedded_monospaced_font; + case FontForMoney: + return QVariant::fromValue(m_font_money); #ifdef ENABLE_WALLET case CoinControlFeatures: return fCoinControlFeatures; @@ -847,11 +901,15 @@ bool OptionsModel::setData(const QModelIndex & index, const QVariant & value, in setRestartRequired(true); } break; - case UseEmbeddedMonospacedFont: - m_use_embedded_monospaced_font = value.toBool(); - settings.setValue("UseEmbeddedMonospacedFont", m_use_embedded_monospaced_font); - Q_EMIT useEmbeddedMonospacedFontChanged(m_use_embedded_monospaced_font); + case FontForMoney: + { + const auto& new_font = value.value(); + if (m_font_money == new_font) break; + settings.setValue("FontForMoney", FontChoiceToString(new_font)); + m_font_money = new_font; + Q_EMIT fontForMoneyChanged(getFontForMoney()); break; + } #ifdef ENABLE_WALLET case CoinControlFeatures: fCoinControlFeatures = value.toBool(); diff --git a/src/qt/optionsmodel.h b/src/qt/optionsmodel.h index 7df90fd8fa1a..09c735664dec 100644 --- a/src/qt/optionsmodel.h +++ b/src/qt/optionsmodel.h @@ -11,8 +11,10 @@ #include #include +#include #include +#include namespace interfaces { class Node; @@ -66,7 +68,7 @@ class OptionsModel : public QAbstractListModel FontWeightNormal, // int FontWeightBold, // int Language, // QString - UseEmbeddedMonospacedFont, // bool + FontForMoney, // FontChoice CoinControlFeatures, // bool SubFeeFromAmount, // bool KeepChangeAddress, // bool @@ -94,6 +96,14 @@ class OptionsModel : public QAbstractListModel OptionIDRowCount, }; + enum class FontChoiceAbstract { + EmbeddedFont, + BestSystemFont, + }; + typedef std::variant FontChoice; + static inline const FontChoice UseBestSystemFont{FontChoiceAbstract::BestSystemFont}; + static QFont getFontForChoice(const FontChoice& fc); + void Init(bool resetSettings = false); void Reset(); @@ -109,7 +119,7 @@ class OptionsModel : public QAbstractListModel bool getMinimizeOnClose() const { return fMinimizeOnClose; } BitcoinUnit getDisplayUnit() const { return m_display_bitcoin_unit; } QString getThirdPartyTxUrls() const { return strThirdPartyTxUrls; } - bool getUseEmbeddedMonospacedFont() const { return m_use_embedded_monospaced_font; } + QFont getFontForMoney() const; bool getCoinControlFeatures() const { return fCoinControlFeatures; } bool getSubFeeFromAmount() const { return m_sub_fee_from_amount; } bool getEnablePSBTControls() const { return m_enable_psbt_controls; } @@ -140,7 +150,7 @@ class OptionsModel : public QAbstractListModel QString language; BitcoinUnit m_display_bitcoin_unit; QString strThirdPartyTxUrls; - bool m_use_embedded_monospaced_font; + FontChoice m_font_money{FontChoiceAbstract::EmbeddedFont}; bool fCoinControlFeatures; bool m_sub_fee_from_amount; bool m_enable_psbt_controls; @@ -149,6 +159,9 @@ class OptionsModel : public QAbstractListModel /* settings that were overridden by command-line */ QString strOverriddenByCommandLine; + static QString FontChoiceToString(const OptionsModel::FontChoice&); + static FontChoice FontChoiceFromString(const QString&); + // Add option to list of GUI options overridden through command line/config file void addOverriddenOption(const std::string &option); @@ -163,7 +176,9 @@ class OptionsModel : public QAbstractListModel void coinControlFeaturesChanged(bool); void keepChangeAddressChanged(bool); void showTrayIconChanged(bool); - void useEmbeddedMonospacedFontChanged(bool); + void fontForMoneyChanged(const QFont&); }; +Q_DECLARE_METATYPE(OptionsModel::FontChoice) + #endif // BITCOIN_QT_OPTIONSMODEL_H diff --git a/src/qt/overviewpage.cpp b/src/qt/overviewpage.cpp index 19f2bb651e0b..feb4c59226e3 100644 --- a/src/qt/overviewpage.cpp +++ b/src/qt/overviewpage.cpp @@ -165,7 +165,13 @@ OverviewPage::OverviewPage(QWidget* parent) : }, {GUIUtil::g_font_registry.GetWeightBold()}); // Calls GUIUtil::updateFonts() internally - setMonospacedFont(/*use_embedded_font=*/false); + setMonospacedFont(GUIUtil::fixedPitchFont( +#ifdef Q_OS_MACOS + true +#else + false +#endif // Q_OS_MACOS + )); m_balances.balance = -1; @@ -302,8 +308,8 @@ void OverviewPage::setClientModel(ClientModel *model) // Show warning, for example if this is a prerelease version connect(model, &ClientModel::alertsChanged, this, &OverviewPage::updateAlerts); updateAlerts(model->getStatusBarWarnings()); - connect(model->getOptionsModel(), &OptionsModel::useEmbeddedMonospacedFontChanged, this, &OverviewPage::setMonospacedFont); - setMonospacedFont(model->getOptionsModel()->getUseEmbeddedMonospacedFont()); + connect(model->getOptionsModel(), &OptionsModel::fontForMoneyChanged, this, &OverviewPage::setMonospacedFont); + setMonospacedFont(clientModel->getOptionsModel()->getFontForMoney()); // explicitly update CoinJoin frame and transaction list to reflect actual settings updateAdvancedCJUI(model->getOptionsModel()->getShowAdvancedCJUI()); } @@ -376,12 +382,12 @@ void OverviewPage::showOutOfSyncWarning(bool fShow) ui->labelTransactionsStatus->setVisible(fShow); } -void OverviewPage::setMonospacedFont(bool use_embedded_font) +void OverviewPage::setMonospacedFont(const QFont& f) { GUIUtil::setFont({ ui->labelTotal, ui->labelWatchTotal, - }, {GUIUtil::fixedPitchFont(use_embedded_font).family(), GUIUtil::g_font_registry.GetWeightBold(), 14}); + }, {f.family(), GUIUtil::g_font_registry.GetWeightBold(), 14}); GUIUtil::setFont({ ui->labelAmountRounds, @@ -393,7 +399,7 @@ void OverviewPage::setMonospacedFont(bool use_embedded_font) ui->labelWatchAvailable, ui->labelWatchPending, ui->labelWatchImmature, - }, {GUIUtil::fixedPitchFont(use_embedded_font).family(), GUIUtil::g_font_registry.GetWeightBold()}); + }, {f.family(), GUIUtil::g_font_registry.GetWeightBold()}); GUIUtil::updateFonts(); } diff --git a/src/qt/overviewpage.h b/src/qt/overviewpage.h index 62d9a0dbc5d5..8c507e073e2a 100644 --- a/src/qt/overviewpage.h +++ b/src/qt/overviewpage.h @@ -8,7 +8,9 @@ #include #include +#include #include + #include class ClientModel; @@ -71,7 +73,7 @@ private Q_SLOTS: void handleTransactionClicked(const QModelIndex &index); void updateAlerts(const QString &warnings); void updateWatchOnlyLabels(bool showWatchOnly); - void setMonospacedFont(bool use_embedded_font); + void setMonospacedFont(const QFont&); }; #endif // BITCOIN_QT_OVERVIEWPAGE_H From e5a8d0523e61c4bd32c2dbbef07becb05c4034a3 Mon Sep 17 00:00:00 2001 From: Kittywhiskers Van Gogh <63189531+kwvg@users.noreply.github.com> Date: Fri, 26 Dec 2025 17:14:48 +0530 Subject: [PATCH 09/14] refactor: move monospace font selector to appearance widget Dash already has an appearance widget for managing font parameters, the selector shouldn't be in "Display". Review with `git log -p -n1 --color-moved=dimmed_zebra`. --- src/qt/appearancewidget.cpp | 65 ++++++++++++++++++++++++++++++++ src/qt/forms/appearancewidget.ui | 25 ++++++++++++ src/qt/forms/optionsdialog.ui | 25 ------------ src/qt/optionsdialog.cpp | 63 ------------------------------- 4 files changed, 90 insertions(+), 88 deletions(-) diff --git a/src/qt/appearancewidget.cpp b/src/qt/appearancewidget.cpp index 300edd30e06c..fdabbb1b6ba5 100644 --- a/src/qt/appearancewidget.cpp +++ b/src/qt/appearancewidget.cpp @@ -15,9 +15,65 @@ #include #include +#include +#include #include #include +int setFontChoice(QComboBox* cb, const OptionsModel::FontChoice& fc) +{ + int i; + for (i = cb->count(); --i >= 0; ) { + QVariant item_data = cb->itemData(i); + if (!item_data.canConvert()) continue; + if (item_data.value() == fc) { + break; + } + } + if (i == -1) { + // New item needed + QFont chosen_font = OptionsModel::getFontForChoice(fc); + QSignalBlocker block_currentindexchanged_signal(cb); // avoid triggering QFontDialog + cb->insertItem(0, QFontInfo(chosen_font).family(), QVariant::fromValue(fc)); + i = 0; + } + + cb->setCurrentIndex(i); + return i; +} + +void setupFontOptions(QComboBox* cb, QLabel* preview) +{ + QFont embedded_font{GUIUtil::fixedPitchFont(true)}; + QFont system_font{GUIUtil::fixedPitchFont(false)}; + cb->addItem(QObject::tr("Embedded \"%1\"").arg(QFontInfo(embedded_font).family()), QVariant::fromValue(OptionsModel::FontChoice{OptionsModel::FontChoiceAbstract::EmbeddedFont})); + cb->addItem(QObject::tr("Default system font \"%1\"").arg(QFontInfo(system_font).family()), QVariant::fromValue(OptionsModel::FontChoice{OptionsModel::FontChoiceAbstract::BestSystemFont})); + cb->addItem(QObject::tr("Custom…")); + + const auto& on_font_choice_changed = [cb, preview](int index) { + static int previous_index = -1; + QVariant item_data = cb->itemData(index); + QFont f; + if (item_data.canConvert()) { + f = OptionsModel::getFontForChoice(item_data.value()); + } else { + bool ok; + f = QFontDialog::getFont(&ok, GUIUtil::fixedPitchFont(false), cb->parentWidget()); + if (!ok) { + cb->setCurrentIndex(previous_index); + return; + } + index = setFontChoice(cb, OptionsModel::FontChoice{f}); + } + if (preview) { + preview->setFont(f); + } + previous_index = index; + }; + QObject::connect(cb, QOverload::of(&QComboBox::currentIndexChanged), on_font_choice_changed); + on_font_choice_changed(cb->currentIndex()); +} + AppearanceWidget::AppearanceWidget(QWidget* parent) : QWidget(parent), ui{new Ui::AppearanceWidget()}, @@ -55,6 +111,9 @@ AppearanceWidget::AppearanceWidget(QWidget* parent) : connect(ui->fontScaleSlider, &QSlider::sliderReleased, [this]() { Q_EMIT appearanceChanged(); }); connect(ui->fontWeightNormalSlider, &QSlider::sliderReleased, [this]() { Q_EMIT appearanceChanged(); }); connect(ui->fontWeightBoldSlider, &QSlider::sliderReleased, [this]() { Q_EMIT appearanceChanged(); }); + + setupFontOptions(ui->moneyFont, ui->moneyFont_preview); + connect(ui->moneyFont, &QComboBox::currentTextChanged, [this]() { Q_EMIT appearanceChanged(); }); } AppearanceWidget::~AppearanceWidget() @@ -104,6 +163,9 @@ void AppearanceWidget::setModel(OptionsModel* _model) mapper->toFirst(); + const auto& font_for_money = _model->data(_model->index(OptionsModel::FontForMoney, 0), Qt::EditRole).value(); + setFontChoice(ui->moneyFont, font_for_money); + const bool override_family{_model->isOptionOverridden("-font-family")}; if (override_family) { ui->fontFamily->setEnabled(false); @@ -139,6 +201,9 @@ void AppearanceWidget::setModel(OptionsModel* _model) void AppearanceWidget::accept() { fAcceptChanges = true; + if (model) { + model->setData(model->index(OptionsModel::FontForMoney, 0), ui->moneyFont->itemData(ui->moneyFont->currentIndex())); + } } void AppearanceWidget::updateTheme(const QString& theme) diff --git a/src/qt/forms/appearancewidget.ui b/src/qt/forms/appearancewidget.ui index d8d42ad007a6..80fde5faf97c 100644 --- a/src/qt/forms/appearancewidget.ui +++ b/src/qt/forms/appearancewidget.ui @@ -479,6 +479,31 @@ + + + + + + Font in the Overview tab: + + + moneyFont + + + + + + + + + + 111.11111111 DASH +909.09090909 DASH + + + + + diff --git a/src/qt/forms/optionsdialog.ui b/src/qt/forms/optionsdialog.ui index 04d5da99d3ff..49e06646e9c3 100644 --- a/src/qt/forms/optionsdialog.ui +++ b/src/qt/forms/optionsdialog.ui @@ -1095,31 +1095,6 @@ https://explore.transifex.com/dash/dash/ - - - - - - Font in the Overview tab: - - - moneyFont - - - - - - - - - - 111.11111111 DASH -909.09090909 DASH - - - - - diff --git a/src/qt/optionsdialog.cpp b/src/qt/optionsdialog.cpp index 4e2cb58b6cc8..9518d6f6ff38 100644 --- a/src/qt/optionsdialog.cpp +++ b/src/qt/optionsdialog.cpp @@ -29,11 +29,9 @@ #include -#include #include #include #include -#include #include #include #include @@ -42,60 +40,6 @@ #include #include -int setFontChoice(QComboBox* cb, const OptionsModel::FontChoice& fc) -{ - int i; - for (i = cb->count(); --i >= 0; ) { - QVariant item_data = cb->itemData(i); - if (!item_data.canConvert()) continue; - if (item_data.value() == fc) { - break; - } - } - if (i == -1) { - // New item needed - QFont chosen_font = OptionsModel::getFontForChoice(fc); - QSignalBlocker block_currentindexchanged_signal(cb); // avoid triggering QFontDialog - cb->insertItem(0, QFontInfo(chosen_font).family(), QVariant::fromValue(fc)); - i = 0; - } - - cb->setCurrentIndex(i); - return i; -} - -void setupFontOptions(QComboBox* cb, QLabel* preview) -{ - QFont embedded_font{GUIUtil::fixedPitchFont(true)}; - QFont system_font{GUIUtil::fixedPitchFont(false)}; - cb->addItem(QObject::tr("Embedded \"%1\"").arg(QFontInfo(embedded_font).family()), QVariant::fromValue(OptionsModel::FontChoice{OptionsModel::FontChoiceAbstract::EmbeddedFont})); - cb->addItem(QObject::tr("Default system font \"%1\"").arg(QFontInfo(system_font).family()), QVariant::fromValue(OptionsModel::FontChoice{OptionsModel::FontChoiceAbstract::BestSystemFont})); - cb->addItem(QObject::tr("Custom…")); - - const auto& on_font_choice_changed = [cb, preview](int index) { - static int previous_index = -1; - QVariant item_data = cb->itemData(index); - QFont f; - if (item_data.canConvert()) { - f = OptionsModel::getFontForChoice(item_data.value()); - } else { - bool ok; - f = QFontDialog::getFont(&ok, GUIUtil::fixedPitchFont(false), cb->parentWidget()); - if (!ok) { - cb->setCurrentIndex(previous_index); - return; - } - index = setFontChoice(cb, OptionsModel::FontChoice{f}); - } - if (preview) { - preview->setFont(f); - } - previous_index = index; - }; - QObject::connect(cb, QOverload::of(&QComboBox::currentIndexChanged), on_font_choice_changed); - on_font_choice_changed(cb->currentIndex()); -} - OptionsDialog::OptionsDialog(QWidget *parent, bool enableWallet) : QDialog(parent, GUIUtil::dialog_flags), ui(new Ui::OptionsDialog), @@ -273,8 +217,6 @@ OptionsDialog::OptionsDialog(QWidget *parent, bool enableWallet) : ui->minimizeToTray->setEnabled(false); } - setupFontOptions(ui->moneyFont, ui->moneyFont_preview); - GUIUtil::handleCloseWindowShortcut(this); } @@ -326,9 +268,6 @@ void OptionsDialog::setModel(OptionsModel *_model) appearance->setModel(_model); - const auto& font_for_money = _model->data(_model->index(OptionsModel::FontForMoney, 0), Qt::EditRole).value(); - setFontChoice(ui->moneyFont, font_for_money); - updateDefaultProxyNets(); } @@ -502,8 +441,6 @@ void OptionsDialog::on_resetButton_clicked() void OptionsDialog::on_okButton_clicked() { - model->setData(model->index(OptionsModel::FontForMoney, 0), ui->moneyFont->itemData(ui->moneyFont->currentIndex())); - mapper->submit(); appearance->accept(); #ifdef ENABLE_WALLET From e0513ff16a71cfff3dd161a7d34e6f39567035cd Mon Sep 17 00:00:00 2001 From: Kittywhiskers Van Gogh <63189531+kwvg@users.noreply.github.com> Date: Fri, 26 Dec 2025 15:28:58 +0530 Subject: [PATCH 10/14] qt: add horizontal spacer for visual consistency --- src/qt/forms/appearancewidget.ui | 13 +++++++++++++ 1 file changed, 13 insertions(+) diff --git a/src/qt/forms/appearancewidget.ui b/src/qt/forms/appearancewidget.ui index 80fde5faf97c..7a88033bfa55 100644 --- a/src/qt/forms/appearancewidget.ui +++ b/src/qt/forms/appearancewidget.ui @@ -491,6 +491,19 @@ + + + + Qt::Horizontal + + + + 40 + 20 + + + + From 658905b7847d646fdf283128ad764f1d688a3457 Mon Sep 17 00:00:00 2001 From: Kittywhiskers Van Gogh <63189531+kwvg@users.noreply.github.com> Date: Fri, 26 Dec 2025 17:27:04 +0530 Subject: [PATCH 11/14] qt: add non-monospace option and use it as default Also: - Refactor `AppearanceWidget` ctor to bunch `connect` calls - Add refresh of money preview if using default font and font choice or boldness changed --- src/qt/appearancewidget.cpp | 39 +++++++++++++++++++++++++++++-------- src/qt/appearancewidget.h | 1 + src/qt/optionsmodel.cpp | 37 ++++++++++++++++++++++++++--------- src/qt/optionsmodel.h | 5 +++-- src/qt/overviewpage.cpp | 8 +------- 5 files changed, 64 insertions(+), 26 deletions(-) diff --git a/src/qt/appearancewidget.cpp b/src/qt/appearancewidget.cpp index fdabbb1b6ba5..77e4946df4ac 100644 --- a/src/qt/appearancewidget.cpp +++ b/src/qt/appearancewidget.cpp @@ -46,8 +46,9 @@ void setupFontOptions(QComboBox* cb, QLabel* preview) { QFont embedded_font{GUIUtil::fixedPitchFont(true)}; QFont system_font{GUIUtil::fixedPitchFont(false)}; + cb->addItem(QObject::tr("Default monospace font \"%1\"").arg(QFontInfo(system_font).family()), QVariant::fromValue(OptionsModel::FontChoice{OptionsModel::FontChoiceAbstract::BestSystemFont})); cb->addItem(QObject::tr("Embedded \"%1\"").arg(QFontInfo(embedded_font).family()), QVariant::fromValue(OptionsModel::FontChoice{OptionsModel::FontChoiceAbstract::EmbeddedFont})); - cb->addItem(QObject::tr("Default system font \"%1\"").arg(QFontInfo(system_font).family()), QVariant::fromValue(OptionsModel::FontChoice{OptionsModel::FontChoiceAbstract::BestSystemFont})); + cb->addItem(QObject::tr("Use existing font"), QVariant::fromValue(OptionsModel::FontChoice{OptionsModel::FontChoiceAbstract::ApplicationFont})); cb->addItem(QObject::tr("Custom…")); const auto& on_font_choice_changed = [cb, preview](int index) { @@ -100,20 +101,26 @@ AppearanceWidget::AppearanceWidget(QWidget* parent) : mapper->setSubmitPolicy(QDataWidgetMapper::ManualSubmit); mapper->setOrientation(Qt::Vertical); - connect(ui->theme, &QComboBox::currentTextChanged, this, &AppearanceWidget::updateTheme); + setupFontOptions(ui->moneyFont, ui->moneyFont_preview); + connect(ui->fontFamily, QOverload::of(&QComboBox::currentIndexChanged), this, &AppearanceWidget::updateFontFamily); + connect(ui->fontFamily, QOverload::of(&QComboBox::currentIndexChanged), [this]() { Q_EMIT appearanceChanged(); }); + connect(ui->fontFamily, QOverload::of(&QComboBox::currentIndexChanged), this, &AppearanceWidget::updateMoneyPreview); + + connect(ui->fontScaleSlider, &QSlider::sliderReleased, [this]() { Q_EMIT appearanceChanged(); }); connect(ui->fontScaleSlider, &QSlider::valueChanged, this, &AppearanceWidget::updateFontScale); - connect(ui->fontWeightNormalSlider, &QSlider::valueChanged, [this](auto nValue) { updateFontWeightNormal(nValue); }); + + connect(ui->fontWeightBoldSlider, &QSlider::sliderReleased, [this]() { Q_EMIT appearanceChanged(); }); connect(ui->fontWeightBoldSlider, &QSlider::valueChanged, [this](auto nValue) { updateFontWeightBold(nValue); }); + connect(ui->fontWeightBoldSlider, &QSlider::valueChanged, this, &AppearanceWidget::updateMoneyPreview); - connect(ui->theme, &QComboBox::currentTextChanged, [this]() { Q_EMIT appearanceChanged(); }); - connect(ui->fontFamily, &QComboBox::currentTextChanged, [this]() { Q_EMIT appearanceChanged(); }); - connect(ui->fontScaleSlider, &QSlider::sliderReleased, [this]() { Q_EMIT appearanceChanged(); }); connect(ui->fontWeightNormalSlider, &QSlider::sliderReleased, [this]() { Q_EMIT appearanceChanged(); }); - connect(ui->fontWeightBoldSlider, &QSlider::sliderReleased, [this]() { Q_EMIT appearanceChanged(); }); + connect(ui->fontWeightNormalSlider, &QSlider::valueChanged, [this](auto nValue) { updateFontWeightNormal(nValue); }); - setupFontOptions(ui->moneyFont, ui->moneyFont_preview); connect(ui->moneyFont, &QComboBox::currentTextChanged, [this]() { Q_EMIT appearanceChanged(); }); + + connect(ui->theme, &QComboBox::currentTextChanged, this, &AppearanceWidget::updateTheme); + connect(ui->theme, &QComboBox::currentTextChanged, [this]() { Q_EMIT appearanceChanged(); }); } AppearanceWidget::~AppearanceWidget() @@ -259,6 +266,22 @@ void AppearanceWidget::updateFontWeightBold(int nValue, bool fForce) GUIUtil::updateFonts(); } +void AppearanceWidget::updateMoneyPreview() +{ + QVariant item_data = ui->moneyFont->currentData(); + if (!item_data.canConvert()) { + return; + } + const auto fc = item_data.value(); + if (!std::holds_alternative(fc)) { + return; + } + if (std::get(fc) != OptionsModel::FontChoiceAbstract::ApplicationFont) { + return; + } + ui->moneyFont_preview->setFont(GUIUtil::getFontBold()); +} + void AppearanceWidget::updateWeightSlider(const bool fForce) { int nMaximum = GUIUtil::g_font_registry.GetSupportedWeights().size() - 1; diff --git a/src/qt/appearancewidget.h b/src/qt/appearancewidget.h index d55c685d08ce..ff289ab84d94 100644 --- a/src/qt/appearancewidget.h +++ b/src/qt/appearancewidget.h @@ -42,6 +42,7 @@ private Q_SLOTS: void updateFontScale(int nScale); void updateFontWeightNormal(int nValue, bool fForce = false); void updateFontWeightBold(int nValue, bool fForce = false); + void updateMoneyPreview(); private: Ui::AppearanceWidget* ui; diff --git a/src/qt/optionsmodel.cpp b/src/qt/optionsmodel.cpp index 58e8550cb121..13ce12aadd55 100644 --- a/src/qt/optionsmodel.cpp +++ b/src/qt/optionsmodel.cpp @@ -36,6 +36,7 @@ const char *DEFAULT_GUI_PROXY_HOST = "127.0.0.1"; static QString GetDefaultProxyAddress(); +static const QLatin1String fontchoice_str_app_font{"application_font"}; static const QLatin1String fontchoice_str_embedded{"embedded"}; static const QLatin1String fontchoice_str_best_system{"best_system"}; static const QString fontchoice_str_custom_prefix{QStringLiteral("custom, ")}; @@ -43,18 +44,24 @@ static const QString fontchoice_str_custom_prefix{QStringLiteral("custom, ")}; QString OptionsModel::FontChoiceToString(const OptionsModel::FontChoice& f) { if (std::holds_alternative(f)) { - if (f == UseBestSystemFont) { + switch (std::get(f)) { + case FontChoiceAbstract::ApplicationFont: + return fontchoice_str_app_font; + case FontChoiceAbstract::BestSystemFont: return fontchoice_str_best_system; - } else { + case FontChoiceAbstract::EmbeddedFont: return fontchoice_str_embedded; } + assert(false); } return fontchoice_str_custom_prefix + std::get(f).toString(); } OptionsModel::FontChoice OptionsModel::FontChoiceFromString(const QString& s) { - if (s == fontchoice_str_best_system) { + if (s == fontchoice_str_app_font) { + return FontChoiceAbstract::ApplicationFont; + } else if (s == fontchoice_str_best_system) { return FontChoiceAbstract::BestSystemFont; } else if (s == fontchoice_str_embedded) { return FontChoiceAbstract::EmbeddedFont; @@ -63,7 +70,7 @@ OptionsModel::FontChoice OptionsModel::FontChoiceFromString(const QString& s) f.fromString(s.mid(fontchoice_str_custom_prefix.size())); return f; } else { - return FontChoiceAbstract::EmbeddedFont; // default + return FontChoiceAbstract::ApplicationFont; // default } } @@ -518,8 +525,19 @@ QFont OptionsModel::getFontForChoice(const FontChoice& fc) { QFont f; if (std::holds_alternative(fc)) { - f = GUIUtil::fixedPitchFont(fc != UseBestSystemFont); - f.setWeight(QFont::Bold); + switch (std::get(fc)) { + case FontChoiceAbstract::ApplicationFont: + f = GUIUtil::getFontBold(); + break; + case FontChoiceAbstract::EmbeddedFont: + f = GUIUtil::fixedPitchFont(true); + f.setWeight(QFont::Bold); + break; + case FontChoiceAbstract::BestSystemFont: + f = GUIUtil::fixedPitchFont(false); + f.setWeight(QFont::Bold); + break; + } } else { f = std::get(fc); } @@ -904,9 +922,10 @@ bool OptionsModel::setData(const QModelIndex & index, const QVariant & value, in case FontForMoney: { const auto& new_font = value.value(); - if (m_font_money == new_font) break; - settings.setValue("FontForMoney", FontChoiceToString(new_font)); - m_font_money = new_font; + if (m_font_money != new_font) { + settings.setValue("FontForMoney", FontChoiceToString(new_font)); + m_font_money = new_font; + } Q_EMIT fontForMoneyChanged(getFontForMoney()); break; } diff --git a/src/qt/optionsmodel.h b/src/qt/optionsmodel.h index 09c735664dec..1220c45ca192 100644 --- a/src/qt/optionsmodel.h +++ b/src/qt/optionsmodel.h @@ -97,8 +97,9 @@ class OptionsModel : public QAbstractListModel }; enum class FontChoiceAbstract { - EmbeddedFont, + ApplicationFont, BestSystemFont, + EmbeddedFont, }; typedef std::variant FontChoice; static inline const FontChoice UseBestSystemFont{FontChoiceAbstract::BestSystemFont}; @@ -150,7 +151,7 @@ class OptionsModel : public QAbstractListModel QString language; BitcoinUnit m_display_bitcoin_unit; QString strThirdPartyTxUrls; - FontChoice m_font_money{FontChoiceAbstract::EmbeddedFont}; + FontChoice m_font_money{FontChoiceAbstract::ApplicationFont}; bool fCoinControlFeatures; bool m_sub_fee_from_amount; bool m_enable_psbt_controls; diff --git a/src/qt/overviewpage.cpp b/src/qt/overviewpage.cpp index feb4c59226e3..d5747d74e4a5 100644 --- a/src/qt/overviewpage.cpp +++ b/src/qt/overviewpage.cpp @@ -165,13 +165,7 @@ OverviewPage::OverviewPage(QWidget* parent) : }, {GUIUtil::g_font_registry.GetWeightBold()}); // Calls GUIUtil::updateFonts() internally - setMonospacedFont(GUIUtil::fixedPitchFont( -#ifdef Q_OS_MACOS - true -#else - false -#endif // Q_OS_MACOS - )); + setMonospacedFont(GUIUtil::getFontBold()); m_balances.balance = -1; From 83af951dee0cc28a016122e654d9f4e8cb1eb4bf Mon Sep 17 00:00:00 2001 From: Kittywhiskers Van Gogh <63189531+kwvg@users.noreply.github.com> Date: Fri, 26 Dec 2025 17:39:01 +0530 Subject: [PATCH 12/14] fix: set money font when setting wallet model instead of ctor Wallet model is initialized earlier, this will apply our font preferences sooner which should prevent the font from not showing correctly until tabs are changed. --- src/qt/overviewpage.cpp | 13 +++++++------ 1 file changed, 7 insertions(+), 6 deletions(-) diff --git a/src/qt/overviewpage.cpp b/src/qt/overviewpage.cpp index d5747d74e4a5..6c9f06b956ad 100644 --- a/src/qt/overviewpage.cpp +++ b/src/qt/overviewpage.cpp @@ -164,8 +164,7 @@ OverviewPage::OverviewPage(QWidget* parent) : ui->labelSpendable }, {GUIUtil::g_font_registry.GetWeightBold()}); - // Calls GUIUtil::updateFonts() internally - setMonospacedFont(GUIUtil::getFontBold()); + GUIUtil::updateFonts(); m_balances.balance = -1; @@ -302,8 +301,6 @@ void OverviewPage::setClientModel(ClientModel *model) // Show warning, for example if this is a prerelease version connect(model, &ClientModel::alertsChanged, this, &OverviewPage::updateAlerts); updateAlerts(model->getStatusBarWarnings()); - connect(model->getOptionsModel(), &OptionsModel::fontForMoneyChanged, this, &OverviewPage::setMonospacedFont); - setMonospacedFont(clientModel->getOptionsModel()->getFontForMoney()); // explicitly update CoinJoin frame and transaction list to reflect actual settings updateAdvancedCJUI(model->getOptionsModel()->getShowAdvancedCJUI()); } @@ -322,13 +319,17 @@ void OverviewPage::setWalletModel(WalletModel *model) setBalance(balances); connect(model, &WalletModel::balanceChanged, this, &OverviewPage::setBalance); - connect(model->getOptionsModel(), &OptionsModel::displayUnitChanged, this, &OverviewPage::updateDisplayUnit); - updateWatchOnlyLabels((wallet.haveWatchOnly() && !model->wallet().privateKeysDisabled()) || gArgs.GetBoolArg("-debug-ui", false)); connect(model, &WalletModel::notifyWatchonlyChanged, [this](bool showWatchOnly) { updateWatchOnlyLabels(showWatchOnly && !walletModel->wallet().privateKeysDisabled()); }); + // Money font and unit + setMonospacedFont(model->getOptionsModel()->getFontForMoney()); + connect(model->getOptionsModel(), &OptionsModel::fontForMoneyChanged, this, &OverviewPage::setMonospacedFont); + connect(model->getOptionsModel(), &OptionsModel::displayUnitChanged, this, &OverviewPage::updateDisplayUnit); + + // CoinJoin connect(model->getOptionsModel(), &OptionsModel::coinJoinRoundsChanged, this, &OverviewPage::updateCoinJoinProgress); connect(model->getOptionsModel(), &OptionsModel::coinJoinAmountChanged, this, &OverviewPage::updateCoinJoinProgress); connect(model->getOptionsModel(), &OptionsModel::AdvancedCJUIChanged, this, &OverviewPage::updateAdvancedCJUI); From b59b0f7516d50fe98d6117c65c0654d5bad8e320 Mon Sep 17 00:00:00 2001 From: UdjinM6 Date: Fri, 2 Jan 2026 05:21:05 +0300 Subject: [PATCH 13/14] feat(qt): add live preview for monospace font in appearance settings - Add updateMoneyFont() slot to update font immediately on selection - Save original font choice to restore on Cancel - Include full optionsmodel.h header for FontChoice type usage - Matches behavior of other appearance settings (theme, font family, etc.) --- src/qt/appearancewidget.cpp | 26 +++++++++++++++++++++++--- src/qt/appearancewidget.h | 5 +++-- 2 files changed, 26 insertions(+), 5 deletions(-) diff --git a/src/qt/appearancewidget.cpp b/src/qt/appearancewidget.cpp index 77e4946df4ac..0c742cb73f95 100644 --- a/src/qt/appearancewidget.cpp +++ b/src/qt/appearancewidget.cpp @@ -118,6 +118,7 @@ AppearanceWidget::AppearanceWidget(QWidget* parent) : connect(ui->fontWeightNormalSlider, &QSlider::valueChanged, [this](auto nValue) { updateFontWeightNormal(nValue); }); connect(ui->moneyFont, &QComboBox::currentTextChanged, [this]() { Q_EMIT appearanceChanged(); }); + connect(ui->moneyFont, QOverload::of(&QComboBox::currentIndexChanged), this, &AppearanceWidget::updateMoneyFont); connect(ui->theme, &QComboBox::currentTextChanged, this, &AppearanceWidget::updateTheme); connect(ui->theme, &QComboBox::currentTextChanged, [this]() { Q_EMIT appearanceChanged(); }); @@ -145,6 +146,13 @@ AppearanceWidget::~AppearanceWidget() if (prevWeightBold != GUIUtil::g_font_registry.GetWeightBold()) { GUIUtil::g_font_registry.SetWeightBold(prevWeightBold); } + // Restore monospace font if cancelled + if (model) { + const auto& current_money_font = model->data(model->index(OptionsModel::FontForMoney, 0), Qt::EditRole).value(); + if (current_money_font != prevMoneyFont) { + model->setData(model->index(OptionsModel::FontForMoney, 0), QVariant::fromValue(prevMoneyFont)); + } + } GUIUtil::setApplicationFont(); GUIUtil::updateFonts(); } @@ -171,6 +179,7 @@ void AppearanceWidget::setModel(OptionsModel* _model) mapper->toFirst(); const auto& font_for_money = _model->data(_model->index(OptionsModel::FontForMoney, 0), Qt::EditRole).value(); + prevMoneyFont = font_for_money; // Save original value for cancel setFontChoice(ui->moneyFont, font_for_money); const bool override_family{_model->isOptionOverridden("-font-family")}; @@ -208,9 +217,7 @@ void AppearanceWidget::setModel(OptionsModel* _model) void AppearanceWidget::accept() { fAcceptChanges = true; - if (model) { - model->setData(model->index(OptionsModel::FontForMoney, 0), ui->moneyFont->itemData(ui->moneyFont->currentIndex())); - } + // Note: FontForMoney is now updated immediately via updateMoneyFont() } void AppearanceWidget::updateTheme(const QString& theme) @@ -282,6 +289,19 @@ void AppearanceWidget::updateMoneyPreview() ui->moneyFont_preview->setFont(GUIUtil::getFontBold()); } +void AppearanceWidget::updateMoneyFont(int index) +{ + if (!model) { + return; + } + QVariant item_data = ui->moneyFont->itemData(index); + if (!item_data.canConvert()) { + return; + } + // Update the model immediately to trigger live preview in Overview page + model->setData(model->index(OptionsModel::FontForMoney, 0), item_data); +} + void AppearanceWidget::updateWeightSlider(const bool fForce) { int nMaximum = GUIUtil::g_font_registry.GetSupportedWeights().size() - 1; diff --git a/src/qt/appearancewidget.h b/src/qt/appearancewidget.h index ff289ab84d94..ef02c69f43e0 100644 --- a/src/qt/appearancewidget.h +++ b/src/qt/appearancewidget.h @@ -9,13 +9,12 @@ #include #include +#include namespace Ui { class AppearanceWidget; } -class OptionsModel; - class QDataWidgetMapper; class QSlider; class QComboBox; @@ -43,6 +42,7 @@ private Q_SLOTS: void updateFontWeightNormal(int nValue, bool fForce = false); void updateFontWeightBold(int nValue, bool fForce = false); void updateMoneyPreview(); + void updateMoneyFont(int index); private: Ui::AppearanceWidget* ui; @@ -54,6 +54,7 @@ private Q_SLOTS: QString prevFontFamily; QFont::Weight prevWeightNormal; QFont::Weight prevWeightBold; + OptionsModel::FontChoice prevMoneyFont{OptionsModel::FontChoiceAbstract::ApplicationFont}; void updateWeightSlider(bool fForce = false); }; From 636e7a6f1e86274e6f207753092eb881f3ca0592 Mon Sep 17 00:00:00 2001 From: UdjinM6 Date: Fri, 2 Jan 2026 10:52:00 +0300 Subject: [PATCH 14/14] refactor: remove redundant preview and simplify font handling - Remove moneyFont_preview label from appearance dialog since Overview page now shows live preview - Remove updateMoneyPreview() slot and related signal connections - Simplify setupFontOptions() to remove preview parameter - Remove moneyFont_preview from vecIgnoreObjects in guiutil_font.cpp - Simplify getFontForChoice() by removing unused weight/size settings since callers only use the font family (weight and size are overridden by setMonospacedFont()) - Use g_font_registry.GetFont() directly for ApplicationFont case - Set consistent width (282px) for moneyFont combobox to match other comboboxes in the dialog --- src/qt/appearancewidget.cpp | 33 ++++++-------------------------- src/qt/appearancewidget.h | 1 - src/qt/forms/appearancewidget.ui | 19 +++++++++++------- src/qt/guiutil_font.cpp | 3 +-- src/qt/optionsmodel.cpp | 7 +++---- 5 files changed, 22 insertions(+), 41 deletions(-) diff --git a/src/qt/appearancewidget.cpp b/src/qt/appearancewidget.cpp index 0c742cb73f95..ee439b71078f 100644 --- a/src/qt/appearancewidget.cpp +++ b/src/qt/appearancewidget.cpp @@ -42,7 +42,7 @@ int setFontChoice(QComboBox* cb, const OptionsModel::FontChoice& fc) return i; } -void setupFontOptions(QComboBox* cb, QLabel* preview) +void setupFontOptions(QComboBox* cb) { QFont embedded_font{GUIUtil::fixedPitchFont(true)}; QFont system_font{GUIUtil::fixedPitchFont(false)}; @@ -51,24 +51,21 @@ void setupFontOptions(QComboBox* cb, QLabel* preview) cb->addItem(QObject::tr("Use existing font"), QVariant::fromValue(OptionsModel::FontChoice{OptionsModel::FontChoiceAbstract::ApplicationFont})); cb->addItem(QObject::tr("Custom…")); - const auto& on_font_choice_changed = [cb, preview](int index) { + const auto& on_font_choice_changed = [cb](int index) { static int previous_index = -1; QVariant item_data = cb->itemData(index); - QFont f; if (item_data.canConvert()) { - f = OptionsModel::getFontForChoice(item_data.value()); + // Valid predefined choice, nothing to do } else { + // "Custom..." was selected, show font dialog bool ok; - f = QFontDialog::getFont(&ok, GUIUtil::fixedPitchFont(false), cb->parentWidget()); + QFont f = QFontDialog::getFont(&ok, GUIUtil::fixedPitchFont(false), cb->parentWidget()); if (!ok) { cb->setCurrentIndex(previous_index); return; } index = setFontChoice(cb, OptionsModel::FontChoice{f}); } - if (preview) { - preview->setFont(f); - } previous_index = index; }; QObject::connect(cb, QOverload::of(&QComboBox::currentIndexChanged), on_font_choice_changed); @@ -101,18 +98,16 @@ AppearanceWidget::AppearanceWidget(QWidget* parent) : mapper->setSubmitPolicy(QDataWidgetMapper::ManualSubmit); mapper->setOrientation(Qt::Vertical); - setupFontOptions(ui->moneyFont, ui->moneyFont_preview); + setupFontOptions(ui->moneyFont); connect(ui->fontFamily, QOverload::of(&QComboBox::currentIndexChanged), this, &AppearanceWidget::updateFontFamily); connect(ui->fontFamily, QOverload::of(&QComboBox::currentIndexChanged), [this]() { Q_EMIT appearanceChanged(); }); - connect(ui->fontFamily, QOverload::of(&QComboBox::currentIndexChanged), this, &AppearanceWidget::updateMoneyPreview); connect(ui->fontScaleSlider, &QSlider::sliderReleased, [this]() { Q_EMIT appearanceChanged(); }); connect(ui->fontScaleSlider, &QSlider::valueChanged, this, &AppearanceWidget::updateFontScale); connect(ui->fontWeightBoldSlider, &QSlider::sliderReleased, [this]() { Q_EMIT appearanceChanged(); }); connect(ui->fontWeightBoldSlider, &QSlider::valueChanged, [this](auto nValue) { updateFontWeightBold(nValue); }); - connect(ui->fontWeightBoldSlider, &QSlider::valueChanged, this, &AppearanceWidget::updateMoneyPreview); connect(ui->fontWeightNormalSlider, &QSlider::sliderReleased, [this]() { Q_EMIT appearanceChanged(); }); connect(ui->fontWeightNormalSlider, &QSlider::valueChanged, [this](auto nValue) { updateFontWeightNormal(nValue); }); @@ -273,22 +268,6 @@ void AppearanceWidget::updateFontWeightBold(int nValue, bool fForce) GUIUtil::updateFonts(); } -void AppearanceWidget::updateMoneyPreview() -{ - QVariant item_data = ui->moneyFont->currentData(); - if (!item_data.canConvert()) { - return; - } - const auto fc = item_data.value(); - if (!std::holds_alternative(fc)) { - return; - } - if (std::get(fc) != OptionsModel::FontChoiceAbstract::ApplicationFont) { - return; - } - ui->moneyFont_preview->setFont(GUIUtil::getFontBold()); -} - void AppearanceWidget::updateMoneyFont(int index) { if (!model) { diff --git a/src/qt/appearancewidget.h b/src/qt/appearancewidget.h index ef02c69f43e0..1929d0b6b33a 100644 --- a/src/qt/appearancewidget.h +++ b/src/qt/appearancewidget.h @@ -41,7 +41,6 @@ private Q_SLOTS: void updateFontScale(int nScale); void updateFontWeightNormal(int nValue, bool fForce = false); void updateFontWeightBold(int nValue, bool fForce = false); - void updateMoneyPreview(); void updateMoneyFont(int index); private: diff --git a/src/qt/forms/appearancewidget.ui b/src/qt/forms/appearancewidget.ui index 7a88033bfa55..955e94d21969 100644 --- a/src/qt/forms/appearancewidget.ui +++ b/src/qt/forms/appearancewidget.ui @@ -505,13 +505,18 @@ - - - - - - 111.11111111 DASH -909.09090909 DASH + + + + 282 + 0 + + + + + 282 + 16777215 + diff --git a/src/qt/guiutil_font.cpp b/src/qt/guiutil_font.cpp index 0913f3ddc507..7190a32fe5ec 100644 --- a/src/qt/guiutil_font.cpp +++ b/src/qt/guiutil_font.cpp @@ -94,9 +94,8 @@ constexpr std::array vecIgnoreClasses{ }; //! List of Qt objects to ignore when applying fonts -constexpr std::array vecIgnoreObjects{ +constexpr std::array vecIgnoreObjects{ "messagesWidget", - "moneyFont_preview", }; //! Weights considered when testing for weights supported by a font diff --git a/src/qt/optionsmodel.cpp b/src/qt/optionsmodel.cpp index 13ce12aadd55..ba84e8e75558 100644 --- a/src/qt/optionsmodel.cpp +++ b/src/qt/optionsmodel.cpp @@ -527,21 +527,20 @@ QFont OptionsModel::getFontForChoice(const FontChoice& fc) if (std::holds_alternative(fc)) { switch (std::get(fc)) { case FontChoiceAbstract::ApplicationFont: - f = GUIUtil::getFontBold(); + f.setFamily(GUIUtil::g_font_registry.GetFont()); break; case FontChoiceAbstract::EmbeddedFont: f = GUIUtil::fixedPitchFont(true); - f.setWeight(QFont::Bold); break; case FontChoiceAbstract::BestSystemFont: f = GUIUtil::fixedPitchFont(false); - f.setWeight(QFont::Bold); break; } } else { f = std::get(fc); } - f.setPointSize(10); + // Note: Only the font family is actually used by callers. + // Weight and size are overridden in setMonospacedFont(). return f; }