Refactorings to RetroPie#857 in C++11 standard and modified es_settings.cfg format for random collections

This commit is contained in:
Gemba 2024-02-09 21:59:04 +01:00
parent 6c7dc88ffe
commit a4768e7022
7 changed files with 210 additions and 172 deletions

View file

@ -15,36 +15,6 @@
#include <pugixml.hpp>
#include <fstream>
std::string myCollectionsName = "collections";
std::string randomCollectionName = "random";
#define LAST_PLAYED_MAX 50
std::map<std::string, int> stringToRandomSettingsMap(std::string sourceStr)
{
std::map<std::string, int> results;
// we parse the comma-separated settings list in the format [system]:[setting]
std::vector<std::string> vectorSettings = Utils::String::delimitedStringToVector(sourceStr, ",", false);
// iterate the map
for(std::vector<std::string>::iterator it = vectorSettings.begin() ; it != vectorSettings.end() ; it++ )
{
if (!(*it).empty())
{
std::vector<std::string> systemSettings = Utils::String::delimitedStringToVector((*it), ":", false);
try
{
results[systemSettings.at(0)] = std::stoi(systemSettings.at(1));
}
catch (std::exception& e)
{
LOG(LogError) << "Error parsing random collection settings: '" << (*it) << "' is in an invalid format.";
}
}
}
return results;
}
/* Handling the getting, initialization, deinitialization, saving and deletion of
* a CollectionSystemManager Instance */
CollectionSystemManager* CollectionSystemManager::sInstance = NULL;
@ -52,12 +22,12 @@ CollectionSystemManager* CollectionSystemManager::sInstance = NULL;
CollectionSystemManager::CollectionSystemManager(Window* window) : mWindow(window)
{
CollectionSystemDecl systemDecls[] = {
//type name long name //default sort // theme folder // isCustom
{ AUTO_ALL_GAMES, "all", "all games", "name, ascending", "auto-allgames", false },
{ AUTO_LAST_PLAYED, "recent", "last played", "last played, descending", "auto-lastplayed", false },
{ AUTO_FAVORITES, "favorites", "favorites", "name, ascending", "auto-favorites", false },
{ AUTO_RANDOM, randomCollectionName, "random", "name, ascending", "auto-random", false },
{ CUSTOM_COLLECTION, myCollectionsName, "collections", "name, ascending", "custom-collections", true }
//type name long name (display) default sort (key, order) theme folder isCustom
{ AUTO_ALL_GAMES, "all", "all games", "name, ascending", "auto-allgames", false },
{ AUTO_LAST_PLAYED, "recent", "last played", "last played, descending", "auto-lastplayed", false },
{ AUTO_FAVORITES, "favorites", "favorites", "name, ascending", "auto-favorites", false },
{ AUTO_RANDOM, RANDOM_COLL_ID, "random", "name, ascending", "auto-random", false },
{ CUSTOM_COLLECTION, CUSTOM_COLL_ID, "collections", "name, ascending", "custom-collections", true }
};
// create a map
@ -156,7 +126,7 @@ void CollectionSystemManager::saveCustomCollection(SystemData* sys)
void CollectionSystemManager::loadCollectionSystems(bool async)
{
initAutoCollectionSystems();
CollectionSystemDecl decl = mCollectionSystemDeclsIndex[myCollectionsName];
CollectionSystemDecl decl = mCollectionSystemDeclsIndex[CUSTOM_COLL_ID];
mCustomCollectionsBundle = createNewCollectionEntry(decl.name, decl, false);
// we will also load custom systems here
initCustomCollectionSystems();
@ -225,7 +195,7 @@ void CollectionSystemManager::updateSystemsList()
if(mCustomCollectionsBundle->getRootFolder()->getChildren().size() > 0)
{
mCustomCollectionsBundle->getRootFolder()->sort(getSortTypeFromString(mCollectionSystemDeclsIndex[myCollectionsName].defaultSort));
mCustomCollectionsBundle->getRootFolder()->sort(getSortTypeFromString(mCollectionSystemDeclsIndex[CUSTOM_COLL_ID].defaultSort));
SystemData::sSystemVector.push_back(mCustomCollectionsBundle);
}
@ -553,7 +523,7 @@ bool CollectionSystemManager::toggleGameInCollection(FileData* file)
rootFolder->addChild(newGame);
fileIndex->addToIndex(newGame);
// this is the biggest performance bottleneck for this process.
// this code has been here for 7 years, since this feature was added.
// this code has been here for 7 years, since this feature was added.
// I might have been playing it safe back then, but it feels unnecessary, especially given following onFileChanged to sort
// Commenting this out for now.
//ViewController::get()->getGameListView(systemViewToUpdate)->onFileChanged(newGame, FILE_METADATA_CHANGED);
@ -599,7 +569,7 @@ bool CollectionSystemManager::toggleGameInCollection(FileData* file)
{
s = new GuiInfoPopup(mWindow, "Removed '" + Utils::String::removeParenthesis(name) + "' from '" + Utils::String::toUpper(sysName) + "'", 4000);
}
mWindow->setInfoPopup(s);
return true;
}
@ -628,17 +598,17 @@ SystemData* CollectionSystemManager::getSystemToView(SystemData* sys)
void CollectionSystemManager::recreateCollection(SystemData* sysData)
{
CollectionSystemData* colSysData;
if (mAutoCollectionSystemsData.find(sysData->getName()) != mAutoCollectionSystemsData.end())
if (mAutoCollectionSystemsData.find(sysData->getName()) != mAutoCollectionSystemsData.end())
{
// it's an auto collection
colSysData = &mAutoCollectionSystemsData[sysData->getName()];
}
else if (mCustomCollectionSystemsData.find(sysData->getName()) != mCustomCollectionSystemsData.end())
else if (mCustomCollectionSystemsData.find(sysData->getName()) != mCustomCollectionSystemsData.end())
{
// it's a custom collection
colSysData = &mCustomCollectionSystemsData[sysData->getName()];
}
else
else
{
LOG(LogDebug) << "Couldn't find collection to recreate in either custom or auto collections: " << sysData->getName();
return;
@ -657,13 +627,13 @@ void CollectionSystemManager::recreateCollection(SystemData* sysData)
// while there are games there, remove them from the view and system
while(rootFolder->getChildrenByFilename().size() > 0)
ViewController::get()->getGameListView(systemViewToUpdate).get()->remove(rootFolder->getChildrenByFilename().begin()->second, false, false);
colSysData->isPopulated = false;
if (sysDecl.isCustom)
populateCustomCollection(colSysData);
else
populateAutoCollection(colSysData);
rootFolder->sort(getSortTypeFromString(colSysData->decl.defaultSort));
ViewController::get()->onFileChanged(systemViewToUpdate->getRootFolder(), FILE_SORTED);
@ -785,7 +755,7 @@ SystemData* CollectionSystemManager::getAllGamesCollection()
SystemData* CollectionSystemManager::addNewCustomCollection(std::string name)
{
CollectionSystemDecl decl = mCollectionSystemDeclsIndex[myCollectionsName];
CollectionSystemDecl decl = mCollectionSystemDeclsIndex[CUSTOM_COLL_ID];
decl.themeFolder = name;
decl.name = name;
decl.longName = name;
@ -819,15 +789,22 @@ SystemData* CollectionSystemManager::createNewCollectionEntry(std::string name,
return newSys;
}
void CollectionSystemManager::addRandomGames(SystemData* newSys, SystemData* sourceSystem, FileData* rootFolder,
FileFilterIndex* index, std::map<std::string, int> settingsValues, int defaultValue)
void CollectionSystemManager::addRandomGames(SystemData* newSys, SystemData* sourceSystem, FileData* rootFolder,
FileFilterIndex* index, std::map<std::string, std::map<std::string, int>> mapsForRandomColl, int defaultValue)
{
int gamesForSourceSystem = defaultValue;
if (settingsValues.find(sourceSystem->getFullName()) != settingsValues.end())
for (auto& m : mapsForRandomColl)
{
// we won't add more than the max
gamesForSourceSystem = Math::min(RANDOM_SYSTEM_MAX, settingsValues[sourceSystem->getFullName()]);
// m.first unused
std::map<std::string, int> collMap = m.second;
if (collMap.find(sourceSystem->getFullName()) != collMap.end())
{
int maxForSys = collMap[sourceSystem->getFullName()];
// we won't add more than the max and less than 0
gamesForSourceSystem = Math::max(Math::min(RANDOM_SYSTEM_MAX, maxForSys), 0);
break;
}
}
// load exclusion collection
@ -836,7 +813,8 @@ void CollectionSystemManager::addRandomGames(SystemData* newSys, SystemData* sou
auto sysDataIt = mCustomCollectionSystemsData.find(exclusionCollection);
if (!exclusionCollection.empty() && sysDataIt != mCustomCollectionSystemsData.end()) {
if (!sysDataIt->second.isPopulated) {
if (!sysDataIt->second.isPopulated)
{
populateCustomCollection(&(sysDataIt->second));
}
@ -845,13 +823,13 @@ void CollectionSystemManager::addRandomGames(SystemData* newSys, SystemData* sou
}
// we do this to avoid trying to add more games than there are in the system
gamesForSourceSystem = Math::min(gamesForSourceSystem, sourceSystem->getRootFolder()->getFilesRecursive(GAME).size());
gamesForSourceSystem = Math::min(gamesForSourceSystem, sourceSystem->getRootFolder()->getFilesRecursive(GAME).size());
int startCount = rootFolder->getFilesRecursive(GAME).size();
int endCount = startCount + gamesForSourceSystem;
int retryCount = 10;
for (int iterCount = startCount; iterCount < endCount; )
for (int iterCount = startCount; iterCount < endCount;)
{
FileData* randomGame = sourceSystem->getRandomGame()->getSourceFileData();
CollectionFileData* newGame = NULL;
@ -863,8 +841,8 @@ void CollectionSystemManager::addRandomGames(SystemData* newSys, SystemData* sou
rootFolder->addChild(newGame);
index->addToIndex(newGame);
}
if (rootFolder->getFilesRecursive(GAME).size() > iterCount)
if (rootFolder->getFilesRecursive(GAME).size() > iterCount)
{
// added game, proceed
iterCount++;
@ -876,7 +854,7 @@ void CollectionSystemManager::addRandomGames(SystemData* newSys, SystemData* sou
LOG(LogDebug) << "Clash: " << randomGame->getName() << " already exists or in exclusion list. Deleting and trying again";
delete newGame;
retryCount--;
if (retryCount == 0)
if (retryCount == 0)
{
// we give up. Either we were very unlucky, or all the games in this system are already there.
LOG(LogDebug) << "Giving up retrying: cannot add this game. Deleting and moving on.";
@ -886,38 +864,40 @@ void CollectionSystemManager::addRandomGames(SystemData* newSys, SystemData* sou
}
}
void CollectionSystemManager::populateRandomCollectionFromCollections(std::map<std::string, int> settingsValues)
void CollectionSystemManager::populateRandomCollectionFromCollections(std::map<std::string, std::map<std::string, int>> mapsForRandomColl)
{
CollectionSystemData* sysData = &mAutoCollectionSystemsData[randomCollectionName];
CollectionSystemData* sysData = &mAutoCollectionSystemsData[RANDOM_COLL_ID];
SystemData* newSys = sysData->system;
CollectionSystemDecl sysDecl = sysData->decl;
FileData* rootFolder = newSys->getRootFolder();
FileFilterIndex* index = newSys->getIndex();
// iterate the auto collections map
for(std::map<std::string, CollectionSystemData>::iterator it = mAutoCollectionSystemsData.begin() ; it != mAutoCollectionSystemsData.end() ; it++ )
for(auto &c : mAutoCollectionSystemsData)
{
CollectionSystemData csd = c.second;
// we can't add games from the random collection to the random collection
if (it->second.decl.type != AUTO_RANDOM)
if (csd.decl.type != AUTO_RANDOM)
{
// collections might not be populated
if (!it->second.isPopulated)
populateAutoCollection(&(it->second));
if (!csd.isPopulated)
populateAutoCollection(&csd);
if (it->second.isPopulated)
addRandomGames(newSys, it->second.system, rootFolder, index, settingsValues, DEFAULT_RANDOM_COLLECTIONS_GAMES);
if (csd.isPopulated)
addRandomGames(newSys, csd.system, rootFolder, index, mapsForRandomColl, DEFAULT_RANDOM_COLLECTIONS_GAMES);
}
}
// iterate the custom collections map
for(std::map<std::string, CollectionSystemData>::iterator it = mCustomCollectionSystemsData.begin() ; it != mCustomCollectionSystemsData.end() ; it++ )
for(auto &c : mCustomCollectionSystemsData)
{
CollectionSystemData csd = c.second;
// collections might not be populated
if (!it->second.isPopulated)
populateCustomCollection(&(it->second));
if (it->second.isPopulated)
addRandomGames(newSys, it->second.system, rootFolder, index, settingsValues, DEFAULT_RANDOM_COLLECTIONS_GAMES);
if (!csd.isPopulated)
populateCustomCollection(&csd);
if (csd.isPopulated)
addRandomGames(newSys, csd.system, rootFolder, index, mapsForRandomColl, DEFAULT_RANDOM_COLLECTIONS_GAMES);
}
}
@ -929,13 +909,16 @@ void CollectionSystemManager::populateAutoCollection(CollectionSystemData* sysDa
FileData* rootFolder = newSys->getRootFolder();
FileFilterIndex* index = newSys->getIndex();
std::map<std::string, int> settingsValues;
if (sysDecl.type == AUTO_RANDOM)
std::map<std::string, std::map<std::string, int>> mapsForRandomColl;
if (sysDecl.type == AUTO_RANDOM)
{
std::string randomSystems = Settings::getInstance()->getString("RandomCollectionSystems");
std::string randomCollections = Settings::getInstance()->getString("RandomCollectionSystemsAuto") + "," +
Settings::getInstance()->getString("RandomCollectionSystemsCustom");
settingsValues = stringToRandomSettingsMap(randomSystems + "," + randomCollections);
// user may have defined a custom collection with the same name as a system name, thus keeping maps in another map
std::map<std::string, int> randomSystems = Settings::getInstance()->getMap("RandomCollectionSystems");
mapsForRandomColl["RandomCollectionSystems"] = randomSystems;
std::map<std::string, int> randomAutoColl = Settings::getInstance()->getMap("RandomCollectionSystemsAuto");
mapsForRandomColl["RandomCollectionSystemsAuto"] = randomAutoColl;
std::map<std::string, int> randomCustColl = Settings::getInstance()->getMap("RandomCollectionSystemsCustom");
mapsForRandomColl["RandomCollectionSystemsCustom"] = randomCustColl;
}
// Only iterate through game systems, not collections yet
for(auto sysIt = SystemData::sSystemVector.cbegin(); sysIt != SystemData::sSystemVector.cend(); sysIt++)
@ -945,7 +928,7 @@ void CollectionSystemManager::populateAutoCollection(CollectionSystemData* sysDa
{
if (sysDecl.type == AUTO_RANDOM)
{
addRandomGames(newSys, (*sysIt), rootFolder, index, settingsValues, DEFAULT_RANDOM_SYSTEM_GAMES);
addRandomGames(newSys, *sysIt, rootFolder, index, mapsForRandomColl, DEFAULT_RANDOM_SYSTEM_GAMES);
}
else
{
@ -953,7 +936,7 @@ void CollectionSystemManager::populateAutoCollection(CollectionSystemData* sysDa
for(auto gameIt = files.cbegin(); gameIt != files.cend(); gameIt++)
{
bool include = includeFileInAutoCollections((*gameIt));
bool include = includeFileInAutoCollections(*gameIt);
switch(sysDecl.type) {
case AUTO_LAST_PLAYED:
include = include && (*gameIt)->metadata.get("playcount") > "0";
@ -964,7 +947,6 @@ void CollectionSystemManager::populateAutoCollection(CollectionSystemData* sysDa
break;
case AUTO_ALL_GAMES:
break;
case AUTO_RANDOM:
default:
// No-op to prevent compiler warnings
// Getting here means that the file is not part of a pre-defined collection.
@ -972,7 +954,7 @@ void CollectionSystemManager::populateAutoCollection(CollectionSystemData* sysDa
break;
}
if (include)
if (include)
{
CollectionFileData* newGame = new CollectionFileData(*gameIt, newSys);
rootFolder->addChild(newGame);
@ -983,20 +965,22 @@ void CollectionSystemManager::populateAutoCollection(CollectionSystemData* sysDa
}
}
int trimValue = LAST_PLAYED_MAX;
std::string trimRandom = Settings::getInstance()->getString("RandomCollectionMaxItems");
if (!trimRandom.empty() && sysDecl.type == AUTO_RANDOM)
trimValue = std::stoi(trimRandom);
// here we finish populating the Random collection based on other Collections
if (sysDecl.type == AUTO_RANDOM)
populateRandomCollectionFromCollections(settingsValues);
populateRandomCollectionFromCollections(mapsForRandomColl);
// sort before optional trimming
rootFolder->sort(getSortTypeFromString(sysDecl.defaultSort));
if (sysData->isEnabled && (sysDecl.type == AUTO_LAST_PLAYED || (sysDecl.type == AUTO_RANDOM && !trimRandom.empty())))
trimCollectionCount(rootFolder, trimValue, sysDecl.type == AUTO_RANDOM);
// sort before optional trimming, if collection is displayed
if (sysData->isEnabled)
rootFolder->sort(getSortTypeFromString(sysDecl.defaultSort));
if (sysData->isEnabled && (sysDecl.type == AUTO_LAST_PLAYED || sysDecl.type == AUTO_RANDOM))
{
int trimValue = LAST_PLAYED_MAX;
if (sysDecl.type == AUTO_RANDOM)
trimValue = Settings::getInstance()->getInt("RandomCollectionMaxGames");
if (trimValue > 0)
trimCollectionCount(rootFolder, trimValue, sysDecl.type == AUTO_RANDOM);
}
sysData->isPopulated = true;
}
@ -1028,7 +1012,7 @@ void CollectionSystemManager::populateCustomCollection(CollectionSystemData* sys
for(std::string gameKey; getline(input, gameKey); )
{
std::unordered_map<std::string,FileData*>::const_iterator it = allFilesMap.find(gameKey);
if (it != allFilesMap.cend())
if (it != allFilesMap.cend())
{
CollectionFileData* newGame = new CollectionFileData(it->second, newSys);
rootFolder->addChild(newGame);
@ -1093,10 +1077,10 @@ void CollectionSystemManager::addEnabledCollectionsToDisplayedSystems(std::map<s
{
if(it->second.decl.isCustom)
populateCustomCollection(&(it->second));
else
populateAutoCollection(&(it->second));
else
populateAutoCollection(&(it->second));
}
// check if it has its own view
if(!it->second.decl.isCustom || themeFolderExists(it->first) || !Settings::getInstance()->getBool("UseCustomCollectionsSystem"))
{
@ -1304,7 +1288,7 @@ bool CollectionSystemManager::includeFileInAutoCollections(FileData* file)
bool CollectionSystemManager::needDoublePress(int presscount) {
if (Settings::getInstance()->getBool("DoublePressRemovesFromFavs") && presscount < 2)
if (Settings::getInstance()->getBool("DoublePressRemovesFromFavs") && presscount < 2)
{
GuiInfoPopup* toast = new GuiInfoPopup(mWindow, "Press again to remove from '" + Utils::String::toUpper(mEditingCollection)
+ "'", DOUBLE_PRESS_DETECTION_DURATION, 100, 200);

View file

@ -13,9 +13,13 @@ class Window;
struct SystemEnvironmentData;
class FileFilterIndex;
#define RANDOM_SYSTEM_MAX 5
#define DEFAULT_RANDOM_SYSTEM_GAMES 1
#define DEFAULT_RANDOM_COLLECTIONS_GAMES 0
static const std::string CUSTOM_COLL_ID = "collections";
static const std::string RANDOM_COLL_ID = "random";
constexpr int LAST_PLAYED_MAX = 50;
constexpr int RANDOM_SYSTEM_MAX = 5;
constexpr int DEFAULT_RANDOM_SYSTEM_GAMES = 1;
constexpr int DEFAULT_RANDOM_COLLECTIONS_GAMES = 0;
enum CollectionSystemType
{
@ -45,8 +49,6 @@ struct CollectionSystemData
bool needsSave;
};
std::map<std::string, int> stringToRandomSettingsMap(std::string sourceStr);
class CollectionSystemManager
{
public:
@ -109,8 +111,8 @@ private:
void populateAutoCollection(CollectionSystemData* sysData);
void populateCustomCollection(CollectionSystemData* sysData);
void addRandomGames(SystemData* newSys, SystemData* sourceSystem, FileData* rootFolder, FileFilterIndex* index,
std::map<std::string, int> settingsValues, int defaultValue);
void populateRandomCollectionFromCollections(std::map<std::string, int> settingsValues);
std::map<std::string, std::map<std::string, int>> mapsForRandomColl, int defaultValue);
void populateRandomCollectionFromCollections(std::map<std::string, std::map<std::string, int>> mapsForRandomColl);
void removeCollectionsFromDisplayedSystems();
void addEnabledCollectionsToDisplayedSystems(std::map<std::string, CollectionSystemData>* colSystemData, bool processRandom);

View file

@ -23,7 +23,7 @@ void GuiCollectionSystemsOptions::initializeMenu()
addSystemsToMenu();
// manage random collection
addEntry("RANDOM GAME COLL. SETTINGS", 0x777777FF, true, [this] { openRandomCollectionSettings(); });
addEntry("RANDOM GAME COLLECTION SETTINGS", 0x777777FF, true, [this] { openRandomCollectionSettings(); });
// add "Create New Custom Collection from Theme"
std::vector<std::string> unusedFolders = CollectionSystemManager::get()->getUnusedSystemsFromTheme();
@ -135,7 +135,7 @@ void GuiCollectionSystemsOptions::addEntry(const char* name, unsigned int color,
mMenu.addRow(row);
}
void GuiCollectionSystemsOptions::createCollection(std::string inName)
void GuiCollectionSystemsOptions::createCollection(std::string inName)
{
std::string name = CollectionSystemManager::get()->getValidNewCollectionName(inName);
SystemData* newSys = CollectionSystemManager::get()->addNewCustomCollection(name);
@ -152,7 +152,7 @@ void GuiCollectionSystemsOptions::createCollection(std::string inName)
return;
}
void GuiCollectionSystemsOptions::openRandomCollectionSettings()
void GuiCollectionSystemsOptions::openRandomCollectionSettings()
{
mWindow->pushGui(new GuiRandomCollectionOptions(mWindow));
}

View file

@ -1,5 +1,6 @@
#include "guis/GuiRandomCollectionOptions.h"
#include "GuiRandomCollectionOptions.h"
#include "components/OptionListComponent.h"
#include "components/SwitchComponent.h"
#include "guis/GuiSettings.h"
@ -16,20 +17,20 @@ GuiRandomCollectionOptions::GuiRandomCollectionOptions(Window* window) : GuiComp
autoCollectionLists.clear();
systemLists.clear();
mNeedsCollectionRefresh = false;
initializeMenu();
}
void GuiRandomCollectionOptions::initializeMenu()
{
// get collections
addEntry("INCLUDED SYSTEMS", 0x777777FF, true, [this] { selectSystems(); });
addEntry("INCLUDED AUTO COLLECTIONS", 0x777777FF, true, [this] { selectAutoCollections(); });
addEntry("INCLUDED CUSTOM COLLECTIONS", 0x777777FF, true, [this] { selectCustomCollections(); });
addEntry("INCLUDE SYSTEMS", 0x777777FF, true, [this] { selectSystems(); });
addEntry("INCLUDE AUTO COLLECTIONS", 0x777777FF, true, [this] { selectAutoCollections(); });
addEntry("INCLUDE CUSTOM COLLECTIONS", 0x777777FF, true, [this] { selectCustomCollections(); });
// Add option to exclude games from a collection
exclusionCollection = std::make_shared< OptionListComponent<std::string> >(mWindow, "EXCLUDE GAMES FROM", false);
// Add default option
exclusionCollection->add("<NONE>", "", Settings::getInstance()->getString("RandomCollectionExclusionCollection") == "");
@ -41,21 +42,21 @@ void GuiRandomCollectionOptions::initializeMenu()
}
mMenu.addWithLabel("EXCLUDE GAMES FROM", exclusionCollection);
// Add option to trim random collection items
trimRandom = std::make_shared< OptionListComponent<std::string> >(mWindow, "MAX GAMES", false);
trimRandom = std::make_shared<NumberList>(mWindow, "MAX GAMES", false);
// Add default entry
trimRandom->add("ALL", "", Settings::getInstance()->getString("RandomCollectionMaxItems") == "");
// add all enabled Custom Systems
int maxGames = Settings::getInstance()->getInt("RandomCollectionMaxGames");
trimRandom->add("ALL", 0, maxGames == 0);
// add limit values for size of random collection
for(int i = 5; i <= 50; i = i+5)
{
trimRandom->add(std::to_string(i), std::to_string(i), Settings::getInstance()->getString("RandomCollectionMaxItems") == std::to_string(i));
trimRandom->add(std::to_string(i), i, maxGames == i);
}
mMenu.addWithLabel("MAX ITEMS", trimRandom);
mMenu.addWithLabel("MAX GAMES", trimRandom);
addChild(&mMenu);
@ -87,20 +88,20 @@ void GuiRandomCollectionOptions::addEntry(const char* name, unsigned int color,
void GuiRandomCollectionOptions::selectSystems()
{
std::map<std::string, CollectionSystemData> systems;
for(auto sysIt = SystemData::sSystemVector.cbegin(); sysIt != SystemData::sSystemVector.cend(); sysIt++)
for(auto &sys : SystemData::sSystemVector)
{
// we won't iterate all collections
if ((*sysIt)->isGameSystem() && !(*sysIt)->isCollection())
if (sys->isGameSystem() && !sys->isCollection())
{
CollectionSystemDecl sysDecl;
sysDecl.name = (*sysIt)->getName();
sysDecl.longName = (*sysIt)->getFullName();
sysDecl.name = sys->getName();
sysDecl.longName = sys->getFullName();
CollectionSystemData newCollectionData;
newCollectionData.system = (*sysIt);
newCollectionData.system = sys;
newCollectionData.decl = sysDecl;
newCollectionData.isEnabled = true;
systems[sysDecl.name] = newCollectionData;
}
}
@ -122,37 +123,32 @@ GuiRandomCollectionOptions::~GuiRandomCollectionOptions()
}
std::string GuiRandomCollectionOptions::collectionListsToString(std::vector< SystemGames> collectionLists) {
std::string result;
for (std::vector< SystemGames>::const_iterator it = collectionLists.cbegin(); it != collectionLists.cend(); it++)
{
if (it != collectionLists.cbegin())
result += ",";
result += (*it).name + ":" + std::to_string((*it).gamesSelection->getSelected());
}
return result;
}
void GuiRandomCollectionOptions::selectEntries(std::map<std::string, CollectionSystemData> collection, std::string settingsLabel, int defaultValue, std::vector< SystemGames>* results) {
auto s = new GuiSettings(mWindow, "INCLUDE GAMES FROM");
std::map<std::string, int> settingsValues = stringToRandomSettingsMap(Settings::getInstance()->getString(settingsLabel));
std::map<std::string, int> initValues = Settings::getInstance()->getMap(settingsLabel);
results->clear();
// add Auto Systems
for(std::map<std::string, CollectionSystemData>::const_iterator it = collection.cbegin() ; it != collection.cend() ; it++ )
for(auto &c : collection)
{
if (it->second.system != CollectionSystemManager::get()->getRandomCollection())
CollectionSystemData csd = c.second;
if (csd.system != CollectionSystemManager::get()->getRandomCollection())
{
ComponentListRow row;
std::string label = it->second.decl.longName;
int selectedValue = defaultValue;
std::string label = csd.decl.longName;
int selectedValue = defaultValue;
if (settingsValues.find(label) != settingsValues.end())
selectedValue = Math::min(RANDOM_SYSTEM_MAX, settingsValues[label]);
if (initValues.find(label) != initValues.end())
{
int maxForSys = initValues[label];
// we won't add more than the max and less than 0
selectedValue = Math::max(Math::min(RANDOM_SYSTEM_MAX, maxForSys), 0);
mNeedsCollectionRefresh |= selectedValue != maxForSys; // force overwrite of outlier in settings
}
initValues[label] = selectedValue;
std::shared_ptr<NumberList> colItems = std::make_shared<NumberList>(mWindow, label, false);
for (int i = 0; i <= RANDOM_SYSTEM_MAX; i++)
@ -170,31 +166,32 @@ void GuiRandomCollectionOptions::selectEntries(std::map<std::string, CollectionS
}
}
setSize((float)Renderer::getScreenWidth(), (float)Renderer::getScreenHeight());
s->setPosition((mSize.x() - s->getSize().x()) / 2, (mSize.y() - s->getSize().y()) / 2);
s->addSaveFunc([this, settingsLabel, results] { applyGroupSettings(settingsLabel, results); });
s->addSaveFunc([this, settingsLabel, initValues, results] { applyGroupSettings(settingsLabel, initValues, results); });
mWindow->pushGui(s);
}
void GuiRandomCollectionOptions::applyGroupSettings(std::string settingsLabel, std::vector< SystemGames>* results)
void GuiRandomCollectionOptions::applyGroupSettings(std::string settingsLabel, const std::map<std::string, int> &initialValues, std::vector<SystemGames> *results)
{
std::string curOptions = GuiRandomCollectionOptions::collectionListsToString((*results));
std::string prevOptions = Settings::getInstance()->getString(settingsLabel);
if (!curOptions.empty() && curOptions != prevOptions)
std::map<std::string, int> currentValues;
for (auto it = results->begin(); it != results->end(); ++it)
{
currentValues[(*it).name] = (*it).gamesSelection->getSelected();
}
if (currentValues != initialValues)
{
Settings::getInstance()->setString(settingsLabel, curOptions);
mNeedsCollectionRefresh = true;
Settings::getInstance()->setMap(settingsLabel, currentValues);
}
}
void GuiRandomCollectionOptions::saveSettings()
{
std::string curTrim = trimRandom->getSelected();
std::string prevTrim = Settings::getInstance()->getString("RandomCollectionMaxItems");
Settings::getInstance()->setString("RandomCollectionMaxItems", curTrim);
int curTrim = trimRandom->getSelected();
int prevTrim = Settings::getInstance()->getInt("RandomCollectionMaxGames");
Settings::getInstance()->setInt("RandomCollectionMaxGames", curTrim);
std::string curExclusion = exclusionCollection->getSelected();
std::string prevExclusion = Settings::getInstance()->getString("RandomCollectionExclusionCollection");
@ -202,7 +199,7 @@ void GuiRandomCollectionOptions::saveSettings()
mNeedsCollectionRefresh |= (curTrim != prevTrim || curExclusion != prevExclusion);
if (mNeedsCollectionRefresh)
if (mNeedsCollectionRefresh)
{
Settings::getInstance()->saveFile();
CollectionSystemManager::get()->recreateCollection(CollectionSystemManager::get()->getRandomCollection());

View file

@ -4,6 +4,7 @@
#include "components/MenuComponent.h"
template<typename T>
class OptionListComponent;
class SwitchComponent;
@ -30,7 +31,7 @@ public:
private:
void initializeMenu();
void saveSettings();
void applyGroupSettings(std::string settingsLabel, std::vector< SystemGames>* results);
void applyGroupSettings(std::string settingsLabel, const std::map<std::string, int> &initialValues, std::vector<SystemGames>* results);
void addSystemsToMenu();
void addEntry(const char* name, unsigned int color, bool add_arrow, const std::function<void()>& func);
void selectEntries(std::map<std::string, CollectionSystemData> collection, std::string settingsLabel, int defaultValue, std::vector< SystemGames>* results);
@ -39,14 +40,12 @@ private:
void selectAutoCollections();
void selectCustomCollections();
std::string collectionListsToString(std::vector< SystemGames> collectionLists);
bool mNeedsCollectionRefresh;
std::vector< SystemGames> customCollectionLists;
std::vector< SystemGames> autoCollectionLists;
std::vector< SystemGames> systemLists;
std::shared_ptr< OptionListComponent<std::string> > trimRandom;
std::shared_ptr< NumberList> trimRandom;
std::shared_ptr< OptionListComponent<std::string> > exclusionCollection;
MenuComponent mMenu;
SystemData* mSystem;

View file

@ -139,10 +139,13 @@ void Settings::setDefaults()
mStringMap["VlcScreenSaverResolution"] = "original";
// Audio out device for Video playback using OMX player.
mStringMap["OMXAudioDev"] = "both";
mStringMap["RandomCollectionMaxItems"] = "";
mStringMap["RandomCollectionSystemsAuto"] = "";
mStringMap["RandomCollectionSystemsCustom"] = "";
mStringMap["RandomCollectionSystems"] = "";
mIntMap["RandomCollectionMaxGames"] = 0; // 0 == no limit
std::map<std::string, int> m1;
mMapIntMap["RandomCollectionSystemsAuto"] = m1;
std::map<std::string, int> m2;
mMapIntMap["RandomCollectionSystemsCustom"] = m2;
std::map<std::string, int> m3;
mMapIntMap["RandomCollectionSystems"] = m3;
mStringMap["RandomCollectionExclusionCollection"] = "";
mStringMap["CollectionSystemsAuto"] = "";
mStringMap["CollectionSystemsCustom"] = "";
@ -218,6 +221,20 @@ void Settings::saveFile()
node.append_attribute("value").set_value(iter->second.c_str());
}
for(auto &m : mMapIntMap)
{
pugi::xml_node node = doc.append_child("map");
node.append_attribute("name").set_value(m.first.c_str());
std::string datatype = "int";
node.append_attribute("type").set_value(datatype.c_str());
for(auto &intMap : m.second) // intMap is a <string, int> map
{
pugi::xml_node entry = node.append_child(datatype.c_str());
entry.append_attribute("name").set_value(intMap.first.c_str());
entry.append_attribute("value").set_value(intMap.second);
}
}
doc.save_file(path.c_str());
Scripting::fireEvent("config-changed");
@ -248,9 +265,45 @@ void Settings::loadFile()
for(pugi::xml_node node = doc.child("string"); node; node = node.next_sibling("string"))
setString(node.attribute("name").as_string(), node.attribute("value").as_string());
for(pugi::xml_node node = doc.child("map"); node; node = node.next_sibling("map"))
{
std::string mapName = node.attribute("name").as_string();
std::string mapType = node.attribute("type").as_string();
if (mapType == "int") {
// only supporting int value maps currently
std::map<std::string, int> _map;
for(pugi::xml_node entry : node.children(mapType.c_str()))
{
_map[entry.attribute("name").as_string()] = entry.attribute("value").as_int();
}
setMap(mapName, _map);
} else {
LOG(LogWarning) << "Map: '" << mapName << "'. Unsupported data type '"<< mapType <<"'. Value ignored!";
}
}
processBackwardCompatibility();
}
void Settings::setMap(const std::string& key, const std::map<std::string, int>& map)
{
mMapIntMap[key] = map;
}
const std::map<std::string, int> Settings::getMap(const std::string& key)
{
if(mMapIntMap.find(key) == mMapIntMap.cend())
{
LOG(LogError) << "Tried to use undefined setting " << key << "!";
std::map<std::string, int> empty;
return empty;
}
return mMapIntMap[key];
}
template<typename Map>
void Settings::renameSetting(Map& map, std::string&& oldName, std::string&& newName)
{

View file

@ -20,11 +20,13 @@ public:
int getInt(const std::string& name);
float getFloat(const std::string& name);
const std::string& getString(const std::string& name);
const std::map<std::string, int> getMap(const std::string& name);
void setBool(const std::string& name, bool value);
void setInt(const std::string& name, int value);
void setFloat(const std::string& name, float value);
void setString(const std::string& name, const std::string& value);
void setMap(const std::string& name, const std::map<std::string, int>& map);
private:
static Settings* sInstance;
@ -40,6 +42,7 @@ private:
std::map<std::string, int> mIntMap;
std::map<std::string, float> mFloatMap;
std::map<std::string, std::string> mStringMap;
std::map<std::string, std::map<std::string, int>> mMapIntMap;
};
#endif // ES_CORE_SETTINGS_H