diff --git a/RetroFE/Source/CMakeLists.txt b/RetroFE/Source/CMakeLists.txt index c1b5f1e..f0899fe 100644 --- a/RetroFE/Source/CMakeLists.txt +++ b/RetroFE/Source/CMakeLists.txt @@ -79,9 +79,9 @@ set(RETROFE_HEADERS "${RETROFE_DIR}/Source/Collection/Item.h" "${RETROFE_DIR}/Source/Collection/MenuParser.h" "${RETROFE_DIR}/Source/Control/UserInput.h" - "${RETROFE_DIR}/Source/Database/CollectionDatabase.h" "${RETROFE_DIR}/Source/Database/Configuration.h" "${RETROFE_DIR}/Source/Database/DB.h" + "${RETROFE_DIR}/Source/Database/MetadataDatabase.h" "${RETROFE_DIR}/Source/Database/MamelistMetadata.h" "${RETROFE_DIR}/Source/Execute/AttractMode.h" "${RETROFE_DIR}/Source/Execute/Launcher.h" @@ -122,9 +122,9 @@ set(RETROFE_SOURCES "${RETROFE_DIR}/Source/Collection/Item.cpp" "${RETROFE_DIR}/Source/Collection/MenuParser.cpp" "${RETROFE_DIR}/Source/Control/UserInput.cpp" - "${RETROFE_DIR}/Source/Database/CollectionDatabase.cpp" "${RETROFE_DIR}/Source/Database/Configuration.cpp" "${RETROFE_DIR}/Source/Database/DB.cpp" + "${RETROFE_DIR}/Source/Database/MetadataDatabase.cpp" "${RETROFE_DIR}/Source/Database/MamelistMetadata.cpp" "${RETROFE_DIR}/Source/Execute/AttractMode.cpp" "${RETROFE_DIR}/Source/Execute/Launcher.cpp" diff --git a/RetroFE/Source/Collection/CollectionInfo.cpp b/RetroFE/Source/Collection/CollectionInfo.cpp index b4fee86..61b5308 100644 --- a/RetroFE/Source/Collection/CollectionInfo.cpp +++ b/RetroFE/Source/Collection/CollectionInfo.cpp @@ -14,6 +14,7 @@ * along with RetroFE. If not, see . */ #include "CollectionInfo.h" +#include "Item.h" #include "../Database/Configuration.h" #include @@ -32,6 +33,14 @@ CollectionInfo::CollectionInfo(std::string name, CollectionInfo::~CollectionInfo() { + std::vector::iterator it = Items.begin(); + + while(it != Items.end()) + { + delete *it; + Items.erase(it); + it = Items.begin(); + } } std::string CollectionInfo::GetName() const @@ -74,6 +83,10 @@ void CollectionInfo::GetExtensions(std::vector &extensions) extensions.push_back(token); } } +std::vector *CollectionInfo::GetItems() +{ + return &Items; +} diff --git a/RetroFE/Source/Collection/CollectionInfo.h b/RetroFE/Source/Collection/CollectionInfo.h index 9f5750e..c3d2d4b 100644 --- a/RetroFE/Source/Collection/CollectionInfo.h +++ b/RetroFE/Source/Collection/CollectionInfo.h @@ -6,6 +6,8 @@ #include #include +class Item; + class CollectionInfo { public: @@ -17,6 +19,7 @@ public: std::string GetMetadataType() const; std::string GetMetadataPath() const; std::string GetExtensions() const; + std::vector *GetItems(); void GetExtensions(std::vector &extensions); private: @@ -25,4 +28,5 @@ private: std::string Extensions; std::string MetadataType; std::string MetadataPath; + std::vector Items; }; diff --git a/RetroFE/Source/Collection/CollectionInfoBuilder.cpp b/RetroFE/Source/Collection/CollectionInfoBuilder.cpp index 41138be..fb68d51 100644 --- a/RetroFE/Source/Collection/CollectionInfoBuilder.cpp +++ b/RetroFE/Source/Collection/CollectionInfoBuilder.cpp @@ -15,86 +15,28 @@ */ #include "CollectionInfoBuilder.h" #include "CollectionInfo.h" +#include "Item.h" #include "../Database/Configuration.h" +#include "../Database/MetadataDatabase.h" +#include "../Database/DB.h" #include "../Utility/Log.h" +#include "../Utility/Utils.h" +#include #include #include -CollectionInfoBuilder::CollectionInfoBuilder(Configuration &c) +CollectionInfoBuilder::CollectionInfoBuilder(Configuration &c, DB &db) : Conf(c) + , MetaDB(db, c) { } CollectionInfoBuilder::~CollectionInfoBuilder() { - std::map::iterator it = InfoMap.begin(); - - for(it == InfoMap.begin(); it != InfoMap.end(); ++it) - { - delete it->second; - } - - InfoMap.clear(); } -bool CollectionInfoBuilder::LoadAllCollections() +CollectionInfo *CollectionInfoBuilder::BuildCollection(std::string name) { - std::vector collections; - - Conf.GetChildKeyCrumbs("collections", collections); - - if(collections.size() == 0) - { - Logger::Write(Logger::ZONE_ERROR, "Collections", "No collections were found. Please configure Settings.conf"); - return false; - } - - bool retVal = true; - std::vector::iterator it; - - for(it = collections.begin(); it != collections.end(); ++it) - { - // todo: There is nothing that should really stop us from creating a collection - // in the main folder. I just need to find some time to look at the impacts if - // I remove this conditional check. - if(*it != "Main") - { - std::string oldCollection = Conf.GetCurrentCollection(); - Conf.SetCurrentCollection(*it); - if(ImportCollection(*it)) - { - Logger::Write(Logger::ZONE_INFO, "Collections", "Adding collection " + *it); - } - else - { - // Continue processing the rest of the collections if an error occurs during import. - // ImportCollection() will print out an error to the log file. - retVal = false; - } - Conf.SetCurrentCollection(oldCollection); - } - } - - return retVal; -} - -void CollectionInfoBuilder::GetCollections(std::vector &collections) -{ - std::map::iterator InfoMapIt; - - for(InfoMapIt = InfoMap.begin(); InfoMapIt != InfoMap.end(); ++InfoMapIt) - { - collections.push_back(InfoMapIt->second); - } -} - -bool CollectionInfoBuilder::ImportCollection(std::string name) -{ - // create a new instance if one does not exist - if(InfoMap.find(name) != InfoMap.end()) - { - return true; - } std::string listItemsPathKey = "collections." + name + ".list.path"; std::string listFilterKey = "collections." + name + ".list.filter"; std::string extensionsKey = "collections." + name + ".list.extensions"; @@ -128,7 +70,87 @@ bool CollectionInfoBuilder::ImportCollection(std::string name) Logger::Write(Logger::ZONE_WARNING, "Collections", ss.str()); } - InfoMap[name] = new CollectionInfo(name, listItemsPath, extensions, metadataType, metadataPath); + CollectionInfo *collection = new CollectionInfo(name, listItemsPath, extensions, metadataType, metadataPath); + std::vector *list = collection->GetItems(); - return (InfoMap[name] != NULL); + ImportDirectory(collection); + + return collection; } + +bool CollectionInfoBuilder::ImportDirectory(CollectionInfo *info) +{ + DIR *dp; + struct dirent *dirp; + std::string path = info->GetListPath(); + std::map includeFilter; + std::map excludeFilter; + bool retVal = true; + std::string includeFile = Configuration::GetAbsolutePath() + "/Collections/" + info->GetName() + "/Include.txt"; + std::string excludeFile = Configuration::GetAbsolutePath() + "/Collections/" + info->GetName() + "/Exclude.txt"; + std::string launcher; + + (void)Conf.GetProperty("collections." + info->GetName() + ".launcher", launcher); + + dp = opendir(path.c_str()); + std::vector extensions; + info->GetExtensions(extensions); + std::vector::iterator extensionsIt; + + if(dp == NULL) + { + Logger::Write(Logger::ZONE_ERROR, "CollectionInfoBuilder", "Could not read directory \"" + path + "\""); + //todo: store into a database + } + else + { + while((dirp = readdir(dp)) != NULL) + { + std::string file = dirp->d_name; + + Utils::NormalizeBackSlashes(file); + size_t position = file.find_last_of("."); + std::string basename = (std::string::npos == position)? file : file.substr(0, position); + + if((includeFilter.size() == 0 || includeFilter.find(basename) != includeFilter.end()) && + (excludeFilter.size() == 0 || excludeFilter.find(basename) == excludeFilter.end())) + { + for(extensionsIt = extensions.begin(); extensionsIt != extensions.end(); ++extensionsIt) + { + std::string comparator = "." + *extensionsIt; + int start = file.length() - comparator.length() + 1; + + if(start >= 0) + { + if(file.compare(start, comparator.length(), *extensionsIt) == 0) + { + Item *i = new Item(); + i->SetName(basename); + i->SetFullTitle(basename); + i->SetTitle(basename); + i->SetLauncher(launcher); + info->GetItems()->push_back(i); + } + } + } + } + } + } + + MetaDB.UpdateMetadata(info); + + while(includeFilter.size() > 0) + { + std::map::iterator it = includeFilter.begin(); + delete it->second; + includeFilter.erase(it); + } + while(excludeFilter.size() > 0) + { + std::map::iterator it = excludeFilter.begin(); + delete it->second; + excludeFilter.erase(it); + } + + return true; +} \ No newline at end of file diff --git a/RetroFE/Source/Collection/CollectionInfoBuilder.h b/RetroFE/Source/Collection/CollectionInfoBuilder.h index f512bcf..b07f444 100644 --- a/RetroFE/Source/Collection/CollectionInfoBuilder.h +++ b/RetroFE/Source/Collection/CollectionInfoBuilder.h @@ -3,6 +3,8 @@ */ #pragma once +#include "../Database/DB.h" +#include "../Database/MetadataDatabase.h" #include #include #include @@ -10,16 +12,16 @@ class Configuration; class CollectionInfo; + class CollectionInfoBuilder { public: - CollectionInfoBuilder(Configuration &c); + CollectionInfoBuilder(Configuration &c, DB &db); virtual ~CollectionInfoBuilder(); - bool LoadAllCollections(); - void GetCollections(std::vector &keys); + CollectionInfo *BuildCollection(std::string collectionName); private: - bool ImportCollection(std::string name); - std::map InfoMap; + MetadataDatabase MetaDB; + bool ImportDirectory(CollectionInfo *info); Configuration &Conf; }; diff --git a/RetroFE/Source/Collection/MenuParser.cpp b/RetroFE/Source/Collection/MenuParser.cpp index 0465128..eb76da8 100644 --- a/RetroFE/Source/Collection/MenuParser.cpp +++ b/RetroFE/Source/Collection/MenuParser.cpp @@ -15,10 +15,10 @@ */ #include "MenuParser.h" +#include "CollectionInfo.h" #include "Item.h" #include "../Utility/Log.h" #include "../Database/Configuration.h" -#include "../Database/CollectionDatabase.h" #include "../Database/DB.h" #include #include @@ -39,11 +39,11 @@ MenuParser::~MenuParser() } //todo: clean up this method, too much nesting -bool MenuParser::GetMenuItems(CollectionDatabase *cdb, std::string collectionName, std::vector &items) +bool MenuParser::GetMenuItems(CollectionInfo *collection) { bool retVal = false; //todo: magic string - std::string menuFilename = Configuration::GetAbsolutePath() + "/Collections/" + collectionName + "/Menu.xml"; + std::string menuFilename = Configuration::GetAbsolutePath() + "/Collections/" + collection->GetName() + "/Menu.xml"; rapidxml::xml_document<> doc; rapidxml::xml_node<> * rootNode; @@ -93,18 +93,23 @@ bool MenuParser::GetMenuItems(CollectionDatabase *cdb, std::string collectionNam item->SetFullTitle(title); item->SetName(collectionAttribute->value()); item->SetIsLeaf(false); - items.push_back(item); + collection->GetItems()->push_back(item); + } else { std::string collectionName = collectionAttribute->value(); Logger::Write(Logger::ZONE_INFO, "Menu", "Loading collection into menu: " + collectionName); - cdb->GetCollection(collectionAttribute->value(), items); + + //todo: unsupported option with this refactor + // need to append the collection } } } - std::sort( items.begin(), items.end(), VectorSort); + // todo: sorting should occur within the collection itself, not externally + std::vector *items = collection->GetItems(); + std::sort( items->begin(), items->end(), VectorSort); retVal = true; } diff --git a/RetroFE/Source/Collection/MenuParser.h b/RetroFE/Source/Collection/MenuParser.h index a712149..8c6e194 100644 --- a/RetroFE/Source/Collection/MenuParser.h +++ b/RetroFE/Source/Collection/MenuParser.h @@ -2,16 +2,14 @@ * file 'LICENSE.txt', which is part of this source code package. */ #pragma once -#include "Item.h" -#include -class CollectionDatabase; +class CollectionInfo; class MenuParser { public: MenuParser(); virtual ~MenuParser(); - bool GetMenuItems(CollectionDatabase *cdb, std::string collectionName, std::vector &items); + bool GetMenuItems(CollectionInfo *cdb); }; diff --git a/RetroFE/Source/Database/CollectionDatabase.cpp b/RetroFE/Source/Database/CollectionDatabase.cpp deleted file mode 100644 index 6394232..0000000 --- a/RetroFE/Source/Database/CollectionDatabase.cpp +++ /dev/null @@ -1,759 +0,0 @@ -/* This file is part of RetroFE. - * - * RetroFE is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * RetroFE is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with RetroFE. If not, see . - */ -#include "CollectionDatabase.h" -#include "../Collection/CollectionInfoBuilder.h" -#include "../Collection/CollectionInfo.h" -#include "../Collection/Item.h" -#include "../Utility/Log.h" -#include "../Utility/Utils.h" -#include "MamelistMetadata.h" -#include "Configuration.h" -#include "DB.h" -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -CollectionDatabase::CollectionDatabase(DB &db, Configuration &c) - : Config(c) - , DBInstance(db) -{ - -} - -CollectionDatabase::~CollectionDatabase() -{ -} - -bool CollectionDatabase::ResetDatabase() -{ - bool retVal = true; - int rc; - char *error = NULL; - sqlite3 *handle = DBInstance.GetHandle(); - - Logger::Write(Logger::ZONE_INFO, "Database", "Erasing"); - - std::string sql; - sql.append("DROP TABLE IF EXISTS CollectionItems;"); - sql.append("DROP TABLE IF EXISTS Meta;"); - sql.append("DROP TABLE IF EXISTS Collections;"); - - rc = sqlite3_exec(handle, sql.c_str(), NULL, 0, &error); - - if(rc != SQLITE_OK) - { - std::stringstream ss; - ss << "Unable to create Configurations table. Error: " << error; - Logger::Write(Logger::ZONE_ERROR, "Database", ss.str()); - retVal = false; - } - - return retVal; -} - -bool CollectionDatabase::Initialize() -{ - int rc; - char *error = NULL; - sqlite3 *handle = DBInstance.GetHandle(); - - std::string sql; - sql.append("CREATE TABLE IF NOT EXISTS CollectionItems("); - sql.append("collectionName TEXT KEY,"); - sql.append("filePath TEXT NOT NULL DEFAULT '',"); - sql.append("name TEXT NOT NULL DEFAULT '',"); - sql.append("hidden INT NOT NULL DEFAULT 0);"); - - sql.append("CREATE TABLE IF NOT EXISTS Meta("); - sql.append("collectionName TEXT KEY,"); - sql.append("name TEXT NOT NULL DEFAULT '',"); - sql.append("title TEXT NOT NULL DEFAULT '',"); - sql.append("year TEXT NOT NULL DEFAULT '',"); - sql.append("manufacturer TEXT NOT NULL DEFAULT '',"); - sql.append("cloneOf TEXT NOT NULL DEFAULT '',"); - sql.append("players INTEGER,"); - sql.append("buttons INTEGER);"); - sql.append("CREATE UNIQUE INDEX IF NOT EXISTS MetaUniqueId ON Meta(collectionName, name);"); - - sql.append("CREATE TABLE IF NOT EXISTS Collections("); - sql.append("collectionName TEXT KEY,"); - sql.append("crc32 UNSIGNED INTEGER NOT NULL DEFAULT 0);"); - sql.append("CREATE UNIQUE INDEX IF NOT EXISTS CollectionsUniqueId ON Collections(collectionName);"); - - rc = sqlite3_exec(handle, sql.c_str(), NULL, 0, &error); - - if(rc != SQLITE_OK) - { - std::stringstream ss; - ss << "Unable to create Configurations table. Error: " << error; - Logger::Write(Logger::ZONE_ERROR, "Database", ss.str()); - - return false; - } - - return true; -} - - -bool CollectionDatabase::Import() -{ - bool retVal = true; - - // should keep allocation here - CollectionInfoBuilder cib(Config); - - (void)cib.LoadAllCollections(); - - std::vector collections; - cib.GetCollections(collections); - - std::vector::iterator it; - for(it = collections.begin(); it != collections.end() && retVal; ++it) - { - CollectionInfo *info = *it; - std::string title = info->GetName(); - unsigned long crc32 = CalculateCollectionCrc32(info); - - std::stringstream crcStr; - crcStr << crc32; - - if(title != "Main") - { - if(CollectionChanged(info, crc32)) - { - std::string msg = "Detected collection \"" + title + "\" has changed (new CRC: " + crcStr.str() + "). Rebuilding database for this collection."; - Logger::Write(Logger::ZONE_INFO, "Database", msg); - - (void)ImportDirectory(info, crc32); - retVal = true; - } - else - { - std::stringstream ss; - std::string msg = "Collection \"" + title + "\" has not changed (CRC: " + crcStr.str() + "). Using existing database settings."; - Logger::Write(Logger::ZONE_INFO, "Database", msg); - - } - } - //std::cout << "Importing collection metadata for " << info->GetFullTitle() << " (collections." << info->GetName() << ")" << std::endl; - //ImportMetadata(info); - } - Logger::Write(Logger::ZONE_INFO, "Database", "Updating complete"); - - return retVal; -} - -unsigned long CollectionDatabase::CalculateCollectionCrc32(CollectionInfo *info) -{ - unsigned long crc = crc32(0L, Z_NULL, 0); - - // start off by reading all of the contents in the collection configuration folders - std::string settingsFile = info->GetSettingsPath() + "/Settings.conf"; - crc = CrcFile(settingsFile, crc); - - - std::string includeFile = info->GetSettingsPath() + "/Include.txt"; - crc = CrcFile(includeFile, crc); - - std::string excludeFile = info->GetSettingsPath() + "/Exclude.txt"; - crc = CrcFile(excludeFile, crc); - - std::string mamelistFile = info->GetSettingsPath() + "/Mamelist.xml"; - crc = CrcFile(mamelistFile, crc); - - DIR *dp; - struct dirent *dirp; - std::string path = info->GetListPath(); - dp = opendir(path.c_str()); - - if(dp == NULL) - { - Logger::Write(Logger::ZONE_ERROR, "Database", "Could not read directory for caching \"" + info->GetListPath() + "\""); - return crc; - } - - std::vector extensions; - info->GetExtensions(extensions); - std::vector::iterator extensionsIt; - - // md5sum each filename for the matching extension - while((dirp = readdir(dp)) != NULL) - { - std::string file = dirp->d_name; - for(extensionsIt = extensions.begin(); extensionsIt != extensions.end(); ++extensionsIt) - { - std::string comparator = "." + *extensionsIt; - int start = file.length() - comparator.length() + 1; - - if(start >= 0 && file.compare(start, comparator.length(), *extensionsIt) == 0) - { - std::string filename = dirp->d_name; - filename.append("\n"); - crc = crc32(crc, (const unsigned char *)filename.c_str(), (unsigned int)filename.length()); - } - } - } - - return crc; -} - -unsigned long CollectionDatabase::CrcFile(std::string file, unsigned long crc) -{ - // CRC both the filename and its contents - crc = crc32(crc, (const unsigned char *)file.c_str(), (unsigned int)file.length()); - std::ifstream ifFile(file.c_str()); - if(ifFile.good()) - { - std::stringstream ss; - ss << ifFile.rdbuf(); - - crc = crc32(crc, (const unsigned char *)ss.str().c_str(), (unsigned int)ss.str().length()); - Logger::Write(Logger::ZONE_INFO, "Database", "Crcing \"" + file + "\""); - ifFile.close(); - } - - return crc; -} - -bool CollectionDatabase::CollectionChanged(CollectionInfo *info, unsigned long crc32) -{ - bool retVal = true; - - sqlite3 *handle = DBInstance.GetHandle(); - int rc; - sqlite3_stmt *stmt; - - sqlite3_prepare_v2(handle, - "SELECT crc32 " - "FROM Collections WHERE collectionName=? and crc32=?;", - -1, &stmt, 0); - - sqlite3_bind_text(stmt, 1, info->GetName().c_str(), -1, SQLITE_TRANSIENT); - sqlite3_bind_int(stmt, 2, crc32); - - rc = sqlite3_step(stmt); - - if(rc == SQLITE_ROW) - { - retVal = false; - } - - return retVal; -} - -bool CollectionDatabase::SetHidden(std::string collectionName, Item *item, bool hidden) -{ - bool retVal = true; - char *error = NULL; - sqlite3 *handle = DBInstance.GetHandle(); - std::string mode = (hidden) ? "hidden":"visible"; - int isHidden = (hidden)?1:0; - - Logger::Write(Logger::ZONE_DEBUG, "Database", "Marking \"" + item->GetFullTitle() + "\" " + mode); - - sqlite3_stmt *stmt; - sqlite3_prepare_v2(handle, - "UPDATE CollectionItems SET hidden=? WHERE collectionName=? AND name=?;", - -1, &stmt, 0); - - sqlite3_bind_int(stmt, 1, isHidden); - sqlite3_bind_text(stmt, 2, collectionName.c_str(), -1, SQLITE_TRANSIENT); - sqlite3_bind_text(stmt, 3, item->GetFullTitle().c_str(), -1, SQLITE_TRANSIENT); - - sqlite3_step(stmt); - sqlite3_finalize(stmt); - - sqlite3_exec(handle, "COMMIT TRANSACTION;", NULL, NULL, &error); - - return retVal; -} - -//todo: This file needs MASSIVE REFACTORING! -bool CollectionDatabase::ImportDirectory(CollectionInfo *info, unsigned long crc32) -{ - DIR *dp; - struct dirent *dirp; - std::string path = info->GetListPath(); - std::map includeFilter; - std::map excludeFilter; - std::map includeList; - std::map metaList; - bool retVal = true; - char *error = NULL; - sqlite3 *handle = DBInstance.GetHandle(); - std::string includeFile = Configuration::GetAbsolutePath() + "/Collections/" + info->GetName() + "/Include.txt"; - std::string excludeFile = Configuration::GetAbsolutePath() + "/Collections/" + info->GetName() + "/Exclude.txt"; - std::string includeHyperListFile = Configuration::GetAbsolutePath() + "/Collections/" + info->GetName() + "/Include.xml"; - - if(!ImportBasicList(info, includeFile, includeFilter)) - { - ImportHyperList(info, includeHyperListFile, includeFilter); - - } - //todo: this shouldn't be read twice, perform a copy - ImportHyperList(info, includeHyperListFile, metaList); - - (void)ImportBasicList(info, excludeFile, excludeFilter); - - dp = opendir(path.c_str()); - std::vector extensions; - info->GetExtensions(extensions); - std::vector::iterator extensionsIt; - - if(dp == NULL) - { - Logger::Write(Logger::ZONE_ERROR, "Database", "Could not read directory \"" + info->GetListPath() + "\""); - //todo: store into a database - } - else - { - while((dirp = readdir(dp)) != NULL) - { - std::string file = dirp->d_name; - - Utils::NormalizeBackSlashes(file); - size_t position = file.find_last_of("."); - std::string basename = (std::string::npos == position)? file : file.substr(0, position); - - - if((includeFilter.size() == 0 || includeFilter.find(basename) != includeFilter.end()) && - (excludeFilter.size() == 0 || excludeFilter.find(basename) == excludeFilter.end())) - { - for(extensionsIt = extensions.begin(); extensionsIt != extensions.end(); ++extensionsIt) - { - std::string comparator = "." + *extensionsIt; - int start = file.length() - comparator.length() + 1; - - if(start >= 0) - { - if(file.compare(start, comparator.length(), *extensionsIt) == 0) - { - if(includeList.find(basename) == includeList.end()) - { - Item *i = new Item(); - i->SetFullTitle(file); - includeList[basename] = i; - } - if(metaList.find(basename) == metaList.end()) - { - Item *i = new Item(); - i->SetFullTitle(file); - metaList[basename] = i; - } - } - } - } - } - } - } - - while(includeFilter.size() > 0) - { - std::map::iterator it = includeFilter.begin(); - delete it->second; - includeFilter.erase(it); - } - while(excludeFilter.size() > 0) - { - std::map::iterator it = excludeFilter.begin(); - delete it->second; - excludeFilter.erase(it); - } - - - Logger::Write(Logger::ZONE_INFO, "Database", "Scanning to import \"" + path + "\""); - sqlite3_exec(handle, "BEGIN IMMEDIATE TRANSACTION;", NULL, NULL, &error); - - sqlite3_stmt *stmt; - sqlite3_prepare_v2(handle, - "DELETE FROM Collections WHERE collectionName=?;", - -1, &stmt, 0); - sqlite3_bind_text(stmt, 1, info->GetName().c_str(), -1, SQLITE_TRANSIENT); - sqlite3_step(stmt); - sqlite3_finalize(stmt); - - sqlite3_prepare_v2(handle, - "DELETE FROM CollectionItems WHERE collectionName=?;", - -1, &stmt, 0); - sqlite3_bind_text(stmt, 1, info->GetName().c_str(), -1, SQLITE_TRANSIENT); - sqlite3_step(stmt); - sqlite3_finalize(stmt); - - sqlite3_prepare_v2(handle, - "DELETE FROM Meta WHERE collectionName=?;", - -1, &stmt, 0); - sqlite3_bind_text(stmt, 1, info->GetName().c_str(), -1, SQLITE_TRANSIENT); - sqlite3_step(stmt); - sqlite3_finalize(stmt); - - if(sqlite3_exec(handle, "COMMIT TRANSACTION;", NULL, NULL, &error) != SQLITE_OK) - { - std::stringstream ss; - ss << "Updating cache collection failure " << error; - Logger::Write(Logger::ZONE_ERROR, "Database", ss.str()); - retVal = false; - } - - std::map::iterator it; - - if(sqlite3_exec(handle, "BEGIN IMMEDIATE TRANSACTION;", NULL, NULL, &error) != SQLITE_OK) - { - std::stringstream ss; - ss << "Delete cache collection failure " << error; - Logger::Write(Logger::ZONE_ERROR, "Database", ss.str()); - retVal = false; - } - - for(it = includeList.begin(); it != includeList.end(); it++) - { - std::string basename = it->first; - Item *file = it->second; - - std::string name = file->GetFullTitle(); - Utils::NormalizeBackSlashes(name); - file->SetFullTitle(name); - - sqlite3_prepare_v2(handle, - "INSERT OR REPLACE INTO CollectionItems (collectionName, filePath, name) VALUES (?,?,?);", - -1, &stmt, 0); - - sqlite3_bind_text(stmt, 1, info->GetName().c_str(), -1, SQLITE_TRANSIENT); - sqlite3_bind_text(stmt, 2, file->GetFullTitle().c_str(), -1, SQLITE_TRANSIENT); - sqlite3_bind_text(stmt, 3, basename.c_str(), -1, SQLITE_TRANSIENT); - - //todo: better error handling for all of these messages - sqlite3_step(stmt); - sqlite3_finalize(stmt); - } - for(it = metaList.begin(); it != metaList.end(); it++) - { - std::string basename = it->first; - Item *file = it->second; - - sqlite3_prepare_v2(handle, - "INSERT OR REPLACE INTO Meta (collectionName, name, title, year, manufacturer, cloneOf, players, buttons) VALUES (?,?,?,?,?,?,?,?);", - -1, &stmt, 0); - - sqlite3_bind_text(stmt, 1, info->GetName().c_str(), -1, SQLITE_TRANSIENT); - sqlite3_bind_text(stmt, 2, basename.c_str(), -1, SQLITE_TRANSIENT); - sqlite3_bind_text(stmt, 3, basename.c_str(), -1, SQLITE_TRANSIENT); - sqlite3_bind_text(stmt, 4, file->GetYear().c_str(), -1, SQLITE_TRANSIENT); - sqlite3_bind_text(stmt, 5, file->GetManufacturer().c_str(), -1, SQLITE_TRANSIENT); - sqlite3_bind_text(stmt, 6, file->GetCloneOf().c_str(), -1, SQLITE_TRANSIENT); - sqlite3_bind_text(stmt, 7, file->GetNumberPlayersString().c_str(), -1, SQLITE_TRANSIENT); - sqlite3_bind_text(stmt, 8, file->GetNumberButtonsString().c_str(), -1, SQLITE_TRANSIENT); - - sqlite3_step(stmt); - sqlite3_finalize(stmt); - } - - sqlite3_prepare_v2(handle, - "INSERT OR REPLACE INTO Collections (collectionName, crc32) VALUES (?,?);", - -1, &stmt, 0); - - sqlite3_bind_text(stmt, 1, info->GetName().c_str(), -1, SQLITE_TRANSIENT); - sqlite3_bind_int(stmt, 2, crc32); - - sqlite3_step(stmt); - sqlite3_finalize(stmt); - - - if(sqlite3_exec(handle, "COMMIT TRANSACTION;", NULL, NULL, &error) != SQLITE_OK) - { - std::stringstream ss; - ss << "Updating cache collection failure " << error; - Logger::Write(Logger::ZONE_ERROR, "Database", ss.str()); - retVal = false; - } - - Logger::Write(Logger::ZONE_INFO, "Database", "Imported files from \"" + path + "\" into database"); - - //todo: create a helper method to get this file directly (copy paste hazard) - std::string mamelistFile = info->GetSettingsPath() + "/Mamelist.xml"; - std::ifstream infile(mamelistFile.c_str()); - - if(infile.good()) - { - Logger::Write(Logger::ZONE_INFO, "Database", "Updating Mamelist metadata for \"" + info->GetName() + "\" (\"" + mamelistFile + "\") into database. This will take a while..."); - MamelistMetadata mld(DBInstance); - mld.Import(mamelistFile, info->GetName()); - } - infile.close(); - - - while(includeList.size() > 0) - { - std::map::iterator it = includeList.begin(); - delete it->second; - includeList.erase(it); - } - while(metaList.size() > 0) - { - std::map::iterator it = metaList.begin(); - delete it->second; - metaList.erase(it); - } - return retVal; -} - -bool CollectionDatabase::ImportBasicList(CollectionInfo *info, std::string file, std::map &list) -{ - bool retVal = false; - - Logger::Write(Logger::ZONE_DEBUG, "Database", "Checking to see if \"" + file + "\" exists"); - - std::ifstream includeStream(file.c_str()); - - if (includeStream.good()) - { - Logger::Write(Logger::ZONE_DEBUG, "Database", "Importing \"" + file + "\""); - std::string line; - - while(std::getline(includeStream, line)) - { - if(list.find(line) == list.end()) - { - Item *i = new Item(); - line.erase( std::remove(line.begin(), line.end(), '\r'), line.end() ); - - i->SetFullTitle(line); - list[line] = i; - Logger::Write(Logger::ZONE_DEBUG, "Database", "Including \"" + line + "\" (if file exists)"); - } - } - - retVal = true; - } - - return retVal; -} -bool CollectionDatabase::ImportHyperList(CollectionInfo *info, std::string hyperlistFile, std::map &list) -{ - bool retVal = false; - rapidxml::xml_document<> doc; - std::ifstream file(hyperlistFile.c_str()); - std::vector buffer((std::istreambuf_iterator(file)), std::istreambuf_iterator()); - - Logger::Write(Logger::ZONE_DEBUG, "Database", "Checking to see if \"" + hyperlistFile + "\" exists"); - - if(!file.good()) - { - Logger::Write(Logger::ZONE_INFO, "Database", "Could not find HyperList file: " + hyperlistFile); - return retVal; - } - - try - { - Logger::Write(Logger::ZONE_INFO, "Database", "Importing: " + hyperlistFile); - buffer.push_back('\0'); - - doc.parse<0>(&buffer[0]); - - rapidxml::xml_node<> *root = doc.first_node("menu"); - - - if(!root) - { - Logger::Write(Logger::ZONE_ERROR, "CollectionDatabase", "Does not appear to be a HyperList file (missing tag)"); - return NULL; - } - else - { - for(rapidxml::xml_node<> *game = root->first_node("game"); game; game = game->next_sibling("game")) - { - rapidxml::xml_attribute<> *nameXml = game->first_attribute("name"); - rapidxml::xml_node<> *descriptionXml = game->first_node("description"); - rapidxml::xml_node<> *cloneofXml = game->first_node("cloneof"); - rapidxml::xml_node<> *crcXml = game->first_node("crc"); - rapidxml::xml_node<> *manufacturerXml = game->first_node("manufacturer"); - rapidxml::xml_node<> *yearXml = game->first_node("year"); - rapidxml::xml_node<> *genreXml = game->first_node("genre"); - rapidxml::xml_node<> *ratingXml = game->first_node("rating"); - rapidxml::xml_node<> *enabledXml = game->first_node("enabled"); - std::string name = (nameXml) ? nameXml->value() : ""; - std::string description = (descriptionXml) ? descriptionXml->value() : ""; - std::string crc = (crcXml) ? crcXml->value() : ""; - std::string cloneOf = (cloneofXml) ? cloneofXml->value() : ""; - std::string manufacturer = (manufacturerXml) ? manufacturerXml->value() : ""; - std::string year = (yearXml) ? yearXml->value() : ""; - std::string genre = (genreXml) ? genreXml->value() : ""; - std::string rating = (ratingXml) ? ratingXml->value() : ""; - std::string enabled = (enabledXml) ? enabledXml->value() : ""; - - if(name.length() > 0 && list.find(name) == list.end()) - { - Item *i = new Item(); - i->SetFullTitle(name); - i->SetYear(year); - i->SetManufacturer(manufacturer); - i->SetCloneOf(cloneOf); - list[name] = i; - Logger::Write(Logger::ZONE_DEBUG, "Database", "Including \"" + name + "\" (if file exists)"); - } - - } - } - } - catch(rapidxml::parse_error &e) - { - std::string what = e.what(); - long line = static_cast(std::count(&buffer.front(), e.where(), char('\n')) + 1); - std::stringstream ss; - ss << "Could not parse layout file. [Line: " << line << "] Reason: " << e.what(); - - Logger::Write(Logger::ZONE_ERROR, "Layout", ss.str()); - } - catch(std::exception &e) - { - std::string what = e.what(); - Logger::Write(Logger::ZONE_ERROR, "Layout", "Could not parse layout file. Reason: " + what); - } - - - return retVal; -} - -/* -bool CollectionDatabase::ImportMetadata(CollectionInfo *info) -{ - bool retVal = true; - std::string type = info->GetMetadataType(); - - if(type.compare("mamelist") == 0) - { - MamelistMetadata meta; - //todo: pass in collectionName - retVal = meta.Import(info->GetMetadataPath(), "arcade"); - } - else if(!type.empty()) - { - std::stringstream ss; - ss << "Unsupported metadata type \"" << type << "\" for " << info->GetFullTitle() << " (collections." << info->GetName() << ".metadata.type)" << std::endl; - Log::Write(Log::ERROR, "Database", ss.str()); - - retVal = false; - } - - return retVal; -} -*/ - -bool CollectionDatabase::GetCollection(std::string collectionName, std::vector &list) -{ - bool retVal = true; - - sqlite3 *handle = DBInstance.GetHandle(); - int rc; - sqlite3_stmt *stmt; - - bool showParenthesis = true; - bool showSquareBrackets = true; - - (void)Config.GetProperty("showParenthesis", showParenthesis); - (void)Config.GetProperty("showSquareBrackets", showSquareBrackets); - - //todo: program crashes if this query fails - sqlite3_prepare_v2(handle, - "SELECT DISTINCT CollectionItems.filePath, CollectionItems.name, Meta.title, Meta.year, Meta.manufacturer, Meta.players, Meta.buttons, Meta.cloneOf " - "FROM CollectionItems, Meta WHERE CollectionItems.collectionName=? AND Meta.collectionName=? AND CollectionItems.name=Meta.name AND CollectionItems.hidden=0 ORDER BY title ASC;", - -1, &stmt, 0); - - sqlite3_bind_text(stmt, 1, collectionName.c_str(), -1, SQLITE_TRANSIENT); - sqlite3_bind_text(stmt, 2, collectionName.c_str(), -1, SQLITE_TRANSIENT); - - rc = sqlite3_step(stmt); - - while(rc == SQLITE_ROW) - { - std::string filePath = (char *)sqlite3_column_text(stmt, 0); - std::string name = (char *)sqlite3_column_text(stmt, 1); - std::string fullTitle = (char *)sqlite3_column_text(stmt, 2); - std::string year = (char *)sqlite3_column_text(stmt, 3); - std::string manufacturer = (char *)sqlite3_column_text(stmt, 4); - int numberPlayers = (int)sqlite3_column_int(stmt, 5); - int numberButtons = (int)sqlite3_column_int(stmt, 6); - std::string cloneOf = (char *)sqlite3_column_text(stmt, 7); - std::string launcher; - std::string title = fullTitle; - - if(!showParenthesis) - { - std::string::size_type firstPos = title.find_first_of("("); - std::string::size_type secondPos = title.find_first_of(")", firstPos); - - while(firstPos != std::string::npos && secondPos != std::string::npos) - { - firstPos = title.find_first_of("("); - secondPos = title.find_first_of(")", firstPos); - - if (firstPos != std::string::npos) - { - title.erase(firstPos, (secondPos - firstPos) + 1); - } - } - } - if(!showSquareBrackets) - { - std::string::size_type firstPos = title.find_first_of("["); - std::string::size_type secondPos = title.find_first_of("]", firstPos); - - while(firstPos != std::string::npos && secondPos != std::string::npos) - { - firstPos = title.find_first_of("["); - secondPos = title.find_first_of("]", firstPos); - - if (firstPos != std::string::npos && secondPos != std::string::npos) - { - title.erase(firstPos, (secondPos - firstPos) + 1); - } - } - } - - Item *item = new Item(); - item->SetFilePath(filePath); - item->SetName(name); - item->SetTitle(title); - item->SetFullTitle(fullTitle); - item->SetYear(year); - item->SetManufacturer(manufacturer); - item->SetNumberPlayers(numberPlayers); - item->SetNumberButtons(numberButtons); - item->SetCloneOf(cloneOf); - - //std::cout << "loading " << title << std::endl; - if(Config.GetProperty("collections." + collectionName + ".launcher", launcher)) - { - item->SetLauncher(launcher); - } - - list.push_back(item); - - rc = sqlite3_step(stmt); - } - - //todo: query the metadata table to populate each item - - return retVal; -} diff --git a/RetroFE/Source/Database/CollectionDatabase.h b/RetroFE/Source/Database/CollectionDatabase.h deleted file mode 100644 index ff656b2..0000000 --- a/RetroFE/Source/Database/CollectionDatabase.h +++ /dev/null @@ -1,44 +0,0 @@ -/* This file is subject to the terms and conditions defined in - * file 'LICENSE.txt', which is part of this source code package. - */ -#pragma once - -#include -#include -#include - -class DB; -class Configuration; -class CollectionInfo; -class Item; - -class CollectionDatabase -{ -public: - CollectionDatabase(DB &db, Configuration &c); - virtual ~CollectionDatabase(); - bool Initialize(); - bool Import(); - bool ResetDatabase(); - - - bool GetCollection(std::string collectionName, std::vector &list); - bool SetHidden(std::string collectionName, Item *item, bool hidden); - -private: - unsigned long CalculateCollectionCrc32(CollectionInfo *info); - bool CollectionChanged(CollectionInfo *info, unsigned long crc32); - unsigned long CrcFile(std::string file, unsigned long crc); - -// bool ImportMetadata(CollectionInfo *info); - bool ImportDirectory(CollectionInfo *info, unsigned long crc32); - bool ImportBasicList(CollectionInfo *info, - std::string file, - std::map &list); - bool ImportHyperList(CollectionInfo *info, - std::string file, - std::map &list); - std::map *ImportHyperList(CollectionInfo *info); - Configuration &Config; - DB &DBInstance; -}; diff --git a/RetroFE/Source/Database/MetadataDatabase.cpp b/RetroFE/Source/Database/MetadataDatabase.cpp new file mode 100644 index 0000000..50e5959 --- /dev/null +++ b/RetroFE/Source/Database/MetadataDatabase.cpp @@ -0,0 +1,198 @@ +/* This file is part of RetroFE. + * + * RetroFE is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * RetroFE is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with RetroFE. If not, see . + */ +#include "MetadataDatabase.h" +#include "../Collection/CollectionInfo.h" +#include "../Collection/Item.h" +#include "../Utility/Log.h" +#include "../Utility/Utils.h" +#include "MamelistMetadata.h" +#include "Configuration.h" +#include "DB.h" +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +MetadataDatabase::MetadataDatabase(DB &db, Configuration &c) + : Config(c) + , DBInstance(db) +{ + +} + +MetadataDatabase::~MetadataDatabase() +{ +} + +bool MetadataDatabase::ResetDatabase() +{ + bool retVal = true; + int rc; + char *error = NULL; + sqlite3 *handle = DBInstance.GetHandle(); + + Logger::Write(Logger::ZONE_INFO, "Database", "Erasing"); + + std::string sql; + sql.append("DROP TABLE IF EXISTS Meta;"); + + rc = sqlite3_exec(handle, sql.c_str(), NULL, 0, &error); + + if(rc != SQLITE_OK) + { + std::stringstream ss; + ss << "Unable to create Metadata table. Error: " << error; + Logger::Write(Logger::ZONE_ERROR, "Database", ss.str()); + retVal = false; + } + + return retVal; +} + +bool MetadataDatabase::Initialize() +{ + int rc; + char *error = NULL; + sqlite3 *handle = DBInstance.GetHandle(); + + std::string sql; + sql.append("CREATE TABLE IF NOT EXISTS Meta("); + sql.append("collectionName TEXT KEY,"); + sql.append("name TEXT NOT NULL DEFAULT '',"); + sql.append("title TEXT NOT NULL DEFAULT '',"); + sql.append("year TEXT NOT NULL DEFAULT '',"); + sql.append("manufacturer TEXT NOT NULL DEFAULT '',"); + sql.append("cloneOf TEXT NOT NULL DEFAULT '',"); + sql.append("players INTEGER,"); + sql.append("buttons INTEGER);"); + sql.append("CREATE UNIQUE INDEX IF NOT EXISTS MetaUniqueId ON Meta(collectionName, name);"); + + rc = sqlite3_exec(handle, sql.c_str(), NULL, 0, &error); + + if(rc != SQLITE_OK) + { + std::stringstream ss; + ss << "Unable to create Metadata table. Error: " << error; + Logger::Write(Logger::ZONE_ERROR, "Database", ss.str()); + + return false; + } + + return true; +} + +void MetadataDatabase::UpdateMetadata(CollectionInfo *collection) +{ + sqlite3 *handle = DBInstance.GetHandle(); + int rc; + sqlite3_stmt *stmt; + + bool showParenthesis = true; + bool showSquareBrackets = true; + + (void)Config.GetProperty("showParenthesis", showParenthesis); + (void)Config.GetProperty("showSquareBrackets", showSquareBrackets); + + + // items into a hash to make it easily searchable + std::vector *items = collection->GetItems(); + std::map itemMap; + + for(std::vector::iterator it = items->begin(); it != items->end(); it++) + { + itemMap[(*it)->GetName()] = *it; + } + + //todo: program crashes if this query fails + sqlite3_prepare_v2(handle, + "SELECT DISTINCT Meta.name, Meta.title, Meta.year, Meta.manufacturer, Meta.players, Meta.buttons, Meta.cloneOf " + "FROM Meta WHERE collectionName=? ORDER BY title ASC;", + -1, &stmt, 0); + + sqlite3_bind_text(stmt, 1, collection->GetName().c_str(), -1, SQLITE_TRANSIENT); + + rc = sqlite3_step(stmt); + + while(rc == SQLITE_ROW) + { + std::string name = (char *)sqlite3_column_text(stmt, 0); + std::string fullTitle = (char *)sqlite3_column_text(stmt, 1); + std::string year = (char *)sqlite3_column_text(stmt, 2); + std::string manufacturer = (char *)sqlite3_column_text(stmt, 3); + int numberPlayers = (int)sqlite3_column_int(stmt, 4); + int numberButtons = (int)sqlite3_column_int(stmt, 5); + std::string cloneOf = (char *)sqlite3_column_text(stmt, 6); + std::string launcher; + std::string title = fullTitle; + + //todo: this should be a helper method, peformed both in CollectionInfoBuilder + if(!showParenthesis) + { + std::string::size_type firstPos = title.find_first_of("("); + std::string::size_type secondPos = title.find_first_of(")", firstPos); + + while(firstPos != std::string::npos && secondPos != std::string::npos) + { + firstPos = title.find_first_of("("); + secondPos = title.find_first_of(")", firstPos); + + if (firstPos != std::string::npos) + { + title.erase(firstPos, (secondPos - firstPos) + 1); + } + } + } + if(!showSquareBrackets) + { + std::string::size_type firstPos = title.find_first_of("["); + std::string::size_type secondPos = title.find_first_of("]", firstPos); + + while(firstPos != std::string::npos && secondPos != std::string::npos) + { + firstPos = title.find_first_of("["); + secondPos = title.find_first_of("]", firstPos); + + if (firstPos != std::string::npos && secondPos != std::string::npos) + { + title.erase(firstPos, (secondPos - firstPos) + 1); + } + } + } + + std::map::iterator it = itemMap.find(name); + + if(it != itemMap.end()) + { + Item *item = it->second; + item->SetTitle(title); + item->SetFullTitle(fullTitle); + item->SetYear(year); + item->SetManufacturer(manufacturer); + item->SetNumberPlayers(numberPlayers); + item->SetNumberButtons(numberButtons); + item->SetCloneOf(cloneOf); + } + rc = sqlite3_step(stmt); + } +} diff --git a/RetroFE/Source/Database/MetadataDatabase.h b/RetroFE/Source/Database/MetadataDatabase.h new file mode 100644 index 0000000..affb195 --- /dev/null +++ b/RetroFE/Source/Database/MetadataDatabase.h @@ -0,0 +1,28 @@ +/* This file is subject to the terms and conditions defined in + * file 'LICENSE.txt', which is part of this source code package. + */ +#pragma once + +#include +#include +#include + +class DB; +class Configuration; +class CollectionInfo; +class Item; + +class MetadataDatabase +{ +public: + MetadataDatabase(DB &db, Configuration &c); + virtual ~MetadataDatabase(); + bool Initialize(); + bool ResetDatabase(); + + void UpdateMetadata(CollectionInfo *collection); + +private: + Configuration &Config; + DB &DBInstance; +}; diff --git a/RetroFE/Source/Graphics/ComponentItemBindingBuilder.cpp b/RetroFE/Source/Graphics/ComponentItemBindingBuilder.cpp index b2ef206..27d592c 100644 --- a/RetroFE/Source/Graphics/ComponentItemBindingBuilder.cpp +++ b/RetroFE/Source/Graphics/ComponentItemBindingBuilder.cpp @@ -15,8 +15,8 @@ */ #include "ComponentItemBindingBuilder.h" #include "ComponentItemBinding.h" -#include "../Database/CollectionDatabase.h" #include "../Collection/Item.h" +#include "../Utility/Log.h" ComponentItemBindingBuilder::ComponentItemBindingBuilder() { diff --git a/RetroFE/Source/Graphics/Page.cpp b/RetroFE/Source/Graphics/Page.cpp index 42115ec..10b2724 100644 --- a/RetroFE/Source/Graphics/Page.cpp +++ b/RetroFE/Source/Graphics/Page.cpp @@ -17,6 +17,7 @@ #include "Page.h" #include "ComponentItemBinding.h" #include "Component/Component.h" +#include "../Collection/CollectionInfo.h" #include "Component/Text.h" #include "../Utility/Log.h" #include "Component/ScrollingList.h" @@ -298,9 +299,9 @@ void Page::PageScroll(ScrollDirection direction) } -void Page::SetItems(std::vector *items) +void Page::SetCollection(CollectionInfo *collection) { - std::vector *sprites = ComponentItemBindingBuilder::BuildCollectionItems(items); + std::vector *sprites = ComponentItemBindingBuilder::BuildCollectionItems(collection->GetItems()); if(Menu) { Menu->SetItems(sprites); diff --git a/RetroFE/Source/Graphics/Page.h b/RetroFE/Source/Graphics/Page.h index e5a1fa9..3be321b 100644 --- a/RetroFE/Source/Graphics/Page.h +++ b/RetroFE/Source/Graphics/Page.h @@ -8,6 +8,7 @@ #include #include +class CollectionInfo; class Component; class Configuration; class ScrollingList; @@ -29,7 +30,7 @@ public: Page(std::string collectionName, Configuration &c); virtual ~Page(); virtual void OnNewItemSelected(Item *); - void SetItems(std::vector *items); + void SetCollection(CollectionInfo *collection); void SetMenu(ScrollingList *s); void SetLoadSound(Sound *chunk) { diff --git a/RetroFE/Source/Main.cpp b/RetroFE/Source/Main.cpp index 722be0d..2cdae21 100644 --- a/RetroFE/Source/Main.cpp +++ b/RetroFE/Source/Main.cpp @@ -16,8 +16,6 @@ #include "Database/Configuration.h" #include "Database/CollectionDatabase.h" -#include "Collection/CollectionInfoBuilder.h" -#include "Collection/CollectionInfo.h" #include "Database/MamelistMetadata.h" #include "Execute/Launcher.h" #include "Utility/Log.h" @@ -30,7 +28,6 @@ static bool ImportConfiguration(Configuration *c); static bool StartLogging(); -CollectionDatabase *InitializeCollectionDatabase(DB &db, Configuration &config); int main(int argc, char *argv[]) { diff --git a/RetroFE/Source/RetroFE.cpp b/RetroFE/Source/RetroFE.cpp index 6d4d3bd..a49ea50 100644 --- a/RetroFE/Source/RetroFE.cpp +++ b/RetroFE/Source/RetroFE.cpp @@ -15,7 +15,8 @@ */ #include "RetroFE.h" -#include "Database/CollectionDatabase.h" +#include "Collection/CollectionInfoBuilder.h" +#include "Collection/CollectionInfo.h" #include "Database/Configuration.h" #include "Collection/Item.h" #include "Execute/Launcher.h" @@ -41,7 +42,6 @@ RetroFE::RetroFE(Configuration &c) , InitializeThread(NULL) , Config(c) , Db(NULL) - , CollectionDB(NULL) , Input(Config) , KeyInputDisable(0) , CurrentTime(0) @@ -53,30 +53,6 @@ RetroFE::~RetroFE() DeInitialize(); } -CollectionDatabase *RetroFE::InitializeCollectionDatabase(DB &db, Configuration &config) -{ - CollectionDatabase *cdb = NULL; - - config.SetStatus("Initializing database"); - std::string dbFile = (Configuration::GetAbsolutePath() + "/cache.db"); - std::ifstream infile(dbFile.c_str()); - - cdb = new CollectionDatabase(db, config); - - if(!cdb->Initialize()) - { - delete cdb; - cdb = NULL; - } - else if(!cdb->Import()) - { - delete cdb; - cdb = NULL; - } - - return cdb; -} - void RetroFE::Render() { SDL_LockMutex(SDL::GetMutex()); @@ -115,16 +91,6 @@ int RetroFE::Initialize(void *context) return -1; } - - instance->CollectionDB = instance->InitializeCollectionDatabase(*instance->Db, instance->Config); - - if(!instance->CollectionDB) - { - Logger::Write(Logger::ZONE_ERROR, "RetroFE", "Could not initialize CollectionDB!"); - delete instance->Db; - return -1; - } - instance->Config.GetProperty("videoEnable", videoEnable); instance->Config.GetProperty("videoLoop", videoLoop); @@ -204,11 +170,6 @@ bool RetroFE::DeInitialize() Db = NULL; } - if(CollectionDB) - { - delete CollectionDB; - Db = NULL; - } Initialized = false; //todo: handle video deallocation return retVal; @@ -492,7 +453,8 @@ Page *RetroFE::LoadPage(std::string collectionName) Page *page = NULL; - std::vector *collection = GetCollection(collectionName); + Config.SetCurrentCollection(collectionName); + CollectionInfo *collection = GetCollection(collectionName); std::string layoutName = GetLayout(collectionName); if(PageChain.size() > 0) @@ -510,8 +472,7 @@ Page *RetroFE::LoadPage(std::string collectionName) } else { - Config.SetCurrentCollection(collectionName); - page->SetItems(collection); + page->SetCollection(collection); page->Start(); PageChain.push_back(page); @@ -522,11 +483,10 @@ Page *RetroFE::LoadPage(std::string collectionName) Page *RetroFE::LoadSplashPage() { PageBuilder pb("Splash", "", Config, &FC); - std::vector *coll = new std::vector(); Page * page = pb.BuildPage(); // page->SetStatusText("foobar"); Config.SetCurrentCollection(""); - page->SetItems(coll); + page->SetCollection(new CollectionInfo("", "", "", "", "")); page->Start(); PageChain.push_back(page); @@ -534,16 +494,16 @@ Page *RetroFE::LoadSplashPage() } -std::vector *RetroFE::GetCollection(std::string collectionName) +CollectionInfo *RetroFE::GetCollection(std::string collectionName) { // the page will deallocate this once its done - std::vector *collection = new std::vector(); MenuParser mp; - mp.GetMenuItems(CollectionDB, collectionName, *collection); - CollectionDB->GetCollection(collectionName, *collection); + CollectionInfoBuilder cib(Config, *Db); + CollectionInfo *collection = cib.BuildCollection(collectionName); + mp.GetMenuItems(collection); - if(collection->size() == 0) + if(collection->GetItems()->size() == 0) { Logger::Write(Logger::ZONE_WARNING, "RetroFE", "No list items found for collection " + collectionName); } diff --git a/RetroFE/Source/RetroFE.h b/RetroFE/Source/RetroFE.h index c2054f1..1702b25 100644 --- a/RetroFE/Source/RetroFE.h +++ b/RetroFE/Source/RetroFE.h @@ -13,7 +13,7 @@ #include #include -class CollectionDatabase; +class CollectionInfo; class Configuration; class Page; @@ -47,7 +47,6 @@ private: }; void Render(); - CollectionDatabase *InitializeCollectionDatabase(DB &db, Configuration &config); bool Back(bool &exit); void Quit(); void WaitToInitialize(); @@ -56,10 +55,9 @@ private: RETROFE_STATE ProcessUserInput(Page *page); void Update(float dt, bool scrollActive); std::string GetLayout(std::string collectionName); - std::vector *GetCollection(std::string collectionName); + CollectionInfo *GetCollection(std::string collectionName); Configuration &Config; DB *Db; - CollectionDatabase *CollectionDB; UserInput Input; std::list PageChain; float KeyInputDisable;