[tests] Add -blocknotify functional test
[bitcoinplatinum.git] / src / qt / optionsmodel.cpp
blobfb8c60d100168f8ec9719e5f5ce7a8fb2c4fff42
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"
7 #endif
9 #include "optionsmodel.h"
11 #include "bitcoinunits.h"
12 #include "guiutil.h"
14 #include "amount.h"
15 #include "init.h"
16 #include "validation.h" // For DEFAULT_SCRIPTCHECK_THREADS
17 #include "net.h"
18 #include "netbase.h"
19 #include "txdb.h" // for -dbcache defaults
20 #include "intro.h"
22 #ifdef ENABLE_WALLET
23 #include "wallet/wallet.h"
24 #include "wallet/walletdb.h"
25 #endif
27 #include <QNetworkProxy>
28 #include <QSettings>
29 #include <QStringList>
31 OptionsModel::OptionsModel(QObject *parent, bool resetSettings) :
32 QAbstractListModel(parent)
34 Init(resetSettings);
37 void OptionsModel::addOverriddenOption(const std::string &option)
39 strOverriddenByCommandLine += QString::fromStdString(option) + "=" + QString::fromStdString(gArgs.GetArg(option, "")) + " ";
42 // Writes all missing QSettings with their default values
43 void OptionsModel::Init(bool resetSettings)
45 if (resetSettings)
46 Reset();
48 checkAndMigrate();
50 QSettings settings;
52 // Ensure restart flag is unset on client startup
53 setRestartRequired(false);
55 // These are Qt-only settings:
57 // Window
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();
71 // Display
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 gArgs.SoftSetArg() or gArgs.SoftSetBoolArg() return false we were overridden
90 // by command-line and show this in the UI.
92 // Main
93 if (!settings.contains("nDatabaseCache"))
94 settings.setValue("nDatabaseCache", (qint64)nDefaultDbCache);
95 if (!gArgs.SoftSetArg("-dbcache", settings.value("nDatabaseCache").toString().toStdString()))
96 addOverriddenOption("-dbcache");
98 if (!settings.contains("nThreadsScriptVerif"))
99 settings.setValue("nThreadsScriptVerif", DEFAULT_SCRIPTCHECK_THREADS);
100 if (!gArgs.SoftSetArg("-par", settings.value("nThreadsScriptVerif").toString().toStdString()))
101 addOverriddenOption("-par");
103 if (!settings.contains("strDataDir"))
104 settings.setValue("strDataDir", Intro::getDefaultDataDirectory());
106 // Wallet
107 #ifdef ENABLE_WALLET
108 if (!settings.contains("bSpendZeroConfChange"))
109 settings.setValue("bSpendZeroConfChange", true);
110 if (!gArgs.SoftSetBoolArg("-spendzeroconfchange", settings.value("bSpendZeroConfChange").toBool()))
111 addOverriddenOption("-spendzeroconfchange");
112 #endif
114 // Network
115 if (!settings.contains("fUseUPnP"))
116 settings.setValue("fUseUPnP", DEFAULT_UPNP);
117 if (!gArgs.SoftSetBoolArg("-upnp", settings.value("fUseUPnP").toBool()))
118 addOverriddenOption("-upnp");
120 if (!settings.contains("fListen"))
121 settings.setValue("fListen", DEFAULT_LISTEN);
122 if (!gArgs.SoftSetBoolArg("-listen", settings.value("fListen").toBool()))
123 addOverriddenOption("-listen");
125 if (!settings.contains("fUseProxy"))
126 settings.setValue("fUseProxy", false);
127 if (!settings.contains("addrProxy") || !settings.value("addrProxy").toString().contains(':'))
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() && !gArgs.SoftSetArg("-proxy", settings.value("addrProxy").toString().toStdString()))
131 addOverriddenOption("-proxy");
132 else if(!settings.value("fUseProxy").toBool() && !gArgs.GetArg("-proxy", "").empty())
133 addOverriddenOption("-proxy");
135 if (!settings.contains("fUseSeparateProxyTor"))
136 settings.setValue("fUseSeparateProxyTor", false);
137 if (!settings.contains("addrSeparateProxyTor") || !settings.value("addrSeparateProxyTor").toString().contains(':'))
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() && !gArgs.SoftSetArg("-onion", settings.value("addrSeparateProxyTor").toString().toStdString()))
141 addOverriddenOption("-onion");
142 else if(!settings.value("fUseSeparateProxyTor").toBool() && !gArgs.GetArg("-onion", "").empty())
143 addOverriddenOption("-onion");
145 // Display
146 if (!settings.contains("language"))
147 settings.setValue("language", "");
148 if (!gArgs.SoftSetArg("-lang", settings.value("language").toString().toStdString()))
149 addOverriddenOption("-lang");
151 language = settings.value("language").toString();
154 /** Helper function to copy contents from one QSettings to another.
155 * By using allKeys this also covers nested settings in a hierarchy.
157 static void CopySettings(QSettings& dst, const QSettings& src)
159 for (const QString& key : src.allKeys()) {
160 dst.setValue(key, src.value(key));
164 /** Back up a QSettings to an ini-formatted file. */
165 static void BackupSettings(const fs::path& filename, const QSettings& src)
167 qWarning() << "Backing up GUI settings to" << GUIUtil::boostPathToQString(filename);
168 QSettings dst(GUIUtil::boostPathToQString(filename), QSettings::IniFormat);
169 dst.clear();
170 CopySettings(dst, src);
173 void OptionsModel::Reset()
175 QSettings settings;
177 // Backup old settings to chain-specific datadir for troubleshooting
178 BackupSettings(GetDataDir(true) / "guisettings.ini.bak", settings);
180 // Save the strDataDir setting
181 QString dataDir = Intro::getDefaultDataDirectory();
182 dataDir = settings.value("strDataDir", dataDir).toString();
184 // Remove all entries from our QSettings object
185 settings.clear();
187 // Set strDataDir
188 settings.setValue("strDataDir", dataDir);
190 // Set that this was reset
191 settings.setValue("fReset", true);
193 // default setting for OptionsModel::StartAtStartup - disabled
194 if (GUIUtil::GetStartOnSystemStartup())
195 GUIUtil::SetStartOnSystemStartup(false);
198 int OptionsModel::rowCount(const QModelIndex & parent) const
200 return OptionIDRowCount;
203 // read QSettings values and return them
204 QVariant OptionsModel::data(const QModelIndex & index, int role) const
206 if(role == Qt::EditRole)
208 QSettings settings;
209 switch(index.row())
211 case StartAtStartup:
212 return GUIUtil::GetStartOnSystemStartup();
213 case HideTrayIcon:
214 return fHideTrayIcon;
215 case MinimizeToTray:
216 return fMinimizeToTray;
217 case MapPortUPnP:
218 #ifdef USE_UPNP
219 return settings.value("fUseUPnP");
220 #else
221 return false;
222 #endif
223 case MinimizeOnClose:
224 return fMinimizeOnClose;
226 // default proxy
227 case ProxyUse:
228 return settings.value("fUseProxy", false);
229 case ProxyIP: {
230 // contains IP at index 0 and port at index 1
231 QStringList strlIpPort = settings.value("addrProxy").toString().split(":", QString::SkipEmptyParts);
232 return strlIpPort.at(0);
234 case ProxyPort: {
235 // contains IP at index 0 and port at index 1
236 QStringList strlIpPort = settings.value("addrProxy").toString().split(":", QString::SkipEmptyParts);
237 return strlIpPort.at(1);
240 // separate Tor proxy
241 case ProxyUseTor:
242 return settings.value("fUseSeparateProxyTor", false);
243 case ProxyIPTor: {
244 // contains IP at index 0 and port at index 1
245 QStringList strlIpPort = settings.value("addrSeparateProxyTor").toString().split(":", QString::SkipEmptyParts);
246 return strlIpPort.at(0);
248 case ProxyPortTor: {
249 // contains IP at index 0 and port at index 1
250 QStringList strlIpPort = settings.value("addrSeparateProxyTor").toString().split(":", QString::SkipEmptyParts);
251 return strlIpPort.at(1);
254 #ifdef ENABLE_WALLET
255 case SpendZeroConfChange:
256 return settings.value("bSpendZeroConfChange");
257 #endif
258 case DisplayUnit:
259 return nDisplayUnit;
260 case ThirdPartyTxUrls:
261 return strThirdPartyTxUrls;
262 case Language:
263 return settings.value("language");
264 case CoinControlFeatures:
265 return fCoinControlFeatures;
266 case DatabaseCache:
267 return settings.value("nDatabaseCache");
268 case ThreadsScriptVerif:
269 return settings.value("nThreadsScriptVerif");
270 case Listen:
271 return settings.value("fListen");
272 default:
273 return QVariant();
276 return QVariant();
279 // write QSettings values
280 bool OptionsModel::setData(const QModelIndex & index, const QVariant & value, int role)
282 bool successful = true; /* set to false on parse error */
283 if(role == Qt::EditRole)
285 QSettings settings;
286 switch(index.row())
288 case StartAtStartup:
289 successful = GUIUtil::SetStartOnSystemStartup(value.toBool());
290 break;
291 case HideTrayIcon:
292 fHideTrayIcon = value.toBool();
293 settings.setValue("fHideTrayIcon", fHideTrayIcon);
294 Q_EMIT hideTrayIconChanged(fHideTrayIcon);
295 break;
296 case MinimizeToTray:
297 fMinimizeToTray = value.toBool();
298 settings.setValue("fMinimizeToTray", fMinimizeToTray);
299 break;
300 case MapPortUPnP: // core option - can be changed on-the-fly
301 settings.setValue("fUseUPnP", value.toBool());
302 MapPort(value.toBool());
303 break;
304 case MinimizeOnClose:
305 fMinimizeOnClose = value.toBool();
306 settings.setValue("fMinimizeOnClose", fMinimizeOnClose);
307 break;
309 // default proxy
310 case ProxyUse:
311 if (settings.value("fUseProxy") != value) {
312 settings.setValue("fUseProxy", value.toBool());
313 setRestartRequired(true);
315 break;
316 case ProxyIP: {
317 // contains current IP at index 0 and current port at index 1
318 QStringList strlIpPort = settings.value("addrProxy").toString().split(":", QString::SkipEmptyParts);
319 // if that key doesn't exist or has a changed IP
320 if (!settings.contains("addrProxy") || strlIpPort.at(0) != value.toString()) {
321 // construct new value from new IP and current port
322 QString strNewValue = value.toString() + ":" + strlIpPort.at(1);
323 settings.setValue("addrProxy", strNewValue);
324 setRestartRequired(true);
327 break;
328 case ProxyPort: {
329 // contains current IP at index 0 and current port at index 1
330 QStringList strlIpPort = settings.value("addrProxy").toString().split(":", QString::SkipEmptyParts);
331 // if that key doesn't exist or has a changed port
332 if (!settings.contains("addrProxy") || strlIpPort.at(1) != value.toString()) {
333 // construct new value from current IP and new port
334 QString strNewValue = strlIpPort.at(0) + ":" + value.toString();
335 settings.setValue("addrProxy", strNewValue);
336 setRestartRequired(true);
339 break;
341 // separate Tor proxy
342 case ProxyUseTor:
343 if (settings.value("fUseSeparateProxyTor") != value) {
344 settings.setValue("fUseSeparateProxyTor", value.toBool());
345 setRestartRequired(true);
347 break;
348 case ProxyIPTor: {
349 // contains current IP at index 0 and current port at index 1
350 QStringList strlIpPort = settings.value("addrSeparateProxyTor").toString().split(":", QString::SkipEmptyParts);
351 // if that key doesn't exist or has a changed IP
352 if (!settings.contains("addrSeparateProxyTor") || strlIpPort.at(0) != value.toString()) {
353 // construct new value from new IP and current port
354 QString strNewValue = value.toString() + ":" + strlIpPort.at(1);
355 settings.setValue("addrSeparateProxyTor", strNewValue);
356 setRestartRequired(true);
359 break;
360 case ProxyPortTor: {
361 // contains current IP at index 0 and current port at index 1
362 QStringList strlIpPort = settings.value("addrSeparateProxyTor").toString().split(":", QString::SkipEmptyParts);
363 // if that key doesn't exist or has a changed port
364 if (!settings.contains("addrSeparateProxyTor") || strlIpPort.at(1) != value.toString()) {
365 // construct new value from current IP and new port
366 QString strNewValue = strlIpPort.at(0) + ":" + value.toString();
367 settings.setValue("addrSeparateProxyTor", strNewValue);
368 setRestartRequired(true);
371 break;
373 #ifdef ENABLE_WALLET
374 case SpendZeroConfChange:
375 if (settings.value("bSpendZeroConfChange") != value) {
376 settings.setValue("bSpendZeroConfChange", value);
377 setRestartRequired(true);
379 break;
380 #endif
381 case DisplayUnit:
382 setDisplayUnit(value);
383 break;
384 case ThirdPartyTxUrls:
385 if (strThirdPartyTxUrls != value.toString()) {
386 strThirdPartyTxUrls = value.toString();
387 settings.setValue("strThirdPartyTxUrls", strThirdPartyTxUrls);
388 setRestartRequired(true);
390 break;
391 case Language:
392 if (settings.value("language") != value) {
393 settings.setValue("language", value);
394 setRestartRequired(true);
396 break;
397 case CoinControlFeatures:
398 fCoinControlFeatures = value.toBool();
399 settings.setValue("fCoinControlFeatures", fCoinControlFeatures);
400 Q_EMIT coinControlFeaturesChanged(fCoinControlFeatures);
401 break;
402 case DatabaseCache:
403 if (settings.value("nDatabaseCache") != value) {
404 settings.setValue("nDatabaseCache", value);
405 setRestartRequired(true);
407 break;
408 case ThreadsScriptVerif:
409 if (settings.value("nThreadsScriptVerif") != value) {
410 settings.setValue("nThreadsScriptVerif", value);
411 setRestartRequired(true);
413 break;
414 case Listen:
415 if (settings.value("fListen") != value) {
416 settings.setValue("fListen", value);
417 setRestartRequired(true);
419 break;
420 default:
421 break;
425 Q_EMIT dataChanged(index, index);
427 return successful;
430 /** Updates current unit in memory, settings and emits displayUnitChanged(newUnit) signal */
431 void OptionsModel::setDisplayUnit(const QVariant &value)
433 if (!value.isNull())
435 QSettings settings;
436 nDisplayUnit = value.toInt();
437 settings.setValue("nDisplayUnit", nDisplayUnit);
438 Q_EMIT displayUnitChanged(nDisplayUnit);
442 bool OptionsModel::getProxySettings(QNetworkProxy& proxy) const
444 // Directly query current base proxy, because
445 // GUI settings can be overridden with -proxy.
446 proxyType curProxy;
447 if (GetProxy(NET_IPV4, curProxy)) {
448 proxy.setType(QNetworkProxy::Socks5Proxy);
449 proxy.setHostName(QString::fromStdString(curProxy.proxy.ToStringIP()));
450 proxy.setPort(curProxy.proxy.GetPort());
452 return true;
454 else
455 proxy.setType(QNetworkProxy::NoProxy);
457 return false;
460 void OptionsModel::setRestartRequired(bool fRequired)
462 QSettings settings;
463 return settings.setValue("fRestartRequired", fRequired);
466 bool OptionsModel::isRestartRequired() const
468 QSettings settings;
469 return settings.value("fRestartRequired", false).toBool();
472 void OptionsModel::checkAndMigrate()
474 // Migration of default values
475 // Check if the QSettings container was already loaded with this client version
476 QSettings settings;
477 static const char strSettingsVersionKey[] = "nSettingsVersion";
478 int settingsVersion = settings.contains(strSettingsVersionKey) ? settings.value(strSettingsVersionKey).toInt() : 0;
479 if (settingsVersion < CLIENT_VERSION)
481 // -dbcache was bumped from 100 to 300 in 0.13
482 // see https://github.com/bitcoin/bitcoin/pull/8273
483 // force people to upgrade to the new value if they are using 100MB
484 if (settingsVersion < 130000 && settings.contains("nDatabaseCache") && settings.value("nDatabaseCache").toLongLong() == 100)
485 settings.setValue("nDatabaseCache", (qint64)nDefaultDbCache);
487 settings.setValue(strSettingsVersionKey, CLIENT_VERSION);