aboutsummaryrefslogtreecommitdiff
path: root/src/qt/walletcontroller.cpp
diff options
context:
space:
mode:
authorfanquake <fanquake@gmail.com>2019-09-07 14:44:47 +0800
committerfanquake <fanquake@gmail.com>2019-09-07 14:45:58 +0800
commitb5a8d0cff1e5f35e51b5c086e4352cc36f354998 (patch)
treebaaf93bab7fd75d0d56760427ac9ff93f718a864 /src/qt/walletcontroller.cpp
parente4b974830ee84269621cddf0370fa12b0fb55bd6 (diff)
parent613de61a04c210a51af9997e69f66439a17a632a (diff)
downloadbitcoin-b5a8d0cff1e5f35e51b5c086e4352cc36f354998.tar.xz
Merge #15450: gui: Create wallet menu option
613de61a04c210a51af9997e69f66439a17a632a Add Create Wallet menu action (Andrew Chow) 9b41cbb28f603f4f71f5854d6ae2527932bba3cb Expose wallet creation to the GUI via WalletController (Andrew Chow) 78863e290006e61060622dbdbecc5b58c0fefa05 Add CreateWalletDialog to create wallets from the GUI (Andrew Chow) 60adb21c7affb41ec475a62a53fb0a36bea35dfb Optionally allow AskPassphraseDialog to output the passphrase (Andrew Chow) bc6d8a3662f0fb992073e5e80269a90a722d76e0 gui: Refactor OpenWalletActivity (João Barbosa) Pull request description: This PR adds a menu option to create a new wallet. When clicked, a `CreateWalletDialog` will be created and prompt the user to name the wallet and choose whether to disable private keys, make a blank wallet, and encrypt the wallet. If the wallet is encrypted, the wallet will be born encrypted with the wallet first created blank, then encrypted, and then a new HD seed generated and set. To allow the newly created wallets to be encrypted, some changes to how encrypting a wallet works. Instead of encrypting and locking the wallet, the wallet will be encrypted and then unlocked. This is also an extra belt-and-suspenders check to make sure that encryption worked. ACKs for top commit: fanquake: ACK 613de61a04c210a51af9997e69f66439a17a632a - re-reviewed on macOS. I'm going to merge this now. It's had a stack of review, and as mentioned multiple times above, lets get this into `master` so it can get more testing pre `v0.19.0`. Tree-SHA512: 3f22cc20b13703ffc90d366ae9133114832fea77f4f319da7fd85eb454f2f0bd5d7e1e6e20284dea2f370d8574f83b45669dcbbe506b994410d32e8e7a6fa877
Diffstat (limited to 'src/qt/walletcontroller.cpp')
-rw-r--r--src/qt/walletcontroller.cpp174
1 files changed, 151 insertions, 23 deletions
diff --git a/src/qt/walletcontroller.cpp b/src/qt/walletcontroller.cpp
index a8e7bce6b5..1a4f51c066 100644
--- a/src/qt/walletcontroller.cpp
+++ b/src/qt/walletcontroller.cpp
@@ -2,8 +2,14 @@
// Distributed under the MIT software license, see the accompanying
// file COPYING or http://www.opensource.org/licenses/mit-license.php.
+#include <qt/askpassphrasedialog.h>
+#include <qt/createwalletdialog.h>
+#include <qt/guiconstants.h>
+#include <qt/guiutil.h>
#include <qt/walletcontroller.h>
+#include <wallet/wallet.h>
+
#include <interfaces/handler.h>
#include <interfaces/node.h>
@@ -13,10 +19,13 @@
#include <QMessageBox>
#include <QMutexLocker>
#include <QThread>
+#include <QTimer>
#include <QWindow>
WalletController::WalletController(interfaces::Node& node, const PlatformStyle* platform_style, OptionsModel* options_model, QObject* parent)
: 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)
@@ -29,15 +38,17 @@ WalletController::WalletController(interfaces::Node& node, const PlatformStyle*
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
@@ -60,13 +71,6 @@ std::map<std::string, bool> WalletController::listWalletDir() const
return wallets;
}
-OpenWalletActivity* WalletController::openWallet(const std::string& name, QWidget* parent)
-{
- OpenWalletActivity* activity = new OpenWalletActivity(this, name);
- activity->moveToThread(&m_activity_thread);
- return activity;
-}
-
void WalletController::closeWallet(WalletModel* wallet_model, QWidget* parent)
{
QMessageBox box(parent);
@@ -140,23 +144,147 @@ void WalletController::removeAndDeleteWallet(WalletModel* wallet_model)
delete wallet_model;
}
+WalletControllerActivity::WalletControllerActivity(WalletController* wallet_controller, QWidget* parent_widget)
+ : QObject(wallet_controller)
+ , m_wallet_controller(wallet_controller)
+ , m_parent_widget(parent_widget)
+{
+}
-OpenWalletActivity::OpenWalletActivity(WalletController* wallet_controller, const std::string& name)
- : m_wallet_controller(wallet_controller)
- , m_name(name)
-{}
+WalletControllerActivity::~WalletControllerActivity()
+{
+ delete m_progress_dialog;
+}
-void OpenWalletActivity::open()
+void WalletControllerActivity::showProgressDialog(const QString& label_text)
{
- std::string error, warning;
- std::unique_ptr<interfaces::Wallet> wallet = m_wallet_controller->m_node.loadWallet(m_name, error, warning);
- if (!warning.empty()) {
- Q_EMIT message(QMessageBox::Warning, QString::fromStdString(warning));
+ 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);
+}
+
+CreateWalletActivity::CreateWalletActivity(WalletController* wallet_controller, QWidget* parent_widget)
+ : WalletControllerActivity(wallet_controller, parent_widget)
+{
+ m_passphrase.reserve(MAX_PASSPHRASE_SIZE);
+}
+
+CreateWalletActivity::~CreateWalletActivity()
+{
+ delete m_create_wallet_dialog;
+ delete m_passphrase_dialog;
+}
+
+void CreateWalletActivity::askPasshprase()
+{
+ m_passphrase_dialog = new AskPassphraseDialog(AskPassphraseDialog::Encrypt, m_parent_widget, &m_passphrase);
+ m_passphrase_dialog->show();
+
+ connect(m_passphrase_dialog, &QObject::destroyed, [this] {
+ m_passphrase_dialog = nullptr;
+ });
+ connect(m_passphrase_dialog, &QDialog::accepted, [this] {
+ createWallet();
+ });
+ connect(m_passphrase_dialog, &QDialog::rejected, [this] {
+ Q_EMIT finished();
+ });
+}
+
+void CreateWalletActivity::createWallet()
+{
+ showProgressDialog(tr("Creating Wallet <b>%1</b>...").arg(m_create_wallet_dialog->walletName().toHtmlEscaped()));
+
+ std::string name = m_create_wallet_dialog->walletName().toStdString();
+ uint64_t flags = 0;
+ if (m_create_wallet_dialog->disablePrivateKeys()) {
+ flags |= WALLET_FLAG_DISABLE_PRIVATE_KEYS;
}
- if (wallet) {
- Q_EMIT opened(m_wallet_controller->getOrCreateWallet(std::move(wallet)));
- } else {
- Q_EMIT message(QMessageBox::Critical, QString::fromStdString(error));
+ if (m_create_wallet_dialog->blank()) {
+ flags |= WALLET_FLAG_BLANK_WALLET;
}
+
+ QTimer::singleShot(500, worker(), [this, name, flags] {
+ std::unique_ptr<interfaces::Wallet> wallet;
+ WalletCreationStatus status = node().createWallet(m_passphrase, flags, name, m_error_message, m_warning_message, wallet);
+
+ if (status == WalletCreationStatus::SUCCESS) m_wallet_model = m_wallet_controller->getOrCreateWallet(std::move(wallet));
+
+ QTimer::singleShot(500, this, &CreateWalletActivity::finish);
+ });
+}
+
+void CreateWalletActivity::finish()
+{
+ m_progress_dialog->hide();
+
+ if (!m_error_message.empty()) {
+ QMessageBox::critical(m_parent_widget, tr("Create wallet failed"), QString::fromStdString(m_error_message));
+ } else if (!m_warning_message.empty()) {
+ QMessageBox::warning(m_parent_widget, tr("Create wallet warning"), QString::fromStdString(m_warning_message));
+ }
+
+ if (m_wallet_model) Q_EMIT created(m_wallet_model);
+
+ Q_EMIT finished();
+}
+
+void CreateWalletActivity::create()
+{
+ m_create_wallet_dialog = new CreateWalletDialog(m_parent_widget);
+ m_create_wallet_dialog->setWindowModality(Qt::ApplicationModal);
+ m_create_wallet_dialog->show();
+
+ connect(m_create_wallet_dialog, &QObject::destroyed, [this] {
+ m_create_wallet_dialog = nullptr;
+ });
+ connect(m_create_wallet_dialog, &QDialog::rejected, [this] {
+ Q_EMIT finished();
+ });
+ connect(m_create_wallet_dialog, &QDialog::accepted, [this] {
+ if (m_create_wallet_dialog->encrypt()) {
+ askPasshprase();
+ } else {
+ createWallet();
+ }
+ });
+}
+
+OpenWalletActivity::OpenWalletActivity(WalletController* wallet_controller, QWidget* parent_widget)
+ : WalletControllerActivity(wallet_controller, parent_widget)
+{
+}
+
+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 (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(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);
+ });
+}