From 42e3bc0dd859cdd55dc49c01edba8ed9890ea2cd Mon Sep 17 00:00:00 2001 From: Luke Dashjr Date: Thu, 3 Aug 2023 20:34:08 +0000 Subject: [PATCH] Qt/Options: Handle manual pruning cleanly --- src/qt/intro.cpp | 22 +++++++++++--- src/qt/optionsdialog.cpp | 6 +++- src/qt/optionsmodel.cpp | 66 +++++++++++++++++++++++++++------------- src/qt/optionsmodel.h | 2 +- 4 files changed, 68 insertions(+), 28 deletions(-) diff --git a/src/qt/intro.cpp b/src/qt/intro.cpp index 7e8fe8e418..bcd8cf427d 100644 --- a/src/qt/intro.cpp +++ b/src/qt/intro.cpp @@ -143,22 +143,32 @@ Intro::Intro(QWidget *parent, int64_t blockchain_size_gb, int64_t chain_state_si ui->pruneMiB->setRange(min_prune_target_MiB, std::numeric_limits::max()); if (gArgs.IsArgSet("-prune")) { m_prune_checkbox_is_default = false; - ui->prune->setChecked(gArgs.GetIntArg("-prune", 0) >= 1); + switch (gArgs.GetIntArg("-prune", 0)) { + case 0: + ui->prune->setChecked(false); + break; + case 1: + ui->prune->setTristate(); + ui->prune->setCheckState(Qt::PartiallyChecked); + break; + default: + ui->prune->setChecked(true); + } ui->prune->setEnabled(false); } ui->pruneMiB->setValue(m_prune_target_mib); ui->pruneMiB->setToolTip(ui->prune->toolTip()); ui->lblPruneSuffix->setToolTip(ui->prune->toolTip()); - UpdatePruneLabels(ui->prune->isChecked()); + UpdatePruneLabels(ui->prune->checkState() == Qt::Checked); - connect(ui->prune, &QCheckBox::toggled, [this](bool prune_checked) { + connect(ui->prune, &QCheckBox::stateChanged, [this](int prune_state) { m_prune_checkbox_is_default = false; - UpdatePruneLabels(prune_checked); + UpdatePruneLabels(prune_state == Qt::Checked); UpdateFreeSpaceLabel(); }); connect(ui->pruneMiB, qOverload(&QSpinBox::valueChanged), [this](int prune_MiB) { m_prune_target_mib = prune_MiB; - UpdatePruneLabels(ui->prune->isChecked()); + UpdatePruneLabels(ui->prune->checkState() == Qt::Checked); UpdateFreeSpaceLabel(); }); @@ -198,6 +208,8 @@ int64_t Intro::getPruneMiB() const switch (ui->prune->checkState()) { case Qt::Checked: return m_prune_target_mib; + case Qt::PartiallyChecked: + return 1; case Qt::Unchecked: default: return 0; } diff --git a/src/qt/optionsdialog.cpp b/src/qt/optionsdialog.cpp index 3d214912d3..1cd1a499b4 100644 --- a/src/qt/optionsdialog.cpp +++ b/src/qt/optionsdialog.cpp @@ -302,7 +302,11 @@ void OptionsDialog::setMapper() mapper->addMapping(ui->bitcoinAtStartup, OptionsModel::StartAtStartup); mapper->addMapping(ui->threadsScriptVerif, OptionsModel::ThreadsScriptVerif); mapper->addMapping(ui->databaseCache, OptionsModel::DatabaseCache); - mapper->addMapping(ui->prune, OptionsModel::Prune); + + if (model->data(model->index(OptionsModel::PruneTristate, 0), Qt::EditRole).value() == Qt::PartiallyChecked) { + ui->prune->setTristate(); + } + mapper->addMapping(ui->prune, OptionsModel::PruneTristate); mapper->addMapping(ui->pruneSizeMiB, OptionsModel::PruneSizeMiB); /* Wallet */ diff --git a/src/qt/optionsmodel.cpp b/src/qt/optionsmodel.cpp index 2634f4e39a..ef2c81f5cd 100644 --- a/src/qt/optionsmodel.cpp +++ b/src/qt/optionsmodel.cpp @@ -55,7 +55,7 @@ static const char* SettingName(OptionsModel::OptionID option) case OptionsModel::Listen: return "listen"; case OptionsModel::Server: return "server"; case OptionsModel::PruneSizeMiB: return "prune"; - case OptionsModel::Prune: return "prune"; + case OptionsModel::PruneTristate: return "prune"; case OptionsModel::ProxyIP: return "proxy"; case OptionsModel::ProxyPort: return "proxy"; case OptionsModel::ProxyUse: return "proxy"; @@ -73,7 +73,7 @@ static void UpdateRwSetting(interfaces::Node& node, OptionsModel::OptionID optio if (value.isNum() && (option == OptionsModel::DatabaseCache || option == OptionsModel::ThreadsScriptVerif || - option == OptionsModel::Prune || + option == OptionsModel::PruneTristate || option == OptionsModel::PruneSizeMiB)) { // Write certain old settings as strings, even though they are numbers, // because Bitcoin 22.x releases try to read these specific settings as @@ -89,10 +89,17 @@ static void UpdateRwSetting(interfaces::Node& node, OptionsModel::OptionID optio } //! Convert enabled/size values to bitcoin -prune setting. -static util::SettingsValue PruneSettingFromMiB(bool prune_enabled, int prune_size_mib) +static util::SettingsValue PruneSettingFromMiB(Qt::CheckState prune_enabled, int prune_size_mib) { - assert(!prune_enabled || prune_size_mib >= 1); // PruneSizeMiB and ParsePruneSizeMiB never return less - return prune_enabled ? prune_size_mib : 0; + assert(prune_enabled != Qt::Checked || prune_size_mib >= 1); // PruneSizeMiB and ParsePruneSizeMiB never return less + switch (prune_enabled) { + case Qt::Unchecked: + return 0; + case Qt::PartiallyChecked: + return 1; + default: + return prune_size_mib; + } } //! Get pruning enabled value to show in GUI from bitcoin -prune setting. @@ -102,6 +109,19 @@ static bool PruneEnabled(const util::SettingsValue& prune_setting) return SettingToInt(prune_setting, 0) > 1; } +//! Get pruning enabled value to show in GUI from bitcoin -prune setting. +static Qt::CheckState PruneSettingAsTristate(const util::SettingsValue& prune_setting) +{ + switch (SettingToInt(prune_setting, 0)) { + case 0: + return Qt::Unchecked; + case 1: + return Qt::PartiallyChecked; + default: + return Qt::Checked; + } +} + //! Get pruning size value to show in GUI from bitcoin -prune setting. If //! pruning is not enabled, just show default recommended pruning size (2GB). static int PruneSizeAsMiB(const util::SettingsValue& prune_setting) @@ -217,7 +237,7 @@ bool OptionsModel::Init(bilingual_str& error) // These are shared with the core or have a command-line parameter // and we want command-line parameters to overwrite the GUI settings. for (OptionID option : {DatabaseCache, ThreadsScriptVerif, SpendZeroConfChange, ExternalSignerPath, MapPortUPnP, - MapPortNatpmp, Listen, Server, Prune, ProxyUse, ProxyUseTor, Language}) { + MapPortNatpmp, Listen, Server, PruneTristate, ProxyUse, ProxyUseTor, Language}) { std::string setting = SettingName(option); if (node().isSettingIgnored(setting)) addOverriddenOption("-" + setting); try { @@ -371,7 +391,7 @@ static QString GetDefaultProxyAddress() void OptionsModel::SetPruneTargetMiB(int prune_target_mib) { const util::SettingsValue cur_value = node().getPersistentSetting("prune"); - const util::SettingsValue new_value = PruneSettingFromMiB(prune_target_mib > 0, prune_target_mib); + const util::SettingsValue new_value = prune_target_mib; // Force setting to take effect. It is still safe to change the value at // this point because this function is only called after the intro screen is @@ -381,16 +401,15 @@ void OptionsModel::SetPruneTargetMiB(int prune_target_mib) // Update settings.json if value configured in intro screen is different // from saved value. Avoid writing settings.json if bitcoin.conf value // doesn't need to be overridden. - if (PruneEnabled(cur_value) != PruneEnabled(new_value) || - PruneSizeAsMiB(cur_value) != PruneSizeAsMiB(new_value)) { + if (cur_value.write() != new_value.write()) { // Call UpdateRwSetting() instead of setOption() to avoid setting // RestartRequired flag - UpdateRwSetting(node(), Prune, "", new_value); + UpdateRwSetting(node(), PruneTristate, "", new_value); } // Keep previous pruning size, if pruning was disabled. if (PruneEnabled(cur_value)) { - UpdateRwSetting(node(), Prune, "-prev", PruneEnabled(new_value) ? util::SettingsValue{} : cur_value); + UpdateRwSetting(node(), PruneTristate, "-prev", PruneEnabled(new_value) ? util::SettingsValue{} : cur_value); } } @@ -503,8 +522,8 @@ QVariant OptionsModel::getOption(OptionID option, const std::string& suffix) con return fCoinControlFeatures; case EnablePSBTControls: return settings.value("enable_psbt_controls"); - case Prune: - return PruneEnabled(setting()); + case PruneTristate: + return PruneSettingAsTristate(setting()); case PruneSizeMiB: return PruneEnabled(setting()) ? PruneSizeAsMiB(setting()) : suffix.empty() ? getOption(option, "-prev") : @@ -741,22 +760,24 @@ bool OptionsModel::setOption(OptionID option, const QVariant& value, const std:: m_enable_psbt_controls = value.toBool(); settings.setValue("enable_psbt_controls", m_enable_psbt_controls); break; - case Prune: + case PruneTristate: if (changed()) { - if (suffix.empty() && !value.toBool()) setOption(option, true, "-prev"); - update(PruneSettingFromMiB(value.toBool(), getOption(PruneSizeMiB).toInt())); - if (suffix.empty() && value.toBool()) UpdateRwSetting(node(), option, "-prev", {}); + const bool is_autoprune = (value.value() == Qt::Checked); + if (suffix.empty() && !is_autoprune) setOption(option, true, "-prev"); + update(PruneSettingFromMiB(value.value(), getOption(PruneSizeMiB).toInt())); + if (suffix.empty() && is_autoprune) UpdateRwSetting(node(), option, "-prev", {}); if (suffix.empty()) setRestartRequired(true); } break; case PruneSizeMiB: if (changed()) { - if (suffix.empty() && !getOption(Prune).toBool()) { + const bool is_autoprune = (Qt::Checked == getOption(PruneTristate).value()); + if (suffix.empty() && !is_autoprune) { setOption(option, value, "-prev"); } else { - update(PruneSettingFromMiB(true, value.toInt())); + update(PruneSettingFromMiB(Qt::Checked, value.toInt())); } - if (suffix.empty() && getOption(Prune).toBool()) setRestartRequired(true); + if (suffix.empty() && is_autoprune) setRestartRequired(true); } break; case DatabaseCache: @@ -878,6 +899,9 @@ void OptionsModel::checkAndMigrate() const int64_t prune_size_gb = value.toInt(); const int prune_size_mib = std::max(prune_size_gb * GB_BYTES / MiB_BYTES, MIN_DISK_SPACE_FOR_BLOCK_FILES / MiB_BYTES); setOption(option, prune_size_mib); + } else if (option == PruneTristate) { + // Stored as bool + setOption(option, value.toBool() ? Qt::Checked : Qt::Unchecked); } else { setOption(option, value); } @@ -896,7 +920,7 @@ void OptionsModel::checkAndMigrate() migrate_setting(Listen, "fListen"); migrate_setting(Server, "server"); migrate_setting(PruneSizeMiB, "nPruneSize"); - migrate_setting(Prune, "bPrune"); + migrate_setting(PruneTristate, "bPrune"); migrate_setting(ProxyIP, "addrProxy"); migrate_setting(ProxyUse, "fUseProxy"); migrate_setting(ProxyIPTor, "addrSeparateProxyTor"); diff --git a/src/qt/optionsmodel.h b/src/qt/optionsmodel.h index 7d3c1eaa41..482dfcbe08 100644 --- a/src/qt/optionsmodel.h +++ b/src/qt/optionsmodel.h @@ -59,7 +59,7 @@ public: CoinControlFeatures, // bool SubFeeFromAmount, // bool ThreadsScriptVerif, // int - Prune, // bool + PruneTristate, // Qt::CheckState PruneSizeMiB, // int DatabaseCache, // int ExternalSignerPath, // QString