From 72aa41e54c1ec87bb54cde536ea51abc9d2413ec Mon Sep 17 00:00:00 2001 From: DeckerSU Date: Thu, 27 Jan 2022 18:44:48 +0300 Subject: [PATCH] qt: Add privacy feature to Overview page Backport of the following Bitcoin upstream commits: - https://github.com/bitcoin/bitcoin/commit/8d75115844baefe5cad4d82ec8dce001dd16eb9c - https://github.com/bitcoin/bitcoin/commit/73d8ef72742ab9193e9e95158b26176bfaab3f66 Note that connect statements in this commit using new Qt5 connect syntax, so as "TODO" we might want to switch to the new syntax everywhere, like this: - https://github.com/bitcoin/bitcoin/commit/f78558f1e39198779bdb17e2b0e256fb99ad4b28 --- src/qt/komodooceangui.cpp | 14 +++++++++++++ src/qt/komodooceangui.h | 4 ++++ src/qt/komodounits.cpp | 12 ++++++++++- src/qt/komodounits.h | 2 ++ src/qt/overviewpage.cpp | 42 +++++++++++++++++++++++++++++---------- src/qt/overviewpage.h | 3 +++ src/qt/walletframe.cpp | 3 +++ src/qt/walletview.cpp | 2 ++ src/qt/walletview.h | 2 ++ 9 files changed, 72 insertions(+), 12 deletions(-) diff --git a/src/qt/komodooceangui.cpp b/src/qt/komodooceangui.cpp index e4ea7670..0dd17809 100644 --- a/src/qt/komodooceangui.cpp +++ b/src/qt/komodooceangui.cpp @@ -398,6 +398,11 @@ void KomodoOceanGUI::createActions() showHelpMessageAction->setMenuRole(QAction::NoRole); showHelpMessageAction->setStatusTip(tr("Show the %1 help message to get a list with possible Komodo command-line options").arg(tr(PACKAGE_NAME))); + m_mask_values_action = new QAction(tr("&Mask values"), this); + m_mask_values_action->setShortcut(QKeySequence(Qt::CTRL + Qt::SHIFT + Qt::Key_M)); + m_mask_values_action->setStatusTip(tr("Mask the values in the Overview tab")); + m_mask_values_action->setCheckable(true); + connect(quitAction, SIGNAL(triggered()), qApp, SLOT(quit())); connect(aboutAction, SIGNAL(triggered()), this, SLOT(aboutClicked())); connect(aboutQtAction, SIGNAL(triggered()), qApp, SLOT(aboutQt())); @@ -420,6 +425,7 @@ void KomodoOceanGUI::createActions() connect(usedReceivingAddressesAction, SIGNAL(triggered()), walletFrame, SLOT(usedReceivingAddresses())); connect(usedReceivingZAddressesAction, SIGNAL(triggered()), walletFrame, SLOT(usedReceivingZAddresses())); connect(openAction, SIGNAL(triggered()), this, SLOT(openClicked())); + connect(m_mask_values_action, &QAction::toggled, this, &KomodoOceanGUI::setPrivacy); } #endif // ENABLE_WALLET @@ -459,6 +465,8 @@ void KomodoOceanGUI::createMenuBar() settings->addAction(encryptWalletAction); settings->addAction(changePassphraseAction); settings->addSeparator(); + settings->addAction(m_mask_values_action); + settings->addSeparator(); } settings->addAction(optionsAction); @@ -1242,6 +1250,12 @@ void KomodoOceanGUI::toggleNetworkActive() } } +bool KomodoOceanGUI::isPrivacyModeActivated() const +{ + assert(m_mask_values_action); + return m_mask_values_action->isChecked(); +} + UnitDisplayStatusBarControl::UnitDisplayStatusBarControl(const PlatformStyle *platformStyle) : optionsModel(0), menu(0) diff --git a/src/qt/komodooceangui.h b/src/qt/komodooceangui.h index 111dd498..e3687f49 100644 --- a/src/qt/komodooceangui.h +++ b/src/qt/komodooceangui.h @@ -56,6 +56,7 @@ class KomodoOceanGUI : public QMainWindow The client model represents the part of the core that communicates with the P2P network, and is wallet-agnostic. */ void setClientModel(ClientModel *clientModel); + bool isPrivacyModeActivated() const; #ifdef ENABLE_WALLET /** Set the wallet model. @@ -114,6 +115,7 @@ class KomodoOceanGUI : public QMainWindow QAction *openRPCConsoleAction; QAction *openAction; QAction *showHelpMessageAction; + QAction *m_mask_values_action; QSystemTrayIcon *trayIcon; QMenu *trayIconMenu; @@ -156,6 +158,8 @@ class KomodoOceanGUI : public QMainWindow /** Signal raised when a URI was entered or dragged to the GUI */ void receivedURI(const QString &uri); + void setPrivacy(bool privacy); + public Q_SLOTS: /** Set number of connections shown in the UI */ void setNumConnections(int count); diff --git a/src/qt/komodounits.cpp b/src/qt/komodounits.cpp index 3a9978c4..ccc20257 100644 --- a/src/qt/komodounits.cpp +++ b/src/qt/komodounits.cpp @@ -98,7 +98,6 @@ QString KomodoUnits::format(int unit, const CAmount& nIn, bool fPlus, SeparatorS qint64 remainder = n_abs % coin; QString quotient_str = QString::number(quotient); QString remainder_str = QString::number(remainder).rightJustified(num_decimals, '0'); - // Use SI-style thin space separators as these are locale independent and can't be // confused with the decimal marker. QChar thin_sp(THIN_SP_CP); @@ -135,6 +134,17 @@ QString KomodoUnits::formatHtmlWithUnit(int unit, const CAmount& amount, bool pl return QString("%1").arg(str); } +QString KomodoUnits::formatWithPrivacy(int unit, const CAmount& amount, SeparatorStyle separators, bool privacy) +{ + assert(amount >= 0); + QString value; + if (privacy) { + value = format(unit, 0, false, separators).replace('0', '#'); + } else { + value = format(unit, amount, false, separators); + } + return value + QString(" ") + name(unit); +} bool KomodoUnits::parse(int unit, const QString &value, CAmount *val_out) { diff --git a/src/qt/komodounits.h b/src/qt/komodounits.h index 2d22340a..e4d9dabb 100644 --- a/src/qt/komodounits.h +++ b/src/qt/komodounits.h @@ -90,6 +90,8 @@ class KomodoUnits: public QAbstractListModel static QString formatWithUnit(int unit, const CAmount& amount, bool plussign=false, SeparatorStyle separators=separatorStandard); //! Format as HTML string (with unit) static QString formatHtmlWithUnit(int unit, const CAmount& amount, bool plussign=false, SeparatorStyle separators=separatorStandard); + //! Format as string (with unit) of fixed length to preserve privacy, if it is set. + static QString formatWithPrivacy(int unit, const CAmount& amount, SeparatorStyle separators, bool privacy); //! Parse string to coin amount static bool parse(int unit, const QString &value, CAmount *val_out); //! Gets title for amount column including current display unit if optionsModel reference available */ diff --git a/src/qt/overviewpage.cpp b/src/qt/overviewpage.cpp index 64a753e2..f8abbc7a 100644 --- a/src/qt/overviewpage.cpp +++ b/src/qt/overviewpage.cpp @@ -17,7 +17,9 @@ #include "util.h" // for KOMODO_ASSETCHAIN_MAXLEN #include +#include #include +#include #define DECORATION_SIZE 54 #define NUM_ITEMS 5 @@ -159,6 +161,24 @@ void OverviewPage::handleOutOfSyncWarningClicks() Q_EMIT outOfSyncWarningClicked(); } +void OverviewPage::setPrivacy(bool privacy) +{ + m_privacy = privacy; + + if (currentBalance != -1) { + setBalance(currentBalance, currentUnconfirmedBalance, currentImmatureBalance, + currentWatchOnlyBalance, currentWatchUnconfBalance, currentWatchImmatureBalance, + currentPrivateBalance, currentInterestBalance); + } + + ui->listTransactions->setVisible(!m_privacy); + + const QString status_tip = m_privacy ? tr("Privacy mode activated for the Overview tab. To unmask the values, uncheck Settings->Mask values.") : ""; + setStatusTip(status_tip); + QStatusTipEvent event(status_tip); + QApplication::sendEvent(this, &event); +} + OverviewPage::~OverviewPage() { delete ui; @@ -175,17 +195,17 @@ void OverviewPage::setBalance(const CAmount& balance, const CAmount& unconfirmed currentWatchImmatureBalance = watchImmatureBalance; currentPrivateBalance = privateBalance; currentInterestBalance = interestBalance; - ui->labelBalance->setText(KomodoUnits::formatWithUnit(unit, balance, false, KomodoUnits::separatorAlways)); - ui->labelUnconfirmed->setText(KomodoUnits::formatWithUnit(unit, unconfirmedBalance, false, KomodoUnits::separatorAlways)); - ui->labelImmature->setText(KomodoUnits::formatWithUnit(unit, immatureBalance, false, KomodoUnits::separatorAlways)); - ui->labelTotal->setText(KomodoUnits::formatWithUnit(unit, balance + unconfirmedBalance + immatureBalance + privateBalance + interestBalance, false, KomodoUnits::separatorAlways)); - ui->labelWatchAvailable->setText(KomodoUnits::formatWithUnit(unit, watchOnlyBalance, false, KomodoUnits::separatorAlways)); - ui->labelWatchPending->setText(KomodoUnits::formatWithUnit(unit, watchUnconfBalance, false, KomodoUnits::separatorAlways)); - ui->labelWatchImmature->setText(KomodoUnits::formatWithUnit(unit, watchImmatureBalance, false, KomodoUnits::separatorAlways)); - ui->labelWatchTotal->setText(KomodoUnits::formatWithUnit(unit, watchOnlyBalance + watchUnconfBalance + watchImmatureBalance, false, KomodoUnits::separatorAlways)); - - ui->labelPrivateBalance->setText(KomodoUnits::formatWithUnit(unit, privateBalance, false, KomodoUnits::separatorAlways)); - ui->labelInterestBalance->setText(KomodoUnits::formatWithUnit(unit, interestBalance, false, KomodoUnits::separatorAlways)); + ui->labelBalance->setText(KomodoUnits::formatWithPrivacy(unit, balance, KomodoUnits::separatorAlways, m_privacy)); + ui->labelUnconfirmed->setText(KomodoUnits::formatWithPrivacy(unit, unconfirmedBalance, KomodoUnits::separatorAlways, m_privacy)); + ui->labelImmature->setText(KomodoUnits::formatWithPrivacy(unit, immatureBalance, KomodoUnits::separatorAlways, m_privacy)); + ui->labelTotal->setText(KomodoUnits::formatWithPrivacy(unit, balance + unconfirmedBalance + immatureBalance + privateBalance + interestBalance, KomodoUnits::separatorAlways, m_privacy)); + ui->labelWatchAvailable->setText(KomodoUnits::formatWithPrivacy(unit, watchOnlyBalance, KomodoUnits::separatorAlways, m_privacy)); + ui->labelWatchPending->setText(KomodoUnits::formatWithPrivacy(unit, watchUnconfBalance, KomodoUnits::separatorAlways, m_privacy)); + ui->labelWatchImmature->setText(KomodoUnits::formatWithPrivacy(unit, watchImmatureBalance, KomodoUnits::separatorAlways, m_privacy)); + ui->labelWatchTotal->setText(KomodoUnits::formatWithPrivacy(unit, watchOnlyBalance + watchUnconfBalance + watchImmatureBalance, KomodoUnits::separatorAlways, m_privacy)); + + ui->labelPrivateBalance->setText(KomodoUnits::formatWithPrivacy(unit, privateBalance, KomodoUnits::separatorAlways, m_privacy)); + ui->labelInterestBalance->setText(KomodoUnits::formatWithPrivacy(unit, interestBalance, KomodoUnits::separatorAlways, m_privacy)); // only show immature (newly mined) balance if it's non-zero, so as not to complicate things // for the non-mining users diff --git a/src/qt/overviewpage.h b/src/qt/overviewpage.h index c83d38ec..2e6d69e6 100644 --- a/src/qt/overviewpage.h +++ b/src/qt/overviewpage.h @@ -41,6 +41,7 @@ public Q_SLOTS: void setBalance(const CAmount& balance, const CAmount& unconfirmedBalance, const CAmount& immatureBalance, const CAmount& watchOnlyBalance, const CAmount& watchUnconfBalance, const CAmount& watchImmatureBalance, const CAmount& privateBalance, const CAmount& interestBalance); + void setPrivacy(bool privacy); Q_SIGNALS: void transactionClicked(const QModelIndex &index); @@ -62,6 +63,8 @@ public Q_SLOTS: TxViewDelegate *txdelegate; std::unique_ptr filter; + bool m_privacy{false}; + private Q_SLOTS: void updateDisplayUnit(); void handleTransactionClicked(const QModelIndex &index); diff --git a/src/qt/walletframe.cpp b/src/qt/walletframe.cpp index da4602f9..00718ca9 100644 --- a/src/qt/walletframe.cpp +++ b/src/qt/walletframe.cpp @@ -49,6 +49,7 @@ bool WalletFrame::addWallet(const QString& name, WalletModel *walletModel) walletView->setClientModel(clientModel); walletView->setWalletModel(walletModel); walletView->showOutOfSyncWarning(bOutOfSync); + walletView->setPrivacy(gui->isPrivacyModeActivated()); /* TODO we should goto the currently selected page once dynamically adding wallets is supported */ walletView->gotoOverviewPage(); @@ -60,6 +61,8 @@ bool WalletFrame::addWallet(const QString& name, WalletModel *walletModel) connect(walletView, SIGNAL(outOfSyncWarningClicked()), this, SLOT(outOfSyncWarningClicked())); + connect(gui, &KomodoOceanGUI::setPrivacy, walletView, &WalletView::setPrivacy); + return true; } diff --git a/src/qt/walletview.cpp b/src/qt/walletview.cpp index 7054d31c..bb32e6dc 100644 --- a/src/qt/walletview.cpp +++ b/src/qt/walletview.cpp @@ -85,6 +85,8 @@ WalletView::WalletView(const PlatformStyle *_platformStyle, QWidget *parent): connect(zsendCoinsPage, SIGNAL(message(QString,QString,unsigned int)), this, SIGNAL(message(QString,QString,unsigned int))); // Pass through messages from transactionView connect(transactionView, SIGNAL(message(QString,QString,unsigned int)), this, SIGNAL(message(QString,QString,unsigned int))); + + connect(this, &WalletView::setPrivacy, overviewPage, &OverviewPage::setPrivacy); } WalletView::~WalletView() diff --git a/src/qt/walletview.h b/src/qt/walletview.h index f806ff05..87ce1fb8 100644 --- a/src/qt/walletview.h +++ b/src/qt/walletview.h @@ -134,6 +134,8 @@ public Q_SLOTS: void incomingTransaction(const QString& date, int unit, const CAmount& amount, const QString& type, const QString& address, const QString& label); /** Notify that the out of sync warning icon has been pressed */ void outOfSyncWarningClicked(); + + void setPrivacy(bool privacy); }; #endif // KOMODO_QT_WALLETVIEW_H