From 8b6a4c21f3c26772406be680f00684bf02c0925c Mon Sep 17 00:00:00 2001 From: Akatsuki Levi Date: Wed, 13 Mar 2024 19:55:17 -0300 Subject: [PATCH] feat: Changed folders in list to be a toggleable option --- src/suyu/game_list.cpp | 65 +++++++++++++++++++++++++++-------- src/suyu/game_list.h | 1 + src/suyu/game_list_worker.cpp | 40 ++++++++++++++++----- src/suyu/main.cpp | 11 ++++++ src/suyu/main.h | 1 + src/suyu/main.ui | 12 +++++++ src/suyu/uisettings.h | 1 + 7 files changed, 107 insertions(+), 24 deletions(-) diff --git a/src/suyu/game_list.cpp b/src/suyu/game_list.cpp index 2c06aa69df..f6f42d2ffe 100644 --- a/src/suyu/game_list.cpp +++ b/src/suyu/game_list.cpp @@ -383,6 +383,17 @@ GameList::~GameList() { UnloadController(); } +void GameList::ClearList() { + // Clear all items + item_model->setRowCount(0); + + // Notify a reload is pending + UISettings::values.is_game_list_reload_pending.exchange(true); + UISettings::values.is_game_list_reload_pending.notify_all(); + + // Load stuff back up +} + void GameList::SetFilterFocus() { if (tree_view->model()->rowCount() > 0) { search_field->setFocus(); @@ -471,7 +482,9 @@ bool GameList::IsEmpty() const { void GameList::DonePopulating(const QStringList& watch_list) { emit ShowList(!IsEmpty()); - // item_model->invisibleRootItem()->appendRow(new GameListAddDir()); + if (UISettings::values.show_folders_in_list) { + item_model->invisibleRootItem()->appendRow(new GameListAddDir()); + } // Add favorites row item_model->invisibleRootItem()->insertRow(0, new GameListFavorites()); @@ -889,22 +902,44 @@ void GameList::ToggleFavorite(u64 program_id) { void GameList::AddFavorite(u64 program_id) { auto* favorites_row = item_model->item(0); - for (int i = 1; i < item_model->rowCount() - 1; i++) { - const auto* game = item_model->item(i); - if (game->data(GameListItemPath::ProgramIdRole).toULongLong() != program_id) { - continue; + if (UISettings::values.show_folders_in_list) { + for (int i = 0; i < item_model->rowCount(); i++) { + const auto* folder = item_model->item(i); + for (int j = 0; j < folder->rowCount(); j++) { + if (folder->child(j)->data(GameListItemPath::ProgramIdRole).toULongLong() == + program_id) { + QList list; + for (int k = 0; k < COLUMN_COUNT; k++) { + list.append(folder->child(j, k)->clone()); + } + list[0]->setData(folder->child(j)->data(GameListItem::SortRole), + GameListItem::SortRole); + list[0]->setText(folder->child(j)->data(Qt::DisplayRole).toString()); + + favorites_row->appendRow(list); + return; + } + } } - - QList list; - for (int j = 0; j < COLUMN_COUNT; j++) { - list.append(item_model->item(i, j)->clone()); - } - - list[0]->setData(game->data(GameListItem::SortRole), GameListItem::SortRole); - list[0]->setText(game->data(Qt::DisplayRole).toString()); - - favorites_row->appendRow(list); return; + } else { + for (int i = 1; i < item_model->rowCount() - 1; i++) { + const auto* game = item_model->item(i); + if (game->data(GameListItemPath::ProgramIdRole).toULongLong() != program_id) { + continue; + } + + QList list; + for (int j = 0; j < COLUMN_COUNT; j++) { + list.append(item_model->item(i, j)->clone()); + } + + list[0]->setData(game->data(GameListItem::SortRole), GameListItem::SortRole); + list[0]->setText(game->data(Qt::DisplayRole).toString()); + + favorites_row->appendRow(list); + return; + } } } diff --git a/src/suyu/game_list.h b/src/suyu/game_list.h index c9b41687de..45a50fe2f3 100644 --- a/src/suyu/game_list.h +++ b/src/suyu/game_list.h @@ -84,6 +84,7 @@ public: ~GameList() override; QString GetLastFilterResultItem() const; + void ClearList(); void ClearFilter(); void SetFilterFocus(); void SetFilterVisible(bool visibility); diff --git a/src/suyu/game_list_worker.cpp b/src/suyu/game_list_worker.cpp index 112e64b66b..93eeb40a14 100644 --- a/src/suyu/game_list_worker.cpp +++ b/src/suyu/game_list_worker.cpp @@ -330,13 +330,19 @@ void GameListWorker::AddTitlesToGameList(GameListDir* parent_dir) { auto entry = MakeGameListEntry(file->GetFullPath(), name, file->GetSize(), icon, *loader, program_id, compatibility_list, play_time_manager, patch); - RecordEvent([=](GameList* game_list) { game_list->AddRootEntry(entry); }); + RecordEvent([=](GameList* game_list) { + if (UISettings::values.show_folders_in_list) { + game_list->AddEntry(entry, parent_dir); + } else { + game_list->AddRootEntry(entry); + } + }); } } void GameListWorker::ScanFileSystem(ScanTarget target, const std::string& dir_path, bool deep_scan, GameListDir* parent_dir) { - const auto callback = [this, target](const std::filesystem::path& path) -> bool { + const auto callback = [this, target, parent_dir](const std::filesystem::path& path) -> bool { if (stop_requested) { // Breaks the callback loop. return false; @@ -424,7 +430,13 @@ void GameListWorker::ScanFileSystem(ScanTarget target, const std::string& dir_pa physical_name, name, Common::FS::GetSize(physical_name), icon, *loader, program_id, compatibility_list, play_time_manager, patch); - RecordEvent([=](GameList* game_list) { game_list->AddRootEntry(entry); }); + RecordEvent([=](GameList* game_list) { + if (UISettings::values.show_folders_in_list) { + game_list->AddEntry(entry, parent_dir); + } else { + game_list->AddRootEntry(entry); + } + }); } } } else if (is_dir) { @@ -446,11 +458,9 @@ void GameListWorker::run() { watch_list.clear(); provider->ClearAllEntries(); - /* const auto DirEntryReady = [&](GameListDir* game_list_dir) { RecordEvent([=](GameList* game_list) { game_list->AddDirEntry(game_list_dir); }); }; - */ for (UISettings::GameDir& game_dir : game_dirs) { if (stop_requested) { @@ -459,20 +469,32 @@ void GameListWorker::run() { if (game_dir.path == std::string("SDMC")) { auto* const game_list_dir = new GameListDir(game_dir, GameListItemType::SdmcDir); - // DirEntryReady(game_list_dir); + + if (UISettings::values.show_folders_in_list) + DirEntryReady(game_list_dir); + AddTitlesToGameList(game_list_dir); } else if (game_dir.path == std::string("UserNAND")) { auto* const game_list_dir = new GameListDir(game_dir, GameListItemType::UserNandDir); - // DirEntryReady(game_list_dir); + + if (UISettings::values.show_folders_in_list) + DirEntryReady(game_list_dir); + AddTitlesToGameList(game_list_dir); } else if (game_dir.path == std::string("SysNAND")) { auto* const game_list_dir = new GameListDir(game_dir, GameListItemType::SysNandDir); - // DirEntryReady(game_list_dir); + + if (UISettings::values.show_folders_in_list) + DirEntryReady(game_list_dir); + AddTitlesToGameList(game_list_dir); } else { watch_list.append(QString::fromStdString(game_dir.path)); auto* const game_list_dir = new GameListDir(game_dir); - // DirEntryReady(game_list_dir); + + if (UISettings::values.show_folders_in_list) + DirEntryReady(game_list_dir); + ScanFileSystem(ScanTarget::FillManualContentProvider, game_dir.path, game_dir.deep_scan, game_list_dir); ScanFileSystem(ScanTarget::PopulateGameList, game_dir.path, game_dir.deep_scan, diff --git a/src/suyu/main.cpp b/src/suyu/main.cpp index 784486c78c..8952b324df 100644 --- a/src/suyu/main.cpp +++ b/src/suyu/main.cpp @@ -1416,6 +1416,7 @@ void GMainWindow::RestoreUIState() { game_list->SetFilterVisible(ui->action_Show_Filter_Bar->isChecked()); ui->action_Show_Status_Bar->setChecked(UISettings::values.show_status_bar.GetValue()); + ui->action_Show_Folders_In_List->setChecked(UISettings::values.show_folders_in_list.GetValue()); statusBar()->setVisible(ui->action_Show_Status_Bar->isChecked()); Debugger::ToggleConsole(); } @@ -1531,6 +1532,7 @@ void GMainWindow::ConnectMenuEvents() { connect_menu(ui->action_Display_Dock_Widget_Headers, &GMainWindow::OnDisplayTitleBars); connect_menu(ui->action_Show_Filter_Bar, &GMainWindow::OnToggleFilterBar); connect_menu(ui->action_Show_Status_Bar, &GMainWindow::OnToggleStatusBar); + connect_menu(ui->action_Show_Folders_In_List, &GMainWindow::OnToggleFoldersInList); connect_menu(ui->action_Reset_Window_Size_720, &GMainWindow::ResetWindowSize720); connect_menu(ui->action_Reset_Window_Size_900, &GMainWindow::ResetWindowSize900); @@ -4185,6 +4187,14 @@ void GMainWindow::OnToggleStatusBar() { statusBar()->setVisible(ui->action_Show_Status_Bar->isChecked()); } +void GMainWindow::OnToggleFoldersInList() { + UISettings::values.show_folders_in_list = ui->action_Show_Folders_In_List->isChecked(); + + game_list->ClearList(); + game_list->LoadCompatibilityList(); + game_list->PopulateAsync(UISettings::values.game_dirs); +} + void GMainWindow::OnAlbum() { constexpr u64 AlbumId = static_cast(Service::AM::AppletProgramId::PhotoViewer); auto bis_system = system->GetFileSystemController().GetSystemNANDContents(); @@ -4573,6 +4583,7 @@ void GMainWindow::UpdateUISettings() { UISettings::values.display_titlebar = ui->action_Display_Dock_Widget_Headers->isChecked(); UISettings::values.show_filter_bar = ui->action_Show_Filter_Bar->isChecked(); UISettings::values.show_status_bar = ui->action_Show_Status_Bar->isChecked(); + UISettings::values.show_folders_in_list = ui->action_Show_Folders_In_List->isChecked(); UISettings::values.first_start = false; } diff --git a/src/suyu/main.h b/src/suyu/main.h index 6a157ed97e..7fa28477a7 100644 --- a/src/suyu/main.h +++ b/src/suyu/main.h @@ -383,6 +383,7 @@ private slots: void OnAbout(); void OnToggleFilterBar(); void OnToggleStatusBar(); + void OnToggleFoldersInList(); void OnDisplayTitleBars(bool); void InitializeHotkeys(); void ToggleFullscreen(); diff --git a/src/suyu/main.ui b/src/suyu/main.ui index c660b3d3a2..fece5f7069 100644 --- a/src/suyu/main.ui +++ b/src/suyu/main.ui @@ -124,6 +124,7 @@ + @@ -288,6 +289,17 @@ Show Status Bar + + + true + + + Show Folders in List + + + Show Status Bar + + true diff --git a/src/suyu/uisettings.h b/src/suyu/uisettings.h index 89fc353589..f1956bddf1 100644 --- a/src/suyu/uisettings.h +++ b/src/suyu/uisettings.h @@ -200,6 +200,7 @@ struct Values { std::atomic_bool is_game_list_reload_pending{false}; Setting cache_game_list{linkage, true, "cache_game_list", Category::UiGameList}; Setting favorites_expanded{linkage, true, "favorites_expanded", Category::UiGameList}; + Setting show_folders_in_list{linkage, true, "show_folders_in_list", Category::UiGameList}; QVector favorited_ids; // Compatibility List