From 94afd1a5d37d434bbb98d3d1b65c5845266c3f0c Mon Sep 17 00:00:00 2001 From: Oliver Hamlet Date: Fri, 26 Dec 2014 17:17:35 +0000 Subject: [PATCH] Swapped game vector for list. Fixes #357. --- src/backend/game.cpp | 32 +++------------------- src/backend/game.h | 4 +-- src/gui/app.cpp | 64 +++++++++++++++++++++++++++++++------------- src/gui/app.h | 9 ++++--- src/gui/handler.cpp | 2 +- 5 files changed, 57 insertions(+), 54 deletions(-) diff --git a/src/backend/game.cpp b/src/backend/game.cpp index a7172ba5..51659d7e 100644 --- a/src/backend/game.cpp +++ b/src/backend/game.cpp @@ -43,11 +43,11 @@ namespace fs = boost::filesystem; namespace lc = boost::locale; namespace loot { - std::vector GetGames(YAML::Node& settings) { - vector games; + std::list GetGames(YAML::Node& settings) { + list games; if (settings["games"]) - games = settings["games"].as< vector >(); + games = settings["games"].as< list >(); if (find(games.begin(), games.end(), Game(Game::tes4)) == games.end()) games.push_back(Game(Game::tes4)); @@ -67,32 +67,6 @@ namespace loot { return games; } - size_t SelectGame(const YAML::Node& settings, const std::vector& games, const std::string& cmdLineGame) { - 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["lastGame"] && settings["lastGame"].as() != "auto") - preferredGame = settings["lastGame"].as(); - } - - // Get index of preferred game if there is one. - for (size_t i = 0; i < games.size(); ++i) { - if (preferredGame.empty() && games[i].IsInstalled()) - return i; - else if (!preferredGame.empty() && preferredGame == games[i].FolderName() && games[i].IsInstalled()) - return i; - } - // Preferred game not found, just pick the first installed one. - for (size_t i = 0; i < games.size(); ++i) { - if (games[i].IsInstalled()) - return i; - } - - throw error(error::no_game_detected, "None of the supported games were detected."); - } - // MetadataList member functions //------------------------------ diff --git a/src/backend/game.h b/src/backend/game.h index e3249f53..74fc79aa 100644 --- a/src/backend/game.h +++ b/src/backend/game.h @@ -185,9 +185,7 @@ namespace loot { void InitLibloHandle(); }; - std::vector GetGames(YAML::Node& settings); - - size_t SelectGame(const YAML::Node& settings, const std::vector& games, const std::string& cmdLineGame); + std::list GetGames(YAML::Node& settings); } #endif diff --git a/src/gui/app.cpp b/src/gui/app.cpp index 07822592..95263581 100644 --- a/src/gui/app.cpp +++ b/src/gui/app.cpp @@ -136,7 +136,7 @@ namespace loot { // LootState member functions //--------------------------- - LootState::LootState() : numUnappliedChanges(0), _currentGame(0) {} + LootState::LootState() : numUnappliedChanges(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. @@ -239,9 +239,9 @@ namespace loot { try { BOOST_LOG_TRIVIAL(debug) << "Selecting game."; - _currentGame = SelectGame(_settings, _games, cmdLineGame); + SelectGame(cmdLineGame); BOOST_LOG_TRIVIAL(debug) << "Initialising game-specific settings."; - _games[_currentGame].Init(true); + _currentGame->Init(true); // Update game path in settings object. _settings["games"] = _games; } @@ -255,20 +255,21 @@ namespace loot { _initErrors.push_back((format(translate("Error: Game-specific settings could not be initialised. %1%")) % e.what()).str()); } } - BOOST_LOG_TRIVIAL(debug) << "Game selected is " << _games[_currentGame].Name(); + BOOST_LOG_TRIVIAL(debug) << "Game selected is " << _currentGame->Name(); } const std::vector& LootState::InitErrors() const { return _initErrors; } - void LootState::UpdateGames(std::vector& games) { + void LootState::UpdateGames(std::list& games) { // Acquire the lock for the scope of this method. base::AutoLock lock_scope(_lock); unordered_set newGameFolders; // Update existing games, add new games. + BOOST_LOG_TRIVIAL(trace) << "Updating existing games and adding new games."; for (auto &game : games) { auto pos = find(_games.begin(), _games.end(), game); @@ -276,6 +277,7 @@ namespace loot { pos->SetDetails(game.Name(), game.Master(), game.RepoURL(), game.RepoBranch(), game.GamePath().string(), game.RegistryKey()); } else { + BOOST_LOG_TRIVIAL(trace) << "Adding new game entry for: " << game.FolderName(); _games.push_back(game); } @@ -284,13 +286,10 @@ namespace loot { // Remove deleted games. As the current game is stored using its index, // removing an earlier game may invalidate it. + BOOST_LOG_TRIVIAL(trace) << "Removing deleted games."; for (auto it = _games.begin(); it != _games.end();) { if (newGameFolders.find(it->FolderName()) == newGameFolders.end()) { - if (distance(_games.begin(), it) < _currentGame) { - // Deleting a game before the current game, so the current game's - // index decreases by one. - --_currentGame; - } + BOOST_LOG_TRIVIAL(trace) << "Removing game: " << it->FolderName(); it = _games.erase(it); } else @@ -298,7 +297,7 @@ namespace loot { } // Re-initialise the current game in case the game path setting was changed. - _games[_currentGame].Init(true); + _currentGame->Init(true); // Update game path in settings object. _settings["games"] = _games; } @@ -308,20 +307,19 @@ namespace loot { base::AutoLock lock_scope(_lock); BOOST_LOG_TRIVIAL(debug) << "Changing current game to that with folder: " << newGameFolder; - auto it = find(_games.begin(), _games.end(), newGameFolder); + _currentGame = find(_games.begin(), _games.end(), newGameFolder); + _currentGame->Init(true); - _currentGame = std::distance(_games.begin(), it); - _games[_currentGame].Init(true); // Update game path in settings object. _settings["games"] = _games; - BOOST_LOG_TRIVIAL(debug) << "New game is " << _games[_currentGame].Name(); + 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); - return _games[_currentGame]; + return *_currentGame; } std::vector LootState::InstalledGames() const { @@ -348,7 +346,7 @@ namespace loot { // Acquire the lock for the scope of this method. base::AutoLock lock_scope(_lock); - _settings["lastGame"] = _games[_currentGame].FolderName(); + _settings["lastGame"] = _currentGame->FolderName(); _settings["lastVersion"] = to_string(g_version_major) + "." + to_string(g_version_minor) + "." + to_string(g_version_patch); //Save settings. @@ -367,6 +365,36 @@ namespace loot { } } + void LootState::SelectGame(std::string preferredGame) { + if (preferredGame.empty()) { + // Get preferred game from settings. + if (_settings["game"] && _settings["game"].as() != "auto") + preferredGame = _settings["game"].as(); + else if (_settings["lastGame"] && _settings["lastGame"].as() != "auto") + preferredGame = _settings["lastGame"].as(); + } + + // 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; + } + } + + // 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; + } + } + + throw error(error::no_game_detected, "None of the supported games were detected."); + } + bool LootState::AreSettingsValid() { // Acquire the lock for the scope of this method. base::AutoLock lock_scope(_lock); @@ -455,7 +483,7 @@ namespace loot { root["enableDebugLogging"] = false; root["updateMasterlist"] = true; - std::vector games; + std::list games; games.push_back(Game(Game::tes4)); games.push_back(Game(Game::tes5)); games.push_back(Game(Game::fo3)); diff --git a/src/gui/app.h b/src/gui/app.h index d63ba2f7..992cac71 100644 --- a/src/gui/app.h +++ b/src/gui/app.h @@ -74,7 +74,7 @@ namespace loot { Game& CurrentGame(); void ChangeGame(const std::string& newGameFolder); - void UpdateGames(std::vector& games); + void UpdateGames(std::list& games); // Get the folder names of the installed games. std::vector InstalledGames() const; @@ -86,10 +86,13 @@ namespace loot { int numUnappliedChanges; private: YAML::Node _settings; - std::vector _games; - size_t _currentGame; + std::list _games; + std::list::iterator _currentGame; std::vector _initErrors; + // 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; diff --git a/src/gui/handler.cpp b/src/gui/handler.cpp index 8e5855fe..df2841c2 100644 --- a/src/gui/handler.cpp +++ b/src/gui/handler.cpp @@ -273,7 +273,7 @@ namespace loot { // It will be restored when LOOT is next loaded. try { BOOST_LOG_TRIVIAL(trace) << "Updating games object."; - vector games(request["args"][0]["games"].as< vector >()); + list games(request["args"][0]["games"].as< list >()); g_app_state.UpdateGames(games); // Also enable/disable debug logging as required.