From 953124934563267240c48cac6d0027a682ba3595 Mon Sep 17 00:00:00 2001 From: collecting <217662237+CollectingW@users.noreply.github.com> Date: Tue, 19 May 2026 05:01:44 -0400 Subject: [PATCH] fix: CLI QT Issue w/ booting directly from a file --- src/citron/game_list.cpp | 25 ++++++++-------- src/citron/game_list.h | 1 - src/citron/game_list_worker.cpp | 51 +++++---------------------------- src/citron/game_list_worker.h | 23 ++------------- 4 files changed, 23 insertions(+), 77 deletions(-) diff --git a/src/citron/game_list.cpp b/src/citron/game_list.cpp index 38f7837130..5e65803320 100644 --- a/src/citron/game_list.cpp +++ b/src/citron/game_list.cpp @@ -1166,6 +1166,9 @@ GameList::GameList(std::shared_ptr vfs_, GMainWindow* parent) : QWidget{parent}, vfs{std::move(vfs_)}, provider{provider_}, play_time_manager{play_time_manager_}, system{system_} { + qRegisterMetaType("GameListDir*"); + qRegisterMetaType>("QList"); + watcher = new QFileSystemWatcher(this); connect(watcher, &QFileSystemWatcher::directoryChanged, this, &GameList::RefreshGameDirectory); @@ -2192,9 +2195,6 @@ void GameList::ClearFilter() { search_field->clear(); } -void GameList::WorkerEvent() { - current_worker->ProcessEvents(this); -} void GameList::AddDirEntry(GameListDir* entry_items) { if (!entry_items) @@ -2950,9 +2950,7 @@ void GameList::DonePopulating(const QStringList& watch_list) { QTimer::singleShot(0, this, [this]() { current_worker.reset(); }); } - for (const auto& watch_dir : watch_list) { - watcher->addPath(watch_dir); - } + emit PopulatingCompleted(); if (progress_bar) { @@ -3004,15 +3002,13 @@ void GameList::DonePopulating(const QStringList& watch_list) { watcher->removePaths(watch_dirs); } constexpr int LIMIT_WATCH_DIRECTORIES = 5000; - constexpr int SLICE_SIZE = 25; int len = std::min(static_cast(watch_list.size()), LIMIT_WATCH_DIRECTORIES); tree_view->setEnabled(true); tree_view->setFocus(); - for (int i = 0; i < len; i += SLICE_SIZE) { - watcher->addPaths(watch_list.mid(i, i + SLICE_SIZE)); - QCoreApplication::processEvents(); - } + const bool old_signals_blocked = watcher->blockSignals(true); + watcher->addPaths(watch_list.mid(0, len)); + watcher->blockSignals(old_signals_blocked); int children_total = 0; for (int i = 1; i < item_model->rowCount() - 1; ++i) { children_total += item_model->item(i, 0)->rowCount(); @@ -3869,7 +3865,11 @@ void GameList::PopulateAsync(QVector& game_dirs, bool is_sm current_worker = std::make_unique( vfs, provider, game_dirs, compatibility_list, play_time_manager, system, main_window->GetMultiplayerState()->GetSession()); - connect(current_worker.get(), &GameListWorker::DataAvailable, this, &GameList::WorkerEvent, + connect(current_worker.get(), &GameListWorker::DirEntryReady, this, &GameList::AddDirEntry, + Qt::QueuedConnection); + connect(current_worker.get(), &GameListWorker::EntryReady, this, &GameList::AddEntry, + Qt::QueuedConnection); + connect(current_worker.get(), &GameListWorker::Finished, this, &GameList::DonePopulating, Qt::QueuedConnection); if (progress_bar) { @@ -3923,6 +3923,7 @@ void GameList::RefreshGameDirectory() { void GameList::CancelPopulation() { if (current_worker) { + current_worker->disconnect(); current_worker->Cancel(); } current_worker.reset(); diff --git a/src/citron/game_list.h b/src/citron/game_list.h index 687af5d328..5de41afd7c 100644 --- a/src/citron/game_list.h +++ b/src/citron/game_list.h @@ -209,7 +209,6 @@ protected: private: friend class GameListWorker; - void WorkerEvent(); void AddDirEntry(GameListDir* entry_items); void AddEntry(const QList& entry_items, const QString& parent_path); diff --git a/src/citron/game_list_worker.cpp b/src/citron/game_list_worker.cpp index 37dfc91fd4..c9d5937e53 100644 --- a/src/citron/game_list_worker.cpp +++ b/src/citron/game_list_worker.cpp @@ -540,41 +540,6 @@ void GameListWorker::Cancel() { stop_requested.store(true); } -void GameListWorker::ProcessEvents(GameList* game_list) { - while (true) { - std::function func; - { - // Lock queue to protect concurrent modification. - std::scoped_lock lk(lock); - - // If we can't pop a function, return. - if (queued_events.empty()) { - return; - } - - // Pop a function. - func = std::move(queued_events.back()); - queued_events.pop_back(); - } - - // Run the function. - func(game_list); - } -} - -template -void GameListWorker::RecordEvent(F&& func) { - { - // Lock queue to protect concurrent modification. - std::scoped_lock lk(lock); - - // Add the function into the front of the queue. - queued_events.emplace_front(std::move(func)); - } - - // Data now available. - emit DataAvailable(); -} void GameListWorker::AddTitlesToGameList(const QString& parent_path, const std::map>& online_stats) { @@ -631,7 +596,7 @@ void GameListWorker::AddTitlesToGameList(const QString& parent_path, auto entry = MakeGameListEntry(file->GetFullPath(), name, original_name, file->GetSize(), icon, *loader, program_id, compatibility_list, play_time_manager, patch, online_stats); - RecordEvent([=](GameList* game_list) { game_list->AddEntry(entry, parent_path); }); + emit EntryReady(entry, parent_path); } } @@ -721,8 +686,7 @@ void GameListWorker::ScanFileSystem(ScanTarget target, const std::string& dir_pa MakeGameListEntry(physical_name, name, original_name, cached->file_size, icon, *loader, cached->program_id, compatibility_list, play_time_manager, patch, online_stats); - RecordEvent( - [=](GameList* game_list) { game_list->AddEntry(entry, parent_path); }); + emit EntryReady(entry, parent_path); } } } @@ -803,8 +767,7 @@ void GameListWorker::ScanFileSystem(ScanTarget target, const std::string& dir_pa auto entry = MakeGameListEntry(physical_name, name, original_name, file_size, icon, *loader, program_id, compatibility_list, play_time_manager, patch, online_stats); - RecordEvent( - [=](GameList* game_list) { game_list->AddEntry(entry, parent_path); }); + emit EntryReady(entry, parent_path); } } } @@ -876,8 +839,8 @@ void GameListWorker::run() { if (total_files <= 0) total_files = 1; - const auto DirEntryReady = [&](GameListDir* game_list_dir) { - RecordEvent([=](GameList* game_list) { game_list->AddDirEntry(game_list_dir); }); + const auto TriggerDirEntryReady = [&](GameListDir* game_list_dir) { + emit DirEntryReady(game_list_dir); }; for (UISettings::GameDir& game_dir : game_dirs) { @@ -890,13 +853,13 @@ void GameListWorker::run() { watch_list.append(QString::fromStdString(game_dir.path)); auto* const game_list_dir = new GameListDir(game_dir); const QString dir_path_q = game_list_dir->data(GameListDir::FullPathRole).toString(); - DirEntryReady(game_list_dir); + TriggerDirEntryReady(game_list_dir); ScanFileSystem(ScanTarget::Both, game_dir.path, game_dir.deep_scan, dir_path_q, online_stats, processed_files, total_files); } - RecordEvent([this](GameList* game_list) { game_list->DonePopulating(watch_list); }); + emit Finished(watch_list); SaveGameMetadataCache(); processing_completed.Set(); } diff --git a/src/citron/game_list_worker.h b/src/citron/game_list_worker.h index e189a991c8..921e140c59 100644 --- a/src/citron/game_list_worker.h +++ b/src/citron/game_list_worker.h @@ -11,7 +11,6 @@ #include #include // Required for std::pair - #include #include #include @@ -23,7 +22,6 @@ #include "common/thread.h" #include "network/announce_multiplayer_session.h" - namespace Core { class System; } @@ -67,24 +65,12 @@ public: /// Request the worker to stop. void Cancel(); -public: - /** - * Synchronously processes any events queued by the worker. - * - * AddDirEntry is called on the game list for every discovered directory. - * AddEntry is called on the game list for every discovered program. - * DonePopulating is called on the game list when processing completes. - */ - void ProcessEvents(GameList* game_list); - signals: - void DataAvailable(); + void DirEntryReady(GameListDir* entry_items); + void EntryReady(const QList& entry_items, const QString& parent_path); + void Finished(const QStringList& watch_list); void ProgressUpdated(int percent); -private: - template - void RecordEvent(F&& func); - private: void AddTitlesToGameList(const QString& parent_path, const std::map>& online_stats); @@ -102,9 +88,6 @@ private: QStringList watch_list; - std::mutex lock; - std::condition_variable cv; - std::deque> queued_events; std::atomic_bool stop_requested = false; Common::Event processing_completed;