Bitcoin Core 22.99.0
P2P Digital Currency
overviewpage.cpp
Go to the documentation of this file.
1// Copyright (c) 2011-2020 The Bitcoin Core developers
2// Distributed under the MIT software license, see the accompanying
3// file COPYING or http://www.opensource.org/licenses/mit-license.php.
4
5#include <qt/overviewpage.h>
7
8#include <qt/bitcoinunits.h>
9#include <qt/clientmodel.h>
10#include <qt/guiconstants.h>
11#include <qt/guiutil.h>
12#include <qt/optionsmodel.h>
13#include <qt/platformstyle.h>
17#include <qt/walletmodel.h>
18
19#include <QAbstractItemDelegate>
20#include <QApplication>
21#include <QDateTime>
22#include <QPainter>
23#include <QStatusTipEvent>
24
25#include <algorithm>
26#include <map>
27
28#define DECORATION_SIZE 54
29#define NUM_ITEMS 5
30
31Q_DECLARE_METATYPE(interfaces::WalletBalances)
32
33class TxViewDelegate : public QAbstractItemDelegate
34{
35 Q_OBJECT
36public:
37 explicit TxViewDelegate(const PlatformStyle *_platformStyle, QObject *parent=nullptr):
38 QAbstractItemDelegate(parent), unit(BitcoinUnits::BTC),
39 platformStyle(_platformStyle)
40 {
41 connect(this, &TxViewDelegate::width_changed, this, &TxViewDelegate::sizeHintChanged);
42 }
43
44 inline void paint(QPainter *painter, const QStyleOptionViewItem &option,
45 const QModelIndex &index ) const override
46 {
47 painter->save();
48
49 QIcon icon = qvariant_cast<QIcon>(index.data(TransactionTableModel::RawDecorationRole));
50 QRect mainRect = option.rect;
51 QRect decorationRect(mainRect.topLeft(), QSize(DECORATION_SIZE, DECORATION_SIZE));
52 int xspace = DECORATION_SIZE + 8;
53 int ypad = 6;
54 int halfheight = (mainRect.height() - 2*ypad)/2;
55 QRect amountRect(mainRect.left() + xspace, mainRect.top()+ypad, mainRect.width() - xspace, halfheight);
56 QRect addressRect(mainRect.left() + xspace, mainRect.top()+ypad+halfheight, mainRect.width() - xspace, halfheight);
57 icon = platformStyle->SingleColorIcon(icon);
58 icon.paint(painter, decorationRect);
59
60 QDateTime date = index.data(TransactionTableModel::DateRole).toDateTime();
61 QString address = index.data(Qt::DisplayRole).toString();
62 qint64 amount = index.data(TransactionTableModel::AmountRole).toLongLong();
63 bool confirmed = index.data(TransactionTableModel::ConfirmedRole).toBool();
64 QVariant value = index.data(Qt::ForegroundRole);
65 QColor foreground = option.palette.color(QPalette::Text);
66 if(value.canConvert<QBrush>())
67 {
68 QBrush brush = qvariant_cast<QBrush>(value);
69 foreground = brush.color();
70 }
71
72 if (index.data(TransactionTableModel::WatchonlyRole).toBool()) {
73 QIcon iconWatchonly = qvariant_cast<QIcon>(index.data(TransactionTableModel::WatchonlyDecorationRole));
74 QRect watchonlyRect(addressRect.left(), addressRect.top(), 16, addressRect.height());
75 iconWatchonly = platformStyle->TextColorIcon(iconWatchonly);
76 iconWatchonly.paint(painter, watchonlyRect);
77 addressRect.setLeft(addressRect.left() + watchonlyRect.width() + 5);
78 }
79
80 painter->setPen(foreground);
81 QRect boundingRect;
82 painter->drawText(addressRect, Qt::AlignLeft | Qt::AlignVCenter, address, &boundingRect);
83
84 if(amount < 0)
85 {
86 foreground = COLOR_NEGATIVE;
87 }
88 else if(!confirmed)
89 {
90 foreground = COLOR_UNCONFIRMED;
91 }
92 else
93 {
94 foreground = option.palette.color(QPalette::Text);
95 }
96 painter->setPen(foreground);
97 QString amountText = BitcoinUnits::formatWithUnit(unit, amount, true, BitcoinUnits::SeparatorStyle::ALWAYS);
98 if(!confirmed)
99 {
100 amountText = QString("[") + amountText + QString("]");
101 }
102
103 QRect amount_bounding_rect;
104 painter->drawText(amountRect, Qt::AlignRight | Qt::AlignVCenter, amountText, &amount_bounding_rect);
105
106 painter->setPen(option.palette.color(QPalette::Text));
107 QRect date_bounding_rect;
108 painter->drawText(amountRect, Qt::AlignLeft | Qt::AlignVCenter, GUIUtil::dateTimeStr(date), &date_bounding_rect);
109
110 // 0.4*date_bounding_rect.width() is used to visually distinguish a date from an amount.
111 const int minimum_width = 1.4 * date_bounding_rect.width() + amount_bounding_rect.width();
112 const auto search = m_minimum_width.find(index.row());
113 if (search == m_minimum_width.end() || search->second != minimum_width) {
114 m_minimum_width[index.row()] = minimum_width;
115 Q_EMIT width_changed(index);
116 }
117
118 painter->restore();
119 }
120
121 inline QSize sizeHint(const QStyleOptionViewItem &option, const QModelIndex &index) const override
122 {
123 const auto search = m_minimum_width.find(index.row());
124 const int minimum_text_width = search == m_minimum_width.end() ? 0 : search->second;
125 return {DECORATION_SIZE + 8 + minimum_text_width, DECORATION_SIZE};
126 }
127
128 int unit;
129
130Q_SIGNALS:
132 void width_changed(const QModelIndex& index) const;
133
134private:
136 mutable std::map<int, int> m_minimum_width;
137};
138
139#include <qt/overviewpage.moc>
140
141OverviewPage::OverviewPage(const PlatformStyle *platformStyle, QWidget *parent) :
142 QWidget(parent),
143 ui(new Ui::OverviewPage),
144 clientModel(nullptr),
145 walletModel(nullptr),
146 m_platform_style{platformStyle},
147 txdelegate(new TxViewDelegate(platformStyle, this))
148{
149 ui->setupUi(this);
150
151 m_balances.balance = -1;
152
153 // use a SingleColorIcon for the "out of sync warning" icon
154 QIcon icon = m_platform_style->SingleColorIcon(QStringLiteral(":/icons/warning"));
155 ui->labelTransactionsStatus->setIcon(icon);
156 ui->labelWalletStatus->setIcon(icon);
157
158 // Recent transactions
159 ui->listTransactions->setItemDelegate(txdelegate);
160 ui->listTransactions->setIconSize(QSize(DECORATION_SIZE, DECORATION_SIZE));
161 ui->listTransactions->setMinimumHeight(NUM_ITEMS * (DECORATION_SIZE + 2));
162 ui->listTransactions->setAttribute(Qt::WA_MacShowFocusRect, false);
163
164 connect(ui->listTransactions, &TransactionOverviewWidget::clicked, this, &OverviewPage::handleTransactionClicked);
165
166 // start with displaying the "out of sync" warnings
168 connect(ui->labelWalletStatus, &QPushButton::clicked, this, &OverviewPage::outOfSyncWarningClicked);
169 connect(ui->labelTransactionsStatus, &QPushButton::clicked, this, &OverviewPage::outOfSyncWarningClicked);
170}
171
172void OverviewPage::handleTransactionClicked(const QModelIndex &index)
173{
174 if(filter)
175 Q_EMIT transactionClicked(filter->mapToSource(index));
176}
177
178void OverviewPage::setPrivacy(bool privacy)
179{
180 m_privacy = privacy;
181 if (m_balances.balance != -1) {
183 }
184
185 ui->listTransactions->setVisible(!m_privacy);
186
187 const QString status_tip = m_privacy ? tr("Privacy mode activated for the Overview tab. To unmask the values, uncheck Settings->Mask values.") : "";
188 setStatusTip(status_tip);
189 QStatusTipEvent event(status_tip);
190 QApplication::sendEvent(this, &event);
191}
192
194{
195 delete ui;
196}
197
199{
201 m_balances = balances;
202 if (walletModel->wallet().isLegacy()) {
208 } else {
217 }
218 } else {
223 }
224 // only show immature (newly mined) balance if it's non-zero, so as not to complicate things
225 // for the non-mining users
226 bool showImmature = balances.immature_balance != 0;
227 bool showWatchOnlyImmature = balances.immature_watch_only_balance != 0;
228
229 // for symmetry reasons also show immature label when the watch-only one is shown
230 ui->labelImmature->setVisible(showImmature || showWatchOnlyImmature);
231 ui->labelImmatureText->setVisible(showImmature || showWatchOnlyImmature);
232 ui->labelWatchImmature->setVisible(!walletModel->wallet().privateKeysDisabled() && showWatchOnlyImmature); // show watch-only immature balance
233}
234
235// show/hide watch-only labels
237{
238 ui->labelSpendable->setVisible(showWatchOnly); // show spendable label (only when watch-only is active)
239 ui->labelWatchonly->setVisible(showWatchOnly); // show watch-only label
240 ui->lineWatchBalance->setVisible(showWatchOnly); // show watch-only balance separator line
241 ui->labelWatchAvailable->setVisible(showWatchOnly); // show watch-only available balance
242 ui->labelWatchPending->setVisible(showWatchOnly); // show watch-only pending balance
243 ui->labelWatchTotal->setVisible(showWatchOnly); // show watch-only total balance
244
245 if (!showWatchOnly)
246 ui->labelWatchImmature->hide();
247}
248
250{
251 this->clientModel = model;
252 if (model) {
253 // Show warning, for example if this is a prerelease version
256
259 }
260}
261
263{
264 this->walletModel = model;
265 if(model && model->getOptionsModel())
266 {
267 // Set up transaction list
268 filter.reset(new TransactionFilterProxy());
269 filter->setSourceModel(model->getTransactionTableModel());
270 filter->setLimit(NUM_ITEMS);
271 filter->setDynamicSortFilter(true);
272 filter->setSortRole(Qt::EditRole);
273 filter->setShowInactive(false);
274 filter->sort(TransactionTableModel::Date, Qt::DescendingOrder);
275
276 ui->listTransactions->setModel(filter.get());
278
279 // Keep up to date with wallet
280 interfaces::Wallet& wallet = model->wallet();
281 interfaces::WalletBalances balances = wallet.getBalances();
282 setBalance(balances);
284
286
287 updateWatchOnlyLabels(wallet.haveWatchOnly() && !model->wallet().privateKeysDisabled());
288 connect(model, &WalletModel::notifyWatchonlyChanged, [this](bool showWatchOnly) {
290 });
291 }
292
293 // update the display unit, to not use the default ("BTC")
295}
296
298{
299 if (e->type() == QEvent::PaletteChange) {
300 QIcon icon = m_platform_style->SingleColorIcon(QStringLiteral(":/icons/warning"));
301 ui->labelTransactionsStatus->setIcon(icon);
302 ui->labelWalletStatus->setIcon(icon);
303 }
304
305 QWidget::changeEvent(e);
306}
307
309{
311 {
312 if (m_balances.balance != -1) {
314 }
315
316 // Update txdelegate->unit with the current unit
318
319 ui->listTransactions->update();
320 }
321}
322
323void OverviewPage::updateAlerts(const QString &warnings)
324{
325 this->ui->labelAlerts->setVisible(!warnings.isEmpty());
326 this->ui->labelAlerts->setText(warnings);
327}
328
330{
331 ui->labelWalletStatus->setVisible(fShow);
332 ui->labelTransactionsStatus->setVisible(fShow);
333}
334
335void OverviewPage::setMonospacedFont(bool use_embedded_font)
336{
337 QFont f = GUIUtil::fixedPitchFont(use_embedded_font);
338 f.setWeight(QFont::Bold);
339 ui->labelBalance->setFont(f);
340 ui->labelUnconfirmed->setFont(f);
341 ui->labelImmature->setFont(f);
342 ui->labelTotal->setFont(f);
343 ui->labelWatchAvailable->setFont(f);
344 ui->labelWatchPending->setFont(f);
345 ui->labelWatchImmature->setFont(f);
346 ui->labelWatchTotal->setFont(f);
347}
Bitcoin unit definitions.
Definition: bitcoinunits.h:32
static QString formatWithPrivacy(int unit, const CAmount &amount, SeparatorStyle separators, bool privacy)
Format as string (with unit) of fixed length to preserve privacy, if it is set.
static QString formatWithUnit(int unit, const CAmount &amount, bool plussign=false, SeparatorStyle separators=SeparatorStyle::STANDARD)
Format as string (with unit)
Model for Bitcoin network client.
Definition: clientmodel.h:48
QString getStatusBarWarnings() const
Return warnings to be displayed in status bar.
void alertsChanged(const QString &warnings)
OptionsModel * getOptionsModel()
int getDisplayUnit() const
Definition: optionsmodel.h:88
bool getUseEmbeddedMonospacedFont() const
Definition: optionsmodel.h:90
void displayUnitChanged(int unit)
void useEmbeddedMonospacedFontChanged(bool)
Overview ("home") page widget.
Definition: overviewpage.h:29
void updateDisplayUnit()
const PlatformStyle * m_platform_style
Definition: overviewpage.h:58
interfaces::WalletBalances m_balances
Definition: overviewpage.h:55
void setWalletModel(WalletModel *walletModel)
void updateAlerts(const QString &warnings)
void updateWatchOnlyLabels(bool showWatchOnly)
void setClientModel(ClientModel *clientModel)
WalletModel * walletModel
Definition: overviewpage.h:54
void setMonospacedFont(bool use_embedded_font)
Ui::OverviewPage * ui
Definition: overviewpage.h:52
void handleTransactionClicked(const QModelIndex &index)
void changeEvent(QEvent *e) override
void transactionClicked(const QModelIndex &index)
OverviewPage(const PlatformStyle *platformStyle, QWidget *parent=nullptr)
std::unique_ptr< TransactionFilterProxy > filter
Definition: overviewpage.h:61
void outOfSyncWarningClicked()
void showOutOfSyncWarning(bool fShow)
ClientModel * clientModel
Definition: overviewpage.h:53
void setBalance(const interfaces::WalletBalances &balances)
TxViewDelegate * txdelegate
Definition: overviewpage.h:60
void setPrivacy(bool privacy)
QIcon SingleColorIcon(const QString &filename) const
Colorize an icon (given filename) with the icon color.
Filter the transaction list according to pre-specified rules.
@ DateRole
Date and time this transaction was created.
@ RawDecorationRole
Unprocessed icon.
@ WatchonlyDecorationRole
Watch-only icon.
@ WatchonlyRole
Watch-only boolean.
@ AmountRole
Net amount of transaction.
@ ConfirmedRole
Is transaction confirmed?
TxViewDelegate(const PlatformStyle *_platformStyle, QObject *parent=nullptr)
std::map< int, int > m_minimum_width
void width_changed(const QModelIndex &index) const
An intermediate signal for emitting from the paint() const member function.
QSize sizeHint(const QStyleOptionViewItem &option, const QModelIndex &index) const override
const PlatformStyle * platformStyle
void paint(QPainter *painter, const QStyleOptionViewItem &option, const QModelIndex &index) const override
QLabel * labelWatchImmature
QPushButton * labelWalletStatus
QFrame * lineWatchBalance
QLabel * labelAlerts
QLabel * labelWatchonly
QLabel * labelBalance
QLabel * labelUnconfirmed
QLabel * labelImmature
QLabel * labelWatchAvailable
QLabel * labelSpendable
QLabel * labelWatchPending
QLabel * labelImmatureText
void setupUi(QWidget *OverviewPage)
QLabel * labelWatchTotal
QPushButton * labelTransactionsStatus
TransactionOverviewWidget * listTransactions
Interface to Bitcoin wallet from Qt view code.
Definition: walletmodel.h:52
void notifyWatchonlyChanged(bool fHaveWatchonly)
OptionsModel * getOptionsModel()
interfaces::Wallet & wallet() const
Definition: walletmodel.h:144
void balanceChanged(const interfaces::WalletBalances &balances)
TransactionTableModel * getTransactionTableModel()
Interface for accessing a wallet.
Definition: wallet.h:53
virtual bool isLegacy()=0
Return whether is a legacy wallet.
virtual bool privateKeysDisabled()=0
#define COLOR_UNCONFIRMED
Definition: guiconstants.h:25
#define COLOR_NEGATIVE
Definition: guiconstants.h:27
QFont fixedPitchFont(bool use_embedded_font)
Definition: guiutil.cpp:88
QString dateTimeStr(const QDateTime &date)
Definition: guiutil.cpp:78
#define DECORATION_SIZE
#define NUM_ITEMS
Collection of wallet balances.
Definition: wallet.h:356
CAmount unconfirmed_watch_only_balance
Definition: wallet.h:362
CAmount immature_watch_only_balance
Definition: wallet.h:363