diff --git a/src/qt/overviewpage.cpp b/src/qt/overviewpage.cpp index e6d523d960..ea5c4d40e0 100644 --- a/src/qt/overviewpage.cpp +++ b/src/qt/overviewpage.cpp @@ -161,16 +161,46 @@ void OverviewPage::showEvent(QShowEvent *event) updateTransactions(); } +int OverviewPage::getNumTransactionsForView() +{ + // Compute the maximum number of transactions the transaction list widget + // can hold without overflowing. + const size_t itemHeight = DECORATION_SIZE + ui->listTransactions->spacing(); + const size_t contentsHeight = ui->listTransactions->height(); + const int numItems = contentsHeight / itemHeight; + + return numItems; +} + + void OverviewPage::updateTransactions() { - if(filter) + if (filter) { - // Show the maximum number of transactions the transaction list widget - // can hold without overflowing. - const size_t itemHeight = DECORATION_SIZE + ui->listTransactions->spacing(); - const size_t contentsHeight = ui->listTransactions->height(); - const size_t numItems = contentsHeight / itemHeight; - filter->setLimit(numItems); + int numItems = getNumTransactionsForView(); + + // This is a "stairstep" approach, using x3 to x6 factors to size the setLimit. + // Based on testing with a wallet with a large number of transactions (40k+) + // Using a factor of three is a good balance between the setRowHidden loop + // and the very high expense of the getLimit call, which invalidates the filter + // and sort, and implicitly redoes the sort, which can take seconds for a large + // wallet. + + // Most main window resizes will be done without an actual call to setLimit. + if (filter->getLimit() < numItems) + { + filter->setLimit(numItems * 3); + } + else if (filter->getLimit() > numItems * 6) + { + filter->setLimit(numItems * 3); + } + + for (int i = 0; i <= filter->getLimit(); ++i) + { + ui->listTransactions->setRowHidden(i, i >= numItems); + } + ui->listTransactions->update(); } } @@ -240,8 +270,8 @@ void OverviewPage::setWalletModel(WalletModel *model) filter->setDynamicSortFilter(true); filter->setSortRole(Qt::EditRole); filter->setShowInactive(false); + filter->setLimit(getNumTransactionsForView()); filter->sort(TransactionTableModel::Status, Qt::DescendingOrder); - ui->listTransactions->setModel(filter.get()); ui->listTransactions->setModelColumn(TransactionTableModel::ToAddress); @@ -250,6 +280,9 @@ void OverviewPage::setWalletModel(WalletModel *model) connect(model, SIGNAL(balanceChanged(qint64, qint64, qint64, qint64)), this, SLOT(setBalance(qint64, qint64, qint64, qint64))); connect(model->getOptionsModel(), SIGNAL(displayUnitChanged(int)), this, SLOT(updateDisplayUnit())); + + connect(model, SIGNAL(transactionUpdated()), this, SLOT(updateTransactions())); + UpdateBoincUtilization(); } diff --git a/src/qt/overviewpage.h b/src/qt/overviewpage.h index f3e131f9a8..6c870e585f 100644 --- a/src/qt/overviewpage.h +++ b/src/qt/overviewpage.h @@ -47,7 +47,7 @@ public slots: void showEvent(QShowEvent *event); private: - void updateTransactions(); + int getNumTransactionsForView(); Ui::OverviewPage *ui; ResearcherModel *researcherModel; @@ -62,6 +62,7 @@ public slots: private slots: void updateDisplayUnit(); + void updateTransactions(); void updateResearcherStatus(); void updateMagnitude(); void updatePendingAccrual(); diff --git a/src/qt/transactionfilterproxy.cpp b/src/qt/transactionfilterproxy.cpp index 3cea26579a..7cb7498fff 100644 --- a/src/qt/transactionfilterproxy.cpp +++ b/src/qt/transactionfilterproxy.cpp @@ -87,6 +87,11 @@ void TransactionFilterProxy::setLimit(int limit) invalidate(); } +int TransactionFilterProxy::getLimit() +{ + return this->limitRows; +} + void TransactionFilterProxy::setShowInactive(bool showInactive) { this->showInactive = showInactive; diff --git a/src/qt/transactionfilterproxy.h b/src/qt/transactionfilterproxy.h index 2c86f62ab8..429ce1407c 100644 --- a/src/qt/transactionfilterproxy.h +++ b/src/qt/transactionfilterproxy.h @@ -31,6 +31,9 @@ class TransactionFilterProxy : public QSortFilterProxyModel /** Set maximum number of rows returned, -1 if unlimited. */ void setLimit(int limit); + /** Get maximum number of rows returned, -1 if unlimited. */ + int getLimit(); + /** Set whether to show conflicted transactions. */ void setShowInactive(bool showInactive); diff --git a/src/qt/transactiontablemodel.cpp b/src/qt/transactiontablemodel.cpp index 5e9b9fde0f..6f2e292e62 100644 --- a/src/qt/transactiontablemodel.cpp +++ b/src/qt/transactiontablemodel.cpp @@ -115,7 +115,8 @@ class TransactionTablePriv status = CT_DELETED; /* In model, but want to hide, treat as deleted */ } - LogPrint(BCLog::LogFlags::VERBOSE, " inWallet=%i inModel=%i Index=%i-%i showTransaction=%i derivedStatus=%i", inWallet, inModel, lowerIndex, upperIndex, showTransaction, status); + LogPrint(BCLog::LogFlags::VERBOSE, " inWallet=%i inModel=%i Index=%i-%i showTransaction=%i derivedStatus=%i", + inWallet, inModel, lowerIndex, upperIndex, showTransaction, status); switch(status) diff --git a/src/qt/walletmodel.cpp b/src/qt/walletmodel.cpp index 41be1f564f..cce29d8791 100644 --- a/src/qt/walletmodel.cpp +++ b/src/qt/walletmodel.cpp @@ -126,16 +126,24 @@ void WalletModel::checkBalanceChanged() void WalletModel::updateTransaction(const QString &hash, int status) { - if(transactionTableModel) + if (transactionTableModel) + { transactionTableModel->updateTransaction(hash, status); + // Note this is subtly different than the below. If a resync is being done on a wallet + // that already has transactions, the numTransactionsChanged will not be emitted after the + // wallet is loaded because the size() does not change. See the comments in the header file. + emit transactionUpdated(); + } + // Balance and number of transactions might have changed checkBalanceChanged(); int newNumTransactions = getNumTransactions(); - if(cachedNumTransactions != newNumTransactions) + if (cachedNumTransactions != newNumTransactions) { cachedNumTransactions = newNumTransactions; + emit numTransactionsChanged(newNumTransactions); } } diff --git a/src/qt/walletmodel.h b/src/qt/walletmodel.h index ec65ce8279..4f6580ac8e 100644 --- a/src/qt/walletmodel.h +++ b/src/qt/walletmodel.h @@ -163,6 +163,11 @@ public slots: void pollBalanceChanged(); signals: + // Transaction updated. This is necessary because on a resync from zero with an existing wallet. + // the numTransactionsChanged signal will not be emitted, and therefore the overpage transaction list + // needs this signal instead. + void transactionUpdated(); + // Signal that balance in wallet changed void balanceChanged(qint64 balance, qint64 stake, qint64 unconfirmedBalance, qint64 immatureBalance);