BSHA3  0.17.99
P2P Blockchain, based on Bitcoin
optionsmodel.cpp
Go to the documentation of this file.
1 // Copyright (c) 2011-2018 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)
7 #endif
8 
9 #include <qt/optionsmodel.h>
10 
11 #include <qt/bitcoinunits.h>
12 #include <qt/guiutil.h>
13 
14 #include <interfaces/node.h>
15 #include <validation.h> // For DEFAULT_SCRIPTCHECK_THREADS
16 #include <net.h>
17 #include <netbase.h>
18 #include <txdb.h> // for -dbcache defaults
19 #include <qt/intro.h>
20 
21 #include <QNetworkProxy>
22 #include <QSettings>
23 #include <QStringList>
24 
25 const char *DEFAULT_GUI_PROXY_HOST = "127.0.0.1";
26 
27 static const QString GetDefaultProxyAddress();
28 
29 OptionsModel::OptionsModel(interfaces::Node& node, QObject *parent, bool resetSettings) :
30  QAbstractListModel(parent), m_node(node)
31 {
32  Init(resetSettings);
33 }
34 
35 void OptionsModel::addOverriddenOption(const std::string &option)
36 {
37  strOverriddenByCommandLine += QString::fromStdString(option) + "=" + QString::fromStdString(gArgs.GetArg(option, "")) + " ";
38 }
39 
40 // Writes all missing QSettings with their default values
41 void OptionsModel::Init(bool resetSettings)
42 {
43  if (resetSettings)
44  Reset();
45 
47 
48  QSettings settings;
49 
50  // Ensure restart flag is unset on client startup
51  setRestartRequired(false);
52 
53  // These are Qt-only settings:
54 
55  // Window
56  if (!settings.contains("fHideTrayIcon"))
57  settings.setValue("fHideTrayIcon", false);
58  fHideTrayIcon = settings.value("fHideTrayIcon").toBool();
60 
61  if (!settings.contains("fMinimizeToTray"))
62  settings.setValue("fMinimizeToTray", false);
63  fMinimizeToTray = settings.value("fMinimizeToTray").toBool() && !fHideTrayIcon;
64 
65  if (!settings.contains("fMinimizeOnClose"))
66  settings.setValue("fMinimizeOnClose", false);
67  fMinimizeOnClose = settings.value("fMinimizeOnClose").toBool();
68 
69  // Display
70  if (!settings.contains("nDisplayUnit"))
71  settings.setValue("nDisplayUnit", BitcoinUnits::BTC);
72  nDisplayUnit = settings.value("nDisplayUnit").toInt();
73 
74  if (!settings.contains("strThirdPartyTxUrls"))
75  settings.setValue("strThirdPartyTxUrls", "");
76  strThirdPartyTxUrls = settings.value("strThirdPartyTxUrls", "").toString();
77 
78  if (!settings.contains("fCoinControlFeatures"))
79  settings.setValue("fCoinControlFeatures", false);
80  fCoinControlFeatures = settings.value("fCoinControlFeatures", false).toBool();
81 
82  // These are shared with the core or have a command-line parameter
83  // and we want command-line parameters to overwrite the GUI settings.
84  //
85  // If setting doesn't exist create it with defaults.
86  //
87  // If gArgs.SoftSetArg() or gArgs.SoftSetBoolArg() return false we were overridden
88  // by command-line and show this in the UI.
89 
90  // Main
91  if (!settings.contains("bPrune"))
92  settings.setValue("bPrune", false);
93  if (!settings.contains("nPruneSize"))
94  settings.setValue("nPruneSize", 2);
95  // Convert prune size to MB:
96  const uint64_t nPruneSizeMB = settings.value("nPruneSize").toInt() * 1000;
97  if (!m_node.softSetArg("-prune", settings.value("bPrune").toBool() ? std::to_string(nPruneSizeMB) : "0")) {
98  addOverriddenOption("-prune");
99  }
100 
101  if (!settings.contains("nDatabaseCache"))
102  settings.setValue("nDatabaseCache", (qint64)nDefaultDbCache);
103  if (!m_node.softSetArg("-dbcache", settings.value("nDatabaseCache").toString().toStdString()))
104  addOverriddenOption("-dbcache");
105 
106  if (!settings.contains("nThreadsScriptVerif"))
107  settings.setValue("nThreadsScriptVerif", DEFAULT_SCRIPTCHECK_THREADS);
108  if (!m_node.softSetArg("-par", settings.value("nThreadsScriptVerif").toString().toStdString()))
109  addOverriddenOption("-par");
110 
111  if (!settings.contains("strDataDir"))
112  settings.setValue("strDataDir", Intro::getDefaultDataDirectory());
113 
114  // Wallet
115 #ifdef ENABLE_WALLET
116  if (!settings.contains("bSpendZeroConfChange"))
117  settings.setValue("bSpendZeroConfChange", true);
118  if (!m_node.softSetBoolArg("-spendzeroconfchange", settings.value("bSpendZeroConfChange").toBool()))
119  addOverriddenOption("-spendzeroconfchange");
120 #endif
121 
122  // Network
123  if (!settings.contains("fUseUPnP"))
124  settings.setValue("fUseUPnP", DEFAULT_UPNP);
125  if (!m_node.softSetBoolArg("-upnp", settings.value("fUseUPnP").toBool()))
126  addOverriddenOption("-upnp");
127 
128  if (!settings.contains("fListen"))
129  settings.setValue("fListen", DEFAULT_LISTEN);
130  if (!m_node.softSetBoolArg("-listen", settings.value("fListen").toBool()))
131  addOverriddenOption("-listen");
132 
133  if (!settings.contains("fUseProxy"))
134  settings.setValue("fUseProxy", false);
135  if (!settings.contains("addrProxy"))
136  settings.setValue("addrProxy", GetDefaultProxyAddress());
137  // Only try to set -proxy, if user has enabled fUseProxy
138  if (settings.value("fUseProxy").toBool() && !m_node.softSetArg("-proxy", settings.value("addrProxy").toString().toStdString()))
139  addOverriddenOption("-proxy");
140  else if(!settings.value("fUseProxy").toBool() && !gArgs.GetArg("-proxy", "").empty())
141  addOverriddenOption("-proxy");
142 
143  if (!settings.contains("fUseSeparateProxyTor"))
144  settings.setValue("fUseSeparateProxyTor", false);
145  if (!settings.contains("addrSeparateProxyTor"))
146  settings.setValue("addrSeparateProxyTor", GetDefaultProxyAddress());
147  // Only try to set -onion, if user has enabled fUseSeparateProxyTor
148  if (settings.value("fUseSeparateProxyTor").toBool() && !m_node.softSetArg("-onion", settings.value("addrSeparateProxyTor").toString().toStdString()))
149  addOverriddenOption("-onion");
150  else if(!settings.value("fUseSeparateProxyTor").toBool() && !gArgs.GetArg("-onion", "").empty())
151  addOverriddenOption("-onion");
152 
153  // Display
154  if (!settings.contains("language"))
155  settings.setValue("language", "");
156  if (!m_node.softSetArg("-lang", settings.value("language").toString().toStdString()))
157  addOverriddenOption("-lang");
158 
159  language = settings.value("language").toString();
160 }
161 
165 static void CopySettings(QSettings& dst, const QSettings& src)
166 {
167  for (const QString& key : src.allKeys()) {
168  dst.setValue(key, src.value(key));
169  }
170 }
171 
173 static void BackupSettings(const fs::path& filename, const QSettings& src)
174 {
175  qWarning() << "Backing up GUI settings to" << GUIUtil::boostPathToQString(filename);
176  QSettings dst(GUIUtil::boostPathToQString(filename), QSettings::IniFormat);
177  dst.clear();
178  CopySettings(dst, src);
179 }
180 
182 {
183  QSettings settings;
184 
185  // Backup old settings to chain-specific datadir for troubleshooting
186  BackupSettings(GetDataDir(true) / "guisettings.ini.bak", settings);
187 
188  // Save the strDataDir setting
189  QString dataDir = Intro::getDefaultDataDirectory();
190  dataDir = settings.value("strDataDir", dataDir).toString();
191 
192  // Remove all entries from our QSettings object
193  settings.clear();
194 
195  // Set strDataDir
196  settings.setValue("strDataDir", dataDir);
197 
198  // Set that this was reset
199  settings.setValue("fReset", true);
200 
201  // default setting for OptionsModel::StartAtStartup - disabled
204 }
205 
206 int OptionsModel::rowCount(const QModelIndex & parent) const
207 {
208  return OptionIDRowCount;
209 }
210 
211 struct ProxySetting {
212  bool is_set;
213  QString ip;
214  QString port;
215 };
216 
217 static ProxySetting GetProxySetting(QSettings &settings, const QString &name)
218 {
219  static const ProxySetting default_val = {false, DEFAULT_GUI_PROXY_HOST, QString("%1").arg(DEFAULT_GUI_PROXY_PORT)};
220  // Handle the case that the setting is not set at all
221  if (!settings.contains(name)) {
222  return default_val;
223  }
224  // contains IP at index 0 and port at index 1
225  QStringList ip_port = settings.value(name).toString().split(":", QString::SkipEmptyParts);
226  if (ip_port.size() == 2) {
227  return {true, ip_port.at(0), ip_port.at(1)};
228  } else { // Invalid: return default
229  return default_val;
230  }
231 }
232 
233 static void SetProxySetting(QSettings &settings, const QString &name, const ProxySetting &ip_port)
234 {
235  settings.setValue(name, ip_port.ip + ":" + ip_port.port);
236 }
237 
238 static const QString GetDefaultProxyAddress()
239 {
240  return QString("%1:%2").arg(DEFAULT_GUI_PROXY_HOST).arg(DEFAULT_GUI_PROXY_PORT);
241 }
242 
243 // read QSettings values and return them
244 QVariant OptionsModel::data(const QModelIndex & index, int role) const
245 {
246  if(role == Qt::EditRole)
247  {
248  QSettings settings;
249  switch(index.row())
250  {
251  case StartAtStartup:
253  case HideTrayIcon:
254  return fHideTrayIcon;
255  case MinimizeToTray:
256  return fMinimizeToTray;
257  case MapPortUPnP:
258 #ifdef USE_UPNP
259  return settings.value("fUseUPnP");
260 #else
261  return false;
262 #endif
263  case MinimizeOnClose:
264  return fMinimizeOnClose;
265 
266  // default proxy
267  case ProxyUse:
268  return settings.value("fUseProxy", false);
269  case ProxyIP:
270  return GetProxySetting(settings, "addrProxy").ip;
271  case ProxyPort:
272  return GetProxySetting(settings, "addrProxy").port;
273 
274  // separate Tor proxy
275  case ProxyUseTor:
276  return settings.value("fUseSeparateProxyTor", false);
277  case ProxyIPTor:
278  return GetProxySetting(settings, "addrSeparateProxyTor").ip;
279  case ProxyPortTor:
280  return GetProxySetting(settings, "addrSeparateProxyTor").port;
281 
282 #ifdef ENABLE_WALLET
283  case SpendZeroConfChange:
284  return settings.value("bSpendZeroConfChange");
285 #endif
286  case DisplayUnit:
287  return nDisplayUnit;
288  case ThirdPartyTxUrls:
289  return strThirdPartyTxUrls;
290  case Language:
291  return settings.value("language");
292  case CoinControlFeatures:
293  return fCoinControlFeatures;
294  case Prune:
295  return settings.value("bPrune");
296  case PruneSize:
297  return settings.value("nPruneSize");
298  case DatabaseCache:
299  return settings.value("nDatabaseCache");
300  case ThreadsScriptVerif:
301  return settings.value("nThreadsScriptVerif");
302  case Listen:
303  return settings.value("fListen");
304  default:
305  return QVariant();
306  }
307  }
308  return QVariant();
309 }
310 
311 // write QSettings values
312 bool OptionsModel::setData(const QModelIndex & index, const QVariant & value, int role)
313 {
314  bool successful = true; /* set to false on parse error */
315  if(role == Qt::EditRole)
316  {
317  QSettings settings;
318  switch(index.row())
319  {
320  case StartAtStartup:
321  successful = GUIUtil::SetStartOnSystemStartup(value.toBool());
322  break;
323  case HideTrayIcon:
324  fHideTrayIcon = value.toBool();
325  settings.setValue("fHideTrayIcon", fHideTrayIcon);
327  break;
328  case MinimizeToTray:
329  fMinimizeToTray = value.toBool();
330  settings.setValue("fMinimizeToTray", fMinimizeToTray);
331  break;
332  case MapPortUPnP: // core option - can be changed on-the-fly
333  settings.setValue("fUseUPnP", value.toBool());
334  m_node.mapPort(value.toBool());
335  break;
336  case MinimizeOnClose:
337  fMinimizeOnClose = value.toBool();
338  settings.setValue("fMinimizeOnClose", fMinimizeOnClose);
339  break;
340 
341  // default proxy
342  case ProxyUse:
343  if (settings.value("fUseProxy") != value) {
344  settings.setValue("fUseProxy", value.toBool());
345  setRestartRequired(true);
346  }
347  break;
348  case ProxyIP: {
349  auto ip_port = GetProxySetting(settings, "addrProxy");
350  if (!ip_port.is_set || ip_port.ip != value.toString()) {
351  ip_port.ip = value.toString();
352  SetProxySetting(settings, "addrProxy", ip_port);
353  setRestartRequired(true);
354  }
355  }
356  break;
357  case ProxyPort: {
358  auto ip_port = GetProxySetting(settings, "addrProxy");
359  if (!ip_port.is_set || ip_port.port != value.toString()) {
360  ip_port.port = value.toString();
361  SetProxySetting(settings, "addrProxy", ip_port);
362  setRestartRequired(true);
363  }
364  }
365  break;
366 
367  // separate Tor proxy
368  case ProxyUseTor:
369  if (settings.value("fUseSeparateProxyTor") != value) {
370  settings.setValue("fUseSeparateProxyTor", value.toBool());
371  setRestartRequired(true);
372  }
373  break;
374  case ProxyIPTor: {
375  auto ip_port = GetProxySetting(settings, "addrSeparateProxyTor");
376  if (!ip_port.is_set || ip_port.ip != value.toString()) {
377  ip_port.ip = value.toString();
378  SetProxySetting(settings, "addrSeparateProxyTor", ip_port);
379  setRestartRequired(true);
380  }
381  }
382  break;
383  case ProxyPortTor: {
384  auto ip_port = GetProxySetting(settings, "addrSeparateProxyTor");
385  if (!ip_port.is_set || ip_port.port != value.toString()) {
386  ip_port.port = value.toString();
387  SetProxySetting(settings, "addrSeparateProxyTor", ip_port);
388  setRestartRequired(true);
389  }
390  }
391  break;
392 
393 #ifdef ENABLE_WALLET
394  case SpendZeroConfChange:
395  if (settings.value("bSpendZeroConfChange") != value) {
396  settings.setValue("bSpendZeroConfChange", value);
397  setRestartRequired(true);
398  }
399  break;
400 #endif
401  case DisplayUnit:
402  setDisplayUnit(value);
403  break;
404  case ThirdPartyTxUrls:
405  if (strThirdPartyTxUrls != value.toString()) {
406  strThirdPartyTxUrls = value.toString();
407  settings.setValue("strThirdPartyTxUrls", strThirdPartyTxUrls);
408  setRestartRequired(true);
409  }
410  break;
411  case Language:
412  if (settings.value("language") != value) {
413  settings.setValue("language", value);
414  setRestartRequired(true);
415  }
416  break;
417  case CoinControlFeatures:
418  fCoinControlFeatures = value.toBool();
419  settings.setValue("fCoinControlFeatures", fCoinControlFeatures);
421  break;
422  case Prune:
423  if (settings.value("bPrune") != value) {
424  settings.setValue("bPrune", value);
425  setRestartRequired(true);
426  }
427  break;
428  case PruneSize:
429  if (settings.value("nPruneSize") != value) {
430  settings.setValue("nPruneSize", value);
431  setRestartRequired(true);
432  }
433  break;
434  case DatabaseCache:
435  if (settings.value("nDatabaseCache") != value) {
436  settings.setValue("nDatabaseCache", value);
437  setRestartRequired(true);
438  }
439  break;
440  case ThreadsScriptVerif:
441  if (settings.value("nThreadsScriptVerif") != value) {
442  settings.setValue("nThreadsScriptVerif", value);
443  setRestartRequired(true);
444  }
445  break;
446  case Listen:
447  if (settings.value("fListen") != value) {
448  settings.setValue("fListen", value);
449  setRestartRequired(true);
450  }
451  break;
452  default:
453  break;
454  }
455  }
456 
457  Q_EMIT dataChanged(index, index);
458 
459  return successful;
460 }
461 
463 void OptionsModel::setDisplayUnit(const QVariant &value)
464 {
465  if (!value.isNull())
466  {
467  QSettings settings;
468  nDisplayUnit = value.toInt();
469  settings.setValue("nDisplayUnit", nDisplayUnit);
471  }
472 }
473 
474 bool OptionsModel::getProxySettings(QNetworkProxy& proxy) const
475 {
476  // Directly query current base proxy, because
477  // GUI settings can be overridden with -proxy.
478  proxyType curProxy;
479  if (m_node.getProxy(NET_IPV4, curProxy)) {
480  proxy.setType(QNetworkProxy::Socks5Proxy);
481  proxy.setHostName(QString::fromStdString(curProxy.proxy.ToStringIP()));
482  proxy.setPort(curProxy.proxy.GetPort());
483 
484  return true;
485  }
486  else
487  proxy.setType(QNetworkProxy::NoProxy);
488 
489  return false;
490 }
491 
493 {
494  QSettings settings;
495  return settings.setValue("fRestartRequired", fRequired);
496 }
497 
499 {
500  QSettings settings;
501  return settings.value("fRestartRequired", false).toBool();
502 }
503 
505 {
506  // Migration of default values
507  // Check if the QSettings container was already loaded with this client version
508  QSettings settings;
509  static const char strSettingsVersionKey[] = "nSettingsVersion";
510  int settingsVersion = settings.contains(strSettingsVersionKey) ? settings.value(strSettingsVersionKey).toInt() : 0;
511  if (settingsVersion < CLIENT_VERSION)
512  {
513  // -dbcache was bumped from 100 to 300 in 0.13
514  // see https://github.com/bitcoin/bitcoin/pull/8273
515  // force people to upgrade to the new value if they are using 100MB
516  if (settingsVersion < 130000 && settings.contains("nDatabaseCache") && settings.value("nDatabaseCache").toLongLong() == 100)
517  settings.setValue("nDatabaseCache", (qint64)nDefaultDbCache);
518 
519  settings.setValue(strSettingsVersionKey, CLIENT_VERSION);
520  }
521 
522  // Overwrite the 'addrProxy' setting in case it has been set to an illegal
523  // default value (see issue #12623; PR #12650).
524  if (settings.contains("addrProxy") && settings.value("addrProxy").toString().endsWith("%2")) {
525  settings.setValue("addrProxy", GetDefaultProxyAddress());
526  }
527 
528  // Overwrite the 'addrSeparateProxyTor' setting in case it has been set to an illegal
529  // default value (see issue #12623; PR #12650).
530  if (settings.contains("addrSeparateProxyTor") && settings.value("addrSeparateProxyTor").toString().endsWith("%2")) {
531  settings.setValue("addrSeparateProxyTor", GetDefaultProxyAddress());
532  }
533 }
OptionsModel(interfaces::Node &node, QObject *parent=0, bool resetSettings=false)
unsigned short GetPort() const
Definition: netaddress.cpp:505
bool setData(const QModelIndex &index, const QVariant &value, int role=Qt::EditRole)
void addOverriddenOption(const std::string &option)
void hideTrayIconChanged(bool)
bool getProxySettings(QNetworkProxy &proxy) const
virtual bool getProxy(Network net, proxyType &proxy_info)=0
Get proxy.
QString language
Definition: optionsmodel.h:92
bool GetStartOnSystemStartup()
Definition: guiutil.cpp:752
void coinControlFeaturesChanged(bool)
bool fMinimizeOnClose
Definition: optionsmodel.h:91
bool isRestartRequired() const
static QString getDefaultDataDirectory()
Determine default data directory for operating system.
Definition: intro.cpp:185
interfaces::Node & m_node
Definition: optionsmodel.h:87
void setDisplayUnit(const QVariant &value)
Updates current unit in memory, settings and emits displayUnitChanged(newUnit) signal.
bool fHideTrayIcon
Definition: optionsmodel.h:89
std::string ToStringIP() const
Definition: netaddress.cpp:254
const char * name
Definition: rest.cpp:37
bool fMinimizeToTray
Definition: optionsmodel.h:90
const char * DEFAULT_GUI_PROXY_HOST
void Init(bool resetSettings=false)
void displayUnitChanged(int unit)
bool fCoinControlFeatures
Definition: optionsmodel.h:95
void checkAndMigrate()
ArgsManager gArgs
Definition: util.cpp:88
CService proxy
Definition: netbase.h:36
virtual void mapPort(bool use_upnp)=0
Map port.
void setRestartRequired(bool fRequired)
QString strThirdPartyTxUrls
Definition: optionsmodel.h:94
QVariant data(const QModelIndex &index, int role=Qt::DisplayRole) const
std::string GetArg(const std::string &strArg, const std::string &strDefault) const
Return string argument or default value.
Definition: util.cpp:526
bool SetStartOnSystemStartup(bool fAutoStart)
Definition: guiutil.cpp:753
const fs::path & GetDataDir(bool fNetSpecific)
Definition: util.cpp:766
virtual bool softSetArg(const std::string &arg, const std::string &value)=0
Set a command line argument if it doesn&#39;t already have a value.
QString boostPathToQString(const fs::path &path)
Definition: guiutil.cpp:768
int rowCount(const QModelIndex &parent=QModelIndex()) const
Top-level interface for a bitcoin node (bsha3d process).
Definition: node.h:35
QString strOverriddenByCommandLine
Definition: optionsmodel.h:97
virtual bool softSetBoolArg(const std::string &arg, bool value)=0
Set a command line boolean argument if it doesn&#39;t already have a value.