diff --git a/src/qt/bitcoin.cpp b/src/qt/bitcoin.cpp --- a/src/qt/bitcoin.cpp +++ b/src/qt/bitcoin.cpp @@ -555,6 +555,7 @@ // IMPORTANT if it is no longer a typedef use the normal variant above qRegisterMetaType("Amount"); qRegisterMetaType>("std::function"); + qRegisterMetaType("QMessageBox::Icon"); // Need to register any types Qt doesn't know about if you intend // to use them with the signal/slot mechanism Qt provides. Even pointers. diff --git a/src/qt/bitcoingui.cpp b/src/qt/bitcoingui.cpp --- a/src/qt/bitcoingui.cpp +++ b/src/qt/bitcoingui.cpp @@ -453,8 +453,13 @@ : QString::fromStdString(path); QAction *action = m_open_wallet_action->menu()->addAction(name); connect(action, &QAction::triggered, [this, path] { - setCurrentWallet(m_wallet_controller->openWallet( - config->GetChainParams(), path)); + OpenWalletActivity *activity = + m_wallet_controller->openWallet( + config->GetChainParams(), path); + connect(activity, &OpenWalletActivity::opened, this, + &BitcoinGUI::setCurrentWallet); + connect(activity, &OpenWalletActivity::finished, activity, + &QObject::deleteLater); }); } }); diff --git a/src/qt/walletcontroller.h b/src/qt/walletcontroller.h --- a/src/qt/walletcontroller.h +++ b/src/qt/walletcontroller.h @@ -14,6 +14,7 @@ #include #include +#include #include class OptionsModel; @@ -24,6 +25,8 @@ class Node; } // namespace interfaces +class OpenWalletActivity; + /** * Controller between interfaces::Node, WalletModel instances and the GUI. */ @@ -42,8 +45,9 @@ std::vector getWallets() const; std::vector getWalletsAvailableToOpen() const; - WalletModel *openWallet(const CChainParams ¶ms, const std::string &name, - QWidget *parent = nullptr); + OpenWalletActivity *openWallet(const CChainParams ¶ms, + const std::string &name, + QWidget *parent = nullptr); private Q_SLOTS: void addWallet(WalletModel *wallet_model); @@ -63,6 +67,29 @@ mutable QMutex m_mutex; std::vector m_wallets; std::unique_ptr m_handler_load_wallet; + + friend class OpenWalletActivity; +}; + +class OpenWalletActivity : public QObject { + Q_OBJECT + +public: + OpenWalletActivity(WalletController *wallet_controller, + const std::string &name, const CChainParams ¶ms); + +public Q_SLOTS: + void open(); + +Q_SIGNALS: + void message(QMessageBox::Icon icon, const QString text); + void finished(); + void opened(WalletModel *wallet_model); + +private: + WalletController *const m_wallet_controller; + std::string const m_name; + const CChainParams &m_chain_params; }; #endif // BITCOIN_QT_WALLETCONTROLLER_H diff --git a/src/qt/walletcontroller.cpp b/src/qt/walletcontroller.cpp --- a/src/qt/walletcontroller.cpp +++ b/src/qt/walletcontroller.cpp @@ -57,21 +57,13 @@ return wallets; } -WalletModel *WalletController::openWallet(const CChainParams ¶ms, - const std::string &name, - QWidget *parent) { - std::string error, warning; - WalletModel *wallet_model = - getOrCreateWallet(m_node.loadWallet(params, name, error, warning)); - if (wallet_model == nullptr) { - QMessageBox::warning(parent, tr("Open Wallet"), - QString::fromStdString(error)); - } - if (!warning.empty()) { - QMessageBox::information(parent, tr("Open Wallet"), - QString::fromStdString(warning)); - } - return wallet_model; +OpenWalletActivity *WalletController::openWallet(const CChainParams ¶ms, + const std::string &name, + QWidget *parent) { + OpenWalletActivity *activity = new OpenWalletActivity(this, name, params); + activity->moveToThread(&m_activity_thread); + QMetaObject::invokeMethod(activity, "open", Qt::QueuedConnection); + return activity; } WalletModel *WalletController::getOrCreateWallet( std::unique_ptr wallet) { @@ -145,3 +137,26 @@ // CWallet shared pointer. delete wallet_model; } + +OpenWalletActivity::OpenWalletActivity(WalletController *wallet_controller, + const std::string &name, + const CChainParams ¶ms) + : m_wallet_controller(wallet_controller), m_name(name), + m_chain_params(params) {} + +void OpenWalletActivity::open() { + std::string error, warning; + std::unique_ptr wallet = + m_wallet_controller->m_node.loadWallet(m_chain_params, m_name, error, + warning); + if (!warning.empty()) { + Q_EMIT message(QMessageBox::Warning, QString::fromStdString(warning)); + } + if (wallet) { + Q_EMIT opened( + m_wallet_controller->getOrCreateWallet(std::move(wallet))); + } else { + Q_EMIT message(QMessageBox::Critical, QString::fromStdString(error)); + } + Q_EMIT finished(); +}