gui: Replace interface::Node references with pointers

No change in behavior. Replacing references with pointers allows Node interface
creation to be delayed until later during gui startup next commit to support
implementing -ipcconnect option
This commit is contained in:
Russell Yanofsky 2018-08-23 13:42:31 -04:00
parent 91aced7c7e
commit 102abff9eb
9 changed files with 74 additions and 41 deletions

View file

@ -196,10 +196,9 @@ void BitcoinCore::shutdown()
static int qt_argc = 1; static int qt_argc = 1;
static const char* qt_argv = "bitcoin-qt"; static const char* qt_argv = "bitcoin-qt";
BitcoinApplication::BitcoinApplication(interfaces::Node& node): BitcoinApplication::BitcoinApplication():
QApplication(qt_argc, const_cast<char **>(&qt_argv)), QApplication(qt_argc, const_cast<char **>(&qt_argv)),
coreThread(nullptr), coreThread(nullptr),
m_node(node),
optionsModel(nullptr), optionsModel(nullptr),
clientModel(nullptr), clientModel(nullptr),
window(nullptr), window(nullptr),
@ -249,12 +248,13 @@ void BitcoinApplication::createPaymentServer()
void BitcoinApplication::createOptionsModel(bool resetSettings) void BitcoinApplication::createOptionsModel(bool resetSettings)
{ {
optionsModel = new OptionsModel(m_node, this, resetSettings); optionsModel = new OptionsModel(this, resetSettings);
optionsModel->setNode(node());
} }
void BitcoinApplication::createWindow(const NetworkStyle *networkStyle) void BitcoinApplication::createWindow(const NetworkStyle *networkStyle)
{ {
window = new BitcoinGUI(m_node, platformStyle, networkStyle, nullptr); window = new BitcoinGUI(node(), platformStyle, networkStyle, nullptr);
pollShutdownTimer = new QTimer(window); pollShutdownTimer = new QTimer(window);
connect(pollShutdownTimer, &QTimer::timeout, window, &BitcoinGUI::detectShutdown); connect(pollShutdownTimer, &QTimer::timeout, window, &BitcoinGUI::detectShutdown);
@ -262,17 +262,25 @@ void BitcoinApplication::createWindow(const NetworkStyle *networkStyle)
void BitcoinApplication::createSplashScreen(const NetworkStyle *networkStyle) void BitcoinApplication::createSplashScreen(const NetworkStyle *networkStyle)
{ {
SplashScreen *splash = new SplashScreen(m_node, nullptr, networkStyle); assert(!m_splash);
m_splash = new SplashScreen(nullptr, networkStyle);
m_splash->setNode(node());
// We don't hold a direct pointer to the splash screen after creation, but the splash // We don't hold a direct pointer to the splash screen after creation, but the splash
// screen will take care of deleting itself when finish() happens. // screen will take care of deleting itself when finish() happens.
splash->show(); m_splash->show();
connect(this, &BitcoinApplication::splashFinished, splash, &SplashScreen::finish); connect(this, &BitcoinApplication::splashFinished, m_splash, &SplashScreen::finish);
connect(this, &BitcoinApplication::requestedShutdown, splash, &QWidget::close); connect(this, &BitcoinApplication::requestedShutdown, m_splash, &QWidget::close);
}
void BitcoinApplication::setNode(interfaces::Node& node)
{
assert(!m_node);
m_node = &node;
} }
bool BitcoinApplication::baseInitialize() bool BitcoinApplication::baseInitialize()
{ {
return m_node.baseInitialize(); return node().baseInitialize();
} }
void BitcoinApplication::startThread() void BitcoinApplication::startThread()
@ -280,7 +288,7 @@ void BitcoinApplication::startThread()
if(coreThread) if(coreThread)
return; return;
coreThread = new QThread(this); coreThread = new QThread(this);
BitcoinCore *executor = new BitcoinCore(m_node); BitcoinCore *executor = new BitcoinCore(node());
executor->moveToThread(coreThread); executor->moveToThread(coreThread);
/* communication to and from thread */ /* communication to and from thread */
@ -334,7 +342,7 @@ void BitcoinApplication::requestShutdown()
window->unsubscribeFromCoreSignals(); window->unsubscribeFromCoreSignals();
// Request node shutdown, which can interrupt long operations, like // Request node shutdown, which can interrupt long operations, like
// rescanning a wallet. // rescanning a wallet.
m_node.startShutdown(); node().startShutdown();
// Unsetting the client model can cause the current thread to wait for node // Unsetting the client model can cause the current thread to wait for node
// to complete an operation, like wait for a RPC execution to complete. // to complete an operation, like wait for a RPC execution to complete.
window->setClientModel(nullptr); window->setClientModel(nullptr);
@ -356,7 +364,7 @@ void BitcoinApplication::initializeResult(bool success, interfaces::BlockAndHead
{ {
// Log this only after AppInitMain finishes, as then logging setup is guaranteed complete // Log this only after AppInitMain finishes, as then logging setup is guaranteed complete
qInfo() << "Platform customization:" << platformStyle->getName(); qInfo() << "Platform customization:" << platformStyle->getName();
clientModel = new ClientModel(m_node, optionsModel); clientModel = new ClientModel(node(), optionsModel);
window->setClientModel(clientModel, &tip_info); window->setClientModel(clientModel, &tip_info);
#ifdef ENABLE_WALLET #ifdef ENABLE_WALLET
if (WalletModel::isWalletEnabled()) { if (WalletModel::isWalletEnabled()) {
@ -456,7 +464,8 @@ int GuiMain(int argc, char* argv[])
QCoreApplication::setAttribute(Qt::AA_EnableHighDpiScaling); QCoreApplication::setAttribute(Qt::AA_EnableHighDpiScaling);
#endif #endif
BitcoinApplication app(*node); BitcoinApplication app;
app.setNode(*node);
/// 2. Parse command-line options. We do this after qt in order to show an error if there are problems parsing these /// 2. Parse command-line options. We do this after qt in order to show an error if there are problems parsing these
// Command-line options take precedence: // Command-line options take precedence:
@ -612,10 +621,10 @@ int GuiMain(int argc, char* argv[])
} }
} catch (const std::exception& e) { } catch (const std::exception& e) {
PrintExceptionContinue(&e, "Runaway exception"); PrintExceptionContinue(&e, "Runaway exception");
app.handleRunawayException(QString::fromStdString(node->getWarnings().translated)); app.handleRunawayException(QString::fromStdString(app.node().getWarnings().translated));
} catch (...) { } catch (...) {
PrintExceptionContinue(nullptr, "Runaway exception"); PrintExceptionContinue(nullptr, "Runaway exception");
app.handleRunawayException(QString::fromStdString(node->getWarnings().translated)); app.handleRunawayException(QString::fromStdString(app.node().getWarnings().translated));
} }
return rv; return rv;
} }

View file

@ -10,6 +10,7 @@
#endif #endif
#include <QApplication> #include <QApplication>
#include <assert.h>
#include <memory> #include <memory>
#include <interfaces/node.h> #include <interfaces/node.h>
@ -20,6 +21,7 @@ class NetworkStyle;
class OptionsModel; class OptionsModel;
class PaymentServer; class PaymentServer;
class PlatformStyle; class PlatformStyle;
class SplashScreen;
class WalletController; class WalletController;
class WalletModel; class WalletModel;
@ -54,7 +56,7 @@ class BitcoinApplication: public QApplication
{ {
Q_OBJECT Q_OBJECT
public: public:
explicit BitcoinApplication(interfaces::Node& node); explicit BitcoinApplication();
~BitcoinApplication(); ~BitcoinApplication();
#ifdef ENABLE_WALLET #ifdef ENABLE_WALLET
@ -88,6 +90,9 @@ public:
/// Setup platform style /// Setup platform style
void setupPlatformStyle(); void setupPlatformStyle();
interfaces::Node& node() const { assert(m_node); return *m_node; }
void setNode(interfaces::Node& node);
public Q_SLOTS: public Q_SLOTS:
void initializeResult(bool success, interfaces::BlockAndHeaderTipInfo tip_info); void initializeResult(bool success, interfaces::BlockAndHeaderTipInfo tip_info);
void shutdownResult(); void shutdownResult();
@ -102,7 +107,6 @@ Q_SIGNALS:
private: private:
QThread *coreThread; QThread *coreThread;
interfaces::Node& m_node;
OptionsModel *optionsModel; OptionsModel *optionsModel;
ClientModel *clientModel; ClientModel *clientModel;
BitcoinGUI *window; BitcoinGUI *window;
@ -114,6 +118,8 @@ private:
int returnValue; int returnValue;
const PlatformStyle *platformStyle; const PlatformStyle *platformStyle;
std::unique_ptr<QWidget> shutdownWindow; std::unique_ptr<QWidget> shutdownWindow;
SplashScreen* m_splash = nullptr;
interfaces::Node* m_node = nullptr;
void startThread(); void startThread();
}; };

View file

@ -27,8 +27,8 @@ const char *DEFAULT_GUI_PROXY_HOST = "127.0.0.1";
static const QString GetDefaultProxyAddress(); static const QString GetDefaultProxyAddress();
OptionsModel::OptionsModel(interfaces::Node& node, QObject *parent, bool resetSettings) : OptionsModel::OptionsModel(QObject *parent, bool resetSettings) :
QAbstractListModel(parent), m_node(node) QAbstractListModel(parent)
{ {
Init(resetSettings); Init(resetSettings);
} }
@ -353,7 +353,7 @@ bool OptionsModel::setData(const QModelIndex & index, const QVariant & value, in
break; break;
case MapPortUPnP: // core option - can be changed on-the-fly case MapPortUPnP: // core option - can be changed on-the-fly
settings.setValue("fUseUPnP", value.toBool()); settings.setValue("fUseUPnP", value.toBool());
m_node.mapPort(value.toBool()); node().mapPort(value.toBool());
break; break;
case MinimizeOnClose: case MinimizeOnClose:
fMinimizeOnClose = value.toBool(); fMinimizeOnClose = value.toBool();

View file

@ -11,6 +11,8 @@
#include <QAbstractListModel> #include <QAbstractListModel>
#include <assert.h>
namespace interfaces { namespace interfaces {
class Node; class Node;
} }
@ -39,7 +41,7 @@ class OptionsModel : public QAbstractListModel
Q_OBJECT Q_OBJECT
public: public:
explicit OptionsModel(interfaces::Node& node, QObject *parent = nullptr, bool resetSettings = false); explicit OptionsModel(QObject *parent = nullptr, bool resetSettings = false);
enum OptionID { enum OptionID {
StartAtStartup, // bool StartAtStartup, // bool
@ -92,10 +94,11 @@ public:
void setRestartRequired(bool fRequired); void setRestartRequired(bool fRequired);
bool isRestartRequired() const; bool isRestartRequired() const;
interfaces::Node& node() const { return m_node; } interfaces::Node& node() const { assert(m_node); return *m_node; }
void setNode(interfaces::Node& node) { assert(!m_node); m_node = &node; }
private: private:
interfaces::Node& m_node; interfaces::Node* m_node = nullptr;
/* Qt-only settings */ /* Qt-only settings */
bool fHideTrayIcon; bool fHideTrayIcon;
bool fMinimizeToTray; bool fMinimizeToTray;

View file

@ -24,8 +24,8 @@
#include <QScreen> #include <QScreen>
SplashScreen::SplashScreen(interfaces::Node& node, Qt::WindowFlags f, const NetworkStyle *networkStyle) : SplashScreen::SplashScreen(Qt::WindowFlags f, const NetworkStyle *networkStyle) :
QWidget(nullptr, f), curAlignment(0), m_node(node) QWidget(nullptr, f), curAlignment(0)
{ {
// set reference point, paddings // set reference point, paddings
int paddingRight = 50; int paddingRight = 50;
@ -124,7 +124,6 @@ SplashScreen::SplashScreen(interfaces::Node& node, Qt::WindowFlags f, const Netw
setFixedSize(r.size()); setFixedSize(r.size());
move(QGuiApplication::primaryScreen()->geometry().center() - r.center()); move(QGuiApplication::primaryScreen()->geometry().center() - r.center());
subscribeToCoreSignals();
installEventFilter(this); installEventFilter(this);
GUIUtil::handleCloseWindowShortcut(this); GUIUtil::handleCloseWindowShortcut(this);
@ -132,14 +131,26 @@ SplashScreen::SplashScreen(interfaces::Node& node, Qt::WindowFlags f, const Netw
SplashScreen::~SplashScreen() SplashScreen::~SplashScreen()
{ {
unsubscribeFromCoreSignals(); if (m_node) unsubscribeFromCoreSignals();
}
void SplashScreen::setNode(interfaces::Node& node)
{
assert(!m_node);
m_node = &node;
subscribeToCoreSignals();
}
void SplashScreen::shutdown()
{
if (m_node) m_node->startShutdown();
} }
bool SplashScreen::eventFilter(QObject * obj, QEvent * ev) { bool SplashScreen::eventFilter(QObject * obj, QEvent * ev) {
if (ev->type() == QEvent::KeyPress) { if (ev->type() == QEvent::KeyPress) {
QKeyEvent *keyEvent = static_cast<QKeyEvent *>(ev); QKeyEvent *keyEvent = static_cast<QKeyEvent *>(ev);
if (keyEvent->key() == Qt::Key_Q) { if (keyEvent->key() == Qt::Key_Q) {
m_node.startShutdown(); shutdown();
} }
} }
return QObject::eventFilter(obj, ev); return QObject::eventFilter(obj, ev);
@ -183,10 +194,10 @@ void SplashScreen::ConnectWallet(std::unique_ptr<interfaces::Wallet> wallet)
void SplashScreen::subscribeToCoreSignals() void SplashScreen::subscribeToCoreSignals()
{ {
// Connect signals to client // Connect signals to client
m_handler_init_message = m_node.handleInitMessage(std::bind(InitMessage, this, std::placeholders::_1)); m_handler_init_message = m_node->handleInitMessage(std::bind(InitMessage, this, std::placeholders::_1));
m_handler_show_progress = m_node.handleShowProgress(std::bind(ShowProgress, this, std::placeholders::_1, std::placeholders::_2, std::placeholders::_3)); m_handler_show_progress = m_node->handleShowProgress(std::bind(ShowProgress, this, std::placeholders::_1, std::placeholders::_2, std::placeholders::_3));
#ifdef ENABLE_WALLET #ifdef ENABLE_WALLET
m_handler_load_wallet = m_node.handleLoadWallet([this](std::unique_ptr<interfaces::Wallet> wallet) { ConnectWallet(std::move(wallet)); }); m_handler_load_wallet = m_node->handleLoadWallet([this](std::unique_ptr<interfaces::Wallet> wallet) { ConnectWallet(std::move(wallet)); });
#endif #endif
} }
@ -221,6 +232,6 @@ void SplashScreen::paintEvent(QPaintEvent *event)
void SplashScreen::closeEvent(QCloseEvent *event) void SplashScreen::closeEvent(QCloseEvent *event)
{ {
m_node.startShutdown(); // allows an "emergency" shutdown during startup shutdown(); // allows an "emergency" shutdown during startup
event->ignore(); event->ignore();
} }

View file

@ -28,8 +28,9 @@ class SplashScreen : public QWidget
Q_OBJECT Q_OBJECT
public: public:
explicit SplashScreen(interfaces::Node& node, Qt::WindowFlags f, const NetworkStyle *networkStyle); explicit SplashScreen(Qt::WindowFlags f, const NetworkStyle *networkStyle);
~SplashScreen(); ~SplashScreen();
void setNode(interfaces::Node& node);
protected: protected:
void paintEvent(QPaintEvent *event) override; void paintEvent(QPaintEvent *event) override;
@ -50,6 +51,8 @@ private:
void subscribeToCoreSignals(); void subscribeToCoreSignals();
/** Disconnect core signals to splash screen */ /** Disconnect core signals to splash screen */
void unsubscribeFromCoreSignals(); void unsubscribeFromCoreSignals();
/** Initiate shutdown */
void shutdown();
/** Connect wallet signals to splash screen */ /** Connect wallet signals to splash screen */
void ConnectWallet(std::unique_ptr<interfaces::Wallet> wallet); void ConnectWallet(std::unique_ptr<interfaces::Wallet> wallet);
@ -58,7 +61,7 @@ private:
QColor curColor; QColor curColor;
int curAlignment; int curAlignment;
interfaces::Node& m_node; interfaces::Node* m_node = nullptr;
std::unique_ptr<interfaces::Handler> m_handler_init_message; std::unique_ptr<interfaces::Handler> m_handler_init_message;
std::unique_ptr<interfaces::Handler> m_handler_show_progress; std::unique_ptr<interfaces::Handler> m_handler_show_progress;
std::unique_ptr<interfaces::Handler> m_handler_load_wallet; std::unique_ptr<interfaces::Handler> m_handler_load_wallet;

View file

@ -108,7 +108,7 @@ void TestAddAddressesToSendBook(interfaces::Node& node)
// Initialize relevant QT models. // Initialize relevant QT models.
std::unique_ptr<const PlatformStyle> platformStyle(PlatformStyle::instantiate("other")); std::unique_ptr<const PlatformStyle> platformStyle(PlatformStyle::instantiate("other"));
OptionsModel optionsModel(node); OptionsModel optionsModel;
ClientModel clientModel(node, &optionsModel); ClientModel clientModel(node, &optionsModel);
AddWallet(wallet); AddWallet(wallet);
WalletModel walletModel(interfaces::MakeWallet(wallet), clientModel, platformStyle.get()); WalletModel walletModel(interfaces::MakeWallet(wallet), clientModel, platformStyle.get());

View file

@ -68,10 +68,11 @@ int main(int argc, char* argv[])
// Don't remove this, it's needed to access // Don't remove this, it's needed to access
// QApplication:: and QCoreApplication:: in the tests // QApplication:: and QCoreApplication:: in the tests
BitcoinApplication app(*node); BitcoinApplication app;
app.setNode(*node);
app.setApplicationName("Bitcoin-Qt-test"); app.setApplicationName("Bitcoin-Qt-test");
node->context()->args = &gArgs; // Make gArgs available in the NodeContext app.node().context()->args = &gArgs; // Make gArgs available in the NodeContext
AppTests app_tests(app); AppTests app_tests(app);
if (QTest::qExec(&app_tests) != 0) { if (QTest::qExec(&app_tests) != 0) {
fInvalid = true; fInvalid = true;
@ -80,7 +81,7 @@ int main(int argc, char* argv[])
if (QTest::qExec(&test1) != 0) { if (QTest::qExec(&test1) != 0) {
fInvalid = true; fInvalid = true;
} }
RPCNestedTests test3(*node); RPCNestedTests test3(app.node());
if (QTest::qExec(&test3) != 0) { if (QTest::qExec(&test3) != 0) {
fInvalid = true; fInvalid = true;
} }
@ -89,11 +90,11 @@ int main(int argc, char* argv[])
fInvalid = true; fInvalid = true;
} }
#ifdef ENABLE_WALLET #ifdef ENABLE_WALLET
WalletTests test5(*node); WalletTests test5(app.node());
if (QTest::qExec(&test5) != 0) { if (QTest::qExec(&test5) != 0) {
fInvalid = true; fInvalid = true;
} }
AddressBookTests test6(*node); AddressBookTests test6(app.node());
if (QTest::qExec(&test6) != 0) { if (QTest::qExec(&test6) != 0) {
fInvalid = true; fInvalid = true;
} }

View file

@ -163,7 +163,7 @@ void TestGUI(interfaces::Node& node)
std::unique_ptr<const PlatformStyle> platformStyle(PlatformStyle::instantiate("other")); std::unique_ptr<const PlatformStyle> platformStyle(PlatformStyle::instantiate("other"));
SendCoinsDialog sendCoinsDialog(platformStyle.get()); SendCoinsDialog sendCoinsDialog(platformStyle.get());
TransactionView transactionView(platformStyle.get()); TransactionView transactionView(platformStyle.get());
OptionsModel optionsModel(node); OptionsModel optionsModel;
ClientModel clientModel(node, &optionsModel); ClientModel clientModel(node, &optionsModel);
AddWallet(wallet); AddWallet(wallet);
WalletModel walletModel(interfaces::MakeWallet(wallet), clientModel, platformStyle.get()); WalletModel walletModel(interfaces::MakeWallet(wallet), clientModel, platformStyle.get());