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
This commit is contained in:
Wladimir J. van der Laan 2012-03-24 18:48:18 +01:00
parent 7e7bcce2d9
commit 98e6175874
13 changed files with 46 additions and 54 deletions

View file

@ -67,6 +67,10 @@ inline void MainFrameRepaint()
{ {
} }
inline void AddressBookRepaint()
{
}
inline void InitMessage(const std::string &message) inline void InitMessage(const std::string &message)
{ {
} }

View file

@ -94,8 +94,6 @@ void AddressBookPage::setModel(AddressTableModel *model)
this->model = model; this->model = model;
if(!model) if(!model)
return; return;
// Refresh list from core
model->updateList();
proxyModel = new QSortFilterProxyModel(this); proxyModel = new QSortFilterProxyModel(this);
proxyModel->setSourceModel(model); proxyModel->setSourceModel(model);

View file

@ -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 // Update address book model from Bitcoin core
beginResetModel(); beginResetModel();
@ -285,10 +285,9 @@ QString AddressTableModel::addRow(const QString &type, const QString &label, con
{ {
return QString(); return QString();
} }
// Add entry and update list // Add entry
CRITICAL_BLOCK(wallet->cs_wallet) CRITICAL_BLOCK(wallet->cs_wallet)
wallet->SetAddressBookName(strAddress, strLabel); wallet->SetAddressBookName(strAddress, strLabel);
updateList();
return QString::fromStdString(strAddress); return QString::fromStdString(strAddress);
} }
@ -306,15 +305,9 @@ bool AddressTableModel::removeRows(int row, int count, const QModelIndex & paren
{ {
wallet->DelAddressBookName(rec->address.toStdString()); wallet->DelAddressBookName(rec->address.toStdString());
} }
updateList();
return true; return true;
} }
void AddressTableModel::update()
{
}
/* Look up label for address in address book, if not found return empty string. /* Look up label for address in address book, if not found return empty string.
*/ */
QString AddressTableModel::labelForAddress(const QString &address) const QString AddressTableModel::labelForAddress(const QString &address) const

View file

@ -56,10 +56,6 @@ public:
*/ */
QString addRow(const QString &type, const QString &label, const QString &address); 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. /* Look up label for address in address book, if not found return empty string.
*/ */
QString labelForAddress(const QString &address) const; QString labelForAddress(const QString &address) const;
@ -82,6 +78,8 @@ signals:
void defaultAddressChanged(const QString &address); void defaultAddressChanged(const QString &address);
public slots: public slots:
/* Update address list from core. Invalidates any indices.
*/
void update(); void update();
}; };

View file

@ -33,8 +33,10 @@ Q_IMPORT_PLUGIN(qtaccessiblewidgets)
#endif #endif
// Need a global reference for the notifications to find the GUI // Need a global reference for the notifications to find the GUI
BitcoinGUI *guiref; static BitcoinGUI *guiref;
QSplashScreen *splashref; 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) 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<void> fn)
void MainFrameRepaint() void MainFrameRepaint()
{ {
if(guiref) if(clientmodel)
QMetaObject::invokeMethod(guiref, "refreshStatusBar", Qt::QueuedConnection); 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) void InitMessage(const std::string &message)
@ -230,7 +240,9 @@ int main(int argc, char *argv[])
splash.finish(&window); splash.finish(&window);
ClientModel clientModel(&optionsModel); ClientModel clientModel(&optionsModel);
clientmodel = &clientModel;
WalletModel walletModel(pwalletMain, &optionsModel); WalletModel walletModel(pwalletMain, &optionsModel);
walletmodel = &walletModel;
guiref = &window; guiref = &window;
window.setClientModel(&clientModel); window.setClientModel(&clientModel);
@ -270,6 +282,8 @@ int main(int argc, char *argv[])
app.exec(); app.exec();
guiref = 0; guiref = 0;
clientmodel = 0;
walletmodel = 0;
} }
Shutdown(NULL); Shutdown(NULL);
} }

View file

@ -538,19 +538,6 @@ void BitcoinGUI::setNumBlocks(int count)
progressBar->setToolTip(tooltip); 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) void BitcoinGUI::error(const QString &title, const QString &message)
{ {
// Report errors from network/worker thread // Report errors from network/worker thread

View file

@ -113,8 +113,6 @@ public slots:
@see WalletModel::EncryptionStatus @see WalletModel::EncryptionStatus
*/ */
void setEncryptionStatus(int status); 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. */ /** Notify the user of an error in the network or transaction handling code. */
void error(const QString &title, const QString &message); void error(const QString &title, const QString &message);

View file

@ -6,19 +6,12 @@
#include "headers.h" #include "headers.h"
#include <QTimer>
#include <QDateTime> #include <QDateTime>
ClientModel::ClientModel(OptionsModel *optionsModel, QObject *parent) : ClientModel::ClientModel(OptionsModel *optionsModel, QObject *parent) :
QObject(parent), optionsModel(optionsModel), QObject(parent), optionsModel(optionsModel),
cachedNumConnections(0), cachedNumBlocks(0) 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; numBlocksAtStartup = -1;
} }
@ -47,14 +40,23 @@ void ClientModel::update()
{ {
int newNumConnections = getNumConnections(); int newNumConnections = getNumConnections();
int newNumBlocks = getNumBlocks(); int newNumBlocks = getNumBlocks();
QString newStatusBar = getStatusBarWarnings();
if(cachedNumConnections != newNumConnections) if(cachedNumConnections != newNumConnections)
emit numConnectionsChanged(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); emit numBlocksChanged(newNumBlocks);
}
cachedNumConnections = newNumConnections; cachedNumConnections = newNumConnections;
cachedNumBlocks = newNumBlocks; cachedNumBlocks = newNumBlocks;
cachedStatusBar = newStatusBar;
} }
bool ClientModel::isTestNet() const bool ClientModel::isTestNet() const

View file

@ -43,6 +43,7 @@ private:
int cachedNumConnections; int cachedNumConnections;
int cachedNumBlocks; int cachedNumBlocks;
QString cachedStatusBar;
int numBlocksAtStartup; int numBlocksAtStartup;

View file

@ -7,7 +7,6 @@
#include "headers.h" #include "headers.h"
#include "db.h" // for BackupWallet #include "db.h" // for BackupWallet
#include <QTimer>
#include <QSet> #include <QSet>
WalletModel::WalletModel(CWallet *wallet, OptionsModel *optionsModel, QObject *parent) : 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), cachedBalance(0), cachedUnconfirmedBalance(0), cachedNumTransactions(0),
cachedEncryptionStatus(Unencrypted) 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); addressTableModel = new AddressTableModel(wallet, this);
transactionTableModel = new TransactionTableModel(wallet, this); transactionTableModel = new TransactionTableModel(wallet, this);
} }
@ -69,6 +62,11 @@ void WalletModel::update()
addressTableModel->update(); addressTableModel->update();
} }
void WalletModel::updateAddressList()
{
addressTableModel->update();
}
bool WalletModel::validateAddress(const QString &address) bool WalletModel::validateAddress(const QString &address)
{ {
CBitcoinAddress addressParsed(address.toStdString()); CBitcoinAddress addressParsed(address.toStdString());
@ -164,9 +162,6 @@ WalletModel::SendCoinsReturn WalletModel::sendCoins(const QList<SendCoinsRecipie
} }
} }
// Update our model of the address table
addressTableModel->updateList();
return SendCoinsReturn(OK, 0, hex); return SendCoinsReturn(OK, 0, hex);
} }

View file

@ -138,9 +138,8 @@ signals:
void error(const QString &title, const QString &message); void error(const QString &title, const QString &message);
public slots: public slots:
private slots:
void update(); void update();
void updateAddressList();
}; };

View file

@ -44,6 +44,7 @@ extern void ThreadSafeHandleURL(const std::string& strURL);
extern void CalledSetStatusBar(const std::string& strText, int nField); extern void CalledSetStatusBar(const std::string& strText, int nField);
extern void UIThreadCall(boost::function0<void> fn); extern void UIThreadCall(boost::function0<void> fn);
extern void MainFrameRepaint(); extern void MainFrameRepaint();
extern void AddressBookRepaint();
extern void InitMessage(const std::string &message); extern void InitMessage(const std::string &message);
extern std::string _(const char* psz); extern std::string _(const char* psz);

View file

@ -1279,6 +1279,7 @@ int CWallet::LoadWallet(bool& fFirstRunRet)
bool CWallet::SetAddressBookName(const CBitcoinAddress& address, const string& strName) bool CWallet::SetAddressBookName(const CBitcoinAddress& address, const string& strName)
{ {
mapAddressBook[address] = strName; mapAddressBook[address] = strName;
AddressBookRepaint();
if (!fFileBacked) if (!fFileBacked)
return false; return false;
return CWalletDB(strWalletFile).WriteName(address.ToString(), strName); 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) bool CWallet::DelAddressBookName(const CBitcoinAddress& address)
{ {
mapAddressBook.erase(address); mapAddressBook.erase(address);
AddressBookRepaint();
if (!fFileBacked) if (!fFileBacked)
return false; return false;
return CWalletDB(strWalletFile).EraseName(address.ToString()); return CWalletDB(strWalletFile).EraseName(address.ToString());