diff --git a/es-app/src/CollectionSystemManager.cpp b/es-app/src/CollectionSystemManager.cpp index bdc9916b9..364160fff 100644 --- a/es-app/src/CollectionSystemManager.cpp +++ b/es-app/src/CollectionSystemManager.cpp @@ -448,6 +448,8 @@ void CollectionSystemManager::exitEditMode() mWindow->setInfoPopup(s); mIsEditingCustom = false; mEditingCollection = "Favorites"; + + mEditingCollectionSystemData->system->onMetaDataSavePoint(); } // adds or removes a game from a specific collection @@ -521,6 +523,9 @@ bool CollectionSystemManager::toggleGameInCollection(FileData* file) md->set("favorite", "false"); } file->getSourceFileData()->getSystem()->getIndex()->addToIndex(file); + + file->getSourceFileData()->getSystem()->onMetaDataSavePoint(); + refreshCollectionSystems(file->getSourceFileData()); } if (adding) diff --git a/es-app/src/FileData.cpp b/es-app/src/FileData.cpp index 5251b3373..31b9848b8 100644 --- a/es-app/src/FileData.cpp +++ b/es-app/src/FileData.cpp @@ -310,6 +310,8 @@ void FileData::launchGame(Window* window) //update last played time gameToUpdate->metadata.set("lastplayed", Utils::Time::DateTime(Utils::Time::now())); CollectionSystemManager::get()->refreshCollectionSystems(gameToUpdate); + + gameToUpdate->mSystem->onMetaDataSavePoint(); } CollectionFileData::CollectionFileData(FileData* file, SystemData* system) diff --git a/es-app/src/Gamelist.cpp b/es-app/src/Gamelist.cpp index a6975de2f..313670420 100644 --- a/es-app/src/Gamelist.cpp +++ b/es-app/src/Gamelist.cpp @@ -1,5 +1,7 @@ #include "Gamelist.h" +#include + #include "utils/FileSystemUtil.h" #include "FileData.h" #include "FileFilterIndex.h" @@ -250,6 +252,8 @@ void updateGamelist(SystemData* system) //now write the file if (numUpdated > 0) { + const auto startTs = std::chrono::system_clock::now(); + //make sure the folders leading up to this path exist (or the write will fail) std::string xmlWritePath(system->getGamelistPath(true)); Utils::FileSystem::createDirectory(Utils::FileSystem::getParent(xmlWritePath)); @@ -259,6 +263,9 @@ void updateGamelist(SystemData* system) if (!doc.save_file(xmlWritePath.c_str())) { LOG(LogError) << "Error saving gamelist.xml to \"" << xmlWritePath << "\" (for system " << system->getName() << ")!"; } + + const auto endTs = std::chrono::system_clock::now(); + LOG(LogInfo) << "Saved gamelist.xml for system \"" << system->getName() << "\" in " << std::chrono::duration_cast(endTs - startTs).count() << " ms"; } }else{ LOG(LogError) << "Found no root folder for system \"" << system->getName() << "\"!"; diff --git a/es-app/src/SystemData.cpp b/es-app/src/SystemData.cpp index 65c4fc975..11ff0b830 100644 --- a/es-app/src/SystemData.cpp +++ b/es-app/src/SystemData.cpp @@ -50,11 +50,8 @@ SystemData::SystemData(const std::string& name, const std::string& fullName, Sys SystemData::~SystemData() { - //save changed game data back to xml - if(!Settings::getInstance()->getBool("IgnoreGamelist") && Settings::getInstance()->getBool("SaveGamelistsOnExit") && !mIsCollectionSystem) - { - updateGamelist(this); - } + if(Settings::getInstance()->getString("SaveGamelistsMode") == "on exit") + writeMetaData(); delete mRootFolder; delete mFilterIndex; @@ -502,3 +499,18 @@ void SystemData::loadTheme() mTheme = std::make_shared(); // reset to empty } } + +void SystemData::writeMetaData() { + if(Settings::getInstance()->getBool("IgnoreGamelist") || mIsCollectionSystem) + return; + + //save changed game data back to xml + updateGamelist(this); +} + +void SystemData::onMetaDataSavePoint() { + if(Settings::getInstance()->getString("SaveGamelistsMode") != "always") + return; + + writeMetaData(); +} diff --git a/es-app/src/SystemData.h b/es-app/src/SystemData.h index 63bf667fe..b72e48e38 100644 --- a/es-app/src/SystemData.h +++ b/es-app/src/SystemData.h @@ -68,6 +68,7 @@ public: void loadTheme(); FileFilterIndex* getIndex() { return mFilterIndex; }; + void onMetaDataSavePoint(); private: bool mIsCollectionSystem; @@ -81,6 +82,7 @@ private: void populateFolder(FileData* folder); void indexAllGameFilters(const FileData* folder); void setIsGameSystemStatus(); + void writeMetaData(); FileFilterIndex* mFilterIndex; diff --git a/es-app/src/guis/GuiMenu.cpp b/es-app/src/guis/GuiMenu.cpp index 8e588989f..42a781c31 100644 --- a/es-app/src/guis/GuiMenu.cpp +++ b/es-app/src/guis/GuiMenu.cpp @@ -401,10 +401,18 @@ void GuiMenu::openOtherSettings() }); // gamelists - auto save_gamelists = std::make_shared(mWindow); - save_gamelists->setState(Settings::getInstance()->getBool("SaveGamelistsOnExit")); - s->addWithLabel("SAVE METADATA ON EXIT", save_gamelists); - s->addSaveFunc([save_gamelists] { Settings::getInstance()->setBool("SaveGamelistsOnExit", save_gamelists->getState()); }); + auto gamelistsSaveMode = std::make_shared< OptionListComponent >(mWindow, "SAVE METADATA", false); + std::vector saveModes; + saveModes.push_back("on exit"); + saveModes.push_back("always"); + saveModes.push_back("never"); + + for(auto it = saveModes.cbegin(); it != saveModes.cend(); it++) + gamelistsSaveMode->add(*it, *it, Settings::getInstance()->getString("SaveGamelistsMode") == *it); + s->addWithLabel("SAVE METADATA", gamelistsSaveMode); + s->addSaveFunc([gamelistsSaveMode] { + Settings::getInstance()->setString("SaveGamelistsMode", gamelistsSaveMode->getSelected()); + }); auto parse_gamelists = std::make_shared(mWindow); parse_gamelists->setState(Settings::getInstance()->getBool("ParseGamelistOnly")); diff --git a/es-app/src/guis/GuiMetaDataEd.cpp b/es-app/src/guis/GuiMetaDataEd.cpp index fe7d29a96..edfde7355 100644 --- a/es-app/src/guis/GuiMetaDataEd.cpp +++ b/es-app/src/guis/GuiMetaDataEd.cpp @@ -199,6 +199,8 @@ void GuiMetaDataEd::save() // update respective Collection Entries CollectionSystemManager::get()->refreshCollectionSystems(mScraperParams.game); + + mScraperParams.system->onMetaDataSavePoint(); } void GuiMetaDataEd::fetch() diff --git a/es-core/src/Settings.cpp b/es-core/src/Settings.cpp index 3ad7f6586..d110efac2 100644 --- a/es-core/src/Settings.cpp +++ b/es-core/src/Settings.cpp @@ -75,7 +75,6 @@ void Settings::setDefaults() mBoolMap["HideConsole"] = true; mBoolMap["QuickSystemSelect"] = true; mBoolMap["MoveCarousel"] = true; - mBoolMap["SaveGamelistsOnExit"] = true; mBoolMap["Debug"] = false; mBoolMap["DebugGrid"] = false; @@ -96,6 +95,7 @@ void Settings::setDefaults() mStringMap["ScreenSaverBehavior"] = "dim"; mStringMap["Scraper"] = "TheGamesDB"; mStringMap["GamelistViewStyle"] = "automatic"; + mStringMap["SaveGamelistsMode"] = "on exit"; mBoolMap["ScreenSaverControls"] = true; mStringMap["ScreenSaverGameInfo"] = "never"; @@ -225,6 +225,19 @@ void Settings::loadFile() setFloat(node.attribute("name").as_string(), node.attribute("value").as_float()); 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()); + + processBackwardCompatibility(); +} + +void Settings::processBackwardCompatibility() +{ + { // SaveGamelistsOnExit -> SaveGamelistsMode + std::map::const_iterator it = mBoolMap.find("SaveGamelistsOnExit"); + if (it != mBoolMap.end()) { + mStringMap["SaveGamelistsMode"] = it->second ? "on exit" : "never"; + mBoolMap.erase(it); + } + } } //Print a warning message if the setting we're trying to get doesn't already exist in the map, then return the value in the map. diff --git a/es-core/src/Settings.h b/es-core/src/Settings.h index 413694b71..e9b9f7f03 100644 --- a/es-core/src/Settings.h +++ b/es-core/src/Settings.h @@ -31,6 +31,7 @@ private: //Clear everything and load default values. void setDefaults(); + void processBackwardCompatibility(); std::map mBoolMap; std::map mIntMap;