diff --git a/resources/report/css/style.css b/resources/report/css/style.css index 10ee901b..8a0a9aed 100644 --- a/resources/report/css/style.css +++ b/resources/report/css/style.css @@ -96,6 +96,10 @@ header > ol > li > ol > li { header li > span, #filtersToggle > span { margin-right: 1em; } +header li.disabled { + cursor: default; + color: #999; +} #container { position: fixed; diff --git a/resources/report/js/plugin.js b/resources/report/js/plugin.js index 25ab2d65..acddec48 100644 --- a/resources/report/js/plugin.js +++ b/resources/report/js/plugin.js @@ -327,6 +327,7 @@ function Plugin(obj) { Plugin.prototype.createListItem = function() { var li = new PluginListItem(); + this.li = li; li.shadowRoot.querySelector('a').href = '#' + this.id; diff --git a/resources/report/js/script.js b/resources/report/js/script.js index 34ac569c..b2b2afcd 100644 --- a/resources/report/js/script.js +++ b/resources/report/js/script.js @@ -189,6 +189,92 @@ function openLogLocation(evt) { } }); } +function updateSelectedGame() { + /* Highlight game in menu. Could use fa-chevron-right instead. */ + var gameMenuItems = document.getElementById('gameMenu').children[0].children; + for (var i = 0; i < gameMenuItems.length; ++i) { + if (gameMenuItems[i].getAttribute('data-target') != loot.game.folder) { + gameMenuItems[i].querySelector('.fa').classList.toggle('fa-angle-double-right', false); + } else { + gameMenuItems[i].querySelector('.fa').classList.toggle('fa-angle-double-right', true); + } + } + + /* Also enable/disable the redate plugins option. */ + var index = undefined; + for (var i = 0; i < loot.settings.games.length; ++i) { + if (loot.settings.games[i].folder == loot.game.folder) { + index = i; + } + } + if (loot.settings.games.type == 'Skyrim') { + document.getElementById('redatePluginsButton').classList.toggle('disabled', false); + } else { + document.getElementById('redatePluginsButton').classList.toggle('disabled', true); + } +} +function changeGame(evt) { + /* First store current game info in loot.games object. + This object may not exist, so initialise it using the corresponding + loot.settings.games object. */ + var index = undefined; + if (loot.games) { + for (var i = 0; i < loot.games.length; ++i) { + if (loot.games[i].folder == loot.game.folder) { + index = i; + } + } + } else { + for (var i = 0; i < loot.settings.games.length; ++i) { + if (loot.settings.games[i].folder == loot.game.folder) { + index = i; + } + } + + loot.games = []; + loot.games.push(loot.settings.games[index]); + index = 0; + + } + loot.games[index].globalMessages = loot.game.globalMessages; + loot.games[index].masterlist = loot.game.masterlist; + loot.games[index].plugins = loot.game.plugins; + + + /* Now send off a CEF query with the folder name of the new game. */ + var request = { + name: 'changeGame', + args: [ + evt.target.getAttribute('data-target') + ] + }; + + // Create and send a new query. + var request_id = window.cefQuery({ + request: JSON.stringify(request), + persistent: false, + onSuccess: function(response) { + + /* First clear the UI of all existing game-specific data. Also + clear the card and li variables for each plugin object. */ + loot.games[index].plugins.forEach(function(plugin){ + plugin.card.parentElement.removeChild(plugin.card); + plugin.card = undefined; + plugin.li.parentElement.removeChild(plugin.li); + plugin.li = undefined; + }); + + /* Now update interface for new data. */ + updateInterfaceWithGameInfo(); + + /* Now update game menu to highlight the newly selected game. */ + updateSelectedGame(); + }, + onFailure: function(error_code, error_message) { + showMessageBox('error', "Error", "Error code: " + error_code + "; " + error_message); + } + }); +} function openReadme(evt) { // Create and send a new query. var request_id = window.cefQuery({ @@ -241,6 +327,10 @@ function cancelSort(evt) { }); } function redatePlugins(evt) { + if (evt.target.classList.contains('disabled')) { + return; + } + showMessageDialog('Redate Plugins', 'This feature is provided so that modders using the Creation Kit may set the load order it uses. A side-effect is that any subscribed Steam Workshop mods will be re-downloaded by Steam. Do you wish to continue?'); //showMessageBox('info', 'Redate Plugins', 'Plugins were successfully redated.'); @@ -301,6 +391,8 @@ function toggleMenu(evt) { elements[i].removeEventListener('click', copyMetadata, false); } else if (action == 'clear-metadata') { elements[i].removeEventListener('click', clearMetadata, false); + } else if (action == 'change-game') { + elements[i].removeEventListener('click', changeGame, false); } } @@ -320,6 +412,8 @@ function toggleMenu(evt) { elements[i].addEventListener('click', copyMetadata, false); } else if (action == 'clear-metadata') { elements[i].addEventListener('click', clearMetadata, false); + } else if (action == 'change-game') { + elements[i].addEventListener('click', changeGame, false); } } @@ -608,15 +702,8 @@ function initGlobalVars() { gameTable.addRow(loot.settings.games[i]); } - /* Highlight game in menu. Could use fa-chevron-right instead. */ - var gameMenuItems = document.getElementById('gameMenu').children[0].children; - for (var i = 0; i < gameMenuItems.length; ++i) { - if (gameMenuItems[i].getAttribute('data-target') != loot.game.folder) { - gameMenuItems[i].querySelector('.fa').classList.toggle('fa-angle-double-right', false); - } else { - gameMenuItems[i].querySelector('.fa').classList.toggle('fa-angle-double-right', true); - } - } + /* Highlight game in menu. */ + updateSelectedGame(); gameSelect.value = loot.settings.game; document.getElementById('languageSelect').value = loot.settings.language; diff --git a/src/gui/app.cpp b/src/gui/app.cpp index 0c3ebbf2..3383ceee 100644 --- a/src/gui/app.cpp +++ b/src/gui/app.cpp @@ -228,6 +228,22 @@ namespace loot { } } + void LootState::ChangeGame(const std::string& newGameFolder) { + BOOST_LOG_TRIVIAL(debug) << "Changing current game..."; + auto it = std::find_if(_games.begin(), _games.end(), [&newGameFolder](const Game& game){ + return game.FolderName() == newGameFolder; + }); + + _currentGame = std::distance(_games.begin(), it); + try { + _games[_currentGame].Init(); + BOOST_LOG_TRIVIAL(debug) << "New game is " << _games[_currentGame].Name(); + } + catch (std::exception& e) { + BOOST_LOG_TRIVIAL(error) << "Game-specific settings could not be initialised." << e.what(); + } + } + Game& LootState::CurrentGame() { return _games[_currentGame]; } diff --git a/src/gui/app.h b/src/gui/app.h index fddb62e0..1737d5a3 100644 --- a/src/gui/app.h +++ b/src/gui/app.h @@ -67,6 +67,7 @@ namespace loot { LootState(); void Init(const std::string& cmdLineGame); + void ChangeGame(const std::string& newGameFolder); Game& CurrentGame(); diff --git a/src/gui/handler.cpp b/src/gui/handler.cpp index 522426ed..7f8347f4 100644 --- a/src/gui/handler.cpp +++ b/src/gui/handler.cpp @@ -154,6 +154,23 @@ namespace loot { return true; } + else if (requestName == "changeGame") { + // Has one arg, which is the folder name of the new game. + const std::string folder = req["args"][0].as(); + + BOOST_LOG_TRIVIAL(info) << "Changing game to that with folder: " << folder; + g_app_state.ChangeGame(folder); + + BOOST_LOG_TRIVIAL(info) << "Setting LOOT window title bar text to include game name: " << g_app_state.CurrentGame().Name(); +#if defined(OS_WIN) + HWND handle = browser->GetHost()->GetWindowHandle(); + SetWindowText(handle, ToWinWide("LOOT: " + g_app_state.CurrentGame().Name()).c_str()); +#endif + + callback->Success(GetGameData()); + return true; + + } } return false;