// this updates all collection files related to the argument file
void CollectionSystemManager::updateCollectionSystems(FileData* file)
{
	// collection files use the full path as key, to avoid clashes
	std::string key = file->getFullPath();
	// find games in collection systems
	for(auto sysIt = SystemData::sSystemVector.begin(); sysIt != SystemData::sSystemVector.end(); sysIt++)
	{
		if ((*sysIt)->isCollection()) {
			const std::unordered_map<std::string, FileData*>& children = (*sysIt)->getRootFolder()->getChildrenByFilename();
			bool found = children.find(key) != children.end();
			FileData* rootFolder = (*sysIt)->getRootFolder();
			FileFilterIndex* fileIndex = (*sysIt)->getIndex();
			std::string name = (*sysIt)->getName();
			if (found) {
				// if we found it, we need to update it
				FileData* collectionEntry = children.at(key);
				// remove from index, so we can re-index metadata after refreshing
				fileIndex->removeFromIndex(collectionEntry);
				collectionEntry->refreshMetadata();
				if (name == "favorites" && file->metadata.get("favorite") == "false") {
					// need to check if still marked as favorite, if not remove
					ViewController::get()->getGameListView((*sysIt)).get()->remove(collectionEntry, false);
					ViewController::get()->onFileChanged((*sysIt)->getRootFolder(), FILE_REMOVED);
				}
				else
				{
					// re-index with new metadata
					fileIndex->addToIndex(collectionEntry);
					ViewController::get()->onFileChanged(collectionEntry, FILE_METADATA_CHANGED);
				}
			}
			else
			{
				// we didn't find it here - we need to check if we should add it
				if (name == "recent" && file->metadata.get("playcount") > "0" ||
					name == "favorites" && file->metadata.get("favorite") == "true") {
					CollectionFileData* newGame = new CollectionFileData(file, (*sysIt));
					rootFolder->addChild(newGame);
					fileIndex->addToIndex(newGame);
					ViewController::get()->onFileChanged(file, FILE_METADATA_CHANGED);
					ViewController::get()->getGameListView((*sysIt))->onFileChanged(newGame, FILE_METADATA_CHANGED);
				}
			}
			rootFolder->sort(getSortType(mCollectionSystemDecls[name].defaultSort));
			ViewController::get()->onFileChanged(rootFolder, FILE_SORTED);
		}
	}
}
void CollectionSystemManager::loadAutoCollectionSystems()
{
	for(std::map<std::string, CollectionSystemDecl>::iterator it = mCollectionSystemDecls.begin() ; it != mCollectionSystemDecls.end() ; it++ )
	{
		CollectionSystemDecl sysDecl = it->second;
		if (!sysDecl.isCustom && !findCollectionSystem(sysDecl.name))
		{
			SystemData* newSys = new SystemData(sysDecl.name, sysDecl.longName, mCollectionEnvData, sysDecl.themeFolder, true);

			FileData* rootFolder = newSys->getRootFolder();
			FileFilterIndex* index = newSys->getIndex();
			for(auto sysIt = SystemData::sSystemVector.begin(); sysIt != SystemData::sSystemVector.end(); sysIt++)
			{
				if ((*sysIt)->isGameSystem()) {
					std::vector<FileData*> files = (*sysIt)->getRootFolder()->getFilesRecursive(GAME);
					for(auto gameIt = files.begin(); gameIt != files.end(); gameIt++)
					{
						bool include = includeFileInAutoCollections((*gameIt));
						switch(sysDecl.type) {
							case AUTO_LAST_PLAYED:
								include = include && (*gameIt)->metadata.get("playcount") > "0";
								break;
							case AUTO_FAVORITES:
								// we may still want to add files we don't want in auto collections in "favorites"
								include = (*gameIt)->metadata.get("favorite") == "true";
								break;
						}

						if (include) {
							CollectionFileData* newGame = new CollectionFileData(*gameIt, newSys);
							rootFolder->addChild(newGame);
							index->addToIndex(newGame);
						}
					}
				}
			}
			rootFolder->sort(getSortType(sysDecl.defaultSort));
			mAutoCollectionSystems.push_back(newSys);

			CollectionSystemData newCollectionData;
			newCollectionData.system = newSys;
			newCollectionData.decl = sysDecl;
			newCollectionData.isEnabled = false;
			mAllCollectionSystems[sysDecl.name] = newCollectionData;
		}
	}
}
FileData* findOrCreateFile(SystemData* system, const boost::filesystem::path& path, FileType type, bool trustGamelist)
{
	// first, verify that path is within the system's root folder
	FileData* root = system->getRootFolder();

	fs::path relative;
	bool contains = false;
	if (trustGamelist)
	{
		relative = removeCommonPathUsingStrings(path, root->getPath(), contains);
	}
	else
	{
		relative = removeCommonPath(path, root->getPath(), contains);
	}
	if(!contains)
	{
		LOG(LogError) << "File path \"" << path << "\" is outside system path \"" << system->getStartPath() << "\"";
		return NULL;
	}

	auto path_it = relative.begin();
	FileData* treeNode = root;
	bool found = false;
	while(path_it != relative.end())
	{
		const std::unordered_map<std::string, FileData*>& children = treeNode->getChildrenByFilename();

		std::string key = path_it->string();
		found = children.find(key) != children.end();
		if (found) {
			treeNode = children.at(key);
		}

		// this is the end
		if(path_it == --relative.end())
		{
			if(found)
				return treeNode;

			if(type == FOLDER)
			{
				LOG(LogWarning) << "gameList: folder doesn't already exist, won't create";
				return NULL;
			}

			FileData* file = new FileData(type, path, system);
			treeNode->addChild(file);
			return file;
		}

		if(!found)
		{
			// don't create folders unless it's leading up to a game
			// if type is a folder it's gonna be empty, so don't bother
			if(type == FOLDER)
			{
				LOG(LogWarning) << "gameList: folder doesn't already exist, won't create";
				return NULL;
			}
			
			// create missing folder
			FileData* folder = new FileData(FOLDER, treeNode->getPath().stem() / *path_it, system);
			treeNode->addChild(folder);
			treeNode = folder;
		}

		path_it++;
	}

	return NULL;
}
Exemple #4
0
void parseGamelist(SystemData* system)
{
	std::string xmlpath = system->getGamelistPath(false);

	if(!boost::filesystem::exists(xmlpath))
		return;

	LOG(LogInfo) << "Parsing XML file \"" << xmlpath << "\"...";

	pugi::xml_document doc;
	pugi::xml_parse_result result = doc.load_file(xmlpath.c_str());

	if(!result)
	{
		LOG(LogError) << "Error parsing XML file \"" << xmlpath << "\"!\n	" << result.description();
		return;
	}

	pugi::xml_node root = doc.child("gameList");
	if(!root)
	{
		LOG(LogError) << "Could not find <gameList> node in gamelist \"" << xmlpath << "\"!";
		return;
	}

	fs::path relativeTo = system->getStartPath();

	FileData* rootFd = system->getRootFolder();

	// parse folders first
	//const char* tag = "folder";

	for(pugi::xml_node fileNode = root.child("folder"); fileNode; fileNode = fileNode.next_sibling("folder"))
	{
		fs::path path = resolvePath(fileNode.child("path").text().get(), relativeTo, false);

		FileData* file = new FileData(FOLDER, path, system);
		rootFd->addChild(file);

		//load the metadata
		//std::string defaultName = file->metadata.get("name");
		std::string defaultName = "defaultName";

		file->metadata = MetaDataList::createFromXML(FOLDER_METADATA, fileNode, relativeTo);

		//make sure name gets set if one didn't exist
		if(file->metadata.get("name").empty())
			file->metadata.set("name", defaultName);

		// parse game items for current folder
		for (pugi::xml_node childNode = fileNode.child("game"); childNode; childNode = childNode.next_sibling("game")) {
			fs::path path = resolvePath(childNode.child("path").text().get(), relativeTo, false);
			FileData* newFile = new FileData(GAME, path, system);
			file->addChild(newFile);

			newFile->metadata = MetaDataList::createFromXML(GAME_METADATA, childNode, relativeTo);

			//make sure name gets set if one didn't exist
			if(newFile->metadata.get("name").empty())
				newFile->metadata.set("name", defaultName);

		}
	}



	/*

	const char* tagList[2] = { "game", "folder" };
	FileType typeList[2] = { GAME, FOLDER };
	for(int i = 0; i < 2; i++)
	{
		const char* tag = tagList[i];
		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(), relativeTo, false);
			

			FileData* file = new FileData(GAME, path, system);
			rootFd->addChild(file);

			//load the metadata
			//std::string defaultName = file->metadata.get("name");
			std::string defaultName = "defaultName";

			file->metadata = MetaDataList::createFromXML(GAME_METADATA, fileNode, relativeTo);

			//make sure name gets set if one didn't exist
			if(file->metadata.get("name").empty())
				file->metadata.set("name", defaultName);
		}
	}
	*/
}
Exemple #5
0
FileData* findOrCreateFile(SystemData* system, const boost::filesystem::path& path, FileType type)
{
	// first, verify that path is within the system's root folder
	FileData* root = system->getRootFolder();
	
	bool contains = false;
	fs::path relative = removeCommonPath(path, root->getPath(), contains);
	if(!contains)
	{
		LOG(LogError) << "File path \"" << path << "\" is outside system path \"" << system->getStartPath() << "\"";
		return NULL;
	}

	auto path_it = relative.begin();
	FileData* treeNode = root;
	bool found = false;
	while(path_it != relative.end())
	{
		const std::vector<FileData*>& children = treeNode->getChildren();
		found = false;
		for(auto child_it = children.begin(); child_it != children.end(); child_it++)
		{
			if((*child_it)->getPath().filename() == *path_it)
			{
				treeNode = *child_it;
				found = true;
				break;
			}
		}

		// this is the end
		if(path_it == --relative.end())
		{
			if(found)
				return treeNode;

			if(type == FOLDER)
			{
				LOG(LogWarning) << "gameList: folder doesn't already exist, won't create";
				return NULL;
			}
    		//LOG(LogInfo) << "File type" << type << " File path \"" << path << "System " << system;
			FileData* file = new FileData(type, path, system);
			treeNode->addChild(file);
			return file;
		}

		if(!found)
		{
			// don't create folders unless it's leading up to a game
			// if type is a folder it's gonna be empty, so don't bother
			if(type == FOLDER)
			{
				LOG(LogWarning) << "gameList: folder doesn't already exist, won't create";
				return NULL;
			}
			
			// create missing folder
			FileData* folder = new FileData(FOLDER, treeNode->getPath().stem() / *path_it, system);
			treeNode->addChild(folder);
			treeNode = folder;
		}

		path_it++;
	}

	return NULL;
}