From 5c65747551c217105501b869d153f22f411dfa1b Mon Sep 17 00:00:00 2001 From: Aloshi Date: Sun, 3 Nov 2013 19:54:13 -0600 Subject: [PATCH] Moved metadata type declarations more behind-the-scenes. The original plan was to allow each system to have customizable lists of metadata, which made constructing metadata really painful (the declaration list isn't stored on the metadata instance because that's pretty wasteful for 2,000 games). Now they're constructed by passing a MetaDataListType enum in the constructor. Declaration lists are now managed by const globals passed by reference through getMDDByType(MetaDataListType). --- src/MetaData.cpp | 83 ++++++++++++++++++++---------- src/MetaData.h | 27 ++++++---- src/ScraperCmdLine.cpp | 2 +- src/SystemData.cpp | 7 +-- src/SystemData.h | 3 +- src/XMLReader.cpp | 6 +-- src/components/GuiGameList.cpp | 2 +- src/scrapers/GamesDBScraper.cpp | 2 +- src/scrapers/Scraper.cpp | 2 +- src/scrapers/TheArchiveScraper.cpp | 2 +- 10 files changed, 82 insertions(+), 54 deletions(-) diff --git a/src/MetaData.cpp b/src/MetaData.cpp index 5879888d2..4a782f5bc 100644 --- a/src/MetaData.cpp +++ b/src/MetaData.cpp @@ -6,36 +6,57 @@ #include "components/RatingComponent.h" #include "components/DateTimeComponent.h" -MetaDataList::MetaDataList() + +MetaDataDecl gameDecls[] = { + {"name", MD_STRING, "", false}, + {"desc", MD_MULTILINE_STRING, "", false}, + {"image", MD_IMAGE_PATH, "", false}, + {"thumbnail", MD_IMAGE_PATH, "", false}, + {"rating", MD_RATING, "0", false}, + {"releasedate", MD_DATE, "0", false}, + {"playcount", MD_INT, "0", true}, + {"lastplayed", MD_TIME, "0", true} +}; +const std::vector gameMDD(gameDecls, gameDecls + sizeof(gameDecls) / sizeof(gameDecls[0])); + +MetaDataDecl folderDecls[] = { + {"name", MD_STRING, "", false}, + {"desc", MD_MULTILINE_STRING, "", false}, + {"image", MD_IMAGE_PATH, "", false}, + {"thumbnail", MD_IMAGE_PATH, "", false}, +}; +const std::vector folderMDD(folderDecls, folderDecls + sizeof(folderDecls) / sizeof(folderDecls[0])); + +const std::vector& getMDDByType(MetaDataListType type) { + switch(type) + { + case GAME_METADATA: + return gameMDD; + case FOLDER_METADATA: + return folderMDD; + } + + LOG(LogError) << "Invalid MDD type"; + return gameMDD; } -MetaDataList::MetaDataList(const std::vector& mdd) + + +MetaDataList::MetaDataList(MetaDataListType type) + : mType(type) { + const std::vector& mdd = getMDD(); for(auto iter = mdd.begin(); iter != mdd.end(); iter++) set(iter->key, iter->defaultValue); } -std::vector MetaDataList::getDefaultGameMDD() -{ - MetaDataDecl decls[] = { - {"name", MD_STRING, "", false}, - {"desc", MD_MULTILINE_STRING, "", false}, - {"image", MD_IMAGE_PATH, "", false}, - {"thumbnail", MD_IMAGE_PATH, "", false}, - {"rating", MD_RATING, "0", false}, - {"releasedate", MD_DATE, "0", false}, - {"playcount", MD_INT, "0", true}, - {"lastplayed", MD_TIME, "0", true} - }; - std::vector mdd(decls, decls + sizeof(decls) / sizeof(decls[0])); - return mdd; -} - -MetaDataList MetaDataList::createFromXML(const std::vector& mdd, pugi::xml_node node) +MetaDataList MetaDataList::createFromXML(MetaDataListType type, pugi::xml_node node) { - MetaDataList mdl; + MetaDataList mdl(type); + + const std::vector& mdd = mdl.getMDD(); for(auto iter = mdd.begin(); iter != mdd.end(); iter++) { @@ -51,19 +72,25 @@ MetaDataList MetaDataList::createFromXML(const std::vector& mdd, p return mdl; } -void MetaDataList::appendToXML(pugi::xml_node parent, const std::vector& ignoreDefaults) const +void MetaDataList::appendToXML(pugi::xml_node parent, bool ignoreDefaults) const { + const std::vector& mdd = getMDD(); + for(auto iter = mMap.begin(); iter != mMap.end(); iter++) { bool write = true; - for(auto mddIter = ignoreDefaults.begin(); mddIter != ignoreDefaults.end(); mddIter++) - { - if(mddIter->key == iter->first) - { - if(iter->second == mddIter->defaultValue) - write = false; - break; + if(ignoreDefaults) + { + for(auto mddIter = mdd.begin(); mddIter != mdd.end(); mddIter++) + { + if(mddIter->key == iter->first) + { + if(iter->second == mddIter->defaultValue) + write = false; + + break; + } } } diff --git a/src/MetaData.h b/src/MetaData.h index f83d2aeed..48c6c3f5c 100644 --- a/src/MetaData.h +++ b/src/MetaData.h @@ -31,16 +31,22 @@ struct MetaDataDecl boost::posix_time::ptime string_to_ptime(const std::string& str, const std::string& fmt = "%Y%m%dT%H%M%S%F%q"); +enum MetaDataListType +{ + GAME_METADATA, + FOLDER_METADATA +}; + +const std::vector& getMDDByType(MetaDataListType type); + class MetaDataList { public: - static std::vector getDefaultGameMDD(); - - static MetaDataList createFromXML(const std::vector& mdd, pugi::xml_node node); - - //MetaDataDecl required to set our defaults. - MetaDataList(const std::vector& mdd); + static MetaDataList createFromXML(MetaDataListType type, pugi::xml_node node); + void appendToXML(pugi::xml_node parent, bool ignoreDefaults = false) const; + MetaDataList(MetaDataListType type); + void set(const std::string& key, const std::string& value); void setTime(const std::string& key, const boost::posix_time::ptime& time); //times are internally stored as ISO strings (e.g. boost::posix_time::to_iso_string(ptime)) @@ -52,11 +58,11 @@ public: static GuiComponent* makeDisplay(Window* window, MetaDataType as); static GuiComponent* makeEditor(Window* window, MetaDataType as); - void appendToXML(pugi::xml_node parent, const std::vector& ignoreDefaults = std::vector()) const; + inline MetaDataListType getType() const { return mType; } + inline const std::vector& getMDD() const { return getMDDByType(getType()); } private: - MetaDataList(); - + MetaDataListType mType; std::map mMap; }; @@ -64,7 +70,8 @@ private: //options for storing metadata... //store internally everything as a string - this is all going to be read to/from XML anyway, after all -//store using individual get/set functions ala Settings - this is a fair amount of work but the most explicit, for better or worse +// - problem: this does not play nice with lists of values +//store using individual get/set functions ala Settings - this is a fair amount of work but the most explicit and type-safe, for better or worse //let's think about some of the special types we would like to support... //image paths, sound paths, ratings, play counts diff --git a/src/ScraperCmdLine.cpp b/src/ScraperCmdLine.cpp index f62b64a03..53fce16c5 100644 --- a/src/ScraperCmdLine.cpp +++ b/src/ScraperCmdLine.cpp @@ -243,7 +243,7 @@ int run_scraper_cmdline() for(auto gameIt = files.begin(); gameIt != files.end(); gameIt++) { GameData* game = (GameData*)(*gameIt); - std::vector mdd = (*sysIt)->getGameMDD(); + const std::vector& mdd = game->metadata()->getMDD(); for(auto i = mdd.begin(); i != mdd.end(); i++) { std::string key = i->key; diff --git a/src/SystemData.cpp b/src/SystemData.cpp index 9a308510a..84b3e7ddd 100644 --- a/src/SystemData.cpp +++ b/src/SystemData.cpp @@ -142,7 +142,7 @@ void SystemData::populateFolder(FolderData* folder) isGame = false; if(std::find(mSearchExtensions.begin(), mSearchExtensions.end(), extension) != mSearchExtensions.end()) { - GameData* newGame = new GameData(filePath.generic_string(), MetaDataList(getGameMDD())); + GameData* newGame = new GameData(filePath.generic_string(), MetaDataList(GAME_METADATA)); folder->pushFileData(newGame); isGame = true; } @@ -335,11 +335,6 @@ bool SystemData::hasGamelist() return (fs::exists(getGamelistPath())); } -std::vector SystemData::getGameMDD() -{ - return MetaDataList::getDefaultGameMDD(); -} - PlatformIds::PlatformId SystemData::getPlatformId() { return mPlatformId; diff --git a/src/SystemData.h b/src/SystemData.h index fb82961b9..6040d2e61 100644 --- a/src/SystemData.h +++ b/src/SystemData.h @@ -27,8 +27,7 @@ public: std::string getGamelistPath(); bool hasGamelist(); - std::vector getGameMDD(); - + unsigned int getGameCount(); void launchGame(Window* window, GameData* game); diff --git a/src/XMLReader.cpp b/src/XMLReader.cpp index 5cd25df08..35f8fdcda 100644 --- a/src/XMLReader.cpp +++ b/src/XMLReader.cpp @@ -91,7 +91,7 @@ GameData* createGameFromPath(std::string gameAbsPath, SystemData* system) loops++; } - GameData* game = new GameData(gameAbsPath, MetaDataList(system->getGameMDD())); + GameData* game = new GameData(gameAbsPath, MetaDataList(GAME_METADATA)); folder->pushFileData(game); return game; } @@ -156,7 +156,7 @@ void parseGamelist(SystemData* system) game = createGameFromPath(path, system); //load the metadata - *(game->metadata()) = MetaDataList::createFromXML(system->getGameMDD(), gameNode); + *(game->metadata()) = MetaDataList::createFromXML(GAME_METADATA, gameNode); //make sure name gets set if one didn't exist if(game->metadata()->get("name").empty()) @@ -173,7 +173,7 @@ void addGameDataNode(pugi::xml_node& parent, const GameData* game, SystemData* s pugi::xml_node newGame = parent.append_child("game"); //write metadata - const_cast(game)->metadata()->appendToXML(newGame, system->getGameMDD()); + const_cast(game)->metadata()->appendToXML(newGame, true); if(newGame.children().begin() == newGame.child("name") //first element is name && ++newGame.children().begin() == newGame.children().end() //theres only one element diff --git a/src/components/GuiGameList.cpp b/src/components/GuiGameList.cpp index c7c5a6baa..88908c6d7 100644 --- a/src/components/GuiGameList.cpp +++ b/src/components/GuiGameList.cpp @@ -149,7 +149,7 @@ bool GuiGameList::input(InputConfig* config, Input input) ScraperSearchParams searchParams; searchParams.game = game; searchParams.system = mSystem; - mWindow->pushGui(new GuiMetaDataEd(mWindow, game->metadata(), mSystem->getGameMDD(), searchParams, game->getBaseName(), + mWindow->pushGui(new GuiMetaDataEd(mWindow, game->metadata(), game->metadata()->getMDD(), searchParams, game->getBaseName(), [&] { updateDetailData(); }, [game, root, this] { boost::filesystem::remove(game->getPath()); diff --git a/src/scrapers/GamesDBScraper.cpp b/src/scrapers/GamesDBScraper.cpp index 00dfe1765..10be80824 100644 --- a/src/scrapers/GamesDBScraper.cpp +++ b/src/scrapers/GamesDBScraper.cpp @@ -99,7 +99,7 @@ std::vector GamesDBScraper::parseReq(ScraperSearchParams params, s pugi::xml_node game = data.child("Game"); while(game && resultNum < MAX_SCRAPER_RESULTS) { - mdl.push_back(MetaDataList(params.system->getGameMDD())); + mdl.push_back(MetaDataList(GAME_METADATA)); mdl.back().set("name", game.child("GameTitle").text().get()); mdl.back().set("desc", game.child("Overview").text().get()); diff --git a/src/scrapers/Scraper.cpp b/src/scrapers/Scraper.cpp index 8f8058ac6..4f5d0a7af 100644 --- a/src/scrapers/Scraper.cpp +++ b/src/scrapers/Scraper.cpp @@ -177,7 +177,7 @@ std::shared_ptr createScraperByName(const std::string& name) void resolveMetaDataAssetsAsync(Window* window, const ScraperSearchParams& params, MetaDataList mdl, std::function returnFunc) { - std::vector mdd = params.system->getGameMDD(); + const std::vector& mdd = params.game->metadata()->getMDD(); for(auto it = mdd.begin(); it != mdd.end(); it++) { std::string key = it->key; diff --git a/src/scrapers/TheArchiveScraper.cpp b/src/scrapers/TheArchiveScraper.cpp index efa542a77..4ad80a161 100644 --- a/src/scrapers/TheArchiveScraper.cpp +++ b/src/scrapers/TheArchiveScraper.cpp @@ -44,7 +44,7 @@ std::vector TheArchiveScraper::parseReq(ScraperSearchParams params pugi::xml_node game = data.child("game"); while(game && resultNum < MAX_SCRAPER_RESULTS) { - mdl.push_back(MetaDataList(params.system->getGameMDD())); + mdl.push_back(MetaDataList(GAME_METADATA)); mdl.back().set("name", game.child("title").text().get()); mdl.back().set("desc", game.child("description").text().get());