Skip to content

Commit 8969828

Browse files
committed
[Qt] New status bar Unit Display Control and related changes.
- New status bar control shows the current Unit of Display. When clicked (left,or right button) it shows a context menu that allows the user to switch the current Unit of Display (BTC, mBTC, uBTC) - Recent Requests and Transaction Table headers are now updated when unit of display is changed, because their "Amount" column now displays the current unit of display. - Takes care of issue #3970 Units in transaction export csv file. - Small refactors for reusability. - Demo Video https://www.youtube.com/watch?v=wwcr0Yh68go&list=UUG3jF2hgofmLWP0tRPisQAQ - changes after Diapolo's feedback. Have not been able to build after last pool, issues with boost on MacOSX, will test on Ubuntu these changes. - removed return statement on switch - renamed onDisplayUnitsChanged(int) to updateDisplayUnit(int) - now getAmountColumnTitle(int unit) takes a simple unit parameter. moved to BitcoinUnits.
1 parent 343feec commit 8969828

11 files changed

+187
-7
lines changed

src/qt/bitcoingui.cpp

Lines changed: 78 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -28,6 +28,7 @@
2828

2929
#include <iostream>
3030

31+
#include <QAction>
3132
#include <QApplication>
3233
#include <QDateTime>
3334
#include <QDesktopWidget>
@@ -39,6 +40,7 @@
3940
#include <QMenuBar>
4041
#include <QMessageBox>
4142
#include <QMimeData>
43+
#include <QPoint>
4244
#include <QProgressBar>
4345
#include <QProgressDialog>
4446
#include <QSettings>
@@ -49,6 +51,8 @@
4951
#include <QToolBar>
5052
#include <QVBoxLayout>
5153

54+
55+
5256
#if QT_VERSION < 0x050000
5357
#include <QUrl>
5458
#include <QTextDocument>
@@ -156,10 +160,13 @@ BitcoinGUI::BitcoinGUI(bool fIsTestnet, QWidget *parent) :
156160
QHBoxLayout *frameBlocksLayout = new QHBoxLayout(frameBlocks);
157161
frameBlocksLayout->setContentsMargins(3,0,3,0);
158162
frameBlocksLayout->setSpacing(3);
163+
unitDisplayControl = new UnitDisplayStatusBarControl();
159164
labelEncryptionIcon = new QLabel();
160165
labelConnectionsIcon = new QLabel();
161166
labelBlocksIcon = new QLabel();
162167
frameBlocksLayout->addStretch();
168+
frameBlocksLayout->addWidget(unitDisplayControl);
169+
frameBlocksLayout->addStretch();
163170
frameBlocksLayout->addWidget(labelEncryptionIcon);
164171
frameBlocksLayout->addStretch();
165172
frameBlocksLayout->addWidget(labelConnectionsIcon);
@@ -420,6 +427,8 @@ void BitcoinGUI::setClientModel(ClientModel *clientModel)
420427
walletFrame->setClientModel(clientModel);
421428
}
422429
#endif
430+
431+
this->unitDisplayControl->setOptionsModel(clientModel->getOptionsModel());
423432
}
424433
}
425434

@@ -1000,3 +1009,72 @@ void BitcoinGUI::unsubscribeFromCoreSignals()
10001009
// Disconnect signals from client
10011010
uiInterface.ThreadSafeMessageBox.disconnect(boost::bind(ThreadSafeMessageBox, this, _1, _2, _3));
10021011
}
1012+
1013+
UnitDisplayStatusBarControl::UnitDisplayStatusBarControl():QLabel()
1014+
{
1015+
optionsModel = 0;
1016+
createContextMenu();
1017+
setStyleSheet("font:11pt; color: #333333");
1018+
setToolTip(tr("Unit to show amounts in. Click to select another unit."));
1019+
}
1020+
1021+
/** So that it responds to left-button clicks */
1022+
void UnitDisplayStatusBarControl::mousePressEvent(QMouseEvent *event)
1023+
{
1024+
onDisplayUnitsClicked(event->pos());
1025+
}
1026+
1027+
/** Creates context menu, its actions, and wires up all the relevant signals for mouse events. */
1028+
void UnitDisplayStatusBarControl::createContextMenu()
1029+
{
1030+
menu = new QMenu();
1031+
foreach(BitcoinUnits::Unit u, BitcoinUnits::availableUnits())
1032+
{
1033+
QAction *menuAction = new QAction(QString(BitcoinUnits::name(u)), this);
1034+
menuAction->setData(QVariant(u));
1035+
menu->addAction(menuAction);
1036+
}
1037+
connect(menu,SIGNAL(triggered(QAction*)),this,SLOT(onMenuSelection(QAction*)));
1038+
1039+
// what happens on right click.
1040+
setContextMenuPolicy(Qt::CustomContextMenu);
1041+
connect(this,SIGNAL(customContextMenuRequested(const QPoint&)),this,SLOT(onDisplayUnitsClicked(const QPoint&)));
1042+
}
1043+
1044+
/** Lets the control know about the Options Model (and its signals) */
1045+
void UnitDisplayStatusBarControl::setOptionsModel(OptionsModel *optionsModel)
1046+
{
1047+
if (optionsModel)
1048+
{
1049+
this->optionsModel = optionsModel;
1050+
1051+
// be aware of a display unit change reported by the OptionsModel object.
1052+
connect(optionsModel,SIGNAL(displayUnitChanged(int)),this,SLOT(updateDisplayUnit(int)));
1053+
1054+
// initialize the display units label with the current value in the model.
1055+
updateDisplayUnit(optionsModel->getDisplayUnit());
1056+
}
1057+
}
1058+
1059+
/** When Display Units are changed on OptionsModel it will refresh the display text of the control on the status bar */
1060+
void UnitDisplayStatusBarControl::updateDisplayUnit(int newUnits)
1061+
{
1062+
setText(BitcoinUnits::name(newUnits));
1063+
}
1064+
1065+
/** Shows context menu with Display Unit options by the mouse coordinates */
1066+
void UnitDisplayStatusBarControl::onDisplayUnitsClicked(const QPoint& point)
1067+
{
1068+
QPoint globalPos = mapToGlobal(point);
1069+
menu->exec(globalPos);
1070+
}
1071+
1072+
/** Tells underlying optionsModel to update its current display unit. */
1073+
void UnitDisplayStatusBarControl::onMenuSelection(QAction* action)
1074+
{
1075+
if (action)
1076+
{
1077+
optionsModel->setDisplayUnit(action->data());
1078+
}
1079+
}
1080+

src/qt/bitcoingui.h

Lines changed: 37 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -9,22 +9,30 @@
99
#include "config/bitcoin-config.h"
1010
#endif
1111

12+
#include <QLabel>
1213
#include <QMainWindow>
1314
#include <QMap>
15+
#include <QMenu>
16+
#include <QPoint>
1417
#include <QSystemTrayIcon>
1518

1619
class ClientModel;
1720
class Notificator;
21+
class OptionsModel;
1822
class RPCConsole;
1923
class SendCoinsRecipient;
2024
class WalletFrame;
2125
class WalletModel;
2226

2327
class CWallet;
2428

29+
class UnitDisplayStatusBarControl;
30+
2531
QT_BEGIN_NAMESPACE
2632
class QAction;
2733
class QLabel;
34+
class QMenu;
35+
class QPoint;
2836
class QProgressBar;
2937
class QProgressDialog;
3038
QT_END_NAMESPACE
@@ -69,6 +77,7 @@ class BitcoinGUI : public QMainWindow
6977
ClientModel *clientModel;
7078
WalletFrame *walletFrame;
7179

80+
UnitDisplayStatusBarControl *unitDisplayControl;
7281
QLabel *labelEncryptionIcon;
7382
QLabel *labelConnectionsIcon;
7483
QLabel *labelBlocksIcon;
@@ -198,4 +207,32 @@ private slots:
198207
void showProgress(const QString &title, int nProgress);
199208
};
200209

210+
class UnitDisplayStatusBarControl : public QLabel
211+
{
212+
Q_OBJECT
213+
214+
public:
215+
explicit UnitDisplayStatusBarControl();
216+
/** Lets the control know about the Options Model (and its signals) */
217+
void setOptionsModel(OptionsModel *optionsModel);
218+
219+
protected:
220+
/** So that it responds to left-button clicks */
221+
void mousePressEvent(QMouseEvent *event);
222+
223+
private:
224+
OptionsModel *optionsModel;
225+
QMenu* menu;
226+
/** Shows context menu with Display Unit options by the mouse coordinates */
227+
void onDisplayUnitsClicked(const QPoint& point);
228+
/** Creates context menu, its actions, and wires up all the relevant signals for mouse events. */
229+
void createContextMenu();
230+
231+
private slots:
232+
/** When Display Units are changed on OptionsModel it will refresh the display text of the control on the status bar */
233+
void updateDisplayUnit(int newUnits);
234+
/** Tells underlying optionsModel to update its current display unit. */
235+
void onMenuSelection(QAction* action);
236+
};
237+
201238
#endif // BITCOINGUI_H

src/qt/bitcoinunits.cpp

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -169,6 +169,16 @@ bool BitcoinUnits::parse(int unit, const QString &value, qint64 *val_out)
169169
return ok;
170170
}
171171

172+
QString BitcoinUnits::getAmountColumnTitle(int unit)
173+
{
174+
QString amountTitle = QObject::tr("Amount");
175+
if (BitcoinUnits::valid(unit))
176+
{
177+
amountTitle += " ("+BitcoinUnits::name(unit) + ")";
178+
}
179+
return amountTitle;
180+
}
181+
172182
int BitcoinUnits::rowCount(const QModelIndex &parent) const
173183
{
174184
Q_UNUSED(parent);

src/qt/bitcoinunits.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -54,6 +54,8 @@ class BitcoinUnits: public QAbstractListModel
5454
static QString formatWithUnit(int unit, qint64 amount, bool plussign=false);
5555
//! Parse string to coin amount
5656
static bool parse(int unit, const QString &value, qint64 *val_out);
57+
//! Gets title for amount column including current display unit if optionsModel reference available */
58+
static QString getAmountColumnTitle(int unit);
5759
///@}
5860

5961
//! @name AbstractListModel implementation

src/qt/optionsmodel.cpp

Lines changed: 14 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -308,9 +308,7 @@ bool OptionsModel::setData(const QModelIndex & index, const QVariant & value, in
308308
break;
309309
#endif
310310
case DisplayUnit:
311-
nDisplayUnit = value.toInt();
312-
settings.setValue("nDisplayUnit", nDisplayUnit);
313-
emit displayUnitChanged(nDisplayUnit);
311+
setDisplayUnit(value);
314312
break;
315313
case DisplayAddresses:
316314
bDisplayAddresses = value.toBool();
@@ -356,11 +354,24 @@ bool OptionsModel::setData(const QModelIndex & index, const QVariant & value, in
356354
break;
357355
}
358356
}
357+
359358
emit dataChanged(index, index);
360359

361360
return successful;
362361
}
363362

363+
/** Updates current unit in memory, settings and emits displayUnitChanged(newUnit) signal */
364+
void OptionsModel::setDisplayUnit(const QVariant &value)
365+
{
366+
if (!value.isNull())
367+
{
368+
QSettings settings;
369+
nDisplayUnit = value.toInt();
370+
settings.setValue("nDisplayUnit", nDisplayUnit);
371+
emit displayUnitChanged(nDisplayUnit);
372+
}
373+
}
374+
364375
bool OptionsModel::getProxySettings(QNetworkProxy& proxy) const
365376
{
366377
// Directly query current base proxy, because

src/qt/optionsmodel.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -52,6 +52,8 @@ class OptionsModel : public QAbstractListModel
5252
int rowCount(const QModelIndex & parent = QModelIndex()) const;
5353
QVariant data(const QModelIndex & index, int role = Qt::DisplayRole) const;
5454
bool setData(const QModelIndex & index, const QVariant & value, int role = Qt::EditRole);
55+
/** Updates current unit in memory, settings and emits displayUnitChanged(newUnit) signal */
56+
void setDisplayUnit(const QVariant &value);
5557

5658
/* Explicit getters */
5759
bool getMinimizeToTray() { return fMinimizeToTray; }

src/qt/recentrequeststablemodel.cpp

Lines changed: 26 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -21,7 +21,9 @@ RecentRequestsTableModel::RecentRequestsTableModel(CWallet *wallet, WalletModel
2121
addNewRequest(request);
2222

2323
/* These columns must match the indices in the ColumnIndex enumeration */
24-
columns << tr("Date") << tr("Label") << tr("Message") << tr("Amount");
24+
columns << tr("Date") << tr("Label") << tr("Message") << getAmountTitle();
25+
26+
connect(walletModel->getOptionsModel(), SIGNAL(displayUnitChanged(int)), this, SLOT(updateDisplayUnit()));
2527
}
2628

2729
RecentRequestsTableModel::~RecentRequestsTableModel()
@@ -101,6 +103,24 @@ QVariant RecentRequestsTableModel::headerData(int section, Qt::Orientation orien
101103
return QVariant();
102104
}
103105

106+
/** Updates the column title to "Amount (DisplayUnit)" and emits headerDataChanged() signal for table headers to react. */
107+
void RecentRequestsTableModel::updateAmountColumnTitle()
108+
{
109+
columns[Amount] = getAmountTitle();
110+
emit headerDataChanged(Qt::Horizontal,Amount,Amount);
111+
}
112+
113+
/** Gets title for amount column including current display unit if optionsModel reference available. */
114+
QString RecentRequestsTableModel::getAmountTitle()
115+
{
116+
QString amountTitle = tr("Amount");
117+
if (this->walletModel->getOptionsModel() != NULL)
118+
{
119+
amountTitle += " ("+BitcoinUnits::name(this->walletModel->getOptionsModel()->getDisplayUnit()) + ")";
120+
}
121+
return amountTitle;
122+
}
123+
104124
QModelIndex RecentRequestsTableModel::index(int row, int column, const QModelIndex &parent) const
105125
{
106126
Q_UNUSED(parent);
@@ -185,6 +205,11 @@ void RecentRequestsTableModel::sort(int column, Qt::SortOrder order)
185205
emit dataChanged(index(0, 0, QModelIndex()), index(list.size() - 1, NUMBER_OF_COLUMNS - 1, QModelIndex()));
186206
}
187207

208+
void RecentRequestsTableModel::updateDisplayUnit()
209+
{
210+
updateAmountColumnTitle();
211+
}
212+
188213
bool RecentRequestEntryLessThan::operator()(RecentRequestEntry &left, RecentRequestEntry &right) const
189214
{
190215
RecentRequestEntry *pLeft = &left;

src/qt/recentrequeststablemodel.h

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -91,12 +91,18 @@ class RecentRequestsTableModel: public QAbstractTableModel
9191

9292
public slots:
9393
void sort(int column, Qt::SortOrder order = Qt::AscendingOrder);
94+
void updateDisplayUnit();
9495

9596
private:
9697
WalletModel *walletModel;
9798
QStringList columns;
9899
QList<RecentRequestEntry> list;
99100
int64_t nReceiveRequestsMaxId;
101+
102+
/** Updates the column title to "Amount (DisplayUnit)" and emits headerDataChanged() signal for table headers to react. */
103+
void updateAmountColumnTitle();
104+
/** Gets title for amount column including current display unit if optionsModel reference available. */
105+
QString getAmountTitle();
100106
};
101107

102108
#endif

src/qt/transactiontablemodel.cpp

Lines changed: 9 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -235,8 +235,7 @@ TransactionTableModel::TransactionTableModel(CWallet* wallet, WalletModel *paren
235235
walletModel(parent),
236236
priv(new TransactionTablePriv(wallet, this))
237237
{
238-
columns << QString() << tr("Date") << tr("Type") << tr("Address") << tr("Amount");
239-
238+
columns << QString() << tr("Date") << tr("Type") << tr("Address") << BitcoinUnits::getAmountColumnTitle(walletModel->getOptionsModel()->getDisplayUnit());
240239
priv->refreshWallet();
241240

242241
connect(walletModel->getOptionsModel(), SIGNAL(displayUnitChanged(int)), this, SLOT(updateDisplayUnit()));
@@ -247,6 +246,13 @@ TransactionTableModel::~TransactionTableModel()
247246
delete priv;
248247
}
249248

249+
/** Updates the column title to "Amount (DisplayUnit)" and emits headerDataChanged() signal for table headers to react. */
250+
void TransactionTableModel::updateAmountColumnTitle()
251+
{
252+
columns[Amount] = BitcoinUnits::getAmountColumnTitle(walletModel->getOptionsModel()->getDisplayUnit());
253+
emit headerDataChanged(Qt::Horizontal,Amount,Amount);
254+
}
255+
250256
void TransactionTableModel::updateTransaction(const QString &hash, int status)
251257
{
252258
uint256 updated;
@@ -624,5 +630,6 @@ QModelIndex TransactionTableModel::index(int row, int column, const QModelIndex
624630
void TransactionTableModel::updateDisplayUnit()
625631
{
626632
// emit dataChanged to update Amount column with the current unit
633+
updateAmountColumnTitle();
627634
emit dataChanged(index(0, Amount), index(priv->size()-1, Amount));
628635
}

src/qt/transactiontablemodel.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -87,6 +87,8 @@ public slots:
8787
void updateTransaction(const QString &hash, int status);
8888
void updateConfirmations();
8989
void updateDisplayUnit();
90+
/** Updates the column title to "Amount (DisplayUnit)" and emits headerDataChanged() signal for table headers to react. */
91+
void updateAmountColumnTitle();
9092

9193
friend class TransactionTablePriv;
9294
};

0 commit comments

Comments
 (0)