Improve Tor support
[novacoin.git] / src / qt / optionsmodel.cpp
1 #include "optionsmodel.h"
2 #include "bitcoinunits.h"
3 #include <QSettings>
4
5 #include "init.h"
6 #include "walletdb.h"
7 #include "guiutil.h"
8
9 OptionsModel::OptionsModel(QObject *parent) :
10     QAbstractListModel(parent)
11 {
12     Init();
13 }
14
15 bool static ApplyProxySettings()
16 {
17     QSettings settings;
18     CService addrProxy(settings.value("addrProxy", "127.0.0.1:9050").toString().toStdString());
19     int nSocksVersion(settings.value("nSocksVersion", 5).toInt());
20     if (!settings.value("fUseProxy", false).toBool()) {
21         addrProxy = CService();
22         nSocksVersion = 0;
23         return false;
24     }
25     if (nSocksVersion && !addrProxy.IsValid())
26         return false;
27
28     if (!IsLimited(NET_IPV4))
29         SetProxy(NET_IPV4, addrProxy, nSocksVersion);
30     if (nSocksVersion > 4) {
31 #ifdef USE_IPV6
32         if (!IsLimited(NET_IPV6))
33             SetProxy(NET_IPV6, addrProxy, nSocksVersion);
34 #endif
35     }
36
37     SetNameProxy(addrProxy, nSocksVersion);
38
39     return true;
40 }
41
42 bool static ApplyTorSettings()
43 {
44     QSettings settings;
45     CService addrTor(settings.value("addrTor", "127.0.0.1:9050").toString().toStdString());
46     if (!settings.value("fUseTor", false).toBool()) {
47         addrTor = CService();
48         return false;
49     }
50     if (!addrTor.IsValid())
51         return false;
52
53     SetProxy(NET_TOR, addrTor, 5);
54     SetReachable(NET_TOR);
55
56     return true;
57 }
58
59 void OptionsModel::Init()
60 {
61     QSettings settings;
62
63     // These are Qt-only settings:
64     nDisplayUnit = settings.value("nDisplayUnit", BitcoinUnits::BTC).toInt();
65     bDisplayAddresses = settings.value("bDisplayAddresses", false).toBool();
66     if (!settings.contains("strThirdPartyTxUrls")) {
67         if(fTestNet)
68             settings.setValue("strThirdPartyTxUrls", "");
69         else
70             settings.setValue("strThirdPartyTxUrls", "https://bitinfocharts.com/novacoin/tx/%s|https://coinplorer.com/NVC/Transactions/%s|https://explorer.novaco.in/tx/%s|https://bchain.info/NVC/tx/%s");
71     }
72     strThirdPartyTxUrls = settings.value("strThirdPartyTxUrls", "https://bitinfocharts.com/novacoin/tx/%s|https://coinplorer.com/NVC/Transactions/%s|https://explorer.novaco.in/tx/%s|https://bchain.info/NVC/tx/%s").toString();
73     fMinimizeToTray = settings.value("fMinimizeToTray", false).toBool();
74     fMinimizeOnClose = settings.value("fMinimizeOnClose", false).toBool();
75     fCoinControlFeatures = settings.value("fCoinControlFeatures", false).toBool();
76     nTransactionFee = settings.value("nTransactionFee").toLongLong();
77     language = settings.value("language", "").toString();
78
79     // These are shared with core Bitcoin; we want
80     // command-line options to override the GUI settings:
81     if (settings.contains("fUseUPnP"))
82         SoftSetBoolArg("-upnp", settings.value("fUseUPnP").toBool());
83     if ( !(settings.value("fTorOnly").toBool() && settings.contains("addrTor")) ) {
84         if (settings.contains("addrProxy") && settings.value("fUseProxy").toBool())
85             SoftSetArg("-proxy", settings.value("addrProxy").toString().toStdString());
86         if (settings.contains("nSocksVersion") && settings.value("fUseProxy").toBool())
87             SoftSetArg("-socks", settings.value("nSocksVersion").toString().toStdString());
88     }
89
90     if (settings.contains("addrTor") && settings.value("fUseTor").toBool()) {
91         SoftSetArg("-tor", settings.value("addrTor").toString().toStdString());
92         if (settings.value("fTorOnly").toBool())
93             SoftSetArg("-onlynet", "tor");
94     }
95
96     if (settings.contains("detachDB"))
97         SoftSetBoolArg("-detachdb", settings.value("detachDB").toBool());
98     if (!language.isEmpty())
99         SoftSetArg("-lang", language.toStdString());
100 }
101
102 bool OptionsModel::Upgrade()
103 {
104     QSettings settings;
105
106     if (settings.contains("bImportFinished"))
107         return false; // Already upgraded
108
109     settings.setValue("bImportFinished", true);
110
111     // Move settings from old wallet.dat (if any):
112     CWalletDB walletdb(strWalletFileName);
113
114     QList<QString> intOptions;
115     intOptions << "nDisplayUnit" << "nTransactionFee";
116     foreach(QString key, intOptions)
117     {
118         int value = 0;
119         if (walletdb.ReadSetting(key.toStdString(), value))
120         {
121             settings.setValue(key, value);
122             walletdb.EraseSetting(key.toStdString());
123         }
124     }
125     QList<QString> boolOptions;
126     boolOptions << "bDisplayAddresses" << "fMinimizeToTray" << "fMinimizeOnClose" << "fUseProxy" << "fUseTor" << "fTorOnly" << "fUseUPnP";
127     foreach(QString key, boolOptions)
128     {
129         bool value = false;
130         if (walletdb.ReadSetting(key.toStdString(), value))
131         {
132             settings.setValue(key, value);
133             walletdb.EraseSetting(key.toStdString());
134         }
135     }
136     try
137     {
138         CAddress addrProxyAddress, addrTorAddress;
139         if (walletdb.ReadSetting("addrProxy", addrProxyAddress))
140         {
141             settings.setValue("addrProxy", addrProxyAddress.ToStringIPPort().c_str());
142             walletdb.EraseSetting("addrProxy");
143         }
144
145         if (walletdb.ReadSetting("addrTor", addrTorAddress))
146         {
147             settings.setValue("addrTor", addrTorAddress.ToStringIPPort().c_str());
148             walletdb.EraseSetting("addrTor");
149         }
150     }
151     catch (std::ios_base::failure &e)
152     {
153         // 0.6.0rc1 saved this as a CService, which causes failure when parsing as a CAddress
154         CService addrProxy, addrTor;
155         if (walletdb.ReadSetting("addrProxy", addrProxy))
156         {
157             settings.setValue("addrProxy", addrProxy.ToStringIPPort().c_str());
158             walletdb.EraseSetting("addrProxy");
159         }
160
161         if (walletdb.ReadSetting("addrTor", addrTor))
162         {
163             settings.setValue("addrTor", addrTor.ToStringIPPort().c_str());
164             walletdb.EraseSetting("addrTor");
165         }
166     }
167
168     ApplyProxySettings();
169     ApplyTorSettings();
170     Init();
171
172     return true;
173 }
174
175
176 int OptionsModel::rowCount(const QModelIndex & parent) const
177 {
178     return OptionIDRowCount;
179 }
180
181 QVariant OptionsModel::data(const QModelIndex & index, int role) const
182 {
183     if(role == Qt::EditRole)
184     {
185         QSettings settings;
186         switch(index.row())
187         {
188         case StartAtStartup:
189             return QVariant(GUIUtil::GetStartOnSystemStartup());
190         case MinimizeToTray:
191             return QVariant(fMinimizeToTray);
192         case MapPortUPnP:
193             return settings.value("fUseUPnP", GetBoolArg("-upnp", true));
194         case MinimizeOnClose:
195             return QVariant(fMinimizeOnClose);
196         case ProxyUse:
197             return settings.value("fUseProxy", false);
198         case ProxyIP: {
199             proxyType proxy;
200             if (GetProxy(NET_IPV4, proxy))
201                 return QVariant(QString::fromStdString(proxy.first.ToStringIP()));
202             else
203                 return QVariant(QString::fromStdString("127.0.0.1"));
204         }
205         case ProxyPort: {
206             proxyType proxy;
207             if (GetProxy(NET_IPV4, proxy))
208                 return QVariant(proxy.first.GetPort());
209             else
210                 return QVariant(9050);
211         }
212         case ProxySocksVersion:
213             return settings.value("nSocksVersion", 5);
214         case TorUse:
215             return settings.value("fUseTor", false);
216         case TorIP: {
217             proxyType proxy;
218             if (GetProxy(NET_TOR, proxy))
219                 return QVariant(QString::fromStdString(proxy.first.ToStringIP()));
220             else
221                 return QVariant(QString::fromStdString("127.0.0.1"));
222         }
223         case TorPort: {
224             proxyType proxy;
225             if (GetProxy(NET_TOR, proxy))
226                 return QVariant(proxy.first.GetPort());
227             else
228                 return QVariant(9050);
229         }
230         case TorOnly:
231             return settings.value("fTorOnly", false);
232         case Fee:
233             return QVariant(static_cast<qlonglong>(nTransactionFee));
234         case DisplayUnit:
235             return QVariant(nDisplayUnit);
236         case DisplayAddresses:
237             return QVariant(bDisplayAddresses);
238         case ThirdPartyTxUrls:
239             return QVariant(strThirdPartyTxUrls);
240         case DetachDatabases:
241             return QVariant(bitdb.GetDetach());
242         case Language:
243             return settings.value("language", "");
244         case CoinControlFeatures:
245             return QVariant(fCoinControlFeatures);
246         default:
247             return QVariant();
248         }
249     }
250     return QVariant();
251 }
252
253 bool OptionsModel::setData(const QModelIndex & index, const QVariant & value, int role)
254 {
255     bool successful = true; /* set to false on parse error */
256     if(role == Qt::EditRole)
257     {
258         QSettings settings;
259         switch(index.row())
260         {
261         case StartAtStartup:
262             successful = GUIUtil::SetStartOnSystemStartup(value.toBool());
263             break;
264         case MinimizeToTray:
265             fMinimizeToTray = value.toBool();
266             settings.setValue("fMinimizeToTray", fMinimizeToTray);
267             break;
268         case MapPortUPnP:
269             fUseUPnP = value.toBool();
270             settings.setValue("fUseUPnP", fUseUPnP);
271             MapPort();
272             break;
273         case MinimizeOnClose:
274             fMinimizeOnClose = value.toBool();
275             settings.setValue("fMinimizeOnClose", fMinimizeOnClose);
276             break;
277         case ProxyUse:
278             settings.setValue("fUseProxy", value.toBool());
279             ApplyProxySettings();
280             break;
281         case ProxyIP: {
282             proxyType proxy;
283             proxy.first = CService("127.0.0.1", 9050);
284             GetProxy(NET_IPV4, proxy);
285
286             CNetAddr addr(value.toString().toStdString());
287             proxy.first.SetIP(addr);
288             settings.setValue("addrProxy", proxy.first.ToStringIPPort().c_str());
289             successful = ApplyProxySettings();
290         }
291         break;
292         case ProxyPort: {
293             proxyType proxy;
294             proxy.first = CService("127.0.0.1", 9050);
295             GetProxy(NET_IPV4, proxy);
296
297             proxy.first.SetPort(value.toInt());
298             settings.setValue("addrProxy", proxy.first.ToStringIPPort().c_str());
299             successful = ApplyProxySettings();
300         }
301         break;
302         case ProxySocksVersion: {
303             proxyType proxy;
304             proxy.second = 5;
305             GetProxy(NET_IPV4, proxy);
306
307             proxy.second = value.toInt();
308             settings.setValue("nSocksVersion", proxy.second);
309             successful = ApplyProxySettings();
310         }
311         break;
312         case TorUse: {
313             settings.setValue("fUseTor", value.toBool());
314             ApplyTorSettings();
315         }
316         break;
317         case TorIP: {
318             proxyType proxy;
319             proxy.first = CService("127.0.0.1", 9050);
320             GetProxy(NET_IPV4, proxy);
321
322             CNetAddr addr(value.toString().toStdString());
323             proxy.first.SetIP(addr);
324             settings.setValue("addrTor", proxy.first.ToStringIPPort().c_str());
325             successful = ApplyTorSettings();
326         }
327         break;
328         case TorPort: {
329             proxyType proxy;
330             proxy.first = CService("127.0.0.1", 9050);
331             GetProxy(NET_IPV4, proxy);
332
333             proxy.first.SetPort(value.toInt());
334             settings.setValue("addrTor", proxy.first.ToStringIPPort().c_str());
335             successful = ApplyTorSettings();
336         }
337         break;
338         case TorOnly: {
339             settings.setValue("fTorOnly", value.toBool());
340             ApplyTorSettings();
341         }
342         break;
343         case Fee:
344             nTransactionFee = value.toLongLong();
345             settings.setValue("nTransactionFee", static_cast<qlonglong>(nTransactionFee));
346             emit transactionFeeChanged(nTransactionFee);
347             break;
348         case DisplayUnit:
349             nDisplayUnit = value.toInt();
350             settings.setValue("nDisplayUnit", nDisplayUnit);
351             emit displayUnitChanged(nDisplayUnit);
352             break;
353         case DisplayAddresses:
354             bDisplayAddresses = value.toBool();
355             settings.setValue("bDisplayAddresses", bDisplayAddresses);
356             break;
357         case DetachDatabases: {
358             bool fDetachDB = value.toBool();
359             bitdb.SetDetach(fDetachDB);
360             settings.setValue("detachDB", fDetachDB);
361             }
362             break;
363         case ThirdPartyTxUrls:
364             if (strThirdPartyTxUrls != value.toString()) {
365                 strThirdPartyTxUrls = value.toString();
366                 settings.setValue("strThirdPartyTxUrls", strThirdPartyTxUrls);
367             }
368             break;
369         case Language:
370             settings.setValue("language", value);
371             break;
372         case CoinControlFeatures: {
373             fCoinControlFeatures = value.toBool();
374             settings.setValue("fCoinControlFeatures", fCoinControlFeatures);
375             emit coinControlFeaturesChanged(fCoinControlFeatures);
376             }
377             break;
378         default:
379             break;
380         }
381     }
382     emit dataChanged(index, index);
383
384     return successful;
385 }
386
387 qint64 OptionsModel::getTransactionFee()
388 {
389     return nTransactionFee;
390 }
391
392 bool OptionsModel::getCoinControlFeatures()
393 {
394     return fCoinControlFeatures;
395 }
396
397 bool OptionsModel::getMinimizeToTray()
398 {
399     return fMinimizeToTray;
400 }
401
402 bool OptionsModel::getMinimizeOnClose()
403 {
404     return fMinimizeOnClose;
405 }
406
407 int OptionsModel::getDisplayUnit()
408 {
409     return nDisplayUnit;
410 }
411
412 bool OptionsModel::getDisplayAddresses()
413 {
414     return bDisplayAddresses;
415 }