Bitcoin Core  21.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>
6 #include <qt/forms/ui_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 <QDateTime>
21 #include <QPainter>
22 #include <QStatusTipEvent>
23 
24 #define DECORATION_SIZE 54
25 #define NUM_ITEMS 5
26 
27 Q_DECLARE_METATYPE(interfaces::WalletBalances)
28 
29 class TxViewDelegate : public QAbstractItemDelegate
30 {
31  Q_OBJECT
32 public:
33  explicit TxViewDelegate(const PlatformStyle *_platformStyle, QObject *parent=nullptr):
34  QAbstractItemDelegate(parent), unit(BitcoinUnits::BTC),
35  platformStyle(_platformStyle)
36  {
37 
38  }
39 
40  inline void paint(QPainter *painter, const QStyleOptionViewItem &option,
41  const QModelIndex &index ) const override
42  {
43  painter->save();
44 
45  QIcon icon = qvariant_cast<QIcon>(index.data(TransactionTableModel::RawDecorationRole));
46  QRect mainRect = option.rect;
47  QRect decorationRect(mainRect.topLeft(), QSize(DECORATION_SIZE, DECORATION_SIZE));
48  int xspace = DECORATION_SIZE + 8;
49  int ypad = 6;
50  int halfheight = (mainRect.height() - 2*ypad)/2;
51  QRect amountRect(mainRect.left() + xspace, mainRect.top()+ypad, mainRect.width() - xspace, halfheight);
52  QRect addressRect(mainRect.left() + xspace, mainRect.top()+ypad+halfheight, mainRect.width() - xspace, halfheight);
53  icon = platformStyle->SingleColorIcon(icon);
54  icon.paint(painter, decorationRect);
55 
56  QDateTime date = index.data(TransactionTableModel::DateRole).toDateTime();
57  QString address = index.data(Qt::DisplayRole).toString();
58  qint64 amount = index.data(TransactionTableModel::AmountRole).toLongLong();
59  bool confirmed = index.data(TransactionTableModel::ConfirmedRole).toBool();
60  QVariant value = index.data(Qt::ForegroundRole);
61  QColor foreground = option.palette.color(QPalette::Text);
62  if(value.canConvert<QBrush>())
63  {
64  QBrush brush = qvariant_cast<QBrush>(value);
65  foreground = brush.color();
66  }
67 
68  painter->setPen(foreground);
69  QRect boundingRect;
70  painter->drawText(addressRect, Qt::AlignLeft|Qt::AlignVCenter, address, &boundingRect);
71 
72  if (index.data(TransactionTableModel::WatchonlyRole).toBool())
73  {
74  QIcon iconWatchonly = qvariant_cast<QIcon>(index.data(TransactionTableModel::WatchonlyDecorationRole));
75  QRect watchonlyRect(boundingRect.right() + 5, mainRect.top()+ypad+halfheight, 16, halfheight);
76  iconWatchonly.paint(painter, watchonlyRect);
77  }
78 
79  if(amount < 0)
80  {
81  foreground = COLOR_NEGATIVE;
82  }
83  else if(!confirmed)
84  {
85  foreground = COLOR_UNCONFIRMED;
86  }
87  else
88  {
89  foreground = option.palette.color(QPalette::Text);
90  }
91  painter->setPen(foreground);
92  QString amountText = BitcoinUnits::formatWithUnit(unit, amount, true, BitcoinUnits::SeparatorStyle::ALWAYS);
93  if(!confirmed)
94  {
95  amountText = QString("[") + amountText + QString("]");
96  }
97  painter->drawText(amountRect, Qt::AlignRight|Qt::AlignVCenter, amountText);
98 
99  painter->setPen(option.palette.color(QPalette::Text));
100  painter->drawText(amountRect, Qt::AlignLeft|Qt::AlignVCenter, GUIUtil::dateTimeStr(date));
101 
102  painter->restore();
103  }
104 
105  inline QSize sizeHint(const QStyleOptionViewItem &option, const QModelIndex &index) const override
106  {
107  return QSize(DECORATION_SIZE, DECORATION_SIZE);
108  }
109 
110  int unit;
112 
113 };
114 #include <qt/overviewpage.moc>
115 
116 OverviewPage::OverviewPage(const PlatformStyle *platformStyle, QWidget *parent) :
117  QWidget(parent),
118  ui(new Ui::OverviewPage),
119  clientModel(nullptr),
120  walletModel(nullptr),
121  txdelegate(new TxViewDelegate(platformStyle, this))
122 {
123  ui->setupUi(this);
124 
125  m_balances.balance = -1;
126 
127  // use a SingleColorIcon for the "out of sync warning" icon
128  QIcon icon = platformStyle->SingleColorIcon(":/icons/warning");
129  icon.addPixmap(icon.pixmap(QSize(64,64), QIcon::Normal), QIcon::Disabled); // also set the disabled icon because we are using a disabled QPushButton to work around missing HiDPI support of QLabel (https://bugreports.qt.io/browse/QTBUG-42503)
130  ui->labelTransactionsStatus->setIcon(icon);
131  ui->labelWalletStatus->setIcon(icon);
132 
133  // Recent transactions
134  ui->listTransactions->setItemDelegate(txdelegate);
135  ui->listTransactions->setIconSize(QSize(DECORATION_SIZE, DECORATION_SIZE));
136  ui->listTransactions->setMinimumHeight(NUM_ITEMS * (DECORATION_SIZE + 2));
137  ui->listTransactions->setAttribute(Qt::WA_MacShowFocusRect, false);
138 
139  connect(ui->listTransactions, &QListView::clicked, this, &OverviewPage::handleTransactionClicked);
140 
141  // start with displaying the "out of sync" warnings
142  showOutOfSyncWarning(true);
143  connect(ui->labelWalletStatus, &QPushButton::clicked, this, &OverviewPage::handleOutOfSyncWarningClicks);
144  connect(ui->labelTransactionsStatus, &QPushButton::clicked, this, &OverviewPage::handleOutOfSyncWarningClicks);
145 }
146 
147 void OverviewPage::handleTransactionClicked(const QModelIndex &index)
148 {
149  if(filter)
150  Q_EMIT transactionClicked(filter->mapToSource(index));
151 }
152 
154 {
155  Q_EMIT outOfSyncWarningClicked();
156 }
157 
158 void OverviewPage::setPrivacy(bool privacy)
159 {
160  m_privacy = privacy;
161  if (m_balances.balance != -1) {
163  }
164 
165  ui->listTransactions->setVisible(!m_privacy);
166 
167  const QString status_tip = m_privacy ? tr("Privacy mode activated for the Overview tab. To unmask the values, uncheck Settings->Mask values.") : "";
168  setStatusTip(status_tip);
169  QStatusTipEvent event(status_tip);
170  QApplication::sendEvent(this, &event);
171 }
172 
174 {
175  delete ui;
176 }
177 
179 {
180  int unit = walletModel->getOptionsModel()->getDisplayUnit();
181  m_balances = balances;
182  if (walletModel->wallet().isLegacy()) {
188  } else {
197  }
198  } else {
203  }
204  // only show immature (newly mined) balance if it's non-zero, so as not to complicate things
205  // for the non-mining users
206  bool showImmature = balances.immature_balance != 0;
207  bool showWatchOnlyImmature = balances.immature_watch_only_balance != 0;
208 
209  // for symmetry reasons also show immature label when the watch-only one is shown
210  ui->labelImmature->setVisible(showImmature || showWatchOnlyImmature);
211  ui->labelImmatureText->setVisible(showImmature || showWatchOnlyImmature);
212  ui->labelWatchImmature->setVisible(!walletModel->wallet().privateKeysDisabled() && showWatchOnlyImmature); // show watch-only immature balance
213 }
214 
215 // show/hide watch-only labels
216 void OverviewPage::updateWatchOnlyLabels(bool showWatchOnly)
217 {
218  ui->labelSpendable->setVisible(showWatchOnly); // show spendable label (only when watch-only is active)
219  ui->labelWatchonly->setVisible(showWatchOnly); // show watch-only label
220  ui->lineWatchBalance->setVisible(showWatchOnly); // show watch-only balance separator line
221  ui->labelWatchAvailable->setVisible(showWatchOnly); // show watch-only available balance
222  ui->labelWatchPending->setVisible(showWatchOnly); // show watch-only pending balance
223  ui->labelWatchTotal->setVisible(showWatchOnly); // show watch-only total balance
224 
225  if (!showWatchOnly)
226  ui->labelWatchImmature->hide();
227 }
228 
230 {
231  this->clientModel = model;
232  if (model) {
233  // Show warning, for example if this is a prerelease version
236  }
237 }
238 
240 {
241  this->walletModel = model;
242  if(model && model->getOptionsModel())
243  {
244  // Set up transaction list
245  filter.reset(new TransactionFilterProxy());
246  filter->setSourceModel(model->getTransactionTableModel());
247  filter->setLimit(NUM_ITEMS);
248  filter->setDynamicSortFilter(true);
249  filter->setSortRole(Qt::EditRole);
250  filter->setShowInactive(false);
251  filter->sort(TransactionTableModel::Date, Qt::DescendingOrder);
252 
253  ui->listTransactions->setModel(filter.get());
254  ui->listTransactions->setModelColumn(TransactionTableModel::ToAddress);
255 
256  // Keep up to date with wallet
257  interfaces::Wallet& wallet = model->wallet();
258  interfaces::WalletBalances balances = wallet.getBalances();
259  setBalance(balances);
260  connect(model, &WalletModel::balanceChanged, this, &OverviewPage::setBalance);
261 
263 
265  connect(model, &WalletModel::notifyWatchonlyChanged, [this](bool showWatchOnly) {
267  });
268  }
269 
270  // update the display unit, to not use the default ("BTC")
272 }
273 
275 {
277  {
278  if (m_balances.balance != -1) {
280  }
281 
282  // Update txdelegate->unit with the current unit
284 
285  ui->listTransactions->update();
286  }
287 }
288 
289 void OverviewPage::updateAlerts(const QString &warnings)
290 {
291  this->ui->labelAlerts->setVisible(!warnings.isEmpty());
292  this->ui->labelAlerts->setText(warnings);
293 }
294 
296 {
297  ui->labelWalletStatus->setVisible(fShow);
298  ui->labelTransactionsStatus->setVisible(fShow);
299 }
virtual bool privateKeysDisabled()=0
void setWalletModel(WalletModel *walletModel)
interfaces::Wallet & wallet() const
Definition: walletmodel.h:146
Bitcoin unit definitions.
Definition: bitcoinunits.h:31
void updateAlerts(const QString &warnings)
#define DECORATION_SIZE
void handleTransactionClicked(const QModelIndex &index)
interfaces::WalletBalances m_balances
Definition: overviewpage.h:52
void setPrivacy(bool privacy)
std::unique_ptr< TransactionFilterProxy > filter
Definition: overviewpage.h:56
void paint(QPainter *painter, const QStyleOptionViewItem &option, const QModelIndex &index) const override
QString dateTimeStr(const QDateTime &date)
Definition: guiutil.cpp:69
TxViewDelegate(const PlatformStyle *_platformStyle, QObject *parent=nullptr)
QIcon SingleColorIcon(const QString &filename) const
Colorize an icon (given filename) with the icon color.
TxViewDelegate * txdelegate
Definition: overviewpage.h:55
WalletModel * walletModel
Definition: overviewpage.h:51
virtual bool isLegacy()=0
Return whether is a legacy wallet.
void outOfSyncWarningClicked()
QString getStatusBarWarnings() const
Return warnings to be displayed in status bar.
void alertsChanged(const QString &warnings)
int getDisplayUnit() const
Definition: optionsmodel.h:85
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.
#define NUM_ITEMS
Collection of wallet balances.
Definition: wallet.h:349
void updateWatchOnlyLabels(bool showWatchOnly)
Interface for accessing a wallet.
Definition: wallet.h:52
static QString formatWithUnit(int unit, const CAmount &amount, bool plussign=false, SeparatorStyle separators=SeparatorStyle::STANDARD)
Format as string (with unit)
CAmount immature_watch_only_balance
Definition: wallet.h:357
Date and time this transaction was created.
TransactionTableModel * getTransactionTableModel()
void displayUnitChanged(int unit)
#define COLOR_UNCONFIRMED
Definition: guiconstants.h:25
Model for Bitcoin network client.
Definition: clientmodel.h:46
ClientModel * clientModel
Definition: overviewpage.h:50
void transactionClicked(const QModelIndex &index)
const PlatformStyle * platformStyle
void showOutOfSyncWarning(bool fShow)
CAmount unconfirmed_watch_only_balance
Definition: wallet.h:356
Filter the transaction list according to pre-specified rules.
void updateDisplayUnit()
Interface to Bitcoin wallet from Qt view code.
Definition: walletmodel.h:51
virtual bool haveWatchOnly()=0
Return whether wallet has watch only keys.
void notifyWatchonlyChanged(bool fHaveWatchonly)
void setClientModel(ClientModel *clientModel)
QSize sizeHint(const QStyleOptionViewItem &option, const QModelIndex &index) const override
void setBalance(const interfaces::WalletBalances &balances)
void handleOutOfSyncWarningClicks()
OverviewPage(const PlatformStyle *platformStyle, QWidget *parent=nullptr)
virtual WalletBalances getBalances()=0
Get balances.
Overview ("home") page widget.
Definition: overviewpage.h:28
Ui::OverviewPage * ui
Definition: overviewpage.h:49
void balanceChanged(const interfaces::WalletBalances &balances)
#define COLOR_NEGATIVE
Definition: guiconstants.h:27
OptionsModel * getOptionsModel()