diff options
author | Jonas Schnelli <dev@jonasschnelli.ch> | 2020-11-12 12:23:51 +0100 |
---|---|---|
committer | Jonas Schnelli <dev@jonasschnelli.ch> | 2020-11-12 12:23:55 +0100 |
commit | 9bd1316697292251ed5690390794fc64517fc86b (patch) | |
tree | d62f351ce67c08a84e01d243f64bab16977f78eb | |
parent | 8a486158cbc3f18adf12d2d3b737f7f4e7399e7d (diff) | |
parent | 241434200ec2067673d8522fee4f1228abfd8247 (diff) |
Merge bitcoin-core/gui#120: Fix multiwallet transaction notifications
241434200ec2067673d8522fee4f1228abfd8247 refactor: qt: Use vQueueNotifications.clear() (João Barbosa)
989e579d07bb5031639060b717f7a0be15d10e29 qt: Make transaction notification queue wallet specific (João Barbosa)
7b3b2303f44031c3545651858f697a495c3ea37a move-only: Define TransactionNotification before TransactionTablePriv (João Barbosa)
Pull request description:
Currently `vQueueNotifications` holds transactions of any wallet, but the queue is dispatched on a given wallet and it assumes notifications are of that wallet.
This means that some transactions can be missed if multiple wallets are loaded.
Fix this by having a queue for each wallet.
ACKs for top commit:
jonasschnelli:
utACK 241434200ec2067673d8522fee4f1228abfd8247
hebasto:
ACK 241434200ec2067673d8522fee4f1228abfd8247, I have reviewed the code and it looks OK, I agree it can be merged.
ryanofsky:
Code review ACK 241434200ec2067673d8522fee4f1228abfd8247. Only change is dropping one commit
Tree-SHA512: 61beac5a16ed659e3a25ad145dbceafcef963aaf8f9838355298949ec2324e2bd760f59353cd251d30cf0334d8dc1642a1f3821d8a9eec092533b581f6ce86db
-rw-r--r-- | src/qt/transactiontablemodel.cpp | 75 |
1 files changed, 39 insertions, 36 deletions
diff --git a/src/qt/transactiontablemodel.cpp b/src/qt/transactiontablemodel.cpp index c560dc58e7..3148089b52 100644 --- a/src/qt/transactiontablemodel.cpp +++ b/src/qt/transactiontablemodel.cpp @@ -54,6 +54,30 @@ struct TxLessThan } }; +// queue notifications to show a non freezing progress dialog e.g. for rescan +struct TransactionNotification +{ +public: + TransactionNotification() {} + TransactionNotification(uint256 _hash, ChangeType _status, bool _showTransaction): + hash(_hash), status(_status), showTransaction(_showTransaction) {} + + void invoke(QObject *ttm) + { + QString strHash = QString::fromStdString(hash.GetHex()); + qDebug() << "NotifyTransactionChanged: " + strHash + " status= " + QString::number(status); + bool invoked = QMetaObject::invokeMethod(ttm, "updateTransaction", Qt::QueuedConnection, + Q_ARG(QString, strHash), + Q_ARG(int, status), + Q_ARG(bool, showTransaction)); + assert(invoked); + } +private: + uint256 hash; + ChangeType status; + bool showTransaction; +}; + // Private implementation class TransactionTablePriv { @@ -71,6 +95,12 @@ public: */ QList<TransactionRecord> cachedWallet; + bool fQueueNotifications = false; + std::vector< TransactionNotification > vQueueNotifications; + + void NotifyTransactionChanged(const uint256 &hash, ChangeType status); + void ShowProgress(const std::string &title, int nProgress); + /* Query entire wallet anew from core. */ void refreshWallet(interfaces::Wallet& wallet) @@ -674,34 +704,7 @@ void TransactionTableModel::updateDisplayUnit() Q_EMIT dataChanged(index(0, Amount), index(priv->size()-1, Amount)); } -// queue notifications to show a non freezing progress dialog e.g. for rescan -struct TransactionNotification -{ -public: - TransactionNotification() {} - TransactionNotification(uint256 _hash, ChangeType _status, bool _showTransaction): - hash(_hash), status(_status), showTransaction(_showTransaction) {} - - void invoke(QObject *ttm) - { - QString strHash = QString::fromStdString(hash.GetHex()); - qDebug() << "NotifyTransactionChanged: " + strHash + " status= " + QString::number(status); - bool invoked = QMetaObject::invokeMethod(ttm, "updateTransaction", Qt::QueuedConnection, - Q_ARG(QString, strHash), - Q_ARG(int, status), - Q_ARG(bool, showTransaction)); - assert(invoked); - } -private: - uint256 hash; - ChangeType status; - bool showTransaction; -}; - -static bool fQueueNotifications = false; -static std::vector< TransactionNotification > vQueueNotifications; - -static void NotifyTransactionChanged(TransactionTableModel *ttm, const uint256 &hash, ChangeType status) +void TransactionTablePriv::NotifyTransactionChanged(const uint256 &hash, ChangeType status) { // Find transaction in wallet // Determine whether to show transaction or not (determine this here so that no relocking is needed in GUI thread) @@ -714,10 +717,10 @@ static void NotifyTransactionChanged(TransactionTableModel *ttm, const uint256 & vQueueNotifications.push_back(notification); return; } - notification.invoke(ttm); + notification.invoke(parent); } -static void ShowProgress(TransactionTableModel *ttm, const std::string &title, int nProgress) +void TransactionTablePriv::ShowProgress(const std::string &title, int nProgress) { if (nProgress == 0) fQueueNotifications = true; @@ -726,27 +729,27 @@ static void ShowProgress(TransactionTableModel *ttm, const std::string &title, i { fQueueNotifications = false; if (vQueueNotifications.size() > 10) { // prevent balloon spam, show maximum 10 balloons - bool invoked = QMetaObject::invokeMethod(ttm, "setProcessingQueuedTransactions", Qt::QueuedConnection, Q_ARG(bool, true)); + bool invoked = QMetaObject::invokeMethod(parent, "setProcessingQueuedTransactions", Qt::QueuedConnection, Q_ARG(bool, true)); assert(invoked); } for (unsigned int i = 0; i < vQueueNotifications.size(); ++i) { if (vQueueNotifications.size() - i <= 10) { - bool invoked = QMetaObject::invokeMethod(ttm, "setProcessingQueuedTransactions", Qt::QueuedConnection, Q_ARG(bool, false)); + bool invoked = QMetaObject::invokeMethod(parent, "setProcessingQueuedTransactions", Qt::QueuedConnection, Q_ARG(bool, false)); assert(invoked); } - vQueueNotifications[i].invoke(ttm); + vQueueNotifications[i].invoke(parent); } - std::vector<TransactionNotification >().swap(vQueueNotifications); // clear + vQueueNotifications.clear(); } } void TransactionTableModel::subscribeToCoreSignals() { // Connect signals to wallet - m_handler_transaction_changed = walletModel->wallet().handleTransactionChanged(std::bind(NotifyTransactionChanged, this, std::placeholders::_1, std::placeholders::_2)); - m_handler_show_progress = walletModel->wallet().handleShowProgress(std::bind(ShowProgress, this, std::placeholders::_1, std::placeholders::_2)); + m_handler_transaction_changed = walletModel->wallet().handleTransactionChanged(std::bind(&TransactionTablePriv::NotifyTransactionChanged, priv, std::placeholders::_1, std::placeholders::_2)); + m_handler_show_progress = walletModel->wallet().handleShowProgress(std::bind(&TransactionTablePriv::ShowProgress, priv, std::placeholders::_1, std::placeholders::_2)); } void TransactionTableModel::unsubscribeFromCoreSignals() |