mirror of
https://github.com/loot/libloot.git
synced 2026-07-27 14:16:01 -07:00
Merge branch 'reimplement-app-settings' into dev
This commit is contained in:
+8
-3
@@ -132,6 +132,7 @@ set (LOOT_GUI_SRC ${LOOT_SRC}
|
||||
"${CMAKE_SOURCE_DIR}/src/gui/handler.cpp"
|
||||
"${CMAKE_SOURCE_DIR}/src/gui/loot_handler.cpp"
|
||||
"${CMAKE_SOURCE_DIR}/src/gui/loot_app.cpp"
|
||||
"${CMAKE_SOURCE_DIR}/src/gui/loot_settings.cpp"
|
||||
"${CMAKE_SOURCE_DIR}/src/gui/loot_state.cpp"
|
||||
"${CMAKE_SOURCE_DIR}/src/gui/scheme.cpp"
|
||||
"${CMAKE_SOURCE_DIR}/src/resource.rc")
|
||||
@@ -143,6 +144,7 @@ set (LOOT_GUI_HEADERS ${LOOT_HEADERS}
|
||||
"${CMAKE_SOURCE_DIR}/src/gui/handler.h"
|
||||
"${CMAKE_SOURCE_DIR}/src/gui/loot_handler.h"
|
||||
"${CMAKE_SOURCE_DIR}/src/gui/loot_app.h"
|
||||
"${CMAKE_SOURCE_DIR}/src/gui/loot_settings.h"
|
||||
"${CMAKE_SOURCE_DIR}/src/gui/loot_state.h"
|
||||
"${CMAKE_SOURCE_DIR}/src/gui/scheme.h"
|
||||
"${CMAKE_SOURCE_DIR}/src/gui/resource.h")
|
||||
@@ -160,7 +162,9 @@ set (LOOT_VALIDATOR_SRC ${LOOT_SRC}
|
||||
|
||||
set (LOOT_VALIDATOR_HEADERS ${LOOT_HEADERS})
|
||||
|
||||
set (LOOT_TESTS_SRC "${CMAKE_SOURCE_DIR}/src/api/loot_db.cpp"
|
||||
set (LOOT_TESTS_SRC ${LOOT_SRC}
|
||||
"${CMAKE_SOURCE_DIR}/src/api/loot_db.cpp"
|
||||
"${CMAKE_SOURCE_DIR}/src/gui/loot_settings.cpp"
|
||||
"${CMAKE_SOURCE_DIR}/src/tests/main.cpp")
|
||||
|
||||
set (LOOT_TESTS_HEADERS "${CMAKE_SOURCE_DIR}/src/tests/fixtures.h"
|
||||
@@ -188,7 +192,8 @@ set (LOOT_TESTS_HEADERS "${CMAKE_SOURCE_DIR}/src/tests/fixtures.h"
|
||||
"${CMAKE_SOURCE_DIR}/src/tests/backend/plugin/test_plugin.h"
|
||||
"${CMAKE_SOURCE_DIR}/src/tests/backend/test_metadata_list.h"
|
||||
"${CMAKE_SOURCE_DIR}/src/tests/backend/test_masterlist.h"
|
||||
"${CMAKE_SOURCE_DIR}/src/tests/backend/test_plugin_sorter.h")
|
||||
"${CMAKE_SOURCE_DIR}/src/tests/backend/test_plugin_sorter.h"
|
||||
"${CMAKE_SOURCE_DIR}/src/tests/gui/test_loot_settings.h")
|
||||
|
||||
source_group("Header Files" FILES ${LOOT_HEADERS} ${LOOT_GUI_HEADERS} ${LOOT_API_HEADERS} ${LOOT_TESTS_HEADERS})
|
||||
|
||||
@@ -309,7 +314,7 @@ target_link_libraries (loot${PROJECT_ARCH} ${Boost_LIBRARIES} ${YAML_CPP_LIBRARI
|
||||
|
||||
IF (${GTEST_FOUND})
|
||||
# Build tests.
|
||||
add_executable(tests ${LOOT_TESTS_SRC} ${LOOT_SRC} ${LOOT_TESTS_HEADERS})
|
||||
add_executable(tests ${LOOT_TESTS_SRC} ${LOOT_TESTS_HEADERS})
|
||||
target_link_libraries(tests loot${PROJECT_ARCH} ${Boost_LIBRARIES} ${YAML_CPP_LIBRARIES} ${LOOT_LIBS} ${GTEST_BOTH_LIBRARIES})
|
||||
ENDIF ()
|
||||
|
||||
|
||||
@@ -191,12 +191,4 @@ namespace loot {
|
||||
return LoadOrderHandler::IsPluginActive(pluginName);
|
||||
}
|
||||
}
|
||||
|
||||
std::list<Game> ToGames(const std::list<GameSettings>& settings) {
|
||||
return list<Game>(settings.begin(), settings.end());
|
||||
}
|
||||
|
||||
std::list<GameSettings> ToGameSettings(const std::list<Game>& games) {
|
||||
return list<GameSettings>(games.begin(), games.end());
|
||||
}
|
||||
}
|
||||
|
||||
@@ -54,9 +54,6 @@ namespace loot {
|
||||
private:
|
||||
bool _pluginsFullyLoaded;
|
||||
};
|
||||
|
||||
std::list<Game> ToGames(const std::list<GameSettings>& settings);
|
||||
std::list<GameSettings> ToGameSettings(const std::list<Game>& games);
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
@@ -226,33 +226,6 @@ namespace loot {
|
||||
_gamePath = path;
|
||||
return *this;
|
||||
}
|
||||
|
||||
std::list<GameSettings> GetGameSettings(YAML::Node& settings) {
|
||||
list<GameSettings> games;
|
||||
|
||||
if (settings["games"])
|
||||
games = settings["games"].as< list<GameSettings> >();
|
||||
|
||||
if (find(games.begin(), games.end(), GameSettings(GameSettings::tes4)) == games.end())
|
||||
games.push_back(GameSettings(GameSettings::tes4));
|
||||
|
||||
if (find(games.begin(), games.end(), GameSettings(GameSettings::tes5)) == games.end())
|
||||
games.push_back(GameSettings(GameSettings::tes5));
|
||||
|
||||
if (find(games.begin(), games.end(), GameSettings(GameSettings::fo3)) == games.end())
|
||||
games.push_back(GameSettings(GameSettings::fo3));
|
||||
|
||||
if (find(games.begin(), games.end(), GameSettings(GameSettings::fonv)) == games.end())
|
||||
games.push_back(GameSettings(GameSettings::fonv));
|
||||
|
||||
if (find(games.begin(), games.end(), GameSettings(GameSettings::fo4)) == games.end())
|
||||
games.push_back(GameSettings(GameSettings::fo4));
|
||||
|
||||
// If there were any missing defaults, make sure they're in settings now.
|
||||
settings["games"] = games;
|
||||
|
||||
return games;
|
||||
}
|
||||
}
|
||||
|
||||
namespace YAML {
|
||||
|
||||
@@ -85,8 +85,6 @@ namespace loot {
|
||||
|
||||
boost::filesystem::path _gamePath; //Path to the game's folder.
|
||||
};
|
||||
|
||||
std::list<GameSettings> GetGameSettings(YAML::Node& settings);
|
||||
}
|
||||
|
||||
namespace YAML {
|
||||
|
||||
+20
-53
@@ -160,12 +160,12 @@ namespace loot {
|
||||
return true;
|
||||
}
|
||||
else if (request == "cancelSort") {
|
||||
--_lootState.numUnappliedChanges;
|
||||
_lootState.decrementUnappliedChangeCounter();
|
||||
callback->Success("");
|
||||
return true;
|
||||
}
|
||||
else if (request == "editorOpened") {
|
||||
++_lootState.numUnappliedChanges;
|
||||
_lootState.incrementUnappliedChangeCounter();
|
||||
callback->Success("");
|
||||
return true;
|
||||
}
|
||||
@@ -173,7 +173,7 @@ namespace loot {
|
||||
// This version of the editorClosed query has no arguments as it is
|
||||
// sent when editing is cancelled. Just update the unapplied changes
|
||||
// counter.
|
||||
--_lootState.numUnappliedChanges;
|
||||
_lootState.decrementUnappliedChangeCounter();
|
||||
callback->Success("");
|
||||
return true;
|
||||
}
|
||||
@@ -253,7 +253,7 @@ namespace loot {
|
||||
// One argument, which is the plugin metadata that has changed (+ its name).
|
||||
try {
|
||||
callback->Success(ApplyUserEdits(request["args"][0]));
|
||||
--_lootState.numUnappliedChanges;
|
||||
_lootState.decrementUnappliedChangeCounter();
|
||||
}
|
||||
catch (loot::error &e) {
|
||||
BOOST_LOG_TRIVIAL(error) << "Failed to apply plugin metadata. Details: " << e.what();
|
||||
@@ -275,20 +275,16 @@ namespace loot {
|
||||
else if (requestName == "closeSettings") {
|
||||
BOOST_LOG_TRIVIAL(trace) << "Settings dialog closed and changes accepted, updating settings object.";
|
||||
|
||||
// Update the game details and settings.
|
||||
_lootState.UpdateSettings(request["args"][0]);
|
||||
// Update the settings.
|
||||
_lootState.load(request["args"][0]);
|
||||
// If the user has deleted a default game, we don't want to restore it now.
|
||||
// It will be restored when LOOT is next loaded.
|
||||
try {
|
||||
BOOST_LOG_TRIVIAL(trace) << "Updating games object.";
|
||||
list<GameSettings> games(request["args"][0]["games"].as< list<GameSettings> >());
|
||||
_lootState.UpdateGames(games);
|
||||
_lootState.UpdateGamesFromSettings();
|
||||
|
||||
// Also enable/disable debug logging as required.
|
||||
if (request["args"][0]["enableDebugLogging"] && request["args"][0]["enableDebugLogging"].as<bool>())
|
||||
boost::log::core::get()->set_logging_enabled(true);
|
||||
else
|
||||
boost::log::core::get()->set_logging_enabled(false);
|
||||
boost::log::core::get()->set_logging_enabled(_lootState.isDebugLoggingEnabled());
|
||||
|
||||
// Now send back the new list of installed games to the UI.
|
||||
BOOST_LOG_TRIVIAL(trace) << "Getting new list of installed games.";
|
||||
@@ -301,7 +297,7 @@ namespace loot {
|
||||
return true;
|
||||
}
|
||||
else if (requestName == "applySort") {
|
||||
--_lootState.numUnappliedChanges;
|
||||
_lootState.decrementUnappliedChangeCounter();
|
||||
BOOST_LOG_TRIVIAL(trace) << "User has accepted sorted load order, applying it.";
|
||||
try {
|
||||
_lootState.CurrentGame().SetLoadOrder(request["args"][0].as<list<string>>());
|
||||
@@ -381,11 +377,7 @@ namespace loot {
|
||||
// Has two args: the first is the filter ID, the second is the value.
|
||||
BOOST_LOG_TRIVIAL(trace) << "Saving filter states.";
|
||||
try {
|
||||
YAML::Node settings = _lootState.GetSettings();
|
||||
|
||||
settings["filters"][request["args"][0].as<string>()] = request["args"][1];
|
||||
|
||||
_lootState.UpdateSettings(settings);
|
||||
_lootState.storeFilterState(request["args"][0].as<string>(), request["args"][1].as<bool>());
|
||||
callback->Success("");
|
||||
}
|
||||
catch (exception &e) {
|
||||
@@ -581,7 +573,7 @@ namespace loot {
|
||||
|
||||
std::string Handler::GetSettings() {
|
||||
BOOST_LOG_TRIVIAL(info) << "Getting LOOT settings.";
|
||||
return JSON::stringify(_lootState.GetSettings());
|
||||
return JSON::stringify(_lootState.toYaml());
|
||||
}
|
||||
|
||||
std::string Handler::GetLanguages() {
|
||||
@@ -779,13 +771,7 @@ namespace loot {
|
||||
}
|
||||
|
||||
SendProgressUpdate(frame, loc::translate("Loading general messages..."));
|
||||
//Set language.
|
||||
unsigned int language;
|
||||
if (_lootState.GetSettings()["language"])
|
||||
language = Language(_lootState.GetSettings()["language"].as<string>()).Code();
|
||||
else
|
||||
language = Language::any;
|
||||
BOOST_LOG_TRIVIAL(info) << "Using message language: " << Language(language).Name();
|
||||
BOOST_LOG_TRIVIAL(info) << "Using message language: " << _lootState.getLanguage().Name();
|
||||
|
||||
//Evaluate any conditions in the global messages.
|
||||
BOOST_LOG_TRIVIAL(debug) << "Evaluating global message conditions.";
|
||||
@@ -801,7 +787,7 @@ namespace loot {
|
||||
try {
|
||||
list<Message>::iterator it = messages.begin();
|
||||
while (it != messages.end()) {
|
||||
if (!it->EvalCondition(_lootState.CurrentGame(), language))
|
||||
if (!it->EvalCondition(_lootState.CurrentGame(), _lootState.getLanguage().Code()))
|
||||
it = messages.erase(it);
|
||||
else
|
||||
++it;
|
||||
@@ -830,14 +816,7 @@ namespace loot {
|
||||
void Handler::UpdateMasterlist(CefRefPtr<CefFrame> frame, CefRefPtr<Callback> callback) {
|
||||
try {
|
||||
BOOST_LOG_TRIVIAL(debug) << "Updating and parsing masterlist.";
|
||||
|
||||
//Set language.
|
||||
unsigned int language;
|
||||
if (_lootState.GetSettings()["language"])
|
||||
language = Language(_lootState.GetSettings()["language"].as<string>()).Code();
|
||||
else
|
||||
language = Language::any;
|
||||
BOOST_LOG_TRIVIAL(info) << "Using message language: " << Language(language).Name();
|
||||
BOOST_LOG_TRIVIAL(info) << "Using message language: " << _lootState.getLanguage().Name();
|
||||
|
||||
// Update / parse masterlist.
|
||||
bool wasChanged = true;
|
||||
@@ -914,7 +893,7 @@ namespace loot {
|
||||
try {
|
||||
list<Message>::iterator it = messages.begin();
|
||||
while (it != messages.end()) {
|
||||
if (!it->EvalCondition(_lootState.CurrentGame(), language))
|
||||
if (!it->EvalCondition(_lootState.CurrentGame(), _lootState.getLanguage().Code()))
|
||||
it = messages.erase(it);
|
||||
else
|
||||
++it;
|
||||
@@ -974,13 +953,7 @@ namespace loot {
|
||||
|
||||
void Handler::SortPlugins(CefRefPtr<CefFrame> frame, CefRefPtr<Callback> callback) {
|
||||
BOOST_LOG_TRIVIAL(info) << "Beginning sorting operation.";
|
||||
//Set language.
|
||||
unsigned int language;
|
||||
if (_lootState.GetSettings()["language"])
|
||||
language = Language(_lootState.GetSettings()["language"].as<string>()).Code();
|
||||
else
|
||||
language = Language::any;
|
||||
BOOST_LOG_TRIVIAL(info) << "Using message language: " << Language(language).Name();
|
||||
BOOST_LOG_TRIVIAL(info) << "Using message language: " << _lootState.getLanguage().Name();
|
||||
|
||||
try {
|
||||
// Always reload all the plugins.
|
||||
@@ -989,7 +962,7 @@ namespace loot {
|
||||
|
||||
//Sort plugins into their load order.
|
||||
PluginSorter sorter;
|
||||
list<Plugin> plugins = sorter.Sort(_lootState.CurrentGame(), language, [this, frame](const string& message) {
|
||||
list<Plugin> plugins = sorter.Sort(_lootState.CurrentGame(), _lootState.getLanguage().Code(), [this, frame](const string& message) {
|
||||
this->SendProgressUpdate(frame, message);
|
||||
});
|
||||
|
||||
@@ -1010,7 +983,7 @@ namespace loot {
|
||||
|
||||
node.push_back(pluginNode);
|
||||
}
|
||||
++_lootState.numUnappliedChanges;
|
||||
_lootState.incrementUnappliedChangeCounter();
|
||||
|
||||
if (node.size() > 0)
|
||||
callback->Success(JSON::stringify(node));
|
||||
@@ -1024,13 +997,7 @@ namespace loot {
|
||||
}
|
||||
|
||||
YAML::Node Handler::GenerateDerivedMetadata(const Plugin& file, const PluginMetadata& masterlist, const PluginMetadata& userlist) {
|
||||
//Set language.
|
||||
unsigned int language;
|
||||
if (_lootState.GetSettings()["language"])
|
||||
language = Language(_lootState.GetSettings()["language"].as<string>()).Code();
|
||||
else
|
||||
language = Language::any;
|
||||
BOOST_LOG_TRIVIAL(info) << "Using message language: " << Language(language).Name();
|
||||
BOOST_LOG_TRIVIAL(info) << "Using message language: " << _lootState.getLanguage().Name();
|
||||
|
||||
// Now rederive the displayed metadata from the masterlist and userlist.
|
||||
Plugin tempPlugin(file);
|
||||
@@ -1041,7 +1008,7 @@ namespace loot {
|
||||
//Evaluate any conditions
|
||||
BOOST_LOG_TRIVIAL(trace) << "Evaluate conditions for merged plugin data.";
|
||||
try {
|
||||
tempPlugin.EvalAllConditions(_lootState.CurrentGame(), language);
|
||||
tempPlugin.EvalAllConditions(_lootState.CurrentGame(), _lootState.getLanguage().Code());
|
||||
}
|
||||
catch (std::exception& e) {
|
||||
BOOST_LOG_TRIVIAL(error) << "\"" << tempPlugin.Name() << "\" contains a condition that could not be evaluated. Details: " << e.what();
|
||||
|
||||
@@ -96,15 +96,13 @@ namespace loot {
|
||||
// Need to set the global locale for this process so that messages will
|
||||
// be translated.
|
||||
BOOST_LOG_TRIVIAL(debug) << "Initialising language settings in UI thread.";
|
||||
const YAML::Node& settings = lootState.GetSettings();
|
||||
if (settings["language"] && settings["language"].as<string>() != Language(Language::english).Locale()) {
|
||||
if (lootState.getLanguage().Code() != Language::english) {
|
||||
boost::locale::generator gen;
|
||||
gen.add_messages_path(g_path_l10n.string());
|
||||
gen.add_messages_domain("loot");
|
||||
|
||||
loot::Language lang(settings["language"].as<string>());
|
||||
BOOST_LOG_TRIVIAL(debug) << "Selected language: " << lang.Name();
|
||||
locale::global(gen(lang.Locale() + ".UTF-8"));
|
||||
BOOST_LOG_TRIVIAL(debug) << "Selected language: " << lootState.getLanguage().Name();
|
||||
locale::global(gen(lootState.getLanguage().Locale() + ".UTF-8"));
|
||||
boost::filesystem::path::imbue(locale());
|
||||
}
|
||||
|
||||
|
||||
+18
-17
@@ -97,15 +97,13 @@ namespace loot {
|
||||
#endif
|
||||
|
||||
// Set window size & position.
|
||||
YAML::Node settings = _lootState.GetSettings();
|
||||
|
||||
if (settings["window"]["left"] && settings["window"]["top"] && settings["window"]["right"] && settings["window"]["bottom"]) {
|
||||
if (_lootState.isWindowPositionStored()) {
|
||||
#ifdef _WIN32
|
||||
RECT rc;
|
||||
rc.left = settings["window"]["left"].as<long>();
|
||||
rc.top = settings["window"]["top"].as<long>();
|
||||
rc.right = settings["window"]["right"].as<long>();
|
||||
rc.bottom = settings["window"]["bottom"].as<long>();
|
||||
rc.left = _lootState.getWindowPosition().left;
|
||||
rc.top = _lootState.getWindowPosition().top;
|
||||
rc.right = _lootState.getWindowPosition().right;
|
||||
rc.bottom = _lootState.getWindowPosition().bottom;
|
||||
|
||||
// Fit the saved window size/position to the current monitor setup.
|
||||
|
||||
@@ -154,7 +152,7 @@ namespace loot {
|
||||
assert(CefCurrentlyOn(TID_UI));
|
||||
|
||||
// Check if unapplied changes exist.
|
||||
if (_lootState.numUnappliedChanges > 0) {
|
||||
if (_lootState.hasUnappliedChanges()) {
|
||||
browser->GetMainFrame()->ExecuteJavaScript("onQuit();", browser->GetMainFrame()->GetURL(), 0);
|
||||
return true;
|
||||
}
|
||||
@@ -175,21 +173,24 @@ namespace loot {
|
||||
void LootHandler::OnBeforeClose(CefRefPtr<CefBrowser> browser) {
|
||||
assert(CefCurrentlyOn(TID_UI));
|
||||
|
||||
// Save window size & position.
|
||||
YAML::Node settings = _lootState.GetSettings();
|
||||
|
||||
#ifdef _WIN32
|
||||
RECT rc;
|
||||
GetWindowRect(browser->GetHost()->GetWindowHandle(), &rc);
|
||||
|
||||
settings["window"]["left"] = rc.left;
|
||||
settings["window"]["top"] = rc.top;
|
||||
settings["window"]["right"] = rc.right;
|
||||
settings["window"]["bottom"] = rc.bottom;
|
||||
LootSettings::WindowPosition position;
|
||||
position.top = rc.top;
|
||||
position.bottom = rc.bottom;
|
||||
position.left = rc.left;
|
||||
position.right = rc.right;
|
||||
_lootState.storeWindowPosition(position);
|
||||
#endif
|
||||
|
||||
_lootState.UpdateSettings(settings);
|
||||
_lootState.SaveSettings();
|
||||
try {
|
||||
_lootState.save(g_path_settings);
|
||||
}
|
||||
catch (std::exception &e) {
|
||||
BOOST_LOG_TRIVIAL(error) << "Failed to save LOOT's settings. Error: " << e.what();
|
||||
}
|
||||
|
||||
// Cancel any javascript callbacks.
|
||||
browser_side_router_->OnBeforeClose(browser);
|
||||
|
||||
@@ -0,0 +1,295 @@
|
||||
/* LOOT
|
||||
|
||||
A load order optimisation tool for Oblivion, Skyrim, Fallout 3 and
|
||||
Fallout: New Vegas.
|
||||
|
||||
Copyright (C) 2014-2015 WrinklyNinja
|
||||
|
||||
This file is part of LOOT.
|
||||
|
||||
LOOT is free software: you can redistribute
|
||||
it and/or modify it under the terms of the GNU General Public License
|
||||
as published by the Free Software Foundation, either version 3 of
|
||||
the License, or (at your option) any later version.
|
||||
|
||||
LOOT is distributed in the hope that it will
|
||||
be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with LOOT. If not, see
|
||||
<http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#include "loot_settings.h"
|
||||
#include "backend/globals.h"
|
||||
|
||||
#include <thread>
|
||||
|
||||
#include <boost/filesystem/fstream.hpp>
|
||||
|
||||
using namespace std;
|
||||
|
||||
namespace loot {
|
||||
LootSettings::WindowPosition::WindowPosition() : top(0), bottom(0), left(0), right(0) {}
|
||||
|
||||
LootSettings::LootSettings() :
|
||||
gameSettings({
|
||||
GameSettings(GameSettings::tes4),
|
||||
GameSettings(GameSettings::tes5),
|
||||
GameSettings(GameSettings::fo3),
|
||||
GameSettings(GameSettings::fonv),
|
||||
GameSettings(GameSettings::fo4),
|
||||
GameSettings(GameSettings::tes4, "Nehrim")
|
||||
.SetName("Nehrim - At Fate's Edge")
|
||||
.SetMaster("Nehrim.esm")
|
||||
.SetRegistryKey("Software\\Microsoft\\Windows\\CurrentVersion\\Uninstall\\Nehrim - At Fate's Edge_is1\\InstallLocation"),
|
||||
}),
|
||||
enableDebugLogging(false),
|
||||
updateMasterlist(true),
|
||||
game("auto"),
|
||||
language(Language(Language::english)),
|
||||
lastGame("auto"),
|
||||
lastVersion(std::to_string(g_version_major) + "." + std::to_string(g_version_minor) + "." + std::to_string(g_version_patch)) {}
|
||||
|
||||
void LootSettings::load(YAML::Node& settings) {
|
||||
std::lock_guard<std::recursive_mutex> guard(mutex);
|
||||
|
||||
upgradeYaml(settings);
|
||||
|
||||
if (settings["enableDebugLogging"])
|
||||
enableDebugLogging = settings["enableDebugLogging"].as<bool>();
|
||||
if (settings["updateMasterlist"])
|
||||
updateMasterlist = settings["updateMasterlist"].as<bool>();
|
||||
if (settings["game"])
|
||||
game = settings["game"].as<string>();
|
||||
if (settings["language"])
|
||||
language = Language(settings["language"].as<string>());
|
||||
if (settings["lastGame"])
|
||||
lastGame = settings["lastGame"].as<string>();
|
||||
if (settings["lastVersion"])
|
||||
lastVersion = settings["lastVersion"].as<string>();
|
||||
|
||||
if (settings["window"]
|
||||
&& settings["window"]["top"] && settings["window"]["bottom"]
|
||||
&& settings["window"]["left"] && settings["window"]["right"]) {
|
||||
windowPosition.top = settings["window"]["top"].as<long>();
|
||||
windowPosition.bottom = settings["window"]["bottom"].as<long>();
|
||||
windowPosition.left = settings["window"]["left"].as<long>();
|
||||
windowPosition.right = settings["window"]["right"].as<long>();
|
||||
}
|
||||
|
||||
if (settings["games"]) {
|
||||
gameSettings = settings["games"].as<vector<GameSettings>>();
|
||||
|
||||
// If a base game isn't in the settings, add it.
|
||||
if (find(begin(gameSettings), end(gameSettings), GameSettings(GameSettings::tes4)) == end(gameSettings))
|
||||
gameSettings.push_back(GameSettings(GameSettings::tes4));
|
||||
|
||||
if (find(begin(gameSettings), end(gameSettings), GameSettings(GameSettings::tes5)) == end(gameSettings))
|
||||
gameSettings.push_back(GameSettings(GameSettings::tes5));
|
||||
|
||||
if (find(begin(gameSettings), end(gameSettings), GameSettings(GameSettings::fo3)) == end(gameSettings))
|
||||
gameSettings.push_back(GameSettings(GameSettings::fo3));
|
||||
|
||||
if (find(begin(gameSettings), end(gameSettings), GameSettings(GameSettings::fonv)) == end(gameSettings))
|
||||
gameSettings.push_back(GameSettings(GameSettings::fonv));
|
||||
|
||||
if (find(begin(gameSettings), end(gameSettings), GameSettings(GameSettings::fo4)) == end(gameSettings))
|
||||
gameSettings.push_back(GameSettings(GameSettings::fo4));
|
||||
}
|
||||
|
||||
if (settings["filters"])
|
||||
filters = settings["filters"].as<map<string, bool>>();
|
||||
}
|
||||
|
||||
void LootSettings::load(const boost::filesystem::path& file) {
|
||||
boost::filesystem::ifstream in(file);
|
||||
YAML::Node content = YAML::Load(in);
|
||||
load(content);
|
||||
}
|
||||
|
||||
void LootSettings::save(const boost::filesystem::path& file) {
|
||||
std::lock_guard<std::recursive_mutex> guard(mutex);
|
||||
|
||||
YAML::Emitter yout;
|
||||
yout.SetIndent(2);
|
||||
yout << toYaml();
|
||||
|
||||
boost::filesystem::ofstream out(file);
|
||||
out << yout.c_str();
|
||||
}
|
||||
|
||||
bool LootSettings::isDebugLoggingEnabled() const {
|
||||
std::lock_guard<std::recursive_mutex> guard(mutex);
|
||||
|
||||
return enableDebugLogging;
|
||||
}
|
||||
|
||||
bool LootSettings::isWindowPositionStored() const {
|
||||
std::lock_guard<std::recursive_mutex> guard(mutex);
|
||||
|
||||
return windowPosition.top != 0 || windowPosition.bottom != 0 || windowPosition.left != 0 || windowPosition.right != 0;
|
||||
}
|
||||
|
||||
std::string LootSettings::getGame() const {
|
||||
std::lock_guard<std::recursive_mutex> guard(mutex);
|
||||
|
||||
return game;
|
||||
}
|
||||
|
||||
std::string LootSettings::getLastGame() const {
|
||||
std::lock_guard<std::recursive_mutex> guard(mutex);
|
||||
|
||||
return lastGame;
|
||||
}
|
||||
|
||||
std::string LootSettings::getLastVersion() const {
|
||||
std::lock_guard<std::recursive_mutex> guard(mutex);
|
||||
|
||||
return lastVersion;
|
||||
}
|
||||
|
||||
const Language& LootSettings::getLanguage() const {
|
||||
std::lock_guard<std::recursive_mutex> guard(mutex);
|
||||
|
||||
return language;
|
||||
}
|
||||
|
||||
const LootSettings::WindowPosition& LootSettings::getWindowPosition() const {
|
||||
std::lock_guard<std::recursive_mutex> guard(mutex);
|
||||
|
||||
return windowPosition;
|
||||
}
|
||||
|
||||
std::vector<GameSettings> LootSettings::getGameSettings() const {
|
||||
std::lock_guard<std::recursive_mutex> guard(mutex);
|
||||
|
||||
return gameSettings;
|
||||
}
|
||||
|
||||
void LootSettings::storeLastGame(const std::string& lastGame) {
|
||||
std::lock_guard<std::recursive_mutex> guard(mutex);
|
||||
|
||||
this->lastGame = lastGame;
|
||||
}
|
||||
|
||||
void LootSettings::storeWindowPosition(const WindowPosition& position) {
|
||||
std::lock_guard<std::recursive_mutex> guard(mutex);
|
||||
|
||||
windowPosition = position;
|
||||
}
|
||||
|
||||
void LootSettings::storeGameSettings(const std::vector<GameSettings>& gameSettings) {
|
||||
std::lock_guard<std::recursive_mutex> guard(mutex);
|
||||
|
||||
this->gameSettings = gameSettings;
|
||||
}
|
||||
|
||||
void LootSettings::storeFilterState(const std::string& filterId, bool enabled) {
|
||||
std::lock_guard<std::recursive_mutex> guard(mutex);
|
||||
|
||||
filters[filterId] = enabled;
|
||||
}
|
||||
|
||||
void LootSettings::updateLastVersion() {
|
||||
std::lock_guard<std::recursive_mutex> guard(mutex);
|
||||
|
||||
lastVersion = std::to_string(g_version_major) + "." + std::to_string(g_version_minor) + "." + std::to_string(g_version_patch);
|
||||
}
|
||||
|
||||
YAML::Node LootSettings::toYaml() const {
|
||||
std::lock_guard<std::recursive_mutex> guard(mutex);
|
||||
|
||||
YAML::Node node;
|
||||
|
||||
node["enableDebugLogging"] = enableDebugLogging;
|
||||
node["updateMasterlist"] = updateMasterlist;
|
||||
node["game"] = game;
|
||||
node["language"] = language.Locale();
|
||||
node["lastGame"] = lastGame;
|
||||
node["lastVersion"] = lastVersion;
|
||||
|
||||
if (isWindowPositionStored()) {
|
||||
node["window"]["top"] = windowPosition.top;
|
||||
node["window"]["bottom"] = windowPosition.bottom;
|
||||
node["window"]["left"] = windowPosition.left;
|
||||
node["window"]["right"] = windowPosition.right;
|
||||
}
|
||||
|
||||
node["games"] = gameSettings;
|
||||
|
||||
if (!filters.empty())
|
||||
node["filters"] = filters;
|
||||
|
||||
return node;
|
||||
}
|
||||
|
||||
void LootSettings::upgradeYaml(YAML::Node& yaml) {
|
||||
// Upgrade YAML settings' keys and values from those used in earlier
|
||||
// versions of LOOT.
|
||||
|
||||
if (yaml["Debug Verbosity"] && !yaml["enableDebugLogging"])
|
||||
yaml["enableDebugLogging"] = yaml["Debug Verbosity"].as<unsigned int>() > 0;
|
||||
|
||||
if (yaml["Update Masterlist"] && !yaml["updateMasterlist"])
|
||||
yaml["updateMasterlist"] = yaml["Update Masterlist"];
|
||||
|
||||
if (yaml["Game"] && !yaml["game"])
|
||||
yaml["game"] = yaml["Game"];
|
||||
|
||||
if (yaml["Language"] && !yaml["language"])
|
||||
yaml["language"] = yaml["Language"];
|
||||
|
||||
if (yaml["Last Game"] && !yaml["lastGame"])
|
||||
yaml["lastGame"] = yaml["Last Game"];
|
||||
|
||||
if (yaml["Games"] && !yaml["games"]) {
|
||||
yaml["games"] = yaml["Games"];
|
||||
|
||||
for (auto node : yaml["games"]) {
|
||||
if (node["url"]) {
|
||||
node["repo"] = node["url"];
|
||||
node["branch"] = "v0.8";
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (yaml["games"]) {
|
||||
const set<string> oldDefaultBranches({
|
||||
"master",
|
||||
"v0.7",
|
||||
});
|
||||
|
||||
// Handle exception if YAML is invalid, eg. if an unrecognised
|
||||
// game type is used (which can happen if downgrading from a
|
||||
// later version of LOOT that supports more game types).
|
||||
// However, can't remove elements from a sequence Node, so have to
|
||||
// copy the valid elements into a new node then overwrite the
|
||||
// original.
|
||||
YAML::Node validGames;
|
||||
for (auto node : yaml["games"]) {
|
||||
try {
|
||||
GameSettings settings(node.as<GameSettings>());
|
||||
|
||||
if (!yaml["Games"]) {
|
||||
// Update existing default branch, if the default
|
||||
// repositories are used.
|
||||
if (settings.RepoURL() == GameSettings(settings.Id()).RepoURL()
|
||||
&& oldDefaultBranches.count(settings.RepoBranch()) == 1) {
|
||||
settings.SetRepoBranch("v0.8");
|
||||
}
|
||||
}
|
||||
|
||||
validGames.push_back(settings);
|
||||
}
|
||||
catch (...) {}
|
||||
}
|
||||
yaml["games"] = validGames;
|
||||
}
|
||||
|
||||
if (yaml["filters"])
|
||||
yaml["filters"].remove("contentFilter");
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,90 @@
|
||||
/* LOOT
|
||||
|
||||
A load order optimisation tool for Oblivion, Skyrim, Fallout 3 and
|
||||
Fallout: New Vegas.
|
||||
|
||||
Copyright (C) 2014-2015 WrinklyNinja
|
||||
|
||||
This file is part of LOOT.
|
||||
|
||||
LOOT is free software: you can redistribute
|
||||
it and/or modify it under the terms of the GNU General Public License
|
||||
as published by the Free Software Foundation, either version 3 of
|
||||
the License, or (at your option) any later version.
|
||||
|
||||
LOOT is distributed in the hope that it will
|
||||
be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with LOOT. If not, see
|
||||
<http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#ifndef LOOT_GUI_LOOT_SETTINGS
|
||||
#define LOOT_GUI_LOOT_SETTINGS
|
||||
|
||||
#include "backend/game/game_settings.h"
|
||||
#include "backend/helpers/language.h"
|
||||
|
||||
#include <map>
|
||||
#include <mutex>
|
||||
#include <string>
|
||||
#include <vector>
|
||||
|
||||
#include <boost/filesystem.hpp>
|
||||
#include <yaml-cpp/yaml.h>
|
||||
|
||||
namespace loot {
|
||||
class LootSettings {
|
||||
public:
|
||||
struct WindowPosition {
|
||||
WindowPosition();
|
||||
|
||||
long top;
|
||||
long bottom;
|
||||
long left;
|
||||
long right;
|
||||
};
|
||||
|
||||
LootSettings();
|
||||
|
||||
void load(YAML::Node& settings);
|
||||
void load(const boost::filesystem::path& file);
|
||||
void save(const boost::filesystem::path& file);
|
||||
|
||||
bool isDebugLoggingEnabled() const;
|
||||
bool isWindowPositionStored() const;
|
||||
std::string getGame() const;
|
||||
std::string getLastGame() const;
|
||||
std::string getLastVersion() const;
|
||||
const Language& getLanguage() const;
|
||||
const WindowPosition& getWindowPosition() const;
|
||||
std::vector<GameSettings> getGameSettings() const;
|
||||
|
||||
void storeLastGame(const std::string& lastGame);
|
||||
void storeWindowPosition(const WindowPosition& position);
|
||||
void storeGameSettings(const std::vector<GameSettings>& gameSettings);
|
||||
void storeFilterState(const std::string& filterId, bool enabled);
|
||||
void updateLastVersion();
|
||||
|
||||
YAML::Node toYaml() const;
|
||||
private:
|
||||
bool enableDebugLogging;
|
||||
bool updateMasterlist;
|
||||
std::string game;
|
||||
std::string lastGame;
|
||||
std::string lastVersion;
|
||||
Language language;
|
||||
WindowPosition windowPosition;
|
||||
std::vector<GameSettings> gameSettings;
|
||||
std::map<std::string, bool> filters;
|
||||
|
||||
mutable std::recursive_mutex mutex;
|
||||
|
||||
static void upgradeYaml(YAML::Node& yaml);
|
||||
};
|
||||
}
|
||||
|
||||
#endif
|
||||
+56
-209
@@ -39,6 +39,10 @@
|
||||
#include <boost/log/utility/setup/common_attributes.hpp>
|
||||
#include <boost/log/support/date_time.hpp>
|
||||
|
||||
#ifdef _WIN32
|
||||
#include <windows.h>
|
||||
#endif
|
||||
|
||||
using namespace std;
|
||||
using boost::locale::translate;
|
||||
using boost::format;
|
||||
@@ -46,7 +50,7 @@ using boost::format;
|
||||
namespace fs = boost::filesystem;
|
||||
|
||||
namespace loot {
|
||||
LootState::LootState() : numUnappliedChanges(0), _currentGame(_games.end()) {}
|
||||
LootState::LootState() : unappliedChangeCounter(0), _currentGame(_games.end()) {}
|
||||
|
||||
void LootState::Init(const std::string& cmdLineGame) {
|
||||
// Do some preliminary locale / UTF-8 support setup here, in case the settings file reading requires it.
|
||||
@@ -71,39 +75,26 @@ namespace loot {
|
||||
}
|
||||
if (fs::exists(g_path_settings)) {
|
||||
try {
|
||||
fs::ifstream in(g_path_settings);
|
||||
_settings = YAML::Load(in);
|
||||
in.close();
|
||||
load(g_path_settings);
|
||||
}
|
||||
catch (exception& e) {
|
||||
_initErrors.push_back((format(translate("Error: Settings parsing failed. %1%")) % e.what()).str());
|
||||
}
|
||||
}
|
||||
// Check if the settings are valid (or if they don't exist).
|
||||
if (!AreSettingsValid()) {
|
||||
_settings = GetDefaultSettings();
|
||||
}
|
||||
|
||||
//Set up logging.
|
||||
boost::log::add_file_log(
|
||||
boost::log::keywords::file_name = g_path_log.string().c_str(),
|
||||
boost::log::keywords::auto_flush = true,
|
||||
boost::log::keywords::format = (
|
||||
boost::log::expressions::stream
|
||||
<< "[" << boost::log::expressions::format_date_time< boost::posix_time::ptime >("TimeStamp", "%H:%M:%S") << "]"
|
||||
<< " [" << boost::log::trivial::severity << "]: "
|
||||
<< boost::log::expressions::smessage
|
||||
)
|
||||
boost::log::expressions::stream
|
||||
<< "[" << boost::log::expressions::format_date_time< boost::posix_time::ptime >("TimeStamp", "%H:%M:%S") << "]"
|
||||
<< " [" << boost::log::trivial::severity << "]: "
|
||||
<< boost::log::expressions::smessage
|
||||
)
|
||||
);
|
||||
boost::log::add_common_attributes();
|
||||
bool enableDebugLogging = false;
|
||||
if (_settings["enableDebugLogging"]) {
|
||||
enableDebugLogging = _settings["enableDebugLogging"].as<bool>();
|
||||
}
|
||||
if (enableDebugLogging)
|
||||
boost::log::core::get()->set_logging_enabled(true);
|
||||
else
|
||||
boost::log::core::get()->set_logging_enabled(false);
|
||||
boost::log::core::get()->set_logging_enabled(isDebugLoggingEnabled());
|
||||
|
||||
// Log some useful info.
|
||||
BOOST_LOG_TRIVIAL(info) << "LOOT Version: " << g_version_major << "." << g_version_minor << "." << g_version_patch;
|
||||
@@ -121,9 +112,9 @@ namespace loot {
|
||||
fs::remove(g_path_local / "CEFDebugLog.txt");
|
||||
|
||||
// Now that settings have been loaded, set the locale again to handle translations.
|
||||
if (_settings["language"] && _settings["language"].as<string>() != Language(Language::english).Locale()) {
|
||||
if (getLanguage().Code() != Language::english) {
|
||||
BOOST_LOG_TRIVIAL(debug) << "Initialising language settings.";
|
||||
loot::Language lang(_settings["language"].as<string>());
|
||||
loot::Language lang(getLanguage());
|
||||
BOOST_LOG_TRIVIAL(debug) << "Selected language: " << lang.Name();
|
||||
|
||||
//Boost.Locale initialisation: Generate and imbue locales.
|
||||
@@ -136,17 +127,7 @@ namespace loot {
|
||||
|
||||
//Detect installed games.
|
||||
BOOST_LOG_TRIVIAL(debug) << "Detecting installed games.";
|
||||
try {
|
||||
_games = ToGames(GetGameSettings(_settings));
|
||||
}
|
||||
catch (YAML::Exception& e) {
|
||||
BOOST_LOG_TRIVIAL(error) << "Games' settings parsing failed. " << e.what();
|
||||
_initErrors.push_back((format(translate("Error: Games' settings parsing failed. %1%")) % e.what()).str());
|
||||
// Now redo, but with no games settings, so only the hardcoded defaults get loaded. It means the user can
|
||||
// at least still then edit them.
|
||||
YAML::Node node;
|
||||
_games = ToGames(GetGameSettings(node));
|
||||
}
|
||||
_games = ToGames(getGameSettings());
|
||||
|
||||
try {
|
||||
BOOST_LOG_TRIVIAL(debug) << "Selecting game.";
|
||||
@@ -154,7 +135,7 @@ namespace loot {
|
||||
BOOST_LOG_TRIVIAL(debug) << "Initialising game-specific settings.";
|
||||
_currentGame->Init(true);
|
||||
// Update game path in settings object.
|
||||
_settings["games"] = ToGameSettings(_games);
|
||||
storeGameSettings(ToGameSettings(_games));
|
||||
}
|
||||
catch (loot::error &e) {
|
||||
if (e.code() == loot::error::no_game_detected) {
|
||||
@@ -172,15 +153,20 @@ namespace loot {
|
||||
return _initErrors;
|
||||
}
|
||||
|
||||
void LootState::UpdateGames(std::list<GameSettings>& games) {
|
||||
// Acquire the lock for the scope of this method.
|
||||
base::AutoLock lock_scope(_lock);
|
||||
void LootState::save(const boost::filesystem::path & file) {
|
||||
storeLastGame(_currentGame->FolderName());
|
||||
updateLastVersion();
|
||||
LootSettings::save(file);
|
||||
}
|
||||
|
||||
void LootState::UpdateGamesFromSettings() {
|
||||
std::lock_guard<std::mutex> guard(mutex);
|
||||
|
||||
unordered_set<string> newGameFolders;
|
||||
|
||||
// Update existing games, add new games.
|
||||
BOOST_LOG_TRIVIAL(trace) << "Updating existing games and adding new games.";
|
||||
for (auto &game : games) {
|
||||
for (const auto &game : getGameSettings()) {
|
||||
auto pos = find(_games.begin(), _games.end(), game);
|
||||
|
||||
if (pos != _games.end()) {
|
||||
@@ -214,25 +200,23 @@ namespace loot {
|
||||
// Re-initialise the current game in case the game path setting was changed.
|
||||
_currentGame->Init(true);
|
||||
// Update game path in settings object.
|
||||
_settings["games"] = ToGameSettings(_games);
|
||||
storeGameSettings(ToGameSettings(_games));
|
||||
}
|
||||
|
||||
void LootState::ChangeGame(const std::string& newGameFolder) {
|
||||
// Acquire the lock for the scope of this method.
|
||||
base::AutoLock lock_scope(_lock);
|
||||
std::lock_guard<std::mutex> guard(mutex);
|
||||
|
||||
BOOST_LOG_TRIVIAL(debug) << "Changing current game to that with folder: " << newGameFolder;
|
||||
_currentGame = find(_games.begin(), _games.end(), Game(Game::autodetect, newGameFolder));
|
||||
_currentGame->Init(true);
|
||||
|
||||
// Update game path in settings object.
|
||||
_settings["games"] = ToGameSettings(_games);
|
||||
storeGameSettings(ToGameSettings(_games));
|
||||
BOOST_LOG_TRIVIAL(debug) << "New game is " << _currentGame->Name();
|
||||
}
|
||||
|
||||
Game& LootState::CurrentGame() {
|
||||
// Acquire the lock for the scope of this method.
|
||||
base::AutoLock lock_scope(_lock);
|
||||
std::lock_guard<std::mutex> guard(mutex);
|
||||
|
||||
return *_currentGame;
|
||||
}
|
||||
@@ -246,186 +230,49 @@ namespace loot {
|
||||
return installedGames;
|
||||
}
|
||||
|
||||
const YAML::Node& LootState::GetSettings() const {
|
||||
return _settings;
|
||||
bool LootState::hasUnappliedChanges() const {
|
||||
return unappliedChangeCounter > 0;
|
||||
}
|
||||
|
||||
void LootState::UpdateSettings(const YAML::Node& settings) {
|
||||
// Acquire the lock for the scope of this method.
|
||||
base::AutoLock lock_scope(_lock);
|
||||
|
||||
_settings = settings;
|
||||
void LootState::incrementUnappliedChangeCounter() {
|
||||
++unappliedChangeCounter;
|
||||
}
|
||||
|
||||
void LootState::SaveSettings() {
|
||||
// Acquire the lock for the scope of this method.
|
||||
base::AutoLock lock_scope(_lock);
|
||||
|
||||
_settings["lastGame"] = _currentGame->FolderName();
|
||||
_settings["lastVersion"] = to_string(g_version_major) + "." + to_string(g_version_minor) + "." + to_string(g_version_patch);
|
||||
|
||||
//Save settings.
|
||||
try {
|
||||
BOOST_LOG_TRIVIAL(debug) << "Saving LOOT settings.";
|
||||
YAML::Emitter yout;
|
||||
yout.SetIndent(2);
|
||||
yout << _settings;
|
||||
|
||||
fs::ofstream out(loot::g_path_settings);
|
||||
out << yout.c_str();
|
||||
out.close();
|
||||
}
|
||||
catch (std::exception &e) {
|
||||
BOOST_LOG_TRIVIAL(error) << "Failed to save LOOT's settings. Error: " << e.what();
|
||||
}
|
||||
void LootState::decrementUnappliedChangeCounter() {
|
||||
--unappliedChangeCounter;
|
||||
}
|
||||
|
||||
void LootState::SelectGame(std::string preferredGame) {
|
||||
if (preferredGame.empty()) {
|
||||
// Get preferred game from settings.
|
||||
if (_settings["game"] && _settings["game"].as<string>() != "auto")
|
||||
preferredGame = _settings["game"].as<string>();
|
||||
else if (_settings["lastGame"] && _settings["lastGame"].as<string>() != "auto")
|
||||
preferredGame = _settings["lastGame"].as<string>();
|
||||
if (getGame() != "auto")
|
||||
preferredGame = getGame();
|
||||
else if (getLastGame() != "auto")
|
||||
preferredGame = getLastGame();
|
||||
}
|
||||
|
||||
// Get iterator to preferred game if there is one.
|
||||
_currentGame = _games.end();
|
||||
for (auto it = _games.begin(); it != _games.end(); ++it) {
|
||||
if ((preferredGame.empty() && it->IsInstalled())
|
||||
|| (!preferredGame.empty() && preferredGame == it->FolderName() && it->IsInstalled())) {
|
||||
_currentGame = it;
|
||||
return;
|
||||
}
|
||||
// Get iterator to preferred game.
|
||||
_currentGame = find_if(begin(_games), end(_games), [&](auto& game) {
|
||||
return (preferredGame.empty() || preferredGame == game.FolderName()) && game.IsInstalled();
|
||||
});
|
||||
// If the preferred game cannot be found, get the first installed game.
|
||||
if (_currentGame == end(_games)) {
|
||||
_currentGame = find_if(begin(_games), end(_games), [](auto& game) {
|
||||
return game.IsInstalled();
|
||||
});
|
||||
}
|
||||
|
||||
// Preferred game not found, just pick the first installed one.
|
||||
for (auto it = _games.begin(); it != _games.end(); ++it) {
|
||||
if (it->IsInstalled()) {
|
||||
_currentGame = it;
|
||||
return;
|
||||
}
|
||||
// If no game can be selected, throw an exception.
|
||||
if (_currentGame == end(_games)) {
|
||||
BOOST_LOG_TRIVIAL(error) << "None of the supported games were detected.";
|
||||
throw error(error::no_game_detected, translate("None of the supported games were detected."));
|
||||
}
|
||||
|
||||
BOOST_LOG_TRIVIAL(error) << "None of the supported games were detected.";
|
||||
throw error(error::no_game_detected, translate("None of the supported games were detected."));
|
||||
}
|
||||
|
||||
bool LootState::AreSettingsValid() {
|
||||
// Acquire the lock for the scope of this method.
|
||||
base::AutoLock lock_scope(_lock);
|
||||
|
||||
if (!_settings["language"]) {
|
||||
if (_settings["Language"]) {
|
||||
// Conversion from 0.6 key.
|
||||
_settings["language"] = _settings["Language"];
|
||||
_settings.remove("Language");
|
||||
}
|
||||
else
|
||||
return false;
|
||||
}
|
||||
if (!_settings["game"]) {
|
||||
if (_settings["Game"]) {
|
||||
// Conversion from 0.6 key.
|
||||
_settings["game"] = _settings["Game"];
|
||||
_settings.remove("Game");
|
||||
}
|
||||
else
|
||||
return false;
|
||||
}
|
||||
if (!_settings["lastGame"]) {
|
||||
if (_settings["Last Game"]) {
|
||||
// Conversion from 0.6 key.
|
||||
_settings["lastGame"] = _settings["Last Game"];
|
||||
_settings.remove("Last Game");
|
||||
}
|
||||
else
|
||||
return false;
|
||||
}
|
||||
if (!_settings["enableDebugLogging"]) {
|
||||
if (_settings["Debug Verbosity"]) {
|
||||
// Conversion from 0.6 key.
|
||||
_settings["enableDebugLogging"] = (_settings["Debug Verbosity"].as<unsigned int>() > 0);
|
||||
_settings.remove("Debug Verbosity");
|
||||
}
|
||||
else if (_settings["debugVerbosity"]) {
|
||||
// Conversion from 0.7 alpha key
|
||||
_settings["enableDebugLogging"] = (_settings["debugVerbosity"].as<unsigned int>() > 0);
|
||||
_settings.remove("debugVerbosity");
|
||||
}
|
||||
else
|
||||
return false;
|
||||
}
|
||||
if (!_settings["updateMasterlist"]) {
|
||||
if (_settings["Update Masterlist"]) {
|
||||
// Conversion from 0.6 key.
|
||||
_settings["updateMasterlist"] = _settings["Update Masterlist"];
|
||||
_settings.remove("Update Masterlist");
|
||||
}
|
||||
else
|
||||
return false;
|
||||
}
|
||||
if (!_settings["games"]) {
|
||||
if (_settings["Games"]) {
|
||||
// Conversion from 0.6 key.
|
||||
_settings["games"] = _settings["Games"];
|
||||
|
||||
for (auto node : _settings["games"]) {
|
||||
if (node["url"]) {
|
||||
node["repo"] = node["url"];
|
||||
node["branch"] = "v0.8";
|
||||
node.remove("url");
|
||||
}
|
||||
}
|
||||
|
||||
_settings.remove("Games");
|
||||
}
|
||||
else
|
||||
return false;
|
||||
}
|
||||
else {
|
||||
// Update existing default branches to new version default, if the
|
||||
// default repositories are used.
|
||||
for (auto node : _settings["games"]) {
|
||||
GameSettings settings(node.as<GameSettings>());
|
||||
|
||||
set<string> oldDefaultBranches({
|
||||
"master",
|
||||
"v0.7",
|
||||
});
|
||||
|
||||
if (settings.RepoURL() == GameSettings(settings.Id()).RepoURL()
|
||||
&& oldDefaultBranches.count(settings.RepoBranch()) == 1) {
|
||||
node["branch"] = "v0.8";
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (_settings["windows"])
|
||||
_settings.remove("windows");
|
||||
|
||||
return true;
|
||||
std::list<Game> LootState::ToGames(const std::vector<GameSettings>& settings) {
|
||||
return list<Game>(settings.begin(), settings.end());
|
||||
}
|
||||
|
||||
YAML::Node LootState::GetDefaultSettings() const {
|
||||
YAML::Node root;
|
||||
|
||||
root["language"] = "en";
|
||||
root["game"] = "auto";
|
||||
root["lastGame"] = "auto";
|
||||
root["enableDebugLogging"] = false;
|
||||
root["updateMasterlist"] = true;
|
||||
|
||||
// Add base game definitions, and Nehrim.
|
||||
GetGameSettings(root);
|
||||
|
||||
GameSettings settings(GameSettings::tes4, "Nehrim");
|
||||
settings.SetName("Nehrim - At Fate's Edge")
|
||||
.SetMaster("Nehrim.esm")
|
||||
.SetRegistryKey("Software\\Microsoft\\Windows\\CurrentVersion\\Uninstall\\Nehrim - At Fate's Edge_is1\\InstallLocation");
|
||||
|
||||
root["games"].push_back(settings);
|
||||
|
||||
return root;
|
||||
std::vector<GameSettings> LootState::ToGameSettings(const std::list<Game>& games) {
|
||||
return vector<GameSettings>(games.begin(), games.end());
|
||||
}
|
||||
}
|
||||
|
||||
+17
-21
@@ -25,49 +25,45 @@
|
||||
#ifndef __LOOT_GUI_LOOT_STATE__
|
||||
#define __LOOT_GUI_LOOT_STATE__
|
||||
|
||||
#include "../backend/game/game.h"
|
||||
|
||||
#include <include/cef_app.h>
|
||||
#include <include/base/cef_lock.h>
|
||||
|
||||
#include <yaml-cpp/yaml.h>
|
||||
#include "loot_settings.h"
|
||||
#include "backend/game/game.h"
|
||||
|
||||
namespace loot {
|
||||
class LootState : public CefBase {
|
||||
class LootState : public LootSettings {
|
||||
public:
|
||||
LootState();
|
||||
|
||||
void Init(const std::string& cmdLineGame);
|
||||
const std::vector<std::string>& InitErrors() const;
|
||||
|
||||
void save(const boost::filesystem::path& file);
|
||||
|
||||
Game& CurrentGame();
|
||||
void ChangeGame(const std::string& newGameFolder);
|
||||
void UpdateGames(std::list<GameSettings>& games);
|
||||
void UpdateGamesFromSettings();
|
||||
|
||||
// Get the folder names of the installed games.
|
||||
std::vector<std::string> InstalledGames();
|
||||
|
||||
const YAML::Node& GetSettings() const;
|
||||
void UpdateSettings(const YAML::Node& settings);
|
||||
void SaveSettings();
|
||||
|
||||
// Used to check if LOOT has unaccepted sorting or metadata changes on quit.
|
||||
int numUnappliedChanges;
|
||||
bool hasUnappliedChanges() const;
|
||||
void incrementUnappliedChangeCounter();
|
||||
void decrementUnappliedChangeCounter();
|
||||
private:
|
||||
YAML::Node _settings;
|
||||
std::list<Game> _games;
|
||||
std::list<Game>::iterator _currentGame;
|
||||
std::vector<std::string> _initErrors;
|
||||
|
||||
// Used to check if LOOT has unaccepted sorting or metadata changes on quit.
|
||||
size_t unappliedChangeCounter;
|
||||
|
||||
// Select initial game.
|
||||
void SelectGame(std::string cmdLineGame);
|
||||
|
||||
// Check if the settings file has the right root keys (doesn't check their values).
|
||||
bool AreSettingsValid();
|
||||
YAML::Node GetDefaultSettings() const;
|
||||
static std::list<Game> ToGames(const std::vector<GameSettings>& settings);
|
||||
static std::vector<GameSettings> ToGameSettings(const std::list<Game>& games);
|
||||
|
||||
// Lock used to protect access to member variables.
|
||||
base::Lock _lock;
|
||||
IMPLEMENT_REFCOUNTING(LootState);
|
||||
// Mutex used to protect access to member variables.
|
||||
std::mutex mutex;
|
||||
};
|
||||
}
|
||||
|
||||
|
||||
@@ -655,48 +655,4 @@ TEST_F(Game, shouldShowBlankEspAsActiveIfItHasBeenFullyLoadedAndTheGameHasBeenIn
|
||||
EXPECT_FALSE(game.IsPluginActive("Blank.esp"));
|
||||
}
|
||||
|
||||
TEST(ToGames, EmptySettings) {
|
||||
EXPECT_EQ(std::list<loot::Game>(), loot::ToGames(std::list<loot::GameSettings>()));
|
||||
}
|
||||
|
||||
TEST(ToGames, NonEmptySettings) {
|
||||
std::list<loot::GameSettings> settings({
|
||||
loot::GameSettings(loot::GameSettings::tes4),
|
||||
loot::GameSettings(loot::GameSettings::tes5),
|
||||
loot::GameSettings(loot::GameSettings::fo3),
|
||||
loot::GameSettings(loot::GameSettings::fonv),
|
||||
});
|
||||
|
||||
std::list<loot::Game> expected({
|
||||
loot::Game(loot::Game::tes4),
|
||||
loot::Game(loot::Game::tes5),
|
||||
loot::Game(loot::Game::fo3),
|
||||
loot::Game(loot::Game::fonv),
|
||||
});
|
||||
|
||||
EXPECT_EQ(expected, loot::ToGames(settings));
|
||||
}
|
||||
|
||||
TEST(ToGameSettings, EmptyGames) {
|
||||
EXPECT_EQ(std::list<loot::GameSettings>(), loot::ToGameSettings(std::list<loot::Game>()));
|
||||
}
|
||||
|
||||
TEST(ToGameSettings, NonEmptyGames) {
|
||||
std::list<loot::Game> games({
|
||||
loot::Game(loot::Game::tes4),
|
||||
loot::Game(loot::Game::tes5),
|
||||
loot::Game(loot::Game::fo3),
|
||||
loot::Game(loot::Game::fonv),
|
||||
});
|
||||
|
||||
std::list<loot::GameSettings> expected({
|
||||
loot::GameSettings(loot::GameSettings::tes4),
|
||||
loot::GameSettings(loot::GameSettings::tes5),
|
||||
loot::GameSettings(loot::GameSettings::fo3),
|
||||
loot::GameSettings(loot::GameSettings::fonv),
|
||||
});
|
||||
|
||||
EXPECT_EQ(expected, loot::ToGameSettings(games));
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
@@ -251,43 +251,4 @@ TEST_F(GameSettings, YamlDecode) {
|
||||
EXPECT_EQ("branch1", game.RepoBranch());
|
||||
EXPECT_EQ("", game.GamePath());
|
||||
}
|
||||
|
||||
TEST(GetGameSettings, AllMissing) {
|
||||
YAML::Node settings;
|
||||
|
||||
std::list<loot::GameSettings> expected = {
|
||||
loot::GameSettings(loot::GameSettings::tes4),
|
||||
loot::GameSettings(loot::GameSettings::tes5),
|
||||
loot::GameSettings(loot::GameSettings::fo3),
|
||||
loot::GameSettings(loot::GameSettings::fonv),
|
||||
loot::GameSettings(loot::GameSettings::fo4)
|
||||
};
|
||||
|
||||
EXPECT_FALSE(settings["games"]);
|
||||
EXPECT_EQ(expected, loot::GetGameSettings(settings));
|
||||
EXPECT_EQ(expected, settings["games"].as<std::list<loot::GameSettings>>());
|
||||
}
|
||||
|
||||
TEST(GetGameSettings, MissingFallout3) {
|
||||
std::list<loot::GameSettings> initial({
|
||||
loot::GameSettings(loot::GameSettings::tes4, "folder1"),
|
||||
loot::GameSettings(loot::GameSettings::tes5, "folder2"),
|
||||
loot::GameSettings(loot::GameSettings::fonv, "folder3"),
|
||||
loot::GameSettings(loot::GameSettings::fo4, "folder4")
|
||||
});
|
||||
|
||||
YAML::Node settings;
|
||||
settings["games"] = initial;
|
||||
|
||||
std::list<loot::GameSettings> expected = {
|
||||
loot::GameSettings(loot::GameSettings::tes4, "folder1"),
|
||||
loot::GameSettings(loot::GameSettings::tes5, "folder2"),
|
||||
loot::GameSettings(loot::GameSettings::fonv, "folder3"),
|
||||
loot::GameSettings(loot::GameSettings::fo4, "folder4"),
|
||||
loot::GameSettings(loot::GameSettings::fo3)
|
||||
};
|
||||
|
||||
EXPECT_EQ(expected, loot::GetGameSettings(settings));
|
||||
EXPECT_EQ(expected, settings["games"].as<std::list<loot::GameSettings>>());
|
||||
}
|
||||
#endif
|
||||
|
||||
@@ -0,0 +1,479 @@
|
||||
/* LOOT
|
||||
|
||||
A load order optimisation tool for Oblivion, Skyrim, Fallout 3 and
|
||||
Fallout: New Vegas.
|
||||
|
||||
Copyright (C) 2014-2015 WrinklyNinja
|
||||
|
||||
This file is part of LOOT.
|
||||
|
||||
LOOT is free software: you can redistribute
|
||||
it and/or modify it under the terms of the GNU General Public License
|
||||
as published by the Free Software Foundation, either version 3 of
|
||||
the License, or (at your option) any later version.
|
||||
|
||||
LOOT is distributed in the hope that it will
|
||||
be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with LOOT. If not, see
|
||||
<http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#ifndef LOOT_TEST_GUI_LOOT_SETTINGS
|
||||
#define LOOT_TEST_GUI_LOOT_SETTINGS
|
||||
|
||||
#include "gui/loot_settings.h"
|
||||
#include "backend/globals.h"
|
||||
|
||||
#include "tests/fixtures.h"
|
||||
|
||||
namespace loot {
|
||||
namespace test {
|
||||
class LootSettings : public ::testing::Test {
|
||||
protected:
|
||||
LootSettings() : settingsFile("./settings.yaml") {}
|
||||
|
||||
~LootSettings() {
|
||||
boost::filesystem::remove(settingsFile);
|
||||
}
|
||||
|
||||
boost::filesystem::path settingsFile;
|
||||
loot::LootSettings settings;
|
||||
};
|
||||
|
||||
TEST_F(LootSettings, defaultConstructorShouldSetDefaultValues) {
|
||||
const std::string currentVersion = std::to_string(g_version_major) + "." + std::to_string(g_version_minor) + "." + std::to_string(g_version_patch);
|
||||
const std::vector<GameSettings> expectedGameSettings({
|
||||
GameSettings(GameSettings::tes4),
|
||||
GameSettings(GameSettings::tes5),
|
||||
GameSettings(GameSettings::fo3),
|
||||
GameSettings(GameSettings::fonv),
|
||||
GameSettings(GameSettings::fo4),
|
||||
GameSettings(GameSettings::tes4, "Nehrim")
|
||||
.SetName("Nehrim - At Fate's Edge")
|
||||
.SetMaster("Nehrim.esm")
|
||||
.SetRegistryKey("Software\\Microsoft\\Windows\\CurrentVersion\\Uninstall\\Nehrim - At Fate's Edge_is1\\InstallLocation"),
|
||||
});
|
||||
|
||||
EXPECT_FALSE(settings.isDebugLoggingEnabled());
|
||||
EXPECT_EQ("auto", settings.getGame());
|
||||
EXPECT_EQ("en", settings.getLanguage().Locale());
|
||||
EXPECT_EQ("auto", settings.getLastGame());
|
||||
EXPECT_FALSE(settings.isWindowPositionStored());
|
||||
|
||||
const YAML::Node node = settings.toYaml();
|
||||
EXPECT_TRUE(node["updateMasterlist"].as<bool>());
|
||||
EXPECT_EQ(currentVersion, node["lastVersion"].as<std::string>());
|
||||
EXPECT_FALSE(node["filters"]);
|
||||
|
||||
// GameSettings equality only checks name and folder, so check
|
||||
// other settings individually.
|
||||
const std::vector<GameSettings> actualGameSettings = settings.getGameSettings();
|
||||
EXPECT_EQ(expectedGameSettings, actualGameSettings);
|
||||
|
||||
EXPECT_EQ(expectedGameSettings[0].Id(), actualGameSettings[0].Id());
|
||||
EXPECT_EQ(expectedGameSettings[0].Master(), actualGameSettings[0].Master());
|
||||
EXPECT_EQ(expectedGameSettings[0].RegistryKey(), actualGameSettings[0].RegistryKey());
|
||||
EXPECT_EQ(expectedGameSettings[0].RepoURL(), actualGameSettings[0].RepoURL());
|
||||
EXPECT_EQ(expectedGameSettings[0].RepoBranch(), actualGameSettings[0].RepoBranch());
|
||||
|
||||
EXPECT_EQ(expectedGameSettings[1].Id(), actualGameSettings[1].Id());
|
||||
EXPECT_EQ(expectedGameSettings[1].Master(), actualGameSettings[1].Master());
|
||||
EXPECT_EQ(expectedGameSettings[1].RegistryKey(), actualGameSettings[1].RegistryKey());
|
||||
EXPECT_EQ(expectedGameSettings[1].RepoURL(), actualGameSettings[1].RepoURL());
|
||||
EXPECT_EQ(expectedGameSettings[1].RepoBranch(), actualGameSettings[1].RepoBranch());
|
||||
|
||||
EXPECT_EQ(expectedGameSettings[2].Id(), actualGameSettings[2].Id());
|
||||
EXPECT_EQ(expectedGameSettings[2].Master(), actualGameSettings[2].Master());
|
||||
EXPECT_EQ(expectedGameSettings[2].RegistryKey(), actualGameSettings[2].RegistryKey());
|
||||
EXPECT_EQ(expectedGameSettings[2].RepoURL(), actualGameSettings[2].RepoURL());
|
||||
EXPECT_EQ(expectedGameSettings[2].RepoBranch(), actualGameSettings[2].RepoBranch());
|
||||
|
||||
EXPECT_EQ(expectedGameSettings[3].Id(), actualGameSettings[3].Id());
|
||||
EXPECT_EQ(expectedGameSettings[3].Master(), actualGameSettings[3].Master());
|
||||
EXPECT_EQ(expectedGameSettings[3].RegistryKey(), actualGameSettings[3].RegistryKey());
|
||||
EXPECT_EQ(expectedGameSettings[3].RepoURL(), actualGameSettings[3].RepoURL());
|
||||
EXPECT_EQ(expectedGameSettings[3].RepoBranch(), actualGameSettings[3].RepoBranch());
|
||||
|
||||
EXPECT_EQ(expectedGameSettings[4].Id(), actualGameSettings[4].Id());
|
||||
EXPECT_EQ(expectedGameSettings[4].Master(), actualGameSettings[4].Master());
|
||||
EXPECT_EQ(expectedGameSettings[4].RegistryKey(), actualGameSettings[4].RegistryKey());
|
||||
EXPECT_EQ(expectedGameSettings[4].RepoURL(), actualGameSettings[4].RepoURL());
|
||||
EXPECT_EQ(expectedGameSettings[4].RepoBranch(), actualGameSettings[4].RepoBranch());
|
||||
|
||||
EXPECT_EQ(expectedGameSettings[5].Id(), actualGameSettings[5].Id());
|
||||
EXPECT_EQ(expectedGameSettings[5].Master(), actualGameSettings[5].Master());
|
||||
EXPECT_EQ(expectedGameSettings[5].RegistryKey(), actualGameSettings[5].RegistryKey());
|
||||
EXPECT_EQ(expectedGameSettings[5].RepoURL(), actualGameSettings[5].RepoURL());
|
||||
EXPECT_EQ(expectedGameSettings[5].RepoBranch(), actualGameSettings[5].RepoBranch());
|
||||
}
|
||||
|
||||
TEST_F(LootSettings, loadingFromFileShouldLoadContentAsYaml) {
|
||||
boost::filesystem::ofstream out(settingsFile);
|
||||
out << "enableDebugLogging: true" << std::endl;
|
||||
out.close();
|
||||
|
||||
settings.load(settingsFile);
|
||||
|
||||
EXPECT_TRUE(settings.isDebugLoggingEnabled());
|
||||
}
|
||||
|
||||
TEST_F(LootSettings, loadingFromYamlShouldStoreLoadedValues) {
|
||||
const bool enableDebugLogging = true;
|
||||
const bool updateMasterlist = true;
|
||||
const std::string game = "Oblivion";
|
||||
const std::string language = "fr";
|
||||
const std::string lastGame = "Skyrim";
|
||||
const std::string lastVersion = "0.7.1";
|
||||
const std::map<std::string, long> window({
|
||||
{"top", 1},
|
||||
{"bottom", 2},
|
||||
{"left", 3},
|
||||
{"right", 4},
|
||||
});
|
||||
const std::vector<GameSettings> games({
|
||||
GameSettings(GameSettings::tes4).SetName("Game Name"),
|
||||
});
|
||||
const std::map<std::string, bool> filters({
|
||||
{"hideBashTags", false},
|
||||
{"hideCRCs", true},
|
||||
});
|
||||
|
||||
YAML::Node inputYaml;
|
||||
inputYaml["enableDebugLogging"] = enableDebugLogging;
|
||||
inputYaml["updateMasterlist"] = updateMasterlist;
|
||||
inputYaml["game"] = game;
|
||||
inputYaml["language"] = language;
|
||||
inputYaml["lastGame"] = lastGame;
|
||||
inputYaml["lastVersion"] = lastVersion;
|
||||
inputYaml["window"] = window;
|
||||
inputYaml["games"] = games;
|
||||
inputYaml["filters"] = filters;
|
||||
|
||||
settings.load(inputYaml);
|
||||
|
||||
EXPECT_EQ(enableDebugLogging, settings.isDebugLoggingEnabled());
|
||||
EXPECT_EQ(game, settings.getGame());
|
||||
EXPECT_EQ(language, settings.getLanguage().Locale());
|
||||
EXPECT_EQ(lastGame, settings.getLastGame());
|
||||
|
||||
EXPECT_EQ(1, settings.getWindowPosition().top);
|
||||
EXPECT_EQ(2, settings.getWindowPosition().bottom);
|
||||
EXPECT_EQ(3, settings.getWindowPosition().left);
|
||||
EXPECT_EQ(4, settings.getWindowPosition().right);
|
||||
|
||||
const YAML::Node outputYaml = settings.toYaml();
|
||||
EXPECT_EQ(updateMasterlist, outputYaml["updateMasterlist"].as<bool>());
|
||||
EXPECT_EQ(lastVersion, outputYaml["lastVersion"].as<std::string>());
|
||||
|
||||
for (const auto& filter : filters) {
|
||||
EXPECT_EQ(filter.second, outputYaml["filters"][filter.first].as<bool>());
|
||||
}
|
||||
|
||||
EXPECT_EQ(games[0].Name(), settings.getGameSettings()[0].Name());
|
||||
}
|
||||
|
||||
TEST_F(LootSettings, loadingFromEmptyYamlShouldNotThrow) {
|
||||
YAML::Node yaml;
|
||||
EXPECT_NO_THROW(settings.load(yaml));
|
||||
}
|
||||
|
||||
TEST_F(LootSettings, loadingFromYamlShouldUpgradeFromVersion0Point6Format) {
|
||||
const unsigned int DebugVerbosity = 3;
|
||||
const bool UpdateMasterlist = true;
|
||||
const std::string Game = "Oblivion";
|
||||
const std::string Language = "fr";
|
||||
const std::string LastGame = "Skyrim";
|
||||
const std::vector<GameSettings> Games({
|
||||
GameSettings(GameSettings::tes4).SetName("Game Name"),
|
||||
});
|
||||
|
||||
YAML::Node inputYaml;
|
||||
inputYaml["Debug Verbosity"] = DebugVerbosity;
|
||||
inputYaml["Update Masterlist"] = UpdateMasterlist;
|
||||
inputYaml["Game"] = Game;
|
||||
inputYaml["Language"] = Language;
|
||||
inputYaml["Last Game"] = LastGame;
|
||||
|
||||
inputYaml["Games"] = Games;
|
||||
inputYaml["Games"][0]["url"] = inputYaml["Games"][0]["repo"];
|
||||
inputYaml["Games"][0].remove("repo");
|
||||
inputYaml["Games"][0].remove("branch");
|
||||
|
||||
settings.load(inputYaml);
|
||||
|
||||
const YAML::Node outputYaml = settings.toYaml();
|
||||
EXPECT_TRUE(settings.isDebugLoggingEnabled());
|
||||
EXPECT_EQ(UpdateMasterlist, outputYaml["updateMasterlist"].as<bool>());
|
||||
EXPECT_EQ(Game, settings.getGame());
|
||||
EXPECT_EQ(Language, settings.getLanguage().Locale());
|
||||
EXPECT_EQ(LastGame, settings.getLastGame());
|
||||
|
||||
EXPECT_EQ(Games[0].Name(), settings.getGameSettings()[0].Name());
|
||||
EXPECT_EQ(Games[0].RepoURL(), settings.getGameSettings()[0].RepoURL());
|
||||
EXPECT_EQ(Games[0].RepoBranch(), settings.getGameSettings()[0].RepoBranch());
|
||||
}
|
||||
|
||||
TEST_F(LootSettings, loadingFromYamlShouldNotUpgradeVersion0Point6SettingsIfEquivalentsAlreadyExist) {
|
||||
const unsigned int DebugVerbosity = 3;
|
||||
const bool enableDebugLogging = false;
|
||||
const bool UpdateMasterlist = true;
|
||||
const bool updateMasterlist = false;
|
||||
const std::string Game = "Oblivion";
|
||||
const std::string game = "auto";
|
||||
const std::string Language = "fr";
|
||||
const std::string language = "en";
|
||||
const std::string LastGame = "Skyrim";
|
||||
const std::string lastGame = "auto";
|
||||
const std::vector<GameSettings> Games({
|
||||
GameSettings(GameSettings::tes4).SetName("Old Game Name"),
|
||||
});
|
||||
const std::vector<GameSettings> games({
|
||||
GameSettings(GameSettings::fo3).SetName("Game Name"),
|
||||
});
|
||||
|
||||
YAML::Node inputYaml;
|
||||
inputYaml["Debug Verbosity"] = DebugVerbosity;
|
||||
inputYaml["enableDebugLogging"] = enableDebugLogging;
|
||||
inputYaml["Update Masterlist"] = UpdateMasterlist;
|
||||
inputYaml["updateMasterlist"] = updateMasterlist;
|
||||
inputYaml["Game"] = Game;
|
||||
inputYaml["game"] = game;
|
||||
inputYaml["Language"] = Language;
|
||||
inputYaml["language"] = language;
|
||||
inputYaml["Last Game"] = LastGame;
|
||||
inputYaml["lastGame"] = lastGame;
|
||||
|
||||
inputYaml["Games"] = Games;
|
||||
inputYaml["Games"][0]["url"] = inputYaml["Games"][0]["repo"];
|
||||
inputYaml["Games"][0].remove("repo");
|
||||
inputYaml["Games"][0].remove("branch");
|
||||
inputYaml["games"] = games;
|
||||
|
||||
settings.load(inputYaml);
|
||||
|
||||
const YAML::Node outputYaml = settings.toYaml();
|
||||
|
||||
EXPECT_EQ(enableDebugLogging, settings.isDebugLoggingEnabled());
|
||||
EXPECT_EQ(updateMasterlist, outputYaml["updateMasterlist"].as<bool>());
|
||||
EXPECT_EQ(game, settings.getGame());
|
||||
EXPECT_EQ(language, settings.getLanguage().Locale());
|
||||
EXPECT_EQ(lastGame, settings.getLastGame());
|
||||
|
||||
EXPECT_EQ(games[0].Name(), settings.getGameSettings()[0].Name());
|
||||
}
|
||||
|
||||
TEST_F(LootSettings, loadingFromYamlShouldUpgradeOldDefaultGameRepositoryBranches) {
|
||||
const std::vector<GameSettings> games({GameSettings(GameSettings::tes4)});
|
||||
|
||||
YAML::Node inputYaml;
|
||||
inputYaml["games"] = games;
|
||||
inputYaml["games"][0]["branch"] = "v0.7";
|
||||
|
||||
settings.load(inputYaml);
|
||||
|
||||
EXPECT_EQ(games[0].RepoBranch(), settings.getGameSettings()[0].RepoBranch());
|
||||
}
|
||||
|
||||
TEST_F(LootSettings, loadingFromYamlShouldNotUpgradeNonDefaultGameRepositoryBranches) {
|
||||
const std::vector<GameSettings> games({GameSettings(GameSettings::tes4)});
|
||||
|
||||
YAML::Node inputYaml;
|
||||
inputYaml["games"] = games;
|
||||
inputYaml["games"][0]["branch"] = "foo";
|
||||
|
||||
settings.load(inputYaml);
|
||||
|
||||
EXPECT_EQ("foo", settings.getGameSettings()[0].RepoBranch());
|
||||
}
|
||||
|
||||
TEST_F(LootSettings, loadingFromYamlShouldAddMissingBaseGames) {
|
||||
const std::vector<GameSettings> games({GameSettings(GameSettings::tes4)});
|
||||
YAML::Node inputYaml;
|
||||
inputYaml["games"] = games;
|
||||
|
||||
settings.load(inputYaml);
|
||||
|
||||
const std::vector<GameSettings> expectedGameSettings({
|
||||
GameSettings(GameSettings::tes4),
|
||||
GameSettings(GameSettings::tes5),
|
||||
GameSettings(GameSettings::fo3),
|
||||
GameSettings(GameSettings::fonv),
|
||||
GameSettings(GameSettings::fo4),
|
||||
});
|
||||
EXPECT_EQ(expectedGameSettings, settings.getGameSettings());
|
||||
}
|
||||
|
||||
TEST_F(LootSettings, loadingFromYamlShouldSkipUnrecognisedGames) {
|
||||
YAML::Node inputYaml;
|
||||
inputYaml["games"][0] = GameSettings(GameSettings::tes4);
|
||||
inputYaml["games"][0]["type"] = "Foobar";
|
||||
inputYaml["games"][0]["name"] = "Foobar";
|
||||
inputYaml["games"][1] = GameSettings(GameSettings::tes5).SetName("Game Name");
|
||||
|
||||
settings.load(inputYaml);
|
||||
|
||||
EXPECT_EQ("Game Name", settings.getGameSettings()[0].Name());
|
||||
}
|
||||
|
||||
TEST_F(LootSettings, loadingFromYamlShouldRemoveTheContentFilterSetting) {
|
||||
YAML::Node inputYaml;
|
||||
inputYaml["filters"]["contentFilter"] = "foo";
|
||||
|
||||
settings.load(inputYaml);
|
||||
}
|
||||
|
||||
TEST_F(LootSettings, saveShouldWriteSettingsAsYamlToPassedFile) {
|
||||
settings.storeLastGame("Skyrim");
|
||||
settings.save(settingsFile);
|
||||
|
||||
settings.storeLastGame("auto");
|
||||
settings.load(settingsFile);
|
||||
|
||||
EXPECT_EQ("Skyrim", settings.getLastGame());
|
||||
}
|
||||
|
||||
TEST_F(LootSettings, getLanguageShouldReturnTheCurrentValue) {
|
||||
YAML::Node inputYaml;
|
||||
inputYaml["language"] = "fr";
|
||||
|
||||
settings.load(inputYaml);
|
||||
|
||||
EXPECT_EQ("fr", settings.getLanguage().Locale());
|
||||
}
|
||||
|
||||
TEST_F(LootSettings, isWindowPositionStoredShouldReturnFalseIfAllPositionValuesAreZero) {
|
||||
loot::LootSettings::WindowPosition position;
|
||||
settings.storeWindowPosition(position);
|
||||
|
||||
EXPECT_FALSE(settings.isWindowPositionStored());
|
||||
}
|
||||
|
||||
TEST_F(LootSettings, isWindowPositionStoredShouldReturnTrueIfTopPositionValueIsNonZero) {
|
||||
loot::LootSettings::WindowPosition position;
|
||||
position.top = 1;
|
||||
settings.storeWindowPosition(position);
|
||||
|
||||
EXPECT_TRUE(settings.isWindowPositionStored());
|
||||
}
|
||||
|
||||
TEST_F(LootSettings, isWindowPositionStoredShouldReturnTrueIfBottomPositionValueIsNonZero) {
|
||||
loot::LootSettings::WindowPosition position;
|
||||
position.bottom = 1;
|
||||
settings.storeWindowPosition(position);
|
||||
|
||||
EXPECT_TRUE(settings.isWindowPositionStored());
|
||||
}
|
||||
|
||||
TEST_F(LootSettings, isWindowPositionStoredShouldReturnTrueIfLeftPositionValueIsNonZero) {
|
||||
loot::LootSettings::WindowPosition position;
|
||||
position.left = 1;
|
||||
settings.storeWindowPosition(position);
|
||||
|
||||
EXPECT_TRUE(settings.isWindowPositionStored());
|
||||
}
|
||||
|
||||
TEST_F(LootSettings, isWindowPositionStoredShouldReturnTrueIfRightPositionValueIsNonZero) {
|
||||
loot::LootSettings::WindowPosition position;
|
||||
position.right = 1;
|
||||
settings.storeWindowPosition(position);
|
||||
|
||||
EXPECT_TRUE(settings.isWindowPositionStored());
|
||||
}
|
||||
|
||||
TEST_F(LootSettings, storeGameSettingsShouldReplaceExistingGameSettings) {
|
||||
const std::vector<GameSettings> gameSettings({GameSettings(GameSettings::tes5)});
|
||||
settings.storeGameSettings(gameSettings);
|
||||
|
||||
EXPECT_EQ(gameSettings, settings.getGameSettings());
|
||||
}
|
||||
|
||||
TEST_F(LootSettings, storeLastGameShouldReplaceExistingValue) {
|
||||
settings.storeLastGame("Fallout3");
|
||||
|
||||
EXPECT_EQ("Fallout3", settings.getLastGame());
|
||||
}
|
||||
|
||||
TEST_F(LootSettings, storeWindowPositionShouldReplaceExistingValue) {
|
||||
loot::LootSettings::WindowPosition expectedPosition;
|
||||
expectedPosition.top = 1;
|
||||
settings.storeWindowPosition(expectedPosition);
|
||||
|
||||
loot::LootSettings::WindowPosition actualPosition = settings.getWindowPosition();
|
||||
EXPECT_EQ(expectedPosition.top, actualPosition.top);
|
||||
EXPECT_EQ(expectedPosition.bottom, actualPosition.bottom);
|
||||
EXPECT_EQ(expectedPosition.left, actualPosition.left);
|
||||
EXPECT_EQ(expectedPosition.right, actualPosition.right);
|
||||
}
|
||||
|
||||
TEST_F(LootSettings, updateLastVersionShouldSetValueToCurrentLootVersion) {
|
||||
const std::string currentVersion = std::to_string(g_version_major) + "." + std::to_string(g_version_minor) + "." + std::to_string(g_version_patch);
|
||||
YAML::Node inputYaml;
|
||||
inputYaml["lastVersion"] = "v0.7.1";
|
||||
|
||||
settings.load(inputYaml);
|
||||
settings.updateLastVersion();
|
||||
|
||||
EXPECT_EQ(currentVersion, settings.getLastVersion());
|
||||
}
|
||||
|
||||
TEST_F(LootSettings, toYamlShouldOutputStoredSettings) {
|
||||
const bool enableDebugLogging = true;
|
||||
const bool updateMasterlist = true;
|
||||
const std::string game = "Oblivion";
|
||||
const std::string language = "fr";
|
||||
const std::string lastGame = "Skyrim";
|
||||
const std::string lastVersion = "0.7.1";
|
||||
const std::map<std::string, long> window({
|
||||
{"top", 1},
|
||||
{"bottom", 2},
|
||||
{"left", 3},
|
||||
{"right", 4},
|
||||
});
|
||||
const std::vector<GameSettings> games({
|
||||
GameSettings(GameSettings::tes4).SetName("Game Name"),
|
||||
});
|
||||
const std::map<std::string, bool> filters({
|
||||
{"hideBashTags", false},
|
||||
{"hideCRCs", true},
|
||||
});
|
||||
|
||||
YAML::Node inputYaml;
|
||||
inputYaml["enableDebugLogging"] = enableDebugLogging;
|
||||
inputYaml["updateMasterlist"] = updateMasterlist;
|
||||
inputYaml["game"] = game;
|
||||
inputYaml["language"] = language;
|
||||
inputYaml["lastGame"] = lastGame;
|
||||
inputYaml["lastVersion"] = lastVersion;
|
||||
inputYaml["window"] = window;
|
||||
inputYaml["games"] = games;
|
||||
inputYaml["filters"] = filters;
|
||||
|
||||
settings.load(inputYaml);
|
||||
|
||||
const YAML::Node outputYaml = settings.toYaml();
|
||||
|
||||
EXPECT_EQ(enableDebugLogging, outputYaml["enableDebugLogging"].as<bool>());
|
||||
EXPECT_EQ(updateMasterlist, outputYaml["updateMasterlist"].as<bool>());
|
||||
EXPECT_EQ(game, outputYaml["game"].as<std::string>());
|
||||
EXPECT_EQ(language, outputYaml["language"].as<std::string>());
|
||||
EXPECT_EQ(lastGame, outputYaml["lastGame"].as<std::string>());
|
||||
EXPECT_EQ(lastVersion, outputYaml["lastVersion"].as<std::string>());
|
||||
|
||||
for (const auto& position : window) {
|
||||
EXPECT_EQ(position.second, outputYaml["window"][position.first].as<long>());
|
||||
}
|
||||
|
||||
for (const auto& filter : filters) {
|
||||
EXPECT_EQ(filter.second, outputYaml["filters"][filter.first].as<bool>());
|
||||
}
|
||||
|
||||
EXPECT_EQ(games[0].Name(), outputYaml["games"][0]["name"].as<std::string>());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#endif
|
||||
@@ -51,6 +51,7 @@
|
||||
#include "backend/test_metadata_list.h"
|
||||
#include "backend/test_masterlist.h"
|
||||
#include "backend/test_plugin_sorter.h"
|
||||
#include "gui/test_loot_settings.h"
|
||||
|
||||
#include <boost/log/core.hpp>
|
||||
|
||||
|
||||
Reference in New Issue
Block a user