// Copyright (c) 2011-2013 The Bitcoin developers // Distributed under the MIT/X11 software license, see the accompanying // file COPYING or http://www.opensource.org/licenses/mit-license.php. #if defined(HAVE_CONFIG_H) #include "bitcoin-config.h" #endif #include "optionsmodel.h" #include "bitcoinunits.h" #include "guiutil.h" #include "init.h" #include "main.h" #include "net.h" #ifdef ENABLE_WALLET #include "wallet.h" #include "walletdb.h" #endif #include #include #include OptionsModel::OptionsModel(QObject *parent) : QAbstractListModel(parent) { Init(); } // Writes all missing QSettings with their default values void OptionsModel::Init() { QSettings settings; // Ensure restart flag is unset on client startup setRestartRequired(false); // These are Qt-only settings: // Window if (!settings.contains("fMinimizeToTray")) settings.setValue("fMinimizeToTray", false); fMinimizeToTray = settings.value("fMinimizeToTray").toBool(); if (!settings.contains("fMinimizeOnClose")) settings.setValue("fMinimizeOnClose", false); fMinimizeOnClose = settings.value("fMinimizeOnClose").toBool(); // Display if (!settings.contains("nDisplayUnit")) settings.setValue("nDisplayUnit", BitcoinUnits::BTC); nDisplayUnit = settings.value("nDisplayUnit").toInt(); if (!settings.contains("bDisplayAddresses")) settings.setValue("bDisplayAddresses", false); bDisplayAddresses = settings.value("bDisplayAddresses", false).toBool(); if (!settings.contains("fCoinControlFeatures")) settings.setValue("fCoinControlFeatures", false); fCoinControlFeatures = settings.value("fCoinControlFeatures", false).toBool(); // These are shared with the core or have a command-line parameter // and we want command-line parameters to overwrite the GUI settings. // // If setting doesn't exist create it with defaults. // // If SoftSetArg() or SoftSetBoolArg() return false we were overridden // by command-line and show this in the UI. // Main #ifdef ENABLE_WALLET if (!settings.contains("nTransactionFee")) settings.setValue("nTransactionFee", 0); #endif if (!settings.contains("nDatabaseCache")) settings.setValue("nDatabaseCache", 25); if (!SoftSetArg("-dbcache", settings.value("nDatabaseCache").toString().toStdString())) strOverriddenByCommandLine += "-dbcache "; if (!settings.contains("nThreadsScriptVerif")) settings.setValue("nThreadsScriptVerif", 0); if (!SoftSetArg("-par", settings.value("nThreadsScriptVerif").toString().toStdString())) strOverriddenByCommandLine += "-par "; // Network if (!settings.contains("fUseUPnP")) #ifdef USE_UPNP settings.setValue("fUseUPnP", true); #else settings.setValue("fUseUPnP", false); #endif if (!SoftSetBoolArg("-upnp", settings.value("fUseUPnP").toBool())) strOverriddenByCommandLine += "-upnp "; if (!settings.contains("fUseProxy")) settings.setValue("fUseProxy", false); if (!settings.contains("addrProxy")) settings.setValue("addrProxy", "127.0.0.1:9050"); // Only try to set -proxy, if user has enabled fUseProxy if (settings.value("fUseProxy").toBool() && !SoftSetArg("-proxy", settings.value("addrProxy").toString().toStdString())) strOverriddenByCommandLine += "-proxy "; if (!settings.contains("nSocksVersion")) settings.setValue("nSocksVersion", 5); // Only try to set -socks, if user has enabled fUseProxy if (settings.value("fUseProxy").toBool() && !SoftSetArg("-socks", settings.value("nSocksVersion").toString().toStdString())) strOverriddenByCommandLine += "-socks "; // Display if (!settings.contains("language")) settings.setValue("language", ""); if (!SoftSetArg("-lang", settings.value("language").toString().toStdString())) strOverriddenByCommandLine += "-lang"; language = settings.value("language").toString(); } void OptionsModel::Reset() { QSettings settings; // Remove all entries from our QSettings object settings.clear(); // default setting for OptionsModel::StartAtStartup - disabled if (GUIUtil::GetStartOnSystemStartup()) GUIUtil::SetStartOnSystemStartup(false); // Ensure Upgrade() is not running again by setting the bImportFinished flag settings.setValue("bImportFinished", true); } void OptionsModel::Upgrade() { QSettings settings; // Already upgraded if (settings.contains("bImportFinished")) return; settings.setValue("bImportFinished", true); #ifdef ENABLE_WALLET // Move settings from old wallet.dat (if any): CWalletDB walletdb(strWalletFile); QList intOptions; intOptions << "nDisplayUnit" << "nTransactionFee"; foreach(QString key, intOptions) { int value = 0; if (walletdb.ReadSetting(key.toStdString(), value)) { settings.setValue(key, value); walletdb.EraseSetting(key.toStdString()); } } QList boolOptions; boolOptions << "bDisplayAddresses" << "fMinimizeToTray" << "fMinimizeOnClose" << "fUseProxy" << "fUseUPnP"; foreach(QString key, boolOptions) { bool value = false; if (walletdb.ReadSetting(key.toStdString(), value)) { settings.setValue(key, value); walletdb.EraseSetting(key.toStdString()); } } try { CAddress addrProxyAddress; if (walletdb.ReadSetting("addrProxy", addrProxyAddress)) { settings.setValue("addrProxy", addrProxyAddress.ToStringIPPort().c_str()); walletdb.EraseSetting("addrProxy"); } } catch (std::ios_base::failure &e) { // 0.6.0rc1 saved this as a CService, which causes failure when parsing as a CAddress CService addrProxy; if (walletdb.ReadSetting("addrProxy", addrProxy)) { settings.setValue("addrProxy", addrProxy.ToStringIPPort().c_str()); walletdb.EraseSetting("addrProxy"); } } #endif Init(); } int OptionsModel::rowCount(const QModelIndex & parent) const { return OptionIDRowCount; } // read QSettings values and return them QVariant OptionsModel::data(const QModelIndex & index, int role) const { if(role == Qt::EditRole) { QSettings settings; switch(index.row()) { case StartAtStartup: return GUIUtil::GetStartOnSystemStartup(); case MinimizeToTray: return fMinimizeToTray; case MapPortUPnP: #ifdef USE_UPNP return settings.value("fUseUPnP"); #else return false; #endif case MinimizeOnClose: return fMinimizeOnClose; // default proxy case ProxyUse: return settings.value("fUseProxy", false); case ProxyIP: { // contains IP at index 0 and port at index 1 QStringList strlIpPort = settings.value("addrProxy").toString().split(":", QString::SkipEmptyParts); return strlIpPort.at(0); } case ProxyPort: { // contains IP at index 0 and port at index 1 QStringList strlIpPort = settings.value("addrProxy").toString().split(":", QString::SkipEmptyParts); return strlIpPort.at(1); } case ProxySocksVersion: return settings.value("nSocksVersion", 5); #ifdef ENABLE_WALLET case Fee: // Attention: Init() is called before nTransactionFee is set in AppInit2()! // To ensure we can change the fee on-the-fly update our QSetting when // opening OptionsDialog, which queries Fee via the mapper. if (nTransactionFee != settings.value("nTransactionFee").toLongLong()) settings.setValue("nTransactionFee", (qint64)nTransactionFee); // Todo: Consider to revert back to use just nTransactionFee here, if we don't want // -paytxfee to update our QSettings! return settings.value("nTransactionFee"); #endif case DisplayUnit: return nDisplayUnit; case DisplayAddresses: return bDisplayAddresses; case Language: return settings.value("language"); case CoinControlFeatures: return fCoinControlFeatures; case DatabaseCache: return settings.value("nDatabaseCache"); case ThreadsScriptVerif: return settings.value("nThreadsScriptVerif"); default: return QVariant(); } } return QVariant(); } // write QSettings values bool OptionsModel::setData(const QModelIndex & index, const QVariant & value, int role) { bool successful = true; /* set to false on parse error */ if(role == Qt::EditRole) { QSettings settings; switch(index.row()) { case StartAtStartup: successful = GUIUtil::SetStartOnSystemStartup(value.toBool()); break; case MinimizeToTray: fMinimizeToTray = value.toBool(); settings.setValue("fMinimizeToTray", fMinimizeToTray); break; case MapPortUPnP: // core option - can be changed on-the-fly settings.setValue("fUseUPnP", value.toBool()); MapPort(value.toBool()); break; case MinimizeOnClose: fMinimizeOnClose = value.toBool(); settings.setValue("fMinimizeOnClose", fMinimizeOnClose); break; // default proxy case ProxyUse: if (settings.value("fUseProxy") != value) { settings.setValue("fUseProxy", value.toBool()); setRestartRequired(true); } break; case ProxyIP: { // contains current IP at index 0 and current port at index 1 QStringList strlIpPort = settings.value("addrProxy").toString().split(":", QString::SkipEmptyParts); // if that key doesn't exist or has a changed IP if (!settings.contains("addrProxy") || strlIpPort.at(0) != value.toString()) { // construct new value from new IP and current port QString strNewValue = value.toString() + ":" + strlIpPort.at(1); settings.setValue("addrProxy", strNewValue); setRestartRequired(true); } } break; case ProxyPort: { // contains current IP at index 0 and current port at index 1 QStringList strlIpPort = settings.value("addrProxy").toString().split(":", QString::SkipEmptyParts); // if that key doesn't exist or has a changed port if (!settings.contains("addrProxy") || strlIpPort.at(1) != value.toString()) { // construct new value from current IP and new port QString strNewValue = strlIpPort.at(0) + ":" + value.toString(); settings.setValue("addrProxy", strNewValue); setRestartRequired(true); } } break; case ProxySocksVersion: { if (settings.value("nSocksVersion") != value) { settings.setValue("nSocksVersion", value.toInt()); setRestartRequired(true); } } break; #ifdef ENABLE_WALLET case Fee: // core option - can be changed on-the-fly // Todo: Add is valid check and warn via message, if not nTransactionFee = value.toLongLong(); settings.setValue("nTransactionFee", (qint64)nTransactionFee); emit transactionFeeChanged(nTransactionFee); break; #endif case DisplayUnit: nDisplayUnit = value.toInt(); settings.setValue("nDisplayUnit", nDisplayUnit); emit displayUnitChanged(nDisplayUnit); break; case DisplayAddresses: bDisplayAddresses = value.toBool(); settings.setValue("bDisplayAddresses", bDisplayAddresses); break; case Language: if (settings.value("language") != value) { settings.setValue("language", value); setRestartRequired(true); } break; case CoinControlFeatures: fCoinControlFeatures = value.toBool(); settings.setValue("fCoinControlFeatures", fCoinControlFeatures); emit coinControlFeaturesChanged(fCoinControlFeatures); break; case DatabaseCache: if (settings.value("nDatabaseCache") != value) { settings.setValue("nDatabaseCache", value); setRestartRequired(true); } break; case ThreadsScriptVerif: if (settings.value("nThreadsScriptVerif") != value) { settings.setValue("nThreadsScriptVerif", value); setRestartRequired(true); } break; default: break; } } emit dataChanged(index, index); return successful; } bool OptionsModel::getProxySettings(QNetworkProxy& proxy) const { // Directly query current base proxy, because // GUI settings can be overridden with -proxy. proxyType curProxy; if (GetProxy(NET_IPV4, curProxy)) { if (curProxy.second == 5) { proxy.setType(QNetworkProxy::Socks5Proxy); proxy.setHostName(QString::fromStdString(curProxy.first.ToStringIP())); proxy.setPort(curProxy.first.GetPort()); return true; } else return false; } else proxy.setType(QNetworkProxy::NoProxy); return true; } void OptionsModel::setRestartRequired(bool fRequired) { QSettings settings; return settings.setValue("fRestartRequired", fRequired); } bool OptionsModel::isRestartRequired() { QSettings settings; return settings.value("fRestartRequired", false).toBool(); }