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.
5 #include <qt/overviewpage.h>
6 #include <qt/forms/ui_overviewpage.h>
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>
14 #include <qt/transactionfilterproxy.h>
15 #include <qt/transactiontablemodel.h>
16 #include <qt/walletmodel.h>
18 #include <QAbstractItemDelegate>
21 #define DECORATION_SIZE 54
24 class TxViewDelegate
: public QAbstractItemDelegate
28 explicit TxViewDelegate(const PlatformStyle
*_platformStyle
, QObject
*parent
=nullptr):
29 QAbstractItemDelegate(parent
), unit(BitcoinUnits::BTC
),
30 platformStyle(_platformStyle
)
35 inline void paint(QPainter
*painter
, const QStyleOptionViewItem
&option
,
36 const QModelIndex
&index
) const
40 QIcon icon
= qvariant_cast
<QIcon
>(index
.data(TransactionTableModel::RawDecorationRole
));
41 QRect mainRect
= option
.rect
;
42 QRect
decorationRect(mainRect
.topLeft(), QSize(DECORATION_SIZE
, DECORATION_SIZE
));
43 int xspace
= DECORATION_SIZE
+ 8;
45 int halfheight
= (mainRect
.height() - 2*ypad
)/2;
46 QRect
amountRect(mainRect
.left() + xspace
, mainRect
.top()+ypad
, mainRect
.width() - xspace
, halfheight
);
47 QRect
addressRect(mainRect
.left() + xspace
, mainRect
.top()+ypad
+halfheight
, mainRect
.width() - xspace
, halfheight
);
48 icon
= platformStyle
->SingleColorIcon(icon
);
49 icon
.paint(painter
, decorationRect
);
51 QDateTime date
= index
.data(TransactionTableModel::DateRole
).toDateTime();
52 QString address
= index
.data(Qt::DisplayRole
).toString();
53 qint64 amount
= index
.data(TransactionTableModel::AmountRole
).toLongLong();
54 bool confirmed
= index
.data(TransactionTableModel::ConfirmedRole
).toBool();
55 QVariant value
= index
.data(Qt::ForegroundRole
);
56 QColor foreground
= option
.palette
.color(QPalette::Text
);
57 if(value
.canConvert
<QBrush
>())
59 QBrush brush
= qvariant_cast
<QBrush
>(value
);
60 foreground
= brush
.color();
63 painter
->setPen(foreground
);
65 painter
->drawText(addressRect
, Qt::AlignLeft
|Qt::AlignVCenter
, address
, &boundingRect
);
67 if (index
.data(TransactionTableModel::WatchonlyRole
).toBool())
69 QIcon iconWatchonly
= qvariant_cast
<QIcon
>(index
.data(TransactionTableModel::WatchonlyDecorationRole
));
70 QRect
watchonlyRect(boundingRect
.right() + 5, mainRect
.top()+ypad
+halfheight
, 16, halfheight
);
71 iconWatchonly
.paint(painter
, watchonlyRect
);
76 foreground
= COLOR_NEGATIVE
;
80 foreground
= COLOR_UNCONFIRMED
;
84 foreground
= option
.palette
.color(QPalette::Text
);
86 painter
->setPen(foreground
);
87 QString amountText
= BitcoinUnits::formatWithUnit(unit
, amount
, true, BitcoinUnits::separatorAlways
);
90 amountText
= QString("[") + amountText
+ QString("]");
92 painter
->drawText(amountRect
, Qt::AlignRight
|Qt::AlignVCenter
, amountText
);
94 painter
->setPen(option
.palette
.color(QPalette::Text
));
95 painter
->drawText(amountRect
, Qt::AlignLeft
|Qt::AlignVCenter
, GUIUtil::dateTimeStr(date
));
100 inline QSize
sizeHint(const QStyleOptionViewItem
&option
, const QModelIndex
&index
) const
102 return QSize(DECORATION_SIZE
, DECORATION_SIZE
);
106 const PlatformStyle
*platformStyle
;
109 #include <qt/overviewpage.moc>
111 OverviewPage::OverviewPage(const PlatformStyle
*platformStyle
, QWidget
*parent
) :
113 ui(new Ui::OverviewPage
),
117 currentUnconfirmedBalance(-1),
118 currentImmatureBalance(-1),
119 currentWatchOnlyBalance(-1),
120 currentWatchUnconfBalance(-1),
121 currentWatchImmatureBalance(-1),
122 txdelegate(new TxViewDelegate(platformStyle
, this))
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
);
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);
138 connect(ui
->listTransactions
, SIGNAL(clicked(QModelIndex
)), this, SLOT(handleTransactionClicked(QModelIndex
)));
140 // start with displaying the "out of sync" warnings
141 showOutOfSyncWarning(true);
142 connect(ui
->labelWalletStatus
, SIGNAL(clicked()), this, SLOT(handleOutOfSyncWarningClicks()));
143 connect(ui
->labelTransactionsStatus
, SIGNAL(clicked()), this, SLOT(handleOutOfSyncWarningClicks()));
146 void OverviewPage::handleTransactionClicked(const QModelIndex
&index
)
149 Q_EMIT
transactionClicked(filter
->mapToSource(index
));
152 void OverviewPage::handleOutOfSyncWarningClicks()
154 Q_EMIT
outOfSyncWarningClicked();
157 OverviewPage::~OverviewPage()
162 void OverviewPage::setBalance(const CAmount
& balance
, const CAmount
& unconfirmedBalance
, const CAmount
& immatureBalance
, const CAmount
& watchOnlyBalance
, const CAmount
& watchUnconfBalance
, const CAmount
& watchImmatureBalance
)
164 int unit
= walletModel
->getOptionsModel()->getDisplayUnit();
165 currentBalance
= balance
;
166 currentUnconfirmedBalance
= unconfirmedBalance
;
167 currentImmatureBalance
= immatureBalance
;
168 currentWatchOnlyBalance
= watchOnlyBalance
;
169 currentWatchUnconfBalance
= watchUnconfBalance
;
170 currentWatchImmatureBalance
= watchImmatureBalance
;
171 ui
->labelBalance
->setText(BitcoinUnits::formatWithUnit(unit
, balance
, false, BitcoinUnits::separatorAlways
));
172 ui
->labelUnconfirmed
->setText(BitcoinUnits::formatWithUnit(unit
, unconfirmedBalance
, false, BitcoinUnits::separatorAlways
));
173 ui
->labelImmature
->setText(BitcoinUnits::formatWithUnit(unit
, immatureBalance
, false, BitcoinUnits::separatorAlways
));
174 ui
->labelTotal
->setText(BitcoinUnits::formatWithUnit(unit
, balance
+ unconfirmedBalance
+ immatureBalance
, false, BitcoinUnits::separatorAlways
));
175 ui
->labelWatchAvailable
->setText(BitcoinUnits::formatWithUnit(unit
, watchOnlyBalance
, false, BitcoinUnits::separatorAlways
));
176 ui
->labelWatchPending
->setText(BitcoinUnits::formatWithUnit(unit
, watchUnconfBalance
, false, BitcoinUnits::separatorAlways
));
177 ui
->labelWatchImmature
->setText(BitcoinUnits::formatWithUnit(unit
, watchImmatureBalance
, false, BitcoinUnits::separatorAlways
));
178 ui
->labelWatchTotal
->setText(BitcoinUnits::formatWithUnit(unit
, watchOnlyBalance
+ watchUnconfBalance
+ watchImmatureBalance
, false, BitcoinUnits::separatorAlways
));
180 // only show immature (newly mined) balance if it's non-zero, so as not to complicate things
181 // for the non-mining users
182 bool showImmature
= immatureBalance
!= 0;
183 bool showWatchOnlyImmature
= watchImmatureBalance
!= 0;
185 // for symmetry reasons also show immature label when the watch-only one is shown
186 ui
->labelImmature
->setVisible(showImmature
|| showWatchOnlyImmature
);
187 ui
->labelImmatureText
->setVisible(showImmature
|| showWatchOnlyImmature
);
188 ui
->labelWatchImmature
->setVisible(showWatchOnlyImmature
); // show watch-only immature balance
191 // show/hide watch-only labels
192 void OverviewPage::updateWatchOnlyLabels(bool showWatchOnly
)
194 ui
->labelSpendable
->setVisible(showWatchOnly
); // show spendable label (only when watch-only is active)
195 ui
->labelWatchonly
->setVisible(showWatchOnly
); // show watch-only label
196 ui
->lineWatchBalance
->setVisible(showWatchOnly
); // show watch-only balance separator line
197 ui
->labelWatchAvailable
->setVisible(showWatchOnly
); // show watch-only available balance
198 ui
->labelWatchPending
->setVisible(showWatchOnly
); // show watch-only pending balance
199 ui
->labelWatchTotal
->setVisible(showWatchOnly
); // show watch-only total balance
202 ui
->labelWatchImmature
->hide();
205 void OverviewPage::setClientModel(ClientModel
*model
)
207 this->clientModel
= model
;
210 // Show warning if this is a prerelease version
211 connect(model
, SIGNAL(alertsChanged(QString
)), this, SLOT(updateAlerts(QString
)));
212 updateAlerts(model
->getStatusBarWarnings());
216 void OverviewPage::setWalletModel(WalletModel
*model
)
218 this->walletModel
= model
;
219 if(model
&& model
->getOptionsModel())
221 // Set up transaction list
222 filter
.reset(new TransactionFilterProxy());
223 filter
->setSourceModel(model
->getTransactionTableModel());
224 filter
->setLimit(NUM_ITEMS
);
225 filter
->setDynamicSortFilter(true);
226 filter
->setSortRole(Qt::EditRole
);
227 filter
->setShowInactive(false);
228 filter
->sort(TransactionTableModel::Date
, Qt::DescendingOrder
);
230 ui
->listTransactions
->setModel(filter
.get());
231 ui
->listTransactions
->setModelColumn(TransactionTableModel::ToAddress
);
233 // Keep up to date with wallet
234 setBalance(model
->getBalance(), model
->getUnconfirmedBalance(), model
->getImmatureBalance(),
235 model
->getWatchBalance(), model
->getWatchUnconfirmedBalance(), model
->getWatchImmatureBalance());
236 connect(model
, SIGNAL(balanceChanged(CAmount
,CAmount
,CAmount
,CAmount
,CAmount
,CAmount
)), this, SLOT(setBalance(CAmount
,CAmount
,CAmount
,CAmount
,CAmount
,CAmount
)));
238 connect(model
->getOptionsModel(), SIGNAL(displayUnitChanged(int)), this, SLOT(updateDisplayUnit()));
240 updateWatchOnlyLabels(model
->haveWatchOnly());
241 connect(model
, SIGNAL(notifyWatchonlyChanged(bool)), this, SLOT(updateWatchOnlyLabels(bool)));
244 // update the display unit, to not use the default ("BTC")
248 void OverviewPage::updateDisplayUnit()
250 if(walletModel
&& walletModel
->getOptionsModel())
252 if(currentBalance
!= -1)
253 setBalance(currentBalance
, currentUnconfirmedBalance
, currentImmatureBalance
,
254 currentWatchOnlyBalance
, currentWatchUnconfBalance
, currentWatchImmatureBalance
);
256 // Update txdelegate->unit with the current unit
257 txdelegate
->unit
= walletModel
->getOptionsModel()->getDisplayUnit();
259 ui
->listTransactions
->update();
263 void OverviewPage::updateAlerts(const QString
&warnings
)
265 this->ui
->labelAlerts
->setVisible(!warnings
.isEmpty());
266 this->ui
->labelAlerts
->setText(warnings
);
269 void OverviewPage::showOutOfSyncWarning(bool fShow
)
271 ui
->labelWalletStatus
->setVisible(fShow
);
272 ui
->labelTransactionsStatus
->setVisible(fShow
);