Bitcoin ABC  0.29.2
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 
26 Q_DECLARE_METATYPE(interfaces::WalletBalances)
27 
28 class TxViewDelegate : public QAbstractItemDelegate {
29  Q_OBJECT
30 public:
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,
104  GUIUtil::dateTimeStr(date));
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 
119 OverviewPage::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
146  showOutOfSyncWarning(true);
147  connect(ui->labelWalletStatus, &QPushButton::clicked, this,
149  connect(ui->labelTransactionsStatus, &QPushButton::clicked, this,
151 }
152 
153 void OverviewPage::handleTransactionClicked(const QModelIndex &index) {
154  if (filter) {
155  Q_EMIT transactionClicked(filter->mapToSource(index));
156  }
157 }
158 
160  Q_EMIT outOfSyncWarningClicked();
161 }
162 
163 void OverviewPage::setPrivacy(bool privacy) {
164  m_privacy = privacy;
165  if (m_balances.balance != -Amount::satoshi()) {
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 
185  int unit = walletModel->getOptionsModel()->getDisplayUnit();
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
268 void 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());
324  connect(model, &WalletModel::notifyWatchonlyChanged,
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 
349 void 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:75
#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