From 769f3dd3139e170d705b224c1cbd2c60cc0376f3 Mon Sep 17 00:00:00 2001 From: Oliver Hamlet Date: Sat, 19 Nov 2016 11:59:34 +0000 Subject: [PATCH] Add --loot-data-path parameter to LOOT It sets the path used for LOOT's local application data storage, overriding the default (%LOCALAPPDATA%\LOOT on Windows). Closes #700. --- docs/app/usage/initialisation.rst | 8 +++++- resources/l10n/template.pot | 12 ++++++-- src/api/api.cpp | 2 +- src/backend/app/loot_paths.cpp | 8 ++++-- src/backend/app/loot_paths.h | 6 ++-- src/gui/loot_app.cpp | 9 ++---- src/gui/loot_app.h | 3 +- src/gui/main.cpp | 38 ++++++++++++++++--------- src/tests/backend/app/loot_paths_test.h | 22 ++++++++------ 9 files changed, 69 insertions(+), 39 deletions(-) diff --git a/docs/app/usage/initialisation.rst b/docs/app/usage/initialisation.rst index a2bd85c7..47dffd53 100644 --- a/docs/app/usage/initialisation.rst +++ b/docs/app/usage/initialisation.rst @@ -4,7 +4,13 @@ Initialisation When LOOT is run, it will attempt to detect which of the supported games are installed. If a :ref:`default game ` has been set, LOOT will run for it, otherwise it will run for the same game as it last ran for. If the relevant game cannot be detected, or if there is no record of the last game LOOT ran for, it will run for the first detected game. -LOOT can also be launched with the ``--game=`` command line parameter to set the game to run for. If the supplied game folder name is valid, the default and last game values are ignored. The default folder names are ``Oblivion``, ``Skyrim``, ``Fallout3``, ``FalloutNV`` and ``Fallout4``. +LOOT's initialisation can be customised using command line parameters: + +``--game=``: + Set the game to run for. If the supplied game folder name is valid, the default and last game values are ignored. The default folder names are ``Oblivion``, ``Skyrim``, ``Fallout3``, ``FalloutNV`` and ``Fallout4``. + +``--loot-data-path=``: + Set the path to use for LOOT's application data storage. If this is an empty string or not specified, defaults to ``%LOCALAPPDATA%\LOOT`` on Windows and (in order of decreasing preference) ``$XDG_CONFIG_HOME/LOOT``, ``$HOME/.config/LOOT`` or the current path on Linux. If LOOT cannot detect any supported game installs, it will immediately open the :doc:`Settings dialog `. There you can edit LOOT’s settings to provide a path to a supported game, after which you can select it from the game menu. diff --git a/resources/l10n/template.pot b/resources/l10n/template.pot index 6fe5d50d..4685f7f8 100644 --- a/resources/l10n/template.pot +++ b/resources/l10n/template.pot @@ -8,7 +8,7 @@ msgid "" msgstr "" "Project-Id-Version: LOOT 0.10.0\n" "Report-Msgid-Bugs-To: https://github.com/loot/loot/issues\n" -"POT-Creation-Date: 2016-11-12 08:53+0000\n" +"POT-Creation-Date: 2016-11-19 11:59+0000\n" "PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n" "Last-Translator: FULL NAME \n" "Language-Team: LANGUAGE \n" @@ -21,6 +21,10 @@ msgstr "" msgid "Identifying conflicting plugins..." msgstr "" +#: src/gui/html/js/events.js:80 +msgid "Updating and parsing masterlist..." +msgstr "" + #: src/gui/html/js/events.js:100 msgid "No masterlist update was necessary." msgstr "" @@ -45,6 +49,10 @@ msgstr "" msgid "Redate" msgstr "" +#: src/gui/html/js/events.js:185 +msgid "Plugins were successfully redated." +msgstr "" + #: src/gui/html/js/events.js:191 msgid "" "Are you sure you want to clear all existing user-added metadata from all " @@ -633,7 +641,7 @@ msgstr "" msgid "Sorting load order..." msgstr "" -#: src/backend/app/loot_paths.cpp:84 +#: src/backend/app/loot_paths.cpp:88 msgid "Failed to get %LOCALAPPDATA% path." msgstr "" diff --git a/src/api/api.cpp b/src/api/api.cpp index 1e08d730..b1b6665a 100644 --- a/src/api/api.cpp +++ b/src/api/api.cpp @@ -50,7 +50,7 @@ LOOT_API bool IsCompatible(const unsigned int versionMajor, const unsigned int v LOOT_API std::shared_ptr CreateDatabase(const GameType game, const std::string& gamePath, const std::string& gameLocalPath) { - loot::LootPaths::initialise(); + loot::LootPaths::initialise(""); //Disable logging or else stdout will get overrun. boost::log::core::get()->set_logging_enabled(false); diff --git a/src/backend/app/loot_paths.cpp b/src/backend/app/loot_paths.cpp index 599ee3db..60fba5f6 100644 --- a/src/backend/app/loot_paths.cpp +++ b/src/backend/app/loot_paths.cpp @@ -66,13 +66,17 @@ boost::filesystem::path LootPaths::getLogPath() { return lootDataPath_ / "LOOTDebugLog.txt"; } -void LootPaths::initialise() { +void LootPaths::initialise(const std::string& lootDataPath) { // Set the locale to get UTF-8 conversions working correctly. std::locale::global(boost::locale::generator().generate("")); boost::filesystem::path::imbue(std::locale()); lootAppPath_ = boost::filesystem::current_path(); - lootDataPath_ = getLocalAppDataPath() / "LOOT"; + + if (!lootDataPath.empty()) + lootDataPath_ = lootDataPath; + else + lootDataPath_ = getLocalAppDataPath() / "LOOT"; } boost::filesystem::path LootPaths::getLocalAppDataPath() { diff --git a/src/backend/app/loot_paths.h b/src/backend/app/loot_paths.h index 83ae33fc..7e3c5384 100644 --- a/src/backend/app/loot_paths.h +++ b/src/backend/app/loot_paths.h @@ -37,9 +37,9 @@ public: static boost::filesystem::path getSettingsPath(); static boost::filesystem::path getLogPath(); - // Sets the app path to the current path, and the data path to the user - // local app data path / "LOOT". - static void initialise(); + // Sets the app path to the current path, and the data path to the given + // path or (if it is an empty string), local app data path / "LOOT". + static void initialise(const std::string& lootDataPath); private: //Get the local application data path. static boost::filesystem::path getLocalAppDataPath(); diff --git a/src/gui/loot_app.cpp b/src/gui/loot_app.cpp index 56cc79eb..3335f6e4 100644 --- a/src/gui/loot_app.cpp +++ b/src/gui/loot_app.cpp @@ -35,12 +35,9 @@ #include "gui/loot_scheme_handler_factory.h" namespace loot { -LootApp::LootApp() { - LootPaths::initialise(); -} - -void LootApp::Initialise(const std::string& commandLineGameArg) { - lootState_.init(commandLineGameArg); +void LootApp::Initialise(const std::string& defaultGame, const std::string& lootDataPath) { + LootPaths::initialise(lootDataPath); + lootState_.init(defaultGame); } void LootApp::OnBeforeCommandLineProcessing(const CefString& process_type, diff --git a/src/gui/loot_app.h b/src/gui/loot_app.h index 053988cb..d287f9fb 100644 --- a/src/gui/loot_app.h +++ b/src/gui/loot_app.h @@ -36,8 +36,7 @@ class LootApp : public CefApp, public CefBrowserProcessHandler, public CefRenderProcessHandler { public: - LootApp(); - void Initialise(const std::string& commandLineGameArg); + void Initialise(const std::string& defaultGame, const std::string& lootDataPath); // Override CefApp methods. virtual void OnBeforeCommandLineProcessing(const CefString& process_type, diff --git a/src/gui/main.cpp b/src/gui/main.cpp index e32b8726..cfb2e670 100644 --- a/src/gui/main.cpp +++ b/src/gui/main.cpp @@ -76,6 +76,27 @@ int XIOErrorHandlerImpl(Display *display) { } #endif +void processCommandLineArguments(CefRefPtr app) { + std::string defaultGame; + std::string lootDataPath; + + // Record command line arguments. + CefRefPtr command_line = CefCommandLine::CreateCommandLine(); +#ifdef _WIN32 + command_line->InitFromString(::GetCommandLineW()); +#endif + + if (command_line->HasSwitch("game")) { // Format is: --game= + defaultGame = command_line->GetSwitchValue("game"); + } + + if (command_line->HasSwitch("loot-data-path")) { + lootDataPath = command_line->GetSwitchValue("loot-data-path"); + } + + app.get()->Initialise(defaultGame, lootDataPath); +} + #ifdef _WIN32 int APIENTRY wWinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPTSTR lpCmdLine, int nCmdShow) { #else @@ -124,21 +145,10 @@ int main(int argc, char* argv[]) { } #endif - // Handle command line args (not CEF args) - //---------------------------------------- + // Handle command line args (not CEF args) + //---------------------------------------- - std::string gameStr; - - // Record command line arguments. - CefRefPtr command_line = CefCommandLine::CreateCommandLine(); -#ifdef _WIN32 - command_line->InitFromString(::GetCommandLineW()); -#endif - if (command_line->HasSwitch("game")) { // Format is: --game= - gameStr = command_line->GetSwitchValue("game"); - } - - app.get()->Initialise(gameStr); + processCommandLineArguments(app); // Back to CEF //------------ diff --git a/src/tests/backend/app/loot_paths_test.h b/src/tests/backend/app/loot_paths_test.h index 9815f74a..175ca689 100644 --- a/src/tests/backend/app/loot_paths_test.h +++ b/src/tests/backend/app/loot_paths_test.h @@ -32,43 +32,43 @@ along with LOOT. If not, see namespace loot { namespace test { TEST(LootPaths, getReadmePathShouldUseLootAppPath) { - LootPaths::initialise(); + LootPaths::initialise(""); EXPECT_EQ(boost::filesystem::current_path() / "docs" / "index.html", LootPaths::getReadmePath()); } TEST(LootPaths, getResourcesPathShouldUseLootAppPath) { - LootPaths::initialise(); + LootPaths::initialise(""); EXPECT_EQ(boost::filesystem::current_path() / "resources", LootPaths::getResourcesPath()); } TEST(LootPaths, getL10nPathShouldUseLootAppPath) { - LootPaths::initialise(); + LootPaths::initialise(""); EXPECT_EQ(boost::filesystem::current_path() / "resources" / "l10n", LootPaths::getL10nPath()); } TEST(LootPaths, getSettingsPathShouldUseLootDataPath) { - LootPaths::initialise(); + LootPaths::initialise(""); EXPECT_EQ(LootPaths::getLootDataPath() / "settings.yaml", LootPaths::getSettingsPath()); } TEST(LootPaths, getLogPathShouldUseLootDataPath) { - LootPaths::initialise(); + LootPaths::initialise(""); EXPECT_EQ(LootPaths::getLootDataPath() / "LOOTDebugLog.txt", LootPaths::getLogPath()); } TEST(LootPaths, initialiseShouldSetTheAppPathToTheCurrentPath) { - LootPaths::initialise(); + LootPaths::initialise(""); EXPECT_EQ(boost::filesystem::current_path(), LootPaths::getReadmePath().parent_path().parent_path()); } -TEST(LootPaths, initialiseShouldSetTheDataPathToTheLocalAppDataPathSlashLoot) { - LootPaths::initialise(); +TEST(LootPaths, initialiseShouldSetTheDataPathToTheLocalAppDataPathSlashLootIfGivenAnEmptyString) { + LootPaths::initialise(""); // Can't actually know what the path should be, but we can check // its properties. @@ -76,6 +76,12 @@ TEST(LootPaths, initialiseShouldSetTheDataPathToTheLocalAppDataPathSlashLoot) { EXPECT_FALSE(LootPaths::getLootDataPath().parent_path().empty()); EXPECT_TRUE(boost::filesystem::exists(LootPaths::getLootDataPath().parent_path())); } + +TEST(LootPaths, initialiseShouldSetTheDataPathToGivenStringIfNonEmpty) { + LootPaths::initialise("foo"); + + EXPECT_EQ("foo", LootPaths::getLootDataPath()); +} } }