From ab1b288fa7994db5f036e93d5f8ba73372017c40 Mon Sep 17 00:00:00 2001 From: "Wladimir J. van der Laan" Date: Sun, 6 May 2012 19:40:58 +0200 Subject: Convert UI interface to boost::signals2. - Signals now go directly from the core to WalletModel/ClientModel. - WalletModel subscribes to signals on CWallet: Prepares for multi-wallet support, by no longer assuming an implicit global wallet. - Gets rid of noui.cpp, the few lines that were left are merged into init.cpp - Rename wxXXX message flags to MF_XXX, to make them UI indifferent. - ThreadSafeMessageBox no longer returns the value `4` which was never used, converted to void. --- src/qt/bitcoin.cpp | 84 +++++++++----------------------------------------- src/qt/clientmodel.cpp | 45 +++++++++++++++++++++++++++ src/qt/clientmodel.h | 3 ++ src/qt/qtipcserver.cpp | 4 +-- src/qt/walletmodel.cpp | 49 ++++++++++++++++++++++++++++- src/qt/walletmodel.h | 3 ++ 6 files changed, 116 insertions(+), 72 deletions(-) (limited to 'src/qt') diff --git a/src/qt/bitcoin.cpp b/src/qt/bitcoin.cpp index a50443021f..c5592b28df 100644 --- a/src/qt/bitcoin.cpp +++ b/src/qt/bitcoin.cpp @@ -36,15 +36,13 @@ Q_IMPORT_PLUGIN(qtaccessiblewidgets) // Need a global reference for the notifications to find the GUI static BitcoinGUI *guiref; static QSplashScreen *splashref; -static WalletModel *walletmodel; -static ClientModel *clientmodel; -int ThreadSafeMessageBox(const std::string& message, const std::string& caption, int style) +static void ThreadSafeMessageBox(const std::string& message, const std::string& caption, int style) { // Message from network thread if(guiref) { - bool modal = (style & wxMODAL); + bool modal = (style & MF_MODAL); // in case of modal message, use blocking connection to wait for user to click OK QMetaObject::invokeMethod(guiref, "error", modal ? GUIUtil::blockingGUIThreadConnection() : Qt::QueuedConnection, @@ -57,10 +55,9 @@ int ThreadSafeMessageBox(const std::string& message, const std::string& caption, printf("%s: %s\n", caption.c_str(), message.c_str()); fprintf(stderr, "%s: %s\n", caption.c_str(), message.c_str()); } - return 4; } -bool ThreadSafeAskFee(int64 nFeeRequired, const std::string& strCaption) +static bool ThreadSafeAskFee(int64 nFeeRequired, const std::string& strCaption) { if(!guiref) return false; @@ -75,7 +72,7 @@ bool ThreadSafeAskFee(int64 nFeeRequired, const std::string& strCaption) return payFee; } -void ThreadSafeHandleURI(const std::string& strURI) +static void ThreadSafeHandleURI(const std::string& strURI) { if(!guiref) return; @@ -84,7 +81,7 @@ void ThreadSafeHandleURI(const std::string& strURI) Q_ARG(QString, QString::fromStdString(strURI))); } -void InitMessage(const std::string &message) +static void InitMessage(const std::string &message) { if(splashref) { @@ -93,7 +90,7 @@ void InitMessage(const std::string &message) } } -void QueueShutdown() +static void QueueShutdown() { QMetaObject::invokeMethod(QCoreApplication::instance(), "quit", Qt::QueuedConnection); } @@ -101,66 +98,11 @@ void QueueShutdown() /* Translate string to current locale using Qt. */ -std::string _(const char* psz) +static std::string Translate(const char* psz) { return QCoreApplication::translate("bitcoin-core", psz).toStdString(); } -void NotifyBlocksChanged() -{ - // This notification is too frequent. Don't trigger a signal. - // Don't remove it, though, as it might be useful later. -} - -void NotifyKeyStoreStatusChanged(CBasicKeyStore *wallet) -{ - // This currently ignores the wallet argument. When multiple wallet support is implemented, this - // parameter should be mapped to a specific WalletModel for that wallet. - OutputDebugStringF("NotifyKeyStoreStatusChanged\n"); - if(walletmodel) - QMetaObject::invokeMethod(walletmodel, "updateStatus", Qt::QueuedConnection); -} - -void NotifyAddressBookChanged(CWallet *wallet, const std::string &address, const std::string &label, ChangeType status) -{ - // This currently ignores the wallet argument. When multiple wallet support is implemented, this - // parameter should be mapped to a specific WalletModel for that wallet. - OutputDebugStringF("NotifyAddressBookChanged %s %s status=%i\n", address.c_str(), label.c_str(), status); - if(walletmodel) - QMetaObject::invokeMethod(walletmodel, "updateAddressBook", Qt::QueuedConnection, - Q_ARG(QString, QString::fromStdString(address)), - Q_ARG(QString, QString::fromStdString(label)), - Q_ARG(int, status)); -} - -void NotifyTransactionChanged(CWallet *wallet, const uint256 &hash, ChangeType status) -{ - // This currently ignores the wallet argument. When multiple wallet support is implemented, this - // parameter should be mapped to a specific WalletModel for that wallet. - OutputDebugStringF("NotifyTransactionChanged %s status=%i\n", hash.GetHex().c_str(), status); - if(walletmodel) - QMetaObject::invokeMethod(walletmodel, "updateTransaction", Qt::QueuedConnection, - Q_ARG(QString, QString::fromStdString(hash.GetHex())), - Q_ARG(int, status)); -} - -void NotifyNumConnectionsChanged(int newNumConnections) -{ - // Too noisy: OutputDebugStringF("NotifyNumConnectionsChanged %i\n", newNumConnections); - if(clientmodel) - QMetaObject::invokeMethod(clientmodel, "updateNumConnections", Qt::QueuedConnection, - Q_ARG(int, newNumConnections)); -} - -void NotifyAlertChanged(const uint256 &hash, ChangeType status) -{ - OutputDebugStringF("NotifyAlertChanged %s status=%i\n", hash.GetHex().c_str(), status); - if(clientmodel) - QMetaObject::invokeMethod(clientmodel, "updateAlert", Qt::QueuedConnection, - Q_ARG(QString, QString::fromStdString(hash.GetHex())), - Q_ARG(int, status)); -} - /* Handle runaway exceptions. Shows a message box with the problem and quits the program. */ static void handleRunawayException(std::exception *e) @@ -307,6 +249,14 @@ int main(int argc, char *argv[]) if (translator.load(lang_territory, ":/translations/")) app.installTranslator(&translator); + // Subscribe to global signals from core + uiInterface.ThreadSafeMessageBox.connect(ThreadSafeMessageBox); + uiInterface.ThreadSafeAskFee.connect(ThreadSafeAskFee); + uiInterface.ThreadSafeHandleURI.connect(ThreadSafeHandleURI); + uiInterface.InitMessage.connect(InitMessage); + uiInterface.QueueShutdown.connect(QueueShutdown); + uiInterface.Translate.connect(Translate); + // Show help message immediately after parsing command-line options (for "-lang") and setting locale, // but before showing splash screen. if (mapArgs.count("-?") || mapArgs.count("--help")) @@ -348,9 +298,7 @@ int main(int argc, char *argv[]) splash.finish(&window); ClientModel clientModel(&optionsModel); - clientmodel = &clientModel; WalletModel walletModel(pwalletMain, &optionsModel); - walletmodel = &walletModel; window.setClientModel(&clientModel); window.setWalletModel(&walletModel); @@ -392,8 +340,6 @@ int main(int argc, char *argv[]) window.setClientModel(0); window.setWalletModel(0); guiref = 0; - clientmodel = 0; - walletmodel = 0; } Shutdown(NULL); } diff --git a/src/qt/clientmodel.cpp b/src/qt/clientmodel.cpp index 1914ef90b5..64fd2a9450 100644 --- a/src/qt/clientmodel.cpp +++ b/src/qt/clientmodel.cpp @@ -22,6 +22,13 @@ ClientModel::ClientModel(OptionsModel *optionsModel, QObject *parent) : pollTimer->setInterval(MODEL_UPDATE_DELAY); pollTimer->start(); connect(pollTimer, SIGNAL(timeout()), this, SLOT(updateTimer())); + + subscribeToCoreSignals(); +} + +ClientModel::~ClientModel() +{ + unsubscribeFromCoreSignals(); } int ClientModel::getNumConnections() const @@ -127,3 +134,41 @@ QDateTime ClientModel::formatClientStartupTime() const { return QDateTime::fromTime_t(nClientStartupTime); } + +// Handlers for core signals +static void NotifyBlocksChanged(ClientModel *clientmodel) +{ + // This notification is too frequent. Don't trigger a signal. + // Don't remove it, though, as it might be useful later. +} + +static void NotifyNumConnectionsChanged(ClientModel *clientmodel, int newNumConnections) +{ + // Too noisy: OutputDebugStringF("NotifyNumConnectionsChanged %i\n", newNumConnections); + QMetaObject::invokeMethod(clientmodel, "updateNumConnections", Qt::QueuedConnection, + Q_ARG(int, newNumConnections)); +} + +static void NotifyAlertChanged(ClientModel *clientmodel, const uint256 &hash, ChangeType status) +{ + OutputDebugStringF("NotifyAlertChanged %s status=%i\n", hash.GetHex().c_str(), status); + QMetaObject::invokeMethod(clientmodel, "updateAlert", Qt::QueuedConnection, + Q_ARG(QString, QString::fromStdString(hash.GetHex())), + Q_ARG(int, status)); +} + +void ClientModel::subscribeToCoreSignals() +{ + // Connect signals to client + uiInterface.NotifyBlocksChanged.connect(boost::bind(NotifyBlocksChanged, this)); + uiInterface.NotifyNumConnectionsChanged.connect(boost::bind(NotifyNumConnectionsChanged, this, _1)); + uiInterface.NotifyAlertChanged.connect(boost::bind(NotifyAlertChanged, this, _1, _2)); +} + +void ClientModel::unsubscribeFromCoreSignals() +{ + // Disconnect signals from client + uiInterface.NotifyBlocksChanged.disconnect(boost::bind(NotifyBlocksChanged, this)); + uiInterface.NotifyNumConnectionsChanged.disconnect(boost::bind(NotifyNumConnectionsChanged, this, _1)); + uiInterface.NotifyAlertChanged.disconnect(boost::bind(NotifyAlertChanged, this, _1, _2)); +} diff --git a/src/qt/clientmodel.h b/src/qt/clientmodel.h index bf2cd84a1c..0349c389c5 100644 --- a/src/qt/clientmodel.h +++ b/src/qt/clientmodel.h @@ -19,6 +19,7 @@ class ClientModel : public QObject Q_OBJECT public: explicit ClientModel(OptionsModel *optionsModel, QObject *parent = 0); + ~ClientModel(); OptionsModel *getOptionsModel(); @@ -52,6 +53,8 @@ private: QTimer *pollTimer; + void subscribeToCoreSignals(); + void unsubscribeFromCoreSignals(); signals: void numConnectionsChanged(int count); void numBlocksChanged(int count, int countOfPeers); diff --git a/src/qt/qtipcserver.cpp b/src/qt/qtipcserver.cpp index 06ada5aaca..3d7d90e902 100644 --- a/src/qt/qtipcserver.cpp +++ b/src/qt/qtipcserver.cpp @@ -31,7 +31,7 @@ void ipcThread(void* parg) ptime d = boost::posix_time::microsec_clock::universal_time() + millisec(100); if(mq->timed_receive(&strBuf, sizeof(strBuf), nSize, nPriority, d)) { - ThreadSafeHandleURI(std::string(strBuf, nSize)); + uiInterface.ThreadSafeHandleURI(std::string(strBuf, nSize)); Sleep(1000); } if (fShutdown) @@ -69,7 +69,7 @@ void ipcInit() ptime d = boost::posix_time::microsec_clock::universal_time() + millisec(1); if(mq->timed_receive(&strBuf, sizeof(strBuf), nSize, nPriority, d)) { - ThreadSafeHandleURI(std::string(strBuf, nSize)); + uiInterface.ThreadSafeHandleURI(std::string(strBuf, nSize)); } else break; diff --git a/src/qt/walletmodel.cpp b/src/qt/walletmodel.cpp index 4e082a8abc..1a9700ef09 100644 --- a/src/qt/walletmodel.cpp +++ b/src/qt/walletmodel.cpp @@ -18,6 +18,13 @@ WalletModel::WalletModel(CWallet *wallet, OptionsModel *optionsModel, QObject *p { addressTableModel = new AddressTableModel(wallet, this); transactionTableModel = new TransactionTableModel(wallet, this); + + subscribeToCoreSignals(); +} + +WalletModel::~WalletModel() +{ + unsubscribeFromCoreSignals(); } qint64 WalletModel::getBalance() const @@ -147,7 +154,7 @@ WalletModel::SendCoinsReturn WalletModel::sendCoins(const QListNotifyStatusChanged.connect(boost::bind(&NotifyKeyStoreStatusChanged, this, _1)); + wallet->NotifyAddressBookChanged.connect(boost::bind(NotifyAddressBookChanged, this, _1, _2, _3, _4)); + wallet->NotifyTransactionChanged.connect(boost::bind(NotifyTransactionChanged, this, _1, _2, _3)); +} + +void WalletModel::unsubscribeFromCoreSignals() +{ + // Disconnect signals from wallet + wallet->NotifyStatusChanged.disconnect(boost::bind(&NotifyKeyStoreStatusChanged, this, _1)); + wallet->NotifyAddressBookChanged.disconnect(boost::bind(NotifyAddressBookChanged, this, _1, _2, _3, _4)); + wallet->NotifyTransactionChanged.disconnect(boost::bind(NotifyTransactionChanged, this, _1, _2, _3)); +} + // WalletModel::UnlockContext implementation WalletModel::UnlockContext WalletModel::requestUnlock() { diff --git a/src/qt/walletmodel.h b/src/qt/walletmodel.h index 8250794f21..c413ed2436 100644 --- a/src/qt/walletmodel.h +++ b/src/qt/walletmodel.h @@ -24,6 +24,7 @@ class WalletModel : public QObject Q_OBJECT public: explicit WalletModel(CWallet *wallet, OptionsModel *optionsModel, QObject *parent = 0); + ~WalletModel(); enum StatusCode // Returned by sendCoins { @@ -118,6 +119,8 @@ private: qint64 cachedNumTransactions; EncryptionStatus cachedEncryptionStatus; + void subscribeToCoreSignals(); + void unsubscribeFromCoreSignals(); signals: // Signal that balance in wallet changed void balanceChanged(qint64 balance, qint64 unconfirmedBalance); -- cgit v1.2.3