Skip to content

Commit cbc83fa

Browse files
committed
Implement GUI overview screen value masking
1 parent fbcb66d commit cbc83fa

File tree

6 files changed

+122
-12
lines changed

6 files changed

+122
-12
lines changed

src/qt/bitcoingui.cpp

Lines changed: 35 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -408,6 +408,11 @@ void BitcoinGUI::createActions()
408408
resetblockchainAction = new QAction(tr("&Reset blockchain data"), this);
409409
resetblockchainAction->setToolTip(tr("Remove blockchain data and start chain from zero"));
410410

411+
m_mask_values_action = new QAction(tr("&Mask values"), this);
412+
m_mask_values_action->setShortcut(QKeySequence(Qt::CTRL + Qt::SHIFT + Qt::Key_M));
413+
m_mask_values_action->setStatusTip(tr("Mask the values in the Overview screen"));
414+
m_mask_values_action->setCheckable(true);
415+
411416
connect(quitAction, &QAction::triggered, this, &BitcoinGUI::tryQuit);
412417
connect(aboutAction, &QAction::triggered, this, &BitcoinGUI::aboutClicked);
413418
connect(optionsAction, &QAction::triggered, this, &BitcoinGUI::optionsClicked);
@@ -554,6 +559,8 @@ void BitcoinGUI::createMenuBar()
554559
settings->addSeparator();
555560
settings->addAction(optionsAction);
556561
settings->addAction(openConfigAction);
562+
settings->addSeparator();
563+
settings->addAction(m_mask_values_action);
557564

558565
QMenu *community = appMenuBar->addMenu(tr("&Community"));
559566
community->addAction(bxAction);
@@ -758,6 +765,13 @@ void BitcoinGUI::setClientModel(ClientModel *clientModel)
758765
// Report errors from network/worker thread
759766
connect(clientModel, &ClientModel::error, this, &BitcoinGUI::error);
760767

768+
// Ensure the checkbox for mask values action matches the retrieved state from the optionsModel.
769+
m_mask_values_action->setChecked(isPrivacyModeActivated());
770+
771+
// Connect the action to the setPrivacy function. (This has to be done after the setting of the
772+
// checkbox state instead of in the createActions above.
773+
connect(m_mask_values_action, &QAction::toggled, this, &BitcoinGUI::setPrivacy);
774+
761775
rpcConsole->setClientModel(clientModel);
762776
addressBookPage->setOptionsModel(clientModel->getOptionsModel());
763777
receiveCoinsPage->setOptionsModel(clientModel->getOptionsModel());
@@ -839,6 +853,13 @@ void BitcoinGUI::createTrayIcon()
839853
notificator = new Notificator(qApp->applicationName(), trayIcon, this);
840854
}
841855

856+
bool BitcoinGUI::isPrivacyModeActivated() const
857+
{
858+
if (!clientModel || !clientModel->getOptionsModel()) return false;
859+
860+
return clientModel->getOptionsModel()->getMaskValues();
861+
}
862+
842863
void BitcoinGUI::createTrayIconMenu()
843864
{
844865
#ifndef Q_OS_MAC
@@ -1278,6 +1299,20 @@ void BitcoinGUI::resetblockchainClicked()
12781299
}
12791300
}
12801301

1302+
void BitcoinGUI::setPrivacy()
1303+
{
1304+
if (!clientModel || !clientModel->getOptionsModel()) return;
1305+
1306+
bool privacy_mode(!clientModel->getOptionsModel()->getMaskValues());
1307+
1308+
clientModel->getOptionsModel()->setMaskValues(privacy_mode);
1309+
1310+
// Need to call updateMinerStatus from here to feed back in the Coin Weight to the overview screen.
1311+
// Not ideal, but the normal trigger to update the Staking fields on the overview screen normally come from
1312+
// the core, not the GUI. Here the privacy state change is coming from the GUI.
1313+
clientModel->updateMinerStatus(g_miner_status.StakingActive(), g_miner_status.GetSearchReport().CoinWeight());
1314+
}
1315+
12811316
bool BitcoinGUI::tryQuit()
12821317
{
12831318
if(clientModel &&

src/qt/bitcoingui.h

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -72,6 +72,12 @@ class BitcoinGUI : public QMainWindow
7272
*/
7373
void setVotingModel(VotingModel *votingModel);
7474

75+
/**
76+
* @brief Queries the state of privacy mode (mask values on overview screen).
77+
* @return boolean of the mask values state
78+
*/
79+
bool isPrivacyModeActivated() const;
80+
7581
protected:
7682
void changeEvent(QEvent *e);
7783
void closeEvent(QCloseEvent *event);
@@ -140,6 +146,7 @@ class BitcoinGUI : public QMainWindow
140146
QAction *openRPCConsoleAction;
141147
QAction *snapshotAction;
142148
QAction *resetblockchainAction;
149+
QAction *m_mask_values_action;
143150

144151
QSystemTrayIcon *trayIcon;
145152
QMenu *trayIconMenu;
@@ -244,6 +251,7 @@ private slots:
244251
void peersClicked();
245252
void snapshotClicked();
246253
void resetblockchainClicked();
254+
void setPrivacy();
247255
bool tryQuit();
248256

249257
#ifndef Q_OS_MAC

src/qt/overviewpage.cpp

Lines changed: 64 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -19,7 +19,9 @@
1919
#include "gridcoin/voting/fwd.h"
2020

2121
#include <QAbstractItemDelegate>
22+
#include <QApplication>
2223
#include <QPainter>
24+
#include <QStatusTipEvent>
2325

2426
#define DECORATION_SIZE 40
2527

@@ -196,8 +198,16 @@ int OverviewPage::getNumTransactionsForView()
196198
// Compute the maximum number of transactions the transaction list widget
197199
// can hold without overflowing.
198200
const size_t itemHeight = txdelegate->height() + ui->listTransactions->spacing();
199-
const size_t contentsHeight = ui->listTransactions->height();
200-
const int numItems = contentsHeight / itemHeight;
201+
202+
// We have to use the frame here because when the listTransactions is hidden, the recentTransactionsNoResult
203+
// takes up the space and would cause the calculation to be off.
204+
const size_t contentsHeight = std::max(ui->recentTransactionsFrame->height() - ui->recentTransLabel->height(), 0);
205+
206+
LogPrint(BCLog::LogFlags::QT, "INFO: %s: contentsHeight = %u, itemHeight = %u",
207+
__func__, contentsHeight, itemHeight);
208+
209+
// take one off so that there is not a "half-visible one" there, ensure not below 0.
210+
const int numItems = std::max((int) (contentsHeight / itemHeight) - 1, 0);
201211

202212
return numItems;
203213
}
@@ -262,12 +272,13 @@ void OverviewPage::setBalance(qint64 balance, qint64 stake, qint64 unconfirmedBa
262272
currentStake = stake;
263273
currentUnconfirmedBalance = unconfirmedBalance;
264274
currentImmatureBalance = immatureBalance;
265-
ui->headerBalanceLabel->setText(BitcoinUnits::formatOverviewRounded(balance));
266-
ui->balanceLabel->setText(BitcoinUnits::formatWithUnit(unit, balance));
267-
ui->stakeLabel->setText(BitcoinUnits::formatWithUnit(unit, stake));
268-
ui->unconfirmedLabel->setText(BitcoinUnits::formatWithUnit(unit, unconfirmedBalance));
269-
ui->immatureLabel->setText(BitcoinUnits::formatWithUnit(unit, immatureBalance));
270-
ui->totalLabel->setText(BitcoinUnits::formatWithUnit(unit, balance + stake + unconfirmedBalance + immatureBalance));
275+
ui->headerBalanceLabel->setText(BitcoinUnits::formatOverviewRounded(balance, m_privacy));
276+
ui->balanceLabel->setText(BitcoinUnits::formatWithPrivacy(unit, balance, m_privacy));
277+
ui->stakeLabel->setText(BitcoinUnits::formatWithPrivacy(unit, stake, m_privacy));
278+
ui->unconfirmedLabel->setText(BitcoinUnits::formatWithPrivacy(unit, unconfirmedBalance, m_privacy));
279+
ui->immatureLabel->setText(BitcoinUnits::formatWithPrivacy(unit, immatureBalance, m_privacy));
280+
ui->totalLabel->setText(BitcoinUnits::formatWithPrivacy(unit, balance + stake + unconfirmedBalance + immatureBalance,
281+
m_privacy));
271282

272283
// only show immature (newly mined) balance if it's non-zero, so as not to complicate things
273284
// for the non-mining users
@@ -289,14 +300,45 @@ void OverviewPage::setDifficulty(double difficulty, double net_weight)
289300

290301
void OverviewPage::setCoinWeight(double coin_weight)
291302
{
292-
ui->coinWeightLabel->setText(QString::number(coin_weight, 'f', 2));
303+
QString text;
304+
305+
if (m_privacy) {
306+
text = QString("#.##");
307+
} else {
308+
text = QString::number(coin_weight, 'f', 2);
309+
}
310+
311+
ui->coinWeightLabel->setText(text);
293312
}
294313

295314
void OverviewPage::setCurrentPollTitle(const QString& title)
296315
{
297316
ui->currentPollsTitleLabel->setText(title);
298317
}
299318

319+
void OverviewPage::setPrivacy(bool privacy)
320+
{
321+
m_privacy = privacy;
322+
if (currentBalance != -1) {
323+
setBalance(currentBalance, currentStake, currentUnconfirmedBalance, currentImmatureBalance);
324+
}
325+
326+
ui->listTransactions->setVisible(!m_privacy);
327+
if (researcherModel) researcherModel->setMaskAccrual(m_privacy);
328+
329+
LogPrint(BCLog::LogFlags::QT, "INFO: %s: m_privacy = %u", __func__, m_privacy);
330+
331+
const QString status_tip = m_privacy ? tr("Privacy mode activated for the Overview screen. To unmask the values, uncheck "
332+
"Settings->Mask values.") : "";
333+
334+
updateTransactions();
335+
updatePendingAccrual();
336+
337+
setStatusTip(status_tip);
338+
QStatusTipEvent event(status_tip);
339+
QApplication::sendEvent(this, &event);
340+
}
341+
300342
void OverviewPage::setResearcherModel(ResearcherModel *researcherModel)
301343
{
302344
this->researcherModel = researcherModel;
@@ -324,7 +366,13 @@ void OverviewPage::setWalletModel(WalletModel *model)
324366
filter->setDynamicSortFilter(true);
325367
filter->setSortRole(Qt::EditRole);
326368
filter->setShowInactive(false);
327-
filter->setLimit(getNumTransactionsForView());
369+
370+
int num_transactions_for_view = getNumTransactionsForView();
371+
filter->setLimit(num_transactions_for_view);
372+
373+
LogPrint(BCLog::LogFlags::QT, "INFO: %s: num_transactions_for_view = %i, getLimit() = %i",
374+
__func__, num_transactions_for_view, filter->getLimit());
375+
328376
filter->sort(TransactionTableModel::Status, Qt::DescendingOrder);
329377
ui->listTransactions->setModel(filter.get());
330378
ui->listTransactions->setModelColumn(TransactionTableModel::ToAddress);
@@ -337,6 +385,12 @@ void OverviewPage::setWalletModel(WalletModel *model)
337385

338386
connect(model->getOptionsModel(), &OptionsModel::LimitTxnDisplayChanged, this, &OverviewPage::updateTransactions);
339387
connect(model, &WalletModel::transactionUpdated, this, &OverviewPage::updateTransactions);
388+
389+
// Set the privacy state for the overview screen from the optionsModel for init.
390+
setPrivacy(model->getOptionsModel()->getMaskValues());
391+
392+
// Connect the privacy mode setting to the options dialog.
393+
connect(walletModel->getOptionsModel(), &OptionsModel::MaskValuesChanged, this, & OverviewPage::setPrivacy);
340394
}
341395

342396
// update the display unit, to not use the default ("BTC")

src/qt/overviewpage.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -35,6 +35,7 @@ public slots:
3535
void setDifficulty(double difficulty, double net_weight);
3636
void setCoinWeight(double coin_weight);
3737
void setCurrentPollTitle(const QString& title);
38+
void setPrivacy(bool privacy);
3839

3940
signals:
4041
void transactionClicked(const QModelIndex &index);
@@ -55,6 +56,7 @@ public slots:
5556
qint64 currentUnconfirmedBalance;
5657
qint64 currentImmatureBalance;
5758
int scaledDecorationSize;
59+
bool m_privacy = false;
5860

5961
TxViewDelegate *txdelegate;
6062
std::unique_ptr<TransactionFilterProxy> filter;

src/qt/researcher/researchermodel.cpp

Lines changed: 11 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -202,6 +202,11 @@ void ResearcherModel::setTheme(const QString& theme_name)
202202
emit beaconChanged();
203203
}
204204

205+
void ResearcherModel::setMaskAccrual(bool privacy)
206+
{
207+
m_mask_accrual = privacy;
208+
}
209+
205210
bool ResearcherModel::configuredForInvestorMode() const
206211
{
207212
return m_configured_for_investor_mode;
@@ -303,11 +308,15 @@ QString ResearcherModel::formatMagnitude() const
303308

304309
QString ResearcherModel::formatAccrual(const int display_unit) const
305310
{
311+
QString text;
312+
306313
if (outOfSync()) {
307-
return "...";
314+
text = "...";
315+
} else {
316+
text = BitcoinUnits::formatWithPrivacy(display_unit, m_researcher->Accrual(), m_mask_accrual);
308317
}
309318

310-
return BitcoinUnits::formatWithUnit(display_unit, m_researcher->Accrual());
319+
return text;
311320
}
312321

313322
QString ResearcherModel::formatStatus() const

src/qt/researcher/researchermodel.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -81,6 +81,7 @@ class ResearcherModel : public QObject
8181

8282
void showWizard(WalletModel* wallet_model);
8383
void setTheme(const QString& theme_name);
84+
void setMaskAccrual(bool privacy);
8485

8586
bool configuredForInvestorMode() const;
8687
bool outOfSync() const;
@@ -120,6 +121,7 @@ class ResearcherModel : public QObject
120121
bool m_configured_for_investor_mode;
121122
bool m_wizard_open;
122123
bool m_out_of_sync;
124+
bool m_mask_accrual;
123125
QString m_theme_suffix;
124126

125127
void subscribeToCoreSignals();

0 commit comments

Comments
 (0)