diff --git a/es-app/src/CollectionSystemsManager.cpp b/es-app/src/CollectionSystemsManager.cpp index 50512fb80..154c6e038 100644 --- a/es-app/src/CollectionSystemsManager.cpp +++ b/es-app/src/CollectionSystemsManager.cpp @@ -756,6 +756,9 @@ SystemData* CollectionSystemsManager::getSystemToView(SystemData* sys) FileData* CollectionSystemsManager::updateCollectionFolderMetadata(SystemData* sys) { + if (sys->getRootFolder()->getParent() == nullptr) + return nullptr; + FileData* rootFolder {sys->getRootFolder()}; FileFilterIndex* idx {rootFolder->getSystem()->getIndex()}; std::string desc {"This collection is empty"}; @@ -763,7 +766,7 @@ FileData* CollectionSystemsManager::updateCollectionFolderMetadata(SystemData* s std::vector gamesListRandom; if (UIModeController::getInstance()->isUIModeKid()) { - for (FileData* game : rootFolder->getChildrenListToDisplay()) { + for (auto game : rootFolder->getChildrenListToDisplay()) { if (game->getKidgame()) gamesList.push_back(game); } @@ -781,11 +784,11 @@ FileData* CollectionSystemsManager::updateCollectionFolderMetadata(SystemData* s std::mt19937 engine {randDev()}; int target; - for (int i = 0; i < 3; ++i) { + for (int i {0}; i < 3; ++i) { std::uniform_int_distribution uniform_dist {0, gameCount - 1 - i}; target = uniform_dist(engine); gamesListRandom.push_back(gamesList[target]); - std::vector::iterator it {(gamesList.begin() + target)}; + std::vector::iterator it {gamesList.begin() + target}; gamesList.erase(it); if (gamesList.size() == 0) break; @@ -796,31 +799,62 @@ FileData* CollectionSystemsManager::updateCollectionFolderMetadata(SystemData* s } if (gameCount > 0) { - if (Settings::getInstance()->getBool("CollectionShowSystemInfo")) { + auto nameSuffix = ViewController::getInstance() + ->getGamelistView(sys->getRootFolder()->getParent()->getSystem()) + ->getDescriptionSystemNameSuffix(); + if (nameSuffix.first) { + auto caseConversion = [nameSuffix](std::string name) -> std::string { + if (nameSuffix.second == LetterCase::UPPERCASE) + return Utils::String::toUpper(name); + else if (nameSuffix.second == LetterCase::CAPITALIZE) + return Utils::String::toCapitalized(name); + else + return Utils::String::toLower(name); + }; switch (gameCount) { case 1: { - desc = "This collection contains 1 game: '" + - gamesList[0]->metadata.get("name") + " [" + - gamesList[0]->getSourceFileData()->getSystem()->getName() + "]'"; + desc = "This collection contains 1 game: '"; + desc.append(gamesList[0]->metadata.get("name")) + .append(" [") + .append(caseConversion( + gamesList[0]->getSourceFileData()->getSystem()->getName())) + .append("]'"); break; } case 2: { - desc = "This collection contains 2 games: '" + - gamesList[0]->metadata.get("name") + " [" + - gamesList[0]->getSourceFileData()->getSystem()->getName() + "]' and '" + - gamesList[1]->metadata.get("name") + " [" + - gamesList[1]->getSourceFileData()->getSystem()->getName() + "]'"; + desc = "This collection contains 2 games: '"; + desc.append(gamesList[0]->metadata.get("name")) + .append(" [") + .append(caseConversion( + gamesList[0]->getSourceFileData()->getSystem()->getName())) + .append("]' and '") + .append(gamesList[1]->metadata.get("name")) + .append(" [") + .append(caseConversion( + gamesList[1]->getSourceFileData()->getSystem()->getName())) + .append("]'"); break; } default: { - desc = "This collection contains " + std::to_string(gameCount) + " games: '" + - gamesList[0]->metadata.get("name") + " [" + - gamesList[0]->getSourceFileData()->getSystem()->getName() + "]', '" + - gamesList[1]->metadata.get("name") + " [" + - gamesList[1]->getSourceFileData()->getSystem()->getName() + "]' and '" + - gamesList[2]->metadata.get("name") + " [" + - gamesList[2]->getSourceFileData()->getSystem()->getName() + "]'"; - desc += (gameCount == 3 ? "" : ", among others"); + desc = "This collection contains "; + desc.append(std::to_string(gameCount)) + .append(" games: '") + .append(gamesList[0]->metadata.get("name")) + .append(" [") + .append(caseConversion( + gamesList[0]->getSourceFileData()->getSystem()->getName())) + .append("]', '") + .append(gamesList[1]->metadata.get("name")) + .append(" [") + .append(caseConversion( + gamesList[1]->getSourceFileData()->getSystem()->getName())) + .append("]' and '") + .append(gamesList[2]->metadata.get("name")) + .append(" [") + .append(caseConversion( + gamesList[2]->getSourceFileData()->getSystem()->getName())) + .append("]'"); + desc.append(gameCount == 3 ? "" : ", among others"); break; } } @@ -828,31 +862,40 @@ FileData* CollectionSystemsManager::updateCollectionFolderMetadata(SystemData* s else { switch (gameCount) { case 1: { - desc = "This collection contains 1 game: '" + - gamesList[0]->metadata.get("name") + " '"; + desc = "This collection contains 1 game: '"; + desc.append(gamesList[0]->metadata.get("name")).append("'"); break; } case 2: { - desc = "This collection contains 2 games: '" + - gamesList[0]->metadata.get("name") + "' and '" + - gamesList[1]->metadata.get("name") + "'"; + desc = "This collection contains 2 games: '"; + desc.append(gamesList[0]->metadata.get("name")) + .append("' and '") + .append(gamesList[1]->metadata.get("name")) + .append("'"); break; } default: { - desc = "This collection contains " + std::to_string(gameCount) + " games: '" + - gamesList[0]->metadata.get("name") + "', '" + - gamesList[1]->metadata.get("name") + "' and '" + - gamesList[2]->metadata.get("name") + "'"; - desc += (gameCount == 3 ? "" : ", among others"); + desc = "This collection contains "; + desc.append(std::to_string(gameCount)) + .append(" games: '") + .append(gamesList[0]->metadata.get("name")) + .append("', '") + .append(gamesList[1]->metadata.get("name")) + .append("' and '") + .append(gamesList[2]->metadata.get("name")) + .append("'"); + desc.append(gameCount == 3 ? "" : ", among others"); break; } } } } - if (idx->isFiltered()) - desc += "\n\n'" + rootFolder->getSystem()->getFullName() + - "' is filtered so there may be more games available"; + if (idx->isFiltered()) { + desc.append("\n\n'") + .append(rootFolder->getSystem()->getFullName()) + .append("' is filtered so there may be more games available"); + } rootFolder->metadata.set("desc", desc); @@ -1139,7 +1182,7 @@ void CollectionSystemsManager::populateAutoCollection(CollectionSystemData* sysD if (!(*gameIt)->getCountAsGame()) continue; - CollectionFileData* newGame = new CollectionFileData(*gameIt, newSys); + CollectionFileData* newGame {new CollectionFileData(*gameIt, newSys)}; rootFolder->addChild(newGame); index->addToIndex(newGame); } diff --git a/es-app/src/FileData.cpp b/es-app/src/FileData.cpp index 65ca82427..6b3d42688 100644 --- a/es-app/src/FileData.cpp +++ b/es-app/src/FileData.cpp @@ -21,7 +21,6 @@ #include "Window.h" #include "utils/FileSystemUtil.h" #include "utils/PlatformUtil.h" -#include "utils/StringUtil.h" #include "utils/TimeUtil.h" #include "views/GamelistView.h" #include "views/ViewController.h" @@ -73,23 +72,6 @@ FileData::~FileData() mParent->removeChild(this); } -std::string FileData::getDisplayName() const -{ - const std::string& stem {Utils::FileSystem::getStem(mPath)}; - return stem; -} - -std::string FileData::getCleanName() const -{ - return Utils::String::removeParenthesis(this->getDisplayName()); -} - -const std::string& FileData::getName() -{ - // Return metadata name. - return metadata.get("name"); -} - const std::string& FileData::getSortName() { if (mSystem->isCustomCollection() && mType == GAME) { @@ -1965,7 +1947,6 @@ CollectionFileData::CollectionFileData(FileData* file, SystemData* system) { // We use this constructor to create a clone of the filedata, and change its system. mSourceFileData = file->getSourceFileData(); - refreshMetadata(); mParent = nullptr; metadata = mSourceFileData->metadata; mSystemName = mSourceFileData->getSystem()->getName(); @@ -1978,25 +1959,3 @@ CollectionFileData::~CollectionFileData() mParent->removeChild(this); mParent = nullptr; } - -void CollectionFileData::refreshMetadata() -{ - metadata = mSourceFileData->metadata; - mDirty = true; -} - -const std::string& CollectionFileData::getName() -{ - if (mDirty) { - mCollectionFileName = mSourceFileData->metadata.get("name"); - mCollectionFileName.append(" [") - .append(Utils::String::toUpper(mSourceFileData->getSystem()->getName())) - .append("]"); - mDirty = false; - } - - if (Settings::getInstance()->getBool("CollectionShowSystemInfo")) - return mCollectionFileName; - - return mSourceFileData->metadata.get("name"); -} diff --git a/es-app/src/FileData.h b/es-app/src/FileData.h index 85ca7903a..30ccb4f4d 100644 --- a/es-app/src/FileData.h +++ b/es-app/src/FileData.h @@ -13,6 +13,7 @@ #include "MetaData.h" #include "utils/FileSystemUtil.h" +#include "utils/StringUtil.h" #include #include @@ -38,8 +39,19 @@ public: virtual ~FileData(); - virtual const std::string& getName(); + const std::string& getName() { return metadata.get("name"); } const std::string& getSortName(); + // Returns our best guess at the "real" name for this file. + std::string getDisplayName() const + { + const std::string& stem {Utils::FileSystem::getStem(mPath)}; + return stem; + } + std::string getCleanName() const + { + return Utils::String::removeParenthesis(this->getDisplayName()); + } + const bool getFavorite(); const bool getKidgame(); const bool getHidden(); @@ -108,12 +120,6 @@ public: virtual FileData* getSourceFileData() { return this; } const std::string& getSystemName() const { return mSystemName; } - // Returns our best guess at the "real" name for this file. - std::string getDisplayName() const; - - // As above, but also remove parenthesis. - std::string getCleanName() const; - void launchGame(); const std::string findEmulatorPath(std::string& command); @@ -173,15 +179,8 @@ class CollectionFileData : public FileData public: CollectionFileData(FileData* file, SystemData* system); ~CollectionFileData(); - const std::string& getName(); - void refreshMetadata(); FileData* getSourceFileData() { return mSourceFileData; } std::string getKey() { return getFullPath(); } - -private: - // Needs to be updated when metadata changes. - std::string mCollectionFileName; - bool mDirty; }; #endif // ES_APP_FILE_DATA_H diff --git a/es-app/src/FileFilterIndex.cpp b/es-app/src/FileFilterIndex.cpp index 0842adb32..3c63f03bf 100644 --- a/es-app/src/FileFilterIndex.cpp +++ b/es-app/src/FileFilterIndex.cpp @@ -22,7 +22,6 @@ FileFilterIndex::FileFilterIndex() : mFilterByText {false} - , mTextRemoveSystem {false} , mFilterByRatings {false} , mFilterByDeveloper {false} , mFilterByPublisher {false} @@ -404,17 +403,10 @@ bool FileFilterIndex::showFile(FileData* game) bool keepGoing = false; // Name filters take precedence over all other filters, so if there is no match for - // the game name, then always return false. If we're in a collection system and the option - // to show the system name has been enabled, then exclude the system name that is encapsulated - // in [] from the search string. - if (mTextFilter != "" && mTextRemoveSystem && - !(Utils::String::toUpper(game->getName().substr(0, game->getName().find_last_of("["))) - .find(Utils::String::toUpper(mTextFilter)) != std::string::npos)) { - return false; - } - else if (mTextFilter != "" && - !(Utils::String::toUpper(game->getName()).find(Utils::String::toUpper(mTextFilter)) != - std::string::npos)) { + // the game name, then always return false. + if (mTextFilter != "" && + !(Utils::String::toUpper(game->getName()).find(Utils::String::toUpper(mTextFilter)) != + std::string::npos)) { return false; } diff --git a/es-app/src/FileFilterIndex.h b/es-app/src/FileFilterIndex.h index 975c58432..a034a361e 100644 --- a/es-app/src/FileFilterIndex.h +++ b/es-app/src/FileFilterIndex.h @@ -62,7 +62,6 @@ public: bool isFiltered(); bool isKeyBeingFilteredBy(std::string key, FilterIndexType type); std::vector& getFilterDataDecls() { return filterDataDecl; } - void setTextRemoveSystem(bool status) { mTextRemoveSystem = status; } void importIndex(FileFilterIndex* indexToImport); void resetIndex(); @@ -92,7 +91,6 @@ private: std::string mTextFilter; bool mFilterByText; - bool mTextRemoveSystem; bool mFilterByRatings; bool mFilterByDeveloper; diff --git a/es-app/src/guis/GuiCollectionSystemsOptions.cpp b/es-app/src/guis/GuiCollectionSystemsOptions.cpp index b93673a87..63d1b96f0 100644 --- a/es-app/src/guis/GuiCollectionSystemsOptions.cpp +++ b/es-app/src/guis/GuiCollectionSystemsOptions.cpp @@ -368,22 +368,6 @@ GuiCollectionSystemsOptions::GuiCollectionSystemsOptions(std::string title) setInvalidateCachedBackground(); } }); - - // Show system names in collections. - auto collection_show_system_info = std::make_shared(); - collection_show_system_info->setState( - Settings::getInstance()->getBool("CollectionShowSystemInfo")); - addWithLabel("SHOW SYSTEM NAMES IN COLLECTIONS", collection_show_system_info); - addSaveFunc([this, collection_show_system_info] { - if (collection_show_system_info->getState() != - Settings::getInstance()->getBool("CollectionShowSystemInfo")) { - Settings::getInstance()->setBool("CollectionShowSystemInfo", - collection_show_system_info->getState()); - setNeedsSaving(); - setNeedsReloading(); - setInvalidateCachedBackground(); - } - }); } void GuiCollectionSystemsOptions::createCustomCollection(std::string inName) diff --git a/es-app/src/guis/GuiGamelistFilter.cpp b/es-app/src/guis/GuiGamelistFilter.cpp index eaa12edf9..5379f5974 100644 --- a/es-app/src/guis/GuiGamelistFilter.cpp +++ b/es-app/src/guis/GuiGamelistFilter.cpp @@ -35,15 +35,6 @@ void GuiGamelistFilter::initializeMenu() // Get filters from system. mFilterIndex = mSystem->getIndex(); - // If this is a collection and system names are shown per game, then let FileFilterIndex - // know about this so the system names will not be included in game name text searches. - if (ViewController::getInstance()->getState().getSystem()->isCollection()) { - if (Settings::getInstance()->getBool("CollectionShowSystemInfo")) - mFilterIndex->setTextRemoveSystem(true); - else - mFilterIndex->setTextRemoveSystem(false); - } - ComponentListRow row; // Show filtered menu. diff --git a/es-app/src/views/GamelistBase.cpp b/es-app/src/views/GamelistBase.cpp index cd70cc13d..40765eba7 100644 --- a/es-app/src/views/GamelistBase.cpp +++ b/es-app/src/views/GamelistBase.cpp @@ -32,6 +32,7 @@ GamelistBase::GamelistBase(FileData* root) , mIsFolder {false} , mVideoPlaying {false} , mLeftRightAvailable {true} + , mSystemNameSuffix {false} { setSize(Renderer::getScreenWidth(), Renderer::getScreenHeight()); } @@ -552,7 +553,8 @@ void GamelistBase::populateList(const std::vector& files, FileData* f mFirstGameEntry = nullptr; bool favoriteStar {true}; bool isEditing {false}; - bool customCollection {false}; + bool isCollection {false}; + bool isCustomCollection {false}; std::string editingCollection; std::string inCollectionPrefix; LetterCase letterCase {LetterCase::NONE}; @@ -563,10 +565,11 @@ void GamelistBase::populateList(const std::vector& files, FileData* f } if (files.size() > 0) { - customCollection = files.front()->getSystem()->isCustomCollection(); + isCollection = files.front()->getSystem()->isCollection(); + isCustomCollection = files.front()->getSystem()->isCustomCollection(); // Read the settings that control whether a unicode star character should be added // as a prefix to the game name. - if (customCollection) + if (isCustomCollection) favoriteStar = Settings::getInstance()->getBool("FavStarCustom"); else favoriteStar = Settings::getInstance()->getBool("FavoritesStar"); @@ -575,6 +578,25 @@ void GamelistBase::populateList(const std::vector& files, FileData* f if (mPrimary != nullptr) mPrimary->clear(); + auto nameSuffixFunc = [this](std::vector::const_iterator it, std::string& name) { + if ((*it)->getType() == GAME) { + const LetterCase letterCase {mPrimary->getLetterCaseSystemNameSuffix()}; + name.append(" ["); + if (letterCase == LetterCase::UPPERCASE) { + name.append( + Utils::String::toUpper((*it)->getSourceFileData()->getSystem()->getName())); + } + else if (letterCase == LetterCase::CAPITALIZE) { + name.append(Utils::String::toCapitalized( + (*it)->getSourceFileData()->getSystem()->getName())); + } + else { + name.append((*it)->getSourceFileData()->getSystem()->getName()); + } + name.append("]"); + } + }; + auto theme = mRoot->getSystem()->getTheme(); std::string name; std::string defaultImage; @@ -596,7 +618,7 @@ void GamelistBase::populateList(const std::vector& files, FileData* f if (!mFirstGameEntry && (*it)->getType() == GAME) mFirstGameEntry = (*it); - if (customCollection && (*it)->getType() == FOLDER) { + if (isCustomCollection && (*it)->getType() == FOLDER) { letterCase = mPrimary->getLetterCaseCustomCollections(); if (letterCase == LetterCase::UNDEFINED) letterCase = mPrimary->getLetterCase(); @@ -617,6 +639,9 @@ void GamelistBase::populateList(const std::vector& files, FileData* f else if (letterCase == LetterCase::CAPITALIZE) carouselEntry.name = Utils::String::toCapitalized(carouselEntry.name); + if (isCollection && mSystemNameSuffix) + nameSuffixFunc(it, carouselEntry.name); + if (defaultImage != "") carouselEntry.data.defaultImagePath = defaultImage; @@ -634,6 +659,9 @@ void GamelistBase::populateList(const std::vector& files, FileData* f else if (letterCase == LetterCase::CAPITALIZE) gridEntry.name = Utils::String::toCapitalized(gridEntry.name); + if (isCollection && mSystemNameSuffix) + nameSuffixFunc(it, gridEntry.name); + if (defaultImage != "") gridEntry.data.defaultImagePath = defaultImage; @@ -698,6 +726,9 @@ void GamelistBase::populateList(const std::vector& files, FileData* f else if (letterCase == LetterCase::CAPITALIZE) name = Utils::String::toCapitalized(name); + if (isCollection && mSystemNameSuffix) + nameSuffixFunc(it, name); + textListEntry.name = name; textListEntry.object = *it; if ((*it)->getType() == FOLDER) diff --git a/es-app/src/views/GamelistBase.h b/es-app/src/views/GamelistBase.h index 839e1a9eb..7453f89fa 100644 --- a/es-app/src/views/GamelistBase.h +++ b/es-app/src/views/GamelistBase.h @@ -115,6 +115,7 @@ protected: bool mIsFolder; bool mVideoPlaying; bool mLeftRightAvailable; + bool mSystemNameSuffix; private: }; diff --git a/es-app/src/views/GamelistView.cpp b/es-app/src/views/GamelistView.cpp index 32305a60e..b08226b79 100644 --- a/es-app/src/views/GamelistView.cpp +++ b/es-app/src/views/GamelistView.cpp @@ -36,6 +36,25 @@ GamelistView::~GamelistView() mThemeExtras.clear(); } +const std::pair GamelistView::getDescriptionSystemNameSuffix() const +{ + if (mLegacyMode) + return std::make_pair(true, LetterCase::UPPERCASE); + + bool suffix {false}; + LetterCase letterCase {LetterCase::UPPERCASE}; + + for (auto& text : mContainerTextComponents) { + if (text->getThemeMetadata() == "description" && text->getSystemNameSuffix()) { + suffix = true; + letterCase = text->getLetterCaseSystemNameSuffix(); + break; + } + } + + return std::make_pair(suffix, letterCase); +} + void GamelistView::onFileChanged(FileData* file, bool reloadGamelist) { if (reloadGamelist) { @@ -379,6 +398,8 @@ void GamelistView::onThemeChanged(const std::shared_ptr& theme) addChild(mPrimary); } + mSystemNameSuffix = mPrimary->getSystemNameSuffix(); + populateList(mRoot->getChildrenListToDisplay(), mRoot); // Check whether the primary component uses the left and right buttons for its navigation. @@ -893,7 +914,25 @@ void GamelistView::updateView(const CursorState& state) continue; } - text->setValue(getMetadataValue()); + if (metadata == "name" && file->getSystem()->isCollection() && + text->getSystemNameSuffix()) { + const LetterCase letterCase {text->getLetterCaseSystemNameSuffix()}; + std::string suffix {" ["}; + if (letterCase == LetterCase::UPPERCASE) + suffix.append( + Utils::String::toUpper(file->getSourceFileData()->getSystem()->getName())); + else if (letterCase == LetterCase::CAPITALIZE) + suffix.append(Utils::String::toCapitalized( + file->getSourceFileData()->getSystem()->getName())); + else + suffix.append(file->getSourceFileData()->getSystem()->getName()); + suffix.append("]"); + + text->setValue(getMetadataValue() + suffix); + } + else { + text->setValue(getMetadataValue()); + } } for (auto& date : mDateTimeComponents) { diff --git a/es-app/src/views/GamelistView.h b/es-app/src/views/GamelistView.h index 4723d2d16..68e370b4a 100644 --- a/es-app/src/views/GamelistView.h +++ b/es-app/src/views/GamelistView.h @@ -18,6 +18,8 @@ public: GamelistView(FileData* root); ~GamelistView(); + const std::pair getDescriptionSystemNameSuffix() const; + // Called when a FileData* is added, has its metadata changed, or is removed. void onFileChanged(FileData* file, bool reloadGamelist) override; void onShow() override; diff --git a/es-app/src/views/SystemView.cpp b/es-app/src/views/SystemView.cpp index e32c3a0af..681cf19cb 100644 --- a/es-app/src/views/SystemView.cpp +++ b/es-app/src/views/SystemView.cpp @@ -1240,8 +1240,35 @@ void SystemView::updateGameSelectors() std::vector games {gameSelector->getGames()}; if (games.size() > gameSelectorEntry) { const std::string metadata {text->getThemeMetadata()}; - if (metadata == "name") - text->setValue(games.at(gameSelectorEntry)->metadata.get("name")); + if (metadata == "name") { + if (mPrimary->getSelected()->isCollection() && text->getSystemNameSuffix()) { + const LetterCase letterCase {text->getLetterCaseSystemNameSuffix()}; + std::string suffix {" ["}; + if (letterCase == LetterCase::UPPERCASE) { + suffix.append(Utils::String::toUpper(games.at(gameSelectorEntry) + ->getSourceFileData() + ->getSystem() + ->getName())); + } + else if (letterCase == LetterCase::CAPITALIZE) { + suffix.append(Utils::String::toCapitalized(games.at(gameSelectorEntry) + ->getSourceFileData() + ->getSystem() + ->getName())); + } + else { + suffix.append(games.at(gameSelectorEntry) + ->getSourceFileData() + ->getSystem() + ->getName()); + } + suffix.append("]"); + text->setValue(games.at(gameSelectorEntry)->metadata.get("name") + suffix); + } + else { + text->setValue(games.at(gameSelectorEntry)->metadata.get("name")); + } + } if (metadata == "description") text->setValue(games.at(gameSelectorEntry)->metadata.get("desc")); if (metadata == "rating") diff --git a/es-core/src/Settings.cpp b/es-core/src/Settings.cpp index b7342e720..4b15effab 100644 --- a/es-core/src/Settings.cpp +++ b/es-core/src/Settings.cpp @@ -235,7 +235,6 @@ void Settings::setDefaults() mStringMap["CollectionCustomGrouping"] = {"unthemed", "unthemed"}; mBoolMap["FavFirstCustom"] = {false, false}; mBoolMap["FavStarCustom"] = {false, false}; - mBoolMap["CollectionShowSystemInfo"] = {true, true}; // Other settings. mStringMap["MediaDirectory"] = {"", ""}; diff --git a/es-core/src/ThemeData.cpp b/es-core/src/ThemeData.cpp index 5431b144d..6590344d3 100644 --- a/es-core/src/ThemeData.cpp +++ b/es-core/src/ThemeData.cpp @@ -182,6 +182,8 @@ std::map> {"letterCaseAutoCollections", STRING}, {"letterCaseCustomCollections", STRING}, {"lineSpacing", FLOAT}, + {"systemNameSuffix", BOOLEAN}, + {"letterCaseSystemNameSuffix", STRING}, {"fadeAbovePrimary", BOOLEAN}, {"zIndex", FLOAT}, {"legacyZIndexMode", STRING}}}, // For backward compatibility with legacy themes. @@ -227,6 +229,8 @@ std::map> {"letterCaseAutoCollections", STRING}, {"letterCaseCustomCollections", STRING}, {"lineSpacing", FLOAT}, + {"systemNameSuffix", BOOLEAN}, + {"letterCaseSystemNameSuffix", STRING}, {"fadeAbovePrimary", BOOLEAN}, {"zIndex", FLOAT}}}, {"textlist", @@ -259,6 +263,8 @@ std::map> {"lineSpacing", FLOAT}, {"indicators", STRING}, {"collectionIndicators", STRING}, + {"systemNameSuffix", BOOLEAN}, + {"letterCaseSystemNameSuffix", STRING}, {"fadeAbovePrimary", BOOLEAN}, {"zIndex", FLOAT}}}, {"image", @@ -368,6 +374,8 @@ std::map> {"systemdata", STRING}, {"metadata", STRING}, {"defaultValue", STRING}, + {"systemNameSuffix", BOOLEAN}, + {"letterCaseSystemNameSuffix", STRING}, {"metadataElement", BOOLEAN}, {"gameselector", STRING}, {"gameselectorEntry", UNSIGNED_INTEGER}, diff --git a/es-core/src/components/TextComponent.cpp b/es-core/src/components/TextComponent.cpp index f07d5ba5d..f8d7b477d 100644 --- a/es-core/src/components/TextComponent.cpp +++ b/es-core/src/components/TextComponent.cpp @@ -20,6 +20,8 @@ TextComponent::TextComponent() , mColorOpacity {1.0f} , mBgColorOpacity {0.0f} , mRenderBackground {false} + , mSystemNameSuffix {false} + , mLetterCaseSystemNameSuffix {LetterCase::UPPERCASE} , mUppercase {false} , mLowercase {false} , mCapitalize {false} @@ -49,6 +51,8 @@ TextComponent::TextComponent(const std::string& text, , mColorOpacity {1.0f} , mBgColorOpacity {0.0f} , mRenderBackground {false} + , mSystemNameSuffix {false} + , mLetterCaseSystemNameSuffix {LetterCase::UPPERCASE} , mUppercase {false} , mLowercase {false} , mCapitalize {false} @@ -465,6 +469,12 @@ void TextComponent::applyTheme(const std::shared_ptr& theme, mDefaultValue = defaultValue; } } + if (mThemeMetadata == "name" || mThemeMetadata == "description") { + if (elem->has("systemNameSuffix")) + mSystemNameSuffix = elem->get("systemNameSuffix"); + else + mSystemNameSuffix = true; + } break; } } @@ -475,6 +485,24 @@ void TextComponent::applyTheme(const std::shared_ptr& theme, } } + if (properties & LETTER_CASE && elem->has("letterCaseSystemNameSuffix")) { + const std::string& letterCase {elem->get("letterCaseSystemNameSuffix")}; + if (letterCase == "uppercase") { + mLetterCaseSystemNameSuffix = LetterCase::UPPERCASE; + } + else if (letterCase == "lowercase") { + mLetterCaseSystemNameSuffix = LetterCase::LOWERCASE; + } + else if (letterCase == "capitalize") { + mLetterCaseSystemNameSuffix = LetterCase::CAPITALIZE; + } + else { + LOG(LogWarning) << "TextComponent: Invalid theme configuration, property " + "\"letterCaseSystemNameSuffix\" for element \"" + << element.substr(5) << "\" defined as \"" << letterCase << "\""; + } + } + if (properties & LETTER_CASE && elem->has("letterCase")) { const std::string& letterCase {elem->get("letterCase")}; if (letterCase == "uppercase") { diff --git a/es-core/src/components/TextComponent.h b/es-core/src/components/TextComponent.h index 58d4e2015..c4b912cca 100644 --- a/es-core/src/components/TextComponent.h +++ b/es-core/src/components/TextComponent.h @@ -77,6 +77,8 @@ public: std::shared_ptr getFont() const override { return mFont; } Alignment getHorizontalAlignment() { return mHorizontalAlignment; } Alignment getVerticalAlignment() { return mVerticalAlignment; } + const bool getSystemNameSuffix() const { return mSystemNameSuffix; } + const LetterCase getLetterCaseSystemNameSuffix() const { return mLetterCaseSystemNameSuffix; } int getTextCacheGlyphHeight() override { @@ -108,6 +110,8 @@ private: float mColorOpacity; float mBgColorOpacity; bool mRenderBackground; + bool mSystemNameSuffix; + LetterCase mLetterCaseSystemNameSuffix; bool mUppercase; bool mLowercase; diff --git a/es-core/src/components/primary/CarouselComponent.h b/es-core/src/components/primary/CarouselComponent.h index 3b4e4018e..6c3524b20 100644 --- a/es-core/src/components/primary/CarouselComponent.h +++ b/es-core/src/components/primary/CarouselComponent.h @@ -73,6 +73,11 @@ public: { return mLetterCaseCustomCollections; } + const bool getSystemNameSuffix() const override { return mSystemNameSuffix; } + const LetterCase getLetterCaseSystemNameSuffix() const override + { + return mLetterCaseSystemNameSuffix; + } void setCancelTransitionsCallback(const std::function& func) override { @@ -176,6 +181,8 @@ private: LetterCase mLetterCaseAutoCollections; LetterCase mLetterCaseCustomCollections; float mLineSpacing; + bool mSystemNameSuffix; + LetterCase mLetterCaseSystemNameSuffix; bool mFadeAbovePrimary; }; @@ -233,6 +240,8 @@ CarouselComponent::CarouselComponent() , mLetterCaseAutoCollections {LetterCase::UNDEFINED} , mLetterCaseCustomCollections {LetterCase::UNDEFINED} , mLineSpacing {1.5f} + , mSystemNameSuffix {true} + , mLetterCaseSystemNameSuffix {LetterCase::UPPERCASE} , mFadeAbovePrimary {false} { } @@ -1611,6 +1620,27 @@ void CarouselComponent::applyTheme(const std::shared_ptr& theme, } } + if (mGamelistView && elem->has("systemNameSuffix")) + mSystemNameSuffix = elem->get("systemNameSuffix"); + + if (mGamelistView && properties & LETTER_CASE && elem->has("letterCaseSystemNameSuffix")) { + const std::string& letterCase {elem->get("letterCaseSystemNameSuffix")}; + if (letterCase == "uppercase") { + mLetterCaseSystemNameSuffix = LetterCase::UPPERCASE; + } + else if (letterCase == "lowercase") { + mLetterCaseSystemNameSuffix = LetterCase::LOWERCASE; + } + else if (letterCase == "capitalize") { + mLetterCaseSystemNameSuffix = LetterCase::CAPITALIZE; + } + else { + LOG(LogWarning) << "CarouselComponent: Invalid theme configuration, property " + "\"letterCaseSystemNameSuffix\" for element \"" + << element.substr(9) << "\" defined as \"" << letterCase << "\""; + } + } + if (elem->has("fadeAbovePrimary")) mFadeAbovePrimary = elem->get("fadeAbovePrimary"); diff --git a/es-core/src/components/primary/GridComponent.h b/es-core/src/components/primary/GridComponent.h index db2260647..1d40a1788 100644 --- a/es-core/src/components/primary/GridComponent.h +++ b/es-core/src/components/primary/GridComponent.h @@ -66,6 +66,11 @@ public: { return mLetterCaseCustomCollections; } + const bool getSystemNameSuffix() const override { return mSystemNameSuffix; } + const LetterCase getLetterCaseSystemNameSuffix() const override + { + return mLetterCaseSystemNameSuffix; + } const std::string& getDefaultGridImage() const { return mDefaultImage; } void setDefaultImage(std::string defaultImage) { mDefaultImage = defaultImage; } bool input(InputConfig* config, Input input) override; @@ -176,6 +181,8 @@ private: LetterCase mLetterCaseAutoCollections; LetterCase mLetterCaseCustomCollections; float mLineSpacing; + bool mSystemNameSuffix; + LetterCase mLetterCaseSystemNameSuffix; bool mFadeAbovePrimary; }; @@ -229,6 +236,8 @@ GridComponent::GridComponent() , mLetterCaseAutoCollections {LetterCase::UNDEFINED} , mLetterCaseCustomCollections {LetterCase::UNDEFINED} , mLineSpacing {1.5f} + , mSystemNameSuffix {true} + , mLetterCaseSystemNameSuffix {LetterCase::UPPERCASE} , mFadeAbovePrimary {false} { } @@ -1180,6 +1189,27 @@ void GridComponent::applyTheme(const std::shared_ptr& theme, } } + if (mGamelistView && elem->has("systemNameSuffix")) + mSystemNameSuffix = elem->get("systemNameSuffix"); + + if (mGamelistView && properties & LETTER_CASE && elem->has("letterCaseSystemNameSuffix")) { + const std::string& letterCase {elem->get("letterCaseSystemNameSuffix")}; + if (letterCase == "uppercase") { + mLetterCaseSystemNameSuffix = LetterCase::UPPERCASE; + } + else if (letterCase == "lowercase") { + mLetterCaseSystemNameSuffix = LetterCase::LOWERCASE; + } + else if (letterCase == "capitalize") { + mLetterCaseSystemNameSuffix = LetterCase::CAPITALIZE; + } + else { + LOG(LogWarning) << "GridComponent: Invalid theme configuration, property " + "\"letterCaseSystemNameSuffix\" for element \"" + << element.substr(5) << "\" defined as \"" << letterCase << "\""; + } + } + if (elem->has("fadeAbovePrimary")) mFadeAbovePrimary = elem->get("fadeAbovePrimary"); diff --git a/es-core/src/components/primary/PrimaryComponent.h b/es-core/src/components/primary/PrimaryComponent.h index dcde939d6..0564de3db 100644 --- a/es-core/src/components/primary/PrimaryComponent.h +++ b/es-core/src/components/primary/PrimaryComponent.h @@ -47,6 +47,8 @@ public: virtual const LetterCase getLetterCase() const = 0; virtual const LetterCase getLetterCaseAutoCollections() const = 0; virtual const LetterCase getLetterCaseCustomCollections() const = 0; + virtual const bool getSystemNameSuffix() const = 0; + virtual const LetterCase getLetterCaseSystemNameSuffix() const = 0; // Functions used by some primary components. virtual void onDemandTextureLoad() {} diff --git a/es-core/src/components/primary/TextListComponent.h b/es-core/src/components/primary/TextListComponent.h index e9d7ef550..007ca572f 100644 --- a/es-core/src/components/primary/TextListComponent.h +++ b/es-core/src/components/primary/TextListComponent.h @@ -84,6 +84,11 @@ public: { return mLetterCaseCustomCollections; } + const bool getSystemNameSuffix() const override { return mSystemNameSuffix; } + const LetterCase getLetterCaseSystemNameSuffix() const override + { + return mLetterCaseSystemNameSuffix; + } private: void onShow() override { mLoopTime = 0; } @@ -145,6 +150,8 @@ private: float mLineSpacing; std::string mIndicators; std::string mCollectionIndicators; + bool mSystemNameSuffix; + LetterCase mLetterCaseSystemNameSuffix; bool mFadeAbovePrimary; }; @@ -181,6 +188,8 @@ TextListComponent::TextListComponent() , mLineSpacing {1.5f} , mIndicators {"symbols"} , mCollectionIndicators {"symbols"} + , mSystemNameSuffix {true} + , mLetterCaseSystemNameSuffix {LetterCase::UPPERCASE} , mFadeAbovePrimary {false} { } @@ -711,6 +720,27 @@ void TextListComponent::applyTheme(const std::shared_ptr& theme, } } + if (mGamelistView && elem->has("systemNameSuffix")) + mSystemNameSuffix = elem->get("systemNameSuffix"); + + if (mGamelistView && properties & LETTER_CASE && elem->has("letterCaseSystemNameSuffix")) { + const std::string& letterCase {elem->get("letterCaseSystemNameSuffix")}; + if (letterCase == "uppercase") { + mLetterCaseSystemNameSuffix = LetterCase::UPPERCASE; + } + else if (letterCase == "lowercase") { + mLetterCaseSystemNameSuffix = LetterCase::LOWERCASE; + } + else if (letterCase == "capitalize") { + mLetterCaseSystemNameSuffix = LetterCase::CAPITALIZE; + } + else { + LOG(LogWarning) << "TextListComponent: Invalid theme configuration, property " + "\"letterCaseSystemNameSuffix\" for element \"" + << element.substr(9) << "\" defined as \"" << letterCase << "\""; + } + } + if (elem->has("selectorImagePath")) { const std::string& path {elem->get("selectorImagePath")}; bool tile {elem->has("selectorImageTile") && elem->get("selectorImageTile")};