Changeset View
Changeset View
Standalone View
Standalone View
src/qt/sendcoinsdialog.cpp
Show All 24 Lines | |||||
#include "wallet/wallet.h" | #include "wallet/wallet.h" | ||||
#include <QMessageBox> | #include <QMessageBox> | ||||
#include <QScrollBar> | #include <QScrollBar> | ||||
#include <QSettings> | #include <QSettings> | ||||
#include <QTextDocument> | #include <QTextDocument> | ||||
#include <QTimer> | #include <QTimer> | ||||
static const std::array<int, 9> confTargets = { | |||||
{2, 4, 6, 12, 24, 48, 144, 504, 1008}}; | |||||
int getConfTargetForIndex(int index) { | |||||
if (index + 1 > static_cast<int>(confTargets.size())) { | |||||
return confTargets.back(); | |||||
} | |||||
if (index < 0) { | |||||
return confTargets[0]; | |||||
} | |||||
return confTargets[index]; | |||||
} | |||||
int getIndexForConfTarget(int target) { | |||||
for (unsigned int i = 0; i < confTargets.size(); i++) { | |||||
if (confTargets[i] >= target) { | |||||
return i; | |||||
} | |||||
} | |||||
return confTargets.size() - 1; | |||||
} | |||||
SendCoinsDialog::SendCoinsDialog(const PlatformStyle *_platformStyle, | SendCoinsDialog::SendCoinsDialog(const PlatformStyle *_platformStyle, | ||||
QWidget *parent) | QWidget *parent) | ||||
: QDialog(parent), ui(new Ui::SendCoinsDialog), clientModel(0), model(0), | : QDialog(parent), ui(new Ui::SendCoinsDialog), clientModel(0), model(0), | ||||
fNewRecipientAllowed(true), fFeeMinimized(true), | fNewRecipientAllowed(true), fFeeMinimized(true), | ||||
platformStyle(_platformStyle) { | platformStyle(_platformStyle) { | ||||
ui->setupUi(this); | ui->setupUi(this); | ||||
if (!_platformStyle->getImagesOnButtons()) { | if (!_platformStyle->getImagesOnButtons()) { | ||||
▲ Show 20 Lines • Show All 151 Lines • ▼ Show 20 Lines | if (_model && _model->getOptionsModel()) { | ||||
connect(_model->getOptionsModel(), | connect(_model->getOptionsModel(), | ||||
SIGNAL(coinControlFeaturesChanged(bool)), this, | SIGNAL(coinControlFeaturesChanged(bool)), this, | ||||
SLOT(coinControlFeatureChanged(bool))); | SLOT(coinControlFeatureChanged(bool))); | ||||
ui->frameCoinControl->setVisible( | ui->frameCoinControl->setVisible( | ||||
_model->getOptionsModel()->getCoinControlFeatures()); | _model->getOptionsModel()->getCoinControlFeatures()); | ||||
coinControlUpdateLabels(); | coinControlUpdateLabels(); | ||||
// fee section | // fee section | ||||
connect(ui->sliderSmartFee, SIGNAL(valueChanged(int)), this, | for (const int &n : confTargets) { | ||||
ui->confTargetSelector->addItem( | |||||
tr("%1 (%2 blocks)") | |||||
.arg(GUIUtil::formatNiceTimeOffset( | |||||
n * Params().GetConsensus().nPowTargetSpacing)) | |||||
.arg(n)); | |||||
} | |||||
connect(ui->confTargetSelector, SIGNAL(currentIndexChanged(int)), this, | |||||
SLOT(updateSmartFeeLabel())); | SLOT(updateSmartFeeLabel())); | ||||
connect(ui->sliderSmartFee, SIGNAL(valueChanged(int)), this, | connect(ui->confTargetSelector, SIGNAL(currentIndexChanged(int)), this, | ||||
SLOT(updateGlobalFeeVariables())); | SLOT(updateGlobalFeeVariables())); | ||||
connect(ui->sliderSmartFee, SIGNAL(valueChanged(int)), this, | connect(ui->confTargetSelector, SIGNAL(currentIndexChanged(int)), this, | ||||
SLOT(coinControlUpdateLabels())); | SLOT(coinControlUpdateLabels())); | ||||
connect(ui->groupFee, SIGNAL(buttonClicked(int)), this, | connect(ui->groupFee, SIGNAL(buttonClicked(int)), this, | ||||
SLOT(updateFeeSectionControls())); | SLOT(updateFeeSectionControls())); | ||||
connect(ui->groupFee, SIGNAL(buttonClicked(int)), this, | connect(ui->groupFee, SIGNAL(buttonClicked(int)), this, | ||||
SLOT(updateGlobalFeeVariables())); | SLOT(updateGlobalFeeVariables())); | ||||
connect(ui->groupFee, SIGNAL(buttonClicked(int)), this, | connect(ui->groupFee, SIGNAL(buttonClicked(int)), this, | ||||
SLOT(coinControlUpdateLabels())); | SLOT(coinControlUpdateLabels())); | ||||
connect(ui->groupCustomFee, SIGNAL(buttonClicked(int)), this, | connect(ui->groupCustomFee, SIGNAL(buttonClicked(int)), this, | ||||
Show All 17 Lines | if (_model && _model->getOptionsModel()) { | ||||
updateFeeSectionControls(); | updateFeeSectionControls(); | ||||
updateMinFeeLabel(); | updateMinFeeLabel(); | ||||
updateSmartFeeLabel(); | updateSmartFeeLabel(); | ||||
updateGlobalFeeVariables(); | updateGlobalFeeVariables(); | ||||
// set the smartfee-sliders default value (wallets default conf.target | // set the smartfee-sliders default value (wallets default conf.target | ||||
// or last stored value) | // or last stored value) | ||||
QSettings settings; | QSettings settings; | ||||
if (settings.value("nSmartFeeSliderPosition").toInt() == 0) { | if (settings.value("nSmartFeeSliderPosition").toInt() != 0) { | ||||
ui->sliderSmartFee->setValue(ui->sliderSmartFee->maximum() - | // migrate nSmartFeeSliderPosition to nConfTarget | ||||
model->getDefaultConfirmTarget() + 2); | // nConfTarget is available since 0.18.7 (replaced | ||||
// nSmartFeeSliderPosition) 25 == old slider range | |||||
int nConfirmTarget = | |||||
25 - settings.value("nSmartFeeSliderPosition").toInt(); | |||||
settings.setValue("nConfTarget", nConfirmTarget); | |||||
settings.remove("nSmartFeeSliderPosition"); | |||||
} | |||||
if (settings.value("nConfTarget").toInt() == 0) { | |||||
ui->confTargetSelector->setCurrentIndex( | |||||
getIndexForConfTarget(model->getDefaultConfirmTarget())); | |||||
} else { | } else { | ||||
ui->sliderSmartFee->setValue( | ui->confTargetSelector->setCurrentIndex( | ||||
settings.value("nSmartFeeSliderPosition").toInt()); | getIndexForConfTarget(settings.value("nConfTarget").toInt())); | ||||
} | } | ||||
} | } | ||||
} | } | ||||
SendCoinsDialog::~SendCoinsDialog() { | SendCoinsDialog::~SendCoinsDialog() { | ||||
QSettings settings; | QSettings settings; | ||||
settings.setValue("fFeeSectionMinimized", fFeeMinimized); | settings.setValue("fFeeSectionMinimized", fFeeMinimized); | ||||
settings.setValue("nFeeRadio", ui->groupFee->checkedId()); | settings.setValue("nFeeRadio", ui->groupFee->checkedId()); | ||||
settings.setValue("nCustomFeeRadio", ui->groupCustomFee->checkedId()); | settings.setValue("nCustomFeeRadio", ui->groupCustomFee->checkedId()); | ||||
settings.setValue("nSmartFeeSliderPosition", ui->sliderSmartFee->value()); | settings.setValue( | ||||
"nConfTarget", | |||||
getConfTargetForIndex(ui->confTargetSelector->currentIndex())); | |||||
settings.setValue("nTransactionFee", | settings.setValue("nTransactionFee", | ||||
qint64(ui->customFee->value() / SATOSHI)); | qint64(ui->customFee->value() / SATOSHI)); | ||||
settings.setValue("fPayOnlyMinFee", ui->checkBoxMinimumFee->isChecked()); | settings.setValue("fPayOnlyMinFee", ui->checkBoxMinimumFee->isChecked()); | ||||
delete ui; | delete ui; | ||||
} | } | ||||
void SendCoinsDialog::on_sendButton_clicked() { | void SendCoinsDialog::on_sendButton_clicked() { | ||||
Show All 35 Lines | void SendCoinsDialog::on_sendButton_clicked() { | ||||
// Always use a CCoinControl instance, use the CoinControlDialog instance if | // Always use a CCoinControl instance, use the CoinControlDialog instance if | ||||
// CoinControl has been enabled | // CoinControl has been enabled | ||||
CCoinControl ctrl; | CCoinControl ctrl; | ||||
if (model->getOptionsModel()->getCoinControlFeatures()) { | if (model->getOptionsModel()->getCoinControlFeatures()) { | ||||
ctrl = *CoinControlDialog::coinControl; | ctrl = *CoinControlDialog::coinControl; | ||||
} | } | ||||
if (ui->radioSmartFee->isChecked()) { | if (ui->radioSmartFee->isChecked()) { | ||||
ctrl.nConfirmTarget = | ctrl.nConfirmTarget = | ||||
ui->sliderSmartFee->maximum() - ui->sliderSmartFee->value() + 2; | getConfTargetForIndex(ui->confTargetSelector->currentIndex()); | ||||
} else { | } else { | ||||
ctrl.nConfirmTarget = 0; | ctrl.nConfirmTarget = 0; | ||||
} | } | ||||
prepareStatus = model->prepareTransaction(currentTransaction, &ctrl); | prepareStatus = model->prepareTransaction(currentTransaction, &ctrl); | ||||
// process prepareStatus and on error generate message shown to user | // process prepareStatus and on error generate message shown to user | ||||
processSendCoinsReturn( | processSendCoinsReturn( | ||||
▲ Show 20 Lines • Show All 375 Lines • ▼ Show 20 Lines | |||||
} | } | ||||
void SendCoinsDialog::setMinimumFee() { | void SendCoinsDialog::setMinimumFee() { | ||||
ui->radioCustomPerKilobyte->setChecked(true); | ui->radioCustomPerKilobyte->setChecked(true); | ||||
ui->customFee->setValue(GetMinimumFee(1000, 2, g_mempool)); | ui->customFee->setValue(GetMinimumFee(1000, 2, g_mempool)); | ||||
} | } | ||||
void SendCoinsDialog::updateFeeSectionControls() { | void SendCoinsDialog::updateFeeSectionControls() { | ||||
ui->sliderSmartFee->setEnabled(ui->radioSmartFee->isChecked()); | ui->confTargetSelector->setEnabled(ui->radioSmartFee->isChecked()); | ||||
ui->labelSmartFee->setEnabled(ui->radioSmartFee->isChecked()); | ui->labelSmartFee->setEnabled(ui->radioSmartFee->isChecked()); | ||||
ui->labelSmartFee2->setEnabled(ui->radioSmartFee->isChecked()); | ui->labelSmartFee2->setEnabled(ui->radioSmartFee->isChecked()); | ||||
ui->labelSmartFee3->setEnabled(ui->radioSmartFee->isChecked()); | ui->labelSmartFee3->setEnabled(ui->radioSmartFee->isChecked()); | ||||
ui->labelFeeEstimation->setEnabled(ui->radioSmartFee->isChecked()); | ui->labelFeeEstimation->setEnabled(ui->radioSmartFee->isChecked()); | ||||
ui->labelSmartFeeNormal->setEnabled(ui->radioSmartFee->isChecked()); | |||||
ui->labelSmartFeeFast->setEnabled(ui->radioSmartFee->isChecked()); | |||||
ui->confirmationTargetLabel->setEnabled(ui->radioSmartFee->isChecked()); | |||||
ui->checkBoxMinimumFee->setEnabled(ui->radioCustomFee->isChecked()); | ui->checkBoxMinimumFee->setEnabled(ui->radioCustomFee->isChecked()); | ||||
ui->labelMinFeeWarning->setEnabled(ui->radioCustomFee->isChecked()); | ui->labelMinFeeWarning->setEnabled(ui->radioCustomFee->isChecked()); | ||||
ui->radioCustomPerKilobyte->setEnabled( | ui->radioCustomPerKilobyte->setEnabled( | ||||
ui->radioCustomFee->isChecked() && | ui->radioCustomFee->isChecked() && | ||||
!ui->checkBoxMinimumFee->isChecked()); | !ui->checkBoxMinimumFee->isChecked()); | ||||
ui->radioCustomAtLeast->setEnabled( | ui->radioCustomAtLeast->setEnabled( | ||||
ui->radioCustomFee->isChecked() && | ui->radioCustomFee->isChecked() && | ||||
!ui->checkBoxMinimumFee->isChecked() && | !ui->checkBoxMinimumFee->isChecked() && | ||||
CoinControlDialog::coinControl->HasSelected()); | CoinControlDialog::coinControl->HasSelected()); | ||||
ui->customFee->setEnabled(ui->radioCustomFee->isChecked() && | ui->customFee->setEnabled(ui->radioCustomFee->isChecked() && | ||||
!ui->checkBoxMinimumFee->isChecked()); | !ui->checkBoxMinimumFee->isChecked()); | ||||
} | } | ||||
void SendCoinsDialog::updateGlobalFeeVariables() { | void SendCoinsDialog::updateGlobalFeeVariables() { | ||||
if (ui->radioSmartFee->isChecked()) { | if (ui->radioSmartFee->isChecked()) { | ||||
int nConfirmTarget = | |||||
ui->sliderSmartFee->maximum() - ui->sliderSmartFee->value() + 2; | |||||
payTxFee = CFeeRate(Amount::zero()); | payTxFee = CFeeRate(Amount::zero()); | ||||
// set nMinimumTotalFee to 0 to not accidentally pay a custom fee | // set nMinimumTotalFee to 0 to not accidentally pay a custom fee | ||||
CoinControlDialog::coinControl->nMinimumTotalFee = Amount::zero(); | CoinControlDialog::coinControl->nMinimumTotalFee = Amount::zero(); | ||||
// show the estimated required time for confirmation | |||||
ui->confirmationTargetLabel->setText( | |||||
GUIUtil::formatDurationStr( | |||||
nConfirmTarget * | |||||
model->getChainParams().GetConsensus().nPowTargetSpacing) + | |||||
" / " + tr("%n block(s)", "", nConfirmTarget)); | |||||
} else { | } else { | ||||
payTxFee = CFeeRate(Amount(ui->customFee->value())); | payTxFee = CFeeRate(Amount(ui->customFee->value())); | ||||
// if user has selected to set a minimum absolute fee, pass the value to | // if user has selected to set a minimum absolute fee, pass the value to | ||||
// coincontrol | // coincontrol | ||||
// set nMinimumTotalFee to 0 in case of user has selected that the fee | // set nMinimumTotalFee to 0 in case of user has selected that the fee | ||||
// is per KB | // is per KB | ||||
CoinControlDialog::coinControl->nMinimumTotalFee = | CoinControlDialog::coinControl->nMinimumTotalFee = | ||||
Show All 30 Lines | |||||
} | } | ||||
void SendCoinsDialog::updateSmartFeeLabel() { | void SendCoinsDialog::updateSmartFeeLabel() { | ||||
if (!model || !model->getOptionsModel()) { | if (!model || !model->getOptionsModel()) { | ||||
return; | return; | ||||
} | } | ||||
int nBlocksToConfirm = | int nBlocksToConfirm = | ||||
ui->sliderSmartFee->maximum() - ui->sliderSmartFee->value() + 2; | getConfTargetForIndex(ui->confTargetSelector->currentIndex()); | ||||
int estimateFoundAtBlocks = nBlocksToConfirm; | int estimateFoundAtBlocks = nBlocksToConfirm; | ||||
CFeeRate feeRate = | CFeeRate feeRate = | ||||
g_mempool.estimateSmartFee(nBlocksToConfirm, &estimateFoundAtBlocks); | g_mempool.estimateSmartFee(nBlocksToConfirm, &estimateFoundAtBlocks); | ||||
// not enough data => minfee | // not enough data => minfee | ||||
if (feeRate <= CFeeRate(Amount::zero())) { | if (feeRate <= CFeeRate(Amount::zero())) { | ||||
ui->labelSmartFee->setText( | ui->labelSmartFee->setText( | ||||
BitcoinUnits::formatWithUnit( | BitcoinUnits::formatWithUnit( | ||||
model->getOptionsModel()->getDisplayUnit(), | model->getOptionsModel()->getDisplayUnit(), | ||||
▲ Show 20 Lines • Show All 251 Lines • Show Last 20 Lines |