file watcher
This commit is contained in:
@@ -1,7 +1,7 @@
|
||||
// SPDX-FileCopyrightText: Copyright 2025 Eden Emulator Project
|
||||
// SPDX-License-Identifier: GPL-3.0-or-later
|
||||
|
||||
#include "yuzu/game_list.h"
|
||||
#include <regex>
|
||||
#include <QApplication>
|
||||
#include <QDir>
|
||||
#include <QFileInfo>
|
||||
@@ -13,20 +13,21 @@
|
||||
#include <QMenu>
|
||||
#include <QThreadPool>
|
||||
#include <QToolButton>
|
||||
#include <fmt/ranges.h>
|
||||
#include "common/common_types.h"
|
||||
#include "common/logging/log.h"
|
||||
#include "core/core.h"
|
||||
#include "core/file_sys/patch_manager.h"
|
||||
#include "core/file_sys/registered_cache.h"
|
||||
#include "qt_common/util/game.h"
|
||||
#include "core/hle/service/filesystem/filesystem.h"
|
||||
#include "qt_common/config/uisettings.h"
|
||||
#include "qt_common/util/game.h"
|
||||
#include "yuzu/compatibility_list.h"
|
||||
#include "yuzu/game_list.h"
|
||||
#include "yuzu/game_list_p.h"
|
||||
#include "yuzu/game_list_worker.h"
|
||||
#include "yuzu/main.h"
|
||||
#include "yuzu/util/controller_navigation.h"
|
||||
#include <fmt/ranges.h>
|
||||
#include <regex>
|
||||
|
||||
GameListSearchField::KeyReleaseEater::KeyReleaseEater(GameList* gamelist_, QObject* parent)
|
||||
: QObject(parent), gamelist{gamelist_} {}
|
||||
@@ -318,7 +319,8 @@ GameList::GameList(FileSys::VirtualFilesystem vfs_, FileSys::ManualContentProvid
|
||||
: QWidget{parent}, vfs{std::move(vfs_)}, provider{provider_},
|
||||
play_time_manager{play_time_manager_}, system{system_} {
|
||||
watcher = new QFileSystemWatcher(this);
|
||||
connect(watcher, &QFileSystemWatcher::directoryChanged, this, &GameList::RefreshGameDirectory);
|
||||
connect(watcher, &QFileSystemWatcher::directoryChanged, this,
|
||||
&GameList::OnWatchedDirectoryChanged);
|
||||
|
||||
this->main_window = parent;
|
||||
layout = new QVBoxLayout;
|
||||
@@ -486,14 +488,21 @@ void GameList::DonePopulating(const QStringList& watch_list) {
|
||||
if (!watch_dirs.isEmpty()) {
|
||||
watcher->removePaths(watch_dirs);
|
||||
}
|
||||
|
||||
QStringList all_watch_paths = watch_list;
|
||||
for (const auto& dir : Settings::values.external_dirs) {
|
||||
all_watch_paths.append(QString::fromStdString(dir));
|
||||
}
|
||||
all_watch_paths.removeDuplicates();
|
||||
|
||||
// Workaround: Add the watch paths in chunks to allow the gui to refresh
|
||||
// This prevents the UI from stalling when a large number of watch paths are added
|
||||
// Also artificially caps the watcher to a certain number of directories
|
||||
constexpr int LIMIT_WATCH_DIRECTORIES = 5000;
|
||||
constexpr int SLICE_SIZE = 25;
|
||||
int len = (std::min)(static_cast<int>(watch_list.size()), LIMIT_WATCH_DIRECTORIES);
|
||||
int len = (std::min)(static_cast<int>(all_watch_paths.size()), LIMIT_WATCH_DIRECTORIES);
|
||||
for (int i = 0; i < len; i += SLICE_SIZE) {
|
||||
watcher->addPaths(watch_list.mid(i, i + SLICE_SIZE));
|
||||
watcher->addPaths(all_watch_paths.mid(i, i + SLICE_SIZE));
|
||||
QCoreApplication::processEvents();
|
||||
}
|
||||
tree_view->setEnabled(true);
|
||||
@@ -619,26 +628,32 @@ void GameList::AddGamePopup(QMenu& context_menu, u64 program_id, const std::stri
|
||||
emit RemoveInstalledEntryRequested(program_id, QtCommon::Game::InstalledEntryType::Update);
|
||||
});
|
||||
connect(remove_dlc, &QAction::triggered, [this, program_id]() {
|
||||
emit RemoveInstalledEntryRequested(program_id, QtCommon::Game::InstalledEntryType::AddOnContent);
|
||||
emit RemoveInstalledEntryRequested(program_id,
|
||||
QtCommon::Game::InstalledEntryType::AddOnContent);
|
||||
});
|
||||
connect(remove_gl_shader_cache, &QAction::triggered, [this, program_id, path]() {
|
||||
emit RemoveFileRequested(program_id, QtCommon::Game::GameListRemoveTarget::GlShaderCache, path);
|
||||
emit RemoveFileRequested(program_id, QtCommon::Game::GameListRemoveTarget::GlShaderCache,
|
||||
path);
|
||||
});
|
||||
connect(remove_vk_shader_cache, &QAction::triggered, [this, program_id, path]() {
|
||||
emit RemoveFileRequested(program_id, QtCommon::Game::GameListRemoveTarget::VkShaderCache, path);
|
||||
emit RemoveFileRequested(program_id, QtCommon::Game::GameListRemoveTarget::VkShaderCache,
|
||||
path);
|
||||
});
|
||||
connect(remove_shader_cache, &QAction::triggered, [this, program_id, path]() {
|
||||
emit RemoveFileRequested(program_id, QtCommon::Game::GameListRemoveTarget::AllShaderCache, path);
|
||||
emit RemoveFileRequested(program_id, QtCommon::Game::GameListRemoveTarget::AllShaderCache,
|
||||
path);
|
||||
});
|
||||
connect(remove_custom_config, &QAction::triggered, [this, program_id, path]() {
|
||||
emit RemoveFileRequested(program_id, QtCommon::Game::GameListRemoveTarget::CustomConfiguration, path);
|
||||
emit RemoveFileRequested(program_id,
|
||||
QtCommon::Game::GameListRemoveTarget::CustomConfiguration, path);
|
||||
});
|
||||
connect(set_play_time, &QAction::triggered,
|
||||
[this, program_id]() { emit SetPlayTimeRequested(program_id); });
|
||||
connect(remove_play_time_data, &QAction::triggered,
|
||||
[this, program_id]() { emit RemovePlayTimeRequested(program_id); });
|
||||
connect(remove_cache_storage, &QAction::triggered, [this, program_id, path] {
|
||||
emit RemoveFileRequested(program_id, QtCommon::Game::GameListRemoveTarget::CacheStorage, path);
|
||||
emit RemoveFileRequested(program_id, QtCommon::Game::GameListRemoveTarget::CacheStorage,
|
||||
path);
|
||||
});
|
||||
connect(dump_romfs, &QAction::triggered, [this, program_id, path]() {
|
||||
emit DumpRomFSRequested(program_id, path, DumpRomFSTarget::Normal);
|
||||
@@ -665,8 +680,8 @@ void GameList::AddGamePopup(QMenu& context_menu, u64 program_id, const std::stri
|
||||
connect(properties, &QAction::triggered,
|
||||
[this, path]() { emit OpenPerGameGeneralRequested(path); });
|
||||
|
||||
connect(ryujinx, &QAction::triggered, [this, program_id]() { emit LinkToRyujinxRequested(program_id);
|
||||
});
|
||||
connect(ryujinx, &QAction::triggered,
|
||||
[this, program_id]() { emit LinkToRyujinxRequested(program_id); });
|
||||
};
|
||||
|
||||
void GameList::AddCustomDirPopup(QMenu& context_menu, QModelIndex selected) {
|
||||
@@ -830,8 +845,7 @@ QStandardItemModel* GameList::GetModel() const {
|
||||
return item_model;
|
||||
}
|
||||
|
||||
void GameList::PopulateAsync(QVector<UISettings::GameDir>& game_dirs)
|
||||
{
|
||||
void GameList::PopulateAsync(QVector<UISettings::GameDir>& game_dirs) {
|
||||
tree_view->setEnabled(false);
|
||||
|
||||
// Update the columns in case UISettings has changed
|
||||
@@ -848,12 +862,8 @@ void GameList::PopulateAsync(QVector<UISettings::GameDir>& game_dirs)
|
||||
item_model->removeRows(0, item_model->rowCount());
|
||||
search_field->clear();
|
||||
|
||||
current_worker = std::make_unique<GameListWorker>(vfs,
|
||||
provider,
|
||||
game_dirs,
|
||||
compatibility_list,
|
||||
play_time_manager,
|
||||
system);
|
||||
current_worker = std::make_unique<GameListWorker>(vfs, provider, game_dirs, compatibility_list,
|
||||
play_time_manager, system);
|
||||
|
||||
// Get events from the worker as data becomes available
|
||||
connect(current_worker.get(), &GameListWorker::DataAvailable, this, &GameList::WorkerEvent,
|
||||
@@ -882,8 +892,7 @@ const QStringList GameList::supported_file_extensions = {
|
||||
QStringLiteral("nso"), QStringLiteral("nro"), QStringLiteral("nca"),
|
||||
QStringLiteral("xci"), QStringLiteral("nsp"), QStringLiteral("kip")};
|
||||
|
||||
void GameList::RefreshGameDirectory()
|
||||
{
|
||||
void GameList::RefreshGameDirectory() {
|
||||
if (!UISettings::values.game_dirs.empty() && current_worker != nullptr) {
|
||||
LOG_INFO(Frontend, "Change detected in the games directory. Reloading game list.");
|
||||
PopulateAsync(UISettings::values.game_dirs);
|
||||
@@ -967,6 +976,17 @@ GameListPlaceholder::GameListPlaceholder(GMainWindow* parent) : QWidget{parent}
|
||||
|
||||
GameListPlaceholder::~GameListPlaceholder() = default;
|
||||
|
||||
void GameList::OnWatchedDirectoryChanged(const QString& path) {
|
||||
LOG_INFO(Frontend, "Change detected in watched directory {}. Reloading content.",
|
||||
path.toStdString());
|
||||
|
||||
system.GetFileSystemController().RebuildExternalContentIndex();
|
||||
|
||||
QtCommon::Game::ResetMetadata(false);
|
||||
|
||||
RefreshGameDirectory();
|
||||
}
|
||||
|
||||
void GameListPlaceholder::onUpdateThemedIcons() {
|
||||
image->setPixmap(QIcon::fromTheme(QStringLiteral("plus_folder")).pixmap(200));
|
||||
}
|
||||
|
||||
@@ -81,6 +81,8 @@ public:
|
||||
void LoadCompatibilityList();
|
||||
void PopulateAsync(QVector<UISettings::GameDir>& game_dirs);
|
||||
|
||||
void OnWatchedDirectoryChanged(const QString& path);
|
||||
|
||||
void SaveInterfaceLayout();
|
||||
void LoadInterfaceLayout();
|
||||
|
||||
|
||||
Reference in New Issue
Block a user