diff --git a/gui/include/bitcoingui.h b/gui/include/bitcoingui.h index 80c24a37..955d7b47 100644 --- a/gui/include/bitcoingui.h +++ b/gui/include/bitcoingui.h @@ -67,6 +67,7 @@ private slots: void newAddressClicked(); void copyClipboardClicked(); + void error(const QString &title, const QString &message); }; #endif diff --git a/gui/include/clientmodel.h b/gui/include/clientmodel.h index a5613e34..828c80f8 100644 --- a/gui/include/clientmodel.h +++ b/gui/include/clientmodel.h @@ -9,18 +9,35 @@ class ClientModel : public QObject public: explicit ClientModel(QObject *parent = 0); + enum StatusCode + { + OK, + InvalidAmount, + InvalidAddress, + AmountExceedsBalance, + AmountWithFeeExceedsBalance, + Aborted, + MiscError + }; + qint64 getBalance(); QString getAddress(); int getNumConnections(); int getNumBlocks(); int getNumTransactions(); + qint64 getTransactionFee(); + + StatusCode sendCoins(const QString &payTo, qint64 payAmount); + signals: void balanceChanged(qint64 balance); void addressChanged(const QString &address); void numConnectionsChanged(int count); void numBlocksChanged(int count); void numTransactionsChanged(int count); + /* Asynchronous error notification */ + void error(const QString &title, const QString &message); public slots: diff --git a/gui/include/sendcoinsdialog.h b/gui/include/sendcoinsdialog.h index 95dd34b1..f73c38d6 100644 --- a/gui/include/sendcoinsdialog.h +++ b/gui/include/sendcoinsdialog.h @@ -6,6 +6,7 @@ namespace Ui { class SendCoinsDialog; } +class ClientModel; class SendCoinsDialog : public QDialog { @@ -15,8 +16,11 @@ public: explicit SendCoinsDialog(QWidget *parent = 0, const QString &address = ""); ~SendCoinsDialog(); + void setModel(ClientModel *model); + private: Ui::SendCoinsDialog *ui; + ClientModel *model; private slots: void on_buttonBox_rejected(); diff --git a/gui/src/bitcoingui.cpp b/gui/src/bitcoingui.cpp index b409744b..66a3edd3 100644 --- a/gui/src/bitcoingui.cpp +++ b/gui/src/bitcoingui.cpp @@ -31,6 +31,7 @@ #include #include #include +#include #include @@ -160,6 +161,9 @@ void BitcoinGUI::setModel(ClientModel *model) setAddress(model->getAddress()); connect(model, SIGNAL(addressChanged(QString)), this, SLOT(setAddress(QString))); + + /* Report errors from network/worker thread */ + connect(model, SIGNAL(error(QString,QString)), this, SLOT(error(QString,QString))); } void BitcoinGUI::createTrayIcon() @@ -226,6 +230,7 @@ QWidget *BitcoinGUI::createTabs() void BitcoinGUI::sendcoinsClicked() { SendCoinsDialog dlg; + dlg.setModel(model); dlg.exec(); } @@ -296,3 +301,11 @@ void BitcoinGUI::setNumTransactions(int count) { labelTransactions->setText(QLocale::system().toString(count)+" "+tr("transaction(s)", "", count)); } + +void BitcoinGUI::error(const QString &title, const QString &message) +{ + /* Report errors from network/worker thread */ + QMessageBox::critical(this, title, + message, + QMessageBox::Ok, QMessageBox::Ok); +} diff --git a/gui/src/clientmodel.cpp b/gui/src/clientmodel.cpp index e355676c..be8b0b41 100644 --- a/gui/src/clientmodel.cpp +++ b/gui/src/clientmodel.cpp @@ -51,6 +51,11 @@ int ClientModel::getNumTransactions() return numTransactions; } +qint64 ClientModel::getTransactionFee() +{ + return nTransactionFee; +} + void ClientModel::update() { emit balanceChanged(getBalance()); @@ -59,3 +64,51 @@ void ClientModel::update() emit numBlocksChanged(getNumBlocks()); emit numTransactionsChanged(getNumTransactions()); } + +ClientModel::StatusCode ClientModel::sendCoins(const QString &payTo, qint64 payAmount) +{ + uint160 hash160 = 0; + bool valid = false; + + if(!AddressToHash160(payTo.toUtf8().constData(), hash160)) + { + return InvalidAddress; + } + + if(payAmount <= 0) + { + return InvalidAmount; + } + + if(payAmount > getBalance()) + { + return AmountExceedsBalance; + } + + if((payAmount + nTransactionFee) > getBalance()) + { + return AmountWithFeeExceedsBalance; + } + + CRITICAL_BLOCK(cs_main) + { + // Send to bitcoin address + CWalletTx wtx; + CScript scriptPubKey; + scriptPubKey << OP_DUP << OP_HASH160 << hash160 << OP_EQUALVERIFY << OP_CHECKSIG; + + std::string strError = SendMoney(scriptPubKey, payAmount, wtx, true); + if (strError == "") + return OK; + else if (strError == "ABORTED") + return Aborted; + else + { + emit error(tr("Sending..."), QString::fromStdString(strError)); + return MiscError; + } + } + + return OK; +} + diff --git a/gui/src/sendcoinsdialog.cpp b/gui/src/sendcoinsdialog.cpp index 123b930a..398e236e 100644 --- a/gui/src/sendcoinsdialog.cpp +++ b/gui/src/sendcoinsdialog.cpp @@ -1,5 +1,6 @@ #include "sendcoinsdialog.h" #include "ui_sendcoinsdialog.h" +#include "clientmodel.h" #include "addressbookdialog.h" #include "bitcoinaddressvalidator.h" @@ -15,7 +16,8 @@ SendCoinsDialog::SendCoinsDialog(QWidget *parent, const QString &address) : QDialog(parent), - ui(new Ui::SendCoinsDialog) + ui(new Ui::SendCoinsDialog), + model(0) { ui->setupUi(this); @@ -35,6 +37,11 @@ SendCoinsDialog::SendCoinsDialog(QWidget *parent, const QString &address) : } } +void SendCoinsDialog::setModel(ClientModel *model) +{ + this->model = model; +} + SendCoinsDialog::~SendCoinsDialog() { delete ui; @@ -42,35 +49,50 @@ SendCoinsDialog::~SendCoinsDialog() void SendCoinsDialog::on_sendButton_clicked() { - QByteArray payTo = ui->payTo->text().toUtf8(); - uint160 payToHash = 0; - int64 payAmount = 0.0; - bool valid = false; + bool valid; + QString payAmount = ui->payAmount->text(); + qint64 payAmountParsed; - if(!AddressToHash160(payTo.constData(), payToHash)) + valid = ParseMoney(payAmount.toStdString(), payAmountParsed); + + if(!valid) { - QMessageBox::warning(this, tr("Warning"), - tr("The recepient address is not valid, please recheck."), - QMessageBox::Ok, - QMessageBox::Ok); - ui->payTo->setFocus(); + QMessageBox::warning(this, tr("Send Coins"), + tr("The amount to pay must be a valid number."), + QMessageBox::Ok, QMessageBox::Ok); return; } - valid = ParseMoney(ui->payAmount->text().toStdString(), payAmount); - if(!valid || payAmount <= 0) + switch(model->sendCoins(ui->payTo->text(), payAmountParsed)) { - QMessageBox::warning(this, tr("Warning"), - tr("The amount to pay must be a valid number larger than 0."), - QMessageBox::Ok, - QMessageBox::Ok); + case ClientModel::InvalidAddress: + QMessageBox::warning(this, tr("Send Coins"), + tr("The recepient address is not valid, please recheck."), + QMessageBox::Ok, QMessageBox::Ok); + ui->payTo->setFocus(); + break; + case ClientModel::InvalidAmount: + QMessageBox::warning(this, tr("Send Coins"), + tr("The amount to pay must be larger than 0."), + QMessageBox::Ok, QMessageBox::Ok); ui->payAmount->setFocus(); - return; + break; + case ClientModel::AmountExceedsBalance: + QMessageBox::warning(this, tr("Send Coins"), + tr("Amount exceeds your balance"), + QMessageBox::Ok, QMessageBox::Ok); + ui->payAmount->setFocus(); + break; + case ClientModel::AmountWithFeeExceedsBalance: + QMessageBox::warning(this, tr("Send Coins"), + tr("Total exceeds your balance when the %1 transaction fee is included"). + arg(QString::fromStdString(FormatMoney(model->getTransactionFee()))), + QMessageBox::Ok, QMessageBox::Ok); + ui->payAmount->setFocus(); + break; } - qDebug() << "Pay " << payAmount; - /* TODO: send command to core, once this succeeds do accept() */ - accept(); + //accept(); } void SendCoinsDialog::on_pasteButton_clicked()