From 21b187dacc21f9059b54965a99e5fbcbb049feb7 Mon Sep 17 00:00:00 2001 From: Rosalie Wanders Date: Tue, 6 May 2025 01:10:27 +0200 Subject: [PATCH] RMG: implement search for the ROM browser --- .../UserInterface/Dialog/SettingsDialog.cpp | 3 +- .../UserInterface/Dialog/SettingsDialog.ui | 18 +++ Source/RMG/UserInterface/MainWindow.cpp | 9 ++ Source/RMG/UserInterface/MainWindow.hpp | 1 + Source/RMG/UserInterface/MainWindow.ui | 10 ++ .../Resource/icons/black/svg/search-line.svg | 1 + .../Resource/icons/white/svg/search-line.svg | 1 + Source/RMG/UserInterface/UIResources.qrc | 2 + .../Widget/RomBrowser/RomBrowserWidget.cpp | 110 ++++++++++++++---- .../Widget/RomBrowser/RomBrowserWidget.hpp | 13 ++- 10 files changed, 144 insertions(+), 24 deletions(-) create mode 100644 Source/RMG/UserInterface/Resource/icons/black/svg/search-line.svg create mode 100644 Source/RMG/UserInterface/Resource/icons/white/svg/search-line.svg diff --git a/Source/RMG/UserInterface/Dialog/SettingsDialog.cpp b/Source/RMG/UserInterface/Dialog/SettingsDialog.cpp index 830898fb..ba461d5c 100644 --- a/Source/RMG/UserInterface/Dialog/SettingsDialog.cpp +++ b/Source/RMG/UserInterface/Dialog/SettingsDialog.cpp @@ -1058,7 +1058,8 @@ void SettingsDialog::commonHotkeySettings(SettingsDialogAction action) { { this->fullscreenKeyButton, SettingsID::KeyBinding_Fullscreen }, { this->logKeyButton, SettingsID::Keybinding_ViewLog }, - { this->refreshRomListKeyButton, SettingsID::KeyBinding_RefreshROMList } + { this->refreshRomListKeyButton, SettingsID::KeyBinding_RefreshROMList }, + { this->searchKeyButton, SettingsID::KeyBinding_ViewSearch } }; diff --git a/Source/RMG/UserInterface/Dialog/SettingsDialog.ui b/Source/RMG/UserInterface/Dialog/SettingsDialog.ui index 80c1f9c9..fb2bf0d4 100644 --- a/Source/RMG/UserInterface/Dialog/SettingsDialog.ui +++ b/Source/RMG/UserInterface/Dialog/SettingsDialog.ui @@ -1681,6 +1681,24 @@ + + + + + + Search + + + + + + + + + + + + diff --git a/Source/RMG/UserInterface/MainWindow.cpp b/Source/RMG/UserInterface/MainWindow.cpp index 6e7fbbc4..3f6d9408 100644 --- a/Source/RMG/UserInterface/MainWindow.cpp +++ b/Source/RMG/UserInterface/MainWindow.cpp @@ -847,6 +847,9 @@ void MainWindow::updateActions(bool inEmulation, bool isPaused) keyBinding = QString::fromStdString(CoreSettingsGetStringValue(SettingsID::Keybinding_ViewLog)); this->action_View_Log->setShortcut(QKeySequence(keyBinding)); this->action_View_ClearRomCache->setEnabled(!inEmulation); + keyBinding = QString::fromStdString(CoreSettingsGetStringValue(SettingsID::KeyBinding_ViewSearch)); + this->action_View_Search->setShortcut(QKeySequence(keyBinding)); + this->action_View_Search->setEnabled(!inEmulation); #ifdef NETPLAY this->action_Netplay_CreateSession->setEnabled(!inEmulation && this->netplaySessionDialog == nullptr); @@ -1180,6 +1183,7 @@ void MainWindow::connectActionSignals(void) connect(this->action_View_RefreshRoms, &QAction::triggered, this, &MainWindow::on_Action_View_RefreshRoms); connect(this->action_View_ClearRomCache, &QAction::triggered, this, &MainWindow::on_Action_View_ClearRomCache); connect(this->action_View_Log, &QAction::triggered, this, &MainWindow::on_Action_View_Log); + connect(this->action_View_Search, &QAction::triggered, this, &MainWindow::on_Action_View_Search); connect(this->action_Netplay_CreateSession, &QAction::triggered, this, &MainWindow::on_Action_Netplay_CreateSession); connect(this->action_Netplay_BrowseSessions, &QAction::triggered, this, &MainWindow::on_Action_Netplay_BrowseSessions); @@ -1952,6 +1956,11 @@ void MainWindow::on_Action_View_Log(void) this->logDialog.show(); } +void MainWindow::on_Action_View_Search(void) +{ + this->ui_Widget_RomBrowser->SetToggleSearch(); +} + void MainWindow::on_Action_Netplay_CreateSession(void) { #ifdef NETPLAY diff --git a/Source/RMG/UserInterface/MainWindow.hpp b/Source/RMG/UserInterface/MainWindow.hpp index 86512da2..49958878 100644 --- a/Source/RMG/UserInterface/MainWindow.hpp +++ b/Source/RMG/UserInterface/MainWindow.hpp @@ -210,6 +210,7 @@ class MainWindow : public QMainWindow, private Ui::MainWindow void on_Action_View_RefreshRoms(void); void on_Action_View_ClearRomCache(void); void on_Action_View_Log(void); + void on_Action_View_Search(void); void on_Action_Netplay_CreateSession(void); void on_Action_Netplay_BrowseSessions(void); diff --git a/Source/RMG/UserInterface/MainWindow.ui b/Source/RMG/UserInterface/MainWindow.ui index fd06940a..4ed119a0 100644 --- a/Source/RMG/UserInterface/MainWindow.ui +++ b/Source/RMG/UserInterface/MainWindow.ui @@ -137,6 +137,8 @@ + + @@ -633,6 +635,14 @@ View Session + + + + + + Search + + diff --git a/Source/RMG/UserInterface/Resource/icons/black/svg/search-line.svg b/Source/RMG/UserInterface/Resource/icons/black/svg/search-line.svg new file mode 100644 index 00000000..6da739b4 --- /dev/null +++ b/Source/RMG/UserInterface/Resource/icons/black/svg/search-line.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/Source/RMG/UserInterface/Resource/icons/white/svg/search-line.svg b/Source/RMG/UserInterface/Resource/icons/white/svg/search-line.svg new file mode 100644 index 00000000..a4d4a7a6 --- /dev/null +++ b/Source/RMG/UserInterface/Resource/icons/white/svg/search-line.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/Source/RMG/UserInterface/UIResources.qrc b/Source/RMG/UserInterface/UIResources.qrc index 6133cbd2..88b56f99 100644 --- a/Source/RMG/UserInterface/UIResources.qrc +++ b/Source/RMG/UserInterface/UIResources.qrc @@ -31,6 +31,7 @@ Resource/icons/black/svg/shut-down-line.svg Resource/icons/black/svg/speed-line.svg Resource/icons/black/svg/tools-line.svg + Resource/icons/black/svg/search-line.svg Resource/icons/black/svg/server-line.svg Resource/icons/black/svg/settings-3-line.svg Resource/icons/black/svg/volume-up-line.svg @@ -63,6 +64,7 @@ Resource/icons/white/svg/shut-down-line.svg Resource/icons/white/svg/speed-line.svg Resource/icons/white/svg/tools-line.svg + Resource/icons/white/svg/search-line.svg Resource/icons/white/svg/server-line.svg Resource/icons/white/svg/settings-3-line.svg Resource/icons/white/svg/volume-up-line.svg diff --git a/Source/RMG/UserInterface/Widget/RomBrowser/RomBrowserWidget.cpp b/Source/RMG/UserInterface/Widget/RomBrowser/RomBrowserWidget.cpp index 57bdda95..bd246d3e 100644 --- a/Source/RMG/UserInterface/Widget/RomBrowser/RomBrowserWidget.cpp +++ b/Source/RMG/UserInterface/Widget/RomBrowser/RomBrowserWidget.cpp @@ -56,11 +56,27 @@ Q_DECLARE_METATYPE(RomBrowserModelData); // Exported Functions // -RomBrowserWidget::RomBrowserWidget(QWidget *parent) : QStackedWidget(parent) +RomBrowserWidget::RomBrowserWidget(QWidget *parent) : QWidget(parent) { // configure signal types qRegisterMetaType("CoreRomType"); + // configure stacked widget + this->stackedWidget = new QStackedWidget(this); + + // configure search line edit + this->searchLineEdit = new QLineEdit(this); + this->searchLineEdit->setPlaceholderText("Search"); + this->searchLineEdit->setVisible(false); + connect(this->searchLineEdit, &QLineEdit::textChanged, this, &RomBrowserWidget::on_searchLineEdit_textChanged); + + // configure layout + QVBoxLayout* layout = new QVBoxLayout(this); + layout->addWidget(this->stackedWidget); + layout->addWidget(this->searchLineEdit); + layout->setContentsMargins(0, 0, 0, 0); + this->setLayout(layout); + // configure rom searcher thread this->romSearcherThread = new Thread::RomSearcherThread(this); connect(this->romSearcherThread, &Thread::RomSearcherThread::RomsFound, this, &RomBrowserWidget::on_RomBrowserThread_RomsFound); @@ -68,21 +84,23 @@ RomBrowserWidget::RomBrowserWidget(QWidget *parent) : QStackedWidget(parent) // configure empty widget this->emptyWidget = new Widget::RomBrowserEmptyWidget(this); - this->addWidget(this->emptyWidget); + this->stackedWidget->addWidget(this->emptyWidget); connect(this->emptyWidget, &RomBrowserEmptyWidget::SelectRomDirectory, this, &RomBrowserWidget::on_Action_ChangeRomDirectory); connect(this->emptyWidget, &RomBrowserEmptyWidget::Refresh, this, &RomBrowserWidget::on_Action_RefreshRomList); connect(this->emptyWidget, &RomBrowserEmptyWidget::FileDropped, this, &RomBrowserWidget::FileDropped); // configure loading widget this->loadingWidget = new Widget::RomBrowserLoadingWidget(this); - connect(this, &QStackedWidget::currentChanged, this->loadingWidget, &RomBrowserLoadingWidget::on_RomBrowserWidget_currentChanged); + connect(this->stackedWidget, &QStackedWidget::currentChanged, this->loadingWidget, &RomBrowserLoadingWidget::on_RomBrowserWidget_currentChanged); connect(this->loadingWidget, &RomBrowserLoadingWidget::FileDropped, this, &RomBrowserWidget::FileDropped); - this->loadingWidget->SetWidgetIndex(this->addWidget(this->loadingWidget)); + this->loadingWidget->SetWidgetIndex(this->stackedWidget->addWidget(this->loadingWidget)); // configure list view widget this->listViewWidget = new Widget::RomBrowserListViewWidget(this); this->listViewModel = new QStandardItemModel(this); - this->listViewWidget->setModel(this->listViewModel); + this->listViewProxyModel = new QSortFilterProxyModel(this); + this->listViewProxyModel->setSourceModel(this->listViewModel); + this->listViewWidget->setModel(this->listViewProxyModel); this->listViewWidget->setFrameStyle(QFrame::NoFrame); this->listViewWidget->setItemDelegate(new NoFocusDelegate(this)); this->listViewWidget->setWordWrap(false); @@ -101,7 +119,7 @@ RomBrowserWidget::RomBrowserWidget(QWidget *parent) : QStackedWidget(parent) this->listViewWidget->horizontalHeader()->setSortIndicatorShown(false); this->listViewWidget->horizontalHeader()->setHighlightSections(false); this->listViewWidget->horizontalHeader()->setContextMenuPolicy(Qt::ContextMenuPolicy::CustomContextMenu); - this->addWidget(this->listViewWidget); + this->stackedWidget->addWidget(this->listViewWidget); connect(this->listViewWidget, &QTableView::doubleClicked, this, &RomBrowserWidget::on_DoubleClicked); connect(this->listViewWidget->horizontalHeader(), &QHeaderView::sortIndicatorChanged, this, &RomBrowserWidget::on_listViewWidget_sortIndicatorChanged); connect(this->listViewWidget->horizontalHeader(), &QHeaderView::sectionResized, this, &RomBrowserWidget::on_listViewWidget_sectionResized); @@ -139,7 +157,9 @@ RomBrowserWidget::RomBrowserWidget(QWidget *parent) : QStackedWidget(parent) // configure grid view widget this->gridViewWidget = new Widget::RomBrowserGridViewWidget(this); this->gridViewModel = new QStandardItemModel(this); - this->gridViewWidget->setModel(this->gridViewModel); + this->gridViewProxyModel = new QSortFilterProxyModel(this); + this->gridViewProxyModel->setSourceModel(this->gridViewModel); + this->gridViewWidget->setModel(this->gridViewProxyModel); this->gridViewWidget->setFlow(QListView::Flow::LeftToRight); this->gridViewWidget->setResizeMode(QListView::Adjust); #ifndef DRAG_DROP @@ -157,7 +177,7 @@ RomBrowserWidget::RomBrowserWidget(QWidget *parent) : QStackedWidget(parent) int iconWidth = CoreSettingsGetIntValue(SettingsID::RomBrowser_GridViewIconWidth); int iconHeight = CoreSettingsGetIntValue(SettingsID::RomBrowser_GridViewIconHeight); this->gridViewWidget->setIconSize(QSize(iconWidth, iconHeight)); - this->addWidget(this->gridViewWidget); + this->stackedWidget->addWidget(this->gridViewWidget); connect(this->gridViewWidget, &QListView::doubleClicked, this, &RomBrowserWidget::on_DoubleClicked); connect(this->gridViewWidget, &QListView::iconSizeChanged, this, &RomBrowserWidget::on_gridViewWidget_iconSizeChanged); connect(this->gridViewWidget, &Widget::RomBrowserGridViewWidget::ZoomIn, this, &RomBrowserWidget::on_ZoomIn); @@ -279,11 +299,15 @@ void RomBrowserWidget::RefreshRomList(void) QString directory = QString::fromStdString(CoreSettingsGetStringValue(SettingsID::RomBrowser_Directory)); if (directory.isEmpty()) { - this->setCurrentWidget(this->emptyWidget); + this->stackedWidget->setCurrentWidget(this->emptyWidget); return; } - this->setCurrentWidget(this->loadingWidget); + this->stackedWidget->setCurrentWidget(this->loadingWidget); + + this->showSearchLineEdit = this->searchLineEdit->isVisible(); + this->searchLineEdit->hide(); + this->romSearcherTimer.start(); this->romSearcherThread->SetMaximumFiles(CoreSettingsGetIntValue(SettingsID::RomBrowser_MaxItems)); @@ -308,9 +332,9 @@ void RomBrowserWidget::ShowList(void) // only change widget now when we're not refreshing if (!this->IsRefreshingRomList() && - this->currentWidget() != this->emptyWidget) + this->stackedWidget->currentWidget() != this->emptyWidget) { - this->setCurrentWidget(this->listViewWidget); + this->stackedWidget->setCurrentWidget(this->listViewWidget); } } @@ -320,9 +344,9 @@ void RomBrowserWidget::ShowGrid(void) // only change widget now when we're not refreshing if (!this->IsRefreshingRomList() && - this->currentWidget() != this->emptyWidget) + this->stackedWidget->currentWidget() != this->emptyWidget) { - this->setCurrentWidget(this->gridViewWidget); + this->stackedWidget->setCurrentWidget(this->gridViewWidget); } } @@ -330,7 +354,7 @@ void RomBrowserWidget::SetGridViewUniformSizes(bool value) { // refresh ROM list when we're currently in the grid view // and we're not refreshing already - if (this->currentWidget() == this->gridViewWidget && + if (this->stackedWidget->currentWidget() == this->gridViewWidget && !this->IsRefreshingRomList()) { if (this->gridViewWidget->uniformItemSizes() != value) @@ -344,6 +368,32 @@ void RomBrowserWidget::SetGridViewUniformSizes(bool value) this->gridViewWidget->setUniformItemSizes(value); } +void RomBrowserWidget::SetToggleSearch(void) +{ + const bool show = !this->searchLineEdit->isVisible(); + + // do nothing when not in a valid view + QWidget* currentWidget = this->stackedWidget->currentWidget(); + if (currentWidget == this->loadingWidget || + currentWidget == this->emptyWidget) + { + return; + } + + this->searchLineEdit->setVisible(show); + + if (show) + { + // set focus when it's being shown + this->searchLineEdit->setFocus(); + } + else + { + // reset search when hidden + this->searchLineEdit->setText(""); + } +} + QMap RomBrowserWidget::GetModelData(void) { QMap data; @@ -370,7 +420,7 @@ QMap RomBrowserWidget::GetModelData(void) QStandardItemModel* RomBrowserWidget::getCurrentModel(void) { - QWidget* currentWidget = this->currentWidget(); + QWidget* currentWidget = this->stackedWidget->currentWidget(); if (currentWidget == this->loadingWidget) { currentWidget = this->currentViewWidget; @@ -390,7 +440,7 @@ QStandardItemModel* RomBrowserWidget::getCurrentModel(void) QAbstractItemView* RomBrowserWidget::getCurrentModelView(void) { - QWidget* currentWidget = this->currentWidget(); + QWidget* currentWidget = this->stackedWidget->currentWidget(); if (currentWidget == this->loadingWidget) { currentWidget = this->currentViewWidget; @@ -614,7 +664,8 @@ QIcon RomBrowserWidget::getCurrentCover(QString file, CoreRomHeader header, Core void RomBrowserWidget::timerEvent(QTimerEvent* event) { this->killTimer(event->timerId()); - this->setCurrentWidget(this->currentViewWidget); + this->stackedWidget->setCurrentWidget(this->currentViewWidget); + this->searchLineEdit->setVisible(this->showSearchLineEdit); } void RomBrowserWidget::on_DoubleClicked(const QModelIndex& index) @@ -794,6 +845,20 @@ void RomBrowserWidget::generateStateMenu(void) this->menu_PlayGameWithSlot->setDisabled(this->menu_PlayGameWithSlot->isEmpty()); } +void RomBrowserWidget::on_searchLineEdit_textChanged(const QString& text) +{ + // TODO: I should really make a custom data + // model at this point to save memory & CPU cycles... + + this->listViewProxyModel->setFilterCaseSensitivity(Qt::CaseInsensitive); + this->listViewProxyModel->setFilterWildcard(text); + this->listViewProxyModel->setFilterKeyColumn(0); + + this->gridViewProxyModel->setFilterCaseSensitivity(Qt::CaseInsensitive); + this->gridViewProxyModel->setFilterWildcard(text); + this->gridViewProxyModel->setFilterKeyColumn(0); +} + void RomBrowserWidget::on_listViewWidget_sortIndicatorChanged(int logicalIndex, Qt::SortOrder sortOrder) { CoreSettingsSetValue(SettingsID::RomBrowser_ListViewSortSection, logicalIndex); @@ -910,8 +975,8 @@ void RomBrowserWidget::on_RomBrowserThread_RomsFound(QListlistViewModel->sort(this->listViewSortSection, (Qt::SortOrder)this->listViewSortOrder); - this->gridViewModel->sort(0, Qt::SortOrder::AscendingOrder); + this->listViewProxyModel->sort(this->listViewSortSection, (Qt::SortOrder)this->listViewSortOrder); + this->gridViewProxyModel->sort(0, Qt::SortOrder::AscendingOrder); // retrieve column settings std::vector columnSizes = CoreSettingsGetIntListValue(SettingsID::RomBrowser_ColumnSizes); @@ -1007,7 +1072,7 @@ void RomBrowserWidget::on_RomBrowserThread_Finished(bool canceled) if (this->listViewModel->rowCount() == 0) { - this->setCurrentWidget(this->emptyWidget); + this->stackedWidget->setCurrentWidget(this->emptyWidget); return; } @@ -1020,7 +1085,8 @@ void RomBrowserWidget::on_RomBrowserThread_Finished(bool canceled) return; } - this->setCurrentWidget(this->currentViewWidget); + this->stackedWidget->setCurrentWidget(this->currentViewWidget); + this->searchLineEdit->setVisible(this->showSearchLineEdit); } void RomBrowserWidget::on_Action_PlayGame(void) diff --git a/Source/RMG/UserInterface/Widget/RomBrowser/RomBrowserWidget.hpp b/Source/RMG/UserInterface/Widget/RomBrowser/RomBrowserWidget.hpp index ee93015c..5e6e7db9 100644 --- a/Source/RMG/UserInterface/Widget/RomBrowser/RomBrowserWidget.hpp +++ b/Source/RMG/UserInterface/Widget/RomBrowser/RomBrowserWidget.hpp @@ -18,12 +18,14 @@ #include "RomBrowserLoadingWidget.hpp" #include "RomBrowserEmptyWidget.hpp" +#include #include #include #include #include #include #include +#include #include #include #include @@ -37,7 +39,7 @@ namespace UserInterface { namespace Widget { -class RomBrowserWidget : public QStackedWidget +class RomBrowserWidget : public QWidget { Q_OBJECT @@ -53,17 +55,24 @@ class RomBrowserWidget : public QStackedWidget void ShowGrid(void); void SetGridViewUniformSizes(bool value); + void SetToggleSearch(void); QMap GetModelData(void); private: + QStackedWidget* stackedWidget = nullptr; Widget::RomBrowserEmptyWidget* emptyWidget = nullptr; Widget::RomBrowserLoadingWidget* loadingWidget = nullptr; Widget::RomBrowserListViewWidget* listViewWidget = nullptr; QStandardItemModel* listViewModel = nullptr; + QSortFilterProxyModel* listViewProxyModel = nullptr; Widget::RomBrowserGridViewWidget* gridViewWidget = nullptr; QStandardItemModel* gridViewModel = nullptr; + QSortFilterProxyModel* gridViewProxyModel = nullptr; + + QLineEdit* searchLineEdit = nullptr; + bool showSearchLineEdit = false; QWidget* currentViewWidget = nullptr; @@ -116,6 +125,8 @@ class RomBrowserWidget : public QStackedWidget void generatePlayWithDiskMenu(void); void generateStateMenu(void); + void on_searchLineEdit_textChanged(const QString& text); + void on_listViewWidget_sortIndicatorChanged(int logicalIndex, Qt::SortOrder sortOrder); void on_listViewWidget_sectionResized(int logicalIndex, int oldWidth, int newWidth); void on_listViewWidget_sectionMoved(int logicalIndex, int oldVisualIndex, int newVisualIndex);