diff --git a/src/qt/forms/receiverequestdialog.ui b/src/qt/forms/receiverequestdialog.ui
index 9f896ee3b..f6d472346 100644
--- a/src/qt/forms/receiverequestdialog.ui
+++ b/src/qt/forms/receiverequestdialog.ui
@@ -1,168 +1,326 @@
ReceiveRequestDialog
0
0
- 487
- 597
+ 413
+ 229
-
- -
-
-
-
- 0
- 0
-
-
-
-
- 300
- 320
-
-
-
- QR Code
+
+ Request payment to ...
+
+
+
+ QLayout::SetFixedSize
+
+
-
+
+
+ QR image
+
+
+ Qt::NoTextInteraction
+
+
+
+ -
+
+
+
+ 75
+ true
+
+
+
+ Payment information
+
+
+ Qt::NoTextInteraction
+
+
+
+ -
+
+
+
+ 75
+ true
+
+
+
+ URI:
Qt::PlainText
-
- Qt::AlignCenter
+
+ Qt::NoTextInteraction
+
+
+
+ -
+
+
+ bitcoin:BC1...
+
+
+ Qt::RichText
true
+
+ Qt::TextSelectableByMouse
+
+
+
+ -
+
+
+
+ 75
+ true
+
+
+
+ Address:
+
+
+ Qt::NoTextInteraction
+
- -
-
-
-
- 0
- 0
-
-
-
-
- 0
- 50
-
-
-
- QFrame::NoFrame
-
-
- QFrame::Plain
-
-
+
-
+
+
+ bc1...
+
+
+ Qt::PlainText
+
+
+ Qt::TextSelectableByMouse
+
+
+
+ -
+
+
+
+ 75
+ true
+
+
+
+ Amount:
+
+
+ Qt::NoTextInteraction
+
+
+
+ -
+
+
+ 0.00000000 BTC
+
+
+ Qt::PlainText
+
+
+ Qt::TextSelectableByMouse
+
+
+
+ -
+
+
+
+ 75
+ true
+
+
+
+ Label:
+
+
+ Qt::NoTextInteraction
+
+
+
+ -
+
+
+ label content
+
+
+ Qt::PlainText
+
+
+ true
+
+
+ Qt::TextSelectableByMouse
+
+
+
+ -
+
+
+
+ 75
+ true
+
+
+
+ Message:
+
+
+ Qt::NoTextInteraction
+
+
+
+ -
+
+
+ message content
+
+
+ Qt::PlainText
+
+
+ true
+
+
+ Qt::TextSelectableByMouse
+
+
+
+ -
+
+
+
+ 75
+ true
+
+
+
+ Wallet:
+
+
+ Qt::NoTextInteraction
+
+
+
+ -
+
+
+ wallet name
+
+
+ Qt::PlainText
+
+
true
- Qt::TextSelectableByKeyboard|Qt::TextSelectableByMouse
+ Qt::TextSelectableByMouse
- -
+
-
-
Copy &URI
false
-
Copy &Address
false
-
&Save Image...
false
-
Qt::Horizontal
40
20
-
+
+ Qt::StrongFocus
+
- QDialogButtonBox::Close
+ QDialogButtonBox::Ok
QRImageWidget
QLabel
+
+ buttonBox
+ btnCopyURI
+ btnCopyAddress
+ btnSaveAs
+
-
- buttonBox
- rejected()
- ReceiveRequestDialog
- reject()
-
-
- 452
- 573
-
-
- 243
- 298
-
-
-
buttonBox
accepted()
ReceiveRequestDialog
accept()
- 452
- 573
+ 135
+ 230
- 243
- 298
+ 135
+ 126
diff --git a/src/qt/receiverequestdialog.cpp b/src/qt/receiverequestdialog.cpp
index de327ba44..2e5d3407f 100644
--- a/src/qt/receiverequestdialog.cpp
+++ b/src/qt/receiverequestdialog.cpp
@@ -1,108 +1,108 @@
// Copyright (c) 2011-2016 The Bitcoin Core developers
// Copyright (c) 2017-2019 The Bitcoin developers
// Distributed under the MIT software license, see the accompanying
// file COPYING or http://www.opensource.org/licenses/mit-license.php.
#include
#include
#include
#include
#include
#include
#include
-#include
-#include
+#include
+#include
#if defined(HAVE_CONFIG_H)
#include /* for USE_QRCODE */
#endif
ReceiveRequestDialog::ReceiveRequestDialog(QWidget *parent)
: QDialog(parent), ui(new Ui::ReceiveRequestDialog), model(nullptr) {
ui->setupUi(this);
-
-#ifndef USE_QRCODE
- ui->btnSaveAs->setVisible(false);
- ui->lblQRCode->setVisible(false);
-#endif
-
- connect(ui->btnSaveAs, &QPushButton::clicked, ui->lblQRCode,
- &QRImageWidget::saveImage);
-
GUIUtil::handleCloseWindowShortcut(this);
}
ReceiveRequestDialog::~ReceiveRequestDialog() {
delete ui;
}
void ReceiveRequestDialog::setModel(WalletModel *_model) {
this->model = _model;
if (_model) {
connect(_model->getOptionsModel(), &OptionsModel::displayUnitChanged,
this, &ReceiveRequestDialog::update);
}
// update the display unit if necessary
update();
}
void ReceiveRequestDialog::setInfo(const SendCoinsRecipient &_info) {
this->info = _info;
- update();
-}
+ setWindowTitle(tr("Request payment to %1")
+ .arg(info.label.isEmpty() ? info.address : info.label));
+ QString uri = GUIUtil::formatBitcoinURI(info);
-void ReceiveRequestDialog::update() {
- if (!model) {
- return;
- }
- QString target = info.label;
- if (target.isEmpty()) {
- target = info.address;
+#ifdef USE_QRCODE
+ if (ui->qr_code->setQR(uri, info.address)) {
+ connect(ui->btnSaveAs, &QPushButton::clicked, ui->qr_code,
+ &QRImageWidget::saveImage);
+ } else {
+ ui->btnSaveAs->setEnabled(false);
}
- setWindowTitle(tr("Request payment to %1").arg(target));
+#else
+ ui->btnSaveAs->hide();
+ ui->qr_code->hide();
+#endif
+
+ ui->uri_content->setText("" +
+ GUIUtil::HtmlEscape(uri) + "");
+ ui->address_content->setText(info.address);
+
+ if (info.amount == Amount::zero()) {
+ ui->amount_tag->hide();
+ ui->amount_content->hide();
+ } // Amount is set in update() slot.
+ update();
- QString uri = GUIUtil::formatBitcoinURI(info);
- ui->btnSaveAs->setEnabled(false);
- QString html;
- html += "";
- html += "" + tr("Payment information") + "
";
- html += "" + tr("URI") + ": ";
- html += "" + GUIUtil::HtmlEscape(uri) + "
";
- html += "" + tr("Address") +
- ": " + GUIUtil::HtmlEscape(info.address) + "
";
- if (info.amount != Amount::zero()) {
- html += "" + tr("Amount") + ": " +
- BitcoinUnits::formatHtmlWithUnit(
- model->getOptionsModel()->getDisplayUnit(), info.amount) +
- "
";
- }
if (!info.label.isEmpty()) {
- html += "" + tr("Label") +
- ": " + GUIUtil::HtmlEscape(info.label) + "
";
+ ui->label_content->setText(info.label);
+ } else {
+ ui->label_tag->hide();
+ ui->label_content->hide();
}
+
if (!info.message.isEmpty()) {
- html += "" + tr("Message") +
- ": " + GUIUtil::HtmlEscape(info.message) + "
";
+ ui->message_content->setText(info.message);
+ } else {
+ ui->message_tag->hide();
+ ui->message_content->hide();
}
- if (model->isMultiwallet()) {
- html += "" + tr("Wallet") +
- ": " + GUIUtil::HtmlEscape(model->getWalletName()) + "
";
+
+ if (!model->getWalletName().isEmpty()) {
+ ui->wallet_content->setText(model->getWalletName());
+ } else {
+ ui->wallet_tag->hide();
+ ui->wallet_content->hide();
}
- ui->outUri->setText(html);
+}
- if (ui->lblQRCode->setQR(uri, info.address)) {
- ui->btnSaveAs->setEnabled(true);
+void ReceiveRequestDialog::update() {
+ if (!model) {
+ return;
}
+ ui->amount_content->setText(BitcoinUnits::formatWithUnit(
+ model->getOptionsModel()->getDisplayUnit(), info.amount));
}
void ReceiveRequestDialog::on_btnCopyURI_clicked() {
GUIUtil::setClipboard(GUIUtil::formatBitcoinURI(info));
}
void ReceiveRequestDialog::on_btnCopyAddress_clicked() {
GUIUtil::setClipboard(info.address);
}
diff --git a/src/qt/test/wallettests.cpp b/src/qt/test/wallettests.cpp
index 255463669..661124961 100644
--- a/src/qt/test/wallettests.cpp
+++ b/src/qt/test/wallettests.cpp
@@ -1,281 +1,315 @@
// Copyright (c) 2015-2021 The Bitcoin developers
// Distributed under the MIT software license, see the accompanying
// file COPYING or http://www.opensource.org/licenses/mit-license.php.
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
namespace {
//! Press "Yes" or "Cancel" buttons in modal send confirmation dialog.
void ConfirmSend(QString *text = nullptr, bool cancel = false) {
QTimer::singleShot(0, Qt::PreciseTimer, [text, cancel]() {
for (QWidget *widget : QApplication::topLevelWidgets()) {
if (widget->inherits("SendConfirmationDialog")) {
SendConfirmationDialog *dialog =
qobject_cast(widget);
if (text) {
*text = dialog->text();
}
QAbstractButton *button = dialog->button(
cancel ? QMessageBox::Cancel : QMessageBox::Yes);
button->setEnabled(true);
button->click();
}
}
});
}
//! Send coins to address and return txid.
TxId SendCoins(CWallet &wallet, SendCoinsDialog &sendCoinsDialog,
const CTxDestination &address, Amount amount) {
QVBoxLayout *entries = sendCoinsDialog.findChild("entries");
SendCoinsEntry *entry =
qobject_cast(entries->itemAt(0)->widget());
entry->findChild("payTo")->setText(
QString::fromStdString(EncodeCashAddr(address, Params())));
entry->findChild("payAmount")->setValue(amount);
TxId txid;
boost::signals2::scoped_connection c =
wallet.NotifyTransactionChanged.connect(
[&txid](CWallet *, const TxId &hash, ChangeType status) {
if (status == CT_NEW) {
txid = hash;
}
});
ConfirmSend();
bool invoked =
QMetaObject::invokeMethod(&sendCoinsDialog, "on_sendButton_clicked");
assert(invoked);
return txid;
}
//! Find index of txid in transaction list.
QModelIndex FindTx(const QAbstractItemModel &model, const uint256 &txid) {
QString hash = QString::fromStdString(txid.ToString());
int rows = model.rowCount({});
for (int row = 0; row < rows; ++row) {
QModelIndex index = model.index(row, 0, {});
if (model.data(index, TransactionTableModel::TxHashRole) == hash) {
return index;
}
}
return {};
}
//! Simple qt wallet tests.
//
// Test widgets can be debugged interactively calling show() on them and
// manually running the event loop, e.g.:
//
// sendCoinsDialog.show();
// QEventLoop().exec();
//
// This also requires overriding the default minimal Qt platform:
//
// QT_QPA_PLATFORM=xcb src/qt/test/test_bitcoin-qt # Linux
// QT_QPA_PLATFORM=windows src/qt/test/test_bitcoin-qt # Windows
// QT_QPA_PLATFORM=cocoa src/qt/test/test_bitcoin-qt # macOS
void TestGUI(interfaces::Node &node) {
// Set up wallet and chain with 105 blocks (5 mature blocks for spending).
TestChain100Setup test;
for (int i = 0; i < 5; ++i) {
test.CreateAndProcessBlock(
{}, GetScriptForRawPubKey(test.coinbaseKey.GetPubKey()));
}
node.setContext(&test.m_node);
std::shared_ptr wallet =
std::make_shared(node.context()->chain.get(), WalletLocation(),
CreateMockWalletDatabase());
bool firstRun;
wallet->LoadWallet(firstRun);
{
auto spk_man = wallet->GetOrCreateLegacyScriptPubKeyMan();
LOCK2(wallet->cs_wallet, spk_man->cs_KeyStore);
wallet->SetAddressBook(
GetDestinationForKey(test.coinbaseKey.GetPubKey(),
wallet->m_default_address_type),
"", "receive");
spk_man->AddKeyPubKey(test.coinbaseKey, test.coinbaseKey.GetPubKey());
wallet->SetLastBlockProcessed(105,
::ChainActive().Tip()->GetBlockHash());
}
{
WalletRescanReserver reserver(*wallet);
reserver.reserve();
CWallet::ScanResult result = wallet->ScanForWalletTransactions(
Params().GetConsensus().hashGenesisBlock, 0 /* block height */,
{} /* max height */, reserver, true /* fUpdate */);
QCOMPARE(result.status, CWallet::ScanResult::SUCCESS);
QCOMPARE(result.last_scanned_block,
::ChainActive().Tip()->GetBlockHash());
QVERIFY(result.last_failed_block.IsNull());
}
wallet->SetBroadcastTransactions(true);
// Create widgets for sending coins and listing transactions.
std::unique_ptr platformStyle(
PlatformStyle::instantiate("other"));
OptionsModel optionsModel;
ClientModel clientModel(node, &optionsModel);
AddWallet(wallet);
WalletModel walletModel(interfaces::MakeWallet(wallet), clientModel,
platformStyle.get());
RemoveWallet(wallet);
SendCoinsDialog sendCoinsDialog(platformStyle.get(), &walletModel);
{
// Check balance in send dialog
QLabel *balanceLabel =
sendCoinsDialog.findChild("labelBalance");
QString balanceText = balanceLabel->text();
int unit = walletModel.getOptionsModel()->getDisplayUnit();
Amount balance = walletModel.wallet().getBalance();
QString balanceComparison = BitcoinUnits::formatWithUnit(
unit, balance, false, BitcoinUnits::separatorAlways);
QCOMPARE(balanceText, balanceComparison);
}
// Send two transactions, and verify they are added to transaction list.
TransactionTableModel *transactionTableModel =
walletModel.getTransactionTableModel();
QCOMPARE(transactionTableModel->rowCount({}), 105);
TxId txid1 = SendCoins(*wallet.get(), sendCoinsDialog,
CTxDestination(PKHash()), 5 * COIN);
TxId txid2 = SendCoins(*wallet.get(), sendCoinsDialog,
CTxDestination(PKHash()), 10 * COIN);
QCOMPARE(transactionTableModel->rowCount({}), 107);
QVERIFY(FindTx(*transactionTableModel, txid1).isValid());
QVERIFY(FindTx(*transactionTableModel, txid2).isValid());
// Check current balance on OverviewPage
OverviewPage overviewPage(platformStyle.get());
overviewPage.setWalletModel(&walletModel);
QLabel *balanceLabel = overviewPage.findChild("labelBalance");
QString balanceText = balanceLabel->text().trimmed();
int unit = walletModel.getOptionsModel()->getDisplayUnit();
Amount balance = walletModel.wallet().getBalance();
QString balanceComparison = BitcoinUnits::formatWithUnit(
unit, balance, false, BitcoinUnits::separatorAlways);
QCOMPARE(balanceText, balanceComparison);
// Check Request Payment button
ReceiveCoinsDialog receiveCoinsDialog(platformStyle.get());
receiveCoinsDialog.setModel(&walletModel);
RecentRequestsTableModel *requestTableModel =
walletModel.getRecentRequestsTableModel();
// Label input
QLineEdit *labelInput =
receiveCoinsDialog.findChild("reqLabel");
labelInput->setText("TEST_LABEL_1");
// Amount input
BitcoinAmountField *amountInput =
receiveCoinsDialog.findChild("reqAmount");
amountInput->setValue(1 * SATOSHI);
// Message input
QLineEdit *messageInput =
receiveCoinsDialog.findChild("reqMessage");
messageInput->setText("TEST_MESSAGE_1");
int initialRowCount = requestTableModel->rowCount({});
QPushButton *requestPaymentButton =
receiveCoinsDialog.findChild("receiveButton");
requestPaymentButton->click();
for (QWidget *widget : QApplication::topLevelWidgets()) {
if (widget->inherits("ReceiveRequestDialog")) {
ReceiveRequestDialog *receiveRequestDialog =
qobject_cast(widget);
- QTextEdit *rlist =
- receiveRequestDialog->QObject::findChild("outUri");
- QString paymentText = rlist->toPlainText();
- QStringList paymentTextList = paymentText.split('\n');
- QCOMPARE(paymentTextList.at(0), QString("Payment information"));
- QVERIFY(paymentTextList.at(1).indexOf(QString("URI: ecregtest:")) !=
- -1);
- QVERIFY(paymentTextList.at(2).indexOf(QString("Address:")) != -1);
- QCOMPARE(paymentTextList.at(3),
- QString("Amount: 0.01 ") +
+ QCOMPARE(receiveRequestDialog
+ ->QObject::findChild("payment_header")
+ ->text(),
+ QString("Payment information"));
+ QCOMPARE(
+ receiveRequestDialog->QObject::findChild("uri_tag")
+ ->text(),
+ QString("URI:"));
+ QString uri = receiveRequestDialog
+ ->QObject::findChild("uri_content")
+ ->text();
+ QCOMPARE(uri.count("ecregtest:"), 2);
+ QCOMPARE(receiveRequestDialog
+ ->QObject::findChild("address_tag")
+ ->text(),
+ QString("Address:"));
+
+ QCOMPARE(uri.count("amount=0.01"), 2);
+ QCOMPARE(
+ receiveRequestDialog->QObject::findChild("amount_tag")
+ ->text(),
+ QString("Amount:"));
+ QCOMPARE(receiveRequestDialog
+ ->QObject::findChild("amount_content")
+ ->text(),
+ QString("0.01 ") +
QString::fromStdString(Currency::get().ticker));
- QCOMPARE(paymentTextList.at(4), QString("Label: TEST_LABEL_1"));
- QCOMPARE(paymentTextList.at(5), QString("Message: TEST_MESSAGE_1"));
+
+ QCOMPARE(uri.count("label=TEST_LABEL_1"), 2);
+ QCOMPARE(
+ receiveRequestDialog->QObject::findChild("label_tag")
+ ->text(),
+ QString("Label:"));
+ QCOMPARE(receiveRequestDialog
+ ->QObject::findChild("label_content")
+ ->text(),
+ QString("TEST_LABEL_1"));
+
+ QCOMPARE(uri.count("message=TEST_MESSAGE_1"), 2);
+ QCOMPARE(receiveRequestDialog
+ ->QObject::findChild("message_tag")
+ ->text(),
+ QString("Message:"));
+ QCOMPARE(receiveRequestDialog
+ ->QObject::findChild("message_content")
+ ->text(),
+ QString("TEST_MESSAGE_1"));
}
}
// Clear button
QPushButton *clearButton =
receiveCoinsDialog.findChild("clearButton");
clearButton->click();
QCOMPARE(labelInput->text(), QString(""));
QCOMPARE(amountInput->value(), Amount::zero());
QCOMPARE(messageInput->text(), QString(""));
// Check addition to history
int currentRowCount = requestTableModel->rowCount({});
QCOMPARE(currentRowCount, initialRowCount + 1);
// Check Remove button
QTableView *table =
receiveCoinsDialog.findChild("recentRequestsView");
table->selectRow(currentRowCount - 1);
QPushButton *removeRequestButton =
receiveCoinsDialog.findChild("removeRequestButton");
removeRequestButton->click();
QCOMPARE(requestTableModel->rowCount({}), currentRowCount - 1);
}
} // namespace
void WalletTests::walletTests() {
#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 WalletTests on mac build with 'minimal' platform set due "
"to Qt bugs. To run AppTests, invoke with 'QT_QPA_PLATFORM=cocoa "
"test_bitcoin-qt' on mac, or else use a linux or windows build.");
return;
}
#endif
TestGUI(m_node);
}