Accept "bitcoin:" URL drops from browsers
[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
10 #include <QMessageBox>
11 #include <QLocale>
12 #include <QTextDocument>
13 #include <QDebug>
14
15 SendCoinsDialog::SendCoinsDialog(QWidget *parent) :
16     QDialog(parent),
17     ui(new Ui::SendCoinsDialog),
18     model(0)
19 {
20     ui->setupUi(this);
21
22     addEntry();
23
24     connect(ui->addButton, SIGNAL(clicked()), this, SLOT(addEntry()));
25 }
26
27 void SendCoinsDialog::setModel(WalletModel *model)
28 {
29     this->model = model;
30
31     for(int i = 0; i < ui->entries->count(); ++i)
32     {
33         SendCoinsEntry *entry = qobject_cast<SendCoinsEntry*>(ui->entries->itemAt(i)->widget());
34         if(entry)
35         {
36             entry->setModel(model);
37         }
38     }
39 }
40
41 SendCoinsDialog::~SendCoinsDialog()
42 {
43     delete ui;
44 }
45
46 void SendCoinsDialog::on_sendButton_clicked()
47 {
48     QList<SendCoinsRecipient> recipients;
49     bool valid = true;
50     for(int i = 0; i < ui->entries->count(); ++i)
51     {
52         SendCoinsEntry *entry = qobject_cast<SendCoinsEntry*>(ui->entries->itemAt(i)->widget());
53         if(entry)
54         {
55             if(entry->validate())
56             {
57                 recipients.append(entry->getValue());
58             }
59             else
60             {
61                 valid = false;
62             }
63         }
64     }
65
66     if(!valid || recipients.isEmpty())
67     {
68         return;
69     }
70
71     // Format confirmation message
72     QStringList formatted;
73     foreach(const SendCoinsRecipient &rcp, recipients)
74     {
75         formatted.append(tr("<b>%1</b> to %2 (%3)").arg(BitcoinUnits::formatWithUnit(BitcoinUnits::BTC, rcp.amount), Qt::escape(rcp.label), rcp.address));
76     }
77
78     QMessageBox::StandardButton retval = QMessageBox::question(this, tr("Confirm send coins"),
79                           tr("Are you sure you want to send %1?").arg(formatted.join(tr(" and "))),
80           QMessageBox::Yes|QMessageBox::Cancel,
81           QMessageBox::Cancel);
82
83     if(retval != QMessageBox::Yes)
84     {
85         return;
86     }
87
88     WalletModel::SendCoinsReturn sendstatus = model->sendCoins(recipients);
89     switch(sendstatus.status)
90     {
91     case WalletModel::InvalidAddress:
92         QMessageBox::warning(this, tr("Send Coins"),
93             tr("The recepient address is not valid, please recheck."),
94             QMessageBox::Ok, QMessageBox::Ok);
95         break;
96     case WalletModel::InvalidAmount:
97         QMessageBox::warning(this, tr("Send Coins"),
98             tr("The amount to pay must be larger than 0."),
99             QMessageBox::Ok, QMessageBox::Ok);
100         break;
101     case WalletModel::AmountExceedsBalance:
102         QMessageBox::warning(this, tr("Send Coins"),
103             tr("Amount exceeds your balance"),
104             QMessageBox::Ok, QMessageBox::Ok);
105         break;
106     case WalletModel::AmountWithFeeExceedsBalance:
107         QMessageBox::warning(this, tr("Send Coins"),
108             tr("Total exceeds your balance when the %1 transaction fee is included").
109             arg(BitcoinUnits::formatWithUnit(BitcoinUnits::BTC, sendstatus.fee)),
110             QMessageBox::Ok, QMessageBox::Ok);
111         break;
112     case WalletModel::DuplicateAddress:
113         QMessageBox::warning(this, tr("Send Coins"),
114             tr("Duplicate address found, can only send to each address once in one send operation"),
115             QMessageBox::Ok, QMessageBox::Ok);
116         break;
117     case WalletModel::TransactionCreationFailed:
118         QMessageBox::warning(this, tr("Send Coins"),
119             tr("Error: Transaction creation failed  "),
120             QMessageBox::Ok, QMessageBox::Ok);
121         break;
122         break;
123     case WalletModel::TransactionCommitFailed:
124         QMessageBox::warning(this, tr("Send Coins"),
125             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."),
126             QMessageBox::Ok, QMessageBox::Ok);
127         break;
128     case WalletModel::OK:
129         accept();
130         break;
131     }
132 }
133
134 void SendCoinsDialog::clear()
135 {
136     // Remove entries until only one left
137     while(ui->entries->count())
138     {
139         delete ui->entries->takeAt(0)->widget();
140     }
141     addEntry();
142
143     updateRemoveEnabled();
144
145     ui->sendButton->setDefault(true);
146 }
147
148 void SendCoinsDialog::reject()
149 {
150     clear();
151 }
152
153 void SendCoinsDialog::accept()
154 {
155     clear();
156 }
157
158 SendCoinsEntry *SendCoinsDialog::addEntry()
159 {
160     SendCoinsEntry *entry = new SendCoinsEntry(this);
161     entry->setModel(model);
162     ui->entries->addWidget(entry);
163     connect(entry, SIGNAL(removeEntry(SendCoinsEntry*)), this, SLOT(removeEntry(SendCoinsEntry*)));
164
165     updateRemoveEnabled();
166
167     // Focus the field, so that entry can start immediately
168     entry->clear();
169     return entry;
170 }
171
172 void SendCoinsDialog::updateRemoveEnabled()
173 {
174     // Remove buttons are enabled as soon as there is more than one send-entry
175     bool enabled = (ui->entries->count() > 1);
176     for(int i = 0; i < ui->entries->count(); ++i)
177     {
178         SendCoinsEntry *entry = qobject_cast<SendCoinsEntry*>(ui->entries->itemAt(i)->widget());
179         if(entry)
180         {
181             entry->setRemoveEnabled(enabled);
182         }
183     }
184     setupTabChain(0);
185 }
186
187 void SendCoinsDialog::removeEntry(SendCoinsEntry* entry)
188 {
189     delete entry;
190     updateRemoveEnabled();
191 }
192
193 QWidget *SendCoinsDialog::setupTabChain(QWidget *prev)
194 {
195     for(int i = 0; i < ui->entries->count(); ++i)
196     {
197         SendCoinsEntry *entry = qobject_cast<SendCoinsEntry*>(ui->entries->itemAt(i)->widget());
198         if(entry)
199         {
200             prev = entry->setupTabChain(prev);
201         }
202     }
203     QWidget::setTabOrder(prev, ui->addButton);
204     QWidget::setTabOrder(ui->addButton, ui->sendButton);
205     return ui->sendButton;
206 }
207
208 void SendCoinsDialog::pasteEntry(const SendCoinsRecipient &rv)
209 {
210     SendCoinsEntry *entry = 0;
211     // Replace the first entry if it is still unused
212     if(ui->entries->count() == 1)
213     {
214         SendCoinsEntry *first = qobject_cast<SendCoinsEntry*>(ui->entries->itemAt(0)->widget());
215         if(first->isClear())
216         {
217             entry = first;
218         }
219     }
220     if(!entry)
221     {
222         entry = addEntry();
223     }
224
225     entry->setValue(rv);
226 }
227
228
229 void SendCoinsDialog::handleURL(const QUrl *url)
230 {
231     SendCoinsRecipient rv;
232     if(!GUIUtil::parseBitcoinURL(url, &rv))
233     {
234         return;
235     }
236     pasteEntry(rv);
237 }