neobytes/src/qt/sendcoinsdialog.cpp
sje397 8fdb7e108f Added 'immature balance' for miners. Only displayed if the balance is greater than zero.
This adds a field labelled 'Immature' in the overview section under the 'unconfirmed' field, which shows mined
income that has not yet matured (which is currently not displayed anywhere, even though the transactions
exist in the transaction list). To do that I added a 'GetImmatureBalance' method to the wallet, and connected
that through to the GUI as per the 'GetBalance' and 'GetUnconfirmedBalance' methods. I did a small 'no-op'
change to make the code in adjacent functions a little more readable (imo); it was a change I had made in my
repo earlier...but I thought it wouldn't hurt so left it in. Immature balance comes from mined income that is
at least two blocks deep in the chain (same logic as displayed transactions).

My reasoning is:
- as a miner, it's a critical stat I want to see
- as a miner, and taking into account the label 'immature', the uncertainty is pretty clearly implied
- those numbers are already displayed in the transaction list
- this makes the overview numbers add up to what's in the transaction list
- it's not displayed if the immature balance is 0, so won't bother non-miners

I also 'cleaned' the overview UI a little, moving code to the XML and removing HTML.
2012-05-25 23:15:27 +10:00

290 lines
8.0 KiB
C++

#include "sendcoinsdialog.h"
#include "ui_sendcoinsdialog.h"
#include "walletmodel.h"
#include "bitcoinunits.h"
#include "addressbookpage.h"
#include "optionsmodel.h"
#include "sendcoinsentry.h"
#include "guiutil.h"
#include "askpassphrasedialog.h"
#include <QMessageBox>
#include <QLocale>
#include <QTextDocument>
#include <QScrollBar>
SendCoinsDialog::SendCoinsDialog(QWidget *parent) :
QDialog(parent),
ui(new Ui::SendCoinsDialog),
model(0)
{
ui->setupUi(this);
#ifdef Q_WS_MAC // Icons on push buttons are very uncommon on Mac
ui->addButton->setIcon(QIcon());
ui->clearButton->setIcon(QIcon());
ui->sendButton->setIcon(QIcon());
#endif
addEntry();
connect(ui->addButton, SIGNAL(clicked()), this, SLOT(addEntry()));
connect(ui->clearButton, SIGNAL(clicked()), this, SLOT(clear()));
fNewRecipientAllowed = true;
}
void SendCoinsDialog::setModel(WalletModel *model)
{
this->model = model;
for(int i = 0; i < ui->entries->count(); ++i)
{
SendCoinsEntry *entry = qobject_cast<SendCoinsEntry*>(ui->entries->itemAt(i)->widget());
if(entry)
{
entry->setModel(model);
}
}
if(model)
{
setBalance(model->getBalance(), model->getUnconfirmedBalance(), model->getImmatureBalance());
connect(model, SIGNAL(balanceChanged(qint64, qint64, qint64)), this, SLOT(setBalance(qint64, qint64, qint64)));
}
}
SendCoinsDialog::~SendCoinsDialog()
{
delete ui;
}
void SendCoinsDialog::on_sendButton_clicked()
{
QList<SendCoinsRecipient> recipients;
bool valid = true;
if(!model)
return;
for(int i = 0; i < ui->entries->count(); ++i)
{
SendCoinsEntry *entry = qobject_cast<SendCoinsEntry*>(ui->entries->itemAt(i)->widget());
if(entry)
{
if(entry->validate())
{
recipients.append(entry->getValue());
}
else
{
valid = false;
}
}
}
if(!valid || recipients.isEmpty())
{
return;
}
// Format confirmation message
QStringList formatted;
foreach(const SendCoinsRecipient &rcp, recipients)
{
formatted.append(tr("<b>%1</b> to %2 (%3)").arg(BitcoinUnits::formatWithUnit(BitcoinUnits::BTC, rcp.amount), Qt::escape(rcp.label), rcp.address));
}
fNewRecipientAllowed = false;
QMessageBox::StandardButton retval = QMessageBox::question(this, tr("Confirm send coins"),
tr("Are you sure you want to send %1?").arg(formatted.join(tr(" and "))),
QMessageBox::Yes|QMessageBox::Cancel,
QMessageBox::Cancel);
if(retval != QMessageBox::Yes)
{
fNewRecipientAllowed = true;
return;
}
WalletModel::UnlockContext ctx(model->requestUnlock());
if(!ctx.isValid())
{
// Unlock wallet was cancelled
fNewRecipientAllowed = true;
return;
}
WalletModel::SendCoinsReturn sendstatus = model->sendCoins(recipients);
switch(sendstatus.status)
{
case WalletModel::InvalidAddress:
QMessageBox::warning(this, tr("Send Coins"),
tr("The recepient address is not valid, please recheck."),
QMessageBox::Ok, QMessageBox::Ok);
break;
case WalletModel::InvalidAmount:
QMessageBox::warning(this, tr("Send Coins"),
tr("The amount to pay must be larger than 0."),
QMessageBox::Ok, QMessageBox::Ok);
break;
case WalletModel::AmountExceedsBalance:
QMessageBox::warning(this, tr("Send Coins"),
tr("The amount exceeds your balance."),
QMessageBox::Ok, QMessageBox::Ok);
break;
case WalletModel::AmountWithFeeExceedsBalance:
QMessageBox::warning(this, tr("Send Coins"),
tr("The total exceeds your balance when the %1 transaction fee is included.").
arg(BitcoinUnits::formatWithUnit(BitcoinUnits::BTC, sendstatus.fee)),
QMessageBox::Ok, QMessageBox::Ok);
break;
case WalletModel::DuplicateAddress:
QMessageBox::warning(this, tr("Send Coins"),
tr("Duplicate address found, can only send to each address once per send operation."),
QMessageBox::Ok, QMessageBox::Ok);
break;
case WalletModel::TransactionCreationFailed:
QMessageBox::warning(this, tr("Send Coins"),
tr("Error: Transaction creation failed."),
QMessageBox::Ok, QMessageBox::Ok);
break;
case WalletModel::TransactionCommitFailed:
QMessageBox::warning(this, tr("Send Coins"),
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."),
QMessageBox::Ok, QMessageBox::Ok);
break;
case WalletModel::Aborted: // User aborted, nothing to do
break;
case WalletModel::OK:
accept();
break;
}
fNewRecipientAllowed = true;
}
void SendCoinsDialog::clear()
{
// Remove entries until only one left
while(ui->entries->count())
{
delete ui->entries->takeAt(0)->widget();
}
addEntry();
updateRemoveEnabled();
ui->sendButton->setDefault(true);
}
void SendCoinsDialog::reject()
{
clear();
}
void SendCoinsDialog::accept()
{
clear();
}
SendCoinsEntry *SendCoinsDialog::addEntry()
{
SendCoinsEntry *entry = new SendCoinsEntry(this);
entry->setModel(model);
ui->entries->addWidget(entry);
connect(entry, SIGNAL(removeEntry(SendCoinsEntry*)), this, SLOT(removeEntry(SendCoinsEntry*)));
updateRemoveEnabled();
// Focus the field, so that entry can start immediately
entry->clear();
entry->setFocus();
ui->scrollAreaWidgetContents->resize(ui->scrollAreaWidgetContents->sizeHint());
QCoreApplication::instance()->processEvents();
QScrollBar* bar = ui->scrollArea->verticalScrollBar();
if (bar)
bar->setSliderPosition(bar->maximum());
return entry;
}
void SendCoinsDialog::updateRemoveEnabled()
{
// Remove buttons are enabled as soon as there is more than one send-entry
bool enabled = (ui->entries->count() > 1);
for(int i = 0; i < ui->entries->count(); ++i)
{
SendCoinsEntry *entry = qobject_cast<SendCoinsEntry*>(ui->entries->itemAt(i)->widget());
if(entry)
{
entry->setRemoveEnabled(enabled);
}
}
setupTabChain(0);
}
void SendCoinsDialog::removeEntry(SendCoinsEntry* entry)
{
delete entry;
updateRemoveEnabled();
}
QWidget *SendCoinsDialog::setupTabChain(QWidget *prev)
{
for(int i = 0; i < ui->entries->count(); ++i)
{
SendCoinsEntry *entry = qobject_cast<SendCoinsEntry*>(ui->entries->itemAt(i)->widget());
if(entry)
{
prev = entry->setupTabChain(prev);
}
}
QWidget::setTabOrder(prev, ui->addButton);
QWidget::setTabOrder(ui->addButton, ui->sendButton);
return ui->sendButton;
}
void SendCoinsDialog::pasteEntry(const SendCoinsRecipient &rv)
{
if (!fNewRecipientAllowed)
return;
SendCoinsEntry *entry = 0;
// Replace the first entry if it is still unused
if(ui->entries->count() == 1)
{
SendCoinsEntry *first = qobject_cast<SendCoinsEntry*>(ui->entries->itemAt(0)->widget());
if(first->isClear())
{
entry = first;
}
}
if(!entry)
{
entry = addEntry();
}
entry->setValue(rv);
}
void SendCoinsDialog::handleURI(const QString &uri)
{
SendCoinsRecipient rv;
if(!GUIUtil::parseBitcoinURI(uri, &rv))
{
return;
}
pasteEntry(rv);
}
void SendCoinsDialog::setBalance(qint64 balance, qint64 unconfirmedBalance, qint64 immatureBalance)
{
Q_UNUSED(unconfirmedBalance);
Q_UNUSED(immatureBalance);
if(!model || !model->getOptionsModel())
return;
int unit = model->getOptionsModel()->getDisplayUnit();
ui->labelBalance->setText(BitcoinUnits::formatWithUnit(unit, balance));
}