mirror of
https://github.com/RetroDECK/ES-DE.git
synced 2025-03-06 14:27:43 +00:00
231 lines
12 KiB
C++
231 lines
12 KiB
C++
// SPDX-License-Identifier: MIT
|
|
//
|
|
// ES-DE Frontend
|
|
// MetaData.cpp
|
|
//
|
|
// Static data for default metadata values as well as functions
|
|
// to read and write metadata from the gamelist files.
|
|
//
|
|
|
|
#include "MetaData.h"
|
|
|
|
#include "Log.h"
|
|
#include "utils/FileSystemUtil.h"
|
|
#include "utils/LocalizationUtil.h"
|
|
|
|
#include <pugixml.hpp>
|
|
|
|
namespace
|
|
{
|
|
// clang-format off
|
|
// The statistic entries must be placed at the bottom or otherwise there will be problems with
|
|
// saving the values in GuiMetaDataEd.
|
|
MetaDataDecl gameDecls[] {
|
|
// Key Type Default value Statistic Name in GuiMetaDataEd Prompt in GuiMetaDataEd Scrape
|
|
{"name", MD_STRING, "", false, "NAME", "ENTER NAME", true},
|
|
{"sortname", MD_STRING, "", false, "SORTNAME", "ENTER SORTNAME", false},
|
|
{"collectionsortname", MD_STRING, "", false, "CUSTOM COLLECTIONS SORTNAME", "ENTER COLLECTIONS SORTNAME", false},
|
|
{"desc", MD_MULTILINE_STRING, "", false, "DESCRIPTION", "ENTER DESCRIPTION", true},
|
|
{"rating", MD_RATING, "0", false, "RATING", "ENTER RATING", true},
|
|
{"releasedate", MD_DATE, "19700101T000000", false, "RELEASE DATE", "ENTER RELEASE DATE", true},
|
|
{"developer", MD_STRING, "unknown", false, "DEVELOPER", "ENTER DEVELOPER", true},
|
|
{"publisher", MD_STRING, "unknown", false, "PUBLISHER", "ENTER PUBLISHER", true},
|
|
{"genre", MD_STRING, "unknown", false, "GENRE", "ENTER GENRE", true},
|
|
{"players", MD_STRING, "unknown", false, "PLAYERS", "ENTER NUMBER OF PLAYERS", true},
|
|
{"favorite", MD_BOOL, "false", false, "FAVORITE", "ENTER FAVORITE OFF/ON", false},
|
|
{"completed", MD_BOOL, "false", false, "COMPLETED", "ENTER COMPLETED OFF/ON", false},
|
|
{"kidgame", MD_BOOL, "false", false, "KIDGAME", "ENTER KIDGAME OFF/ON", false},
|
|
{"hidden", MD_BOOL, "false", false, "HIDDEN", "ENTER HIDDEN OFF/ON", false},
|
|
{"broken", MD_BOOL, "false", false, "BROKEN/NOT WORKING", "ENTER BROKEN OFF/ON", false},
|
|
{"nogamecount", MD_BOOL, "false", false, "EXCLUDE FROM GAME COUNTER", "ENTER DON'T COUNT AS GAME OFF/ON", false},
|
|
{"nomultiscrape", MD_BOOL, "false", false, "EXCLUDE FROM MULTI-SCRAPER", "ENTER NO MULTI-SCRAPE OFF/ON", false},
|
|
{"hidemetadata", MD_BOOL, "false", false, "HIDE METADATA FIELDS", "ENTER HIDE METADATA OFF/ON", false},
|
|
{"playcount", MD_INT, "0", false, "TIMES PLAYED", "ENTER NUMBER OF TIMES PLAYED", false},
|
|
{"controller", MD_CONTROLLER, "", false, "CONTROLLER", "SELECT CONTROLLER", true},
|
|
{"altemulator", MD_ALT_EMULATOR, "", false, "ALTERNATIVE EMULATOR", "SELECT ALTERNATIVE EMULATOR", false},
|
|
{"lastplayed", MD_TIME, "0", true, "LAST PLAYED", "ENTER LAST PLAYED DATE", false}
|
|
};
|
|
|
|
MetaDataDecl folderDecls[] {
|
|
// Key Type Default value Statistic Name in GuiMetaDataEd Prompt in GuiMetaDataEd Scrape
|
|
{"name", MD_STRING, "", false, "NAME", "ENTER NAME", true},
|
|
{"desc", MD_MULTILINE_STRING, "", false, "DESCRIPTION", "ENTER DESCRIPTION", true},
|
|
{"rating", MD_RATING, "0", false, "RATING", "ENTER RATING", true},
|
|
{"releasedate", MD_DATE, "19700101T000000", false, "RELEASE DATE", "ENTER RELEASE DATE", true},
|
|
{"developer", MD_STRING, "unknown", false, "DEVELOPER", "ENTER DEVELOPER", true},
|
|
{"publisher", MD_STRING, "unknown", false, "PUBLISHER", "ENTER PUBLISHER", true},
|
|
{"genre", MD_STRING, "unknown", false, "GENRE", "ENTER GENRE", true},
|
|
{"players", MD_STRING, "unknown", false, "PLAYERS", "ENTER NUMBER OF PLAYERS", true},
|
|
{"favorite", MD_BOOL, "false", false, "FAVORITE", "ENTER FAVORITE OFF/ON", false},
|
|
{"completed", MD_BOOL, "false", false, "COMPLETED", "ENTER COMPLETED OFF/ON", false},
|
|
{"kidgame", MD_BOOL, "false", false, "KIDGAME (ONLY AFFECTS BADGES)", "ENTER KIDGAME OFF/ON", false},
|
|
{"hidden", MD_BOOL, "false", false, "HIDDEN", "ENTER HIDDEN OFF/ON", false},
|
|
{"broken", MD_BOOL, "false", false, "BROKEN/NOT WORKING", "ENTER BROKEN OFF/ON", false},
|
|
{"nomultiscrape", MD_BOOL, "false", false, "EXCLUDE FROM MULTI-SCRAPER", "ENTER NO MULTI-SCRAPE OFF/ON", false},
|
|
{"hidemetadata", MD_BOOL, "false", false, "HIDE METADATA FIELDS", "ENTER HIDE METADATA OFF/ON", false},
|
|
{"controller", MD_CONTROLLER, "", false, "CONTROLLER", "SELECT CONTROLLER", true},
|
|
{"folderlink", MD_FOLDER_LINK, "", false, "FOLDER LINK", "SELECT FOLDER LINK", false},
|
|
{"lastplayed", MD_TIME, "0", true, "LAST PLAYED", "ENTER LAST PLAYED DATE", false}
|
|
};
|
|
// clang-format on
|
|
|
|
const std::vector<MetaDataDecl> gameMDD {gameDecls,
|
|
gameDecls + sizeof(gameDecls) / sizeof(gameDecls[0])};
|
|
|
|
const std::vector<MetaDataDecl> folderMDD {
|
|
folderDecls, folderDecls + sizeof(folderDecls) / sizeof(folderDecls[0])};
|
|
|
|
} // namespace
|
|
|
|
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(MetaDataListType type)
|
|
: mType(type)
|
|
, mWasChanged(false)
|
|
{
|
|
const std::vector<MetaDataDecl>& mdd = getMDD();
|
|
for (auto it = mdd.cbegin(); it != mdd.cend(); ++it)
|
|
set(it->key, it->defaultValue);
|
|
}
|
|
|
|
MetaDataList MetaDataList::createFromXML(MetaDataListType type,
|
|
pugi::xml_node& node,
|
|
const std::string& relativeTo)
|
|
{
|
|
MetaDataList mdl(type);
|
|
|
|
const std::vector<MetaDataDecl>& mdd = mdl.getMDD();
|
|
|
|
for (auto it = mdd.cbegin(); it != mdd.cend(); ++it) {
|
|
pugi::xml_node md = node.child(it->key.c_str());
|
|
if (md && !md.text().empty()) {
|
|
// If it's a path, resolve relative paths.
|
|
std::string value = md.text().get();
|
|
if (it->type == MD_PATH)
|
|
value = Utils::FileSystem::resolveRelativePath(value, relativeTo, true);
|
|
mdl.set(it->key, value);
|
|
}
|
|
else {
|
|
mdl.set(it->key, it->defaultValue);
|
|
}
|
|
}
|
|
return mdl;
|
|
}
|
|
|
|
void MetaDataList::appendToXML(pugi::xml_node& parent,
|
|
bool ignoreDefaults,
|
|
const std::string& relativeTo) const
|
|
{
|
|
const std::vector<MetaDataDecl>& mdd = getMDD();
|
|
|
|
for (auto it = mdd.cbegin(); it != mdd.cend(); ++it) {
|
|
auto mapIter = mMap.find(it->key);
|
|
if (mapIter != mMap.cend()) {
|
|
// We have this value!
|
|
// If it's just the default (and we ignore defaults), don't write it.
|
|
if (ignoreDefaults && mapIter->second == it->defaultValue)
|
|
continue;
|
|
|
|
// Try and make paths relative if we can.
|
|
std::string value = mapIter->second;
|
|
if (it->type == MD_PATH)
|
|
value = Utils::FileSystem::createRelativePath(value, relativeTo, true);
|
|
|
|
parent.append_child(mapIter->first.c_str()).text().set(value.c_str());
|
|
}
|
|
}
|
|
}
|
|
|
|
void MetaDataList::set(const std::string& key, const std::string& value)
|
|
{
|
|
mMap[key] = value;
|
|
mWasChanged = true;
|
|
}
|
|
|
|
const std::string& MetaDataList::get(const std::string& key) const
|
|
{
|
|
// Check that the key actually exists, otherwise return an empty string.
|
|
if (mMap.count(key) > 0)
|
|
return mMap.at(key);
|
|
else
|
|
return mNoResult;
|
|
}
|
|
|
|
int MetaDataList::getInt(const std::string& key) const
|
|
{
|
|
// Return integer value.
|
|
return atoi(get(key).c_str());
|
|
}
|
|
|
|
float MetaDataList::getFloat(const std::string& key) const
|
|
{
|
|
// Return float value.
|
|
return static_cast<float>(atof(get(key).c_str()));
|
|
}
|
|
|
|
bool MetaDataList::wasChanged() const
|
|
{
|
|
// Return whether the metadata was changed.
|
|
return mWasChanged;
|
|
}
|
|
|
|
void MetaDataList::resetChangedFlag()
|
|
{
|
|
// Reset the change flag.
|
|
mWasChanged = false;
|
|
}
|
|
|
|
#if defined(GETTEXT_DUMMY_ENTRIES)
|
|
void gettextMessageCatalogEntries()
|
|
{
|
|
_p("metadata", "NAME");
|
|
_p("metadata", "ENTER NAME");
|
|
_p("metadata", "SORTNAME");
|
|
_p("metadata", "ENTER SORTNAME");
|
|
_p("metadata", "CUSTOM COLLECTIONS SORTNAME");
|
|
_p("metadata", "ENTER COLLECTIONS SORTNAME");
|
|
_p("metadata", "DESCRIPTION");
|
|
_p("metadata", "ENTER DESCRIPTION");
|
|
_p("metadata", "RATING");
|
|
_p("metadata", "RELEASE DATE");
|
|
_p("metadata", "DEVELOPER");
|
|
_p("metadata", "ENTER DEVELOPER");
|
|
_p("metadata", "PUBLISHER");
|
|
_p("metadata", "ENTER PUBLISHER");
|
|
_p("metadata", "GENRE");
|
|
_p("metadata", "ENTER GENRE");
|
|
_p("metadata", "PLAYERS");
|
|
_p("metadata", "ENTER NUMBER OF PLAYERS");
|
|
_p("metadata", "FAVORITE");
|
|
_p("metadata", "COMPLETED");
|
|
_p("metadata", "KIDGAME");
|
|
_p("metadata", "KIDGAME (ONLY AFFECTS BADGES)");
|
|
_p("metadata", "HIDDEN");
|
|
_p("metadata", "BROKEN/NOT WORKING");
|
|
_p("metadata", "EXCLUDE FROM GAME COUNTER");
|
|
_p("metadata", "EXCLUDE FROM MULTI-SCRAPER");
|
|
_p("metadata", "HIDE METADATA FIELDS");
|
|
_p("metadata", "TIMES PLAYED");
|
|
_p("metadata", "ENTER NUMBER OF TIMES PLAYED");
|
|
_p("metadata", "CONTROLLER");
|
|
_p("metadata", "SELECT CONTROLLER");
|
|
_p("metadata", "ALTERNATIVE EMULATOR");
|
|
_p("metadata", "SELECT ALTERNATIVE EMULATOR");
|
|
_p("metadata", "FOLDER LINK");
|
|
_p("metadata", "SELECT FOLDER LINK");
|
|
_p("metadata", "LAST PLAYED");
|
|
_p("metadata", "ENTER LAST PLAYED DATE");
|
|
}
|
|
#endif
|