aboutsummaryrefslogtreecommitdiff
path: root/src/qt
diff options
context:
space:
mode:
Diffstat (limited to 'src/qt')
-rw-r--r--src/qt/bitcoin.cpp5
-rw-r--r--src/qt/bitcoingui.cpp45
-rw-r--r--src/qt/bitcoingui.h2
-rw-r--r--src/qt/paymentserver.cpp26
-rw-r--r--src/qt/test/apptests.cpp2
-rw-r--r--src/qt/test/rpcnestedtests.cpp2
-rw-r--r--src/qt/walletcontroller.cpp65
-rw-r--r--src/qt/walletcontroller.h31
8 files changed, 160 insertions, 18 deletions
diff --git a/src/qt/bitcoin.cpp b/src/qt/bitcoin.cpp
index 85d79ee26c..1b063771ef 100644
--- a/src/qt/bitcoin.cpp
+++ b/src/qt/bitcoin.cpp
@@ -55,9 +55,6 @@
#if defined(QT_STATICPLUGIN)
#include <QtPlugin>
-#if QT_VERSION < 0x050400
-Q_IMPORT_PLUGIN(AccessibleFactory)
-#endif
#if defined(QT_QPA_PLATFORM_XCB)
Q_IMPORT_PLUGIN(QXcbIntegrationPlugin);
#elif defined(QT_QPA_PLATFORM_WINDOWS)
@@ -456,7 +453,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..bc88dd5e0a 100644
--- a/src/qt/bitcoingui.cpp
+++ b/src/qt/bitcoingui.cpp
@@ -334,6 +334,13 @@ 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"));
+
+ m_close_wallet_action = new QAction(tr("Close Wallet..."), this);
+ m_close_wallet_action->setStatusTip(tr("Close 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 +368,40 @@ 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);
+ });
+ }
+ });
+ connect(m_close_wallet_action, &QAction::triggered, [this] {
+ m_wallet_controller->closeWallet(walletFrame->currentWalletModel(), this);
+ });
}
#endif // ENABLE_WALLET
@@ -382,6 +423,9 @@ void BitcoinGUI::createMenuBar()
QMenu *file = appMenuBar->addMenu(tr("&File"));
if(walletFrame)
{
+ file->addAction(m_open_wallet_action);
+ file->addAction(m_close_wallet_action);
+ file->addSeparator();
file->addAction(openAction);
file->addAction(backupWalletAction);
file->addAction(signMessageAction);
@@ -656,6 +700,7 @@ void BitcoinGUI::setWalletActionsEnabled(bool enabled)
usedSendingAddressesAction->setEnabled(enabled);
usedReceivingAddressesAction->setEnabled(enabled);
openAction->setEnabled(enabled);
+ m_close_wallet_action->setEnabled(enabled);
}
void BitcoinGUI::createTrayIcon()
diff --git a/src/qt/bitcoingui.h b/src/qt/bitcoingui.h
index c31cefe603..b58ccbb455 100644
--- a/src/qt/bitcoingui.h
+++ b/src/qt/bitcoingui.h
@@ -147,6 +147,8 @@ private:
QAction* openRPCConsoleAction = nullptr;
QAction* openAction = nullptr;
QAction* showHelpMessageAction = nullptr;
+ QAction* m_open_wallet_action{nullptr};
+ QAction* m_close_wallet_action{nullptr};
QAction* m_wallet_selector_label_action = nullptr;
QAction* m_wallet_selector_action = nullptr;
diff --git a/src/qt/paymentserver.cpp b/src/qt/paymentserver.cpp
index b1ec90ad36..43dccec4ea 100644
--- a/src/qt/paymentserver.cpp
+++ b/src/qt/paymentserver.cpp
@@ -292,9 +292,9 @@ void PaymentServer::handleURIOrFile(const QString& s)
else if (s.startsWith(BITCOIN_IPC_PREFIX, Qt::CaseInsensitive)) // bitcoin: URI
{
QUrlQuery uri((QUrl(s)));
+#ifdef ENABLE_BIP70
if (uri.hasQueryItem("r")) // payment request URI
{
-#ifdef ENABLE_BIP70
Q_EMIT message(tr("URI handling"),
tr("You are using a BIP70 URL which will be unsupported in the future."),
CClientUIInterface::ICON_WARNING);
@@ -315,19 +315,23 @@ void PaymentServer::handleURIOrFile(const QString& s)
tr("Payment request fetch URL is invalid: %1").arg(fetchUrl.toString()),
CClientUIInterface::ICON_WARNING);
}
-#else
- Q_EMIT message(tr("URI handling"),
- tr("Cannot process payment request because BIP70 support was not compiled in."),
- CClientUIInterface::ICON_WARNING);
-#endif
return;
}
- else // normal URI
+ else
+#endif
+ // normal URI
{
SendCoinsRecipient recipient;
if (GUIUtil::parseBitcoinURI(s, &recipient))
{
if (!IsValidDestinationString(recipient.address.toStdString())) {
+#ifndef ENABLE_BIP70
+ if (uri.hasQueryItem("r")) { // payment request
+ Q_EMIT message(tr("URI handling"),
+ tr("Cannot process payment request because BIP70 support was not compiled in."),
+ CClientUIInterface::ICON_WARNING);
+ }
+#endif
Q_EMIT message(tr("URI handling"), tr("Invalid payment address %1").arg(recipient.address),
CClientUIInterface::MSG_ERROR);
}
@@ -343,9 +347,9 @@ void PaymentServer::handleURIOrFile(const QString& s)
}
}
-#ifdef ENABLE_BIP70
if (QFile::exists(s)) // payment request file
{
+#ifdef ENABLE_BIP70
PaymentRequestPlus request;
SendCoinsRecipient recipient;
if (!readPaymentRequestFromFile(s, request))
@@ -358,8 +362,12 @@ void PaymentServer::handleURIOrFile(const QString& s)
Q_EMIT receivedPaymentRequest(recipient);
return;
- }
+#else
+ Q_EMIT message(tr("Payment request file handling"),
+ tr("Cannot process payment request because BIP70 support was not compiled in."),
+ CClientUIInterface::ICON_WARNING);
#endif
+ }
}
void PaymentServer::handleURIConnection()
diff --git a/src/qt/test/apptests.cpp b/src/qt/test/apptests.cpp
index 2c477a2e98..da25d83175 100644
--- a/src/qt/test/apptests.cpp
+++ b/src/qt/test/apptests.cpp
@@ -27,9 +27,7 @@
#include <QTest>
#include <QTextEdit>
#include <QtGlobal>
-#if QT_VERSION >= 0x050000
#include <QtTest/QtTestWidgets>
-#endif
#include <QtTest/QtTestGui>
#include <new>
#include <string>
diff --git a/src/qt/test/rpcnestedtests.cpp b/src/qt/test/rpcnestedtests.cpp
index 173c814f1e..f8a9c25303 100644
--- a/src/qt/test/rpcnestedtests.cpp
+++ b/src/qt/test/rpcnestedtests.cpp
@@ -120,7 +120,6 @@ void RPCNestedTests::rpcNestedTests()
RPCConsole::RPCExecuteCommandLine(*node, result, "rpcNestedTest( abc , cba )");
QVERIFY(result == "[\"abc\",\"cba\"]");
-#if QT_VERSION >= 0x050300
// do the QVERIFY_EXCEPTION_THROWN checks only with Qt5.3 and higher (QVERIFY_EXCEPTION_THROWN was introduced in Qt5.3)
QVERIFY_EXCEPTION_THROWN(RPCConsole::RPCExecuteCommandLine(*node, result, "getblockchaininfo() .\n"), std::runtime_error); //invalid syntax
QVERIFY_EXCEPTION_THROWN(RPCConsole::RPCExecuteCommandLine(*node, result, "getblockchaininfo() getblockchaininfo()"), std::runtime_error); //invalid syntax
@@ -131,5 +130,4 @@ void RPCNestedTests::rpcNestedTests()
QVERIFY_EXCEPTION_THROWN(RPCConsole::RPCExecuteCommandLine(*node, result, "rpcNestedTest abc,,abc"), std::runtime_error); //don't tollerate empty arguments when using ,
QVERIFY_EXCEPTION_THROWN(RPCConsole::RPCExecuteCommandLine(*node, result, "rpcNestedTest(abc,,abc)"), std::runtime_error); //don't tollerate empty arguments when using ,
QVERIFY_EXCEPTION_THROWN(RPCConsole::RPCExecuteCommandLine(*node, result, "rpcNestedTest(abc,,)"), std::runtime_error); //don't tollerate empty arguments when using ,
-#endif
}
diff --git a/src/qt/walletcontroller.cpp b/src/qt/walletcontroller.cpp
index df2b7a3f9b..c532ffbbfe 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,41 @@ 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;
+}
+
+void WalletController::closeWallet(WalletModel* wallet_model, QWidget* parent)
+{
+ QMessageBox box(parent);
+ box.setWindowTitle(tr("Close wallet"));
+ box.setText(tr("Are you sure you wish to close wallet <i>%1</i>?").arg(wallet_model->getDisplayName()));
+ box.setInformativeText(tr("Closing the wallet for too long can result in having to resync the entire chain if pruning is enabled."));
+ box.setStandardButtons(QMessageBox::Yes|QMessageBox::Cancel);
+ box.setDefaultButton(QMessageBox::Yes);
+ if (box.exec() != QMessageBox::Yes) return;
+
+ // First remove wallet from node.
+ wallet_model->wallet().remove();
+ // Now release the model.
+ removeAndDeleteWallet(wallet_model);
+}
+
WalletModel* WalletController::getOrCreateWallet(std::unique_ptr<interfaces::Wallet> wallet)
{
QMutexLocker locker(&m_mutex);
@@ -93,3 +135,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..19b3a82253 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,10 @@ public:
~WalletController();
std::vector<WalletModel*> getWallets() const;
+ std::vector<std::string> getWalletsAvailableToOpen() const;
+
+ OpenWalletActivity* openWallet(const std::string& name, QWidget* parent = nullptr);
+ void closeWallet(WalletModel* wallet_model, QWidget* parent = nullptr);
private Q_SLOTS:
void addWallet(WalletModel* wallet_model);
@@ -48,12 +56,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