Changes to custom collections are now immediately written to disk.

This commit is contained in:
Leon Styhre 2020-10-19 20:58:00 +02:00
parent 9f617cd038
commit 46520202f7
5 changed files with 68 additions and 72 deletions

View file

@ -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.

View file

@ -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<std::string, CollectionSystemData>::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<std::string> fileGameEntries;
std::vector<std::string> 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<std::string> fileGameEntries;
std::vector<std::string> 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<std::string, FileData*>::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<std::string, FileData*>::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)

View file

@ -51,7 +51,6 @@ struct CollectionSystemData {
CollectionSystemDecl decl;
bool isEnabled;
bool isPopulated;
bool needsSave;
};
class CollectionSystemManager

View file

@ -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());

View file

@ -36,8 +36,8 @@ private:
void updateSettings(std::string newAutoSettings, std::string newCustomSettings);
void createCollection(std::string inName);
void exitEditMode();
std::shared_ptr< OptionListComponent<std::string> > autoOptionList;
std::shared_ptr< OptionListComponent<std::string> > customOptionList;
std::shared_ptr<OptionListComponent<std::string>> autoOptionList;
std::shared_ptr<OptionListComponent<std::string>> customOptionList;
std::shared_ptr<SwitchComponent> bundleCustomCollections;
std::shared_ptr<SwitchComponent> sortFavFirstCustomSwitch;
std::shared_ptr<SwitchComponent> toggleSystemNameInCollections;