Reworked QT settings
authorGavin Andresen <gavinandresen@gmail.com>
Fri, 17 Feb 2012 02:09:41 +0000 (21:09 -0500)
committerPieter Wuille <pieter.wuille@gmail.com>
Sun, 26 Feb 2012 22:38:28 +0000 (23:38 +0100)
src/init.cpp
src/qt/bitcoin.cpp
src/qt/optionsmodel.cpp
src/qt/optionsmodel.h
src/util.cpp
src/util.h

index b701e90..a9d9eb7 100644 (file)
@@ -150,27 +150,15 @@ bool AppInit2(int argc, char* argv[])
     //
     // Parameters
     //
-    // If Qt is used, parameters are parsed in qt/bitcoin.cpp's main()
+    // If Qt is used, parameters/bitcoin.conf are parsed in qt/bitcoin.cpp's main()
 #if !defined(QT_GUI)
     ParseParameters(argc, argv);
-#endif
-
-    if (mapArgs.count("-datadir"))
+    if (!ReadConfigFile(mapArgs, mapMultiArgs))
     {
-        if (filesystem::is_directory(filesystem::system_complete(mapArgs["-datadir"])))
-        {
-            filesystem::path pathDataDir = filesystem::system_complete(mapArgs["-datadir"]);
-            strlcpy(pszSetDataDir, pathDataDir.string().c_str(), sizeof(pszSetDataDir));
-        }
-        else
-        {
-            fprintf(stderr, "Error: Specified directory does not exist\n");
-            Shutdown(NULL);
-        }
+        fprintf(stderr, "Error: Specified directory does not exist\n");
+        Shutdown(NULL);
     }
-
-
-    ReadConfigFile(mapArgs, mapMultiArgs); // Must be done after processing datadir
+#endif
 
     if (mapArgs.count("-?") || mapArgs.count("--help"))
     {
index 03b89f0..5e79f6e 100644 (file)
@@ -152,8 +152,28 @@ int main(int argc, char *argv[])
     Q_INIT_RESOURCE(bitcoin);
     QApplication app(argc, argv);
 
+    // Command-line options take precedence:
     ParseParameters(argc, argv);
 
+    // ... then bitcoin.conf:
+    if (!ReadConfigFile(mapArgs, mapMultiArgs))
+    {
+        fprintf(stderr, "Error: Specified directory does not exist\n");
+        return 1;
+    }
+
+    // Application identification (must be set before OptionsModel is initialized,
+    // as it is used to locate QSettings)
+    app.setOrganizationName("Bitcoin");
+    app.setOrganizationDomain("bitcoin.org");
+    if(GetBoolArg("-testnet")) // Separate UI settings for testnet
+        app.setApplicationName("Bitcoin-Qt-testnet");
+    else
+        app.setApplicationName("Bitcoin-Qt");
+
+    // ... then GUI settings:
+    OptionsModel optionsModel;
+
     // Get desired locale ("en_US") from command line or system locale
     QString lang_territory = QString::fromStdString(GetArg("-lang", QLocale::system().name().toStdString()));
     // Load language files for configured locale:
@@ -180,8 +200,6 @@ int main(int argc, char *argv[])
     if (!translator.isEmpty())
         app.installTranslator(&translator);
 
-    app.setApplicationName(QApplication::translate("main", "Bitcoin-Qt"));
-
     QSplashScreen splash(QPixmap(":/images/splash"), 0);
     if (GetBoolArg("-splash", true) && !GetBoolArg("-min"))
     {
@@ -201,10 +219,13 @@ int main(int argc, char *argv[])
             {
                 // Put this in a block, so that BitcoinGUI is cleaned up properly before
                 // calling Shutdown() in case of exceptions.
+
+                optionsModel.Upgrade(); // Must be done after AppInit2
+
                 BitcoinGUI window;
                 if (splashref)
                     splash.finish(&window);
-                OptionsModel optionsModel(pwalletMain);
+
                 ClientModel clientModel(&optionsModel);
                 WalletModel walletModel(pwalletMain, &optionsModel);
 
index dd69093..417e2b8 100644 (file)
@@ -1,21 +1,94 @@
 #include "optionsmodel.h"
 #include "bitcoinunits.h"
+#include <QSettings>
 
 #include "headers.h"
 #include "init.h"
 
-OptionsModel::OptionsModel(CWallet *wallet, QObject *parent) :
-    QAbstractListModel(parent),
-    wallet(wallet),
-    nDisplayUnit(BitcoinUnits::BTC),
-    bDisplayAddresses(false)
+OptionsModel::OptionsModel(QObject *parent) :
+    QAbstractListModel(parent)
 {
-    // Read our specific settings from the wallet db
-    CWalletDB walletdb(wallet->strWalletFile);
-    walletdb.ReadSetting("nDisplayUnit", nDisplayUnit);
-    walletdb.ReadSetting("bDisplayAddresses", bDisplayAddresses);
+    Init();
 }
 
+void OptionsModel::Init()
+{
+    QSettings settings;
+
+    // These are QT-only settings:
+    nDisplayUnit = settings.value("nDisplayUnit", BitcoinUnits::BTC).toInt();
+    bDisplayAddresses = settings.value("bDisplayAddresses", false).toBool();
+    fMinimizeToTray = settings.value("fMinimizeToTray", false).toBool();
+    fMinimizeOnClose = settings.value("fMinimizeOnClose", false).toBool();
+    nTransactionFee = settings.value("nTransactionFee").toLongLong();
+
+    // These are shared with core bitcoin; we want
+    // command-line options to override the GUI settings:
+    if (settings.contains("fUseUPnP"))
+        SoftSetBoolArg("-upnp", settings.value("fUseUPnP").toBool());
+    if (settings.contains("addrProxy") && settings.value("fUseProxy").toBool())
+        SoftSetArg("-proxy", settings.value("addrProxy").toString().toStdString());
+}
+
+bool OptionsModel::Upgrade()
+{
+    QSettings settings;
+
+    if (settings.contains("bImportFinished"))
+        return false; // Already upgraded
+
+    settings.setValue("bImportFinished", true);
+
+    // Move settings from old wallet.dat (if any):
+    CWalletDB walletdb("wallet.dat");
+
+    QList<QString> 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<QString> 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))
+        {
+            addrProxy = addrProxyAddress;
+            settings.setValue("addrProxy", addrProxy.ToStringIP().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
+        if (walletdb.ReadSetting("addrProxy", addrProxy))
+        {
+            settings.setValue("addrProxy", addrProxy.ToStringIP().c_str());
+            walletdb.EraseSetting("addrProxy");
+        }
+    }
+    Init();
+
+    return true;
+}
+
+
 int OptionsModel::rowCount(const QModelIndex & parent) const
 {
     return OptionIDRowCount;
@@ -25,6 +98,7 @@ QVariant OptionsModel::data(const QModelIndex & index, int role) const
 {
     if(role == Qt::EditRole)
     {
+        QSettings settings;
         switch(index.row())
         {
         case StartAtStartup:
@@ -32,11 +106,11 @@ QVariant OptionsModel::data(const QModelIndex & index, int role) const
         case MinimizeToTray:
             return QVariant(fMinimizeToTray);
         case MapPortUPnP:
-            return QVariant(fUseUPnP);
+            return settings.value("fUseUPnP", GetBoolArg("-upnp", true));
         case MinimizeOnClose:
             return QVariant(fMinimizeOnClose);
         case ConnectSOCKS4:
-            return QVariant(fUseProxy);
+            return settings.value("fUseProxy", false);
         case ProxyIP:
             return QVariant(QString::fromStdString(addrProxy.ToStringIP()));
         case ProxyPort:
@@ -59,7 +133,7 @@ bool OptionsModel::setData(const QModelIndex & index, const QVariant & value, in
     bool successful = true; /* set to false on parse error */
     if(role == Qt::EditRole)
     {
-        CWalletDB walletdb(wallet->strWalletFile);
+        QSettings settings;
         switch(index.row())
         {
         case StartAtStartup:
@@ -67,22 +141,22 @@ bool OptionsModel::setData(const QModelIndex & index, const QVariant & value, in
             break;
         case MinimizeToTray:
             fMinimizeToTray = value.toBool();
-            walletdb.WriteSetting("fMinimizeToTray", fMinimizeToTray);
+            settings.setValue("fMinimizeToTray", fMinimizeToTray);
             break;
         case MapPortUPnP:
-            fUseUPnP = value.toBool();
-            walletdb.WriteSetting("fUseUPnP", fUseUPnP);
-#ifdef USE_UPNP
-            MapPort(fUseUPnP);
-#endif
+            {
+                bool bUseUPnP = value.toBool();
+                settings.setValue("fUseUPnP", bUseUPnP);
+                MapPort(bUseUPnP);
+            }
             break;
         case MinimizeOnClose:
             fMinimizeOnClose = value.toBool();
-            walletdb.WriteSetting("fMinimizeOnClose", fMinimizeOnClose);
+            settings.setValue("fMinimizeOnClose", fMinimizeOnClose);
             break;
         case ConnectSOCKS4:
             fUseProxy = value.toBool();
-            walletdb.WriteSetting("fUseProxy", fUseProxy);
+            settings.setValue("fUseProxy", fUseProxy);
             break;
         case ProxyIP:
             {
@@ -91,7 +165,7 @@ bool OptionsModel::setData(const QModelIndex & index, const QVariant & value, in
                 if (addr.IsValid())
                 {
                     addrProxy.SetIP(addr);
-                    walletdb.WriteSetting("addrProxy", CAddress(addrProxy));
+                    settings.setValue("addrProxy", addrProxy.ToStringIP().c_str());
                 }
                 else
                 {
@@ -105,7 +179,7 @@ bool OptionsModel::setData(const QModelIndex & index, const QVariant & value, in
                 if (nPort > 0 && nPort < std::numeric_limits<unsigned short>::max())
                 {
                     addrProxy.SetPort(nPort);
-                    walletdb.WriteSetting("addrProxy", CAddress(addrProxy));
+                    settings.setValue("addrProxy", addrProxy.ToStringIP().c_str());
                 }
                 else
                 {
@@ -115,18 +189,18 @@ bool OptionsModel::setData(const QModelIndex & index, const QVariant & value, in
             break;
         case Fee: {
             nTransactionFee = value.toLongLong();
-            walletdb.WriteSetting("nTransactionFee", nTransactionFee);
+            settings.setValue("nTransactionFee", nTransactionFee);
             }
             break;
         case DisplayUnit: {
             int unit = value.toInt();
             nDisplayUnit = unit;
-            walletdb.WriteSetting("nDisplayUnit", nDisplayUnit);
+            settings.setValue("nDisplayUnit", nDisplayUnit);
             emit displayUnitChanged(unit);
             }
         case DisplayAddresses: {
             bDisplayAddresses = value.toBool();
-            walletdb.WriteSetting("bDisplayAddresses", bDisplayAddresses);
+            settings.setValue("bDisplayAddresses", bDisplayAddresses);
             }
         default:
             break;
index 775362d..0be70f8 100644 (file)
@@ -3,8 +3,6 @@
 
 #include <QAbstractListModel>
 
-class CWallet;
-
 /** Interface from QT to configuration data structure for bitcoin client.
    To QT, the options are presented as a list with the different options
    laid out vertically.
@@ -15,7 +13,7 @@ class OptionsModel : public QAbstractListModel
 {
     Q_OBJECT
 public:
-    explicit OptionsModel(CWallet *wallet, QObject *parent = 0);
+    explicit OptionsModel(QObject *parent = 0);
 
     enum OptionID {
         StartAtStartup, // bool
@@ -31,6 +29,11 @@ public:
         OptionIDRowCount
     };
 
+    void Init();
+
+    /* Migrate settings from wallet.dat after app initialization */
+    bool Upgrade(); /* returns true if settings upgraded */
+
     int rowCount(const QModelIndex & parent = QModelIndex()) const;
     QVariant data(const QModelIndex & index, int role = Qt::DisplayRole) const;
     bool setData(const QModelIndex & index, const QVariant & value, int role = Qt::EditRole);
@@ -42,10 +45,10 @@ public:
     int getDisplayUnit();
     bool getDisplayAddresses();
 private:
-    // Wallet stores persistent options
-    CWallet *wallet;
     int nDisplayUnit;
     bool bDisplayAddresses;
+    bool fMinimizeToTray;
+    bool fMinimizeOnClose;
 signals:
     void displayUnitChanged(int unit);
 
index f1af91d..88d70cd 100644 (file)
@@ -908,15 +908,28 @@ string GetConfigFile()
     return pathConfig.string();
 }
 
-void ReadConfigFile(map<string, string>& mapSettingsRet,
+bool ReadConfigFile(map<string, string>& mapSettingsRet,
                     map<string, vector<string> >& mapMultiSettingsRet)
 {
     namespace fs = boost::filesystem;
     namespace pod = boost::program_options::detail;
 
+    if (mapSettingsRet.count("-datadir"))
+    {
+        if (fs::is_directory(fs::system_complete(mapSettingsRet["-datadir"])))
+        {
+            fs::path pathDataDir = fs::system_complete(mapSettingsRet["-datadir"]);
+            strlcpy(pszSetDataDir, pathDataDir.string().c_str(), sizeof(pszSetDataDir));
+        }
+        else
+        {
+            return false;
+        }
+    }
+
     fs::ifstream streamConfig(GetConfigFile());
     if (!streamConfig.good())
-        return;
+        return true; // No bitcoin.conf file is OK
 
     set<string> setOptions;
     setOptions.insert("*");
@@ -933,6 +946,7 @@ void ReadConfigFile(map<string, string>& mapSettingsRet,
         }
         mapMultiSettingsRet[strKey].push_back(it->value[0]);
     }
+    return true;
 }
 
 string GetPidFile()
index ddc8791..31d3275 100644 (file)
@@ -151,7 +151,7 @@ void GetDataDir(char* pszDirRet);
 std::string GetConfigFile();
 std::string GetPidFile();
 void CreatePidFile(std::string pidFile, pid_t pid);
-void ReadConfigFile(std::map<std::string, std::string>& mapSettingsRet, std::map<std::string, std::vector<std::string> >& mapMultiSettingsRet);
+bool ReadConfigFile(std::map<std::string, std::string>& mapSettingsRet, std::map<std::string, std::vector<std::string> >& mapMultiSettingsRet);
 #ifdef WIN32
 std::string MyGetSpecialFolderPath(int nFolder, bool fCreate);
 #endif