Ticket #3737: optionsReset-v2.patch

File optionsReset-v2.patch, 15.0 KB (added by mimo, 8 years ago)

rebased patch after r17657

  • binaries/data/mods/public/gui/options/options.js

     
    11var g_hasCallback = false;
    22var g_controls;
     3var g_options;
    34
    45function init(data)
    56{
     
    78        g_hasCallback = true;
    89    let revert = data && data.revert;
    910    g_controls = [];
     11    g_options = Engine.ReadJSONFile("gui/options/options.json");
    1012
    11     var options = Engine.ReadJSONFile("gui/options/options.json");
    12     for (let category of Object.keys(options))
     13    for (let category of Object.keys(g_options))
    1314    {
    1415        let lastSize;
    15         for (let i = 0; i < options[category].length; ++i)
     16        for (let i = 0; i < g_options[category].length; ++i)
    1617        {
    17             let option = options[category][i];
     18            let option = g_options[category][i];
    1819            if (!option.label)
    1920                continue;
    2021            let body = Engine.GetGUIObjectByName(category + "[" + i + "]");
     
    7879                if (checked === undefined || revert)
    7980                    checked = Engine.ConfigDB_GetValue("user", keyConfig) === "true";
    8081                else if ((Engine.ConfigDB_GetValue("user", keyConfig) === "true") !== checked)
     82                {
    8183                    Engine.ConfigDB_CreateValue("user", keyConfig, String(checked));
     84                    updateStatus();
     85                }
    8286                break;
    8387            case "renderer":
    8488                keyRenderer = option.parameters.renderer;
     
    106110                    Engine["Renderer_Set" + keyRenderer + "Enabled"](this.checked);
    107111                if (keyConfig)
    108112                    Engine.ConfigDB_CreateValue("user", keyConfig, String(this.checked));
    109                 updateStatus(true);
     113                updateStatus();
    110114            };
    111115        }(keyRenderer, keyConfig);
    112116
     
    164168                Engine.ConfigDB_CreateValue("user", key, this.caption);
    165169                if (functionBody)
    166170                    Engine[functionBody](+this.caption);
    167                 updateStatus(true);
     171                updateStatus();
    168172            };
    169173        }(key, functionBody, minval, maxval);
    170174
     
    211215                if (key === "materialmgr.quality")
    212216                    val = val == 0 ? 2 : val == 1 ? 5 : 8;
    213217                Engine.ConfigDB_CreateValue("user", key, val);
    214                 updateStatus(true);
     218                updateStatus();
    215219            };
    216220        }(key);
    217221
     
    227231    return control;
    228232}
    229233
    230 function updateStatus(val)
     234function updateStatus()
    231235{
    232     if (typeof val == "boolean")
    233         Engine.ConfigDB_CreateValue("user", "nosave.haschanges", String(val));
    234     else
    235         val = Engine.ConfigDB_GetValue("user", "nosave.haschanges") === "true";
    236 
    237     Engine.GetGUIObjectByName("loadOptions").enabled = val;
    238     Engine.GetGUIObjectByName("saveOptions").enabled = val;
     236    let val = Engine.ConfigDB_HasChanges("user");
     237    Engine.GetGUIObjectByName("revertChanges").enabled = val;
     238    Engine.GetGUIObjectByName("saveChanges").enabled = val;
    239239}
    240240
    241241/**
     
    247247        control.onPress();
    248248}
    249249
     250function resetChanges()
     251{
     252    let btCaptions = [translate("No"), translate("Yes")];
     253    let btCode = [null, function(){ reallyResetChanges(); }];
     254    messageBox(500, 200, translate("Resetting the options needs to close the game. Are you sure you want to continue ?"),
     255        translate("Warning"), 0, btCaptions, btCode);
     256}
     257
     258function reallyResetChanges()
     259{
     260    for (let category in g_options)
     261        for (let setting of g_options[category])
     262            if (setting.parameters.config)
     263                Engine.ConfigDB_RemoveValue("user", setting.parameters.config);
     264
     265    Engine.ConfigDB_WriteFile("user", "config/user.cfg");
     266    Engine.Exit();
     267}
     268
    250269function revertChanges()
    251270{
    252271    Engine.ConfigDB_Reload("user");
    253     updateStatus(false);
     272    updateStatus();
    254273    init({ "revert": true });
    255274}
    256275
     
    258277{
    259278    registerChanges();
    260279    Engine.ConfigDB_WriteFile("user", "config/user.cfg");
    261     updateStatus(false);
     280    updateStatus();
    262281}
    263282
    264283/**
     
    267286function closePage()
    268287{
    269288    registerChanges();
    270     if (Engine.ConfigDB_GetValue("user", "nosave.haschanges") === "true")
     289    if (Engine.ConfigDB_HasChanges("user"))
    271290    {
    272291        let btCaptions = [translate("No"), translate("Yes")];
    273292        let btCode = [null, function(){ closePageWithoutConfirmation(); }];
  • binaries/data/mods/public/gui/options/options.xml

     
    6969                </object>
    7070            </repeat>
    7171        </object>
    72         <object name="loadOptions" type="button" style="ModernButtonRed" size="50%-170 100%-44 50%-70 100%-16" hotkey="cancel">
     72        <object type="button" style="ModernButtonRed" size="50%-236 100%-44 50%-136 100%-16" hotkey="cancel">
     73            <translatableAttribute id="caption">Reset</translatableAttribute>
     74            <translatableAttribute id="tooltip">Reset all user settings (will close the game)</translatableAttribute>
     75            <action on="Press">resetChanges();</action>
     76        </object>
     77        <object name="revertChanges" type="button" style="ModernButtonRed" size="50%-104 100%-44 50%-4 100%-16" hotkey="cancel">
    7378            <translatableAttribute id="caption">Revert</translatableAttribute>
    7479            <translatableAttribute id="tooltip">Revert to previous saved settings</translatableAttribute>
    7580            <action on="Press">revertChanges();</action>
    7681        </object>
    77         <object name="saveOptions" type="button" style="ModernButtonRed" size="50%-62 100%-44 50%+38 100%-16">
     82        <object name="saveChanges" type="button" style="ModernButtonRed" size="50%+4 100%-44 50%+104 100%-16">
    7883            <translatableAttribute id="caption">Save</translatableAttribute>
    7984            <translatableAttribute id="tooltip">Save changes</translatableAttribute>
    8085            <action on="Press">saveChanges();</action>
    8186        </object>
    82         <object type="button" style="ModernButtonRed" size="50%+70 100%-44 50%+170 100%-16">
     87        <object type="button" style="ModernButtonRed" size="50%+136 100%-44 50%+236 100%-16">
    8388            <translatableAttribute id="caption">Quit</translatableAttribute>
    8489            <translatableAttribute id="tooltip">Unsaved changes affect this session only</translatableAttribute>
    8590            <action on="Press">closePage();</action>
  • binaries/data/mods/public/gui/splashscreen/splashscreen.xml

     
    2727        <object name="btnOK" type="button" style="ModernButtonRed" size="18 100%-45 50%-5 100%-17" hotkey="cancel">
    2828            <translatableAttribute id="caption">OK</translatableAttribute>
    2929            <action on="Press"><![CDATA[
    30             if (Engine.GetGUIObjectByName("displaySplashScreen").checked)
    31                 Engine.ConfigDB_CreateValue("user", "splashscreenversion", 0);
    32             else
    33                 Engine.ConfigDB_CreateValue("user", "splashscreenversion", Engine.GetFileMTime("gui/splashscreen/splashscreen.txt"));
    34             Engine.ConfigDB_WriteFile("user", "config/user.cfg");
     30            let value = Engine.GetGUIObjectByName("displaySplashScreen").checked ? 0 : Engine.GetFileMTime("gui/splashscreen/splashscreen.txt");
     31            Engine.ConfigDB_CreateValueAndWriteFile("user", "splashscreenversion", value, "config/user.cfg");
    3532            Engine.PopGuiPageCB();
    3633            ]]></action>
    3734        </object>
  • source/ps/ConfigDB.cpp

     
    2929typedef std::map<CStr, CConfigValueSet> TConfigMap;
    3030TConfigMap CConfigDB::m_Map[CFG_LAST];
    3131VfsPath CConfigDB::m_ConfigFile[CFG_LAST];
     32bool CConfigDB::m_HasChanges[CFG_LAST];
    3233
    3334static pthread_mutex_t cfgdb_mutex = PTHREAD_MUTEX_INITIALIZER;
    3435
     
    114115GETVAL(std::string)
    115116#undef GETVAL
    116117
     118bool CConfigDB::HasChanges(EConfigNamespace ns) const
     119{
     120    CHECK_NS(false);
     121
     122    CScopeLock s(&cfgdb_mutex);
     123    return m_HasChanges[ns];
     124}
     125
    117126void CConfigDB::GetValues(EConfigNamespace ns, const CStr& name, CConfigValueSet& values) const
    118127{
    119128    CHECK_NS(;);
     
    187196        it = m_Map[ns].insert(m_Map[ns].begin(), make_pair(name, CConfigValueSet(1)));
    188197
    189198    it->second[0] = value;
     199    m_HasChanges[ns] = true;
    190200}
    191201
     202void CConfigDB::RemoveValue(EConfigNamespace ns, const CStr& name)
     203{
     204    CHECK_NS(;);
     205
     206    CScopeLock s(&cfgdb_mutex);
     207    TConfigMap::iterator it = m_Map[ns].find(name);
     208    if (it == m_Map[ns].end())
     209        return;
     210    m_Map[ns].erase(it);
     211    m_HasChanges[ns] = true;
     212}
     213
    192214void CConfigDB::SetConfigFile(EConfigNamespace ns, const VfsPath& path)
    193215{
    194216    CHECK_NS(;);
     
    357379
    358380    m_Map[ns].swap(newMap);
    359381
     382    m_HasChanges[ns] = false;
    360383    return true;
    361384}
    362385
     
    378401    char* pos = (char*)buf.get();
    379402    for (const std::pair<CStr, CConfigValueSet>& p : m_Map[ns])
    380403    {
    381         if (boost::algorithm::starts_with(p.first, "nosave."))
    382             continue;
    383404        size_t i;
    384405        pos += sprintf(pos, "%s = ", p.first.c_str());
    385406        for (i = 0; i < p.second.size() - 1; ++i)
     
    395416        return false;
    396417    }
    397418
     419    m_HasChanges[ns] = false;
    398420    return true;
    399421}
    400422
     423bool CConfigDB::SetValueAndWriteFile(EConfigNamespace ns, const CStr& name, const CStr& value, const VfsPath& path)
     424{
     425    CHECK_NS(false);
     426
     427    CScopeLock s(&cfgdb_mutex);
     428    bool changed = m_HasChanges[ns];
     429
     430    // if there are no previous changes, we can just set the value and then write to file
     431    if (!changed)
     432    {
     433        SetValueString(ns, name, value);
     434        bool ret = WriteFile(ns, path);
     435        m_HasChanges[ns] = !ret;
     436        return ret;
     437    }
     438
     439    // otherwise we set this value in the specified namespace
     440    SetValueString(ns, name, value);
     441    TConfigMap newMap;
     442    m_Map[ns].swap(newMap);
     443    if (!Reload(ns))
     444    {
     445        m_Map[ns].swap(newMap);
     446        m_HasChanges[ns] = true;
     447        return false;
     448    }
     449    // and add it to be written on file
     450    SetValueString(ns, name, value);
     451    bool ret = WriteFile(ns, path);
     452    m_Map[ns].swap(newMap);
     453    m_HasChanges[ns] = changed || !ret;
     454    return ret;
     455}
     456
    401457#undef CHECK_NS
  • source/ps/ConfigDB.h

     
    5252{
    5353    static std::map<CStr, CConfigValueSet> m_Map[];
    5454    static VfsPath m_ConfigFile[];
     55    static bool m_HasChanges[];
    5556
    5657public:
    5758    CConfigDB();
     
    7273    void GetValue(EConfigNamespace ns, const CStr& name, std::string& value);
    7374
    7475    /**
     76     * Returns true if changed with respect to last write on file
     77     */
     78    bool HasChanges(EConfigNamespace ns) const;
     79
     80    /**
    7581     * Attempt to retrieve a vector of values corresponding to the given setting;
    7682     * will search CFG_COMMAND first, and then all namespaces from the specified
    7783     * namespace down.
     
    96102     * existed the value is replaced.
    97103     */
    98104    void SetValueString(EConfigNamespace ns, const CStr& name, const CStr& value);
     105
     106    /**
     107     * Remove a config value in the specified namespace.
     108     */
     109    void RemoveValue(EConfigNamespace ns, const CStr& name);
    99110   
    100111    /**
    101112     * Set the path to the config file used to populate the specified namespace
     
    135146     *  false:  if an error occurred
    136147     */
    137148    bool WriteFile(EConfigNamespace ns) const;
     149
     150    /**
     151     * Save a config value in the specified namespace (if the config variable
     152     * existed the value is replaced) and write it to file.
     153     *
     154     * Returns:
     155     *  true:   if the config value was successfully saved and written to the file
     156     *  false:  if an error occurred
     157     */
     158    bool SetValueAndWriteFile(EConfigNamespace ns, const CStr& name, const CStr& value, const VfsPath& path);
    138159};
    139160
    140161
  • source/ps/scripting/JSInterface_ConfigDB.cpp

     
    4242    return true;
    4343}
    4444
     45bool JSI_ConfigDB::HasChanges(ScriptInterface::CxPrivate* UNUSED(pCxPrivate), std::wstring cfgNsString)
     46{
     47    EConfigNamespace cfgNs;
     48    if (!GetConfigNamespace(cfgNsString, cfgNs))
     49        return false;
     50
     51    return g_ConfigDB.HasChanges(cfgNs);
     52}
     53
    4554std::string JSI_ConfigDB::GetValue(ScriptInterface::CxPrivate* UNUSED(pCxPrivate), std::wstring cfgNsString, std::string name)
    4655{
    4756    EConfigNamespace cfgNs;
     
    6372    return true;
    6473}
    6574
     75bool JSI_ConfigDB::RemoveValue(ScriptInterface::CxPrivate* UNUSED(pCxPrivate), std::wstring cfgNsString, std::string name)
     76{
     77    EConfigNamespace cfgNs;
     78    if (!GetConfigNamespace(cfgNsString, cfgNs))
     79        return false;
     80
     81    g_ConfigDB.RemoveValue(cfgNs, name);
     82    return true;
     83}
     84
    6685bool JSI_ConfigDB::WriteFile(ScriptInterface::CxPrivate* UNUSED(pCxPrivate), std::wstring cfgNsString, Path path)
    6786{
    6887    EConfigNamespace cfgNs;
     
    7392    return ret;
    7493}
    7594
     95bool JSI_ConfigDB::CreateValueAndWriteFile(ScriptInterface::CxPrivate* UNUSED(pCxPrivate), std::wstring cfgNsString,  std::string name, std::string value, Path path)
     96{
     97    EConfigNamespace cfgNs;
     98    if (!GetConfigNamespace(cfgNsString, cfgNs))
     99        return false;
     100
     101    bool ret = g_ConfigDB.SetValueAndWriteFile(cfgNs, name, value, path);
     102    return ret;
     103}
     104
    76105bool JSI_ConfigDB::Reload(ScriptInterface::CxPrivate* UNUSED(pCxPrivate), std::wstring cfgNsString)
    77106{
    78107    EConfigNamespace cfgNs;
     
    95124
    96125void JSI_ConfigDB::RegisterScriptFunctions(ScriptInterface& scriptInterface)
    97126{
     127    scriptInterface.RegisterFunction<bool, std::wstring, &JSI_ConfigDB::HasChanges>("ConfigDB_HasChanges");
    98128    scriptInterface.RegisterFunction<std::string, std::wstring, std::string, &JSI_ConfigDB::GetValue>("ConfigDB_GetValue");
    99129    scriptInterface.RegisterFunction<bool, std::wstring, std::string, std::string, &JSI_ConfigDB::CreateValue>("ConfigDB_CreateValue");
     130    scriptInterface.RegisterFunction<bool, std::wstring, std::string, &JSI_ConfigDB::RemoveValue>("ConfigDB_RemoveValue");
    100131    scriptInterface.RegisterFunction<bool, std::wstring, Path, &JSI_ConfigDB::WriteFile>("ConfigDB_WriteFile");
     132    scriptInterface.RegisterFunction<bool, std::wstring, std::string, std::string, Path, &JSI_ConfigDB::CreateValueAndWriteFile>("ConfigDB_CreateValueAndWriteFile");
    101133    scriptInterface.RegisterFunction<bool, std::wstring, Path, &JSI_ConfigDB::SetFile>("ConfigDB_SetFile");
    102134    scriptInterface.RegisterFunction<bool, std::wstring, &JSI_ConfigDB::Reload>("ConfigDB_Reload");
    103135   
  • source/ps/scripting/JSInterface_ConfigDB.h

     
    2424namespace JSI_ConfigDB
    2525{
    2626    bool GetConfigNamespace(std::wstring cfgNsString, EConfigNamespace& cfgNs);
     27    bool HasChanges(ScriptInterface::CxPrivate* pCxPrivate, std::wstring cfgNsString);
    2728    std::string GetValue(ScriptInterface::CxPrivate* pCxPrivate, std::wstring cfgNsString, std::string name);
    2829    bool CreateValue(ScriptInterface::CxPrivate* pCxPrivate, std::wstring cfgNsString, std::string name, std::string value);
     30    bool RemoveValue(ScriptInterface::CxPrivate* pCxPrivate, std::wstring cfgNsString, std::string name);
    2931    bool WriteFile(ScriptInterface::CxPrivate* pCxPrivate, std::wstring cfgNsString, Path path);
     32    bool CreateValueAndWriteFile(ScriptInterface::CxPrivate* pCxPrivate, std::wstring cfgNsString, std::string name, std::string value, Path path);
    3033    bool Reload(ScriptInterface::CxPrivate* pCxPrivate, std::wstring cfgNsString);
    3134    bool SetFile(ScriptInterface::CxPrivate* pCxPrivate, std::wstring cfgNsString, Path path);
    3235    void RegisterScriptFunctions(ScriptInterface& scriptInterface);