mirror of
https://github.com/RetroPie/EmulationStation.git
synced 2024-06-12 17:37:24 -04:00
Refactorings to RetroPie#857 in C++11 standard and modified es_settings.cfg format for random collections
This commit is contained in:
parent
6c7dc88ffe
commit
a4768e7022
|
@ -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);
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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));
|
||||
}
|
||||
|
|
|
@ -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());
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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)
|
||||
{
|
||||
|
|
|
@ -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
|
||||
|
|
Loading…
Reference in a new issue