You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

overviewpage.cpp 11KB

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