fix warnings: enumeration values 'XX' not handled in switch [-Wswitch-enum]
[novacoin.git] / src / qt / sendcoinsdialog.cpp
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"
8 #include "guiutil.h"
9 #include "askpassphrasedialog.h"
10
11 #include <QMessageBox>
12 #include <QLocale>
13 #include <QTextDocument>
14 #include <QScrollBar>
15
16 SendCoinsDialog::SendCoinsDialog(QWidget *parent) :
17     QDialog(parent),
18     ui(new Ui::SendCoinsDialog),
19     model(0)
20 {
21     ui->setupUi(this);
22
23 #ifdef Q_WS_MAC // Icons on push buttons are very uncommon on Mac
24     ui->addButton->setIcon(QIcon());
25     ui->clearButton->setIcon(QIcon());
26     ui->sendButton->setIcon(QIcon());
27 #endif
28
29     addEntry();
30
31     connect(ui->addButton, SIGNAL(clicked()), this, SLOT(addEntry()));
32     connect(ui->clearButton, SIGNAL(clicked()), this, SLOT(clear()));
33 }
34
35 void SendCoinsDialog::setModel(WalletModel *model)
36 {
37     this->model = model;
38
39     for(int i = 0; i < ui->entries->count(); ++i)
40     {
41         SendCoinsEntry *entry = qobject_cast<SendCoinsEntry*>(ui->entries->itemAt(i)->widget());
42         if(entry)
43         {
44             entry->setModel(model);
45         }
46     }
47     if(model)
48     {
49         setBalance(model->getBalance(), model->getUnconfirmedBalance());
50         connect(model, SIGNAL(balanceChanged(qint64, qint64)), this, SLOT(setBalance(qint64, qint64)));
51     }
52 }
53
54 SendCoinsDialog::~SendCoinsDialog()
55 {
56     delete ui;
57 }
58
59 void SendCoinsDialog::on_sendButton_clicked()
60 {
61     QList<SendCoinsRecipient> recipients;
62     bool valid = true;
63
64     if(!model)
65         return;
66
67     for(int i = 0; i < ui->entries->count(); ++i)
68     {
69         SendCoinsEntry *entry = qobject_cast<SendCoinsEntry*>(ui->entries->itemAt(i)->widget());
70         if(entry)
71         {
72             if(entry->validate())
73             {
74                 recipients.append(entry->getValue());
75             }
76             else
77             {
78                 valid = false;
79             }
80         }
81     }
82
83     if(!valid || recipients.isEmpty())
84     {
85         return;
86     }
87
88     // Format confirmation message
89     QStringList formatted;
90     foreach(const SendCoinsRecipient &rcp, recipients)
91     {
92         formatted.append(tr("<b>%1</b> to %2 (%3)").arg(BitcoinUnits::formatWithUnit(BitcoinUnits::BTC, rcp.amount), Qt::escape(rcp.label), rcp.address));
93     }
94
95     QMessageBox::StandardButton retval = QMessageBox::question(this, tr("Confirm send coins"),
96                           tr("Are you sure you want to send %1?").arg(formatted.join(tr(" and "))),
97           QMessageBox::Yes|QMessageBox::Cancel,
98           QMessageBox::Cancel);
99
100     if(retval != QMessageBox::Yes)
101     {
102         return;
103     }
104
105     WalletModel::UnlockContext ctx(model->requestUnlock());
106     if(!ctx.isValid())
107     {
108         // Unlock wallet was cancelled
109         return;
110     }
111
112     WalletModel::SendCoinsReturn sendstatus = model->sendCoins(recipients);
113     switch(sendstatus.status)
114     {
115     case WalletModel::InvalidAddress:
116         QMessageBox::warning(this, tr("Send Coins"),
117             tr("The recepient address is not valid, please recheck."),
118             QMessageBox::Ok, QMessageBox::Ok);
119         break;
120     case WalletModel::InvalidAmount:
121         QMessageBox::warning(this, tr("Send Coins"),
122             tr("The amount to pay must be larger than 0."),
123             QMessageBox::Ok, QMessageBox::Ok);
124         break;
125     case WalletModel::AmountExceedsBalance:
126         QMessageBox::warning(this, tr("Send Coins"),
127             tr("Amount exceeds your balance"),
128             QMessageBox::Ok, QMessageBox::Ok);
129         break;
130     case WalletModel::AmountWithFeeExceedsBalance:
131         QMessageBox::warning(this, tr("Send Coins"),
132             tr("Total exceeds your balance when the %1 transaction fee is included").
133             arg(BitcoinUnits::formatWithUnit(BitcoinUnits::BTC, sendstatus.fee)),
134             QMessageBox::Ok, QMessageBox::Ok);
135         break;
136     case WalletModel::DuplicateAddress:
137         QMessageBox::warning(this, tr("Send Coins"),
138             tr("Duplicate address found, can only send to each address once in one send operation"),
139             QMessageBox::Ok, QMessageBox::Ok);
140         break;
141     case WalletModel::TransactionCreationFailed:
142         QMessageBox::warning(this, tr("Send Coins"),
143             tr("Error: Transaction creation failed  "),
144             QMessageBox::Ok, QMessageBox::Ok);
145         break;
146     case WalletModel::TransactionCommitFailed:
147         QMessageBox::warning(this, tr("Send Coins"),
148             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."),
149             QMessageBox::Ok, QMessageBox::Ok);
150         break;
151     case WalletModel::Aborted: // User aborted, nothing to do
152         break;
153     case WalletModel::OK:
154         accept();
155         break;
156     }
157 }
158
159 void SendCoinsDialog::clear()
160 {
161     // Remove entries until only one left
162     while(ui->entries->count())
163     {
164         delete ui->entries->takeAt(0)->widget();
165     }
166     addEntry();
167
168     updateRemoveEnabled();
169
170     ui->sendButton->setDefault(true);
171 }
172
173 void SendCoinsDialog::reject()
174 {
175     clear();
176 }
177
178 void SendCoinsDialog::accept()
179 {
180     clear();
181 }
182
183 SendCoinsEntry *SendCoinsDialog::addEntry()
184 {
185     SendCoinsEntry *entry = new SendCoinsEntry(this);
186     entry->setModel(model);
187     ui->entries->addWidget(entry);
188     connect(entry, SIGNAL(removeEntry(SendCoinsEntry*)), this, SLOT(removeEntry(SendCoinsEntry*)));
189
190     updateRemoveEnabled();
191
192     // Focus the field, so that entry can start immediately
193     entry->clear();
194     entry->setFocus();
195     ui->scrollAreaWidgetContents->resize(ui->scrollAreaWidgetContents->sizeHint());
196     QCoreApplication::instance()->processEvents();
197     QScrollBar* bar = ui->scrollArea->verticalScrollBar();
198     if (bar)
199         bar->setSliderPosition(bar->maximum());
200     return entry;
201 }
202
203 void SendCoinsDialog::updateRemoveEnabled()
204 {
205     // Remove buttons are enabled as soon as there is more than one send-entry
206     bool enabled = (ui->entries->count() > 1);
207     for(int i = 0; i < ui->entries->count(); ++i)
208     {
209         SendCoinsEntry *entry = qobject_cast<SendCoinsEntry*>(ui->entries->itemAt(i)->widget());
210         if(entry)
211         {
212             entry->setRemoveEnabled(enabled);
213         }
214     }
215     setupTabChain(0);
216 }
217
218 void SendCoinsDialog::removeEntry(SendCoinsEntry* entry)
219 {
220     delete entry;
221     updateRemoveEnabled();
222 }
223
224 QWidget *SendCoinsDialog::setupTabChain(QWidget *prev)
225 {
226     for(int i = 0; i < ui->entries->count(); ++i)
227     {
228         SendCoinsEntry *entry = qobject_cast<SendCoinsEntry*>(ui->entries->itemAt(i)->widget());
229         if(entry)
230         {
231             prev = entry->setupTabChain(prev);
232         }
233     }
234     QWidget::setTabOrder(prev, ui->addButton);
235     QWidget::setTabOrder(ui->addButton, ui->sendButton);
236     return ui->sendButton;
237 }
238
239 void SendCoinsDialog::pasteEntry(const SendCoinsRecipient &rv)
240 {
241     SendCoinsEntry *entry = 0;
242     // Replace the first entry if it is still unused
243     if(ui->entries->count() == 1)
244     {
245         SendCoinsEntry *first = qobject_cast<SendCoinsEntry*>(ui->entries->itemAt(0)->widget());
246         if(first->isClear())
247         {
248             entry = first;
249         }
250     }
251     if(!entry)
252     {
253         entry = addEntry();
254     }
255
256     entry->setValue(rv);
257 }
258
259
260 void SendCoinsDialog::handleURI(const QUrl *uri)
261 {
262     SendCoinsRecipient rv;
263     if(!GUIUtil::parseBitcoinURI(uri, &rv))
264     {
265         return;
266     }
267     pasteEntry(rv);
268 }
269
270 void SendCoinsDialog::handleURI(const QString &uri)
271 {
272     SendCoinsRecipient rv;
273     if(!GUIUtil::parseBitcoinURI(uri, &rv))
274     {
275         return;
276     }
277     pasteEntry(rv);
278 }
279
280 void SendCoinsDialog::setBalance(qint64 balance, qint64 unconfirmedBalance)
281 {
282     Q_UNUSED(unconfirmedBalance);
283     if(!model || !model->getOptionsModel())
284         return;
285
286     int unit = model->getOptionsModel()->getDisplayUnit();
287     ui->labelBalance->setText(BitcoinUnits::formatWithUnit(unit, balance));
288 }