Bitcoin Core  0.20.99
P2P Digital Currency
overviewpage.cpp
Go to the documentation of this file.
1 // Copyright (c) 2011-2019 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 <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 {
30  Q_OBJECT
31 public:
32  explicit TxViewDelegate(const PlatformStyle *_platformStyle, QObject *parent=nullptr):
33  QAbstractItemDelegate(parent), unit(BitcoinUnits::BTC),
34  platformStyle(_platformStyle)
35  {
36 
37  }
38 
39  inline void paint(QPainter *painter, const QStyleOptionViewItem &option,
40  const QModelIndex &index ) const override
41  {
42  painter->save();
43 
44  QIcon icon = qvariant_cast<QIcon>(index.data(TransactionTableModel::RawDecorationRole));
45  QRect mainRect = option.rect;
46  QRect decorationRect(mainRect.topLeft(), QSize(DECORATION_SIZE, DECORATION_SIZE));
47  int xspace = DECORATION_SIZE + 8;
48  int ypad = 6;
49  int halfheight = (mainRect.height() - 2*ypad)/2;
50  QRect amountRect(mainRect.left() + xspace, mainRect.top()+ypad, mainRect.width() - xspace, halfheight);
51  QRect addressRect(mainRect.left() + xspace, mainRect.top()+ypad+halfheight, mainRect.width() - xspace, halfheight);
52  icon = platformStyle->SingleColorIcon(icon);
53  icon.paint(painter, decorationRect);
54 
55  QDateTime date = index.data(TransactionTableModel::DateRole).toDateTime();
56  QString address = index.data(Qt::DisplayRole).toString();
57  qint64 amount = index.data(TransactionTableModel::AmountRole).toLongLong();
58  bool confirmed = index.data(TransactionTableModel::ConfirmedRole).toBool();
59  QVariant value = index.data(Qt::ForegroundRole);
60  QColor foreground = option.palette.color(QPalette::Text);
61  if(value.canConvert<QBrush>())
62  {
63  QBrush brush = qvariant_cast<QBrush>(value);
64  foreground = brush.color();
65  }
66 
67  painter->setPen(foreground);
68  QRect boundingRect;
69  painter->drawText(addressRect, Qt::AlignLeft|Qt::AlignVCenter, address, &boundingRect);
70 
71  if (index.data(TransactionTableModel::WatchonlyRole).toBool())
72  {
73  QIcon iconWatchonly = qvariant_cast<QIcon>(index.data(TransactionTableModel::WatchonlyDecorationRole));
74  QRect watchonlyRect(boundingRect.right() + 5, mainRect.top()+ypad+halfheight, 16, halfheight);
75  iconWatchonly.paint(painter, watchonlyRect);
76  }
77 
78  if(amount < 0)
79  {
80  foreground = COLOR_NEGATIVE;
81  }
82  else if(!confirmed)
83  {
84  foreground = COLOR_UNCONFIRMED;
85  }
86  else
87  {
88  foreground = option.palette.color(QPalette::Text);
89  }
90  painter->setPen(foreground);
91  QString amountText = BitcoinUnits::formatWithUnit(unit, amount, true, BitcoinUnits::SeparatorStyle::ALWAYS);
92  if(!confirmed)
93  {
94  amountText = QString("[") + amountText + QString("]");
95  }
96  painter->drawText(amountRect, Qt::AlignRight|Qt::AlignVCenter, amountText);
97 
98  painter->setPen(option.palette.color(QPalette::Text));
99  painter->drawText(amountRect, Qt::AlignLeft|Qt::AlignVCenter, GUIUtil::dateTimeStr(date));
100 
101  painter->restore();
102  }
103 
104  inline QSize sizeHint(const QStyleOptionViewItem &option, const QModelIndex &index) const override
105  {
106  return QSize(DECORATION_SIZE, DECORATION_SIZE);
107  }
108 
109  int unit;
111 
112 };
113 #include <qt/overviewpage.moc>
114 
115 OverviewPage::OverviewPage(const PlatformStyle *platformStyle, QWidget *parent) :
116  QWidget(parent),
117  ui(new Ui::OverviewPage),
118  clientModel(nullptr),
119  walletModel(nullptr),
120  txdelegate(new TxViewDelegate(platformStyle, this))
121 {
122  ui->setupUi(this);
123 
124  m_balances.balance = -1;
125 
126  // use a SingleColorIcon for the "out of sync warning" icon
127  QIcon icon = platformStyle->SingleColorIcon(":/icons/warning");
128  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)
129  ui->labelTransactionsStatus->setIcon(icon);
130  ui->labelWalletStatus->setIcon(icon);
131 
132  // Recent transactions
133  ui->listTransactions->setItemDelegate(txdelegate);
134  ui->listTransactions->setIconSize(QSize(DECORATION_SIZE, DECORATION_SIZE));
135  ui->listTransactions->setMinimumHeight(NUM_ITEMS * (DECORATION_SIZE + 2));
136  ui->listTransactions->setAttribute(Qt::WA_MacShowFocusRect, false);
137 
138  connect(ui->listTransactions, &QListView::clicked, this, &OverviewPage::handleTransactionClicked);
139 
140  // start with displaying the "out of sync" warnings
141  showOutOfSyncWarning(true);
142  connect(ui->labelWalletStatus, &QPushButton::clicked, this, &OverviewPage::handleOutOfSyncWarningClicks);
143  connect(ui->labelTransactionsStatus, &QPushButton::clicked, this, &OverviewPage::handleOutOfSyncWarningClicks);
144 }
145 
146 void OverviewPage::handleTransactionClicked(const QModelIndex &index)
147 {
148  if(filter)
149  Q_EMIT transactionClicked(filter->mapToSource(index));
150 }
151 
153 {
154  Q_EMIT outOfSyncWarningClicked();
155 }
156 
157 void OverviewPage::setPrivacy(bool privacy)
158 {
159  m_privacy = privacy;
160  if (m_balances.balance != -1) {
162  }
163 
164  ui->listTransactions->setVisible(!m_privacy);
165 
166  const QString status_tip = m_privacy ? tr("Privacy mode activated for the Overview tab. To unmask the values, uncheck Settings->Mask values.") : "";
167  setStatusTip(status_tip);
168  QStatusTipEvent event(status_tip);
169  QApplication::sendEvent(this, &event);
170 }
171 
173 {
174  delete ui;
175 }
176 
178 {
179  int unit = walletModel->getOptionsModel()->getDisplayUnit();
180  m_balances = balances;
181  if (walletModel->wallet().isLegacy()) {
187  } else {
196  }
197  } else {
202  }
203  // only show immature (newly mined) balance if it's non-zero, so as not to complicate things
204  // for the non-mining users
205  bool showImmature = balances.immature_balance != 0;
206  bool showWatchOnlyImmature = balances.immature_watch_only_balance != 0;
207 
208  // for symmetry reasons also show immature label when the watch-only one is shown
209  ui->labelImmature->setVisible(showImmature || showWatchOnlyImmature);
210  ui->labelImmatureText->setVisible(showImmature || showWatchOnlyImmature);
211  ui->labelWatchImmature->setVisible(!walletModel->wallet().privateKeysDisabled() && showWatchOnlyImmature); // show watch-only immature balance
212 }
213 
214 // show/hide watch-only labels
215 void OverviewPage::updateWatchOnlyLabels(bool showWatchOnly)
216 {
217  ui->labelSpendable->setVisible(showWatchOnly); // show spendable label (only when watch-only is active)
218  ui->labelWatchonly->setVisible(showWatchOnly); // show watch-only label
219  ui->lineWatchBalance->setVisible(showWatchOnly); // show watch-only balance separator line
220  ui->labelWatchAvailable->setVisible(showWatchOnly); // show watch-only available balance
221  ui->labelWatchPending->setVisible(showWatchOnly); // show watch-only pending balance
222  ui->labelWatchTotal->setVisible(showWatchOnly); // show watch-only total balance
223 
224  if (!showWatchOnly)
225  ui->labelWatchImmature->hide();
226 }
227 
229 {
230  this->clientModel = model;
231  if (model) {
232  // Show warning, for example if this is a prerelease version
235  }
236 }
237 
239 {
240  this->walletModel = model;
241  if(model && model->getOptionsModel())
242  {
243  // Set up transaction list
244  filter.reset(new TransactionFilterProxy());
245  filter->setSourceModel(model->getTransactionTableModel());
246  filter->setLimit(NUM_ITEMS);
247  filter->setDynamicSortFilter(true);
248  filter->setSortRole(Qt::EditRole);
249  filter->setShowInactive(false);
250  filter->sort(TransactionTableModel::Date, Qt::DescendingOrder);
251 
252  ui->listTransactions->setModel(filter.get());
253  ui->listTransactions->setModelColumn(TransactionTableModel::ToAddress);
254 
255  // Keep up to date with wallet
256  interfaces::Wallet& wallet = model->wallet();
257  interfaces::WalletBalances balances = wallet.getBalances();
258  setBalance(balances);
259  connect(model, &WalletModel::balanceChanged, this, &OverviewPage::setBalance);
260 
262 
264  connect(model, &WalletModel::notifyWatchonlyChanged, [this](bool showWatchOnly) {
266  });
267  }
268 
269  // update the display unit, to not use the default ("BTC")
271 }
272 
274 {
276  {
277  if (m_balances.balance != -1) {
279  }
280 
281  // Update txdelegate->unit with the current unit
283 
284  ui->listTransactions->update();
285  }
286 }
287 
288 void OverviewPage::updateAlerts(const QString &warnings)
289 {
290  this->ui->labelAlerts->setVisible(!warnings.isEmpty());
291  this->ui->labelAlerts->setText(warnings);
292 }
293 
295 {
296  ui->labelWalletStatus->setVisible(fShow);
297  ui->labelTransactionsStatus->setVisible(fShow);
298 }
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:68
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:84
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()