Moved game counting to the sort function and improved the custom collection handling.

This commit is contained in:
Leon Styhre 2020-09-21 18:13:27 +02:00
parent c5ecfb4e36
commit 1c831249da
10 changed files with 100 additions and 51 deletions

View file

@ -23,7 +23,9 @@ Many bugs have been fixed, and numerous features that were only partially implem
* Updated scraper to support additional media files, detailed configuration of what to scrape, semi-automatic mode etc. * Updated scraper to support additional media files, detailed configuration of what to scrape, semi-automatic mode etc.
* In the metadata editor, any values updated by the single-game scraper or by the user are now highlighted using a different font color * In the metadata editor, any values updated by the single-game scraper or by the user are now highlighted using a different font color
* Files or folders can now be flagged for exclusion when scraping with the multi-scraper, and for folders it can be set to apply recursively * Files or folders can now be flagged for exclusion when scraping with the multi-scraper, and for folders it can be set to apply recursively
* Gamelist sorting now working as expected and is persistent throughout the application session * Gamelist sorting is now working as expected and is persistent throughout the application session
* Game counting is now done during sorting instead of every time a system is selected. This should make the UI more responsive in case of large game libraries
* Added a system view counter for favorite games in addition to the total number of games
* Added support for jumping to the start and end of gamelists and menus using the controller trigger buttons (or equivalent keyboard mappings) * Added support for jumping to the start and end of gamelists and menus using the controller trigger buttons (or equivalent keyboard mappings)
* Full navigation sound support, configurable per theme with a fallback to the built-in sounds if the theme does not support it * Full navigation sound support, configurable per theme with a fallback to the built-in sounds if the theme does not support it
* New default theme rbsimple-DE bundled with the software, this theme is largely based on recalbox-multi by the Recalbox community * New default theme rbsimple-DE bundled with the software, this theme is largely based on recalbox-multi by the Recalbox community

View file

@ -1,4 +1,6 @@
// SPDX-License-Identifier: MIT
// //
// EmulationStation Desktop Edition
// CollectionSystemManager.cpp // CollectionSystemManager.cpp
// //
// Manages collections of the following two types: // Manages collections of the following two types:
@ -30,8 +32,9 @@
#include "Settings.h" #include "Settings.h"
#include "SystemData.h" #include "SystemData.h"
#include "ThemeData.h" #include "ThemeData.h"
#include <pugixml.hpp>
#include <fstream> #include <fstream>
#include <pugixml.hpp>
std::string myCollectionsName = "collections"; std::string myCollectionsName = "collections";
@ -237,8 +240,7 @@ void CollectionSystemManager::updateSystemsList()
} }
// If we were editing a custom collection, and it's no longer enabled, exit edit mode. // If we were editing a custom collection, and it's no longer enabled, exit edit mode.
if (mIsEditingCustom && !mEditingCollectionSystemData->isEnabled) if (mIsEditingCustom && !mEditingCollectionSystemData->isEnabled) {
{
exitEditMode(); exitEditMode();
} }
} }
@ -385,14 +387,18 @@ void CollectionSystemManager::updateCollectionSystem(FileData* file, CollectionS
if (sysData.decl.isCustom && if (sysData.decl.isCustom &&
Settings::getInstance()->getBool("UseCustomCollectionsSystem")) { Settings::getInstance()->getBool("UseCustomCollectionsSystem")) {
// In case of a returned null pointer, we know there is no parent. // In case of a returned null pointer, we know there is no parent.
if (rootFolder->getParent() == nullptr) if (rootFolder->getParent() == nullptr) {
ViewController::get()->onFileChanged(rootFolder, FILE_METADATA_CHANGED); ViewController::get()->onFileChanged(rootFolder, FILE_METADATA_CHANGED);
else }
else {
rootFolder->getParent()->sort(rootFolder->getSortTypeFromString(
rootFolder->getSortTypeString()), mFavoritesSorting);
ViewController::get()->onFileChanged( ViewController::get()->onFileChanged(
rootFolder->getParent(), FILE_METADATA_CHANGED); rootFolder->getParent(), FILE_METADATA_CHANGED);
} }
} }
} }
}
} }
void CollectionSystemManager::trimCollectionCount(FileData* rootFolder, int limit) void CollectionSystemManager::trimCollectionCount(FileData* rootFolder, int limit)
@ -591,6 +597,9 @@ bool CollectionSystemManager::toggleGameInCollection(FileData* file)
ViewController::get()->getGameListView(systemViewToUpdate).get()-> ViewController::get()->getGameListView(systemViewToUpdate).get()->
remove(collectionEntry, false); remove(collectionEntry, false);
systemViewToUpdate->getRootFolder()->sort(rootFolder->getSortTypeFromString(
rootFolder->getSortTypeString()),
Settings::getInstance()->getBool("FavFirstCustom"));
} }
else { else {
// We didn't find it here, so we should add it. // We didn't find it here, so we should add it.
@ -601,10 +610,6 @@ bool CollectionSystemManager::toggleGameInCollection(FileData* file)
onFileChanged(newGame, FILE_METADATA_CHANGED); onFileChanged(newGame, FILE_METADATA_CHANGED);
if (name == "recent") if (name == "recent")
rootFolder->sort(rootFolder->getSortTypeFromString("last played, descending")); rootFolder->sort(rootFolder->getSortTypeFromString("last played, descending"));
else
rootFolder->sort(rootFolder->getSortTypeFromString(
rootFolder->getSortTypeString()),
Settings::getInstance()->getBool("FavFirstCustom"));
ViewController::get()->onFileChanged(systemViewToUpdate-> ViewController::get()->onFileChanged(systemViewToUpdate->
getRootFolder(), FILE_SORTED); getRootFolder(), FILE_SORTED);
@ -612,6 +617,7 @@ bool CollectionSystemManager::toggleGameInCollection(FileData* file)
// Add to bundle index as well, if needed. // Add to bundle index as well, if needed.
if (systemViewToUpdate != sysData) if (systemViewToUpdate != sysData)
systemViewToUpdate->getIndex()->addToIndex(newGame); systemViewToUpdate->getIndex()->addToIndex(newGame);
refreshCollectionSystems(newGame);
} }
updateCollectionFolderMetadata(sysData); updateCollectionFolderMetadata(sysData);
} }
@ -783,15 +789,15 @@ SystemData* CollectionSystemManager::addNewCustomCollection(std::string name)
decl.name = name; decl.name = name;
decl.longName = name; decl.longName = name;
return createNewCollectionEntry(name, decl); return createNewCollectionEntry(name, decl, true, true);
} }
// Create a new empty collection system based on the name and declaration. // Create a new empty collection system based on the name and declaration.
SystemData* CollectionSystemManager::createNewCollectionEntry( SystemData* CollectionSystemManager::createNewCollectionEntry(
std::string name, CollectionSystemDecl sysDecl, bool index) std::string name, CollectionSystemDecl sysDecl, bool index, bool custom)
{ {
SystemData* newSys = new SystemData( SystemData* newSys = new SystemData(
name, sysDecl.longName, mCollectionEnvData, sysDecl.themeFolder, true); name, sysDecl.longName, mCollectionEnvData, sysDecl.themeFolder, true, custom);
CollectionSystemData newCollectionData; CollectionSystemData newCollectionData;
newCollectionData.system = newSys; newCollectionData.system = newSys;

View file

@ -1,4 +1,6 @@
// SPDX-License-Identifier: MIT
// //
// EmulationStation Desktop Edition
// CollectionSystemManager.h // CollectionSystemManager.h
// //
// Manages collections of the following two types: // Manages collections of the following two types:
@ -17,7 +19,6 @@
// the required re-sort and refresh of the gamelists. // the required re-sort and refresh of the gamelists.
// //
#pragma once
#ifndef ES_APP_COLLECTION_SYSTEM_MANAGER_H #ifndef ES_APP_COLLECTION_SYSTEM_MANAGER_H
#define ES_APP_COLLECTION_SYSTEM_MANAGER_H #define ES_APP_COLLECTION_SYSTEM_MANAGER_H
@ -111,7 +112,7 @@ private:
void initCustomCollectionSystems(); void initCustomCollectionSystems();
SystemData* getAllGamesCollection(); SystemData* getAllGamesCollection();
SystemData* createNewCollectionEntry(std::string name, SystemData* createNewCollectionEntry(std::string name,
CollectionSystemDecl sysDecl, bool index = true); CollectionSystemDecl sysDecl, bool index = true, bool custom = false);
void populateAutoCollection(CollectionSystemData* sysData); void populateAutoCollection(CollectionSystemData* sysData);
void populateCustomCollection(CollectionSystemData* sysData); void populateCustomCollection(CollectionSystemData* sysData);
@ -126,9 +127,7 @@ private:
std::vector<std::string> getUserCollectionThemeFolders(); std::vector<std::string> getUserCollectionThemeFolders();
void trimCollectionCount(FileData* rootFolder, int limit); void trimCollectionCount(FileData* rootFolder, int limit);
bool themeFolderExists(std::string folder); bool themeFolderExists(std::string folder);
bool includeFileInAutoCollections(FileData* file); bool includeFileInAutoCollections(FileData* file);
SystemData* mCustomCollectionsBundle; SystemData* mCustomCollectionsBundle;

View file

@ -436,7 +436,8 @@ void FileData::removeChild(FileData* file)
assert(false); assert(false);
} }
void FileData::sort(ComparisonFunction& comparator, bool ascending) void FileData::sort(ComparisonFunction& comparator, bool ascending,
std::pair<unsigned int, unsigned int>& gameCount)
{ {
mFirstLetterIndex.clear(); mFirstLetterIndex.clear();
mOnlyFolders = true; mOnlyFolders = true;
@ -507,6 +508,14 @@ void FileData::sort(ComparisonFunction& comparator, bool ascending)
} }
for (auto it = mChildren.cbegin(); it != mChildren.cend(); it++) { for (auto it = mChildren.cbegin(); it != mChildren.cend(); it++) {
// Game count, which will be displayed in the system view.
if ((*it)->getType() == GAME && (*it)->getCountAsGame()) {
if (!(*it)->getFavorite())
gameCount.first++;
else
gameCount.second++;
}
if ((*it)->getType() != FOLDER) if ((*it)->getType() != FOLDER)
mOnlyFolders = false; mOnlyFolders = false;
@ -517,7 +526,7 @@ void FileData::sort(ComparisonFunction& comparator, bool ascending)
} }
// Iterate through any child folders. // Iterate through any child folders.
if ((*it)->getChildren().size() > 0) if ((*it)->getChildren().size() > 0)
(*it)->sort(comparator, ascending); (*it)->sort(comparator, ascending, gameCount);
} }
// If there are only folders in the gamelist, then it makes sense to still // If there are only folders in the gamelist, then it makes sense to still
@ -540,7 +549,8 @@ void FileData::sort(ComparisonFunction& comparator, bool ascending)
mFirstLetterIndex.insert(mFirstLetterIndex.begin(), FOLDER_CHAR); mFirstLetterIndex.insert(mFirstLetterIndex.begin(), FOLDER_CHAR);
} }
void FileData::sortFavoritesOnTop(ComparisonFunction& comparator, bool ascending) void FileData::sortFavoritesOnTop(ComparisonFunction& comparator, bool ascending,
std::pair<unsigned int, unsigned int>& gameCount)
{ {
mFirstLetterIndex.clear(); mFirstLetterIndex.clear();
mOnlyFolders = true; mOnlyFolders = true;
@ -560,6 +570,14 @@ void FileData::sortFavoritesOnTop(ComparisonFunction& comparator, bool ascending
continue; continue;
} }
// Game count, which will be displayed in the system view.
if (mChildren[i]->getType() == GAME && mChildren[i]->getCountAsGame()) {
if (!mChildren[i]->getFavorite())
gameCount.first++;
else
gameCount.second++;
}
if (foldersOnTop && mChildren[i]->getType() == FOLDER) { if (foldersOnTop && mChildren[i]->getType() == FOLDER) {
if (!mChildren[i]->getFavorite()) if (!mChildren[i]->getFavorite())
mChildrenFolders.push_back(mChildren[i]); mChildrenFolders.push_back(mChildren[i]);
@ -664,13 +682,13 @@ void FileData::sortFavoritesOnTop(ComparisonFunction& comparator, bool ascending
for (auto it = mChildrenFavoritesFolders.cbegin(); it != for (auto it = mChildrenFavoritesFolders.cbegin(); it !=
mChildrenFavoritesFolders.cend(); it++) { mChildrenFavoritesFolders.cend(); it++) {
if ((*it)->getChildren().size() > 0) if ((*it)->getChildren().size() > 0)
(*it)->sortFavoritesOnTop(comparator, ascending); (*it)->sortFavoritesOnTop(comparator, ascending, gameCount);
} }
// Iterate through any child folders. // Iterate through any child folders.
for (auto it = mChildrenFolders.cbegin(); it != mChildrenFolders.cend(); it++) { for (auto it = mChildrenFolders.cbegin(); it != mChildrenFolders.cend(); it++) {
if ((*it)->getChildren().size() > 0) if ((*it)->getChildren().size() > 0)
(*it)->sortFavoritesOnTop(comparator, ascending); (*it)->sortFavoritesOnTop(comparator, ascending, gameCount);
} }
if (!ascending) { if (!ascending) {
@ -695,10 +713,12 @@ void FileData::sortFavoritesOnTop(ComparisonFunction& comparator, bool ascending
void FileData::sort(const SortType& type, bool mFavoritesOnTop) void FileData::sort(const SortType& type, bool mFavoritesOnTop)
{ {
mGameCount = std::make_pair(0, 0);
if (mFavoritesOnTop) if (mFavoritesOnTop)
sortFavoritesOnTop(*type.comparisonFunction, type.ascending); sortFavoritesOnTop(*type.comparisonFunction, type.ascending, mGameCount);
else else
sort(*type.comparisonFunction, type.ascending); sort(*type.comparisonFunction, type.ascending, mGameCount);
} }
FileData::SortType FileData::getSortTypeFromString(std::string desc) { FileData::SortType FileData::getSortTypeFromString(std::string desc) {

View file

@ -51,6 +51,7 @@ public:
const bool getFavorite(); const bool getFavorite();
const bool getHidden(); const bool getHidden();
const bool getCountAsGame(); const bool getCountAsGame();
const std::pair<unsigned int, unsigned int> getGameCount() { return mGameCount; };
const bool getExcludeFromScraper(); const bool getExcludeFromScraper();
const std::vector<FileData*> getChildrenRecursive() const; const std::vector<FileData*> getChildrenRecursive() const;
inline FileType getType() const { return mType; } inline FileType getType() const { return mType; }
@ -123,8 +124,10 @@ public:
description(sortDescription) {} description(sortDescription) {}
}; };
void sort(ComparisonFunction& comparator, bool ascending = true); void sort(ComparisonFunction& comparator, bool ascending,
void sortFavoritesOnTop(ComparisonFunction& comparator, bool ascending = true); std::pair<unsigned int, unsigned int>& gameCount);
void sortFavoritesOnTop(ComparisonFunction& comparator, bool ascending,
std::pair<unsigned int, unsigned int>& gameCount);
void sort(const SortType& type, bool mFavoritesOnTop = false); void sort(const SortType& type, bool mFavoritesOnTop = false);
MetaDataList metadata; MetaDataList metadata;
@ -151,6 +154,8 @@ private:
std::vector<FileData*> mChildren; std::vector<FileData*> mChildren;
std::vector<FileData*> mFilteredChildren; std::vector<FileData*> mFilteredChildren;
std::vector<std::string> mFirstLetterIndex; std::vector<std::string> mFirstLetterIndex;
// The pair includes non-favorite games, and favorite games.
std::pair<unsigned int, unsigned int> mGameCount;
bool mOnlyFolders; bool mOnlyFolders;
// Used for flagging a game for deletion from its gamelist.xml file. // Used for flagging a game for deletion from its gamelist.xml file.
bool mDeletionFlag; bool mDeletionFlag;

View file

@ -1,4 +1,6 @@
// SPDX-License-Identifier: MIT
// //
// EmulationStation Desktop Edition
// SystemData.cpp // SystemData.cpp
// //
// Provides data structures for the game systems and populates and indexes them based // Provides data structures for the game systems and populates and indexes them based
@ -12,6 +14,7 @@
#include "resources/ResourceManager.h" #include "resources/ResourceManager.h"
#include "utils/FileSystemUtil.h" #include "utils/FileSystemUtil.h"
#include "utils/StringUtil.h" #include "utils/StringUtil.h"
#include "views/UIModeController.h"
#include "CollectionSystemManager.h" #include "CollectionSystemManager.h"
#include "FileFilterIndex.h" #include "FileFilterIndex.h"
#include "FileSorts.h" #include "FileSorts.h"
@ -20,10 +23,9 @@
#include "Platform.h" #include "Platform.h"
#include "Settings.h" #include "Settings.h"
#include "ThemeData.h" #include "ThemeData.h"
#include "views/UIModeController.h"
#include <pugixml.hpp>
#include <fstream> #include <fstream>
#include <pugixml.hpp>
std::vector<SystemData*> SystemData::sSystemVector; std::vector<SystemData*> SystemData::sSystemVector;
@ -32,12 +34,14 @@ SystemData::SystemData(
const std::string& fullName, const std::string& fullName,
SystemEnvironmentData* envData, SystemEnvironmentData* envData,
const std::string& themeFolder, const std::string& themeFolder,
bool CollectionSystem) bool CollectionSystem,
bool CustomCollectionSystem)
: mName(name), : mName(name),
mFullName(fullName), mFullName(fullName),
mEnvData(envData), mEnvData(envData),
mThemeFolder(themeFolder), mThemeFolder(themeFolder),
mIsCollectionSystem(CollectionSystem), mIsCollectionSystem(CollectionSystem),
mIsCustomCollectionSystem(CustomCollectionSystem),
mIsGameSystem(true), mIsGameSystem(true),
mScrapeFlag(false) mScrapeFlag(false)
{ {
@ -402,9 +406,11 @@ std::string SystemData::getConfigPath(bool forWrite)
bool SystemData::isVisible() bool SystemData::isVisible()
{ {
return (getDisplayedGameCount() > 0 || // This function doesn't make much sense at the moment; if a game system does not have any
(UIModeController::getInstance()->isUIModeFull() && mIsCollectionSystem) || // games available, it will not be processed during startup and will as such not exist.
(mIsCollectionSystem && mName == "favorites")); // In the future this function may be used for an option to hide specific systems, but
// for the time being all systems will always be visible.
return true;
} }
SystemData* SystemData::getNext() const SystemData* SystemData::getNext() const
@ -488,11 +494,6 @@ bool SystemData::hasGamelist() const
return (Utils::FileSystem::exists(getGamelistPath(false))); return (Utils::FileSystem::exists(getGamelistPath(false)));
} }
unsigned int SystemData::getGameCount() const
{
return (unsigned int)mRootFolder->getFilesRecursive(GAME).size();
}
SystemData* SystemData::getRandomSystem(const SystemData* currentSystem) SystemData* SystemData::getRandomSystem(const SystemData* currentSystem)
{ {
unsigned int total = 0; unsigned int total = 0;
@ -612,10 +613,12 @@ FileData* SystemData::getRandomGame(const FileData* currentGame)
return gameList.at(target); return gameList.at(target);
} }
unsigned int SystemData::getDisplayedGameCount() const std::pair<unsigned int, unsigned int> SystemData::getDisplayedGameCount() const
{ {
// Pass the flag to only count games that are marked with the flag 'countasgame'. // Return all games for the system which are marked as 'countasgame'. As this flag is set
return (unsigned int)mRootFolder->getFilesRecursive(GAME, true, false).size(); // by default, normally most games will be included in the number returned from here.
// The actual game counting takes place in FileData during sorting.
return mRootFolder->getGameCount();
} }
void SystemData::loadTheme() void SystemData::loadTheme()

View file

@ -1,4 +1,6 @@
// SPDX-License-Identifier: MIT
// //
// EmulationStation Desktop Edition
// SystemData.h // SystemData.h
// //
// Provides data structures for the game systems and populates and indexes them based // Provides data structures for the game systems and populates and indexes them based
@ -7,7 +9,6 @@
// loading. // loading.
// //
#pragma once
#ifndef ES_APP_SYSTEM_DATA_H #ifndef ES_APP_SYSTEM_DATA_H
#define ES_APP_SYSTEM_DATA_H #define ES_APP_SYSTEM_DATA_H
@ -36,7 +37,8 @@ public:
const std::string& fullName, const std::string& fullName,
SystemEnvironmentData* envData, SystemEnvironmentData* envData,
const std::string& themeFolder, const std::string& themeFolder,
bool CollectionSystem = false); bool CollectionSystem = false,
bool CustomCollectionSystem = false);
~SystemData(); ~SystemData();
@ -60,8 +62,7 @@ public:
bool hasGamelist() const; bool hasGamelist() const;
std::string getThemePath() const; std::string getThemePath() const;
unsigned int getGameCount() const; std::pair<unsigned int, unsigned int> getDisplayedGameCount() const;
unsigned int getDisplayedGameCount() const;
bool getScrapeFlag() { return mScrapeFlag; }; bool getScrapeFlag() { return mScrapeFlag; };
void setScrapeFlag(bool scrapeflag) { mScrapeFlag = scrapeflag; } void setScrapeFlag(bool scrapeflag) { mScrapeFlag = scrapeflag; }
@ -80,6 +81,7 @@ public:
inline std::vector<SystemData*>::const_reverse_iterator getRevIterator() const inline std::vector<SystemData*>::const_reverse_iterator getRevIterator() const
{ return std::find(sSystemVector.crbegin(), sSystemVector.crend(), this); }; { return std::find(sSystemVector.crbegin(), sSystemVector.crend(), this); };
inline bool isCollection() { return mIsCollectionSystem; }; inline bool isCollection() { return mIsCollectionSystem; };
inline bool isCustomCollection() { return mIsCustomCollectionSystem; };
inline bool isGameSystem() { return mIsGameSystem; }; inline bool isGameSystem() { return mIsGameSystem; };
bool isVisible(); bool isVisible();
@ -101,6 +103,7 @@ public:
private: private:
bool mIsCollectionSystem; bool mIsCollectionSystem;
bool mIsCustomCollectionSystem;
bool mIsGameSystem; bool mIsGameSystem;
bool mScrapeFlag; // Only used by scraper GUI to remember which systems to scrape. bool mScrapeFlag; // Only used by scraper GUI to remember which systems to scrape.
std::string mName; std::string mName;

View file

@ -283,16 +283,25 @@ void SystemView::onCursorChanged(const CursorState& /*state*/)
Math::lerp(infoStartOpacity, 0.f, t) * 255)); Math::lerp(infoStartOpacity, 0.f, t) * 255));
}, static_cast<int>(infoStartOpacity * (goFast ? 10 : 150))); }, static_cast<int>(infoStartOpacity * (goFast ? 10 : 150)));
unsigned int gameCount = getSelected()->getDisplayedGameCount(); std::pair<unsigned int, unsigned int> gameCount = getSelected()->getDisplayedGameCount();
// Also change the text after we've fully faded out. // Also change the text after we've fully faded out.
setAnimation(infoFadeOut, 0, [this, gameCount] { setAnimation(infoFadeOut, 0, [this, gameCount] {
std::stringstream ss; std::stringstream ss;
unsigned int totalGameCount = gameCount.first + gameCount.second;
if (!getSelected()->isGameSystem()) if (!getSelected()->isGameSystem())
ss << "CONFIGURATION"; ss << "CONFIGURATION";
else if (getSelected()->isCollection() && (getSelected()->getName() == "favorites"))
ss << totalGameCount << " GAME" << (totalGameCount == 1 ? " " : "S");
// The 'recent' gamelist has probably been trimmed after sorting, so we'll cap it at
// its maximum limit of 50 games.
else if (getSelected()->isCollection() && (getSelected()->getName() == "recent"))
ss << (totalGameCount > 50 ? 50 : totalGameCount) << " GAME" <<
(totalGameCount == 1 ? " " : "S");
else else
ss << gameCount << " GAMES AVAILABLE"; ss << totalGameCount << " GAME" << (totalGameCount == 1 ? " " : "S ") << "(" <<
gameCount.second << " FAVORITE" << (gameCount.second == 1 ? ")" : "S)");
mSystemInfo.setText(ss.str()); mSystemInfo.setText(ss.str());
}, false, 1); }, false, 1);

View file

@ -200,7 +200,8 @@ bool ISimpleGameListView::input(InputConfig* config, Input input)
else else
favoritesSorting = Settings::getInstance()->getBool("FavoritesFirst"); favoritesSorting = Settings::getInstance()->getBool("FavoritesFirst");
if (favoritesSorting && static_cast<std::string>(getName()) != "recent") { if (favoritesSorting && static_cast<std::string>(
mRoot->getSystem()->getName()) != "recent") {
FileData* entryToSelect; FileData* entryToSelect;
// Add favorite flag. // Add favorite flag.
if (!getCursor()->getFavorite()) { if (!getCursor()->getFavorite()) {
@ -300,9 +301,11 @@ bool ISimpleGameListView::input(InputConfig* config, Input input)
} }
else if (CollectionSystemManager::get()->toggleGameInCollection(entryToUpdate)) { else if (CollectionSystemManager::get()->toggleGameInCollection(entryToUpdate)) {
// Jump to the first entry in the gamelist if the last favorite was unmarked. // Jump to the first entry in the gamelist if the last favorite was unmarked.
if (foldersOnTop && removedLastFavorite) if (foldersOnTop && removedLastFavorite &&
!entryToUpdate->getSystem()->isCustomCollection())
setCursor(getFirstGameEntry()); setCursor(getFirstGameEntry());
else if (removedLastFavorite) else if (removedLastFavorite &&
!entryToUpdate->getSystem()->isCustomCollection())
setCursor(getFirstEntry()); setCursor(getFirstEntry());
return true; return true;
} }

View file

@ -9,9 +9,9 @@
#ifndef ES_APP_VIEWS_GAME_LIST_ISIMPLE_GAME_LIST_VIEW_H #ifndef ES_APP_VIEWS_GAME_LIST_ISIMPLE_GAME_LIST_VIEW_H
#define ES_APP_VIEWS_GAME_LIST_ISIMPLE_GAME_LIST_VIEW_H #define ES_APP_VIEWS_GAME_LIST_ISIMPLE_GAME_LIST_VIEW_H
#include "views/gamelist/IGameListView.h"
#include "components/ImageComponent.h" #include "components/ImageComponent.h"
#include "components/TextComponent.h" #include "components/TextComponent.h"
#include "views/gamelist/IGameListView.h"
#include <stack> #include <stack>
@ -46,7 +46,6 @@ protected:
ImageComponent mBackground; ImageComponent mBackground;
std::vector<GuiComponent*> mThemeExtras; std::vector<GuiComponent*> mThemeExtras;
std::stack<FileData*> mCursorStack; std::stack<FileData*> mCursorStack;
}; };