aboutsummaryrefslogtreecommitdiff
path: root/src/yuzu/game/game_list.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'src/yuzu/game/game_list.cpp')
-rw-r--r--src/yuzu/game/game_list.cpp126
1 files changed, 52 insertions, 74 deletions
diff --git a/src/yuzu/game/game_list.cpp b/src/yuzu/game/game_list.cpp
index 3ea84ba0cb..a1304b4343 100644
--- a/src/yuzu/game/game_list.cpp
+++ b/src/yuzu/game/game_list.cpp
@@ -22,22 +22,21 @@
#include <QVariantAnimation>
#include "common/common_types.h"
-#include "common/logging.h"
#include "core/core.h"
#include "core/file_sys/patch_manager.h"
#include "core/file_sys/registered_cache.h"
#include "qt_common/config/uisettings.h"
+#include "qt_common/game_list/game_list_p.h"
+#include "qt_common/game_list/model.h"
#include "qt_common/qt_common.h"
#include "qt_common/util/game.h"
#include "yuzu/compatibility_list.h"
-#include "yuzu/game/game_list.h"
-#include "qt_common/game_list/game_list_p.h"
#include "yuzu/game/game_grid.h"
+#include "yuzu/game/game_list.h"
#include "yuzu/game/game_tree.h"
-#include "qt_common/game_list/model.h"
+#include "yuzu/game/search_field.h"
#include "yuzu/main_window.h"
#include "yuzu/util/controller_navigation.h"
-#include "yuzu/game/search_field.h"
GameList::GameList(FileSys::VirtualFilesystem vfs_, FileSys::ManualContentProvider* provider_,
PlayTime::PlayTimeManager& play_time_manager_, Core::System& system_,
@@ -62,8 +61,6 @@ GameList::GameList(FileSys::VirtualFilesystem vfs_, FileSys::ManualContentProvid
SetupScrollAnimation();
- connect(main_window, &MainWindow::UpdateThemedIcons, this, &GameList::OnUpdateThemedIcons);
-
connect(tree_view, &QTreeView::activated, this, &GameList::ValidateEntry);
connect(tree_view, &QTreeView::customContextMenuRequested, this, &GameList::PopupContextMenu);
@@ -87,6 +84,7 @@ GameList::GameList(FileSys::VirtualFilesystem vfs_, FileSys::ManualContentProvid
connect(item_model, &GameListModel::ShowList, this, &GameList::ShowList);
connect(item_model, &GameListModel::SaveConfig, this, &GameList::SaveConfig);
+ connect(item_model, &GameListModel::PopulatingStarted, this, &GameList::OnPopulate);
connect(tree_view, &GameTree::FilterResultReady, search_field,
[this](int visible, int total) { search_field->setFilterResult(visible, total); });
@@ -137,15 +135,17 @@ void GameList::LoadCompatibilityList() {
item_model->LoadCompatibilityList();
}
-void GameList::PopulateAsync(QVector<UISettings::GameDir>& game_dirs) {
+void GameList::OnPopulate() {
m_currentView->setEnabled(false);
- tree_view->UpdateColumnVisibility(item_model);
-
- if (!m_isTreeMode) {
+ if (m_isTreeMode) {
grid_view->UpdateIconSize();
+ } else {
+ tree_view->UpdateColumnVisibility(item_model);
}
+}
+void GameList::PopulateAsync(QVector<UISettings::GameDir>& game_dirs) {
item_model->PopulateAsync(game_dirs);
}
@@ -196,8 +196,10 @@ void GameList::ResetViewMode() {
auto scroller = QScroller::scroller(view);
QScrollerProperties props;
- props.setScrollMetric(QScrollerProperties::HorizontalOvershootPolicy, QScrollerProperties::OvershootAlwaysOff);
- props.setScrollMetric(QScrollerProperties::VerticalOvershootPolicy, QScrollerProperties::OvershootAlwaysOff);
+ props.setScrollMetric(QScrollerProperties::HorizontalOvershootPolicy,
+ QScrollerProperties::OvershootAlwaysOff);
+ props.setScrollMetric(QScrollerProperties::VerticalOvershootPolicy,
+ QScrollerProperties::OvershootAlwaysOff);
scroller->setScrollerProperties(props);
if (m_isTreeMode != newTreeMode) {
@@ -223,10 +225,6 @@ void GameList::OnFilterCloseClicked() {
main_window->filterBarSetChecked(false);
}
-void GameList::OnUpdateThemedIcons() {
- item_model->OnUpdateThemedIcons();
-}
-
void GameList::OnPopulatingCompleted(const QStringList& watch_list) {
emit ShowList(!item_model->IsEmpty());
@@ -255,50 +253,44 @@ void GameList::OnPopulatingCompleted(const QStringList& watch_list) {
}
}
- // Clear out the old directories to watch for changes and add the new ones
+ // Watcher updates
auto* watcher = item_model->GetWatcher();
- const QStringList current_watch = watcher->directories();
+ auto current_watch_list = watcher->directories();
- constexpr int LIMIT_WATCH_DIRECTORIES = 5000;
+ constexpr qsizetype LIMIT_WATCH_DIRECTORIES = 5000;
constexpr int SLICE_SIZE = 25;
- QStringList desired_watch = watch_list;
- if (desired_watch.size() > LIMIT_WATCH_DIRECTORIES) {
- desired_watch = desired_watch.mid(0, LIMIT_WATCH_DIRECTORIES);
- }
-
- // Only re-arm the watcher when the set of directories actually changed. Re-adding the same
- // paths makes the macOS QFileSystemWatcher re-emit directoryChanged (the FSEvent arrives
- // asynchronously, so the blockSignals guard below does not catch it), which retriggers a full
- // refresh and loops forever, making the game list visibly flash. Comparing the sets breaks
- // that loop: at steady state we leave the watcher untouched and no spurious event is produced.
- QStringList sorted_current = current_watch;
- QStringList sorted_desired = desired_watch;
- sorted_current.sort();
- sorted_desired.sort();
-
- if (sorted_current != sorted_desired) {
- if (!current_watch.isEmpty()) {
- watcher->removePaths(current_watch);
- }
-
-#ifdef __APPLE__
- const bool old_signals_blocked = watcher->blockSignals(true);
-#endif
+ QStringList to_remove, to_add;
- for (int i = 0; i < desired_watch.size(); i += SLICE_SIZE) {
- auto chunk = desired_watch.mid(i, SLICE_SIZE);
+ const auto slice = [&](const QStringList& list, std::function<void(const QStringList&)> callback) {
+ const int len = (std::min)(list.size(), LIMIT_WATCH_DIRECTORIES);
+ for (int i = 0; i < len; i += SLICE_SIZE) {
+ auto chunk = list.mid(i, SLICE_SIZE);
if (!chunk.isEmpty()) {
- watcher->addPaths(chunk);
+ callback(chunk);
}
QCoreApplication::processEvents();
}
+ };
-#ifdef __APPLE__
- watcher->blockSignals(old_signals_blocked);
-#endif
+ // remove any paths not in the new watch list
+ for (const auto& path : std::as_const(current_watch_list)) {
+ if (!watch_list.contains(path)) {
+ to_remove.emplaceBack(path);
+ }
}
+ slice(to_remove, [watcher](const QStringList& chunk) { watcher->removePaths(chunk); });
+
+ // add any paths not in the old watch list
+ for (const auto& path : std::as_const(watch_list)) {
+ if (!current_watch_list.contains(path)) {
+ to_add.emplaceBack(path);
+ }
+ }
+
+ slice(to_add, [watcher](const QStringList& chunk) { watcher->addPaths(chunk); });
+
m_currentView->setEnabled(true);
int children_total = 0;
@@ -317,23 +309,16 @@ void GameList::OnPopulatingCompleted(const QStringList& watch_list) {
}
void GameList::RefreshGameDirectory() {
- item_model->ResetExternalWatcher();
-
- if (!UISettings::values.game_dirs.empty()) {
- LOG_INFO(Frontend, "Change detected in the games directory. Reloading game list.");
- item_model->StopWorker();
- QtCommon::system->GetFileSystemController().CreateFactories(*QtCommon::vfs);
- PopulateAsync(UISettings::values.game_dirs);
- }
+ item_model->RefreshGameDirectory();
}
void GameList::RefreshExternalContent() {
- if (!UISettings::values.game_dirs.empty()) {
- LOG_INFO(Frontend, "External content directory changed. Clearing metadata cache.");
- item_model->StopWorker();
- QtCommon::Game::ResetMetadata(false);
- QtCommon::system->GetFileSystemController().CreateFactories(*QtCommon::vfs);
- PopulateAsync(UISettings::values.game_dirs);
+ item_model->RefreshExternalContent();
+}
+
+void GameList::UpdateIconSizes() {
+ if (!m_isTreeMode) {
+ grid_view->UpdateIconSize();
}
}
@@ -491,9 +476,8 @@ void GameList::AddGamePopup(QMenu& context_menu, u64 program_id, const std::stri
});
connect(start_game, &QAction::triggered, this,
[this, path]() { emit BootGame(QString::fromStdString(path), StartGameType::Normal); });
- connect(start_game_global, &QAction::triggered, this, [this, path]() {
- emit BootGame(QString::fromStdString(path), StartGameType::Global);
- });
+ connect(start_game_global, &QAction::triggered, this,
+ [this, path]() { emit BootGame(QString::fromStdString(path), StartGameType::Global); });
connect(open_mod_location, &QAction::triggered, this, [this, program_id, path]() {
emit OpenFolderRequested(program_id, GameListOpenTarget::ModData, path);
});
@@ -632,7 +616,8 @@ void GameList::AddFavoritesPopup(QMenu& context_menu) {
connect(clear, &QAction::triggered, this, [this] {
UISettings::values.favorited_ids.clear();
- item_model->invisibleRootItem()->child(0)->removeRows(0, item_model->invisibleRootItem()->child(0)->rowCount());
+ item_model->invisibleRootItem()->child(0)->removeRows(
+ 0, item_model->invisibleRootItem()->child(0)->rowCount());
tree_view->setRowHidden(0, item_model->invisibleRootItem()->index(), true);
});
}
@@ -731,9 +716,6 @@ bool GameList::eventFilter(QObject* obj, QEvent* event) {
}
GameListPlaceholder::GameListPlaceholder(MainWindow* parent) : QWidget{parent} {
- connect(parent, &MainWindow::UpdateThemedIcons, this,
- &GameListPlaceholder::onUpdateThemedIcons);
-
layout = new QVBoxLayout;
image = new QLabel;
text = new QLabel;
@@ -754,10 +736,6 @@ GameListPlaceholder::GameListPlaceholder(MainWindow* parent) : QWidget{parent} {
GameListPlaceholder::~GameListPlaceholder() = default;
-void GameListPlaceholder::onUpdateThemedIcons() {
- image->setPixmap(QIcon::fromTheme(QStringLiteral("plus_folder")).pixmap(200));
-}
-
void GameListPlaceholder::mouseDoubleClickEvent(QMouseEvent* event) {
emit GameListPlaceholder::AddDirectory();
}