Skip to content

Commit 5f75c5e

Browse files
committed
Merge #16432: qt: Add privacy to the Overview page
8d75115 qt: Add privacy feature to Overview page (Hennadii Stepanov) 73d8ef7 qt: Add BitcoinUnits::formatWithPrivacy() function (Hennadii Stepanov) Pull request description: This PR allows to hide/reveal values on the Overviewpage by checking/unchecking Menu->Settings-> Mask Values Closes #16407 Privacy mode is OFF (the default behavior): ![Screenshot from 2020-01-02 15-08-28](https://user-images.githubusercontent.com/32963518/71669074-28ab6980-2d74-11ea-8e54-4973aa307192.png) Privacy mode is ON: ![Screenshot from 2020-01-02 15-10-23 cropped](https://user-images.githubusercontent.com/32963518/71669082-2d701d80-2d74-11ea-9df5-d4acc4982dbe.png) ACKs for top commit: jonatack: Tested ACK 8d75115 jonasschnelli: Tested ACK 8d75115 Tree-SHA512: 42f396d5bf0d343b306fb7e925f86f66b3fc3a257af370a812f4be181b5269298f9b23bd8a3ce25ab61de92908c4018d8c2dc8591d11bc58d79c4eb7206fc6ec
2 parents adc143f + 8d75115 commit 5f75c5e

File tree

11 files changed

+96
-29
lines changed

11 files changed

+96
-29
lines changed

src/qt/bitcoingui.cpp

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -354,6 +354,11 @@ void BitcoinGUI::createActions()
354354
showHelpMessageAction->setMenuRole(QAction::NoRole);
355355
showHelpMessageAction->setStatusTip(tr("Show the %1 help message to get a list with possible Bitcoin command-line options").arg(PACKAGE_NAME));
356356

357+
m_mask_values_action = new QAction(tr("&Mask values"), this);
358+
m_mask_values_action->setShortcut(QKeySequence(Qt::CTRL + Qt::SHIFT + Qt::Key_M));
359+
m_mask_values_action->setStatusTip(tr("Mask the values in the Overview tab"));
360+
m_mask_values_action->setCheckable(true);
361+
357362
connect(quitAction, &QAction::triggered, qApp, QApplication::quit);
358363
connect(aboutAction, &QAction::triggered, this, &BitcoinGUI::aboutClicked);
359364
connect(aboutQtAction, &QAction::triggered, qApp, QApplication::aboutQt);
@@ -416,6 +421,8 @@ void BitcoinGUI::createActions()
416421
connect(activity, &CreateWalletActivity::finished, activity, &QObject::deleteLater);
417422
activity->create();
418423
});
424+
425+
connect(m_mask_values_action, &QAction::toggled, this, &BitcoinGUI::setPrivacy);
419426
}
420427
#endif // ENABLE_WALLET
421428

@@ -456,6 +463,8 @@ void BitcoinGUI::createMenuBar()
456463
settings->addAction(encryptWalletAction);
457464
settings->addAction(changePassphraseAction);
458465
settings->addSeparator();
466+
settings->addAction(m_mask_values_action);
467+
settings->addSeparator();
459468
}
460469
settings->addAction(optionsAction);
461470

@@ -1414,6 +1423,12 @@ void BitcoinGUI::unsubscribeFromCoreSignals()
14141423
m_handler_question->disconnect();
14151424
}
14161425

1426+
bool BitcoinGUI::isPrivacyModeActivated() const
1427+
{
1428+
assert(m_mask_values_action);
1429+
return m_mask_values_action->isChecked();
1430+
}
1431+
14171432
UnitDisplayStatusBarControl::UnitDisplayStatusBarControl(const PlatformStyle *platformStyle) :
14181433
optionsModel(nullptr),
14191434
menu(nullptr)

src/qt/bitcoingui.h

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -99,6 +99,8 @@ class BitcoinGUI : public QMainWindow
9999
/** Disconnect core signals from GUI client */
100100
void unsubscribeFromCoreSignals();
101101

102+
bool isPrivacyModeActivated() const;
103+
102104
protected:
103105
void changeEvent(QEvent *e) override;
104106
void closeEvent(QCloseEvent *event) override;
@@ -155,6 +157,7 @@ class BitcoinGUI : public QMainWindow
155157
QAction* m_close_wallet_action{nullptr};
156158
QAction* m_wallet_selector_label_action = nullptr;
157159
QAction* m_wallet_selector_action = nullptr;
160+
QAction* m_mask_values_action{nullptr};
158161

159162
QLabel *m_wallet_selector_label = nullptr;
160163
QComboBox* m_wallet_selector = nullptr;
@@ -207,6 +210,7 @@ class BitcoinGUI : public QMainWindow
207210
void receivedURI(const QString &uri);
208211
/** Signal raised when RPC console shown */
209212
void consoleShown(RPCConsole* console);
213+
void setPrivacy(bool privacy);
210214

211215
public Q_SLOTS:
212216
/** Set number of connections shown in the UI */

src/qt/bitcoinunits.cpp

Lines changed: 15 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,8 @@
66

77
#include <QStringList>
88

9+
#include <cassert>
10+
911
BitcoinUnits::BitcoinUnits(QObject *parent):
1012
QAbstractListModel(parent),
1113
unitlist(availableUnits())
@@ -94,7 +96,7 @@ int BitcoinUnits::decimals(int unit)
9496
}
9597
}
9698

97-
QString BitcoinUnits::format(int unit, const CAmount& nIn, bool fPlus, SeparatorStyle separators)
99+
QString BitcoinUnits::format(int unit, const CAmount& nIn, bool fPlus, SeparatorStyle separators, bool justify)
98100
{
99101
// Note: not using straight sprintf here because we do NOT want
100102
// localized number formatting.
@@ -106,6 +108,7 @@ QString BitcoinUnits::format(int unit, const CAmount& nIn, bool fPlus, Separator
106108
qint64 n_abs = (n > 0 ? n : -n);
107109
qint64 quotient = n_abs / coin;
108110
QString quotient_str = QString::number(quotient);
111+
if (justify) quotient_str = quotient_str.rightJustified(16 - num_decimals, ' ');
109112

110113
// Use SI-style thin space separators as these are locale independent and can't be
111114
// confused with the decimal marker.
@@ -150,6 +153,17 @@ QString BitcoinUnits::formatHtmlWithUnit(int unit, const CAmount& amount, bool p
150153
return QString("<span style='white-space: nowrap;'>%1</span>").arg(str);
151154
}
152155

156+
QString BitcoinUnits::formatWithPrivacy(int unit, const CAmount& amount, SeparatorStyle separators, bool privacy)
157+
{
158+
assert(amount >= 0);
159+
QString value;
160+
if (privacy) {
161+
value = format(unit, 0, false, separators, true).replace('0', '#');
162+
} else {
163+
value = format(unit, amount, false, separators, true);
164+
}
165+
return value + QString(" ") + shortName(unit);
166+
}
153167

154168
bool BitcoinUnits::parse(int unit, const QString &value, CAmount *val_out)
155169
{

src/qt/bitcoinunits.h

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -72,11 +72,13 @@ class BitcoinUnits: public QAbstractListModel
7272
//! Number of decimals left
7373
static int decimals(int unit);
7474
//! Format as string
75-
static QString format(int unit, const CAmount& amount, bool plussign=false, SeparatorStyle separators=separatorStandard);
75+
static QString format(int unit, const CAmount& amount, bool plussign = false, SeparatorStyle separators = separatorStandard, bool justify = false);
7676
//! Format as string (with unit)
7777
static QString formatWithUnit(int unit, const CAmount& amount, bool plussign=false, SeparatorStyle separators=separatorStandard);
7878
//! Format as HTML string (with unit)
7979
static QString formatHtmlWithUnit(int unit, const CAmount& amount, bool plussign=false, SeparatorStyle separators=separatorStandard);
80+
//! Format as string (with unit) of fixed length to preserve privacy, if it is set.
81+
static QString formatWithPrivacy(int unit, const CAmount& amount, SeparatorStyle separators, bool privacy);
8082
//! Parse string to coin amount
8183
static bool parse(int unit, const QString &value, CAmount *val_out);
8284
//! Gets title for amount column including current display unit if optionsModel reference available */

src/qt/forms/overviewpage.ui

Lines changed: 18 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -6,8 +6,8 @@
66
<rect>
77
<x>0</x>
88
<y>0</y>
9-
<width>596</width>
10-
<height>342</height>
9+
<width>798</width>
10+
<height>318</height>
1111
</rect>
1212
</property>
1313
<property name="windowTitle">
@@ -118,6 +118,7 @@
118118
<widget class="QLabel" name="labelWatchPending">
119119
<property name="font">
120120
<font>
121+
<family>Monospace</family>
121122
<weight>75</weight>
122123
<bold>true</bold>
123124
</font>
@@ -129,7 +130,7 @@
129130
<string>Unconfirmed transactions to watch-only addresses</string>
130131
</property>
131132
<property name="text">
132-
<string notr="true">0.000 000 00 BTC</string>
133+
<string notr="true">0.00000000 BTC</string>
133134
</property>
134135
<property name="alignment">
135136
<set>Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter</set>
@@ -143,6 +144,7 @@
143144
<widget class="QLabel" name="labelUnconfirmed">
144145
<property name="font">
145146
<font>
147+
<family>Monospace</family>
146148
<weight>75</weight>
147149
<bold>true</bold>
148150
</font>
@@ -154,7 +156,7 @@
154156
<string>Total of transactions that have yet to be confirmed, and do not yet count toward the spendable balance</string>
155157
</property>
156158
<property name="text">
157-
<string notr="true">0.000 000 00 BTC</string>
159+
<string notr="true">0.00000000 BTC</string>
158160
</property>
159161
<property name="alignment">
160162
<set>Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter</set>
@@ -168,6 +170,7 @@
168170
<widget class="QLabel" name="labelWatchImmature">
169171
<property name="font">
170172
<font>
173+
<family>Monospace</family>
171174
<weight>75</weight>
172175
<bold>true</bold>
173176
</font>
@@ -179,7 +182,7 @@
179182
<string>Mined balance in watch-only addresses that has not yet matured</string>
180183
</property>
181184
<property name="text">
182-
<string notr="true">0.000 000 00 BTC</string>
185+
<string notr="true">0.00000000 BTC</string>
183186
</property>
184187
<property name="alignment">
185188
<set>Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter</set>
@@ -226,6 +229,7 @@
226229
<widget class="QLabel" name="labelImmature">
227230
<property name="font">
228231
<font>
232+
<family>Monospace</family>
229233
<weight>75</weight>
230234
<bold>true</bold>
231235
</font>
@@ -237,7 +241,7 @@
237241
<string>Mined balance that has not yet matured</string>
238242
</property>
239243
<property name="text">
240-
<string notr="true">0.000 000 00 BTC</string>
244+
<string notr="true">0.00000000 BTC</string>
241245
</property>
242246
<property name="alignment">
243247
<set>Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter</set>
@@ -271,6 +275,7 @@
271275
<widget class="QLabel" name="labelTotal">
272276
<property name="font">
273277
<font>
278+
<family>Monospace</family>
274279
<weight>75</weight>
275280
<bold>true</bold>
276281
</font>
@@ -282,7 +287,7 @@
282287
<string>Your current total balance</string>
283288
</property>
284289
<property name="text">
285-
<string notr="true">0.000000 00 BTC</string>
290+
<string notr="true">21 000 000.00000000 BTC</string>
286291
</property>
287292
<property name="alignment">
288293
<set>Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter</set>
@@ -296,6 +301,7 @@
296301
<widget class="QLabel" name="labelWatchTotal">
297302
<property name="font">
298303
<font>
304+
<family>Monospace</family>
299305
<weight>75</weight>
300306
<bold>true</bold>
301307
</font>
@@ -307,7 +313,7 @@
307313
<string>Current total balance in watch-only addresses</string>
308314
</property>
309315
<property name="text">
310-
<string notr="true">0.000000 00 BTC</string>
316+
<string notr="true">21 000 000.00000000 BTC</string>
311317
</property>
312318
<property name="alignment">
313319
<set>Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter</set>
@@ -338,6 +344,7 @@
338344
<widget class="QLabel" name="labelBalance">
339345
<property name="font">
340346
<font>
347+
<family>Monospace</family>
341348
<weight>75</weight>
342349
<bold>true</bold>
343350
</font>
@@ -349,7 +356,7 @@
349356
<string>Your current spendable balance</string>
350357
</property>
351358
<property name="text">
352-
<string notr="true">0.000000 00 BTC</string>
359+
<string notr="true">21 000 000.00000000 BTC</string>
353360
</property>
354361
<property name="alignment">
355362
<set>Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter</set>
@@ -363,6 +370,7 @@
363370
<widget class="QLabel" name="labelWatchAvailable">
364371
<property name="font">
365372
<font>
373+
<family>Monospace</family>
366374
<weight>75</weight>
367375
<bold>true</bold>
368376
</font>
@@ -374,7 +382,7 @@
374382
<string>Your current balance in watch-only addresses</string>
375383
</property>
376384
<property name="text">
377-
<string notr="true">0.000000 00 BTC</string>
385+
<string notr="true">21 000 000.00000000 BTC</string>
378386
</property>
379387
<property name="alignment">
380388
<set>Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter</set>

src/qt/overviewpage.cpp

Lines changed: 33 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,9 @@
1616
#include <qt/walletmodel.h>
1717

1818
#include <QAbstractItemDelegate>
19+
#include <QApplication>
1920
#include <QPainter>
21+
#include <QStatusTipEvent>
2022

2123
#define DECORATION_SIZE 54
2224
#define NUM_ITEMS 5
@@ -152,6 +154,21 @@ void OverviewPage::handleOutOfSyncWarningClicks()
152154
Q_EMIT outOfSyncWarningClicked();
153155
}
154156

157+
void OverviewPage::setPrivacy(bool privacy)
158+
{
159+
m_privacy = privacy;
160+
if (m_balances.balance != -1) {
161+
setBalance(m_balances);
162+
}
163+
164+
ui->listTransactions->setVisible(!m_privacy);
165+
166+
const QString status_tip = m_privacy ? tr("Privacy mode activated for the Overview tab. To unmask the values, uncheck Settings->Mask values.") : "";
167+
setStatusTip(status_tip);
168+
QStatusTipEvent event(status_tip);
169+
QApplication::sendEvent(this, &event);
170+
}
171+
155172
OverviewPage::~OverviewPage()
156173
{
157174
delete ui;
@@ -163,25 +180,25 @@ void OverviewPage::setBalance(const interfaces::WalletBalances& balances)
163180
m_balances = balances;
164181
if (walletModel->wallet().isLegacy()) {
165182
if (walletModel->wallet().privateKeysDisabled()) {
166-
ui->labelBalance->setText(BitcoinUnits::formatWithUnit(unit, balances.watch_only_balance, false, BitcoinUnits::separatorAlways));
167-
ui->labelUnconfirmed->setText(BitcoinUnits::formatWithUnit(unit, balances.unconfirmed_watch_only_balance, false, BitcoinUnits::separatorAlways));
168-
ui->labelImmature->setText(BitcoinUnits::formatWithUnit(unit, balances.immature_watch_only_balance, false, BitcoinUnits::separatorAlways));
169-
ui->labelTotal->setText(BitcoinUnits::formatWithUnit(unit, balances.watch_only_balance + balances.unconfirmed_watch_only_balance + balances.immature_watch_only_balance, false, BitcoinUnits::separatorAlways));
183+
ui->labelBalance->setText(BitcoinUnits::formatWithPrivacy(unit, balances.watch_only_balance, BitcoinUnits::separatorAlways, m_privacy));
184+
ui->labelUnconfirmed->setText(BitcoinUnits::formatWithPrivacy(unit, balances.unconfirmed_watch_only_balance, BitcoinUnits::separatorAlways, m_privacy));
185+
ui->labelImmature->setText(BitcoinUnits::formatWithPrivacy(unit, balances.immature_watch_only_balance, BitcoinUnits::separatorAlways, m_privacy));
186+
ui->labelTotal->setText(BitcoinUnits::formatWithPrivacy(unit, balances.watch_only_balance + balances.unconfirmed_watch_only_balance + balances.immature_watch_only_balance, BitcoinUnits::separatorAlways, m_privacy));
170187
} else {
171-
ui->labelBalance->setText(BitcoinUnits::formatWithUnit(unit, balances.balance, false, BitcoinUnits::separatorAlways));
172-
ui->labelUnconfirmed->setText(BitcoinUnits::formatWithUnit(unit, balances.unconfirmed_balance, false, BitcoinUnits::separatorAlways));
173-
ui->labelImmature->setText(BitcoinUnits::formatWithUnit(unit, balances.immature_balance, false, BitcoinUnits::separatorAlways));
174-
ui->labelTotal->setText(BitcoinUnits::formatWithUnit(unit, balances.balance + balances.unconfirmed_balance + balances.immature_balance, false, BitcoinUnits::separatorAlways));
175-
ui->labelWatchAvailable->setText(BitcoinUnits::formatWithUnit(unit, balances.watch_only_balance, false, BitcoinUnits::separatorAlways));
176-
ui->labelWatchPending->setText(BitcoinUnits::formatWithUnit(unit, balances.unconfirmed_watch_only_balance, false, BitcoinUnits::separatorAlways));
177-
ui->labelWatchImmature->setText(BitcoinUnits::formatWithUnit(unit, balances.immature_watch_only_balance, false, BitcoinUnits::separatorAlways));
178-
ui->labelWatchTotal->setText(BitcoinUnits::formatWithUnit(unit, balances.watch_only_balance + balances.unconfirmed_watch_only_balance + balances.immature_watch_only_balance, false, BitcoinUnits::separatorAlways));
188+
ui->labelBalance->setText(BitcoinUnits::formatWithPrivacy(unit, balances.balance, BitcoinUnits::separatorAlways, m_privacy));
189+
ui->labelUnconfirmed->setText(BitcoinUnits::formatWithPrivacy(unit, balances.unconfirmed_balance, BitcoinUnits::separatorAlways, m_privacy));
190+
ui->labelImmature->setText(BitcoinUnits::formatWithPrivacy(unit, balances.immature_balance, BitcoinUnits::separatorAlways, m_privacy));
191+
ui->labelTotal->setText(BitcoinUnits::formatWithPrivacy(unit, balances.balance + balances.unconfirmed_balance + balances.immature_balance, BitcoinUnits::separatorAlways, m_privacy));
192+
ui->labelWatchAvailable->setText(BitcoinUnits::formatWithPrivacy(unit, balances.watch_only_balance, BitcoinUnits::separatorAlways, m_privacy));
193+
ui->labelWatchPending->setText(BitcoinUnits::formatWithPrivacy(unit, balances.unconfirmed_watch_only_balance, BitcoinUnits::separatorAlways, m_privacy));
194+
ui->labelWatchImmature->setText(BitcoinUnits::formatWithPrivacy(unit, balances.immature_watch_only_balance, BitcoinUnits::separatorAlways, m_privacy));
195+
ui->labelWatchTotal->setText(BitcoinUnits::formatWithPrivacy(unit, balances.watch_only_balance + balances.unconfirmed_watch_only_balance + balances.immature_watch_only_balance, BitcoinUnits::separatorAlways, m_privacy));
179196
}
180197
} else {
181-
ui->labelBalance->setText(BitcoinUnits::formatWithUnit(unit, balances.balance, false, BitcoinUnits::separatorAlways));
182-
ui->labelUnconfirmed->setText(BitcoinUnits::formatWithUnit(unit, balances.unconfirmed_balance, false, BitcoinUnits::separatorAlways));
183-
ui->labelImmature->setText(BitcoinUnits::formatWithUnit(unit, balances.immature_balance, false, BitcoinUnits::separatorAlways));
184-
ui->labelTotal->setText(BitcoinUnits::formatWithUnit(unit, balances.balance + balances.unconfirmed_balance + balances.immature_balance, false, BitcoinUnits::separatorAlways));
198+
ui->labelBalance->setText(BitcoinUnits::formatWithPrivacy(unit, balances.balance, BitcoinUnits::separatorAlways, m_privacy));
199+
ui->labelUnconfirmed->setText(BitcoinUnits::formatWithPrivacy(unit, balances.unconfirmed_balance, BitcoinUnits::separatorAlways, m_privacy));
200+
ui->labelImmature->setText(BitcoinUnits::formatWithPrivacy(unit, balances.immature_balance, BitcoinUnits::separatorAlways, m_privacy));
201+
ui->labelTotal->setText(BitcoinUnits::formatWithPrivacy(unit, balances.balance + balances.unconfirmed_balance + balances.immature_balance, BitcoinUnits::separatorAlways, m_privacy));
185202
}
186203
// only show immature (newly mined) balance if it's non-zero, so as not to complicate things
187204
// for the non-mining users

src/qt/overviewpage.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -39,6 +39,7 @@ class OverviewPage : public QWidget
3939

4040
public Q_SLOTS:
4141
void setBalance(const interfaces::WalletBalances& balances);
42+
void setPrivacy(bool privacy);
4243

4344
Q_SIGNALS:
4445
void transactionClicked(const QModelIndex &index);
@@ -49,6 +50,7 @@ public Q_SLOTS:
4950
ClientModel *clientModel;
5051
WalletModel *walletModel;
5152
interfaces::WalletBalances m_balances;
53+
bool m_privacy{false};
5254

5355
TxViewDelegate *txdelegate;
5456
std::unique_ptr<TransactionFilterProxy> filter;

src/qt/test/wallettests.cpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -201,7 +201,7 @@ void TestGUI(interfaces::Node& node)
201201
OverviewPage overviewPage(platformStyle.get());
202202
overviewPage.setWalletModel(&walletModel);
203203
QLabel* balanceLabel = overviewPage.findChild<QLabel*>("labelBalance");
204-
QString balanceText = balanceLabel->text();
204+
QString balanceText = balanceLabel->text().trimmed();
205205
int unit = walletModel.getOptionsModel()->getDisplayUnit();
206206
CAmount balance = walletModel.wallet().getBalance();
207207
QString balanceComparison = BitcoinUnits::formatWithUnit(unit, balance, false, BitcoinUnits::separatorAlways);

src/qt/walletframe.cpp

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -53,6 +53,7 @@ bool WalletFrame::addWallet(WalletModel *walletModel)
5353
walletView->setClientModel(clientModel);
5454
walletView->setWalletModel(walletModel);
5555
walletView->showOutOfSyncWarning(bOutOfSync);
56+
walletView->setPrivacy(gui->isPrivacyModeActivated());
5657

5758
WalletView* current_wallet_view = currentWalletView();
5859
if (current_wallet_view) {
@@ -73,6 +74,7 @@ bool WalletFrame::addWallet(WalletModel *walletModel)
7374
connect(walletView, &WalletView::encryptionStatusChanged, gui, &BitcoinGUI::updateWalletStatus);
7475
connect(walletView, &WalletView::incomingTransaction, gui, &BitcoinGUI::incomingTransaction);
7576
connect(walletView, &WalletView::hdEnabledStatusChanged, gui, &BitcoinGUI::updateWalletStatus);
77+
connect(gui, &BitcoinGUI::setPrivacy, walletView, &WalletView::setPrivacy);
7678

7779
return true;
7880
}

0 commit comments

Comments
 (0)