Browse Source

file watcher

fs_external_dlcupdates
unknown 2 months ago
committed by crueter
parent
commit
cd92452202
  1. 70
      src/yuzu/game_list.cpp
  2. 2
      src/yuzu/game_list.h

70
src/yuzu/game_list.cpp

@ -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));
}

2
src/yuzu/game_list.h

@ -81,6 +81,8 @@ public:
void LoadCompatibilityList();
void PopulateAsync(QVector<UISettings::GameDir>& game_dirs);
void OnWatchedDirectoryChanged(const QString& path);
void SaveInterfaceLayout();
void LoadInterfaceLayout();

Loading…
Cancel
Save