Bitcoin Core  31.0.0
P2P Digital Currency
overviewpage.cpp
Go to the documentation of this file.
1 // Copyright (c) 2011-present 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), platformStyle(_platformStyle)
39  {
40  connect(this, &TxViewDelegate::width_changed, this, &TxViewDelegate::sizeHintChanged);
41  }
42 
43  inline void paint(QPainter *painter, const QStyleOptionViewItem &option,
44  const QModelIndex &index ) const override
45  {
46  painter->save();
47 
48  QIcon icon = qvariant_cast<QIcon>(index.data(TransactionTableModel::RawDecorationRole));
49  QRect mainRect = option.rect;
50  QRect decorationRect(mainRect.topLeft(), QSize(DECORATION_SIZE, DECORATION_SIZE));
51  int xspace = DECORATION_SIZE + 8;
52  int ypad = 6;
53  int halfheight = (mainRect.height() - 2*ypad)/2;
54  QRect amountRect(mainRect.left() + xspace, mainRect.top()+ypad, mainRect.width() - xspace, halfheight);
55  QRect addressRect(mainRect.left() + xspace, mainRect.top()+ypad+halfheight, mainRect.width() - xspace, halfheight);
56  icon = platformStyle->SingleColorIcon(icon);
57  icon.paint(painter, decorationRect);
58 
59  QDateTime date = index.data(TransactionTableModel::DateRole).toDateTime();
60  QString address = index.data(Qt::DisplayRole).toString();
61  qint64 amount = index.data(TransactionTableModel::AmountRole).toLongLong();
62  bool confirmed = index.data(TransactionTableModel::ConfirmedRole).toBool();
63  QVariant value = index.data(Qt::ForegroundRole);
64  QColor foreground = option.palette.color(QPalette::Text);
65  if(value.canConvert<QBrush>())
66  {
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, address, &boundingRect);
74 
75  if(amount < 0)
76  {
77  foreground = COLOR_NEGATIVE;
78  }
79  else if(!confirmed)
80  {
81  foreground = COLOR_UNCONFIRMED;
82  }
83  else
84  {
85  foreground = option.palette.color(QPalette::Text);
86  }
87  painter->setPen(foreground);
88  QString amountText = BitcoinUnits::formatWithUnit(unit, amount, true, BitcoinUnits::SeparatorStyle::ALWAYS);
89  if(!confirmed)
90  {
91  amountText = QString("[") + amountText + QString("]");
92  }
93 
94  QRect amount_bounding_rect;
95  painter->drawText(amountRect, Qt::AlignRight | Qt::AlignVCenter, amountText, &amount_bounding_rect);
96 
97  painter->setPen(option.palette.color(QPalette::Text));
98  QRect date_bounding_rect;
99  painter->drawText(amountRect, Qt::AlignLeft | Qt::AlignVCenter, GUIUtil::dateTimeStr(date), &date_bounding_rect);
100 
101  // 0.4*date_bounding_rect.width() is used to visually distinguish a date from an amount.
102  const int minimum_width = 1.4 * date_bounding_rect.width() + amount_bounding_rect.width();
103  const auto search = m_minimum_width.find(index.row());
104  if (search == m_minimum_width.end() || search->second != minimum_width) {
105  m_minimum_width[index.row()] = minimum_width;
106  Q_EMIT width_changed(index);
107  }
108 
109  painter->restore();
110  }
111 
112  inline QSize sizeHint(const QStyleOptionViewItem &option, const QModelIndex &index) const override
113  {
114  const auto search = m_minimum_width.find(index.row());
115  const int minimum_text_width = search == m_minimum_width.end() ? 0 : search->second;
116  return {DECORATION_SIZE + 8 + minimum_text_width, DECORATION_SIZE};
117  }
118 
120 
121 Q_SIGNALS:
123  void width_changed(const QModelIndex& index) const;
124 
125 private:
127  mutable std::map<int, int> m_minimum_width;
128 };
129 
130 #include <qt/overviewpage.moc>
131 
132 OverviewPage::OverviewPage(const PlatformStyle *platformStyle, QWidget *parent) :
133  QWidget(parent),
134  ui(new Ui::OverviewPage),
135  m_platform_style{platformStyle},
136  txdelegate(new TxViewDelegate(platformStyle, this))
137 {
138  ui->setupUi(this);
139 
140  // use a SingleColorIcon for the "out of sync warning" icon
141  QIcon icon = m_platform_style->SingleColorIcon(QStringLiteral(":/icons/warning"));
142  ui->labelTransactionsStatus->setIcon(icon);
143  ui->labelWalletStatus->setIcon(icon);
144 
145  // Recent transactions
146  ui->listTransactions->setItemDelegate(txdelegate);
147  ui->listTransactions->setIconSize(QSize(DECORATION_SIZE, DECORATION_SIZE));
148  ui->listTransactions->setMinimumHeight(NUM_ITEMS * (DECORATION_SIZE + 2));
149  ui->listTransactions->setAttribute(Qt::WA_MacShowFocusRect, false);
150 
151  connect(ui->listTransactions, &TransactionOverviewWidget::clicked, this, &OverviewPage::handleTransactionClicked);
152 
153  // start with displaying the "out of sync" warnings
154  showOutOfSyncWarning(true);
155  connect(ui->labelWalletStatus, &QPushButton::clicked, this, &OverviewPage::outOfSyncWarningClicked);
156  connect(ui->labelTransactionsStatus, &QPushButton::clicked, this, &OverviewPage::outOfSyncWarningClicked);
157 }
158 
159 void OverviewPage::handleTransactionClicked(const QModelIndex &index)
160 {
161  if(filter)
162  Q_EMIT transactionClicked(filter->mapToSource(index));
163 }
164 
165 void OverviewPage::setPrivacy(bool privacy)
166 {
167  m_privacy = privacy;
168  clientModel->getOptionsModel()->setOption(OptionsModel::OptionID::MaskValues, privacy);
169  const auto& balances = walletModel->getCachedBalance();
170  if (balances.balance != -1) {
171  setBalance(balances);
172  }
173 
174  ui->listTransactions->setVisible(!m_privacy);
175 
176  const QString status_tip = m_privacy ? tr("Privacy mode activated for the Overview tab. To unmask the values, uncheck Settings->Mask values.") : "";
177  setStatusTip(status_tip);
178  QStatusTipEvent event(status_tip);
179  QApplication::sendEvent(this, &event);
180 }
181 
183 {
184  delete ui;
185 }
186 
188 {
194  // only show immature (newly mined) balance if it's non-zero, so as not to complicate things
195  // for the non-mining users
196  bool showImmature = balances.immature_balance != 0;
197 
198  ui->labelImmature->setVisible(showImmature);
199  ui->labelImmatureText->setVisible(showImmature);
200 }
201 
203 {
204  this->clientModel = model;
205  if (model) {
206  // Show warning, for example if this is a prerelease version
209 
212  }
213 }
214 
216 {
217  this->walletModel = model;
218  if(model && model->getOptionsModel())
219  {
220  // Set up transaction list
221  filter.reset(new TransactionFilterProxy());
222  filter->setSourceModel(model->getTransactionTableModel());
223  filter->setDynamicSortFilter(true);
224  filter->setSortRole(Qt::EditRole);
225  filter->setShowInactive(false);
226  filter->sort(TransactionTableModel::Date, Qt::DescendingOrder);
227 
228  ui->listTransactions->setModel(filter.get());
229  ui->listTransactions->setModelColumn(TransactionTableModel::ToAddress);
230 
231  connect(filter.get(), &TransactionFilterProxy::rowsInserted, this, &OverviewPage::LimitTransactionRows);
232  connect(filter.get(), &TransactionFilterProxy::rowsRemoved, this, &OverviewPage::LimitTransactionRows);
233  connect(filter.get(), &TransactionFilterProxy::rowsMoved, this, &OverviewPage::LimitTransactionRows);
235  // Keep up to date with wallet
236  setBalance(model->getCachedBalance());
237  connect(model, &WalletModel::balanceChanged, this, &OverviewPage::setBalance);
238 
240  }
241 
242  // update the display unit, to not use the default ("BTC")
244 }
245 
247 {
248  if (e->type() == QEvent::PaletteChange) {
249  QIcon icon = m_platform_style->SingleColorIcon(QStringLiteral(":/icons/warning"));
250  ui->labelTransactionsStatus->setIcon(icon);
251  ui->labelWalletStatus->setIcon(icon);
252  }
253 
254  QWidget::changeEvent(e);
255 }
256 
257 // Only show most recent NUM_ITEMS rows
259 {
260  if (filter && ui->listTransactions && ui->listTransactions->model() && filter.get() == ui->listTransactions->model()) {
261  for (int i = 0; i < filter->rowCount(); ++i) {
262  ui->listTransactions->setRowHidden(i, i >= NUM_ITEMS);
263  }
264  }
265 }
266 
268 {
270  const auto& balances = walletModel->getCachedBalance();
271  if (balances.balance != -1) {
272  setBalance(balances);
273  }
274 
275  // Update txdelegate->unit with the current unit
277 
278  ui->listTransactions->update();
279  }
280 }
281 
282 void OverviewPage::updateAlerts(const QString &warnings)
283 {
284  this->ui->labelAlerts->setVisible(!warnings.isEmpty());
285  this->ui->labelAlerts->setText(warnings);
286 }
287 
289 {
290  ui->labelWalletStatus->setVisible(fShow);
291  ui->labelTransactionsStatus->setVisible(fShow);
292 }
293 
295 {
296  ui->labelBalance->setFont(f);
297  ui->labelUnconfirmed->setFont(f);
298  ui->labelImmature->setFont(f);
299  ui->labelTotal->setFont(f);
300 }
OptionsModel * getOptionsModel() const
void setWalletModel(WalletModel *walletModel)
Unit
Bitcoin units.
Definition: bitcoinunits.h:42
void updateAlerts(const QString &warnings)
std::map< int, int > m_minimum_width
#define DECORATION_SIZE
void width_changed(const QModelIndex &index) const
An intermediate signal for emitting from the paint() const member function.
void handleTransactionClicked(const QModelIndex &index)
void setPrivacy(bool privacy)
std::unique_ptr< TransactionFilterProxy > filter
Definition: overviewpage.h:60
void paint(QPainter *painter, const QStyleOptionViewItem &option, const QModelIndex &index) const override
interfaces::WalletBalances getCachedBalance() const
TransactionTableModel * getTransactionTableModel() const
QString dateTimeStr(const QDateTime &date)
Definition: guiutil.cpp:90
TxViewDelegate(const PlatformStyle *_platformStyle, QObject *parent=nullptr)
BitcoinUnit getDisplayUnit() const
Definition: optionsmodel.h:103
OptionsModel * getOptionsModel()
QIcon SingleColorIcon(const QString &filename) const
Colorize an icon (given filename) with the icon color.
TxViewDelegate * txdelegate
Definition: overviewpage.h:59
WalletModel * walletModel
Definition: overviewpage.h:54
void changeEvent(QEvent *e) override
void outOfSyncWarningClicked()
QString getStatusBarWarnings() const
Return warnings to be displayed in status bar.
void alertsChanged(const QString &warnings)
static QString formatWithUnit(Unit unit, const CAmount &amount, bool plussign=false, SeparatorStyle separators=SeparatorStyle::STANDARD)
Format as string (with unit)
void LimitTransactionRows()
bool setOption(OptionID option, const QVariant &value, const std::string &suffix="")
void setMonospacedFont(const QFont &)
static QString formatWithPrivacy(Unit unit, const CAmount &amount, SeparatorStyle separators, bool privacy)
Format as string (with unit) of fixed length to preserve privacy, if it is set.
void displayUnitChanged(BitcoinUnit unit)
#define NUM_ITEMS
Collection of wallet balances.
Definition: wallet.h:367
BitcoinUnit unit
Date and time this transaction was created.
#define COLOR_UNCONFIRMED
Definition: guiconstants.h:31
Model for Bitcoin network client.
Definition: clientmodel.h:56
ClientModel * clientModel
Definition: overviewpage.h:53
void transactionClicked(const QModelIndex &index)
const PlatformStyle * platformStyle
void showOutOfSyncWarning(bool fShow)
const PlatformStyle * m_platform_style
Definition: overviewpage.h:57
Filter the transaction list according to pre-specified rules.
void updateDisplayUnit()
Interface to Bitcoin wallet from Qt view code.
Definition: walletmodel.h:48
QFont getFontForMoney() const
void setClientModel(ClientModel *clientModel)
QSize sizeHint(const QStyleOptionViewItem &option, const QModelIndex &index) const override
void setBalance(const interfaces::WalletBalances &balances)
OverviewPage(const PlatformStyle *platformStyle, QWidget *parent=nullptr)
void fontForMoneyChanged(const QFont &)
Overview ("home") page widget.
Definition: overviewpage.h:28
Ui::OverviewPage * ui
Definition: overviewpage.h:52
void balanceChanged(const interfaces::WalletBalances &balances)
#define COLOR_NEGATIVE
Definition: guiconstants.h:33