diff --git a/src/qt/bitcoin.cpp b/src/qt/bitcoin.cpp index 791a29f7a00..aa18549a7b8 100644 --- a/src/qt/bitcoin.cpp +++ b/src/qt/bitcoin.cpp @@ -257,6 +257,8 @@ void BitcoinApplication::createOptionsModel(bool resetSettings) void BitcoinApplication::createWindow(const NetworkStyle *networkStyle) { window = new BitcoinGUI(node(), platformStyle, networkStyle, nullptr); + connect(window, &BitcoinGUI::quitClicked, this, &BitcoinApplication::requestShutdown); + connect(window, &BitcoinGUI::rpcExecutorThreadFinished, this, &BitcoinApplication::requestNodeShutdown); pollShutdownTimer = new QTimer(window); connect(pollShutdownTimer, &QTimer::timeout, window, &BitcoinGUI::detectShutdown); @@ -338,9 +340,7 @@ void BitcoinApplication::requestShutdown() // for example the RPC console may still be executing a command. shutdownWindow.reset(ShutdownWindow::showShutdownWindow(window)); - qDebug() << __func__ << ": Requesting shutdown"; - startThread(); - window->hide(); + window->hideAll(); // Must disconnect node signals otherwise current thread can deadlock since // no event loop is running. window->unsubscribeFromCoreSignals(); @@ -354,9 +354,6 @@ void BitcoinApplication::requestShutdown() delete clientModel; clientModel = nullptr; - - // Request shutdown from core thread - Q_EMIT requestedShutdown(); } void BitcoinApplication::initializeResult(bool success, interfaces::BlockAndHeaderTipInfo tip_info) @@ -406,13 +403,21 @@ void BitcoinApplication::initializeResult(bool success, interfaces::BlockAndHead pollShutdownTimer->start(200); } else { Q_EMIT splashFinished(); // Make sure splash screen doesn't stick around during shutdown - quit(); // Exit first main loop invocation + requestNodeShutdown(); } } +void BitcoinApplication::requestNodeShutdown() +{ + qDebug() << __func__ << ": Requesting shutdown"; + startThread(); + // Request shutdown from core thread + Q_EMIT requestedShutdown(); +} + void BitcoinApplication::shutdownResult() { - quit(); // Exit second main loop invocation after shutdown finished + quit(); } void BitcoinApplication::handleRunawayException(const QString &message) @@ -616,8 +621,6 @@ int GuiMain(int argc, char* argv[]) #if defined(Q_OS_WIN) WinShutdownMonitor::registerShutdownBlockReason(QObject::tr("%1 didn't yet exit safely...").arg(PACKAGE_NAME), (HWND)app.getMainWinId()); #endif - app.exec(); - app.requestShutdown(); app.exec(); rv = app.getReturnValue(); } else { diff --git a/src/qt/bitcoin.h b/src/qt/bitcoin.h index 69e0a5921e7..1c065f82bb7 100644 --- a/src/qt/bitcoin.h +++ b/src/qt/bitcoin.h @@ -78,8 +78,6 @@ class BitcoinApplication: public QApplication /// Request core initialization void requestInitialize(); - /// Request core shutdown - void requestShutdown(); /// Get process return value int getReturnValue() const { return returnValue; } @@ -95,6 +93,9 @@ class BitcoinApplication: public QApplication public Q_SLOTS: void initializeResult(bool success, interfaces::BlockAndHeaderTipInfo tip_info); + /// Request core shutdown + void requestShutdown(); + void requestNodeShutdown(); void shutdownResult(); /// Handle runaway exceptions. Shows a message box with the problem and quits the program. void handleRunawayException(const QString &message); diff --git a/src/qt/bitcoingui.cpp b/src/qt/bitcoingui.cpp index 6677c9e3b59..bae0902d281 100644 --- a/src/qt/bitcoingui.cpp +++ b/src/qt/bitcoingui.cpp @@ -98,6 +98,8 @@ BitcoinGUI::BitcoinGUI(interfaces::Node& node, const PlatformStyle *_platformSty updateWindowTitle(); rpcConsole = new RPCConsole(node, _platformStyle, nullptr); + connect(rpcConsole, &RPCConsole::executorThreadFinished, this, &BitcoinGUI::rpcExecutorThreadFinished); + helpMessageDialog = new HelpMessageDialog(this, false); #ifdef ENABLE_WALLET if(enableWallet) @@ -228,8 +230,6 @@ BitcoinGUI::~BitcoinGUI() QSettings settings; settings.setValue("MainWindowGeometry", saveGeometry()); - if(trayIcon) // Hide tray icon, as deleting will let it linger until quit (on Ubuntu) - trayIcon->hide(); #ifdef Q_OS_MAC delete m_app_nap_inhibitor; delete appMenuBar; @@ -369,15 +369,13 @@ void BitcoinGUI::createActions() m_mask_values_action->setStatusTip(tr("Mask the values in the Overview tab")); m_mask_values_action->setCheckable(true); - connect(quitAction, &QAction::triggered, qApp, QApplication::quit); + connect(quitAction, &QAction::triggered, this, &BitcoinGUI::quitClicked); connect(aboutAction, &QAction::triggered, this, &BitcoinGUI::aboutClicked); connect(aboutQtAction, &QAction::triggered, qApp, QApplication::aboutQt); connect(optionsAction, &QAction::triggered, this, &BitcoinGUI::optionsClicked); connect(toggleHideAction, &QAction::triggered, this, &BitcoinGUI::toggleHidden); connect(showHelpMessageAction, &QAction::triggered, this, &BitcoinGUI::showHelpMessageClicked); connect(openRPCConsoleAction, &QAction::triggered, this, &BitcoinGUI::showDebugWindow); - // prevents an open debug window from becoming stuck/unusable on client shutdown - connect(quitAction, &QAction::triggered, rpcConsole, &QWidget::hide); #ifdef ENABLE_WALLET if(walletFrame) @@ -625,11 +623,6 @@ void BitcoinGUI::setClientModel(ClientModel *_clientModel, interfaces::BlockAndH } else { // Disable possibility to show main window via action toggleHideAction->setEnabled(false); - if(trayIconMenu) - { - // Disable context menu on tray icon - trayIconMenu->clear(); - } // Propagate cleared model to child objects rpcConsole->setClientModel(nullptr); #ifdef ENABLE_WALLET @@ -955,6 +948,7 @@ void BitcoinGUI::openOptionsDialogWithTab(OptionsDialog::Tab tab) OptionsDialog dlg(this, enableWallet); dlg.setCurrentTab(tab); dlg.setModel(clientModel->getOptionsModel()); + connect(&dlg, &OptionsDialog::quitOnReset, this, &BitcoinGUI::quitClicked); dlg.exec(); } @@ -1167,10 +1161,7 @@ void BitcoinGUI::closeEvent(QCloseEvent *event) { if(!clientModel->getOptionsModel()->getMinimizeOnClose()) { - // close rpcConsole in case it was open to make some space for the shutdown window - rpcConsole->close(); - - QApplication::quit(); + Q_EMIT quitClicked(); } else { @@ -1363,9 +1354,7 @@ void BitcoinGUI::detectShutdown() { if (m_node.shutdownRequested()) { - if(rpcConsole) - rpcConsole->hide(); - qApp->quit(); + Q_EMIT quitClicked(); } } @@ -1395,6 +1384,14 @@ void BitcoinGUI::showModalOverlay() modalOverlay->toggleVisibility(); } +void BitcoinGUI::hideAll() +{ + trayIconMenu->clear(); + trayIcon->hide(); + rpcConsole->hide(); + hide(); +} + static bool ThreadSafeMessageBox(BitcoinGUI* gui, const bilingual_str& message, const std::string& caption, unsigned int style) { bool modal = (style & CClientUIInterface::MODAL); diff --git a/src/qt/bitcoingui.h b/src/qt/bitcoingui.h index 147f19e68df..82cb7258cd8 100644 --- a/src/qt/bitcoingui.h +++ b/src/qt/bitcoingui.h @@ -211,6 +211,8 @@ class BitcoinGUI : public QMainWindow void openOptionsDialogWithTab(OptionsDialog::Tab tab); Q_SIGNALS: + void quitClicked(); + void rpcExecutorThreadFinished(); /** Signal raised when a URI was entered or dragged to the GUI */ void receivedURI(const QString &uri); /** Signal raised when RPC console shown */ @@ -319,6 +321,9 @@ public Q_SLOTS: void showProgress(const QString &title, int nProgress); void showModalOverlay(); + + /** Hide all windows and tray icon. */ + void hideAll(); }; class UnitDisplayStatusBarControl : public QLabel diff --git a/src/qt/optionsdialog.cpp b/src/qt/optionsdialog.cpp index e6b9488344f..8b801695f62 100644 --- a/src/qt/optionsdialog.cpp +++ b/src/qt/optionsdialog.cpp @@ -282,7 +282,8 @@ void OptionsDialog::on_resetButton_clicked() /* reset all options and close GUI */ model->Reset(); - QApplication::quit(); + close(); + Q_EMIT quitOnReset(); } } diff --git a/src/qt/optionsdialog.h b/src/qt/optionsdialog.h index ba35ff3b67e..f14aec3449b 100644 --- a/src/qt/optionsdialog.h +++ b/src/qt/optionsdialog.h @@ -68,6 +68,7 @@ private Q_SLOTS: Q_SIGNALS: void proxyIpChecks(QValidatedLineEdit *pUiProxyIp, uint16_t nProxyPort); + void quitOnReset(); private: Ui::OptionsDialog *ui; diff --git a/src/qt/rpcconsole.cpp b/src/qt/rpcconsole.cpp index b2582198941..fa2e48981f1 100644 --- a/src/qt/rpcconsole.cpp +++ b/src/qt/rpcconsole.cpp @@ -707,8 +707,8 @@ void RPCConsole::setClientModel(ClientModel *model, int bestblock_height, int64_ } if (!model) { // Client model is being set to 0, this means shutdown() is about to be called. + connect(&thread, &QThread::finished, this, &RPCConsole::executorThreadFinished); thread.quit(); - thread.wait(); } } diff --git a/src/qt/rpcconsole.h b/src/qt/rpcconsole.h index b9806e40c97..d8f01262d0e 100644 --- a/src/qt/rpcconsole.h +++ b/src/qt/rpcconsole.h @@ -134,6 +134,7 @@ public Q_SLOTS: Q_SIGNALS: // For RPC command executor void cmdRequest(const QString &command, const WalletModel* wallet_model); + void executorThreadFinished(); private: struct TranslatedStrings {