sendcoinsentry.cpp
1 // Copyright (c) 2011-2022 The Bitcoin Core developers 2 // Distributed under the MIT software license, see the accompanying 3 // file COPYING or http://www.opensource.org/licenses/mit-license.php. 4 5 #include <qt/sendcoinsentry.h> 6 #include <qt/forms/ui_sendcoinsentry.h> 7 8 #include <qt/addressbookpage.h> 9 #include <qt/addresstablemodel.h> 10 #include <qt/guiutil.h> 11 #include <qt/optionsmodel.h> 12 #include <qt/platformstyle.h> 13 #include <qt/walletmodel.h> 14 15 #include <QApplication> 16 #include <QClipboard> 17 18 SendCoinsEntry::SendCoinsEntry(const PlatformStyle *_platformStyle, QWidget *parent) : 19 QWidget(parent), 20 ui(new Ui::SendCoinsEntry), 21 platformStyle(_platformStyle) 22 { 23 ui->setupUi(this); 24 25 ui->addressBookButton->setIcon(platformStyle->SingleColorIcon(":/icons/address-book")); 26 ui->pasteButton->setIcon(platformStyle->SingleColorIcon(":/icons/editpaste")); 27 ui->deleteButton->setIcon(platformStyle->SingleColorIcon(":/icons/remove")); 28 29 if (platformStyle->getUseExtraSpacing()) 30 ui->payToLayout->setSpacing(4); 31 32 GUIUtil::setupAddressWidget(ui->payTo, this); 33 34 // Connect signals 35 connect(ui->payAmount, &BitcoinAmountField::valueChanged, this, &SendCoinsEntry::payAmountChanged); 36 connect(ui->checkboxSubtractFeeFromAmount, &QCheckBox::toggled, this, &SendCoinsEntry::subtractFeeFromAmountChanged); 37 connect(ui->deleteButton, &QPushButton::clicked, this, &SendCoinsEntry::deleteClicked); 38 connect(ui->useAvailableBalanceButton, &QPushButton::clicked, this, &SendCoinsEntry::useAvailableBalanceClicked); 39 } 40 41 SendCoinsEntry::~SendCoinsEntry() 42 { 43 delete ui; 44 } 45 46 void SendCoinsEntry::on_pasteButton_clicked() 47 { 48 // Paste text from clipboard into recipient field 49 ui->payTo->setText(QApplication::clipboard()->text()); 50 } 51 52 void SendCoinsEntry::on_addressBookButton_clicked() 53 { 54 if(!model) 55 return; 56 AddressBookPage dlg(platformStyle, AddressBookPage::ForSelection, AddressBookPage::SendingTab, this); 57 dlg.setModel(model->getAddressTableModel()); 58 if(dlg.exec()) 59 { 60 ui->payTo->setText(dlg.getReturnValue()); 61 ui->payAmount->setFocus(); 62 } 63 } 64 65 void SendCoinsEntry::on_payTo_textChanged(const QString &address) 66 { 67 updateLabel(address); 68 } 69 70 void SendCoinsEntry::setModel(WalletModel *_model) 71 { 72 this->model = _model; 73 74 if (_model && _model->getOptionsModel()) 75 connect(_model->getOptionsModel(), &OptionsModel::displayUnitChanged, this, &SendCoinsEntry::updateDisplayUnit); 76 77 clear(); 78 } 79 80 void SendCoinsEntry::clear() 81 { 82 // clear UI elements for normal payment 83 ui->payTo->clear(); 84 ui->addAsLabel->clear(); 85 ui->payAmount->clear(); 86 if (model && model->getOptionsModel()) { 87 ui->checkboxSubtractFeeFromAmount->setChecked(model->getOptionsModel()->getSubFeeFromAmount()); 88 } 89 ui->messageTextLabel->clear(); 90 ui->messageTextLabel->hide(); 91 ui->messageLabel->hide(); 92 93 // update the display unit, to not use the default ("BTC") 94 updateDisplayUnit(); 95 } 96 97 void SendCoinsEntry::checkSubtractFeeFromAmount() 98 { 99 ui->checkboxSubtractFeeFromAmount->setChecked(true); 100 } 101 102 void SendCoinsEntry::deleteClicked() 103 { 104 Q_EMIT removeEntry(this); 105 } 106 107 void SendCoinsEntry::useAvailableBalanceClicked() 108 { 109 Q_EMIT useAvailableBalance(this); 110 } 111 112 bool SendCoinsEntry::validate(interfaces::Node& node) 113 { 114 if (!model) 115 return false; 116 117 // Check input validity 118 bool retval = true; 119 120 if (!model->validateAddress(ui->payTo->text())) 121 { 122 ui->payTo->setValid(false); 123 retval = false; 124 } 125 126 if (!ui->payAmount->validate()) 127 { 128 retval = false; 129 } 130 131 // Sending a zero amount is invalid 132 if (ui->payAmount->value(nullptr) <= 0) 133 { 134 ui->payAmount->setValid(false); 135 retval = false; 136 } 137 138 // Reject dust outputs: 139 if (retval && GUIUtil::isDust(node, ui->payTo->text(), ui->payAmount->value())) { 140 ui->payAmount->setValid(false); 141 retval = false; 142 } 143 144 return retval; 145 } 146 147 SendCoinsRecipient SendCoinsEntry::getValue() 148 { 149 recipient.address = ui->payTo->text(); 150 recipient.label = ui->addAsLabel->text(); 151 recipient.amount = ui->payAmount->value(); 152 recipient.message = ui->messageTextLabel->text(); 153 recipient.fSubtractFeeFromAmount = (ui->checkboxSubtractFeeFromAmount->checkState() == Qt::Checked); 154 155 return recipient; 156 } 157 158 QWidget *SendCoinsEntry::setupTabChain(QWidget *prev) 159 { 160 QWidget::setTabOrder(prev, ui->payTo); 161 QWidget::setTabOrder(ui->payTo, ui->addAsLabel); 162 QWidget *w = ui->payAmount->setupTabChain(ui->addAsLabel); 163 QWidget::setTabOrder(w, ui->checkboxSubtractFeeFromAmount); 164 QWidget::setTabOrder(ui->checkboxSubtractFeeFromAmount, ui->addressBookButton); 165 QWidget::setTabOrder(ui->addressBookButton, ui->pasteButton); 166 QWidget::setTabOrder(ui->pasteButton, ui->deleteButton); 167 return ui->deleteButton; 168 } 169 170 void SendCoinsEntry::setValue(const SendCoinsRecipient &value) 171 { 172 recipient = value; 173 { 174 // message 175 ui->messageTextLabel->setText(recipient.message); 176 ui->messageTextLabel->setVisible(!recipient.message.isEmpty()); 177 ui->messageLabel->setVisible(!recipient.message.isEmpty()); 178 179 ui->addAsLabel->clear(); 180 ui->payTo->setText(recipient.address); // this may set a label from addressbook 181 if (!recipient.label.isEmpty()) // if a label had been set from the addressbook, don't overwrite with an empty label 182 ui->addAsLabel->setText(recipient.label); 183 ui->payAmount->setValue(recipient.amount); 184 } 185 } 186 187 void SendCoinsEntry::setAddress(const QString &address) 188 { 189 ui->payTo->setText(address); 190 ui->payAmount->setFocus(); 191 } 192 193 void SendCoinsEntry::setAmount(const CAmount &amount) 194 { 195 ui->payAmount->setValue(amount); 196 } 197 198 bool SendCoinsEntry::isClear() 199 { 200 return ui->payTo->text().isEmpty(); 201 } 202 203 void SendCoinsEntry::setFocus() 204 { 205 ui->payTo->setFocus(); 206 } 207 208 void SendCoinsEntry::updateDisplayUnit() 209 { 210 if (model && model->getOptionsModel()) { 211 ui->payAmount->setDisplayUnit(model->getOptionsModel()->getDisplayUnit()); 212 } 213 } 214 215 void SendCoinsEntry::changeEvent(QEvent* e) 216 { 217 if (e->type() == QEvent::PaletteChange) { 218 ui->addressBookButton->setIcon(platformStyle->SingleColorIcon(QStringLiteral(":/icons/address-book"))); 219 ui->pasteButton->setIcon(platformStyle->SingleColorIcon(QStringLiteral(":/icons/editpaste"))); 220 ui->deleteButton->setIcon(platformStyle->SingleColorIcon(QStringLiteral(":/icons/remove"))); 221 } 222 223 QWidget::changeEvent(e); 224 } 225 226 bool SendCoinsEntry::updateLabel(const QString &address) 227 { 228 if(!model) 229 return false; 230 231 // Fill in label from address book, if address has an associated label 232 QString associatedLabel = model->getAddressTableModel()->labelForAddress(address); 233 if(!associatedLabel.isEmpty()) 234 { 235 ui->addAsLabel->setText(associatedLabel); 236 return true; 237 } 238 239 return false; 240 }