Bitcoin ABC 0.26.3
P2P Digital Currency
Loading...
Searching...
No Matches
optionsmodel.cpp
Go to the documentation of this file.
1// Copyright (c) 2011-2016 The Bitcoin Core developers
2// Distributed under the MIT software license, see the accompanying
3// file COPYING or http://www.opensource.org/licenses/mit-license.php.
4
5#if defined(HAVE_CONFIG_H)
6#include <config/bitcoin-config.h>
7#endif
8
9#include <qt/optionsmodel.h>
10
11#include <common/args.h>
12#include <interfaces/node.h>
13#include <mapport.h>
14#include <net.h>
15#include <netbase.h>
16#include <qt/bitcoinunits.h>
17#include <qt/guiconstants.h>
18#include <qt/guiutil.h>
19#include <txdb.h> // for -dbcache defaults
20#include <util/string.h>
21#include <validation.h> // For DEFAULT_SCRIPTCHECK_THREADS
22
23#include <QDebug> // needed by qInfo()
24#ifdef ENABLE_BIP70
25#include <QNetworkProxy>
26#endif
27#include <QSettings>
28#include <QStringList>
29
30const char *DEFAULT_GUI_PROXY_HOST = "127.0.0.1";
31
32static const QString GetDefaultProxyAddress();
33
34OptionsModel::OptionsModel(QObject *parent, bool resetSettings)
35 : QAbstractListModel(parent) {
36 Init(resetSettings);
37}
38
39void OptionsModel::addOverriddenOption(const std::string &option) {
41 QString::fromStdString(option) + "=" +
42 QString::fromStdString(gArgs.GetArg(option, "")) + " ";
43}
44
45// Writes all missing QSettings with their default values
46void OptionsModel::Init(bool resetSettings) {
47 if (resetSettings) {
48 Reset();
49 }
50
52
54
55 // Ensure restart flag is unset on client startup
56 setRestartRequired(false);
57
58 // These are Qt-only settings:
59
60 // Window
61 if (!settings.contains("fHideTrayIcon")) {
62 settings.setValue("fHideTrayIcon", false);
63 }
64 fHideTrayIcon = settings.value("fHideTrayIcon").toBool();
66
67 if (!settings.contains("fMinimizeToTray")) {
68 settings.setValue("fMinimizeToTray", false);
69 }
71 settings.value("fMinimizeToTray").toBool() && !fHideTrayIcon;
72
73 if (!settings.contains("fMinimizeOnClose")) {
74 settings.setValue("fMinimizeOnClose", false);
75 }
76 fMinimizeOnClose = settings.value("fMinimizeOnClose").toBool();
77
78 // Display
79 if (!settings.contains("nDisplayUnit")) {
80 settings.setValue("nDisplayUnit", BitcoinUnits::base);
81 }
82 nDisplayUnit = settings.value("nDisplayUnit").toInt();
83
84 if (!settings.contains("strThirdPartyTxUrls")) {
85 settings.setValue("strThirdPartyTxUrls", "");
86 }
87 strThirdPartyTxUrls = settings.value("strThirdPartyTxUrls", "").toString();
88
89 if (!settings.contains("fCoinControlFeatures")) {
90 settings.setValue("fCoinControlFeatures", false);
91 }
93 settings.value("fCoinControlFeatures", false).toBool();
94
95 // These are shared with the core or have a command-line parameter
96 // and we want command-line parameters to overwrite the GUI settings.
97 //
98 // If setting doesn't exist create it with defaults.
99 //
100 // If gArgs.SoftSetArg() or gArgs.SoftSetBoolArg() return false we were
101 // overridden
102 // by command-line and show this in the UI.
103
104 // Main
105 if (!settings.contains("bPrune")) {
106 settings.setValue("bPrune", false);
107 }
108 if (!settings.contains("nPruneSize")) {
109 settings.setValue("nPruneSize", DEFAULT_PRUNE_TARGET_GB);
110 }
111 SetPruneEnabled(settings.value("bPrune").toBool());
112
113 if (!settings.contains("nDatabaseCache")) {
114 settings.setValue("nDatabaseCache", (qint64)DEFAULT_DB_CACHE_MB);
115 }
116 if (!gArgs.SoftSetArg(
117 "-dbcache",
118 settings.value("nDatabaseCache").toString().toStdString())) {
119 addOverriddenOption("-dbcache");
120 }
121
122 if (!settings.contains("nThreadsScriptVerif")) {
123 settings.setValue("nThreadsScriptVerif", DEFAULT_SCRIPTCHECK_THREADS);
124 }
125 if (!gArgs.SoftSetArg(
126 "-par",
127 settings.value("nThreadsScriptVerif").toString().toStdString())) {
128 addOverriddenOption("-par");
129 }
130
131 if (!settings.contains("strDataDir")) {
132 settings.setValue("strDataDir", GUIUtil::getDefaultDataDirectory());
133 }
134
135// Wallet
136#ifdef ENABLE_WALLET
137 if (!settings.contains("bSpendZeroConfChange")) {
138 settings.setValue("bSpendZeroConfChange", true);
139 }
141 "-spendzeroconfchange",
142 settings.value("bSpendZeroConfChange").toBool())) {
143 addOverriddenOption("-spendzeroconfchange");
144 }
145#endif
146
147 // Network
148 if (!settings.contains("fUseUPnP")) {
149 settings.setValue("fUseUPnP", DEFAULT_UPNP);
150 }
151 if (!gArgs.SoftSetBoolArg("-upnp", settings.value("fUseUPnP").toBool())) {
152 addOverriddenOption("-upnp");
153 }
154
155 if (!settings.contains("fUseNatpmp")) {
156 settings.setValue("fUseNatpmp", DEFAULT_NATPMP);
157 }
158 if (!gArgs.SoftSetBoolArg("-natpmp",
159 settings.value("fUseNatpmp").toBool())) {
160 addOverriddenOption("-natpmp");
161 }
162
163 if (!settings.contains("fListen")) {
164 settings.setValue("fListen", DEFAULT_LISTEN);
165 }
166 if (!gArgs.SoftSetBoolArg("-listen", settings.value("fListen").toBool())) {
167 addOverriddenOption("-listen");
168 }
169
170 if (!settings.contains("fUseProxy")) {
171 settings.setValue("fUseProxy", false);
172 }
173 if (!settings.contains("addrProxy")) {
174 settings.setValue("addrProxy", GetDefaultProxyAddress());
175 }
176 // Only try to set -proxy, if user has enabled fUseProxy
177 if (settings.value("fUseProxy").toBool() &&
179 "-proxy", settings.value("addrProxy").toString().toStdString())) {
180 addOverriddenOption("-proxy");
181 } else if (!settings.value("fUseProxy").toBool() &&
182 !gArgs.GetArg("-proxy", "").empty()) {
183 addOverriddenOption("-proxy");
184 }
185
186 if (!settings.contains("fUseSeparateProxyTor")) {
187 settings.setValue("fUseSeparateProxyTor", false);
188 }
189 if (!settings.contains("addrSeparateProxyTor")) {
190 settings.setValue("addrSeparateProxyTor", GetDefaultProxyAddress());
191 }
192 // Only try to set -onion, if user has enabled fUseSeparateProxyTor
193 if (settings.value("fUseSeparateProxyTor").toBool() &&
195 "-onion",
196 settings.value("addrSeparateProxyTor").toString().toStdString())) {
197 addOverriddenOption("-onion");
198 } else if (!settings.value("fUseSeparateProxyTor").toBool() &&
199 !gArgs.GetArg("-onion", "").empty()) {
200 addOverriddenOption("-onion");
201 }
202
203 // Display
204 if (!settings.contains("language")) {
205 settings.setValue("language", "");
206 }
207 if (!gArgs.SoftSetArg(
208 "-lang", settings.value("language").toString().toStdString())) {
209 addOverriddenOption("-lang");
210 }
211
212 language = settings.value("language").toString();
213}
214
219static void CopySettings(QSettings &dst, const QSettings &src) {
220 for (const QString &key : src.allKeys()) {
221 dst.setValue(key, src.value(key));
222 }
223}
224
226static void BackupSettings(const fs::path &filename, const QSettings &src) {
227 qInfo() << "Backing up GUI settings to"
228 << GUIUtil::boostPathToQString(filename);
229 QSettings dst(GUIUtil::boostPathToQString(filename), QSettings::IniFormat);
230 dst.clear();
231 CopySettings(dst, src);
232}
233
236
237 // Backup old settings to chain-specific datadir for troubleshooting
238 BackupSettings(gArgs.GetDataDirNet() / "guisettings.ini.bak", settings);
239
240 // Save the strDataDir setting
242 dataDir = settings.value("strDataDir", dataDir).toString();
243
244 // Remove all entries from our QSettings object
245 settings.clear();
246
247 // Set strDataDir
248 settings.setValue("strDataDir", dataDir);
249
250 // Set that this was reset
251 settings.setValue("fReset", true);
252
253 // default setting for OptionsModel::StartAtStartup - disabled
256 }
257}
258
259int OptionsModel::rowCount(const QModelIndex &parent) const {
260 return OptionIDRowCount;
261}
262
268
270 static const ProxySetting default_val = {
273 // Handle the case that the setting is not set at all
274 if (!settings.contains(name)) {
275 return default_val;
276 }
277 // contains IP at index 0 and port at index 1
279 GUIUtil::splitSkipEmptyParts(settings.value(name).toString(), ":");
280 if (ip_port.size() == 2) {
281 return {true, ip_port.at(0), ip_port.at(1)};
282 } else { // Invalid: return default
283 return default_val;
284 }
285}
286
288 const ProxySetting &ip_port) {
289 settings.setValue(name, ip_port.ip + ":" + ip_port.port);
290}
291
293 return QString("%1:%2")
296}
297
298void OptionsModel::SetPruneEnabled(bool prune, bool force) {
300 settings.setValue("bPrune", prune);
302 PruneGBtoMiB(settings.value("nPruneSize").toInt());
303 std::string prune_val = prune ? ToString(prune_target_mib) : "0";
304 if (force) {
305 gArgs.ForceSetArg("-prune", prune_val);
306 return;
307 }
308 if (!gArgs.SoftSetArg("-prune", prune_val)) {
309 addOverriddenOption("-prune");
310 }
311}
312
314 const bool prune = prune_target_gb > 0;
315 if (prune) {
317 settings.setValue("nPruneSize", prune_target_gb);
318 }
319 SetPruneEnabled(prune, force);
320}
321
322// read QSettings values and return them
323QVariant OptionsModel::data(const QModelIndex &index, int role) const {
324 if (role == Qt::EditRole) {
326 switch (index.row()) {
327 case StartAtStartup:
329 case HideTrayIcon:
330 return fHideTrayIcon;
331 case MinimizeToTray:
332 return fMinimizeToTray;
333 case MapPortUPnP:
334#ifdef USE_UPNP
335 return settings.value("fUseUPnP");
336#else
337 return false;
338#endif // USE_UPNP
339 case MapPortNatpmp:
340#ifdef USE_NATPMP
341 return settings.value("fUseNatpmp");
342#else
343 return false;
344#endif // USE_NATPMP
345 case MinimizeOnClose:
346 return fMinimizeOnClose;
347
348 // default proxy
349 case ProxyUse:
350 return settings.value("fUseProxy", false);
351 case ProxyIP:
352 return GetProxySetting(settings, "addrProxy").ip;
353 case ProxyPort:
354 return GetProxySetting(settings, "addrProxy").port;
355
356 // separate Tor proxy
357 case ProxyUseTor:
358 return settings.value("fUseSeparateProxyTor", false);
359 case ProxyIPTor:
360 return GetProxySetting(settings, "addrSeparateProxyTor").ip;
361 case ProxyPortTor:
362 return GetProxySetting(settings, "addrSeparateProxyTor").port;
363
364#ifdef ENABLE_WALLET
366 return settings.value("bSpendZeroConfChange");
367#endif
368 case DisplayUnit:
369 return nDisplayUnit;
370 case ThirdPartyTxUrls:
371 return strThirdPartyTxUrls;
372 case Language:
373 return settings.value("language");
376 case Prune:
377 return settings.value("bPrune");
378 case PruneSize:
379 return settings.value("nPruneSize");
380 case DatabaseCache:
381 return settings.value("nDatabaseCache");
383 return settings.value("nThreadsScriptVerif");
384 case Listen:
385 return settings.value("fListen");
386 default:
387 return QVariant();
388 }
389 }
390 return QVariant();
391}
392
393// write QSettings values
394bool OptionsModel::setData(const QModelIndex &index, const QVariant &value,
395 int role) {
396 bool successful = true; /* set to false on parse error */
397 if (role == Qt::EditRole) {
399 switch (index.row()) {
400 case StartAtStartup:
402 break;
403 case HideTrayIcon:
404 fHideTrayIcon = value.toBool();
405 settings.setValue("fHideTrayIcon", fHideTrayIcon);
407 break;
408 case MinimizeToTray:
409 fMinimizeToTray = value.toBool();
410 settings.setValue("fMinimizeToTray", fMinimizeToTray);
411 break;
412 case MapPortUPnP: // core option - can be changed on-the-fly
413 settings.setValue("fUseUPnP", value.toBool());
414 break;
415 case MapPortNatpmp: // core option - can be changed on-the-fly
416 settings.setValue("fUseNatpmp", value.toBool());
417 break;
418 case MinimizeOnClose:
419 fMinimizeOnClose = value.toBool();
420 settings.setValue("fMinimizeOnClose", fMinimizeOnClose);
421 break;
422
423 // default proxy
424 case ProxyUse:
425 if (settings.value("fUseProxy") != value) {
426 settings.setValue("fUseProxy", value.toBool());
427 setRestartRequired(true);
428 }
429 break;
430 case ProxyIP: {
431 auto ip_port = GetProxySetting(settings, "addrProxy");
432 if (!ip_port.is_set || ip_port.ip != value.toString()) {
433 ip_port.ip = value.toString();
434 SetProxySetting(settings, "addrProxy", ip_port);
435 setRestartRequired(true);
436 }
437 } break;
438 case ProxyPort: {
439 auto ip_port = GetProxySetting(settings, "addrProxy");
440 if (!ip_port.is_set || ip_port.port != value.toString()) {
441 ip_port.port = value.toString();
442 SetProxySetting(settings, "addrProxy", ip_port);
443 setRestartRequired(true);
444 }
445 } break;
446
447 // separate Tor proxy
448 case ProxyUseTor:
449 if (settings.value("fUseSeparateProxyTor") != value) {
450 settings.setValue("fUseSeparateProxyTor", value.toBool());
451 setRestartRequired(true);
452 }
453 break;
454 case ProxyIPTor: {
455 auto ip_port =
456 GetProxySetting(settings, "addrSeparateProxyTor");
457 if (!ip_port.is_set || ip_port.ip != value.toString()) {
458 ip_port.ip = value.toString();
459 SetProxySetting(settings, "addrSeparateProxyTor", ip_port);
460 setRestartRequired(true);
461 }
462 } break;
463 case ProxyPortTor: {
464 auto ip_port =
465 GetProxySetting(settings, "addrSeparateProxyTor");
466 if (!ip_port.is_set || ip_port.port != value.toString()) {
467 ip_port.port = value.toString();
468 SetProxySetting(settings, "addrSeparateProxyTor", ip_port);
469 setRestartRequired(true);
470 }
471 } break;
472
473#ifdef ENABLE_WALLET
475 if (settings.value("bSpendZeroConfChange") != value) {
476 settings.setValue("bSpendZeroConfChange", value);
477 setRestartRequired(true);
478 }
479 break;
480#endif
481 case DisplayUnit:
482 setDisplayUnit(value);
483 break;
484 case ThirdPartyTxUrls:
485 if (strThirdPartyTxUrls != value.toString()) {
486 strThirdPartyTxUrls = value.toString();
487 settings.setValue("strThirdPartyTxUrls",
489 setRestartRequired(true);
490 }
491 break;
492 case Language:
493 if (settings.value("language") != value) {
494 settings.setValue("language", value);
495 setRestartRequired(true);
496 }
497 break;
499 fCoinControlFeatures = value.toBool();
500 settings.setValue("fCoinControlFeatures", fCoinControlFeatures);
502 break;
503 case Prune:
504 if (settings.value("bPrune") != value) {
505 settings.setValue("bPrune", value);
506 setRestartRequired(true);
507 }
508 break;
509 case PruneSize:
510 if (settings.value("nPruneSize") != value) {
511 settings.setValue("nPruneSize", value);
512 setRestartRequired(true);
513 }
514 break;
515 case DatabaseCache:
516 if (settings.value("nDatabaseCache") != value) {
517 settings.setValue("nDatabaseCache", value);
518 setRestartRequired(true);
519 }
520 break;
522 if (settings.value("nThreadsScriptVerif") != value) {
523 settings.setValue("nThreadsScriptVerif", value);
524 setRestartRequired(true);
525 }
526 break;
527 case Listen:
528 if (settings.value("fListen") != value) {
529 settings.setValue("fListen", value);
530 setRestartRequired(true);
531 }
532 break;
533 default:
534 break;
535 }
536 }
537
538 Q_EMIT dataChanged(index, index);
539
540 return successful;
541}
542
546 if (!value.isNull()) {
548 nDisplayUnit = value.toInt();
549 settings.setValue("nDisplayUnit", nDisplayUnit);
551 }
552}
553
554#ifdef ENABLE_BIP70
556 // Directly query current base proxy, because
557 // GUI settings can be overridden with -proxy.
559 if (node().getProxy(NET_IPV4, curProxy)) {
560 proxy.setType(QNetworkProxy::Socks5Proxy);
561 proxy.setHostName(QString::fromStdString(curProxy.proxy.ToStringIP()));
562 proxy.setPort(curProxy.proxy.GetPort());
563
564 return true;
565 } else {
566 proxy.setType(QNetworkProxy::NoProxy);
567 }
568
569 return false;
570}
571#endif
572
575 return settings.setValue("fRestartRequired", fRequired);
576}
577
580 return settings.value("fRestartRequired", false).toBool();
581}
582
584 // Migration of default values
585 // Check if the QSettings container was already loaded with this client
586 // version
588 static const char strSettingsVersionKey[] = "nSettingsVersion";
590 ? settings.value(strSettingsVersionKey).toInt()
591 : 0;
593 // -dbcache was bumped from 100 to 300 in 0.13
594 // see https://github.com/bitcoin/bitcoin/pull/8273
595 // force people to upgrade to the new value if they are using 100MB
596 if (settingsVersion < 130000 && settings.contains("nDatabaseCache") &&
597 settings.value("nDatabaseCache").toLongLong() == 100) {
598 settings.setValue("nDatabaseCache", (qint64)DEFAULT_DB_CACHE_MB);
599 }
600
602 }
603
604 // Overwrite the 'addrProxy' setting in case it has been set to an illegal
605 // default value (see issue #12623; PR #12650).
606 if (settings.contains("addrProxy") &&
607 settings.value("addrProxy").toString().endsWith("%2")) {
608 settings.setValue("addrProxy", GetDefaultProxyAddress());
609 }
610
611 // Overwrite the 'addrSeparateProxyTor' setting in case it has been set to
612 // an illegal default value (see issue #12623; PR #12650).
613 if (settings.contains("addrSeparateProxyTor") &&
614 settings.value("addrSeparateProxyTor").toString().endsWith("%2")) {
615 settings.setValue("addrSeparateProxyTor", GetDefaultProxyAddress());
616 }
617}
ArgsManager gArgs
Definition args.cpp:38
void ForceSetArg(const std::string &strArg, const std::string &strValue)
Definition args.cpp:597
fs::path GetDataDirNet() const
Get data directory path with appended network identifier.
Definition args.h:215
bool SoftSetArg(const std::string &strArg, const std::string &strValue)
Set an argument if it doesn't already have a value.
Definition args.cpp:579
std::string GetArg(const std::string &strArg, const std::string &strDefault) const
Return string argument or default value.
Definition args.cpp:494
bool SoftSetBoolArg(const std::string &strArg, bool fValue)
Set a boolean argument if it doesn't already have a value.
Definition args.cpp:589
QVariant data(const QModelIndex &index, int role=Qt::DisplayRole) const override
QString strOverriddenByCommandLine
bool getProxySettings(QNetworkProxy &proxy) const
bool isRestartRequired() const
void Init(bool resetSettings=false)
bool fCoinControlFeatures
interfaces::Node & node() const
void setDisplayUnit(const QVariant &value)
Updates current unit in memory, settings and emits displayUnitChanged(newUnit) signal.
void coinControlFeaturesChanged(bool)
QString strThirdPartyTxUrls
OptionsModel(QObject *parent=nullptr, bool resetSettings=false)
int rowCount(const QModelIndex &parent=QModelIndex()) const override
void SetPruneTargetGB(int prune_target_gb, bool force=false)
void SetPruneEnabled(bool prune, bool force=false)
void displayUnitChanged(int unit)
bool setData(const QModelIndex &index, const QVariant &value, int role=Qt::EditRole) override
void checkAndMigrate()
QString language
void addOverriddenOption(const std::string &option)
bool fMinimizeOnClose
void setRestartRequired(bool fRequired)
void hideTrayIconChanged(bool)
Path class wrapper to block calls to the fs::path(std::string) implicit constructor and the fs::path:...
Definition fs.h:30
static constexpr int CLIENT_VERSION
bitcoind-res.rc includes this file, but it cannot cope with real c++ code.
static constexpr int DEFAULT_PRUNE_TARGET_GB
static constexpr bool DEFAULT_NATPMP
Definition mapport.h:17
static constexpr bool DEFAULT_UPNP
Definition mapport.h:11
QString getDefaultDataDirectory()
Determine default data directory for operating system.
Definition guiutil.cpp:290
QString boostPathToQString(const fs::path &path)
Convert OS specific boost path to QString through UTF-8.
Definition guiutil.cpp:785
bool SetStartOnSystemStartup(bool fAutoStart)
Definition guiutil.cpp:770
bool GetStartOnSystemStartup()
Definition guiutil.cpp:767
QStringList splitSkipEmptyParts(const QString &s, const QString &separator)
Definition guiutil.cpp:448
static const bool DEFAULT_LISTEN
-listen default
Definition net.h:84
@ NET_IPV4
IPv4.
Definition netaddress.h:50
static void CopySettings(QSettings &dst, const QSettings &src)
Helper function to copy contents from one QSettings to another.
static const QString GetDefaultProxyAddress()
static ProxySetting GetProxySetting(QSettings &settings, const QString &name)
static void SetProxySetting(QSettings &settings, const QString &name, const ProxySetting &ip_port)
static void BackupSettings(const fs::path &filename, const QSettings &src)
Back up a QSettings to an ini-formatted file.
const char * DEFAULT_GUI_PROXY_HOST
static int64_t PruneGBtoMiB(int gb)
Convert displayed prune target GB to configured MiB.
static constexpr uint16_t DEFAULT_GUI_PROXY_PORT
T GetRand(T nMax=std::numeric_limits< T >::max()) noexcept
Generate a uniform random integer of type T in the range [0..nMax) nMax defaults to std::numeric_limi...
Definition random.h:85
const char * name
Definition rest.cpp:47
static std::string ToString(const CService &ip)
Definition db.h:37
static constexpr int64_t DEFAULT_DB_CACHE_MB
-dbcache default (MiB)
Definition txdb.h:40
static const int DEFAULT_SCRIPTCHECK_THREADS
-par default (number of script-checking threads, 0 = auto)
Definition validation.h:85