aboutsummaryrefslogtreecommitdiff
path: root/src/qt/optionsmodel.cpp
diff options
context:
space:
mode:
authorRyan Ofsky <ryan@ofsky.org>2019-04-29 15:29:00 -0400
committerRyan Ofsky <ryan@ofsky.org>2022-05-26 11:05:10 -0400
commit284f339de68905131331f7fdb4c0b945c9a1b8cd (patch)
tree13c3569075b3d8dd0e1fd5ceb340e1d833984f53 /src/qt/optionsmodel.cpp
parent2642dee1364ddc9b174e0ccb6b7b37ae44899c2a (diff)
Migrate -dbcache setting from QSettings to settings.json
This is just the first of multiple settings that will be stored in the bitcoin persistent setting file and shared with bitcoind, instead of being stored as Qt settings backed by the windows registry or platform specific config files which are ignored by bitcoind. Co-Authored-By: furszy <matiasfurszyfer@protonmail.com>
Diffstat (limited to 'src/qt/optionsmodel.cpp')
-rw-r--r--src/qt/optionsmodel.cpp81
1 files changed, 66 insertions, 15 deletions
diff --git a/src/qt/optionsmodel.cpp b/src/qt/optionsmodel.cpp
index 612d3009c1..6f61afed54 100644
--- a/src/qt/optionsmodel.cpp
+++ b/src/qt/optionsmodel.cpp
@@ -26,14 +26,41 @@
#include <QStringList>
#include <QVariant>
+#include <univalue.h>
+
const char *DEFAULT_GUI_PROXY_HOST = "127.0.0.1";
static const QString GetDefaultProxyAddress();
-OptionsModel::OptionsModel(interfaces::Node& node, QObject *parent, bool resetSettings) :
+/** Map GUI option ID to node setting name. */
+static const char* SettingName(OptionsModel::OptionID option)
+{
+ switch (option) {
+ case OptionsModel::DatabaseCache: return "dbcache";
+ default: throw std::logic_error(strprintf("GUI option %i has no corresponding node setting.", option));
+ }
+}
+
+/** Call node.updateRwSetting() with Bitcoin 22.x workaround. */
+static void UpdateRwSetting(interfaces::Node& node, OptionsModel::OptionID option, const util::SettingsValue& value)
+{
+ if (value.isNum() && option == OptionsModel::DatabaseCache) {
+ // Write certain old settings as strings, even though they are numbers,
+ // because Bitcoin 22.x releases try to read these specific settings as
+ // strings in addOverriddenOption() calls at startup, triggering
+ // uncaught exceptions in UniValue::get_str(). These errors were fixed
+ // in later releases by https://github.com/bitcoin/bitcoin/pull/24498.
+ // If new numeric settings are added, they can be written as numbers
+ // instead of strings, because bitcoin 22.x will not try to read these.
+ node.updateRwSetting(SettingName(option), value.getValStr());
+ } else {
+ node.updateRwSetting(SettingName(option), value);
+ }
+}
+
+OptionsModel::OptionsModel(interfaces::Node& node, QObject *parent) :
QAbstractListModel(parent), m_node{node}
{
- Init(resetSettings);
}
void OptionsModel::addOverriddenOption(const std::string &option)
@@ -42,11 +69,8 @@ void OptionsModel::addOverriddenOption(const std::string &option)
}
// Writes all missing QSettings with their default values
-void OptionsModel::Init(bool resetSettings)
+bool OptionsModel::Init(bilingual_str& error)
{
- if (resetSettings)
- Reset();
-
checkAndMigrate();
QSettings settings;
@@ -98,7 +122,20 @@ void OptionsModel::Init(bool resetSettings)
// 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}) {
+ std::string setting = SettingName(option);
+ if (node().isSettingIgnored(setting)) addOverriddenOption("-" + setting);
+ try {
+ getOption(option);
+ } catch (const std::exception& e) {
+ // This handles exceptions thrown by univalue that can happen if
+ // settings in settings.json don't have the expected types.
+ error.original = strprintf("Could not read setting \"%s\", %s.", setting, e.what());
+ error.translated = tr("Could not read setting \"%1\", %2.").arg(QString::fromStdString(setting), e.what()).toStdString();
+ return false;
+ }
+ }
+
// If setting doesn't exist create it with defaults.
//
// If gArgs.SoftSetArg() or gArgs.SoftSetBoolArg() return false we were overridden
@@ -111,11 +148,6 @@ void OptionsModel::Init(bool resetSettings)
settings.setValue("nPruneSize", DEFAULT_PRUNE_TARGET_GB);
SetPruneEnabled(settings.value("bPrune").toBool());
- if (!settings.contains("nDatabaseCache"))
- settings.setValue("nDatabaseCache", (qint64)nDefaultDbCache);
- if (!gArgs.SoftSetArg("-dbcache", settings.value("nDatabaseCache").toString().toStdString()))
- addOverriddenOption("-dbcache");
-
if (!settings.contains("nThreadsScriptVerif"))
settings.setValue("nThreadsScriptVerif", DEFAULT_SCRIPTCHECK_THREADS);
if (!gArgs.SoftSetArg("-par", settings.value("nThreadsScriptVerif").toString().toStdString()))
@@ -222,6 +254,8 @@ void OptionsModel::Init(bool resetSettings)
}
m_use_embedded_monospaced_font = settings.value("UseEmbeddedMonospacedFont").toBool();
Q_EMIT useEmbeddedMonospacedFontChanged(m_use_embedded_monospaced_font);
+
+ return true;
}
/** Helper function to copy contents from one QSettings to another.
@@ -356,6 +390,8 @@ bool OptionsModel::setData(const QModelIndex & index, const QVariant & value, in
QVariant OptionsModel::getOption(OptionID option) const
{
+ auto setting = [&]{ return node().getPersistentSetting(SettingName(option)); };
+
QSettings settings;
switch (option) {
case StartAtStartup:
@@ -420,7 +456,7 @@ QVariant OptionsModel::getOption(OptionID option) const
case PruneSize:
return settings.value("nPruneSize");
case DatabaseCache:
- return settings.value("nDatabaseCache");
+ return qlonglong(SettingToInt(setting(), nDefaultDbCache));
case ThreadsScriptVerif:
return settings.value("nThreadsScriptVerif");
case Listen:
@@ -434,6 +470,9 @@ QVariant OptionsModel::getOption(OptionID option) const
bool OptionsModel::setOption(OptionID option, const QVariant& value)
{
+ auto changed = [&] { return value.isValid() && value != getOption(option); };
+ auto update = [&](const util::SettingsValue& value) { return UpdateRwSetting(node(), option, value); };
+
bool successful = true; /* set to false on parse error */
QSettings settings;
@@ -574,8 +613,8 @@ bool OptionsModel::setOption(OptionID option, const QVariant& value)
}
break;
case DatabaseCache:
- if (settings.value("nDatabaseCache") != value) {
- settings.setValue("nDatabaseCache", value);
+ if (changed()) {
+ update(static_cast<int64_t>(value.toLongLong()));
setRestartRequired(true);
}
break;
@@ -654,4 +693,16 @@ void OptionsModel::checkAndMigrate()
if (settings.contains("addrSeparateProxyTor") && settings.value("addrSeparateProxyTor").toString().endsWith("%2")) {
settings.setValue("addrSeparateProxyTor", GetDefaultProxyAddress());
}
+
+ // Migrate and delete legacy GUI settings that have now moved to <datadir>/settings.json.
+ auto migrate_setting = [&](OptionID option, const QString& qt_name) {
+ if (!settings.contains(qt_name)) return;
+ QVariant value = settings.value(qt_name);
+ if (node().getPersistentSetting(SettingName(option)).isNull()) {
+ setOption(option, value);
+ }
+ settings.remove(qt_name);
+ };
+
+ migrate_setting(DatabaseCache, "nDatabaseCache");
}