aboutsummaryrefslogtreecommitdiff
path: root/src/qt
diff options
context:
space:
mode:
authorJonas Schnelli <dev@jonasschnelli.ch>2019-02-12 08:19:05 -1000
committerJonas Schnelli <dev@jonasschnelli.ch>2019-02-12 08:20:50 -1000
commit7d3f255316fc0d45272a38e3fea206105f67dc45 (patch)
tree9ea3977ad966597372981d790b40650e2f820783 /src/qt
parentd8794a78a887a920276c7124f1c46d69592c6c4e (diff)
parent1951ea4342db4122032660139248b79a02c574f3 (diff)
Merge #15153: gui: Add Open Wallet menu
1951ea434 gui: Show indeterminate progress dialog while opening walllet (João Barbosa) 8847cdaaa gui: Add OpenWalletActivity (João Barbosa) 4c8982a88 interfaces: Avoid interface instance if wallet is null (João Barbosa) be82dea23 gui: Add thread to run background activity in WalletController (João Barbosa) 6c49a55b4 gui: Add Open Wallet menu (João Barbosa) 32a8c6abf gui: Add openWallet and getWalletsAvailableToOpen to WalletController (João Barbosa) ab288b4e5 interfaces: Add loadWallet to Node (João Barbosa) 17abc0fd5 wallet: Factor out LoadWallet (João Barbosa) Pull request description: The *Open Wallet* menu has all the available wallets currently not loaded. The list of the available wallets comes from `listWalletDir`. In the future the menu can be replaced by a custom dialog. <img width="674" alt="screenshot 2019-01-12 at 12 17 02" src="https://user-images.githubusercontent.com/3534524/51073166-ac041480-1664-11e9-8302-be81702bc146.png"> Tree-SHA512: ebfd75eee0c8264863748899843afab67dadb7dff21313c11e3cb5b6108d954978dd1f1ae786bc07580c5a771ea4ab38d18c1643c9b9b3683ed53f0f6c582e38
Diffstat (limited to 'src/qt')
-rw-r--r--src/qt/bitcoin.cpp2
-rw-r--r--src/qt/bitcoingui.cpp37
-rw-r--r--src/qt/bitcoingui.h1
-rw-r--r--src/qt/walletcontroller.cpp49
-rw-r--r--src/qt/walletcontroller.h30
5 files changed, 117 insertions, 2 deletions
diff --git a/src/qt/bitcoin.cpp b/src/qt/bitcoin.cpp
index 85d79ee26c..d6c6fd6e98 100644
--- a/src/qt/bitcoin.cpp
+++ b/src/qt/bitcoin.cpp
@@ -456,7 +456,7 @@ int GuiMain(int argc, char* argv[])
// IMPORTANT if it is no longer a typedef use the normal variant above
qRegisterMetaType< CAmount >("CAmount");
qRegisterMetaType< std::function<void()> >("std::function<void()>");
-
+ qRegisterMetaType<QMessageBox::Icon>("QMessageBox::Icon");
/// 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:
node->setupServerArgs();
diff --git a/src/qt/bitcoingui.cpp b/src/qt/bitcoingui.cpp
index ba7e8c7daf..f7a4bad916 100644
--- a/src/qt/bitcoingui.cpp
+++ b/src/qt/bitcoingui.cpp
@@ -334,6 +334,10 @@ void BitcoinGUI::createActions()
openAction = new QAction(platformStyle->TextColorIcon(":/icons/open"), tr("Open &URI..."), this);
openAction->setStatusTip(tr("Open a bitcoin: URI or payment request"));
+ m_open_wallet_action = new QAction(tr("Open Wallet"), this);
+ m_open_wallet_action->setMenu(new QMenu(this));
+ m_open_wallet_action->setStatusTip(tr("Open a wallet"));
+
showHelpMessageAction = new QAction(platformStyle->TextColorIcon(":/icons/info"), tr("&Command-line options"), this);
showHelpMessageAction->setMenuRole(QAction::NoRole);
showHelpMessageAction->setStatusTip(tr("Show the %1 help message to get a list with possible Bitcoin command-line options").arg(tr(PACKAGE_NAME)));
@@ -361,6 +365,37 @@ void BitcoinGUI::createActions()
connect(usedSendingAddressesAction, &QAction::triggered, walletFrame, &WalletFrame::usedSendingAddresses);
connect(usedReceivingAddressesAction, &QAction::triggered, walletFrame, &WalletFrame::usedReceivingAddresses);
connect(openAction, &QAction::triggered, this, &BitcoinGUI::openClicked);
+ connect(m_open_wallet_action->menu(), &QMenu::aboutToShow, [this] {
+ m_open_wallet_action->menu()->clear();
+ for (std::string path : m_wallet_controller->getWalletsAvailableToOpen()) {
+ QString name = path.empty() ? QString("["+tr("default wallet")+"]") : QString::fromStdString(path);
+ QAction* action = m_open_wallet_action->menu()->addAction(name);
+ connect(action, &QAction::triggered, [this, name, path] {
+ OpenWalletActivity* activity = m_wallet_controller->openWallet(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(activity, &OpenWalletActivity::opened, this, &BitcoinGUI::setCurrentWallet);
+ connect(activity, &OpenWalletActivity::finished, activity, &QObject::deleteLater);
+ connect(activity, &OpenWalletActivity::finished, dialog, &QObject::deleteLater);
+ });
+ }
+ });
}
#endif // ENABLE_WALLET
@@ -382,6 +417,8 @@ void BitcoinGUI::createMenuBar()
QMenu *file = appMenuBar->addMenu(tr("&File"));
if(walletFrame)
{
+ file->addAction(m_open_wallet_action);
+ file->addSeparator();
file->addAction(openAction);
file->addAction(backupWalletAction);
file->addAction(signMessageAction);
diff --git a/src/qt/bitcoingui.h b/src/qt/bitcoingui.h
index c31cefe603..c226494020 100644
--- a/src/qt/bitcoingui.h
+++ b/src/qt/bitcoingui.h
@@ -147,6 +147,7 @@ private:
QAction* openRPCConsoleAction = nullptr;
QAction* openAction = nullptr;
QAction* showHelpMessageAction = nullptr;
+ QAction* m_open_wallet_action{nullptr};
QAction* m_wallet_selector_label_action = nullptr;
QAction* m_wallet_selector_action = nullptr;
diff --git a/src/qt/walletcontroller.cpp b/src/qt/walletcontroller.cpp
index df2b7a3f9b..3483c75970 100644
--- a/src/qt/walletcontroller.cpp
+++ b/src/qt/walletcontroller.cpp
@@ -9,6 +9,7 @@
#include <algorithm>
+#include <QMessageBox>
#include <QMutexLocker>
#include <QThread>
@@ -25,11 +26,17 @@ WalletController::WalletController(interfaces::Node& node, const PlatformStyle*
for (std::unique_ptr<interfaces::Wallet>& wallet : m_node.getWallets()) {
getOrCreateWallet(std::move(wallet));
}
+
+ 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() {}
+WalletController::~WalletController()
+{
+ m_activity_thread.quit();
+ m_activity_thread.wait();
+}
std::vector<WalletModel*> WalletController::getWallets() const
{
@@ -37,6 +44,25 @@ std::vector<WalletModel*> WalletController::getWallets() const
return m_wallets;
}
+std::vector<std::string> WalletController::getWalletsAvailableToOpen() const
+{
+ QMutexLocker locker(&m_mutex);
+ std::vector<std::string> wallets = m_node.listWalletDir();
+ for (WalletModel* wallet_model : m_wallets) {
+ auto it = std::remove(wallets.begin(), wallets.end(), wallet_model->wallet().getWalletName());
+ if (it != wallets.end()) wallets.erase(it);
+ }
+ return wallets;
+}
+
+OpenWalletActivity* WalletController::openWallet(const std::string& name, QWidget* parent)
+{
+ OpenWalletActivity* activity = new OpenWalletActivity(this, name);
+ activity->moveToThread(&m_activity_thread);
+ QMetaObject::invokeMethod(activity, "open", Qt::QueuedConnection);
+ return activity;
+}
+
WalletModel* WalletController::getOrCreateWallet(std::unique_ptr<interfaces::Wallet> wallet)
{
QMutexLocker locker(&m_mutex);
@@ -93,3 +119,24 @@ void WalletController::removeAndDeleteWallet(WalletModel* wallet_model)
// CWallet shared pointer.
delete wallet_model;
}
+
+
+OpenWalletActivity::OpenWalletActivity(WalletController* wallet_controller, const std::string& name)
+ : m_wallet_controller(wallet_controller)
+ , m_name(name)
+{}
+
+void OpenWalletActivity::open()
+{
+ 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));
+ }
+ if (wallet) {
+ Q_EMIT opened(m_wallet_controller->getOrCreateWallet(std::move(wallet)));
+ } else {
+ Q_EMIT message(QMessageBox::Critical, QString::fromStdString(error));
+ }
+ Q_EMIT finished();
+}
diff --git a/src/qt/walletcontroller.h b/src/qt/walletcontroller.h
index 22b71b07ff..f19c0e1f3d 100644
--- a/src/qt/walletcontroller.h
+++ b/src/qt/walletcontroller.h
@@ -12,7 +12,9 @@
#include <memory>
#include <vector>
+#include <QMessageBox>
#include <QMutex>
+#include <QThread>
class OptionsModel;
class PlatformStyle;
@@ -22,6 +24,8 @@ class Handler;
class Node;
} // namespace interfaces
+class OpenWalletActivity;
+
/**
* Controller between interfaces::Node, WalletModel instances and the GUI.
*/
@@ -37,6 +41,9 @@ public:
~WalletController();
std::vector<WalletModel*> getWallets() const;
+ std::vector<std::string> getWalletsAvailableToOpen() const;
+
+ OpenWalletActivity* openWallet(const std::string& name, QWidget* parent = nullptr);
private Q_SLOTS:
void addWallet(WalletModel* wallet_model);
@@ -48,12 +55,35 @@ Q_SIGNALS:
void coinsSent(WalletModel* wallet_model, SendCoinsRecipient recipient, QByteArray transaction);
private:
+ QThread m_activity_thread;
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;
+};
+
+class OpenWalletActivity : public QObject
+{
+ Q_OBJECT
+
+public:
+ OpenWalletActivity(WalletController* wallet_controller, const std::string& name);
+
+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;
};
#endif // BITCOIN_QT_WALLETCONTROLLER_H