From 98e61758744ed34e8b7f59b37edb6d09b33d5517 Mon Sep 17 00:00:00 2001 From: Wladimir J. van der Laan Date: Sat, 24 Mar 2012 18:48:18 +0100 Subject: [PATCH] Update UI through async calls MainFrameRepaint and AddressBookRepaint instead of a timer. - Overall, this is better design - This fixes problems with the address book UI not updating when the address book is changed through RPC - Move Statusbar change detection responsibility to ClientModel --- src/noui.h | 4 ++++ src/qt/addressbookpage.cpp | 2 -- src/qt/addresstablemodel.cpp | 11 ++--------- src/qt/addresstablemodel.h | 6 ++---- src/qt/bitcoin.cpp | 22 ++++++++++++++++++---- src/qt/bitcoingui.cpp | 13 ------------- src/qt/bitcoingui.h | 2 -- src/qt/clientmodel.cpp | 18 ++++++++++-------- src/qt/clientmodel.h | 1 + src/qt/walletmodel.cpp | 15 +++++---------- src/qt/walletmodel.h | 3 +-- src/qtui.h | 1 + src/wallet.cpp | 2 ++ 13 files changed, 46 insertions(+), 54 deletions(-) diff --git a/src/noui.h b/src/noui.h index 458fc64..e4faa2e 100644 --- a/src/noui.h +++ b/src/noui.h @@ -67,6 +67,10 @@ inline void MainFrameRepaint() { } +inline void AddressBookRepaint() +{ +} + inline void InitMessage(const std::string &message) { } diff --git a/src/qt/addressbookpage.cpp b/src/qt/addressbookpage.cpp index cb185be..8821283 100644 --- a/src/qt/addressbookpage.cpp +++ b/src/qt/addressbookpage.cpp @@ -94,8 +94,6 @@ void AddressBookPage::setModel(AddressTableModel *model) this->model = model; if(!model) return; - // Refresh list from core - model->updateList(); proxyModel = new QSortFilterProxyModel(this); proxyModel->setSourceModel(model); diff --git a/src/qt/addresstablemodel.cpp b/src/qt/addresstablemodel.cpp index 8fd6d52..198a857 100644 --- a/src/qt/addresstablemodel.cpp +++ b/src/qt/addresstablemodel.cpp @@ -231,7 +231,7 @@ QModelIndex AddressTableModel::index(int row, int column, const QModelIndex & pa } } -void AddressTableModel::updateList() +void AddressTableModel::update() { // Update address book model from Bitcoin core beginResetModel(); @@ -285,10 +285,9 @@ QString AddressTableModel::addRow(const QString &type, const QString &label, con { return QString(); } - // Add entry and update list + // Add entry CRITICAL_BLOCK(wallet->cs_wallet) wallet->SetAddressBookName(strAddress, strLabel); - updateList(); return QString::fromStdString(strAddress); } @@ -306,15 +305,9 @@ bool AddressTableModel::removeRows(int row, int count, const QModelIndex & paren { wallet->DelAddressBookName(rec->address.toStdString()); } - updateList(); return true; } -void AddressTableModel::update() -{ - -} - /* Look up label for address in address book, if not found return empty string. */ QString AddressTableModel::labelForAddress(const QString &address) const diff --git a/src/qt/addresstablemodel.h b/src/qt/addresstablemodel.h index 0743300..7fd07cf 100644 --- a/src/qt/addresstablemodel.h +++ b/src/qt/addresstablemodel.h @@ -56,10 +56,6 @@ public: */ QString addRow(const QString &type, const QString &label, const QString &address); - /* Update address list from core. Invalidates any indices. - */ - void updateList(); - /* Look up label for address in address book, if not found return empty string. */ QString labelForAddress(const QString &address) const; @@ -82,6 +78,8 @@ signals: void defaultAddressChanged(const QString &address); public slots: + /* Update address list from core. Invalidates any indices. + */ void update(); }; diff --git a/src/qt/bitcoin.cpp b/src/qt/bitcoin.cpp index 0f7c96e..f330fee 100644 --- a/src/qt/bitcoin.cpp +++ b/src/qt/bitcoin.cpp @@ -33,8 +33,10 @@ Q_IMPORT_PLUGIN(qtaccessiblewidgets) #endif // Need a global reference for the notifications to find the GUI -BitcoinGUI *guiref; -QSplashScreen *splashref; +static BitcoinGUI *guiref; +static QSplashScreen *splashref; +static WalletModel *walletmodel; +static ClientModel *clientmodel; int MyMessageBox(const std::string& message, const std::string& caption, int style, wxWindow* parent, int x, int y) { @@ -98,8 +100,16 @@ void UIThreadCall(boost::function0 fn) void MainFrameRepaint() { - if(guiref) - QMetaObject::invokeMethod(guiref, "refreshStatusBar", Qt::QueuedConnection); + if(clientmodel) + QMetaObject::invokeMethod(clientmodel, "update", Qt::QueuedConnection); + if(walletmodel) + QMetaObject::invokeMethod(walletmodel, "update", Qt::QueuedConnection); +} + +void AddressBookRepaint() +{ + if(walletmodel) + QMetaObject::invokeMethod(walletmodel, "updateAddressList", Qt::QueuedConnection); } void InitMessage(const std::string &message) @@ -230,7 +240,9 @@ int main(int argc, char *argv[]) splash.finish(&window); ClientModel clientModel(&optionsModel); + clientmodel = &clientModel; WalletModel walletModel(pwalletMain, &optionsModel); + walletmodel = &walletModel; guiref = &window; window.setClientModel(&clientModel); @@ -270,6 +282,8 @@ int main(int argc, char *argv[]) app.exec(); guiref = 0; + clientmodel = 0; + walletmodel = 0; } Shutdown(NULL); } diff --git a/src/qt/bitcoingui.cpp b/src/qt/bitcoingui.cpp index cf4e43c..f2d1318 100644 --- a/src/qt/bitcoingui.cpp +++ b/src/qt/bitcoingui.cpp @@ -538,19 +538,6 @@ void BitcoinGUI::setNumBlocks(int count) progressBar->setToolTip(tooltip); } -void BitcoinGUI::refreshStatusBar() -{ - /* Might display multiple times in the case of multiple alerts - static QString prevStatusBar; - QString newStatusBar = clientModel->getStatusBarWarnings(); - if (prevStatusBar != newStatusBar) - { - prevStatusBar = newStatusBar; - error(tr("Network Alert"), newStatusBar); - }*/ - setNumBlocks(clientModel->getNumBlocks()); -} - void BitcoinGUI::error(const QString &title, const QString &message) { // Report errors from network/worker thread diff --git a/src/qt/bitcoingui.h b/src/qt/bitcoingui.h index dbc3264..2130bab 100644 --- a/src/qt/bitcoingui.h +++ b/src/qt/bitcoingui.h @@ -113,8 +113,6 @@ public slots: @see WalletModel::EncryptionStatus */ void setEncryptionStatus(int status); - /** Set the status bar text if there are any warnings (removes sync progress bar if applicable) */ - void refreshStatusBar(); /** Notify the user of an error in the network or transaction handling code. */ void error(const QString &title, const QString &message); diff --git a/src/qt/clientmodel.cpp b/src/qt/clientmodel.cpp index 5a0b4aa..8163da0 100644 --- a/src/qt/clientmodel.cpp +++ b/src/qt/clientmodel.cpp @@ -6,19 +6,12 @@ #include "headers.h" -#include #include ClientModel::ClientModel(OptionsModel *optionsModel, QObject *parent) : QObject(parent), optionsModel(optionsModel), cachedNumConnections(0), cachedNumBlocks(0) { - // Until signal notifications is built into the bitcoin core, - // simply update everything after polling using a timer. - QTimer *timer = new QTimer(this); - connect(timer, SIGNAL(timeout()), this, SLOT(update())); - timer->start(MODEL_UPDATE_DELAY); - numBlocksAtStartup = -1; } @@ -47,14 +40,23 @@ void ClientModel::update() { int newNumConnections = getNumConnections(); int newNumBlocks = getNumBlocks(); + QString newStatusBar = getStatusBarWarnings(); if(cachedNumConnections != newNumConnections) emit numConnectionsChanged(newNumConnections); - if(cachedNumBlocks != newNumBlocks) + if(cachedNumBlocks != newNumBlocks || cachedStatusBar != newStatusBar) + { + // Simply emit a numBlocksChanged for now in case the status message changes, + // so that the view updates the status bar. + // TODO: It should send a notification. + // (However, this might generate looped notifications and needs to be thought through and tested carefully) + // error(tr("Network Alert"), newStatusBar); emit numBlocksChanged(newNumBlocks); + } cachedNumConnections = newNumConnections; cachedNumBlocks = newNumBlocks; + cachedStatusBar = newStatusBar; } bool ClientModel::isTestNet() const diff --git a/src/qt/clientmodel.h b/src/qt/clientmodel.h index 5a12c4f..3dfbcec 100644 --- a/src/qt/clientmodel.h +++ b/src/qt/clientmodel.h @@ -43,6 +43,7 @@ private: int cachedNumConnections; int cachedNumBlocks; + QString cachedStatusBar; int numBlocksAtStartup; diff --git a/src/qt/walletmodel.cpp b/src/qt/walletmodel.cpp index 8344a65..0841854 100644 --- a/src/qt/walletmodel.cpp +++ b/src/qt/walletmodel.cpp @@ -7,7 +7,6 @@ #include "headers.h" #include "db.h" // for BackupWallet -#include #include WalletModel::WalletModel(CWallet *wallet, OptionsModel *optionsModel, QObject *parent) : @@ -16,12 +15,6 @@ WalletModel::WalletModel(CWallet *wallet, OptionsModel *optionsModel, QObject *p cachedBalance(0), cachedUnconfirmedBalance(0), cachedNumTransactions(0), cachedEncryptionStatus(Unencrypted) { - // Until signal notifications is built into the bitcoin core, - // simply update everything after polling using a timer. - QTimer *timer = new QTimer(this); - connect(timer, SIGNAL(timeout()), this, SLOT(update())); - timer->start(MODEL_UPDATE_DELAY); - addressTableModel = new AddressTableModel(wallet, this); transactionTableModel = new TransactionTableModel(wallet, this); } @@ -69,6 +62,11 @@ void WalletModel::update() addressTableModel->update(); } +void WalletModel::updateAddressList() +{ + addressTableModel->update(); +} + bool WalletModel::validateAddress(const QString &address) { CBitcoinAddress addressParsed(address.toStdString()); @@ -164,9 +162,6 @@ WalletModel::SendCoinsReturn WalletModel::sendCoins(const QListupdateList(); - return SendCoinsReturn(OK, 0, hex); } diff --git a/src/qt/walletmodel.h b/src/qt/walletmodel.h index e894842..6a85abd 100644 --- a/src/qt/walletmodel.h +++ b/src/qt/walletmodel.h @@ -138,9 +138,8 @@ signals: void error(const QString &title, const QString &message); public slots: - -private slots: void update(); + void updateAddressList(); }; diff --git a/src/qtui.h b/src/qtui.h index 9791ba5..70952da 100644 --- a/src/qtui.h +++ b/src/qtui.h @@ -44,6 +44,7 @@ extern void ThreadSafeHandleURL(const std::string& strURL); extern void CalledSetStatusBar(const std::string& strText, int nField); extern void UIThreadCall(boost::function0 fn); extern void MainFrameRepaint(); +extern void AddressBookRepaint(); extern void InitMessage(const std::string &message); extern std::string _(const char* psz); diff --git a/src/wallet.cpp b/src/wallet.cpp index 27ed722..3bdb4bb 100644 --- a/src/wallet.cpp +++ b/src/wallet.cpp @@ -1279,6 +1279,7 @@ int CWallet::LoadWallet(bool& fFirstRunRet) bool CWallet::SetAddressBookName(const CBitcoinAddress& address, const string& strName) { mapAddressBook[address] = strName; + AddressBookRepaint(); if (!fFileBacked) return false; return CWalletDB(strWalletFile).WriteName(address.ToString(), strName); @@ -1287,6 +1288,7 @@ bool CWallet::SetAddressBookName(const CBitcoinAddress& address, const string& s bool CWallet::DelAddressBookName(const CBitcoinAddress& address) { mapAddressBook.erase(address); + AddressBookRepaint(); if (!fFileBacked) return false; return CWalletDB(strWalletFile).EraseName(address.ToString()); -- 1.7.1