Started to implement plugin sorting.

The C++ side sends a list of plugin names in sorted order back, and the
JS reorders the cards and nav list items to match. Old and new load
orders are recorded, and if sorting is cancelled the old order is used
to reorder the UI again, otherwise if it is accepted the JS sends the
plugin list back to C++, which applies the load order.

The actual sorting doesn't yet happen, the C++ just sends back the
current load order right now. If `loot.neverTellMeTheOdds` is true, then
the received load order is randomly shuffled.

Also fixed initialisation of the masterlist update checkbox state, and
the type thrown by the filter application function.
This commit is contained in:
WrinklyNinja
2014-08-15 18:06:03 +01:00
parent fcda2077f5
commit 73f3f42cf8
4 changed files with 109 additions and 9 deletions
+84 -5
View File
@@ -126,7 +126,7 @@ function togglePlugins(evt) {
var hiddenPluginNo = 0;
var hiddenMessageNo = 0;
if (sections.length - 2 != entries.length) {
throw "Error: Number of plugins in sidebar doesn't match number of plugins in main area!";
throw Error("Error: Number of plugins in sidebar doesn't match number of plugins in main area!");
}
/* The conflict filter, if enabled, executes C++ code, so needs to be
handled using a promise, so the rest of the function should wait until
@@ -372,14 +372,93 @@ function updateMasterlist(evt) {
loot.game.globalMessages = result.globalMessages;
}).catch(processCefError);
}
function sortUIElements(pluginNames) {
/* pluginNames is an array of plugin names in their sorted order. Rearrange
the plugin cards and nav entries to match it. */
var main = document.getElementById('main');
var pluginsNav = document.getElementById('pluginsNav');
var entries = pluginsNav.children;
if (main.children.length - 2 != entries.length) {
throw Error("Error: Number of plugins in sidebar doesn't match number of plugins in main area!");
}
pluginNames.forEach(function(name){
var card = document.getElementById(name.replace(/\s+/g, ''));
var li;
for (var i = 0; i < entries.length; ++i) {
if (entries[i].getElementsByClassName('name')[0].textContent == name) {
li = entries[i];
}
}
/* Easiest just to remove them and add them on at the end. */
main.removeChild(card);
main.appendChild(card);
pluginsNav.removeChild(li);
pluginsNav.appendChild(li);
});
}
function sortPlugins(evt) {
loot.query('sortPlugins').catch(processCefError);
if (loot.settings.updateMasterlist) {
updateMasterlist(evt);
}
loot.query('sortPlugins').then(JSON.parse).then(function(result){
if (loot.neverTellMeTheOdds) {
/* Array shuffler from <https://stackoverflow.com/questions/6274339/how-can-i-shuffle-an-array-in-javascript> */
for(var j, x, i = result.length; i; j = Math.floor(Math.random() * i), x = result[--i], result[i] = result[j], result[j] = x);
}
/* Record the previous order in case the user cancels sorting. */
/* Start at 2 to skip summary and general messages. */
var cards = document.getElementById('main').children;
loot.newLoadOrder = result;
loot.lastLoadOrder = [];
for (var i = 2; i < cards.length; ++i) {
loot.lastLoadOrder.push(cards[i].getElementsByTagName('h1')[0].textContent);
}
/* Now update the UI for the new order. */
sortUIElements(result);
/* Now hide the masterlist update buttons, and display the accept and
cancel sort buttons. */
hideElement(document.getElementById('updateMasterlistButton'));
hideElement(document.getElementById('sortButton'));
showElement(document.getElementById('applySortButton'));
showElement(document.getElementById('cancelSortButton'));
}).catch(processCefError);
}
function applySort(evt) {
loot.query('applySort').catch(processCefError);
var request = JSON.stringify({
name: 'applySort',
args: [
loot.newLoadOrder
]
});
loot.query(request).then(function(result){
/* Remove old load order storage. */
delete loot.lastLoadOrder;
delete loot.newLoadOrder;
/* Now show the masterlist update buttons, and hide the accept and
cancel sort buttons. */
showElement(document.getElementById('updateMasterlistButton'));
showElement(document.getElementById('sortButton'));
hideElement(document.getElementById('applySortButton'));
hideElement(document.getElementById('cancelSortButton'));
}).catch(processCefError);
}
function cancelSort(evt) {
loot.query('cancelSort').catch(processCefError);
/* Sort UI elements again according to stored old load order. */
sortUIElements(loot.lastLoadOrder);
delete loot.lastLoadOrder;
delete loot.newLoadOrder;
/* Now show the masterlist update buttons, and hide the accept and
cancel sort buttons. */
showElement(document.getElementById('updateMasterlistButton'));
showElement(document.getElementById('sortButton'));
hideElement(document.getElementById('applySortButton'));
hideElement(document.getElementById('cancelSortButton'));
}
function redatePlugins(evt) {
if (evt.target.classList.contains('disabled')) {
@@ -578,7 +657,7 @@ function closeSettingsDialog(evt) {
games: document.getElementById('gameTable').getRowsData(false),
language: document.getElementById('languageSelect').value,
lastGame: loot.game.folder,
updateMasterlist: document.getElementById('updateMasterlist').value,
updateMasterlist: document.getElementById('updateMasterlist').checked,
};
/* Send the settings back to the C++ side. */
+3 -3
View File
@@ -533,7 +533,7 @@ namespace loot {
lo_destroy_handle(gh);
}
void Game::SetLoadOrder(const std::list<Plugin>& loadOrder) const {
void Game::SetLoadOrder(const std::list<std::string>& loadOrder) const {
BOOST_LOG_TRIVIAL(debug) << "Setting load order for game: " << _name;
lo_game_handle gh = nullptr;
@@ -587,8 +587,8 @@ namespace loot {
pluginArr = new char*[pluginArrSize];
int i = 0;
for (const auto &plugin: loadOrder) {
pluginArr[i] = new char[plugin.Name().length() + 1];
strcpy(pluginArr[i], plugin.Name().c_str());
pluginArr[i] = new char[plugin.length() + 1];
strcpy(pluginArr[i], plugin.c_str());
++i;
}
+1 -1
View File
@@ -118,7 +118,7 @@ namespace loot {
bool IsActive(const std::string& plugin) const;
void GetLoadOrder(std::list<std::string>& loadOrder) const;
void SetLoadOrder(const std::list<Plugin>& loadOrder) const; //Modifies game load order, even though const.
void SetLoadOrder(const std::list<std::string>& loadOrder) const; //Modifies game load order, even though const.
void RefreshActivePluginsList();
void RedatePlugins(); //Change timestamps to match load order (Skyrim only).
+21
View File
@@ -171,6 +171,13 @@ namespace loot {
callback->Success(UpdateMasterlist());
return true;
}
else if (request == "sortPlugins") {
//Sort plugins into their load order.
list<string> loadOrder;
g_app_state.CurrentGame().GetLoadOrder(loadOrder);
callback->Success(JSON::stringify(YAML::Node(loadOrder)));
return true;
}
else {
// May be a request with arguments.
YAML::Node req;
@@ -394,6 +401,20 @@ namespace loot {
callback->Success("");
return true;
}
else if (requestName == "applySort") {
BOOST_LOG_TRIVIAL(trace) << "User has accepted sorted load order, applying it.";
list<string> loadOrder = req["args"][0].as<list<string>>();
try {
g_app_state.CurrentGame().SetLoadOrder(loadOrder);
}
catch (exception &e) {
callback->Failure(-1, e.what());
return true;
}
callback->Success("");
return true;
}
}
return false;