From 35ecf854c084c248ad640c6af030a9d1ed726c47 Mon Sep 17 00:00:00 2001 From: "Wladimir J. van der Laan" Date: Wed, 8 Jan 2014 08:59:24 +0100 Subject: [PATCH] qt: Remove global references in bitcoin.cpp Remove the need for global references `guiref` and `splashref` by making the BitcoinGUI and SplashScreen classes register for the UI interface signals themselves. --- src/qt/bitcoin.cpp | 69 +++++++++++++---------------------------- src/qt/bitcoingui.cpp | 32 +++++++++++++++++++ src/qt/bitcoingui.h | 5 +++ src/qt/splashscreen.cpp | 34 ++++++++++++++++++++ src/qt/splashscreen.h | 11 +++++++ 5 files changed, 103 insertions(+), 48 deletions(-) diff --git a/src/qt/bitcoin.cpp b/src/qt/bitcoin.cpp index 8bcf187ae..098b17490 100644 --- a/src/qt/bitcoin.cpp +++ b/src/qt/bitcoin.cpp @@ -30,7 +30,6 @@ #include #include #include -#include #include #include #include @@ -56,43 +55,8 @@ Q_IMPORT_PLUGIN(QWindowsIntegrationPlugin); // Declare meta types used for QMetaObject::invokeMethod Q_DECLARE_METATYPE(bool*) -// Need a global reference for the notifications to find the GUI and splash screen -static QWeakPointer guiref; -static QWeakPointer splashref; - -static bool ThreadSafeMessageBox(const std::string& message, const std::string& caption, unsigned int style) -{ - if(!guiref.isNull()) - { - bool modal = (style & CClientUIInterface::MODAL); - bool ret = false; - // In case of modal message, use blocking connection to wait for user to click a button - QMetaObject::invokeMethod(guiref.data(), "message", - modal ? GUIUtil::blockingGUIThreadConnection() : Qt::QueuedConnection, - Q_ARG(QString, QString::fromStdString(caption)), - Q_ARG(QString, QString::fromStdString(message)), - Q_ARG(unsigned int, style), - Q_ARG(bool*, &ret)); - return ret; - } - else - { - LogPrintf("%s: %s\n", caption.c_str(), message.c_str()); - fprintf(stderr, "%s: %s\n", caption.c_str(), message.c_str()); - return false; - } -} - static void InitMessage(const std::string &message) { - if(!splashref.isNull()) - { - QMetaObject::invokeMethod(splashref.data(), "showMessage", - Qt::QueuedConnection, - Q_ARG(QString, QString::fromStdString(message)), - Q_ARG(int, Qt::AlignBottom|Qt::AlignHCenter), - Q_ARG(QColor, QColor(55,55,55))); - } LogPrintf("init message: %s\n", message.c_str()); } @@ -199,6 +163,8 @@ public: void createOptionsModel(); /// Create main window void createWindow(bool isaTestNet); + /// Create splash screen + void createSplashScreen(bool isaTestNet); /// Request core initialization void requestInitialize(); @@ -218,6 +184,7 @@ signals: void requestedInitialize(); void requestedShutdown(); void stopThread(); + void splashFinished(QWidget *window); private: QThread *coreThread; @@ -295,6 +262,10 @@ BitcoinApplication::~BitcoinApplication() emit stopThread(); coreThread->wait(); LogPrintf("Stopped thread\n"); + + delete window; + delete paymentServer; + delete optionsModel; } void BitcoinApplication::createPaymentServer() @@ -310,13 +281,20 @@ void BitcoinApplication::createOptionsModel() void BitcoinApplication::createWindow(bool isaTestNet) { window = new BitcoinGUI(isaTestNet, 0); - guiref = window; QTimer* pollShutdownTimer = new QTimer(window); connect(pollShutdownTimer, SIGNAL(timeout()), window, SLOT(detectShutdown())); pollShutdownTimer->start(200); } +void BitcoinApplication::createSplashScreen(bool isaTestNet) +{ + SplashScreen *splash = new SplashScreen(QPixmap(), 0, isaTestNet); + splash->setAttribute(Qt::WA_DeleteOnClose); + splash->show(); + connect(this, SIGNAL(splashFinished(QWidget*)), splash, SLOT(slotFinish(QWidget*))); +} + void BitcoinApplication::startThread() { coreThread = new QThread(this); @@ -348,9 +326,11 @@ void BitcoinApplication::requestShutdown() window->hide(); window->setClientModel(0); window->removeAllWallets(); - guiref.clear(); delete walletModel; + walletModel = 0; + delete clientModel; + clientModel = 0; // Show a simple window indicating shutdown status QWidget *shutdownWindow = new QWidget(); @@ -382,8 +362,7 @@ void BitcoinApplication::initializeResult(int retval) PaymentServer::LoadRootCAs(); paymentServer->setOptionsModel(optionsModel); - if (!splashref.isNull()) - splashref.data()->finish(window); + emit splashFinished(window); clientModel = new ClientModel(optionsModel); window->setClientModel(clientModel); @@ -489,6 +468,7 @@ int main(int argc, char *argv[]) // Now that QSettings are accessible, initialize translations QTranslator qtTranslatorBase, qtTranslator, translatorBase, translator; initTranslations(qtTranslatorBase, qtTranslator, translatorBase, translator); + uiInterface.Translate.connect(Translate); // Show help message immediately after parsing command-line options (for "-lang") and setting locale, // but before showing splash screen. @@ -543,9 +523,7 @@ int main(int argc, char *argv[]) app.createOptionsModel(); // Subscribe to global signals from core - uiInterface.ThreadSafeMessageBox.connect(ThreadSafeMessageBox); uiInterface.InitMessage.connect(InitMessage); - uiInterface.Translate.connect(Translate); // Show help message immediately after parsing command-line options (for "-lang") and setting locale, // but before showing splash screen. @@ -557,12 +535,7 @@ int main(int argc, char *argv[]) } if (GetBoolArg("-splash", true) && !GetBoolArg("-min", false)) - { - SplashScreen *splash = new SplashScreen(QPixmap(), 0, isaTestNet); - splash->setAttribute(Qt::WA_DeleteOnClose); - splash->show(); - splashref = splash; - } + app.createSplashScreen(isaTestNet); try { diff --git a/src/qt/bitcoingui.cpp b/src/qt/bitcoingui.cpp index 6be5a6401..f8daa08c4 100644 --- a/src/qt/bitcoingui.cpp +++ b/src/qt/bitcoingui.cpp @@ -170,10 +170,16 @@ BitcoinGUI::BitcoinGUI(bool fIsTestnet, QWidget *parent) : // Initially wallet actions should be disabled setWalletActionsEnabled(false); + + // Subscribe to notifications from core + subscribeToCoreSignals(); } BitcoinGUI::~BitcoinGUI() { + // Unsubscribe from notifications from core + unsubscribeFromCoreSignals(); + GUIUtil::saveWindowGeometry("nWindow", this); if(trayIcon) // Hide tray icon, as deleting will let it linger until quit (on Ubuntu) trayIcon->hide(); @@ -851,3 +857,29 @@ void BitcoinGUI::detectShutdown() if (ShutdownRequested()) QMetaObject::invokeMethod(QCoreApplication::instance(), "quit", Qt::QueuedConnection); } + +static bool ThreadSafeMessageBox(BitcoinGUI *gui, const std::string& message, const std::string& caption, unsigned int style) +{ + bool modal = (style & CClientUIInterface::MODAL); + bool ret = false; + // In case of modal message, use blocking connection to wait for user to click a button + QMetaObject::invokeMethod(gui, "message", + modal ? GUIUtil::blockingGUIThreadConnection() : Qt::QueuedConnection, + Q_ARG(QString, QString::fromStdString(caption)), + Q_ARG(QString, QString::fromStdString(message)), + Q_ARG(unsigned int, style), + Q_ARG(bool*, &ret)); + return ret; +} + +void BitcoinGUI::subscribeToCoreSignals() +{ + // Connect signals to client + uiInterface.ThreadSafeMessageBox.connect(boost::bind(ThreadSafeMessageBox, this, _1, _2, _3)); +} + +void BitcoinGUI::unsubscribeFromCoreSignals() +{ + // Disconnect signals from client + uiInterface.ThreadSafeMessageBox.disconnect(boost::bind(ThreadSafeMessageBox, this, _1, _2, _3)); +} diff --git a/src/qt/bitcoingui.h b/src/qt/bitcoingui.h index 75c61d2a8..f5d5bb976 100644 --- a/src/qt/bitcoingui.h +++ b/src/qt/bitcoingui.h @@ -111,6 +111,11 @@ private: /** Enable or disable all wallet-related actions */ void setWalletActionsEnabled(bool enabled); + /** Connect core signals to GUI client */ + void subscribeToCoreSignals(); + /** Disconnect core signals from GUI client */ + void unsubscribeFromCoreSignals(); + signals: /** Signal raised when a URI was entered or dragged to the GUI */ void receivedURI(const QString &uri); diff --git a/src/qt/splashscreen.cpp b/src/qt/splashscreen.cpp index 0e998c6d7..8b16496c1 100644 --- a/src/qt/splashscreen.cpp +++ b/src/qt/splashscreen.cpp @@ -6,6 +6,7 @@ #include "clientversion.h" #include "util.h" +#include "ui_interface.h" #include #include @@ -85,4 +86,37 @@ SplashScreen::SplashScreen(const QPixmap &pixmap, Qt::WindowFlags f, bool isTest pixPaint.end(); this->setPixmap(newPixmap); + + subscribeToCoreSignals(); +} + +SplashScreen::~SplashScreen() +{ + unsubscribeFromCoreSignals(); +} + +void SplashScreen::slotFinish(QWidget *mainWin) +{ + finish(mainWin); +} + +static void InitMessage(SplashScreen *splash, const std::string &message) +{ + QMetaObject::invokeMethod(splash, "showMessage", + Qt::QueuedConnection, + Q_ARG(QString, QString::fromStdString(message)), + Q_ARG(int, Qt::AlignBottom|Qt::AlignHCenter), + Q_ARG(QColor, QColor(55,55,55))); +} + +void SplashScreen::subscribeToCoreSignals() +{ + // Connect signals to client + uiInterface.InitMessage.connect(boost::bind(InitMessage, this, _1)); +} + +void SplashScreen::unsubscribeFromCoreSignals() +{ + // Disconnect signals from client + uiInterface.InitMessage.disconnect(boost::bind(InitMessage, this, _1)); } diff --git a/src/qt/splashscreen.h b/src/qt/splashscreen.h index 070e376c9..6bc10e60a 100644 --- a/src/qt/splashscreen.h +++ b/src/qt/splashscreen.h @@ -15,6 +15,17 @@ class SplashScreen : public QSplashScreen public: explicit SplashScreen(const QPixmap &pixmap, Qt::WindowFlags f, bool isTestNet); + ~SplashScreen(); + +public slots: + /** Slot to call finish() method as it's not defined as slot */ + void slotFinish(QWidget *mainWin); + +private: + /** Connect core signals to splash screen */ + void subscribeToCoreSignals(); + /** Disconnect core signals to splash screen */ + void unsubscribeFromCoreSignals(); }; #endif // SPLASHSCREEN_H