mirror of
https://github.com/bitcoin/bitcoin.git
synced 2025-02-27 20:42:47 +01:00
Make users accustomed to the other subdivision units (mBTC, muBTC) by showing the total amount in all units in the confirmation dialog. This was recently raised on the mailing list and could be a preparation for switching over the default unit eventually.
623 lines
21 KiB
C++
623 lines
21 KiB
C++
// Copyright (c) 2011-2013 The Bitcoin developers
|
|
// Distributed under the MIT/X11 software license, see the accompanying
|
|
// file COPYING or http://www.opensource.org/licenses/mit-license.php.
|
|
|
|
#include "sendcoinsdialog.h"
|
|
#include "ui_sendcoinsdialog.h"
|
|
|
|
#include "bitcoinunits.h"
|
|
#include "guiutil.h"
|
|
#include "optionsmodel.h"
|
|
#include "sendcoinsentry.h"
|
|
#include "walletmodel.h"
|
|
#include "coincontroldialog.h"
|
|
#include "addresstablemodel.h"
|
|
|
|
#include "base58.h"
|
|
#include "ui_interface.h"
|
|
#include "coincontrol.h"
|
|
|
|
#include <QMessageBox>
|
|
#include <QScrollBar>
|
|
#include <QTextDocument>
|
|
|
|
SendCoinsDialog::SendCoinsDialog(QWidget *parent) :
|
|
QDialog(parent),
|
|
ui(new Ui::SendCoinsDialog),
|
|
model(0)
|
|
{
|
|
ui->setupUi(this);
|
|
|
|
#ifdef Q_OS_MAC // Icons on push buttons are very uncommon on Mac
|
|
ui->addButton->setIcon(QIcon());
|
|
ui->clearButton->setIcon(QIcon());
|
|
ui->sendButton->setIcon(QIcon());
|
|
#endif
|
|
#if QT_VERSION >= 0x040700
|
|
/* Do not move this to the XML file, Qt before 4.7 will choke on it */
|
|
ui->lineEditCoinControlChange->setPlaceholderText(tr("Enter a Bitcoin address (e.g. 1NS17iag9jJgTHD1VXjvLCEnZuQ3rJDE9L)"));
|
|
#endif
|
|
|
|
addEntry();
|
|
|
|
connect(ui->addButton, SIGNAL(clicked()), this, SLOT(addEntry()));
|
|
connect(ui->clearButton, SIGNAL(clicked()), this, SLOT(clear()));
|
|
|
|
// Coin Control
|
|
ui->lineEditCoinControlChange->setFont(GUIUtil::bitcoinAddressFont());
|
|
connect(ui->pushButtonCoinControl, SIGNAL(clicked()), this, SLOT(coinControlButtonClicked()));
|
|
connect(ui->checkBoxCoinControlChange, SIGNAL(stateChanged(int)), this, SLOT(coinControlChangeChecked(int)));
|
|
connect(ui->lineEditCoinControlChange, SIGNAL(textEdited(const QString &)), this, SLOT(coinControlChangeEdited(const QString &)));
|
|
|
|
// Coin Control: clipboard actions
|
|
QAction *clipboardQuantityAction = new QAction(tr("Copy quantity"), this);
|
|
QAction *clipboardAmountAction = new QAction(tr("Copy amount"), this);
|
|
QAction *clipboardFeeAction = new QAction(tr("Copy fee"), this);
|
|
QAction *clipboardAfterFeeAction = new QAction(tr("Copy after fee"), this);
|
|
QAction *clipboardBytesAction = new QAction(tr("Copy bytes"), this);
|
|
QAction *clipboardPriorityAction = new QAction(tr("Copy priority"), this);
|
|
QAction *clipboardLowOutputAction = new QAction(tr("Copy low output"), this);
|
|
QAction *clipboardChangeAction = new QAction(tr("Copy change"), this);
|
|
connect(clipboardQuantityAction, SIGNAL(triggered()), this, SLOT(coinControlClipboardQuantity()));
|
|
connect(clipboardAmountAction, SIGNAL(triggered()), this, SLOT(coinControlClipboardAmount()));
|
|
connect(clipboardFeeAction, SIGNAL(triggered()), this, SLOT(coinControlClipboardFee()));
|
|
connect(clipboardAfterFeeAction, SIGNAL(triggered()), this, SLOT(coinControlClipboardAfterFee()));
|
|
connect(clipboardBytesAction, SIGNAL(triggered()), this, SLOT(coinControlClipboardBytes()));
|
|
connect(clipboardPriorityAction, SIGNAL(triggered()), this, SLOT(coinControlClipboardPriority()));
|
|
connect(clipboardLowOutputAction, SIGNAL(triggered()), this, SLOT(coinControlClipboardLowOutput()));
|
|
connect(clipboardChangeAction, SIGNAL(triggered()), this, SLOT(coinControlClipboardChange()));
|
|
ui->labelCoinControlQuantity->addAction(clipboardQuantityAction);
|
|
ui->labelCoinControlAmount->addAction(clipboardAmountAction);
|
|
ui->labelCoinControlFee->addAction(clipboardFeeAction);
|
|
ui->labelCoinControlAfterFee->addAction(clipboardAfterFeeAction);
|
|
ui->labelCoinControlBytes->addAction(clipboardBytesAction);
|
|
ui->labelCoinControlPriority->addAction(clipboardPriorityAction);
|
|
ui->labelCoinControlLowOutput->addAction(clipboardLowOutputAction);
|
|
ui->labelCoinControlChange->addAction(clipboardChangeAction);
|
|
|
|
fNewRecipientAllowed = true;
|
|
}
|
|
|
|
void SendCoinsDialog::setModel(WalletModel *model)
|
|
{
|
|
this->model = model;
|
|
|
|
if(model && model->getOptionsModel())
|
|
{
|
|
for(int i = 0; i < ui->entries->count(); ++i)
|
|
{
|
|
SendCoinsEntry *entry = qobject_cast<SendCoinsEntry*>(ui->entries->itemAt(i)->widget());
|
|
if(entry)
|
|
{
|
|
entry->setModel(model);
|
|
}
|
|
}
|
|
|
|
setBalance(model->getBalance(), model->getUnconfirmedBalance(), model->getImmatureBalance());
|
|
connect(model, SIGNAL(balanceChanged(qint64, qint64, qint64)), this, SLOT(setBalance(qint64, qint64, qint64)));
|
|
connect(model->getOptionsModel(), SIGNAL(displayUnitChanged(int)), this, SLOT(updateDisplayUnit()));
|
|
|
|
// Coin Control
|
|
connect(model->getOptionsModel(), SIGNAL(displayUnitChanged(int)), this, SLOT(coinControlUpdateLabels()));
|
|
connect(model->getOptionsModel(), SIGNAL(coinControlFeaturesChanged(bool)), this, SLOT(coinControlFeatureChanged(bool)));
|
|
connect(model->getOptionsModel(), SIGNAL(transactionFeeChanged(qint64)), this, SLOT(coinControlUpdateLabels()));
|
|
ui->frameCoinControl->setVisible(model->getOptionsModel()->getCoinControlFeatures());
|
|
coinControlUpdateLabels();
|
|
}
|
|
}
|
|
|
|
SendCoinsDialog::~SendCoinsDialog()
|
|
{
|
|
delete ui;
|
|
}
|
|
|
|
void SendCoinsDialog::on_sendButton_clicked()
|
|
{
|
|
if(!model || !model->getOptionsModel())
|
|
return;
|
|
|
|
QList<SendCoinsRecipient> recipients;
|
|
bool valid = true;
|
|
|
|
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)
|
|
{
|
|
// generate bold amount string
|
|
QString amount = "<b>" + BitcoinUnits::formatWithUnit(model->getOptionsModel()->getDisplayUnit(), rcp.amount);
|
|
amount.append("</b>");
|
|
// generate monospace address string
|
|
QString address = "<span style='font-family: monospace;'>" + rcp.address;
|
|
address.append("</span>");
|
|
|
|
QString recipientElement;
|
|
|
|
if (!rcp.paymentRequest.IsInitialized()) // normal payment
|
|
{
|
|
if(rcp.label.length() > 0) // label with address
|
|
{
|
|
recipientElement = tr("%1 to %2").arg(amount, GUIUtil::HtmlEscape(rcp.label));
|
|
recipientElement.append(QString(" (%1)").arg(address));
|
|
}
|
|
else // just address
|
|
{
|
|
recipientElement = tr("%1 to %2").arg(amount, address);
|
|
}
|
|
}
|
|
else if(!rcp.authenticatedMerchant.isEmpty()) // secure payment request
|
|
{
|
|
recipientElement = tr("%1 to %2").arg(amount, GUIUtil::HtmlEscape(rcp.authenticatedMerchant));
|
|
}
|
|
else // insecure payment request
|
|
{
|
|
recipientElement = tr("%1 to %2").arg(amount, address);
|
|
}
|
|
|
|
formatted.append(recipientElement);
|
|
}
|
|
|
|
fNewRecipientAllowed = false;
|
|
|
|
|
|
WalletModel::UnlockContext ctx(model->requestUnlock());
|
|
if(!ctx.isValid())
|
|
{
|
|
// Unlock wallet was cancelled
|
|
fNewRecipientAllowed = true;
|
|
return;
|
|
}
|
|
|
|
// prepare transaction for getting txFee earlier
|
|
WalletModelTransaction currentTransaction(recipients);
|
|
WalletModel::SendCoinsReturn prepareStatus;
|
|
if (model->getOptionsModel()->getCoinControlFeatures()) // coin control enabled
|
|
prepareStatus = model->prepareTransaction(currentTransaction, CoinControlDialog::coinControl);
|
|
else
|
|
prepareStatus = model->prepareTransaction(currentTransaction);
|
|
|
|
// process prepareStatus and on error generate message shown to user
|
|
processSendCoinsReturn(prepareStatus,
|
|
BitcoinUnits::formatWithUnit(model->getOptionsModel()->getDisplayUnit(), currentTransaction.getTransactionFee()));
|
|
|
|
if(prepareStatus.status != WalletModel::OK) {
|
|
fNewRecipientAllowed = true;
|
|
return;
|
|
}
|
|
|
|
qint64 txFee = currentTransaction.getTransactionFee();
|
|
QString questionString = tr("Are you sure you want to send?");
|
|
questionString.append("<br /><br />%1");
|
|
|
|
if(txFee > 0)
|
|
{
|
|
// append fee string if a fee is required
|
|
questionString.append("<hr /><span style='color:#aa0000;'>");
|
|
questionString.append(BitcoinUnits::formatWithUnit(model->getOptionsModel()->getDisplayUnit(), txFee));
|
|
questionString.append("</span> ");
|
|
questionString.append(tr("added as transaction fee"));
|
|
}
|
|
|
|
// add total amount in all subdivision units
|
|
questionString.append("<hr />");
|
|
qint64 totalAmount = currentTransaction.getTotalTransactionAmount() + txFee;
|
|
QStringList alternativeUnits;
|
|
foreach(BitcoinUnits::Unit u, BitcoinUnits::availableUnits())
|
|
{
|
|
if(u != model->getOptionsModel()->getDisplayUnit())
|
|
alternativeUnits.append(BitcoinUnits::formatWithUnit(u, totalAmount));
|
|
}
|
|
questionString.append(tr("Total Amount %1 (= %2)")
|
|
.arg(BitcoinUnits::formatWithUnit(model->getOptionsModel()->getDisplayUnit(), totalAmount))
|
|
.arg(alternativeUnits.join(" "+tr("or")+" ")));
|
|
|
|
QMessageBox::StandardButton retval = QMessageBox::question(this, tr("Confirm send coins"),
|
|
questionString.arg(formatted.join("<br />")),
|
|
QMessageBox::Yes | QMessageBox::Cancel,
|
|
QMessageBox::Cancel);
|
|
|
|
if(retval != QMessageBox::Yes)
|
|
{
|
|
fNewRecipientAllowed = true;
|
|
return;
|
|
}
|
|
|
|
// now send the prepared transaction
|
|
WalletModel::SendCoinsReturn sendStatus = model->sendCoins(currentTransaction);
|
|
// process sendStatus and on error generate message shown to user
|
|
processSendCoinsReturn(sendStatus);
|
|
|
|
if (sendStatus.status == WalletModel::OK)
|
|
{
|
|
accept();
|
|
CoinControlDialog::coinControl->UnSelectAll();
|
|
coinControlUpdateLabels();
|
|
}
|
|
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*)));
|
|
connect(entry, SIGNAL(payAmountChanged()), this, SLOT(coinControlUpdateLabels()));
|
|
|
|
updateRemoveEnabled();
|
|
|
|
// Focus the field, so that entry can start immediately
|
|
entry->clear();
|
|
entry->setFocus();
|
|
ui->scrollAreaWidgetContents->resize(ui->scrollAreaWidgetContents->sizeHint());
|
|
qApp->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);
|
|
|
|
coinControlUpdateLabels();
|
|
}
|
|
|
|
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::setAddress(const QString &address)
|
|
{
|
|
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->setAddress(address);
|
|
}
|
|
|
|
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);
|
|
coinControlUpdateLabels();
|
|
}
|
|
|
|
bool SendCoinsDialog::handlePaymentRequest(const SendCoinsRecipient &rv)
|
|
{
|
|
QString strSendCoins = tr("Send Coins");
|
|
if (rv.paymentRequest.IsInitialized()) {
|
|
// Expired payment request?
|
|
const payments::PaymentDetails& details = rv.paymentRequest.getDetails();
|
|
if (details.has_expires() && (int64_t)details.expires() < GetTime())
|
|
{
|
|
emit message(strSendCoins, tr("Payment request expired"),
|
|
CClientUIInterface::MSG_WARNING);
|
|
return false;
|
|
}
|
|
}
|
|
else {
|
|
CBitcoinAddress address(rv.address.toStdString());
|
|
if (!address.IsValid()) {
|
|
emit message(strSendCoins, tr("Invalid payment address %1").arg(rv.address),
|
|
CClientUIInterface::MSG_WARNING);
|
|
return false;
|
|
}
|
|
}
|
|
|
|
pasteEntry(rv);
|
|
return true;
|
|
}
|
|
|
|
void SendCoinsDialog::setBalance(qint64 balance, qint64 unconfirmedBalance, qint64 immatureBalance)
|
|
{
|
|
Q_UNUSED(unconfirmedBalance);
|
|
Q_UNUSED(immatureBalance);
|
|
|
|
if(model && model->getOptionsModel())
|
|
{
|
|
ui->labelBalance->setText(BitcoinUnits::formatWithUnit(model->getOptionsModel()->getDisplayUnit(), balance));
|
|
}
|
|
}
|
|
|
|
void SendCoinsDialog::updateDisplayUnit()
|
|
{
|
|
setBalance(model->getBalance(), 0, 0);
|
|
}
|
|
|
|
void SendCoinsDialog::processSendCoinsReturn(const WalletModel::SendCoinsReturn &sendCoinsReturn, const QString &msgArg)
|
|
{
|
|
QPair<QString, CClientUIInterface::MessageBoxFlags> msgParams;
|
|
// Default to a warning message, override if error message is needed
|
|
msgParams.second = CClientUIInterface::MSG_WARNING;
|
|
|
|
// This comment is specific to SendCoinsDialog usage of WalletModel::SendCoinsReturn.
|
|
// WalletModel::TransactionCommitFailed is used only in WalletModel::sendCoins()
|
|
// all others are used only in WalletModel::prepareTransaction()
|
|
switch(sendCoinsReturn.status)
|
|
{
|
|
case WalletModel::InvalidAddress:
|
|
msgParams.first = tr("The recipient address is not valid, please recheck.");
|
|
break;
|
|
case WalletModel::InvalidAmount:
|
|
msgParams.first = tr("The amount to pay must be larger than 0.");
|
|
break;
|
|
case WalletModel::AmountExceedsBalance:
|
|
msgParams.first = tr("The amount exceeds your balance.");
|
|
break;
|
|
case WalletModel::AmountWithFeeExceedsBalance:
|
|
msgParams.first = tr("The total exceeds your balance when the %1 transaction fee is included.").arg(msgArg);
|
|
break;
|
|
case WalletModel::DuplicateAddress:
|
|
msgParams.first = tr("Duplicate address found, can only send to each address once per send operation.");
|
|
break;
|
|
case WalletModel::TransactionCreationFailed:
|
|
msgParams.first = tr("Transaction creation failed!");
|
|
msgParams.second = CClientUIInterface::MSG_ERROR;
|
|
break;
|
|
case WalletModel::TransactionCommitFailed:
|
|
msgParams.first = tr("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.");
|
|
msgParams.second = CClientUIInterface::MSG_ERROR;
|
|
break;
|
|
// OK and Aborted are included to prevent a compiler warning.
|
|
case WalletModel::OK:
|
|
case WalletModel::Aborted:
|
|
default:
|
|
return;
|
|
}
|
|
|
|
emit message(tr("Send Coins"), msgParams.first, msgParams.second);
|
|
}
|
|
|
|
// Coin Control: copy label "Quantity" to clipboard
|
|
void SendCoinsDialog::coinControlClipboardQuantity()
|
|
{
|
|
GUIUtil::setClipboard(ui->labelCoinControlQuantity->text());
|
|
}
|
|
|
|
// Coin Control: copy label "Amount" to clipboard
|
|
void SendCoinsDialog::coinControlClipboardAmount()
|
|
{
|
|
GUIUtil::setClipboard(ui->labelCoinControlAmount->text().left(ui->labelCoinControlAmount->text().indexOf(" ")));
|
|
}
|
|
|
|
// Coin Control: copy label "Fee" to clipboard
|
|
void SendCoinsDialog::coinControlClipboardFee()
|
|
{
|
|
GUIUtil::setClipboard(ui->labelCoinControlFee->text().left(ui->labelCoinControlFee->text().indexOf(" ")));
|
|
}
|
|
|
|
// Coin Control: copy label "After fee" to clipboard
|
|
void SendCoinsDialog::coinControlClipboardAfterFee()
|
|
{
|
|
GUIUtil::setClipboard(ui->labelCoinControlAfterFee->text().left(ui->labelCoinControlAfterFee->text().indexOf(" ")));
|
|
}
|
|
|
|
// Coin Control: copy label "Bytes" to clipboard
|
|
void SendCoinsDialog::coinControlClipboardBytes()
|
|
{
|
|
GUIUtil::setClipboard(ui->labelCoinControlBytes->text());
|
|
}
|
|
|
|
// Coin Control: copy label "Priority" to clipboard
|
|
void SendCoinsDialog::coinControlClipboardPriority()
|
|
{
|
|
GUIUtil::setClipboard(ui->labelCoinControlPriority->text());
|
|
}
|
|
|
|
// Coin Control: copy label "Low output" to clipboard
|
|
void SendCoinsDialog::coinControlClipboardLowOutput()
|
|
{
|
|
GUIUtil::setClipboard(ui->labelCoinControlLowOutput->text());
|
|
}
|
|
|
|
// Coin Control: copy label "Change" to clipboard
|
|
void SendCoinsDialog::coinControlClipboardChange()
|
|
{
|
|
GUIUtil::setClipboard(ui->labelCoinControlChange->text().left(ui->labelCoinControlChange->text().indexOf(" ")));
|
|
}
|
|
|
|
// Coin Control: settings menu - coin control enabled/disabled by user
|
|
void SendCoinsDialog::coinControlFeatureChanged(bool checked)
|
|
{
|
|
ui->frameCoinControl->setVisible(checked);
|
|
|
|
if (!checked && model) // coin control features disabled
|
|
CoinControlDialog::coinControl->SetNull();
|
|
}
|
|
|
|
// Coin Control: button inputs -> show actual coin control dialog
|
|
void SendCoinsDialog::coinControlButtonClicked()
|
|
{
|
|
CoinControlDialog dlg;
|
|
dlg.setModel(model);
|
|
dlg.exec();
|
|
coinControlUpdateLabels();
|
|
}
|
|
|
|
// Coin Control: checkbox custom change address
|
|
void SendCoinsDialog::coinControlChangeChecked(int state)
|
|
{
|
|
if (model)
|
|
{
|
|
if (state == Qt::Checked)
|
|
CoinControlDialog::coinControl->destChange = CBitcoinAddress(ui->lineEditCoinControlChange->text().toStdString()).Get();
|
|
else
|
|
CoinControlDialog::coinControl->destChange = CNoDestination();
|
|
}
|
|
|
|
ui->lineEditCoinControlChange->setEnabled((state == Qt::Checked));
|
|
ui->labelCoinControlChangeLabel->setVisible((state == Qt::Checked));
|
|
}
|
|
|
|
// Coin Control: custom change address changed
|
|
void SendCoinsDialog::coinControlChangeEdited(const QString & text)
|
|
{
|
|
if (model)
|
|
{
|
|
CoinControlDialog::coinControl->destChange = CBitcoinAddress(text.toStdString()).Get();
|
|
|
|
// label for the change address
|
|
ui->labelCoinControlChangeLabel->setStyleSheet("QLabel{color:black;}");
|
|
if (text.isEmpty())
|
|
ui->labelCoinControlChangeLabel->setText("");
|
|
else if (!CBitcoinAddress(text.toStdString()).IsValid())
|
|
{
|
|
ui->labelCoinControlChangeLabel->setStyleSheet("QLabel{color:red;}");
|
|
ui->labelCoinControlChangeLabel->setText(tr("Warning: Invalid Bitcoin address"));
|
|
}
|
|
else
|
|
{
|
|
QString associatedLabel = model->getAddressTableModel()->labelForAddress(text);
|
|
if (!associatedLabel.isEmpty())
|
|
ui->labelCoinControlChangeLabel->setText(associatedLabel);
|
|
else
|
|
{
|
|
CPubKey pubkey;
|
|
CKeyID keyid;
|
|
CBitcoinAddress(text.toStdString()).GetKeyID(keyid);
|
|
if (model->getPubKey(keyid, pubkey))
|
|
ui->labelCoinControlChangeLabel->setText(tr("(no label)"));
|
|
else
|
|
{
|
|
ui->labelCoinControlChangeLabel->setStyleSheet("QLabel{color:red;}");
|
|
ui->labelCoinControlChangeLabel->setText(tr("Warning: Unknown change address"));
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
// Coin Control: update labels
|
|
void SendCoinsDialog::coinControlUpdateLabels()
|
|
{
|
|
if (!model || !model->getOptionsModel() || !model->getOptionsModel()->getCoinControlFeatures())
|
|
return;
|
|
|
|
// set pay amounts
|
|
CoinControlDialog::payAmounts.clear();
|
|
for(int i = 0; i < ui->entries->count(); ++i)
|
|
{
|
|
SendCoinsEntry *entry = qobject_cast<SendCoinsEntry*>(ui->entries->itemAt(i)->widget());
|
|
if(entry)
|
|
CoinControlDialog::payAmounts.append(entry->getValue().amount);
|
|
}
|
|
|
|
if (CoinControlDialog::coinControl->HasSelected())
|
|
{
|
|
// actual coin control calculation
|
|
CoinControlDialog::updateLabels(model, this);
|
|
|
|
// show coin control stats
|
|
ui->labelCoinControlAutomaticallySelected->hide();
|
|
ui->widgetCoinControl->show();
|
|
}
|
|
else
|
|
{
|
|
// hide coin control stats
|
|
ui->labelCoinControlAutomaticallySelected->show();
|
|
ui->widgetCoinControl->hide();
|
|
ui->labelCoinControlInsuffFunds->hide();
|
|
}
|
|
}
|
|
|