Bitcoin ABC 0.32.4
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), platformStyle(_platformStyle) {}
34
35 inline void paint(QPainter *painter, const QStyleOptionViewItem &option,
36 const QModelIndex &index) const override {
37 painter->save();
38
39 QIcon icon = qvariant_cast<QIcon>(
41 QRect mainRect = option.rect;
42 QRect decorationRect(mainRect.topLeft(),
44 int xspace = DECORATION_SIZE + 8;
45 int ypad = 6;
46 int halfheight = (mainRect.height() - 2 * ypad) / 2;
47 QRect amountRect(mainRect.left() + xspace, mainRect.top() + ypad,
48 mainRect.width() - xspace, halfheight);
49 QRect addressRect(mainRect.left() + xspace,
50 mainRect.top() + ypad + halfheight,
51 mainRect.width() - xspace, halfheight);
52 icon = platformStyle->SingleColorIcon(icon);
53 icon.paint(painter, decorationRect);
54
55 QDateTime date =
56 index.data(TransactionTableModel::DateRole).toDateTime();
57 QString address = index.data(Qt::DisplayRole).toString();
58 Amount amount(
59 int64_t(
60 index.data(TransactionTableModel::AmountRole).toLongLong()) *
61 SATOSHI);
62 bool confirmed =
63 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 QBrush brush = qvariant_cast<QBrush>(value);
68 foreground = brush.color();
69 }
70
71 painter->setPen(foreground);
72 QRect boundingRect;
73 painter->drawText(addressRect, Qt::AlignLeft | Qt::AlignVCenter,
74 address, &boundingRect);
75
76 if (index.data(TransactionTableModel::WatchonlyRole).toBool()) {
77 QIcon iconWatchonly = qvariant_cast<QIcon>(
79 QRect watchonlyRect(boundingRect.right() + 5,
80 mainRect.top() + ypad + halfheight, 16,
81 halfheight);
82 iconWatchonly.paint(painter, watchonlyRect);
83 }
84
85 if (amount < Amount::zero()) {
86 foreground = COLOR_NEGATIVE;
87 } else if (!confirmed) {
88 foreground = COLOR_UNCONFIRMED;
89 } else {
90 foreground = option.palette.color(QPalette::Text);
91 }
92 painter->setPen(foreground);
93 QString amountText = BitcoinUnits::formatWithUnit(
94 unit, amount, true, BitcoinUnits::SeparatorStyle::ALWAYS);
95 if (!confirmed) {
96 amountText = QString("[") + amountText + QString("]");
97 }
98 painter->drawText(amountRect, Qt::AlignRight | Qt::AlignVCenter,
99 amountText);
100
101 painter->setPen(option.palette.color(QPalette::Text));
102 painter->drawText(amountRect, Qt::AlignLeft | Qt::AlignVCenter,
104
105 painter->restore();
106 }
107
108 inline QSize sizeHint(const QStyleOptionViewItem &option,
109 const QModelIndex &index) const override {
110 return QSize(DECORATION_SIZE, DECORATION_SIZE);
111 }
112
115};
116#include <qt/overviewpage.moc>
117
118OverviewPage::OverviewPage(const PlatformStyle *platformStyle, QWidget *parent)
119 : QWidget(parent), ui(new Ui::OverviewPage), clientModel(nullptr),
120 walletModel(nullptr),
121 txdelegate(new TxViewDelegate(platformStyle, this)) {
122 ui->setupUi(this);
123
125
126 // use a SingleColorIcon for the "out of sync warning" icon
127 QIcon icon = platformStyle->SingleColorIcon(":/icons/warning");
128 // also set the disabled icon because we are using a disabled QPushButton to
129 // work around missing HiDPI support of QLabel
130 // (https://bugreports.qt.io/browse/QTBUG-42503)
131 icon.addPixmap(icon.pixmap(QSize(64, 64), QIcon::Normal), QIcon::Disabled);
132 ui->labelTransactionsStatus->setIcon(icon);
133 ui->labelWalletStatus->setIcon(icon);
134
135 // Recent transactions
136 ui->listTransactions->setItemDelegate(txdelegate);
137 ui->listTransactions->setIconSize(QSize(DECORATION_SIZE, DECORATION_SIZE));
138 ui->listTransactions->setMinimumHeight(NUM_ITEMS * (DECORATION_SIZE + 2));
139 ui->listTransactions->setAttribute(Qt::WA_MacShowFocusRect, false);
140
141 connect(ui->listTransactions, &QListView::clicked, this,
143
144 // start with displaying the "out of sync" warnings
146 connect(ui->labelWalletStatus, &QPushButton::clicked, this,
148 connect(ui->labelTransactionsStatus, &QPushButton::clicked, this,
150}
151
152void OverviewPage::handleTransactionClicked(const QModelIndex &index) {
153 if (filter) {
154 Q_EMIT transactionClicked(filter->mapToSource(index));
155 }
156}
157
160}
161
162void OverviewPage::setPrivacy(bool privacy) {
163 m_privacy = privacy;
166 }
167
168 ui->listTransactions->setVisible(!m_privacy);
169
170 const QString status_tip =
171 m_privacy ? tr("Privacy mode activated for the Overview tab. To unmask "
172 "the values, uncheck Settings->Mask values.")
173 : "";
174 setStatusTip(status_tip);
175 QStatusTipEvent event(status_tip);
176 QApplication::sendEvent(this, &event);
177}
178
180 delete ui;
181}
182
185 m_balances = balances;
186 if (walletModel->wallet().isLegacy()) {
188 ui->labelBalance->setText(BitcoinUnits::formatWithPrivacy(
189 unit, balances.watch_only_balance,
191 ui->labelUnconfirmed->setText(BitcoinUnits::formatWithPrivacy(
192 unit, balances.unconfirmed_watch_only_balance,
194 ui->labelImmature->setText(BitcoinUnits::formatWithPrivacy(
195 unit, balances.immature_watch_only_balance,
197 ui->labelTotal->setText(BitcoinUnits::formatWithPrivacy(
198 unit,
199 balances.watch_only_balance +
203 } else {
204 ui->labelBalance->setText(BitcoinUnits::formatWithPrivacy(
206 m_privacy));
207 ui->labelUnconfirmed->setText(BitcoinUnits::formatWithPrivacy(
208 unit, balances.unconfirmed_balance,
210 ui->labelImmature->setText(BitcoinUnits::formatWithPrivacy(
211 unit, balances.immature_balance,
213 ui->labelTotal->setText(BitcoinUnits::formatWithPrivacy(
214 unit,
215 balances.balance + balances.unconfirmed_balance +
216 balances.immature_balance,
218 ui->labelWatchAvailable->setText(BitcoinUnits::formatWithPrivacy(
219 unit, balances.watch_only_balance,
221 ui->labelWatchPending->setText(BitcoinUnits::formatWithPrivacy(
222 unit, balances.unconfirmed_watch_only_balance,
224 ui->labelWatchImmature->setText(BitcoinUnits::formatWithPrivacy(
225 unit, balances.immature_watch_only_balance,
227 ui->labelWatchTotal->setText(BitcoinUnits::formatWithPrivacy(
228 unit,
229 balances.watch_only_balance +
233 }
234 } else {
235 ui->labelBalance->setText(BitcoinUnits::formatWithPrivacy(
237 m_privacy));
238 ui->labelUnconfirmed->setText(BitcoinUnits::formatWithPrivacy(
239 unit, balances.unconfirmed_balance,
241 ui->labelImmature->setText(BitcoinUnits::formatWithPrivacy(
242 unit, balances.immature_balance,
244 ui->labelTotal->setText(BitcoinUnits::formatWithPrivacy(
245 unit,
246 balances.balance + balances.unconfirmed_balance +
247 balances.immature_balance,
249 }
250
251 // only show immature (newly mined) balance if it's non-zero, so as not to
252 // complicate things for the non-mining users
253 bool showImmature = balances.immature_balance != Amount::zero();
254 bool showWatchOnlyImmature =
256
257 // for symmetry reasons also show immature label when the watch-only one is
258 // shown
259 ui->labelImmature->setVisible(showImmature || showWatchOnlyImmature);
260 ui->labelImmatureText->setVisible(showImmature || showWatchOnlyImmature);
261 // show watch-only immature balance
262 ui->labelWatchImmature->setVisible(
263 !walletModel->wallet().privateKeysDisabled() && showWatchOnlyImmature);
264}
265
266// show/hide watch-only labels
267void OverviewPage::updateWatchOnlyLabels(bool showWatchOnly) {
268 // show spendable label (only when watch-only is active)
269 ui->labelSpendable->setVisible(showWatchOnly);
270 // show watch-only label
271 ui->labelWatchonly->setVisible(showWatchOnly);
272 // show watch-only balance separator line
273 ui->lineWatchBalance->setVisible(showWatchOnly);
274 // show watch-only available balance
275 ui->labelWatchAvailable->setVisible(showWatchOnly);
276 // show watch-only pending balance
277 ui->labelWatchPending->setVisible(showWatchOnly);
278 // show watch-only total balance
279 ui->labelWatchTotal->setVisible(showWatchOnly);
280
281 if (!showWatchOnly) {
282 ui->labelWatchImmature->hide();
283 }
284}
285
287 this->clientModel = model;
288 if (model) {
289 // Show warning, for example if this is a prerelease version
290 connect(model, &ClientModel::alertsChanged, this,
293 }
294}
295
297 this->walletModel = model;
298 if (model && model->getOptionsModel()) {
299 // Set up transaction list
300 filter.reset(new TransactionFilterProxy());
301 filter->setSourceModel(model->getTransactionTableModel());
302 filter->setLimit(NUM_ITEMS);
303 filter->setDynamicSortFilter(true);
304 filter->setSortRole(Qt::EditRole);
305 filter->setShowInactive(false);
306 filter->sort(TransactionTableModel::Date, Qt::DescendingOrder);
307
308 ui->listTransactions->setModel(filter.get());
309 ui->listTransactions->setModelColumn(TransactionTableModel::ToAddress);
310
311 // Keep up to date with wallet
312 interfaces::Wallet &wallet = model->wallet();
313 interfaces::WalletBalances balances = wallet.getBalances();
314 setBalance(balances);
315 connect(model, &WalletModel::balanceChanged, this,
317
320
321 updateWatchOnlyLabels(wallet.haveWatchOnly() &&
322 !model->wallet().privateKeysDisabled());
324 [this](bool showWatchOnly) {
326 showWatchOnly &&
328 });
329 }
330
331 // update the display unit, to not use the default ("XEC")
333}
334
337 if (m_balances.balance != -SATOSHI) {
339 }
340
341 // Update txdelegate->unit with the current unit
343
344 ui->listTransactions->update();
345 }
346}
347
348void OverviewPage::updateAlerts(const QString &warnings) {
349 this->ui->labelAlerts->setVisible(!warnings.isEmpty());
350 this->ui->labelAlerts->setText(warnings);
351}
352
354 ui->labelWalletStatus->setVisible(fShow);
355 ui->labelTransactionsStatus->setVisible(fShow);
356}
static constexpr Amount SATOSHI
Definition: amount.h:143
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:60
virtual bool isLegacy()=0
Return whether is a legacy wallet.
virtual bool privateKeysDisabled()=0
#define COLOR_UNCONFIRMED
Definition: guiconstants.h:28
#define COLOR_NEGATIVE
Definition: guiconstants.h:30
QString dateTimeStr(const QDateTime &date)
Definition: guiutil.cpp:83
#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:354
Amount immature_watch_only_balance
Definition: wallet.h:361
Amount unconfirmed_watch_only_balance
Definition: wallet.h:360