Skip to content

Commit

Permalink
[backport#15450 1/5] gui: Refactor OpenWalletActivity
Browse files Browse the repository at this point in the history
Summary:
bitcoin/bitcoin@bc6d8a3

Partial backport of Core [[bitcoin/bitcoin#15450 | PR15450]]

depends on D7108

Test Plan:
  ninja check

Open bitcoin-qt open and close wallets to make sure it works as before

Reviewers: #bitcoin_abc, deadalnix

Reviewed By: #bitcoin_abc, deadalnix

Subscribers: deadalnix

Differential Revision: https://reviews.bitcoinabc.org/D7102
  • Loading branch information
promag authored and majcosta committed Aug 3, 2020
1 parent ad8837b commit e677cd7
Show file tree
Hide file tree
Showing 3 changed files with 113 additions and 73 deletions.
34 changes: 5 additions & 29 deletions src/qt/bitcoingui.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -459,39 +459,15 @@ void BitcoinGUI::createActions() {
continue;
}

connect(action, &QAction::triggered, [this, name, path] {
OpenWalletActivity *activity =
m_wallet_controller->openWallet(
config->GetChainParams(), path);

QProgressDialog *dialog = new QProgressDialog(this);
dialog->setLabelText(tr("Opening Wallet <b>%1</b>...")
.arg(name.toHtmlEscaped()));
dialog->setRange(0, 0);
dialog->setCancelButton(nullptr);
dialog->setWindowModality(Qt::ApplicationModal);
dialog->show();

connect(activity, &OpenWalletActivity::message, this,
[this](QMessageBox::Icon icon, QString text) {
QMessageBox box;
box.setIcon(icon);
box.setText(tr("Open Wallet Failed"));
box.setInformativeText(text);
box.setStandardButtons(QMessageBox::Ok);
box.setDefaultButton(QMessageBox::Ok);
connect(this, &QObject::destroyed, &box,
&QDialog::accept);
box.exec();
});
connect(action, &QAction::triggered, [this, path] {
auto activity =
new OpenWalletActivity(m_wallet_controller, this,
this->config->GetChainParams());
connect(activity, &OpenWalletActivity::opened, this,
&BitcoinGUI::setCurrentWallet);
connect(activity, &OpenWalletActivity::finished, activity,
&QObject::deleteLater);
connect(activity, &OpenWalletActivity::finished, dialog,
&QObject::deleteLater);
bool invoked = QMetaObject::invokeMethod(activity, "open");
assert(invoked);
activity->open(path);
});
}
if (m_open_wallet_menu->isEmpty()) {
Expand Down
96 changes: 67 additions & 29 deletions src/qt/walletcontroller.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -2,22 +2,25 @@
// Distributed under the MIT software license, see the accompanying
// file COPYING or http://www.opensource.org/licenses/mit-license.php.

#include <qt/guiutil.h>
#include <qt/walletcontroller.h>

#include <interfaces/handler.h>
#include <interfaces/node.h>

#include <QApplication>
#include <QMutexLocker>
#include <QTimer>
#include <QWindow>

#include <algorithm>

WalletController::WalletController(interfaces::Node &node,
const PlatformStyle *platform_style,
OptionsModel *options_model, QObject *parent)
: QObject(parent), m_node(node), m_platform_style(platform_style),
m_options_model(options_model) {
: QObject(parent), m_activity_thread(new QThread(this)),
m_activity_worker(new QObject), m_node(node),
m_platform_style(platform_style), m_options_model(options_model) {
m_handler_load_wallet = m_node.handleLoadWallet(
[this](std::unique_ptr<interfaces::Wallet> wallet) {
getOrCreateWallet(std::move(wallet));
Expand All @@ -27,14 +30,16 @@ WalletController::WalletController(interfaces::Node &node,
getOrCreateWallet(std::move(wallet));
}

m_activity_thread.start();
m_activity_worker->moveToThread(m_activity_thread);
m_activity_thread->start();
}

// Not using the default destructor because not all member types definitions are
// available in the header, just forward declared.
WalletController::~WalletController() {
m_activity_thread.quit();
m_activity_thread.wait();
m_activity_thread->quit();
m_activity_thread->wait();
delete m_activity_worker;
}

std::vector<WalletModel *> WalletController::getOpenWallets() const {
Expand All @@ -57,13 +62,6 @@ std::map<std::string, bool> WalletController::listWalletDir() const {
return wallets;
}

OpenWalletActivity *WalletController::openWallet(const CChainParams &params,
const std::string &name,
QWidget *parent) {
OpenWalletActivity *activity = new OpenWalletActivity(this, name, params);
activity->moveToThread(&m_activity_thread);
return activity;
}
void WalletController::closeWallet(WalletModel *wallet_model, QWidget *parent) {
QMessageBox box(parent);
box.setWindowTitle(tr("Close wallet"));
Expand Down Expand Up @@ -150,25 +148,65 @@ void WalletController::removeAndDeleteWallet(WalletModel *wallet_model) {
delete wallet_model;
}

WalletControllerActivity::WalletControllerActivity(
WalletController *wallet_controller, QWidget *parent_widget,
const CChainParams &chainparams)
: QObject(wallet_controller), m_wallet_controller(wallet_controller),
m_parent_widget(parent_widget), m_chainparams(chainparams) {}

WalletControllerActivity::~WalletControllerActivity() {
delete m_progress_dialog;
}

void WalletControllerActivity::showProgressDialog(const QString &label_text) {
m_progress_dialog = new QProgressDialog(m_parent_widget);

m_progress_dialog->setLabelText(label_text);
m_progress_dialog->setRange(0, 0);
m_progress_dialog->setCancelButton(nullptr);
m_progress_dialog->setWindowModality(Qt::ApplicationModal);
GUIUtil::PolishProgressDialog(m_progress_dialog);
}

OpenWalletActivity::OpenWalletActivity(WalletController *wallet_controller,
const std::string &name,
const CChainParams &params)
: m_wallet_controller(wallet_controller), m_name(name),
m_chain_params(params) {}

void OpenWalletActivity::open() {
std::string error, warning;
std::unique_ptr<interfaces::Wallet> 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));
QWidget *parent_widget,
const CChainParams &chainparams)
: WalletControllerActivity(wallet_controller, parent_widget, chainparams) {}

void OpenWalletActivity::finish() {
m_progress_dialog->hide();

if (!m_error_message.empty()) {
QMessageBox::critical(m_parent_widget, tr("Open wallet failed"),
QString::fromStdString(m_error_message));
} else if (!m_warning_message.empty()) {
QMessageBox::warning(m_parent_widget, tr("Open wallet warning"),
QString::fromStdString(m_warning_message));
}
if (wallet) {
Q_EMIT opened(
m_wallet_controller->getOrCreateWallet(std::move(wallet)));
} else {
Q_EMIT message(QMessageBox::Critical, QString::fromStdString(error));

if (m_wallet_model) {
Q_EMIT opened(m_wallet_model);
}

Q_EMIT finished();
}

void OpenWalletActivity::open(const std::string &path) {
QString name = path.empty() ? QString("[" + tr("default wallet") + "]")
: QString::fromStdString(path);

showProgressDialog(
tr("Opening Wallet <b>%1</b>...").arg(name.toHtmlEscaped()));

QTimer::singleShot(0, worker(), [this, path] {
std::unique_ptr<interfaces::Wallet> wallet = node().loadWallet(
this->m_chainparams, path, m_error_message, m_warning_message);

if (wallet) {
m_wallet_model =
m_wallet_controller->getOrCreateWallet(std::move(wallet));
}

QTimer::singleShot(0, this, &OpenWalletActivity::finish);
});
}
56 changes: 41 additions & 15 deletions src/qt/walletcontroller.h
Original file line number Diff line number Diff line change
Expand Up @@ -12,9 +12,12 @@

#include <map>
#include <memory>
#include <string>
#include <vector>

#include <QMessageBox>
#include <QProgressDialog>
#include <QString>
#include <QThread>

class OptionsModel;
Expand All @@ -26,14 +29,14 @@ class Node;
} // namespace interfaces

class OpenWalletActivity;
class WalletControllerActivity;

/**
* Controller between interfaces::Node, WalletModel instances and the GUI.
*/
class WalletController : public QObject {
Q_OBJECT

WalletModel *getOrCreateWallet(std::unique_ptr<interfaces::Wallet> wallet);
void removeAndDeleteWallet(WalletModel *wallet_model);

public:
Expand All @@ -45,13 +48,12 @@ class WalletController : public QObject {
//! Returns wallet models currently open.
std::vector<WalletModel *> getOpenWallets() const;

WalletModel *getOrCreateWallet(std::unique_ptr<interfaces::Wallet> wallet);

//! Returns all wallet names in the wallet dir mapped to whether the wallet
//! is loaded.
std::map<std::string, bool> listWalletDir() const;

OpenWalletActivity *openWallet(const CChainParams &params,
const std::string &name,
QWidget *parent = nullptr);
void closeWallet(WalletModel *wallet_model, QWidget *parent = nullptr);

Q_SIGNALS:
Expand All @@ -62,36 +64,60 @@ class WalletController : public QObject {
QByteArray transaction);

private:
QThread m_activity_thread;
QThread *const m_activity_thread;
QObject *const m_activity_worker;
interfaces::Node &m_node;
const PlatformStyle *const m_platform_style;
OptionsModel *const m_options_model;
mutable QMutex m_mutex;
std::vector<WalletModel *> m_wallets;
std::unique_ptr<interfaces::Handler> m_handler_load_wallet;

friend class OpenWalletActivity;
friend class WalletControllerActivity;
};

class WalletControllerActivity : public QObject {
Q_OBJECT

public:
WalletControllerActivity(WalletController *wallet_controller,
QWidget *parent_widget,
const CChainParams &chainparams);
virtual ~WalletControllerActivity();

Q_SIGNALS:
void finished();

protected:
interfaces::Node &node() const { return m_wallet_controller->m_node; }
QObject *worker() const { return m_wallet_controller->m_activity_worker; }

void showProgressDialog(const QString &label_text);

WalletController *const m_wallet_controller;
QWidget *const m_parent_widget;
QProgressDialog *m_progress_dialog{nullptr};
WalletModel *m_wallet_model{nullptr};
std::string m_error_message;
std::string m_warning_message;

const CChainParams &m_chainparams;
};

class OpenWalletActivity : public QObject {
class OpenWalletActivity : public WalletControllerActivity {
Q_OBJECT

public:
OpenWalletActivity(WalletController *wallet_controller,
const std::string &name, const CChainParams &params);
QWidget *parent_widget, const CChainParams &chainparams);

public Q_SLOTS:
void open();
void open(const std::string &path);

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;
void finish();
};

#endif // BITCOIN_QT_WALLETCONTROLLER_H

0 comments on commit e677cd7

Please sign in to comment.