diff --git a/resources/report/js/script.js b/resources/report/js/script.js index 18c10f24..76bee270 100644 --- a/resources/report/js/script.js +++ b/resources/report/js/script.js @@ -624,87 +624,113 @@ function setupEventHandlers() { document.body.addEventListener('mouseover', toggleHoverText, false); } -function initUI() { - if (typeof loot == 'undefined') { - console.log('loot is not defined.'); - return; - } - - document.getElementById('LOOTVersion').textContent = loot.version; - /* Fill in languages, games, settings values. */ - - /* Fill in game row template's game type options. */ - var select = document.getElementById('gameRow').content.querySelector('select'); - for (var j = 0; j < loot.gameTypes.length; ++j) { - var option = document.createElement('option'); - option.value = loot.gameTypes[j]; - option.textContent = loot.gameTypes[j]; - select.appendChild(option); - } - - /* Now fill game lists/table. */ - var gameSelect = document.getElementById('defaultGameSelect'); - var gameMenu = document.getElementById('gameMenu').firstElementChild; - var gameTableBody = document.getElementById('gameTable').getElementsByTagName('tbody')[0]; - /* Add "auto" value for default game. */ - var option = document.createElement('option'); - option.value = 'auto'; - option.textContent = 'Autodetect'; - gameSelect.appendChild(option); - /* Add row for creating new rows. */ - setupTable(gameTableBody); - for (var i = 0; i < loot.settings.games.length; ++i) { - var option = document.createElement('option'); - option.value = loot.settings.games[i].folder; - option.textContent = loot.settings.games[i].name; - gameSelect.appendChild(option); - - var li = document.createElement('li'); - li.setAttribute('data-action', 'change-game'); - li.setAttribute('data-target', loot.settings.games[i].folder); - li.textContent = loot.settings.games[i].name; - gameMenu.appendChild(li); - - addTableRow(gameTableBody, loot.settings.games[i]); - } - - /* Now fill in language options. */ - var settingsLangSelect = document.getElementById('languageSelect'); - var messageLangSelect = document.getElementById('messageRow').content.querySelector('.language'); - for (var i = 0; i < loot.languages.length; ++i) { - var option = document.createElement('option'); - option.value = loot.languages[i]; - option.textContent = loot.languages[i]; - settingsLangSelect.appendChild(option); - messageLangSelect.appendChild(option.cloneNode(true)); - } - - /* Now fill in settings values. */ - gameSelect.value = loot.settings.game; - settingsLangSelect.value = loot.settings.language; - debugVerbositySelect.value = loot.settings.debugVerbosity; +function processCefError(errorCode, errorMessage) { + showMessageBox('error', "Error", "Error code: " + error_code + "; " + error_message); } function initGlobalVars() { // Create and send a new query. var request_id = window.cefQuery({ - request: 'initGlobalVars', + request: 'getVersion', persistent: false, onSuccess: function(response) { try { - var temp = JSON.parse(response); - loot.version = temp.version; - loot.settings = temp.settings; - loot.gameTypes = temp.gameTypes; - loot.languages = temp.languages; + loot.version = JSON.parse(response); + + document.getElementById('LOOTVersion').textContent = loot.version; } catch (e) { console.log(e); console.log('Response: ' + response); } - initUI(); }, - onFailure: function(error_code, error_message) { - showMessageBox('error', "Error", "Error code: " + error_code + "; " + error_message); - } + onFailure: processCefError + }); + var request_id = window.cefQuery({ + request: 'getLanguages', + persistent: false, + onSuccess: function(response) { + try { + loot.languages = JSON.parse(response); + + /* Now fill in language options. */ + var settingsLangSelect = document.getElementById('languageSelect'); + var messageLangSelect = document.getElementById('messageRow').content.querySelector('.language'); + for (var i = 0; i < loot.languages.length; ++i) { + var option = document.createElement('option'); + option.value = loot.languages[i].locale; + option.textContent = loot.languages[i].name; + settingsLangSelect.appendChild(option); + messageLangSelect.appendChild(option.cloneNode(true)); + } + } catch (e) { + console.log(e); + console.log('Response: ' + response); + } + }, + onFailure: processCefError + }); + var request_id = window.cefQuery({ + request: 'getGameTypes', + persistent: false, + onSuccess: function(response) { + try { + loot.gameTypes = JSON.parse(response); + + /* Fill in game row template's game type options. */ + var select = document.getElementById('gameRow').content.querySelector('select'); + for (var j = 0; j < loot.gameTypes.length; ++j) { + var option = document.createElement('option'); + option.value = loot.gameTypes[j]; + option.textContent = loot.gameTypes[j]; + select.appendChild(option); + } + } catch (e) { + console.log(e); + console.log('Response: ' + response); + } + + // Settings depend on having the game types filled, so now send the CEF query for the settings. + var request_id = window.cefQuery({ + request: 'getSettings', + persistent: false, + onSuccess: function(response) { + try { + loot.settings = JSON.parse(response); + + + /* Now fill game lists/table. */ + var gameSelect = document.getElementById('defaultGameSelect'); + var gameMenu = document.getElementById('gameMenu').firstElementChild; + var gameTableBody = document.getElementById('gameTable').getElementsByTagName('tbody')[0]; + /* Add row for creating new rows. */ + setupTable(gameTableBody); + for (var i = 0; i < loot.settings.games.length; ++i) { + var option = document.createElement('option'); + option.value = loot.settings.games[i].folder; + option.textContent = loot.settings.games[i].name; + gameSelect.appendChild(option); + + var li = document.createElement('li'); + li.setAttribute('data-action', 'change-game'); + li.setAttribute('data-target', loot.settings.games[i].folder); + li.textContent = loot.settings.games[i].name; + gameMenu.appendChild(li); + + addTableRow(gameTableBody, loot.settings.games[i]); + } + + gameSelect.value = loot.settings.game; + document.getElementById('languageSelect').value = loot.settings.language; + document.getElementById('debugVerbositySelect').value = loot.settings.debugVerbosity; + } catch (e) { + console.log(e); + console.log('Response: ' + response); + } + + }, + onFailure: processCefError + }); + }, + onFailure: processCefError }); } function updateInterfaceWithGameInfo(response) { @@ -860,10 +886,10 @@ function updateInterfaceWithGameInfo(response) { // Now set up event handlers, as they depend on the plugin cards having been created. setupEventHandlers(); } -function initGameVars() { +function getGameData() { // Create and send a new query. var request_id = window.cefQuery({ - request: 'initGameVars', + request: 'getGameData', persistent: false, onSuccess: updateInterfaceWithGameInfo, onFailure: function(error_code, error_message) { @@ -873,7 +899,7 @@ function initGameVars() { } initGlobalVars(); -initGameVars(); +getGameData(); if (isStorageSupported()) { loadSettings(); } diff --git a/resources/report/report.html b/resources/report/report.html index d2e2d540..f576a3e7 100644 --- a/resources/report/report.html +++ b/resources/report/report.html @@ -283,6 +283,7 @@ along with LOOT. If not, see <http://www.gnu.org/licenses/>.

Settings


diff --git a/resources/settings.yaml b/resources/settings.yaml index 8363bbe7..8311c432 100644 --- a/resources/settings.yaml +++ b/resources/settings.yaml @@ -1,15 +1,15 @@ # Example Default LOOT Settings File # This file is written in YAML . -Language: eng # One of 'eng', 'spa', 'rus' or ''. +language: eng # One of 'eng', 'spa', 'rus' or ''. -Game: auto # auto, or one of the 'folder' values below. -Last Game: auto # auto, or one of the 'folder' values below. -Debug Verbosity: 0 # 0, 1, 2, 3. Logging takes place if > 0. -Update Masterlist: true +game: auto # auto, or one of the 'folder' values below. +lastGame: auto # auto, or one of the 'folder' values below. +debugVerbosity: 0 # 0, 1, 2, 3. Logging takes place if > 0. +updateMasterlist: true # Games. The four types are 'Oblivion', 'Skyrim', 'Fallout3' and 'FalloutNV'. They correspond to each base game's libespm and libloadorder settings. -Games: +games: - folder: Oblivion name: "TES IV: Oblivion" type: Oblivion diff --git a/src/backend/game.cpp b/src/backend/game.cpp index b40ffd56..8bfbfbdb 100644 --- a/src/backend/game.cpp +++ b/src/backend/game.cpp @@ -44,8 +44,8 @@ namespace loot { std::vector GetGames(const YAML::Node& settings) { vector games; - if (settings["Games"]) - games = settings["Games"].as< vector >(); + if (settings["games"]) + games = settings["games"].as< vector >(); if (find(games.begin(), games.end(), Game(Game::tes4)) == games.end()) games.push_back(Game(Game::tes4)); @@ -66,10 +66,10 @@ namespace loot { string preferredGame(cmdLineGame); if (preferredGame.empty()) { // Get preferred game from settings. - if (settings["Game"] && settings["Game"].as() != "auto") - preferredGame = settings["Game"].as(); - else if (settings["Last Game"] && settings["Last Game"].as() != "auto") - preferredGame = settings["Last Game"].as(); + if (settings["game"] && settings["game"].as() != "auto") + preferredGame = settings["game"].as(); + else if (settings["lastGame"] && settings["lastGame"].as() != "auto") + preferredGame = settings["lastGame"].as(); } // Get index of preferred game if there is one. diff --git a/src/backend/generators.cpp b/src/backend/generators.cpp index c45c1a3c..b66ca267 100644 --- a/src/backend/generators.cpp +++ b/src/backend/generators.cpp @@ -412,11 +412,11 @@ namespace loot { YAML::Node root; std::vector games; - root["Language"] = "en"; - root["Game"] = "auto"; - root["Last Game"] = "auto"; - root["Debug Verbosity"] = 0; - root["Update Masterlist"] = true; + root["language"] = "en"; + root["game"] = "auto"; + root["lastGame"] = "auto"; + root["debugVerbosity"] = 0; + root["updateMasterlist"] = true; games.push_back(Game(Game::tes4)); games.push_back(Game(Game::tes5)); @@ -424,7 +424,7 @@ namespace loot { games.push_back(Game(Game::fonv)); games.push_back(Game(Game::tes4, "Nehrim").SetDetails("Nehrim - At Fate's Edge", "Nehrim.esm", "https://github.com/loot/oblivion.git", "master", "", "Software\\Microsoft\\Windows\\CurrentVersion\\Uninstall\\Nehrim - At Fate's Edge_is1\\InstallLocation")); - root["Games"] = games; + root["games"] = games; //Save settings. YAML::Emitter yout; diff --git a/src/backend/json.h b/src/backend/json.h index f6cbb256..b7252d02 100644 --- a/src/backend/json.h +++ b/src/backend/json.h @@ -38,7 +38,7 @@ namespace loot { return YAML::Load(json); } - inline static std::string stringify(YAML::Node& yaml) { + inline static std::string stringify(const YAML::Node& yaml) { YAML::Emitter out; out.SetOutputCharset(YAML::EscapeNonAscii); diff --git a/src/gui/app.cpp b/src/gui/app.cpp index 33c302f4..c37df9fb 100644 --- a/src/gui/app.cpp +++ b/src/gui/app.cpp @@ -170,8 +170,8 @@ namespace loot { ); boost::log::add_common_attributes(); unsigned int verbosity; - if (_settings["Debug Verbosity"]) { - verbosity = _settings["Debug Verbosity"].as(); + if (_settings["debugVerbosity"]) { + verbosity = _settings["debugVerbosity"].as(); } if (verbosity == 0) boost::log::core::get()->set_logging_enabled(false); @@ -191,8 +191,8 @@ namespace loot { BOOST_LOG_TRIVIAL(debug) << "Initialising language settings."; //Defaults in case language string is empty or setting is missing. string localeId = loot::Language(loot::Language::any).Locale() + ".UTF-8"; - if (_settings["Language"]) { - loot::Language lang(_settings["Language"].as()); + if (_settings["language"]) { + loot::Language lang(_settings["language"].as()); BOOST_LOG_TRIVIAL(debug) << "Selected language: " << lang.Name(); localeId = lang.Locale() + ".UTF-8"; } @@ -249,4 +249,11 @@ namespace loot { Game& LootState::CurrentGame() { return _games[_currentGame]; } + + const YAML::Node& LootState::GetSettings() const { + return _settings; + } + const YAML::Node& LootState::GetSetting(const std::string& setting) const { + return _settings[setting]; + } } \ No newline at end of file diff --git a/src/gui/app.h b/src/gui/app.h index 56a4baf4..8bed8f4a 100644 --- a/src/gui/app.h +++ b/src/gui/app.h @@ -75,8 +75,13 @@ namespace loot { LootState(); void Init(const std::string& cmdLineGame); + Game& CurrentGame(); + const YAML::Node& GetSettings() const; + const YAML::Node& GetSetting(const std::string& setting) const; + + private: YAML::Node _settings; std::vector _games; size_t _currentGame; diff --git a/src/gui/handler.cpp b/src/gui/handler.cpp index f8de31a1..57c91b9b 100644 --- a/src/gui/handler.cpp +++ b/src/gui/handler.cpp @@ -69,179 +69,196 @@ namespace loot { CefRefPtr callback) { if (request == "openReadme") { - // Open readme in default application. - HINSTANCE ret = ShellExecute(0, NULL, ToWinWide(ToFileURL(g_path_readme)).c_str(), NULL, NULL, SW_SHOWNORMAL); - if ((int)ret > 32) - callback->Success(request); - else - callback->Failure((int)ret, "Shell execute failed."); + try { + OpenReadme(); + callback->Success(""); + } + catch (error &e) { + callback->Failure(e.code(), e.what()); + } + catch (exception &e) { + callback->Failure(-1, e.what()); + } return true; } else if (request == "openLogLocation") { - //Open debug log folder. - HINSTANCE ret = ShellExecute(NULL, L"open", ToWinWide(g_path_log.parent_path().string()).c_str(), NULL, NULL, SW_SHOWNORMAL); - if ((int)ret > 32) - callback->Success(request); - else - callback->Failure((int)ret, "Shell execute failed."); - return true; - } - else if (request == "initGlobalVars") { - // Convert the _settings YAML object to a JSON string, and also add members for the LOOT version, game types and languages. - - if (g_app_state._games.empty()) { - BOOST_LOG_TRIVIAL(warning) << "Application state not yet initialised, initialising now..."; - g_app_state.Init(""); - BOOST_LOG_TRIVIAL(info) << "Application state initialised."; - } - - YAML::Node temp; - - // LOOT Version - //------------- - - temp["version"] = to_string(g_version_major) + "." + to_string(g_version_minor) + "." + to_string(g_version_patch); - - // LOOT Settings - //-------------- - - //temp["settings"] = g_app_state._settings; - - // Do a bit of translation of key names into more javascript-friendly names. - // Consider instead making the settings file use the more friendly names itself. - - temp["settings"]["debugVerbosity"] = g_app_state._settings["Debug Verbosity"]; - temp["settings"]["game"] = g_app_state._settings["Game"]; - temp["settings"]["games"] = g_app_state._settings["Games"]; - temp["settings"]["language"] = Language(g_app_state._settings["Language"].as()).Name(); - temp["settings"]["lastGame"] = g_app_state._settings["Last Game"]; - - // LOOT Game Types - //----------------- - - vector gameTypes; - gameTypes.push_back(Game(Game::tes4).FolderName()); - gameTypes.push_back(Game(Game::tes5).FolderName()); - gameTypes.push_back(Game(Game::fo3).FolderName()); - gameTypes.push_back(Game(Game::fonv).FolderName()); - - temp["gameTypes"] = gameTypes; - - // LOOT Languages - //--------------- - - BOOST_LOG_TRIVIAL(debug) << "Setting GUI values for LOOT's languages."; - - temp["languages"] = Language::Names(); - - // Now output as JSON - //------------------- - - callback->Success(JSON::stringify(temp)); - - return true; - } - else if (request == "initGameVars") { - // Get masterlist revision info and parse if it exists. Also get plugin headers info and parse userlist if it exists. - - if (g_app_state._games.empty()) { - BOOST_LOG_TRIVIAL(warning) << "Application state not yet initialised, initialising now..."; - g_app_state.Init(""); - BOOST_LOG_TRIVIAL(info) << "Application state initialised."; - } - - g_app_state.CurrentGame().LoadPlugins(true); - - //Sort plugins into their load order. - list installed; - list loadOrder; - g_app_state.CurrentGame().GetLoadOrder(loadOrder); - for (const auto &pluginName : loadOrder) { - const auto pos = g_app_state.CurrentGame().plugins.find(pluginName); - - if (pos != g_app_state.CurrentGame().plugins.end()) - installed.push_back(pos->second); - } - - //Parse masterlist, don't update it. - if (fs::exists(g_app_state.CurrentGame().MasterlistPath())) { - BOOST_LOG_TRIVIAL(debug) << "Parsing masterlist."; - g_app_state.CurrentGame().masterlist.MetadataList::Load(g_app_state.CurrentGame().MasterlistPath()); - } - - //Parse userlist. - if (fs::exists(g_app_state.CurrentGame().UserlistPath())) { - BOOST_LOG_TRIVIAL(debug) << "Parsing userlist."; - g_app_state.CurrentGame().userlist.Load(g_app_state.CurrentGame().UserlistPath()); - } - - // Now convert to a single object that can be turned into a JSON string - //--------------------------------------------------------------------- - - // The data structure is to be set as 'loot.game'. - YAML::Node gameNode; - - // ID the game using its folder value. - gameNode["folder"] = g_app_state.CurrentGame().FolderName(); - - // Store the masterlist revision and date. - gameNode["masterlist"]["revision"] = g_app_state.CurrentGame().masterlist.GetRevision(g_app_state.CurrentGame().MasterlistPath()); - gameNode["masterlist"]["date"] = g_app_state.CurrentGame().masterlist.GetDate(g_app_state.CurrentGame().MasterlistPath()); - - // Now store plugin data. - for (const auto& plugin : g_app_state.CurrentGame().plugins) { - // Test data has 'hasUserEdits', and 'tagsAdd', 'tagsRemove' keys, but - // the first will be handled by userlist lookups, and the other two are probably - // going to get moved around, haven't decided how best to handle the split between masterlist, userlist and plugin-sourced metadata. - YAML::Node pluginNode; - pluginNode["name"] = plugin.second.Name(); - pluginNode["isActive"] = g_app_state.CurrentGame().IsActive(plugin.first); - pluginNode["isDummy"] = (plugin.second.FormIDs().size() == 0); - pluginNode["loadsBSA"] = plugin.second.LoadsBSA(g_app_state.CurrentGame()); - pluginNode["crc"] = IntToHexString(plugin.second.Crc()); - pluginNode["version"] = plugin.second.Version(); - - gameNode["plugins"].push_back(pluginNode); - } - - //Set language. - unsigned int language; - if (g_app_state._settings["Language"]) - language = Language(g_app_state._settings["Language"].as()).Code(); - else - language = loot::Language::any; - - BOOST_LOG_TRIVIAL(info) << "Using message language: " << Language(language).Name(); - - //Evaluate any conditions in the global messages. - BOOST_LOG_TRIVIAL(debug) << "Evaluating global message conditions."; try { - list::iterator it = g_app_state.CurrentGame().masterlist.messages.begin(); - while (it != g_app_state.CurrentGame().masterlist.messages.end()) { - if (!it->EvalCondition(g_app_state.CurrentGame(), language)) - it = g_app_state.CurrentGame().masterlist.messages.erase(it); - else - ++it; - } + OpenLogLocation(); + callback->Success(""); } - catch (std::exception& e) { - BOOST_LOG_TRIVIAL(error) << "A global message contains a condition that could not be evaluated. Details: " << e.what(); - g_app_state.CurrentGame().masterlist.messages.push_back(loot::Message(loot::Message::error, (format(loc::translate("A global message contains a condition that could not be evaluated. Details: %1%")) % e.what()).str())); + catch (error &e) { + callback->Failure(e.code(), e.what()); + } + catch (exception &e) { + callback->Failure(-1, e.what()); } - - // Now store global messages from masterlist. - gameNode["globalMessages"] = g_app_state.CurrentGame().masterlist.messages; - - callback->Success(JSON::stringify(gameNode)); - return true; - + } + else if (request == "getVersion") { + callback->Success(GetVersion()); + return true; + } + else if (request == "getSettings") { + callback->Success(GetSettings()); + return true; + } + else if (request == "getLanguages") { + callback->Success(GetLanguages()); + return true; + } + else if (request == "getGameTypes") { + callback->Success(GetGameTypes()); + return true; + } + else if (request == "getGameData") { + callback->Success(GetGameData()); + return true; } return false; } + void Handler::OpenReadme() { + BOOST_LOG_TRIVIAL(info) << "Opening LOOT readme."; + // Open readme in default application. + HINSTANCE ret = ShellExecute(0, NULL, ToWinWide(ToFileURL(g_path_readme)).c_str(), NULL, NULL, SW_SHOWNORMAL); + if ((int)ret <= 32) + throw error(error::windows_error, "Shell execute failed."); + } + + void Handler::OpenLogLocation() { + BOOST_LOG_TRIVIAL(info) << "Opening LOOT local appdata folder."; + //Open debug log folder. + HINSTANCE ret = ShellExecute(NULL, L"open", ToWinWide(g_path_log.parent_path().string()).c_str(), NULL, NULL, SW_SHOWNORMAL); + if ((int)ret <= 32) + throw error(error::windows_error, "Shell execute failed."); + } + + std::string Handler::GetVersion() { + BOOST_LOG_TRIVIAL(info) << "Getting LOOT version."; + YAML::Node version(to_string(g_version_major) + "." + to_string(g_version_minor) + "." + to_string(g_version_patch)); + return JSON::stringify(version); + } + + std::string Handler::GetSettings() { + BOOST_LOG_TRIVIAL(info) << "Getting LOOT settings."; + return JSON::stringify(g_app_state.GetSettings()); + } + + std::string Handler::GetLanguages() { + BOOST_LOG_TRIVIAL(info) << "Getting LOOT's supported languages."; + // Need to get an array of language names and their corresponding codes. + YAML::Node temp; + vector names = Language::Names(); + for (const auto& name : names) { + YAML::Node lang; + lang["name"] = name; + lang["locale"] = Language(name).Locale(); + temp.push_back(lang); + } + return JSON::stringify(temp); + } + + std::string Handler::GetGameTypes() { + BOOST_LOG_TRIVIAL(info) << "Getting LOOT's supported game types."; + YAML::Node temp; + temp.push_back(Game(Game::tes4).FolderName()); + temp.push_back(Game(Game::tes5).FolderName()); + temp.push_back(Game(Game::fo3).FolderName()); + temp.push_back(Game(Game::fonv).FolderName()); + return JSON::stringify(temp); + } + + std::string Handler::GetGameData() { + BOOST_LOG_TRIVIAL(info) << "Getting data specific to LOOT's active game."; + // Get masterlist revision info and parse if it exists. Also get plugin headers info and parse userlist if it exists. + + g_app_state.CurrentGame().LoadPlugins(true); + + //Sort plugins into their load order. + list installed; + list loadOrder; + g_app_state.CurrentGame().GetLoadOrder(loadOrder); + for (const auto &pluginName : loadOrder) { + const auto pos = g_app_state.CurrentGame().plugins.find(pluginName); + + if (pos != g_app_state.CurrentGame().plugins.end()) + installed.push_back(pos->second); + } + + //Parse masterlist, don't update it. + if (fs::exists(g_app_state.CurrentGame().MasterlistPath())) { + BOOST_LOG_TRIVIAL(debug) << "Parsing masterlist."; + g_app_state.CurrentGame().masterlist.MetadataList::Load(g_app_state.CurrentGame().MasterlistPath()); + } + + //Parse userlist. + if (fs::exists(g_app_state.CurrentGame().UserlistPath())) { + BOOST_LOG_TRIVIAL(debug) << "Parsing userlist."; + g_app_state.CurrentGame().userlist.Load(g_app_state.CurrentGame().UserlistPath()); + } + + // Now convert to a single object that can be turned into a JSON string + //--------------------------------------------------------------------- + + // The data structure is to be set as 'loot.game'. + YAML::Node gameNode; + + // ID the game using its folder value. + gameNode["folder"] = g_app_state.CurrentGame().FolderName(); + + // Store the masterlist revision and date. + gameNode["masterlist"]["revision"] = g_app_state.CurrentGame().masterlist.GetRevision(g_app_state.CurrentGame().MasterlistPath()); + gameNode["masterlist"]["date"] = g_app_state.CurrentGame().masterlist.GetDate(g_app_state.CurrentGame().MasterlistPath()); + + // Now store plugin data. + for (const auto& plugin : g_app_state.CurrentGame().plugins) { + // Test data has 'hasUserEdits', and 'tagsAdd', 'tagsRemove' keys, but + // the first will be handled by userlist lookups, and the other two are probably + // going to get moved around, haven't decided how best to handle the split between masterlist, userlist and plugin-sourced metadata. + YAML::Node pluginNode; + pluginNode["name"] = plugin.second.Name(); + pluginNode["isActive"] = g_app_state.CurrentGame().IsActive(plugin.first); + pluginNode["isDummy"] = (plugin.second.FormIDs().size() == 0); + pluginNode["loadsBSA"] = plugin.second.LoadsBSA(g_app_state.CurrentGame()); + pluginNode["crc"] = IntToHexString(plugin.second.Crc()); + pluginNode["version"] = plugin.second.Version(); + + gameNode["plugins"].push_back(pluginNode); + } + + //Set language. + unsigned int language; + if (g_app_state.GetSetting("language")) + language = Language(g_app_state.GetSetting("language").as()).Code(); + else + language = loot::Language::any; + + BOOST_LOG_TRIVIAL(info) << "Using message language: " << Language(language).Name(); + + //Evaluate any conditions in the global messages. + BOOST_LOG_TRIVIAL(debug) << "Evaluating global message conditions."; + try { + list::iterator it = g_app_state.CurrentGame().masterlist.messages.begin(); + while (it != g_app_state.CurrentGame().masterlist.messages.end()) { + if (!it->EvalCondition(g_app_state.CurrentGame(), language)) + it = g_app_state.CurrentGame().masterlist.messages.erase(it); + else + ++it; + } + } + catch (std::exception& e) { + BOOST_LOG_TRIVIAL(error) << "A global message contains a condition that could not be evaluated. Details: " << e.what(); + g_app_state.CurrentGame().masterlist.messages.push_back(loot::Message(loot::Message::error, (format(loc::translate("A global message contains a condition that could not be evaluated. Details: %1%")) % e.what()).str())); + } + + // Now store global messages from masterlist. + gameNode["globalMessages"] = g_app_state.CurrentGame().masterlist.messages; + + return JSON::stringify(gameNode); + } + // LootHandler methods //-------------------- diff --git a/src/gui/handler.h b/src/gui/handler.h index 17874814..b4cf3a85 100644 --- a/src/gui/handler.h +++ b/src/gui/handler.h @@ -46,6 +46,14 @@ namespace loot { const CefString& request, bool persistent, CefRefPtr callback) OVERRIDE; + private: + void OpenReadme(); + void OpenLogLocation(); + std::string GetVersion(); + std::string GetSettings(); + std::string GetLanguages(); + std::string GetGameTypes(); + std::string GetGameData(); }; class LootHandler : public CefClient, diff --git a/src/gui/main_win.cpp b/src/gui/main_win.cpp index 38553f03..8071159c 100644 --- a/src/gui/main_win.cpp +++ b/src/gui/main_win.cpp @@ -51,14 +51,14 @@ CefSettings GetCefSettings() { // Don't set CEF locale, as it tries to load resources and crashes // if they can't be found. - /*if (_settings["Language"]) { - loot::Language lang(_settings["Language"].as()); + /*if (_settings["language"]) { + loot::Language lang(_settings["language"].as()); CefString(&cef_settings.locale).FromString(lang.Locale()); }*/ // Set CEF logging. CefString(&cef_settings.log_file).FromString("CEFDebugLog.txt"); - /*if (!_settings["Debug Verbosity"] || _settings["Debug Verbosity"].as() == 0) + /*if (!_settings["debugVerbosity"] || _settings["debugVerbosity"].as() == 0) cef_settings.log_severity = LOGSEVERITY_DISABLE; */ // Enable remote debugging.