From 17491eb359612ec3d6afb62cae16a4b8fc281d0e Mon Sep 17 00:00:00 2001 From: Kittywhiskers Van Gogh <63189531+kwvg@users.noreply.github.com> Date: Thu, 29 Jan 2026 01:07:15 +0530 Subject: [PATCH 01/35] refactor: drop `emitCoinJoinEnabledChanged()`, use `setOption()` instead --- src/qt/optionsdialog.cpp | 4 +--- src/qt/optionsmodel.cpp | 6 +----- src/qt/optionsmodel.h | 1 - 3 files changed, 2 insertions(+), 9 deletions(-) diff --git a/src/qt/optionsdialog.cpp b/src/qt/optionsdialog.cpp index 5e9d38f5a892..e5f8feb1f947 100644 --- a/src/qt/optionsdialog.cpp +++ b/src/qt/optionsdialog.cpp @@ -290,10 +290,8 @@ void OptionsDialog::setModel(OptionsModel *_model) #ifdef ENABLE_WALLET model->node().coinJoinOptions().setEnabled(fChecked); #endif + model->setOption(OptionsModel::CoinJoinEnabled, fChecked); updateCoinJoinVisibility(); - if (this->model != nullptr) { - this->model->emitCoinJoinEnabledChanged(); - } updateWidth(); }); diff --git a/src/qt/optionsmodel.cpp b/src/qt/optionsmodel.cpp index 48685389a3fd..839945623919 100644 --- a/src/qt/optionsmodel.cpp +++ b/src/qt/optionsmodel.cpp @@ -855,6 +855,7 @@ bool OptionsModel::setOption(OptionID option, const QVariant& value, const std:: break; case CoinJoinEnabled: if (changed()) { + node().coinJoinOptions().setEnabled(value.toBool()); update(value.toBool()); Q_EMIT coinJoinEnabledChanged(); } @@ -1045,11 +1046,6 @@ void OptionsModel::setDisplayUnit(const QVariant& new_unit) Q_EMIT displayUnitChanged(m_display_bitcoin_unit); } -void OptionsModel::emitCoinJoinEnabledChanged() -{ - Q_EMIT coinJoinEnabledChanged(); -} - void OptionsModel::setRestartRequired(bool fRequired) { QSettings settings; diff --git a/src/qt/optionsmodel.h b/src/qt/optionsmodel.h index 1bf20c7b0efc..89690d4295f2 100644 --- a/src/qt/optionsmodel.h +++ b/src/qt/optionsmodel.h @@ -132,7 +132,6 @@ class OptionsModel : public QAbstractListModel bool getShowAdvancedCJUI() { return fShowAdvancedCJUI; } const QString& getOverriddenByCommandLine() { return strOverriddenByCommandLine; } bool isOptionOverridden(const QString& option) const { return strOverriddenByCommandLine.contains(option); } - void emitCoinJoinEnabledChanged(); /* Explicit setters */ void SetPruneTargetGB(int prune_target_gb); From 2deba788f58b14aa8ad5c53b8cc4b1a0230e5eff Mon Sep 17 00:00:00 2001 From: Kittywhiskers Van Gogh <63189531+kwvg@users.noreply.github.com> Date: Thu, 22 Jan 2026 04:48:51 +0530 Subject: [PATCH 02/35] refactor: improve CoinJoin tab nullptr checks, bail-out condition Also `s/coinJoinEnabledChanged/showCoinJoinChanged/g` to establish a naming convention that will be used soon. --- src/qt/bitcoingui.cpp | 50 ++++++++++++++++++++------------------ src/qt/bitcoingui.h | 1 + src/qt/optionsmodel.cpp | 2 +- src/qt/optionsmodel.h | 2 +- src/qt/overviewpage.cpp | 2 +- src/qt/transactionview.cpp | 2 +- 6 files changed, 32 insertions(+), 27 deletions(-) diff --git a/src/qt/bitcoingui.cpp b/src/qt/bitcoingui.cpp index 249e4d25d751..df955cdbb7e0 100644 --- a/src/qt/bitcoingui.cpp +++ b/src/qt/bitcoingui.cpp @@ -762,7 +762,8 @@ void BitcoinGUI::createToolBars() button->setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Preferred); button->setToolTip(button->statusTip()); button->setCheckable(true); - toolbar->addWidget(button); + QAction* action = toolbar->addWidget(button); + if (button == coinJoinCoinsButton) { m_coinjoin_action = action; } } overviewButton->setChecked(true); @@ -877,20 +878,22 @@ void BitcoinGUI::setClientModel(ClientModel *_clientModel, interfaces::BlockAndH walletFrame->setClientModel(_clientModel); } #endif // ENABLE_WALLET - unitDisplayControl->setOptionsModel(_clientModel->getOptionsModel()); OptionsModel* optionsModel = _clientModel->getOptionsModel(); - if (optionsModel && trayIcon) { - // be aware of the tray icon disable state change reported by the OptionsModel object. - connect(optionsModel, &OptionsModel::showTrayIconChanged, trayIcon, &QSystemTrayIcon::setVisible); + if (optionsModel) { + unitDisplayControl->setOptionsModel(optionsModel); + m_mask_values_action->setChecked(optionsModel->getOption(OptionsModel::OptionID::MaskValues).toBool()); - // initialize the disable state of the tray icon with the current value in the model. - trayIcon->setVisible(optionsModel->getShowTrayIcon()); + connect(optionsModel, &OptionsModel::showCoinJoinChanged, this, &BitcoinGUI::updateCoinJoinVisibility); - connect(optionsModel, &OptionsModel::coinJoinEnabledChanged, this, &BitcoinGUI::updateCoinJoinVisibility); - } + if (trayIcon) { + // be aware of the tray icon disable state change reported by the OptionsModel object. + connect(optionsModel, &OptionsModel::showTrayIconChanged, trayIcon, &QSystemTrayIcon::setVisible); - m_mask_values_action->setChecked(_clientModel->getOptionsModel()->getOption(OptionsModel::OptionID::MaskValues).toBool()); + // initialize the disable state of the tray icon with the current value in the model. + trayIcon->setVisible(optionsModel->getShowTrayIcon()); + } + } } else { if(trayIconMenu) { @@ -1449,21 +1452,22 @@ void BitcoinGUI::updateProgressBarVisibility() void BitcoinGUI::updateCoinJoinVisibility() { + const bool fEnabled{ #ifdef ENABLE_WALLET - bool fEnabled = m_node.coinJoinOptions().isEnabled(); + m_node.coinJoinOptions().isEnabled() #else - bool fEnabled = false; -#endif - // CoinJoin button is the third QToolButton, show/hide the underlying QAction - // Hiding the QToolButton itself doesn't work for the GUI part - // but is still needed for shortcuts to work properly. - if (appToolBar != nullptr) { - appToolBar->actions()[4]->setVisible(fEnabled); - coinJoinCoinsButton->setVisible(fEnabled); - GUIUtil::updateButtonGroupShortcuts(tabGroup); - } - coinJoinCoinsAction->setVisible(fEnabled); - showCoinJoinHelpAction->setVisible(fEnabled); + false +#endif // ENABLE_WALLET + }; + + // Show/hide the underlying QAction, hiding the QToolButton itself doesn't + // work for the GUI part but is still needed for shortcuts to work properly. + if (m_coinjoin_action) m_coinjoin_action->setVisible(fEnabled); + if (coinJoinCoinsButton) coinJoinCoinsButton->setVisible(fEnabled); + if (coinJoinCoinsAction) coinJoinCoinsAction->setVisible(fEnabled); + if (showCoinJoinHelpAction) showCoinJoinHelpAction->setVisible(fEnabled); + + GUIUtil::updateButtonGroupShortcuts(tabGroup); updateWidth(); } diff --git a/src/qt/bitcoingui.h b/src/qt/bitcoingui.h index 576605443e7c..12bf11ea175e 100644 --- a/src/qt/bitcoingui.h +++ b/src/qt/bitcoingui.h @@ -149,6 +149,7 @@ class BitcoinGUI : public QMainWindow QAction* usedReceivingAddressesAction = nullptr; QAction* signMessageAction = nullptr; QAction* verifyMessageAction = nullptr; + QAction* m_coinjoin_action = nullptr; QAction* m_load_psbt_action = nullptr; QAction* m_load_psbt_clipboard_action = nullptr; QAction* aboutAction = nullptr; diff --git a/src/qt/optionsmodel.cpp b/src/qt/optionsmodel.cpp index 839945623919..622c3317aab5 100644 --- a/src/qt/optionsmodel.cpp +++ b/src/qt/optionsmodel.cpp @@ -857,7 +857,7 @@ bool OptionsModel::setOption(OptionID option, const QVariant& value, const std:: if (changed()) { node().coinJoinOptions().setEnabled(value.toBool()); update(value.toBool()); - Q_EMIT coinJoinEnabledChanged(); + Q_EMIT showCoinJoinChanged(); } break; case ShowAdvancedCJUI: diff --git a/src/qt/optionsmodel.h b/src/qt/optionsmodel.h index 89690d4295f2..00ae0f6aa569 100644 --- a/src/qt/optionsmodel.h +++ b/src/qt/optionsmodel.h @@ -174,12 +174,12 @@ class OptionsModel : public QAbstractListModel Q_SIGNALS: void displayUnitChanged(BitcoinUnit unit); - void coinJoinEnabledChanged(); void coinJoinRoundsChanged(); void coinJoinAmountChanged(); void AdvancedCJUIChanged(bool); void coinControlFeaturesChanged(bool); void keepChangeAddressChanged(bool); + void showCoinJoinChanged(); void showTrayIconChanged(bool); void fontForMoneyChanged(const QFont&); }; diff --git a/src/qt/overviewpage.cpp b/src/qt/overviewpage.cpp index 85c30efdcc92..92eff689b868 100644 --- a/src/qt/overviewpage.cpp +++ b/src/qt/overviewpage.cpp @@ -330,7 +330,7 @@ void OverviewPage::setWalletModel(WalletModel *model) connect(model->getOptionsModel(), &OptionsModel::coinJoinRoundsChanged, this, &OverviewPage::updateCoinJoinProgress); connect(model->getOptionsModel(), &OptionsModel::coinJoinAmountChanged, this, &OverviewPage::updateCoinJoinProgress); connect(model->getOptionsModel(), &OptionsModel::AdvancedCJUIChanged, this, &OverviewPage::updateAdvancedCJUI); - connect(model->getOptionsModel(), &OptionsModel::coinJoinEnabledChanged, [this]() { + connect(model->getOptionsModel(), &OptionsModel::showCoinJoinChanged, [this]() { coinJoinStatus(true); }); diff --git a/src/qt/transactionview.cpp b/src/qt/transactionview.cpp index b8054e4522f4..b050deff7082 100644 --- a/src/qt/transactionview.cpp +++ b/src/qt/transactionview.cpp @@ -245,7 +245,7 @@ void TransactionView::setModel(WalletModel *_model) } } - connect(_model->getOptionsModel(), &OptionsModel::coinJoinEnabledChanged, this, &TransactionView::updateCoinJoinVisibility); + connect(_model->getOptionsModel(), &OptionsModel::showCoinJoinChanged, this, &TransactionView::updateCoinJoinVisibility); } // show/hide column Watch-only From 8a0907c8935fdf602bdedfdf25c00601c9f214e9 Mon Sep 17 00:00:00 2001 From: Kittywhiskers Van Gogh <63189531+kwvg@users.noreply.github.com> Date: Mon, 19 Jan 2026 05:21:50 +0530 Subject: [PATCH 03/35] move-only: move `subFeeFromAmount` into `verticalLayout_2` This should fix the misalignment of the `subFeeFromAmount` `QCheckBox` compared to the rest of the `QCheckBox`es Review with `git log -p -n1 --ignore-space-change --color-moved=dimmed_zebra`. --- src/qt/forms/optionsdialog.ui | 20 ++++++++++---------- 1 file changed, 10 insertions(+), 10 deletions(-) diff --git a/src/qt/forms/optionsdialog.ui b/src/qt/forms/optionsdialog.ui index eda0ce5cdd69..fbfcd6248196 100644 --- a/src/qt/forms/optionsdialog.ui +++ b/src/qt/forms/optionsdialog.ui @@ -325,18 +325,18 @@ - - - - Whether to set subtract fee from amount as default or not. - - - Subtract &fee from amount by default - - - + + + + Whether to set subtract fee from amount as default or not. + + + Subtract &fee from amount by default + + + From 45da71c29ad76c2c2d91dbdfc91f014aab9aed5b Mon Sep 17 00:00:00 2001 From: Kittywhiskers Van Gogh <63189531+kwvg@users.noreply.github.com> Date: Tue, 20 Jan 2026 13:48:50 +0530 Subject: [PATCH 04/35] chore: enforce alphabetical sorting in `src/Makefile.qt.include` Review with `git log -p -n1 --color-moved=dimmed_zebra`. --- src/Makefile.qt.include | 108 ++++++++++++++++++++-------------------- 1 file changed, 54 insertions(+), 54 deletions(-) diff --git a/src/Makefile.qt.include b/src/Makefile.qt.include index 582f293ad853..c6d793485551 100644 --- a/src/Makefile.qt.include +++ b/src/Makefile.qt.include @@ -20,22 +20,22 @@ QT_FORMS_UI = \ qt/forms/askpassphrasedialog.ui \ qt/forms/coincontroldialog.ui \ qt/forms/createwalletdialog.ui \ + qt/forms/debugwindow.ui \ qt/forms/editaddressdialog.ui \ qt/forms/governancelist.ui \ - qt/forms/proposalwizard.ui \ qt/forms/helpmessagedialog.ui \ qt/forms/intro.ui \ - qt/forms/modaloverlay.ui \ qt/forms/masternodelist.ui \ qt/forms/mnemonicverificationdialog.ui \ - qt/forms/qrdialog.ui \ + qt/forms/modaloverlay.ui \ qt/forms/openuridialog.ui \ qt/forms/optionsdialog.ui \ qt/forms/overviewpage.ui \ + qt/forms/proposalwizard.ui \ qt/forms/psbtoperationsdialog.ui \ + qt/forms/qrdialog.ui \ qt/forms/receivecoinsdialog.ui \ qt/forms/receiverequestdialog.ui \ - qt/forms/debugwindow.ui \ qt/forms/sendcoinsdialog.ui \ qt/forms/sendcoinsentry.ui \ qt/forms/signverifymessagedialog.ui \ @@ -46,7 +46,6 @@ QT_MOC_CPP = \ qt/moc_addresstablemodel.cpp \ qt/moc_appearancewidget.cpp \ qt/moc_askpassphrasedialog.cpp \ - qt/moc_createwalletdialog.cpp \ qt/moc_bantablemodel.cpp \ qt/moc_bitcoin.cpp \ qt/moc_bitcoinaddressvalidator.cpp \ @@ -56,26 +55,27 @@ QT_MOC_CPP = \ qt/moc_clientmodel.cpp \ qt/moc_coincontroldialog.cpp \ qt/moc_coincontroltreewidget.cpp \ + qt/moc_createwalletdialog.cpp \ qt/moc_csvmodelwriter.cpp \ qt/moc_editaddressdialog.cpp \ qt/moc_governancelist.cpp \ - qt/moc_proposalwizard.cpp \ qt/moc_guiutil.cpp \ qt/moc_initexecutor.cpp \ qt/moc_intro.cpp \ qt/moc_macdockiconhandler.cpp \ qt/moc_macnotificationhandler.cpp \ - qt/moc_modaloverlay.cpp \ qt/moc_masternodelist.cpp \ qt/moc_mnemonicverificationdialog.cpp \ + qt/moc_modaloverlay.cpp \ qt/moc_notificator.cpp \ qt/moc_openuridialog.cpp \ qt/moc_optionsdialog.cpp \ qt/moc_optionsmodel.cpp \ qt/moc_overviewpage.cpp \ + qt/moc_paymentserver.cpp \ qt/moc_peertablemodel.cpp \ qt/moc_peertablesortproxy.cpp \ - qt/moc_paymentserver.cpp \ + qt/moc_proposalwizard.cpp \ qt/moc_psbtoperationsdialog.cpp \ qt/moc_qrdialog.cpp \ qt/moc_qrimagewidget.cpp \ @@ -136,7 +136,6 @@ BITCOIN_QT_H = \ qt/csvmodelwriter.h \ qt/editaddressdialog.h \ qt/governancelist.h \ - qt/proposalwizard.h \ qt/guiconstants.h \ qt/guiutil.h \ qt/guiutil_font.h \ @@ -145,9 +144,9 @@ BITCOIN_QT_H = \ qt/macdockiconhandler.h \ qt/macnotificationhandler.h \ qt/macos_appnap.h \ - qt/modaloverlay.h \ qt/masternodelist.h \ qt/mnemonicverificationdialog.h \ + qt/modaloverlay.h \ qt/networkstyle.h \ qt/notificator.h \ qt/openuridialog.h \ @@ -157,6 +156,7 @@ BITCOIN_QT_H = \ qt/paymentserver.h \ qt/peertablemodel.h \ qt/peertablesortproxy.h \ + qt/proposalwizard.h \ qt/psbtoperationsdialog.h \ qt/qrdialog.h \ qt/qrimagewidget.h \ @@ -189,36 +189,36 @@ BITCOIN_QT_H = \ qt/winshutdownmonitor.h QT_RES_ICONS = \ - qt/res/icons/dash.ico \ - qt/res/icons/dash_testnet.ico \ - qt/res/icons/dash.png \ - qt/res/icons/warning.png \ qt/res/icons/address-book.png \ - qt/res/icons/transaction0.png \ - qt/res/icons/transaction1.png \ - qt/res/icons/transaction2.png \ - qt/res/icons/transaction3.png \ - qt/res/icons/transaction4.png \ - qt/res/icons/transaction5.png \ - qt/res/icons/transaction_abandoned.png \ - qt/res/icons/transaction_locked.png \ qt/res/icons/connect1_16.png \ qt/res/icons/connect2_16.png \ qt/res/icons/connect3_16.png \ qt/res/icons/connect4_16.png \ + qt/res/icons/dash.ico \ + qt/res/icons/dash.png \ + qt/res/icons/dash_testnet.ico \ qt/res/icons/editcopy.png \ qt/res/icons/editpaste.png \ qt/res/icons/eye.png \ qt/res/icons/eye_minus.png \ qt/res/icons/eye_plus.png \ + qt/res/icons/fontbigger.png \ + qt/res/icons/fontsmaller.png \ qt/res/icons/hd_enabled.png \ qt/res/icons/lock_closed.png \ qt/res/icons/lock_open.png \ qt/res/icons/proxy.png \ qt/res/icons/remove.png \ qt/res/icons/synced.png \ - qt/res/icons/fontbigger.png \ - qt/res/icons/fontsmaller.png + qt/res/icons/transaction0.png \ + qt/res/icons/transaction1.png \ + qt/res/icons/transaction2.png \ + qt/res/icons/transaction3.png \ + qt/res/icons/transaction4.png \ + qt/res/icons/transaction5.png \ + qt/res/icons/transaction_abandoned.png \ + qt/res/icons/transaction_locked.png \ + qt/res/icons/warning.png BITCOIN_QT_BASE_CPP = \ qt/appearancewidget.cpp \ @@ -260,12 +260,12 @@ BITCOIN_QT_WALLET_CPP = \ qt/createwalletdialog.cpp \ qt/editaddressdialog.cpp \ qt/governancelist.cpp \ - qt/proposalwizard.cpp \ qt/masternodelist.cpp \ qt/mnemonicverificationdialog.cpp \ qt/openuridialog.cpp \ qt/overviewpage.cpp \ qt/paymentserver.cpp \ + qt/proposalwizard.cpp \ qt/psbtoperationsdialog.cpp \ qt/qrdialog.cpp \ qt/qrimagewidget.cpp \ @@ -301,50 +301,50 @@ QT_RES_IMAGES = \ qt/res/images/arrow_down_light.png \ qt/res/images/arrow_left_dark.png \ qt/res/images/arrow_left_light.png \ - qt/res/images/arrow_right_dark.png \ - qt/res/images/arrow_right_light.png \ - qt/res/images/arrow_up_dark.png \ - qt/res/images/arrow_up_light.png \ - qt/res/images/arrow_light_down_normal.png \ qt/res/images/arrow_light_down_hover.png \ - qt/res/images/arrow_light_left_normal.png \ + qt/res/images/arrow_light_down_normal.png \ qt/res/images/arrow_light_left_hover.png \ - qt/res/images/arrow_light_right_normal.png \ + qt/res/images/arrow_light_left_normal.png \ qt/res/images/arrow_light_right_hover.png \ - qt/res/images/arrow_light_up_normal.png \ + qt/res/images/arrow_light_right_normal.png \ qt/res/images/arrow_light_up_hover.png \ - qt/res/images/checkbox_normal_dark.png \ - qt/res/images/checkbox_normal_hover_dark.png \ - qt/res/images/checkbox_normal_disabled_dark.png \ + qt/res/images/arrow_light_up_normal.png \ + qt/res/images/arrow_right_dark.png \ + qt/res/images/arrow_right_light.png \ + qt/res/images/arrow_up_dark.png \ + qt/res/images/arrow_up_light.png \ qt/res/images/checkbox_checked_dark.png \ - qt/res/images/checkbox_checked_hover_dark.png \ qt/res/images/checkbox_checked_disabled_dark.png \ + qt/res/images/checkbox_checked_disabled_light.png \ + qt/res/images/checkbox_checked_hover_dark.png \ + qt/res/images/checkbox_checked_hover_light.png \ + qt/res/images/checkbox_checked_light.png \ + qt/res/images/checkbox_normal_dark.png \ + qt/res/images/checkbox_normal_disabled_dark.png \ + qt/res/images/checkbox_normal_disabled_light.png \ + qt/res/images/checkbox_normal_hover_dark.png \ + qt/res/images/checkbox_normal_hover_light.png \ + qt/res/images/checkbox_normal_light.png \ qt/res/images/checkbox_partly_checked_dark.png \ - qt/res/images/checkbox_partly_checked_hover_dark.png \ qt/res/images/checkbox_partly_checked_disabled_dark.png \ - qt/res/images/checkbox_normal_light.png \ - qt/res/images/checkbox_normal_hover_light.png \ - qt/res/images/checkbox_normal_disabled_light.png \ - qt/res/images/checkbox_checked_light.png \ - qt/res/images/checkbox_checked_hover_light.png \ - qt/res/images/checkbox_checked_disabled_light.png \ - qt/res/images/checkbox_partly_checked_light.png \ - qt/res/images/checkbox_partly_checked_hover_light.png \ qt/res/images/checkbox_partly_checked_disabled_light.png \ + qt/res/images/checkbox_partly_checked_hover_dark.png \ + qt/res/images/checkbox_partly_checked_hover_light.png \ + qt/res/images/checkbox_partly_checked_light.png \ qt/res/images/dash_logo_toolbar.png \ qt/res/images/dash_logo_toolbar_blue.png \ - qt/res/images/radio_normal_dark.png \ - qt/res/images/radio_normal_hover_dark.png \ qt/res/images/radio_checked_dark.png \ - qt/res/images/radio_checked_hover_dark.png \ - qt/res/images/radio_normal_disabled_dark.png \ qt/res/images/radio_checked_disabled_dark.png \ - qt/res/images/radio_normal_light.png \ - qt/res/images/radio_normal_hover_light.png \ - qt/res/images/radio_checked_light.png \ + qt/res/images/radio_checked_disabled_light.png \ + qt/res/images/radio_checked_hover_dark.png \ qt/res/images/radio_checked_hover_light.png \ + qt/res/images/radio_checked_light.png \ + qt/res/images/radio_normal_dark.png \ + qt/res/images/radio_normal_disabled_dark.png \ qt/res/images/radio_normal_disabled_light.png \ - qt/res/images/radio_checked_disabled_light.png \ + qt/res/images/radio_normal_hover_dark.png \ + qt/res/images/radio_normal_hover_light.png \ + qt/res/images/radio_normal_light.png \ qt/res/images/splash.png QT_RES_CSS = \ From c8558b83ee76b231b1a15e0816ba3196daf0d891 Mon Sep 17 00:00:00 2001 From: Kittywhiskers Van Gogh <63189531+kwvg@users.noreply.github.com> Date: Thu, 22 Jan 2026 19:41:50 +0530 Subject: [PATCH 05/35] refactor: add `getScaledFont` helper, keep `getFont` internal --- src/qt/guiutil_font.cpp | 137 ++++++++++++++++++---------------- src/qt/guiutil_font.h | 10 +-- src/qt/overviewpage.cpp | 4 +- src/qt/trafficgraphwidget.cpp | 4 +- 4 files changed, 82 insertions(+), 73 deletions(-) diff --git a/src/qt/guiutil_font.cpp b/src/qt/guiutil_font.cpp index 70879d397a1d..7b387a8d3a07 100644 --- a/src/qt/guiutil_font.cpp +++ b/src/qt/guiutil_font.cpp @@ -113,6 +113,69 @@ QString qstrprintf(const std::string& fmt, const Args&... args) { return QString::fromStdString(tfm::format(fmt, args...)); } + +//! Returns a properly weighted QFont object with the selected font +QFont getFont(const GUIUtil::FontAttrib& font_attrib) +{ + QFont font; + if (!GUIUtil::fontsLoaded()) { + return font; + } + + if (font_attrib.m_font == GUIUtil::MONTSERRAT_FONT_STR) { + assert(mapMontserrat.count(font_attrib.m_weight)); +#ifdef Q_OS_MACOS + font.setFamily(font_attrib.m_font); + font.setStyleName([&]() { + std::string ret{mapMontserrat.at(font_attrib.m_weight).first}; + if (font_attrib.m_is_italic) { + if (ret == "Regular") { + ret = "Italic"; + } else { + ret += " Italic"; + } + } + return QString::fromStdString(ret); + }()); +#else + if (font_attrib.m_weight == QFont::Normal || font_attrib.m_weight == QFont::Bold) { + font.setFamily(font_attrib.m_font); + } else { + font.setFamily(qstrprintf("%s %s", font_attrib.m_font.toStdString(), mapMontserrat.at(font_attrib.m_weight).first)); + } +#endif // Q_OS_MACOS + } else if (font_attrib.m_font == GUIUtil::OS_FONT_STR) { + font.setFamily(g_default_font->family()); + } else if (font_attrib.m_font == GUIUtil::OS_MONO_FONT_STR) { + font.setFamily(QFontDatabase::systemFont(QFontDatabase::FixedFont).family()); + } else { + font.setFamily(font_attrib.m_font); + } + + if (font_attrib.m_font == GUIUtil::ROBOTO_MONO_FONT_STR || font_attrib.m_font == GUIUtil::OS_MONO_FONT_STR) { + font.setStyleHint(QFont::Monospace); + } + +#ifdef Q_OS_MACOS + if (font_attrib.m_font != GUIUtil::MONTSERRAT_FONT_STR) +#endif // Q_OS_MACOS + { + font.setWeight(font_attrib.m_weight); + font.setStyle(font_attrib.m_is_italic ? QFont::StyleItalic : QFont::StyleNormal); + } + + if (font_attrib.m_point_size != -1) { + font.setPointSizeF(GUIUtil::g_font_registry.GetScaledFontSize(font_attrib.m_point_size)); + } + + if (gArgs.GetBoolArg("-debug-ui", false)) { + qDebug() << qstrprintf("%s: font size: %d, family: %s, style: %s, weight: %d match %s", __func__, + font.pointSizeF(), font.family().toStdString(), font.styleName().toStdString(), + font.weight(), font.exactMatch() ? "true" : "false"); + } + + return font; +} } // anonymous namespace namespace GUIUtil { @@ -462,68 +525,6 @@ void updateFonts() } } -QFont getFont(const FontAttrib& font_attrib) -{ - QFont font; - if (!fontsLoaded()) { - return font; - } - - if (font_attrib.m_font == MONTSERRAT_FONT_STR) { - assert(mapMontserrat.count(font_attrib.m_weight)); -#ifdef Q_OS_MACOS - font.setFamily(font_attrib.m_font); - font.setStyleName([&]() { - std::string ret{mapMontserrat.at(font_attrib.m_weight).first}; - if (font_attrib.m_is_italic) { - if (ret == "Regular") { - ret = "Italic"; - } else { - ret += " Italic"; - } - } - return QString::fromStdString(ret); - }()); -#else - if (font_attrib.m_weight == QFont::Normal || font_attrib.m_weight == QFont::Bold) { - font.setFamily(font_attrib.m_font); - } else { - font.setFamily(qstrprintf("%s %s", font_attrib.m_font.toStdString(), mapMontserrat.at(font_attrib.m_weight).first)); - } -#endif // Q_OS_MACOS - } else if (font_attrib.m_font == OS_FONT_STR) { - font.setFamily(g_default_font->family()); - } else if (font_attrib.m_font == OS_MONO_FONT_STR) { - font.setFamily(QFontDatabase::systemFont(QFontDatabase::FixedFont).family()); - } else { - font.setFamily(font_attrib.m_font); - } - - 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_attrib.m_font != MONTSERRAT_FONT_STR) -#endif // Q_OS_MACOS - { - font.setWeight(font_attrib.m_weight); - font.setStyle(font_attrib.m_is_italic ? QFont::StyleItalic : QFont::StyleNormal); - } - - if (font_attrib.m_point_size != -1) { - font.setPointSizeF(g_font_registry.GetScaledFontSize(font_attrib.m_point_size)); - } - - if (gArgs.GetBoolArg("-debug-ui", false)) { - qDebug() << qstrprintf("%s: font size: %d, family: %s, style: %s, weight: %d match %s", __func__, - font.pointSizeF(), font.family().toStdString(), font.styleName().toStdString(), - font.weight(), font.exactMatch() ? "true" : "false"); - } - - return font; -} - std::vector getFonts(bool selectable_only) { std::vector ret; @@ -533,14 +534,22 @@ std::vector getFonts(bool selectable_only) return ret; } +QFont getFontBold() +{ + return getFont({g_font_registry.GetWeightBold()}); +} + QFont getFontNormal() { return getFont({g_font_registry.GetWeightNormal()}); } -QFont getFontBold() +QFont getScaledFont(double baseSize, bool bold, double multiplier) { - return getFont({g_font_registry.GetWeightBold()}); + return getFont({ + bold ? g_font_registry.GetWeightBold() : g_font_registry.GetWeightNormal(), + baseSize * multiplier + }); } QFont::Weight FontRegistry::IdxToWeight(int index) const diff --git a/src/qt/guiutil_font.h b/src/qt/guiutil_font.h index f12333b67e93..ad5428e13fad 100644 --- a/src/qt/guiutil_font.h +++ b/src/qt/guiutil_font.h @@ -81,7 +81,7 @@ class FontRegistry { } double GetScaleSteps() const { return m_scale_steps; } - double GetScaledFontSize(int size) const { return std::round(size * (1 + (m_font_scale * m_scale_steps)) * 4) / 4.0; } + double GetScaledFontSize(double size) const { return std::round(size * (1 + (m_font_scale * m_scale_steps)) * 4) / 4.0; } QString GetFont() const { return m_font; } int GetFontScale() const { return m_font_scale; } int GetFontSize() const { return m_font_size; } @@ -158,14 +158,14 @@ 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 FontAttrib& font_attrib); +/** Get the default bold QFont */ +QFont getFontBold(); /** Get the default normal QFont */ QFont getFontNormal(); -/** Get the default bold QFont */ -QFont getFontBold(); +/** Get a scaled font with the specified base size, weight, and optional multiplier. */ +QFont getScaledFont(double baseSize, bool bold, double multiplier = 1); /** (Bitcoin) Return a monospace font */ QFont fixedPitchFont(bool use_embedded_font = false); diff --git a/src/qt/overviewpage.cpp b/src/qt/overviewpage.cpp index 92eff689b868..1f2bd8032152 100644 --- a/src/qt/overviewpage.cpp +++ b/src/qt/overviewpage.cpp @@ -71,7 +71,7 @@ class TxViewDelegate : public QAbstractItemDelegate // Draw first line (with slightly bigger font than the second line will get) // Content: Date/Time, Optional IS indicator, Amount - painter->setFont(GUIUtil::getFont({GUIUtil::g_font_registry.GetWeightNormal(), GUIUtil::g_font_registry.GetScaledFontSize(initialFontSize * 1.17), false})); + painter->setFont(GUIUtil::getScaledFont(/*baseSize=*/initialFontSize, /*bold=*/false, /*multiplier=*/1.17)); // Date/Time colorForeground = qvariant_cast(indexDate.data(Qt::ForegroundRole)); QString strDate = indexDate.data(Qt::DisplayRole).toString(); @@ -92,7 +92,7 @@ class TxViewDelegate : public QAbstractItemDelegate // Draw second line (with the initial font) // Content: Address/label, Optional Watchonly indicator - painter->setFont(GUIUtil::getFont({GUIUtil::g_font_registry.GetWeightNormal(), GUIUtil::g_font_registry.GetScaledFontSize(initialFontSize), false})); + painter->setFont(GUIUtil::getScaledFont(/*baseSize=*/initialFontSize, /*bold=*/false)); // Address/Label colorForeground = qvariant_cast(indexAddress.data(Qt::ForegroundRole)); QString address = indexAddress.data(Qt::DisplayRole).toString(); diff --git a/src/qt/trafficgraphwidget.cpp b/src/qt/trafficgraphwidget.cpp index 265bb669ed57..c88bf1c9513b 100644 --- a/src/qt/trafficgraphwidget.cpp +++ b/src/qt/trafficgraphwidget.cpp @@ -162,8 +162,8 @@ void TrafficGraphWidget::paintEvent(QPaintEvent *) const QString strReceived = tr("Received"); const QString strSent = tr("Sent"); // Get a bold font for the title and a normal one for the rest - QFont fontTotal = GUIUtil::getFont({GUIUtil::g_font_registry.GetWeightBold(), 16, false}); - QFont fontInOut = GUIUtil::getFont({GUIUtil::g_font_registry.GetWeightNormal(), 12, false}); + QFont fontTotal = GUIUtil::getScaledFont(/*baseSize=*/16, /*bold=*/true); + QFont fontInOut = GUIUtil::getScaledFont(/*baseSize=*/12, /*bold=*/false); // Use font metrics to determine minimum rect sizes depending on the font scale QFontMetrics fmTotal(fontTotal); QFontMetrics fmInOut(fontInOut); From 1c7cfcc2ab834262ed9c8fda070b8ef3ae91e756 Mon Sep 17 00:00:00 2001 From: Kittywhiskers Van Gogh <63189531+kwvg@users.noreply.github.com> Date: Tue, 20 Jan 2026 14:10:57 +0530 Subject: [PATCH 06/35] refactor: add `pruneStaleEntities` helper to deduplicate pruning --- src/qt/guiutil_font.cpp | 40 +++++++++++++++++++--------------------- 1 file changed, 19 insertions(+), 21 deletions(-) diff --git a/src/qt/guiutil_font.cpp b/src/qt/guiutil_font.cpp index 7b387a8d3a07..8de09fced8b0 100644 --- a/src/qt/guiutil_font.cpp +++ b/src/qt/guiutil_font.cpp @@ -176,6 +176,23 @@ QFont getFont(const GUIUtil::FontAttrib& font_attrib) return font; } + +//! Removes entries from a map where QPointer keys point to deleted objects +template +size_t pruneStaleEntities(T& map) +{ + size_t removed{0}; + auto it = map.begin(); + while (it != map.end()) { + if (it->first.isNull()) { + it = map.erase(it); + ++removed; + } else { + ++it; + } + } + return removed; +} } // anonymous namespace namespace GUIUtil { @@ -440,27 +457,8 @@ void updateFonts() // 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; - } - } + const size_t nRemovedDefaultFonts{pruneStaleEntities(mapWidgetDefaultFontSizes)}; + const size_t nRemovedFontUpdates{pruneStaleEntities(mapFontUpdates)}; size_t nUpdatable{0}, nUpdated{0}; std::map mapWidgetFonts; From fa48b81efe392b0c72f5b11da1205513ae633761 Mon Sep 17 00:00:00 2001 From: Kittywhiskers Van Gogh <63189531+kwvg@users.noreply.github.com> Date: Thu, 29 Jan 2026 00:58:33 +0530 Subject: [PATCH 07/35] move-only: split proposal model out to `src/qt/proposalmodel.{cpp,h}` Review with `git log -p -n1 --color-moved=dimmed_zebra`. --- src/Makefile.qt.include | 3 + src/qt/governancelist.cpp | 294 ++---------------------------- src/qt/governancelist.h | 77 -------- src/qt/proposalmodel.cpp | 275 ++++++++++++++++++++++++++++ src/qt/proposalmodel.h | 88 +++++++++ test/util/data/non-backported.txt | 1 + 6 files changed, 379 insertions(+), 359 deletions(-) create mode 100644 src/qt/proposalmodel.cpp create mode 100644 src/qt/proposalmodel.h diff --git a/src/Makefile.qt.include b/src/Makefile.qt.include index c6d793485551..2973e930ae25 100644 --- a/src/Makefile.qt.include +++ b/src/Makefile.qt.include @@ -75,6 +75,7 @@ QT_MOC_CPP = \ qt/moc_paymentserver.cpp \ qt/moc_peertablemodel.cpp \ qt/moc_peertablesortproxy.cpp \ + qt/moc_proposalmodel.cpp \ qt/moc_proposalwizard.cpp \ qt/moc_psbtoperationsdialog.cpp \ qt/moc_qrdialog.cpp \ @@ -156,6 +157,7 @@ BITCOIN_QT_H = \ qt/paymentserver.h \ qt/peertablemodel.h \ qt/peertablesortproxy.h \ + qt/proposalmodel.h \ qt/proposalwizard.h \ qt/psbtoperationsdialog.h \ qt/qrdialog.h \ @@ -265,6 +267,7 @@ BITCOIN_QT_WALLET_CPP = \ qt/openuridialog.cpp \ qt/overviewpage.cpp \ qt/paymentserver.cpp \ + qt/proposalmodel.cpp \ qt/proposalwizard.cpp \ qt/psbtoperationsdialog.cpp \ qt/qrdialog.cpp \ diff --git a/src/qt/governancelist.cpp b/src/qt/governancelist.cpp index 32706b33b1a7..8f2b484dca6d 100644 --- a/src/qt/governancelist.cpp +++ b/src/qt/governancelist.cpp @@ -2,301 +2,31 @@ // Distributed under the MIT software license, see the accompanying // file COPYING or http://www.opensource.org/licenses/mit-license.php. -#include #include -#include -#include -#include -#include -#include #include #include #include + +#include +#include +#include +#include + +#include #include #include -#include -#include -#include -#include -#include -#include #include