aboutsummaryrefslogtreecommitdiff
path: root/src/qt/sendcoinsdialog.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'src/qt/sendcoinsdialog.cpp')
-rw-r--r--src/qt/sendcoinsdialog.cpp71
1 files changed, 47 insertions, 24 deletions
diff --git a/src/qt/sendcoinsdialog.cpp b/src/qt/sendcoinsdialog.cpp
index 2718392940..579ef0c3fd 100644
--- a/src/qt/sendcoinsdialog.cpp
+++ b/src/qt/sendcoinsdialog.cpp
@@ -1,4 +1,4 @@
-// Copyright (c) 2011-2020 The Bitcoin Core developers
+// Copyright (c) 2011-2021 The Bitcoin Core developers
// Distributed under the MIT software license, see the accompanying
// file COPYING or http://www.opensource.org/licenses/mit-license.php.
@@ -24,17 +24,24 @@
#include <node/ui_interface.h>
#include <policy/fees.h>
#include <txmempool.h>
+#include <validation.h>
#include <wallet/coincontrol.h>
#include <wallet/fees.h>
#include <wallet/wallet.h>
-#include <validation.h>
+#include <array>
+#include <chrono>
+#include <fstream>
+#include <memory>
#include <QFontMetrics>
#include <QScrollBar>
#include <QSettings>
#include <QTextDocument>
+using wallet::CCoinControl;
+using wallet::DEFAULT_PAY_TX_FEE;
+
static constexpr std::array confTargets{2, 4, 6, 12, 24, 48, 144, 504, 1008};
int getConfTargetForIndex(int index) {
if (index+1 > static_cast<int>(confTargets.size())) {
@@ -324,16 +331,22 @@ bool SendCoinsDialog::PrepareSendText(QString& question_string, QString& informa
formatted.append(recipientElement);
}
- if (model->wallet().privateKeysDisabled() && !model->wallet().hasExternalSigner()) {
- question_string.append(tr("Do you want to draft this transaction?"));
- } else {
- question_string.append(tr("Are you sure you want to send?"));
- }
-
+ /*: Message displayed when attempting to create a transaction. Cautionary text to prompt the user to verify
+ that the displayed transaction details represent the transaction the user intends to create. */
+ question_string.append(tr("Do you want to create this transaction?"));
question_string.append("<br /><span style='font-size:10pt;'>");
if (model->wallet().privateKeysDisabled() && !model->wallet().hasExternalSigner()) {
+ /*: Text to inform a user attempting to create a transaction of their current options. At this stage,
+ a user can only create a PSBT. This string is displayed when private keys are disabled and an external
+ signer is not available. */
question_string.append(tr("Please, review your transaction proposal. This will produce a Partially Signed Bitcoin Transaction (PSBT) which you can save or copy and then sign with e.g. an offline %1 wallet, or a PSBT-compatible hardware wallet.").arg(PACKAGE_NAME));
+ } else if (model->getOptionsModel()->getEnablePSBTControls()) {
+ /*: Text to inform a user attempting to create a transaction of their current options. At this stage,
+ a user can send their transaction or create a PSBT. This string is displayed when both private keys
+ and PSBT controls are enabled. */
+ question_string.append(tr("Please, review your transaction. You can create and send this transaction or create a Partially Signed Bitcoin Transaction (PSBT), which you can save or copy and then sign with, e.g., an offline %1 wallet, or a PSBT-compatible hardware wallet.").arg(PACKAGE_NAME));
} else {
+ /*: Text to prompt a user to review the details of the transaction they are attempting to send. */
question_string.append(tr("Please, review your transaction."));
}
question_string.append("</span>%1");
@@ -397,21 +410,20 @@ void SendCoinsDialog::sendButtonClicked([[maybe_unused]] bool checked)
if (!PrepareSendText(question_string, informative_text, detailed_text)) return;
assert(m_current_transaction);
- const QString confirmation = model->wallet().privateKeysDisabled() && !model->wallet().hasExternalSigner() ? tr("Confirm transaction proposal") : tr("Confirm send coins");
- const QString confirmButtonText = model->wallet().privateKeysDisabled() && !model->wallet().hasExternalSigner() ? tr("Create Unsigned") : tr("Sign and send");
- auto confirmationDialog = new SendConfirmationDialog(confirmation, question_string, informative_text, detailed_text, SEND_CONFIRM_DELAY, confirmButtonText, this);
+ const QString confirmation = tr("Confirm send coins");
+ auto confirmationDialog = new SendConfirmationDialog(confirmation, question_string, informative_text, detailed_text, SEND_CONFIRM_DELAY, !model->wallet().privateKeysDisabled(), model->getOptionsModel()->getEnablePSBTControls(), this);
confirmationDialog->setAttribute(Qt::WA_DeleteOnClose);
// TODO: Replace QDialog::exec() with safer QDialog::show().
const auto retval = static_cast<QMessageBox::StandardButton>(confirmationDialog->exec());
- if(retval != QMessageBox::Yes)
+ if(retval != QMessageBox::Yes && retval != QMessageBox::Save)
{
fNewRecipientAllowed = true;
return;
}
bool send_failure = false;
- if (model->wallet().privateKeysDisabled()) {
+ if (retval == QMessageBox::Save) {
CMutableTransaction mtx = CMutableTransaction{*(m_current_transaction->getWtx())};
PartiallySignedTransaction psbtx(mtx);
bool complete = false;
@@ -500,7 +512,7 @@ void SendCoinsDialog::sendButtonClicked([[maybe_unused]] bool checked)
if (filename.isEmpty()) {
return;
}
- std::ofstream out(filename.toLocal8Bit().data(), std::ofstream::out | std::ofstream::binary);
+ std::ofstream out{filename.toLocal8Bit().data(), std::ofstream::out | std::ofstream::binary};
out << ssTx.str();
out.close();
Q_EMIT message(tr("PSBT saved"), "PSBT saved to disk", CClientUIInterface::MSG_INFORMATION);
@@ -512,6 +524,7 @@ void SendCoinsDialog::sendButtonClicked([[maybe_unused]] bool checked)
assert(false);
} // msgBox.exec()
} else {
+ assert(!model->wallet().privateKeysDisabled());
// now send the prepared transaction
WalletModel::SendCoinsReturn sendStatus = model->sendCoins(*m_current_transaction);
// process sendStatus and on error generate message shown to user
@@ -917,7 +930,7 @@ void SendCoinsDialog::coinControlButtonClicked()
{
auto dlg = new CoinControlDialog(*m_coin_control, model, platformStyle);
connect(dlg, &QDialog::finished, this, &SendCoinsDialog::coinControlUpdateLabels);
- GUIUtil::ShowModalDialogAndDeleteOnClose(dlg);
+ GUIUtil::ShowModalDialogAsynchronously(dlg);
}
// Coin Control: checkbox custom change address
@@ -1031,8 +1044,8 @@ void SendCoinsDialog::coinControlUpdateLabels()
}
}
-SendConfirmationDialog::SendConfirmationDialog(const QString& title, const QString& text, const QString& informative_text, const QString& detailed_text, int _secDelay, const QString& _confirmButtonText, QWidget* parent)
- : QMessageBox(parent), secDelay(_secDelay), confirmButtonText(_confirmButtonText)
+SendConfirmationDialog::SendConfirmationDialog(const QString& title, const QString& text, const QString& informative_text, const QString& detailed_text, int _secDelay, bool enable_send, bool always_show_unsigned, QWidget* parent)
+ : QMessageBox(parent), secDelay(_secDelay), m_enable_send(enable_send)
{
setIcon(QMessageBox::Question);
setWindowTitle(title); // On macOS, the window title is ignored (as required by the macOS Guidelines).
@@ -1040,26 +1053,28 @@ SendConfirmationDialog::SendConfirmationDialog(const QString& title, const QStri
setInformativeText(informative_text);
setDetailedText(detailed_text);
setStandardButtons(QMessageBox::Yes | QMessageBox::Cancel);
+ if (always_show_unsigned || !enable_send) addButton(QMessageBox::Save);
setDefaultButton(QMessageBox::Cancel);
yesButton = button(QMessageBox::Yes);
if (confirmButtonText.isEmpty()) {
confirmButtonText = yesButton->text();
}
- updateYesButton();
+ m_psbt_button = button(QMessageBox::Save);
+ updateButtons();
connect(&countDownTimer, &QTimer::timeout, this, &SendConfirmationDialog::countDown);
}
int SendConfirmationDialog::exec()
{
- updateYesButton();
- countDownTimer.start(1000);
+ updateButtons();
+ countDownTimer.start(1s);
return QMessageBox::exec();
}
void SendConfirmationDialog::countDown()
{
secDelay--;
- updateYesButton();
+ updateButtons();
if(secDelay <= 0)
{
@@ -1067,16 +1082,24 @@ void SendConfirmationDialog::countDown()
}
}
-void SendConfirmationDialog::updateYesButton()
+void SendConfirmationDialog::updateButtons()
{
if(secDelay > 0)
{
yesButton->setEnabled(false);
- yesButton->setText(confirmButtonText + " (" + QString::number(secDelay) + ")");
+ yesButton->setText(confirmButtonText + (m_enable_send ? (" (" + QString::number(secDelay) + ")") : QString("")));
+ if (m_psbt_button) {
+ m_psbt_button->setEnabled(false);
+ m_psbt_button->setText(m_psbt_button_text + " (" + QString::number(secDelay) + ")");
+ }
}
else
{
- yesButton->setEnabled(true);
+ yesButton->setEnabled(m_enable_send);
yesButton->setText(confirmButtonText);
+ if (m_psbt_button) {
+ m_psbt_button->setEnabled(true);
+ m_psbt_button->setText(m_psbt_button_text);
+ }
}
}