From 9a9e21c91061f995dd3609df28994d64dffebc27 Mon Sep 17 00:00:00 2001 From: dustinface <35775977+xdustinface@users.noreply.github.com> Date: Mon, 28 Sep 2020 09:41:19 +0200 Subject: [PATCH] qt: Add PrivateSend tab in OptionsDialog, allow to show/hide PS UI (#3717) * qt: Add PrivateSend tab in OptionsDialog, allow to show/hide PS UI * qt: Decrease height of OptionsDialog * Apply suggestions from code review Co-authored-by: UdjinM6 * qt: Remove obsolete visibility adjustments Not longer needed since the page is just not reachable if the button is hidden. * qt: Make sure PrivateSend related parts are always initialized properly Not only if its enabled on startup.. * qt: Make updatePrivateSendVisibility a slot to fix the signal connection * qt: Fix UI updates on OverviewPage if PrivateSend enabled gets toggled Other way of connecting the slot with true as parameter didn't work.. * qt: Only update and emit the signal for advanced PS UI if required * qt: Update fPrivateSendEnabled in OptionsModel instead of OptionsDialog * qt: Recover the PrivateSend enabled state if OptionsDialog gets rejected * qt: Enable PrivateSend UI by default * qt: Add some brackets * qt: Add a comment * qt: Add a linebreak to the "Enable PrivateSend features" tooltip * qt: Remove obsolete comment Co-authored-by: PastaPastaPasta <6443210+PastaPastaPasta@users.noreply.github.com> * qt: Move comment * qt: Properly reset the previous PS state if OptionsDialog gets rejected Handle all reject reasons not only the cancle button. Co-authored-by: UdjinM6 Co-authored-by: PastaPastaPasta <6443210+PastaPastaPasta@users.noreply.github.com> --- src/qt/bitcoingui.cpp | 2 + src/qt/bitcoingui.h | 4 +- src/qt/forms/optionsdialog.ui | 99 ++++++++++++++++++++++++---------- src/qt/optionsdialog.cpp | 51 +++++++++++++----- src/qt/optionsdialog.h | 1 + src/qt/optionsmodel.cpp | 28 ++++++++-- src/qt/optionsmodel.h | 3 ++ src/qt/overviewpage.cpp | 51 +++++++++--------- src/qt/res/css/dark.css | 4 ++ src/qt/res/css/general.css | 5 ++ src/qt/res/css/light.css | 4 ++ src/qt/res/css/traditional.css | 4 ++ src/qt/transactionview.cpp | 2 + 13 files changed, 185 insertions(+), 73 deletions(-) diff --git a/src/qt/bitcoingui.cpp b/src/qt/bitcoingui.cpp index 5107a7f7e9..fe74d2135e 100644 --- a/src/qt/bitcoingui.cpp +++ b/src/qt/bitcoingui.cpp @@ -760,6 +760,8 @@ void BitcoinGUI::setClientModel(ClientModel *_clientModel) // initialize the disable state of the tray icon with the current value in the model. setTrayIconVisible(optionsModel->getHideTrayIcon()); + + connect(optionsModel, SIGNAL(privateSendEnabledChanged()), this, SLOT(updatePrivateSendVisibility())); } } else { // Disable possibility to show main window via action diff --git a/src/qt/bitcoingui.h b/src/qt/bitcoingui.h index 2862eb75db..a9c048fd75 100644 --- a/src/qt/bitcoingui.h +++ b/src/qt/bitcoingui.h @@ -198,8 +198,6 @@ private: void updateProgressBarVisibility(); - void updatePrivateSendVisibility(); - void updateToolBarShortcuts(); Q_SIGNALS: @@ -331,6 +329,8 @@ private Q_SLOTS: void toggleNetworkActive(); void showModalOverlay(); + + void updatePrivateSendVisibility(); }; class UnitDisplayStatusBarControl : public QLabel diff --git a/src/qt/forms/optionsdialog.ui b/src/qt/forms/optionsdialog.ui index b55a26af78..ac4bcfc424 100644 --- a/src/qt/forms/optionsdialog.ui +++ b/src/qt/forms/optionsdialog.ui @@ -7,7 +7,7 @@ 0 0 583 - 537 + 420 @@ -51,6 +51,16 @@ + + + + PrivateSend + + + true + + + @@ -234,25 +244,66 @@ - - - Whether to show coin control features or not. - - - Enable coin &control features - - + + + + + Whether to show coin control features or not. + + + Enable coin &control features + + + + + + + Show additional tab listing all your masternodes in first sub-tab<br/>and all masternodes on the network in second sub-tab. + + + Show Masternodes Tab + + + + + + + If you disable the spending of unconfirmed change, the change from a transaction<br/>cannot be used until that transaction has at least one confirmation.<br/>This also affects how your balance is computed. + + + &Spend unconfirmed change + + + + + + + Show mixing interface on Overview screen and reveal PrivateSend screen which allows to spend fully mixed coins only.<br/>A new tab with more settings will also appear in this dialog, please make sure to check them before mixing your coins. + + + Enable PrivateSend features + + + + - - - Show additional tab listing all your masternodes in first sub-tab<br/>and all masternodes on the network in second sub-tab. + + + Qt::Vertical - - Show Masternodes Tab + + + 20 + 40 + - + + + + + @@ -264,12 +315,12 @@ - + - If you disable the spending of unconfirmed change, the change from a transaction<br/>cannot be used until that transaction has at least one confirmation.<br/>This also affects how your balance is computed. + Show system popups for PrivateSend mixing transactions<br/>just like for all other transaction types. - &Spend unconfirmed change + Show popups for PrivateSend transactions @@ -293,16 +344,6 @@ - - - - Show system popups for PrivateSend mixing transactions<br/>just like for all other transaction types. - - - Show popups for PrivateSend transactions - - - @@ -373,7 +414,7 @@ - + Qt::Vertical diff --git a/src/qt/optionsdialog.cpp b/src/qt/optionsdialog.cpp index c75625bf18..808da31bf1 100644 --- a/src/qt/optionsdialog.cpp +++ b/src/qt/optionsdialog.cpp @@ -79,12 +79,15 @@ OptionsDialog::OptionsDialog(QWidget *parent, bool enableWallet) : connect(ui->connectSocksTor, SIGNAL(toggled(bool)), this, SLOT(updateProxyValidationState())); pageButtons.addButton(ui->btnMain, pageButtons.buttons().size()); - /* remove Wallet tab in case of -disablewallet */ + /* Remove Wallet/PrivateSend tabs in case of -disablewallet */ if (!enableWallet) { ui->stackedWidgetOptions->removeWidget(ui->pageWallet); ui->btnWallet->hide(); + ui->stackedWidgetOptions->removeWidget(ui->pagePrivateSend); + ui->btnPrivateSend->hide(); } else { pageButtons.addButton(ui->btnWallet, pageButtons.buttons().size()); + pageButtons.addButton(ui->btnPrivateSend, pageButtons.buttons().size()); } pageButtons.addButton(ui->btnNetwork, pageButtons.buttons().size()); pageButtons.addButton(ui->btnDisplay, pageButtons.buttons().size()); @@ -155,6 +158,16 @@ OptionsDialog::OptionsDialog(QWidget *parent, bool enableWallet) : ui->widgetAppearance->setLayout(appearanceLayout); updatePrivateSendVisibility(); + + // Store the current PrivateSend enabled state to recover it if it gets changed but the dialog gets not accepted but declined. +#ifdef ENABLE_WALLET + fPrivateSendEnabledPrev = CPrivateSendClientOptions::IsEnabled(); + connect(this, &OptionsDialog::rejected, [=]() { + if (fPrivateSendEnabledPrev != CPrivateSendClientOptions::IsEnabled()) { + ui->privateSendEnabled->click(); + } + }); +#endif } OptionsDialog::~OptionsDialog() @@ -179,6 +192,17 @@ void OptionsDialog::setModel(OptionsModel *_model) ui->overriddenByCommandLineLabel->setText(strLabel); } + +#ifdef ENABLE_WALLET + // If -enableprivatesend was passed in on the command line, set the checkbox + // to the value given via commandline and disable it (make it unclickable). + if (strLabel.contains("-enableprivatesend")) { + bool fEnabled = CPrivateSendClientOptions::IsEnabled(); + ui->privateSendEnabled->setChecked(fEnabled); + ui->privateSendEnabled->setEnabled(false); + } +#endif + mapper->setModel(_model); setMapper(); mapper->toFirst(); @@ -204,6 +228,16 @@ void OptionsDialog::setModel(OptionsModel *_model) connect(ui->digits, SIGNAL(valueChanged()), this, SLOT(showRestartWarning())); connect(ui->lang, SIGNAL(valueChanged()), this, SLOT(showRestartWarning())); connect(ui->thirdPartyTxUrls, SIGNAL(textChanged(const QString &)), this, SLOT(showRestartWarning())); + + connect(ui->privateSendEnabled, &QCheckBox::clicked, [=](bool fChecked) { +#ifdef ENABLE_WALLET + CPrivateSendClientOptions::SetEnabled(fChecked); +#endif + updatePrivateSendVisibility(); + if (_model != nullptr) { + _model->emitPrivateSendEnabledChanged(); + } + }); } void OptionsDialog::setMapper() @@ -217,6 +251,7 @@ void OptionsDialog::setMapper() #endif mapper->addMapping(ui->threadsScriptVerif, OptionsModel::ThreadsScriptVerif); mapper->addMapping(ui->databaseCache, OptionsModel::DatabaseCache); + mapper->addMapping(ui->privateSendEnabled, OptionsModel::PrivateSendEnabled); /* Wallet */ mapper->addMapping(ui->coinControlFeatures, OptionsModel::CoinControlFeatures); @@ -396,19 +431,7 @@ void OptionsDialog::updatePrivateSendVisibility() #else bool fEnabled = false; #endif - std::vector vecWidgets{ - ui->showAdvancedPSUI, - ui->showPrivateSendPopups, - ui->lowKeysWarning, - ui->privateSendMultiSession, - ui->privateSendAmount, - ui->lblPrivateSendAmountText, - ui->lblPrivateSendRoundsText, - ui->privateSendRounds, - }; - for (auto w : vecWidgets) { - w->setVisible(fEnabled); - } + ui->btnPrivateSend->setVisible(fEnabled); } ProxyAddressValidator::ProxyAddressValidator(QObject *parent) : diff --git a/src/qt/optionsdialog.h b/src/qt/optionsdialog.h index 99848c120b..7fdbe7fff7 100644 --- a/src/qt/optionsdialog.h +++ b/src/qt/optionsdialog.h @@ -74,6 +74,7 @@ private: QButtonGroup pageButtons; QString previousTheme; AppearanceWidget* appearance; + bool fPrivateSendEnabledPrev{false}; }; #endif // BITCOIN_QT_OPTIONSDIALOG_H diff --git a/src/qt/optionsmodel.cpp b/src/qt/optionsmodel.cpp index 6acea84c52..b28a640535 100644 --- a/src/qt/optionsmodel.cpp +++ b/src/qt/optionsmodel.cpp @@ -113,6 +113,13 @@ void OptionsModel::Init(bool resetSettings) settings.setValue("digits", "2"); // PrivateSend + if (!settings.contains("fPrivateSendEnabled")) { + settings.setValue("fPrivateSendEnabled", true); + } + if (!gArgs.SoftSetBoolArg("-enableprivatesend", settings.value("fPrivateSendEnabled").toBool())) { + addOverriddenOption("-enableprivatesend"); + } + if (!settings.contains("fShowAdvancedPSUI")) settings.setValue("fShowAdvancedPSUI", false); fShowAdvancedPSUI = settings.value("fShowAdvancedPSUI", false).toBool(); @@ -330,6 +337,8 @@ QVariant OptionsModel::data(const QModelIndex & index, int role) const return settings.value("bSpendZeroConfChange"); case ShowMasternodesTab: return settings.value("fShowMasternodesTab"); + case PrivateSendEnabled: + return settings.value("fPrivateSendEnabled"); case ShowAdvancedPSUI: return fShowAdvancedPSUI; case ShowPrivateSendPopups: @@ -486,10 +495,18 @@ bool OptionsModel::setData(const QModelIndex & index, const QVariant & value, in setRestartRequired(true); } break; + case PrivateSendEnabled: + if (settings.value("fPrivateSendEnabled") != value) { + settings.setValue("fPrivateSendEnabled", value.toBool()); + Q_EMIT privateSendEnabledChanged(); + } + break; case ShowAdvancedPSUI: - fShowAdvancedPSUI = value.toBool(); - settings.setValue("fShowAdvancedPSUI", fShowAdvancedPSUI); - Q_EMIT advancedPSUIChanged(fShowAdvancedPSUI); + if (settings.value("fShowAdvancedPSUI") != value) { + fShowAdvancedPSUI = value.toBool(); + settings.setValue("fShowAdvancedPSUI", fShowAdvancedPSUI); + Q_EMIT advancedPSUIChanged(fShowAdvancedPSUI); + } break; case ShowPrivateSendPopups: settings.setValue("fShowPrivateSendPopups", value); @@ -638,6 +655,11 @@ bool OptionsModel::getProxySettings(QNetworkProxy& proxy) const return false; } +void OptionsModel::emitPrivateSendEnabledChanged() +{ + Q_EMIT privateSendEnabledChanged(); +} + void OptionsModel::setRestartRequired(bool fRequired) { QSettings settings; diff --git a/src/qt/optionsmodel.h b/src/qt/optionsmodel.h index e1e36ac45a..27bd7fc32c 100644 --- a/src/qt/optionsmodel.h +++ b/src/qt/optionsmodel.h @@ -55,6 +55,7 @@ public: DatabaseCache, // int SpendZeroConfChange, // bool ShowMasternodesTab, // bool + PrivateSendEnabled, // bool ShowAdvancedPSUI, // bool ShowPrivateSendPopups, // bool LowKeysWarning, // bool @@ -84,6 +85,7 @@ public: bool getCoinControlFeatures() const { return fCoinControlFeatures; } bool getShowAdvancedPSUI() { return fShowAdvancedPSUI; } const QString& getOverriddenByCommandLine() { return strOverriddenByCommandLine; } + void emitPrivateSendEnabledChanged(); /* Restart flag helper */ void setRestartRequired(bool fRequired); @@ -110,6 +112,7 @@ private: void checkAndMigrate(); Q_SIGNALS: void displayUnitChanged(int unit); + void privateSendEnabledChanged(); void privateSendRoundsChanged(); void privateSentAmountChanged(); void advancedPSUIChanged(bool); diff --git a/src/qt/overviewpage.cpp b/src/qt/overviewpage.cpp index 4237061e77..0b25721ec0 100644 --- a/src/qt/overviewpage.cpp +++ b/src/qt/overviewpage.cpp @@ -163,30 +163,14 @@ OverviewPage::OverviewPage(QWidget* parent) : // start with displaying the "out of sync" warnings showOutOfSyncWarning(true); - if (!CPrivateSendClientOptions::IsEnabled()) return; - - // Disable any PS UI for masternode or when autobackup is disabled or failed for whatever reason - if(fMasternodeMode || nWalletBackups <= 0){ - DisablePrivateSendCompletely(); - if (nWalletBackups <= 0) { - ui->labelPrivateSendEnabled->setToolTip(tr("Automatic backups are disabled, no mixing available!")); - } - } else { - // Disable privateSendClient builtin support for automatic backups while we are in GUI, - // we'll handle automatic backups and user warnings in privateSendStatus() - for (auto& pair : privateSendClientManagers) { - if (!pair.second->IsMixing()) { - ui->togglePrivateSend->setText(tr("Start Mixing")); - } else { - ui->togglePrivateSend->setText(tr("Stop Mixing")); - } - pair.second->fCreateAutoBackups = false; - } - - timer = new QTimer(this); - connect(timer, SIGNAL(timeout()), this, SLOT(privateSendStatus())); - timer->start(1000); + // Disable privateSendClient builtin support for automatic backups while we are in GUI, + // we'll handle automatic backups and user warnings in privateSendStatus() + for (auto& pair : privateSendClientManagers) { + pair.second->fCreateAutoBackups = false; } + + timer = new QTimer(this); + connect(timer, SIGNAL(timeout()), this, SLOT(privateSendStatus())); } void OverviewPage::handleTransactionClicked(const QModelIndex &index) @@ -298,11 +282,12 @@ void OverviewPage::setWalletModel(WalletModel *model) // explicitly update PS frame and transaction list to reflect actual settings updateAdvancedPSUI(model->getOptionsModel()->getShowAdvancedPSUI()); - if (!CPrivateSendClientOptions::IsEnabled()) return; - connect(model->getOptionsModel(), SIGNAL(privateSendRoundsChanged()), this, SLOT(updatePrivateSendProgress())); connect(model->getOptionsModel(), SIGNAL(privateSentAmountChanged()), this, SLOT(updatePrivateSendProgress())); connect(model->getOptionsModel(), SIGNAL(advancedPSUIChanged(bool)), this, SLOT(updateAdvancedPSUI(bool))); + connect(model->getOptionsModel(), &OptionsModel::privateSendEnabledChanged, [=]() { + privateSendStatus(true); + }); connect(ui->togglePrivateSend, SIGNAL(clicked()), this, SLOT(togglePrivateSend())); @@ -459,13 +444,29 @@ void OverviewPage::privateSendStatus(bool fForce) if(!walletModel) return; + // Disable any PS UI for masternode or when autobackup is disabled or failed for whatever reason + if (fMasternodeMode || nWalletBackups <= 0) { + DisablePrivateSendCompletely(); + if (nWalletBackups <= 0) { + ui->labelPrivateSendEnabled->setToolTip(tr("Automatic backups are disabled, no mixing available!")); + } + return; + } + bool fIsEnabled = CPrivateSendClientOptions::IsEnabled(); ui->framePrivateSend->setVisible(fIsEnabled); if (!fIsEnabled) { SetupTransactionList(NUM_ITEMS_DISABLED); + if (timer != nullptr) { + timer->stop(); + } return; } + if (timer != nullptr && !timer->isActive()) { + timer->start(1000); + } + // Wrap all privatesend related widgets we want to show/hide state based. // Value of the map contains a flag if this widget belongs to the advanced // PrivateSend UI option or not. True if it does, false if not. diff --git a/src/qt/res/css/dark.css b/src/qt/res/css/dark.css index 1e83c2071a..6f4466cdd8 100644 --- a/src/qt/res/css/dark.css +++ b/src/qt/res/css/dark.css @@ -477,6 +477,7 @@ QPushButton - Special case, tabbar replacement buttons /* Options dialog buttons */ #btnMain, #btnWallet, +#btnPrivateSend, #btnNetwork, #btnDisplay, #btnAppearance, @@ -496,6 +497,7 @@ QPushButton - Special case, tabbar replacement buttons /* Options dialog buttons */ #btnMain:hover:checked, #btnWallet:hover:checked, +#btnPrivateSend:hover:checked, #btnNetwork:hover:checked, #btnDisplay:hover:checked, #btnAppearance:hover:checked, @@ -515,6 +517,7 @@ QPushButton - Special case, tabbar replacement buttons /* Options dialog buttons */ #btnMain:hover:!checked, #btnWallet:hover:!checked, +#btnPrivateSend:hover:!checked, #btnNetwork:hover:!checked, #btnDisplay:hover:!checked, #btnAppearance:hover:!checked, @@ -534,6 +537,7 @@ QPushButton - Special case, tabbar replacement buttons /* Options dialog buttons */ #btnMain:checked, #btnWallet:checked, +#btnPrivateSend:checked, #btnNetwork:checked, #btnDisplay:checked, #btnAppearance:checked, diff --git a/src/qt/res/css/general.css b/src/qt/res/css/general.css index fbea9f5c2e..a2a6484564 100644 --- a/src/qt/res/css/general.css +++ b/src/qt/res/css/general.css @@ -621,6 +621,7 @@ QPushButton - Special case, tabbar replacement buttons /* Options dialog buttons */ #btnMain, #btnWallet, +#btnPrivateSend, #btnNetwork, #btnDisplay, #btnAppearance, @@ -643,6 +644,7 @@ QPushButton - Special case, tabbar replacement buttons /* Options dialog buttons */ #btnMain:hover:checked, #btnWallet:hover:checked, +#btnPrivateSend:hover:checked, #btnNetwork:hover:checked, #btnDisplay:hover:checked, #btnAppearance:hover:checked, @@ -665,6 +667,7 @@ QPushButton - Special case, tabbar replacement buttons /* Options dialog buttons */ #btnMain:hover:!checked, #btnWallet:hover:!checked, +#btnPrivateSend:hover:!checked, #btnNetwork:hover:!checked, #btnDisplay:hover:!checked, #btnAppearance:hover:!checked, @@ -687,6 +690,7 @@ QPushButton - Special case, tabbar replacement buttons /* Options dialog buttons */ #btnMain:checked, #btnWallet:checked, +#btnPrivateSend:checked, #btnNetwork:checked, #btnDisplay:checked, #btnAppearance:checked, @@ -708,6 +712,7 @@ QPushButton - Special case, tabbar replacement buttons /* Options dialog buttons */ #btnMain:hover:pressed, #btnWallet:hover:pressed, +#btnPrivateSend:hover:pressed, #btnNetwork:hover:pressed, #btnDisplay:hover:pressed, #btnAppearance:hover:pressed, diff --git a/src/qt/res/css/light.css b/src/qt/res/css/light.css index 9e4eeee21a..e6ec7de045 100644 --- a/src/qt/res/css/light.css +++ b/src/qt/res/css/light.css @@ -459,6 +459,7 @@ QPushButton - Special case, tabbar replacement buttons /* Options dialog buttons */ #btnMain, #btnWallet, +#btnPrivateSend, #btnNetwork, #btnDisplay, #btnAppearance, @@ -478,6 +479,7 @@ QPushButton - Special case, tabbar replacement buttons /* Options dialog buttons */ #btnMain:hover:checked, #btnWallet:hover:checked, +#btnPrivateSend:hover:checked, #btnNetwork:hover:checked, #btnDisplay:hover:checked, #btnAppearance:hover:checked, @@ -497,6 +499,7 @@ QPushButton - Special case, tabbar replacement buttons /* Options dialog buttons */ #btnMain:hover:!checked, #btnWallet:hover:!checked, +#btnPrivateSend:hover:!checked, #btnNetwork:hover:!checked, #btnDisplay:hover:!checked, #btnAppearance:hover:!checked, @@ -516,6 +519,7 @@ QPushButton - Special case, tabbar replacement buttons /* Options dialog buttons */ #btnMain:checked, #btnWallet:checked, +#btnPrivateSend:checked, #btnNetwork:checked, #btnDisplay:checked, #btnAppearance:checked, diff --git a/src/qt/res/css/traditional.css b/src/qt/res/css/traditional.css index dc297193e6..b50d0bbf47 100644 --- a/src/qt/res/css/traditional.css +++ b/src/qt/res/css/traditional.css @@ -54,6 +54,7 @@ QPushButton - Special case, tabbar replacement buttons /* Options dialog buttons */ #btnMain, #btnWallet, +#btnPrivateSend, #btnNetwork, #btnDisplay, #btnAppearance, @@ -77,6 +78,7 @@ QPushButton - Special case, tabbar replacement buttons /* Options dialog buttons */ #btnMain:hover:checked, #btnWallet:hover:checked, +#btnPrivateSend:hover:checked, #btnNetwork:hover:checked, #btnDisplay:hover:checked, #btnAppearance:hover:checked, @@ -99,6 +101,7 @@ QPushButton - Special case, tabbar replacement buttons /* Options dialog buttons */ #btnMain:hover:!checked, #btnWallet:hover:!checked, +#btnPrivateSend:hover:!checked, #btnNetwork:hover:!checked, #btnDisplay:hover:!checked, #btnAppearance:hover:!checked, @@ -121,6 +124,7 @@ QPushButton - Special case, tabbar replacement buttons /* Options dialog buttons */ #btnMain:checked, #btnWallet:checked, +#btnPrivateSend:checked, #btnNetwork:checked, #btnDisplay:checked, #btnAppearance:checked, diff --git a/src/qt/transactionview.cpp b/src/qt/transactionview.cpp index 3649535003..0bfa017612 100644 --- a/src/qt/transactionview.cpp +++ b/src/qt/transactionview.cpp @@ -250,6 +250,8 @@ void TransactionView::setModel(WalletModel *_model) mapperThirdPartyTxUrls->setMapping(thirdPartyTxUrlAction, listUrls[i].trimmed()); } } + + connect(_model->getOptionsModel(), SIGNAL(privateSendEnabledChanged()), this, SLOT(updatePrivateSendVisibility())); } // show/hide column Watch-only