aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorWladimir J. van der Laan <laanwj@gmail.com>2012-05-06 19:40:58 +0200
committerWladimir J. van der Laan <laanwj@gmail.com>2012-05-20 10:44:50 +0200
commitab1b288fa7994db5f036e93d5f8ba73372017c40 (patch)
tree6454168811d3f2c011e907770b3ac7cfe8c49495
parentfe4a655042f7de31dce120aeed72345579f1b59f (diff)
downloadbitcoin-ab1b288fa7994db5f036e93d5f8ba73372017c40.tar.xz
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.
-rw-r--r--src/bitcoinrpc.cpp16
-rw-r--r--src/init.cpp39
-rw-r--r--src/keystore.cpp5
-rw-r--r--src/keystore.h6
-rw-r--r--src/main.cpp14
-rw-r--r--src/makefile.linux-mingw3
-rw-r--r--src/makefile.mingw3
-rw-r--r--src/makefile.osx3
-rw-r--r--src/makefile.unix3
-rw-r--r--src/net.cpp2
-rw-r--r--src/noui.cpp59
-rw-r--r--src/qt/bitcoin.cpp84
-rw-r--r--src/qt/clientmodel.cpp45
-rw-r--r--src/qt/clientmodel.h3
-rw-r--r--src/qt/qtipcserver.cpp4
-rw-r--r--src/qt/walletmodel.cpp49
-rw-r--r--src/qt/walletmodel.h3
-rw-r--r--src/ui_interface.h127
-rw-r--r--src/util.cpp2
-rw-r--r--src/wallet.cpp4
-rw-r--r--src/wallet.h11
21 files changed, 263 insertions, 222 deletions
diff --git a/src/bitcoinrpc.cpp b/src/bitcoinrpc.cpp
index 334425a9a9..cc4d85cbbe 100644
--- a/src/bitcoinrpc.cpp
+++ b/src/bitcoinrpc.cpp
@@ -435,7 +435,7 @@ Value stop(const Array& params, bool fHelp)
"stop\n"
"Stop Bitcoin server.");
// Shutdown will take long enough that the response should get back
- QueueShutdown();
+ uiInterface.QueueShutdown();
return "Bitcoin server stopping";
}
@@ -1928,7 +1928,7 @@ Value encryptwallet(const Array& params, bool fHelp)
// BDB seems to have a bad habit of writing old data into
// slack space in .dat files; that is bad if the old data is
// unencrypted private keys. So:
- QueueShutdown();
+ uiInterface.QueueShutdown();
return "wallet encrypted; Bitcoin server stopping, restart to run with encrypted wallet";
}
@@ -2620,7 +2620,7 @@ void ThreadRPCServer2(void* parg)
strWhatAmI = strprintf(_("To use the %s option"), "\"-server\"");
else if (mapArgs.count("-daemon"))
strWhatAmI = strprintf(_("To use the %s option"), "\"-daemon\"");
- ThreadSafeMessageBox(strprintf(
+ uiInterface.ThreadSafeMessageBox(strprintf(
_("%s, you must set a rpcpassword in the configuration file:\n %s\n"
"It is recommended you use the following random password:\n"
"rpcuser=bitcoinrpc\n"
@@ -2630,8 +2630,8 @@ void ThreadRPCServer2(void* parg)
strWhatAmI.c_str(),
GetConfigFile().string().c_str(),
EncodeBase58(&rand_pwd[0],&rand_pwd[0]+32).c_str()),
- _("Error"), wxOK | wxMODAL);
- QueueShutdown();
+ _("Error"), MF_OK | MF_MODAL);
+ uiInterface.QueueShutdown();
return;
}
@@ -2650,9 +2650,9 @@ void ThreadRPCServer2(void* parg)
}
catch(boost::system::system_error &e)
{
- ThreadSafeMessageBox(strprintf(_("An error occured while setting up the RPC port %i for listening: %s"), endpoint.port(), e.what()),
- _("Error"), wxOK | wxMODAL);
- QueueShutdown();
+ uiInterface.ThreadSafeMessageBox(strprintf(_("An error occured while setting up the RPC port %i for listening: %s"), endpoint.port(), e.what()),
+ _("Error"), MF_OK | MF_MODAL);
+ uiInterface.QueueShutdown();
return;
}
diff --git a/src/init.cpp b/src/init.cpp
index 47b6f92324..096f289640 100644
--- a/src/init.cpp
+++ b/src/init.cpp
@@ -22,6 +22,7 @@ using namespace std;
using namespace boost;
CWallet* pwalletMain;
+CClientUIInterface uiInterface;
//////////////////////////////////////////////////////////////////////////////
//
@@ -90,9 +91,33 @@ void HandleSIGTERM(int)
// Start
//
#if !defined(QT_GUI)
+static int noui_ThreadSafeMessageBox(const std::string& message, const std::string& caption, int style)
+{
+ printf("%s: %s\n", caption.c_str(), message.c_str());
+ fprintf(stderr, "%s: %s\n", caption.c_str(), message.c_str());
+ return 4;
+}
+
+static bool noui_ThreadSafeAskFee(int64 nFeeRequired, const std::string& strCaption)
+{
+ return true;
+}
+
+static void noui_QueueShutdown()
+{
+ // Without UI, Shutdown can simply be started in a new thread
+ CreateThread(Shutdown, NULL);
+}
+
int main(int argc, char* argv[])
{
bool fRet = false;
+
+ // Connect bitcoind signal handlers
+ uiInterface.ThreadSafeMessageBox.connect(noui_ThreadSafeMessageBox);
+ uiInterface.ThreadSafeAskFee.connect(noui_ThreadSafeAskFee);
+ uiInterface.QueueShutdown.connect(noui_QueueShutdown);
+
fRet = AppInit(argc, argv);
if (fRet && fDaemon)
@@ -160,13 +185,13 @@ bool AppInit(int argc, char* argv[])
bool static InitError(const std::string &str)
{
- ThreadSafeMessageBox(str, _("Bitcoin"), wxOK | wxMODAL);
+ uiInterface.ThreadSafeMessageBox(str, _("Bitcoin"), MF_OK|MF_MODAL);
return false;
}
bool static InitWarning(const std::string &str)
{
- ThreadSafeMessageBox(str, _("Bitcoin"), wxOK | wxICON_EXCLAMATION | wxMODAL);
+ uiInterface.ThreadSafeMessageBox(str, _("Bitcoin"), MF_OK | MF_ICON_EXCLAMATION | MF_MODAL);
return true;
}
@@ -367,7 +392,7 @@ bool AppInit2()
fprintf(stdout, "Bitcoin server starting\n");
int64 nStart;
- InitMessage(_("Loading addresses..."));
+ uiInterface.InitMessage(_("Loading addresses..."));
printf("Loading addresses...\n");
nStart = GetTimeMillis();
@@ -380,7 +405,7 @@ bool AppInit2()
printf("Loaded %i addresses from peers.dat %"PRI64d"ms\n",
addrman.size(), GetTimeMillis() - nStart);
- InitMessage(_("Loading block index..."));
+ uiInterface.InitMessage(_("Loading block index..."));
printf("Loading block index...\n");
nStart = GetTimeMillis();
if (!LoadBlockIndex())
@@ -406,7 +431,7 @@ bool AppInit2()
}
}
- InitMessage(_("Loading wallet..."));
+ uiInterface.InitMessage(_("Loading wallet..."));
printf("Loading wallet...\n");
nStart = GetTimeMillis();
bool fFirstRun;
@@ -474,14 +499,14 @@ bool AppInit2()
}
if (pindexBest != pindexRescan)
{
- InitMessage(_("Rescanning..."));
+ uiInterface.InitMessage(_("Rescanning..."));
printf("Rescanning last %i blocks (from block %i)...\n", pindexBest->nHeight - pindexRescan->nHeight, pindexRescan->nHeight);
nStart = GetTimeMillis();
pwalletMain->ScanForWalletTransactions(pindexRescan, true);
printf(" rescan %15"PRI64d"ms\n", GetTimeMillis() - nStart);
}
- InitMessage(_("Done loading"));
+ uiInterface.InitMessage(_("Done loading"));
printf("Done loading\n");
//// debug print
diff --git a/src/keystore.cpp b/src/keystore.cpp
index 55fba4c372..bdeae30135 100644
--- a/src/keystore.cpp
+++ b/src/keystore.cpp
@@ -5,7 +5,6 @@
#include "keystore.h"
#include "script.h"
-#include "ui_interface.h"
bool CKeyStore::GetPubKey(const CBitcoinAddress &address, std::vector<unsigned char> &vchPubKeyOut) const
{
@@ -84,7 +83,7 @@ bool CCryptoKeyStore::Lock()
vMasterKey.clear();
}
- NotifyKeyStoreStatusChanged(this);
+ NotifyStatusChanged(this);
return true;
}
@@ -114,7 +113,7 @@ bool CCryptoKeyStore::Unlock(const CKeyingMaterial& vMasterKeyIn)
}
vMasterKey = vMasterKeyIn;
}
- NotifyKeyStoreStatusChanged(this);
+ NotifyStatusChanged(this);
return true;
}
diff --git a/src/keystore.h b/src/keystore.h
index dd7110db58..6b5d01cfa5 100644
--- a/src/keystore.h
+++ b/src/keystore.h
@@ -8,6 +8,7 @@
#include "crypter.h"
#include "sync.h"
#include "base58.h"
+#include <boost/signals2/signal.hpp>
class CScript;
@@ -174,6 +175,11 @@ public:
mi++;
}
}
+
+ /* Wallet status (encrypted, locked) changed.
+ * Note: Called without locks held.
+ */
+ boost::signals2::signal<void (CCryptoKeyStore* wallet)> NotifyStatusChanged;
};
#endif
diff --git a/src/main.cpp b/src/main.cpp
index 7e7a0badfd..8410b9af4a 100644
--- a/src/main.cpp
+++ b/src/main.cpp
@@ -946,7 +946,7 @@ void static InvalidChainFound(CBlockIndex* pindexNew)
{
bnBestInvalidWork = pindexNew->bnChainWork;
CTxDB().WriteBestInvalidWork(bnBestInvalidWork);
- NotifyBlocksChanged();
+ uiInterface.NotifyBlocksChanged();
}
printf("InvalidChainFound: invalid block=%s height=%d work=%s\n", pindexNew->GetBlockHash().ToString().substr(0,20).c_str(), pindexNew->nHeight, pindexNew->bnChainWork.ToString().c_str());
printf("InvalidChainFound: current best=%s height=%d work=%s\n", hashBestChain.ToString().substr(0,20).c_str(), nBestHeight, bnBestChainWork.ToString().c_str());
@@ -1647,7 +1647,7 @@ bool CBlock::AddToBlockIndex(unsigned int nFile, unsigned int nBlockPos)
hashPrevBestCoinBase = vtx[0].GetHash();
}
- NotifyBlocksChanged();
+ uiInterface.NotifyBlocksChanged();
return true;
}
@@ -1858,8 +1858,8 @@ bool CheckDiskSpace(uint64 nAdditionalBytes)
string strMessage = _("Warning: Disk space is low");
strMiscWarning = strMessage;
printf("*** %s\n", strMessage.c_str());
- ThreadSafeMessageBox(strMessage, "Bitcoin", wxOK | wxICON_EXCLAMATION | wxMODAL);
- QueueShutdown();
+ uiInterface.ThreadSafeMessageBox(strMessage, "Bitcoin", MF_OK | MF_ICON_EXCLAMATION | MF_MODAL);
+ uiInterface.QueueShutdown();
return false;
}
return true;
@@ -2204,13 +2204,13 @@ bool CAlert::ProcessAlert()
if (Cancels(alert))
{
printf("cancelling alert %d\n", alert.nID);
- NotifyAlertChanged((*mi).first, CT_DELETED);
+ uiInterface.NotifyAlertChanged((*mi).first, CT_DELETED);
mapAlerts.erase(mi++);
}
else if (!alert.IsInEffect())
{
printf("expiring alert %d\n", alert.nID);
- NotifyAlertChanged((*mi).first, CT_DELETED);
+ uiInterface.NotifyAlertChanged((*mi).first, CT_DELETED);
mapAlerts.erase(mi++);
}
else
@@ -2232,7 +2232,7 @@ bool CAlert::ProcessAlert()
mapAlerts.insert(make_pair(GetHash(), *this));
// Notify UI if it applies to me
if(AppliesToMe())
- NotifyAlertChanged(GetHash(), CT_NEW);
+ uiInterface.NotifyAlertChanged(GetHash(), CT_NEW);
}
printf("accepted alert %d, AppliesToMe()=%d\n", nID, AppliesToMe());
diff --git a/src/makefile.linux-mingw b/src/makefile.linux-mingw
index 61b38a663e..1e9dd687f3 100644
--- a/src/makefile.linux-mingw
+++ b/src/makefile.linux-mingw
@@ -64,8 +64,7 @@ OBJS= \
obj/sync.o \
obj/util.o \
obj/wallet.o \
- obj/walletdb.o \
- obj/noui.o
+ obj/walletdb.o
all: bitcoind.exe
diff --git a/src/makefile.mingw b/src/makefile.mingw
index 47bf8d5304..fdd4f4635d 100644
--- a/src/makefile.mingw
+++ b/src/makefile.mingw
@@ -61,8 +61,7 @@ OBJS= \
obj/sync.o \
obj/util.o \
obj/wallet.o \
- obj/walletdb.o \
- obj/noui.o
+ obj/walletdb.o
all: bitcoind.exe
diff --git a/src/makefile.osx b/src/makefile.osx
index 227756f274..d6433a6983 100644
--- a/src/makefile.osx
+++ b/src/makefile.osx
@@ -88,8 +88,7 @@ OBJS= \
obj/sync.o \
obj/util.o \
obj/wallet.o \
- obj/walletdb.o \
- obj/noui.o
+ obj/walletdb.o
ifdef USE_UPNP
DEFS += -DUSE_UPNP=$(USE_UPNP)
diff --git a/src/makefile.unix b/src/makefile.unix
index 04e17866e5..ec6609f991 100644
--- a/src/makefile.unix
+++ b/src/makefile.unix
@@ -108,8 +108,7 @@ OBJS= \
obj/sync.o \
obj/util.o \
obj/wallet.o \
- obj/walletdb.o \
- obj/noui.o
+ obj/walletdb.o
all: bitcoind
diff --git a/src/net.cpp b/src/net.cpp
index 32875b0f06..8eff9cbe78 100644
--- a/src/net.cpp
+++ b/src/net.cpp
@@ -705,7 +705,7 @@ void ThreadSocketHandler2(void* parg)
if (vNodes.size() != nPrevNodeCount)
{
nPrevNodeCount = vNodes.size();
- NotifyNumConnectionsChanged(vNodes.size());
+ uiInterface.NotifyNumConnectionsChanged(vNodes.size());
}
diff --git a/src/noui.cpp b/src/noui.cpp
deleted file mode 100644
index c7b74bea73..0000000000
--- a/src/noui.cpp
+++ /dev/null
@@ -1,59 +0,0 @@
-// Copyright (c) 2010 Satoshi Nakamoto
-// Copyright (c) 2009-2012 The Bitcoin developers
-// Distributed under the MIT/X11 software license, see the accompanying
-// file license.txt or http://www.opensource.org/licenses/mit-license.php.
-#include "ui_interface.h"
-
-#include <string>
-#include "init.h"
-
-int ThreadSafeMessageBox(const std::string& message, const std::string& caption, int style)
-{
- 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)
-{
- return true;
-}
-
-void InitMessage(const std::string &message)
-{
-}
-
-std::string _(const char* psz)
-{
- return psz;
-}
-
-void QueueShutdown()
-{
- // Without UI, Shutdown can simply be started in a new thread
- CreateThread(Shutdown, NULL);
-}
-
-void NotifyBlocksChanged()
-{
-}
-
-void NotifyKeyStoreStatusChanged(CBasicKeyStore *wallet)
-{
-}
-
-void NotifyAddressBookChanged(CWallet *wallet, const std::string &address, const std::string &label, EntryStatus status)
-{
-}
-
-void NotifyTransactionChanged(CWallet *wallet, const uint256 &hashTx, EntryStatus status)
-{
-}
-
-void NotifyNumConnectionsChanged(int newNumConnections)
-{
-}
-
-void NotifyAlertChanged(const uint256 &hash, EntryStatus status)
-{
-}
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 QList<SendCoinsRecipie
}
return TransactionCreationFailed;
}
- if(!ThreadSafeAskFee(nFeeRequired, tr("Sending...").toStdString()))
+ if(!uiInterface.ThreadSafeAskFee(nFeeRequired, tr("Sending...").toStdString()))
{
return Aborted;
}
@@ -254,6 +261,46 @@ bool WalletModel::backupWallet(const QString &filename)
return BackupWallet(*wallet, filename.toLocal8Bit().data());
}
+// Handlers for core signals
+static void NotifyKeyStoreStatusChanged(WalletModel *walletmodel, CCryptoKeyStore *wallet)
+{
+ OutputDebugStringF("NotifyKeyStoreStatusChanged\n");
+ QMetaObject::invokeMethod(walletmodel, "updateStatus", Qt::QueuedConnection);
+}
+
+static void NotifyAddressBookChanged(WalletModel *walletmodel, CWallet *wallet, const std::string &address, const std::string &label, ChangeType status)
+{
+ OutputDebugStringF("NotifyAddressBookChanged %s %s status=%i\n", address.c_str(), label.c_str(), status);
+ QMetaObject::invokeMethod(walletmodel, "updateAddressBook", Qt::QueuedConnection,
+ Q_ARG(QString, QString::fromStdString(address)),
+ Q_ARG(QString, QString::fromStdString(label)),
+ Q_ARG(int, status));
+}
+
+static void NotifyTransactionChanged(WalletModel *walletmodel, CWallet *wallet, const uint256 &hash, ChangeType status)
+{
+ OutputDebugStringF("NotifyTransactionChanged %s status=%i\n", hash.GetHex().c_str(), status);
+ QMetaObject::invokeMethod(walletmodel, "updateTransaction", Qt::QueuedConnection,
+ Q_ARG(QString, QString::fromStdString(hash.GetHex())),
+ Q_ARG(int, status));
+}
+
+void WalletModel::subscribeToCoreSignals()
+{
+ // Connect signals to wallet
+ wallet->NotifyStatusChanged.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);
diff --git a/src/ui_interface.h b/src/ui_interface.h
index c1ed265a01..954a781005 100644
--- a/src/ui_interface.h
+++ b/src/ui_interface.h
@@ -6,40 +6,47 @@
#include <string>
#include "util.h" // for int64
+#include <boost/signals2/signal.hpp>
+#include <boost/signals2/last_value.hpp>
class CBasicKeyStore;
class CWallet;
class uint256;
-#define wxYES 0x00000002
-#define wxOK 0x00000004
-#define wxNO 0x00000008
-#define wxYES_NO (wxYES|wxNO)
-#define wxCANCEL 0x00000010
-#define wxAPPLY 0x00000020
-#define wxCLOSE 0x00000040
-#define wxOK_DEFAULT 0x00000000
-#define wxYES_DEFAULT 0x00000000
-#define wxNO_DEFAULT 0x00000080
-#define wxCANCEL_DEFAULT 0x80000000
-#define wxICON_EXCLAMATION 0x00000100
-#define wxICON_HAND 0x00000200
-#define wxICON_WARNING wxICON_EXCLAMATION
-#define wxICON_ERROR wxICON_HAND
-#define wxICON_QUESTION 0x00000400
-#define wxICON_INFORMATION 0x00000800
-#define wxICON_STOP wxICON_HAND
-#define wxICON_ASTERISK wxICON_INFORMATION
-#define wxICON_MASK (0x00000100|0x00000200|0x00000400|0x00000800)
-#define wxFORWARD 0x00001000
-#define wxBACKWARD 0x00002000
-#define wxRESET 0x00004000
-#define wxHELP 0x00008000
-#define wxMORE 0x00010000
-#define wxSETUP 0x00020000
-// Force blocking, modal message box dialog (not just notification)
-#define wxMODAL 0x00040000
+/** Flags for CClientUIInterface::ThreadSafeMessageBox */
+enum MessageBoxFlags
+{
+ MF_YES = 0x00000002,
+ MF_OK = 0x00000004,
+ MF_NO = 0x00000008,
+ MF_YES_NO = (MF_YES|MF_NO),
+ MF_CANCEL = 0x00000010,
+ MF_APPLY = 0x00000020,
+ MF_CLOSE = 0x00000040,
+ MF_OK_DEFAULT = 0x00000000,
+ MF_YES_DEFAULT = 0x00000000,
+ MF_NO_DEFAULT = 0x00000080,
+ MF_CANCEL_DEFAULT = 0x80000000,
+ MF_ICON_EXCLAMATION = 0x00000100,
+ MF_ICON_HAND = 0x00000200,
+ MF_ICON_WARNING = MF_ICON_EXCLAMATION,
+ MF_ICON_ERROR = MF_ICON_HAND,
+ MF_ICON_QUESTION = 0x00000400,
+ MF_ICON_INFORMATION = 0x00000800,
+ MF_ICON_STOP = MF_ICON_HAND,
+ MF_ICON_ASTERISK = MF_ICON_INFORMATION,
+ MF_ICON_MASK = (0x00000100|0x00000200|0x00000400|0x00000800),
+ MF_FORWARD = 0x00001000,
+ MF_BACKWARD = 0x00002000,
+ MF_RESET = 0x00004000,
+ MF_HELP = 0x00008000,
+ MF_MORE = 0x00010000,
+ MF_SETUP = 0x00020000,
+// Force blocking, modal message box dialog (not just OS notification)
+ MF_MODAL = 0x00040000
+};
+/** General change type (added, updated, removed). */
enum ChangeType
{
CT_NEW,
@@ -47,39 +54,51 @@ enum ChangeType
CT_DELETED
};
-/* These UI communication functions are implemented in bitcoin.cpp (for ui) and noui.cpp (no ui) */
+/** Signals for UI communication. */
+class CClientUIInterface
+{
+public:
+ /** Show message box. */
+ boost::signals2::signal<void (const std::string& message, const std::string& caption, int style)> ThreadSafeMessageBox;
-extern int ThreadSafeMessageBox(const std::string& message, const std::string& caption, int style=wxOK);
-extern bool ThreadSafeAskFee(int64 nFeeRequired, const std::string& strCaption);
-extern void ThreadSafeHandleURI(const std::string& strURI);
-extern void QueueShutdown();
-extern void InitMessage(const std::string &message);
-extern std::string _(const char* psz);
+ /** Ask the user whether he want to pay a fee or not. */
+ boost::signals2::signal<bool (int64 nFeeRequired, const std::string& strCaption), boost::signals2::last_value<bool> > ThreadSafeAskFee;
-/* Block chain changed. */
-extern void NotifyBlocksChanged();
+ /** Handle an URL passed on the command line. */
+ boost::signals2::signal<void (const std::string& strURI)> ThreadSafeHandleURI;
-/* Wallet status (encrypted, locked) changed.
- * Note: Called without locks held.
- */
-extern void NotifyKeyStoreStatusChanged(CBasicKeyStore *wallet);
+ /** Progress message during initialization. */
+ boost::signals2::signal<void (const std::string &message)> InitMessage;
-/* Address book entry changed.
- * Note: called with lock cs_wallet held.
- */
-extern void NotifyAddressBookChanged(CWallet *wallet, const std::string &address, const std::string &label, ChangeType status);
+ /** Initiate client shutdown. */
+ boost::signals2::signal<void ()> QueueShutdown;
-/* Wallet transaction added, removed or updated.
- * Note: called with lock cs_wallet held.
- */
-extern void NotifyTransactionChanged(CWallet *wallet, const uint256 &hashTx, ChangeType status);
+ /** Translate a message to the native language of the user. */
+ boost::signals2::signal<std::string (const char* psz)> Translate;
-/* Number of connections changed. */
-extern void NotifyNumConnectionsChanged(int newNumConnections);
+ /** Block chain changed. */
+ boost::signals2::signal<void ()> NotifyBlocksChanged;
-/* New, updated or cancelled alert.
- * Note: called with lock cs_mapAlerts held.
+ /** Number of network connections changed. */
+ boost::signals2::signal<void (int newNumConnections)> NotifyNumConnectionsChanged;
+
+ /**
+ * New, updated or cancelled alert.
+ * @note called with lock cs_mapAlerts held.
+ */
+ boost::signals2::signal<void (const uint256 &hash, ChangeType status)> NotifyAlertChanged;
+};
+
+extern CClientUIInterface uiInterface;
+
+/**
+ * Translation function: Call Translate signal on UI interface, which returns a boost::optional result.
+ * If no translation slot is registered, nothing is returned, and simply return the input.
*/
-extern void NotifyAlertChanged(const uint256 &hash, ChangeType status);
+inline std::string _(const char* psz)
+{
+ boost::optional<std::string> rv = uiInterface.Translate(psz);
+ return rv ? (*rv) : psz;
+}
#endif
diff --git a/src/util.cpp b/src/util.cpp
index c778e51e3b..a9b65ed941 100644
--- a/src/util.cpp
+++ b/src/util.cpp
@@ -1000,7 +1000,7 @@ void AddTimeData(const CNetAddr& ip, int64 nTime)
string strMessage = _("Warning: Please check that your computer's date and time are correct. If your clock is wrong Bitcoin will not work properly.");
strMiscWarning = strMessage;
printf("*** %s\n", strMessage.c_str());
- ThreadSafeMessageBox(strMessage+" ", string("Bitcoin"), wxOK | wxICON_EXCLAMATION);
+ uiInterface.ThreadSafeMessageBox(strMessage+" ", string("Bitcoin"), MF_OK | MF_ICON_EXCLAMATION);
}
}
}
diff --git a/src/wallet.cpp b/src/wallet.cpp
index 132f68bee6..92ad8c0f10 100644
--- a/src/wallet.cpp
+++ b/src/wallet.cpp
@@ -276,7 +276,7 @@ bool CWallet::EncryptWallet(const SecureString& strWalletPassphrase)
CDB::Rewrite(strWalletFile);
}
- NotifyKeyStoreStatusChanged(this);
+ NotifyStatusChanged(this);
return true;
}
@@ -1229,7 +1229,7 @@ string CWallet::SendMoney(CScript scriptPubKey, int64 nValue, CWalletTx& wtxNew,
return strError;
}
- if (fAskFee && !ThreadSafeAskFee(nFeeRequired, _("Sending...")))
+ if (fAskFee && !uiInterface.ThreadSafeAskFee(nFeeRequired, _("Sending...")))
return "ABORTED";
if (!CommitTransaction(wtxNew, reservekey))
diff --git a/src/wallet.h b/src/wallet.h
index f84e6a3292..b3b2e4f468 100644
--- a/src/wallet.h
+++ b/src/wallet.h
@@ -9,6 +9,7 @@
#include "key.h"
#include "keystore.h"
#include "script.h"
+#include "ui_interface.h"
class CWalletTx;
class CReserveKey;
@@ -261,6 +262,16 @@ public:
// get the current wallet format (the oldest client version guaranteed to understand this wallet)
int GetVersion() { return nWalletVersion; }
+
+ /** Address book entry changed.
+ * @note called with lock cs_wallet held.
+ */
+ boost::signals2::signal<void (CWallet *wallet, const std::string &address, const std::string &label, ChangeType status)> NotifyAddressBookChanged;
+
+ /** Wallet transaction added, removed or updated.
+ * @note called with lock cs_wallet held.
+ */
+ boost::signals2::signal<void (CWallet *wallet, const uint256 &hashTx, ChangeType status)> NotifyTransactionChanged;
};
/** A key allocated from the key pool. */