aboutsummaryrefslogtreecommitdiff
path: root/src/qt/bitcoingui.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'src/qt/bitcoingui.cpp')
-rw-r--r--src/qt/bitcoingui.cpp514
1 files changed, 335 insertions, 179 deletions
diff --git a/src/qt/bitcoingui.cpp b/src/qt/bitcoingui.cpp
index c8f8b9c7d3..ff66df376b 100644
--- a/src/qt/bitcoingui.cpp
+++ b/src/qt/bitcoingui.cpp
@@ -1,4 +1,4 @@
-// Copyright (c) 2011-2017 The Bitcoin Core developers
+// Copyright (c) 2011-2019 The Bitcoin Core developers
// Distributed under the MIT software license, see the accompanying
// file COPYING or http://www.opensource.org/licenses/mit-license.php.
@@ -19,6 +19,7 @@
#include <qt/utilitydialog.h>
#ifdef ENABLE_WALLET
+#include <qt/walletcontroller.h>
#include <qt/walletframe.h>
#include <qt/walletmodel.h>
#include <qt/walletview.h>
@@ -28,13 +29,15 @@
#include <qt/macdockiconhandler.h>
#endif
+#include <chain.h>
#include <chainparams.h>
#include <interfaces/handler.h>
#include <interfaces/node.h>
#include <ui_interface.h>
-#include <util.h>
+#include <util/system.h>
#include <iostream>
+#include <memory>
#include <QAction>
#include <QApplication>
@@ -43,6 +46,7 @@
#include <QDesktopWidget>
#include <QDragEnterEvent>
#include <QListWidget>
+#include <QMenu>
#include <QMenuBar>
#include <QMessageBox>
#include <QMimeData>
@@ -52,10 +56,13 @@
#include <QStackedWidget>
#include <QStatusBar>
#include <QStyle>
+#include <QSystemTrayIcon>
#include <QTimer>
#include <QToolBar>
#include <QUrlQuery>
#include <QVBoxLayout>
+#include <QWindow>
+
const std::string BitcoinGUI::DEFAULT_UIPLATFORM =
#if defined(Q_OS_MAC)
@@ -70,7 +77,9 @@ const std::string BitcoinGUI::DEFAULT_UIPLATFORM =
BitcoinGUI::BitcoinGUI(interfaces::Node& node, const PlatformStyle *_platformStyle, const NetworkStyle *networkStyle, QWidget *parent) :
QMainWindow(parent),
m_node(node),
- platformStyle(_platformStyle)
+ trayIconMenu{new QMenu()},
+ platformStyle(_platformStyle),
+ m_network_style(networkStyle)
{
QSettings settings;
if (!restoreGeometry(settings.value("MainWindowGeometry").toByteArray())) {
@@ -78,26 +87,14 @@ BitcoinGUI::BitcoinGUI(interfaces::Node& node, const PlatformStyle *_platformSty
move(QApplication::desktop()->availableGeometry().center() - frameGeometry().center());
}
- QString windowTitle = tr(PACKAGE_NAME) + " - ";
#ifdef ENABLE_WALLET
enableWallet = WalletModel::isWalletEnabled();
#endif // ENABLE_WALLET
- if(enableWallet)
- {
- windowTitle += tr("Wallet");
- } else {
- windowTitle += tr("Node");
- }
- windowTitle += " " + networkStyle->getTitleAddText();
-#ifndef Q_OS_MAC
- QApplication::setWindowIcon(networkStyle->getTrayAndWindowIcon());
- setWindowIcon(networkStyle->getTrayAndWindowIcon());
-#else
- MacDockIconHandler::instance()->setIcon(networkStyle->getAppIcon());
-#endif
- setWindowTitle(windowTitle);
+ QApplication::setWindowIcon(m_network_style->getTrayAndWindowIcon());
+ setWindowIcon(m_network_style->getTrayAndWindowIcon());
+ updateWindowTitle();
- rpcConsole = new RPCConsole(node, _platformStyle, 0);
+ rpcConsole = new RPCConsole(node, _platformStyle, nullptr);
helpMessageDialog = new HelpMessageDialog(node, this, false);
#ifdef ENABLE_WALLET
if(enableWallet)
@@ -112,6 +109,7 @@ BitcoinGUI::BitcoinGUI(interfaces::Node& node, const PlatformStyle *_platformSty
* the central widget is the rpc console.
*/
setCentralWidget(rpcConsole);
+ Q_EMIT consoleShown(rpcConsole);
}
// Accept D&D of URIs
@@ -128,7 +126,10 @@ BitcoinGUI::BitcoinGUI(interfaces::Node& node, const PlatformStyle *_platformSty
createToolBars();
// Create system tray icon and notification
- createTrayIcon(networkStyle);
+ if (QSystemTrayIcon::isSystemTrayAvailable()) {
+ createTrayIcon();
+ }
+ notificator = new Notificator(QApplication::applicationName(), trayIcon, this);
// Create status bar
statusBar();
@@ -146,7 +147,7 @@ BitcoinGUI::BitcoinGUI(interfaces::Node& node, const PlatformStyle *_platformSty
unitDisplayControl = new UnitDisplayStatusBarControl(platformStyle);
labelWalletEncryptionIcon = new QLabel();
labelWalletHDStatusIcon = new QLabel();
- labelProxyIcon = new QLabel();
+ labelProxyIcon = new GUIUtil::ClickableLabel();
connectionsControl = new GUIUtil::ClickableLabel();
labelBlocksIcon = new GUIUtil::ClickableLabel();
if(enableWallet)
@@ -193,16 +194,25 @@ BitcoinGUI::BitcoinGUI(interfaces::Node& node, const PlatformStyle *_platformSty
// Subscribe to notifications from core
subscribeToCoreSignals();
- connect(connectionsControl, SIGNAL(clicked(QPoint)), this, SLOT(toggleNetworkActive()));
+ connect(connectionsControl, &GUIUtil::ClickableLabel::clicked, [this] {
+ m_node.setNetworkActive(!m_node.getNetworkActive());
+ });
+ connect(labelProxyIcon, &GUIUtil::ClickableLabel::clicked, [this] {
+ openOptionsDialogWithTab(OptionsDialog::TAB_NETWORK);
+ });
modalOverlay = new ModalOverlay(this->centralWidget());
#ifdef ENABLE_WALLET
if(enableWallet) {
- connect(walletFrame, SIGNAL(requestedSyncWarningInfo()), this, SLOT(showModalOverlay()));
- connect(labelBlocksIcon, SIGNAL(clicked(QPoint)), this, SLOT(showModalOverlay()));
- connect(progressBar, SIGNAL(clicked(QPoint)), this, SLOT(showModalOverlay()));
+ connect(walletFrame, &WalletFrame::requestedSyncWarningInfo, this, &BitcoinGUI::showModalOverlay);
+ connect(labelBlocksIcon, &GUIUtil::ClickableLabel::clicked, this, &BitcoinGUI::showModalOverlay);
+ connect(progressBar, &GUIUtil::ClickableProgressBar::clicked, this, &BitcoinGUI::showModalOverlay);
}
#endif
+
+#ifdef Q_OS_MAC
+ m_app_nap_inhibitor = new CAppNapInhibitor;
+#endif
}
BitcoinGUI::~BitcoinGUI()
@@ -215,6 +225,7 @@ BitcoinGUI::~BitcoinGUI()
if(trayIcon) // Hide tray icon, as deleting will let it linger until quit (on Ubuntu)
trayIcon->hide();
#ifdef Q_OS_MAC
+ delete m_app_nap_inhibitor;
delete appMenuBar;
MacDockIconHandler::cleanup();
#endif
@@ -265,18 +276,18 @@ void BitcoinGUI::createActions()
#ifdef ENABLE_WALLET
// These showNormalIfMinimized are needed because Send Coins and Receive Coins
// can be triggered from the tray menu, and need to show the GUI to be useful.
- connect(overviewAction, SIGNAL(triggered()), this, SLOT(showNormalIfMinimized()));
- connect(overviewAction, SIGNAL(triggered()), this, SLOT(gotoOverviewPage()));
- connect(sendCoinsAction, SIGNAL(triggered()), this, SLOT(showNormalIfMinimized()));
- connect(sendCoinsAction, SIGNAL(triggered()), this, SLOT(gotoSendCoinsPage()));
- connect(sendCoinsMenuAction, SIGNAL(triggered()), this, SLOT(showNormalIfMinimized()));
- connect(sendCoinsMenuAction, SIGNAL(triggered()), this, SLOT(gotoSendCoinsPage()));
- connect(receiveCoinsAction, SIGNAL(triggered()), this, SLOT(showNormalIfMinimized()));
- connect(receiveCoinsAction, SIGNAL(triggered()), this, SLOT(gotoReceiveCoinsPage()));
- connect(receiveCoinsMenuAction, SIGNAL(triggered()), this, SLOT(showNormalIfMinimized()));
- connect(receiveCoinsMenuAction, SIGNAL(triggered()), this, SLOT(gotoReceiveCoinsPage()));
- connect(historyAction, SIGNAL(triggered()), this, SLOT(showNormalIfMinimized()));
- connect(historyAction, SIGNAL(triggered()), this, SLOT(gotoHistoryPage()));
+ connect(overviewAction, &QAction::triggered, [this]{ showNormalIfMinimized(); });
+ connect(overviewAction, &QAction::triggered, this, &BitcoinGUI::gotoOverviewPage);
+ connect(sendCoinsAction, &QAction::triggered, [this]{ showNormalIfMinimized(); });
+ connect(sendCoinsAction, &QAction::triggered, [this]{ gotoSendCoinsPage(); });
+ connect(sendCoinsMenuAction, &QAction::triggered, [this]{ showNormalIfMinimized(); });
+ connect(sendCoinsMenuAction, &QAction::triggered, [this]{ gotoSendCoinsPage(); });
+ connect(receiveCoinsAction, &QAction::triggered, [this]{ showNormalIfMinimized(); });
+ connect(receiveCoinsAction, &QAction::triggered, this, &BitcoinGUI::gotoReceiveCoinsPage);
+ connect(receiveCoinsMenuAction, &QAction::triggered, [this]{ showNormalIfMinimized(); });
+ connect(receiveCoinsMenuAction, &QAction::triggered, this, &BitcoinGUI::gotoReceiveCoinsPage);
+ connect(historyAction, &QAction::triggered, [this]{ showNormalIfMinimized(); });
+ connect(historyAction, &QAction::triggered, this, &BitcoinGUI::gotoHistoryPage);
#endif // ENABLE_WALLET
quitAction = new QAction(platformStyle->TextColorIcon(":/icons/quit"), tr("E&xit"), this);
@@ -313,45 +324,104 @@ void BitcoinGUI::createActions()
openRPCConsoleAction->setStatusTip(tr("Open debugging and diagnostic console"));
// initially disable the debug window menu item
openRPCConsoleAction->setEnabled(false);
+ openRPCConsoleAction->setObjectName("openRPCConsoleAction");
- usedSendingAddressesAction = new QAction(platformStyle->TextColorIcon(":/icons/address-book"), tr("&Sending addresses..."), this);
+ usedSendingAddressesAction = new QAction(platformStyle->TextColorIcon(":/icons/address-book"), tr("&Sending addresses"), this);
usedSendingAddressesAction->setStatusTip(tr("Show the list of used sending addresses and labels"));
- usedReceivingAddressesAction = new QAction(platformStyle->TextColorIcon(":/icons/address-book"), tr("&Receiving addresses..."), this);
+ usedReceivingAddressesAction = new QAction(platformStyle->TextColorIcon(":/icons/address-book"), tr("&Receiving addresses"), this);
usedReceivingAddressesAction->setStatusTip(tr("Show the list of used receiving addresses and labels"));
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)));
- connect(quitAction, SIGNAL(triggered()), qApp, SLOT(quit()));
- connect(aboutAction, SIGNAL(triggered()), this, SLOT(aboutClicked()));
- connect(aboutQtAction, SIGNAL(triggered()), qApp, SLOT(aboutQt()));
- connect(optionsAction, SIGNAL(triggered()), this, SLOT(optionsClicked()));
- connect(toggleHideAction, SIGNAL(triggered()), this, SLOT(toggleHidden()));
- connect(showHelpMessageAction, SIGNAL(triggered()), this, SLOT(showHelpMessageClicked()));
- connect(openRPCConsoleAction, SIGNAL(triggered()), this, SLOT(showDebugWindow()));
+ connect(quitAction, &QAction::triggered, qApp, QApplication::quit);
+ connect(aboutAction, &QAction::triggered, this, &BitcoinGUI::aboutClicked);
+ connect(aboutQtAction, &QAction::triggered, qApp, QApplication::aboutQt);
+ connect(optionsAction, &QAction::triggered, this, &BitcoinGUI::optionsClicked);
+ connect(toggleHideAction, &QAction::triggered, this, &BitcoinGUI::toggleHidden);
+ connect(showHelpMessageAction, &QAction::triggered, this, &BitcoinGUI::showHelpMessageClicked);
+ connect(openRPCConsoleAction, &QAction::triggered, this, &BitcoinGUI::showDebugWindow);
// prevents an open debug window from becoming stuck/unusable on client shutdown
- connect(quitAction, SIGNAL(triggered()), rpcConsole, SLOT(hide()));
+ connect(quitAction, &QAction::triggered, rpcConsole, &QWidget::hide);
#ifdef ENABLE_WALLET
if(walletFrame)
{
- connect(encryptWalletAction, SIGNAL(triggered(bool)), walletFrame, SLOT(encryptWallet(bool)));
- connect(backupWalletAction, SIGNAL(triggered()), walletFrame, SLOT(backupWallet()));
- connect(changePassphraseAction, SIGNAL(triggered()), walletFrame, SLOT(changePassphrase()));
- connect(signMessageAction, SIGNAL(triggered()), this, SLOT(gotoSignMessageTab()));
- connect(verifyMessageAction, SIGNAL(triggered()), this, SLOT(gotoVerifyMessageTab()));
- connect(usedSendingAddressesAction, SIGNAL(triggered()), walletFrame, SLOT(usedSendingAddresses()));
- connect(usedReceivingAddressesAction, SIGNAL(triggered()), walletFrame, SLOT(usedReceivingAddresses()));
- connect(openAction, SIGNAL(triggered()), this, SLOT(openClicked()));
+ connect(encryptWalletAction, &QAction::triggered, walletFrame, &WalletFrame::encryptWallet);
+ connect(backupWalletAction, &QAction::triggered, walletFrame, &WalletFrame::backupWallet);
+ connect(changePassphraseAction, &QAction::triggered, walletFrame, &WalletFrame::changePassphrase);
+ connect(signMessageAction, &QAction::triggered, [this]{ showNormalIfMinimized(); });
+ connect(signMessageAction, &QAction::triggered, [this]{ gotoSignMessageTab(); });
+ connect(verifyMessageAction, &QAction::triggered, [this]{ showNormalIfMinimized(); });
+ connect(verifyMessageAction, &QAction::triggered, [this]{ gotoVerifyMessageTab(); });
+ 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();
+ std::vector<std::string> available_wallets = m_wallet_controller->getWalletsAvailableToOpen();
+ std::vector<std::string> wallets = m_node.listWalletDir();
+ for (const auto& path : wallets) {
+ QString name = path.empty() ? QString("["+tr("default wallet")+"]") : QString::fromStdString(path);
+ QAction* action = m_open_wallet_action->menu()->addAction(name);
+
+ if (std::find(available_wallets.begin(), available_wallets.end(), path) == available_wallets.end()) {
+ // This wallet is already loaded
+ action->setEnabled(false);
+ continue;
+ }
+
+ 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);
+ bool invoked = QMetaObject::invokeMethod(activity, "open");
+ assert(invoked);
+ });
+ }
+ if (wallets.empty()) {
+ QAction* action = m_open_wallet_action->menu()->addAction(tr("No wallets available"));
+ action->setEnabled(false);
+ }
+ });
+ connect(m_close_wallet_action, &QAction::triggered, [this] {
+ m_wallet_controller->closeWallet(walletFrame->currentWalletModel(), this);
+ });
}
#endif // ENABLE_WALLET
- new QShortcut(QKeySequence(Qt::CTRL + Qt::SHIFT + Qt::Key_C), this, SLOT(showDebugWindowActivateConsole()));
- new QShortcut(QKeySequence(Qt::CTRL + Qt::SHIFT + Qt::Key_D), this, SLOT(showDebugWindow()));
+ connect(new QShortcut(QKeySequence(Qt::CTRL + Qt::SHIFT + Qt::Key_C), this), &QShortcut::activated, this, &BitcoinGUI::showDebugWindowActivateConsole);
+ connect(new QShortcut(QKeySequence(Qt::CTRL + Qt::SHIFT + Qt::Key_D), this), &QShortcut::activated, this, &BitcoinGUI::showDebugWindow);
}
void BitcoinGUI::createMenuBar()
@@ -368,14 +438,14 @@ 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);
file->addAction(verifyMessageAction);
file->addSeparator();
- file->addAction(usedSendingAddressesAction);
- file->addAction(usedReceivingAddressesAction);
- file->addSeparator();
}
file->addAction(quitAction);
@@ -388,11 +458,64 @@ void BitcoinGUI::createMenuBar()
}
settings->addAction(optionsAction);
- QMenu *help = appMenuBar->addMenu(tr("&Help"));
- if(walletFrame)
- {
- help->addAction(openRPCConsoleAction);
+ QMenu* window_menu = appMenuBar->addMenu(tr("&Window"));
+
+ QAction* minimize_action = window_menu->addAction(tr("Minimize"));
+ minimize_action->setShortcut(QKeySequence(Qt::CTRL + Qt::Key_M));
+ connect(minimize_action, &QAction::triggered, [] {
+ qApp->focusWindow()->showMinimized();
+ });
+ connect(qApp, &QApplication::focusWindowChanged, [minimize_action] (QWindow* window) {
+ minimize_action->setEnabled(window != nullptr && (window->flags() & Qt::Dialog) != Qt::Dialog && window->windowState() != Qt::WindowMinimized);
+ });
+
+#ifdef Q_OS_MAC
+ QAction* zoom_action = window_menu->addAction(tr("Zoom"));
+ connect(zoom_action, &QAction::triggered, [] {
+ QWindow* window = qApp->focusWindow();
+ if (window->windowState() != Qt::WindowMaximized) {
+ window->showMaximized();
+ } else {
+ window->showNormal();
+ }
+ });
+
+ connect(qApp, &QApplication::focusWindowChanged, [zoom_action] (QWindow* window) {
+ zoom_action->setEnabled(window != nullptr);
+ });
+#else
+ QAction* restore_action = window_menu->addAction(tr("Restore"));
+ connect(restore_action, &QAction::triggered, [] {
+ qApp->focusWindow()->showNormal();
+ });
+
+ connect(qApp, &QApplication::focusWindowChanged, [restore_action] (QWindow* window) {
+ restore_action->setEnabled(window != nullptr);
+ });
+#endif
+
+ if (walletFrame) {
+ window_menu->addSeparator();
+ QAction* main_window_action = window_menu->addAction(tr("Main Window"));
+ connect(main_window_action, &QAction::triggered, [this] {
+ GUIUtil::bringToFront(this);
+ });
+
+ window_menu->addSeparator();
+ window_menu->addAction(usedSendingAddressesAction);
+ window_menu->addAction(usedReceivingAddressesAction);
+ }
+
+ window_menu->addSeparator();
+ for (RPCConsole::TabTypes tab_type : rpcConsole->tabs()) {
+ QAction* tab_action = window_menu->addAction(rpcConsole->tabTitle(tab_type));
+ connect(tab_action, &QAction::triggered, [this, tab_type] {
+ rpcConsole->setTabFocus(tab_type);
+ showDebugWindow();
+ });
}
+
+ QMenu *help = appMenuBar->addMenu(tr("&Help"));
help->addAction(showHelpMessageAction);
help->addSeparator();
help->addAction(aboutAction);
@@ -420,7 +543,8 @@ void BitcoinGUI::createToolBars()
toolbar->addWidget(spacer);
m_wallet_selector = new QComboBox();
- connect(m_wallet_selector, SIGNAL(currentIndexChanged(int)), this, SLOT(setCurrentWalletBySelectorIndex(int)));
+ m_wallet_selector->setSizeAdjustPolicy(QComboBox::AdjustToContents);
+ connect(m_wallet_selector, static_cast<void (QComboBox::*)(int)>(&QComboBox::currentIndexChanged), this, &BitcoinGUI::setCurrentWalletBySelectorIndex);
m_wallet_selector_label = new QLabel();
m_wallet_selector_label->setText(tr("Wallet:") + " ");
@@ -446,18 +570,20 @@ void BitcoinGUI::setClientModel(ClientModel *_clientModel)
// Keep up to date with client
updateNetworkState();
- connect(_clientModel, SIGNAL(numConnectionsChanged(int)), this, SLOT(setNumConnections(int)));
- connect(_clientModel, SIGNAL(networkActiveChanged(bool)), this, SLOT(setNetworkActive(bool)));
+ connect(_clientModel, &ClientModel::numConnectionsChanged, this, &BitcoinGUI::setNumConnections);
+ connect(_clientModel, &ClientModel::networkActiveChanged, this, &BitcoinGUI::setNetworkActive);
modalOverlay->setKnownBestHeight(_clientModel->getHeaderTipHeight(), QDateTime::fromTime_t(_clientModel->getHeaderTipTime()));
setNumBlocks(m_node.getNumBlocks(), QDateTime::fromTime_t(m_node.getLastBlockTime()), m_node.getVerificationProgress(), false);
- connect(_clientModel, SIGNAL(numBlocksChanged(int,QDateTime,double,bool)), this, SLOT(setNumBlocks(int,QDateTime,double,bool)));
+ connect(_clientModel, &ClientModel::numBlocksChanged, this, &BitcoinGUI::setNumBlocks);
// Receive and report messages from client model
- connect(_clientModel, SIGNAL(message(QString,QString,unsigned int)), this, SLOT(message(QString,QString,unsigned int)));
+ connect(_clientModel, &ClientModel::message, [this](const QString &title, const QString &message, unsigned int style){
+ this->message(title, message, style);
+ });
// Show progress dialog
- connect(_clientModel, SIGNAL(showProgress(QString,int)), this, SLOT(showProgress(QString,int)));
+ connect(_clientModel, &ClientModel::showProgress, this, &BitcoinGUI::showProgress);
rpcConsole->setClientModel(_clientModel);
@@ -472,10 +598,9 @@ void BitcoinGUI::setClientModel(ClientModel *_clientModel)
unitDisplayControl->setOptionsModel(_clientModel->getOptionsModel());
OptionsModel* optionsModel = _clientModel->getOptionsModel();
- if(optionsModel)
- {
+ if (optionsModel && trayIcon) {
// be aware of the tray icon disable state change reported by the OptionsModel object.
- connect(optionsModel,SIGNAL(hideTrayIconChanged(bool)),this,SLOT(setTrayIconVisible(bool)));
+ connect(optionsModel, &OptionsModel::hideTrayIconChanged, this, &BitcoinGUI::setTrayIconVisible);
// initialize the disable state of the tray icon with the current value in the model.
setTrayIconVisible(optionsModel->getHideTrayIcon());
@@ -501,27 +626,39 @@ void BitcoinGUI::setClientModel(ClientModel *_clientModel)
}
#ifdef ENABLE_WALLET
-bool BitcoinGUI::addWallet(WalletModel *walletModel)
+void BitcoinGUI::setWalletController(WalletController* wallet_controller)
{
- if(!walletFrame)
- return false;
- const QString name = walletModel->getWalletName();
- QString display_name = name.isEmpty() ? "["+tr("default wallet")+"]" : name;
+ assert(!m_wallet_controller);
+ assert(wallet_controller);
+
+ m_wallet_controller = wallet_controller;
+
+ connect(wallet_controller, &WalletController::walletAdded, this, &BitcoinGUI::addWallet);
+ connect(wallet_controller, &WalletController::walletRemoved, this, &BitcoinGUI::removeWallet);
+
+ for (WalletModel* wallet_model : m_wallet_controller->getWallets()) {
+ addWallet(wallet_model);
+ }
+}
+
+void BitcoinGUI::addWallet(WalletModel* walletModel)
+{
+ if (!walletFrame) return;
+ const QString display_name = walletModel->getDisplayName();
setWalletActionsEnabled(true);
- m_wallet_selector->addItem(display_name, name);
+ rpcConsole->addWallet(walletModel);
+ walletFrame->addWallet(walletModel);
+ m_wallet_selector->addItem(display_name, QVariant::fromValue(walletModel));
if (m_wallet_selector->count() == 2) {
m_wallet_selector_label_action->setVisible(true);
m_wallet_selector_action->setVisible(true);
}
- rpcConsole->addWallet(walletModel);
- return walletFrame->addWallet(walletModel);
}
-bool BitcoinGUI::removeWallet(WalletModel* walletModel)
+void BitcoinGUI::removeWallet(WalletModel* walletModel)
{
- if (!walletFrame) return false;
- QString name = walletModel->getWalletName();
- int index = m_wallet_selector->findData(name);
+ if (!walletFrame) return;
+ int index = m_wallet_selector->findData(QVariant::fromValue(walletModel));
m_wallet_selector->removeItem(index);
if (m_wallet_selector->count() == 0) {
setWalletActionsEnabled(false);
@@ -530,20 +667,27 @@ bool BitcoinGUI::removeWallet(WalletModel* walletModel)
m_wallet_selector_action->setVisible(false);
}
rpcConsole->removeWallet(walletModel);
- return walletFrame->removeWallet(name);
+ walletFrame->removeWallet(walletModel);
+ updateWindowTitle();
}
-bool BitcoinGUI::setCurrentWallet(const QString& name)
+void BitcoinGUI::setCurrentWallet(WalletModel* wallet_model)
{
- if(!walletFrame)
- return false;
- return walletFrame->setCurrentWallet(name);
+ if (!walletFrame) return;
+ walletFrame->setCurrentWallet(wallet_model);
+ for (int index = 0; index < m_wallet_selector->count(); ++index) {
+ if (m_wallet_selector->itemData(index).value<WalletModel*>() == wallet_model) {
+ m_wallet_selector->setCurrentIndex(index);
+ break;
+ }
+ }
+ updateWindowTitle();
}
-bool BitcoinGUI::setCurrentWalletBySelectorIndex(int index)
+void BitcoinGUI::setCurrentWalletBySelectorIndex(int index)
{
- QString internal_name = m_wallet_selector->itemData(index).toString();
- return setCurrentWallet(internal_name);
+ WalletModel* wallet_model = m_wallet_selector->itemData(index).value<WalletModel*>();
+ if (wallet_model) setCurrentWallet(wallet_model);
}
void BitcoinGUI::removeAllWallets()
@@ -571,52 +715,55 @@ void BitcoinGUI::setWalletActionsEnabled(bool enabled)
usedSendingAddressesAction->setEnabled(enabled);
usedReceivingAddressesAction->setEnabled(enabled);
openAction->setEnabled(enabled);
+ m_close_wallet_action->setEnabled(enabled);
}
-void BitcoinGUI::createTrayIcon(const NetworkStyle *networkStyle)
+void BitcoinGUI::createTrayIcon()
{
+ assert(QSystemTrayIcon::isSystemTrayAvailable());
+
#ifndef Q_OS_MAC
- trayIcon = new QSystemTrayIcon(this);
- QString toolTip = tr("%1 client").arg(tr(PACKAGE_NAME)) + " " + networkStyle->getTitleAddText();
- trayIcon->setToolTip(toolTip);
- trayIcon->setIcon(networkStyle->getTrayAndWindowIcon());
- trayIcon->hide();
+ if (QSystemTrayIcon::isSystemTrayAvailable()) {
+ trayIcon = new QSystemTrayIcon(m_network_style->getTrayAndWindowIcon(), this);
+ QString toolTip = tr("%1 client").arg(tr(PACKAGE_NAME)) + " " + m_network_style->getTitleAddText();
+ trayIcon->setToolTip(toolTip);
+ }
#endif
-
- notificator = new Notificator(QApplication::applicationName(), trayIcon, this);
}
void BitcoinGUI::createTrayIconMenu()
{
#ifndef Q_OS_MAC
- // return if trayIcon is unset (only on non-Mac OSes)
+ // return if trayIcon is unset (only on non-macOSes)
if (!trayIcon)
return;
- trayIconMenu = new QMenu(this);
- trayIcon->setContextMenu(trayIconMenu);
-
- connect(trayIcon, SIGNAL(activated(QSystemTrayIcon::ActivationReason)),
- this, SLOT(trayIconActivated(QSystemTrayIcon::ActivationReason)));
+ trayIcon->setContextMenu(trayIconMenu.get());
+ connect(trayIcon, &QSystemTrayIcon::activated, this, &BitcoinGUI::trayIconActivated);
#else
- // Note: On Mac, the dock icon is used to provide the tray's functionality.
+ // Note: On macOS, the Dock icon is used to provide the tray's functionality.
MacDockIconHandler *dockIconHandler = MacDockIconHandler::instance();
- dockIconHandler->setMainWindow(static_cast<QMainWindow*>(this));
- trayIconMenu = dockIconHandler->dockMenu();
+ connect(dockIconHandler, &MacDockIconHandler::dockIconClicked, this, &BitcoinGUI::macosDockIconActivated);
+ trayIconMenu->setAsDockMenu();
#endif
- // Configuration of the tray icon (or dock icon) icon menu
+ // Configuration of the tray icon (or Dock icon) menu
+#ifndef Q_OS_MAC
+ // Note: On macOS, the Dock icon's menu already has Show / Hide action.
trayIconMenu->addAction(toggleHideAction);
trayIconMenu->addSeparator();
- trayIconMenu->addAction(sendCoinsMenuAction);
- trayIconMenu->addAction(receiveCoinsMenuAction);
- trayIconMenu->addSeparator();
- trayIconMenu->addAction(signMessageAction);
- trayIconMenu->addAction(verifyMessageAction);
- trayIconMenu->addSeparator();
+#endif
+ if (enableWallet) {
+ trayIconMenu->addAction(sendCoinsMenuAction);
+ trayIconMenu->addAction(receiveCoinsMenuAction);
+ trayIconMenu->addSeparator();
+ trayIconMenu->addAction(signMessageAction);
+ trayIconMenu->addAction(verifyMessageAction);
+ trayIconMenu->addSeparator();
+ trayIconMenu->addAction(openRPCConsoleAction);
+ }
trayIconMenu->addAction(optionsAction);
- trayIconMenu->addAction(openRPCConsoleAction);
-#ifndef Q_OS_MAC // This is built-in on Mac
+#ifndef Q_OS_MAC // This is built-in on macOS
trayIconMenu->addSeparator();
trayIconMenu->addAction(quitAction);
#endif
@@ -631,16 +778,17 @@ void BitcoinGUI::trayIconActivated(QSystemTrayIcon::ActivationReason reason)
toggleHidden();
}
}
+#else
+void BitcoinGUI::macosDockIconActivated()
+{
+ show();
+ activateWindow();
+}
#endif
void BitcoinGUI::optionsClicked()
{
- if(!clientModel || !clientModel->getOptionsModel())
- return;
-
- OptionsDialog dlg(this, enableWallet);
- dlg.setModel(clientModel->getOptionsModel());
- dlg.exec();
+ openOptionsDialogWithTab(OptionsDialog::TAB_MAIN);
}
void BitcoinGUI::aboutClicked()
@@ -654,10 +802,8 @@ void BitcoinGUI::aboutClicked()
void BitcoinGUI::showDebugWindow()
{
- rpcConsole->showNormal();
- rpcConsole->show();
- rpcConsole->raise();
- rpcConsole->activateWindow();
+ GUIUtil::bringToFront(rpcConsole);
+ Q_EMIT consoleShown(rpcConsole);
}
void BitcoinGUI::showDebugWindowActivateConsole()
@@ -764,8 +910,24 @@ void BitcoinGUI::updateHeadersSyncProgressLabel()
progressBarLabel->setText(tr("Syncing Headers (%1%)...").arg(QString::number(100.0 / (headersTipHeight+estHeadersLeft)*headersTipHeight, 'f', 1)));
}
+void BitcoinGUI::openOptionsDialogWithTab(OptionsDialog::Tab tab)
+{
+ if (!clientModel || !clientModel->getOptionsModel())
+ return;
+
+ OptionsDialog dlg(this, enableWallet);
+ dlg.setCurrentTab(tab);
+ dlg.setModel(clientModel->getOptionsModel());
+ dlg.exec();
+}
+
void BitcoinGUI::setNumBlocks(int count, const QDateTime& blockDate, double nVerificationProgress, bool header)
{
+// Disabling macOS App Nap on initial sync, disk and reindex operations.
+#ifdef Q_OS_MAC
+ (m_node.isInitialBlockDownload() || m_node.getReindex() || m_node.getImporting()) ? m_app_nap_inhibitor->disableAppNap() : m_app_nap_inhibitor->enableAppNap();
+#endif
+
if (modalOverlay)
{
if (header)
@@ -816,8 +978,7 @@ void BitcoinGUI::setNumBlocks(int count, const QDateTime& blockDate, double nVer
tooltip = tr("Processed %n block(s) of transaction history.", "", count);
// Set icon state: spinning if catching up, tick otherwise
- if(secs < 90*60)
- {
+ if (secs < MAX_BLOCK_TIME_GAP) {
tooltip = tr("Up to date") + QString(".<br>") + tooltip;
labelBlocksIcon->setPixmap(platformStyle->SingleColorIcon(":/icons/synced").pixmap(STATUSBAR_ICONSIZE, STATUSBAR_ICONSIZE));
@@ -945,12 +1106,12 @@ void BitcoinGUI::changeEvent(QEvent *e)
QWindowStateChangeEvent *wsevt = static_cast<QWindowStateChangeEvent*>(e);
if(!(wsevt->oldState() & Qt::WindowMinimized) && isMinimized())
{
- QTimer::singleShot(0, this, SLOT(hide()));
+ QTimer::singleShot(0, this, &BitcoinGUI::hide);
e->ignore();
}
else if((wsevt->oldState() & Qt::WindowMinimized) && !isMinimized())
{
- QTimer::singleShot(0, this, SLOT(show()));
+ QTimer::singleShot(0, this, &BitcoinGUI::show);
e->ignore();
}
}
@@ -1052,10 +1213,10 @@ bool BitcoinGUI::handlePaymentRequest(const SendCoinsRecipient& recipient)
return false;
}
-void BitcoinGUI::setHDStatus(int hdEnabled)
+void BitcoinGUI::setHDStatus(bool privkeyDisabled, int hdEnabled)
{
- labelWalletHDStatusIcon->setPixmap(platformStyle->SingleColorIcon(hdEnabled ? ":/icons/hd_enabled" : ":/icons/hd_disabled").pixmap(STATUSBAR_ICONSIZE,STATUSBAR_ICONSIZE));
- labelWalletHDStatusIcon->setToolTip(hdEnabled ? tr("HD key generation is <b>enabled</b>") : tr("HD key generation is <b>disabled</b>"));
+ labelWalletHDStatusIcon->setPixmap(platformStyle->SingleColorIcon(privkeyDisabled ? ":/icons/eye" : hdEnabled ? ":/icons/hd_enabled" : ":/icons/hd_disabled").pixmap(STATUSBAR_ICONSIZE,STATUSBAR_ICONSIZE));
+ labelWalletHDStatusIcon->setToolTip(privkeyDisabled ? tr("Private key <b>disabled</b>") : hdEnabled ? tr("HD key generation is <b>enabled</b>") : tr("HD key generation is <b>disabled</b>"));
// eventually disable the QLabel to set its opacity to 50%
labelWalletHDStatusIcon->setEnabled(hdEnabled);
@@ -1101,7 +1262,7 @@ void BitcoinGUI::updateWalletStatus()
}
WalletModel * const walletModel = walletView->getWalletModel();
setEncryptionStatus(walletModel->getEncryptionStatus());
- setHDStatus(walletModel->wallet().hdEnabled());
+ setHDStatus(walletModel->privateKeysDisabled(), walletModel->wallet().hdEnabled());
}
#endif // ENABLE_WALLET
@@ -1111,7 +1272,7 @@ void BitcoinGUI::updateProxyIcon()
bool proxy_enabled = clientModel->getProxyInfo(ip_port);
if (proxy_enabled) {
- if (labelProxyIcon->pixmap() == 0) {
+ if (labelProxyIcon->pixmap() == nullptr) {
QString ip_port_q = QString::fromStdString(ip_port);
labelProxyIcon->setPixmap(platformStyle->SingleColorIcon(":/icons/proxy").pixmap(STATUSBAR_ICONSIZE, STATUSBAR_ICONSIZE));
labelProxyIcon->setToolTip(tr("Proxy is <b>enabled</b>: %1").arg(ip_port_q));
@@ -1123,29 +1284,33 @@ void BitcoinGUI::updateProxyIcon()
}
}
+void BitcoinGUI::updateWindowTitle()
+{
+ QString window_title = tr(PACKAGE_NAME);
+#ifdef ENABLE_WALLET
+ if (walletFrame) {
+ WalletModel* const wallet_model = walletFrame->currentWalletModel();
+ if (wallet_model && !wallet_model->getWalletName().isEmpty()) {
+ window_title += " - " + wallet_model->getDisplayName();
+ }
+ }
+#endif
+ if (!m_network_style->getTitleAddText().isEmpty()) {
+ window_title += " - " + m_network_style->getTitleAddText();
+ }
+ setWindowTitle(window_title);
+}
+
void BitcoinGUI::showNormalIfMinimized(bool fToggleHidden)
{
if(!clientModel)
return;
- // activateWindow() (sometimes) helps with keyboard focus on Windows
- if (isHidden())
- {
- show();
- activateWindow();
- }
- else if (isMinimized())
- {
- showNormal();
- activateWindow();
- }
- else if (GUIUtil::isObscured(this))
- {
- raise();
- activateWindow();
- }
- else if(fToggleHidden)
+ if (!isHidden() && !isMinimized() && !GUIUtil::isObscured(this) && fToggleHidden) {
hide();
+ } else {
+ GUIUtil::bringToFront(this);
+ }
}
void BitcoinGUI::toggleHidden()
@@ -1165,25 +1330,21 @@ void BitcoinGUI::detectShutdown()
void BitcoinGUI::showProgress(const QString &title, int nProgress)
{
- if (nProgress == 0)
- {
- progressDialog = new QProgressDialog(title, "", 0, 100);
+ if (nProgress == 0) {
+ progressDialog = new QProgressDialog(title, QString(), 0, 100);
+ GUIUtil::PolishProgressDialog(progressDialog);
progressDialog->setWindowModality(Qt::ApplicationModal);
progressDialog->setMinimumDuration(0);
- progressDialog->setCancelButton(0);
progressDialog->setAutoClose(false);
progressDialog->setValue(0);
- }
- else if (nProgress == 100)
- {
- if (progressDialog)
- {
+ } else if (nProgress == 100) {
+ if (progressDialog) {
progressDialog->close();
progressDialog->deleteLater();
}
- }
- else if (progressDialog)
+ } else if (progressDialog) {
progressDialog->setValue(nProgress);
+ }
}
void BitcoinGUI::setTrayIconVisible(bool fHideTrayIcon)
@@ -1200,7 +1361,7 @@ void BitcoinGUI::showModalOverlay()
modalOverlay->toggleVisibility();
}
-static bool ThreadSafeMessageBox(BitcoinGUI *gui, const std::string& message, const std::string& caption, unsigned int style)
+static bool ThreadSafeMessageBox(BitcoinGUI* gui, const std::string& message, const std::string& caption, unsigned int style)
{
bool modal = (style & CClientUIInterface::MODAL);
// The SECURE flag has no effect in the Qt GUI.
@@ -1220,8 +1381,8 @@ static bool ThreadSafeMessageBox(BitcoinGUI *gui, const std::string& message, co
void BitcoinGUI::subscribeToCoreSignals()
{
// Connect signals to client
- m_handler_message_box = m_node.handleMessageBox(boost::bind(ThreadSafeMessageBox, this, _1, _2, _3));
- m_handler_question = m_node.handleQuestion(boost::bind(ThreadSafeMessageBox, this, _1, _3, _4));
+ m_handler_message_box = m_node.handleMessageBox(std::bind(ThreadSafeMessageBox, this, std::placeholders::_1, std::placeholders::_2, std::placeholders::_3));
+ m_handler_question = m_node.handleQuestion(std::bind(ThreadSafeMessageBox, this, std::placeholders::_1, std::placeholders::_3, std::placeholders::_4));
}
void BitcoinGUI::unsubscribeFromCoreSignals()
@@ -1231,14 +1392,9 @@ void BitcoinGUI::unsubscribeFromCoreSignals()
m_handler_question->disconnect();
}
-void BitcoinGUI::toggleNetworkActive()
-{
- m_node.setNetworkActive(!m_node.getNetworkActive());
-}
-
UnitDisplayStatusBarControl::UnitDisplayStatusBarControl(const PlatformStyle *platformStyle) :
- optionsModel(0),
- menu(0)
+ optionsModel(nullptr),
+ menu(nullptr)
{
createContextMenu();
setToolTip(tr("Unit to show amounts in. Click to select another unit."));
@@ -1264,13 +1420,13 @@ void UnitDisplayStatusBarControl::mousePressEvent(QMouseEvent *event)
void UnitDisplayStatusBarControl::createContextMenu()
{
menu = new QMenu(this);
- for (BitcoinUnits::Unit u : BitcoinUnits::availableUnits())
+ for (const BitcoinUnits::Unit u : BitcoinUnits::availableUnits())
{
QAction *menuAction = new QAction(QString(BitcoinUnits::longName(u)), this);
menuAction->setData(QVariant(u));
menu->addAction(menuAction);
}
- connect(menu,SIGNAL(triggered(QAction*)),this,SLOT(onMenuSelection(QAction*)));
+ connect(menu, &QMenu::triggered, this, &UnitDisplayStatusBarControl::onMenuSelection);
}
/** Lets the control know about the Options Model (and its signals) */
@@ -1281,7 +1437,7 @@ void UnitDisplayStatusBarControl::setOptionsModel(OptionsModel *_optionsModel)
this->optionsModel = _optionsModel;
// be aware of a display unit change reported by the OptionsModel object.
- connect(_optionsModel,SIGNAL(displayUnitChanged(int)),this,SLOT(updateDisplayUnit(int)));
+ connect(_optionsModel, &OptionsModel::displayUnitChanged, this, &UnitDisplayStatusBarControl::updateDisplayUnit);
// initialize the display units label with the current value in the model.
updateDisplayUnit(_optionsModel->getDisplayUnit());