]>
Commit | Line | Data |
---|---|---|
f914f1a7 | 1 | // Copyright (c) 2011-2013 The Bitcoin Core developers |
78253fcb | 2 | // Distributed under the MIT software license, see the accompanying |
e592d43f WL |
3 | // file COPYING or http://www.opensource.org/licenses/mit-license.php. |
4 | ||
64c8b699 WL |
5 | #include "overviewpage.h" |
6 | #include "ui_overviewpage.h" | |
7 | ||
e285ffcd | 8 | #include "bitcoinunits.h" |
51ed9ec9 BD |
9 | #include "clientmodel.h" |
10 | #include "guiconstants.h" | |
11 | #include "guiutil.h" | |
ee014e5b | 12 | #include "optionsmodel.h" |
9b7d3fb1 | 13 | #include "scicon.h" |
a99ac8d3 | 14 | #include "transactionfilterproxy.h" |
51ed9ec9 BD |
15 | #include "transactiontablemodel.h" |
16 | #include "walletmodel.h" | |
ee014e5b | 17 | |
2ccd4759 | 18 | #include <QAbstractItemDelegate> |
a99ac8d3 WL |
19 | #include <QPainter> |
20 | ||
2a6b8444 JS |
21 | #define DECORATION_SIZE 54 |
22 | #define NUM_ITEMS 5 | |
82303fc3 | 23 | |
2ccd4759 | 24 | class TxViewDelegate : public QAbstractItemDelegate |
a99ac8d3 | 25 | { |
9b490f71 | 26 | Q_OBJECT |
a99ac8d3 | 27 | public: |
2ccd4759 | 28 | TxViewDelegate(): QAbstractItemDelegate(), unit(BitcoinUnits::BTC) |
a99ac8d3 WL |
29 | { |
30 | ||
31 | } | |
32 | ||
33 | inline void paint(QPainter *painter, const QStyleOptionViewItem &option, | |
34 | const QModelIndex &index ) const | |
35 | { | |
a99ac8d3 WL |
36 | painter->save(); |
37 | ||
9b7d3fb1 | 38 | QIcon icon = qvariant_cast<QIcon>(index.data(TransactionTableModel::RawDecorationRole)); |
a99ac8d3 WL |
39 | QRect mainRect = option.rect; |
40 | QRect decorationRect(mainRect.topLeft(), QSize(DECORATION_SIZE, DECORATION_SIZE)); | |
41 | int xspace = DECORATION_SIZE + 8; | |
42 | int ypad = 6; | |
43 | int halfheight = (mainRect.height() - 2*ypad)/2; | |
44 | QRect amountRect(mainRect.left() + xspace, mainRect.top()+ypad, mainRect.width() - xspace, halfheight); | |
45 | QRect addressRect(mainRect.left() + xspace, mainRect.top()+ypad+halfheight, mainRect.width() - xspace, halfheight); | |
9b7d3fb1 | 46 | icon = SingleColorIcon(icon, SingleColor()); |
a99ac8d3 WL |
47 | icon.paint(painter, decorationRect); |
48 | ||
49 | QDateTime date = index.data(TransactionTableModel::DateRole).toDateTime(); | |
50 | QString address = index.data(Qt::DisplayRole).toString(); | |
51 | qint64 amount = index.data(TransactionTableModel::AmountRole).toLongLong(); | |
52 | bool confirmed = index.data(TransactionTableModel::ConfirmedRole).toBool(); | |
53 | QVariant value = index.data(Qt::ForegroundRole); | |
54 | QColor foreground = option.palette.color(QPalette::Text); | |
41fdc1ca | 55 | if(value.canConvert<QBrush>()) |
a99ac8d3 | 56 | { |
41fdc1ca PK |
57 | QBrush brush = qvariant_cast<QBrush>(value); |
58 | foreground = brush.color(); | |
a99ac8d3 WL |
59 | } |
60 | ||
61 | painter->setPen(foreground); | |
1c5f0af0 CL |
62 | QRect boundingRect; |
63 | painter->drawText(addressRect, Qt::AlignLeft|Qt::AlignVCenter, address, &boundingRect); | |
64 | ||
65 | if (index.data(TransactionTableModel::WatchonlyRole).toBool()) | |
66 | { | |
67 | QIcon iconWatchonly = qvariant_cast<QIcon>(index.data(TransactionTableModel::WatchonlyDecorationRole)); | |
68 | QRect watchonlyRect(boundingRect.right() + 5, mainRect.top()+ypad+halfheight, 16, halfheight); | |
69 | iconWatchonly.paint(painter, watchonlyRect); | |
70 | } | |
a99ac8d3 WL |
71 | |
72 | if(amount < 0) | |
73 | { | |
74 | foreground = COLOR_NEGATIVE; | |
75 | } | |
82303fc3 WL |
76 | else if(!confirmed) |
77 | { | |
78 | foreground = COLOR_UNCONFIRMED; | |
79 | } | |
a99ac8d3 WL |
80 | else |
81 | { | |
82 | foreground = option.palette.color(QPalette::Text); | |
83 | } | |
84 | painter->setPen(foreground); | |
f7d70c60 | 85 | QString amountText = BitcoinUnits::formatWithUnit(unit, amount, true, BitcoinUnits::separatorAlways); |
a99ac8d3 WL |
86 | if(!confirmed) |
87 | { | |
88 | amountText = QString("[") + amountText + QString("]"); | |
89 | } | |
90 | painter->drawText(amountRect, Qt::AlignRight|Qt::AlignVCenter, amountText); | |
91 | ||
92 | painter->setPen(option.palette.color(QPalette::Text)); | |
b0849613 | 93 | painter->drawText(amountRect, Qt::AlignLeft|Qt::AlignVCenter, GUIUtil::dateTimeStr(date)); |
a99ac8d3 WL |
94 | |
95 | painter->restore(); | |
96 | } | |
97 | ||
2ccd4759 WL |
98 | inline QSize sizeHint(const QStyleOptionViewItem &option, const QModelIndex &index) const |
99 | { | |
100 | return QSize(DECORATION_SIZE, DECORATION_SIZE); | |
101 | } | |
102 | ||
a99ac8d3 WL |
103 | int unit; |
104 | ||
105 | }; | |
9b490f71 | 106 | #include "overviewpage.moc" |
64c8b699 WL |
107 | |
108 | OverviewPage::OverviewPage(QWidget *parent) : | |
109 | QWidget(parent), | |
ee014e5b | 110 | ui(new Ui::OverviewPage), |
62e21fb5 WL |
111 | clientModel(0), |
112 | walletModel(0), | |
ee014e5b | 113 | currentBalance(-1), |
a99ac8d3 | 114 | currentUnconfirmedBalance(-1), |
8fdb7e10 | 115 | currentImmatureBalance(-1), |
ffd40da3 J |
116 | currentWatchOnlyBalance(-1), |
117 | currentWatchUnconfBalance(-1), | |
118 | currentWatchImmatureBalance(-1), | |
8fdb7e10 | 119 | txdelegate(new TxViewDelegate()), |
120 | filter(0) | |
64c8b699 WL |
121 | { |
122 | ui->setupUi(this); | |
123 | ||
16d9cb7e JS |
124 | // use a SingleColorIcon for the "out of sync warning" icon |
125 | QIcon icon = SingleColorIcon(":/icons/warning"); | |
126 | 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) | |
127 | ui->labelTransactionsStatus->setIcon(icon); | |
128 | ui->labelWalletStatus->setIcon(icon); | |
129 | ||
a99ac8d3 | 130 | // Recent transactions |
a99ac8d3 WL |
131 | ui->listTransactions->setItemDelegate(txdelegate); |
132 | ui->listTransactions->setIconSize(QSize(DECORATION_SIZE, DECORATION_SIZE)); | |
82303fc3 | 133 | ui->listTransactions->setMinimumHeight(NUM_ITEMS * (DECORATION_SIZE + 2)); |
527137e3 | 134 | ui->listTransactions->setAttribute(Qt::WA_MacShowFocusRect, false); |
1b392019 | 135 | |
3ef1f415 | 136 | connect(ui->listTransactions, SIGNAL(clicked(QModelIndex)), this, SLOT(handleTransactionClicked(QModelIndex))); |
c26f3a9b | 137 | |
c26f3a9b PK |
138 | // start with displaying the "out of sync" warnings |
139 | showOutOfSyncWarning(true); | |
3ef1f415 WL |
140 | } |
141 | ||
142 | void OverviewPage::handleTransactionClicked(const QModelIndex &index) | |
143 | { | |
144 | if(filter) | |
145 | emit transactionClicked(filter->mapToSource(index)); | |
64c8b699 WL |
146 | } |
147 | ||
148 | OverviewPage::~OverviewPage() | |
149 | { | |
150 | delete ui; | |
151 | } | |
152 | ||
a372168e | 153 | void OverviewPage::setBalance(const CAmount& balance, const CAmount& unconfirmedBalance, const CAmount& immatureBalance, const CAmount& watchOnlyBalance, const CAmount& watchUnconfBalance, const CAmount& watchImmatureBalance) |
64c8b699 | 154 | { |
62e21fb5 | 155 | int unit = walletModel->getOptionsModel()->getDisplayUnit(); |
ee014e5b WL |
156 | currentBalance = balance; |
157 | currentUnconfirmedBalance = unconfirmedBalance; | |
8fdb7e10 | 158 | currentImmatureBalance = immatureBalance; |
ffd40da3 J |
159 | currentWatchOnlyBalance = watchOnlyBalance; |
160 | currentWatchUnconfBalance = watchUnconfBalance; | |
161 | currentWatchImmatureBalance = watchImmatureBalance; | |
f7d70c60 RB |
162 | ui->labelBalance->setText(BitcoinUnits::formatWithUnit(unit, balance, false, BitcoinUnits::separatorAlways)); |
163 | ui->labelUnconfirmed->setText(BitcoinUnits::formatWithUnit(unit, unconfirmedBalance, false, BitcoinUnits::separatorAlways)); | |
164 | ui->labelImmature->setText(BitcoinUnits::formatWithUnit(unit, immatureBalance, false, BitcoinUnits::separatorAlways)); | |
165 | ui->labelTotal->setText(BitcoinUnits::formatWithUnit(unit, balance + unconfirmedBalance + immatureBalance, false, BitcoinUnits::separatorAlways)); | |
166 | ui->labelWatchAvailable->setText(BitcoinUnits::formatWithUnit(unit, watchOnlyBalance, false, BitcoinUnits::separatorAlways)); | |
167 | ui->labelWatchPending->setText(BitcoinUnits::formatWithUnit(unit, watchUnconfBalance, false, BitcoinUnits::separatorAlways)); | |
168 | ui->labelWatchImmature->setText(BitcoinUnits::formatWithUnit(unit, watchImmatureBalance, false, BitcoinUnits::separatorAlways)); | |
169 | ui->labelWatchTotal->setText(BitcoinUnits::formatWithUnit(unit, watchOnlyBalance + watchUnconfBalance + watchImmatureBalance, false, BitcoinUnits::separatorAlways)); | |
8fdb7e10 | 170 | |
171 | // only show immature (newly mined) balance if it's non-zero, so as not to complicate things | |
172 | // for the non-mining users | |
173 | bool showImmature = immatureBalance != 0; | |
ffd40da3 | 174 | bool showWatchOnlyImmature = watchImmatureBalance != 0; |
ffd40da3 | 175 | |
94e1b9e0 | 176 | // for symmetry reasons also show immature label when the watch-only one is shown |
ffd40da3 J |
177 | ui->labelImmature->setVisible(showImmature || showWatchOnlyImmature); |
178 | ui->labelImmatureText->setVisible(showImmature || showWatchOnlyImmature); | |
fbe0fcae | 179 | ui->labelWatchImmature->setVisible(showWatchOnlyImmature); // show watch-only immature balance |
939ed973 CL |
180 | } |
181 | ||
182 | // show/hide watch-only labels | |
183 | void OverviewPage::updateWatchOnlyLabels(bool showWatchOnly) | |
184 | { | |
185 | ui->labelSpendable->setVisible(showWatchOnly); // show spendable label (only when watch-only is active) | |
186 | ui->labelWatchonly->setVisible(showWatchOnly); // show watch-only label | |
187 | ui->lineWatchBalance->setVisible(showWatchOnly); // show watch-only balance separator line | |
188 | ui->labelWatchAvailable->setVisible(showWatchOnly); // show watch-only available balance | |
189 | ui->labelWatchPending->setVisible(showWatchOnly); // show watch-only pending balance | |
190 | ui->labelWatchTotal->setVisible(showWatchOnly); // show watch-only total balance | |
191 | ||
192 | if (!showWatchOnly) | |
193 | ui->labelWatchImmature->hide(); | |
64c8b699 | 194 | } |
d52a0f3b | 195 | |
62e21fb5 | 196 | void OverviewPage::setClientModel(ClientModel *model) |
df5ccbd2 | 197 | { |
62e21fb5 WL |
198 | this->clientModel = model; |
199 | if(model) | |
200 | { | |
201 | // Show warning if this is a prerelease version | |
202 | connect(model, SIGNAL(alertsChanged(QString)), this, SLOT(updateAlerts(QString))); | |
203 | updateAlerts(model->getStatusBarWarnings()); | |
204 | } | |
205 | } | |
206 | ||
207 | void OverviewPage::setWalletModel(WalletModel *model) | |
208 | { | |
209 | this->walletModel = model; | |
e0873daf | 210 | if(model && model->getOptionsModel()) |
dead0ff8 WL |
211 | { |
212 | // Set up transaction list | |
3ef1f415 | 213 | filter = new TransactionFilterProxy(); |
dead0ff8 WL |
214 | filter->setSourceModel(model->getTransactionTableModel()); |
215 | filter->setLimit(NUM_ITEMS); | |
216 | filter->setDynamicSortFilter(true); | |
217 | filter->setSortRole(Qt::EditRole); | |
9a3d936f | 218 | filter->setShowInactive(false); |
dead0ff8 | 219 | filter->sort(TransactionTableModel::Status, Qt::DescendingOrder); |
df5ccbd2 | 220 | |
dead0ff8 WL |
221 | ui->listTransactions->setModel(filter); |
222 | ui->listTransactions->setModelColumn(TransactionTableModel::ToAddress); | |
a99ac8d3 | 223 | |
dead0ff8 | 224 | // Keep up to date with wallet |
ffd40da3 J |
225 | setBalance(model->getBalance(), model->getUnconfirmedBalance(), model->getImmatureBalance(), |
226 | model->getWatchBalance(), model->getWatchUnconfirmedBalance(), model->getWatchImmatureBalance()); | |
c122f552 | 227 | connect(model, SIGNAL(balanceChanged(CAmount,CAmount,CAmount,CAmount,CAmount,CAmount)), this, SLOT(setBalance(CAmount,CAmount,CAmount,CAmount,CAmount,CAmount))); |
df5ccbd2 | 228 | |
e0873daf | 229 | connect(model->getOptionsModel(), SIGNAL(displayUnitChanged(int)), this, SLOT(updateDisplayUnit())); |
939ed973 CL |
230 | |
231 | updateWatchOnlyLabels(model->haveWatchOnly()); | |
232 | connect(model, SIGNAL(notifyWatchonlyChanged(bool)), this, SLOT(updateWatchOnlyLabels(bool))); | |
dead0ff8 | 233 | } |
e0873daf PK |
234 | |
235 | // update the display unit, to not use the default ("BTC") | |
236 | updateDisplayUnit(); | |
ee014e5b WL |
237 | } |
238 | ||
e0873daf | 239 | void OverviewPage::updateDisplayUnit() |
ee014e5b | 240 | { |
62e21fb5 | 241 | if(walletModel && walletModel->getOptionsModel()) |
e0873daf PK |
242 | { |
243 | if(currentBalance != -1) | |
ffd40da3 J |
244 | setBalance(currentBalance, currentUnconfirmedBalance, currentImmatureBalance, |
245 | currentWatchOnlyBalance, currentWatchUnconfBalance, currentWatchImmatureBalance); | |
a99ac8d3 | 246 | |
e0873daf | 247 | // Update txdelegate->unit with the current unit |
62e21fb5 | 248 | txdelegate->unit = walletModel->getOptionsModel()->getDisplayUnit(); |
e0873daf PK |
249 | |
250 | ui->listTransactions->update(); | |
251 | } | |
df5ccbd2 | 252 | } |
c26f3a9b | 253 | |
62e21fb5 WL |
254 | void OverviewPage::updateAlerts(const QString &warnings) |
255 | { | |
256 | this->ui->labelAlerts->setVisible(!warnings.isEmpty()); | |
257 | this->ui->labelAlerts->setText(warnings); | |
258 | } | |
259 | ||
c26f3a9b PK |
260 | void OverviewPage::showOutOfSyncWarning(bool fShow) |
261 | { | |
262 | ui->labelWalletStatus->setVisible(fShow); | |
263 | ui->labelTransactionsStatus->setVisible(fShow); | |
264 | } |