7 #include "ui_sendcoinsdialog.h" 23 #include "validation.h" 29 #include <QGraphicsDropShadowEffect> 30 #include <QFontMetrics> 31 #include <QMessageBox> 34 #include <QTextDocument> 42 fNewRecipientAllowed(true),
44 platformStyle(_platformStyle)
49 ui->addButton->setIcon(QIcon());
50 ui->clearButton->setIcon(QIcon());
51 ui->sendButton->setIcon(QIcon());
62 connect(
ui->addButton, SIGNAL(clicked()),
this, SLOT(
addEntry()));
63 connect(
ui->clearButton, SIGNAL(clicked()),
this, SLOT(
clear()));
68 connect(
ui->lineEditCoinControlChange, SIGNAL(textEdited(
const QString &)),
this, SLOT(
coinControlChangeEdited(
const QString &)));
71 QAction *clipboardQuantityAction =
new QAction(tr(
"Copy quantity"),
this);
72 QAction *clipboardAmountAction =
new QAction(tr(
"Copy amount"),
this);
73 QAction *clipboardFeeAction =
new QAction(tr(
"Copy fee"),
this);
74 QAction *clipboardAfterFeeAction =
new QAction(tr(
"Copy after fee"),
this);
75 QAction *clipboardBytesAction =
new QAction(tr(
"Copy bytes"),
this);
76 QAction *clipboardLowOutputAction =
new QAction(tr(
"Copy dust"),
this);
77 QAction *clipboardChangeAction =
new QAction(tr(
"Copy change"),
this);
85 ui->labelCoinControlQuantity->addAction(clipboardQuantityAction);
86 ui->labelCoinControlAmount->addAction(clipboardAmountAction);
87 ui->labelCoinControlFee->addAction(clipboardFeeAction);
88 ui->labelCoinControlAfterFee->addAction(clipboardAfterFeeAction);
89 ui->labelCoinControlBytes->addAction(clipboardBytesAction);
90 ui->labelCoinControlLowOutput->addAction(clipboardLowOutputAction);
91 ui->labelCoinControlChange->addAction(clipboardChangeAction);
95 if (!settings.contains(
"fFeeSectionMinimized"))
96 settings.setValue(
"fFeeSectionMinimized",
true);
97 if (!settings.contains(
"nFeeRadio") && settings.contains(
"nTransactionFee") && settings.value(
"nTransactionFee").toLongLong() > 0)
98 settings.setValue(
"nFeeRadio", 1);
99 if (!settings.contains(
"nFeeRadio"))
100 settings.setValue(
"nFeeRadio", 0);
101 if (!settings.contains(
"nSmartFeeSliderPosition"))
102 settings.setValue(
"nSmartFeeSliderPosition", 0);
103 if (!settings.contains(
"nTransactionFee"))
104 settings.setValue(
"nTransactionFee", (qint64)DEFAULT_TRANSACTION_FEE);
105 if (!settings.contains(
"fPayOnlyMinFee"))
106 settings.setValue(
"fPayOnlyMinFee",
false);
107 ui->groupFee->setId(
ui->radioSmartFee, 0);
108 ui->groupFee->setId(
ui->radioCustomFee, 1);
109 ui->groupFee->button((
int)std::max(0, std::min(1, settings.value(
"nFeeRadio").toInt())))->setChecked(
true);
110 ui->customFee->setValue(settings.value(
"nTransactionFee").toLongLong());
111 ui->checkBoxMinimumFee->setChecked(settings.value(
"fPayOnlyMinFee").toBool());
125 connect(_clientModel, SIGNAL(numBlocksChanged(
int,QDateTime,
double,
bool)),
this, SLOT(
updateSmartFeeLabel()));
131 this->
model = _model;
135 for(
int i = 0; i <
ui->entries->count(); ++i)
146 connect(_model, SIGNAL(balanceChanged(
CAmount,
CAmount,
CAmount,
CAmount,
CAmount,
CAmount)),
this, SLOT(
setBalance(
CAmount,
CAmount,
CAmount,
CAmount,
CAmount,
CAmount)));
157 for (
const int &n : confTargets) {
160 connect(
ui->confTargetSelector, SIGNAL(currentIndexChanged(
int)),
this, SLOT(
updateSmartFeeLabel()));
165 connect(
ui->checkBoxMinimumFee, SIGNAL(stateChanged(
int)),
this, SLOT(
setMinimumFee()));
177 ui->optInRBF->hide();
181 if (settings.value(
"nSmartFeeSliderPosition").toInt() != 0) {
184 int nConfirmTarget = 25 - settings.value(
"nSmartFeeSliderPosition").toInt();
185 settings.setValue(
"nConfTarget", nConfirmTarget);
186 settings.remove(
"nSmartFeeSliderPosition");
188 if (settings.value(
"nConfTarget").toInt() == 0)
199 settings.setValue(
"nFeeRadio",
ui->groupFee->checkedId());
201 settings.setValue(
"nTransactionFee", (qint64)
ui->customFee->value());
202 settings.setValue(
"fPayOnlyMinFee",
ui->checkBoxMinimumFee->isChecked());
210 ui->frameCoinControl->setStyleSheet(QString(
".QFrame {background-color: %1; padding-top: 10px; padding-right: 5px; border: none;}").arg(platformStyle->
WidgetBackGroundColor().name()));
211 ui->widgetCoinControl->setStyleSheet(
".QWidget {background-color: transparent;}");
263 ui->scrollArea->setStyleSheet(QString(
".QScrollArea{background-color: %1; border: none}").arg(platformStyle->
WidgetBackGroundColor().name()));
267 ui->entries->setContentsMargins(10,10,20,0);
268 ui->scrollAreaWidgetContents->setStyleSheet(QString(
".QWidget{ background-color: %1;}").arg(platformStyle->
WidgetBackGroundColor().name()));
274 ui->frameFee->setStyleSheet(QString(
".QFrame {background-color: %1; padding-top: 10px; padding-right: 5px; border: none;}").arg(platformStyle->
WidgetBackGroundColor().name()));
314 QList<SendCoinsRecipient> recipients;
317 for(
int i = 0; i <
ui->entries->count(); ++i)
324 recipients.append(entry->
getValue());
333 if(!valid || recipients.isEmpty())
372 QStringList formatted;
377 amount.append(
"</b>");
379 QString address =
"<span style='font-family: monospace;'>" + rcp.address;
380 address.append(
"</span>");
382 QString recipientElement;
384 if (!rcp.paymentRequest.IsInitialized())
386 if(rcp.label.length() > 0)
389 recipientElement.append(QString(
" (%1)").arg(address));
393 recipientElement = tr(
"%1 to %2").arg(amount, address);
396 else if(!rcp.authenticatedMerchant.isEmpty())
398 recipientElement = tr(
"%1 to %2").arg(amount,
GUIUtil::HtmlEscape(rcp.authenticatedMerchant));
402 recipientElement = tr(
"%1 to %2").arg(amount, address);
405 formatted.append(recipientElement);
408 QString questionString = tr(
"Are you sure you want to send?");
409 questionString.append(
"<br /><br />%1");
414 questionString.append(
"<hr /><span style='color:#aa0000;'>");
416 questionString.append(
"</span> ");
417 questionString.append(tr(
"added as transaction fee"));
420 questionString.append(
" (" + QString::number((
double)currentTransaction.
getTransactionSize() / 1000) +
" kB)");
424 questionString.append(
"<hr />");
426 QStringList alternativeUnits;
432 questionString.append(tr(
"Total Amount %1")
434 questionString.append(QString(
"<span style='font-size:10pt;font-weight:normal;'><br />(=%2)</span>")
435 .arg(alternativeUnits.join(
" " + tr(
"or") +
"<br />")));
446 confirmationDialog.
exec();
447 QMessageBox::StandardButton retval = (QMessageBox::StandardButton)confirmationDialog.result();
449 if(retval != QMessageBox::Yes)
472 while(
ui->entries->count())
474 ui->entries->takeAt(0)->widget()->deleteLater();
495 ui->entries->addWidget(entry);
503 ui->scrollAreaWidgetContents->resize(
ui->scrollAreaWidgetContents->sizeHint());
504 qApp->processEvents();
505 QScrollBar* bar =
ui->scrollArea->verticalScrollBar();
507 bar->setSliderPosition(bar->maximum());
524 if (
ui->entries->count() == 1)
527 entry->deleteLater();
534 for(
int i = 0; i <
ui->entries->count(); ++i)
542 QWidget::setTabOrder(prev,
ui->sendButton);
543 QWidget::setTabOrder(
ui->sendButton,
ui->clearButton);
544 QWidget::setTabOrder(
ui->clearButton,
ui->addButton);
545 return ui->addButton;
552 if(
ui->entries->count() == 1)
575 if(
ui->entries->count() == 1)
601 const CAmount& watchBalance,
const CAmount& watchUnconfirmedBalance,
const CAmount& watchImmatureBalance)
603 Q_UNUSED(unconfirmedBalance);
604 Q_UNUSED(immatureBalance);
605 Q_UNUSED(watchBalance);
606 Q_UNUSED(watchUnconfirmedBalance);
607 Q_UNUSED(watchImmatureBalance);
629 QPair<QString, CClientUIInterface::MessageBoxFlags> msgParams;
636 switch(sendCoinsReturn.
status)
639 msgParams.first = tr(
"The recipient address is not valid. Please recheck.");
642 msgParams.first = tr(
"The amount to pay must be larger than 0.");
645 msgParams.first = tr(
"The amount exceeds your balance.");
648 msgParams.first = tr(
"The total exceeds your balance when the %1 transaction fee is included.").arg(msgArg);
651 msgParams.first = tr(
"Duplicate address found: addresses should only be used once each.");
654 msgParams.first = tr(
"Transaction creation failed!");
658 msgParams.first = tr(
"The transaction was rejected with the following reason: %1").arg(sendCoinsReturn.
reasonCommitFailed);
665 msgParams.first = tr(
"Payment request expired.");
674 Q_EMIT
message(tr(
"Send Coins"), msgParams.first, msgParams.second);
679 ui->labelFeeMinimized->setVisible(fMinimize);
680 ui->buttonChooseFee ->setVisible(fMinimize);
681 ui->buttonMinimizeFee->setVisible(!fMinimize);
682 ui->frameFeeSelection->setVisible(!fMinimize);
683 ui->horizontalLayoutSmartFee->setContentsMargins(0, (fMinimize ? 0 : 6), 0, 0);
705 ui->confTargetSelector ->setEnabled(
ui->radioSmartFee->isChecked());
706 ui->labelSmartFee ->setEnabled(
ui->radioSmartFee->isChecked());
707 ui->labelSmartFee2 ->setEnabled(
ui->radioSmartFee->isChecked());
708 ui->labelSmartFee3 ->setEnabled(
ui->radioSmartFee->isChecked());
709 ui->labelFeeEstimation ->setEnabled(
ui->radioSmartFee->isChecked());
710 ui->checkBoxMinimumFee ->setEnabled(
ui->radioCustomFee->isChecked());
711 ui->labelMinFeeWarning ->setEnabled(
ui->radioCustomFee->isChecked());
712 ui->labelCustomPerKilobyte ->setEnabled(
ui->radioCustomFee->isChecked() && !
ui->checkBoxMinimumFee->isChecked());
713 ui->customFee ->setEnabled(
ui->radioCustomFee->isChecked() && !
ui->checkBoxMinimumFee->isChecked());
721 if (
ui->radioSmartFee->isChecked())
722 ui->labelFeeMinimized->setText(
ui->labelSmartFee->text());
731 ui->checkBoxMinimumFee->setText(tr(
"Pay only the required fee of %1").arg(
738 if (
ui->radioCustomFee->isChecked()) {
762 ui->labelSmartFee2->show();
763 ui->labelFeeEstimation->setText(
"");
764 ui->fallbackFeeWarningLabel->setVisible(
true);
765 int lightness =
ui->fallbackFeeWarningLabel->palette().color(QPalette::WindowText).lightness();
766 QColor warning_colour(255 - (lightness / 5), 176 - (lightness / 3), 48 - (lightness / 14));
767 ui->fallbackFeeWarningLabel->setStyleSheet(
"QLabel { color: " + warning_colour.name() +
"; }");
768 ui->fallbackFeeWarningLabel->setIndent(QFontMetrics(
ui->fallbackFeeWarningLabel->font()).width(
"x"));
772 ui->labelSmartFee2->hide();
773 ui->labelFeeEstimation->setText(tr(
"Estimated to begin confirmation within %n block(s).",
"", feeCalc.
returnedTarget));
774 ui->fallbackFeeWarningLabel->setVisible(
false);
825 ui->frameCoinControl->setVisible(checked);
827 if (!checked &&
model)
845 if (state == Qt::Unchecked)
848 ui->labelCoinControlChangeLabel->clear();
854 ui->lineEditCoinControlChange->setEnabled((state == Qt::Checked));
864 ui->labelCoinControlChangeLabel->setStyleSheet(
"QLabel{color:red;}");
870 ui->labelCoinControlChangeLabel->setText(
"");
874 ui->labelCoinControlChangeLabel->setText(tr(
"Warning: Invalid Raven address"));
879 ui->labelCoinControlChangeLabel->setText(tr(
"Warning: Unknown change address"));
882 QMessageBox::StandardButton btnRetVal = QMessageBox::question(
this, tr(
"Confirm custom change address"), tr(
"The address you selected for change is not part of this wallet. Any or all funds in your wallet may be sent to this address. Are you sure?"),
883 QMessageBox::Yes | QMessageBox::Cancel, QMessageBox::Cancel);
885 if(btnRetVal == QMessageBox::Yes)
889 ui->lineEditCoinControlChange->setText(
"");
890 ui->labelCoinControlChangeLabel->setStyleSheet(
"QLabel{color:black;}");
891 ui->labelCoinControlChangeLabel->setText(
"");
896 ui->labelCoinControlChangeLabel->setStyleSheet(
"QLabel{color:black;}");
900 if (!associatedLabel.isEmpty())
901 ui->labelCoinControlChangeLabel->setText(associatedLabel);
903 ui->labelCoinControlChangeLabel->setText(tr(
"(no label)"));
923 for(
int i = 0; i <
ui->entries->count(); ++i)
926 if(entry && !entry->isHidden())
941 ui->labelCoinControlAutomaticallySelected->hide();
942 ui->widgetCoinControl->show();
947 ui->labelCoinControlAutomaticallySelected->show();
948 ui->widgetCoinControl->hide();
949 ui->labelCoinControlInsuffFunds->hide();
955 QMessageBox(QMessageBox::Question, title, text, QMessageBox::Yes | QMessageBox::Cancel, parent), secDelay(_secDelay)
957 setDefaultButton(QMessageBox::Cancel);
967 return QMessageBox::exec();
void removeEntry(SendCoinsEntry *entry)
boost::variant< CNoDestination, CKeyID, CScriptID > CTxDestination
A txout script template with a specific destination.
void setValue(const SendCoinsRecipient &value)
QGraphicsDropShadowEffect * getShadowEffect()
QString reasonCommitFailed
static CCoinControl * coinControl
void updateFeeMinimizedLabel()
boost::optional< unsigned int > m_confirm_target
Override the default confirmation target if set.
void on_buttonChooseFee_clicked()
SendCoinsRecipient getValue()
CAmount maxTxFee
Absolute maximum transaction fee (in satoshis) used by wallet and mempool (rejects high fee in sendra...
UnlockContext requestUnlock()
void coinControlClipboardQuantity()
void coinControlClipboardAfterFee()
void setAddress(const QString &address)
bool IsValidDestination(const CTxDestination &dest)
Check whether a CTxDestination is a CNoDestination.
CTxDestination DecodeDestination(const std::string &str)
#define SEND_CONFIRM_DELAY
void setupScrollView(const PlatformStyle *platformStyle)
CAmount getTransactionFee() const
SendCoinsReturn sendCoins(WalletModelTransaction &transaction)
QList< SendCoinsRecipient > getRecipients() const
void updateCoinControlState(CCoinControl &ctrl)
QString HtmlEscape(const QString &str, bool fMultiLine)
bool handlePaymentRequest(const SendCoinsRecipient &recipient)
CAmount GetRequiredFee(unsigned int nTxBytes)
Return the minimum required fee taking into account the floating relay fee and user set minimum trans...
AddressTableModel * getAddressTableModel()
void setBalance(const CAmount &balance, const CAmount &unconfirmedBalance, const CAmount &immatureBalance, const CAmount &watchOnlyBalance, const CAmount &watchUnconfBalance, const CAmount &watchImmatureBalance)
A single entry in the dialog for sending ravens.
boost::optional< CFeeRate > m_feerate
Override the default payTxFee if set.
int getDisplayUnit() const
CAmount getBalance(const CCoinControl *coinControl=nullptr) const
void coinControlFeatureChanged(bool)
QWidget * setupTabChain(QWidget *prev)
Set up the tab chain manually, as Qt messes up the tab chain by default in some cases (issue https://...
int64_t CAmount
Amount in corbies (Can be negative)
int getConfTargetForIndex(int index)
CAmount getImmatureBalance() const
CBlockPolicyEstimator feeEstimator
static QList< CAmount > payAmounts
static QString formatWithUnit(int unit, const CAmount &amount, bool plussign=false, SeparatorStyle separators=separatorStandard)
Format as string (with unit)
QWidget * setupTabChain(QWidget *prev)
Set up the tab chain manually, as Qt messes up the tab chain by default in some cases (issue https://...
void on_sendButton_clicked()
SendCoinsEntry * addEntry()
void setupAddressWidget(QValidatedLineEdit *widget, QWidget *parent)
void setAddress(const QString &address)
void coinControlClipboardChange()
void setClientModel(ClientModel *clientModel)
void setClipboard(const QString &str)
ClientModel * clientModel
#define STRING_LABEL_COLOR
CTxDestination destChange
int getDefaultConfirmTarget() const
CAmount getWatchUnconfirmedBalance() const
QString labelForAddress(const QString &address) const
SendCoinsReturn prepareTransaction(WalletModelTransaction &transaction, const CCoinControl &coinControl)
Dialog for sending ravens.
void coinControlChangeEdited(const QString &)
static void updateLabels(WalletModel *, QDialog *)
int getIndexForConfTarget(int target)
Model for Raven network client.
void coinControlUpdateLabels()
void setModel(WalletModel *model)
bool getCoinControlFeatures() const
bool isClear()
Return whether the entry is still empty and unedited.
void minimizeFeeSection(bool fMinimize)
void coinControlClipboardLowOutput()
void updateFeeSectionControls()
void setupCoinControl(const PlatformStyle *platformStyle)
void setModel(WalletModel *model)
static bool fSubtractFeeFromAmount
void updateSmartFeeLabel()
void updateTabsAndLabels()
void setupFeeControl(const PlatformStyle *platformStyle)
const CChainParams & Params()
Return the currently selected parameters.
Interface to Raven wallet from Qt view code.
CAmount getWatchBalance() const
CAmount getUnconfirmedBalance() const
static QString formatHtmlWithUnit(int unit, const CAmount &amount, bool plussign=false, SeparatorStyle separators=separatorStandard)
Format as HTML string (with unit)
SendCoinsDialog(const PlatformStyle *platformStyle, QWidget *parent=0)
SendConfirmationDialog(const QString &title, const QString &text, int secDelay=SEND_CONFIRM_DELAY, QWidget *parent=0)
void setModel(WalletModel *model)
void processSendCoinsReturn(const WalletModel::SendCoinsReturn &sendCoinsReturn, const QString &msgArg=QString())
Fee rate in satoshis per kilobyte: CAmount / kB.
Data model for a walletmodel transaction.
static QList< Unit > availableUnits()
Get list of units, for drop-down box.
void coinControlClipboardBytes()
QFont getTopLabelFont(int weight, int pxsize)
bool fSubtractFeeFromAmount
CAmount getWatchImmatureBalance() const
const PlatformStyle * platformStyle
CAmount getTotalTransactionAmount() const
QString formatNiceTimeOffset(qint64 secs)
void coinControlClipboardAmount()
void on_buttonMinimizeFee_clicked()
QFont getSubLabelFontBolded()
void pasteEntry(const SendCoinsRecipient &rv)
QAbstractButton * yesButton
void message(const QString &title, const QString &message, unsigned int style)
bool fNewRecipientAllowed
CAmount GetMinimumFee(unsigned int nTxBytes, const CCoinControl &coin_control, const CTxMemPool &pool, const CBlockPolicyEstimator &estimator, FeeCalculation *feeCalc)
Estimate the minimum fee considering user set parameters and the required fee.
CAmount GetFeePerK() const
Return the fee in satoshis for a size of 1000 bytes.
void coinControlButtonClicked()
unsigned int getTransactionSize()
void coinControlClipboardFee()
OptionsModel * getOptionsModel()
bool IsSpendable(const CTxDestination &dest) const
void coinControlChangeChecked(int)