mirror of
https://github.com/citron-neo/emulator.git
synced 2026-07-05 15:21:57 -07:00
fix: CLI QT Issue w/ booting directly from a file
This commit is contained in:
+13
-12
@@ -1166,6 +1166,9 @@ GameList::GameList(std::shared_ptr<FileSys::VfsFilesystem> vfs_,
|
||||
GMainWindow* parent)
|
||||
: QWidget{parent}, vfs{std::move(vfs_)}, provider{provider_},
|
||||
play_time_manager{play_time_manager_}, system{system_} {
|
||||
qRegisterMetaType<GameListDir*>("GameListDir*");
|
||||
qRegisterMetaType<QList<QStandardItem*>>("QList<QStandardItem*>");
|
||||
|
||||
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<int>(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<UISettings::GameDir>& game_dirs, bool is_sm
|
||||
current_worker = std::make_unique<GameListWorker>(
|
||||
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();
|
||||
|
||||
@@ -209,7 +209,6 @@ protected:
|
||||
|
||||
private:
|
||||
friend class GameListWorker;
|
||||
void WorkerEvent();
|
||||
|
||||
void AddDirEntry(GameListDir* entry_items);
|
||||
void AddEntry(const QList<QStandardItem*>& entry_items, const QString& parent_path);
|
||||
|
||||
@@ -540,41 +540,6 @@ void GameListWorker::Cancel() {
|
||||
stop_requested.store(true);
|
||||
}
|
||||
|
||||
void GameListWorker::ProcessEvents(GameList* game_list) {
|
||||
while (true) {
|
||||
std::function<void(GameList*)> 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 <typename F>
|
||||
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<u64, std::pair<int, int>>& 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();
|
||||
}
|
||||
|
||||
@@ -11,7 +11,6 @@
|
||||
#include <string>
|
||||
#include <utility> // Required for std::pair
|
||||
|
||||
|
||||
#include <QList>
|
||||
#include <QObject>
|
||||
#include <QRunnable>
|
||||
@@ -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<QStandardItem*>& entry_items, const QString& parent_path);
|
||||
void Finished(const QStringList& watch_list);
|
||||
void ProgressUpdated(int percent);
|
||||
|
||||
private:
|
||||
template <typename F>
|
||||
void RecordEvent(F&& func);
|
||||
|
||||
private:
|
||||
void AddTitlesToGameList(const QString& parent_path,
|
||||
const std::map<u64, std::pair<int, int>>& online_stats);
|
||||
@@ -102,9 +88,6 @@ private:
|
||||
|
||||
QStringList watch_list;
|
||||
|
||||
std::mutex lock;
|
||||
std::condition_variable cv;
|
||||
std::deque<std::function<void(GameList*)>> queued_events;
|
||||
std::atomic_bool stop_requested = false;
|
||||
Common::Event processing_completed;
|
||||
|
||||
|
||||
Reference in New Issue
Block a user