From 46520202f7df3c8ab9551ddd0a3265849fd5467e Mon Sep 17 00:00:00 2001 From: Leon Styhre Date: Mon, 19 Oct 2020 20:58:00 +0200 Subject: [PATCH] Changes to custom collections are now immediately written to disk. --- USERGUIDE.md | 6 +- es-app/src/CollectionSystemManager.cpp | 128 +++++++++--------- es-app/src/CollectionSystemManager.h | 1 - .../src/guis/GuiCollectionSystemsOptions.cpp | 1 + es-app/src/guis/GuiCollectionSystemsOptions.h | 4 +- 5 files changed, 68 insertions(+), 72 deletions(-) diff --git a/USERGUIDE.md b/USERGUIDE.md index f0308553a..81fc89330 100644 --- a/USERGUIDE.md +++ b/USERGUIDE.md @@ -984,7 +984,7 @@ This will remove any media files for the game file or folder and also remove its **Delete** _(Files only)_ -This will remove the actual game file and its gamelist.xml entry, as well as any media files. A prompt will be shown asking for confirmation. The deletion of folders is not supported as that would potentially be a bit dangerous, instead use the appropriate operating system tools to handle deletion of folders. +This will remove the actual game file, its gamelist.xml entry, its entry in any custom collections and its media files. A prompt will be shown asking for confirmation. The deletion of folders is not supported as that would potentially be a bit dangerous, instead use the appropriate operating system tools to handle deletion of folders. ## Screensaver @@ -1016,7 +1016,7 @@ Note that you should only enable these collections if you really need them as th ### Custom collections -These are collections that you create yourself. Example of such collections could be grouping in genres like _Shoot 'em up_, _Fighting_ etc. or perhaps a time period like '1980s', '1990s' and so on. +These are collections that you create yourself. Example of such collections could be grouping in genres like _Shoot em up_, _Fighting games_ etc. or perhaps a time period like '1980s', '1990s' and so on. If the theme set supports it, you can create a custom collection directly from a theme. However, as of version 1.0.0, rbsimple-DE does not provide such themes. @@ -1045,6 +1045,8 @@ The file contents is simply a list of ROM files, such as the following: %ROMPATH%/nes/Legend of Zelda, The.zip ``` +Any changes to custom collections (for example adding or removing a game) will be immediately written to the corresponding collection configuration file. + Note that if you for example copy or migrate a collection from a previous version of EmulationStation or if you're setting up EmulationStation Desktop Edition on a new computer, even though you copy the files into the collections directory, they will not show up in the application. You always need to enable the collection in the menu. ES looks inside the es_settings.cfg file during startup to see which collections should be shown. If you're migrating from a previous version of EmulationStation that has absolute paths in the collection files, these will be rewritten with the %ROMPATH% variable the first time you make a change to the collection. Be aware though that if at this time the ROM was not found by ES, the corresponding entry in the collections file will be deleted. diff --git a/es-app/src/CollectionSystemManager.cpp b/es-app/src/CollectionSystemManager.cpp index 09c642dda..7e29e3210 100644 --- a/es-app/src/CollectionSystemManager.cpp +++ b/es-app/src/CollectionSystemManager.cpp @@ -90,14 +90,11 @@ CollectionSystemManager::~CollectionSystemManager() if (SystemData::sSystemVector.size() > 0) removeCollectionsFromDisplayedSystems(); - // Save and delete all custom collections. + // Delete all custom collections. for (std::map::const_iterator it = mCustomCollectionSystemsData.cbegin(); - it != mCustomCollectionSystemsData.cend() ; it++) { - if (it->second.isPopulated) - saveCustomCollection(it->second.system); + it != mCustomCollectionSystemsData.cend() ; it++) delete it->second.system; - } // Delete the custom collections bundle. if (mCustomCollectionsBundle) @@ -141,66 +138,64 @@ void CollectionSystemManager::saveCustomCollection(SystemData* sys) if (found) { CollectionSystemData sysData = mCustomCollectionSystemsData.at(name); - if (sysData.needsSave) { - // Read back any entries from the configuration file for game files that are - // currently missing, and combine them with the active content. If we wouldn't do - // this, they would be purged from the collection. Maybe a directory has been - // temporarily moved or the files are not reachable for whatever reason. It would - // be incredibly annoying to have entries purged from the collection in such - // instances. Using the logic below, the handling of custom collections corresponds - // to the handling of gamelist.xml files, i.e. it's up to the user to make a - // conscious decision of what entries to remove. - std::vector fileGameEntries; - std::vector activeGameEntries; - std::ifstream configFileIn; - std::ofstream configFileOut; + // Read back any entries from the configuration file for game files that are + // currently missing, and combine them with the active content. If we wouldn't do + // this, they would be purged from the collection. Maybe a directory has been + // temporarily moved or the files are not reachable for whatever reason. It would + // be incredibly annoying to have entries purged from the collection in such + // instances. Using the logic below, the handling of custom collections corresponds + // to the handling of gamelist.xml files, i.e. it's up to the user to make a + // conscious decision of what entries to remove. + std::vector fileGameEntries; + std::vector activeGameEntries; + std::ifstream configFileIn; + std::ofstream configFileOut; - #if defined(_WIN64) - configFileIn.open(Utils::String:: - stringToWideString(getCustomCollectionConfigPath(name)).c_str()); - #else - configFileIn.open(getCustomCollectionConfigPath(name)); - #endif - for (std::string gameEntry; getline(configFileIn, gameEntry); ) { - std::string gamePath = Utils::String::replace(gameEntry, "%ROMPATH%", rompath); - gamePath = Utils::String::replace(gamePath, "//", "/"); - // Only add the entry if it's not a regular file or a symlink, in other words - // only add missing files. - if (!Utils::FileSystem::isRegularFile(gamePath) && - !Utils::FileSystem::isSymlink(gamePath)) - fileGameEntries.push_back(gameEntry); - } - configFileIn.close(); - - for (std::unordered_map::const_iterator - iter = games.cbegin(); iter != games.cend(); ++iter) { - std::string path = iter->first; - // If the ROM path of the game begins with the path from the setting - // ROMDirectory (or the default ROM directory), then replace it with %ROMPATH%. - if (path.find(rompath) == 0) - path.replace(0, rompath.size(), "%ROMPATH%/"); - - activeGameEntries.push_back(path); - } - - fileGameEntries.insert(fileGameEntries.cend(), activeGameEntries.cbegin(), - activeGameEntries.cend()); - std::sort(fileGameEntries.begin(), fileGameEntries.end()); - auto last = std::unique(fileGameEntries.begin(), fileGameEntries.end()); - fileGameEntries.erase(last, fileGameEntries.end()); - - #if defined(_WIN64) - configFile.open(Utils::String:: - stringToWideString(getCustomCollectionConfigPath(name)).c_str()); - #else - configFileOut.open(getCustomCollectionConfigPath(name)); - #endif - - for (auto it = fileGameEntries.cbegin(); it != fileGameEntries.cend(); it++) - configFileOut << (*it) << std::endl; - - configFileOut.close(); + #if defined(_WIN64) + configFileIn.open(Utils::String:: + stringToWideString(getCustomCollectionConfigPath(name)).c_str()); + #else + configFileIn.open(getCustomCollectionConfigPath(name)); + #endif + for (std::string gameEntry; getline(configFileIn, gameEntry); ) { + std::string gamePath = Utils::String::replace(gameEntry, "%ROMPATH%", rompath); + gamePath = Utils::String::replace(gamePath, "//", "/"); + // Only add the entry if it's not a regular file or a symlink, in other words + // only add missing files. + if (!Utils::FileSystem::isRegularFile(gamePath) && + !Utils::FileSystem::isSymlink(gamePath)) + fileGameEntries.push_back(gameEntry); } + configFileIn.close(); + + for (std::unordered_map::const_iterator + iter = games.cbegin(); iter != games.cend(); ++iter) { + std::string path = iter->first; + // If the ROM path of the game begins with the path from the setting + // ROMDirectory (or the default ROM directory), then replace it with %ROMPATH%. + if (path.find(rompath) == 0) + path.replace(0, rompath.size(), "%ROMPATH%/"); + + activeGameEntries.push_back(path); + } + + fileGameEntries.insert(fileGameEntries.cend(), activeGameEntries.cbegin(), + activeGameEntries.cend()); + std::sort(fileGameEntries.begin(), fileGameEntries.end()); + auto last = std::unique(fileGameEntries.begin(), fileGameEntries.end()); + fileGameEntries.erase(last, fileGameEntries.end()); + + #if defined(_WIN64) + configFile.open(Utils::String:: + stringToWideString(getCustomCollectionConfigPath(name)).c_str()); + #else + configFileOut.open(getCustomCollectionConfigPath(name)); + #endif + + for (auto it = fileGameEntries.cbegin(); it != fileGameEntries.cend(); it++) + configFileOut << (*it) << std::endl; + + configFileOut.close(); } else { LOG(LogError) << "Couldn't find collection to save: " << name; @@ -314,7 +309,6 @@ void CollectionSystemManager::refreshCollectionSystems(FileData* file) realSys.system = file->getSystem(); realSys.isEnabled = true; realSys.isPopulated = true; - realSys.needsSave = false; realSys.decl.isCustom = false; updateCollectionSystem(file, realSys); @@ -483,11 +477,12 @@ void CollectionSystemManager::deleteCollectionFiles(FileData* file) bool found = children.find(key) != children.cend(); if (found) { - sysDataIt->second.needsSave = true; FileData* collectionEntry = children.at(key); SystemData* systemViewToUpdate = getSystemToView(sysDataIt->second.system); ViewController::get()->getGameListView(systemViewToUpdate).get()-> remove(collectionEntry, false); + if (sysDataIt->second.decl.isCustom) + saveCustomCollection(sysDataIt->second.system); } } } @@ -622,7 +617,6 @@ bool CollectionSystemManager::toggleGameInCollection(FileData* file) std::string sysName = mEditingCollection; if (mIsEditingCustom) { SystemData* sysData = mEditingCollectionSystemData->system; - mEditingCollectionSystemData->needsSave = true; if (!mEditingCollectionSystemData->isPopulated) populateCustomCollection(mEditingCollectionSystemData); @@ -672,6 +666,7 @@ bool CollectionSystemManager::toggleGameInCollection(FileData* file) refreshCollectionSystems(newGame); } updateCollectionFolderMetadata(sysData); + saveCustomCollection(sysData); } else { file->getSourceFileData()->getSystem()->getIndex()->removeFromIndex(file); @@ -856,7 +851,6 @@ SystemData* CollectionSystemManager::createNewCollectionEntry( newCollectionData.decl = sysDecl; newCollectionData.isEnabled = false; newCollectionData.isPopulated = false; - newCollectionData.needsSave = false; if (index) { if (!sysDecl.isCustom) diff --git a/es-app/src/CollectionSystemManager.h b/es-app/src/CollectionSystemManager.h index 79dd52b5b..7591cd717 100644 --- a/es-app/src/CollectionSystemManager.h +++ b/es-app/src/CollectionSystemManager.h @@ -51,7 +51,6 @@ struct CollectionSystemData { CollectionSystemDecl decl; bool isEnabled; bool isPopulated; - bool needsSave; }; class CollectionSystemManager diff --git a/es-app/src/guis/GuiCollectionSystemsOptions.cpp b/es-app/src/guis/GuiCollectionSystemsOptions.cpp index 38555e296..fe32ce956 100644 --- a/es-app/src/guis/GuiCollectionSystemsOptions.cpp +++ b/es-app/src/guis/GuiCollectionSystemsOptions.cpp @@ -134,6 +134,7 @@ void GuiCollectionSystemsOptions::addEntry(const char* name, unsigned int color, void GuiCollectionSystemsOptions::createCollection(std::string inName) { std::string name = CollectionSystemManager::get()->getValidNewCollectionName(inName); SystemData* newSys = CollectionSystemManager::get()->addNewCustomCollection(name); + CollectionSystemManager::get()->saveCustomCollection(newSys); customOptionList->add(name, name, true); std::string outAuto = Utils::String::vectorToCommaString( autoOptionList->getSelectedObjects()); diff --git a/es-app/src/guis/GuiCollectionSystemsOptions.h b/es-app/src/guis/GuiCollectionSystemsOptions.h index 3116d18de..64f34b1f5 100644 --- a/es-app/src/guis/GuiCollectionSystemsOptions.h +++ b/es-app/src/guis/GuiCollectionSystemsOptions.h @@ -36,8 +36,8 @@ private: void updateSettings(std::string newAutoSettings, std::string newCustomSettings); void createCollection(std::string inName); void exitEditMode(); - std::shared_ptr< OptionListComponent > autoOptionList; - std::shared_ptr< OptionListComponent > customOptionList; + std::shared_ptr> autoOptionList; + std::shared_ptr> customOptionList; std::shared_ptr bundleCustomCollections; std::shared_ptr sortFavFirstCustomSwitch; std::shared_ptr toggleSystemNameInCollections;