Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

gui: Implement privacy mode #2399

Merged
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
35 changes: 35 additions & 0 deletions src/qt/bitcoingui.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -408,6 +408,11 @@ void BitcoinGUI::createActions()
resetblockchainAction = new QAction(tr("&Reset blockchain data"), this);
resetblockchainAction->setToolTip(tr("Remove blockchain data and start chain from zero"));

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 screen"));
m_mask_values_action->setCheckable(true);

connect(quitAction, &QAction::triggered, this, &BitcoinGUI::tryQuit);
connect(aboutAction, &QAction::triggered, this, &BitcoinGUI::aboutClicked);
connect(optionsAction, &QAction::triggered, this, &BitcoinGUI::optionsClicked);
Expand Down Expand Up @@ -554,6 +559,8 @@ void BitcoinGUI::createMenuBar()
settings->addSeparator();
settings->addAction(optionsAction);
settings->addAction(openConfigAction);
settings->addSeparator();
settings->addAction(m_mask_values_action);

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

// Ensure the checkbox for mask values action matches the retrieved state from the optionsModel.
m_mask_values_action->setChecked(isPrivacyModeActivated());

// Connect the action to the setPrivacy function. (This has to be done after the setting of the
jamescowens marked this conversation as resolved.
Show resolved Hide resolved
// checkbox state instead of in the createActions above.
connect(m_mask_values_action, &QAction::toggled, this, &BitcoinGUI::setPrivacy);

rpcConsole->setClientModel(clientModel);
addressBookPage->setOptionsModel(clientModel->getOptionsModel());
receiveCoinsPage->setOptionsModel(clientModel->getOptionsModel());
Expand Down Expand Up @@ -839,6 +853,13 @@ void BitcoinGUI::createTrayIcon()
notificator = new Notificator(qApp->applicationName(), trayIcon, this);
}

bool BitcoinGUI::isPrivacyModeActivated() const
{
if (!clientModel || !clientModel->getOptionsModel()) return false;

return clientModel->getOptionsModel()->getMaskValues();
}

void BitcoinGUI::createTrayIconMenu()
{
#ifndef Q_OS_MAC
Expand Down Expand Up @@ -1278,6 +1299,20 @@ void BitcoinGUI::resetblockchainClicked()
}
}

void BitcoinGUI::setPrivacy()
{
if (!clientModel || !clientModel->getOptionsModel()) return;

bool privacy_mode(!clientModel->getOptionsModel()->getMaskValues());

clientModel->getOptionsModel()->setMaskValues(privacy_mode);

// Need to call updateMinerStatus from here to feed back in the Coin Weight to the overview screen.
// Not ideal, but the normal trigger to update the Staking fields on the overview screen normally come from
// the core, not the GUI. Here the privacy state change is coming from the GUI.
clientModel->updateMinerStatus(g_miner_status.StakingActive(), g_miner_status.GetSearchReport().CoinWeight());
}

bool BitcoinGUI::tryQuit()
{
if(clientModel &&
Expand Down
8 changes: 8 additions & 0 deletions src/qt/bitcoingui.h
Original file line number Diff line number Diff line change
Expand Up @@ -72,6 +72,12 @@ class BitcoinGUI : public QMainWindow
*/
void setVotingModel(VotingModel *votingModel);

/**
* @brief Queries the state of privacy mode (mask values on overview screen).
* @return boolean of the mask values state
*/
bool isPrivacyModeActivated() const;

protected:
void changeEvent(QEvent *e);
void closeEvent(QCloseEvent *event);
Expand Down Expand Up @@ -140,6 +146,7 @@ class BitcoinGUI : public QMainWindow
QAction *openRPCConsoleAction;
QAction *snapshotAction;
QAction *resetblockchainAction;
QAction *m_mask_values_action;

QSystemTrayIcon *trayIcon;
QMenu *trayIconMenu;
Expand Down Expand Up @@ -244,6 +251,7 @@ private slots:
void peersClicked();
void snapshotClicked();
void resetblockchainClicked();
void setPrivacy();
bool tryQuit();

#ifndef Q_OS_MAC
Expand Down
40 changes: 36 additions & 4 deletions src/qt/bitcoinunits.cpp
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
#include "bitcoinunits.h"
#include <assert.h>

#include <QStringList>

Expand Down Expand Up @@ -85,7 +86,7 @@ int BitcoinUnits::decimals(int unit)
}
}

QString BitcoinUnits::format(int unit, qint64 n, bool fPlus)
QString BitcoinUnits::format(int unit, qint64 n, bool fPlus, bool justify)
{
// Note: not using straight sprintf here because we do NOT want
// localized number formatting.
Expand All @@ -97,6 +98,9 @@ QString BitcoinUnits::format(int unit, qint64 n, bool fPlus)
qint64 quotient = n_abs / coin;
qint64 remainder = n_abs % coin;
QString quotient_str = QString::number(quotient);

if (justify) quotient_str = quotient_str.rightJustified(16 - num_decimals, ' ');

QString remainder_str = QString::number(remainder).rightJustified(num_decimals, '0');

// Right-trim excess zeros after the decimal point
Expand All @@ -117,10 +121,33 @@ QString BitcoinUnits::formatWithUnit(int unit, qint64 amount, bool plussign)
return format(unit, amount, plussign) + QString(" ") + name(unit);
}

QString BitcoinUnits::formatOverviewRounded(qint64 amount)
QString BitcoinUnits::formatWithPrivacy(int unit, qint64 amount, bool privacy)
{
// See comments on Bitcoin core PR #16432
assert(amount >= 0);

QString value;
if (privacy) {
value = format(unit, 0, false, false).replace('0', '#');
} else {
value = format(unit, amount, false, false);
}

return value + QString(" ") + name(unit);
}

QString BitcoinUnits::formatOverviewRounded(qint64 amount, bool privacy)
{
QString value;

if (amount < factor(BTC)) {
return format(BTC, amount);
if (privacy) {
value = format(BTC, 0, false, false).replace('0', '#');
} else {
value = format(BTC, amount, false, false);
}

return value;
}

qint64 round_scale = 10;
Expand All @@ -135,7 +162,12 @@ QString BitcoinUnits::formatOverviewRounded(qint64 amount)
// Rounds half-down to avoid over-representing the amount:
const qint64 rounded_amount = static_cast<double>(amount) / round_scale;

return format(BTC, rounded_amount * round_scale);
if (privacy) {
value = format(BTC, 0, false, false).replace('0', '#');
} else {
value = format(BTC, rounded_amount * round_scale, false, false);
}
return value;
}

bool BitcoinUnits::parse(int unit, const QString &value, qint64 *val_out)
Expand Down
8 changes: 5 additions & 3 deletions src/qt/bitcoinunits.h
Original file line number Diff line number Diff line change
Expand Up @@ -41,11 +41,13 @@ class BitcoinUnits: public QAbstractListModel
//! Number of decimals left
static int decimals(int unit);
//! Format as string
static QString format(int unit, qint64 amount, bool plussign=false);
static QString format(int unit, qint64 amount, bool plussign = false, bool justify = false);
//! Format as string (with unit)
static QString formatWithUnit(int unit, qint64 amount, bool plussign=false);
static QString formatWithUnit(int unit, qint64 amount, bool plussign = false);
//! Format as string with optional privacy mask
static QString formatWithPrivacy(int unit, qint64 amount, bool privacy);
//! Format as a rounded string approximation for overview presentation
static QString formatOverviewRounded(qint64 amount);
static QString formatOverviewRounded(qint64 amount, bool privacy = false);
//! Parse string to coin amount
static bool parse(int unit, const QString &value, qint64 *val_out);
///@}
Expand Down
5 changes: 5 additions & 0 deletions src/qt/noresult.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -60,3 +60,8 @@ void NoResult::showDefaultLoadingTitle()
{
setTitle(tr("Loading..."));
}

void NoResult::showPrivacyEnabledTitle()
{
setTitle(tr("Privacy Enabled..."));
}
1 change: 1 addition & 0 deletions src/qt/noresult.h
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,7 @@ public slots:
void showDefaultNothingHereTitle();
void showDefaultNoResultTitle();
void showDefaultLoadingTitle();
void showPrivacyEnabledTitle();

private:
Ui::NoResult *ui;
Expand Down
18 changes: 18 additions & 0 deletions src/qt/optionsmodel.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -51,6 +51,7 @@ void OptionsModel::Init()
fConfirmOnClose = settings.value("fConfirmOnClose", false).toBool();
fCoinControlFeatures = settings.value("fCoinControlFeatures", false).toBool();
fLimitTxnDisplay = settings.value("fLimitTxnDisplay", false).toBool();
fMaskValues = settings.value("fMaskValues", false).toBool();
limitTxnDate = settings.value("limitTxnDate", QDate()).toDate();
nReserveBalance = settings.value("nReserveBalance").toLongLong();
language = settings.value("language", "").toString();
Expand Down Expand Up @@ -133,6 +134,8 @@ QVariant OptionsModel::data(const QModelIndex & index, int role) const
return QVariant(fCoinControlFeatures);
case LimitTxnDisplay:
return QVariant(fLimitTxnDisplay);
case MaskValues:
return QVariant(fMaskValues);
case LimitTxnDate:
return QVariant(limitTxnDate);
case DisableUpdateCheck:
Expand Down Expand Up @@ -268,6 +271,11 @@ bool OptionsModel::setData(const QModelIndex & index, const QVariant & value, in
settings.setValue("fLimitTxnDisplay", fLimitTxnDisplay);
emit LimitTxnDisplayChanged(fLimitTxnDisplay);
break;
case MaskValues:
fMaskValues = value.toBool();
settings.setValue("fMaskValues", fMaskValues);
emit MaskValuesChanged(fMaskValues);
break;
case LimitTxnDate:
limitTxnDate = value.toDate();
settings.setValue("limitTxnDate", limitTxnDate);
Expand Down Expand Up @@ -347,6 +355,11 @@ bool OptionsModel::getLimitTxnDisplay()
return fLimitTxnDisplay;
}

bool OptionsModel::getMaskValues()
{
return fMaskValues;
}

QDate OptionsModel::getLimitTxnDate()
{
return limitTxnDate;
Expand Down Expand Up @@ -423,6 +436,11 @@ void OptionsModel::setCurrentStyle(QString theme)
setData(QAbstractItemModel::createIndex(WalletStylesheet, 0), theme, Qt::EditRole);
}

void OptionsModel::setMaskValues(bool privacy_mode)
{
setData(QAbstractItemModel::createIndex(MaskValues, 0), privacy_mode, Qt::EditRole);
}

QString OptionsModel::getDataDir()
{
return dataDir;
Expand Down
5 changes: 5 additions & 0 deletions src/qt/optionsmodel.h
Original file line number Diff line number Diff line change
Expand Up @@ -44,6 +44,7 @@ class OptionsModel : public QAbstractListModel
StakingEfficiency, // double
MinStakeSplitValue, // int
ContractChangeToInput, // bool
MaskValues, // bool
OptionIDRowCount
};

Expand All @@ -67,6 +68,7 @@ class OptionsModel : public QAbstractListModel
bool getDisplayAddresses();
bool getCoinControlFeatures();
bool getLimitTxnDisplay();
bool getMaskValues();
QDate getLimitTxnDate();
int64_t getLimitTxnDateTime();
QString getLanguage() { return language; }
Expand All @@ -75,6 +77,7 @@ class OptionsModel : public QAbstractListModel

/* Explicit setters */
void setCurrentStyle(QString theme);
void setMaskValues(bool privacy_mode);
void toggleCoinControlFeatures();

private:
Expand All @@ -89,6 +92,7 @@ class OptionsModel : public QAbstractListModel
bool fConfirmOnClose;
bool fCoinControlFeatures;
bool fLimitTxnDisplay;
bool fMaskValues;
QDate limitTxnDate;
QString language;
QString walletStylesheet;
Expand All @@ -99,6 +103,7 @@ class OptionsModel : public QAbstractListModel
void reserveBalanceChanged(qint64);
void coinControlFeaturesChanged(bool);
void LimitTxnDisplayChanged(bool);
void MaskValuesChanged(bool);
void walletStylesheetChanged(QString);
};

Expand Down
Loading