diff --git a/src/qt/forms/optionsdialog.ui b/src/qt/forms/optionsdialog.ui index 240a7a7e9..fea759dee 100644 --- a/src/qt/forms/optionsdialog.ui +++ b/src/qt/forms/optionsdialog.ui @@ -1,900 +1,903 @@ OptionsDialog 0 0 560 440 Options true 0 &Main Automatically start %1 after logging in to the system. &Start %1 on system login Qt::Horizontal 40 5 Disables some advanced features but all blocks will still be fully validated. Reverting this setting requires re-downloading the entire blockchain. Actual disk usage may be somewhat higher. Prune &block storage to GB Qt::PlainText Qt::Horizontal 40 20 Reverting this setting requires re-downloading the entire blockchain. Qt::PlainText Size of &database cache Qt::PlainText databaseCache MiB Qt::PlainText Qt::Horizontal 40 20 Number of script &verification threads Qt::PlainText threadsScriptVerif (0 = auto, <0 = leave that many cores free) Qt::Horizontal 40 20 Qt::Vertical 20 40 W&allet Expert Whether to show coin control features or not. Enable coin &control features If you disable the spending of unconfirmed change, the change from a transaction cannot be used until that transaction has at least one confirmation. This also affects how your balance is computed. &Spend unconfirmed change Qt::Vertical 20 40 &Network Automatically open the Bitcoin client port on the router. This only works when your router supports UPnP and it is enabled. Map port using &UPnP Accept connections from outside. Allow incomin&g connections Connect to the Bitcoin network through a SOCKS5 proxy. &Connect through SOCKS5 proxy (default proxy): Proxy &IP: Qt::PlainText proxyIp 140 0 140 16777215 IP address of the proxy (e.g. IPv4: 127.0.0.1 / IPv6: ::1) &Port: Qt::PlainText proxyPort 55 0 55 16777215 Port of the proxy (e.g. 9050) Qt::Horizontal 40 20 Used for reaching peers via: Qt::PlainText false Shows if the supplied default SOCKS5 proxy is used to reach peers via this network type. IPv4 Qt::PlainText false Shows if the supplied default SOCKS5 proxy is used to reach peers via this network type. IPv6 Qt::PlainText false Shows if the supplied default SOCKS5 proxy is used to reach peers via this network type. Tor Qt::PlainText Qt::Horizontal 40 20 Connect to the Bitcoin network through a separate SOCKS5 proxy for Tor hidden services. Use separate SOCKS&5 proxy to reach peers via Tor hidden services: Proxy &IP: Qt::PlainText proxyIpTor 140 0 140 16777215 IP address of the proxy (e.g. IPv4: 127.0.0.1 / IPv6: ::1) &Port: Qt::PlainText proxyPortTor 55 0 55 16777215 Port of the proxy (e.g. 9050) Qt::Horizontal 40 20 Qt::Vertical 20 40 &Window Hide the icon from the system tray. &Hide tray icon Show only a tray icon after minimizing the window. &Minimize to the tray instead of the taskbar Minimize instead of exit the application when the window is closed. When this option is enabled, the application will be closed only after selecting Exit in the menu. M&inimize on close Qt::Vertical 20 40 &Display User Interface &language: Qt::PlainText lang The user interface language can be set here. This setting will take effect after restarting %1. &Unit to show amounts in: Qt::PlainText unit Choose the default subdivision unit to show in the interface and when sending coins. Third party URLs (e.g. a block explorer) that appear in the transactions tab as context menu items. %s in the URL is replaced by transaction hash. Multiple URLs are separated by vertical bar |. &Third party transaction URLs thirdPartyTxUrls Third party URLs (e.g. a block explorer) that appear in the transactions tab as context menu items. %s in the URL is replaced by transaction hash. Multiple URLs are separated by vertical bar |. + + https://example.com/tx/%s + Qt::Vertical 20 40 Options set in this dialog are overridden by the command line or in the configuration file: Qt::PlainText Qt::Horizontal 40 20 Qt::PlainText true Open the %1 configuration file from the working directory. Open Configuration File false Reset all client options to default. &Reset Options false Qt::Horizontal 40 48 200 0 75 true Qt::PlainText true Qt::Horizontal 40 48 Qt::Vertical 20 40 &OK false true &Cancel false QValidatedLineEdit QLineEdit
qt/qvalidatedlineedit.h
QValueComboBox QComboBox
qt/qvaluecombobox.h
diff --git a/src/qt/forms/sendcoinsentry.ui b/src/qt/forms/sendcoinsentry.ui index 2b05825b0..acd1d660c 100644 --- a/src/qt/forms/sendcoinsentry.ui +++ b/src/qt/forms/sendcoinsentry.ui @@ -1,1284 +1,1287 @@ SendCoinsEntry 0 0 729 150 Qt::TabFocus false QFrame::NoFrame 8 4 12 8 Pay &To: Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter payTo 0 The Bitcoin address to send the payment to Choose previously used address :/icons/address-book:/icons/address-book 22 22 Alt+A Paste address from clipboard :/icons/editpaste:/icons/editpaste 22 22 Alt+P Remove this entry :/icons/remove:/icons/remove 22 22 &Label: Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter addAsLabel Enter a label for this address to add it to the list of used addresses + + Enter a label for this address to add it to your address book + A&mount: Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter payAmount The amount to send in the selected unit The fee will be deducted from the amount being sent. The recipient will receive less bitcoins than you enter in the amount field. If multiple recipients are selected, the fee is split equally. S&ubtract fee from amount Use available balance Message: Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter Qt::PlainText Qt::Horizontal 0 0 0 255 255 127 255 255 255 255 255 191 127 127 63 170 170 84 0 0 0 255 255 255 0 0 0 255 255 255 255 255 127 0 0 0 255 255 191 255 255 220 0 0 0 0 0 0 255 255 127 255 255 255 255 255 191 127 127 63 170 170 84 0 0 0 255 255 255 0 0 0 255 255 255 255 255 127 0 0 0 255 255 191 255 255 220 0 0 0 127 127 63 255 255 127 255 255 255 255 255 191 127 127 63 170 170 84 127 127 63 255 255 255 127 127 63 255 255 127 255 255 127 0 0 0 255 255 127 255 255 220 0 0 0 This is an unauthenticated payment request. true QFrame::NoFrame 12 Pay To: Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter 0 Remove this entry :/icons/remove:/icons/remove Memo: Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter Qt::PlainText A&mount: Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter payAmount_is false 0 0 0 140 232 119 230 255 224 185 243 171 70 116 59 93 155 79 0 0 0 155 255 147 0 0 0 119 255 233 140 232 119 0 0 0 197 243 187 125 194 122 255 255 220 0 0 0 0 0 0 140 232 119 230 255 224 185 243 171 70 116 59 93 155 79 0 0 0 155 255 147 0 0 0 119 255 233 140 232 119 0 0 0 197 243 187 125 194 122 255 255 220 0 0 0 70 116 59 140 232 119 230 255 224 185 243 171 70 116 59 93 155 79 70 116 59 155 255 147 70 116 59 140 232 119 140 232 119 0 0 0 140 232 119 125 194 122 255 255 220 0 0 0 This is an authenticated payment request. true QFrame::NoFrame 12 Pay To: Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter 0 Qt::PlainText Remove this entry :/icons/remove:/icons/remove Memo: Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter Qt::PlainText A&mount: Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter payAmount_s false QValidatedLineEdit QLineEdit
qt/qvalidatedlineedit.h
BitcoinAmountField QLineEdit
qt/bitcoinamountfield.h
1
payTo addressBookButton pasteButton deleteButton addAsLabel payAmount payAmount_is deleteButton_is payAmount_s deleteButton_s
diff --git a/src/qt/forms/signverifymessagedialog.ui b/src/qt/forms/signverifymessagedialog.ui index 202edf27d..f42d19093 100644 --- a/src/qt/forms/signverifymessagedialog.ui +++ b/src/qt/forms/signverifymessagedialog.ui @@ -1,407 +1,410 @@ SignVerifyMessageDialog 0 0 700 380 Signatures - Sign / Verify a Message true 0 &Sign Message You can sign messages/agreements with your addresses to prove you can receive bitcoins sent to them. Be careful not to sign anything vague or random, as phishing attacks may try to trick you into signing your identity over to them. Only sign fully-detailed statements you agree to. Qt::PlainText true 0 The Bitcoin address to sign the message with Choose previously used address :/icons/address-book:/icons/address-book Alt+A false Paste address from clipboard :/icons/editpaste:/icons/editpaste Alt+P false Enter the message you want to sign here Enter the message you want to sign here Signature Qt::PlainText 0 + + Click "Sign Message" to generate signature + true true Copy the current signature to the system clipboard :/icons/editcopy:/icons/editcopy false Sign the message to prove you own this Bitcoin address Sign &Message :/icons/edit:/icons/edit false Reset all sign message fields Clear &All :/icons/remove:/icons/remove false Qt::Horizontal 40 48 75 true true Qt::Horizontal 40 48 &Verify Message Enter the receiver's address, message (ensure you copy line breaks, spaces, tabs, etc. exactly) and signature below to verify the message. Be careful not to read more into the signature than what is in the signed message itself, to avoid being tricked by a man-in-the-middle attack. Note that this only proves the signing party receives with the address, it cannot prove sendership of any transaction! Qt::PlainText Qt::AlignLeading|Qt::AlignLeft|Qt::AlignTop true 0 The Bitcoin address the message was signed with Choose previously used address :/icons/address-book:/icons/address-book Alt+A false The signed message to verify The signed message to verify The signature given when the message was signed The signature given when the message was signed Verify the message to ensure it was signed with the specified Bitcoin address Verify &Message :/icons/transaction_0:/icons/transaction_0 false Reset all verify message fields Clear &All :/icons/remove:/icons/remove false Qt::Horizontal 40 48 75 true true Qt::Horizontal 40 48 QValidatedLineEdit QLineEdit
qt/qvalidatedlineedit.h
diff --git a/src/qt/optionsdialog.cpp b/src/qt/optionsdialog.cpp index 9da8d7cd7..53da01611 100644 --- a/src/qt/optionsdialog.cpp +++ b/src/qt/optionsdialog.cpp @@ -1,425 +1,423 @@ // 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. #if defined(HAVE_CONFIG_H) #include #endif #include #include #include #include #include #include #include #include #include // for -dbcache defaults #include // for DEFAULT_SCRIPTCHECK_THREADS and MAX_SCRIPTCHECK_THREADS #include #include #include #include #include #include #include OptionsDialog::OptionsDialog(QWidget *parent, bool enableWallet) : QDialog(parent), ui(new Ui::OptionsDialog), model(nullptr), mapper(nullptr) { ui->setupUi(this); /* Main elements init */ ui->databaseCache->setMinimum(nMinDbCache); ui->databaseCache->setMaximum(nMaxDbCache); ui->threadsScriptVerif->setMinimum(-GetNumCores()); ui->threadsScriptVerif->setMaximum(MAX_SCRIPTCHECK_THREADS); ui->pruneWarning->setVisible(false); ui->pruneWarning->setStyleSheet("QLabel { color: red; }"); ui->pruneSize->setEnabled(false); connect(ui->prune, &QPushButton::toggled, ui->pruneSize, &QWidget::setEnabled); /* Network elements init */ #ifndef USE_UPNP ui->mapPortUpnp->setEnabled(false); #endif ui->proxyIp->setEnabled(false); ui->proxyPort->setEnabled(false); ui->proxyPort->setValidator(new QIntValidator(1, 65535, this)); ui->proxyIpTor->setEnabled(false); ui->proxyPortTor->setEnabled(false); ui->proxyPortTor->setValidator(new QIntValidator(1, 65535, this)); connect(ui->connectSocks, &QPushButton::toggled, ui->proxyIp, &QWidget::setEnabled); connect(ui->connectSocks, &QPushButton::toggled, ui->proxyPort, &QWidget::setEnabled); connect(ui->connectSocks, &QPushButton::toggled, this, &OptionsDialog::updateProxyValidationState); connect(ui->connectSocksTor, &QPushButton::toggled, ui->proxyIpTor, &QWidget::setEnabled); connect(ui->connectSocksTor, &QPushButton::toggled, ui->proxyPortTor, &QWidget::setEnabled); connect(ui->connectSocksTor, &QPushButton::toggled, this, &OptionsDialog::updateProxyValidationState); /* Window elements init */ #ifdef Q_OS_MAC /* remove Window tab on Mac */ ui->tabWidget->removeTab(ui->tabWidget->indexOf(ui->tabWindow)); /* hide launch at startup option on macOS */ ui->bitcoinAtStartup->setVisible(false); ui->verticalLayout_Main->removeWidget(ui->bitcoinAtStartup); ui->verticalLayout_Main->removeItem(ui->horizontalSpacer_0_Main); #endif /* remove Wallet tab in case of -disablewallet */ if (!enableWallet) { ui->tabWidget->removeTab(ui->tabWidget->indexOf(ui->tabWallet)); } /* Display elements init */ QDir translations(":translations"); ui->bitcoinAtStartup->setToolTip( ui->bitcoinAtStartup->toolTip().arg(PACKAGE_NAME)); ui->bitcoinAtStartup->setText( ui->bitcoinAtStartup->text().arg(PACKAGE_NAME)); ui->openBitcoinConfButton->setToolTip( ui->openBitcoinConfButton->toolTip().arg(PACKAGE_NAME)); ui->lang->setToolTip(ui->lang->toolTip().arg(PACKAGE_NAME)); ui->lang->addItem(QString("(") + tr("default") + QString(")"), QVariant("")); for (const QString &langStr : translations.entryList()) { QLocale locale(langStr); /** check if the locale name consists of 2 parts (language_country) */ if (langStr.contains("_")) { /** display language strings as "native language - native country * (locale name)", e.g. "Deutsch - Deutschland (de)" */ ui->lang->addItem(locale.nativeLanguageName() + QString(" - ") + locale.nativeCountryName() + QString(" (") + langStr + QString(")"), QVariant(langStr)); } else { /** display language strings as "native language (locale name)", * e.g. "Deutsch (de)" */ ui->lang->addItem(locale.nativeLanguageName() + QString(" (") + langStr + QString(")"), QVariant(langStr)); } } - ui->thirdPartyTxUrls->setPlaceholderText("https://example.com/tx/%s"); - ui->unit->setModel(new BitcoinUnits(this)); /* Widget-to-option mapper */ mapper = new QDataWidgetMapper(this); mapper->setSubmitPolicy(QDataWidgetMapper::ManualSubmit); mapper->setOrientation(Qt::Vertical); GUIUtil::ItemDelegate *delegate = new GUIUtil::ItemDelegate(mapper); connect(delegate, &GUIUtil::ItemDelegate::keyEscapePressed, this, &OptionsDialog::reject); mapper->setItemDelegate(delegate); /* setup/change UI elements when proxy IPs are invalid/valid */ ui->proxyIp->setCheckValidator(new ProxyAddressValidator(parent)); ui->proxyIpTor->setCheckValidator(new ProxyAddressValidator(parent)); connect(ui->proxyIp, &QValidatedLineEdit::validationDidChange, this, &OptionsDialog::updateProxyValidationState); connect(ui->proxyIpTor, &QValidatedLineEdit::validationDidChange, this, &OptionsDialog::updateProxyValidationState); connect(ui->proxyPort, &QLineEdit::textChanged, this, &OptionsDialog::updateProxyValidationState); connect(ui->proxyPortTor, &QLineEdit::textChanged, this, &OptionsDialog::updateProxyValidationState); if (!QSystemTrayIcon::isSystemTrayAvailable()) { ui->hideTrayIcon->setChecked(true); ui->hideTrayIcon->setEnabled(false); ui->minimizeToTray->setChecked(false); ui->minimizeToTray->setEnabled(false); } } OptionsDialog::~OptionsDialog() { delete ui; } void OptionsDialog::setModel(OptionsModel *_model) { this->model = _model; if (_model) { /* check if client restart is needed and show persistent message */ if (_model->isRestartRequired()) { showRestartWarning(true); } // Prune values are in GB to be consistent with intro.cpp static constexpr uint64_t nMinDiskSpace = (MIN_DISK_SPACE_FOR_BLOCK_FILES / GB_BYTES) + (MIN_DISK_SPACE_FOR_BLOCK_FILES % GB_BYTES) ? 1 : 0; ui->pruneSize->setRange(nMinDiskSpace, std::numeric_limits::max()); QString strLabel = _model->getOverriddenByCommandLine(); if (strLabel.isEmpty()) { strLabel = tr("none"); } ui->overriddenByCommandLineLabel->setText(strLabel); mapper->setModel(_model); setMapper(); mapper->toFirst(); updateDefaultProxyNets(); } /* warn when one of the following settings changes by user action (placed * here so init via mapper doesn't trigger them) */ /* Main */ connect(ui->prune, &QCheckBox::clicked, this, &OptionsDialog::showRestartWarning); connect(ui->prune, &QCheckBox::clicked, this, &OptionsDialog::togglePruneWarning); connect(ui->pruneSize, static_cast(&QSpinBox::valueChanged), this, &OptionsDialog::showRestartWarning); connect(ui->databaseCache, static_cast(&QSpinBox::valueChanged), this, &OptionsDialog::showRestartWarning); connect(ui->threadsScriptVerif, static_cast(&QSpinBox::valueChanged), this, &OptionsDialog::showRestartWarning); /* Wallet */ connect(ui->spendZeroConfChange, &QCheckBox::clicked, this, &OptionsDialog::showRestartWarning); /* Network */ connect(ui->allowIncoming, &QCheckBox::clicked, this, &OptionsDialog::showRestartWarning); connect(ui->connectSocks, &QCheckBox::clicked, this, &OptionsDialog::showRestartWarning); connect(ui->connectSocksTor, &QCheckBox::clicked, this, &OptionsDialog::showRestartWarning); /* Display */ connect( ui->lang, static_cast(&QValueComboBox::valueChanged), [this] { showRestartWarning(); }); connect(ui->thirdPartyTxUrls, &QLineEdit::textChanged, [this] { showRestartWarning(); }); } void OptionsDialog::setCurrentTab(OptionsDialog::Tab tab) { QWidget *tab_widget = nullptr; if (tab == OptionsDialog::Tab::TAB_NETWORK) { tab_widget = ui->tabNetwork; } if (tab == OptionsDialog::Tab::TAB_MAIN) { tab_widget = ui->tabMain; } if (tab_widget && ui->tabWidget->currentWidget() != tab_widget) { ui->tabWidget->setCurrentWidget(tab_widget); } } void OptionsDialog::setMapper() { /* Main */ mapper->addMapping(ui->bitcoinAtStartup, OptionsModel::StartAtStartup); mapper->addMapping(ui->threadsScriptVerif, OptionsModel::ThreadsScriptVerif); mapper->addMapping(ui->databaseCache, OptionsModel::DatabaseCache); mapper->addMapping(ui->prune, OptionsModel::Prune); mapper->addMapping(ui->pruneSize, OptionsModel::PruneSize); /* Wallet */ mapper->addMapping(ui->spendZeroConfChange, OptionsModel::SpendZeroConfChange); mapper->addMapping(ui->coinControlFeatures, OptionsModel::CoinControlFeatures); /* Network */ mapper->addMapping(ui->mapPortUpnp, OptionsModel::MapPortUPnP); mapper->addMapping(ui->allowIncoming, OptionsModel::Listen); mapper->addMapping(ui->connectSocks, OptionsModel::ProxyUse); mapper->addMapping(ui->proxyIp, OptionsModel::ProxyIP); mapper->addMapping(ui->proxyPort, OptionsModel::ProxyPort); mapper->addMapping(ui->connectSocksTor, OptionsModel::ProxyUseTor); mapper->addMapping(ui->proxyIpTor, OptionsModel::ProxyIPTor); mapper->addMapping(ui->proxyPortTor, OptionsModel::ProxyPortTor); /* Window */ #ifndef Q_OS_MAC if (QSystemTrayIcon::isSystemTrayAvailable()) { mapper->addMapping(ui->hideTrayIcon, OptionsModel::HideTrayIcon); mapper->addMapping(ui->minimizeToTray, OptionsModel::MinimizeToTray); } mapper->addMapping(ui->minimizeOnClose, OptionsModel::MinimizeOnClose); #endif /* Display */ mapper->addMapping(ui->lang, OptionsModel::Language); mapper->addMapping(ui->unit, OptionsModel::DisplayUnit); mapper->addMapping(ui->thirdPartyTxUrls, OptionsModel::ThirdPartyTxUrls); } void OptionsDialog::setOkButtonState(bool fState) { ui->okButton->setEnabled(fState); } void OptionsDialog::on_resetButton_clicked() { if (model) { // confirmation dialog QMessageBox::StandardButton btnRetVal = QMessageBox::question( this, tr("Confirm options reset"), tr("Client restart required to activate changes.") + "

" + tr("Client will be shut down. Do you want to proceed?"), QMessageBox::Yes | QMessageBox::Cancel, QMessageBox::Cancel); if (btnRetVal == QMessageBox::Cancel) { return; } /* reset all options and close GUI */ model->Reset(); QApplication::quit(); } } void OptionsDialog::on_openBitcoinConfButton_clicked() { /* explain the purpose of the config file */ QMessageBox::information( this, tr("Configuration options"), tr("The configuration file is used to specify advanced user options " "which override GUI settings. Additionally, any command-line " "options will override this configuration file.")); /* show an error if there was some problem opening the file */ if (!GUIUtil::openBitcoinConf()) { QMessageBox::critical( this, tr("Error"), tr("The configuration file could not be opened.")); } } void OptionsDialog::on_okButton_clicked() { mapper->submit(); accept(); updateDefaultProxyNets(); } void OptionsDialog::on_cancelButton_clicked() { reject(); } void OptionsDialog::on_hideTrayIcon_stateChanged(int fState) { if (fState) { ui->minimizeToTray->setChecked(false); ui->minimizeToTray->setEnabled(false); } else { ui->minimizeToTray->setEnabled(true); } } void OptionsDialog::togglePruneWarning(bool enabled) { ui->pruneWarning->setVisible(!ui->pruneWarning->isVisible()); } void OptionsDialog::showRestartWarning(bool fPersistent) { ui->statusLabel->setStyleSheet("QLabel { color: red; }"); if (fPersistent) { ui->statusLabel->setText( tr("Client restart required to activate changes.")); } else { ui->statusLabel->setText( tr("This change would require a client restart.")); // clear non-persistent status label after 10 seconds // TODO: should perhaps be a class attribute, if we extend the use of // statusLabel QTimer::singleShot(10000, this, &OptionsDialog::clearStatusLabel); } } void OptionsDialog::clearStatusLabel() { ui->statusLabel->clear(); if (model && model->isRestartRequired()) { showRestartWarning(true); } } void OptionsDialog::updateProxyValidationState() { QValidatedLineEdit *pUiProxyIp = ui->proxyIp; QValidatedLineEdit *otherProxyWidget = (pUiProxyIp == ui->proxyIpTor) ? ui->proxyIp : ui->proxyIpTor; if (pUiProxyIp->isValid() && (!ui->proxyPort->isEnabled() || ui->proxyPort->text().toInt() > 0) && (!ui->proxyPortTor->isEnabled() || ui->proxyPortTor->text().toInt() > 0)) { // Only enable ok button if both proxys are valid setOkButtonState(otherProxyWidget->isValid()); clearStatusLabel(); } else { setOkButtonState(false); ui->statusLabel->setStyleSheet("QLabel { color: red; }"); ui->statusLabel->setText(tr("The supplied proxy address is invalid.")); } } void OptionsDialog::updateDefaultProxyNets() { proxyType proxy; std::string strProxy; QString strDefaultProxyGUI; model->node().getProxy(NET_IPV4, proxy); strProxy = proxy.proxy.ToStringIP() + ":" + proxy.proxy.ToStringPort(); strDefaultProxyGUI = ui->proxyIp->text() + ":" + ui->proxyPort->text(); (strProxy == strDefaultProxyGUI.toStdString()) ? ui->proxyReachIPv4->setChecked(true) : ui->proxyReachIPv4->setChecked(false); model->node().getProxy(NET_IPV6, proxy); strProxy = proxy.proxy.ToStringIP() + ":" + proxy.proxy.ToStringPort(); strDefaultProxyGUI = ui->proxyIp->text() + ":" + ui->proxyPort->text(); (strProxy == strDefaultProxyGUI.toStdString()) ? ui->proxyReachIPv6->setChecked(true) : ui->proxyReachIPv6->setChecked(false); model->node().getProxy(NET_ONION, proxy); strProxy = proxy.proxy.ToStringIP() + ":" + proxy.proxy.ToStringPort(); strDefaultProxyGUI = ui->proxyIp->text() + ":" + ui->proxyPort->text(); (strProxy == strDefaultProxyGUI.toStdString()) ? ui->proxyReachTor->setChecked(true) : ui->proxyReachTor->setChecked(false); } ProxyAddressValidator::ProxyAddressValidator(QObject *parent) : QValidator(parent) {} QValidator::State ProxyAddressValidator::validate(QString &input, int &pos) const { Q_UNUSED(pos); // Validate the proxy CService serv( LookupNumeric(input.toStdString().c_str(), DEFAULT_GUI_PROXY_PORT)); proxyType addrProxy = proxyType(serv, true); if (addrProxy.IsValid()) { return QValidator::Acceptable; } return QValidator::Invalid; } diff --git a/src/qt/sendcoinsentry.cpp b/src/qt/sendcoinsentry.cpp index 63aa9402c..b188c33d7 100644 --- a/src/qt/sendcoinsentry.cpp +++ b/src/qt/sendcoinsentry.cpp @@ -1,312 +1,310 @@ // 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. #if defined(HAVE_CONFIG_H) #include #endif #include #include #include #include #include #include #include #include #include #include #include SendCoinsEntry::SendCoinsEntry(const PlatformStyle *_platformStyle, WalletModel *_model, QWidget *parent) : QStackedWidget(parent), ui(new Ui::SendCoinsEntry), model(_model), platformStyle(_platformStyle) { ui->setupUi(this); ui->addressBookButton->setIcon( platformStyle->SingleColorIcon(":/icons/address-book")); ui->pasteButton->setIcon( platformStyle->SingleColorIcon(":/icons/editpaste")); ui->deleteButton->setIcon(platformStyle->SingleColorIcon(":/icons/remove")); ui->deleteButton_is->setIcon( platformStyle->SingleColorIcon(":/icons/remove")); ui->deleteButton_s->setIcon( platformStyle->SingleColorIcon(":/icons/remove")); setCurrentWidget(ui->SendCoins); if (platformStyle->getUseExtraSpacing()) { ui->payToLayout->setSpacing(4); } - ui->addAsLabel->setPlaceholderText( - tr("Enter a label for this address to add it to your address book")); // normal bitcoin address field GUIUtil::setupAddressWidget(ui->payTo, this); // just a label for displaying bitcoin address(es) ui->payTo_is->setFont(GUIUtil::fixedPitchFont()); // Connect signals connect(ui->payAmount, &BitcoinAmountField::valueChanged, this, &SendCoinsEntry::payAmountChanged); connect(ui->checkboxSubtractFeeFromAmount, &QCheckBox::toggled, this, &SendCoinsEntry::subtractFeeFromAmountChanged); connect(ui->deleteButton, &QPushButton::clicked, this, &SendCoinsEntry::deleteClicked); connect(ui->deleteButton_is, &QPushButton::clicked, this, &SendCoinsEntry::deleteClicked); connect(ui->deleteButton_s, &QPushButton::clicked, this, &SendCoinsEntry::deleteClicked); connect(ui->useAvailableBalanceButton, &QPushButton::clicked, this, &SendCoinsEntry::useAvailableBalanceClicked); // Set the model properly. setModel(model); } SendCoinsEntry::~SendCoinsEntry() { delete ui; } void SendCoinsEntry::on_pasteButton_clicked() { // Paste text from clipboard into recipient field ui->payTo->setText(QApplication::clipboard()->text()); } void SendCoinsEntry::on_addressBookButton_clicked() { if (!model) { return; } AddressBookPage dlg(platformStyle, AddressBookPage::ForSelection, AddressBookPage::SendingTab, this); dlg.setModel(model->getAddressTableModel()); if (dlg.exec()) { ui->payTo->setText(dlg.getReturnValue()); ui->payAmount->setFocus(); } } void SendCoinsEntry::on_payTo_textChanged(const QString &address) { updateLabel(address); } void SendCoinsEntry::setModel(WalletModel *_model) { this->model = _model; if (_model) { ui->messageTextLabel->setToolTip( tr("A message that was attached to the %1 URI which will be stored " "with the transaction for your reference. Note: This message " "will not be sent over the Bitcoin network.") .arg(QString::fromStdString( _model->getChainParams().CashAddrPrefix()))); } if (_model && _model->getOptionsModel()) { connect(_model->getOptionsModel(), &OptionsModel::displayUnitChanged, this, &SendCoinsEntry::updateDisplayUnit); } clear(); } void SendCoinsEntry::clear() { // clear UI elements for normal payment ui->payTo->clear(); ui->addAsLabel->clear(); ui->payAmount->clear(); ui->checkboxSubtractFeeFromAmount->setCheckState(Qt::Unchecked); ui->messageTextLabel->clear(); ui->messageTextLabel->hide(); ui->messageLabel->hide(); // clear UI elements for unauthenticated payment request ui->payTo_is->clear(); ui->memoTextLabel_is->clear(); ui->payAmount_is->clear(); // clear UI elements for authenticated payment request ui->payTo_s->clear(); ui->memoTextLabel_s->clear(); ui->payAmount_s->clear(); // update the display unit, to not use the default ("BCH") updateDisplayUnit(); } void SendCoinsEntry::checkSubtractFeeFromAmount() { ui->checkboxSubtractFeeFromAmount->setChecked(true); } void SendCoinsEntry::deleteClicked() { Q_EMIT removeEntry(this); } void SendCoinsEntry::useAvailableBalanceClicked() { Q_EMIT useAvailableBalance(this); } bool SendCoinsEntry::validate(interfaces::Node &node) { if (!model) { return false; } // Check input validity bool retval = true; #ifdef ENABLE_BIP70 // Skip checks for payment request if (recipient.paymentRequest.IsInitialized()) { return retval; } #endif if (!model->validateAddress(ui->payTo->text())) { ui->payTo->setValid(false); retval = false; } if (!ui->payAmount->validate()) { retval = false; } // Sending a zero amount is invalid if (ui->payAmount->value(nullptr) <= Amount::zero()) { ui->payAmount->setValid(false); retval = false; } // Reject dust outputs: if (retval && GUIUtil::isDust(node, ui->payTo->text(), ui->payAmount->value(), model->getChainParams())) { ui->payAmount->setValid(false); retval = false; } return retval; } SendCoinsRecipient SendCoinsEntry::getValue() { #ifdef ENABLE_BIP70 // Payment request if (recipient.paymentRequest.IsInitialized()) { return recipient; } #endif // Normal payment recipient.address = ui->payTo->text(); recipient.label = ui->addAsLabel->text(); recipient.amount = ui->payAmount->value(); recipient.message = ui->messageTextLabel->text(); recipient.fSubtractFeeFromAmount = (ui->checkboxSubtractFeeFromAmount->checkState() == Qt::Checked); return recipient; } QWidget *SendCoinsEntry::setupTabChain(QWidget *prev) { QWidget::setTabOrder(prev, ui->payTo); QWidget::setTabOrder(ui->payTo, ui->addAsLabel); QWidget *w = ui->payAmount->setupTabChain(ui->addAsLabel); QWidget::setTabOrder(w, ui->checkboxSubtractFeeFromAmount); QWidget::setTabOrder(ui->checkboxSubtractFeeFromAmount, ui->addressBookButton); QWidget::setTabOrder(ui->addressBookButton, ui->pasteButton); QWidget::setTabOrder(ui->pasteButton, ui->deleteButton); return ui->deleteButton; } void SendCoinsEntry::setValue(const SendCoinsRecipient &value) { recipient = value; #ifdef ENABLE_BIP70 // payment request if (recipient.paymentRequest.IsInitialized()) { // unauthenticated if (recipient.authenticatedMerchant.isEmpty()) { ui->payTo_is->setText(recipient.address); ui->memoTextLabel_is->setText(recipient.message); ui->payAmount_is->setValue(recipient.amount); ui->payAmount_is->setReadOnly(true); setCurrentWidget(ui->SendCoins_UnauthenticatedPaymentRequest); } // authenticated else { ui->payTo_s->setText(recipient.authenticatedMerchant); ui->memoTextLabel_s->setText(recipient.message); ui->payAmount_s->setValue(recipient.amount); ui->payAmount_s->setReadOnly(true); setCurrentWidget(ui->SendCoins_AuthenticatedPaymentRequest); } } // normal payment else #endif { // message ui->messageTextLabel->setText(recipient.message); ui->messageTextLabel->setVisible(!recipient.message.isEmpty()); ui->messageLabel->setVisible(!recipient.message.isEmpty()); ui->addAsLabel->clear(); // this may set a label from addressbook ui->payTo->setText(recipient.address); // if a label had been set from the addressbook, don't overwrite with an // empty label if (!recipient.label.isEmpty()) { ui->addAsLabel->setText(recipient.label); } ui->payAmount->setValue(recipient.amount); } } void SendCoinsEntry::setAddress(const QString &address) { ui->payTo->setText(address); ui->payAmount->setFocus(); } void SendCoinsEntry::setAmount(const Amount amount) { ui->payAmount->setValue(amount); } bool SendCoinsEntry::isClear() { return ui->payTo->text().isEmpty() && ui->payTo_is->text().isEmpty() && ui->payTo_s->text().isEmpty(); } void SendCoinsEntry::setFocus() { ui->payTo->setFocus(); } void SendCoinsEntry::updateDisplayUnit() { if (model && model->getOptionsModel()) { // Update payAmount with the current unit ui->payAmount->setDisplayUnit( model->getOptionsModel()->getDisplayUnit()); ui->payAmount_is->setDisplayUnit( model->getOptionsModel()->getDisplayUnit()); ui->payAmount_s->setDisplayUnit( model->getOptionsModel()->getDisplayUnit()); } } bool SendCoinsEntry::updateLabel(const QString &address) { if (!model) { return false; } // Fill in label from address book, if address has an associated label QString associatedLabel = model->getAddressTableModel()->labelForAddress(address); if (!associatedLabel.isEmpty()) { ui->addAsLabel->setText(associatedLabel); return true; } return false; } diff --git a/src/qt/signverifymessagedialog.cpp b/src/qt/signverifymessagedialog.cpp index eb7f20563..70f466aa1 100644 --- a/src/qt/signverifymessagedialog.cpp +++ b/src/qt/signverifymessagedialog.cpp @@ -1,279 +1,276 @@ // 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. #include #include #include #include #include #include #include #include // For MessageSign(), MessageVerify() #include #include #include SignVerifyMessageDialog::SignVerifyMessageDialog( const PlatformStyle *_platformStyle, QWidget *parent) : QDialog(parent), ui(new Ui::SignVerifyMessageDialog), model(nullptr), platformStyle(_platformStyle) { ui->setupUi(this); ui->addressBookButton_SM->setIcon( platformStyle->SingleColorIcon(":/icons/address-book")); ui->pasteButton_SM->setIcon( platformStyle->SingleColorIcon(":/icons/editpaste")); ui->copySignatureButton_SM->setIcon( platformStyle->SingleColorIcon(":/icons/editcopy")); ui->signMessageButton_SM->setIcon( platformStyle->SingleColorIcon(":/icons/edit")); ui->clearButton_SM->setIcon( platformStyle->SingleColorIcon(":/icons/remove")); ui->addressBookButton_VM->setIcon( platformStyle->SingleColorIcon(":/icons/address-book")); ui->verifyMessageButton_VM->setIcon( platformStyle->SingleColorIcon(":/icons/transaction_0")); ui->clearButton_VM->setIcon( platformStyle->SingleColorIcon(":/icons/remove")); - ui->signatureOut_SM->setPlaceholderText( - tr("Click \"Sign Message\" to generate signature")); - GUIUtil::setupAddressWidget(ui->addressIn_SM, this); GUIUtil::setupAddressWidget(ui->addressIn_VM, this); ui->addressIn_SM->installEventFilter(this); ui->messageIn_SM->installEventFilter(this); ui->signatureOut_SM->installEventFilter(this); ui->addressIn_VM->installEventFilter(this); ui->messageIn_VM->installEventFilter(this); ui->signatureIn_VM->installEventFilter(this); ui->signatureOut_SM->setFont(GUIUtil::fixedPitchFont()); ui->signatureIn_VM->setFont(GUIUtil::fixedPitchFont()); } SignVerifyMessageDialog::~SignVerifyMessageDialog() { delete ui; } void SignVerifyMessageDialog::setModel(WalletModel *_model) { this->model = _model; } void SignVerifyMessageDialog::setAddress_SM(const QString &address) { ui->addressIn_SM->setText(address); ui->messageIn_SM->setFocus(); } void SignVerifyMessageDialog::setAddress_VM(const QString &address) { ui->addressIn_VM->setText(address); ui->messageIn_VM->setFocus(); } void SignVerifyMessageDialog::showTab_SM(bool fShow) { ui->tabWidget->setCurrentIndex(0); if (fShow) { this->show(); } } void SignVerifyMessageDialog::showTab_VM(bool fShow) { ui->tabWidget->setCurrentIndex(1); if (fShow) { this->show(); } } void SignVerifyMessageDialog::on_addressBookButton_SM_clicked() { if (model && model->getAddressTableModel()) { AddressBookPage dlg(platformStyle, AddressBookPage::ForSelection, AddressBookPage::ReceivingTab, this); dlg.setModel(model->getAddressTableModel()); if (dlg.exec()) { setAddress_SM(dlg.getReturnValue()); } } } void SignVerifyMessageDialog::on_pasteButton_SM_clicked() { setAddress_SM(QApplication::clipboard()->text()); } void SignVerifyMessageDialog::on_signMessageButton_SM_clicked() { if (!model) { return; } /* Clear old signature to ensure users don't get confused on error with an * old signature displayed */ ui->signatureOut_SM->clear(); CTxDestination destination = DecodeDestination( ui->addressIn_SM->text().toStdString(), model->getChainParams()); if (!IsValidDestination(destination)) { ui->statusLabel_SM->setStyleSheet("QLabel { color: red; }"); ui->statusLabel_SM->setText( tr("The entered address is invalid.") + QString(" ") + tr("Please check the address and try again.")); return; } const PKHash *pkhash = boost::get(&destination); if (!pkhash) { ui->addressIn_SM->setValid(false); ui->statusLabel_SM->setStyleSheet("QLabel { color: red; }"); ui->statusLabel_SM->setText( tr("The entered address does not refer to a key.") + QString(" ") + tr("Please check the address and try again.")); return; } WalletModel::UnlockContext ctx(model->requestUnlock()); if (!ctx.isValid()) { ui->statusLabel_SM->setStyleSheet("QLabel { color: red; }"); ui->statusLabel_SM->setText(tr("Wallet unlock was cancelled.")); return; } const std::string &message = ui->messageIn_SM->document()->toPlainText().toStdString(); std::string signature; SigningResult res = model->wallet().signMessage(message, *pkhash, signature); QString error; switch (res) { case SigningResult::OK: error = tr("No error"); break; case SigningResult::PRIVATE_KEY_NOT_AVAILABLE: error = tr("Private key for the entered address is not available."); break; case SigningResult::SIGNING_FAILED: error = tr("Message signing failed."); break; // no default case, so the compiler can warn about missing cases } if (res != SigningResult::OK) { ui->statusLabel_SM->setStyleSheet("QLabel { color: red; }"); ui->statusLabel_SM->setText(QString("") + error + QString("")); return; } ui->statusLabel_SM->setStyleSheet("QLabel { color: green; }"); ui->statusLabel_SM->setText(QString("") + tr("Message signed.") + QString("")); ui->signatureOut_SM->setText(QString::fromStdString(signature)); } void SignVerifyMessageDialog::on_copySignatureButton_SM_clicked() { GUIUtil::setClipboard(ui->signatureOut_SM->text()); } void SignVerifyMessageDialog::on_clearButton_SM_clicked() { ui->addressIn_SM->clear(); ui->messageIn_SM->clear(); ui->signatureOut_SM->clear(); ui->statusLabel_SM->clear(); ui->addressIn_SM->setFocus(); } void SignVerifyMessageDialog::on_addressBookButton_VM_clicked() { if (model && model->getAddressTableModel()) { AddressBookPage dlg(platformStyle, AddressBookPage::ForSelection, AddressBookPage::SendingTab, this); dlg.setModel(model->getAddressTableModel()); if (dlg.exec()) { setAddress_VM(dlg.getReturnValue()); } } } void SignVerifyMessageDialog::on_verifyMessageButton_VM_clicked() { const std::string &address = ui->addressIn_VM->text().toStdString(); const std::string &signature = ui->signatureIn_VM->text().toStdString(); const std::string &message = ui->messageIn_VM->document()->toPlainText().toStdString(); const auto result = MessageVerify(model->getChainParams(), address, signature, message); if (result == MessageVerificationResult::OK) { ui->statusLabel_VM->setStyleSheet("QLabel { color: green; }"); } else { ui->statusLabel_VM->setStyleSheet("QLabel { color: red; }"); } switch (result) { case MessageVerificationResult::OK: ui->statusLabel_VM->setText(QString("") + tr("Message verified.") + QString("")); return; case MessageVerificationResult::ERR_INVALID_ADDRESS: ui->statusLabel_VM->setText( tr("The entered address is invalid.") + QString(" ") + tr("Please check the address and try again.")); return; case MessageVerificationResult::ERR_ADDRESS_NO_KEY: ui->addressIn_VM->setValid(false); ui->statusLabel_VM->setText( tr("The entered address does not refer to a key.") + QString(" ") + tr("Please check the address and try again.")); return; case MessageVerificationResult::ERR_MALFORMED_SIGNATURE: ui->signatureIn_VM->setValid(false); ui->statusLabel_VM->setText( tr("The signature could not be decoded.") + QString(" ") + tr("Please check the signature and try again.")); return; case MessageVerificationResult::ERR_PUBKEY_NOT_RECOVERED: ui->signatureIn_VM->setValid(false); ui->statusLabel_VM->setText( tr("The signature did not match the message digest.") + QString(" ") + tr("Please check the signature and try again.")); return; case MessageVerificationResult::ERR_NOT_SIGNED: ui->statusLabel_VM->setText(QString("") + tr("Message verification failed.") + QString("")); return; } } void SignVerifyMessageDialog::on_clearButton_VM_clicked() { ui->addressIn_VM->clear(); ui->signatureIn_VM->clear(); ui->messageIn_VM->clear(); ui->statusLabel_VM->clear(); ui->addressIn_VM->setFocus(); } bool SignVerifyMessageDialog::eventFilter(QObject *object, QEvent *event) { if (event->type() == QEvent::MouseButtonPress || event->type() == QEvent::FocusIn) { if (ui->tabWidget->currentIndex() == 0) { /* Clear status message on focus change */ ui->statusLabel_SM->clear(); /* Select generated signature */ if (object == ui->signatureOut_SM) { ui->signatureOut_SM->selectAll(); return true; } } else if (ui->tabWidget->currentIndex() == 1) { /* Clear status message on focus change */ ui->statusLabel_VM->clear(); } } return QDialog::eventFilter(object, event); }