Bitcoin ABC 0.30.5
P2P Digital Currency
overviewpage.cpp
Go to the documentation of this file.
1// Copyright (c) 2011-2016 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/forms/ui_overviewpage.h>
6#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>
16#include <qt/walletmodel.h>
17
18#include <QAbstractItemDelegate>
19#include <QApplication>
20#include <QPainter>
21#include <QStatusTipEvent>
22
23#define DECORATION_SIZE 54
24#define NUM_ITEMS 5
25
26Q_DECLARE_METATYPE(interfaces::WalletBalances)
27
28class TxViewDelegate : public QAbstractItemDelegate {
29 Q_OBJECT
30public:
31 explicit TxViewDelegate(const PlatformStyle *_platformStyle,
32 QObject *parent = nullptr)
33 : QAbstractItemDelegate(parent), unit(BitcoinUnits::base),
34 platformStyle(_platformStyle) {}
35
36 inline void paint(QPainter *painter, const QStyleOptionViewItem &option,
37 const QModelIndex &index) const override {
38 painter->save();
39
40 QIcon icon = qvariant_cast<QIcon>(
42 QRect mainRect = option.rect;
43 QRect decorationRect(mainRect.topLeft(),
45 int xspace = DECORATION_SIZE + 8;
46 int ypad = 6;
47 int halfheight = (mainRect.height() - 2 * ypad) / 2;
48 QRect amountRect(mainRect.left() + xspace, mainRect.top() + ypad,
49 mainRect.width() - xspace, halfheight);
50 QRect addressRect(mainRect.left() + xspace,
51 mainRect.top() + ypad + halfheight,
52 mainRect.width() - xspace, halfheight);
53 icon = platformStyle->SingleColorIcon(icon);
54 icon.paint(painter, decorationRect);
55
56 QDateTime date =
57 index.data(TransactionTableModel::DateRole).toDateTime();
58 QString address = index.data(Qt::DisplayRole).toString();
59 Amount amount(
60 int64_t(
61 index.data(TransactionTableModel::AmountRole).toLongLong()) *
62 SATOSHI);
63 bool confirmed =
64 index.data(TransactionTableModel::ConfirmedRole).toBool();
65 QVariant value = index.data(Qt::ForegroundRole);
66 QColor foreground = option.palette.color(QPalette::Text);
67 if (value.canConvert<QBrush>()) {
68 QBrush brush = qvariant_cast<QBrush>(value);
69 foreground = brush.color();
70 }
71
72 painter->setPen(foreground);
73 QRect boundingRect;
74 painter->drawText(addressRect, Qt::AlignLeft | Qt::AlignVCenter,
75 address, &boundingRect);
76
77 if (index.data(TransactionTableModel::WatchonlyRole).toBool()) {
78 QIcon iconWatchonly = qvariant_cast<QIcon>(
80 QRect watchonlyRect(boundingRect.right() + 5,
81 mainRect.top() + ypad + halfheight, 16,
82 halfheight);
83 iconWatchonly.paint(painter, watchonlyRect);
84 }
85
86 if (amount < Amount::zero()) {
87 foreground = COLOR_NEGATIVE;
88 } else if (!confirmed) {
89 foreground = COLOR_UNCONFIRMED;
90 } else {
91 foreground = option.palette.color(QPalette::Text);
92 }
93 painter->setPen(foreground);
94 QString amountText = BitcoinUnits::formatWithUnit(
95 unit, amount, true, BitcoinUnits::SeparatorStyle::ALWAYS);
96 if (!confirmed) {
97 amountText = QString("[") + amountText + QString("]");
98 }
99 painter->drawText(amountRect, Qt::AlignRight | Qt::AlignVCenter,
100 amountText);
101
102 painter->setPen(option.palette.color(QPalette::Text));
103 painter->drawText(amountRect, Qt::AlignLeft | Qt::AlignVCenter,
105
106 painter->restore();
107 }
108
109 inline QSize sizeHint(const QStyleOptionViewItem &option,
110 const QModelIndex &index) const override {
111 return QSize(DECORATION_SIZE, DECORATION_SIZE);
112 }
113
114 int unit;
116};
117#include <qt/overviewpage.moc>
118
119OverviewPage::OverviewPage(const PlatformStyle *platformStyle, QWidget *parent)
120 : QWidget(parent), ui(new Ui::OverviewPage), clientModel(nullptr),
121 walletModel(nullptr),
122 txdelegate(new TxViewDelegate(platformStyle, this)) {
123 ui->setupUi(this);
124
126
127 // use a SingleColorIcon for the "out of sync warning" icon
128 QIcon icon = platformStyle->SingleColorIcon(":/icons/warning");
129 // also set the disabled icon because we are using a disabled QPushButton to
130 // work around missing HiDPI support of QLabel
131 // (https://bugreports.qt.io/browse/QTBUG-42503)
132 icon.addPixmap(icon.pixmap(QSize(64, 64), QIcon::Normal), QIcon::Disabled);
133 ui->labelTransactionsStatus->setIcon(icon);
134 ui->labelWalletStatus->setIcon(icon);
135
136 // Recent transactions
137 ui->listTransactions->setItemDelegate(txdelegate);
138 ui->listTransactions->setIconSize(QSize(DECORATION_SIZE, DECORATION_SIZE));
139 ui->listTransactions->setMinimumHeight(NUM_ITEMS * (DECORATION_SIZE + 2));
140 ui->listTransactions->setAttribute(Qt::WA_MacShowFocusRect, false);
141
142 connect(ui->listTransactions, &QListView::clicked, this,
144
145 // start with displaying the "out of sync" warnings
147 connect(ui->labelWalletStatus, &QPushButton::clicked, this,
149 connect(ui->labelTransactionsStatus, &QPushButton::clicked, this,
151}
152
153void OverviewPage::handleTransactionClicked(const QModelIndex &index) {
154 if (filter) {
155 Q_EMIT transactionClicked(filter->mapToSource(index));
156 }
157}
158
161}
162
163void OverviewPage::setPrivacy(bool privacy) {
164 m_privacy = privacy;
167 }
168
169 ui->listTransactions->setVisible(!m_privacy);
170
171 const QString status_tip =
172 m_privacy ? tr("Privacy mode activated for the Overview tab. To unmask "
173 "the values, uncheck Settings->Mask values.")
174 : "";
175 setStatusTip(status_tip);
176 QStatusTipEvent event(status_tip);
177 QApplication::sendEvent(this, &event);
178}
179
181 delete ui;
182}
183
186 m_balances = balances;
187 if (walletModel->wallet().isLegacy()) {
189 ui->labelBalance->setText(BitcoinUnits::formatWithPrivacy(
190 unit, balances.watch_only_balance,
192 ui->labelUnconfirmed->setText(BitcoinUnits::formatWithPrivacy(
193 unit, balances.unconfirmed_watch_only_balance,
195 ui->labelImmature->setText(BitcoinUnits::formatWithPrivacy(
196 unit, balances.immature_watch_only_balance,
198 ui->labelTotal->setText(BitcoinUnits::formatWithPrivacy(
199 unit,
200 balances.watch_only_balance +
204 } else {
205 ui->labelBalance->setText(BitcoinUnits::formatWithPrivacy(
207 m_privacy));
208 ui->labelUnconfirmed->setText(BitcoinUnits::formatWithPrivacy(
209 unit, balances.unconfirmed_balance,
211 ui->labelImmature->setText(BitcoinUnits::formatWithPrivacy(
212 unit, balances.immature_balance,
214 ui->labelTotal->setText(BitcoinUnits::formatWithPrivacy(
215 unit,
216 balances.balance + balances.unconfirmed_balance +
217 balances.immature_balance,
219 ui->labelWatchAvailable->setText(BitcoinUnits::formatWithPrivacy(
220 unit, balances.watch_only_balance,
222 ui->labelWatchPending->setText(BitcoinUnits::formatWithPrivacy(
223 unit, balances.unconfirmed_watch_only_balance,
225 ui->labelWatchImmature->setText(BitcoinUnits::formatWithPrivacy(
226 unit, balances.immature_watch_only_balance,
228 ui->labelWatchTotal->setText(BitcoinUnits::formatWithPrivacy(
229 unit,
230 balances.watch_only_balance +
234 }
235 } else {
236 ui->labelBalance->setText(BitcoinUnits::formatWithPrivacy(
238 m_privacy));
239 ui->labelUnconfirmed->setText(BitcoinUnits::formatWithPrivacy(
240 unit, balances.unconfirmed_balance,
242 ui->labelImmature->setText(BitcoinUnits::formatWithPrivacy(
243 unit, balances.immature_balance,
245 ui->labelTotal->setText(BitcoinUnits::formatWithPrivacy(
246 unit,
247 balances.balance + balances.unconfirmed_balance +
248 balances.immature_balance,
250 }
251
252 // only show immature (newly mined) balance if it's non-zero, so as not to
253 // complicate things for the non-mining users
254 bool showImmature = balances.immature_balance != Amount::zero();
255 bool showWatchOnlyImmature =
257
258 // for symmetry reasons also show immature label when the watch-only one is
259 // shown
260 ui->labelImmature->setVisible(showImmature || showWatchOnlyImmature);
261 ui->labelImmatureText->setVisible(showImmature || showWatchOnlyImmature);
262 // show watch-only immature balance
263 ui->labelWatchImmature->setVisible(
264 !walletModel->wallet().privateKeysDisabled() && showWatchOnlyImmature);
265}
266
267// show/hide watch-only labels
268void OverviewPage::updateWatchOnlyLabels(bool showWatchOnly) {
269 // show spendable label (only when watch-only is active)
270 ui->labelSpendable->setVisible(showWatchOnly);
271 // show watch-only label
272 ui->labelWatchonly->setVisible(showWatchOnly);
273 // show watch-only balance separator line
274 ui->lineWatchBalance->setVisible(showWatchOnly);
275 // show watch-only available balance
276 ui->labelWatchAvailable->setVisible(showWatchOnly);
277 // show watch-only pending balance
278 ui->labelWatchPending->setVisible(showWatchOnly);
279 // show watch-only total balance
280 ui->labelWatchTotal->setVisible(showWatchOnly);
281
282 if (!showWatchOnly) {
283 ui->labelWatchImmature->hide();
284 }
285}
286
288 this->clientModel = model;
289 if (model) {
290 // Show warning, for example if this is a prerelease version
291 connect(model, &ClientModel::alertsChanged, this,
294 }
295}
296
298 this->walletModel = model;
299 if (model && model->getOptionsModel()) {
300 // Set up transaction list
301 filter.reset(new TransactionFilterProxy());
302 filter->setSourceModel(model->getTransactionTableModel());
303 filter->setLimit(NUM_ITEMS);
304 filter->setDynamicSortFilter(true);
305 filter->setSortRole(Qt::EditRole);
306 filter->setShowInactive(false);
307 filter->sort(TransactionTableModel::Date, Qt::DescendingOrder);
308
309 ui->listTransactions->setModel(filter.get());
310 ui->listTransactions->setModelColumn(TransactionTableModel::ToAddress);
311
312 // Keep up to date with wallet
313 interfaces::Wallet &wallet = model->wallet();
314 interfaces::WalletBalances balances = wallet.getBalances();
315 setBalance(balances);
316 connect(model, &WalletModel::balanceChanged, this,
318
321
322 updateWatchOnlyLabels(wallet.haveWatchOnly() &&
323 !model->wallet().privateKeysDisabled());
325 [this](bool showWatchOnly) {
327 showWatchOnly &&
329 });
330 }
331
332 // update the display unit, to not use the default ("XEC")
334}
335
338 if (m_balances.balance != -SATOSHI) {
340 }
341
342 // Update txdelegate->unit with the current unit
344
345 ui->listTransactions->update();
346 }
347}
348
349void OverviewPage::updateAlerts(const QString &warnings) {
350 this->ui->labelAlerts->setVisible(!warnings.isEmpty());
351 this->ui->labelAlerts->setText(warnings);
352}
353
355 ui->labelWalletStatus->setVisible(fShow);
356 ui->labelTransactionsStatus->setVisible(fShow);
357}
static constexpr Amount SATOSHI
Definition: amount.h:143
Bitcoin unit definitions.
Definition: bitcoinunits.h:32
static QString formatWithUnit(int unit, const Amount amount, bool plussign=false, SeparatorStyle separators=SeparatorStyle::STANDARD)
Format as string (with unit)
static QString formatWithPrivacy(int unit, const Amount &amount, SeparatorStyle separators, bool privacy)
Format as string (with unit) of fixed length to preserve privacy, if it is set.
Model for Bitcoin network client.
Definition: clientmodel.h:43
QString getStatusBarWarnings() const
Return warnings to be displayed in status bar.
void alertsChanged(const QString &warnings)
int getDisplayUnit() const
Definition: optionsmodel.h:97
void displayUnitChanged(int unit)
Overview ("home") page widget.
Definition: overviewpage.h:28
void updateDisplayUnit()
interfaces::WalletBalances m_balances
Definition: overviewpage.h:52
void setWalletModel(WalletModel *walletModel)
void updateAlerts(const QString &warnings)
void updateWatchOnlyLabels(bool showWatchOnly)
void setClientModel(ClientModel *clientModel)
WalletModel * walletModel
Definition: overviewpage.h:51
Ui::OverviewPage * ui
Definition: overviewpage.h:49
void handleTransactionClicked(const QModelIndex &index)
void transactionClicked(const QModelIndex &index)
void handleOutOfSyncWarningClicks()
OverviewPage(const PlatformStyle *platformStyle, QWidget *parent=nullptr)
std::unique_ptr< TransactionFilterProxy > filter
Definition: overviewpage.h:56
void outOfSyncWarningClicked()
void showOutOfSyncWarning(bool fShow)
ClientModel * clientModel
Definition: overviewpage.h:50
void setBalance(const interfaces::WalletBalances &balances)
TxViewDelegate * txdelegate
Definition: overviewpage.h:55
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)
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
Interface to Bitcoin wallet from Qt view code.
Definition: walletmodel.h:47
void notifyWatchonlyChanged(bool fHaveWatchonly)
OptionsModel * getOptionsModel()
interfaces::Wallet & wallet() const
Definition: walletmodel.h:150
void balanceChanged(const interfaces::WalletBalances &balances)
TransactionTableModel * getTransactionTableModel()
Interface for accessing a wallet.
Definition: wallet.h:59
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
QString dateTimeStr(const QDateTime &date)
Definition: guiutil.cpp:78
#define DECORATION_SIZE
#define NUM_ITEMS
Definition: amount.h:19
static constexpr Amount zero() noexcept
Definition: amount.h:32
static constexpr Amount satoshi() noexcept
Definition: amount.h:33
Collection of wallet balances.
Definition: wallet.h:347
Amount immature_watch_only_balance
Definition: wallet.h:354
Amount unconfirmed_watch_only_balance
Definition: wallet.h:353