LCOV - code coverage report
Current view: top level - src/qt - overviewpage.cpp (source / functions) Hit Total Coverage
Test: total_coverage.info Lines: 0 184 0.0 %
Date: 2020-09-26 01:30:44 Functions: 0 24 0.0 %

          Line data    Source code
       1             : // Copyright (c) 2011-2019 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>
      14             : #include <qt/transactionfilterproxy.h>
      15             : #include <qt/transactiontablemodel.h>
      16             : #include <qt/walletmodel.h>
      17             : 
      18             : #include <QAbstractItemDelegate>
      19             : #include <QApplication>
      20             : #include <QPainter>
      21             : #include <QStatusTipEvent>
      22             : 
      23             : #define DECORATION_SIZE 54
      24             : #define NUM_ITEMS 5
      25             : 
      26           0 : Q_DECLARE_METATYPE(interfaces::WalletBalances)
      27             : 
      28           0 : class TxViewDelegate : public QAbstractItemDelegate
      29             : {
      30             :     Q_OBJECT
      31             : public:
      32           0 :     explicit TxViewDelegate(const PlatformStyle *_platformStyle, QObject *parent=nullptr):
      33           0 :         QAbstractItemDelegate(parent), unit(BitcoinUnits::BTC),
      34           0 :         platformStyle(_platformStyle)
      35           0 :     {
      36             : 
      37           0 :     }
      38             : 
      39           0 :     inline void paint(QPainter *painter, const QStyleOptionViewItem &option,
      40             :                       const QModelIndex &index ) const override
      41             :     {
      42           0 :         painter->save();
      43             : 
      44           0 :         QIcon icon = qvariant_cast<QIcon>(index.data(TransactionTableModel::RawDecorationRole));
      45           0 :         QRect mainRect = option.rect;
      46           0 :         QRect decorationRect(mainRect.topLeft(), QSize(DECORATION_SIZE, DECORATION_SIZE));
      47             :         int xspace = DECORATION_SIZE + 8;
      48             :         int ypad = 6;
      49           0 :         int halfheight = (mainRect.height() - 2*ypad)/2;
      50           0 :         QRect amountRect(mainRect.left() + xspace, mainRect.top()+ypad, mainRect.width() - xspace, halfheight);
      51           0 :         QRect addressRect(mainRect.left() + xspace, mainRect.top()+ypad+halfheight, mainRect.width() - xspace, halfheight);
      52           0 :         icon = platformStyle->SingleColorIcon(icon);
      53           0 :         icon.paint(painter, decorationRect);
      54             : 
      55           0 :         QDateTime date = index.data(TransactionTableModel::DateRole).toDateTime();
      56           0 :         QString address = index.data(Qt::DisplayRole).toString();
      57           0 :         qint64 amount = index.data(TransactionTableModel::AmountRole).toLongLong();
      58           0 :         bool confirmed = index.data(TransactionTableModel::ConfirmedRole).toBool();
      59           0 :         QVariant value = index.data(Qt::ForegroundRole);
      60           0 :         QColor foreground = option.palette.color(QPalette::Text);
      61           0 :         if(value.canConvert<QBrush>())
      62             :         {
      63           0 :             QBrush brush = qvariant_cast<QBrush>(value);
      64           0 :             foreground = brush.color();
      65           0 :         }
      66             : 
      67           0 :         painter->setPen(foreground);
      68           0 :         QRect boundingRect;
      69           0 :         painter->drawText(addressRect, Qt::AlignLeft|Qt::AlignVCenter, address, &boundingRect);
      70             : 
      71           0 :         if (index.data(TransactionTableModel::WatchonlyRole).toBool())
      72             :         {
      73           0 :             QIcon iconWatchonly = qvariant_cast<QIcon>(index.data(TransactionTableModel::WatchonlyDecorationRole));
      74           0 :             QRect watchonlyRect(boundingRect.right() + 5, mainRect.top()+ypad+halfheight, 16, halfheight);
      75           0 :             iconWatchonly.paint(painter, watchonlyRect);
      76           0 :         }
      77             : 
      78           0 :         if(amount < 0)
      79             :         {
      80           0 :             foreground = COLOR_NEGATIVE;
      81           0 :         }
      82           0 :         else if(!confirmed)
      83             :         {
      84           0 :             foreground = COLOR_UNCONFIRMED;
      85           0 :         }
      86             :         else
      87             :         {
      88           0 :             foreground = option.palette.color(QPalette::Text);
      89             :         }
      90           0 :         painter->setPen(foreground);
      91           0 :         QString amountText = BitcoinUnits::formatWithUnit(unit, amount, true, BitcoinUnits::SeparatorStyle::ALWAYS);
      92           0 :         if(!confirmed)
      93             :         {
      94           0 :             amountText = QString("[") + amountText + QString("]");
      95           0 :         }
      96           0 :         painter->drawText(amountRect, Qt::AlignRight|Qt::AlignVCenter, amountText);
      97             : 
      98           0 :         painter->setPen(option.palette.color(QPalette::Text));
      99           0 :         painter->drawText(amountRect, Qt::AlignLeft|Qt::AlignVCenter, GUIUtil::dateTimeStr(date));
     100             : 
     101           0 :         painter->restore();
     102           0 :     }
     103             : 
     104           0 :     inline QSize sizeHint(const QStyleOptionViewItem &option, const QModelIndex &index) const override
     105             :     {
     106           0 :         return QSize(DECORATION_SIZE, DECORATION_SIZE);
     107             :     }
     108             : 
     109             :     int unit;
     110             :     const PlatformStyle *platformStyle;
     111             : 
     112             : };
     113             : #include <qt/overviewpage.moc>
     114             : 
     115           0 : OverviewPage::OverviewPage(const PlatformStyle *platformStyle, QWidget *parent) :
     116           0 :     QWidget(parent),
     117           0 :     ui(new Ui::OverviewPage),
     118           0 :     clientModel(nullptr),
     119           0 :     walletModel(nullptr),
     120           0 :     txdelegate(new TxViewDelegate(platformStyle, this))
     121           0 : {
     122           0 :     ui->setupUi(this);
     123             : 
     124           0 :     m_balances.balance = -1;
     125             : 
     126             :     // use a SingleColorIcon for the "out of sync warning" icon
     127           0 :     QIcon icon = platformStyle->SingleColorIcon(":/icons/warning");
     128           0 :     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           0 :     ui->labelTransactionsStatus->setIcon(icon);
     130           0 :     ui->labelWalletStatus->setIcon(icon);
     131             : 
     132             :     // Recent transactions
     133           0 :     ui->listTransactions->setItemDelegate(txdelegate);
     134           0 :     ui->listTransactions->setIconSize(QSize(DECORATION_SIZE, DECORATION_SIZE));
     135           0 :     ui->listTransactions->setMinimumHeight(NUM_ITEMS * (DECORATION_SIZE + 2));
     136           0 :     ui->listTransactions->setAttribute(Qt::WA_MacShowFocusRect, false);
     137             : 
     138           0 :     connect(ui->listTransactions, &QListView::clicked, this, &OverviewPage::handleTransactionClicked);
     139             : 
     140             :     // start with displaying the "out of sync" warnings
     141           0 :     showOutOfSyncWarning(true);
     142           0 :     connect(ui->labelWalletStatus, &QPushButton::clicked, this, &OverviewPage::handleOutOfSyncWarningClicks);
     143           0 :     connect(ui->labelTransactionsStatus, &QPushButton::clicked, this, &OverviewPage::handleOutOfSyncWarningClicks);
     144           0 : }
     145             : 
     146           0 : void OverviewPage::handleTransactionClicked(const QModelIndex &index)
     147             : {
     148           0 :     if(filter)
     149           0 :         Q_EMIT transactionClicked(filter->mapToSource(index));
     150           0 : }
     151             : 
     152           0 : void OverviewPage::handleOutOfSyncWarningClicks()
     153             : {
     154           0 :     Q_EMIT outOfSyncWarningClicked();
     155           0 : }
     156             : 
     157           0 : void OverviewPage::setPrivacy(bool privacy)
     158             : {
     159           0 :     m_privacy = privacy;
     160           0 :     if (m_balances.balance != -1) {
     161           0 :         setBalance(m_balances);
     162           0 :     }
     163             : 
     164           0 :     ui->listTransactions->setVisible(!m_privacy);
     165             : 
     166           0 :     const QString status_tip = m_privacy ? tr("Privacy mode activated for the Overview tab. To unmask the values, uncheck Settings->Mask values.") : "";
     167           0 :     setStatusTip(status_tip);
     168           0 :     QStatusTipEvent event(status_tip);
     169           0 :     QApplication::sendEvent(this, &event);
     170           0 : }
     171             : 
     172           0 : OverviewPage::~OverviewPage()
     173           0 : {
     174           0 :     delete ui;
     175           0 : }
     176             : 
     177           0 : void OverviewPage::setBalance(const interfaces::WalletBalances& balances)
     178             : {
     179           0 :     int unit = walletModel->getOptionsModel()->getDisplayUnit();
     180           0 :     m_balances = balances;
     181           0 :     if (walletModel->wallet().isLegacy()) {
     182           0 :         if (walletModel->wallet().privateKeysDisabled()) {
     183           0 :             ui->labelBalance->setText(BitcoinUnits::formatWithPrivacy(unit, balances.watch_only_balance, BitcoinUnits::SeparatorStyle::ALWAYS, m_privacy));
     184           0 :             ui->labelUnconfirmed->setText(BitcoinUnits::formatWithPrivacy(unit, balances.unconfirmed_watch_only_balance, BitcoinUnits::SeparatorStyle::ALWAYS, m_privacy));
     185           0 :             ui->labelImmature->setText(BitcoinUnits::formatWithPrivacy(unit, balances.immature_watch_only_balance, BitcoinUnits::SeparatorStyle::ALWAYS, m_privacy));
     186           0 :             ui->labelTotal->setText(BitcoinUnits::formatWithPrivacy(unit, balances.watch_only_balance + balances.unconfirmed_watch_only_balance + balances.immature_watch_only_balance, BitcoinUnits::SeparatorStyle::ALWAYS, m_privacy));
     187           0 :         } else {
     188           0 :             ui->labelBalance->setText(BitcoinUnits::formatWithPrivacy(unit, balances.balance, BitcoinUnits::SeparatorStyle::ALWAYS, m_privacy));
     189           0 :             ui->labelUnconfirmed->setText(BitcoinUnits::formatWithPrivacy(unit, balances.unconfirmed_balance, BitcoinUnits::SeparatorStyle::ALWAYS, m_privacy));
     190           0 :             ui->labelImmature->setText(BitcoinUnits::formatWithPrivacy(unit, balances.immature_balance, BitcoinUnits::SeparatorStyle::ALWAYS, m_privacy));
     191           0 :             ui->labelTotal->setText(BitcoinUnits::formatWithPrivacy(unit, balances.balance + balances.unconfirmed_balance + balances.immature_balance, BitcoinUnits::SeparatorStyle::ALWAYS, m_privacy));
     192           0 :             ui->labelWatchAvailable->setText(BitcoinUnits::formatWithPrivacy(unit, balances.watch_only_balance, BitcoinUnits::SeparatorStyle::ALWAYS, m_privacy));
     193           0 :             ui->labelWatchPending->setText(BitcoinUnits::formatWithPrivacy(unit, balances.unconfirmed_watch_only_balance, BitcoinUnits::SeparatorStyle::ALWAYS, m_privacy));
     194           0 :             ui->labelWatchImmature->setText(BitcoinUnits::formatWithPrivacy(unit, balances.immature_watch_only_balance, BitcoinUnits::SeparatorStyle::ALWAYS, m_privacy));
     195           0 :             ui->labelWatchTotal->setText(BitcoinUnits::formatWithPrivacy(unit, balances.watch_only_balance + balances.unconfirmed_watch_only_balance + balances.immature_watch_only_balance, BitcoinUnits::SeparatorStyle::ALWAYS, m_privacy));
     196             :         }
     197             :     } else {
     198           0 :         ui->labelBalance->setText(BitcoinUnits::formatWithPrivacy(unit, balances.balance, BitcoinUnits::SeparatorStyle::ALWAYS, m_privacy));
     199           0 :         ui->labelUnconfirmed->setText(BitcoinUnits::formatWithPrivacy(unit, balances.unconfirmed_balance, BitcoinUnits::SeparatorStyle::ALWAYS, m_privacy));
     200           0 :         ui->labelImmature->setText(BitcoinUnits::formatWithPrivacy(unit, balances.immature_balance, BitcoinUnits::SeparatorStyle::ALWAYS, m_privacy));
     201           0 :         ui->labelTotal->setText(BitcoinUnits::formatWithPrivacy(unit, balances.balance + balances.unconfirmed_balance + balances.immature_balance, BitcoinUnits::SeparatorStyle::ALWAYS, m_privacy));
     202             :     }
     203             :     // only show immature (newly mined) balance if it's non-zero, so as not to complicate things
     204             :     // for the non-mining users
     205           0 :     bool showImmature = balances.immature_balance != 0;
     206           0 :     bool showWatchOnlyImmature = balances.immature_watch_only_balance != 0;
     207             : 
     208             :     // for symmetry reasons also show immature label when the watch-only one is shown
     209           0 :     ui->labelImmature->setVisible(showImmature || showWatchOnlyImmature);
     210           0 :     ui->labelImmatureText->setVisible(showImmature || showWatchOnlyImmature);
     211           0 :     ui->labelWatchImmature->setVisible(!walletModel->wallet().privateKeysDisabled() && showWatchOnlyImmature); // show watch-only immature balance
     212           0 : }
     213             : 
     214             : // show/hide watch-only labels
     215           0 : void OverviewPage::updateWatchOnlyLabels(bool showWatchOnly)
     216             : {
     217           0 :     ui->labelSpendable->setVisible(showWatchOnly);      // show spendable label (only when watch-only is active)
     218           0 :     ui->labelWatchonly->setVisible(showWatchOnly);      // show watch-only label
     219           0 :     ui->lineWatchBalance->setVisible(showWatchOnly);    // show watch-only balance separator line
     220           0 :     ui->labelWatchAvailable->setVisible(showWatchOnly); // show watch-only available balance
     221           0 :     ui->labelWatchPending->setVisible(showWatchOnly);   // show watch-only pending balance
     222           0 :     ui->labelWatchTotal->setVisible(showWatchOnly);     // show watch-only total balance
     223             : 
     224           0 :     if (!showWatchOnly)
     225           0 :         ui->labelWatchImmature->hide();
     226           0 : }
     227             : 
     228           0 : void OverviewPage::setClientModel(ClientModel *model)
     229             : {
     230           0 :     this->clientModel = model;
     231           0 :     if (model) {
     232             :         // Show warning, for example if this is a prerelease version
     233           0 :         connect(model, &ClientModel::alertsChanged, this, &OverviewPage::updateAlerts);
     234           0 :         updateAlerts(model->getStatusBarWarnings());
     235           0 :     }
     236           0 : }
     237             : 
     238           0 : void OverviewPage::setWalletModel(WalletModel *model)
     239             : {
     240           0 :     this->walletModel = model;
     241           0 :     if(model && model->getOptionsModel())
     242             :     {
     243             :         // Set up transaction list
     244           0 :         filter.reset(new TransactionFilterProxy());
     245           0 :         filter->setSourceModel(model->getTransactionTableModel());
     246           0 :         filter->setLimit(NUM_ITEMS);
     247           0 :         filter->setDynamicSortFilter(true);
     248           0 :         filter->setSortRole(Qt::EditRole);
     249           0 :         filter->setShowInactive(false);
     250           0 :         filter->sort(TransactionTableModel::Date, Qt::DescendingOrder);
     251             : 
     252           0 :         ui->listTransactions->setModel(filter.get());
     253           0 :         ui->listTransactions->setModelColumn(TransactionTableModel::ToAddress);
     254             : 
     255             :         // Keep up to date with wallet
     256           0 :         interfaces::Wallet& wallet = model->wallet();
     257           0 :         interfaces::WalletBalances balances = wallet.getBalances();
     258           0 :         setBalance(balances);
     259           0 :         connect(model, &WalletModel::balanceChanged, this, &OverviewPage::setBalance);
     260             : 
     261           0 :         connect(model->getOptionsModel(), &OptionsModel::displayUnitChanged, this, &OverviewPage::updateDisplayUnit);
     262             : 
     263           0 :         updateWatchOnlyLabels(wallet.haveWatchOnly() && !model->wallet().privateKeysDisabled());
     264           0 :         connect(model, &WalletModel::notifyWatchonlyChanged, [this](bool showWatchOnly) {
     265           0 :             updateWatchOnlyLabels(showWatchOnly && !walletModel->wallet().privateKeysDisabled());
     266           0 :         });
     267           0 :     }
     268             : 
     269             :     // update the display unit, to not use the default ("BTC")
     270           0 :     updateDisplayUnit();
     271           0 : }
     272             : 
     273           0 : void OverviewPage::updateDisplayUnit()
     274             : {
     275           0 :     if(walletModel && walletModel->getOptionsModel())
     276             :     {
     277           0 :         if (m_balances.balance != -1) {
     278           0 :             setBalance(m_balances);
     279           0 :         }
     280             : 
     281             :         // Update txdelegate->unit with the current unit
     282           0 :         txdelegate->unit = walletModel->getOptionsModel()->getDisplayUnit();
     283             : 
     284           0 :         ui->listTransactions->update();
     285           0 :     }
     286           0 : }
     287             : 
     288           0 : void OverviewPage::updateAlerts(const QString &warnings)
     289             : {
     290           0 :     this->ui->labelAlerts->setVisible(!warnings.isEmpty());
     291           0 :     this->ui->labelAlerts->setText(warnings);
     292           0 : }
     293             : 
     294           0 : void OverviewPage::showOutOfSyncWarning(bool fShow)
     295             : {
     296           0 :     ui->labelWalletStatus->setVisible(fShow);
     297           0 :     ui->labelTransactionsStatus->setVisible(fShow);
     298           0 : }

Generated by: LCOV version 1.15