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)
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);
}
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<FileData*> 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,21 +965,25 @@ 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();
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());
}
}
}
for (auto it = mCustomCollectionSystemsData.cbegin();
it != mCustomCollectionSystemsData.cend(); it++) {

View file

@ -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.

View file

@ -436,8 +436,15 @@ void GuiMetaDataEd::save()
mSavedCallback();
// Update all collections where the game is present.
if (mScraperParams.game->getType() == 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.

View file

@ -40,6 +40,7 @@ public:
virtual const std::vector<std::string>& 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<FileData*>& 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<FileData*> mList;
// 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
{ 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<FileData*>& 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<FileData*> mGrid;
// 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* getFirstGameEntry() = 0;
virtual const std::vector<std::string>& getFirstLetterIndex() = 0;
virtual void addPlaceholder(FileData*) = 0;
virtual void copyCursorHistory(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 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;