Skip to content

Commit

Permalink
qt: Early subscribe core signals in transaction table model
Browse files Browse the repository at this point in the history
This fixes the case where transaction notifications arrive between
getWalletTxs and subscribeToCoreSignals.
  • Loading branch information
promag committed Dec 2, 2020
1 parent 7f0f01f commit 5d7d363
Showing 1 changed file with 24 additions and 24 deletions.
48 changes: 24 additions & 24 deletions src/qt/transactiontablemodel.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -95,25 +95,27 @@ class TransactionTablePriv
*/
QList<TransactionRecord> cachedWallet;

bool fQueueNotifications = false;
bool m_loaded = false;
int m_progress = 100;
std::vector< TransactionNotification > vQueueNotifications;

void NotifyTransactionChanged(const uint256 &hash, ChangeType status);
void ShowProgress(const std::string &title, int nProgress);
void DispatchNotifications();

/* Query entire wallet anew from core.
*/
void refreshWallet(interfaces::Wallet& wallet)
{
qDebug() << "TransactionTablePriv::refreshWallet";
cachedWallet.clear();
assert(cachedWallet.empty());
{
for (const auto& wtx : wallet.getWalletTxs()) {
if (TransactionRecord::showTransaction()) {
cachedWallet.append(TransactionRecord::decomposeTransaction(wtx));
}
}
}
m_loaded = true;
DispatchNotifications();
}

/* Update our model of the wallet incrementally, to synchronize our model of the wallet
Expand Down Expand Up @@ -248,12 +250,12 @@ TransactionTableModel::TransactionTableModel(const PlatformStyle *_platformStyle
fProcessingQueuedTransactions(false),
platformStyle(_platformStyle)
{
subscribeToCoreSignals();

columns << QString() << QString() << tr("Date") << tr("Type") << tr("Label") << BitcoinUnits::getAmountColumnTitle(walletModel->getOptionsModel()->getDisplayUnit());
priv->refreshWallet(walletModel->wallet());

connect(walletModel->getOptionsModel(), &OptionsModel::displayUnitChanged, this, &TransactionTableModel::updateDisplayUnit);

subscribeToCoreSignals();
}

TransactionTableModel::~TransactionTableModel()
Expand Down Expand Up @@ -712,44 +714,42 @@ void TransactionTablePriv::NotifyTransactionChanged(const uint256 &hash, ChangeT

TransactionNotification notification(hash, status, showTransaction);

if (fQueueNotifications)
if (!m_loaded || m_progress < 100)
{
vQueueNotifications.push_back(notification);
return;
}
notification.invoke(parent);
}

void TransactionTablePriv::ShowProgress(const std::string &title, int nProgress)
void TransactionTablePriv::DispatchNotifications()
{
if (nProgress == 0)
fQueueNotifications = true;
if (!m_loaded || m_progress < 100) return;

if (nProgress == 100)
if (vQueueNotifications.size() > 10) { // prevent balloon spam, show maximum 10 balloons
bool invoked = QMetaObject::invokeMethod(parent, "setProcessingQueuedTransactions", Qt::QueuedConnection, Q_ARG(bool, true));
assert(invoked);
}
for (unsigned int i = 0; i < vQueueNotifications.size(); ++i)
{
fQueueNotifications = false;
if (vQueueNotifications.size() > 10) { // prevent balloon spam, show maximum 10 balloons
bool invoked = QMetaObject::invokeMethod(parent, "setProcessingQueuedTransactions", Qt::QueuedConnection, Q_ARG(bool, true));
if (vQueueNotifications.size() - i <= 10) {
bool invoked = QMetaObject::invokeMethod(parent, "setProcessingQueuedTransactions", Qt::QueuedConnection, Q_ARG(bool, false));
assert(invoked);
}
for (unsigned int i = 0; i < vQueueNotifications.size(); ++i)
{
if (vQueueNotifications.size() - i <= 10) {
bool invoked = QMetaObject::invokeMethod(parent, "setProcessingQueuedTransactions", Qt::QueuedConnection, Q_ARG(bool, false));
assert(invoked);
}

vQueueNotifications[i].invoke(parent);
}
vQueueNotifications.clear();
vQueueNotifications[i].invoke(parent);
}
vQueueNotifications.clear();
}

void TransactionTableModel::subscribeToCoreSignals()
{
// Connect signals to wallet
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));
m_handler_show_progress = walletModel->wallet().handleShowProgress([this](const std::string&, int progress) {
priv->m_progress = progress;
priv->DispatchNotifications();
});
}

void TransactionTableModel::unsubscribeFromCoreSignals()
Expand Down

0 comments on commit 5d7d363

Please sign in to comment.