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 const char* qt_argv = "bitcoin-qt";
BitcoinApplication::BitcoinApplication(interfaces::Node& node):
BitcoinApplication::BitcoinApplication():
QApplication(qt_argc, const_cast<char **>(&qt_argv)),
coreThread(nullptr),
m_node(node),
optionsModel(nullptr),
clientModel(nullptr),
window(nullptr),
@ -249,12 +248,13 @@ void BitcoinApplication::createPaymentServer()
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)
{
window = new BitcoinGUI(m_node, platformStyle, networkStyle, nullptr);
window = new BitcoinGUI(node(), platformStyle, networkStyle, nullptr);
pollShutdownTimer = new QTimer(window);
connect(pollShutdownTimer, &QTimer::timeout, window, &BitcoinGUI::detectShutdown);
@ -262,17 +262,25 @@ void BitcoinApplication::createWindow(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
// screen will take care of deleting itself when finish() happens.
splash->show();
connect(this, &BitcoinApplication::splashFinished, splash, &SplashScreen::finish);
connect(this, &BitcoinApplication::requestedShutdown, splash, &QWidget::close);
m_splash->show();
connect(this, &BitcoinApplication::splashFinished, m_splash, &SplashScreen::finish);
connect(this, &BitcoinApplication::requestedShutdown, m_splash, &QWidget::close);
}
void BitcoinApplication::setNode(interfaces::Node& node)
{
assert(!m_node);
m_node = &node;
}
bool BitcoinApplication::baseInitialize()
{
return m_node.baseInitialize();
return node().baseInitialize();
}
void BitcoinApplication::startThread()
@ -280,7 +288,7 @@ void BitcoinApplication::startThread()
if(coreThread)
return;
coreThread = new QThread(this);
BitcoinCore *executor = new BitcoinCore(m_node);
BitcoinCore *executor = new BitcoinCore(node());
executor->moveToThread(coreThread);
/* communication to and from thread */
@ -334,7 +342,7 @@ void BitcoinApplication::requestShutdown()
window->unsubscribeFromCoreSignals();
// Request node shutdown, which can interrupt long operations, like
// rescanning a wallet.
m_node.startShutdown();
node().startShutdown();
// 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.
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
qInfo() << "Platform customization:" << platformStyle->getName();
clientModel = new ClientModel(m_node, optionsModel);
clientModel = new ClientModel(node(), optionsModel);
window->setClientModel(clientModel, &tip_info);
#ifdef ENABLE_WALLET
if (WalletModel::isWalletEnabled()) {
@ -456,7 +464,8 @@ int GuiMain(int argc, char* argv[])
QCoreApplication::setAttribute(Qt::AA_EnableHighDpiScaling);
#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
// Command-line options take precedence:
@ -612,10 +621,10 @@ int GuiMain(int argc, char* argv[])
}
} catch (const std::exception& e) {
PrintExceptionContinue(&e, "Runaway exception");
app.handleRunawayException(QString::fromStdString(node->getWarnings().translated));
app.handleRunawayException(QString::fromStdString(app.node().getWarnings().translated));
} catch (...) {
PrintExceptionContinue(nullptr, "Runaway exception");
app.handleRunawayException(QString::fromStdString(node->getWarnings().translated));
app.handleRunawayException(QString::fromStdString(app.node().getWarnings().translated));
}
return rv;
}

View file

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

View file

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

View file

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

View file

@ -24,8 +24,8 @@
#include <QScreen>
SplashScreen::SplashScreen(interfaces::Node& node, Qt::WindowFlags f, const NetworkStyle *networkStyle) :
QWidget(nullptr, f), curAlignment(0), m_node(node)
SplashScreen::SplashScreen(Qt::WindowFlags f, const NetworkStyle *networkStyle) :
QWidget(nullptr, f), curAlignment(0)
{
// set reference point, paddings
int paddingRight = 50;
@ -124,7 +124,6 @@ SplashScreen::SplashScreen(interfaces::Node& node, Qt::WindowFlags f, const Netw
setFixedSize(r.size());
move(QGuiApplication::primaryScreen()->geometry().center() - r.center());
subscribeToCoreSignals();
installEventFilter(this);
GUIUtil::handleCloseWindowShortcut(this);
@ -132,14 +131,26 @@ SplashScreen::SplashScreen(interfaces::Node& node, Qt::WindowFlags f, const Netw
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) {
if (ev->type() == QEvent::KeyPress) {
QKeyEvent *keyEvent = static_cast<QKeyEvent *>(ev);
if (keyEvent->key() == Qt::Key_Q) {
m_node.startShutdown();
shutdown();
}
}
return QObject::eventFilter(obj, ev);
@ -183,10 +194,10 @@ void SplashScreen::ConnectWallet(std::unique_ptr<interfaces::Wallet> wallet)
void SplashScreen::subscribeToCoreSignals()
{
// Connect signals to client
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_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));
#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
}
@ -221,6 +232,6 @@ void SplashScreen::paintEvent(QPaintEvent *event)
void SplashScreen::closeEvent(QCloseEvent *event)
{
m_node.startShutdown(); // allows an "emergency" shutdown during startup
shutdown(); // allows an "emergency" shutdown during startup
event->ignore();
}

View file

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

View file

@ -108,7 +108,7 @@ void TestAddAddressesToSendBook(interfaces::Node& node)
// Initialize relevant QT models.
std::unique_ptr<const PlatformStyle> platformStyle(PlatformStyle::instantiate("other"));
OptionsModel optionsModel(node);
OptionsModel optionsModel;
ClientModel clientModel(node, &optionsModel);
AddWallet(wallet);
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
// QApplication:: and QCoreApplication:: in the tests
BitcoinApplication app(*node);
BitcoinApplication app;
app.setNode(*node);
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);
if (QTest::qExec(&app_tests) != 0) {
fInvalid = true;
@ -80,7 +81,7 @@ int main(int argc, char* argv[])
if (QTest::qExec(&test1) != 0) {
fInvalid = true;
}
RPCNestedTests test3(*node);
RPCNestedTests test3(app.node());
if (QTest::qExec(&test3) != 0) {
fInvalid = true;
}
@ -89,11 +90,11 @@ int main(int argc, char* argv[])
fInvalid = true;
}
#ifdef ENABLE_WALLET
WalletTests test5(*node);
WalletTests test5(app.node());
if (QTest::qExec(&test5) != 0) {
fInvalid = true;
}
AddressBookTests test6(*node);
AddressBookTests test6(app.node());
if (QTest::qExec(&test6) != 0) {
fInvalid = true;
}

View file

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