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