Code cleanup and code documentation

This commit is contained in:
Leon Styhre 2020-06-22 17:27:53 +02:00
parent ac91da6995
commit 672026632d
24 changed files with 1741 additions and 1688 deletions

View file

@ -18,11 +18,12 @@ Some key points:
* Comments should be proper sentences, starting with a capital letter and ending with a dot
* Use K&R placements of braces, read the Linux Kernel coding style document for clarifications
* Always use spaces between keywords and opening brackets, i.e. `if ()`, `for ()`, `while ()` etc.
* Use `std::string` instead of `char *` or `char []` unless there is a very specific reason not to
* Use `std::string` instead of `char *` or `char []` unless there is a very specific reason requiring the latter
* If the arguments (and initializer list) for a function or class exceeds 4 items, arrange them vertically to make the code easier to read
* Always declare one variable per line, never combine multiple declarations of the same type
* Name local variables with the first word in small letters and the proceeding words starting with capital letters, e.g. myExampleVariable
* Name member variables starting with a small 'm', e.g. mMyMemberVariable
* Don't pad variable declarations with spaces to make them align in columns, I'm sure it's well intended but it looks terrible
* Use the same naming convention for functions as for local variables, e.g. someFunction()
* Inline functions can be used but don't overdo it by using them for functions that won't be called very frequently
* Never put more than one statement on a single line, except for lambda expressions

View file

@ -31,4 +31,5 @@ v1.0.0
* Game images were sometimes scaled incorrectly
* Non-transparent favorite icons were not rendered correctly
* Restart and power-off menu entries not working (i.e. on a desktop OS)
* Toggling the screensaver didn't work as expected
* Lots and lots of small bugs and inconsistencies fixed

View file

@ -3,26 +3,22 @@ EmulationStation Desktop Edition
EmulationStation Desktop Edition is a cross-platform graphical front-end for emulators with controller and keyboard navigation.
This is a fork intended for use primarily on desktop computers where EmulationStation is not the primary interface for the computer.
As such, this fork will not provide full control over emulator settings or emulator button mappings or provide system utility functions and similar. Instead it's assumed that the emulators and the overall environment has been properly configured upfront.
This is a fork intended for use primarily on desktop computers where EmulationStation is not the primary interface for the computer. As such, this software will not provide full control over emulator settings or emulator button mappings or provide system utility functions and similar. Instead it's assumed that the emulators and the overall environment has been properly configured upfront.
The software comes preconfigured for use primarily with [RetroArch](https://www.retroarch.com), although this can certainly be changed as all emulator settings are fully configurable, even on a per-game basis.
** Help needed: **
**Help needed:**
Apart from code commits, help is especially needed for thorough testing of the software and for working on the RBSimple-DE theme.
It's impossible for me to test every game system (RBSimple-DE has support for almost a 100 different systems!) so it would be especially useful to hear about any issues with starting games using the default es_systems.cfg configuration file and also if there are any issues regarding scraping for certain systems.
In general, a review of the es_systems.cfg file including the supported file extensions would be great:
[es_systems.cfg_unix](resources/templates/es_systems.cfg_unix
In general, a review of the [es_systems.cfg](resources/templates/es_systems.cfg_unix) file including the supported file extensions would be great.
As for RBSimple-DE there are quite some missing graphic files and other customizations for a number of game systems. \
Check out [MISSING.md](themes/rbsimple-DE/MISSING.md) for more details of what needs to be added.
Finally, if someone could make a proper port to the Macintosh Operating System, that would be great as then all of the three major desktop operating systems would be supported! There is some code present specifically for macOS but I've been unable to test it.
Finally, if someone could make a proper port to the Macintosh Operating System, that would be great as then all of the three major desktop operating systems would be supported. There is some code present specifically for macOS but I've been unable to test it.
General information
@ -34,8 +30,6 @@ General information
[DEVNOTES.md](DEVNOTES.md) is the place to go if you're interested in participating in the development of EmulationStation Desktop Edition.
Or just go ahead and browse the repository for additional information, or maybe more important, to see the actual source code :)
What it can do
==============

View file

@ -1,3 +1,9 @@
//
// FileFilterIndex.cpp
//
// Gamelist filters.
//
#include "FileFilterIndex.h"
#include "utils/StringUtil.h"
@ -10,528 +16,499 @@
#define INCLUDE_UNKNOWN false;
FileFilterIndex::FileFilterIndex()
: filterByFavorites(false), filterByGenre(false), filterByHidden(false), filterByKidGame(false), filterByPlayers(false), filterByPubDev(false), filterByRatings(false)
: filterByFavorites(false),
filterByGenre(false),
filterByHidden(false),
filterByKidGame(false),
filterByPlayers(false),
filterByPubDev(false),
filterByRatings(false)
{
clearAllFilters();
FilterDataDecl filterDecls[] = {
//type //allKeys //filteredBy //filteredKeys //primaryKey //hasSecondaryKey //secondaryKey //menuLabel
{ FAVORITES_FILTER, &favoritesIndexAllKeys, &filterByFavorites, &favoritesIndexFilteredKeys,"favorite", false, "", "FAVORITES" },
{ GENRE_FILTER, &genreIndexAllKeys, &filterByGenre, &genreIndexFilteredKeys, "genre", true, "genre", "GENRE" },
{ PLAYER_FILTER, &playersIndexAllKeys, &filterByPlayers, &playersIndexFilteredKeys, "players", false, "", "PLAYERS" },
{ PUBDEV_FILTER, &pubDevIndexAllKeys, &filterByPubDev, &pubDevIndexFilteredKeys, "developer", true, "publisher", "PUBLISHER / DEVELOPER" },
{ RATINGS_FILTER, &ratingsIndexAllKeys, &filterByRatings, &ratingsIndexFilteredKeys, "rating", false, "", "RATING" },
{ KIDGAME_FILTER, &kidGameIndexAllKeys, &filterByKidGame, &kidGameIndexFilteredKeys, "kidgame", false, "", "KIDGAME" },
{ HIDDEN_FILTER, &hiddenIndexAllKeys, &filterByHidden, &hiddenIndexFilteredKeys, "hidden", false, "", "HIDDEN" }
};
clearAllFilters();
filterDataDecl = std::vector<FilterDataDecl>(filterDecls, filterDecls + sizeof(filterDecls) / sizeof(filterDecls[0]));
FilterDataDecl filterDecls[] = {
//type //allKeys //filteredBy //filteredKeys //primaryKey //hasSecondaryKey //secondaryKey //menuLabel
{ FAVORITES_FILTER, &favoritesIndexAllKeys, &filterByFavorites, &favoritesIndexFilteredKeys,"favorite", false, "", "FAVORITES" },
{ GENRE_FILTER, &genreIndexAllKeys, &filterByGenre, &genreIndexFilteredKeys, "genre", true, "genre", "GENRE" },
{ PLAYER_FILTER, &playersIndexAllKeys, &filterByPlayers, &playersIndexFilteredKeys, "players", false, "", "PLAYERS" },
{ PUBDEV_FILTER, &pubDevIndexAllKeys, &filterByPubDev, &pubDevIndexFilteredKeys, "developer", true, "publisher", "PUBLISHER / DEVELOPER" },
{ RATINGS_FILTER, &ratingsIndexAllKeys, &filterByRatings, &ratingsIndexFilteredKeys, "rating", false, "", "RATING" },
{ KIDGAME_FILTER, &kidGameIndexAllKeys, &filterByKidGame, &kidGameIndexFilteredKeys, "kidgame", false, "", "KIDGAME" },
{ HIDDEN_FILTER, &hiddenIndexAllKeys, &filterByHidden, &hiddenIndexFilteredKeys, "hidden", false, "", "HIDDEN" }
};
filterDataDecl = std::vector<FilterDataDecl>(filterDecls, filterDecls +
sizeof(filterDecls) / sizeof(filterDecls[0]));
}
FileFilterIndex::~FileFilterIndex()
{
resetIndex();
resetIndex();
}
std::vector<FilterDataDecl>& FileFilterIndex::getFilterDataDecls()
{
return filterDataDecl;
return filterDataDecl;
}
void FileFilterIndex::importIndex(FileFilterIndex* indexToImport)
{
struct IndexImportStructure
{
std::map<std::string, int>* destinationIndex;
std::map<std::string, int>* sourceIndex;
};
struct IndexImportStructure {
std::map<std::string, int>* destinationIndex;
std::map<std::string, int>* sourceIndex;
};
IndexImportStructure indexStructDecls[] = {
{ &genreIndexAllKeys, &(indexToImport->genreIndexAllKeys) },
{ &playersIndexAllKeys, &(indexToImport->playersIndexAllKeys) },
{ &pubDevIndexAllKeys, &(indexToImport->pubDevIndexAllKeys) },
{ &ratingsIndexAllKeys, &(indexToImport->ratingsIndexAllKeys) },
{ &favoritesIndexAllKeys, &(indexToImport->favoritesIndexAllKeys) },
{ &hiddenIndexAllKeys, &(indexToImport->hiddenIndexAllKeys) },
{ &kidGameIndexAllKeys, &(indexToImport->kidGameIndexAllKeys) },
};
IndexImportStructure indexStructDecls[] = {
{ &genreIndexAllKeys, &(indexToImport->genreIndexAllKeys) },
{ &playersIndexAllKeys, &(indexToImport->playersIndexAllKeys) },
{ &pubDevIndexAllKeys, &(indexToImport->pubDevIndexAllKeys) },
{ &ratingsIndexAllKeys, &(indexToImport->ratingsIndexAllKeys) },
{ &favoritesIndexAllKeys, &(indexToImport->favoritesIndexAllKeys) },
{ &hiddenIndexAllKeys, &(indexToImport->hiddenIndexAllKeys) },
{ &kidGameIndexAllKeys, &(indexToImport->kidGameIndexAllKeys) },
};
std::vector<IndexImportStructure> indexImportDecl = std::vector<IndexImportStructure>(indexStructDecls, indexStructDecls + sizeof(indexStructDecls) / sizeof(indexStructDecls[0]));
std::vector<IndexImportStructure> indexImportDecl =
std::vector<IndexImportStructure>(indexStructDecls, indexStructDecls +
sizeof(indexStructDecls) / sizeof(indexStructDecls[0]));
for (std::vector<IndexImportStructure>::const_iterator indexesIt = indexImportDecl.cbegin(); indexesIt != indexImportDecl.cend(); ++indexesIt )
{
for (std::map<std::string, int>::const_iterator sourceIt = (*indexesIt).sourceIndex->cbegin(); sourceIt != (*indexesIt).sourceIndex->cend(); ++sourceIt )
{
if ((*indexesIt).destinationIndex->find((*sourceIt).first) == (*indexesIt).destinationIndex->cend())
{
// entry doesn't exist
(*((*indexesIt).destinationIndex))[(*sourceIt).first] = (*sourceIt).second;
}
else
{
(*((*indexesIt).destinationIndex))[(*sourceIt).first] += (*sourceIt).second;
}
}
}
for (std::vector<IndexImportStructure>::const_iterator indexesIt =
indexImportDecl.cbegin(); indexesIt != indexImportDecl.cend(); ++indexesIt )
{
for (std::map<std::string, int>::const_iterator sourceIt =
(*indexesIt).sourceIndex->cbegin(); sourceIt !=
(*indexesIt).sourceIndex->cend(); ++sourceIt ) {
if ((*indexesIt).destinationIndex->find((*sourceIt).first) ==
(*indexesIt).destinationIndex->cend())
// Entry doesn't exist.
(*((*indexesIt).destinationIndex))[(*sourceIt).first] = (*sourceIt).second;
else
(*((*indexesIt).destinationIndex))[(*sourceIt).first] += (*sourceIt).second;
}
}
}
void FileFilterIndex::resetIndex()
{
clearAllFilters();
clearIndex(genreIndexAllKeys);
clearIndex(playersIndexAllKeys);
clearIndex(pubDevIndexAllKeys);
clearIndex(ratingsIndexAllKeys);
clearIndex(favoritesIndexAllKeys);
clearIndex(hiddenIndexAllKeys);
clearIndex(kidGameIndexAllKeys);
clearAllFilters();
clearIndex(genreIndexAllKeys);
clearIndex(playersIndexAllKeys);
clearIndex(pubDevIndexAllKeys);
clearIndex(ratingsIndexAllKeys);
clearIndex(favoritesIndexAllKeys);
clearIndex(hiddenIndexAllKeys);
clearIndex(kidGameIndexAllKeys);
}
std::string FileFilterIndex::getIndexableKey(FileData* game, FilterIndexType type, bool getSecondary)
std::string FileFilterIndex::getIndexableKey(FileData* game,
FilterIndexType type, bool getSecondary)
{
std::string key = "";
switch(type)
{
case GENRE_FILTER:
{
key = Utils::String::toUpper(game->metadata.get("genre"));
key = Utils::String::trim(key);
if (getSecondary && !key.empty()) {
std::istringstream f(key);
std::string newKey;
getline(f, newKey, '/');
if (!newKey.empty() && newKey != key)
{
key = newKey;
}
else
{
key = std::string();
}
}
break;
}
case PLAYER_FILTER:
{
if (getSecondary)
break;
std::string key = "";
switch (type) {
case GENRE_FILTER: {
key = Utils::String::toUpper(game->metadata.get("genre"));
key = Utils::String::trim(key);
if (getSecondary && !key.empty()) {
std::istringstream f(key);
std::string newKey;
getline(f, newKey, '/');
if (!newKey.empty() && newKey != key)
key = newKey;
else
key = std::string();
}
break;
}
case PLAYER_FILTER: {
if (getSecondary)
break;
key = game->metadata.get("players");
break;
}
case PUBDEV_FILTER:
{
key = Utils::String::toUpper(game->metadata.get("publisher"));
key = Utils::String::trim(key);
key = game->metadata.get("players");
break;
}
case PUBDEV_FILTER: {
key = Utils::String::toUpper(game->metadata.get("publisher"));
key = Utils::String::trim(key);
if ((getSecondary && !key.empty()) || (!getSecondary && key.empty()))
key = Utils::String::toUpper(game->metadata.get("developer"));
else
key = Utils::String::toUpper(game->metadata.get("publisher"));
break;
}
case RATINGS_FILTER:
{
int ratingNumber = 0;
if (!getSecondary)
{
std::string ratingString = game->metadata.get("rating");
if (!ratingString.empty()) {
try {
ratingNumber = (int)((std::stod(ratingString)*5)+0.5);
if (ratingNumber < 0)
ratingNumber = 0;
if ((getSecondary && !key.empty()) || (!getSecondary && key.empty()))
key = Utils::String::toUpper(game->metadata.get("developer"));
else
key = Utils::String::toUpper(game->metadata.get("publisher"));
break;
}
case RATINGS_FILTER: {
int ratingNumber = 0;
if (!getSecondary) {
std::string ratingString = game->metadata.get("rating");
if (!ratingString.empty()) {
try {
ratingNumber = (int)((std::stod(ratingString)*5)+0.5);
if (ratingNumber < 0)
ratingNumber = 0;
key = std::to_string(ratingNumber) + " STARS";
}
catch (int e)
{
LOG(LogError) << "Error parsing Rating (invalid value, exception nr.): " << ratingString << ", " << e;
}
}
}
break;
}
case FAVORITES_FILTER:
{
if (game->getType() != GAME)
return "FALSE";
key = Utils::String::toUpper(game->metadata.get("favorite"));
break;
}
case HIDDEN_FILTER:
{
if (game->getType() != GAME)
return "FALSE";
key = Utils::String::toUpper(game->metadata.get("hidden"));
break;
}
case KIDGAME_FILTER:
{
if (game->getType() != GAME)
return "FALSE";
key = Utils::String::toUpper(game->metadata.get("kidgame"));
break;
}
}
key = Utils::String::trim(key);
if (key.empty() || (type == RATINGS_FILTER && key == "0 STARS")) {
key = UNKNOWN_LABEL;
}
return key;
key = std::to_string(ratingNumber) + " STARS";
}
catch (int e) {
LOG(LogError) << "Error parsing Rating (invalid value, exception nr.): " <<
ratingString << ", " << e;
}
}
}
break;
}
case FAVORITES_FILTER: {
if (game->getType() != GAME)
return "FALSE";
key = Utils::String::toUpper(game->metadata.get("favorite"));
break;
}
case HIDDEN_FILTER: {
if (game->getType() != GAME)
return "FALSE";
key = Utils::String::toUpper(game->metadata.get("hidden"));
break;
}
case KIDGAME_FILTER: {
if (game->getType() != GAME)
return "FALSE";
key = Utils::String::toUpper(game->metadata.get("kidgame"));
break;
}
}
key = Utils::String::trim(key);
if (key.empty() || (type == RATINGS_FILTER && key == "0 STARS")) {
key = UNKNOWN_LABEL;
}
return key;
}
void FileFilterIndex::addToIndex(FileData* game)
{
manageGenreEntryInIndex(game);
managePlayerEntryInIndex(game);
managePubDevEntryInIndex(game);
manageRatingsEntryInIndex(game);
manageFavoritesEntryInIndex(game);
manageHiddenEntryInIndex(game);
manageKidGameEntryInIndex(game);
manageGenreEntryInIndex(game);
managePlayerEntryInIndex(game);
managePubDevEntryInIndex(game);
manageRatingsEntryInIndex(game);
manageFavoritesEntryInIndex(game);
manageHiddenEntryInIndex(game);
manageKidGameEntryInIndex(game);
}
void FileFilterIndex::removeFromIndex(FileData* game)
{
manageGenreEntryInIndex(game, true);
managePlayerEntryInIndex(game, true);
managePubDevEntryInIndex(game, true);
manageRatingsEntryInIndex(game, true);
manageFavoritesEntryInIndex(game, true);
manageHiddenEntryInIndex(game, true);
manageKidGameEntryInIndex(game, true);
manageGenreEntryInIndex(game, true);
managePlayerEntryInIndex(game, true);
managePubDevEntryInIndex(game, true);
manageRatingsEntryInIndex(game, true);
manageFavoritesEntryInIndex(game, true);
manageHiddenEntryInIndex(game, true);
manageKidGameEntryInIndex(game, true);
}
void FileFilterIndex::setFilter(FilterIndexType type, std::vector<std::string>* values)
{
// test if it exists before setting
if(type == NONE)
{
clearAllFilters();
}
else
{
for (std::vector<FilterDataDecl>::const_iterator it = filterDataDecl.cbegin(); it != filterDataDecl.cend(); ++it ) {
if ((*it).type == type)
{
FilterDataDecl filterData = (*it);
*(filterData.filteredByRef) = values->size() > 0;
filterData.currentFilteredKeys->clear();
for (std::vector<std::string>::const_iterator vit = values->cbegin(); vit != values->cend(); ++vit ) {
// check if exists
if (filterData.allIndexKeys->find(*vit) != filterData.allIndexKeys->cend()) {
filterData.currentFilteredKeys->push_back(std::string(*vit));
}
}
}
}
}
return;
// Test if it exists before setting.
if (type == NONE) {
clearAllFilters();
}
else {
for (std::vector<FilterDataDecl>::const_iterator it = filterDataDecl.cbegin();
it != filterDataDecl.cend(); ++it ) {
if ((*it).type == type) {
FilterDataDecl filterData = (*it);
*(filterData.filteredByRef) = values->size() > 0;
filterData.currentFilteredKeys->clear();
for (std::vector<std::string>::const_iterator vit =
values->cbegin(); vit != values->cend(); ++vit ) {
// Check if exists.
if (filterData.allIndexKeys->find(*vit) != filterData.allIndexKeys->cend()) {
filterData.currentFilteredKeys->push_back(std::string(*vit));
}
}
}
}
}
return;
}
void FileFilterIndex::clearAllFilters()
{
for (std::vector<FilterDataDecl>::const_iterator it = filterDataDecl.cbegin(); it != filterDataDecl.cend(); ++it )
{
FilterDataDecl filterData = (*it);
*(filterData.filteredByRef) = false;
filterData.currentFilteredKeys->clear();
}
return;
for (std::vector<FilterDataDecl>::const_iterator it = filterDataDecl.cbegin();
it != filterDataDecl.cend(); ++it ) {
FilterDataDecl filterData = (*it);
*(filterData.filteredByRef) = false;
filterData.currentFilteredKeys->clear();
}
return;
}
void FileFilterIndex::resetFilters()
{
clearAllFilters();
setUIModeFilters();
clearAllFilters();
setUIModeFilters();
}
void FileFilterIndex::setUIModeFilters()
{
if(!Settings::getInstance()->getBool("ForceDisableFilters")){
if (UIModeController::getInstance()->isUIModeKiosk())
{
filterByHidden = true;
std::vector<std::string> val = { "FALSE" };
setFilter(HIDDEN_FILTER, &val);
}
if (UIModeController::getInstance()->isUIModeKid())
{
filterByKidGame = true;
std::vector<std::string> val = { "TRUE" };
setFilter(KIDGAME_FILTER, &val);
}
}
if (!Settings::getInstance()->getBool("ForceDisableFilters")){
if (UIModeController::getInstance()->isUIModeKiosk()) {
filterByHidden = true;
std::vector<std::string> val = { "FALSE" };
setFilter(HIDDEN_FILTER, &val);
}
if (UIModeController::getInstance()->isUIModeKid()) {
filterByKidGame = true;
std::vector<std::string> val = { "TRUE" };
setFilter(KIDGAME_FILTER, &val);
}
}
}
void FileFilterIndex::debugPrintIndexes()
{
LOG(LogInfo) << "Printing Indexes...";
for (auto x: playersIndexAllKeys) {
LOG(LogInfo) << "Multiplayer Index: " << x.first << ": " << x.second;
}
for (auto x: genreIndexAllKeys) {
LOG(LogInfo) << "Genre Index: " << x.first << ": " << x.second;
}
for (auto x: ratingsIndexAllKeys) {
LOG(LogInfo) << "Ratings Index: " << x.first << ": " << x.second;
}
for (auto x: pubDevIndexAllKeys) {
LOG(LogInfo) << "PubDev Index: " << x.first << ": " << x.second;
}
for (auto x: favoritesIndexAllKeys) {
LOG(LogInfo) << "Favorites Index: " << x.first << ": " << x.second;
}
for (auto x : hiddenIndexAllKeys) {
LOG(LogInfo) << "Hidden Index: " << x.first << ": " << x.second;
}
for (auto x : kidGameIndexAllKeys) {
LOG(LogInfo) << "KidGames Index: " << x.first << ": " << x.second;
}
LOG(LogInfo) << "Printing Indexes...";
for (auto x: playersIndexAllKeys) {
LOG(LogInfo) << "Multiplayer Index: " << x.first << ": " << x.second;
}
for (auto x: genreIndexAllKeys) {
LOG(LogInfo) << "Genre Index: " << x.first << ": " << x.second;
}
for (auto x: ratingsIndexAllKeys) {
LOG(LogInfo) << "Ratings Index: " << x.first << ": " << x.second;
}
for (auto x: pubDevIndexAllKeys) {
LOG(LogInfo) << "PubDev Index: " << x.first << ": " << x.second;
}
for (auto x: favoritesIndexAllKeys) {
LOG(LogInfo) << "Favorites Index: " << x.first << ": " << x.second;
}
for (auto x : hiddenIndexAllKeys) {
LOG(LogInfo) << "Hidden Index: " << x.first << ": " << x.second;
}
for (auto x : kidGameIndexAllKeys) {
LOG(LogInfo) << "KidGames Index: " << x.first << ": " << x.second;
}
}
bool FileFilterIndex::showFile(FileData* game)
{
// this shouldn't happen, but just in case let's get it out of the way
if (!isFiltered())
return true;
// This shouldn't happen, but just in case let's get it out of the way.
if (!isFiltered())
return true;
// if folder, needs further inspection - i.e. see if folder contains at least one element
// that should be shown
if (game->getType() == FOLDER) {
std::vector<FileData*> children = game->getChildren();
// iterate through all of the children, until there's a match
// If folder, needs further inspection - i.e. see if folder contains at least one element
// that should be shown.
if (game->getType() == FOLDER) {
std::vector<FileData*> children = game->getChildren();
// Iterate through all of the children, until there's a match.
for (std::vector<FileData*>::const_iterator it = children.cbegin();
it != children.cend(); ++it ) {
if (showFile(*it))
return true;
}
return false;
}
for (std::vector<FileData*>::const_iterator it = children.cbegin(); it != children.cend(); ++it ) {
if (showFile(*it))
{
return true;
}
}
return false;
}
bool keepGoing = false;
bool keepGoing = false;
for (std::vector<FilterDataDecl>::const_iterator it = filterDataDecl.cbegin();
it != filterDataDecl.cend(); ++it ) {
FilterDataDecl filterData = (*it);
if (*(filterData.filteredByRef)) {
// Try to find a match.
std::string key = getIndexableKey(game, filterData.type, false);
keepGoing = isKeyBeingFilteredBy(key, filterData.type);
for (std::vector<FilterDataDecl>::const_iterator it = filterDataDecl.cbegin(); it != filterDataDecl.cend(); ++it ) {
FilterDataDecl filterData = (*it);
if(*(filterData.filteredByRef))
{
// try to find a match
std::string key = getIndexableKey(game, filterData.type, false);
keepGoing = isKeyBeingFilteredBy(key, filterData.type);
// if we didn't find a match, try for secondary keys - i.e. publisher and dev, or first genre
if (!keepGoing)
{
if (!filterData.hasSecondaryKey)
{
return false;
}
std::string secKey = getIndexableKey(game, filterData.type, true);
if (secKey != UNKNOWN_LABEL)
{
keepGoing = isKeyBeingFilteredBy(secKey, filterData.type);
}
}
// if still nothing, then it's not a match
if (!keepGoing)
return false;
}
}
return keepGoing;
// If we didn't find a match, try for secondary keys - i.e.
// publisher and dev, or first genre.
if (!keepGoing) {
if (!filterData.hasSecondaryKey)
return false;
std::string secKey = getIndexableKey(game, filterData.type, true);
if (secKey != UNKNOWN_LABEL)
keepGoing = isKeyBeingFilteredBy(secKey, filterData.type);
}
// If still nothing, then it's not a match.
if (!keepGoing)
return false;
}
}
return keepGoing;
}
bool FileFilterIndex::isKeyBeingFilteredBy(std::string key, FilterIndexType type)
{
const FilterIndexType filterTypes[7] = { FAVORITES_FILTER, GENRE_FILTER, PLAYER_FILTER, PUBDEV_FILTER, RATINGS_FILTER,HIDDEN_FILTER, KIDGAME_FILTER };
std::vector<std::string> filterKeysList[7] = { favoritesIndexFilteredKeys, genreIndexFilteredKeys, playersIndexFilteredKeys, pubDevIndexFilteredKeys, ratingsIndexFilteredKeys, hiddenIndexFilteredKeys, kidGameIndexFilteredKeys };
const FilterIndexType filterTypes[7] = { FAVORITES_FILTER, GENRE_FILTER,
PLAYER_FILTER, PUBDEV_FILTER, RATINGS_FILTER,HIDDEN_FILTER, KIDGAME_FILTER };
std::vector<std::string> filterKeysList[7] = { favoritesIndexFilteredKeys,
genreIndexFilteredKeys, playersIndexFilteredKeys, pubDevIndexFilteredKeys,
ratingsIndexFilteredKeys, hiddenIndexFilteredKeys, kidGameIndexFilteredKeys };
for (int i = 0; i < 7; i++)
{
if (filterTypes[i] == type)
{
for (std::vector<std::string>::const_iterator it = filterKeysList[i].cbegin(); it != filterKeysList[i].cend(); ++it )
{
if (key == (*it))
{
return true;
}
}
return false;
}
}
return false;
for (int i = 0; i < 7; i++) {
if (filterTypes[i] == type) {
for (std::vector<std::string>::const_iterator it = filterKeysList[i].cbegin();
it != filterKeysList[i].cend(); ++it ) {
if (key == (*it))
return true;
}
return false;
}
}
return false;
}
void FileFilterIndex::manageGenreEntryInIndex(FileData* game, bool remove)
{
std::string key = getIndexableKey(game, GENRE_FILTER, false);
std::string key = getIndexableKey(game, GENRE_FILTER, false);
// flag for including unknowns
bool includeUnknown = INCLUDE_UNKNOWN;
// Flag for including unknowns.
bool includeUnknown = INCLUDE_UNKNOWN;
// only add unknown in pubdev IF both dev and pub are empty
if (!includeUnknown && (key == UNKNOWN_LABEL || key == "BIOS")) {
// no valid genre info found
return;
}
// Only add unknown in pubdev IF both dev and pub are empty.
if (!includeUnknown && (key == UNKNOWN_LABEL || key == "BIOS"))
// No valid genre info found.
return;
manageIndexEntry(&genreIndexAllKeys, key, remove);
manageIndexEntry(&genreIndexAllKeys, key, remove);
key = getIndexableKey(game, GENRE_FILTER, true);
if (!includeUnknown && key == UNKNOWN_LABEL)
{
manageIndexEntry(&genreIndexAllKeys, key, remove);
}
key = getIndexableKey(game, GENRE_FILTER, true);
if (!includeUnknown && key == UNKNOWN_LABEL)
manageIndexEntry(&genreIndexAllKeys, key, remove);
}
void FileFilterIndex::managePlayerEntryInIndex(FileData* game, bool remove)
{
// flag for including unknowns
bool includeUnknown = INCLUDE_UNKNOWN;
std::string key = getIndexableKey(game, PLAYER_FILTER, false);
// Flag for including unknowns.
bool includeUnknown = INCLUDE_UNKNOWN;
std::string key = getIndexableKey(game, PLAYER_FILTER, false);
// only add unknown in pubdev IF both dev and pub are empty
if (!includeUnknown && key == UNKNOWN_LABEL) {
// no valid player info found
return;
}
// Only add unknown in pubdev IF both dev and pub are empty.
if (!includeUnknown && key == UNKNOWN_LABEL)
// No valid player info found.
return;
manageIndexEntry(&playersIndexAllKeys, key, remove);
manageIndexEntry(&playersIndexAllKeys, key, remove);
}
void FileFilterIndex::managePubDevEntryInIndex(FileData* game, bool remove)
{
std::string pub = getIndexableKey(game, PUBDEV_FILTER, false);
std::string dev = getIndexableKey(game, PUBDEV_FILTER, true);
std::string pub = getIndexableKey(game, PUBDEV_FILTER, false);
std::string dev = getIndexableKey(game, PUBDEV_FILTER, true);
// flag for including unknowns
bool includeUnknown = INCLUDE_UNKNOWN;
bool unknownPub = false;
bool unknownDev = false;
// Flag for including unknowns.
bool includeUnknown = INCLUDE_UNKNOWN;
bool unknownPub = false;
bool unknownDev = false;
if (pub == UNKNOWN_LABEL) {
unknownPub = true;
}
if (dev == UNKNOWN_LABEL) {
unknownDev = true;
}
if (pub == UNKNOWN_LABEL)
unknownPub = true;
if (!includeUnknown && unknownDev && unknownPub) {
// no valid rating info found
return;
}
if (dev == UNKNOWN_LABEL)
unknownDev = true;
if (unknownDev && unknownPub) {
// if no info at all
manageIndexEntry(&pubDevIndexAllKeys, pub, remove);
}
else
{
if (!unknownDev) {
// if no info at all
manageIndexEntry(&pubDevIndexAllKeys, dev, remove);
}
if (!unknownPub) {
// if no info at all
manageIndexEntry(&pubDevIndexAllKeys, pub, remove);
}
}
if (!includeUnknown && unknownDev && unknownPub)
// No valid rating info found.
return;
if (unknownDev && unknownPub) {
// If no info at all.
manageIndexEntry(&pubDevIndexAllKeys, pub, remove);
}
else {
if (!unknownDev) {
// If no info at all.
manageIndexEntry(&pubDevIndexAllKeys, dev, remove);
}
if (!unknownPub) {
// If no info at all.
manageIndexEntry(&pubDevIndexAllKeys, pub, remove);
}
}
}
void FileFilterIndex::manageRatingsEntryInIndex(FileData* game, bool remove)
{
std::string key = getIndexableKey(game, RATINGS_FILTER, false);
std::string key = getIndexableKey(game, RATINGS_FILTER, false);
// flag for including unknowns
bool includeUnknown = INCLUDE_UNKNOWN;
// Flag for including unknowns.
bool includeUnknown = INCLUDE_UNKNOWN;
if (!includeUnknown && key == UNKNOWN_LABEL) {
// no valid rating info found
return;
}
if (!includeUnknown && key == UNKNOWN_LABEL)
// No valid rating info found.
return;
manageIndexEntry(&ratingsIndexAllKeys, key, remove);
manageIndexEntry(&ratingsIndexAllKeys, key, remove);
}
void FileFilterIndex::manageFavoritesEntryInIndex(FileData* game, bool remove)
{
// flag for including unknowns
bool includeUnknown = INCLUDE_UNKNOWN;
std::string key = getIndexableKey(game, FAVORITES_FILTER, false);
if (!includeUnknown && key == UNKNOWN_LABEL) {
// no valid favorites info found
return;
}
// Flag for including unknowns.
bool includeUnknown = INCLUDE_UNKNOWN;
std::string key = getIndexableKey(game, FAVORITES_FILTER, false);
manageIndexEntry(&favoritesIndexAllKeys, key, remove);
if (!includeUnknown && key == UNKNOWN_LABEL)
// No valid favorites info found.
return;
manageIndexEntry(&favoritesIndexAllKeys, key, remove);
}
void FileFilterIndex::manageHiddenEntryInIndex(FileData* game, bool remove)
{
// flag for including unknowns
bool includeUnknown = INCLUDE_UNKNOWN;
std::string key = getIndexableKey(game, HIDDEN_FILTER, false);
if (!includeUnknown && key == UNKNOWN_LABEL) {
// no valid hidden info found
return;
}
// Flag for including unknowns.
bool includeUnknown = INCLUDE_UNKNOWN;
std::string key = getIndexableKey(game, HIDDEN_FILTER, false);
manageIndexEntry(&hiddenIndexAllKeys, key, remove);
if (!includeUnknown && key == UNKNOWN_LABEL)
// No valid hidden info found.
return;
manageIndexEntry(&hiddenIndexAllKeys, key, remove);
}
void FileFilterIndex::manageKidGameEntryInIndex(FileData* game, bool remove)
{
// flag for including unknowns
bool includeUnknown = INCLUDE_UNKNOWN;
std::string key = getIndexableKey(game, KIDGAME_FILTER, false);
if (!includeUnknown && key == UNKNOWN_LABEL) {
// no valid kidgame info found
return;
}
// Flag for including unknowns.
bool includeUnknown = INCLUDE_UNKNOWN;
std::string key = getIndexableKey(game, KIDGAME_FILTER, false);
manageIndexEntry(&kidGameIndexAllKeys, key, remove);
if (!includeUnknown && key == UNKNOWN_LABEL)
// No valid kidgame info found.
return;
manageIndexEntry(&kidGameIndexAllKeys, key, remove);
}
void FileFilterIndex::manageIndexEntry(std::map<std::string, int>* index, std::string key, bool remove) {
bool includeUnknown = INCLUDE_UNKNOWN;
if (!includeUnknown && key == UNKNOWN_LABEL)
return;
if (remove) {
// removing entry
if (index->find(key) == index->cend())
{
// this shouldn't happen
LOG(LogInfo) << "Couldn't find entry in index! " << key;
}
else
{
(index->at(key))--;
if(index->at(key) <= 0) {
index->erase(key);
}
}
}
else
{
// adding entry
if (index->find(key) == index->cend())
{
(*index)[key] = 1;
}
else
{
(index->at(key))++;
}
}
void FileFilterIndex::manageIndexEntry(std::map<std::string, int>* index,
std::string key, bool remove)
{
bool includeUnknown = INCLUDE_UNKNOWN;
if (!includeUnknown && key == UNKNOWN_LABEL)
return;
if (remove) {
// Removing entry.
if (index->find(key) == index->cend()) {
// This shouldn't happen.
LOG(LogInfo) << "Couldn't find entry in index! " << key;
}
else {
(index->at(key))--;
if (index->at(key) <= 0) {
index->erase(key);
}
}
}
else {
// Adding entry.
if (index->find(key) == index->cend())
(*index)[key] = 1;
else
(index->at(key))++;
}
}
void FileFilterIndex::clearIndex(std::map<std::string, int> indexMap)
{
indexMap.clear();
}
indexMap.clear();
}

View file

@ -1,3 +1,9 @@
//
// FileFilterIndex.h
//
// Gamelist filters.
//
#pragma once
#ifndef ES_APP_FILE_FILTER_INDEX_H
#define ES_APP_FILE_FILTER_INDEX_H
@ -7,91 +13,90 @@
class FileData;
enum FilterIndexType
{
NONE,
GENRE_FILTER,
PLAYER_FILTER,
PUBDEV_FILTER,
RATINGS_FILTER,
FAVORITES_FILTER,
HIDDEN_FILTER,
KIDGAME_FILTER
enum FilterIndexType {
NONE,
GENRE_FILTER,
PLAYER_FILTER,
PUBDEV_FILTER,
RATINGS_FILTER,
FAVORITES_FILTER,
HIDDEN_FILTER,
KIDGAME_FILTER
};
struct FilterDataDecl
{
FilterIndexType type; // type of filter
std::map<std::string, int>* allIndexKeys; // all possible filters for this type
bool* filteredByRef; // is it filtered by this type
std::vector<std::string>* currentFilteredKeys; // current keys being filtered for
std::string primaryKey; // primary key in metadata
bool hasSecondaryKey; // has secondary key for comparison
std::string secondaryKey; // what's the secondary key
std::string menuLabel; // text to show in menu
struct FilterDataDecl {
FilterIndexType type; // Type of filter.
std::map<std::string, int>* allIndexKeys; // All possible filters for this type.
bool* filteredByRef; // Is it filtered by this type?
std::vector<std::string>* currentFilteredKeys; // Current keys being filtered for.
std::string primaryKey; // Primary key in metadata.
bool hasSecondaryKey; // Has secondary key for comparison.
std::string secondaryKey; // What's the secondary key.
std::string menuLabel; // Text to show in menu.
};
class FileFilterIndex
{
public:
FileFilterIndex();
~FileFilterIndex();
void addToIndex(FileData* game);
void removeFromIndex(FileData* game);
void setFilter(FilterIndexType type, std::vector<std::string>* values);
void clearAllFilters();
void debugPrintIndexes();
bool showFile(FileData* game);
bool isFiltered() { return (filterByGenre || filterByPlayers || filterByPubDev || filterByRatings || filterByFavorites || filterByHidden || filterByKidGame); };
bool isKeyBeingFilteredBy(std::string key, FilterIndexType type);
std::vector<FilterDataDecl>& getFilterDataDecls();
FileFilterIndex();
~FileFilterIndex();
void addToIndex(FileData* game);
void removeFromIndex(FileData* game);
void setFilter(FilterIndexType type, std::vector<std::string>* values);
void clearAllFilters();
void debugPrintIndexes();
bool showFile(FileData* game);
bool isFiltered() { return (filterByGenre || filterByPlayers || filterByPubDev ||
filterByRatings || filterByFavorites || filterByHidden || filterByKidGame); };
bool isKeyBeingFilteredBy(std::string key, FilterIndexType type);
std::vector<FilterDataDecl>& getFilterDataDecls();
void importIndex(FileFilterIndex* indexToImport);
void resetIndex();
void resetFilters();
void setUIModeFilters();
void importIndex(FileFilterIndex* indexToImport);
void resetIndex();
void resetFilters();
void setUIModeFilters();
private:
std::vector<FilterDataDecl> filterDataDecl;
std::string getIndexableKey(FileData* game, FilterIndexType type, bool getSecondary);
std::vector<FilterDataDecl> filterDataDecl;
std::string getIndexableKey(FileData* game, FilterIndexType type, bool getSecondary);
void manageGenreEntryInIndex(FileData* game, bool remove = false);
void managePlayerEntryInIndex(FileData* game, bool remove = false);
void managePubDevEntryInIndex(FileData* game, bool remove = false);
void manageRatingsEntryInIndex(FileData* game, bool remove = false);
void manageFavoritesEntryInIndex(FileData* game, bool remove = false);
void manageHiddenEntryInIndex(FileData* game, bool remove = false);
void manageKidGameEntryInIndex(FileData* game, bool remove = false);
void manageGenreEntryInIndex(FileData* game, bool remove = false);
void managePlayerEntryInIndex(FileData* game, bool remove = false);
void managePubDevEntryInIndex(FileData* game, bool remove = false);
void manageRatingsEntryInIndex(FileData* game, bool remove = false);
void manageFavoritesEntryInIndex(FileData* game, bool remove = false);
void manageHiddenEntryInIndex(FileData* game, bool remove = false);
void manageKidGameEntryInIndex(FileData* game, bool remove = false);
void manageIndexEntry(std::map<std::string, int>* index, std::string key, bool remove);
void manageIndexEntry(std::map<std::string, int>* index, std::string key, bool remove);
void clearIndex(std::map<std::string, int> indexMap);
void clearIndex(std::map<std::string, int> indexMap);
bool filterByGenre;
bool filterByPlayers;
bool filterByPubDev;
bool filterByRatings;
bool filterByFavorites;
bool filterByHidden;
bool filterByKidGame;
bool filterByGenre;
bool filterByPlayers;
bool filterByPubDev;
bool filterByRatings;
bool filterByFavorites;
bool filterByHidden;
bool filterByKidGame;
std::map<std::string, int> genreIndexAllKeys;
std::map<std::string, int> playersIndexAllKeys;
std::map<std::string, int> pubDevIndexAllKeys;
std::map<std::string, int> ratingsIndexAllKeys;
std::map<std::string, int> favoritesIndexAllKeys;
std::map<std::string, int> hiddenIndexAllKeys;
std::map<std::string, int> kidGameIndexAllKeys;
std::map<std::string, int> genreIndexAllKeys;
std::map<std::string, int> playersIndexAllKeys;
std::map<std::string, int> pubDevIndexAllKeys;
std::map<std::string, int> ratingsIndexAllKeys;
std::map<std::string, int> favoritesIndexAllKeys;
std::map<std::string, int> hiddenIndexAllKeys;
std::map<std::string, int> kidGameIndexAllKeys;
std::vector<std::string> genreIndexFilteredKeys;
std::vector<std::string> playersIndexFilteredKeys;
std::vector<std::string> pubDevIndexFilteredKeys;
std::vector<std::string> ratingsIndexFilteredKeys;
std::vector<std::string> favoritesIndexFilteredKeys;
std::vector<std::string> hiddenIndexFilteredKeys;
std::vector<std::string> kidGameIndexFilteredKeys;
std::vector<std::string> genreIndexFilteredKeys;
std::vector<std::string> playersIndexFilteredKeys;
std::vector<std::string> pubDevIndexFilteredKeys;
std::vector<std::string> ratingsIndexFilteredKeys;
std::vector<std::string> favoritesIndexFilteredKeys;
std::vector<std::string> hiddenIndexFilteredKeys;
std::vector<std::string> kidGameIndexFilteredKeys;
FileData* mRootFolder;
FileData* mRootFolder;
};

View file

@ -1,118 +1,125 @@
//
// FileSorts.cpp
//
// Gamelist sorting functions.
// Actual sorting takes place in FileData.
//
#include "FileSorts.h"
#include "utils/StringUtil.h"
namespace FileSorts
{
const FileData::SortType typesArr[] = {
FileData::SortType(&compareName, true, "filename, ascending"),
FileData::SortType(&compareName, false, "filename, descending"),
const FileData::SortType typesArr[] = {
FileData::SortType(&compareName, true, "filename, ascending"),
FileData::SortType(&compareName, false, "filename, descending"),
FileData::SortType(&compareRating, true, "rating, ascending"),
FileData::SortType(&compareRating, false, "rating, descending"),
FileData::SortType(&compareRating, true, "rating, ascending"),
FileData::SortType(&compareRating, false, "rating, descending"),
FileData::SortType(&compareTimesPlayed, true, "times played, ascending"),
FileData::SortType(&compareTimesPlayed, false, "times played, descending"),
FileData::SortType(&compareTimesPlayed, true, "times played, ascending"),
FileData::SortType(&compareTimesPlayed, false, "times played, descending"),
FileData::SortType(&compareLastPlayed, true, "last played, ascending"),
FileData::SortType(&compareLastPlayed, false, "last played, descending"),
FileData::SortType(&compareLastPlayed, true, "last played, ascending"),
FileData::SortType(&compareLastPlayed, false, "last played, descending"),
FileData::SortType(&compareNumPlayers, true, "number players, ascending"),
FileData::SortType(&compareNumPlayers, false, "number players, descending"),
FileData::SortType(&compareNumPlayers, true, "number players, ascending"),
FileData::SortType(&compareNumPlayers, false, "number players, descending"),
FileData::SortType(&compareReleaseDate, true, "release date, ascending"),
FileData::SortType(&compareReleaseDate, false, "release date, descending"),
FileData::SortType(&compareReleaseDate, true, "release date, ascending"),
FileData::SortType(&compareReleaseDate, false, "release date, descending"),
FileData::SortType(&compareGenre, true, "genre, ascending"),
FileData::SortType(&compareGenre, false, "genre, descending"),
FileData::SortType(&compareGenre, true, "genre, ascending"),
FileData::SortType(&compareGenre, false, "genre, descending"),
FileData::SortType(&compareDeveloper, true, "developer, ascending"),
FileData::SortType(&compareDeveloper, false, "developer, descending"),
FileData::SortType(&compareDeveloper, true, "developer, ascending"),
FileData::SortType(&compareDeveloper, false, "developer, descending"),
FileData::SortType(&comparePublisher, true, "publisher, ascending"),
FileData::SortType(&comparePublisher, false, "publisher, descending"),
FileData::SortType(&comparePublisher, true, "publisher, ascending"),
FileData::SortType(&comparePublisher, false, "publisher, descending"),
FileData::SortType(&compareSystem, true, "system, ascending"),
FileData::SortType(&compareSystem, false, "system, descending")
};
FileData::SortType(&compareSystem, true, "system, ascending"),
FileData::SortType(&compareSystem, false, "system, descending")
};
const std::vector<FileData::SortType> SortTypes(typesArr, typesArr + sizeof(typesArr)/sizeof(typesArr[0]));
const std::vector<FileData::SortType> SortTypes(typesArr, typesArr +
sizeof(typesArr)/sizeof(typesArr[0]));
//returns if file1 should come before file2
bool compareName(const FileData* file1, const FileData* file2)
{
// we compare the actual metadata name, as collection files have the system appended which messes up the order
std::string name1 = Utils::String::toUpper(file1->metadata.get("sortname"));
std::string name2 = Utils::String::toUpper(file2->metadata.get("sortname"));
if(name1.empty()){
name1 = Utils::String::toUpper(file1->metadata.get("name"));
}
if(name2.empty()){
name2 = Utils::String::toUpper(file2->metadata.get("name"));
}
return name1.compare(name2) < 0;
}
// Returns if file1 should come before file2.
bool compareName(const FileData* file1, const FileData* file2)
{
// We compare the actual metadata name, as collection files have the system
// appended which messes up the order.
std::string name1 = Utils::String::toUpper(file1->metadata.get("sortname"));
std::string name2 = Utils::String::toUpper(file2->metadata.get("sortname"));
if(name1.empty()){
name1 = Utils::String::toUpper(file1->metadata.get("name"));
}
if(name2.empty()){
name2 = Utils::String::toUpper(file2->metadata.get("name"));
}
return name1.compare(name2) < 0;
}
bool compareRating(const FileData* file1, const FileData* file2)
{
return file1->metadata.getFloat("rating") < file2->metadata.getFloat("rating");
}
bool compareRating(const FileData* file1, const FileData* file2)
{
return file1->metadata.getFloat("rating") < file2->metadata.getFloat("rating");
}
bool compareTimesPlayed(const FileData* file1, const FileData* file2)
{
//only games have playcount metadata
if(file1->metadata.getType() == GAME_METADATA && file2->metadata.getType() == GAME_METADATA)
{
return (file1)->metadata.getInt("playcount") < (file2)->metadata.getInt("playcount");
}
bool compareTimesPlayed(const FileData* file1, const FileData* file2)
{
//only games have playcount metadata
if(file1->metadata.getType() == GAME_METADATA && file2->metadata.getType() == GAME_METADATA)
return (file1)->metadata.getInt("playcount") < (file2)->metadata.getInt("playcount");
return false;
}
return false;
}
bool compareLastPlayed(const FileData* file1, const FileData* file2)
{
// since it's stored as an ISO string (YYYYMMDDTHHMMSS), we can compare as a string
// as it's a lot faster than the time casts and then time comparisons
return (file1)->metadata.get("lastplayed") < (file2)->metadata.get("lastplayed");
}
bool compareLastPlayed(const FileData* file1, const FileData* file2)
{
// Since it's stored as an ISO string (YYYYMMDDTHHMMSS), we can compare as a string
// which is a lot faster than the time casts and the time comparisons.
return (file1)->metadata.get("lastplayed") < (file2)->metadata.get("lastplayed");
}
bool compareNumPlayers(const FileData* file1, const FileData* file2)
{
return (file1)->metadata.getInt("players") < (file2)->metadata.getInt("players");
}
bool compareNumPlayers(const FileData* file1, const FileData* file2)
{
return (file1)->metadata.getInt("players") < (file2)->metadata.getInt("players");
}
bool compareReleaseDate(const FileData* file1, const FileData* file2)
{
// since it's stored as an ISO string (YYYYMMDDTHHMMSS), we can compare as a string
// as it's a lot faster than the time casts and then time comparisons
return (file1)->metadata.get("releasedate") < (file2)->metadata.get("releasedate");
}
bool compareReleaseDate(const FileData* file1, const FileData* file2)
{
// Since it's stored as an ISO string (YYYYMMDDTHHMMSS), we can compare as a string
// which is a lot faster than the time casts and the time comparisons.
return (file1)->metadata.get("releasedate") < (file2)->metadata.get("releasedate");
}
bool compareGenre(const FileData* file1, const FileData* file2)
{
std::string genre1 = Utils::String::toUpper(file1->metadata.get("genre"));
std::string genre2 = Utils::String::toUpper(file2->metadata.get("genre"));
return genre1.compare(genre2) < 0;
}
bool compareGenre(const FileData* file1, const FileData* file2)
{
std::string genre1 = Utils::String::toUpper(file1->metadata.get("genre"));
std::string genre2 = Utils::String::toUpper(file2->metadata.get("genre"));
return genre1.compare(genre2) < 0;
}
bool compareDeveloper(const FileData* file1, const FileData* file2)
{
std::string developer1 = Utils::String::toUpper(file1->metadata.get("developer"));
std::string developer2 = Utils::String::toUpper(file2->metadata.get("developer"));
return developer1.compare(developer2) < 0;
}
bool compareDeveloper(const FileData* file1, const FileData* file2)
{
std::string developer1 = Utils::String::toUpper(file1->metadata.get("developer"));
std::string developer2 = Utils::String::toUpper(file2->metadata.get("developer"));
return developer1.compare(developer2) < 0;
}
bool comparePublisher(const FileData* file1, const FileData* file2)
{
std::string publisher1 = Utils::String::toUpper(file1->metadata.get("publisher"));
std::string publisher2 = Utils::String::toUpper(file2->metadata.get("publisher"));
return publisher1.compare(publisher2) < 0;
}
bool comparePublisher(const FileData* file1, const FileData* file2)
{
std::string publisher1 = Utils::String::toUpper(file1->metadata.get("publisher"));
std::string publisher2 = Utils::String::toUpper(file2->metadata.get("publisher"));
return publisher1.compare(publisher2) < 0;
}
bool compareSystem(const FileData* file1, const FileData* file2)
{
std::string system1 = Utils::String::toUpper(file1->getSystemName());
std::string system2 = Utils::String::toUpper(file2->getSystemName());
return system1.compare(system2) < 0;
}
bool compareSystem(const FileData* file1, const FileData* file2)
{
std::string system1 = Utils::String::toUpper(file1->getSystemName());
std::string system2 = Utils::String::toUpper(file2->getSystemName());
return system1.compare(system2) < 0;
}
};

View file

@ -1,3 +1,10 @@
//
// FileSorts.h
//
// Gamelist sorting functions.
// Actual sorting takes place in FileData.
//
#pragma once
#ifndef ES_APP_FILE_SORTS_H
#define ES_APP_FILE_SORTS_H
@ -7,18 +14,18 @@
namespace FileSorts
{
bool compareName(const FileData* file1, const FileData* file2);
bool compareRating(const FileData* file1, const FileData* file2);
bool compareTimesPlayed(const FileData* file1, const FileData* fil2);
bool compareLastPlayed(const FileData* file1, const FileData* file2);
bool compareNumPlayers(const FileData* file1, const FileData* file2);
bool compareReleaseDate(const FileData* file1, const FileData* file2);
bool compareGenre(const FileData* file1, const FileData* file2);
bool compareDeveloper(const FileData* file1, const FileData* file2);
bool comparePublisher(const FileData* file1, const FileData* file2);
bool compareSystem(const FileData* file1, const FileData* file2);
bool compareName(const FileData* file1, const FileData* file2);
bool compareRating(const FileData* file1, const FileData* file2);
bool compareTimesPlayed(const FileData* file1, const FileData* fil2);
bool compareLastPlayed(const FileData* file1, const FileData* file2);
bool compareNumPlayers(const FileData* file1, const FileData* file2);
bool compareReleaseDate(const FileData* file1, const FileData* file2);
bool compareGenre(const FileData* file1, const FileData* file2);
bool compareDeveloper(const FileData* file1, const FileData* file2);
bool comparePublisher(const FileData* file1, const FileData* file2);
bool compareSystem(const FileData* file1, const FileData* file2);
extern const std::vector<FileData::SortType> SortTypes;
extern const std::vector<FileData::SortType> SortTypes;
};
#endif // ES_APP_FILE_SORTS_H

View file

@ -88,7 +88,6 @@ MetaDataList MetaDataList::createFromXML(MetaDataListType type,
mdl.set(iter->key, iter->defaultValue);
}
}
return mdl;
}

View file

@ -71,8 +71,6 @@ public:
// An example will be written if the file doesn't exist.
static bool loadConfig();
static void writeExampleConfig(const std::string& path);
// If forWrite, will only return ~/.emulationstation/es_systems.cfg,
// never /etc/emulationstation/es_systems.cfg.
static std::string getConfigPath(bool forWrite);
static std::vector<SystemData*> sSystemVector;

View file

@ -1,3 +1,10 @@
//
// GuiCollectionSystemsOptions.cpp
//
// User interface for the game collection settings.
// Submenu to the GuiMenu main menu.
//
#include "guis/GuiCollectionSystemsOptions.h"
#include "components/OptionListComponent.h"
@ -10,228 +17,237 @@
#include "SystemData.h"
#include "Window.h"
GuiCollectionSystemsOptions::GuiCollectionSystemsOptions(Window* window) : GuiComponent(window), mMenu(window, "GAME COLLECTION SETTINGS")
GuiCollectionSystemsOptions::GuiCollectionSystemsOptions(Window* window)
: GuiComponent(window), mMenu(window, "GAME COLLECTION SETTINGS")
{
initializeMenu();
initializeMenu();
}
void GuiCollectionSystemsOptions::initializeMenu()
{
addChild(&mMenu);
addChild(&mMenu);
// get collections
// Get collections.
addSystemsToMenu();
addSystemsToMenu();
// Add "Create New Custom Collection from Theme".
std::vector<std::string> unusedFolders =
CollectionSystemManager::get()->getUnusedSystemsFromTheme();
if (unusedFolders.size() > 0) {
addEntry("CREATE NEW CUSTOM COLLECTION FROM THEME", 0x777777FF, true,
[this, unusedFolders] {
auto s = new GuiSettings(mWindow, "SELECT THEME FOLDER");
std::shared_ptr< OptionListComponent<std::string>>
folderThemes = std::make_shared< OptionListComponent<std::string>>
(mWindow, getHelpStyle(), "SELECT THEME FOLDER", true);
// add "Create New Custom Collection from Theme"
// Add custom systems.
for(auto it = unusedFolders.cbegin() ; it != unusedFolders.cend() ; it++ ) {
ComponentListRow row;
std::string name = *it;
std::vector<std::string> unusedFolders = CollectionSystemManager::get()->getUnusedSystemsFromTheme();
if (unusedFolders.size() > 0)
{
addEntry("CREATE NEW CUSTOM COLLECTION FROM THEME", 0x777777FF, true,
[this, unusedFolders] {
auto s = new GuiSettings(mWindow, "SELECT THEME FOLDER");
std::shared_ptr< OptionListComponent<std::string>>
folderThemes = std::make_shared< OptionListComponent<std::string>>
(mWindow, getHelpStyle(), "SELECT THEME FOLDER", true);
std::function<void()> createCollectionCall = [name, this, s] {
createCollection(name);
};
row.makeAcceptInputHandler(createCollectionCall);
// add Custom Systems
for(auto it = unusedFolders.cbegin() ; it != unusedFolders.cend() ; it++ )
{
ComponentListRow row;
std::string name = *it;
auto themeFolder = std::make_shared<TextComponent>(mWindow,
Utils::String::toUpper(name), Font::get(FONT_SIZE_SMALL), 0x777777FF);
row.addElement(themeFolder, true);
s->addRow(row);
}
mWindow->pushGui(s);
});
}
std::function<void()> createCollectionCall = [name, this, s] {
createCollection(name);
};
row.makeAcceptInputHandler(createCollectionCall);
ComponentListRow row;
row.addElement(std::make_shared<TextComponent>(mWindow,
"CREATE NEW CUSTOM COLLECTION", Font::get(FONT_SIZE_MEDIUM), 0x777777FF), true);
auto bracket = std::make_shared<ImageComponent>(mWindow);
bracket->setImage(":/graphics/arrow.svg");
bracket->setResize(Vector2f(0, Font::get(FONT_SIZE_MEDIUM)->getLetterHeight()));
row.addElement(bracket, false);
auto createCustomCollection = [this](const std::string& newVal) {
std::string name = newVal;
// We need to store the first GUI and remove it, as it'll
// be deleted by the actual GUI.
Window* window = mWindow;
GuiComponent* topGui = window->peekGui();
window->removeGui(topGui);
createCollection(name);
};
row.makeAcceptInputHandler([this, createCustomCollection] {
mWindow->pushGui(new GuiTextEditPopup(mWindow, getHelpStyle(),
"New Collection Name", "", createCustomCollection, false, "SAVE"));
});
auto themeFolder = std::make_shared<TextComponent>(mWindow, Utils::String::toUpper(name), Font::get(FONT_SIZE_SMALL), 0x777777FF);
row.addElement(themeFolder, true);
s->addRow(row);
}
mWindow->pushGui(s);
});
}
mMenu.addRow(row);
ComponentListRow row;
row.addElement(std::make_shared<TextComponent>(mWindow, "CREATE NEW CUSTOM COLLECTION", Font::get(FONT_SIZE_MEDIUM), 0x777777FF), true);
auto bracket = std::make_shared<ImageComponent>(mWindow);
bracket->setImage(":/graphics/arrow.svg");
bracket->setResize(Vector2f(0, Font::get(FONT_SIZE_MEDIUM)->getLetterHeight()));
row.addElement(bracket, false);
auto createCustomCollection = [this](const std::string& newVal) {
std::string name = newVal;
// we need to store the first Gui and remove it, as it'll be deleted by the actual Gui
Window* window = mWindow;
GuiComponent* topGui = window->peekGui();
window->removeGui(topGui);
createCollection(name);
};
row.makeAcceptInputHandler([this, createCustomCollection] {
mWindow->pushGui(new GuiTextEditPopup(mWindow, getHelpStyle(), "New Collection Name", "", createCustomCollection, false, "SAVE"));
});
sortFavFirstCustomSwitch = std::make_shared<SwitchComponent>(mWindow);
sortFavFirstCustomSwitch->setState(Settings::getInstance()->getBool("FavFirstCustom"));
mMenu.addWithLabel("SORT FAVORITES ON TOP FOR CUSTOM COLLECTIONS", sortFavFirstCustomSwitch);
mMenu.addRow(row);
bundleCustomCollections = std::make_shared<SwitchComponent>(mWindow);
bundleCustomCollections->setState(Settings::getInstance()->
getBool("UseCustomCollectionsSystem"));
mMenu.addWithLabel("GROUP UNTHEMED CUSTOM COLLECTIONS", bundleCustomCollections);
sortFavFirstCustomSwitch = std::make_shared<SwitchComponent>(mWindow);
sortFavFirstCustomSwitch->setState(Settings::getInstance()->getBool("FavFirstCustom"));
mMenu.addWithLabel("SORT FAVORITES ON TOP FOR CUSTOM COLLECTIONS", sortFavFirstCustomSwitch);
toggleSystemNameInCollections = std::make_shared<SwitchComponent>(mWindow);
toggleSystemNameInCollections->setState(Settings::getInstance()->
getBool("CollectionShowSystemInfo"));
mMenu.addWithLabel("SHOW SYSTEM NAMES IN COLLECTIONS", toggleSystemNameInCollections);
bundleCustomCollections = std::make_shared<SwitchComponent>(mWindow);
bundleCustomCollections->setState(Settings::getInstance()->getBool("UseCustomCollectionsSystem"));
mMenu.addWithLabel("GROUP UNTHEMED CUSTOM COLLECTIONS", bundleCustomCollections);
if(CollectionSystemManager::get()->isEditing()) {
row.elements.clear();
row.addElement(std::make_shared<TextComponent>(mWindow, "FINISH EDITING '" +
Utils::String::toUpper(CollectionSystemManager::get()->getEditingCollection()) +
"' COLLECTION", Font::get(FONT_SIZE_MEDIUM), 0x777777FF), true);
row.makeAcceptInputHandler(std::bind(&GuiCollectionSystemsOptions::exitEditMode, this));
mMenu.addRow(row);
}
toggleSystemNameInCollections = std::make_shared<SwitchComponent>(mWindow);
toggleSystemNameInCollections->setState(Settings::getInstance()->getBool("CollectionShowSystemInfo"));
mMenu.addWithLabel("SHOW SYSTEM NAMES IN COLLECTIONS", toggleSystemNameInCollections);
if(CollectionSystemManager::get()->isEditing())
{
row.elements.clear();
row.addElement(std::make_shared<TextComponent>(mWindow, "FINISH EDITING '" + Utils::String::toUpper(CollectionSystemManager::get()->getEditingCollection()) + "' COLLECTION", Font::get(FONT_SIZE_MEDIUM), 0x777777FF), true);
row.makeAcceptInputHandler(std::bind(&GuiCollectionSystemsOptions::exitEditMode, this));
mMenu.addRow(row);
}
mMenu.addButton("BACK", "back", std::bind(&GuiCollectionSystemsOptions::applySettings, this));
mMenu.setPosition((Renderer::getScreenWidth() - mMenu.getSize().x()) / 2, Renderer::getScreenHeight() * 0.15f);
mMenu.addButton("BACK", "back", std::bind(&GuiCollectionSystemsOptions::applySettings, this));
mMenu.setPosition((Renderer::getScreenWidth() - mMenu.getSize().x()) / 2,
Renderer::getScreenHeight() * 0.15f);
}
void GuiCollectionSystemsOptions::addEntry(const char* name, unsigned int color, bool add_arrow, const std::function<void()>& func)
void GuiCollectionSystemsOptions::addEntry(const char* name, unsigned int color,
bool add_arrow, const std::function<void()>& func)
{
std::shared_ptr<Font> font = Font::get(FONT_SIZE_MEDIUM);
std::shared_ptr<Font> font = Font::get(FONT_SIZE_MEDIUM);
// populate the list
ComponentListRow row;
row.addElement(std::make_shared<TextComponent>(mWindow, name, font, color), true);
// Populate the list.
ComponentListRow row;
row.addElement(std::make_shared<TextComponent>(mWindow, name, font, color), true);
if(add_arrow)
{
std::shared_ptr<ImageComponent> bracket = makeArrow(mWindow);
row.addElement(bracket, false);
}
if(add_arrow) {
std::shared_ptr<ImageComponent> bracket = makeArrow(mWindow);
row.addElement(bracket, false);
}
row.makeAcceptInputHandler(func);
mMenu.addRow(row);
row.makeAcceptInputHandler(func);
mMenu.addRow(row);
}
void GuiCollectionSystemsOptions::createCollection(std::string inName) {
std::string name = CollectionSystemManager::get()->getValidNewCollectionName(inName);
SystemData* newSys = CollectionSystemManager::get()->addNewCustomCollection(name);
customOptionList->add(name, name, true);
std::string outAuto = Utils::String::vectorToCommaString(autoOptionList->getSelectedObjects());
std::string outCustom = Utils::String::vectorToCommaString(customOptionList->getSelectedObjects());
updateSettings(outAuto, outCustom);
ViewController::get()->goToSystemView(newSys);
std::string name = CollectionSystemManager::get()->getValidNewCollectionName(inName);
SystemData* newSys = CollectionSystemManager::get()->addNewCustomCollection(name);
customOptionList->add(name, name, true);
std::string outAuto = Utils::String::vectorToCommaString(
autoOptionList->getSelectedObjects());
std::string outCustom = Utils::String::vectorToCommaString(
customOptionList->getSelectedObjects());
updateSettings(outAuto, outCustom);
ViewController::get()->goToSystemView(newSys);
Window* window = mWindow;
CollectionSystemManager::get()->setEditMode(name);
while(window->peekGui() && window->peekGui() != ViewController::get())
delete window->peekGui();
return;
Window* window = mWindow;
CollectionSystemManager::get()->setEditMode(name);
while(window->peekGui() && window->peekGui() != ViewController::get())
delete window->peekGui();
return;
}
void GuiCollectionSystemsOptions::exitEditMode()
{
CollectionSystemManager::get()->exitEditMode();
applySettings();
CollectionSystemManager::get()->exitEditMode();
applySettings();
}
GuiCollectionSystemsOptions::~GuiCollectionSystemsOptions()
{
}
void GuiCollectionSystemsOptions::addSystemsToMenu()
{
std::map<std::string, CollectionSystemData> autoSystems =
CollectionSystemManager::get()->getAutoCollectionSystems();
std::map<std::string, CollectionSystemData> autoSystems = CollectionSystemManager::get()->getAutoCollectionSystems();
autoOptionList = std::make_shared<OptionListComponent<std::string>>
(mWindow, getHelpStyle(), "SELECT COLLECTIONS", true);
autoOptionList = std::make_shared< OptionListComponent<std::string> >(mWindow, getHelpStyle(), "SELECT COLLECTIONS", true);
// Add automatic systems.
for(std::map<std::string, CollectionSystemData>::const_iterator it = autoSystems.cbegin();
it != autoSystems.cend() ; it++ )
autoOptionList->add(it->second.decl.longName, it->second.decl.name, it->second.isEnabled);
mMenu.addWithLabel("AUTOMATIC GAME COLLECTIONS", autoOptionList);
// add Auto Systems
for(std::map<std::string, CollectionSystemData>::const_iterator it = autoSystems.cbegin() ; it != autoSystems.cend() ; it++ )
{
autoOptionList->add(it->second.decl.longName, it->second.decl.name, it->second.isEnabled);
}
mMenu.addWithLabel("AUTOMATIC GAME COLLECTIONS", autoOptionList);
std::map<std::string, CollectionSystemData> customSystems =
CollectionSystemManager::get()->getCustomCollectionSystems();
std::map<std::string, CollectionSystemData> customSystems = CollectionSystemManager::get()->getCustomCollectionSystems();
customOptionList = std::make_shared<OptionListComponent<std::string>>
(mWindow, getHelpStyle(), "SELECT COLLECTIONS", true);
customOptionList = std::make_shared< OptionListComponent<std::string> >(mWindow, getHelpStyle(), "SELECT COLLECTIONS", true);
// add Custom Systems
for(std::map<std::string, CollectionSystemData>::const_iterator it = customSystems.cbegin() ; it != customSystems.cend() ; it++ )
{
customOptionList->add(it->second.decl.longName, it->second.decl.name, it->second.isEnabled);
}
mMenu.addWithLabel("CUSTOM GAME COLLECTIONS", customOptionList);
// Add custom systems.
for(std::map<std::string, CollectionSystemData>::const_iterator it = customSystems.cbegin();
it != customSystems.cend() ; it++ )
customOptionList->add(it->second.decl.longName, it->second.decl.name, it->second.isEnabled);
mMenu.addWithLabel("CUSTOM GAME COLLECTIONS", customOptionList);
}
void GuiCollectionSystemsOptions::applySettings()
{
std::string outAuto = Utils::String::vectorToCommaString(autoOptionList->getSelectedObjects());
std::string prevAuto = Settings::getInstance()->getString("CollectionSystemsAuto");
std::string outCustom = Utils::String::vectorToCommaString(customOptionList->getSelectedObjects());
std::string prevCustom = Settings::getInstance()->getString("CollectionSystemsCustom");
bool outSort = sortFavFirstCustomSwitch->getState();
bool prevSort = Settings::getInstance()->getBool("FavFirstCustom");
bool outBundle = bundleCustomCollections->getState();
bool prevBundle = Settings::getInstance()->getBool("UseCustomCollectionsSystem");
bool prevShow = Settings::getInstance()->getBool("CollectionShowSystemInfo");
bool outShow = toggleSystemNameInCollections->getState();
bool needUpdateSettings = prevAuto != outAuto || prevCustom != outCustom || outSort != prevSort || outBundle != prevBundle || prevShow != outShow ;
if (needUpdateSettings)
{
updateSettings(outAuto, outCustom);
}
std::string outAuto = Utils::String::vectorToCommaString(
autoOptionList->getSelectedObjects());
std::string prevAuto = Settings::getInstance()->getString("CollectionSystemsAuto");
std::string outCustom = Utils::String::vectorToCommaString(
customOptionList->getSelectedObjects());
std::string prevCustom = Settings::getInstance()->getString("CollectionSystemsCustom");
bool outSort = sortFavFirstCustomSwitch->getState();
bool prevSort = Settings::getInstance()->getBool("FavFirstCustom");
bool outBundle = bundleCustomCollections->getState();
bool prevBundle = Settings::getInstance()->getBool("UseCustomCollectionsSystem");
bool prevShow = Settings::getInstance()->getBool("CollectionShowSystemInfo");
bool outShow = toggleSystemNameInCollections->getState();
bool needUpdateSettings = prevAuto != outAuto || prevCustom != outCustom || outSort !=
prevSort || outBundle != prevBundle || prevShow != outShow ;
delete this;
if (needUpdateSettings)
updateSettings(outAuto, outCustom);
delete this;
}
void GuiCollectionSystemsOptions::updateSettings(std::string newAutoSettings, std::string newCustomSettings)
void GuiCollectionSystemsOptions::updateSettings(std::string newAutoSettings,
std::string newCustomSettings)
{
Settings::getInstance()->setString("CollectionSystemsAuto", newAutoSettings);
Settings::getInstance()->setString("CollectionSystemsCustom", newCustomSettings);
Settings::getInstance()->setBool("FavFirstCustom", sortFavFirstCustomSwitch->getState());
Settings::getInstance()->setBool("UseCustomCollectionsSystem", bundleCustomCollections->getState());
Settings::getInstance()->setBool("CollectionShowSystemInfo", toggleSystemNameInCollections->getState());
Settings::getInstance()->saveFile();
CollectionSystemManager::get()->loadEnabledListFromSettings();
CollectionSystemManager::get()->updateSystemsList();
ViewController::get()->goToStart();
ViewController::get()->reloadAll();
Settings::getInstance()->setString("CollectionSystemsAuto", newAutoSettings);
Settings::getInstance()->setString("CollectionSystemsCustom", newCustomSettings);
Settings::getInstance()->setBool("FavFirstCustom", sortFavFirstCustomSwitch->getState());
Settings::getInstance()->setBool("UseCustomCollectionsSystem",
bundleCustomCollections->getState());
Settings::getInstance()->setBool("CollectionShowSystemInfo",
toggleSystemNameInCollections->getState());
Settings::getInstance()->saveFile();
CollectionSystemManager::get()->loadEnabledListFromSettings();
CollectionSystemManager::get()->updateSystemsList();
ViewController::get()->goToStart();
ViewController::get()->reloadAll();
}
bool GuiCollectionSystemsOptions::input(InputConfig* config, Input input)
{
bool consumed = GuiComponent::input(config, input);
if(consumed)
return true;
bool consumed = GuiComponent::input(config, input);
if(config->isMappedTo("b", input) && input.value != 0)
{
applySettings();
}
if(consumed)
return true;
if(config->isMappedTo("b", input) && input.value != 0)
applySettings();
return false;
return false;
}
std::vector<HelpPrompt> GuiCollectionSystemsOptions::getHelpPrompts()
{
std::vector<HelpPrompt> prompts = mMenu.getHelpPrompts();
prompts.push_back(HelpPrompt("a", "select"));
prompts.push_back(HelpPrompt("b", "back"));
return prompts;
std::vector<HelpPrompt> prompts = mMenu.getHelpPrompts();
prompts.push_back(HelpPrompt("a", "select"));
prompts.push_back(HelpPrompt("b", "back"));
return prompts;
}
HelpStyle GuiCollectionSystemsOptions::getHelpStyle()
{
HelpStyle style = HelpStyle();
style.applyTheme(ViewController::get()->getState().getSystem()->getTheme(), "system");
return style;
HelpStyle style = HelpStyle();
style.applyTheme(ViewController::get()->getState().getSystem()->getTheme(), "system");
return style;
}

View file

@ -1,3 +1,10 @@
//
// GuiCollectionSystemsOptions.h
//
// User interface for the game collection settings.
// Submenu to the GuiMenu main menu.
//
#pragma once
#ifndef ES_APP_GUIS_GUI_COLLECTION_SYSTEM_OPTIONS_H
#define ES_APP_GUIS_GUI_COLLECTION_SYSTEM_OPTIONS_H
@ -12,28 +19,29 @@ class SystemData;
class GuiCollectionSystemsOptions : public GuiComponent
{
public:
GuiCollectionSystemsOptions(Window* window);
~GuiCollectionSystemsOptions();
bool input(InputConfig* config, Input input) override;
GuiCollectionSystemsOptions(Window* window);
~GuiCollectionSystemsOptions();
bool input(InputConfig* config, Input input) override;
virtual std::vector<HelpPrompt> getHelpPrompts() override;
HelpStyle getHelpStyle() override;
virtual std::vector<HelpPrompt> getHelpPrompts() override;
HelpStyle getHelpStyle() override;
private:
void initializeMenu();
void applySettings();
void addSystemsToMenu();
void addEntry(const char* name, unsigned int color, bool add_arrow, const std::function<void()>& func);
void updateSettings(std::string newAutoSettings, std::string newCustomSettings);
void createCollection(std::string inName);
void exitEditMode();
std::shared_ptr< OptionListComponent<std::string> > autoOptionList;
std::shared_ptr< OptionListComponent<std::string> > customOptionList;
std::shared_ptr<SwitchComponent> bundleCustomCollections;
std::shared_ptr<SwitchComponent> sortFavFirstCustomSwitch;
std::shared_ptr<SwitchComponent> toggleSystemNameInCollections;
MenuComponent mMenu;
SystemData* mSystem;
void initializeMenu();
void applySettings();
void addSystemsToMenu();
void addEntry(const char* name, unsigned int color,
bool add_arrow, const std::function<void()>& func);
void updateSettings(std::string newAutoSettings, std::string newCustomSettings);
void createCollection(std::string inName);
void exitEditMode();
std::shared_ptr< OptionListComponent<std::string> > autoOptionList;
std::shared_ptr< OptionListComponent<std::string> > customOptionList;
std::shared_ptr<SwitchComponent> bundleCustomCollections;
std::shared_ptr<SwitchComponent> sortFavFirstCustomSwitch;
std::shared_ptr<SwitchComponent> toggleSystemNameInCollections;
MenuComponent mMenu;
SystemData* mSystem;
};
#endif // ES_APP_GUIS_GUI_COLLECTION_SYSTEM_OPTIONS_H

View file

@ -1,3 +1,11 @@
//
// GuiGeneralScreensaverOptions.cpp
//
// User interface for the screensaver options.
// Based on the GuiScreenSaverOptions template.
// Submenu to the GuiMenu main menu.
//
#include "guis/GuiGeneralScreensaverOptions.h"
#include "components/OptionListComponent.h"
@ -8,58 +16,73 @@
#include "guis/GuiVideoScreensaverOptions.h"
#include "Settings.h"
GuiGeneralScreensaverOptions::GuiGeneralScreensaverOptions(Window* window, const char* title) : GuiScreensaverOptions(window, title)
GuiGeneralScreensaverOptions::GuiGeneralScreensaverOptions(Window* window, const char* title)
: GuiScreensaverOptions(window, title)
{
// screensaver time
auto screensaver_time = std::make_shared<SliderComponent>(mWindow, 0.f, 30.f, 1.f, "m");
screensaver_time->setValue((float)(Settings::getInstance()->getInt("ScreenSaverTime") / (1000 * 60)));
addWithLabel("SCREENSAVER AFTER", screensaver_time);
addSaveFunc([screensaver_time] {
Settings::getInstance()->setInt("ScreenSaverTime", (int)Math::round(screensaver_time->getValue()) * (1000 * 60));
PowerSaver::updateTimeouts();
});
// Screensaver time.
auto screensaver_time = std::make_shared<SliderComponent>(mWindow, 0.f, 30.f, 1.f, "m");
screensaver_time->setValue((float)(Settings::getInstance()->
getInt("ScreenSaverTime") / (1000 * 60)));
addWithLabel("SCREENSAVER AFTER", screensaver_time);
addSaveFunc([screensaver_time] {
Settings::getInstance()->setInt("ScreenSaverTime",
(int)Math::round(screensaver_time->getValue()) * (1000 * 60));
PowerSaver::updateTimeouts();
});
// Allow ScreenSaver Controls - ScreenSaverControls
auto ss_controls = std::make_shared<SwitchComponent>(mWindow);
ss_controls->setState(Settings::getInstance()->getBool("ScreenSaverControls"));
addWithLabel("SCREENSAVER CONTROLS", ss_controls);
addSaveFunc([ss_controls] { Settings::getInstance()->setBool("ScreenSaverControls", ss_controls->getState()); });
// Allow ScreenSaver Controls - ScreenSaverControls.
auto ss_controls = std::make_shared<SwitchComponent>(mWindow);
ss_controls->setState(Settings::getInstance()->getBool("ScreenSaverControls"));
addWithLabel("SCREENSAVER CONTROLS", ss_controls);
addSaveFunc([ss_controls] { Settings::getInstance()->setBool("ScreenSaverControls",
ss_controls->getState()); });
// screensaver behavior
auto screensaver_behavior = std::make_shared< OptionListComponent<std::string> >(mWindow, getHelpStyle(), "SCREENSAVER BEHAVIOR", false);
std::vector<std::string> screensavers;
screensavers.push_back("dim");
screensavers.push_back("black");
screensavers.push_back("random video");
screensavers.push_back("slideshow");
for(auto it = screensavers.cbegin(); it != screensavers.cend(); it++)
screensaver_behavior->add(*it, *it, Settings::getInstance()->getString("ScreenSaverBehavior") == *it);
addWithLabel("SCREENSAVER BEHAVIOR", screensaver_behavior);
addSaveFunc([this, screensaver_behavior] {
if (Settings::getInstance()->getString("ScreenSaverBehavior") != "random video" && screensaver_behavior->getSelected() == "random video") {
// if before it wasn't risky but now there's a risk of problems, show warning
mWindow->pushGui(new GuiMsgBox(mWindow, getHelpStyle(),
"The \"Random Video\" screensaver shows videos from your gamelist.\n\nIf you do not have videos, or if in several consecutive attempts the games it selects don't have videos it will default to black.\n\nMore options in the \"UI Settings\" > \"Video Screensaver\" menu.",
"OK", [] { return; }));
}
Settings::getInstance()->setString("ScreenSaverBehavior", screensaver_behavior->getSelected());
PowerSaver::updateTimeouts();
});
// Screensaver behavior.
auto screensaver_behavior = std::make_shared<OptionListComponent<std::string>>
(mWindow, getHelpStyle(), "SCREENSAVER BEHAVIOR", false);
std::vector<std::string> screensavers;
screensavers.push_back("dim");
screensavers.push_back("black");
screensavers.push_back("random video");
screensavers.push_back("slideshow");
for(auto it = screensavers.cbegin(); it != screensavers.cend(); it++)
screensaver_behavior->add(*it, *it, Settings::getInstance()->
getString("ScreenSaverBehavior") == *it);
addWithLabel("SCREENSAVER BEHAVIOR", screensaver_behavior);
addSaveFunc([this, screensaver_behavior] {
if (Settings::getInstance()->getString("ScreenSaverBehavior") !=
"random video" && screensaver_behavior->getSelected() == "random video") {
// If before it wasn't risky but now there's a risk of problems, show warning.
mWindow->pushGui(new GuiMsgBox(mWindow, getHelpStyle(),
"THE \"RANDOM VIDEO\" SCREENSAVER SHOWS\nVIDEOS FROM YOUR GAMELISTS.\n\nIF YOU DO NOT "
"HAVE ANY VIDEOS, THE SCREENSAVER\nWILL DEFAULT TO \"BLACK\".\n\nSEE MORE "
"OPTIONS IN THE MENU \"UI SETTINGS\" >\n\"SCREENSAVER SETTINGS\" > "
"\"VIDEO SCREENSAVER SETTINGS\".",
"OK", [] { return; }));
}
Settings::getInstance()->setString("ScreenSaverBehavior",
screensaver_behavior->getSelected());
PowerSaver::updateTimeouts();
});
ComponentListRow row;
ComponentListRow row;
// show filtered menu
row.elements.clear();
row.addElement(std::make_shared<TextComponent>(mWindow, "VIDEO SCREENSAVER SETTINGS", Font::get(FONT_SIZE_MEDIUM), 0x777777FF), true);
row.addElement(makeArrow(mWindow), false);
row.makeAcceptInputHandler(std::bind(&GuiGeneralScreensaverOptions::openVideoScreensaverOptions, this));
addRow(row);
// Show filtered menu.
row.elements.clear();
row.addElement(std::make_shared<TextComponent>(mWindow,
"VIDEO SCREENSAVER SETTINGS", Font::get(FONT_SIZE_MEDIUM), 0x777777FF), true);
row.addElement(makeArrow(mWindow), false);
row.makeAcceptInputHandler(std::bind(
&GuiGeneralScreensaverOptions::openVideoScreensaverOptions, this));
addRow(row);
row.elements.clear();
row.addElement(std::make_shared<TextComponent>(mWindow, "SLIDESHOW SCREENSAVER SETTINGS", Font::get(FONT_SIZE_MEDIUM), 0x777777FF), true);
row.addElement(makeArrow(mWindow), false);
row.makeAcceptInputHandler(std::bind(&GuiGeneralScreensaverOptions::openSlideshowScreensaverOptions, this));
addRow(row);
row.elements.clear();
row.addElement(std::make_shared<TextComponent>(mWindow,
"SLIDESHOW SCREENSAVER SETTINGS", Font::get(FONT_SIZE_MEDIUM), 0x777777FF), true);
row.addElement(makeArrow(mWindow), false);
row.makeAcceptInputHandler(std::bind(
&GuiGeneralScreensaverOptions::openSlideshowScreensaverOptions, this));
addRow(row);
}
GuiGeneralScreensaverOptions::~GuiGeneralScreensaverOptions()
@ -67,10 +90,9 @@ GuiGeneralScreensaverOptions::~GuiGeneralScreensaverOptions()
}
void GuiGeneralScreensaverOptions::openVideoScreensaverOptions() {
mWindow->pushGui(new GuiVideoScreensaverOptions(mWindow, "VIDEO SCREENSAVER"));
mWindow->pushGui(new GuiVideoScreensaverOptions(mWindow, "VIDEO SCREENSAVER"));
}
void GuiGeneralScreensaverOptions::openSlideshowScreensaverOptions() {
mWindow->pushGui(new GuiSlideshowScreensaverOptions(mWindow, "SLIDESHOW SCREENSAVER"));
}

View file

@ -1,3 +1,11 @@
//
// GuiGeneralScreensaverOptions.h
//
// User interface for the screensaver options.
// Based on the GuiScreenSaverOptions template.
// Submenu to the GuiMenu main menu.
//
#pragma once
#ifndef ES_APP_GUIS_GUI_GENERAL_SCREENSAVER_OPTIONS_H
#define ES_APP_GUIS_GUI_GENERAL_SCREENSAVER_OPTIONS_H
@ -7,12 +15,12 @@
class GuiGeneralScreensaverOptions : public GuiScreensaverOptions
{
public:
GuiGeneralScreensaverOptions(Window* window, const char* title);
virtual ~GuiGeneralScreensaverOptions();
GuiGeneralScreensaverOptions(Window* window, const char* title);
virtual ~GuiGeneralScreensaverOptions();
private:
void openVideoScreensaverOptions();
void openSlideshowScreensaverOptions();
void openVideoScreensaverOptions();
void openSlideshowScreensaverOptions();
};
#endif // ES_APP_GUIS_GUI_GENERAL_SCREENSAVER_OPTIONS_H

View file

@ -1,3 +1,9 @@
//
// GuiInfoPopup.cpp
//
// Popup window used for user notifications.
//
#include "guis/GuiInfoPopup.h"
#include "components/ComponentGrid.h"
@ -5,112 +11,108 @@
#include "components/TextComponent.h"
#include <SDL_timer.h>
GuiInfoPopup::GuiInfoPopup(Window* window, std::string message, int duration) :
GuiComponent(window), mMessage(message), mDuration(duration), running(true)
GuiInfoPopup::GuiInfoPopup(
Window* window,
std::string message,
int duration)
: GuiComponent(window),
mMessage(message),
mDuration(duration),
running(true)
{
mFrame = new NinePatchComponent(window);
float maxWidth = Renderer::getScreenWidth() * 0.9f;
float maxHeight = Renderer::getScreenHeight() * 0.2f;
mFrame = new NinePatchComponent(window);
float maxWidth = Renderer::getScreenWidth() * 0.9f;
float maxHeight = Renderer::getScreenHeight() * 0.2f;
std::shared_ptr<TextComponent> s = std::make_shared<TextComponent>(mWindow,
"",
Font::get(FONT_SIZE_MINI),
0x444444FF,
ALIGN_CENTER);
std::shared_ptr<TextComponent> s = std::make_shared<TextComponent>(mWindow, "",
Font::get(FONT_SIZE_MINI), 0x444444FF, ALIGN_CENTER);
// we do this to force the text container to resize and return an actual expected popup size
s->setSize(0,0);
s->setText(message);
mSize = s->getSize();
// We do this to force the text container to resize and return the actual expected popup size.
s->setSize(0,0);
s->setText(message);
mSize = s->getSize();
// confirm the size isn't larger than the screen width, otherwise cap it
if (mSize.x() > maxWidth) {
s->setSize(maxWidth, mSize[1]);
mSize[0] = maxWidth;
}
if (mSize.y() > maxHeight) {
s->setSize(mSize[0], maxHeight);
mSize[1] = maxHeight;
}
// Confirm that the size isn't larger than the screen width, otherwise cap it.
if (mSize.x() > maxWidth) {
s->setSize(maxWidth, mSize[1]);
mSize[0] = maxWidth;
}
if (mSize.y() > maxHeight) {
s->setSize(mSize[0], maxHeight);
mSize[1] = maxHeight;
}
// add a padding to the box
int paddingX = (int) (Renderer::getScreenWidth() * 0.03f);
int paddingY = (int) (Renderer::getScreenHeight() * 0.02f);
mSize[0] = mSize.x() + paddingX;
mSize[1] = mSize.y() + paddingY;
// Add a padding to the box.
int paddingX = (int) (Renderer::getScreenWidth() * 0.03f);
int paddingY = (int) (Renderer::getScreenHeight() * 0.02f);
mSize[0] = mSize.x() + paddingX;
mSize[1] = mSize.y() + paddingY;
float posX = Renderer::getScreenWidth()*0.5f - mSize.x()*0.5f;
float posY = Renderer::getScreenHeight() * 0.02f;
float posX = Renderer::getScreenWidth()*0.5f - mSize.x()*0.5f;
float posY = Renderer::getScreenHeight() * 0.02f;
setPosition(posX, posY, 0);
setPosition(posX, posY, 0);
mFrame->setImagePath(":/graphics/frame.png");
mFrame->fitTo(mSize, Vector3f::Zero(), Vector2f(-32, -32));
addChild(mFrame);
mFrame->setImagePath(":/graphics/frame.png");
mFrame->fitTo(mSize, Vector3f::Zero(), Vector2f(-32, -32));
addChild(mFrame);
// we only init the actual time when we first start to render
mStartTime = 0;
// We only initialize the actual time when we first start to render.
mStartTime = 0;
mGrid = new ComponentGrid(window, Vector2i(1, 3));
mGrid->setSize(mSize);
mGrid->setEntry(s, Vector2i(0, 1), false, true);
addChild(mGrid);
mGrid = new ComponentGrid(window, Vector2i(1, 3));
mGrid->setSize(mSize);
mGrid->setEntry(s, Vector2i(0, 1), false, true);
addChild(mGrid);
}
GuiInfoPopup::~GuiInfoPopup()
{
}
void GuiInfoPopup::render(const Transform4x4f& /*parentTrans*/)
{
// we use identity as we want to render on a specific window position, not on the view
Transform4x4f trans = getTransform() * Transform4x4f::Identity();
if(running && updateState())
{
// if we're still supposed to be rendering it
Renderer::setMatrix(trans);
renderChildren(trans);
}
// We use Identity() as we want to render on a specific window position, not on the view.
Transform4x4f trans = getTransform() * Transform4x4f::Identity();
if (running && updateState()) {
// If we're still supposed to be rendering it.
Renderer::setMatrix(trans);
renderChildren(trans);
}
}
bool GuiInfoPopup::updateState()
{
int curTime = SDL_GetTicks();
int curTime = SDL_GetTicks();
// we only init the actual time when we first start to render
if(mStartTime == 0)
{
mStartTime = curTime;
}
// We only initialize the actual time when we first start to render.
if (mStartTime == 0)
mStartTime = curTime;
// compute fade in effect
if (curTime - mStartTime > mDuration)
{
// we're past the popup duration, no need to render
running = false;
return false;
}
else if (curTime < mStartTime) {
// if SDL reset
running = false;
return false;
}
else if (curTime - mStartTime <= 500) {
alpha = ((curTime - mStartTime)*255/500);
}
else if (curTime - mStartTime < mDuration - 500)
{
alpha = 255;
}
else
{
alpha = ((-(curTime - mStartTime - mDuration)*255)/500);
}
mGrid->setOpacity((unsigned char)alpha);
// Compute fade-in effect.
if (curTime - mStartTime > mDuration) {
// We're past the popup duration, no need to render.
running = false;
return false;
}
else if (curTime < mStartTime) {
// If SDL reset.
running = false;
return false;
}
else if (curTime - mStartTime <= 500) {
alpha = ((curTime - mStartTime)*255/500);
}
else if (curTime - mStartTime < mDuration - 500) {
alpha = 255;
}
else {
alpha = ((-(curTime - mStartTime - mDuration)*255)/500);
}
mGrid->setOpacity((unsigned char)alpha);
// apply fade in effect to popup frame
mFrame->setEdgeColor(0xFFFFFF00 | (unsigned char)(alpha));
mFrame->setCenterColor(0xFFFFFF00 | (unsigned char)(alpha));
return true;
}
// Apply fade-in effect to popup frame.
mFrame->setEdgeColor(0xFFFFFF00 | (unsigned char)(alpha));
mFrame->setCenterColor(0xFFFFFF00 | (unsigned char)(alpha));
return true;
}

View file

@ -1,3 +1,9 @@
//
// GuiInfoPopup.h
//
// Popup window used for user notifications.
//
#pragma once
#ifndef ES_APP_GUIS_GUI_INFO_POPUP_H
#define ES_APP_GUIS_GUI_INFO_POPUP_H
@ -11,19 +17,20 @@ class NinePatchComponent;
class GuiInfoPopup : public GuiComponent, public Window::InfoPopup
{
public:
GuiInfoPopup(Window* window, std::string message, int duration);
~GuiInfoPopup();
void render(const Transform4x4f& parentTrans) override;
inline void stop() { running = false; };
GuiInfoPopup(Window* window, std::string message, int duration);
~GuiInfoPopup();
void render(const Transform4x4f& parentTrans) override;
inline void stop() { running = false; };
private:
std::string mMessage;
int mDuration;
int alpha;
bool updateState();
int mStartTime;
ComponentGrid* mGrid;
NinePatchComponent* mFrame;
bool running;
std::string mMessage;
int mDuration;
int alpha;
bool updateState();
int mStartTime;
ComponentGrid* mGrid;
NinePatchComponent* mFrame;
bool running;
};
#endif // ES_APP_GUIS_GUI_INFO_POPUP_H

View file

@ -299,12 +299,12 @@ void GuiMenu::openUISettings()
s->addSaveFunc([ UImodeSelection, window, this] {
std::string selectedMode = UImodeSelection->getSelected();
if (selectedMode != "Full") {
std::string msg = "You are changing the UI to a restricted mode:\n" +
selectedMode + "\n";
msg += "This will hide most menu-options to prevent changes to the system.\n";
msg += "To unlock and return to the full UI, enter this code: \n";
std::string msg = "YOU ARE CHANGING THE UI TO A RESTRICTED MODE:\n\"" +
Utils::String::toUpper(selectedMode) + "\"\n";
msg += "THIS WILL HIDE MOST MENU OPTIONS TO PREVENT CHANGES TO THE SYSTEM.\n";
msg += "TO UNLOCK AND RETURN TO THE FULL UI, ENTER THIS CODE: \n";
msg += "\"" + UIModeController::getInstance()->getFormattedPassKeyStr() + "\"\n\n";
msg += "Do you want to proceed?";
msg += "DO YOU WANT TO PROCEED?";
window->pushGui(new GuiMsgBox(window, this->getHelpStyle(), msg,
"YES", [selectedMode] {
LOG(LogDebug) << "Setting UI mode to " << selectedMode;

View file

@ -1,3 +1,9 @@
//
// GuiScreensaverOptions.cpp
//
// User interface template for the screensaver option GUIs.
//
#include "guis/GuiScreensaverOptions.h"
#include "guis/GuiTextEditPopup.h"
@ -6,83 +12,87 @@
#include "SystemData.h"
#include "Window.h"
GuiScreensaverOptions::GuiScreensaverOptions(Window* window, const char* title) : GuiComponent(window), mMenu(window, title)
GuiScreensaverOptions::GuiScreensaverOptions(Window* window, const char* title)
: GuiComponent(window), mMenu(window, title)
{
addChild(&mMenu);
addChild(&mMenu);
mMenu.addButton("BACK", "back", [this] { delete this; });
mMenu.addButton("BACK", "back", [this] { delete this; });
setSize((float)Renderer::getScreenWidth(), (float)Renderer::getScreenHeight());
mMenu.setPosition((mSize.x() - mMenu.getSize().x()) / 2, Renderer::getScreenHeight() * 0.15f);
setSize((float)Renderer::getScreenWidth(), (float)Renderer::getScreenHeight());
mMenu.setPosition((mSize.x() - mMenu.getSize().x()) / 2, Renderer::getScreenHeight() * 0.15f);
}
GuiScreensaverOptions::~GuiScreensaverOptions()
{
save();
save();
}
void GuiScreensaverOptions::save()
{
if(!mSaveFuncs.size())
return;
if(!mSaveFuncs.size())
return;
for(auto it = mSaveFuncs.cbegin(); it != mSaveFuncs.cend(); it++)
(*it)();
for(auto it = mSaveFuncs.cbegin(); it != mSaveFuncs.cend(); it++)
(*it)();
Settings::getInstance()->saveFile();
Settings::getInstance()->saveFile();
}
bool GuiScreensaverOptions::input(InputConfig* config, Input input)
{
if (GuiComponent::input(config, input))
return true;
if (GuiComponent::input(config, input))
return true;
if (config->isMappedTo("b", input) &&
input.value != 0) {
delete this;
return true;
}
if (config->isMappedTo("b", input) &&
input.value != 0) {
delete this;
return true;
}
return false;
return false;
}
HelpStyle GuiScreensaverOptions::getHelpStyle()
{
HelpStyle style = HelpStyle();
style.applyTheme(ViewController::get()->getState().getSystem()->getTheme(), "system");
return style;
HelpStyle style = HelpStyle();
style.applyTheme(ViewController::get()->getState().getSystem()->getTheme(), "system");
return style;
}
std::vector<HelpPrompt> GuiScreensaverOptions::getHelpPrompts()
{
std::vector<HelpPrompt> prompts = mMenu.getHelpPrompts();
prompts.push_back(HelpPrompt("b", "back"));
return prompts;
std::vector<HelpPrompt> prompts = mMenu.getHelpPrompts();
prompts.push_back(HelpPrompt("b", "back"));
return prompts;
}
void GuiScreensaverOptions::addEditableTextComponent(ComponentListRow row, const std::string label, std::shared_ptr<GuiComponent> ed, std::string value)
void GuiScreensaverOptions::addEditableTextComponent(ComponentListRow row,
const std::string label, std::shared_ptr<GuiComponent> ed, std::string value)
{
row.elements.clear();
row.elements.clear();
auto lbl = std::make_shared<TextComponent>(mWindow, Utils::String::toUpper(label), Font::get(FONT_SIZE_MEDIUM), 0x777777FF);
row.addElement(lbl, true); // label
auto lbl = std::make_shared<TextComponent>(mWindow, Utils::String::toUpper(label),
Font::get(FONT_SIZE_MEDIUM), 0x777777FF);
row.addElement(lbl, true); // Label.
row.addElement(ed, true);
row.addElement(ed, true);
auto spacer = std::make_shared<GuiComponent>(mWindow);
spacer->setSize(Renderer::getScreenWidth() * 0.005f, 0);
row.addElement(spacer, false);
auto spacer = std::make_shared<GuiComponent>(mWindow);
spacer->setSize(Renderer::getScreenWidth() * 0.005f, 0);
row.addElement(spacer, false);
auto bracket = std::make_shared<ImageComponent>(mWindow);
bracket->setImage(":/graphics/arrow.svg");
bracket->setResize(Vector2f(0, lbl->getFont()->getLetterHeight()));
row.addElement(bracket, false);
auto bracket = std::make_shared<ImageComponent>(mWindow);
bracket->setImage(":/graphics/arrow.svg");
bracket->setResize(Vector2f(0, lbl->getFont()->getLetterHeight()));
row.addElement(bracket, false);
auto updateVal = [ed](const std::string& newVal) { ed->setValue(newVal); }; // ok callback (apply new value to ed)
row.makeAcceptInputHandler([this, label, ed, updateVal] {
mWindow->pushGui(new GuiTextEditPopup(mWindow, getHelpStyle(), label, ed->getValue(), updateVal, false));
});
assert(ed);
addRow(row);
ed->setValue(value);
// OK callback (apply new value to ed).
auto updateVal = [ed](const std::string& newVal) { ed->setValue(newVal); };
row.makeAcceptInputHandler([this, label, ed, updateVal] {
mWindow->pushGui(new GuiTextEditPopup(mWindow, getHelpStyle(), label,
ed->getValue(), updateVal, false));
});
assert(ed);
addRow(row);
ed->setValue(value);
}

View file

@ -1,3 +1,9 @@
//
// GuiScreensaverOptions.h
//
// User interface template for the screensaver option GUIs.
//
#pragma once
#ifndef ES_APP_GUIS_GUI_SCREENSAVER_OPTIONS_H
#define ES_APP_GUIS_GUI_SCREENSAVER_OPTIONS_H
@ -8,22 +14,24 @@
class GuiScreensaverOptions : public GuiComponent
{
public:
GuiScreensaverOptions(Window* window, const char* title);
virtual ~GuiScreensaverOptions(); // just calls save();
GuiScreensaverOptions(Window* window, const char* title);
virtual ~GuiScreensaverOptions(); // Just calls save()
virtual void save();
inline void addRow(const ComponentListRow& row) { mMenu.addRow(row); };
inline void addWithLabel(const std::string& label, const std::shared_ptr<GuiComponent>& comp) { mMenu.addWithLabel(label, comp); };
inline void addSaveFunc(const std::function<void()>& func) { mSaveFuncs.push_back(func); };
void addEditableTextComponent(ComponentListRow row, const std::string label, std::shared_ptr<GuiComponent> ed, std::string value);
virtual void save();
inline void addRow(const ComponentListRow& row) { mMenu.addRow(row); };
inline void addWithLabel(const std::string& label,
const std::shared_ptr<GuiComponent>& comp) { mMenu.addWithLabel(label, comp); };
inline void addSaveFunc(const std::function<void()>& func) { mSaveFuncs.push_back(func); };
void addEditableTextComponent(ComponentListRow row,
const std::string label, std::shared_ptr<GuiComponent> ed, std::string value);
bool input(InputConfig* config, Input input) override;
std::vector<HelpPrompt> getHelpPrompts() override;
HelpStyle getHelpStyle() override;
bool input(InputConfig* config, Input input) override;
std::vector<HelpPrompt> getHelpPrompts() override;
HelpStyle getHelpStyle() override;
protected:
MenuComponent mMenu;
std::vector< std::function<void()> > mSaveFuncs;
MenuComponent mMenu;
std::vector< std::function<void()> > mSaveFuncs;
};
#endif // ES_APP_GUIS_GUI_SCREENSAVER_OPTIONS_H

View file

@ -1,3 +1,15 @@
//
// Scripting.cpp
//
// Executes custom scripts for various events in EmulationStation.
// By calling fireEvent() the scripts inside the directory corresponding to the
// argument 'eventName' will be executed with arg1 and arg2 as the script arguments.
//
// The scripts are searched for in $HOME/.emulationstation/scripts/<eventName>.
// For example, if the event is called 'game-start', all scripts inside the directory
// $HOME/.emulationstation/scripts/game-start/ will be executed.
//
#include "Scripting.h"
#include "Log.h"
#include "Platform.h"
@ -12,25 +24,21 @@ namespace Scripting
std::list<std::string> scriptDirList;
std::string test;
// check in exepath
test = Utils::FileSystem::getExePath() + "/scripts/" + eventName;
if(Utils::FileSystem::exists(test))
scriptDirList.push_back(test);
// check in homepath
// Check in homepath.
test = Utils::FileSystem::getHomePath() + "/.emulationstation/scripts/" + eventName;
if(Utils::FileSystem::exists(test))
scriptDirList.push_back(test);
for(std::list<std::string>::const_iterator dirIt = scriptDirList.cbegin(); dirIt != scriptDirList.cend(); ++dirIt) {
for(std::list<std::string>::const_iterator dirIt = scriptDirList.cbegin();
dirIt != scriptDirList.cend(); ++dirIt) {
std::list<std::string> scripts = Utils::FileSystem::getDirContent(*dirIt);
for (std::list<std::string>::const_iterator it = scripts.cbegin(); it != scripts.cend(); ++it) {
// append folder to path
for (std::list<std::string>::const_iterator it = scripts.cbegin();
it != scripts.cend(); ++it) {
// Append folder to path.
std::string script = *it + " \"" + arg1 + "\" \"" + arg2 + "\"";
LOG(LogDebug) << " executing: " << script;
runSystemCommand(script);
}
}
}
} // Scripting::
}

View file

@ -1,3 +1,15 @@
//
// Scripting.h
//
// Executes custom scripts for various events in EmulationStation.
// By calling fireEvent() the scripts inside the directory corresponding to the
// argument 'eventName' will be executed with arg1 and arg2 as the script arguments.
//
// The scripts are searched for in $HOME/.emulationstation/scripts/<eventName>.
// For example, if the event is called 'game-start', all scripts inside the directory
// $HOME/.emulationstation/scripts/game-start/ will be executed.
//
#pragma once
#ifndef ES_CORE_SCRIPTING_H
#define ES_CORE_SCRIPTING_H
@ -6,7 +18,8 @@
namespace Scripting
{
void fireEvent(const std::string& eventName, const std::string& arg1="", const std::string& arg2="");
} // Scripting::
void fireEvent(const std::string& eventName,
const std::string& arg1="", const std::string& arg2="");
}
#endif //ES_CORE_SCRIPTING_H

View file

@ -1,7 +1,9 @@
//
// ThemeData.cpp
//
// Theme handling.
// Finds available themes on the file system and loads these,
// including the parsing of individual theme components
// (includes, features, variables, views, elements).
//
#include "ThemeData.h"
@ -417,7 +419,6 @@ void ThemeData::parseView(const pugi::xml_node& root, ThemeView& view)
}
}
void ThemeData::parseElement(const pugi::xml_node& root,
const std::map<std::string, ElementPropertyType>& typeMap, ThemeElement& element)
{

View file

@ -1,7 +1,9 @@
//
// ThemeData.h
//
// Theme handling.
// Finds available themes on the file system and loads these,
// including the parsing of individual theme components
// (includes, features, variables, views, elements).
//
#pragma once
@ -148,7 +150,6 @@ private:
};
public:
ThemeData();
// Throws ThemeException.

File diff suppressed because it is too large Load diff

View file

@ -1,3 +1,9 @@
//
// FileSystemUtil.h
//
// Low-level filesystem functions.
//
#pragma once
#ifndef ES_CORE_UTILS_FILE_SYSTEM_UTIL_H
#define ES_CORE_UTILS_FILE_SYSTEM_UTIL_H
@ -7,42 +13,45 @@
namespace Utils
{
namespace FileSystem
{
typedef std::list<std::string> stringList;
namespace FileSystem
{
typedef std::list<std::string> stringList;
stringList getDirContent (const std::string& _path, const bool _recursive = false);
stringList getPathList (const std::string& _path);
void setHomePath (const std::string& _path);
std::string getHomePath ();
std::string getCWDPath ();
void setExePath (const std::string& _path);
std::string getExePath ();
std::string getInstallPrefixPath ();
std::string getPreferredPath (const std::string& _path);
std::string getGenericPath (const std::string& _path);
std::string getEscapedPath (const std::string& _path);
std::string getCanonicalPath (const std::string& _path);
std::string getAbsolutePath (const std::string& _path, const std::string& _base = getCWDPath());
std::string getParent (const std::string& _path);
std::string getFileName (const std::string& _path);
std::string getStem (const std::string& _path);
std::string getExtension (const std::string& _path);
std::string resolveRelativePath(const std::string& _path, const std::string& _relativeTo, const bool _allowHome);
std::string createRelativePath (const std::string& _path, const std::string& _relativeTo, const bool _allowHome);
std::string removeCommonPath (const std::string& _path, const std::string& _common, bool& _contains);
std::string resolveSymlink (const std::string& _path);
bool removeFile (const std::string& _path);
bool createDirectory (const std::string& _path);
bool exists (const std::string& _path);
bool isAbsolute (const std::string& _path);
bool isRegularFile (const std::string& _path);
bool isDirectory (const std::string& _path);
bool isSymlink (const std::string& _path);
bool isHidden (const std::string& _path);
} // FileSystem::
} // Utils::
stringList getDirContent(const std::string& _path,
const bool _recursive = false);
stringList getPathList(const std::string& _path);
void setHomePath(const std::string& _path);
std::string getHomePath();
std::string getCWDPath();
void setExePath(const std::string& _path);
std::string getExePath();
std::string getInstallPrefixPath ();
std::string getPreferredPath(const std::string& _path);
std::string getGenericPath(const std::string& _path);
std::string getEscapedPath(const std::string& _path);
std::string getCanonicalPath(const std::string& _path);
std::string getAbsolutePath(const std::string& _path,
const std::string& _base = getCWDPath());
std::string getParent(const std::string& _path);
std::string getFileName(const std::string& _path);
std::string getStem(const std::string& _path);
std::string getExtension(const std::string& _path);
std::string resolveRelativePath(const std::string& _path,
const std::string& _relativeTo, const bool _allowHome);
std::string createRelativePath(const std::string& _path,
const std::string& _relativeTo, const bool _allowHome);
std::string removeCommonPath(const std::string& _path,
const std::string& _common, bool& _contains);
std::string resolveSymlink(const std::string& _path);
bool removeFile(const std::string& _path);
bool createDirectory(const std::string& _path);
bool exists(const std::string& _path);
bool isAbsolute(const std::string& _path);
bool isRegularFile(const std::string& _path);
bool isDirectory(const std::string& _path);
bool isSymlink(const std::string& _path);
bool isHidden(const std::string& _path);
}
}
#endif // ES_CORE_UTILS_FILE_SYSTEM_UTIL_H