diff options
Diffstat (limited to 'src/qt/sendcoinsdialog.cpp')
-rw-r--r-- | src/qt/sendcoinsdialog.cpp | 117 |
1 files changed, 63 insertions, 54 deletions
diff --git a/src/qt/sendcoinsdialog.cpp b/src/qt/sendcoinsdialog.cpp index 12d2d0f31c..a01886c3ea 100644 --- a/src/qt/sendcoinsdialog.cpp +++ b/src/qt/sendcoinsdialog.cpp @@ -31,6 +31,25 @@ #include <QTextDocument> #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, QWidget *parent) : QDialog(parent), ui(new Ui::SendCoinsDialog), @@ -152,35 +171,41 @@ void SendCoinsDialog::setModel(WalletModel *_model) coinControlUpdateLabels(); // fee section - connect(ui->sliderSmartFee, SIGNAL(valueChanged(int)), this, SLOT(updateSmartFeeLabel())); - connect(ui->sliderSmartFee, SIGNAL(valueChanged(int)), this, SLOT(updateGlobalFeeVariables())); - connect(ui->sliderSmartFee, SIGNAL(valueChanged(int)), this, SLOT(coinControlUpdateLabels())); + 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())); + connect(ui->confTargetSelector, SIGNAL(currentIndexChanged(int)), this, SLOT(coinControlUpdateLabels())); connect(ui->groupFee, SIGNAL(buttonClicked(int)), this, SLOT(updateFeeSectionControls())); - connect(ui->groupFee, SIGNAL(buttonClicked(int)), this, SLOT(updateGlobalFeeVariables())); connect(ui->groupFee, SIGNAL(buttonClicked(int)), this, SLOT(coinControlUpdateLabels())); - connect(ui->groupCustomFee, SIGNAL(buttonClicked(int)), this, SLOT(updateGlobalFeeVariables())); connect(ui->groupCustomFee, SIGNAL(buttonClicked(int)), this, SLOT(coinControlUpdateLabels())); - connect(ui->customFee, SIGNAL(valueChanged()), this, SLOT(updateGlobalFeeVariables())); connect(ui->customFee, SIGNAL(valueChanged()), this, SLOT(coinControlUpdateLabels())); connect(ui->checkBoxMinimumFee, SIGNAL(stateChanged(int)), this, SLOT(setMinimumFee())); connect(ui->checkBoxMinimumFee, SIGNAL(stateChanged(int)), this, SLOT(updateFeeSectionControls())); - connect(ui->checkBoxMinimumFee, SIGNAL(stateChanged(int)), this, SLOT(updateGlobalFeeVariables())); connect(ui->checkBoxMinimumFee, SIGNAL(stateChanged(int)), this, SLOT(coinControlUpdateLabels())); + connect(ui->optInRBF, SIGNAL(stateChanged(int)), this, SLOT(updateSmartFeeLabel())); + connect(ui->optInRBF, SIGNAL(stateChanged(int)), this, SLOT(coinControlUpdateLabels())); ui->customFee->setSingleStep(CWallet::GetRequiredFee(1000)); updateFeeSectionControls(); updateMinFeeLabel(); updateSmartFeeLabel(); - updateGlobalFeeVariables(); // set default rbf checkbox state ui->optInRBF->setCheckState(model->getDefaultWalletRbf() ? Qt::Checked : Qt::Unchecked); // set the smartfee-sliders default value (wallets default conf.target or last stored value) QSettings settings; - if (settings.value("nSmartFeeSliderPosition").toInt() == 0) - ui->sliderSmartFee->setValue(ui->sliderSmartFee->maximum() - model->getDefaultConfirmTarget() + 2); + if (settings.value("nSmartFeeSliderPosition").toInt() != 0) { + // migrate nSmartFeeSliderPosition to nConfTarget + // nConfTarget is available since 0.15 (replaced nSmartFeeSliderPosition) + int nConfirmTarget = 25 - settings.value("nSmartFeeSliderPosition").toInt(); // 25 == old slider range + settings.setValue("nConfTarget", nConfirmTarget); + settings.remove("nSmartFeeSliderPosition"); + } + if (settings.value("nConfTarget").toInt() == 0) + ui->confTargetSelector->setCurrentIndex(getIndexForConfTarget(model->getDefaultConfirmTarget())); else - ui->sliderSmartFee->setValue(settings.value("nSmartFeeSliderPosition").toInt()); + ui->confTargetSelector->setCurrentIndex(getIndexForConfTarget(settings.value("nConfTarget").toInt())); } } @@ -190,7 +215,7 @@ SendCoinsDialog::~SendCoinsDialog() settings.setValue("fFeeSectionMinimized", fFeeMinimized); settings.setValue("nFeeRadio", ui->groupFee->checkedId()); settings.setValue("nCustomFeeRadio", ui->groupCustomFee->checkedId()); - settings.setValue("nSmartFeeSliderPosition", ui->sliderSmartFee->value()); + settings.setValue("nConfTarget", getConfTargetForIndex(ui->confTargetSelector->currentIndex())); settings.setValue("nTransactionFee", (qint64)ui->customFee->value()); settings.setValue("fPayOnlyMinFee", ui->checkBoxMinimumFee->isChecked()); @@ -243,14 +268,10 @@ void SendCoinsDialog::on_sendButton_clicked() CCoinControl ctrl; if (model->getOptionsModel()->getCoinControlFeatures()) ctrl = *CoinControlDialog::coinControl; - if (ui->radioSmartFee->isChecked()) - ctrl.nConfirmTarget = ui->sliderSmartFee->maximum() - ui->sliderSmartFee->value() + 2; - else - ctrl.nConfirmTarget = 0; - ctrl.signalRbf = ui->optInRBF->isChecked(); + updateCoinControlState(ctrl); - prepareStatus = model->prepareTransaction(currentTransaction, &ctrl); + prepareStatus = model->prepareTransaction(currentTransaction, ctrl); // process prepareStatus and on error generate message shown to user processSendCoinsReturn(prepareStatus, @@ -594,36 +615,17 @@ void SendCoinsDialog::setMinimumFee() void SendCoinsDialog::updateFeeSectionControls() { - ui->sliderSmartFee ->setEnabled(ui->radioSmartFee->isChecked()); + ui->confTargetSelector ->setEnabled(ui->radioSmartFee->isChecked()); ui->labelSmartFee ->setEnabled(ui->radioSmartFee->isChecked()); ui->labelSmartFee2 ->setEnabled(ui->radioSmartFee->isChecked()); ui->labelSmartFee3 ->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->labelMinFeeWarning ->setEnabled(ui->radioCustomFee->isChecked()); ui->radioCustomPerKilobyte ->setEnabled(ui->radioCustomFee->isChecked() && !ui->checkBoxMinimumFee->isChecked()); ui->customFee ->setEnabled(ui->radioCustomFee->isChecked() && !ui->checkBoxMinimumFee->isChecked()); } -void SendCoinsDialog::updateGlobalFeeVariables() -{ - if (ui->radioSmartFee->isChecked()) - { - int nConfirmTarget = ui->sliderSmartFee->maximum() - ui->sliderSmartFee->value() + 2; - payTxFee = CFeeRate(0); - - // show the estimated required time for confirmation - ui->confirmationTargetLabel->setText(GUIUtil::formatDurationStr(nConfirmTarget * Params().GetConsensus().nPowTargetSpacing) + " / " + tr("%n block(s)", "", nConfirmTarget)); - } - else - { - payTxFee = CFeeRate(ui->customFee->value()); - } -} - void SendCoinsDialog::updateFeeMinimizedLabel() { if(!model || !model->getOptionsModel()) @@ -645,18 +647,32 @@ void SendCoinsDialog::updateMinFeeLabel() ); } +void SendCoinsDialog::updateCoinControlState(CCoinControl& ctrl) +{ + if (ui->radioCustomFee->isChecked()) { + ctrl.m_feerate = CFeeRate(ui->customFee->value()); + } else { + ctrl.m_feerate.reset(); + } + // Avoid using global defaults when sending money from the GUI + // Either custom fee will be used or if not selected, the confirmation target from dropdown box + ctrl.m_confirm_target = getConfTargetForIndex(ui->confTargetSelector->currentIndex()); + ctrl.signalRbf = ui->optInRBF->isChecked(); +} + void SendCoinsDialog::updateSmartFeeLabel() { if(!model || !model->getOptionsModel()) return; - - int nBlocksToConfirm = ui->sliderSmartFee->maximum() - ui->sliderSmartFee->value() + 2; + CCoinControl coin_control; + updateCoinControlState(coin_control); + coin_control.m_feerate.reset(); // Explicitly use only fee estimation rate for smart fee labels FeeCalculation feeCalc; - CFeeRate feeRate = ::feeEstimator.estimateSmartFee(nBlocksToConfirm, &feeCalc, ::mempool); - if (feeRate <= CFeeRate(0)) // not enough data => minfee - { - ui->labelSmartFee->setText(BitcoinUnits::formatWithUnit(model->getOptionsModel()->getDisplayUnit(), - std::max(CWallet::fallbackFee.GetFeePerK(), CWallet::GetRequiredFee(1000))) + "/kB"); + CFeeRate feeRate = CFeeRate(CWallet::GetMinimumFee(1000, coin_control, ::mempool, ::feeEstimator, &feeCalc)); + + ui->labelSmartFee->setText(BitcoinUnits::formatWithUnit(model->getOptionsModel()->getDisplayUnit(), feeRate.GetFeePerK()) + "/kB"); + + if (feeCalc.reason == FeeReason::FALLBACK) { ui->labelSmartFee2->show(); // (Smart fee not initialized yet. This usually takes a few blocks...) ui->labelFeeEstimation->setText(""); ui->fallbackFeeWarningLabel->setVisible(true); @@ -667,8 +683,6 @@ void SendCoinsDialog::updateSmartFeeLabel() } else { - ui->labelSmartFee->setText(BitcoinUnits::formatWithUnit(model->getOptionsModel()->getDisplayUnit(), - std::max(feeRate.GetFeePerK(), CWallet::GetRequiredFee(1000))) + "/kB"); ui->labelSmartFee2->hide(); ui->labelFeeEstimation->setText(tr("Estimated to begin confirmation within %n block(s).", "", feeCalc.returnedTarget)); ui->fallbackFeeWarningLabel->setVisible(false); @@ -727,8 +741,6 @@ void SendCoinsDialog::coinControlFeatureChanged(bool checked) if (!checked && model) // coin control features disabled CoinControlDialog::coinControl->SetNull(); - // make sure we set back the confirmation target - updateGlobalFeeVariables(); coinControlUpdateLabels(); } @@ -819,14 +831,11 @@ void SendCoinsDialog::coinControlUpdateLabels() if (!model || !model->getOptionsModel()) return; + updateCoinControlState(*CoinControlDialog::coinControl); + // set pay amounts CoinControlDialog::payAmounts.clear(); CoinControlDialog::fSubtractFeeFromAmount = false; - if (ui->radioSmartFee->isChecked()) { - CoinControlDialog::coinControl->nConfirmTarget = ui->sliderSmartFee->maximum() - ui->sliderSmartFee->value() + 2; - } else { - CoinControlDialog::coinControl->nConfirmTarget = model->getDefaultConfirmTarget(); - } for(int i = 0; i < ui->entries->count(); ++i) { |