Fixed an issue where enabling an auto collection that contained a hidden game could crash the application.

Also fixed an issue where the view style would not change when adding or removing games from collections.
This commit is contained in:
Leon Styhre 2021-02-04 20:14:20 +01:00
parent c9c5e53066
commit f84570705e
7 changed files with 39 additions and 18 deletions

View file

@ -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) if (!file->getSystem()->isGameSystem() || file->getType() != GAME)
return; return;
@ -315,7 +316,8 @@ void CollectionSystemsManager::refreshCollectionSystems(FileData* file)
for (auto sysDataIt = allCollections.cbegin(); for (auto sysDataIt = allCollections.cbegin();
sysDataIt != allCollections.cend(); sysDataIt++) { sysDataIt != allCollections.cend(); sysDataIt++) {
if (sysDataIt->second.isEnabled) if (sysDataIt->second.isEnabled || (refreshDisabledAutoCollections &&
!sysDataIt->second.system->isGroupedCustomCollection()))
updateCollectionSystem(file, sysDataIt->second); updateCollectionSystem(file, sysDataIt->second);
} }
} }
@ -674,9 +676,7 @@ bool CollectionSystemsManager::toggleGameInCollection(FileData* file)
systemViewToUpdate->getRootFolder()->sort(rootFolder->getSortTypeFromString( systemViewToUpdate->getRootFolder()->sort(rootFolder->getSortTypeFromString(
rootFolder->getSortTypeString()), rootFolder->getSortTypeString()),
Settings::getInstance()->getBool("FavFirstCustom")); Settings::getInstance()->getBool("FavFirstCustom"));
if (rootFolder->getChildren().size() == 0) { ViewController::get()->reloadGameListView(systemViewToUpdate);
ViewController::get()->reloadGameListView(systemViewToUpdate);
}
updateCollectionFolderMetadata(systemViewToUpdate); updateCollectionFolderMetadata(systemViewToUpdate);
} }
@ -712,6 +712,10 @@ bool CollectionSystemsManager::toggleGameInCollection(FileData* file)
file->getSourceFileData()->getSystem()->getIndex()->addToIndex(file); file->getSourceFileData()->getSystem()->getIndex()->addToIndex(file);
file->getSourceFileData()->getSystem()->onMetaDataSavePoint(); file->getSourceFileData()->getSystem()->onMetaDataSavePoint();
refreshCollectionSystems(file->getSourceFileData()); refreshCollectionSystems(file->getSourceFileData());
if (mAutoCollectionSystemsData["favorites"].isEnabled)
ViewController::get()->
reloadGameListView(mAutoCollectionSystemsData["favorites"].system);
} }
if (adding) if (adding)
s = new GuiInfoPopup(mWindow, "ADDED '" + s = new GuiInfoPopup(mWindow, "ADDED '" +
@ -947,6 +951,10 @@ void CollectionSystemsManager::repopulateCollection(SystemData* sysData)
std::vector<FileData*> systemEntries = std::vector<FileData*> systemEntries =
autoSystem->system->getRootFolder()->getFilesRecursive(true, true, false); 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()) if (systemEntries.empty())
return; return;
@ -957,19 +965,23 @@ void CollectionSystemsManager::repopulateCollection(SystemData* sysData)
delete entry; delete entry;
} }
// Flag the collection as not populated so it gets repopulated.
autoSystem->isPopulated = false; autoSystem->isPopulated = false;
populateAutoCollection(autoSystem); populateAutoCollection(autoSystem);
// The cursor value is now pointing to some random memory address so we need to set // 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 // it to something valid. For empty collections we need to first create a placeholder
// not mean it's the first row of the gamelist, so we follow up with selecting the // and then point to this, and for collections with games in them we select the first
// first entry after that. If doing this second step without the first step we would // entry.
// crash the application as it would try to access the old (now invalid) pointer.
auto autoView = ViewController::get()->getGameListView(autoSystem->system).get(); auto autoView = ViewController::get()->getGameListView(autoSystem->system).get();
autoView->setCursor(autoSystem->system->getRootFolder()-> if (autoSystem->system->getRootFolder()->getChildren().size() == 0) {
getChildrenRecursive().front()); autoView->addPlaceholder(autoSystem->system->getRootFolder());
autoView->setCursor(autoView->getFirstEntry()); autoView->setCursor(autoView->getLastEntry());
}
else {
autoView->setCursor(autoSystem->system->getRootFolder()->
getChildrenRecursive().front());
autoView->setCursor(autoView->getFirstEntry());
}
} }
} }

View file

@ -83,7 +83,7 @@ public:
// Functions to manage collection files related to a source FileData: // Functions to manage collection files related to a source FileData:
// Update all collection files related to the source file. // 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. // Update the collections, such as when marking or unmarking a game as favorite.
void updateCollectionSystem(FileData* file, CollectionSystemData sysData); void updateCollectionSystem(FileData* file, CollectionSystemData sysData);
// Delete all collection files from all collection systems related to the source file. // Delete all collection files from all collection systems related to the source file.

View file

@ -436,8 +436,15 @@ void GuiMetaDataEd::save()
mSavedCallback(); mSavedCallback();
// Update all collections where the game is present. // Update all collections where the game is present.
if (mScraperParams.game->getType() == GAME) if (mScraperParams.game->getType() == GAME) {
CollectionSystemsManager::get()->refreshCollectionSystems(mScraperParams.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 // If game counting was re-enabled for the game, then reactivate it in any custom collections
// where it may exist. // where it may exist.

View file

@ -40,6 +40,7 @@ public:
virtual const std::vector<std::string>& getFirstLetterIndex() override virtual const std::vector<std::string>& getFirstLetterIndex() override
{ return mFirstLetterIndex; }; { return mFirstLetterIndex; };
virtual void addPlaceholder(FileData* firstEntry = nullptr) override;
protected: protected:
virtual std::string getQuickSystemSelectRightButton() override; virtual std::string getQuickSystemSelectRightButton() override;
@ -47,7 +48,6 @@ protected:
virtual void populateList(const std::vector<FileData*>& files, FileData* firstEntry) override; virtual void populateList(const std::vector<FileData*>& files, FileData* firstEntry) override;
virtual void remove(FileData* game, bool deleteFile) override; virtual void remove(FileData* game, bool deleteFile) override;
virtual void removeMedia(FileData* game) override; virtual void removeMedia(FileData* game) override;
virtual void addPlaceholder(FileData* firstEntry = nullptr);
TextListComponent<FileData*> mList; TextListComponent<FileData*> mList;
// Points to the first game in the list, i.e. the first entry which is of the type 'GAME'. // Points to the first game in the list, i.e. the first entry which is of the type 'GAME'.

View file

@ -50,6 +50,7 @@ public:
virtual const std::vector<std::string>& getFirstLetterIndex() override virtual const std::vector<std::string>& getFirstLetterIndex() override
{ return mFirstLetterIndex; }; { return mFirstLetterIndex; };
virtual void addPlaceholder(FileData* firstEntry = nullptr) override;
protected: protected:
virtual void update(int deltaTime) override; virtual void update(int deltaTime) override;
@ -58,7 +59,6 @@ protected:
virtual void populateList(const std::vector<FileData*>& files, FileData* firstEntry) override; virtual void populateList(const std::vector<FileData*>& files, FileData* firstEntry) override;
virtual void remove(FileData* game, bool deleteFile) override; virtual void remove(FileData* game, bool deleteFile) override;
virtual void removeMedia(FileData* game) override; virtual void removeMedia(FileData* game) override;
virtual void addPlaceholder(FileData* firstEntry = nullptr);
ImageGridComponent<FileData*> mGrid; ImageGridComponent<FileData*> mGrid;
// Points to the first game in the list, i.e. the first entry which is of the type 'GAME'. // Points to the first game in the list, i.e. the first entry which is of the type 'GAME'.

View file

@ -45,6 +45,7 @@ public:
virtual FileData* getLastEntry() = 0; virtual FileData* getLastEntry() = 0;
virtual FileData* getFirstGameEntry() = 0; virtual FileData* getFirstGameEntry() = 0;
virtual const std::vector<std::string>& getFirstLetterIndex() = 0; virtual const std::vector<std::string>& getFirstLetterIndex() = 0;
virtual void addPlaceholder(FileData*) = 0;
virtual void copyCursorHistory(std::vector<FileData*>& cursorHistory) = 0; virtual void copyCursorHistory(std::vector<FileData*>& cursorHistory) = 0;
virtual void populateCursorHistory(std::vector<FileData*>& cursorHistory) = 0; virtual void populateCursorHistory(std::vector<FileData*>& cursorHistory) = 0;

View file

@ -29,6 +29,7 @@ public:
virtual FileData* getCursor() override = 0; virtual FileData* getCursor() override = 0;
virtual void setCursor(FileData*) override = 0; virtual void setCursor(FileData*) override = 0;
virtual void addPlaceholder(FileData*) override = 0;
virtual bool input(InputConfig* config, Input input) override; virtual bool input(InputConfig* config, Input input) override;
virtual void launch(FileData* game) override = 0; virtual void launch(FileData* game) override = 0;