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.
5 #if defined(HAVE_CONFIG_H)
6 #include "config/bitcoin-config.h"
9 #include "optionsmodel.h"
11 #include "bitcoinunits.h"
16 #include "validation.h" // For DEFAULT_SCRIPTCHECK_THREADS
19 #include "txdb.h" // for -dbcache defaults
23 #include "wallet/wallet.h"
24 #include "wallet/walletdb.h"
27 #include <QNetworkProxy>
29 #include <QStringList>
31 OptionsModel::OptionsModel(QObject
*parent
, bool resetSettings
) :
32 QAbstractListModel(parent
)
37 void OptionsModel::addOverriddenOption(const std::string
&option
)
39 strOverriddenByCommandLine
+= QString::fromStdString(option
) + "=" + QString::fromStdString(GetArg(option
, "")) + " ";
42 // Writes all missing QSettings with their default values
43 void OptionsModel::Init(bool resetSettings
)
52 // Ensure restart flag is unset on client startup
53 setRestartRequired(false);
55 // These are Qt-only settings:
58 if (!settings
.contains("fHideTrayIcon"))
59 settings
.setValue("fHideTrayIcon", false);
60 fHideTrayIcon
= settings
.value("fHideTrayIcon").toBool();
61 Q_EMIT
hideTrayIconChanged(fHideTrayIcon
);
63 if (!settings
.contains("fMinimizeToTray"))
64 settings
.setValue("fMinimizeToTray", false);
65 fMinimizeToTray
= settings
.value("fMinimizeToTray").toBool() && !fHideTrayIcon
;
67 if (!settings
.contains("fMinimizeOnClose"))
68 settings
.setValue("fMinimizeOnClose", false);
69 fMinimizeOnClose
= settings
.value("fMinimizeOnClose").toBool();
72 if (!settings
.contains("nDisplayUnit"))
73 settings
.setValue("nDisplayUnit", BitcoinUnits::BTC
);
74 nDisplayUnit
= settings
.value("nDisplayUnit").toInt();
76 if (!settings
.contains("strThirdPartyTxUrls"))
77 settings
.setValue("strThirdPartyTxUrls", "");
78 strThirdPartyTxUrls
= settings
.value("strThirdPartyTxUrls", "").toString();
80 if (!settings
.contains("fCoinControlFeatures"))
81 settings
.setValue("fCoinControlFeatures", false);
82 fCoinControlFeatures
= settings
.value("fCoinControlFeatures", false).toBool();
84 // These are shared with the core or have a command-line parameter
85 // and we want command-line parameters to overwrite the GUI settings.
87 // If setting doesn't exist create it with defaults.
89 // If SoftSetArg() or SoftSetBoolArg() return false we were overridden
90 // by command-line and show this in the UI.
93 if (!settings
.contains("nDatabaseCache"))
94 settings
.setValue("nDatabaseCache", (qint64
)nDefaultDbCache
);
95 if (!SoftSetArg("-dbcache", settings
.value("nDatabaseCache").toString().toStdString()))
96 addOverriddenOption("-dbcache");
98 if (!settings
.contains("nThreadsScriptVerif"))
99 settings
.setValue("nThreadsScriptVerif", DEFAULT_SCRIPTCHECK_THREADS
);
100 if (!SoftSetArg("-par", settings
.value("nThreadsScriptVerif").toString().toStdString()))
101 addOverriddenOption("-par");
103 if (!settings
.contains("strDataDir"))
104 settings
.setValue("strDataDir", Intro::getDefaultDataDirectory());
108 if (!settings
.contains("bSpendZeroConfChange"))
109 settings
.setValue("bSpendZeroConfChange", true);
110 if (!SoftSetBoolArg("-spendzeroconfchange", settings
.value("bSpendZeroConfChange").toBool()))
111 addOverriddenOption("-spendzeroconfchange");
115 if (!settings
.contains("fUseUPnP"))
116 settings
.setValue("fUseUPnP", DEFAULT_UPNP
);
117 if (!SoftSetBoolArg("-upnp", settings
.value("fUseUPnP").toBool()))
118 addOverriddenOption("-upnp");
120 if (!settings
.contains("fListen"))
121 settings
.setValue("fListen", DEFAULT_LISTEN
);
122 if (!SoftSetBoolArg("-listen", settings
.value("fListen").toBool()))
123 addOverriddenOption("-listen");
125 if (!settings
.contains("fUseProxy"))
126 settings
.setValue("fUseProxy", false);
127 if (!settings
.contains("addrProxy"))
128 settings
.setValue("addrProxy", "127.0.0.1:9050");
129 // Only try to set -proxy, if user has enabled fUseProxy
130 if (settings
.value("fUseProxy").toBool() && !SoftSetArg("-proxy", settings
.value("addrProxy").toString().toStdString()))
131 addOverriddenOption("-proxy");
132 else if(!settings
.value("fUseProxy").toBool() && !GetArg("-proxy", "").empty())
133 addOverriddenOption("-proxy");
135 if (!settings
.contains("fUseSeparateProxyTor"))
136 settings
.setValue("fUseSeparateProxyTor", false);
137 if (!settings
.contains("addrSeparateProxyTor"))
138 settings
.setValue("addrSeparateProxyTor", "127.0.0.1:9050");
139 // Only try to set -onion, if user has enabled fUseSeparateProxyTor
140 if (settings
.value("fUseSeparateProxyTor").toBool() && !SoftSetArg("-onion", settings
.value("addrSeparateProxyTor").toString().toStdString()))
141 addOverriddenOption("-onion");
142 else if(!settings
.value("fUseSeparateProxyTor").toBool() && !GetArg("-onion", "").empty())
143 addOverriddenOption("-onion");
146 if (!settings
.contains("language"))
147 settings
.setValue("language", "");
148 if (!SoftSetArg("-lang", settings
.value("language").toString().toStdString()))
149 addOverriddenOption("-lang");
151 language
= settings
.value("language").toString();
154 void OptionsModel::Reset()
158 // Save the strDataDir setting
159 QString dataDir
= Intro::getDefaultDataDirectory();
160 dataDir
= settings
.value("strDataDir", dataDir
).toString();
162 // Remove all entries from our QSettings object
166 settings
.setValue("strDataDir", dataDir
);
168 // Set that this was reset
169 settings
.setValue("fReset", true);
171 // default setting for OptionsModel::StartAtStartup - disabled
172 if (GUIUtil::GetStartOnSystemStartup())
173 GUIUtil::SetStartOnSystemStartup(false);
176 int OptionsModel::rowCount(const QModelIndex
& parent
) const
178 return OptionIDRowCount
;
181 // read QSettings values and return them
182 QVariant
OptionsModel::data(const QModelIndex
& index
, int role
) const
184 if(role
== Qt::EditRole
)
190 return GUIUtil::GetStartOnSystemStartup();
192 return fHideTrayIcon
;
194 return fMinimizeToTray
;
197 return settings
.value("fUseUPnP");
201 case MinimizeOnClose
:
202 return fMinimizeOnClose
;
206 return settings
.value("fUseProxy", false);
208 // contains IP at index 0 and port at index 1
209 QStringList strlIpPort
= settings
.value("addrProxy").toString().split(":", QString::SkipEmptyParts
);
210 return strlIpPort
.at(0);
213 // contains IP at index 0 and port at index 1
214 QStringList strlIpPort
= settings
.value("addrProxy").toString().split(":", QString::SkipEmptyParts
);
215 return strlIpPort
.at(1);
218 // separate Tor proxy
220 return settings
.value("fUseSeparateProxyTor", false);
222 // contains IP at index 0 and port at index 1
223 QStringList strlIpPort
= settings
.value("addrSeparateProxyTor").toString().split(":", QString::SkipEmptyParts
);
224 return strlIpPort
.at(0);
227 // contains IP at index 0 and port at index 1
228 QStringList strlIpPort
= settings
.value("addrSeparateProxyTor").toString().split(":", QString::SkipEmptyParts
);
229 return strlIpPort
.at(1);
233 case SpendZeroConfChange
:
234 return settings
.value("bSpendZeroConfChange");
238 case ThirdPartyTxUrls
:
239 return strThirdPartyTxUrls
;
241 return settings
.value("language");
242 case CoinControlFeatures
:
243 return fCoinControlFeatures
;
245 return settings
.value("nDatabaseCache");
246 case ThreadsScriptVerif
:
247 return settings
.value("nThreadsScriptVerif");
249 return settings
.value("fListen");
257 // write QSettings values
258 bool OptionsModel::setData(const QModelIndex
& index
, const QVariant
& value
, int role
)
260 bool successful
= true; /* set to false on parse error */
261 if(role
== Qt::EditRole
)
267 successful
= GUIUtil::SetStartOnSystemStartup(value
.toBool());
270 fHideTrayIcon
= value
.toBool();
271 settings
.setValue("fHideTrayIcon", fHideTrayIcon
);
272 Q_EMIT
hideTrayIconChanged(fHideTrayIcon
);
275 fMinimizeToTray
= value
.toBool();
276 settings
.setValue("fMinimizeToTray", fMinimizeToTray
);
278 case MapPortUPnP
: // core option - can be changed on-the-fly
279 settings
.setValue("fUseUPnP", value
.toBool());
280 MapPort(value
.toBool());
282 case MinimizeOnClose
:
283 fMinimizeOnClose
= value
.toBool();
284 settings
.setValue("fMinimizeOnClose", fMinimizeOnClose
);
289 if (settings
.value("fUseProxy") != value
) {
290 settings
.setValue("fUseProxy", value
.toBool());
291 setRestartRequired(true);
295 // contains current IP at index 0 and current port at index 1
296 QStringList strlIpPort
= settings
.value("addrProxy").toString().split(":", QString::SkipEmptyParts
);
297 // if that key doesn't exist or has a changed IP
298 if (!settings
.contains("addrProxy") || strlIpPort
.at(0) != value
.toString()) {
299 // construct new value from new IP and current port
300 QString strNewValue
= value
.toString() + ":" + strlIpPort
.at(1);
301 settings
.setValue("addrProxy", strNewValue
);
302 setRestartRequired(true);
307 // contains current IP at index 0 and current port at index 1
308 QStringList strlIpPort
= settings
.value("addrProxy").toString().split(":", QString::SkipEmptyParts
);
309 // if that key doesn't exist or has a changed port
310 if (!settings
.contains("addrProxy") || strlIpPort
.at(1) != value
.toString()) {
311 // construct new value from current IP and new port
312 QString strNewValue
= strlIpPort
.at(0) + ":" + value
.toString();
313 settings
.setValue("addrProxy", strNewValue
);
314 setRestartRequired(true);
319 // separate Tor proxy
321 if (settings
.value("fUseSeparateProxyTor") != value
) {
322 settings
.setValue("fUseSeparateProxyTor", value
.toBool());
323 setRestartRequired(true);
327 // contains current IP at index 0 and current port at index 1
328 QStringList strlIpPort
= settings
.value("addrSeparateProxyTor").toString().split(":", QString::SkipEmptyParts
);
329 // if that key doesn't exist or has a changed IP
330 if (!settings
.contains("addrSeparateProxyTor") || strlIpPort
.at(0) != value
.toString()) {
331 // construct new value from new IP and current port
332 QString strNewValue
= value
.toString() + ":" + strlIpPort
.at(1);
333 settings
.setValue("addrSeparateProxyTor", strNewValue
);
334 setRestartRequired(true);
339 // contains current IP at index 0 and current port at index 1
340 QStringList strlIpPort
= settings
.value("addrSeparateProxyTor").toString().split(":", QString::SkipEmptyParts
);
341 // if that key doesn't exist or has a changed port
342 if (!settings
.contains("addrSeparateProxyTor") || strlIpPort
.at(1) != value
.toString()) {
343 // construct new value from current IP and new port
344 QString strNewValue
= strlIpPort
.at(0) + ":" + value
.toString();
345 settings
.setValue("addrSeparateProxyTor", strNewValue
);
346 setRestartRequired(true);
352 case SpendZeroConfChange
:
353 if (settings
.value("bSpendZeroConfChange") != value
) {
354 settings
.setValue("bSpendZeroConfChange", value
);
355 setRestartRequired(true);
360 setDisplayUnit(value
);
362 case ThirdPartyTxUrls
:
363 if (strThirdPartyTxUrls
!= value
.toString()) {
364 strThirdPartyTxUrls
= value
.toString();
365 settings
.setValue("strThirdPartyTxUrls", strThirdPartyTxUrls
);
366 setRestartRequired(true);
370 if (settings
.value("language") != value
) {
371 settings
.setValue("language", value
);
372 setRestartRequired(true);
375 case CoinControlFeatures
:
376 fCoinControlFeatures
= value
.toBool();
377 settings
.setValue("fCoinControlFeatures", fCoinControlFeatures
);
378 Q_EMIT
coinControlFeaturesChanged(fCoinControlFeatures
);
381 if (settings
.value("nDatabaseCache") != value
) {
382 settings
.setValue("nDatabaseCache", value
);
383 setRestartRequired(true);
386 case ThreadsScriptVerif
:
387 if (settings
.value("nThreadsScriptVerif") != value
) {
388 settings
.setValue("nThreadsScriptVerif", value
);
389 setRestartRequired(true);
393 if (settings
.value("fListen") != value
) {
394 settings
.setValue("fListen", value
);
395 setRestartRequired(true);
403 Q_EMIT
dataChanged(index
, index
);
408 /** Updates current unit in memory, settings and emits displayUnitChanged(newUnit) signal */
409 void OptionsModel::setDisplayUnit(const QVariant
&value
)
414 nDisplayUnit
= value
.toInt();
415 settings
.setValue("nDisplayUnit", nDisplayUnit
);
416 Q_EMIT
displayUnitChanged(nDisplayUnit
);
420 bool OptionsModel::getProxySettings(QNetworkProxy
& proxy
) const
422 // Directly query current base proxy, because
423 // GUI settings can be overridden with -proxy.
425 if (GetProxy(NET_IPV4
, curProxy
)) {
426 proxy
.setType(QNetworkProxy::Socks5Proxy
);
427 proxy
.setHostName(QString::fromStdString(curProxy
.proxy
.ToStringIP()));
428 proxy
.setPort(curProxy
.proxy
.GetPort());
433 proxy
.setType(QNetworkProxy::NoProxy
);
438 void OptionsModel::setRestartRequired(bool fRequired
)
441 return settings
.setValue("fRestartRequired", fRequired
);
444 bool OptionsModel::isRestartRequired() const
447 return settings
.value("fRestartRequired", false).toBool();
450 void OptionsModel::checkAndMigrate()
452 // Migration of default values
453 // Check if the QSettings container was already loaded with this client version
455 static const char strSettingsVersionKey
[] = "nSettingsVersion";
456 int settingsVersion
= settings
.contains(strSettingsVersionKey
) ? settings
.value(strSettingsVersionKey
).toInt() : 0;
457 if (settingsVersion
< CLIENT_VERSION
)
459 // -dbcache was bumped from 100 to 300 in 0.13
460 // see https://github.com/bitcoin/bitcoin/pull/8273
461 // force people to upgrade to the new value if they are using 100MB
462 if (settingsVersion
< 130000 && settings
.contains("nDatabaseCache") && settings
.value("nDatabaseCache").toLongLong() == 100)
463 settings
.setValue("nDatabaseCache", (qint64
)nDefaultDbCache
);
465 settings
.setValue(strSettingsVersionKey
, CLIENT_VERSION
);