diff --git a/contrib/debian/copyright b/contrib/debian/copyright index bd0334e19..0fcd620fd 100644 --- a/contrib/debian/copyright +++ b/contrib/debian/copyright @@ -1,162 +1,152 @@ Format: http://www.debian.org/doc/packaging-manuals/copyright-format/1.0/ Upstream-Name: Bitcoin ABC Upstream-Contact: helpdesk@bitcoinabc.org Source: https://github.com/Bitcoin-ABC/bitcoin-abc Files: * Copyright: 2009-2017, The Bitcoin Core Developers, 2017-2019 The Bitcoin Developers License: Expat Comment: The Bitcoin Developers encompasses those contributing to Bitcoin client open source development (various clients). The Bitcoin Core Developers encompasses the current developers listed on bitcoin.org, as well as the numerous contributors to the project. Files: debian/* Copyright: 2010-2011, Jonas Smedegaard 2011, Matt Corallo 2017, freetrader License: GPL-2+ Files: src/secp256k1/build-aux/m4/ax_jni_include_dir.m4 Copyright: 2008 Don Anderson License: GNU-All-permissive-License Files: src/secp256k1/build-aux/m4/ax_prog_cc_for_build.m4 Copyright: 2008 Paolo Bonzini License: GNU-All-permissive-License Files: src/qt/res/icons/add.png src/qt/res/icons/address-book.png src/qt/res/icons/chevron.png - src/qt/res/icons/configure.png - src/qt/res/icons/debugwindow.png src/qt/res/icons/edit.png src/qt/res/icons/editcopy.png src/qt/res/icons/editpaste.png src/qt/res/icons/export.png src/qt/res/icons/eye.png - src/qt/res/icons/filesave.png src/qt/res/icons/history.png - src/qt/res/icons/info.png - src/qt/res/icons/key.png src/qt/res/icons/lock_*.png - src/qt/res/icons/open.png src/qt/res/icons/overview.png - src/qt/res/icons/quit.png src/qt/res/icons/receive.png src/qt/res/icons/remove.png src/qt/res/icons/send.png src/qt/res/icons/synced.png src/qt/res/icons/transaction*.png src/qt/res/icons/tx_output.png src/qt/res/icons/warning.png Copyright: Stephen Hutchings (and more) http://typicons.com License: Expat Comment: Site: https://github.com/stephenhutchings/typicons.font Files: src/qt/res/icons/connect*.png src/qt/res/src/connect-*.svg src/qt/res/icons/network_disabled.png src/qt/res/src/network_disabled.svg Copyright: Marco Falke Luke Dashjr License: Expat Comment: Inspired by Stephen Hutchings' Typicons Files: src/qt/res/icons/tx_mined.png src/qt/res/src/mine.svg src/qt/res/icons/fontbigger.png src/qt/res/icons/fontsmaller.png src/qt/res/icons/hd_disabled.png src/qt/res/src/hd_disabled.svg src/qt/res/icons/hd_enabled.png src/qt/res/src/hd_enabled.svg Copyright: Jonas Schnelli License: Expat Files: src/qt/res/icons/clock*.png src/qt/res/icons/eye_*.png src/qt/res/icons/tx_in*.png - src/qt/res/icons/verify.png src/qt/res/src/clock_*.svg src/qt/res/src/tx_*.svg - src/qt/res/src/verify.svg Copyright: Stephen Hutchings, Jonas Schnelli License: Expat Comment: Modifications of Stephen Hutchings' Typicons -Files: src/qt/res/icons/about.png - src/qt/res/icons/bitcoin.* +Files: src/qt/res/icons/bitcoin.* src/qt/res/src/bitcoin.svg Copyright: Bitboy, Jonas Schnelli License: public-domain Comment: Site: https://bitcointalk.org/?topic=1756.0 Files: share/pixmaps/bitcoin-abc* License: public-domain Copyright: bitcoincash.org, bitcoinabc.org Files: src/qt/res/icons/proxy.png src/qt/res/src/proxy.svg Copyright: Cristian Mircea Messel Licese: public-domain License: Expat Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: . The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. . THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. License: GNU-All-permissive-License Copying and distribution of this file, with or without modification, are permitted in any medium without royalty provided the copyright notice and this notice are preserved. This file is offered as-is, without any warranty. License: GPL-2+ This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2, or (at your option) any later version. . This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. Comment: On Debian systems the GNU General Public License (GPL) version 2 is located in '/usr/share/common-licenses/GPL-2'. . You should have received a copy of the GNU General Public License along with this program. If not, see . License: GPL-3+ Permission is granted to copy, distribute and/or modify this document under the terms of the GNU General Public License, Version 3 or any later version published by the Free Software Foundation. Comment: On Debian systems the GNU General Public License (GPL) version 3 is located in '/usr/share/common-licenses/GPL-3'. . You should have received a copy of the GNU General Public License along with this program. If not, see . License: public-domain This work is in the public domain. diff --git a/src/qt/bitcoin.qrc b/src/qt/bitcoin.qrc index fddc2a568..037b23e4b 100644 --- a/src/qt/bitcoin.qrc +++ b/src/qt/bitcoin.qrc @@ -1,96 +1,86 @@ res/icons/bitcoin.png res/icons/address-book.png - res/icons/quit.png res/icons/send.png res/icons/connect0.png res/icons/connect1.png res/icons/connect2.png res/icons/connect3.png res/icons/connect4.png res/icons/transaction0.png res/icons/transaction2.png res/icons/transaction_conflicted.png res/icons/clock1.png res/icons/clock2.png res/icons/clock3.png res/icons/clock4.png res/icons/clock5.png res/icons/eye.png res/icons/eye_minus.png res/icons/eye_plus.png - res/icons/configure.png res/icons/receive.png res/icons/editpaste.png res/icons/editcopy.png res/icons/add.png res/icons/edit.png res/icons/history.png res/icons/overview.png res/icons/export.png res/icons/synced.png res/icons/remove.png res/icons/tx_mined.png res/icons/tx_input.png res/icons/tx_output.png res/icons/tx_inout.png res/icons/lock_closed.png res/icons/lock_open.png - res/icons/key.png - res/icons/filesave.png - res/icons/debugwindow.png - res/icons/open.png - res/icons/info.png - res/icons/about.png - res/icons/about_qt.png - res/icons/verify.png res/icons/warning.png res/icons/fontbigger.png res/icons/fontsmaller.png res/icons/chevron.png res/icons/transaction_abandoned.png res/icons/hd_enabled.png res/icons/hd_disabled.png res/icons/network_disabled.png res/icons/proxy.png res/movies/spinner-000.png res/movies/spinner-001.png res/movies/spinner-002.png res/movies/spinner-003.png res/movies/spinner-004.png res/movies/spinner-005.png res/movies/spinner-006.png res/movies/spinner-007.png res/movies/spinner-008.png res/movies/spinner-009.png res/movies/spinner-010.png res/movies/spinner-011.png res/movies/spinner-012.png res/movies/spinner-013.png res/movies/spinner-014.png res/movies/spinner-015.png res/movies/spinner-016.png res/movies/spinner-017.png res/movies/spinner-018.png res/movies/spinner-019.png res/movies/spinner-020.png res/movies/spinner-021.png res/movies/spinner-022.png res/movies/spinner-023.png res/movies/spinner-024.png res/movies/spinner-025.png res/movies/spinner-026.png res/movies/spinner-027.png res/movies/spinner-028.png res/movies/spinner-029.png res/movies/spinner-030.png res/movies/spinner-031.png res/movies/spinner-032.png res/movies/spinner-033.png res/movies/spinner-034.png res/movies/spinner-035.png diff --git a/src/qt/bitcoingui.cpp b/src/qt/bitcoingui.cpp index a039d4559..6bf460b9e 100644 --- a/src/qt/bitcoingui.cpp +++ b/src/qt/bitcoingui.cpp @@ -1,1654 +1,1625 @@ // 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. #include #include #include #include #include #include #include #include #include #include #include #include #ifdef Q_OS_MAC #include #endif #include #include #include #include #include #include #include #include #ifdef ENABLE_WALLET #include #include #include #include #endif // ENABLE_WALLET #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include const std::string BitcoinGUI::DEFAULT_UIPLATFORM = #if defined(Q_OS_MAC) "macosx" #elif defined(Q_OS_WIN) "windows" #else "other" #endif ; BitcoinGUI::BitcoinGUI(interfaces::Node &node, const Config *configIn, const PlatformStyle *_platformStyle, const NetworkStyle *networkStyle, QWidget *parent) : QMainWindow(parent), m_node(node), trayIconMenu{new QMenu()}, config(configIn), platformStyle(_platformStyle), m_network_style(networkStyle) { QSettings settings; if (!restoreGeometry(settings.value("MainWindowGeometry").toByteArray())) { // Restore failed (perhaps missing setting), center the window move(QGuiApplication::primaryScreen()->availableGeometry().center() - frameGeometry().center()); } #ifdef ENABLE_WALLET enableWallet = WalletModel::isWalletEnabled(); #endif // ENABLE_WALLET QApplication::setWindowIcon(m_network_style->getTrayAndWindowIcon()); setWindowIcon(m_network_style->getTrayAndWindowIcon()); updateWindowTitle(); rpcConsole = new RPCConsole(node, _platformStyle, nullptr); helpMessageDialog = new HelpMessageDialog(this, false); #ifdef ENABLE_WALLET if (enableWallet) { /** Create wallet frame and make it the central widget */ walletFrame = new WalletFrame(_platformStyle, this); setCentralWidget(walletFrame); } else #endif // ENABLE_WALLET { /** * When compiled without wallet or -disablewallet is provided, the * central widget is the rpc console. */ setCentralWidget(rpcConsole); Q_EMIT consoleShown(rpcConsole); } // Accept D&D of URIs setAcceptDrops(true); // Create actions for the toolbar, menu bar and tray/dock icon // Needs walletFrame to be initialized createActions(); // Create application menu bar createMenuBar(); // Create the toolbars createToolBars(); // Create system tray icon and notification if (QSystemTrayIcon::isSystemTrayAvailable()) { createTrayIcon(); } notificator = new Notificator(QApplication::applicationName(), trayIcon, this); // Create status bar statusBar(); // Disable size grip because it looks ugly and nobody needs it statusBar()->setSizeGripEnabled(false); // Status bar notification icons QFrame *frameBlocks = new QFrame(); frameBlocks->setContentsMargins(0, 0, 0, 0); frameBlocks->setSizePolicy(QSizePolicy::Fixed, QSizePolicy::Preferred); QHBoxLayout *frameBlocksLayout = new QHBoxLayout(frameBlocks); frameBlocksLayout->setContentsMargins(3, 0, 3, 0); frameBlocksLayout->setSpacing(3); unitDisplayControl = new UnitDisplayStatusBarControl(platformStyle); labelWalletEncryptionIcon = new QLabel(); labelWalletHDStatusIcon = new QLabel(); labelProxyIcon = new GUIUtil::ClickableLabel(); connectionsControl = new GUIUtil::ClickableLabel(); labelBlocksIcon = new GUIUtil::ClickableLabel(); if (enableWallet) { frameBlocksLayout->addStretch(); frameBlocksLayout->addWidget(unitDisplayControl); frameBlocksLayout->addStretch(); frameBlocksLayout->addWidget(labelWalletEncryptionIcon); frameBlocksLayout->addWidget(labelWalletHDStatusIcon); } frameBlocksLayout->addWidget(labelProxyIcon); frameBlocksLayout->addStretch(); frameBlocksLayout->addWidget(connectionsControl); frameBlocksLayout->addStretch(); frameBlocksLayout->addWidget(labelBlocksIcon); frameBlocksLayout->addStretch(); // Progress bar and label for blocks download progressBarLabel = new QLabel(); progressBarLabel->setVisible(false); progressBar = new GUIUtil::ProgressBar(); progressBar->setAlignment(Qt::AlignCenter); progressBar->setVisible(false); // Override style sheet for progress bar for styles that have a segmented // progress bar, as they make the text unreadable (workaround for issue // #1071) // See https://doc.qt.io/qt-5/gallery.html QString curStyle = QApplication::style()->metaObject()->className(); if (curStyle == "QWindowsStyle" || curStyle == "QWindowsXPStyle") { progressBar->setStyleSheet( "QProgressBar { background-color: #e8e8e8; border: 1px solid grey; " "border-radius: 7px; padding: 1px; text-align: center; } " "QProgressBar::chunk { background: QLinearGradient(x1: 0, y1: 0, " "x2: 1, y2: 0, stop: 0 #FF8000, stop: 1 orange); border-radius: " "7px; margin: 0px; }"); } statusBar()->addWidget(progressBarLabel); statusBar()->addWidget(progressBar); statusBar()->addPermanentWidget(frameBlocks); // Install event filter to be able to catch status tip events // (QEvent::StatusTip) this->installEventFilter(this); // Initially wallet actions should be disabled setWalletActionsEnabled(false); // Subscribe to notifications from core subscribeToCoreSignals(); 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(enableWallet, this->centralWidget()); connect(labelBlocksIcon, &GUIUtil::ClickableLabel::clicked, this, &BitcoinGUI::showModalOverlay); connect(progressBar, &GUIUtil::ClickableProgressBar::clicked, this, &BitcoinGUI::showModalOverlay); #ifdef ENABLE_WALLET if (enableWallet) { connect(walletFrame, &WalletFrame::requestedSyncWarningInfo, this, &BitcoinGUI::showModalOverlay); } #endif #ifdef Q_OS_MAC m_app_nap_inhibitor = new CAppNapInhibitor; #endif } BitcoinGUI::~BitcoinGUI() { // Unsubscribe from notifications from core unsubscribeFromCoreSignals(); QSettings settings; settings.setValue("MainWindowGeometry", saveGeometry()); // Hide tray icon, as deleting will let it linger until quit (on Ubuntu) if (trayIcon) { trayIcon->hide(); } #ifdef Q_OS_MAC delete m_app_nap_inhibitor; delete appMenuBar; MacDockIconHandler::cleanup(); #endif delete rpcConsole; } void BitcoinGUI::createActions() { QActionGroup *tabGroup = new QActionGroup(this); overviewAction = new QAction(platformStyle->SingleColorIcon(":/icons/overview"), tr("&Overview"), this); overviewAction->setStatusTip(tr("Show general overview of wallet")); overviewAction->setToolTip(overviewAction->statusTip()); overviewAction->setCheckable(true); overviewAction->setShortcut(QKeySequence(Qt::ALT + Qt::Key_1)); tabGroup->addAction(overviewAction); sendCoinsAction = new QAction( platformStyle->SingleColorIcon(":/icons/send"), tr("&Send"), this); sendCoinsAction->setStatusTip(tr("Send coins to a Bitcoin address")); sendCoinsAction->setToolTip(sendCoinsAction->statusTip()); sendCoinsAction->setCheckable(true); sendCoinsAction->setShortcut(QKeySequence(Qt::ALT + Qt::Key_2)); tabGroup->addAction(sendCoinsAction); - sendCoinsMenuAction = - new QAction(platformStyle->TextColorIcon(":/icons/send"), - sendCoinsAction->text(), this); + sendCoinsMenuAction = new QAction(sendCoinsAction->text(), this); sendCoinsMenuAction->setStatusTip(sendCoinsAction->statusTip()); sendCoinsMenuAction->setToolTip(sendCoinsMenuAction->statusTip()); receiveCoinsAction = new QAction( platformStyle->SingleColorIcon(":/icons/receiving_addresses"), tr("&Receive"), this); receiveCoinsAction->setStatusTip( tr("Request payments (generates QR codes and %1: URIs)") .arg(QString::fromStdString( config->GetChainParams().CashAddrPrefix()))); receiveCoinsAction->setToolTip(receiveCoinsAction->statusTip()); receiveCoinsAction->setCheckable(true); receiveCoinsAction->setShortcut(QKeySequence(Qt::ALT + Qt::Key_3)); tabGroup->addAction(receiveCoinsAction); - receiveCoinsMenuAction = - new QAction(platformStyle->TextColorIcon(":/icons/receiving_addresses"), - receiveCoinsAction->text(), this); + receiveCoinsMenuAction = new QAction(receiveCoinsAction->text(), this); receiveCoinsMenuAction->setStatusTip(receiveCoinsAction->statusTip()); receiveCoinsMenuAction->setToolTip(receiveCoinsMenuAction->statusTip()); historyAction = new QAction(platformStyle->SingleColorIcon(":/icons/history"), tr("&Transactions"), this); historyAction->setStatusTip(tr("Browse transaction history")); historyAction->setToolTip(historyAction->statusTip()); historyAction->setCheckable(true); historyAction->setShortcut(QKeySequence(Qt::ALT + Qt::Key_4)); tabGroup->addAction(historyAction); #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, &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); + quitAction = new QAction(tr("E&xit"), this); quitAction->setStatusTip(tr("Quit application")); quitAction->setShortcut(QKeySequence(Qt::CTRL + Qt::Key_Q)); quitAction->setMenuRole(QAction::QuitRole); - aboutAction = new QAction(platformStyle->TextColorIcon(":/icons/about"), - tr("&About %1").arg(PACKAGE_NAME), this); + aboutAction = new QAction(tr("&About %1").arg(PACKAGE_NAME), this); aboutAction->setStatusTip( tr("Show information about %1").arg(PACKAGE_NAME)); aboutAction->setMenuRole(QAction::AboutRole); aboutAction->setEnabled(false); - aboutQtAction = - new QAction(platformStyle->TextColorIcon(":/icons/about_qt"), - tr("About &Qt"), this); + aboutQtAction = new QAction(tr("About &Qt"), this); aboutQtAction->setStatusTip(tr("Show information about Qt")); aboutQtAction->setMenuRole(QAction::AboutQtRole); - optionsAction = new QAction(platformStyle->TextColorIcon(":/icons/options"), - tr("&Options..."), this); + optionsAction = new QAction(tr("&Options..."), this); optionsAction->setStatusTip( tr("Modify configuration options for %1").arg(PACKAGE_NAME)); optionsAction->setMenuRole(QAction::PreferencesRole); optionsAction->setEnabled(false); - toggleHideAction = - new QAction(platformStyle->TextColorIcon(":/icons/about"), - tr("&Show / Hide"), this); + toggleHideAction = new QAction(tr("&Show / Hide"), this); toggleHideAction->setStatusTip(tr("Show or hide the main Window")); - encryptWalletAction = - new QAction(platformStyle->TextColorIcon(":/icons/lock_closed"), - tr("&Encrypt Wallet..."), this); + encryptWalletAction = new QAction(tr("&Encrypt Wallet..."), this); encryptWalletAction->setStatusTip( tr("Encrypt the private keys that belong to your wallet")); encryptWalletAction->setCheckable(true); - backupWalletAction = - new QAction(platformStyle->TextColorIcon(":/icons/filesave"), - tr("&Backup Wallet..."), this); + backupWalletAction = new QAction(tr("&Backup Wallet..."), this); backupWalletAction->setStatusTip(tr("Backup wallet to another location")); - changePassphraseAction = - new QAction(platformStyle->TextColorIcon(":/icons/key"), - tr("&Change Passphrase..."), this); + changePassphraseAction = new QAction(tr("&Change Passphrase..."), this); changePassphraseAction->setStatusTip( tr("Change the passphrase used for wallet encryption")); - signMessageAction = - new QAction(platformStyle->TextColorIcon(":/icons/edit"), - tr("Sign &message..."), this); + signMessageAction = new QAction(tr("Sign &message..."), this); signMessageAction->setStatusTip( tr("Sign messages with your Bitcoin addresses to prove you own them")); - verifyMessageAction = - new QAction(platformStyle->TextColorIcon(":/icons/verify"), - tr("&Verify message..."), this); + verifyMessageAction = new QAction(tr("&Verify message..."), this); verifyMessageAction->setStatusTip( tr("Verify messages to ensure they were signed with specified Bitcoin " "addresses")); m_load_psbt_action = new QAction(tr("Load PSBT..."), this); m_load_psbt_action->setStatusTip( tr("Load Partially Signed Bitcoin Transaction")); - openRPCConsoleAction = - new QAction(platformStyle->TextColorIcon(":/icons/debugwindow"), - tr("Node window"), this); + openRPCConsoleAction = new QAction(tr("&Debug window"), this); openRPCConsoleAction->setStatusTip( tr("Open node 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(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); + new QAction(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 = new QAction(tr("Open &URI..."), this); openAction->setStatusTip( tr("Open a %1: URI or payment request") .arg(QString::fromStdString( config->GetChainParams().CashAddrPrefix()))); m_open_wallet_action = new QAction(tr("Open Wallet"), this); m_open_wallet_action->setEnabled(false); m_open_wallet_action->setStatusTip(tr("Open a wallet")); m_open_wallet_menu = new QMenu(this); m_close_wallet_action = new QAction(tr("Close Wallet..."), this); m_close_wallet_action->setStatusTip(tr("Close wallet")); m_create_wallet_action = new QAction(tr("Create Wallet..."), this); m_create_wallet_action->setEnabled(false); m_create_wallet_action->setStatusTip(tr("Create a new wallet")); - showHelpMessageAction = - new QAction(platformStyle->TextColorIcon(":/icons/info"), - tr("&Command-line options"), this); + showHelpMessageAction = new QAction(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(PACKAGE_NAME)); 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, &QAction::triggered, rpcConsole, &QWidget::hide); #ifdef ENABLE_WALLET if (walletFrame) { 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(m_load_psbt_action, &QAction::triggered, [this] { gotoLoadPSBT(); }); 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_menu, &QMenu::aboutToShow, [this] { m_open_wallet_menu->clear(); for (const std::pair &i : m_wallet_controller->listWalletDir()) { const std::string &path = i.first; QString name = path.empty() ? QString("[" + tr("default wallet") + "]") : QString::fromStdString(path); // Menu items remove single &. Single & are shown when && is in // the string, but only the first occurrence. So replace only // the first & with && name.replace(name.indexOf(QChar('&')), 1, QString("&&")); QAction *action = m_open_wallet_menu->addAction(name); if (i.second) { // This wallet is already loaded action->setEnabled(false); continue; } 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); activity->open(path); }); } if (m_open_wallet_menu->isEmpty()) { QAction *action = m_open_wallet_menu->addAction(tr("No wallets available")); action->setEnabled(false); } }); connect(m_close_wallet_action, &QAction::triggered, [this] { m_wallet_controller->closeWallet(walletFrame->currentWalletModel(), this); }); connect(m_create_wallet_action, &QAction::triggered, [this] { auto activity = new CreateWalletActivity( m_wallet_controller, this, this->config->GetChainParams()); connect(activity, &CreateWalletActivity::created, this, &BitcoinGUI::setCurrentWallet); connect(activity, &CreateWalletActivity::finished, activity, &QObject::deleteLater); activity->create(); }); } #endif // ENABLE_WALLET 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() { #ifdef Q_OS_MAC // Create a decoupled menu bar on Mac which stays even if the window is // closed appMenuBar = new QMenuBar(); #else // Get the main window's menu bar on other platforms appMenuBar = menuBar(); #endif // Configure the menus QMenu *file = appMenuBar->addMenu(tr("&File")); if (walletFrame) { file->addAction(m_create_wallet_action); 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->addAction(m_load_psbt_action); file->addSeparator(); } file->addAction(quitAction); QMenu *settings = appMenuBar->addMenu(tr("&Settings")); if (walletFrame) { settings->addAction(encryptWalletAction); settings->addAction(changePassphraseAction); settings->addSeparator(); } settings->addAction(optionsAction); 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, [] { QApplication::activeWindow()->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); }); #endif if (walletFrame) { #ifdef Q_OS_MAC window_menu->addSeparator(); QAction *main_window_action = window_menu->addAction(tr("Main Window")); connect(main_window_action, &QAction::triggered, [this] { GUIUtil::bringToFront(this); }); #endif 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)); tab_action->setShortcut(rpcConsole->tabShortcut(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); help->addAction(aboutQtAction); } void BitcoinGUI::createToolBars() { if (walletFrame) { QToolBar *toolbar = addToolBar(tr("Tabs toolbar")); appToolBar = toolbar; toolbar->setContextMenuPolicy(Qt::PreventContextMenu); toolbar->setMovable(false); toolbar->setToolButtonStyle(Qt::ToolButtonTextBesideIcon); toolbar->addAction(overviewAction); toolbar->addAction(sendCoinsAction); toolbar->addAction(receiveCoinsAction); toolbar->addAction(historyAction); overviewAction->setChecked(true); #ifdef ENABLE_WALLET QWidget *spacer = new QWidget(); spacer->setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Expanding); toolbar->addWidget(spacer); m_wallet_selector = new QComboBox(); m_wallet_selector->setSizeAdjustPolicy(QComboBox::AdjustToContents); connect(m_wallet_selector, static_cast( &QComboBox::currentIndexChanged), this, &BitcoinGUI::setCurrentWalletBySelectorIndex); m_wallet_selector_label = new QLabel(); m_wallet_selector_label->setText(tr("Wallet:") + " "); m_wallet_selector_label->setBuddy(m_wallet_selector); m_wallet_selector_label_action = appToolBar->addWidget(m_wallet_selector_label); m_wallet_selector_action = appToolBar->addWidget(m_wallet_selector); m_wallet_selector_label_action->setVisible(false); m_wallet_selector_action->setVisible(false); #endif } } void BitcoinGUI::setClientModel(ClientModel *_clientModel) { this->clientModel = _clientModel; if (_clientModel) { // Create system tray menu (or setup the dock menu) that late to prevent // users from calling actions, while the client has not yet fully loaded createTrayIconMenu(); // Keep up to date with client updateNetworkState(); 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, SynchronizationState::INIT_DOWNLOAD); connect(_clientModel, &ClientModel::numBlocksChanged, this, &BitcoinGUI::setNumBlocks); // Receive and report messages from client model connect(_clientModel, &ClientModel::message, [this](const QString &title, const QString &message, unsigned int style) { this->message(title, message, style); }); // Show progress dialog connect(_clientModel, &ClientModel::showProgress, this, &BitcoinGUI::showProgress); rpcConsole->setClientModel(_clientModel); updateProxyIcon(); #ifdef ENABLE_WALLET if (walletFrame) { walletFrame->setClientModel(_clientModel); } #endif // ENABLE_WALLET unitDisplayControl->setOptionsModel(_clientModel->getOptionsModel()); OptionsModel *optionsModel = _clientModel->getOptionsModel(); if (optionsModel && trayIcon) { // be aware of the tray icon disable state change reported by the // OptionsModel object. 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()); } } else { // Disable possibility to show main window via action toggleHideAction->setEnabled(false); if (trayIconMenu) { // Disable context menu on tray icon trayIconMenu->clear(); } // Propagate cleared model to child objects rpcConsole->setClientModel(nullptr); #ifdef ENABLE_WALLET if (walletFrame) { walletFrame->setClientModel(nullptr); } #endif // ENABLE_WALLET unitDisplayControl->setOptionsModel(nullptr); } } #ifdef ENABLE_WALLET void BitcoinGUI::setWalletController(WalletController *wallet_controller) { assert(!m_wallet_controller); assert(wallet_controller); m_wallet_controller = wallet_controller; m_create_wallet_action->setEnabled(true); m_open_wallet_action->setEnabled(true); m_open_wallet_action->setMenu(m_open_wallet_menu); connect(wallet_controller, &WalletController::walletAdded, this, &BitcoinGUI::addWallet); connect(wallet_controller, &WalletController::walletRemoved, this, &BitcoinGUI::removeWallet); for (WalletModel *wallet_model : m_wallet_controller->getOpenWallets()) { addWallet(wallet_model); } } void BitcoinGUI::addWallet(WalletModel *walletModel) { if (!walletFrame) { return; } if (!walletFrame->addWallet(walletModel)) { return; } const QString display_name = walletModel->getDisplayName(); setWalletActionsEnabled(true); rpcConsole->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); } } void BitcoinGUI::removeWallet(WalletModel *walletModel) { if (!walletFrame) { return; } labelWalletHDStatusIcon->hide(); labelWalletEncryptionIcon->hide(); int index = m_wallet_selector->findData(QVariant::fromValue(walletModel)); m_wallet_selector->removeItem(index); if (m_wallet_selector->count() == 0) { setWalletActionsEnabled(false); } else if (m_wallet_selector->count() == 1) { m_wallet_selector_label_action->setVisible(false); m_wallet_selector_action->setVisible(false); } rpcConsole->removeWallet(walletModel); walletFrame->removeWallet(walletModel); updateWindowTitle(); } void BitcoinGUI::setCurrentWallet(WalletModel *wallet_model) { if (!walletFrame) { return; } walletFrame->setCurrentWallet(wallet_model); for (int index = 0; index < m_wallet_selector->count(); ++index) { if (m_wallet_selector->itemData(index).value() == wallet_model) { m_wallet_selector->setCurrentIndex(index); break; } } updateWindowTitle(); } void BitcoinGUI::setCurrentWalletBySelectorIndex(int index) { WalletModel *wallet_model = m_wallet_selector->itemData(index).value(); if (wallet_model) { setCurrentWallet(wallet_model); } } void BitcoinGUI::removeAllWallets() { if (!walletFrame) { return; } setWalletActionsEnabled(false); walletFrame->removeAllWallets(); } #endif // ENABLE_WALLET void BitcoinGUI::setWalletActionsEnabled(bool enabled) { overviewAction->setEnabled(enabled); sendCoinsAction->setEnabled(enabled); sendCoinsMenuAction->setEnabled(enabled); receiveCoinsAction->setEnabled(enabled); receiveCoinsMenuAction->setEnabled(enabled); historyAction->setEnabled(enabled); encryptWalletAction->setEnabled(enabled); backupWalletAction->setEnabled(enabled); changePassphraseAction->setEnabled(enabled); signMessageAction->setEnabled(enabled); verifyMessageAction->setEnabled(enabled); usedSendingAddressesAction->setEnabled(enabled); usedReceivingAddressesAction->setEnabled(enabled); openAction->setEnabled(enabled); m_close_wallet_action->setEnabled(enabled); } void BitcoinGUI::createTrayIcon() { assert(QSystemTrayIcon::isSystemTrayAvailable()); #ifndef Q_OS_MAC if (QSystemTrayIcon::isSystemTrayAvailable()) { trayIcon = new QSystemTrayIcon(m_network_style->getTrayAndWindowIcon(), this); QString toolTip = tr("%1 client").arg(PACKAGE_NAME) + " " + m_network_style->getTitleAddText(); trayIcon->setToolTip(toolTip); } #endif } void BitcoinGUI::createTrayIconMenu() { #ifndef Q_OS_MAC // Return if trayIcon is unset (only on non-macOSes) if (!trayIcon) { return; } trayIcon->setContextMenu(trayIconMenu.get()); connect(trayIcon, &QSystemTrayIcon::activated, this, &BitcoinGUI::trayIconActivated); #else // Note: On macOS, the Dock icon is used to provide the tray's // functionality. MacDockIconHandler *dockIconHandler = MacDockIconHandler::instance(); connect(dockIconHandler, &MacDockIconHandler::dockIconClicked, this, &BitcoinGUI::macosDockIconActivated); trayIconMenu->setAsDockMenu(); #endif // 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(); #endif if (enableWallet) { trayIconMenu->addAction(sendCoinsMenuAction); trayIconMenu->addAction(receiveCoinsMenuAction); trayIconMenu->addSeparator(); trayIconMenu->addAction(signMessageAction); trayIconMenu->addAction(verifyMessageAction); trayIconMenu->addSeparator(); } trayIconMenu->addAction(optionsAction); trayIconMenu->addAction(openRPCConsoleAction); #ifndef Q_OS_MAC // This is built-in on macOS trayIconMenu->addSeparator(); trayIconMenu->addAction(quitAction); #endif } #ifndef Q_OS_MAC void BitcoinGUI::trayIconActivated(QSystemTrayIcon::ActivationReason reason) { if (reason == QSystemTrayIcon::Trigger) { // Click on system tray icon triggers show/hide of the main window toggleHidden(); } } #else void BitcoinGUI::macosDockIconActivated() { show(); activateWindow(); } #endif void BitcoinGUI::optionsClicked() { openOptionsDialogWithTab(OptionsDialog::TAB_MAIN); } void BitcoinGUI::aboutClicked() { if (!clientModel) { return; } HelpMessageDialog dlg(this, true); dlg.exec(); } void BitcoinGUI::showDebugWindow() { GUIUtil::bringToFront(rpcConsole); Q_EMIT consoleShown(rpcConsole); } void BitcoinGUI::showDebugWindowActivateConsole() { rpcConsole->setTabFocus(RPCConsole::TabTypes::CONSOLE); showDebugWindow(); } void BitcoinGUI::showHelpMessageClicked() { helpMessageDialog->show(); } #ifdef ENABLE_WALLET void BitcoinGUI::openClicked() { OpenURIDialog dlg(config->GetChainParams(), this); if (dlg.exec()) { Q_EMIT receivedURI(dlg.getURI()); } } void BitcoinGUI::gotoOverviewPage() { overviewAction->setChecked(true); if (walletFrame) { walletFrame->gotoOverviewPage(); } } void BitcoinGUI::gotoHistoryPage() { historyAction->setChecked(true); if (walletFrame) { walletFrame->gotoHistoryPage(); } } void BitcoinGUI::gotoReceiveCoinsPage() { receiveCoinsAction->setChecked(true); if (walletFrame) { walletFrame->gotoReceiveCoinsPage(); } } void BitcoinGUI::gotoSendCoinsPage(QString addr) { sendCoinsAction->setChecked(true); if (walletFrame) { walletFrame->gotoSendCoinsPage(addr); } } void BitcoinGUI::gotoSignMessageTab(QString addr) { if (walletFrame) { walletFrame->gotoSignMessageTab(addr); } } void BitcoinGUI::gotoVerifyMessageTab(QString addr) { if (walletFrame) { walletFrame->gotoVerifyMessageTab(addr); } } void BitcoinGUI::gotoLoadPSBT() { if (walletFrame) { walletFrame->gotoLoadPSBT(); } } #endif // ENABLE_WALLET void BitcoinGUI::updateNetworkState() { int count = clientModel->getNumConnections(); QString icon; switch (count) { case 0: icon = ":/icons/connect_0"; break; case 1: case 2: case 3: icon = ":/icons/connect_1"; break; case 4: case 5: case 6: icon = ":/icons/connect_2"; break; case 7: case 8: case 9: icon = ":/icons/connect_3"; break; default: icon = ":/icons/connect_4"; break; } QString tooltip; if (m_node.getNetworkActive()) { tooltip = tr("%n active connection(s) to Bitcoin network", "", count) + QString(".
") + tr("Click to disable network activity."); } else { tooltip = tr("Network activity disabled.") + QString("
") + tr("Click to enable network activity again."); icon = ":/icons/network_disabled"; } // Don't word-wrap this (fixed-width) tooltip tooltip = QString("") + tooltip + QString(""); connectionsControl->setToolTip(tooltip); connectionsControl->setPixmap(platformStyle->SingleColorIcon(icon).pixmap( STATUSBAR_ICONSIZE, STATUSBAR_ICONSIZE)); } void BitcoinGUI::setNumConnections(int count) { updateNetworkState(); } void BitcoinGUI::setNetworkActive(bool networkActive) { updateNetworkState(); } void BitcoinGUI::updateHeadersSyncProgressLabel() { int64_t headersTipTime = clientModel->getHeaderTipTime(); int headersTipHeight = clientModel->getHeaderTipHeight(); int estHeadersLeft = (GetTime() - headersTipTime) / config->GetChainParams().GetConsensus().nPowTargetSpacing; if (estHeadersLeft > HEADER_HEIGHT_DELTA_SYNC) { 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, SynchronizationState sync_state) { // Disabling macOS App Nap on initial sync, disk and reindex operations. #ifdef Q_OS_MAC if (sync_state == SynchronizationState::POST_INIT) { m_app_nap_inhibitor->enableAppNap(); } else { m_app_nap_inhibitor->disableAppNap(); } #endif if (modalOverlay) { if (header) { modalOverlay->setKnownBestHeight(count, blockDate); } else { modalOverlay->tipUpdate(count, blockDate, nVerificationProgress); } } if (!clientModel) { return; } // Prevent orphan statusbar messages (e.g. hover Quit in main menu, wait // until chain-sync starts -> garbled text) statusBar()->clearMessage(); // Acquire current block source enum BlockSource blockSource = clientModel->getBlockSource(); switch (blockSource) { case BlockSource::NETWORK: if (header) { updateHeadersSyncProgressLabel(); return; } progressBarLabel->setText(tr("Synchronizing with network...")); updateHeadersSyncProgressLabel(); break; case BlockSource::DISK: if (header) { progressBarLabel->setText(tr("Indexing blocks on disk...")); } else { progressBarLabel->setText(tr("Processing blocks on disk...")); } break; case BlockSource::REINDEX: progressBarLabel->setText(tr("Reindexing blocks on disk...")); break; case BlockSource::NONE: if (header) { return; } progressBarLabel->setText(tr("Connecting to peers...")); break; } QString tooltip; QDateTime currentDate = QDateTime::currentDateTime(); qint64 secs = blockDate.secsTo(currentDate); tooltip = tr("Processed %n block(s) of transaction history.", "", count); // Set icon state: spinning if catching up, tick otherwise if (secs < MAX_BLOCK_TIME_GAP) { tooltip = tr("Up to date") + QString(".
") + tooltip; labelBlocksIcon->setPixmap( platformStyle->SingleColorIcon(":/icons/synced") .pixmap(STATUSBAR_ICONSIZE, STATUSBAR_ICONSIZE)); #ifdef ENABLE_WALLET if (walletFrame) { walletFrame->showOutOfSyncWarning(false); modalOverlay->showHide(true, true); } #endif // ENABLE_WALLET progressBarLabel->setVisible(false); progressBar->setVisible(false); } else { QString timeBehindText = GUIUtil::formatNiceTimeOffset(secs); progressBarLabel->setVisible(true); progressBar->setFormat(tr("%1 behind").arg(timeBehindText)); progressBar->setMaximum(1000000000); progressBar->setValue(nVerificationProgress * 1000000000.0 + 0.5); progressBar->setVisible(true); tooltip = tr("Catching up...") + QString("
") + tooltip; if (count != prevBlocks) { labelBlocksIcon->setPixmap( platformStyle ->SingleColorIcon(QString(":/movies/spinner-%1") .arg(spinnerFrame, 3, 10, QChar('0'))) .pixmap(STATUSBAR_ICONSIZE, STATUSBAR_ICONSIZE)); spinnerFrame = (spinnerFrame + 1) % SPINNER_FRAMES; } prevBlocks = count; #ifdef ENABLE_WALLET if (walletFrame) { walletFrame->showOutOfSyncWarning(true); modalOverlay->showHide(); } #endif // ENABLE_WALLET tooltip += QString("
"); tooltip += tr("Last received block was generated %1 ago.").arg(timeBehindText); tooltip += QString("
"); tooltip += tr("Transactions after this will not yet be visible."); } // Don't word-wrap this (fixed-width) tooltip tooltip = QString("") + tooltip + QString(""); labelBlocksIcon->setToolTip(tooltip); progressBarLabel->setToolTip(tooltip); progressBar->setToolTip(tooltip); } void BitcoinGUI::message(const QString &title, QString message, unsigned int style, bool *ret, const QString &detailed_message) { // Default title. On macOS, the window title is ignored (as required by the // macOS Guidelines). QString strTitle{PACKAGE_NAME}; // Default to information icon int nMBoxIcon = QMessageBox::Information; int nNotifyIcon = Notificator::Information; QString msgType; if (!title.isEmpty()) { msgType = title; } else { switch (style) { case CClientUIInterface::MSG_ERROR: msgType = tr("Error"); message = tr("Error: %1").arg(message); break; case CClientUIInterface::MSG_WARNING: msgType = tr("Warning"); message = tr("Warning: %1").arg(message); break; case CClientUIInterface::MSG_INFORMATION: msgType = tr("Information"); // No need to prepend the prefix here. break; default: break; } } if (!msgType.isEmpty()) { strTitle += " - " + msgType; } if (style & CClientUIInterface::ICON_ERROR) { nMBoxIcon = QMessageBox::Critical; nNotifyIcon = Notificator::Critical; } else if (style & CClientUIInterface::ICON_WARNING) { nMBoxIcon = QMessageBox::Warning; nNotifyIcon = Notificator::Warning; } if (style & CClientUIInterface::MODAL) { // Check for buttons, use OK as default, if none was supplied QMessageBox::StandardButton buttons; if (!(buttons = (QMessageBox::StandardButton)( style & CClientUIInterface::BTN_MASK))) { buttons = QMessageBox::Ok; } showNormalIfMinimized(); QMessageBox mBox(static_cast(nMBoxIcon), strTitle, message, buttons, this); mBox.setTextFormat(Qt::PlainText); mBox.setDetailedText(detailed_message); int r = mBox.exec(); if (ret != nullptr) { *ret = r == QMessageBox::Ok; } } else { notificator->notify(static_cast(nNotifyIcon), strTitle, message); } } void BitcoinGUI::changeEvent(QEvent *e) { QMainWindow::changeEvent(e); #ifndef Q_OS_MAC // Ignored on Mac if (e->type() == QEvent::WindowStateChange) { if (clientModel && clientModel->getOptionsModel() && clientModel->getOptionsModel()->getMinimizeToTray()) { QWindowStateChangeEvent *wsevt = static_cast(e); if (!(wsevt->oldState() & Qt::WindowMinimized) && isMinimized()) { QTimer::singleShot(0, this, &BitcoinGUI::hide); e->ignore(); } else if ((wsevt->oldState() & Qt::WindowMinimized) && !isMinimized()) { QTimer::singleShot(0, this, &BitcoinGUI::show); e->ignore(); } } } #endif } void BitcoinGUI::closeEvent(QCloseEvent *event) { #ifndef Q_OS_MAC // Ignored on Mac if (clientModel && clientModel->getOptionsModel()) { if (!clientModel->getOptionsModel()->getMinimizeOnClose()) { // close rpcConsole in case it was open to make some space for the // shutdown window rpcConsole->close(); QApplication::quit(); } else { QMainWindow::showMinimized(); event->ignore(); } } #else QMainWindow::closeEvent(event); #endif } void BitcoinGUI::showEvent(QShowEvent *event) { // enable the debug window when the main window shows up openRPCConsoleAction->setEnabled(true); aboutAction->setEnabled(true); optionsAction->setEnabled(true); } #ifdef ENABLE_WALLET void BitcoinGUI::incomingTransaction(const QString &date, int unit, const Amount amount, const QString &type, const QString &address, const QString &label, const QString &walletName) { // On new transaction, make an info balloon QString msg = tr("Date: %1\n").arg(date) + tr("Amount: %1\n") .arg(BitcoinUnits::formatWithUnit(unit, amount, true)); if (m_node.getWallets().size() > 1 && !walletName.isEmpty()) { msg += tr("Wallet: %1\n").arg(walletName); } msg += tr("Type: %1\n").arg(type); if (!label.isEmpty()) { msg += tr("Label: %1\n").arg(label); } else if (!address.isEmpty()) { msg += tr("Address: %1\n").arg(address); } message(amount < Amount::zero() ? tr("Sent transaction") : tr("Incoming transaction"), msg, CClientUIInterface::MSG_INFORMATION); } #endif // ENABLE_WALLET void BitcoinGUI::dragEnterEvent(QDragEnterEvent *event) { // Accept only URIs if (event->mimeData()->hasUrls()) { event->acceptProposedAction(); } } void BitcoinGUI::dropEvent(QDropEvent *event) { if (event->mimeData()->hasUrls()) { for (const QUrl &uri : event->mimeData()->urls()) { Q_EMIT receivedURI(uri.toString()); } } event->acceptProposedAction(); } bool BitcoinGUI::eventFilter(QObject *object, QEvent *event) { // Catch status tip events if (event->type() == QEvent::StatusTip) { // Prevent adding text from setStatusTip(), if we currently use the // status bar for displaying other stuff if (progressBarLabel->isVisible() || progressBar->isVisible()) { return true; } } return QMainWindow::eventFilter(object, event); } #ifdef ENABLE_WALLET bool BitcoinGUI::handlePaymentRequest(const SendCoinsRecipient &recipient) { // URI has to be valid if (walletFrame && walletFrame->handlePaymentRequest(recipient)) { showNormalIfMinimized(); gotoSendCoinsPage(); return true; } return false; } void BitcoinGUI::setHDStatus(bool privkeyDisabled, int hdEnabled) { 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 disabled") : hdEnabled ? tr("HD key generation is enabled") : tr("HD key generation is disabled")); labelWalletHDStatusIcon->show(); // eventually disable the QLabel to set its opacity to 50% labelWalletHDStatusIcon->setEnabled(hdEnabled); } void BitcoinGUI::setEncryptionStatus(int status) { switch (status) { case WalletModel::Unencrypted: labelWalletEncryptionIcon->hide(); encryptWalletAction->setChecked(false); changePassphraseAction->setEnabled(false); encryptWalletAction->setEnabled(true); break; case WalletModel::Unlocked: labelWalletEncryptionIcon->show(); labelWalletEncryptionIcon->setPixmap( platformStyle->SingleColorIcon(":/icons/lock_open") .pixmap(STATUSBAR_ICONSIZE, STATUSBAR_ICONSIZE)); labelWalletEncryptionIcon->setToolTip( tr("Wallet is encrypted and currently unlocked")); encryptWalletAction->setChecked(true); changePassphraseAction->setEnabled(true); encryptWalletAction->setEnabled( false); // TODO: decrypt currently not supported break; case WalletModel::Locked: labelWalletEncryptionIcon->show(); labelWalletEncryptionIcon->setPixmap( platformStyle->SingleColorIcon(":/icons/lock_closed") .pixmap(STATUSBAR_ICONSIZE, STATUSBAR_ICONSIZE)); labelWalletEncryptionIcon->setToolTip( tr("Wallet is encrypted and currently locked")); encryptWalletAction->setChecked(true); changePassphraseAction->setEnabled(true); encryptWalletAction->setEnabled( false); // TODO: decrypt currently not supported break; } } void BitcoinGUI::updateWalletStatus() { if (!walletFrame) { return; } WalletView *const walletView = walletFrame->currentWalletView(); if (!walletView) { return; } WalletModel *const walletModel = walletView->getWalletModel(); setEncryptionStatus(walletModel->getEncryptionStatus()); setHDStatus(walletModel->wallet().privateKeysDisabled(), walletModel->wallet().hdEnabled()); } #endif // ENABLE_WALLET void BitcoinGUI::updateProxyIcon() { std::string ip_port; bool proxy_enabled = clientModel->getProxyInfo(ip_port); if (proxy_enabled) { if (!labelProxyIcon->hasPixmap()) { QString ip_port_q = QString::fromStdString(ip_port); labelProxyIcon->setPixmap( platformStyle->SingleColorIcon(":/icons/proxy") .pixmap(STATUSBAR_ICONSIZE, STATUSBAR_ICONSIZE)); labelProxyIcon->setToolTip( tr("Proxy is enabled: %1").arg(ip_port_q)); } else { labelProxyIcon->show(); } } else { labelProxyIcon->hide(); } } void BitcoinGUI::updateWindowTitle() { QString window_title = 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; } if (!isHidden() && !isMinimized() && !GUIUtil::isObscured(this) && fToggleHidden) { hide(); } else { GUIUtil::bringToFront(this); } } void BitcoinGUI::toggleHidden() { showNormalIfMinimized(true); } void BitcoinGUI::detectShutdown() { if (m_node.shutdownRequested()) { if (rpcConsole) { rpcConsole->hide(); } qApp->quit(); } } void BitcoinGUI::showProgress(const QString &title, int nProgress) { if (nProgress == 0) { progressDialog = new QProgressDialog(title, QString(), 0, 100); GUIUtil::PolishProgressDialog(progressDialog); progressDialog->setWindowModality(Qt::ApplicationModal); progressDialog->setMinimumDuration(0); progressDialog->setAutoClose(false); progressDialog->setValue(0); } else if (nProgress == 100) { if (progressDialog) { progressDialog->close(); progressDialog->deleteLater(); progressDialog = nullptr; } } else if (progressDialog) { progressDialog->setValue(nProgress); } } void BitcoinGUI::setTrayIconVisible(bool fHideTrayIcon) { if (trayIcon) { trayIcon->setVisible(!fHideTrayIcon); } } void BitcoinGUI::showModalOverlay() { if (modalOverlay && (progressBar->isVisible() || modalOverlay->isLayerVisible())) { modalOverlay->toggleVisibility(); } } static bool ThreadSafeMessageBox(BitcoinGUI *gui, const bilingual_str &message, const std::string &caption, unsigned int style) { bool modal = (style & CClientUIInterface::MODAL); // The SECURE flag has no effect in the Qt GUI. // bool secure = (style & CClientUIInterface::SECURE); style &= ~CClientUIInterface::SECURE; bool ret = false; // This is original message, in English, for googling and referencing. QString detailed_message; if (message.original != message.translated) { detailed_message = BitcoinGUI::tr("Original message:") + "\n" + QString::fromStdString(message.original); } // In case of modal message, use blocking connection to wait for user to // click a button bool invoked = QMetaObject::invokeMethod( gui, "message", modal ? GUIUtil::blockingGUIThreadConnection() : Qt::QueuedConnection, Q_ARG(QString, QString::fromStdString(caption)), Q_ARG(QString, QString::fromStdString(message.translated)), Q_ARG(unsigned int, style), Q_ARG(bool *, &ret), Q_ARG(QString, detailed_message)); assert(invoked); return ret; } void BitcoinGUI::subscribeToCoreSignals() { // Connect signals to client 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() { // Disconnect signals from client m_handler_message_box->disconnect(); m_handler_question->disconnect(); } UnitDisplayStatusBarControl::UnitDisplayStatusBarControl( const PlatformStyle *platformStyle) : optionsModel(nullptr), menu(nullptr) { createContextMenu(); setToolTip(tr("Unit to show amounts in. Click to select another unit.")); QList units = BitcoinUnits::availableUnits(); int max_width = 0; const QFontMetrics fm(font()); for (const BitcoinUnits::Unit unit : units) { max_width = qMax(max_width, GUIUtil::TextWidth(fm, BitcoinUnits::longName(unit))); } setMinimumSize(max_width, 0); setAlignment(Qt::AlignRight | Qt::AlignVCenter); setStyleSheet(QString("QLabel { color : %1 }") .arg(platformStyle->SingleColor().name())); } /** So that it responds to button clicks */ void UnitDisplayStatusBarControl::mousePressEvent(QMouseEvent *event) { onDisplayUnitsClicked(event->pos()); } /** Creates context menu, its actions, and wires up all the relevant signals for * mouse events. */ void UnitDisplayStatusBarControl::createContextMenu() { menu = new QMenu(this); 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, &QMenu::triggered, this, &UnitDisplayStatusBarControl::onMenuSelection); } /** Lets the control know about the Options Model (and its signals) */ void UnitDisplayStatusBarControl::setOptionsModel(OptionsModel *_optionsModel) { if (_optionsModel) { this->optionsModel = _optionsModel; // be aware of a display unit change reported by the OptionsModel // object. connect(_optionsModel, &OptionsModel::displayUnitChanged, this, &UnitDisplayStatusBarControl::updateDisplayUnit); // initialize the display units label with the current value in the // model. updateDisplayUnit(_optionsModel->getDisplayUnit()); } } /** When Display Units are changed on OptionsModel it will refresh the display * text of the control on the status bar */ void UnitDisplayStatusBarControl::updateDisplayUnit(int newUnits) { setText(BitcoinUnits::longName(newUnits)); } /** Shows context menu with Display Unit options by the mouse coordinates */ void UnitDisplayStatusBarControl::onDisplayUnitsClicked(const QPoint &point) { QPoint globalPos = mapToGlobal(point); menu->exec(globalPos); } /** Tells underlying optionsModel to update its current display unit. */ void UnitDisplayStatusBarControl::onMenuSelection(QAction *action) { if (action) { optionsModel->setDisplayUnit(action->data()); } } diff --git a/src/qt/res/icons/about.png b/src/qt/res/icons/about.png deleted file mode 100644 index fb500564c..000000000 Binary files a/src/qt/res/icons/about.png and /dev/null differ diff --git a/src/qt/res/icons/about_qt.png b/src/qt/res/icons/about_qt.png deleted file mode 100644 index c40abfd3a..000000000 Binary files a/src/qt/res/icons/about_qt.png and /dev/null differ diff --git a/src/qt/res/icons/configure.png b/src/qt/res/icons/configure.png deleted file mode 100644 index 5333c83d5..000000000 Binary files a/src/qt/res/icons/configure.png and /dev/null differ diff --git a/src/qt/res/icons/debugwindow.png b/src/qt/res/icons/debugwindow.png deleted file mode 100644 index 290fe6086..000000000 Binary files a/src/qt/res/icons/debugwindow.png and /dev/null differ diff --git a/src/qt/res/icons/filesave.png b/src/qt/res/icons/filesave.png deleted file mode 100644 index 779cca1d5..000000000 Binary files a/src/qt/res/icons/filesave.png and /dev/null differ diff --git a/src/qt/res/icons/info.png b/src/qt/res/icons/info.png deleted file mode 100644 index 692b50c2a..000000000 Binary files a/src/qt/res/icons/info.png and /dev/null differ diff --git a/src/qt/res/icons/key.png b/src/qt/res/icons/key.png deleted file mode 100644 index f301c4f38..000000000 Binary files a/src/qt/res/icons/key.png and /dev/null differ diff --git a/src/qt/res/icons/open.png b/src/qt/res/icons/open.png deleted file mode 100644 index 4d958f0e1..000000000 Binary files a/src/qt/res/icons/open.png and /dev/null differ diff --git a/src/qt/res/icons/quit.png b/src/qt/res/icons/quit.png deleted file mode 100644 index 55e34de4b..000000000 Binary files a/src/qt/res/icons/quit.png and /dev/null differ diff --git a/src/qt/res/icons/verify.png b/src/qt/res/icons/verify.png deleted file mode 100644 index 8e2cb2cc1..000000000 Binary files a/src/qt/res/icons/verify.png and /dev/null differ diff --git a/src/qt/res/src/verify.svg b/src/qt/res/src/verify.svg deleted file mode 100644 index 1ff11b7f5..000000000 --- a/src/qt/res/src/verify.svg +++ /dev/null @@ -1,14 +0,0 @@ - - - - - - -