diff options
Diffstat (limited to 'src/qt')
78 files changed, 1483 insertions, 1065 deletions
diff --git a/src/qt/addressbookpage.cpp b/src/qt/addressbookpage.cpp index 26bdf60d4a..726dafccb0 100644 --- a/src/qt/addressbookpage.cpp +++ b/src/qt/addressbookpage.cpp @@ -59,7 +59,7 @@ protected: AddressBookPage::AddressBookPage(const PlatformStyle *platformStyle, Mode _mode, Tabs _tab, QWidget *parent) : QDialog(parent), ui(new Ui::AddressBookPage), - model(0), + model(nullptr), mode(_mode), tab(_tab) { diff --git a/src/qt/addressbookpage.h b/src/qt/addressbookpage.h index 32ab2dfeb5..6394d26801 100644 --- a/src/qt/addressbookpage.h +++ b/src/qt/addressbookpage.h @@ -38,7 +38,7 @@ public: ForEditing /**< Open address book for editing */ }; - explicit AddressBookPage(const PlatformStyle *platformStyle, Mode mode, Tabs tab, QWidget *parent = 0); + explicit AddressBookPage(const PlatformStyle *platformStyle, Mode mode, Tabs tab, QWidget *parent = nullptr); ~AddressBookPage(); void setModel(AddressTableModel *model); diff --git a/src/qt/addresstablemodel.cpp b/src/qt/addresstablemodel.cpp index 2f88e15d21..c3143e948a 100644 --- a/src/qt/addresstablemodel.cpp +++ b/src/qt/addresstablemodel.cpp @@ -153,7 +153,7 @@ public: } else { - return 0; + return nullptr; } } }; @@ -300,8 +300,8 @@ QVariant AddressTableModel::headerData(int section, Qt::Orientation orientation, Qt::ItemFlags AddressTableModel::flags(const QModelIndex &index) const { - if(!index.isValid()) - return 0; + if (!index.isValid()) return Qt::NoItemFlags; + AddressTableEntry *rec = static_cast<AddressTableEntry*>(index.internalPointer()); Qt::ItemFlags retval = Qt::ItemIsSelectable | Qt::ItemIsEnabled; diff --git a/src/qt/addresstablemodel.h b/src/qt/addresstablemodel.h index 41bed4e290..035f3e0571 100644 --- a/src/qt/addresstablemodel.h +++ b/src/qt/addresstablemodel.h @@ -25,7 +25,7 @@ class AddressTableModel : public QAbstractTableModel Q_OBJECT public: - explicit AddressTableModel(WalletModel *parent = 0); + explicit AddressTableModel(WalletModel *parent = nullptr); ~AddressTableModel(); enum ColumnIndex { diff --git a/src/qt/askpassphrasedialog.cpp b/src/qt/askpassphrasedialog.cpp index 821c23c467..a89a15bc9d 100644 --- a/src/qt/askpassphrasedialog.cpp +++ b/src/qt/askpassphrasedialog.cpp @@ -22,7 +22,7 @@ AskPassphraseDialog::AskPassphraseDialog(Mode _mode, QWidget *parent) : QDialog(parent), ui(new Ui::AskPassphraseDialog), mode(_mode), - model(0), + model(nullptr), fCapsLock(false) { ui->setupUi(this); diff --git a/src/qt/bantablemodel.cpp b/src/qt/bantablemodel.cpp index dcfe3dcc57..00c446cc63 100644 --- a/src/qt/bantablemodel.cpp +++ b/src/qt/bantablemodel.cpp @@ -40,8 +40,8 @@ class BanTablePriv public: /** Local cache of peer information */ QList<CCombinedBan> cachedBanlist; - /** Column to sort nodes by */ - int sortColumn; + /** Column to sort nodes by (default to unsorted) */ + int sortColumn{-1}; /** Order (ascending or descending) to sort nodes by */ Qt::SortOrder sortOrder; @@ -76,7 +76,7 @@ public: if (idx >= 0 && idx < cachedBanlist.size()) return &cachedBanlist[idx]; - return 0; + return nullptr; } }; @@ -87,8 +87,6 @@ BanTableModel::BanTableModel(interfaces::Node& node, ClientModel *parent) : { columns << tr("IP/Netmask") << tr("Banned Until"); priv.reset(new BanTablePriv()); - // default to unsorted - priv->sortColumn = -1; // load initial data refresh(); @@ -147,8 +145,7 @@ QVariant BanTableModel::headerData(int section, Qt::Orientation orientation, int Qt::ItemFlags BanTableModel::flags(const QModelIndex &index) const { - if(!index.isValid()) - return 0; + if (!index.isValid()) return Qt::NoItemFlags; Qt::ItemFlags retval = Qt::ItemIsSelectable | Qt::ItemIsEnabled; return retval; diff --git a/src/qt/bantablemodel.h b/src/qt/bantablemodel.h index b8505b599f..9dec5fa6a9 100644 --- a/src/qt/bantablemodel.h +++ b/src/qt/bantablemodel.h @@ -45,7 +45,7 @@ class BanTableModel : public QAbstractTableModel Q_OBJECT public: - explicit BanTableModel(interfaces::Node& node, ClientModel *parent = 0); + explicit BanTableModel(interfaces::Node& node, ClientModel *parent = nullptr); ~BanTableModel(); void startAutoRefresh(); void stopAutoRefresh(); diff --git a/src/qt/bitcoin.cpp b/src/qt/bitcoin.cpp index eaeb93a652..ca26131b95 100644 --- a/src/qt/bitcoin.cpp +++ b/src/qt/bitcoin.cpp @@ -1,4 +1,4 @@ -// Copyright (c) 2011-2018 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. @@ -6,6 +6,7 @@ #include <config/bitcoin-config.h> #endif +#include <qt/bitcoin.h> #include <qt/bitcoingui.h> #include <chainparams.h> @@ -23,7 +24,7 @@ #ifdef ENABLE_WALLET #include <qt/paymentserver.h> -#include <qt/walletmodel.h> +#include <qt/walletcontroller.h> #endif #include <interfaces/handler.h> @@ -71,11 +72,6 @@ Q_DECLARE_METATYPE(bool*) Q_DECLARE_METATYPE(CAmount) Q_DECLARE_METATYPE(uint256) -/** Translate string to current locale using Qt. */ -const std::function<std::string(const char*)> G_TRANSLATION_FUN = [](const char* psz) { - return QCoreApplication::translate("bitcoin-core", psz).toStdString(); -}; - static QString GetLangTerritory() { QSettings settings; @@ -140,101 +136,6 @@ void DebugMessageHandler(QtMsgType type, const QMessageLogContext& context, cons } } -/** Class encapsulating Bitcoin Core startup and shutdown. - * Allows running startup and shutdown in a different thread from the UI thread. - */ -class BitcoinCore: public QObject -{ - Q_OBJECT -public: - explicit BitcoinCore(interfaces::Node& node); - -public Q_SLOTS: - void initialize(); - void shutdown(); - -Q_SIGNALS: - void initializeResult(bool success); - void shutdownResult(); - void runawayException(const QString &message); - -private: - /// Pass fatal exception message to UI thread - void handleRunawayException(const std::exception *e); - - interfaces::Node& m_node; -}; - -/** Main Bitcoin application object */ -class BitcoinApplication: public QApplication -{ - Q_OBJECT -public: - explicit BitcoinApplication(interfaces::Node& node, int &argc, char **argv); - ~BitcoinApplication(); - -#ifdef ENABLE_WALLET - /// Create payment server - void createPaymentServer(); -#endif - /// parameter interaction/setup based on rules - void parameterSetup(); - /// Create options model - void createOptionsModel(bool resetSettings); - /// Create main window - void createWindow(const NetworkStyle *networkStyle); - /// Create splash screen - void createSplashScreen(const NetworkStyle *networkStyle); - - /// Request core initialization - void requestInitialize(); - /// Request core shutdown - void requestShutdown(); - - /// Get process return value - int getReturnValue() const { return returnValue; } - - /// Get window identifier of QMainWindow (BitcoinGUI) - WId getMainWinId() const; - - /// Setup platform style - void setupPlatformStyle(); - -public Q_SLOTS: - void initializeResult(bool success); - void shutdownResult(); - /// Handle runaway exceptions. Shows a message box with the problem and quits the program. - void handleRunawayException(const QString &message); - void addWallet(WalletModel* walletModel); - void removeWallet(); - -Q_SIGNALS: - void requestedInitialize(); - void requestedShutdown(); - void stopThread(); - void splashFinished(); - -private: - QThread *coreThread; - interfaces::Node& m_node; - OptionsModel *optionsModel; - ClientModel *clientModel; - BitcoinGUI *window; - QTimer *pollShutdownTimer; -#ifdef ENABLE_WALLET - PaymentServer* paymentServer; - std::vector<WalletModel*> m_wallet_models; - std::unique_ptr<interfaces::Handler> m_handler_load_wallet; -#endif - int returnValue; - const PlatformStyle *platformStyle; - std::unique_ptr<QWidget> shutdownWindow; - - void startThread(); -}; - -#include <qt/bitcoin.moc> - BitcoinCore::BitcoinCore(interfaces::Node& node) : QObject(), m_node(node) { @@ -277,18 +178,14 @@ void BitcoinCore::shutdown() BitcoinApplication::BitcoinApplication(interfaces::Node& node, int &argc, char **argv): QApplication(argc, argv), - coreThread(0), + coreThread(nullptr), m_node(node), - optionsModel(0), - clientModel(0), - window(0), - pollShutdownTimer(0), -#ifdef ENABLE_WALLET - paymentServer(0), - m_wallet_models(), -#endif + optionsModel(nullptr), + clientModel(nullptr), + window(nullptr), + pollShutdownTimer(nullptr), returnValue(0), - platformStyle(0) + platformStyle(nullptr) { setQuitOnLastWindowClosed(false); } @@ -311,21 +208,21 @@ BitcoinApplication::~BitcoinApplication() if(coreThread) { qDebug() << __func__ << ": Stopping thread"; - Q_EMIT stopThread(); + coreThread->quit(); coreThread->wait(); qDebug() << __func__ << ": Stopped thread"; } delete window; - window = 0; + window = nullptr; #ifdef ENABLE_WALLET delete paymentServer; - paymentServer = 0; + paymentServer = nullptr; #endif delete optionsModel; - optionsModel = 0; + optionsModel = nullptr; delete platformStyle; - platformStyle = 0; + platformStyle = nullptr; } #ifdef ENABLE_WALLET @@ -342,7 +239,7 @@ void BitcoinApplication::createOptionsModel(bool resetSettings) void BitcoinApplication::createWindow(const NetworkStyle *networkStyle) { - window = new BitcoinGUI(m_node, platformStyle, networkStyle, 0); + window = new BitcoinGUI(m_node, platformStyle, networkStyle, nullptr); pollShutdownTimer = new QTimer(window); connect(pollShutdownTimer, &QTimer::timeout, window, &BitcoinGUI::detectShutdown); @@ -350,7 +247,7 @@ void BitcoinApplication::createWindow(const NetworkStyle *networkStyle) void BitcoinApplication::createSplashScreen(const NetworkStyle *networkStyle) { - SplashScreen *splash = new SplashScreen(m_node, 0, networkStyle); + SplashScreen *splash = new SplashScreen(m_node, nullptr, networkStyle); // We don't hold a direct pointer to the splash screen after creation, but the splash // screen will take care of deleting itself when finish() happens. splash->show(); @@ -358,6 +255,11 @@ void BitcoinApplication::createSplashScreen(const NetworkStyle *networkStyle) connect(this, &BitcoinApplication::requestedShutdown, splash, &QWidget::close); } +bool BitcoinApplication::baseInitialize() +{ + return m_node.baseInitialize(); +} + void BitcoinApplication::startThread() { if(coreThread) @@ -373,8 +275,7 @@ void BitcoinApplication::startThread() connect(this, &BitcoinApplication::requestedInitialize, executor, &BitcoinCore::initialize); connect(this, &BitcoinApplication::requestedShutdown, executor, &BitcoinCore::shutdown); /* make sure executor object is deleted in its own thread */ - connect(this, &BitcoinApplication::stopThread, executor, &QObject::deleteLater); - connect(this, &BitcoinApplication::stopThread, coreThread, &QThread::quit); + connect(coreThread, &QThread::finished, executor, &QObject::deleteLater); coreThread->start(); } @@ -406,18 +307,15 @@ void BitcoinApplication::requestShutdown() qDebug() << __func__ << ": Requesting shutdown"; startThread(); window->hide(); - window->setClientModel(0); + window->setClientModel(nullptr); pollShutdownTimer->stop(); #ifdef ENABLE_WALLET - window->removeAllWallets(); - for (const WalletModel* walletModel : m_wallet_models) { - delete walletModel; - } - m_wallet_models.clear(); + delete m_wallet_controller; + m_wallet_controller = nullptr; #endif delete clientModel; - clientModel = 0; + clientModel = nullptr; m_node.startShutdown(); @@ -425,35 +323,6 @@ void BitcoinApplication::requestShutdown() Q_EMIT requestedShutdown(); } -void BitcoinApplication::addWallet(WalletModel* walletModel) -{ -#ifdef ENABLE_WALLET - window->addWallet(walletModel); - - if (m_wallet_models.empty()) { - window->setCurrentWallet(walletModel->getWalletName()); - } - -#ifdef ENABLE_BIP70 - connect(walletModel, &WalletModel::coinsSent, - paymentServer, &PaymentServer::fetchPaymentACK); -#endif - connect(walletModel, &WalletModel::unload, this, &BitcoinApplication::removeWallet); - - m_wallet_models.push_back(walletModel); -#endif -} - -void BitcoinApplication::removeWallet() -{ -#ifdef ENABLE_WALLET - WalletModel* walletModel = static_cast<WalletModel*>(sender()); - m_wallet_models.erase(std::find(m_wallet_models.begin(), m_wallet_models.end(), walletModel)); - window->removeWallet(walletModel); - walletModel->deleteLater(); -#endif -} - void BitcoinApplication::initializeResult(bool success) { qDebug() << __func__ << ": Initialization result: " << success; @@ -464,48 +333,46 @@ void BitcoinApplication::initializeResult(bool success) // Log this only after AppInitMain finishes, as then logging setup is guaranteed complete qWarning() << "Platform customization:" << platformStyle->getName(); #ifdef ENABLE_WALLET + m_wallet_controller = new WalletController(m_node, platformStyle, optionsModel, this); #ifdef ENABLE_BIP70 PaymentServer::LoadRootCAs(); #endif - paymentServer->setOptionsModel(optionsModel); + if (paymentServer) { + paymentServer->setOptionsModel(optionsModel); +#ifdef ENABLE_BIP70 + connect(m_wallet_controller, &WalletController::coinsSent, paymentServer, &PaymentServer::fetchPaymentACK); +#endif + } #endif clientModel = new ClientModel(m_node, optionsModel); window->setClientModel(clientModel); - #ifdef ENABLE_WALLET - m_handler_load_wallet = m_node.handleLoadWallet([this](std::unique_ptr<interfaces::Wallet> wallet) { - WalletModel* wallet_model = new WalletModel(std::move(wallet), m_node, platformStyle, optionsModel, nullptr); - // Fix wallet model thread affinity. - wallet_model->moveToThread(thread()); - QMetaObject::invokeMethod(this, "addWallet", Qt::QueuedConnection, Q_ARG(WalletModel*, wallet_model)); - }); - - for (auto& wallet : m_node.getWallets()) { - addWallet(new WalletModel(std::move(wallet), m_node, platformStyle, optionsModel)); - } + window->setWalletController(m_wallet_controller); #endif - // If -min option passed, start window minimized. - if(gArgs.GetBoolArg("-min", false)) - { - window->showMinimized(); - } - else - { + // If -min option passed, start window minimized (iconified) or minimized to tray + if (!gArgs.GetBoolArg("-min", false)) { window->show(); + } else if (clientModel->getOptionsModel()->getMinimizeToTray() && window->hasTrayIcon()) { + // do nothing as the window is managed by the tray icon + } else { + window->showMinimized(); } Q_EMIT splashFinished(); + Q_EMIT windowShown(window); #ifdef ENABLE_WALLET // Now that initialization/startup is done, process any command-line // bitcoin: URIs or payment requests: - connect(paymentServer, &PaymentServer::receivedPaymentRequest, window, &BitcoinGUI::handlePaymentRequest); - connect(window, &BitcoinGUI::receivedURI, paymentServer, &PaymentServer::handleURIOrFile); - connect(paymentServer, &PaymentServer::message, [this](const QString& title, const QString& message, unsigned int style) { - window->message(title, message, style); - }); - QTimer::singleShot(100, paymentServer, &PaymentServer::uiReady); + if (paymentServer) { + connect(paymentServer, &PaymentServer::receivedPaymentRequest, window, &BitcoinGUI::handlePaymentRequest); + connect(window, &BitcoinGUI::receivedURI, paymentServer, &PaymentServer::handleURIOrFile); + connect(paymentServer, &PaymentServer::message, [this](const QString& title, const QString& message, unsigned int style) { + window->message(title, message, style); + }); + QTimer::singleShot(100, paymentServer, &PaymentServer::uiReady); + } #endif pollShutdownTimer->start(200); } else { @@ -521,7 +388,7 @@ void BitcoinApplication::shutdownResult() void BitcoinApplication::handleRunawayException(const QString &message) { - QMessageBox::critical(0, "Runaway exception", BitcoinGUI::tr("A fatal error occurred. Bitcoin can no longer continue safely and will quit.") + QString("\n\n") + message); + QMessageBox::critical(nullptr, "Runaway exception", BitcoinGUI::tr("A fatal error occurred. Bitcoin can no longer continue safely and will quit.") + QString("\n\n") + message); ::exit(EXIT_FAILURE); } @@ -548,7 +415,7 @@ static void SetupUIArgs() } #ifndef BITCOIN_QT_TEST -int main(int argc, char *argv[]) +int GuiMain(int argc, char* argv[]) { #ifdef WIN32 util::WinCmdLineArgs winArgs; @@ -585,9 +452,6 @@ int main(int argc, char *argv[]) // IMPORTANT if it is no longer a typedef use the normal variant above qRegisterMetaType< CAmount >("CAmount"); qRegisterMetaType< std::function<void()> >("std::function<void()>"); -#ifdef ENABLE_WALLET - qRegisterMetaType<WalletModel*>("WalletModel*"); -#endif /// 2. Parse command-line options. We do this after qt in order to show an error if there are problems parsing these // Command-line options take precedence: @@ -595,7 +459,7 @@ int main(int argc, char *argv[]) SetupUIArgs(); std::string error; if (!node->parseParameters(argc, argv, error)) { - QMessageBox::critical(0, QObject::tr(PACKAGE_NAME), + QMessageBox::critical(nullptr, QObject::tr(PACKAGE_NAME), QObject::tr("Error parsing command line arguments: %1.").arg(QString::fromStdString(error))); return EXIT_FAILURE; } @@ -632,12 +496,12 @@ int main(int argc, char *argv[]) /// - Do not call GetDataDir(true) before this step finishes if (!fs::is_directory(GetDataDir(false))) { - QMessageBox::critical(0, QObject::tr(PACKAGE_NAME), - QObject::tr("Error: Specified data directory \"%1\" does not exist.").arg(QString::fromStdString(gArgs.GetArg("-datadir", "")))); + QMessageBox::critical(nullptr, QObject::tr(PACKAGE_NAME), + QObject::tr("Error: Specified data directory \"%1\" does not exist.").arg(QString::fromStdString(gArgs.GetArg("-datadir", "")))); return EXIT_FAILURE; } if (!node->readConfigFiles(error)) { - QMessageBox::critical(0, QObject::tr(PACKAGE_NAME), + QMessageBox::critical(nullptr, QObject::tr(PACKAGE_NAME), QObject::tr("Error: Cannot parse configuration file: %1.").arg(QString::fromStdString(error))); return EXIT_FAILURE; } @@ -652,7 +516,7 @@ int main(int argc, char *argv[]) try { node->selectParams(gArgs.GetChainName()); } catch(std::exception &e) { - QMessageBox::critical(0, QObject::tr(PACKAGE_NAME), QObject::tr("Error: %1").arg(e.what())); + QMessageBox::critical(nullptr, QObject::tr(PACKAGE_NAME), QObject::tr("Error: %1").arg(e.what())); return EXIT_FAILURE; } #ifdef ENABLE_WALLET @@ -706,7 +570,7 @@ int main(int argc, char *argv[]) // Perform base initialization before spinning up initialization/shutdown thread // This is acceptable because this function only contains steps that are quick to execute, // so the GUI thread won't be held up. - if (node->baseInitialize()) { + if (app.baseInitialize()) { app.requestInitialize(); #if defined(Q_OS_WIN) WinShutdownMonitor::registerShutdownBlockReason(QObject::tr("%1 didn't yet exit safely...").arg(QObject::tr(PACKAGE_NAME)), (HWND)app.getMainWinId()); diff --git a/src/qt/bitcoin.h b/src/qt/bitcoin.h new file mode 100644 index 0000000000..370712d953 --- /dev/null +++ b/src/qt/bitcoin.h @@ -0,0 +1,124 @@ +// Copyright (c) 2011-2016 The Bitcoin Core developers +// Distributed under the MIT software license, see the accompanying +// file COPYING or http://www.opensource.org/licenses/mit-license.php. + +#ifndef BITCOIN_QT_BITCOIN_H +#define BITCOIN_QT_BITCOIN_H + +#if defined(HAVE_CONFIG_H) +#include <config/bitcoin-config.h> +#endif + +#include <QApplication> +#include <memory> +#include <vector> + +class BitcoinGUI; +class ClientModel; +class NetworkStyle; +class OptionsModel; +class PaymentServer; +class PlatformStyle; +class WalletController; +class WalletModel; + +namespace interfaces { +class Handler; +class Node; +} // namespace interfaces + +/** Class encapsulating Bitcoin Core startup and shutdown. + * Allows running startup and shutdown in a different thread from the UI thread. + */ +class BitcoinCore: public QObject +{ + Q_OBJECT +public: + explicit BitcoinCore(interfaces::Node& node); + +public Q_SLOTS: + void initialize(); + void shutdown(); + +Q_SIGNALS: + void initializeResult(bool success); + void shutdownResult(); + void runawayException(const QString &message); + +private: + /// Pass fatal exception message to UI thread + void handleRunawayException(const std::exception *e); + + interfaces::Node& m_node; +}; + +/** Main Bitcoin application object */ +class BitcoinApplication: public QApplication +{ + Q_OBJECT +public: + explicit BitcoinApplication(interfaces::Node& node, int &argc, char **argv); + ~BitcoinApplication(); + +#ifdef ENABLE_WALLET + /// Create payment server + void createPaymentServer(); +#endif + /// parameter interaction/setup based on rules + void parameterSetup(); + /// Create options model + void createOptionsModel(bool resetSettings); + /// Create main window + void createWindow(const NetworkStyle *networkStyle); + /// Create splash screen + void createSplashScreen(const NetworkStyle *networkStyle); + /// Basic initialization, before starting initialization/shutdown thread. Return true on success. + bool baseInitialize(); + + /// Request core initialization + void requestInitialize(); + /// Request core shutdown + void requestShutdown(); + + /// Get process return value + int getReturnValue() const { return returnValue; } + + /// Get window identifier of QMainWindow (BitcoinGUI) + WId getMainWinId() const; + + /// Setup platform style + void setupPlatformStyle(); + +public Q_SLOTS: + void initializeResult(bool success); + void shutdownResult(); + /// Handle runaway exceptions. Shows a message box with the problem and quits the program. + void handleRunawayException(const QString &message); + +Q_SIGNALS: + void requestedInitialize(); + void requestedShutdown(); + void splashFinished(); + void windowShown(BitcoinGUI* window); + +private: + QThread *coreThread; + interfaces::Node& m_node; + OptionsModel *optionsModel; + ClientModel *clientModel; + BitcoinGUI *window; + QTimer *pollShutdownTimer; +#ifdef ENABLE_WALLET + PaymentServer* paymentServer{nullptr}; + WalletController* m_wallet_controller{nullptr}; +#endif + int returnValue; + const PlatformStyle *platformStyle; + std::unique_ptr<QWidget> shutdownWindow; + + void startThread(); +}; + +int GuiMain(int argc, char* argv[]); + +#endif // BITCOIN_QT_BITCOIN_H diff --git a/src/qt/bitcoinamountfield.cpp b/src/qt/bitcoinamountfield.cpp index 558fcf50ba..5854ade655 100644 --- a/src/qt/bitcoinamountfield.cpp +++ b/src/qt/bitcoinamountfield.cpp @@ -60,7 +60,7 @@ public: } } - CAmount value(bool *valid_out=0) const + CAmount value(bool *valid_out=nullptr) const { return parse(text(), valid_out); } @@ -159,7 +159,7 @@ private: * return validity. * @note Must return 0 if !valid. */ - CAmount parse(const QString &text, bool *valid_out=0) const + CAmount parse(const QString &text, bool *valid_out=nullptr) const { CAmount val = 0; bool valid = BitcoinUnits::parse(currentUnit, text, &val); @@ -196,7 +196,7 @@ protected: if (text().isEmpty()) // Allow step-up with empty field return StepUpEnabled; - StepEnabled rv = 0; + StepEnabled rv = StepNone; bool valid = false; CAmount val = value(&valid); if (valid) { @@ -216,7 +216,7 @@ Q_SIGNALS: BitcoinAmountField::BitcoinAmountField(QWidget *parent) : QWidget(parent), - amount(0) + amount(nullptr) { amount = new AmountSpinBox(this); amount->setLocale(QLocale::c()); diff --git a/src/qt/bitcoinamountfield.h b/src/qt/bitcoinamountfield.h index 650481e30d..2db6b65f2c 100644 --- a/src/qt/bitcoinamountfield.h +++ b/src/qt/bitcoinamountfield.h @@ -26,9 +26,9 @@ class BitcoinAmountField: public QWidget Q_PROPERTY(qint64 value READ value WRITE setValue NOTIFY valueChanged USER true) public: - explicit BitcoinAmountField(QWidget *parent = 0); + explicit BitcoinAmountField(QWidget *parent = nullptr); - CAmount value(bool *value=0) const; + CAmount value(bool *value=nullptr) const; void setValue(const CAmount& value); /** If allow empty is set to false the field will be set to the minimum allowed value if left empty. **/ diff --git a/src/qt/bitcoingui.cpp b/src/qt/bitcoingui.cpp index 70255e058a..ba7e8c7daf 100644 --- a/src/qt/bitcoingui.cpp +++ b/src/qt/bitcoingui.cpp @@ -1,4 +1,4 @@ -// Copyright (c) 2011-2018 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,6 +29,7 @@ #include <qt/macdockiconhandler.h> #endif +#include <chain.h> #include <chainparams.h> #include <interfaces/handler.h> #include <interfaces/node.h> @@ -35,6 +37,7 @@ #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,6 +56,7 @@ #include <QStackedWidget> #include <QStatusBar> #include <QStyle> +#include <QSystemTrayIcon> #include <QTimer> #include <QToolBar> #include <QUrlQuery> @@ -72,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())) { @@ -80,22 +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(); - QApplication::setWindowIcon(networkStyle->getTrayAndWindowIcon()); - setWindowIcon(networkStyle->getTrayAndWindowIcon()); - 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) @@ -110,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 @@ -127,7 +127,7 @@ BitcoinGUI::BitcoinGUI(interfaces::Node& node, const PlatformStyle *_platformSty // Create system tray icon and notification if (QSystemTrayIcon::isSystemTrayAvailable()) { - createTrayIcon(networkStyle); + createTrayIcon(); } notificator = new Notificator(QApplication::applicationName(), trayIcon, this); @@ -324,6 +324,7 @@ 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->setStatusTip(tr("Show the list of used sending addresses and labels")); @@ -483,6 +484,7 @@ void BitcoinGUI::createToolBars() toolbar->addWidget(spacer); m_wallet_selector = new QComboBox(); + 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(); @@ -565,27 +567,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); @@ -594,20 +608,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() @@ -637,14 +658,16 @@ void BitcoinGUI::setWalletActionsEnabled(bool enabled) openAction->setEnabled(enabled); } -void BitcoinGUI::createTrayIcon(const NetworkStyle *networkStyle) +void BitcoinGUI::createTrayIcon() { assert(QSystemTrayIcon::isSystemTrayAvailable()); #ifndef Q_OS_MAC - trayIcon = new QSystemTrayIcon(networkStyle->getTrayAndWindowIcon(), this); - QString toolTip = tr("%1 client").arg(tr(PACKAGE_NAME)) + " " + networkStyle->getTitleAddText(); - trayIcon->setToolTip(toolTip); + 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 } @@ -655,16 +678,12 @@ void BitcoinGUI::createTrayIconMenu() if (!trayIcon) return; - trayIconMenu = new QMenu(this); - trayIcon->setContextMenu(trayIconMenu); - + 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 = new QMenu(this); trayIconMenu->setAsDockMenu(); #endif @@ -724,6 +743,7 @@ void BitcoinGUI::aboutClicked() void BitcoinGUI::showDebugWindow() { GUIUtil::bringToFront(rpcConsole); + Q_EMIT consoleShown(rpcConsole); } void BitcoinGUI::showDebugWindowActivateConsole() @@ -898,8 +918,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)); @@ -1193,7 +1212,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)); @@ -1205,6 +1224,23 @@ 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) @@ -1234,25 +1270,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) @@ -1301,8 +1333,8 @@ void BitcoinGUI::unsubscribeFromCoreSignals() } 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.")); diff --git a/src/qt/bitcoingui.h b/src/qt/bitcoingui.h index aeff5dae30..f1b76a6b64 100644 --- a/src/qt/bitcoingui.h +++ b/src/qt/bitcoingui.h @@ -1,4 +1,4 @@ -// Copyright (c) 2011-2018 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. @@ -16,7 +16,6 @@ #include <QLabel> #include <QMainWindow> #include <QMap> -#include <QMenu> #include <QPoint> #include <QSystemTrayIcon> @@ -34,6 +33,7 @@ class PlatformStyle; class RPCConsole; class SendCoinsRecipient; class UnitDisplayStatusBarControl; +class WalletController; class WalletFrame; class WalletModel; class HelpMessageDialog; @@ -47,6 +47,7 @@ class Node; QT_BEGIN_NAMESPACE class QAction; class QComboBox; +class QMenu; class QProgressBar; class QProgressDialog; QT_END_NAMESPACE @@ -67,25 +68,33 @@ class BitcoinGUI : public QMainWindow public: static const std::string DEFAULT_UIPLATFORM; - explicit BitcoinGUI(interfaces::Node& node, const PlatformStyle *platformStyle, const NetworkStyle *networkStyle, QWidget *parent = 0); + explicit BitcoinGUI(interfaces::Node& node, const PlatformStyle *platformStyle, const NetworkStyle *networkStyle, QWidget *parent = nullptr); ~BitcoinGUI(); /** Set the client model. The client model represents the part of the core that communicates with the P2P network, and is wallet-agnostic. */ void setClientModel(ClientModel *clientModel); +#ifdef ENABLE_WALLET + void setWalletController(WalletController* wallet_controller); +#endif #ifdef ENABLE_WALLET /** Set the wallet model. The wallet model represents a bitcoin wallet, and offers access to the list of transactions, address book and sending functionality. */ - bool addWallet(WalletModel *walletModel); - bool removeWallet(WalletModel* walletModel); + void addWallet(WalletModel* walletModel); + void removeWallet(WalletModel* walletModel); void removeAllWallets(); #endif // ENABLE_WALLET bool enableWallet = false; + /** Get the tray icon status. + Some systems have not "system tray" or "notification area" available. + */ + bool hasTrayIcon() const { return trayIcon; } + protected: void changeEvent(QEvent *e); void closeEvent(QCloseEvent *event); @@ -96,6 +105,7 @@ protected: private: interfaces::Node& m_node; + WalletController* m_wallet_controller{nullptr}; std::unique_ptr<interfaces::Handler> m_handler_message_box; std::unique_ptr<interfaces::Handler> m_handler_question; ClientModel* clientModel = nullptr; @@ -141,7 +151,7 @@ private: QComboBox* m_wallet_selector = nullptr; QSystemTrayIcon* trayIcon = nullptr; - QMenu* trayIconMenu = nullptr; + const std::unique_ptr<QMenu> trayIconMenu; Notificator* notificator = nullptr; RPCConsole* rpcConsole = nullptr; HelpMessageDialog* helpMessageDialog = nullptr; @@ -156,6 +166,7 @@ private: int spinnerFrame = 0; const PlatformStyle *platformStyle; + const NetworkStyle* const m_network_style; /** Create the main UI actions. */ void createActions(); @@ -164,7 +175,7 @@ private: /** Create the toolbars */ void createToolBars(); /** Create system tray icon and notification */ - void createTrayIcon(const NetworkStyle *networkStyle); + void createTrayIcon(); /** Create system tray menu (or setup the dock menu) */ void createTrayIconMenu(); @@ -187,6 +198,8 @@ private: Q_SIGNALS: /** Signal raised when a URI was entered or dragged to the GUI */ void receivedURI(const QString &uri); + /** Signal raised when RPC console shown */ + void consoleShown(RPCConsole* console); public Q_SLOTS: /** Set number of connections shown in the UI */ @@ -206,8 +219,8 @@ public Q_SLOTS: void message(const QString &title, const QString &message, unsigned int style, bool *ret = nullptr); #ifdef ENABLE_WALLET - bool setCurrentWallet(const QString& name); - bool setCurrentWalletBySelectorIndex(int index); + void setCurrentWallet(WalletModel* wallet_model); + void setCurrentWalletBySelectorIndex(int index); /** Set the UI status indicators based on the currently selected wallet. */ void updateWalletStatus(); @@ -235,6 +248,7 @@ public Q_SLOTS: private: /** Set the proxy-enabled icon as shown in the UI. */ void updateProxyIcon(); + void updateWindowTitle(); public Q_SLOTS: #ifdef ENABLE_WALLET diff --git a/src/qt/clientmodel.cpp b/src/qt/clientmodel.cpp index 217326f818..30d9e977b8 100644 --- a/src/qt/clientmodel.cpp +++ b/src/qt/clientmodel.cpp @@ -35,9 +35,9 @@ ClientModel::ClientModel(interfaces::Node& node, OptionsModel *_optionsModel, QO QObject(parent), m_node(node), optionsModel(_optionsModel), - peerTableModel(0), - banTableModel(0), - pollTimer(0) + peerTableModel(nullptr), + banTableModel(nullptr), + pollTimer(nullptr) { cachedBestHeaderHeight = -1; cachedBestHeaderTime = -1; diff --git a/src/qt/clientmodel.h b/src/qt/clientmodel.h index 79e7074cca..95f4521f06 100644 --- a/src/qt/clientmodel.h +++ b/src/qt/clientmodel.h @@ -46,7 +46,7 @@ class ClientModel : public QObject Q_OBJECT public: - explicit ClientModel(interfaces::Node& node, OptionsModel *optionsModel, QObject *parent = 0); + explicit ClientModel(interfaces::Node& node, OptionsModel *optionsModel, QObject *parent = nullptr); ~ClientModel(); interfaces::Node& node() const { return m_node; } diff --git a/src/qt/coincontroldialog.cpp b/src/qt/coincontroldialog.cpp index 77f8bcf901..0d9f1adcd2 100644 --- a/src/qt/coincontroldialog.cpp +++ b/src/qt/coincontroldialog.cpp @@ -49,7 +49,7 @@ bool CCoinControlWidgetItem::operator<(const QTreeWidgetItem &other) const { CoinControlDialog::CoinControlDialog(const PlatformStyle *_platformStyle, QWidget *parent) : QDialog(parent), ui(new Ui::CoinControlDialog), - model(0), + model(nullptr), platformStyle(_platformStyle) { ui->setupUi(this); diff --git a/src/qt/coincontroldialog.h b/src/qt/coincontroldialog.h index 8f15ae4b20..efc06a7656 100644 --- a/src/qt/coincontroldialog.h +++ b/src/qt/coincontroldialog.h @@ -43,7 +43,7 @@ class CoinControlDialog : public QDialog Q_OBJECT public: - explicit CoinControlDialog(const PlatformStyle *platformStyle, QWidget *parent = 0); + explicit CoinControlDialog(const PlatformStyle *platformStyle, QWidget *parent = nullptr); ~CoinControlDialog(); void setModel(WalletModel *model); diff --git a/src/qt/coincontroltreewidget.h b/src/qt/coincontroltreewidget.h index 62645fcdb0..88fc8b704f 100644 --- a/src/qt/coincontroltreewidget.h +++ b/src/qt/coincontroltreewidget.h @@ -13,7 +13,7 @@ class CoinControlTreeWidget : public QTreeWidget Q_OBJECT public: - explicit CoinControlTreeWidget(QWidget *parent = 0); + explicit CoinControlTreeWidget(QWidget *parent = nullptr); protected: virtual void keyPressEvent(QKeyEvent *event); diff --git a/src/qt/csvmodelwriter.cpp b/src/qt/csvmodelwriter.cpp index fe63fed52c..656afb6e87 100644 --- a/src/qt/csvmodelwriter.cpp +++ b/src/qt/csvmodelwriter.cpp @@ -10,7 +10,7 @@ CSVModelWriter::CSVModelWriter(const QString &_filename, QObject *parent) : QObject(parent), - filename(_filename), model(0) + filename(_filename), model(nullptr) { } diff --git a/src/qt/csvmodelwriter.h b/src/qt/csvmodelwriter.h index edea369ad1..e8611bea35 100644 --- a/src/qt/csvmodelwriter.h +++ b/src/qt/csvmodelwriter.h @@ -20,7 +20,7 @@ class CSVModelWriter : public QObject Q_OBJECT public: - explicit CSVModelWriter(const QString &filename, QObject *parent = 0); + explicit CSVModelWriter(const QString &filename, QObject *parent = nullptr); void setModel(const QAbstractItemModel *model); void addColumn(const QString &title, int column, int role=Qt::EditRole); diff --git a/src/qt/editaddressdialog.cpp b/src/qt/editaddressdialog.cpp index 0b0b96b30c..4711412ac4 100644 --- a/src/qt/editaddressdialog.cpp +++ b/src/qt/editaddressdialog.cpp @@ -15,9 +15,9 @@ EditAddressDialog::EditAddressDialog(Mode _mode, QWidget *parent) : QDialog(parent), ui(new Ui::EditAddressDialog), - mapper(0), + mapper(nullptr), mode(_mode), - model(0) + model(nullptr) { ui->setupUi(this); diff --git a/src/qt/editaddressdialog.h b/src/qt/editaddressdialog.h index fd88b45793..4d0e0709be 100644 --- a/src/qt/editaddressdialog.h +++ b/src/qt/editaddressdialog.h @@ -30,7 +30,7 @@ public: EditSendingAddress }; - explicit EditAddressDialog(Mode mode, QWidget *parent = 0); + explicit EditAddressDialog(Mode mode, QWidget *parent = nullptr); ~EditAddressDialog(); void setModel(AddressTableModel *model); diff --git a/src/qt/forms/debugwindow.ui b/src/qt/forms/debugwindow.ui index dca16d6f78..f0b976001e 100644 --- a/src/qt/forms/debugwindow.ui +++ b/src/qt/forms/debugwindow.ui @@ -453,6 +453,9 @@ </item> <item> <widget class="QComboBox" name="WalletSelector"> + <property name="sizeAdjustPolicy"> + <enum>QComboBox::AdjustToContents</enum> + </property> <item> <property name="text"> <string>(none)</string> @@ -896,570 +899,593 @@ <attribute name="title"> <string>&Peers</string> </attribute> - <layout class="QGridLayout" name="gridLayout_2"> - <item row="0" column="0" rowspan="2"> - <layout class="QVBoxLayout" name="verticalLayout_101"> - <property name="spacing"> - <number>0</number> - </property> - <item> - <widget class="QTableView" name="peerWidget"> - <property name="horizontalScrollBarPolicy"> - <enum>Qt::ScrollBarAsNeeded</enum> - </property> - <property name="tabKeyNavigation"> - <bool>false</bool> - </property> - <property name="sortingEnabled"> - <bool>true</bool> - </property> - <attribute name="horizontalHeaderHighlightSections"> - <bool>false</bool> - </attribute> - </widget> - </item> - <item> - <widget class="QLabel" name="banHeading"> - <property name="sizePolicy"> - <sizepolicy hsizetype="Preferred" vsizetype="Minimum"> - <horstretch>0</horstretch> - <verstretch>0</verstretch> - </sizepolicy> - </property> - <property name="minimumSize"> - <size> - <width>300</width> - <height>32</height> - </size> - </property> - <property name="maximumSize"> - <size> - <width>16777215</width> - <height>32</height> - </size> - </property> - <property name="font"> - <font> - <pointsize>12</pointsize> - </font> - </property> - <property name="cursor"> - <cursorShape>IBeamCursor</cursorShape> - </property> - <property name="text"> - <string>Banned peers</string> - </property> - <property name="alignment"> - <set>Qt::AlignBottom|Qt::AlignLeading|Qt::AlignLeft</set> - </property> - <property name="wordWrap"> - <bool>true</bool> - </property> - <property name="textInteractionFlags"> - <set>Qt::NoTextInteraction</set> - </property> - </widget> - </item> - <item> - <widget class="QTableView" name="banlistWidget"> - <property name="sizePolicy"> - <sizepolicy hsizetype="Expanding" vsizetype="Expanding"> - <horstretch>0</horstretch> - <verstretch>0</verstretch> - </sizepolicy> - </property> - <property name="horizontalScrollBarPolicy"> - <enum>Qt::ScrollBarAsNeeded</enum> - </property> - <property name="tabKeyNavigation"> - <bool>false</bool> - </property> - <property name="sortingEnabled"> - <bool>true</bool> - </property> - <attribute name="horizontalHeaderHighlightSections"> - <bool>false</bool> - </attribute> - </widget> - </item> - </layout> - </item> - <item row="0" column="1"> - <widget class="QLabel" name="peerHeading"> - <property name="sizePolicy"> - <sizepolicy hsizetype="Preferred" vsizetype="Minimum"> - <horstretch>0</horstretch> - <verstretch>0</verstretch> - </sizepolicy> - </property> - <property name="minimumSize"> - <size> - <width>300</width> - <height>32</height> - </size> - </property> - <property name="font"> - <font> - <pointsize>10</pointsize> - </font> - </property> - <property name="cursor"> - <cursorShape>IBeamCursor</cursorShape> - </property> - <property name="text"> - <string>Select a peer to view detailed information.</string> - </property> - <property name="alignment"> - <set>Qt::AlignHCenter|Qt::AlignTop</set> - </property> - <property name="wordWrap"> - <bool>true</bool> - </property> - <property name="textInteractionFlags"> - <set>Qt::LinksAccessibleByMouse|Qt::TextSelectableByKeyboard|Qt::TextSelectableByMouse</set> + <layout class="QVBoxLayout" name="verticalLayout_6"> + <item> + <widget class="QSplitter" name="splitter"> + <property name="orientation"> + <enum>Qt::Horizontal</enum> </property> - </widget> - </item> - <item row="1" column="1"> - <widget class="QWidget" name="detailWidget" native="true"> - <property name="minimumSize"> - <size> - <width>300</width> - <height>0</height> - </size> + <property name="childrenCollapsible"> + <bool>false</bool> </property> - <layout class="QGridLayout" name="gridLayout_3"> - <item row="0" column="0"> - <widget class="QLabel" name="label_30"> - <property name="text"> - <string>Whitelisted</string> - </property> - </widget> - </item> - <item row="0" column="2"> - <widget class="QLabel" name="peerWhitelisted"> - <property name="cursor"> - <cursorShape>IBeamCursor</cursorShape> - </property> - <property name="text"> - <string>N/A</string> - </property> - <property name="textFormat"> - <enum>Qt::PlainText</enum> - </property> - <property name="textInteractionFlags"> - <set>Qt::LinksAccessibleByMouse|Qt::TextSelectableByKeyboard|Qt::TextSelectableByMouse</set> - </property> - </widget> - </item> - <item row="1" column="0"> - <widget class="QLabel" name="label_23"> - <property name="text"> - <string>Direction</string> - </property> - </widget> - </item> - <item row="1" column="2"> - <widget class="QLabel" name="peerDirection"> - <property name="cursor"> - <cursorShape>IBeamCursor</cursorShape> - </property> - <property name="text"> - <string>N/A</string> - </property> - <property name="textFormat"> - <enum>Qt::PlainText</enum> - </property> - <property name="textInteractionFlags"> - <set>Qt::LinksAccessibleByMouse|Qt::TextSelectableByKeyboard|Qt::TextSelectableByMouse</set> - </property> - </widget> - </item> - <item row="2" column="0"> - <widget class="QLabel" name="label_21"> - <property name="text"> - <string>Version</string> - </property> - </widget> - </item> - <item row="2" column="2"> - <widget class="QLabel" name="peerVersion"> - <property name="cursor"> - <cursorShape>IBeamCursor</cursorShape> - </property> - <property name="text"> - <string>N/A</string> - </property> - <property name="textFormat"> - <enum>Qt::PlainText</enum> - </property> - <property name="textInteractionFlags"> - <set>Qt::LinksAccessibleByMouse|Qt::TextSelectableByKeyboard|Qt::TextSelectableByMouse</set> - </property> - </widget> - </item> - <item row="3" column="0"> - <widget class="QLabel" name="label_28"> - <property name="text"> - <string>User Agent</string> - </property> - </widget> - </item> - <item row="3" column="2"> - <widget class="QLabel" name="peerSubversion"> - <property name="cursor"> - <cursorShape>IBeamCursor</cursorShape> - </property> - <property name="text"> - <string>N/A</string> - </property> - <property name="textFormat"> - <enum>Qt::PlainText</enum> - </property> - <property name="textInteractionFlags"> - <set>Qt::LinksAccessibleByMouse|Qt::TextSelectableByKeyboard|Qt::TextSelectableByMouse</set> - </property> - </widget> - </item> - <item row="4" column="0"> - <widget class="QLabel" name="label_4"> - <property name="text"> - <string>Services</string> - </property> - </widget> - </item> - <item row="4" column="2"> - <widget class="QLabel" name="peerServices"> - <property name="cursor"> - <cursorShape>IBeamCursor</cursorShape> - </property> - <property name="text"> - <string>N/A</string> - </property> - <property name="textFormat"> - <enum>Qt::PlainText</enum> - </property> - <property name="textInteractionFlags"> - <set>Qt::LinksAccessibleByMouse|Qt::TextSelectableByKeyboard|Qt::TextSelectableByMouse</set> - </property> - </widget> - </item> - <item row="5" column="0"> - <widget class="QLabel" name="label_29"> - <property name="text"> - <string>Starting Block</string> - </property> - </widget> - </item> - <item row="5" column="2"> - <widget class="QLabel" name="peerHeight"> - <property name="cursor"> - <cursorShape>IBeamCursor</cursorShape> - </property> - <property name="text"> - <string>N/A</string> - </property> - <property name="textFormat"> - <enum>Qt::PlainText</enum> - </property> - <property name="textInteractionFlags"> - <set>Qt::LinksAccessibleByMouse|Qt::TextSelectableByKeyboard|Qt::TextSelectableByMouse</set> - </property> - </widget> - </item> - <item row="6" column="0"> - <widget class="QLabel" name="label_27"> - <property name="text"> - <string>Synced Headers</string> - </property> - </widget> - </item> - <item row="6" column="2"> - <widget class="QLabel" name="peerSyncHeight"> - <property name="cursor"> - <cursorShape>IBeamCursor</cursorShape> - </property> - <property name="text"> - <string>N/A</string> - </property> - <property name="textFormat"> - <enum>Qt::PlainText</enum> - </property> - <property name="textInteractionFlags"> - <set>Qt::LinksAccessibleByMouse|Qt::TextSelectableByKeyboard|Qt::TextSelectableByMouse</set> - </property> - </widget> - </item> - <item row="7" column="0"> - <widget class="QLabel" name="label_25"> - <property name="text"> - <string>Synced Blocks</string> - </property> - </widget> - </item> - <item row="7" column="2"> - <widget class="QLabel" name="peerCommonHeight"> - <property name="cursor"> - <cursorShape>IBeamCursor</cursorShape> - </property> - <property name="text"> - <string>N/A</string> - </property> - <property name="textFormat"> - <enum>Qt::PlainText</enum> - </property> - <property name="textInteractionFlags"> - <set>Qt::LinksAccessibleByMouse|Qt::TextSelectableByKeyboard|Qt::TextSelectableByMouse</set> - </property> - </widget> - </item> - <item row="8" column="0"> - <widget class="QLabel" name="label_24"> - <property name="text"> - <string>Ban Score</string> - </property> - </widget> - </item> - <item row="8" column="2"> - <widget class="QLabel" name="peerBanScore"> - <property name="cursor"> - <cursorShape>IBeamCursor</cursorShape> - </property> - <property name="text"> - <string>N/A</string> - </property> - <property name="textFormat"> - <enum>Qt::PlainText</enum> - </property> - <property name="textInteractionFlags"> - <set>Qt::LinksAccessibleByMouse|Qt::TextSelectableByKeyboard|Qt::TextSelectableByMouse</set> - </property> - </widget> - </item> - <item row="9" column="0"> - <widget class="QLabel" name="label_22"> - <property name="text"> - <string>Connection Time</string> - </property> - </widget> - </item> - <item row="9" column="2"> - <widget class="QLabel" name="peerConnTime"> - <property name="cursor"> - <cursorShape>IBeamCursor</cursorShape> - </property> - <property name="text"> - <string>N/A</string> - </property> - <property name="textFormat"> - <enum>Qt::PlainText</enum> - </property> - <property name="textInteractionFlags"> - <set>Qt::LinksAccessibleByMouse|Qt::TextSelectableByKeyboard|Qt::TextSelectableByMouse</set> - </property> - </widget> - </item> - <item row="10" column="0"> - <widget class="QLabel" name="label_15"> - <property name="text"> - <string>Last Send</string> - </property> - </widget> - </item> - <item row="10" column="2"> - <widget class="QLabel" name="peerLastSend"> - <property name="cursor"> - <cursorShape>IBeamCursor</cursorShape> - </property> - <property name="text"> - <string>N/A</string> - </property> - <property name="textFormat"> - <enum>Qt::PlainText</enum> - </property> - <property name="textInteractionFlags"> - <set>Qt::LinksAccessibleByMouse|Qt::TextSelectableByKeyboard|Qt::TextSelectableByMouse</set> - </property> - </widget> - </item> - <item row="11" column="0"> - <widget class="QLabel" name="label_19"> - <property name="text"> - <string>Last Receive</string> - </property> - </widget> - </item> - <item row="11" column="2"> - <widget class="QLabel" name="peerLastRecv"> - <property name="cursor"> - <cursorShape>IBeamCursor</cursorShape> - </property> - <property name="text"> - <string>N/A</string> - </property> - <property name="textFormat"> - <enum>Qt::PlainText</enum> - </property> - <property name="textInteractionFlags"> - <set>Qt::LinksAccessibleByMouse|Qt::TextSelectableByKeyboard|Qt::TextSelectableByMouse</set> - </property> - </widget> - </item> - <item row="12" column="0"> - <widget class="QLabel" name="label_18"> - <property name="text"> - <string>Sent</string> - </property> - </widget> - </item> - <item row="12" column="2"> - <widget class="QLabel" name="peerBytesSent"> - <property name="cursor"> - <cursorShape>IBeamCursor</cursorShape> - </property> - <property name="text"> - <string>N/A</string> - </property> - <property name="textFormat"> - <enum>Qt::PlainText</enum> - </property> - <property name="textInteractionFlags"> - <set>Qt::LinksAccessibleByMouse|Qt::TextSelectableByKeyboard|Qt::TextSelectableByMouse</set> - </property> - </widget> - </item> - <item row="13" column="0"> - <widget class="QLabel" name="label_20"> - <property name="text"> - <string>Received</string> - </property> - </widget> - </item> - <item row="13" column="2"> - <widget class="QLabel" name="peerBytesRecv"> - <property name="cursor"> - <cursorShape>IBeamCursor</cursorShape> - </property> - <property name="text"> - <string>N/A</string> - </property> - <property name="textFormat"> - <enum>Qt::PlainText</enum> - </property> - <property name="textInteractionFlags"> - <set>Qt::LinksAccessibleByMouse|Qt::TextSelectableByKeyboard|Qt::TextSelectableByMouse</set> - </property> - </widget> - </item> - <item row="14" column="0"> - <widget class="QLabel" name="label_26"> - <property name="text"> - <string>Ping Time</string> - </property> - </widget> - </item> - <item row="14" column="2"> - <widget class="QLabel" name="peerPingTime"> - <property name="cursor"> - <cursorShape>IBeamCursor</cursorShape> - </property> - <property name="text"> - <string>N/A</string> - </property> - <property name="textFormat"> - <enum>Qt::PlainText</enum> - </property> - <property name="textInteractionFlags"> - <set>Qt::LinksAccessibleByMouse|Qt::TextSelectableByKeyboard|Qt::TextSelectableByMouse</set> - </property> - </widget> - </item> - <item row="15" column="0"> - <widget class="QLabel" name="peerPingWaitLabel"> - <property name="toolTip"> - <string>The duration of a currently outstanding ping.</string> - </property> - <property name="text"> - <string>Ping Wait</string> - </property> - </widget> - </item> - <item row="15" column="2"> - <widget class="QLabel" name="peerPingWait"> - <property name="cursor"> - <cursorShape>IBeamCursor</cursorShape> - </property> - <property name="text"> - <string>N/A</string> - </property> - <property name="textFormat"> - <enum>Qt::PlainText</enum> - </property> - <property name="textInteractionFlags"> - <set>Qt::LinksAccessibleByMouse|Qt::TextSelectableByKeyboard|Qt::TextSelectableByMouse</set> - </property> - </widget> - </item> - <item row="16" column="0"> - <widget class="QLabel" name="peerMinPingLabel"> - <property name="text"> - <string>Min Ping</string> - </property> - </widget> - </item> - <item row="16" column="2"> - <widget class="QLabel" name="peerMinPing"> - <property name="cursor"> - <cursorShape>IBeamCursor</cursorShape> - </property> - <property name="text"> - <string>N/A</string> - </property> - <property name="textFormat"> - <enum>Qt::PlainText</enum> - </property> - <property name="textInteractionFlags"> - <set>Qt::LinksAccessibleByMouse|Qt::TextSelectableByKeyboard|Qt::TextSelectableByMouse</set> - </property> - </widget> - </item> - <item row="17" column="0"> - <widget class="QLabel" name="label_timeoffset"> - <property name="text"> - <string>Time Offset</string> - </property> - </widget> - </item> - <item row="17" column="2"> - <widget class="QLabel" name="timeoffset"> - <property name="cursor"> - <cursorShape>IBeamCursor</cursorShape> - </property> - <property name="text"> - <string>N/A</string> - </property> - <property name="textFormat"> - <enum>Qt::PlainText</enum> - </property> - <property name="textInteractionFlags"> - <set>Qt::LinksAccessibleByMouse|Qt::TextSelectableByKeyboard|Qt::TextSelectableByMouse</set> - </property> - </widget> - </item> - <item row="18" column="1"> - <spacer name="verticalSpacer_3"> - <property name="orientation"> - <enum>Qt::Vertical</enum> - </property> - <property name="sizeHint" stdset="0"> - <size> - <width>20</width> - <height>40</height> - </size> - </property> - </spacer> - </item> - </layout> + <widget class="QWidget" name="widget_1" native="true"> + <property name="sizePolicy"> + <sizepolicy hsizetype="MinimumExpanding" vsizetype="Preferred"> + <horstretch>1</horstretch> + <verstretch>0</verstretch> + </sizepolicy> + </property> + <property name="minimumSize"> + <size> + <width>400</width> + <height>0</height> + </size> + </property> + <layout class="QVBoxLayout" name="verticalLayout_7"> + <item> + <widget class="QTableView" name="peerWidget"> + <property name="tabKeyNavigation"> + <bool>false</bool> + </property> + <property name="sortingEnabled"> + <bool>true</bool> + </property> + <attribute name="horizontalHeaderHighlightSections"> + <bool>false</bool> + </attribute> + </widget> + </item> + <item> + <widget class="QLabel" name="banHeading"> + <property name="sizePolicy"> + <sizepolicy hsizetype="Preferred" vsizetype="Minimum"> + <horstretch>0</horstretch> + <verstretch>0</verstretch> + </sizepolicy> + </property> + <property name="minimumSize"> + <size> + <width>0</width> + <height>32</height> + </size> + </property> + <property name="maximumSize"> + <size> + <width>16777215</width> + <height>32</height> + </size> + </property> + <property name="font"> + <font> + <pointsize>12</pointsize> + </font> + </property> + <property name="cursor"> + <cursorShape>IBeamCursor</cursorShape> + </property> + <property name="text"> + <string>Banned peers</string> + </property> + <property name="alignment"> + <set>Qt::AlignBottom|Qt::AlignLeading|Qt::AlignLeft</set> + </property> + <property name="wordWrap"> + <bool>true</bool> + </property> + <property name="textInteractionFlags"> + <set>Qt::NoTextInteraction</set> + </property> + </widget> + </item> + <item> + <widget class="QTableView" name="banlistWidget"> + <property name="tabKeyNavigation"> + <bool>false</bool> + </property> + <property name="sortingEnabled"> + <bool>true</bool> + </property> + <attribute name="horizontalHeaderHighlightSections"> + <bool>false</bool> + </attribute> + </widget> + </item> + </layout> + </widget> + <widget class="QWidget" name="widget_2" native="true"> + <property name="sizePolicy"> + <sizepolicy hsizetype="Minimum" vsizetype="Preferred"> + <horstretch>0</horstretch> + <verstretch>0</verstretch> + </sizepolicy> + </property> + <property name="minimumSize"> + <size> + <width>300</width> + <height>0</height> + </size> + </property> + <layout class="QVBoxLayout" name="verticalLayout_8"> + <item> + <widget class="QLabel" name="peerHeading"> + <property name="sizePolicy"> + <sizepolicy hsizetype="Preferred" vsizetype="Minimum"> + <horstretch>0</horstretch> + <verstretch>0</verstretch> + </sizepolicy> + </property> + <property name="minimumSize"> + <size> + <width>0</width> + <height>32</height> + </size> + </property> + <property name="font"> + <font> + <pointsize>10</pointsize> + </font> + </property> + <property name="cursor"> + <cursorShape>IBeamCursor</cursorShape> + </property> + <property name="text"> + <string>Select a peer to view detailed information.</string> + </property> + <property name="alignment"> + <set>Qt::AlignHCenter|Qt::AlignTop</set> + </property> + <property name="wordWrap"> + <bool>true</bool> + </property> + <property name="textInteractionFlags"> + <set>Qt::LinksAccessibleByMouse|Qt::TextSelectableByKeyboard|Qt::TextSelectableByMouse</set> + </property> + </widget> + </item> + <item> + <widget class="QScrollArea" name="scrollArea"> + <property name="widgetResizable"> + <bool>true</bool> + </property> + <widget class="QWidget" name="detailWidget"> + <property name="geometry"> + <rect> + <x>0</x> + <y>0</y> + <width>300</width> + <height>426</height> + </rect> + </property> + <property name="minimumSize"> + <size> + <width>300</width> + <height>0</height> + </size> + </property> + <layout class="QGridLayout" name="gridLayout_2" columnstretch="0,1"> + <item row="0" column="0"> + <widget class="QLabel" name="label_30"> + <property name="text"> + <string>Whitelisted</string> + </property> + </widget> + </item> + <item row="0" column="1"> + <widget class="QLabel" name="peerWhitelisted"> + <property name="cursor"> + <cursorShape>IBeamCursor</cursorShape> + </property> + <property name="text"> + <string>N/A</string> + </property> + <property name="textFormat"> + <enum>Qt::PlainText</enum> + </property> + <property name="textInteractionFlags"> + <set>Qt::LinksAccessibleByMouse|Qt::TextSelectableByKeyboard|Qt::TextSelectableByMouse</set> + </property> + </widget> + </item> + <item row="1" column="0"> + <widget class="QLabel" name="label_23"> + <property name="text"> + <string>Direction</string> + </property> + </widget> + </item> + <item row="1" column="1"> + <widget class="QLabel" name="peerDirection"> + <property name="cursor"> + <cursorShape>IBeamCursor</cursorShape> + </property> + <property name="text"> + <string>N/A</string> + </property> + <property name="textFormat"> + <enum>Qt::PlainText</enum> + </property> + <property name="textInteractionFlags"> + <set>Qt::LinksAccessibleByMouse|Qt::TextSelectableByKeyboard|Qt::TextSelectableByMouse</set> + </property> + </widget> + </item> + <item row="2" column="0"> + <widget class="QLabel" name="label_21"> + <property name="text"> + <string>Version</string> + </property> + </widget> + </item> + <item row="2" column="1"> + <widget class="QLabel" name="peerVersion"> + <property name="cursor"> + <cursorShape>IBeamCursor</cursorShape> + </property> + <property name="text"> + <string>N/A</string> + </property> + <property name="textFormat"> + <enum>Qt::PlainText</enum> + </property> + <property name="textInteractionFlags"> + <set>Qt::LinksAccessibleByMouse|Qt::TextSelectableByKeyboard|Qt::TextSelectableByMouse</set> + </property> + </widget> + </item> + <item row="3" column="0"> + <widget class="QLabel" name="label_28"> + <property name="text"> + <string>User Agent</string> + </property> + </widget> + </item> + <item row="3" column="1"> + <widget class="QLabel" name="peerSubversion"> + <property name="cursor"> + <cursorShape>IBeamCursor</cursorShape> + </property> + <property name="text"> + <string>N/A</string> + </property> + <property name="textFormat"> + <enum>Qt::PlainText</enum> + </property> + <property name="textInteractionFlags"> + <set>Qt::LinksAccessibleByMouse|Qt::TextSelectableByKeyboard|Qt::TextSelectableByMouse</set> + </property> + </widget> + </item> + <item row="4" column="0"> + <widget class="QLabel" name="label_4"> + <property name="text"> + <string>Services</string> + </property> + </widget> + </item> + <item row="4" column="1"> + <widget class="QLabel" name="peerServices"> + <property name="cursor"> + <cursorShape>IBeamCursor</cursorShape> + </property> + <property name="text"> + <string>N/A</string> + </property> + <property name="textFormat"> + <enum>Qt::PlainText</enum> + </property> + <property name="textInteractionFlags"> + <set>Qt::LinksAccessibleByMouse|Qt::TextSelectableByKeyboard|Qt::TextSelectableByMouse</set> + </property> + </widget> + </item> + <item row="5" column="0"> + <widget class="QLabel" name="label_29"> + <property name="text"> + <string>Starting Block</string> + </property> + </widget> + </item> + <item row="5" column="1"> + <widget class="QLabel" name="peerHeight"> + <property name="cursor"> + <cursorShape>IBeamCursor</cursorShape> + </property> + <property name="text"> + <string>N/A</string> + </property> + <property name="textFormat"> + <enum>Qt::PlainText</enum> + </property> + <property name="textInteractionFlags"> + <set>Qt::LinksAccessibleByMouse|Qt::TextSelectableByKeyboard|Qt::TextSelectableByMouse</set> + </property> + </widget> + </item> + <item row="6" column="0"> + <widget class="QLabel" name="label_27"> + <property name="text"> + <string>Synced Headers</string> + </property> + </widget> + </item> + <item row="6" column="1"> + <widget class="QLabel" name="peerSyncHeight"> + <property name="cursor"> + <cursorShape>IBeamCursor</cursorShape> + </property> + <property name="text"> + <string>N/A</string> + </property> + <property name="textFormat"> + <enum>Qt::PlainText</enum> + </property> + <property name="textInteractionFlags"> + <set>Qt::LinksAccessibleByMouse|Qt::TextSelectableByKeyboard|Qt::TextSelectableByMouse</set> + </property> + </widget> + </item> + <item row="7" column="0"> + <widget class="QLabel" name="label_25"> + <property name="text"> + <string>Synced Blocks</string> + </property> + </widget> + </item> + <item row="7" column="1"> + <widget class="QLabel" name="peerCommonHeight"> + <property name="cursor"> + <cursorShape>IBeamCursor</cursorShape> + </property> + <property name="text"> + <string>N/A</string> + </property> + <property name="textFormat"> + <enum>Qt::PlainText</enum> + </property> + <property name="textInteractionFlags"> + <set>Qt::LinksAccessibleByMouse|Qt::TextSelectableByKeyboard|Qt::TextSelectableByMouse</set> + </property> + </widget> + </item> + <item row="8" column="0"> + <widget class="QLabel" name="label_24"> + <property name="text"> + <string>Ban Score</string> + </property> + </widget> + </item> + <item row="8" column="1"> + <widget class="QLabel" name="peerBanScore"> + <property name="cursor"> + <cursorShape>IBeamCursor</cursorShape> + </property> + <property name="text"> + <string>N/A</string> + </property> + <property name="textFormat"> + <enum>Qt::PlainText</enum> + </property> + <property name="textInteractionFlags"> + <set>Qt::LinksAccessibleByMouse|Qt::TextSelectableByKeyboard|Qt::TextSelectableByMouse</set> + </property> + </widget> + </item> + <item row="9" column="0"> + <widget class="QLabel" name="label_22"> + <property name="text"> + <string>Connection Time</string> + </property> + </widget> + </item> + <item row="9" column="1"> + <widget class="QLabel" name="peerConnTime"> + <property name="cursor"> + <cursorShape>IBeamCursor</cursorShape> + </property> + <property name="text"> + <string>N/A</string> + </property> + <property name="textFormat"> + <enum>Qt::PlainText</enum> + </property> + <property name="textInteractionFlags"> + <set>Qt::LinksAccessibleByMouse|Qt::TextSelectableByKeyboard|Qt::TextSelectableByMouse</set> + </property> + </widget> + </item> + <item row="10" column="0"> + <widget class="QLabel" name="label_15"> + <property name="text"> + <string>Last Send</string> + </property> + </widget> + </item> + <item row="10" column="1"> + <widget class="QLabel" name="peerLastSend"> + <property name="cursor"> + <cursorShape>IBeamCursor</cursorShape> + </property> + <property name="text"> + <string>N/A</string> + </property> + <property name="textFormat"> + <enum>Qt::PlainText</enum> + </property> + <property name="textInteractionFlags"> + <set>Qt::LinksAccessibleByMouse|Qt::TextSelectableByKeyboard|Qt::TextSelectableByMouse</set> + </property> + </widget> + </item> + <item row="11" column="0"> + <widget class="QLabel" name="label_19"> + <property name="text"> + <string>Last Receive</string> + </property> + </widget> + </item> + <item row="11" column="1"> + <widget class="QLabel" name="peerLastRecv"> + <property name="cursor"> + <cursorShape>IBeamCursor</cursorShape> + </property> + <property name="text"> + <string>N/A</string> + </property> + <property name="textFormat"> + <enum>Qt::PlainText</enum> + </property> + <property name="textInteractionFlags"> + <set>Qt::LinksAccessibleByMouse|Qt::TextSelectableByKeyboard|Qt::TextSelectableByMouse</set> + </property> + </widget> + </item> + <item row="12" column="0"> + <widget class="QLabel" name="label_18"> + <property name="text"> + <string>Sent</string> + </property> + </widget> + </item> + <item row="12" column="1"> + <widget class="QLabel" name="peerBytesSent"> + <property name="cursor"> + <cursorShape>IBeamCursor</cursorShape> + </property> + <property name="text"> + <string>N/A</string> + </property> + <property name="textFormat"> + <enum>Qt::PlainText</enum> + </property> + <property name="textInteractionFlags"> + <set>Qt::LinksAccessibleByMouse|Qt::TextSelectableByKeyboard|Qt::TextSelectableByMouse</set> + </property> + </widget> + </item> + <item row="13" column="0"> + <widget class="QLabel" name="label_20"> + <property name="text"> + <string>Received</string> + </property> + </widget> + </item> + <item row="13" column="1"> + <widget class="QLabel" name="peerBytesRecv"> + <property name="cursor"> + <cursorShape>IBeamCursor</cursorShape> + </property> + <property name="text"> + <string>N/A</string> + </property> + <property name="textFormat"> + <enum>Qt::PlainText</enum> + </property> + <property name="textInteractionFlags"> + <set>Qt::LinksAccessibleByMouse|Qt::TextSelectableByKeyboard|Qt::TextSelectableByMouse</set> + </property> + </widget> + </item> + <item row="14" column="0"> + <widget class="QLabel" name="label_26"> + <property name="text"> + <string>Ping Time</string> + </property> + </widget> + </item> + <item row="14" column="1"> + <widget class="QLabel" name="peerPingTime"> + <property name="cursor"> + <cursorShape>IBeamCursor</cursorShape> + </property> + <property name="text"> + <string>N/A</string> + </property> + <property name="textFormat"> + <enum>Qt::PlainText</enum> + </property> + <property name="textInteractionFlags"> + <set>Qt::LinksAccessibleByMouse|Qt::TextSelectableByKeyboard|Qt::TextSelectableByMouse</set> + </property> + </widget> + </item> + <item row="15" column="0"> + <widget class="QLabel" name="peerPingWaitLabel"> + <property name="toolTip"> + <string>The duration of a currently outstanding ping.</string> + </property> + <property name="text"> + <string>Ping Wait</string> + </property> + </widget> + </item> + <item row="15" column="1"> + <widget class="QLabel" name="peerPingWait"> + <property name="cursor"> + <cursorShape>IBeamCursor</cursorShape> + </property> + <property name="text"> + <string>N/A</string> + </property> + <property name="textFormat"> + <enum>Qt::PlainText</enum> + </property> + <property name="textInteractionFlags"> + <set>Qt::LinksAccessibleByMouse|Qt::TextSelectableByKeyboard|Qt::TextSelectableByMouse</set> + </property> + </widget> + </item> + <item row="16" column="0"> + <widget class="QLabel" name="peerMinPingLabel"> + <property name="text"> + <string>Min Ping</string> + </property> + </widget> + </item> + <item row="16" column="1"> + <widget class="QLabel" name="peerMinPing"> + <property name="cursor"> + <cursorShape>IBeamCursor</cursorShape> + </property> + <property name="text"> + <string>N/A</string> + </property> + <property name="textFormat"> + <enum>Qt::PlainText</enum> + </property> + <property name="textInteractionFlags"> + <set>Qt::LinksAccessibleByMouse|Qt::TextSelectableByKeyboard|Qt::TextSelectableByMouse</set> + </property> + </widget> + </item> + <item row="17" column="0"> + <widget class="QLabel" name="label_timeoffset"> + <property name="text"> + <string>Time Offset</string> + </property> + </widget> + </item> + <item row="17" column="1"> + <widget class="QLabel" name="timeoffset"> + <property name="cursor"> + <cursorShape>IBeamCursor</cursorShape> + </property> + <property name="text"> + <string>N/A</string> + </property> + <property name="textFormat"> + <enum>Qt::PlainText</enum> + </property> + <property name="textInteractionFlags"> + <set>Qt::LinksAccessibleByMouse|Qt::TextSelectableByKeyboard|Qt::TextSelectableByMouse</set> + </property> + </widget> + </item> + </layout> + </widget> + </widget> + </item> + </layout> + </widget> </widget> </item> </layout> diff --git a/src/qt/guiconstants.h b/src/qt/guiconstants.h index 04b03a5435..4d6006c582 100644 --- a/src/qt/guiconstants.h +++ b/src/qt/guiconstants.h @@ -50,5 +50,6 @@ static const int MAX_URI_LENGTH = 255; #define QAPP_ORG_DOMAIN "bitcoin.org" #define QAPP_APP_NAME_DEFAULT "Bitcoin-Qt" #define QAPP_APP_NAME_TESTNET "Bitcoin-Qt-testnet" +#define QAPP_APP_NAME_REGTEST "Bitcoin-Qt-regtest" #endif // BITCOIN_QT_GUICONSTANTS_H diff --git a/src/qt/guiutil.cpp b/src/qt/guiutil.cpp index 2fc166b0c5..b84c07d51a 100644 --- a/src/qt/guiutil.cpp +++ b/src/qt/guiutil.cpp @@ -48,13 +48,15 @@ #include <QFileDialog> #include <QFont> #include <QFontDatabase> +#include <QFontMetrics> #include <QKeyEvent> #include <QLineEdit> +#include <QMouseEvent> +#include <QProgressDialog> #include <QSettings> #include <QTextDocument> // for Qt::mightBeRichText #include <QThread> #include <QUrlQuery> -#include <QMouseEvent> #if defined(Q_OS_MAC) #pragma GCC diagnostic push @@ -933,4 +935,16 @@ bool ItemDelegate::eventFilter(QObject *object, QEvent *event) return QItemDelegate::eventFilter(object, event); } +void PolishProgressDialog(QProgressDialog* dialog) +{ +#ifdef Q_OS_MAC + // Workaround for macOS-only Qt bug; see: QTBUG-65750, QTBUG-70357. + const int margin = dialog->fontMetrics().width("X"); + dialog->resize(dialog->width() + 2 * margin, dialog->height()); + dialog->show(); +#else + Q_UNUSED(dialog); +#endif +} + } // namespace GUIUtil diff --git a/src/qt/guiutil.h b/src/qt/guiutil.h index f1d0aa48ef..cbec73a882 100644 --- a/src/qt/guiutil.h +++ b/src/qt/guiutil.h @@ -31,6 +31,7 @@ class QAbstractItemView; class QDateTime; class QFont; class QLineEdit; +class QProgressDialog; class QUrl; class QWidget; QT_END_NAMESPACE @@ -133,7 +134,7 @@ namespace GUIUtil Q_OBJECT public: - explicit ToolTipToRichTextFilter(int size_threshold, QObject *parent = 0); + explicit ToolTipToRichTextFilter(int size_threshold, QObject *parent = nullptr); protected: bool eventFilter(QObject *obj, QEvent *evt); @@ -248,6 +249,9 @@ namespace GUIUtil private: bool eventFilter(QObject *object, QEvent *event); }; + + // Fix known bugs in QProgressDialog class. + void PolishProgressDialog(QProgressDialog* dialog); } // namespace GUIUtil #endif // BITCOIN_QT_GUIUTIL_H diff --git a/src/qt/intro.cpp b/src/qt/intro.cpp index 0b61b05318..69972fce3b 100644 --- a/src/qt/intro.cpp +++ b/src/qt/intro.cpp @@ -22,10 +22,6 @@ #include <cmath> static const uint64_t GB_BYTES = 1000000000LL; -/* Minimum free space (in GB) needed for data directory */ -constexpr uint64_t BLOCK_CHAIN_SIZE = 220; -/* Minimum free space (in GB) needed for data directory when pruned; Does not include prune target */ -static const uint64_t CHAIN_STATE_SIZE = 3; /* Total required space (in GB) depending on user choice (prune, not prune) */ static uint64_t requiredSpace; @@ -114,11 +110,13 @@ void FreespaceChecker::check() } -Intro::Intro(QWidget *parent) : +Intro::Intro(QWidget *parent, uint64_t blockchain_size, uint64_t chain_state_size) : QDialog(parent), ui(new Ui::Intro), - thread(0), - signalled(false) + thread(nullptr), + signalled(false), + m_blockchain_size(blockchain_size), + m_chain_state_size(chain_state_size) { ui->setupUi(this); ui->welcomeLabel->setText(ui->welcomeLabel->text().arg(tr(PACKAGE_NAME))); @@ -126,14 +124,14 @@ Intro::Intro(QWidget *parent) : ui->lblExplanation1->setText(ui->lblExplanation1->text() .arg(tr(PACKAGE_NAME)) - .arg(BLOCK_CHAIN_SIZE) + .arg(m_blockchain_size) .arg(2009) .arg(tr("Bitcoin")) ); ui->lblExplanation2->setText(ui->lblExplanation2->text().arg(tr(PACKAGE_NAME))); uint64_t pruneTarget = std::max<int64_t>(0, gArgs.GetArg("-prune", 0)); - requiredSpace = BLOCK_CHAIN_SIZE; + requiredSpace = m_blockchain_size; QString storageRequiresMsg = tr("At least %1 GB of data will be stored in this directory, and it will grow over time."); if (pruneTarget) { uint64_t prunedGBs = std::ceil(pruneTarget * 1024 * 1024.0 / GB_BYTES); @@ -145,7 +143,7 @@ Intro::Intro(QWidget *parent) : } else { ui->lblExplanation3->setVisible(false); } - requiredSpace += CHAIN_STATE_SIZE; + requiredSpace += m_chain_state_size; ui->sizeWarningLabel->setText( tr("%1 will download and store a copy of the Bitcoin block chain.").arg(tr(PACKAGE_NAME)) + " " + storageRequiresMsg.arg(requiredSpace) + " " + @@ -158,7 +156,7 @@ Intro::~Intro() { delete ui; /* Ensure thread is finished before it is deleted */ - Q_EMIT stopThread(); + thread->quit(); thread->wait(); } @@ -201,8 +199,15 @@ bool Intro::pickDataDirectory(interfaces::Node& node) if(!fs::exists(GUIUtil::qstringToBoostPath(dataDir)) || gArgs.GetBoolArg("-choosedatadir", DEFAULT_CHOOSE_DATADIR) || settings.value("fReset", false).toBool() || gArgs.GetBoolArg("-resetguisettings", false)) { + /* Use selectParams here to guarantee Params() can be used by node interface */ + try { + node.selectParams(gArgs.GetChainName()); + } catch (const std::exception&) { + return false; + } + /* If current default data directory does not exist, let the user choose one */ - Intro intro; + Intro intro(0, node.getAssumedBlockchainSize(), node.getAssumedChainStateSize()); intro.setDataDirectory(dataDir); intro.setWindowIcon(QIcon(":icons/bitcoin")); @@ -221,7 +226,7 @@ bool Intro::pickDataDirectory(interfaces::Node& node) } break; } catch (const fs::filesystem_error&) { - QMessageBox::critical(0, tr(PACKAGE_NAME), + QMessageBox::critical(nullptr, tr(PACKAGE_NAME), tr("Error: Specified data directory \"%1\" cannot be created.").arg(dataDir)); /* fall through, back to choosing screen */ } @@ -281,7 +286,7 @@ void Intro::on_dataDirectory_textChanged(const QString &dataDirStr) void Intro::on_ellipsisButton_clicked() { - QString dir = QDir::toNativeSeparators(QFileDialog::getExistingDirectory(0, "Choose data directory", ui->dataDirectory->text())); + QString dir = QDir::toNativeSeparators(QFileDialog::getExistingDirectory(nullptr, "Choose data directory", ui->dataDirectory->text())); if(!dir.isEmpty()) ui->dataDirectory->setText(dir); } @@ -306,8 +311,7 @@ void Intro::startThread() connect(executor, &FreespaceChecker::reply, this, &Intro::setStatus); connect(this, &Intro::requestCheck, executor, &FreespaceChecker::check); /* make sure executor object is deleted in its own thread */ - connect(this, &Intro::stopThread, executor, &QObject::deleteLater); - connect(this, &Intro::stopThread, thread, &QThread::quit); + connect(thread, &QThread::finished, executor, &QObject::deleteLater); thread->start(); } diff --git a/src/qt/intro.h b/src/qt/intro.h index 2b3da963e2..b537c94f7d 100644 --- a/src/qt/intro.h +++ b/src/qt/intro.h @@ -30,7 +30,8 @@ class Intro : public QDialog Q_OBJECT public: - explicit Intro(QWidget *parent = 0); + explicit Intro(QWidget *parent = nullptr, + uint64_t blockchain_size = 0, uint64_t chain_state_size = 0); ~Intro(); QString getDataDirectory(); @@ -54,7 +55,6 @@ public: Q_SIGNALS: void requestCheck(); - void stopThread(); public Q_SLOTS: void setStatus(int status, const QString &message, quint64 bytesAvailable); @@ -71,6 +71,8 @@ private: QMutex mutex; bool signalled; QString pathToCheck; + uint64_t m_blockchain_size; + uint64_t m_chain_state_size; void startThread(); void checkPath(const QString &dataDir); diff --git a/src/qt/main.cpp b/src/qt/main.cpp new file mode 100644 index 0000000000..6a3c2249d1 --- /dev/null +++ b/src/qt/main.cpp @@ -0,0 +1,17 @@ +// Copyright (c) 2018 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 <qt/bitcoin.h> + +#include <QCoreApplication> + +#include <functional> +#include <string> + +/** Translate string to current locale using Qt. */ +extern const std::function<std::string(const char*)> G_TRANSLATION_FUN = [](const char* psz) { + return QCoreApplication::translate("bitcoin-core", psz).toStdString(); +}; + +int main(int argc, char* argv[]) { return GuiMain(argc, argv); } diff --git a/src/qt/networkstyle.cpp b/src/qt/networkstyle.cpp index b134a139b0..f0c860e669 100644 --- a/src/qt/networkstyle.cpp +++ b/src/qt/networkstyle.cpp @@ -17,7 +17,7 @@ static const struct { } network_styles[] = { {"main", QAPP_APP_NAME_DEFAULT, 0, 0, ""}, {"test", QAPP_APP_NAME_TESTNET, 70, 30, QT_TRANSLATE_NOOP("SplashScreen", "[testnet]")}, - {"regtest", QAPP_APP_NAME_TESTNET, 160, 30, "[regtest]"} + {"regtest", QAPP_APP_NAME_REGTEST, 160, 30, "[regtest]"} }; static const unsigned network_styles_count = sizeof(network_styles)/sizeof(*network_styles); @@ -88,5 +88,5 @@ const NetworkStyle *NetworkStyle::instantiate(const QString &networkId) network_styles[x].titleAddText); } } - return 0; + return nullptr; } diff --git a/src/qt/notificator.cpp b/src/qt/notificator.cpp index 94505043dc..4b91c19761 100644 --- a/src/qt/notificator.cpp +++ b/src/qt/notificator.cpp @@ -39,7 +39,7 @@ Notificator::Notificator(const QString &_programName, QSystemTrayIcon *_trayIcon mode(None), trayIcon(_trayIcon) #ifdef USE_DBUS - ,interface(0) + ,interface(nullptr) #endif { if(_trayIcon && _trayIcon->supportsMessages()) @@ -154,14 +154,14 @@ QVariant FreedesktopImage::toVariant(const QImage &img) void Notificator::notifyDBus(Class cls, const QString &title, const QString &text, const QIcon &icon, int millisTimeout) { - Q_UNUSED(cls); - // Arguments for DBus call: + // https://developer.gnome.org/notification-spec/ + // Arguments for DBus "Notify" call: QList<QVariant> args; // Program Name: args.append(programName); - // Unique ID of this notification type: + // Replaces ID; A value of 0 means that this notification won't replace any existing notifications: args.append(0U); // Application Icon, empty string @@ -209,9 +209,8 @@ void Notificator::notifyDBus(Class cls, const QString &title, const QString &tex } #endif -void Notificator::notifySystray(Class cls, const QString &title, const QString &text, const QIcon &icon, int millisTimeout) +void Notificator::notifySystray(Class cls, const QString &title, const QString &text, int millisTimeout) { - Q_UNUSED(icon); QSystemTrayIcon::MessageIcon sicon = QSystemTrayIcon::NoIcon; switch(cls) // Set icon based on class { @@ -222,13 +221,12 @@ void Notificator::notifySystray(Class cls, const QString &title, const QString & trayIcon->showMessage(title, text, sicon, millisTimeout); } -// Based on Qt's tray icon implementation #ifdef Q_OS_MAC -void Notificator::notifyMacUserNotificationCenter(Class cls, const QString &title, const QString &text, const QIcon &icon) { +void Notificator::notifyMacUserNotificationCenter(const QString &title, const QString &text) +{ // icon is not supported by the user notification center yet. OSX will use the app icon. MacNotificationHandler::instance()->showNotification(title, text); } - #endif void Notificator::notify(Class cls, const QString &title, const QString &text, const QIcon &icon, int millisTimeout) @@ -241,11 +239,11 @@ void Notificator::notify(Class cls, const QString &title, const QString &text, c break; #endif case QSystemTray: - notifySystray(cls, title, text, icon, millisTimeout); + notifySystray(cls, title, text, millisTimeout); break; #ifdef Q_OS_MAC case UserNotificationCenter: - notifyMacUserNotificationCenter(cls, title, text, icon); + notifyMacUserNotificationCenter(title, text); break; #endif default: diff --git a/src/qt/notificator.h b/src/qt/notificator.h index 10b7b6c50a..7d80b43e43 100644 --- a/src/qt/notificator.h +++ b/src/qt/notificator.h @@ -57,7 +57,7 @@ private: enum Mode { None, /**< Ignore informational notifications, and show a modal pop-up dialog for Critical notifications. */ Freedesktop, /**< Use DBus org.freedesktop.Notifications */ - QSystemTray, /**< Use QSystemTray::showMessage */ + QSystemTray, /**< Use QSystemTrayIcon::showMessage() */ UserNotificationCenter /**< Use the 10.8+ User Notification Center (Mac only) */ }; QString programName; @@ -68,9 +68,9 @@ private: void notifyDBus(Class cls, const QString &title, const QString &text, const QIcon &icon, int millisTimeout); #endif - void notifySystray(Class cls, const QString &title, const QString &text, const QIcon &icon, int millisTimeout); + void notifySystray(Class cls, const QString &title, const QString &text, int millisTimeout); #ifdef Q_OS_MAC - void notifyMacUserNotificationCenter(Class cls, const QString &title, const QString &text, const QIcon &icon); + void notifyMacUserNotificationCenter(const QString &title, const QString &text); #endif }; diff --git a/src/qt/optionsdialog.cpp b/src/qt/optionsdialog.cpp index c9871f6c66..27cec06d4b 100644 --- a/src/qt/optionsdialog.cpp +++ b/src/qt/optionsdialog.cpp @@ -29,8 +29,8 @@ OptionsDialog::OptionsDialog(QWidget *parent, bool enableWallet) : QDialog(parent), ui(new Ui::OptionsDialog), - model(0), - mapper(0) + model(nullptr), + mapper(nullptr) { ui->setupUi(this); diff --git a/src/qt/optionsmodel.h b/src/qt/optionsmodel.h index 2421734527..1af3a72b92 100644 --- a/src/qt/optionsmodel.h +++ b/src/qt/optionsmodel.h @@ -31,7 +31,7 @@ class OptionsModel : public QAbstractListModel Q_OBJECT public: - explicit OptionsModel(interfaces::Node& node, QObject *parent = 0, bool resetSettings = false); + explicit OptionsModel(interfaces::Node& node, QObject *parent = nullptr, bool resetSettings = false); enum OptionID { StartAtStartup, // bool diff --git a/src/qt/overviewpage.cpp b/src/qt/overviewpage.cpp index bec79335e7..d8e48f350a 100644 --- a/src/qt/overviewpage.cpp +++ b/src/qt/overviewpage.cpp @@ -113,8 +113,8 @@ public: OverviewPage::OverviewPage(const PlatformStyle *platformStyle, QWidget *parent) : QWidget(parent), ui(new Ui::OverviewPage), - clientModel(0), - walletModel(0), + clientModel(nullptr), + walletModel(nullptr), txdelegate(new TxViewDelegate(platformStyle, this)) { ui->setupUi(this); diff --git a/src/qt/overviewpage.h b/src/qt/overviewpage.h index 75100ae6f7..00ba7ad4ce 100644 --- a/src/qt/overviewpage.h +++ b/src/qt/overviewpage.h @@ -30,7 +30,7 @@ class OverviewPage : public QWidget Q_OBJECT public: - explicit OverviewPage(const PlatformStyle *platformStyle, QWidget *parent = 0); + explicit OverviewPage(const PlatformStyle *platformStyle, QWidget *parent = nullptr); ~OverviewPage(); void setClientModel(ClientModel *clientModel); diff --git a/src/qt/paymentserver.cpp b/src/qt/paymentserver.cpp index 8148986b51..b1ec90ad36 100644 --- a/src/qt/paymentserver.cpp +++ b/src/qt/paymentserver.cpp @@ -194,10 +194,10 @@ bool PaymentServer::ipcSendCommandLine() PaymentServer::PaymentServer(QObject* parent, bool startLocalServer) : QObject(parent), saveURIs(true), - uriServer(0), - optionsModel(0) + uriServer(nullptr), + optionsModel(nullptr) #ifdef ENABLE_BIP70 - ,netManager(0) + ,netManager(nullptr) #endif { #ifdef ENABLE_BIP70 @@ -223,7 +223,7 @@ PaymentServer::PaymentServer(QObject* parent, bool startLocalServer) : if (!uriServer->listen(name)) { // constructor is called early in init, so don't use "Q_EMIT message()" here - QMessageBox::critical(0, tr("Payment request error"), + QMessageBox::critical(nullptr, tr("Payment request error"), tr("Cannot start bitcoin: click-to-pay handler")); } else { diff --git a/src/qt/peertablemodel.cpp b/src/qt/peertablemodel.cpp index 8cfedca57f..496aeebf7d 100644 --- a/src/qt/peertablemodel.cpp +++ b/src/qt/peertablemodel.cpp @@ -49,8 +49,8 @@ class PeerTablePriv public: /** Local cache of peer information */ QList<CNodeCombinedStats> cachedNodeStats; - /** Column to sort nodes by */ - int sortColumn; + /** Column to sort nodes by (default to unsorted) */ + int sortColumn{-1}; /** Order (ascending or descending) to sort nodes by */ Qt::SortOrder sortOrder; /** Index of rows by node ID */ @@ -96,7 +96,7 @@ public: if (idx >= 0 && idx < cachedNodeStats.size()) return &cachedNodeStats[idx]; - return 0; + return nullptr; } }; @@ -104,12 +104,10 @@ PeerTableModel::PeerTableModel(interfaces::Node& node, ClientModel *parent) : QAbstractTableModel(parent), m_node(node), clientModel(parent), - timer(0) + timer(nullptr) { columns << tr("NodeId") << tr("Node/Service") << tr("Ping") << tr("Sent") << tr("Received") << tr("User Agent"); priv.reset(new PeerTablePriv()); - // default to unsorted - priv->sortColumn = -1; // set up timer for auto refresh timer = new QTimer(this); @@ -199,8 +197,7 @@ QVariant PeerTableModel::headerData(int section, Qt::Orientation orientation, in Qt::ItemFlags PeerTableModel::flags(const QModelIndex &index) const { - if(!index.isValid()) - return 0; + if (!index.isValid()) return Qt::NoItemFlags; Qt::ItemFlags retval = Qt::ItemIsSelectable | Qt::ItemIsEnabled; return retval; diff --git a/src/qt/peertablemodel.h b/src/qt/peertablemodel.h index 738a06496f..b3f5dd7dbe 100644 --- a/src/qt/peertablemodel.h +++ b/src/qt/peertablemodel.h @@ -51,7 +51,7 @@ class PeerTableModel : public QAbstractTableModel Q_OBJECT public: - explicit PeerTableModel(interfaces::Node& node, ClientModel *parent = 0); + explicit PeerTableModel(interfaces::Node& node, ClientModel *parent = nullptr); ~PeerTableModel(); const CNodeCombinedStats *getNodeStats(int idx); int getRowByNodeId(NodeId nodeid); diff --git a/src/qt/platformstyle.cpp b/src/qt/platformstyle.cpp index 56e0830cdc..d537d759de 100644 --- a/src/qt/platformstyle.cpp +++ b/src/qt/platformstyle.cpp @@ -139,6 +139,6 @@ const PlatformStyle *PlatformStyle::instantiate(const QString &platformId) platform_styles[x].useExtraSpacing); } } - return 0; + return nullptr; } diff --git a/src/qt/qvalidatedlineedit.cpp b/src/qt/qvalidatedlineedit.cpp index 85c5a58a84..aa936d6b7c 100644 --- a/src/qt/qvalidatedlineedit.cpp +++ b/src/qt/qvalidatedlineedit.cpp @@ -10,7 +10,7 @@ QValidatedLineEdit::QValidatedLineEdit(QWidget *parent) : QLineEdit(parent), valid(true), - checkValidator(0) + checkValidator(nullptr) { connect(this, &QValidatedLineEdit::textChanged, this, &QValidatedLineEdit::markValid); } diff --git a/src/qt/qvaluecombobox.h b/src/qt/qvaluecombobox.h index f266302310..8892071fba 100644 --- a/src/qt/qvaluecombobox.h +++ b/src/qt/qvaluecombobox.h @@ -16,7 +16,7 @@ class QValueComboBox : public QComboBox Q_PROPERTY(QVariant value READ value WRITE setValue NOTIFY valueChanged USER true) public: - explicit QValueComboBox(QWidget *parent = 0); + explicit QValueComboBox(QWidget *parent = nullptr); QVariant value() const; void setValue(const QVariant &value); diff --git a/src/qt/receivecoinsdialog.cpp b/src/qt/receivecoinsdialog.cpp index a7cc5da19e..bc96b5a6f7 100644 --- a/src/qt/receivecoinsdialog.cpp +++ b/src/qt/receivecoinsdialog.cpp @@ -25,8 +25,8 @@ ReceiveCoinsDialog::ReceiveCoinsDialog(const PlatformStyle *_platformStyle, QWidget *parent) : QDialog(parent), ui(new Ui::ReceiveCoinsDialog), - columnResizingFixer(0), - model(0), + columnResizingFixer(nullptr), + model(nullptr), platformStyle(_platformStyle) { ui->setupUi(this); diff --git a/src/qt/receivecoinsdialog.h b/src/qt/receivecoinsdialog.h index bc0f6248f0..5bca2f46e2 100644 --- a/src/qt/receivecoinsdialog.h +++ b/src/qt/receivecoinsdialog.h @@ -39,7 +39,7 @@ public: MINIMUM_COLUMN_WIDTH = 130 }; - explicit ReceiveCoinsDialog(const PlatformStyle *platformStyle, QWidget *parent = 0); + explicit ReceiveCoinsDialog(const PlatformStyle *platformStyle, QWidget *parent = nullptr); ~ReceiveCoinsDialog(); void setModel(WalletModel *model); diff --git a/src/qt/receiverequestdialog.cpp b/src/qt/receiverequestdialog.cpp index c561d948be..f5b30cf6d2 100644 --- a/src/qt/receiverequestdialog.cpp +++ b/src/qt/receiverequestdialog.cpp @@ -26,7 +26,7 @@ #endif QRImageWidget::QRImageWidget(QWidget *parent): - QLabel(parent), contextMenu(0) + QLabel(parent), contextMenu(nullptr) { contextMenu = new QMenu(this); QAction *saveImageAction = new QAction(tr("&Save Image..."), this); @@ -88,7 +88,7 @@ void QRImageWidget::contextMenuEvent(QContextMenuEvent *event) ReceiveRequestDialog::ReceiveRequestDialog(QWidget *parent) : QDialog(parent), ui(new Ui::ReceiveRequestDialog), - model(0) + model(nullptr) { ui->setupUi(this); diff --git a/src/qt/receiverequestdialog.h b/src/qt/receiverequestdialog.h index 5662af18b7..dd28fd73c8 100644 --- a/src/qt/receiverequestdialog.h +++ b/src/qt/receiverequestdialog.h @@ -28,7 +28,7 @@ class QRImageWidget : public QLabel Q_OBJECT public: - explicit QRImageWidget(QWidget *parent = 0); + explicit QRImageWidget(QWidget *parent = nullptr); QImage exportImage(); public Q_SLOTS: @@ -48,7 +48,7 @@ class ReceiveRequestDialog : public QDialog Q_OBJECT public: - explicit ReceiveRequestDialog(QWidget *parent = 0); + explicit ReceiveRequestDialog(QWidget *parent = nullptr); ~ReceiveRequestDialog(); void setModel(WalletModel *model); diff --git a/src/qt/recentrequeststablemodel.cpp b/src/qt/recentrequeststablemodel.cpp index 82ab48ac20..aa746017f3 100644 --- a/src/qt/recentrequeststablemodel.cpp +++ b/src/qt/recentrequeststablemodel.cpp @@ -15,8 +15,6 @@ RecentRequestsTableModel::RecentRequestsTableModel(WalletModel *parent) : QAbstractTableModel(parent), walletModel(parent) { - nReceiveRequestsMaxId = 0; - // Load entries from wallet std::vector<std::string> vReceiveRequests; parent->loadReceiveRequests(vReceiveRequests); diff --git a/src/qt/recentrequeststablemodel.h b/src/qt/recentrequeststablemodel.h index ff2c0c8098..8a1140e952 100644 --- a/src/qt/recentrequeststablemodel.h +++ b/src/qt/recentrequeststablemodel.h @@ -94,7 +94,7 @@ private: WalletModel *walletModel; QStringList columns; QList<RecentRequestEntry> list; - int64_t nReceiveRequestsMaxId; + int64_t nReceiveRequestsMaxId{0}; /** Updates the column title to "Amount (DisplayUnit)" and emits headerDataChanged() signal for table headers to react. */ void updateAmountColumnTitle(); diff --git a/src/qt/rpcconsole.cpp b/src/qt/rpcconsole.cpp index 774a0d78e7..fc1e14b031 100644 --- a/src/qt/rpcconsole.cpp +++ b/src/qt/rpcconsole.cpp @@ -1,4 +1,4 @@ -// Copyright (c) 2011-2018 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. @@ -18,6 +18,7 @@ #include <netbase.h> #include <rpc/server.h> #include <rpc/client.h> +#include <util/strencodings.h> #include <util/system.h> #include <openssl/crypto.h> @@ -85,7 +86,7 @@ public: explicit RPCExecutor(interfaces::Node& node) : m_node(node) {} public Q_SLOTS: - void request(const QString &command, const QString &walletID); + void request(const QString &command, const WalletModel* wallet_model); Q_SIGNALS: void reply(int category, const QString &command); @@ -148,7 +149,7 @@ public: * @param[out] pstrFilteredOut Command line, filtered to remove any sensitive data */ -bool RPCConsole::RPCParseCommandLine(interfaces::Node* node, std::string &strResult, const std::string &strCommand, const bool fExecute, std::string * const pstrFilteredOut, const std::string *walletID) +bool RPCConsole::RPCParseCommandLine(interfaces::Node* node, std::string &strResult, const std::string &strCommand, const bool fExecute, std::string * const pstrFilteredOut, const WalletModel* wallet_model) { std::vector< std::vector<std::string> > stack; stack.push_back(std::vector<std::string>()); @@ -226,7 +227,7 @@ bool RPCConsole::RPCParseCommandLine(interfaces::Node* node, std::string &strRes if (lastResult.isArray()) { for(char argch: curarg) - if (!std::isdigit(argch)) + if (!IsDigit(argch)) throw std::runtime_error("Invalid result query"); subelement = lastResult[atoi(curarg.c_str())]; } @@ -306,8 +307,8 @@ bool RPCConsole::RPCParseCommandLine(interfaces::Node* node, std::string &strRes std::string method = stack.back()[0]; std::string uri; #ifdef ENABLE_WALLET - if (walletID) { - QByteArray encodedName = QUrl::toPercentEncoding(QString::fromStdString(*walletID)); + if (wallet_model) { + QByteArray encodedName = QUrl::toPercentEncoding(wallet_model->getWalletName()); uri = "/wallet/"+std::string(encodedName.constData(), encodedName.length()); } #endif @@ -387,7 +388,7 @@ bool RPCConsole::RPCParseCommandLine(interfaces::Node* node, std::string &strRes } } -void RPCExecutor::request(const QString &command, const QString &walletID) +void RPCExecutor::request(const QString &command, const WalletModel* wallet_model) { try { @@ -395,13 +396,12 @@ void RPCExecutor::request(const QString &command, const QString &walletID) std::string executableCommand = command.toStdString() + "\n"; // Catch the console-only-help command before RPC call is executed and reply with help text as-if a RPC reply. - if(executableCommand == "help-console\n") - { + if(executableCommand == "help-console\n") { Q_EMIT reply(RPCConsole::CMD_REPLY, QString(("\n" "This console accepts RPC commands using the standard syntax.\n" " example: getblockhash 0\n\n" - "This console can also accept RPC commands using parenthesized syntax.\n" + "This console can also accept RPC commands using the parenthesized syntax.\n" " example: getblockhash(0)\n\n" "Commands may be nested when specified with the parenthesized syntax.\n" @@ -411,16 +411,14 @@ void RPCExecutor::request(const QString &command, const QString &walletID) " example: getblockhash 0\n" " getblockhash,0\n\n" - "Named results can be queried with a non-quoted key string in brackets.\n" - " example: getblock(getblockhash(0) true)[tx]\n\n" + "Named results can be queried with a non-quoted key string in brackets using the parenthesized syntax.\n" + " example: getblock(getblockhash(0) 1)[tx]\n\n" - "Results without keys can be queried using an integer in brackets.\n" - " example: getblock(getblockhash(0),true)[tx][0]\n\n"))); + "Results without keys can be queried with an integer in brackets using the parenthesized syntax.\n" + " example: getblock(getblockhash(0),1)[tx][0]\n\n"))); return; } - std::string wallet_id = walletID.toStdString(); - if (!RPCConsole::RPCExecuteCommandLine(m_node, result, executableCommand, nullptr, walletID.isNull() ? nullptr : &wallet_id)) - { + if (!RPCConsole::RPCExecuteCommandLine(m_node, result, executableCommand, nullptr, wallet_model)) { Q_EMIT reply(RPCConsole::CMD_ERROR, QString("Parse error: unbalanced ' or \"")); return; } @@ -486,7 +484,7 @@ RPCConsole::RPCConsole(interfaces::Node& node, const PlatformStyle *_platformSty // set library version labels #ifdef ENABLE_WALLET - ui->berkeleyDBVersion->setText(DbEnv::version(0, 0, 0)); + ui->berkeleyDBVersion->setText(DbEnv::version(nullptr, nullptr, nullptr)); #else ui->label_berkeleyDBVersion->hide(); ui->berkeleyDBVersion->hide(); @@ -689,8 +687,7 @@ void RPCConsole::setClientModel(ClientModel *model) } if (!model) { // Client model is being set to 0, this means shutdown() is about to be called. - // Make sure we clean up the executor thread - Q_EMIT stopExecutor(); + thread.quit(); thread.wait(); } } @@ -698,10 +695,8 @@ void RPCConsole::setClientModel(ClientModel *model) #ifdef ENABLE_WALLET void RPCConsole::addWallet(WalletModel * const walletModel) { - const QString name = walletModel->getWalletName(); - // use name for text and internal data object (to allow to move to a wallet id later) - QString display_name = name.isEmpty() ? "["+tr("default wallet")+"]" : name; - ui->WalletSelector->addItem(display_name, name); + // use name for text and wallet model for internal data object (to allow to move to a wallet id later) + ui->WalletSelector->addItem(walletModel->getDisplayName(), QVariant::fromValue(walletModel)); if (ui->WalletSelector->count() == 2 && !isVisible()) { // First wallet added, set to default so long as the window isn't presently visible (and potentially in use) ui->WalletSelector->setCurrentIndex(1); @@ -714,8 +709,7 @@ void RPCConsole::addWallet(WalletModel * const walletModel) void RPCConsole::removeWallet(WalletModel * const walletModel) { - const QString name = walletModel->getWalletName(); - ui->WalletSelector->removeItem(ui->WalletSelector->findData(name)); + ui->WalletSelector->removeItem(ui->WalletSelector->findData(QVariant::fromValue(walletModel))); if (ui->WalletSelector->count() == 2) { ui->WalletSelector->setVisible(false); ui->WalletSelectorLabel->setVisible(false); @@ -910,25 +904,25 @@ void RPCConsole::on_lineEdit_returnPressed() cmdBeforeBrowsing = QString(); - QString walletID; + WalletModel* wallet_model{nullptr}; #ifdef ENABLE_WALLET const int wallet_index = ui->WalletSelector->currentIndex(); if (wallet_index > 0) { - walletID = (QString)ui->WalletSelector->itemData(wallet_index).value<QString>(); + wallet_model = ui->WalletSelector->itemData(wallet_index).value<WalletModel*>(); } - if (m_last_wallet_id != walletID) { - if (walletID.isNull()) { - message(CMD_REQUEST, tr("Executing command without any wallet")); + if (m_last_wallet_model != wallet_model) { + if (wallet_model) { + message(CMD_REQUEST, tr("Executing command using \"%1\" wallet").arg(wallet_model->getWalletName())); } else { - message(CMD_REQUEST, tr("Executing command using \"%1\" wallet").arg(walletID)); + message(CMD_REQUEST, tr("Executing command without any wallet")); } - m_last_wallet_id = walletID; + m_last_wallet_model = wallet_model; } #endif message(CMD_REQUEST, QString::fromStdString(strFilteredCmd)); - Q_EMIT cmdRequest(cmd, walletID); + Q_EMIT cmdRequest(cmd, m_last_wallet_model); cmd = QString::fromStdString(strFilteredCmd); @@ -979,11 +973,8 @@ void RPCConsole::startExecutor() // Requests from this object must go to executor connect(this, &RPCConsole::cmdRequest, executor, &RPCExecutor::request); - // On stopExecutor signal - // - quit the Qt event loop in the execution thread - connect(this, &RPCConsole::stopExecutor, &thread, &QThread::quit); - // - queue executor for deletion (in execution thread) - connect(&thread, &QThread::finished, executor, &RPCExecutor::deleteLater, Qt::DirectConnection); + // Make sure executor object is deleted in its own thread + connect(&thread, &QThread::finished, executor, &RPCExecutor::deleteLater); // Default implementation of QThread::run() simply spins up an event loop in the thread, // which is what we want. @@ -992,10 +983,9 @@ void RPCConsole::startExecutor() void RPCConsole::on_tabWidget_currentChanged(int index) { - if (ui->tabWidget->widget(index) == ui->tab_console) + if (ui->tabWidget->widget(index) == ui->tab_console) { ui->lineEdit->setFocus(); - else if (ui->tabWidget->widget(index) != ui->tab_peers) - clearSelectedNode(); + } } void RPCConsole::on_openDebugLogfileButton_clicked() @@ -1221,16 +1211,16 @@ void RPCConsole::banSelectedNode(int bantime) // Get currently selected peer address NodeId id = nodes.at(i).data().toLongLong(); - // Get currently selected peer address - int detailNodeRow = clientModel->getPeerTableModel()->getRowByNodeId(id); - if(detailNodeRow < 0) - return; + // Get currently selected peer address + int detailNodeRow = clientModel->getPeerTableModel()->getRowByNodeId(id); + if (detailNodeRow < 0) return; - // Find possible nodes, ban it and clear the selected node - const CNodeCombinedStats *stats = clientModel->getPeerTableModel()->getNodeStats(detailNodeRow); - if(stats) { + // Find possible nodes, ban it and clear the selected node + const CNodeCombinedStats *stats = clientModel->getPeerTableModel()->getNodeStats(detailNodeRow); + if (stats) { m_node.ban(stats->nodeStats.addr, BanReasonManuallyAdded, bantime); - } + m_node.disconnect(stats->nodeStats.addr); + } } clearSelectedNode(); clientModel->getBanTableModel()->refresh(); diff --git a/src/qt/rpcconsole.h b/src/qt/rpcconsole.h index 20dbf5ec95..79b0f3b19c 100644 --- a/src/qt/rpcconsole.h +++ b/src/qt/rpcconsole.h @@ -1,4 +1,4 @@ -// Copyright (c) 2011-2018 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. @@ -41,9 +41,9 @@ public: explicit RPCConsole(interfaces::Node& node, const PlatformStyle *platformStyle, QWidget *parent); ~RPCConsole(); - static bool RPCParseCommandLine(interfaces::Node* node, std::string &strResult, const std::string &strCommand, bool fExecute, std::string * const pstrFilteredOut = nullptr, const std::string *walletID = nullptr); - static bool RPCExecuteCommandLine(interfaces::Node& node, std::string &strResult, const std::string &strCommand, std::string * const pstrFilteredOut = nullptr, const std::string *walletID = nullptr) { - return RPCParseCommandLine(&node, strResult, strCommand, true, pstrFilteredOut, walletID); + static bool RPCParseCommandLine(interfaces::Node* node, std::string &strResult, const std::string &strCommand, bool fExecute, std::string * const pstrFilteredOut = nullptr, const WalletModel* wallet_model = nullptr); + static bool RPCExecuteCommandLine(interfaces::Node& node, std::string &strResult, const std::string &strCommand, std::string * const pstrFilteredOut = nullptr, const WalletModel* wallet_model = nullptr) { + return RPCParseCommandLine(&node, strResult, strCommand, true, pstrFilteredOut, wallet_model); } void setClientModel(ClientModel *model); @@ -132,8 +132,7 @@ public Q_SLOTS: Q_SIGNALS: // For RPC command executor - void stopExecutor(); - void cmdRequest(const QString &command, const QString &walletID); + void cmdRequest(const QString &command, const WalletModel* wallet_model); private: void startExecutor(); @@ -165,7 +164,7 @@ private: int consoleFontSize = 0; QCompleter *autoCompleter = nullptr; QThread thread; - QString m_last_wallet_id; + WalletModel* m_last_wallet_model{nullptr}; /** Update UI with latest network info from model. */ void updateNetworkState(); diff --git a/src/qt/sendcoinsdialog.cpp b/src/qt/sendcoinsdialog.cpp index 65db0280b7..6e00ab755c 100644 --- a/src/qt/sendcoinsdialog.cpp +++ b/src/qt/sendcoinsdialog.cpp @@ -54,8 +54,8 @@ int getIndexForConfTarget(int target) { SendCoinsDialog::SendCoinsDialog(const PlatformStyle *_platformStyle, QWidget *parent) : QDialog(parent), ui(new Ui::SendCoinsDialog), - clientModel(0), - model(0), + clientModel(nullptr), + model(nullptr), fNewRecipientAllowed(true), fFeeMinimized(true), platformStyle(_platformStyle) @@ -443,7 +443,7 @@ SendCoinsEntry *SendCoinsDialog::addEntry() void SendCoinsDialog::updateTabsAndLabels() { - setupTabChain(0); + setupTabChain(nullptr); coinControlUpdateLabels(); } @@ -478,7 +478,7 @@ QWidget *SendCoinsDialog::setupTabChain(QWidget *prev) void SendCoinsDialog::setAddress(const QString &address) { - SendCoinsEntry *entry = 0; + SendCoinsEntry *entry = nullptr; // Replace the first entry if it is still unused if(ui->entries->count() == 1) { @@ -501,7 +501,7 @@ void SendCoinsDialog::pasteEntry(const SendCoinsRecipient &rv) if(!fNewRecipientAllowed) return; - SendCoinsEntry *entry = 0; + SendCoinsEntry *entry = nullptr; // Replace the first entry if it is still unused if(ui->entries->count() == 1) { diff --git a/src/qt/sendcoinsdialog.h b/src/qt/sendcoinsdialog.h index e1ebc77d59..337a72b878 100644 --- a/src/qt/sendcoinsdialog.h +++ b/src/qt/sendcoinsdialog.h @@ -31,7 +31,7 @@ class SendCoinsDialog : public QDialog Q_OBJECT public: - explicit SendCoinsDialog(const PlatformStyle *platformStyle, QWidget *parent = 0); + explicit SendCoinsDialog(const PlatformStyle *platformStyle, QWidget *parent = nullptr); ~SendCoinsDialog(); void setClientModel(ClientModel *clientModel); @@ -108,7 +108,7 @@ class SendConfirmationDialog : public QMessageBox Q_OBJECT public: - SendConfirmationDialog(const QString &title, const QString &text, int secDelay = SEND_CONFIRM_DELAY, QWidget *parent = 0); + SendConfirmationDialog(const QString &title, const QString &text, int secDelay = SEND_CONFIRM_DELAY, QWidget *parent = nullptr); int exec(); private Q_SLOTS: diff --git a/src/qt/sendcoinsentry.cpp b/src/qt/sendcoinsentry.cpp index 76c942c8b9..7324d759fb 100644 --- a/src/qt/sendcoinsentry.cpp +++ b/src/qt/sendcoinsentry.cpp @@ -21,7 +21,7 @@ SendCoinsEntry::SendCoinsEntry(const PlatformStyle *_platformStyle, QWidget *parent) : QStackedWidget(parent), ui(new Ui::SendCoinsEntry), - model(0), + model(nullptr), platformStyle(_platformStyle) { ui->setupUi(this); @@ -155,7 +155,7 @@ bool SendCoinsEntry::validate(interfaces::Node& node) } // Sending a zero amount is invalid - if (ui->payAmount->value(0) <= 0) + if (ui->payAmount->value(nullptr) <= 0) { ui->payAmount->setValid(false); retval = false; diff --git a/src/qt/sendcoinsentry.h b/src/qt/sendcoinsentry.h index 48ecd598d6..42e2217130 100644 --- a/src/qt/sendcoinsentry.h +++ b/src/qt/sendcoinsentry.h @@ -26,7 +26,7 @@ class SendCoinsEntry : public QStackedWidget Q_OBJECT public: - explicit SendCoinsEntry(const PlatformStyle *platformStyle, QWidget *parent = 0); + explicit SendCoinsEntry(const PlatformStyle *platformStyle, QWidget *parent = nullptr); ~SendCoinsEntry(); void setModel(WalletModel *model); diff --git a/src/qt/signverifymessagedialog.cpp b/src/qt/signverifymessagedialog.cpp index 487fc9ee1e..d37a78fa8c 100644 --- a/src/qt/signverifymessagedialog.cpp +++ b/src/qt/signverifymessagedialog.cpp @@ -22,7 +22,7 @@ SignVerifyMessageDialog::SignVerifyMessageDialog(const PlatformStyle *_platformStyle, QWidget *parent) : QDialog(parent), ui(new Ui::SignVerifyMessageDialog), - model(0), + model(nullptr), platformStyle(_platformStyle) { ui->setupUi(this); diff --git a/src/qt/splashscreen.cpp b/src/qt/splashscreen.cpp index b109a08b1c..0126a2920e 100644 --- a/src/qt/splashscreen.cpp +++ b/src/qt/splashscreen.cpp @@ -26,7 +26,7 @@ SplashScreen::SplashScreen(interfaces::Node& node, Qt::WindowFlags f, const NetworkStyle *networkStyle) : - QWidget(0, f), curAlignment(0), m_node(node) + QWidget(nullptr, f), curAlignment(0), m_node(node) { // set reference point, paddings int paddingRight = 50; diff --git a/src/qt/test/apptests.cpp b/src/qt/test/apptests.cpp new file mode 100644 index 0000000000..2c477a2e98 --- /dev/null +++ b/src/qt/test/apptests.cpp @@ -0,0 +1,117 @@ +// Copyright (c) 2018 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 <qt/test/apptests.h> + +#include <chainparams.h> +#include <init.h> +#include <qt/bitcoin.h> +#include <qt/bitcoingui.h> +#include <qt/networkstyle.h> +#include <qt/rpcconsole.h> +#include <shutdown.h> +#include <validation.h> + +#if defined(HAVE_CONFIG_H) +#include <config/bitcoin-config.h> +#endif +#ifdef ENABLE_WALLET +#include <wallet/db.h> +#endif + +#include <QAction> +#include <QEventLoop> +#include <QLineEdit> +#include <QScopedPointer> +#include <QTest> +#include <QTextEdit> +#include <QtGlobal> +#if QT_VERSION >= 0x050000 +#include <QtTest/QtTestWidgets> +#endif +#include <QtTest/QtTestGui> +#include <new> +#include <string> +#include <univalue.h> + +namespace { +//! Call getblockchaininfo RPC and check first field of JSON output. +void TestRpcCommand(RPCConsole* console) +{ + QEventLoop loop; + QTextEdit* messagesWidget = console->findChild<QTextEdit*>("messagesWidget"); + QObject::connect(messagesWidget, &QTextEdit::textChanged, &loop, &QEventLoop::quit); + QLineEdit* lineEdit = console->findChild<QLineEdit*>("lineEdit"); + QTest::keyClicks(lineEdit, "getblockchaininfo"); + QTest::keyClick(lineEdit, Qt::Key_Return); + loop.exec(); + QString output = messagesWidget->toPlainText(); + UniValue value; + value.read(output.right(output.size() - output.lastIndexOf(QChar::ObjectReplacementCharacter) - 1).toStdString()); + QCOMPARE(value["chain"].get_str(), std::string("regtest")); +} +} // namespace + +//! Entry point for BitcoinApplication tests. +void AppTests::appTests() +{ +#ifdef Q_OS_MAC + if (QApplication::platformName() == "minimal") { + // Disable for mac on "minimal" platform to avoid crashes inside the Qt + // framework when it tries to look up unimplemented cocoa functions, + // and fails to handle returned nulls + // (https://bugreports.qt.io/browse/QTBUG-49686). + QWARN("Skipping AppTests on mac build with 'minimal' platform set due to Qt bugs. To run AppTests, invoke " + "with 'test_bitcoin-qt -platform cocoa' on mac, or else use a linux or windows build."); + return; + } +#endif + + m_app.parameterSetup(); + m_app.createOptionsModel(true /* reset settings */); + QScopedPointer<const NetworkStyle> style( + NetworkStyle::instantiate(QString::fromStdString(Params().NetworkIDString()))); + m_app.setupPlatformStyle(); + m_app.createWindow(style.data()); + connect(&m_app, &BitcoinApplication::windowShown, this, &AppTests::guiTests); + expectCallback("guiTests"); + m_app.baseInitialize(); + m_app.requestInitialize(); + m_app.exec(); + m_app.requestShutdown(); + m_app.exec(); + + // Reset global state to avoid interfering with later tests. + AbortShutdown(); + UnloadBlockIndex(); +} + +//! Entry point for BitcoinGUI tests. +void AppTests::guiTests(BitcoinGUI* window) +{ + HandleCallback callback{"guiTests", *this}; + connect(window, &BitcoinGUI::consoleShown, this, &AppTests::consoleTests); + expectCallback("consoleTests"); + QAction* action = window->findChild<QAction*>("openRPCConsoleAction"); + action->activate(QAction::Trigger); +} + +//! Entry point for RPCConsole tests. +void AppTests::consoleTests(RPCConsole* console) +{ + HandleCallback callback{"consoleTests", *this}; + TestRpcCommand(console); +} + +//! Destructor to shut down after the last expected callback completes. +AppTests::HandleCallback::~HandleCallback() +{ + auto& callbacks = m_app_tests.m_callbacks; + auto it = callbacks.find(m_callback); + assert(it != callbacks.end()); + callbacks.erase(it); + if (callbacks.empty()) { + m_app_tests.m_app.quit(); + } +} diff --git a/src/qt/test/apptests.h b/src/qt/test/apptests.h new file mode 100644 index 0000000000..83bf56f1e4 --- /dev/null +++ b/src/qt/test/apptests.h @@ -0,0 +1,50 @@ +// Copyright (c) 2018 The Bitcoin Core developers +// Distributed under the MIT software license, see the accompanying +// file COPYING or http://www.opensource.org/licenses/mit-license.php. + +#ifndef BITCOIN_QT_TEST_APPTESTS_H +#define BITCOIN_QT_TEST_APPTESTS_H + +#include <QObject> +#include <set> +#include <string> +#include <utility> + +class BitcoinApplication; +class BitcoinGUI; +class RPCConsole; + +class AppTests : public QObject +{ + Q_OBJECT +public: + explicit AppTests(BitcoinApplication& app) : m_app(app) {} + +private Q_SLOTS: + void appTests(); + void guiTests(BitcoinGUI* window); + void consoleTests(RPCConsole* console); + +private: + //! Add expected callback name to list of pending callbacks. + void expectCallback(std::string callback) { m_callbacks.emplace(std::move(callback)); } + + //! RAII helper to remove no-longer-pending callback. + struct HandleCallback + { + std::string m_callback; + AppTests& m_app_tests; + ~HandleCallback(); + }; + + //! Bitcoin application. + BitcoinApplication& m_app; + + //! Set of pending callback names. Used to track expected callbacks and shut + //! down the app after the last callback has been handled and all tests have + //! either run or thrown exceptions. This could be a simple int counter + //! instead of a set of names, but the names might be useful for debugging. + std::multiset<std::string> m_callbacks; +}; + +#endif // BITCOIN_QT_TEST_APPTESTS_H diff --git a/src/qt/test/rpcnestedtests.cpp b/src/qt/test/rpcnestedtests.cpp index ed453336da..173c814f1e 100644 --- a/src/qt/test/rpcnestedtests.cpp +++ b/src/qt/test/rpcnestedtests.cpp @@ -41,7 +41,7 @@ void RPCNestedTests::rpcNestedTests() TestingSetup test; - SetRPCWarmupFinished(); + if (RPCIsInWarmup(nullptr)) SetRPCWarmupFinished(); std::string result; std::string result2; diff --git a/src/qt/test/test_main.cpp b/src/qt/test/test_main.cpp index b6523604fd..a2bf53973b 100644 --- a/src/qt/test/test_main.cpp +++ b/src/qt/test/test_main.cpp @@ -7,6 +7,9 @@ #endif #include <chainparams.h> +#include <interfaces/node.h> +#include <qt/bitcoin.h> +#include <qt/test/apptests.h> #include <qt/test/rpcnestedtests.h> #include <util/system.h> #include <qt/test/uritests.h> @@ -47,12 +50,13 @@ int main(int argc, char *argv[]) { SetupEnvironment(); SetupNetworking(); - SelectParams(CBaseChainParams::MAIN); + SelectParams(CBaseChainParams::REGTEST); noui_connect(); ClearDatadirCache(); fs::path pathTemp = fs::temp_directory_path() / strprintf("test_bitcoin-qt_%lu_%i", (unsigned long)GetTime(), (int)GetRand(100000)); fs::create_directories(pathTemp); gArgs.ForceSetArg("-datadir", pathTemp.string()); + auto node = interfaces::MakeNode(); bool fInvalid = false; @@ -67,11 +71,15 @@ int main(int argc, char *argv[]) // Don't remove this, it's needed to access // QApplication:: and QCoreApplication:: in the tests - QApplication app(argc, argv); + BitcoinApplication app(*node, argc, argv); app.setApplicationName("Bitcoin-Qt-test"); SSL_library_init(); + AppTests app_tests(app); + if (QTest::qExec(&app_tests) != 0) { + fInvalid = true; + } URITests test1; if (QTest::qExec(&test1) != 0) { fInvalid = true; diff --git a/src/qt/trafficgraphwidget.cpp b/src/qt/trafficgraphwidget.cpp index 3aed3f2b97..1588be8da3 100644 --- a/src/qt/trafficgraphwidget.cpp +++ b/src/qt/trafficgraphwidget.cpp @@ -19,14 +19,14 @@ TrafficGraphWidget::TrafficGraphWidget(QWidget *parent) : QWidget(parent), - timer(0), + timer(nullptr), fMax(0.0f), nMins(0), vSamplesIn(), vSamplesOut(), nLastBytesIn(0), nLastBytesOut(0), - clientModel(0) + clientModel(nullptr) { timer = new QTimer(this); connect(timer, &QTimer::timeout, this, &TrafficGraphWidget::updateRates); diff --git a/src/qt/trafficgraphwidget.h b/src/qt/trafficgraphwidget.h index 00660574af..48bd246b34 100644 --- a/src/qt/trafficgraphwidget.h +++ b/src/qt/trafficgraphwidget.h @@ -20,7 +20,7 @@ class TrafficGraphWidget : public QWidget Q_OBJECT public: - explicit TrafficGraphWidget(QWidget *parent = 0); + explicit TrafficGraphWidget(QWidget *parent = nullptr); void setClientModel(ClientModel *model); int getGraphRangeMins() const; diff --git a/src/qt/transactiondescdialog.h b/src/qt/transactiondescdialog.h index f1371b3856..8fd3f3166a 100644 --- a/src/qt/transactiondescdialog.h +++ b/src/qt/transactiondescdialog.h @@ -21,7 +21,7 @@ class TransactionDescDialog : public QDialog Q_OBJECT public: - explicit TransactionDescDialog(const QModelIndex &idx, QWidget *parent = 0); + explicit TransactionDescDialog(const QModelIndex &idx, QWidget *parent = nullptr); ~TransactionDescDialog(); private: diff --git a/src/qt/transactionfilterproxy.h b/src/qt/transactionfilterproxy.h index 9febd59820..685f8d3a26 100644 --- a/src/qt/transactionfilterproxy.h +++ b/src/qt/transactionfilterproxy.h @@ -16,7 +16,7 @@ class TransactionFilterProxy : public QSortFilterProxyModel Q_OBJECT public: - explicit TransactionFilterProxy(QObject *parent = 0); + explicit TransactionFilterProxy(QObject *parent = nullptr); /** Earliest date that can be represented (far in the past) */ static const QDateTime MIN_DATE; diff --git a/src/qt/transactionrecord.cpp b/src/qt/transactionrecord.cpp index d88cfe52ed..aa785553c8 100644 --- a/src/qt/transactionrecord.cpp +++ b/src/qt/transactionrecord.cpp @@ -4,6 +4,7 @@ #include <qt/transactionrecord.h> +#include <chain.h> #include <consensus/consensus.h> #include <interfaces/wallet.h> #include <key_io.h> @@ -12,6 +13,7 @@ #include <stdint.h> +#include <QDateTime> /* Return positive answer if transaction should be shown in list. */ @@ -158,7 +160,7 @@ QList<TransactionRecord> TransactionRecord::decomposeTransaction(const interface return parts; } -void TransactionRecord::updateStatus(const interfaces::WalletTxStatus& wtx, int numBlocks) +void TransactionRecord::updateStatus(const interfaces::WalletTxStatus& wtx, int numBlocks, int64_t block_time) { // Determine transaction status @@ -172,10 +174,9 @@ void TransactionRecord::updateStatus(const interfaces::WalletTxStatus& wtx, int status.depth = wtx.depth_in_main_chain; status.cur_num_blocks = numBlocks; - if (!wtx.is_final) - { - if (wtx.lock_time < LOCKTIME_THRESHOLD) - { + const bool up_to_date = ((int64_t)QDateTime::currentMSecsSinceEpoch() / 1000 - block_time < MAX_BLOCK_TIME_GAP); + if (up_to_date && !wtx.is_final) { + if (wtx.lock_time < LOCKTIME_THRESHOLD) { status.status = TransactionStatus::OpenUntilBlock; status.open_for = wtx.lock_time - numBlocks; } diff --git a/src/qt/transactionrecord.h b/src/qt/transactionrecord.h index 470f70e2ab..3f64cefd09 100644 --- a/src/qt/transactionrecord.h +++ b/src/qt/transactionrecord.h @@ -138,7 +138,7 @@ public: /** Update status from core wallet tx. */ - void updateStatus(const interfaces::WalletTxStatus& wtx, int numBlocks); + void updateStatus(const interfaces::WalletTxStatus& wtx, int numBlocks, int64_t block_time); /** Return whether a status update is needed. */ diff --git a/src/qt/transactiontablemodel.cpp b/src/qt/transactiontablemodel.cpp index 01722146c5..631a9b891d 100644 --- a/src/qt/transactiontablemodel.cpp +++ b/src/qt/transactiontablemodel.cpp @@ -192,12 +192,13 @@ public: // simply re-use the cached status. interfaces::WalletTxStatus wtx; int numBlocks; - if (wallet.tryGetTxStatus(rec->hash, wtx, numBlocks) && rec->statusUpdateNeeded(numBlocks)) { - rec->updateStatus(wtx, numBlocks); + int64_t block_time; + if (wallet.tryGetTxStatus(rec->hash, wtx, numBlocks, block_time) && rec->statusUpdateNeeded(numBlocks)) { + rec->updateStatus(wtx, numBlocks, block_time); } return rec; } - return 0; + return nullptr; } QString describe(interfaces::Node& node, interfaces::Wallet& wallet, TransactionRecord *rec, int unit) diff --git a/src/qt/transactiontablemodel.h b/src/qt/transactiontablemodel.h index 8be3a7ab2e..7a7d98962b 100644 --- a/src/qt/transactiontablemodel.h +++ b/src/qt/transactiontablemodel.h @@ -28,7 +28,7 @@ class TransactionTableModel : public QAbstractTableModel Q_OBJECT public: - explicit TransactionTableModel(const PlatformStyle *platformStyle, WalletModel *parent = 0); + explicit TransactionTableModel(const PlatformStyle *platformStyle, WalletModel *parent = nullptr); ~TransactionTableModel(); enum ColumnIndex { diff --git a/src/qt/transactionview.cpp b/src/qt/transactionview.cpp index 68410c8bd6..eb6437eb31 100644 --- a/src/qt/transactionview.cpp +++ b/src/qt/transactionview.cpp @@ -38,8 +38,8 @@ #include <QVBoxLayout> TransactionView::TransactionView(const PlatformStyle *platformStyle, QWidget *parent) : - QWidget(parent), model(0), transactionProxyModel(0), - transactionView(0), abandonAction(0), bumpFeeAction(0), columnResizingFixer(0) + QWidget(parent), model(nullptr), transactionProxyModel(nullptr), + transactionView(nullptr), abandonAction(nullptr), bumpFeeAction(nullptr), columnResizingFixer(nullptr) { // Build filter row setContentsMargins(0,0,0,0); diff --git a/src/qt/transactionview.h b/src/qt/transactionview.h index fdd8b069c7..e07181d1c8 100644 --- a/src/qt/transactionview.h +++ b/src/qt/transactionview.h @@ -35,7 +35,7 @@ class TransactionView : public QWidget Q_OBJECT public: - explicit TransactionView(const PlatformStyle *platformStyle, QWidget *parent = 0); + explicit TransactionView(const PlatformStyle *platformStyle, QWidget *parent = nullptr); void setModel(WalletModel *model); diff --git a/src/qt/utilitydialog.h b/src/qt/utilitydialog.h index ad1fda4573..f1cedff282 100644 --- a/src/qt/utilitydialog.h +++ b/src/qt/utilitydialog.h @@ -45,7 +45,7 @@ class ShutdownWindow : public QWidget Q_OBJECT public: - explicit ShutdownWindow(QWidget *parent=0, Qt::WindowFlags f=0); + explicit ShutdownWindow(QWidget *parent=nullptr, Qt::WindowFlags f=Qt::Widget); static QWidget *showShutdownWindow(BitcoinGUI *window); protected: diff --git a/src/qt/walletcontroller.cpp b/src/qt/walletcontroller.cpp new file mode 100644 index 0000000000..df2b7a3f9b --- /dev/null +++ b/src/qt/walletcontroller.cpp @@ -0,0 +1,95 @@ +// Copyright (c) 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 <qt/walletcontroller.h> + +#include <interfaces/handler.h> +#include <interfaces/node.h> + +#include <algorithm> + +#include <QMutexLocker> +#include <QThread> + +WalletController::WalletController(interfaces::Node& node, const PlatformStyle* platform_style, OptionsModel* options_model, QObject* parent) + : QObject(parent) + , m_node(node) + , m_platform_style(platform_style) + , m_options_model(options_model) +{ + m_handler_load_wallet = m_node.handleLoadWallet([this](std::unique_ptr<interfaces::Wallet> wallet) { + getOrCreateWallet(std::move(wallet)); + }); + + for (std::unique_ptr<interfaces::Wallet>& wallet : m_node.getWallets()) { + getOrCreateWallet(std::move(wallet)); + } +} + +// Not using the default destructor because not all member types definitions are +// available in the header, just forward declared. +WalletController::~WalletController() {} + +std::vector<WalletModel*> WalletController::getWallets() const +{ + QMutexLocker locker(&m_mutex); + return m_wallets; +} + +WalletModel* WalletController::getOrCreateWallet(std::unique_ptr<interfaces::Wallet> wallet) +{ + QMutexLocker locker(&m_mutex); + + // Return model instance if exists. + if (!m_wallets.empty()) { + std::string name = wallet->getWalletName(); + for (WalletModel* wallet_model : m_wallets) { + if (wallet_model->wallet().getWalletName() == name) { + return wallet_model; + } + } + } + + // Instantiate model and register it. + WalletModel* wallet_model = new WalletModel(std::move(wallet), m_node, m_platform_style, m_options_model, nullptr); + m_wallets.push_back(wallet_model); + + connect(wallet_model, &WalletModel::unload, [this, wallet_model] { + removeAndDeleteWallet(wallet_model); + }); + + // Re-emit coinsSent signal from wallet model. + connect(wallet_model, &WalletModel::coinsSent, this, &WalletController::coinsSent); + + // Notify walletAdded signal on the GUI thread. + if (QThread::currentThread() == thread()) { + addWallet(wallet_model); + } else { + // Handler callback runs in a different thread so fix wallet model thread affinity. + wallet_model->moveToThread(thread()); + QMetaObject::invokeMethod(this, "addWallet", Qt::QueuedConnection, Q_ARG(WalletModel*, wallet_model)); + } + + return wallet_model; +} + +void WalletController::addWallet(WalletModel* wallet_model) +{ + // Take ownership of the wallet model and register it. + wallet_model->setParent(this); + Q_EMIT walletAdded(wallet_model); +} + +void WalletController::removeAndDeleteWallet(WalletModel* wallet_model) +{ + // Unregister wallet model. + { + QMutexLocker locker(&m_mutex); + m_wallets.erase(std::remove(m_wallets.begin(), m_wallets.end(), wallet_model)); + } + Q_EMIT walletRemoved(wallet_model); + // Currently this can trigger the unload since the model can hold the last + // CWallet shared pointer. + delete wallet_model; +} diff --git a/src/qt/walletcontroller.h b/src/qt/walletcontroller.h new file mode 100644 index 0000000000..22b71b07ff --- /dev/null +++ b/src/qt/walletcontroller.h @@ -0,0 +1,59 @@ +// Copyright (c) 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. + +#ifndef BITCOIN_QT_WALLETCONTROLLER_H +#define BITCOIN_QT_WALLETCONTROLLER_H + +#include <qt/walletmodel.h> +#include <sync.h> + +#include <list> +#include <memory> +#include <vector> + +#include <QMutex> + +class OptionsModel; +class PlatformStyle; + +namespace interfaces { +class Handler; +class Node; +} // namespace interfaces + +/** + * Controller between interfaces::Node, WalletModel instances and the GUI. + */ +class WalletController : public QObject +{ + Q_OBJECT + + WalletModel* getOrCreateWallet(std::unique_ptr<interfaces::Wallet> wallet); + void removeAndDeleteWallet(WalletModel* wallet_model); + +public: + WalletController(interfaces::Node& node, const PlatformStyle* platform_style, OptionsModel* options_model, QObject* parent); + ~WalletController(); + + std::vector<WalletModel*> getWallets() const; + +private Q_SLOTS: + void addWallet(WalletModel* wallet_model); + +Q_SIGNALS: + void walletAdded(WalletModel* wallet_model); + void walletRemoved(WalletModel* wallet_model); + + void coinsSent(WalletModel* wallet_model, SendCoinsRecipient recipient, QByteArray transaction); + +private: + interfaces::Node& m_node; + const PlatformStyle* const m_platform_style; + OptionsModel* const m_options_model; + mutable QMutex m_mutex; + std::vector<WalletModel*> m_wallets; + std::unique_ptr<interfaces::Handler> m_handler_load_wallet; +}; + +#endif // BITCOIN_QT_WALLETCONTROLLER_H diff --git a/src/qt/walletframe.cpp b/src/qt/walletframe.cpp index d15bd95b8e..466f2278eb 100644 --- a/src/qt/walletframe.cpp +++ b/src/qt/walletframe.cpp @@ -1,4 +1,4 @@ -// Copyright (c) 2011-2018 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. @@ -46,8 +46,7 @@ bool WalletFrame::addWallet(WalletModel *walletModel) return false; } - const QString name = walletModel->getWalletName(); - if (mapWalletViews.count(name) > 0) { + if (mapWalletViews.count(walletModel) > 0) { return false; } @@ -65,7 +64,7 @@ bool WalletFrame::addWallet(WalletModel *walletModel) } walletStack->addWidget(walletView); - mapWalletViews[name] = walletView; + mapWalletViews[walletModel] = walletView; // Ensure a walletView is able to show the main window connect(walletView, &WalletView::showNormalIfMinimized, [this]{ @@ -77,24 +76,24 @@ bool WalletFrame::addWallet(WalletModel *walletModel) return true; } -bool WalletFrame::setCurrentWallet(const QString& name) +bool WalletFrame::setCurrentWallet(WalletModel* wallet_model) { - if (mapWalletViews.count(name) == 0) + if (mapWalletViews.count(wallet_model) == 0) return false; - WalletView *walletView = mapWalletViews.value(name); + WalletView *walletView = mapWalletViews.value(wallet_model); walletStack->setCurrentWidget(walletView); assert(walletView); walletView->updateEncryptionStatus(); return true; } -bool WalletFrame::removeWallet(const QString &name) +bool WalletFrame::removeWallet(WalletModel* wallet_model) { - if (mapWalletViews.count(name) == 0) + if (mapWalletViews.count(wallet_model) == 0) return false; - WalletView *walletView = mapWalletViews.take(name); + WalletView *walletView = mapWalletViews.take(wallet_model); walletStack->removeWidget(walletView); delete walletView; return true; @@ -102,7 +101,7 @@ bool WalletFrame::removeWallet(const QString &name) void WalletFrame::removeAllWallets() { - QMap<QString, WalletView*>::const_iterator i; + QMap<WalletModel*, WalletView*>::const_iterator i; for (i = mapWalletViews.constBegin(); i != mapWalletViews.constEnd(); ++i) walletStack->removeWidget(i.value()); mapWalletViews.clear(); @@ -120,35 +119,35 @@ bool WalletFrame::handlePaymentRequest(const SendCoinsRecipient &recipient) void WalletFrame::showOutOfSyncWarning(bool fShow) { bOutOfSync = fShow; - QMap<QString, WalletView*>::const_iterator i; + QMap<WalletModel*, WalletView*>::const_iterator i; for (i = mapWalletViews.constBegin(); i != mapWalletViews.constEnd(); ++i) i.value()->showOutOfSyncWarning(fShow); } void WalletFrame::gotoOverviewPage() { - QMap<QString, WalletView*>::const_iterator i; + QMap<WalletModel*, WalletView*>::const_iterator i; for (i = mapWalletViews.constBegin(); i != mapWalletViews.constEnd(); ++i) i.value()->gotoOverviewPage(); } void WalletFrame::gotoHistoryPage() { - QMap<QString, WalletView*>::const_iterator i; + QMap<WalletModel*, WalletView*>::const_iterator i; for (i = mapWalletViews.constBegin(); i != mapWalletViews.constEnd(); ++i) i.value()->gotoHistoryPage(); } void WalletFrame::gotoReceiveCoinsPage() { - QMap<QString, WalletView*>::const_iterator i; + QMap<WalletModel*, WalletView*>::const_iterator i; for (i = mapWalletViews.constBegin(); i != mapWalletViews.constEnd(); ++i) i.value()->gotoReceiveCoinsPage(); } void WalletFrame::gotoSendCoinsPage(QString addr) { - QMap<QString, WalletView*>::const_iterator i; + QMap<WalletModel*, WalletView*>::const_iterator i; for (i = mapWalletViews.constBegin(); i != mapWalletViews.constEnd(); ++i) i.value()->gotoSendCoinsPage(addr); } @@ -209,11 +208,17 @@ void WalletFrame::usedReceivingAddresses() walletView->usedReceivingAddresses(); } -WalletView *WalletFrame::currentWalletView() +WalletView* WalletFrame::currentWalletView() const { return qobject_cast<WalletView*>(walletStack->currentWidget()); } +WalletModel* WalletFrame::currentWalletModel() const +{ + WalletView* wallet_view = currentWalletView(); + return wallet_view ? wallet_view->getWalletModel() : nullptr; +} + void WalletFrame::outOfSyncWarningClicked() { Q_EMIT requestedSyncWarningInfo(); diff --git a/src/qt/walletframe.h b/src/qt/walletframe.h index 1963e89b24..6a74fde9fd 100644 --- a/src/qt/walletframe.h +++ b/src/qt/walletframe.h @@ -1,4 +1,4 @@ -// Copyright (c) 2011-2018 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. @@ -31,14 +31,14 @@ class WalletFrame : public QFrame Q_OBJECT public: - explicit WalletFrame(const PlatformStyle *platformStyle, BitcoinGUI *_gui = 0); + explicit WalletFrame(const PlatformStyle *platformStyle, BitcoinGUI *_gui = nullptr); ~WalletFrame(); void setClientModel(ClientModel *clientModel); bool addWallet(WalletModel *walletModel); - bool setCurrentWallet(const QString& name); - bool removeWallet(const QString &name); + bool setCurrentWallet(WalletModel* wallet_model); + bool removeWallet(WalletModel* wallet_model); void removeAllWallets(); bool handlePaymentRequest(const SendCoinsRecipient& recipient); @@ -53,14 +53,15 @@ private: QStackedWidget *walletStack; BitcoinGUI *gui; ClientModel *clientModel; - QMap<QString, WalletView*> mapWalletViews; + QMap<WalletModel*, WalletView*> mapWalletViews; bool bOutOfSync; const PlatformStyle *platformStyle; public: - WalletView *currentWalletView(); + WalletView* currentWalletView() const; + WalletModel* currentWalletModel() const; public Q_SLOTS: /** Switch to overview (home) page */ diff --git a/src/qt/walletmodel.cpp b/src/qt/walletmodel.cpp index ba16fdd5e1..f139152042 100644 --- a/src/qt/walletmodel.cpp +++ b/src/qt/walletmodel.cpp @@ -1,4 +1,4 @@ -// Copyright (c) 2011-2018 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. @@ -33,15 +33,13 @@ WalletModel::WalletModel(std::unique_ptr<interfaces::Wallet> wallet, interfaces::Node& node, const PlatformStyle *platformStyle, OptionsModel *_optionsModel, QObject *parent) : - QObject(parent), m_wallet(std::move(wallet)), m_node(node), optionsModel(_optionsModel), addressTableModel(0), - transactionTableModel(0), - recentRequestsTableModel(0), + QObject(parent), m_wallet(std::move(wallet)), m_node(node), optionsModel(_optionsModel), addressTableModel(nullptr), + transactionTableModel(nullptr), + recentRequestsTableModel(nullptr), cachedEncryptionStatus(Unencrypted), cachedNumBlocks(0) { fHaveWatchOnly = m_wallet->haveWatchOnly(); - fForceCheckBalanceChanged = false; - addressTableModel = new AddressTableModel(this); transactionTableModel = new TransactionTableModel(platformStyle, this); recentRequestsTableModel = new RecentRequestsTableModel(this); @@ -378,7 +376,7 @@ bool WalletModel::changePassphrase(const SecureString &oldPass, const SecureStri static void NotifyUnload(WalletModel* walletModel) { qDebug() << "NotifyUnload"; - QMetaObject::invokeMethod(walletModel, "unload", Qt::QueuedConnection); + QMetaObject::invokeMethod(walletModel, "unload"); } static void NotifyKeyStoreStatusChanged(WalletModel *walletmodel) @@ -512,7 +510,7 @@ bool WalletModel::bumpFee(uint256 hash, uint256& new_hash) CAmount new_fee; CMutableTransaction mtx; if (!m_wallet->createBumpTransaction(hash, coin_control, 0 /* totalFee */, errors, old_fee, new_fee, mtx)) { - QMessageBox::critical(0, tr("Fee bump error"), tr("Increasing transaction fee failed") + "<br />(" + + QMessageBox::critical(nullptr, tr("Fee bump error"), tr("Increasing transaction fee failed") + "<br />(" + (errors.size() ? QString::fromStdString(errors[0]) : "") +")"); return false; } @@ -551,12 +549,12 @@ bool WalletModel::bumpFee(uint256 hash, uint256& new_hash) // sign bumped transaction if (!m_wallet->signBumpTransaction(mtx)) { - QMessageBox::critical(0, tr("Fee bump error"), tr("Can't sign transaction.")); + QMessageBox::critical(nullptr, tr("Fee bump error"), tr("Can't sign transaction.")); return false; } // commit the bumped transaction if(!m_wallet->commitBumpTransaction(hash, std::move(mtx), errors, new_hash)) { - QMessageBox::critical(0, tr("Fee bump error"), tr("Could not commit transaction") + "<br />(" + + QMessageBox::critical(nullptr, tr("Fee bump error"), tr("Could not commit transaction") + "<br />(" + QString::fromStdString(errors[0])+")"); return false; } @@ -578,6 +576,12 @@ QString WalletModel::getWalletName() const return QString::fromStdString(m_wallet->getWalletName()); } +QString WalletModel::getDisplayName() const +{ + const QString name = getWalletName(); + return name.isEmpty() ? "["+tr("default wallet")+"]" : name; +} + bool WalletModel::isMultiwallet() { return m_node.getWallets().size() > 1; diff --git a/src/qt/walletmodel.h b/src/qt/walletmodel.h index ec4c5a2a6c..c3c8f36909 100644 --- a/src/qt/walletmodel.h +++ b/src/qt/walletmodel.h @@ -1,4 +1,4 @@ -// Copyright (c) 2011-2018 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. @@ -127,7 +127,7 @@ class WalletModel : public QObject Q_OBJECT public: - explicit WalletModel(std::unique_ptr<interfaces::Wallet> wallet, interfaces::Node& node, const PlatformStyle *platformStyle, OptionsModel *optionsModel, QObject *parent = 0); + explicit WalletModel(std::unique_ptr<interfaces::Wallet> wallet, interfaces::Node& node, const PlatformStyle *platformStyle, OptionsModel *optionsModel, QObject *parent = nullptr); ~WalletModel(); enum StatusCode // Returned by sendCoins @@ -219,6 +219,7 @@ public: interfaces::Wallet& wallet() const { return *m_wallet; } QString getWalletName() const; + QString getDisplayName() const; bool isMultiwallet(); @@ -234,7 +235,7 @@ private: interfaces::Node& m_node; bool fHaveWatchOnly; - bool fForceCheckBalanceChanged; + bool fForceCheckBalanceChanged{false}; // Wallet has an options model for wallet-specific options // (transaction fee, for example) diff --git a/src/qt/walletview.cpp b/src/qt/walletview.cpp index a619992344..5f6f93d948 100644 --- a/src/qt/walletview.cpp +++ b/src/qt/walletview.cpp @@ -32,8 +32,8 @@ WalletView::WalletView(const PlatformStyle *_platformStyle, QWidget *parent): QStackedWidget(parent), - clientModel(0), - walletModel(0), + clientModel(nullptr), + walletModel(nullptr), platformStyle(_platformStyle) { // Create tabs @@ -305,24 +305,19 @@ void WalletView::usedReceivingAddresses() void WalletView::showProgress(const QString &title, int nProgress) { - if (nProgress == 0) - { - progressDialog = new QProgressDialog(title, "", 0, 100); + if (nProgress == 0) { + progressDialog = new QProgressDialog(title, tr("Cancel"), 0, 100); + GUIUtil::PolishProgressDialog(progressDialog); progressDialog->setWindowModality(Qt::ApplicationModal); progressDialog->setMinimumDuration(0); progressDialog->setAutoClose(false); progressDialog->setValue(0); - progressDialog->setCancelButtonText(tr("Cancel")); - } - else if (nProgress == 100) - { - if (progressDialog) - { + } else if (nProgress == 100) { + if (progressDialog) { progressDialog->close(); progressDialog->deleteLater(); } - } - else if (progressDialog) { + } else if (progressDialog) { if (progressDialog->wasCanceled()) { getWalletModel()->wallet().abortRescan(); } else { |