mirror of
https://github.com/RetroDECK/ES-DE.git
synced 2025-01-17 22:55:38 +00:00
Made metadata image paths relative too.
Moved some path functions into Util.h/.cpp.
This commit is contained in:
parent
37db651ffa
commit
fac09b6fac
|
@ -4,65 +4,10 @@
|
|||
#include <boost/filesystem.hpp>
|
||||
#include "Log.h"
|
||||
#include "Settings.h"
|
||||
#include "Util.h"
|
||||
|
||||
namespace fs = boost::filesystem;
|
||||
|
||||
// expands "./my/path.sfc" to "[relativeTo]/my/path.sfc"
|
||||
fs::path resolvePath(const fs::path& path, const fs::path& relativeTo)
|
||||
{
|
||||
if(path.begin() != path.end() && *path.begin() == fs::path("."))
|
||||
{
|
||||
fs::path ret = relativeTo;
|
||||
for(auto it = ++path.begin(); it != path.end(); ++it)
|
||||
ret /= *it;
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
return path;
|
||||
}
|
||||
|
||||
// example: removeCommonPath("/home/pi/roms/nes/foo/bar.nes", "/home/pi/roms/nes/") returns "foo/bar.nes"
|
||||
fs::path removeCommonPath(const fs::path& path, const fs::path& relativeTo, bool& contains)
|
||||
{
|
||||
fs::path p = fs::canonical(path);
|
||||
fs::path r = fs::canonical(relativeTo);
|
||||
|
||||
if(p.root_path() != r.root_path())
|
||||
{
|
||||
contains = false;
|
||||
return p;
|
||||
}
|
||||
|
||||
fs::path result;
|
||||
|
||||
// find point of divergence
|
||||
auto itr_path = p.begin();
|
||||
auto itr_relative_to = r.begin();
|
||||
while(*itr_path == *itr_relative_to && itr_path != p.end() && itr_relative_to != r.end())
|
||||
{
|
||||
++itr_path;
|
||||
++itr_relative_to;
|
||||
}
|
||||
|
||||
if(itr_relative_to != r.end())
|
||||
{
|
||||
contains = false;
|
||||
return p;
|
||||
}
|
||||
|
||||
while(itr_path != p.end())
|
||||
{
|
||||
if(*itr_path != fs::path("."))
|
||||
result = result / *itr_path;
|
||||
|
||||
++itr_path;
|
||||
}
|
||||
|
||||
contains = true;
|
||||
return result;
|
||||
}
|
||||
|
||||
FileData* findOrCreateFile(SystemData* system, const boost::filesystem::path& path, FileType type)
|
||||
{
|
||||
// first, verify that path is within the system's root folder
|
||||
|
@ -157,6 +102,8 @@ void parseGamelist(SystemData* system)
|
|||
return;
|
||||
}
|
||||
|
||||
fs::path relativeTo = system->getStartPath();
|
||||
|
||||
const char* tagList[2] = { "game", "folder" };
|
||||
FileType typeList[2] = { GAME, FOLDER };
|
||||
for(int i = 0; i < 2; i++)
|
||||
|
@ -165,7 +112,7 @@ void parseGamelist(SystemData* system)
|
|||
FileType type = typeList[i];
|
||||
for(pugi::xml_node fileNode = root.child(tag); fileNode; fileNode = fileNode.next_sibling(tag))
|
||||
{
|
||||
fs::path path = resolvePath(fileNode.child("path").text().get(), system->getStartPath());
|
||||
fs::path path = resolvePath(fileNode.child("path").text().get(), relativeTo, false);
|
||||
|
||||
if(!boost::filesystem::exists(path))
|
||||
{
|
||||
|
@ -182,7 +129,7 @@ void parseGamelist(SystemData* system)
|
|||
|
||||
//load the metadata
|
||||
std::string defaultName = file->metadata.get("name");
|
||||
file->metadata = MetaDataList::createFromXML(GAME_METADATA, fileNode);
|
||||
file->metadata = MetaDataList::createFromXML(GAME_METADATA, fileNode, relativeTo);
|
||||
|
||||
//make sure name gets set if one didn't exist
|
||||
if(file->metadata.get("name").empty())
|
||||
|
@ -197,7 +144,7 @@ void addFileDataNode(pugi::xml_node& parent, const FileData* file, const char* t
|
|||
pugi::xml_node newNode = parent.append_child(tag);
|
||||
|
||||
//write metadata
|
||||
file->metadata.appendToXML(newNode, true);
|
||||
file->metadata.appendToXML(newNode, true, system->getStartPath());
|
||||
|
||||
if(newNode.children().begin() == newNode.child("name") //first element is name
|
||||
&& ++newNode.children().begin() == newNode.children().end() //theres only one element
|
||||
|
@ -210,17 +157,7 @@ void addFileDataNode(pugi::xml_node& parent, const FileData* file, const char* t
|
|||
//there's something useful in there so we'll keep the node, add the path
|
||||
|
||||
// try and make the path relative if we can so things still work if we change the rom folder location in the future
|
||||
fs::path relPath = file->getPath();
|
||||
|
||||
bool contains = false;
|
||||
relPath = removeCommonPath(relPath, system->getStartPath(), contains);
|
||||
if(contains)
|
||||
{
|
||||
// it's in the start path (which we just stripped off), so add a "./"
|
||||
relPath = "." / relPath;
|
||||
}
|
||||
|
||||
newNode.prepend_child("path").text().set(relPath.generic_string().c_str());
|
||||
newNode.prepend_child("path").text().set(makeRelativePath(file->getPath(), system->getStartPath(), false).generic_string().c_str());
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -284,7 +221,7 @@ void updateGamelist(SystemData* system)
|
|||
continue;
|
||||
}
|
||||
|
||||
fs::path nodePath = resolvePath(pathNode.text().get(), system->getStartPath());
|
||||
fs::path nodePath = resolvePath(pathNode.text().get(), system->getStartPath(), true);
|
||||
fs::path gamePath((*fit)->getPath());
|
||||
if(nodePath == gamePath || (fs::exists(nodePath) && fs::exists(gamePath) && fs::equivalent(nodePath, gamePath)))
|
||||
{
|
||||
|
|
|
@ -1,6 +1,9 @@
|
|||
#include "MetaData.h"
|
||||
#include "components/TextComponent.h"
|
||||
#include "Log.h"
|
||||
#include "Util.h"
|
||||
|
||||
namespace fs = boost::filesystem;
|
||||
|
||||
MetaDataDecl gameDecls[] = {
|
||||
// key, type, default, statistic, name in GuiMetaDataEd, prompt in GuiMetaDataEd
|
||||
|
@ -52,7 +55,7 @@ MetaDataList::MetaDataList(MetaDataListType type)
|
|||
}
|
||||
|
||||
|
||||
MetaDataList MetaDataList::createFromXML(MetaDataListType type, pugi::xml_node node)
|
||||
MetaDataList MetaDataList::createFromXML(MetaDataListType type, pugi::xml_node node, const fs::path& relativeTo)
|
||||
{
|
||||
MetaDataList mdl(type);
|
||||
|
||||
|
@ -63,7 +66,12 @@ MetaDataList MetaDataList::createFromXML(MetaDataListType type, pugi::xml_node n
|
|||
pugi::xml_node md = node.child(iter->key.c_str());
|
||||
if(md)
|
||||
{
|
||||
mdl.set(iter->key, md.text().get());
|
||||
// if it's a path, resolve relative paths
|
||||
std::string value = md.text().get();
|
||||
if(iter->type == MD_IMAGE_PATH)
|
||||
value = resolvePath(value, relativeTo, true).generic_string();
|
||||
|
||||
mdl.set(iter->key, value);
|
||||
}else{
|
||||
mdl.set(iter->key, iter->defaultValue);
|
||||
}
|
||||
|
@ -72,30 +80,27 @@ MetaDataList MetaDataList::createFromXML(MetaDataListType type, pugi::xml_node n
|
|||
return mdl;
|
||||
}
|
||||
|
||||
void MetaDataList::appendToXML(pugi::xml_node parent, bool ignoreDefaults) const
|
||||
void MetaDataList::appendToXML(pugi::xml_node parent, bool ignoreDefaults, const fs::path& relativeTo) const
|
||||
{
|
||||
const std::vector<MetaDataDecl>& mdd = getMDD();
|
||||
|
||||
for(auto iter = mMap.begin(); iter != mMap.end(); iter++)
|
||||
for(auto mddIter = mdd.begin(); mddIter != mdd.end(); mddIter++)
|
||||
{
|
||||
bool write = true;
|
||||
|
||||
if(ignoreDefaults)
|
||||
auto mapIter = mMap.find(mddIter->key);
|
||||
if(mapIter != mMap.end())
|
||||
{
|
||||
for(auto mddIter = mdd.begin(); mddIter != mdd.end(); mddIter++)
|
||||
{
|
||||
if(mddIter->key == iter->first)
|
||||
{
|
||||
if(iter->second == mddIter->defaultValue)
|
||||
write = false;
|
||||
// we have this value!
|
||||
// if it's just the default (and we ignore defaults), don't write it
|
||||
if(ignoreDefaults && mapIter->second == mddIter->defaultValue)
|
||||
continue;
|
||||
|
||||
break;
|
||||
}
|
||||
}
|
||||
// try and make paths relative if we can
|
||||
std::string value = mapIter->second;
|
||||
if(mddIter->type == MD_IMAGE_PATH)
|
||||
value = makeRelativePath(value, relativeTo, true).generic_string();
|
||||
|
||||
parent.append_child(mapIter->first.c_str()).text().set(value.c_str());
|
||||
}
|
||||
|
||||
if(write)
|
||||
parent.append_child(iter->first.c_str()).text().set(iter->second.c_str());
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -5,6 +5,7 @@
|
|||
#include <map>
|
||||
#include "GuiComponent.h"
|
||||
#include <boost/date_time.hpp>
|
||||
#include <boost/filesystem.hpp>
|
||||
|
||||
enum MetaDataType
|
||||
{
|
||||
|
@ -44,8 +45,8 @@ const std::vector<MetaDataDecl>& getMDDByType(MetaDataListType type);
|
|||
class MetaDataList
|
||||
{
|
||||
public:
|
||||
static MetaDataList createFromXML(MetaDataListType type, pugi::xml_node node);
|
||||
void appendToXML(pugi::xml_node parent, bool ignoreDefaults = false) const;
|
||||
static MetaDataList createFromXML(MetaDataListType type, pugi::xml_node node, const boost::filesystem::path& relativeTo);
|
||||
void appendToXML(pugi::xml_node parent, bool ignoreDefaults, const boost::filesystem::path& relativeTo) const;
|
||||
|
||||
MetaDataList(MetaDataListType type);
|
||||
|
||||
|
|
103
src/Util.cpp
103
src/Util.cpp
|
@ -1,6 +1,8 @@
|
|||
#include "Util.h"
|
||||
#include <boost/filesystem.hpp>
|
||||
#include "resources/ResourceManager.h"
|
||||
#include "platform.h"
|
||||
|
||||
namespace fs = boost::filesystem;
|
||||
|
||||
std::string strToUpper(const char* from)
|
||||
{
|
||||
|
@ -70,3 +72,102 @@ std::string getCanonicalPath(const std::string& path)
|
|||
|
||||
return boost::filesystem::canonical(path).generic_string();
|
||||
}
|
||||
|
||||
// expands "./my/path.sfc" to "[relativeTo]/my/path.sfc"
|
||||
// if allowHome is true, also expands "~/my/path.sfc" to "/home/pi/my/path.sfc"
|
||||
fs::path resolvePath(const fs::path& path, const fs::path& relativeTo, bool allowHome)
|
||||
{
|
||||
// nothing here
|
||||
if(path.begin() == path.end())
|
||||
return path;
|
||||
|
||||
if(*path.begin() == ".")
|
||||
{
|
||||
fs::path ret = relativeTo;
|
||||
for(auto it = ++path.begin(); it != path.end(); ++it)
|
||||
ret /= *it;
|
||||
return ret;
|
||||
}
|
||||
|
||||
if(allowHome && *path.begin() == "~")
|
||||
{
|
||||
fs::path ret = getHomePath();
|
||||
for(auto it = ++path.begin(); it != path.end(); ++it)
|
||||
ret /= *it;
|
||||
return ret;
|
||||
}
|
||||
|
||||
return path;
|
||||
}
|
||||
|
||||
// example: removeCommonPath("/home/pi/roms/nes/foo/bar.nes", "/home/pi/roms/nes/") returns "foo/bar.nes"
|
||||
fs::path removeCommonPath(const fs::path& path, const fs::path& relativeTo, bool& contains)
|
||||
{
|
||||
fs::path p = fs::canonical(path);
|
||||
fs::path r = fs::canonical(relativeTo);
|
||||
|
||||
if(p.root_path() != r.root_path())
|
||||
{
|
||||
contains = false;
|
||||
return p;
|
||||
}
|
||||
|
||||
fs::path result;
|
||||
|
||||
// find point of divergence
|
||||
auto itr_path = p.begin();
|
||||
auto itr_relative_to = r.begin();
|
||||
while(*itr_path == *itr_relative_to && itr_path != p.end() && itr_relative_to != r.end())
|
||||
{
|
||||
++itr_path;
|
||||
++itr_relative_to;
|
||||
}
|
||||
|
||||
if(itr_relative_to != r.end())
|
||||
{
|
||||
contains = false;
|
||||
return p;
|
||||
}
|
||||
|
||||
while(itr_path != p.end())
|
||||
{
|
||||
if(*itr_path != fs::path("."))
|
||||
result = result / *itr_path;
|
||||
|
||||
++itr_path;
|
||||
}
|
||||
|
||||
contains = true;
|
||||
return result;
|
||||
}
|
||||
|
||||
// usage: makeRelativePath("/path/to/my/thing.sfc", "/path/to") -> "./my/thing.sfc"
|
||||
// usage: makeRelativePath("/home/pi/my/thing.sfc", "/path/to", true) -> "~/my/thing.sfc"
|
||||
fs::path makeRelativePath(const fs::path& path, const fs::path& relativeTo, bool allowHome)
|
||||
{
|
||||
bool contains = false;
|
||||
|
||||
fs::path ret = removeCommonPath(path, relativeTo, contains);
|
||||
if(contains)
|
||||
{
|
||||
// success
|
||||
ret = "." / ret;
|
||||
return ret;
|
||||
}
|
||||
|
||||
if(allowHome)
|
||||
{
|
||||
contains = false;
|
||||
std::string homePath = getHomePath();
|
||||
ret = removeCommonPath(path, homePath, contains);
|
||||
if(contains)
|
||||
{
|
||||
// success
|
||||
ret = "~" / ret;
|
||||
return ret;
|
||||
}
|
||||
}
|
||||
|
||||
// nothing could be resolved
|
||||
return path;
|
||||
}
|
||||
|
|
12
src/Util.h
12
src/Util.h
|
@ -1,5 +1,6 @@
|
|||
#include <string>
|
||||
#include <Eigen/Dense>
|
||||
#include <boost/filesystem.hpp>
|
||||
|
||||
std::string strToUpper(const char* from);
|
||||
std::string& strToUpper(std::string& str);
|
||||
|
@ -14,3 +15,14 @@ Eigen::Vector2f roundVector(const Eigen::Vector2f& vec);
|
|||
float round(float num);
|
||||
|
||||
std::string getCanonicalPath(const std::string& str);
|
||||
|
||||
// example: removeCommonPath("/home/pi/roms/nes/foo/bar.nes", "/home/pi/roms/nes/") returns "foo/bar.nes"
|
||||
boost::filesystem::path removeCommonPath(const boost::filesystem::path& path, const boost::filesystem::path& relativeTo, bool& contains);
|
||||
|
||||
// usage: makeRelativePath("/path/to/my/thing.sfc", "/path/to") -> "./my/thing.sfc"
|
||||
// usage: makeRelativePath("/home/pi/my/thing.sfc", "/path/to", true) -> "~/my/thing.sfc"
|
||||
boost::filesystem::path makeRelativePath(const boost::filesystem::path& path, const boost::filesystem::path& relativeTo, bool allowHome);
|
||||
|
||||
// expands "./my/path.sfc" to "[relativeTo]/my/path.sfc"
|
||||
// if allowHome is true, also expands "~/my/path.sfc" to "/home/pi/my/path.sfc"
|
||||
boost::filesystem::path resolvePath(const boost::filesystem::path& path, const boost::filesystem::path& relativeTo, bool allowHome);
|
||||
|
|
Loading…
Reference in a new issue