diff --git a/es-app/src/CollectionSystemsManager.cpp b/es-app/src/CollectionSystemsManager.cpp index 7a0c1f10e..587119e17 100644 --- a/es-app/src/CollectionSystemsManager.cpp +++ b/es-app/src/CollectionSystemsManager.cpp @@ -289,7 +289,8 @@ void CollectionSystemsManager::updateSystemsList() } } -void CollectionSystemsManager::refreshCollectionSystems(FileData* file) +void CollectionSystemsManager::refreshCollectionSystems(FileData* file, + bool refreshDisabledAutoCollections) { if (!file->getSystem()->isGameSystem() || file->getType() != GAME) return; @@ -315,7 +316,8 @@ void CollectionSystemsManager::refreshCollectionSystems(FileData* file) for (auto sysDataIt = allCollections.cbegin(); sysDataIt != allCollections.cend(); sysDataIt++) { - if (sysDataIt->second.isEnabled) + if (sysDataIt->second.isEnabled || (refreshDisabledAutoCollections && + !sysDataIt->second.system->isGroupedCustomCollection())) updateCollectionSystem(file, sysDataIt->second); } } @@ -674,9 +676,7 @@ bool CollectionSystemsManager::toggleGameInCollection(FileData* file) systemViewToUpdate->getRootFolder()->sort(rootFolder->getSortTypeFromString( rootFolder->getSortTypeString()), Settings::getInstance()->getBool("FavFirstCustom")); - if (rootFolder->getChildren().size() == 0) { - ViewController::get()->reloadGameListView(systemViewToUpdate); - } + ViewController::get()->reloadGameListView(systemViewToUpdate); updateCollectionFolderMetadata(systemViewToUpdate); } @@ -712,6 +712,10 @@ bool CollectionSystemsManager::toggleGameInCollection(FileData* file) file->getSourceFileData()->getSystem()->getIndex()->addToIndex(file); file->getSourceFileData()->getSystem()->onMetaDataSavePoint(); refreshCollectionSystems(file->getSourceFileData()); + if (mAutoCollectionSystemsData["favorites"].isEnabled) + ViewController::get()-> + reloadGameListView(mAutoCollectionSystemsData["favorites"].system); + } if (adding) s = new GuiInfoPopup(mWindow, "ADDED '" + @@ -947,6 +951,10 @@ void CollectionSystemsManager::repopulateCollection(SystemData* sysData) std::vector systemEntries = autoSystem->system->getRootFolder()->getFilesRecursive(true, true, false); + // Flag the collection as not populated so it gets repopulated. + autoSystem->isPopulated = false; + populateAutoCollection(autoSystem); + if (systemEntries.empty()) return; @@ -957,19 +965,23 @@ void CollectionSystemsManager::repopulateCollection(SystemData* sysData) delete entry; } - // Flag the collection as not populated so it gets repopulated. autoSystem->isPopulated = false; populateAutoCollection(autoSystem); // The cursor value is now pointing to some random memory address so we need to set - // it to something valid, as done here by selecting the first child. This does however - // not mean it's the first row of the gamelist, so we follow up with selecting the - // first entry after that. If doing this second step without the first step we would - // crash the application as it would try to access the old (now invalid) pointer. + // it to something valid. For empty collections we need to first create a placeholder + // and then point to this, and for collections with games in them we select the first + // entry. auto autoView = ViewController::get()->getGameListView(autoSystem->system).get(); - autoView->setCursor(autoSystem->system->getRootFolder()-> - getChildrenRecursive().front()); - autoView->setCursor(autoView->getFirstEntry()); + if (autoSystem->system->getRootFolder()->getChildren().size() == 0) { + autoView->addPlaceholder(autoSystem->system->getRootFolder()); + autoView->setCursor(autoView->getLastEntry()); + } + else { + autoView->setCursor(autoSystem->system->getRootFolder()-> + getChildrenRecursive().front()); + autoView->setCursor(autoView->getFirstEntry()); + } } } diff --git a/es-app/src/CollectionSystemsManager.h b/es-app/src/CollectionSystemsManager.h index b90fd8288..051a8dfdd 100644 --- a/es-app/src/CollectionSystemsManager.h +++ b/es-app/src/CollectionSystemsManager.h @@ -83,7 +83,7 @@ public: // Functions to manage collection files related to a source FileData: // Update all collection files related to the source file. - void refreshCollectionSystems(FileData* file); + void refreshCollectionSystems(FileData* file, bool refreshDisabledAutoCollections = false); // Update the collections, such as when marking or unmarking a game as favorite. void updateCollectionSystem(FileData* file, CollectionSystemData sysData); // Delete all collection files from all collection systems related to the source file. diff --git a/es-app/src/guis/GuiMetaDataEd.cpp b/es-app/src/guis/GuiMetaDataEd.cpp index 6c86191d1..6c5c32bc6 100644 --- a/es-app/src/guis/GuiMetaDataEd.cpp +++ b/es-app/src/guis/GuiMetaDataEd.cpp @@ -436,8 +436,15 @@ void GuiMetaDataEd::save() mSavedCallback(); // Update all collections where the game is present. - if (mScraperParams.game->getType() == GAME) - CollectionSystemsManager::get()->refreshCollectionSystems(mScraperParams.game); + if (mScraperParams.game->getType() == GAME) { + // Update disabled auto collections as well when hiding a game, as otherwise these + // collections could get invalid gamelist cursor positions. A cursor pointing to a + // removed game would crash the application upon enabling the collections. + if (hideGameWhileHidden) + CollectionSystemsManager::get()->refreshCollectionSystems(mScraperParams.game, true); + else + CollectionSystemsManager::get()->refreshCollectionSystems(mScraperParams.game); + } // If game counting was re-enabled for the game, then reactivate it in any custom collections // where it may exist. diff --git a/es-app/src/views/gamelist/BasicGameListView.h b/es-app/src/views/gamelist/BasicGameListView.h index e9fd71282..7bd84f1e0 100644 --- a/es-app/src/views/gamelist/BasicGameListView.h +++ b/es-app/src/views/gamelist/BasicGameListView.h @@ -40,6 +40,7 @@ public: virtual const std::vector& getFirstLetterIndex() override { return mFirstLetterIndex; }; + virtual void addPlaceholder(FileData* firstEntry = nullptr) override; protected: virtual std::string getQuickSystemSelectRightButton() override; @@ -47,7 +48,6 @@ protected: virtual void populateList(const std::vector& files, FileData* firstEntry) override; virtual void remove(FileData* game, bool deleteFile) override; virtual void removeMedia(FileData* game) override; - virtual void addPlaceholder(FileData* firstEntry = nullptr); TextListComponent mList; // Points to the first game in the list, i.e. the first entry which is of the type 'GAME'. diff --git a/es-app/src/views/gamelist/GridGameListView.h b/es-app/src/views/gamelist/GridGameListView.h index b9eabfc26..a5981d4b4 100644 --- a/es-app/src/views/gamelist/GridGameListView.h +++ b/es-app/src/views/gamelist/GridGameListView.h @@ -50,6 +50,7 @@ public: virtual const std::vector& getFirstLetterIndex() override { return mFirstLetterIndex; }; + virtual void addPlaceholder(FileData* firstEntry = nullptr) override; protected: virtual void update(int deltaTime) override; @@ -58,7 +59,6 @@ protected: virtual void populateList(const std::vector& files, FileData* firstEntry) override; virtual void remove(FileData* game, bool deleteFile) override; virtual void removeMedia(FileData* game) override; - virtual void addPlaceholder(FileData* firstEntry = nullptr); ImageGridComponent mGrid; // Points to the first game in the list, i.e. the first entry which is of the type 'GAME'. diff --git a/es-app/src/views/gamelist/IGameListView.h b/es-app/src/views/gamelist/IGameListView.h index b7591d1b2..9ebd7075a 100644 --- a/es-app/src/views/gamelist/IGameListView.h +++ b/es-app/src/views/gamelist/IGameListView.h @@ -45,6 +45,7 @@ public: virtual FileData* getLastEntry() = 0; virtual FileData* getFirstGameEntry() = 0; virtual const std::vector& getFirstLetterIndex() = 0; + virtual void addPlaceholder(FileData*) = 0; virtual void copyCursorHistory(std::vector& cursorHistory) = 0; virtual void populateCursorHistory(std::vector& cursorHistory) = 0; diff --git a/es-app/src/views/gamelist/ISimpleGameListView.h b/es-app/src/views/gamelist/ISimpleGameListView.h index 0cdcbce12..4e9ad130a 100644 --- a/es-app/src/views/gamelist/ISimpleGameListView.h +++ b/es-app/src/views/gamelist/ISimpleGameListView.h @@ -29,6 +29,7 @@ public: virtual FileData* getCursor() override = 0; virtual void setCursor(FileData*) override = 0; + virtual void addPlaceholder(FileData*) override = 0; virtual bool input(InputConfig* config, Input input) override; virtual void launch(FileData* game) override = 0;