sendcoinsentry.cpp raw
1 // Copyright (c) 2011-2022 The Limenka 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, &LimenkaAmountField::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) {
75 ui->payTo->setWarningValidator(new LimenkaAddressUnusedInWalletValidator(*_model));
76 } else {
77 ui->payTo->setWarningValidator(nullptr);
78 }
79
80 if (_model && _model->getOptionsModel())
81 {
82 connect(_model->getOptionsModel(), &OptionsModel::displayUnitChanged, this, &SendCoinsEntry::updateDisplayUnit);
83 connect(_model->getOptionsModel(), &OptionsModel::fontForMoneyChanged, this, &SendCoinsEntry::updateDisplayUnit);
84 }
85
86 clear();
87 }
88
89 void SendCoinsEntry::clear()
90 {
91 // clear UI elements for normal payment
92 ui->payTo->clear();
93 ui->addAsLabel->clear();
94 ui->payAmount->clear();
95 if (model && model->getOptionsModel()) {
96 ui->checkboxSubtractFeeFromAmount->setChecked(model->getOptionsModel()->getSubFeeFromAmount());
97 }
98 ui->messageTextLabel->clear();
99 ui->messageTextLabel->hide();
100 ui->messageLabel->hide();
101
102 // update the display unit, to not use the default ("BTC")
103 updateDisplayUnit();
104 }
105
106 void SendCoinsEntry::checkSubtractFeeFromAmount()
107 {
108 ui->checkboxSubtractFeeFromAmount->setChecked(true);
109 }
110
111 void SendCoinsEntry::deleteClicked()
112 {
113 Q_EMIT removeEntry(this);
114 }
115
116 void SendCoinsEntry::useAvailableBalanceClicked()
117 {
118 Q_EMIT useAvailableBalance(this);
119 }
120
121 bool SendCoinsEntry::validate(interfaces::Node& node)
122 {
123 if (!model)
124 return false;
125
126 // Check input validity
127 bool retval = true;
128
129 if (!model->validateAddress(ui->payTo->text()))
130 {
131 ui->payTo->setValid(false);
132 retval = false;
133 }
134
135 if (!ui->payAmount->validate())
136 {
137 retval = false;
138 }
139
140 // Sending a zero amount is invalid
141 if (ui->payAmount->value(nullptr) <= 0)
142 {
143 ui->payAmount->setValid(false);
144 retval = false;
145 }
146
147 // Reject dust outputs:
148 if (retval && GUIUtil::isDust(node, ui->payTo->text(), ui->payAmount->value())) {
149 ui->payAmount->setValid(false);
150 retval = false;
151 }
152
153 return retval;
154 }
155
156 bool SendCoinsEntry::hasPaytoWarning() const
157 {
158 return ui->payTo->hasWarning();
159 }
160
161 SendCoinsRecipient SendCoinsEntry::getValue()
162 {
163 recipient.address = ui->payTo->text();
164 recipient.label = ui->addAsLabel->text();
165 recipient.amount = ui->payAmount->value();
166 recipient.message = ui->messageTextLabel->text();
167 recipient.fSubtractFeeFromAmount = (ui->checkboxSubtractFeeFromAmount->checkState() == Qt::Checked);
168
169 return recipient;
170 }
171
172 QWidget *SendCoinsEntry::setupTabChain(QWidget *prev)
173 {
174 QWidget::setTabOrder(prev, ui->payTo);
175 QWidget::setTabOrder(ui->payTo, ui->addAsLabel);
176 QWidget *w = ui->payAmount->setupTabChain(ui->addAsLabel);
177 QWidget::setTabOrder(w, ui->checkboxSubtractFeeFromAmount);
178 QWidget::setTabOrder(ui->checkboxSubtractFeeFromAmount, ui->addressBookButton);
179 QWidget::setTabOrder(ui->addressBookButton, ui->pasteButton);
180 QWidget::setTabOrder(ui->pasteButton, ui->deleteButton);
181 return ui->deleteButton;
182 }
183
184 void SendCoinsEntry::setValue(const SendCoinsRecipient &value)
185 {
186 recipient = value;
187 {
188 // message
189 ui->messageTextLabel->setText(recipient.message);
190 ui->messageTextLabel->setVisible(!recipient.message.isEmpty());
191 ui->messageLabel->setVisible(!recipient.message.isEmpty());
192
193 ui->addAsLabel->clear();
194 ui->payTo->setText(recipient.address); // this may set a label from addressbook
195 if (!recipient.label.isEmpty()) // if a label had been set from the addressbook, don't overwrite with an empty label
196 ui->addAsLabel->setText(recipient.label);
197 ui->payAmount->setValue(recipient.amount);
198 }
199 }
200
201 void SendCoinsEntry::setAddress(const QString &address)
202 {
203 ui->payTo->setText(address);
204 ui->payAmount->setFocus();
205 }
206
207 void SendCoinsEntry::setAmount(const CAmount &amount)
208 {
209 ui->payAmount->setValue(amount);
210 }
211
212 bool SendCoinsEntry::isClear()
213 {
214 return ui->payTo->text().isEmpty();
215 }
216
217 void SendCoinsEntry::setFocus()
218 {
219 ui->payTo->setFocus();
220 }
221
222 void SendCoinsEntry::updateDisplayUnit()
223 {
224 if (model && model->getOptionsModel()) {
225 const LimenkaUnit display_unit = model->getOptionsModel()->getDisplayUnit();
226 ui->payAmount->setDisplayUnit(display_unit);
227 const QFont font_for_money = model->getOptionsModel()->getFontForMoney(display_unit);
228 ui->payAmount->setFontForMoney(font_for_money);
229 }
230 }
231
232 void SendCoinsEntry::changeEvent(QEvent* e)
233 {
234 if (e->type() == QEvent::PaletteChange) {
235 ui->addressBookButton->setIcon(platformStyle->SingleColorIcon(QStringLiteral(":/icons/address-book")));
236 ui->pasteButton->setIcon(platformStyle->SingleColorIcon(QStringLiteral(":/icons/editpaste")));
237 ui->deleteButton->setIcon(platformStyle->SingleColorIcon(QStringLiteral(":/icons/remove")));
238 }
239
240 QWidget::changeEvent(e);
241 }
242
243 bool SendCoinsEntry::updateLabel(const QString &address)
244 {
245 if(!model)
246 return false;
247
248 // Fill in label from address book, if address has an associated label
249 QString associatedLabel = model->getAddressTableModel()->labelForAddress(address);
250 if(!associatedLabel.isEmpty())
251 {
252 ui->addAsLabel->setText(associatedLabel);
253 return true;
254 }
255
256 return false;
257 }
258