mirror of
https://github.com/RetroDECK/ES-DE.git
synced 2025-01-17 22:55:38 +00:00
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).
This commit is contained in:
parent
626a2692e5
commit
5c65747551
|
@ -6,19 +6,8 @@
|
|||
#include "components/RatingComponent.h"
|
||||
#include "components/DateTimeComponent.h"
|
||||
|
||||
MetaDataList::MetaDataList()
|
||||
{
|
||||
}
|
||||
|
||||
MetaDataList::MetaDataList(const std::vector<MetaDataDecl>& mdd)
|
||||
{
|
||||
for(auto iter = mdd.begin(); iter != mdd.end(); iter++)
|
||||
set(iter->key, iter->defaultValue);
|
||||
}
|
||||
|
||||
std::vector<MetaDataDecl> MetaDataList::getDefaultGameMDD()
|
||||
{
|
||||
MetaDataDecl decls[] = {
|
||||
MetaDataDecl gameDecls[] = {
|
||||
{"name", MD_STRING, "", false},
|
||||
{"desc", MD_MULTILINE_STRING, "", false},
|
||||
{"image", MD_IMAGE_PATH, "", false},
|
||||
|
@ -27,15 +16,47 @@ std::vector<MetaDataDecl> MetaDataList::getDefaultGameMDD()
|
|||
{"releasedate", MD_DATE, "0", false},
|
||||
{"playcount", MD_INT, "0", true},
|
||||
{"lastplayed", MD_TIME, "0", true}
|
||||
};
|
||||
};
|
||||
const std::vector<MetaDataDecl> gameMDD(gameDecls, gameDecls + sizeof(gameDecls) / sizeof(gameDecls[0]));
|
||||
|
||||
std::vector<MetaDataDecl> mdd(decls, decls + sizeof(decls) / sizeof(decls[0]));
|
||||
return mdd;
|
||||
MetaDataDecl folderDecls[] = {
|
||||
{"name", MD_STRING, "", false},
|
||||
{"desc", MD_MULTILINE_STRING, "", false},
|
||||
{"image", MD_IMAGE_PATH, "", false},
|
||||
{"thumbnail", MD_IMAGE_PATH, "", false},
|
||||
};
|
||||
const std::vector<MetaDataDecl> folderMDD(folderDecls, folderDecls + sizeof(folderDecls) / sizeof(folderDecls[0]));
|
||||
|
||||
const std::vector<MetaDataDecl>& getMDDByType(MetaDataListType type)
|
||||
{
|
||||
switch(type)
|
||||
{
|
||||
case GAME_METADATA:
|
||||
return gameMDD;
|
||||
case FOLDER_METADATA:
|
||||
return folderMDD;
|
||||
}
|
||||
|
||||
LOG(LogError) << "Invalid MDD type";
|
||||
return gameMDD;
|
||||
}
|
||||
|
||||
MetaDataList MetaDataList::createFromXML(const std::vector<MetaDataDecl>& mdd, pugi::xml_node node)
|
||||
|
||||
|
||||
MetaDataList::MetaDataList(MetaDataListType type)
|
||||
: mType(type)
|
||||
{
|
||||
MetaDataList mdl;
|
||||
const std::vector<MetaDataDecl>& mdd = getMDD();
|
||||
for(auto iter = mdd.begin(); iter != mdd.end(); iter++)
|
||||
set(iter->key, iter->defaultValue);
|
||||
}
|
||||
|
||||
|
||||
MetaDataList MetaDataList::createFromXML(MetaDataListType type, pugi::xml_node node)
|
||||
{
|
||||
MetaDataList mdl(type);
|
||||
|
||||
const std::vector<MetaDataDecl>& mdd = mdl.getMDD();
|
||||
|
||||
for(auto iter = mdd.begin(); iter != mdd.end(); iter++)
|
||||
{
|
||||
|
@ -51,12 +72,17 @@ MetaDataList MetaDataList::createFromXML(const std::vector<MetaDataDecl>& mdd, p
|
|||
return mdl;
|
||||
}
|
||||
|
||||
void MetaDataList::appendToXML(pugi::xml_node parent, const std::vector<MetaDataDecl>& ignoreDefaults) const
|
||||
void MetaDataList::appendToXML(pugi::xml_node parent, bool ignoreDefaults) const
|
||||
{
|
||||
const std::vector<MetaDataDecl>& mdd = getMDD();
|
||||
|
||||
for(auto iter = mMap.begin(); iter != mMap.end(); iter++)
|
||||
{
|
||||
bool write = true;
|
||||
for(auto mddIter = ignoreDefaults.begin(); mddIter != ignoreDefaults.end(); mddIter++)
|
||||
|
||||
if(ignoreDefaults)
|
||||
{
|
||||
for(auto mddIter = mdd.begin(); mddIter != mdd.end(); mddIter++)
|
||||
{
|
||||
if(mddIter->key == iter->first)
|
||||
{
|
||||
|
@ -66,6 +92,7 @@ void MetaDataList::appendToXML(pugi::xml_node parent, const std::vector<MetaData
|
|||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if(write)
|
||||
parent.append_child(iter->first.c_str()).text().set(iter->second.c_str());
|
||||
|
|
|
@ -31,15 +31,21 @@ 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<MetaDataDecl>& getMDDByType(MetaDataListType type);
|
||||
|
||||
class MetaDataList
|
||||
{
|
||||
public:
|
||||
static std::vector<MetaDataDecl> getDefaultGameMDD();
|
||||
static MetaDataList createFromXML(MetaDataListType type, pugi::xml_node node);
|
||||
void appendToXML(pugi::xml_node parent, bool ignoreDefaults = false) const;
|
||||
|
||||
static MetaDataList createFromXML(const std::vector<MetaDataDecl>& mdd, pugi::xml_node node);
|
||||
|
||||
//MetaDataDecl required to set our defaults.
|
||||
MetaDataList(const std::vector<MetaDataDecl>& mdd);
|
||||
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<MetaDataDecl>& ignoreDefaults = std::vector<MetaDataDecl>()) const;
|
||||
inline MetaDataListType getType() const { return mType; }
|
||||
inline const std::vector<MetaDataDecl>& getMDD() const { return getMDDByType(getType()); }
|
||||
|
||||
private:
|
||||
MetaDataList();
|
||||
|
||||
MetaDataListType mType;
|
||||
std::map<std::string, std::string> 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
|
||||
|
|
|
@ -243,7 +243,7 @@ int run_scraper_cmdline()
|
|||
for(auto gameIt = files.begin(); gameIt != files.end(); gameIt++)
|
||||
{
|
||||
GameData* game = (GameData*)(*gameIt);
|
||||
std::vector<MetaDataDecl> mdd = (*sysIt)->getGameMDD();
|
||||
const std::vector<MetaDataDecl>& mdd = game->metadata()->getMDD();
|
||||
for(auto i = mdd.begin(); i != mdd.end(); i++)
|
||||
{
|
||||
std::string key = i->key;
|
||||
|
|
|
@ -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<MetaDataDecl> SystemData::getGameMDD()
|
||||
{
|
||||
return MetaDataList::getDefaultGameMDD();
|
||||
}
|
||||
|
||||
PlatformIds::PlatformId SystemData::getPlatformId()
|
||||
{
|
||||
return mPlatformId;
|
||||
|
|
|
@ -27,7 +27,6 @@ public:
|
|||
|
||||
std::string getGamelistPath();
|
||||
bool hasGamelist();
|
||||
std::vector<MetaDataDecl> getGameMDD();
|
||||
|
||||
unsigned int getGameCount();
|
||||
|
||||
|
|
|
@ -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<GameData*>(game)->metadata()->appendToXML(newGame, system->getGameMDD());
|
||||
const_cast<GameData*>(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
|
||||
|
|
|
@ -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());
|
||||
|
|
|
@ -99,7 +99,7 @@ std::vector<MetaDataList> 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());
|
||||
|
||||
|
|
|
@ -177,7 +177,7 @@ std::shared_ptr<Scraper> createScraperByName(const std::string& name)
|
|||
|
||||
void resolveMetaDataAssetsAsync(Window* window, const ScraperSearchParams& params, MetaDataList mdl, std::function<void(MetaDataList)> returnFunc)
|
||||
{
|
||||
std::vector<MetaDataDecl> mdd = params.system->getGameMDD();
|
||||
const std::vector<MetaDataDecl>& mdd = params.game->metadata()->getMDD();
|
||||
for(auto it = mdd.begin(); it != mdd.end(); it++)
|
||||
{
|
||||
std::string key = it->key;
|
||||
|
|
|
@ -44,7 +44,7 @@ std::vector<MetaDataList> 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());
|
||||
|
||||
|
|
Loading…
Reference in a new issue