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>
17 #include <qt/walletmodel.h>
18 
19 #include <QAbstractItemDelegate>
20 #include <QApplication>
21 #include <QDateTime>
22 #include <QPainter>
23 #include <QStatusTipEvent>
24 
25 #include <algorithm>
26 #include <map>
27 
28 #define DECORATION_SIZE 54
29 #define NUM_ITEMS 5
30 
31 Q_DECLARE_METATYPE(interfaces::WalletBalances)
32 
33 class TxViewDelegate : public QAbstractItemDelegate
34 {
35  Q_OBJECT
36 public:
37  explicit TxViewDelegate(const PlatformStyle *_platformStyle, QObject *parent=nullptr):
38  QAbstractItemDelegate(parent), unit(BitcoinUnits::BTC),
39  platformStyle(_platformStyle)
40  {
41  connect(this, &TxViewDelegate::width_changed, this, &TxViewDelegate::sizeHintChanged);
42  }
43 
44  inline void paint(QPainter *painter, const QStyleOptionViewItem &option,
45  const QModelIndex &index ) const override
46  {
47  painter->save();
48 
49  QIcon icon = qvariant_cast<QIcon>(index.data(TransactionTableModel::RawDecorationRole));
50  QRect mainRect = option.rect;
51  QRect decorationRect(mainRect.topLeft(), QSize(DECORATION_SIZE, DECORATION_SIZE));
52  int xspace = DECORATION_SIZE + 8;
53  int ypad = 6;
54  int halfheight = (mainRect.height() - 2*ypad)/2;
55  QRect amountRect(mainRect.left() + xspace, mainRect.top()+ypad, mainRect.width() - xspace, halfheight);
56  QRect addressRect(mainRect.left() + xspace, mainRect.top()+ypad+halfheight, mainRect.width() - xspace, halfheight);
57  icon = platformStyle->SingleColorIcon(icon);
58  icon.paint(painter, decorationRect);
59 
60  QDateTime date = index.data(TransactionTableModel::DateRole).toDateTime();
61  QString address = index.data(Qt::DisplayRole).toString();
62  qint64 amount = index.data(TransactionTableModel::AmountRole).toLongLong();
63  bool confirmed = 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  {
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, address, &boundingRect);
75  int address_rect_min_width = boundingRect.width();
76 
77  if (index.data(TransactionTableModel::WatchonlyRole).toBool())
78  {
79  QIcon iconWatchonly = qvariant_cast<QIcon>(index.data(TransactionTableModel::WatchonlyDecorationRole));
80  QRect watchonlyRect(boundingRect.right() + 5, mainRect.top()+ypad+halfheight, 16, halfheight);
81  iconWatchonly = platformStyle->TextColorIcon(iconWatchonly);
82  iconWatchonly.paint(painter, watchonlyRect);
83  address_rect_min_width += 5 + watchonlyRect.width();
84  }
85 
86  if(amount < 0)
87  {
88  foreground = COLOR_NEGATIVE;
89  }
90  else if(!confirmed)
91  {
92  foreground = COLOR_UNCONFIRMED;
93  }
94  else
95  {
96  foreground = option.palette.color(QPalette::Text);
97  }
98  painter->setPen(foreground);
99  QString amountText = BitcoinUnits::formatWithUnit(unit, amount, true, BitcoinUnits::SeparatorStyle::ALWAYS);
100  if(!confirmed)
101  {
102  amountText = QString("[") + amountText + QString("]");
103  }
104 
105  QRect amount_bounding_rect;
106  painter->drawText(amountRect, Qt::AlignRight | Qt::AlignVCenter, amountText, &amount_bounding_rect);
107 
108  painter->setPen(option.palette.color(QPalette::Text));
109  QRect date_bounding_rect;
110  painter->drawText(amountRect, Qt::AlignLeft | Qt::AlignVCenter, GUIUtil::dateTimeStr(date), &date_bounding_rect);
111 
112  const int minimum_width = std::max(address_rect_min_width, amount_bounding_rect.width() + date_bounding_rect.width());
113  const auto search = m_minimum_width.find(index.row());
114  if (search == m_minimum_width.end() || search->second != minimum_width) {
115  m_minimum_width[index.row()] = minimum_width;
116  Q_EMIT width_changed(index);
117  }
118 
119  painter->restore();
120  }
121 
122  inline QSize sizeHint(const QStyleOptionViewItem &option, const QModelIndex &index) const override
123  {
124  const auto search = m_minimum_width.find(index.row());
125  const int minimum_text_width = search == m_minimum_width.end() ? 0 : search->second;
126  return {DECORATION_SIZE + 8 + minimum_text_width, DECORATION_SIZE};
127  }
128 
129  int unit;
130 
131 Q_SIGNALS:
133  void width_changed(const QModelIndex& index) const;
134 
135 private:
137  mutable std::map<int, int> m_minimum_width;
138 };
139 
140 #include <qt/overviewpage.moc>
141 
142 OverviewPage::OverviewPage(const PlatformStyle *platformStyle, QWidget *parent) :
143  QWidget(parent),
144  ui(new Ui::OverviewPage),
145  clientModel(nullptr),
146  walletModel(nullptr),
147  m_platform_style{platformStyle},
148  txdelegate(new TxViewDelegate(platformStyle, this))
149 {
150  ui->setupUi(this);
151 
152  m_balances.balance = -1;
153 
154  // use a SingleColorIcon for the "out of sync warning" icon
155  QIcon icon = m_platform_style->SingleColorIcon(QStringLiteral(":/icons/warning"));
156  ui->labelTransactionsStatus->setIcon(icon);
157  ui->labelWalletStatus->setIcon(icon);
158 
159  // Recent transactions
160  ui->listTransactions->setItemDelegate(txdelegate);
161  ui->listTransactions->setIconSize(QSize(DECORATION_SIZE, DECORATION_SIZE));
162  ui->listTransactions->setMinimumHeight(NUM_ITEMS * (DECORATION_SIZE + 2));
163  ui->listTransactions->setAttribute(Qt::WA_MacShowFocusRect, false);
164 
165  connect(ui->listTransactions, &TransactionOverviewWidget::clicked, this, &OverviewPage::handleTransactionClicked);
166 
167  // start with displaying the "out of sync" warnings
168  showOutOfSyncWarning(true);
169  connect(ui->labelWalletStatus, &QPushButton::clicked, this, &OverviewPage::outOfSyncWarningClicked);
170  connect(ui->labelTransactionsStatus, &QPushButton::clicked, this, &OverviewPage::outOfSyncWarningClicked);
171 }
172 
173 void OverviewPage::handleTransactionClicked(const QModelIndex &index)
174 {
175  if(filter)
176  Q_EMIT transactionClicked(filter->mapToSource(index));
177 }
178 
179 void OverviewPage::setPrivacy(bool privacy)
180 {
181  m_privacy = privacy;
182  if (m_balances.balance != -1) {
184  }
185 
186  ui->listTransactions->setVisible(!m_privacy);
187 
188  const QString status_tip = m_privacy ? tr("Privacy mode activated for the Overview tab. To unmask the values, uncheck Settings->Mask values.") : "";
189  setStatusTip(status_tip);
190  QStatusTipEvent event(status_tip);
191  QApplication::sendEvent(this, &event);
192 }
193 
195 {
196  delete ui;
197 }
198 
200 {
201  int unit = walletModel->getOptionsModel()->getDisplayUnit();
202  m_balances = balances;
203  if (walletModel->wallet().isLegacy()) {
209  } else {
218  }
219  } else {
224  }
225  // only show immature (newly mined) balance if it's non-zero, so as not to complicate things
226  // for the non-mining users
227  bool showImmature = balances.immature_balance != 0;
228  bool showWatchOnlyImmature = balances.immature_watch_only_balance != 0;
229 
230  // for symmetry reasons also show immature label when the watch-only one is shown
231  ui->labelImmature->setVisible(showImmature || showWatchOnlyImmature);
232  ui->labelImmatureText->setVisible(showImmature || showWatchOnlyImmature);
233  ui->labelWatchImmature->setVisible(!walletModel->wallet().privateKeysDisabled() && showWatchOnlyImmature); // show watch-only immature balance
234 }
235 
236 // show/hide watch-only labels
237 void OverviewPage::updateWatchOnlyLabels(bool showWatchOnly)
238 {
239  ui->labelSpendable->setVisible(showWatchOnly); // show spendable label (only when watch-only is active)
240  ui->labelWatchonly->setVisible(showWatchOnly); // show watch-only label
241  ui->lineWatchBalance->setVisible(showWatchOnly); // show watch-only balance separator line
242  ui->labelWatchAvailable->setVisible(showWatchOnly); // show watch-only available balance
243  ui->labelWatchPending->setVisible(showWatchOnly); // show watch-only pending balance
244  ui->labelWatchTotal->setVisible(showWatchOnly); // show watch-only total balance
245 
246  if (!showWatchOnly)
247  ui->labelWatchImmature->hide();
248 }
249 
251 {
252  this->clientModel = model;
253  if (model) {
254  // Show warning, for example if this is a prerelease version
257 
260  }
261 }
262 
264 {
265  this->walletModel = model;
266  if(model && model->getOptionsModel())
267  {
268  // Set up transaction list
269  filter.reset(new TransactionFilterProxy());
270  filter->setSourceModel(model->getTransactionTableModel());
271  filter->setLimit(NUM_ITEMS);
272  filter->setDynamicSortFilter(true);
273  filter->setSortRole(Qt::EditRole);
274  filter->setShowInactive(false);
275  filter->sort(TransactionTableModel::Date, Qt::DescendingOrder);
276 
277  ui->listTransactions->setModel(filter.get());
278  ui->listTransactions->setModelColumn(TransactionTableModel::ToAddress);
279 
280  // Keep up to date with wallet
281  interfaces::Wallet& wallet = model->wallet();
282  interfaces::WalletBalances balances = wallet.getBalances();
283  setBalance(balances);
284  connect(model, &WalletModel::balanceChanged, this, &OverviewPage::setBalance);
285 
287 
288  updateWatchOnlyLabels(wallet.haveWatchOnly() && !model->wallet().privateKeysDisabled());
289  connect(model, &WalletModel::notifyWatchonlyChanged, [this](bool showWatchOnly) {
291  });
292  }
293 
294  // update the display unit, to not use the default ("BTC")
296 }
297 
299 {
300 #ifdef Q_OS_MACOS
301  if (e->type() == QEvent::PaletteChange) {
302  QIcon icon = m_platform_style->SingleColorIcon(QStringLiteral(":/icons/warning"));
303  ui->labelTransactionsStatus->setIcon(icon);
304  ui->labelWalletStatus->setIcon(icon);
305  }
306 #endif
307 }
308 
310 {
312  {
313  if (m_balances.balance != -1) {
315  }
316 
317  // Update txdelegate->unit with the current unit
319 
320  ui->listTransactions->update();
321  }
322 }
323 
324 void OverviewPage::updateAlerts(const QString &warnings)
325 {
326  this->ui->labelAlerts->setVisible(!warnings.isEmpty());
327  this->ui->labelAlerts->setText(warnings);
328 }
329 
331 {
332  ui->labelWalletStatus->setVisible(fShow);
333  ui->labelTransactionsStatus->setVisible(fShow);
334 }
335 
336 void OverviewPage::setMonospacedFont(bool use_embedded_font)
337 {
338  QFont f = GUIUtil::fixedPitchFont(use_embedded_font);
339  f.setWeight(QFont::Bold);
340  ui->labelBalance->setFont(f);
341  ui->labelUnconfirmed->setFont(f);
342  ui->labelImmature->setFont(f);
343  ui->labelTotal->setFont(f);
344  ui->labelWatchAvailable->setFont(f);
345  ui->labelWatchPending->setFont(f);
346  ui->labelWatchImmature->setFont(f);
347  ui->labelWatchTotal->setFont(f);
348 }
ClientModel::alertsChanged
void alertsChanged(const QString &warnings)
TxViewDelegate::m_minimum_width
std::map< int, int > m_minimum_width
Definition: overviewpage.cpp:137
WalletModel::getOptionsModel
OptionsModel * getOptionsModel()
Definition: walletmodel.cpp:284
transactiontablemodel.h
OverviewPage::OverviewPage
OverviewPage(const PlatformStyle *platformStyle, QWidget *parent=nullptr)
Definition: overviewpage.cpp:142
OverviewPage::~OverviewPage
~OverviewPage()
Definition: overviewpage.cpp:194
TransactionTableModel::Date
@ Date
Definition: transactiontablemodel.h:37
WalletModel
Interface to Bitcoin wallet from Qt view code.
Definition: walletmodel.h:51
OverviewPage::outOfSyncWarningClicked
void outOfSyncWarningClicked()
BitcoinUnits::formatWithUnit
static QString formatWithUnit(int unit, const CAmount &amount, bool plussign=false, SeparatorStyle separators=SeparatorStyle::STANDARD)
Format as string (with unit)
Definition: bitcoinunits.cpp:148
TxViewDelegate::unit
int unit
Definition: overviewpage.cpp:129
PlatformStyle::SingleColorIcon
QIcon SingleColorIcon(const QString &filename) const
Colorize an icon (given filename) with the icon color.
Definition: platformstyle.cpp:105
walletmodel.h
DECORATION_SIZE
#define DECORATION_SIZE
Definition: overviewpage.cpp:28
OverviewPage::updateAlerts
void updateAlerts(const QString &warnings)
Definition: overviewpage.cpp:324
TransactionTableModel::WatchonlyRole
@ WatchonlyRole
Watch-only boolean.
Definition: transactiontablemodel.h:52
transactionoverviewwidget.h
OverviewPage::ui
Ui::OverviewPage * ui
Definition: overviewpage.h:52
interfaces::WalletBalances::unconfirmed_balance
CAmount unconfirmed_balance
Definition: wallet.h:355
OverviewPage
Overview ("home") page widget.
Definition: overviewpage.h:28
OptionsModel::displayUnitChanged
void displayUnitChanged(int unit)
TxViewDelegate::paint
void paint(QPainter *painter, const QStyleOptionViewItem &option, const QModelIndex &index) const override
Definition: overviewpage.cpp:44
WalletModel::getTransactionTableModel
TransactionTableModel * getTransactionTableModel()
Definition: walletmodel.cpp:294
wallet
Definition: interfaces.cpp:47
OverviewPage::txdelegate
TxViewDelegate * txdelegate
Definition: overviewpage.h:60
interfaces::WalletBalances::immature_watch_only_balance
CAmount immature_watch_only_balance
Definition: wallet.h:360
ClientModel::getStatusBarWarnings
QString getStatusBarWarnings() const
Return warnings to be displayed in status bar.
Definition: clientmodel.cpp:177
OverviewPage::filter
std::unique_ptr< TransactionFilterProxy > filter
Definition: overviewpage.h:61
interfaces::WalletBalances::balance
CAmount balance
Definition: wallet.h:354
COLOR_NEGATIVE
#define COLOR_NEGATIVE
Definition: guiconstants.h:27
overviewpage.h
OverviewPage::walletModel
WalletModel * walletModel
Definition: overviewpage.h:54
interfaces::WalletBalances::watch_only_balance
CAmount watch_only_balance
Definition: wallet.h:358
ClientModel::getOptionsModel
OptionsModel * getOptionsModel()
Definition: clientmodel.cpp:182
TxViewDelegate::TxViewDelegate
TxViewDelegate(const PlatformStyle *_platformStyle, QObject *parent=nullptr)
Definition: overviewpage.cpp:37
TxViewDelegate
Definition: overviewpage.cpp:33
TransactionTableModel::RawDecorationRole
@ RawDecorationRole
Unprocessed icon.
Definition: transactiontablemodel.h:76
TransactionTableModel::AmountRole
@ AmountRole
Net amount of transaction.
Definition: transactiontablemodel.h:62
WalletModel::wallet
interfaces::Wallet & wallet() const
Definition: walletmodel.h:144
interfaces::WalletBalances
Collection of wallet balances.
Definition: wallet.h:352
OverviewPage::m_privacy
bool m_privacy
Definition: overviewpage.h:56
TransactionTableModel::ToAddress
@ ToAddress
Definition: transactiontablemodel.h:39
OverviewPage::updateWatchOnlyLabels
void updateWatchOnlyLabels(bool showWatchOnly)
Definition: overviewpage.cpp:237
OverviewPage::setClientModel
void setClientModel(ClientModel *clientModel)
Definition: overviewpage.cpp:250
transactionfilterproxy.h
BitcoinUnits
Bitcoin unit definitions.
Definition: bitcoinunits.h:31
OverviewPage::setBalance
void setBalance(const interfaces::WalletBalances &balances)
Definition: overviewpage.cpp:199
guiutil.h
interfaces::Wallet
Interface for accessing a wallet.
Definition: wallet.h:52
OverviewPage::setMonospacedFont
void setMonospacedFont(bool use_embedded_font)
Definition: overviewpage.cpp:336
GUIUtil::fixedPitchFont
QFont fixedPitchFont(bool use_embedded_font)
Definition: guiutil.cpp:87
OverviewPage::updateDisplayUnit
void updateDisplayUnit()
Definition: overviewpage.cpp:309
OverviewPage::clientModel
ClientModel * clientModel
Definition: overviewpage.h:53
interfaces::WalletBalances::immature_balance
CAmount immature_balance
Definition: wallet.h:356
OverviewPage::transactionClicked
void transactionClicked(const QModelIndex &index)
BitcoinUnits::SeparatorStyle::ALWAYS
@ ALWAYS
platformstyle.h
OverviewPage::changeEvent
void changeEvent(QEvent *e) override
Definition: overviewpage.cpp:298
ClientModel
Model for Bitcoin network client.
Definition: clientmodel.h:47
TxViewDelegate::sizeHint
QSize sizeHint(const QStyleOptionViewItem &option, const QModelIndex &index) const override
Definition: overviewpage.cpp:122
OverviewPage::m_platform_style
const PlatformStyle * m_platform_style
Definition: overviewpage.h:58
Ui
Definition: addressbookpage.h:14
guiconstants.h
TxViewDelegate::platformStyle
const PlatformStyle * platformStyle
Definition: overviewpage.cpp:136
OptionsModel::getDisplayUnit
int getDisplayUnit() const
Definition: optionsmodel.h:87
TransactionTableModel::WatchonlyDecorationRole
@ WatchonlyDecorationRole
Watch-only icon.
Definition: transactiontablemodel.h:54
OverviewPage::m_balances
interfaces::WalletBalances m_balances
Definition: overviewpage.h:55
OptionsModel::useEmbeddedMonospacedFontChanged
void useEmbeddedMonospacedFontChanged(bool)
OverviewPage::handleTransactionClicked
void handleTransactionClicked(const QModelIndex &index)
Definition: overviewpage.cpp:173
bitcoinunits.h
OverviewPage::setWalletModel
void setWalletModel(WalletModel *walletModel)
Definition: overviewpage.cpp:263
OverviewPage::setPrivacy
void setPrivacy(bool privacy)
Definition: overviewpage.cpp:179
interfaces::WalletBalances::unconfirmed_watch_only_balance
CAmount unconfirmed_watch_only_balance
Definition: wallet.h:359
GUIUtil::dateTimeStr
QString dateTimeStr(const QDateTime &date)
Definition: guiutil.cpp:77
TransactionTableModel::DateRole
@ DateRole
Date and time this transaction was created.
Definition: transactiontablemodel.h:50
optionsmodel.h
BitcoinUnits::formatWithPrivacy
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.
Definition: bitcoinunits.cpp:160
WalletModel::balanceChanged
void balanceChanged(const interfaces::WalletBalances &balances)
PlatformStyle
Definition: platformstyle.h:13
OverviewPage::showOutOfSyncWarning
void showOutOfSyncWarning(bool fShow)
Definition: overviewpage.cpp:330
interfaces::Wallet::privateKeysDisabled
virtual bool privateKeysDisabled()=0
WalletModel::notifyWatchonlyChanged
void notifyWatchonlyChanged(bool fHaveWatchonly)
TxViewDelegate::width_changed
void width_changed(const QModelIndex &index) const
An intermediate signal for emitting from the paint() const member function.
NUM_ITEMS
#define NUM_ITEMS
Definition: overviewpage.cpp:29
COLOR_UNCONFIRMED
#define COLOR_UNCONFIRMED
Definition: guiconstants.h:25
OptionsModel::getUseEmbeddedMonospacedFont
bool getUseEmbeddedMonospacedFont() const
Definition: optionsmodel.h:89
interfaces::Wallet::isLegacy
virtual bool isLegacy()=0
Return whether is a legacy wallet.
clientmodel.h
TransactionTableModel::ConfirmedRole
@ ConfirmedRole
Is transaction confirmed?
Definition: transactiontablemodel.h:70
TransactionFilterProxy
Filter the transaction list according to pre-specified rules.
Definition: transactionfilterproxy.h:14