1 #include "sendcoinsdialog.h"
2 #include "ui_sendcoinsdialog.h"
3 #include "walletmodel.h"
4 #include "bitcoinunits.h"
5 #include "addressbookpage.h"
6 #include "optionsmodel.h"
7 #include "sendcoinsentry.h"
9 #include "askpassphrasedialog.h"
12 #include <QMessageBox>
14 #include <QTextDocument>
17 SendCoinsDialog::SendCoinsDialog(QWidget *parent) :
19 ui(new Ui::SendCoinsDialog),
24 #ifdef Q_OS_MAC // Icons on push buttons are very uncommon on Mac
25 ui->addButton->setIcon(QIcon());
26 ui->clearButton->setIcon(QIcon());
27 ui->sendButton->setIcon(QIcon());
32 connect(ui->addButton, SIGNAL(clicked()), this, SLOT(addEntry()));
33 connect(ui->clearButton, SIGNAL(clicked()), this, SLOT(clear()));
35 fNewRecipientAllowed = true;
38 void SendCoinsDialog::setModel(WalletModel *model)
42 for(int i = 0; i < ui->entries->count(); ++i)
44 SendCoinsEntry *entry = qobject_cast<SendCoinsEntry*>(ui->entries->itemAt(i)->widget());
47 entry->setModel(model);
50 if(model && model->getOptionsModel())
52 setBalance(model->getBalance(), model->getStake(), model->getUnconfirmedBalance(), model->getImmatureBalance());
53 connect(model, SIGNAL(balanceChanged(qint64, qint64, quint64, qint64)), this, SLOT(setBalance(qint64, qint64, qint64, qint64)));
54 connect(model->getOptionsModel(), SIGNAL(displayUnitChanged(int)), this, SLOT(updateDisplayUnit()));
58 SendCoinsDialog::~SendCoinsDialog()
63 void SendCoinsDialog::on_sendButton_clicked()
65 QList<SendCoinsRecipient> recipients;
71 for(int i = 0; i < ui->entries->count(); ++i)
73 SendCoinsEntry *entry = qobject_cast<SendCoinsEntry*>(ui->entries->itemAt(i)->widget());
78 recipients.append(entry->getValue());
87 if(!valid || recipients.isEmpty())
92 // Format confirmation message
93 QStringList formatted;
94 foreach(const SendCoinsRecipient &rcp, recipients)
96 formatted.append(tr("<b>%1</b> to %2 (%3)").arg(BitcoinUnits::formatWithUnit(BitcoinUnits::BTC, rcp.amount), Qt::escape(rcp.label), rcp.address));
99 fNewRecipientAllowed = false;
101 QMessageBox::StandardButton retval = QMessageBox::question(this, tr("Confirm send coins"),
102 tr("Are you sure you want to send %1?").arg(formatted.join(tr(" and "))),
103 QMessageBox::Yes|QMessageBox::Cancel,
104 QMessageBox::Cancel);
106 if(retval != QMessageBox::Yes)
108 fNewRecipientAllowed = true;
112 WalletModel::UnlockContext ctx(model->requestUnlock());
115 // Unlock wallet was cancelled
116 fNewRecipientAllowed = true;
120 WalletModel::SendCoinsReturn sendstatus = model->sendCoins(recipients);
121 switch(sendstatus.status)
123 case WalletModel::InvalidAddress:
124 QMessageBox::warning(this, tr("Send Coins"),
125 tr("The recipient address is not valid, please recheck."),
126 QMessageBox::Ok, QMessageBox::Ok);
128 case WalletModel::InvalidAmount:
129 QMessageBox::warning(this, tr("Send Coins"),
130 tr("The amount to pay must be larger than 0."),
131 QMessageBox::Ok, QMessageBox::Ok);
133 case WalletModel::AmountExceedsBalance:
134 QMessageBox::warning(this, tr("Send Coins"),
135 tr("The amount exceeds your balance."),
136 QMessageBox::Ok, QMessageBox::Ok);
138 case WalletModel::AmountWithFeeExceedsBalance:
139 QMessageBox::warning(this, tr("Send Coins"),
140 tr("The total exceeds your balance when the %1 transaction fee is included.").
141 arg(BitcoinUnits::formatWithUnit(BitcoinUnits::BTC, sendstatus.fee)),
142 QMessageBox::Ok, QMessageBox::Ok);
144 case WalletModel::DuplicateAddress:
145 QMessageBox::warning(this, tr("Send Coins"),
146 tr("Duplicate address found, can only send to each address once per send operation."),
147 QMessageBox::Ok, QMessageBox::Ok);
149 case WalletModel::TransactionCreationFailed:
150 QMessageBox::warning(this, tr("Send Coins"),
151 tr("Error: Transaction creation failed."),
152 QMessageBox::Ok, QMessageBox::Ok);
154 case WalletModel::TransactionCommitFailed:
155 QMessageBox::warning(this, tr("Send Coins"),
156 tr("Error: The transaction was rejected. This might happen if some of the coins in your wallet were already spent, such as if you used a copy of wallet.dat and coins were spent in the copy but not marked as spent here."),
157 QMessageBox::Ok, QMessageBox::Ok);
159 case WalletModel::Aborted: // User aborted, nothing to do
161 case WalletModel::OK:
165 fNewRecipientAllowed = true;
168 void SendCoinsDialog::clear()
170 // Remove entries until only one left
171 while(ui->entries->count())
173 delete ui->entries->takeAt(0)->widget();
177 updateRemoveEnabled();
179 ui->sendButton->setDefault(true);
182 void SendCoinsDialog::reject()
187 void SendCoinsDialog::accept()
192 SendCoinsEntry *SendCoinsDialog::addEntry()
194 SendCoinsEntry *entry = new SendCoinsEntry(this);
195 entry->setModel(model);
196 ui->entries->addWidget(entry);
197 connect(entry, SIGNAL(removeEntry(SendCoinsEntry*)), this, SLOT(removeEntry(SendCoinsEntry*)));
199 updateRemoveEnabled();
201 // Focus the field, so that entry can start immediately
204 ui->scrollAreaWidgetContents->resize(ui->scrollAreaWidgetContents->sizeHint());
205 QCoreApplication::instance()->processEvents();
206 QScrollBar* bar = ui->scrollArea->verticalScrollBar();
208 bar->setSliderPosition(bar->maximum());
212 void SendCoinsDialog::updateRemoveEnabled()
214 // Remove buttons are enabled as soon as there is more than one send-entry
215 bool enabled = (ui->entries->count() > 1);
216 for(int i = 0; i < ui->entries->count(); ++i)
218 SendCoinsEntry *entry = qobject_cast<SendCoinsEntry*>(ui->entries->itemAt(i)->widget());
221 entry->setRemoveEnabled(enabled);
227 void SendCoinsDialog::removeEntry(SendCoinsEntry* entry)
230 updateRemoveEnabled();
233 QWidget *SendCoinsDialog::setupTabChain(QWidget *prev)
235 for(int i = 0; i < ui->entries->count(); ++i)
237 SendCoinsEntry *entry = qobject_cast<SendCoinsEntry*>(ui->entries->itemAt(i)->widget());
240 prev = entry->setupTabChain(prev);
243 QWidget::setTabOrder(prev, ui->addButton);
244 QWidget::setTabOrder(ui->addButton, ui->sendButton);
245 return ui->sendButton;
248 void SendCoinsDialog::pasteEntry(const SendCoinsRecipient &rv)
250 if(!fNewRecipientAllowed)
253 SendCoinsEntry *entry = 0;
254 // Replace the first entry if it is still unused
255 if(ui->entries->count() == 1)
257 SendCoinsEntry *first = qobject_cast<SendCoinsEntry*>(ui->entries->itemAt(0)->widget());
271 bool SendCoinsDialog::handleURI(const QString &uri)
273 SendCoinsRecipient rv;
274 // URI has to be valid
275 if (GUIUtil::parseBitcoinURI(uri, &rv))
277 CBitcoinAddress address(rv.address.toStdString());
278 if (!address.IsValid())
287 void SendCoinsDialog::setBalance(qint64 balance, qint64 stake, qint64 unconfirmedBalance, qint64 immatureBalance)
290 Q_UNUSED(unconfirmedBalance);
291 Q_UNUSED(immatureBalance);
292 if(!model || !model->getOptionsModel())
295 int unit = model->getOptionsModel()->getDisplayUnit();
296 ui->labelBalance->setText(BitcoinUnits::formatWithUnit(unit, balance));
299 void SendCoinsDialog::updateDisplayUnit()
301 if(model && model->getOptionsModel())
303 // Update labelBalance with the current balance and the current unit
304 ui->labelBalance->setText(BitcoinUnits::formatWithUnit(model->getOptionsModel()->getDisplayUnit(), model->getBalance()));