[desktop] Clean up game list code, fix external watcher crash, and fix macOS flickering (#4106)

- Remove unnecessary icon update code (the UI reloads this stuff anyways); test on Windows please
- Cleaned up a bunch of duplicated/unused code within the game list
- Fix the game list constantly reloading on macOS
  * When you reconstruct the entire directory list on the watcher the directoryChanged signal fires on macOS--seems like a behavioral change that occurred somewhere in the 6.8 release cycle--and it would enter an infinite loop very quickly
  * To fix this, only the differences between the current and old watch list are accounted for on both ends.
  * Since this bug is now fixed, macOS uses Qt 6.11.1 now. Should theoretically improve our situation.
- Fix the external content watcher crashing; the worker would attempt to read files that didn't exist without any bounds since its cache was still pointing to that file.

This supersedes and replaces #4099.

Reviewed-on: https://git.eden-emu.dev/eden-emu/eden/pulls/4106
Reviewed-by: Lizzie <lizzie@eden-emu.dev>
Reviewed-by: MaranBr <maranbr@eden-emu.dev>
This commit is contained in:
crueter
2026-06-19 22:55:29 +02:00
parent 7c0e993b5b
commit 102d254530
12 changed files with 181 additions and 277 deletions
+38 -43
View File
@@ -32,11 +32,11 @@
#include "qt_common/config/uisettings.h"
#include "qt_common/qt_common.h"
#include "yuzu/compatibility_list.h"
#include "qt_common/game_list/game_list_p.h"
#include "yuzu/compatibility_list.h"
#include "qt_common/game_list/worker.h"
#include "qt_common/game_list/model.h"
#include "qt_common/game_list/worker.h"
namespace {
@@ -391,6 +391,25 @@ void GameListWorker::ScanFileSystem(ScanTarget target, const std::string& dir_pa
std::vector<u64> program_ids;
loader->ReadProgramIds(program_ids);
const auto addEntry = [this, physical_name,
parent_dir](std::unique_ptr<Loader::AppLoader>& app_loader,
const u64 id) {
std::vector<u8> icon;
[[maybe_unused]] const auto res1 = app_loader->ReadIcon(icon);
std::string name = " ";
[[maybe_unused]] const auto res3 = app_loader->ReadTitle(name);
const FileSys::PatchManager patch{id, system.GetFileSystemController(),
system.GetContentProvider()};
auto entry = MakeGameListEntry(
physical_name, name, Common::FS::GetSize(physical_name), icon, *app_loader,
id, compatibility_list, play_time_manager, patch);
RecordEvent([=](GameListModel* model) { model->AddEntry(entry, parent_dir); });
};
if (res2 == Loader::ResultStatus::Success && program_ids.size() > 1 &&
(file_type == Loader::FileType::XCI || file_type == Loader::FileType::NSP)) {
for (const auto id : program_ids) {
@@ -404,38 +423,10 @@ void GameListWorker::ScanFileSystem(ScanTarget target, const std::string& dir_pa
continue;
}
std::vector<u8> icon;
[[maybe_unused]] const auto res1 = loader->ReadIcon(icon);
std::string name = " ";
[[maybe_unused]] const auto res3 = loader->ReadTitle(name);
const FileSys::PatchManager patch{id, system.GetFileSystemController(),
system.GetContentProvider()};
auto entry = MakeGameListEntry(
physical_name, name, Common::FS::GetSize(physical_name), icon, *loader,
id, compatibility_list, play_time_manager, patch);
RecordEvent(
[=](GameListModel* model) { model->AddEntry(entry, parent_dir); });
addEntry(loader, id);
}
} else {
std::vector<u8> icon;
[[maybe_unused]] const auto res1 = loader->ReadIcon(icon);
std::string name = " ";
[[maybe_unused]] const auto res3 = loader->ReadTitle(name);
const FileSys::PatchManager patch{program_id, system.GetFileSystemController(),
system.GetContentProvider()};
auto entry = MakeGameListEntry(
physical_name, name, Common::FS::GetSize(physical_name), icon, *loader,
program_id, compatibility_list, play_time_manager, patch);
RecordEvent(
[=](GameListModel* model) { model->AddEntry(entry, parent_dir); });
addEntry(loader, program_id);
}
}
} else if (is_dir) {
@@ -466,29 +457,33 @@ void GameListWorker::run() {
break;
}
GameListDir* game_list_dir;
bool scan = false;
if (game_dir.path == std::string("SDMC")) {
auto* const game_list_dir = new GameListDir(game_dir, GameListItemType::SdmcDir);
DirEntryReady(game_list_dir);
AddTitlesToGameList(game_list_dir);
game_list_dir = new GameListDir(game_dir, GameListItemType::SdmcDir);
} else if (game_dir.path == std::string("UserNAND")) {
auto* const game_list_dir = new GameListDir(game_dir, GameListItemType::UserNandDir);
DirEntryReady(game_list_dir);
AddTitlesToGameList(game_list_dir);
game_list_dir = new GameListDir(game_dir, GameListItemType::UserNandDir);
} else if (game_dir.path == std::string("SysNAND")) {
auto* const game_list_dir = new GameListDir(game_dir, GameListItemType::SysNandDir);
DirEntryReady(game_list_dir);
AddTitlesToGameList(game_list_dir);
game_list_dir = new GameListDir(game_dir, GameListItemType::SysNandDir);
} else {
const QString qpath = QString::fromStdString(game_dir.path);
if (QDir(qpath).exists()) {
watch_list.append(qpath);
}
auto* const game_list_dir = new GameListDir(game_dir);
DirEntryReady(game_list_dir);
game_list_dir = new GameListDir(game_dir);
scan = true;
}
DirEntryReady(game_list_dir);
if (scan) {
ScanFileSystem(ScanTarget::FillManualContentProvider, game_dir.path, game_dir.deep_scan,
game_list_dir);
ScanFileSystem(ScanTarget::PopulateGameList, game_dir.path, game_dir.deep_scan,
game_list_dir);
} else {
AddTitlesToGameList(game_list_dir);
}
}