From ad219cdd26bbff2c8050e42e2e637208930b3e3a Mon Sep 17 00:00:00 2001 From: Kojin Date: Mon, 4 May 2020 01:55:33 -0400 Subject: [PATCH 1/7] qt: split gamelist into two seperate files --- DobieStation/DobieQt.vcxproj | 19 +++-- DobieStation/DobieQt.vcxproj.filters | 31 ++++--- DobieStation/common.props | 1 - DobieStation/qt.props | 6 +- src/qt/emuwindow.cpp | 3 +- .../gamelistmodel.cpp} | 84 +------------------ src/qt/gamelist/gamelistmodel.hpp | 35 ++++++++ src/qt/gamelist/gamelistwidget.cpp | 82 ++++++++++++++++++ src/qt/gamelist/gamelistwidget.hpp | 24 ++++++ src/qt/gamelistwidget.hpp | 54 ------------ 10 files changed, 181 insertions(+), 158 deletions(-) rename src/qt/{gamelistwidget.cpp => gamelist/gamelistmodel.cpp} (58%) create mode 100644 src/qt/gamelist/gamelistmodel.hpp create mode 100644 src/qt/gamelist/gamelistwidget.cpp create mode 100644 src/qt/gamelist/gamelistwidget.hpp delete mode 100644 src/qt/gamelistwidget.hpp diff --git a/DobieStation/DobieQt.vcxproj b/DobieStation/DobieQt.vcxproj index bb311bc83..9c729c275 100644 --- a/DobieStation/DobieQt.vcxproj +++ b/DobieStation/DobieQt.vcxproj @@ -85,10 +85,11 @@ - + + @@ -103,17 +104,19 @@ - + + - - - - - - + + + + + + + diff --git a/DobieStation/DobieQt.vcxproj.filters b/DobieStation/DobieQt.vcxproj.filters index e073d2fe8..750574d4b 100644 --- a/DobieStation/DobieQt.vcxproj.filters +++ b/DobieStation/DobieQt.vcxproj.filters @@ -19,9 +19,6 @@ Source - - Source - Source @@ -40,25 +37,34 @@ Source + + Source + + + Source + - + + Moc + + Moc - + Moc - + Moc - + Moc - + Moc - + Moc @@ -70,7 +76,7 @@ - + Headers @@ -85,7 +91,10 @@ Headers - + + Headers + + Headers diff --git a/DobieStation/common.props b/DobieStation/common.props index 43d54a60a..4cdbc1692 100644 --- a/DobieStation/common.props +++ b/DobieStation/common.props @@ -29,7 +29,6 @@ 4577;4244;4267;%(DisableSpecificWarnings) - $(UIDir);%(AdditionalIncludeDirectories) $(ExtDir)\libdeflate;$(ExtDir)\libdeflate\common;%(AdditionalIncludeDirectories) diff --git a/DobieStation/qt.props b/DobieStation/qt.props index 24b137a9c..8d2f7addb 100644 --- a/DobieStation/qt.props +++ b/DobieStation/qt.props @@ -13,7 +13,8 @@ $(QTDIR)lib\ $(QTDIR)bin\ $(QTDIR)plugins\ - $(QtToolOutDir)moc_ + $(QtToolOutDir) + moc_ d $(QtDebugSuffix) QtPlugins @@ -32,6 +33,8 @@ QT_CORE_LIB;%(PreprocessorDefinitions) + $(UIDir);%(AdditionalIncludeDirectories) + $(UIDir)gamelist;%(AdditionalIncludeDirectories) $(QtToolOutDir);%(AdditionalIncludeDirectories) $(QtIncludeDir);%(AdditionalIncludeDirectories) $(QtIncludeDir)QtCore;%(AdditionalIncludeDirectories) @@ -76,6 +79,7 @@ + diff --git a/src/qt/emuwindow.cpp b/src/qt/emuwindow.cpp index 1569e8a27..5c6be04c2 100644 --- a/src/qt/emuwindow.cpp +++ b/src/qt/emuwindow.cpp @@ -14,9 +14,10 @@ #include "emuwindow.hpp" #include "settingswindow.hpp" #include "renderwidget.hpp" -#include "gamelistwidget.hpp" #include "bios.hpp" +#include "gamelist/gamelistwidget.hpp" + #include "arg.h" using namespace std; diff --git a/src/qt/gamelistwidget.cpp b/src/qt/gamelist/gamelistmodel.cpp similarity index 58% rename from src/qt/gamelistwidget.cpp rename to src/qt/gamelist/gamelistmodel.cpp index ee3e2dba8..a9bf50b79 100644 --- a/src/qt/gamelistwidget.cpp +++ b/src/qt/gamelist/gamelistmodel.cpp @@ -1,25 +1,14 @@ -#include -#include -#include -#include -#include #include -#include -#include +#include -#include "gamelistwidget.hpp" #include "settings.hpp" - -#include -#include +#include "gamelist/gamelistmodel.hpp" GameListModel::GameListModel(QObject* parent) : QAbstractTableModel(parent) { for (auto& path : Settings::instance().rom_directories) - { games.append(get_directory_entries(path)); - } sort_games(); @@ -167,73 +156,4 @@ void GameListModel::remove_path(const QString& path) games.removeAll(game); endRemoveRows(); } -} - -GameListWidget::GameListWidget(QWidget* parent) - : QStackedWidget(parent) -{ - auto game_list_widget = new QTableView(this); - auto game_list_model = new GameListModel(this); - - game_list_widget->setModel(game_list_model); - game_list_widget->setShowGrid(false); - game_list_widget->setFrameStyle(QFrame::NoFrame); - game_list_widget->setAlternatingRowColors(true); - game_list_widget->setSelectionMode(QAbstractItemView::ExtendedSelection); - game_list_widget->setSelectionBehavior(QAbstractItemView::SelectRows); - game_list_widget->verticalHeader()->setDefaultSectionSize(40); - - auto header = game_list_widget->horizontalHeader(); - header->setMinimumSectionSize(40); - header->setSectionResizeMode(GameListModel::COLUMN_NAME, QHeaderView::Stretch); - - connect(game_list_widget, &QTableView::doubleClicked, [=](const QModelIndex& index) { - QString path = game_list_model->games.at(index.row()); - emit game_double_clicked(path); - }); - - auto default_label = new QLabel(this); - default_label->setAlignment(Qt::AlignHCenter); - default_label->setText(tr( - "No roms found.\n" - "Add a new rom directory to see your roms listed here." - )); - - auto default_button = new QPushButton("&Open Settings", this); - connect(default_button, &QPushButton::clicked, [=]() { - emit settings_requested(); - }); - - auto layout = new QVBoxLayout; - layout->addWidget(default_label); - layout->addWidget(default_button); - layout->setAlignment(Qt::AlignVCenter | Qt::AlignHCenter); - - auto default_widget = new QWidget(this); - default_widget->setLayout(layout); - - addWidget(default_widget); - addWidget(game_list_widget); - - if (game_list_widget->model()->rowCount()) - show_gamelist_view(); - - connect(&Settings::instance(), &Settings::rom_directory_committed, - this, &GameListWidget::show_gamelist_view - ); - - connect(&Settings::instance(), &Settings::rom_directory_uncommitted, [=]() { - if (!game_list_widget->model()->rowCount()) - show_default_view(); - }); -} - -void GameListWidget::show_default_view() -{ - setCurrentIndex(VIEW::DEFAULT); -} - -void GameListWidget::show_gamelist_view() -{ - setCurrentIndex(VIEW::GAMELIST); } \ No newline at end of file diff --git a/src/qt/gamelist/gamelistmodel.hpp b/src/qt/gamelist/gamelistmodel.hpp new file mode 100644 index 000000000..aa3cf7d96 --- /dev/null +++ b/src/qt/gamelist/gamelistmodel.hpp @@ -0,0 +1,35 @@ +#ifndef GAMELISTMODEL_HPP +#define GAMELISTMODEL_HPP + +#include + +class GameListModel final : public QAbstractTableModel +{ + Q_OBJECT +public: + enum + { + COLUMN_NAME, + COLUMN_SIZE + }; + + QStringList games; + + explicit GameListModel(QObject* parent = nullptr); + + QVariant data(const QModelIndex& index, + int role = Qt::DisplayRole) const override; + QVariant headerData(int section, Qt::Orientation, + int role = Qt::DisplayRole) const override; + int rowCount(const QModelIndex& index) const override; + int columnCount(const QModelIndex& index) const override; + + void add_path(const QString& path); + void remove_path(const QString& path); +private: + void sort_games(); + QStringList get_directory_entries(QString path); + QString get_formatted_data_size(uint64_t size) const; +}; + +#endif \ No newline at end of file diff --git a/src/qt/gamelist/gamelistwidget.cpp b/src/qt/gamelist/gamelistwidget.cpp new file mode 100644 index 000000000..e34628c9f --- /dev/null +++ b/src/qt/gamelist/gamelistwidget.cpp @@ -0,0 +1,82 @@ +#include +#include +#include +#include +#include +#include + +#include "settings.hpp" +#include "gamelist/gamelistwidget.hpp" +#include "gamelist/gamelistmodel.hpp" + +#include +#include + +GameListWidget::GameListWidget(QWidget* parent) + : QStackedWidget(parent) +{ + auto game_list_widget = new QTableView(this); + auto game_list_model = new GameListModel(this); + + game_list_widget->setModel(game_list_model); + game_list_widget->setShowGrid(false); + game_list_widget->setFrameStyle(QFrame::NoFrame); + game_list_widget->setAlternatingRowColors(true); + game_list_widget->setSelectionMode(QAbstractItemView::ExtendedSelection); + game_list_widget->setSelectionBehavior(QAbstractItemView::SelectRows); + game_list_widget->verticalHeader()->setDefaultSectionSize(40); + + auto header = game_list_widget->horizontalHeader(); + header->setMinimumSectionSize(40); + header->setSectionResizeMode(GameListModel::COLUMN_NAME, QHeaderView::Stretch); + + connect(game_list_widget, &QTableView::doubleClicked, [=](const QModelIndex& index) { + QString path = game_list_model->games.at(index.row()); + emit game_double_clicked(path); + }); + + auto default_label = new QLabel(this); + default_label->setAlignment(Qt::AlignHCenter); + default_label->setText(tr( + "No roms found.\n" + "Add a new rom directory to see your roms listed here." + )); + + auto default_button = new QPushButton("&Open Settings", this); + connect(default_button, &QPushButton::clicked, [=]() { + emit settings_requested(); + }); + + auto layout = new QVBoxLayout; + layout->addWidget(default_label); + layout->addWidget(default_button); + layout->setAlignment(Qt::AlignVCenter | Qt::AlignHCenter); + + auto default_widget = new QWidget(this); + default_widget->setLayout(layout); + + addWidget(default_widget); + addWidget(game_list_widget); + + if (game_list_widget->model()->rowCount()) + show_gamelist_view(); + + connect(&Settings::instance(), &Settings::rom_directory_committed, + this, &GameListWidget::show_gamelist_view + ); + + connect(&Settings::instance(), &Settings::rom_directory_uncommitted, [=]() { + if (!game_list_widget->model()->rowCount()) + show_default_view(); + }); +} + +void GameListWidget::show_default_view() +{ + setCurrentIndex(VIEW::DEFAULT); +} + +void GameListWidget::show_gamelist_view() +{ + setCurrentIndex(VIEW::GAMELIST); +} \ No newline at end of file diff --git a/src/qt/gamelist/gamelistwidget.hpp b/src/qt/gamelist/gamelistwidget.hpp new file mode 100644 index 000000000..900e9b001 --- /dev/null +++ b/src/qt/gamelist/gamelistwidget.hpp @@ -0,0 +1,24 @@ +#ifndef GAMELISTWIDGET_HPP +#define GAMELISTWIDGET_HPP + +#include +#include + +class GameListWidget : public QStackedWidget +{ + Q_OBJECT + public: + enum VIEW + { + DEFAULT, + GAMELIST + }; + GameListWidget(QWidget* parent = nullptr); + + void show_default_view(); + void show_gamelist_view(); + signals: + void game_double_clicked(QString path); + void settings_requested(); +}; +#endif \ No newline at end of file diff --git a/src/qt/gamelistwidget.hpp b/src/qt/gamelistwidget.hpp deleted file mode 100644 index cd1da7d9b..000000000 --- a/src/qt/gamelistwidget.hpp +++ /dev/null @@ -1,54 +0,0 @@ -#ifndef GAMELISTWIDGET_HPP -#define GAMELISTWIDGET_HPP - -#include -#include -#include - -class GameListModel final : public QAbstractTableModel -{ - Q_OBJECT - public: - enum - { - COLUMN_NAME, - COLUMN_SIZE - }; - - QStringList games; - - explicit GameListModel(QObject* parent = nullptr); - - QVariant data(const QModelIndex& index, - int role = Qt::DisplayRole) const override; - QVariant headerData(int section, Qt::Orientation, - int role = Qt::DisplayRole) const override; - int rowCount(const QModelIndex& index) const override; - int columnCount(const QModelIndex& index) const override; - - void add_path(const QString& path); - void remove_path(const QString& path); - private: - void sort_games(); - QStringList get_directory_entries(QString path); - QString get_formatted_data_size(uint64_t size) const; -}; - -class GameListWidget : public QStackedWidget -{ - Q_OBJECT - public: - enum VIEW - { - DEFAULT, - GAMELIST - }; - GameListWidget(QWidget* parent = nullptr); - - void show_default_view(); - void show_gamelist_view(); - signals: - void game_double_clicked(QString path); - void settings_requested(); -}; -#endif \ No newline at end of file From be4cccbd9e86cb7efbd862fee6b6041825140b0a Mon Sep 17 00:00:00 2001 From: Kojin Date: Wed, 6 May 2020 18:54:30 -0400 Subject: [PATCH 2/7] qt: move gamelist io to it's own thread --- DobieStation/DobieQt.vcxproj | 3 + DobieStation/DobieQt.vcxproj.filters | 9 +++ src/qt/gamelist/gamelistmodel.cpp | 114 ++++++++++----------------- src/qt/gamelist/gamelistmodel.hpp | 59 ++++++++------ src/qt/gamelist/gamelistwatcher.cpp | 103 ++++++++++++++++++++++++ src/qt/gamelist/gamelistwatcher.hpp | 62 +++++++++++++++ src/qt/gamelist/gamelistwidget.cpp | 66 +++++++--------- src/qt/gamelist/gamelistwidget.hpp | 11 ++- 8 files changed, 290 insertions(+), 137 deletions(-) create mode 100644 src/qt/gamelist/gamelistwatcher.cpp create mode 100644 src/qt/gamelist/gamelistwatcher.hpp diff --git a/DobieStation/DobieQt.vcxproj b/DobieStation/DobieQt.vcxproj index 9c729c275..43c68ab34 100644 --- a/DobieStation/DobieQt.vcxproj +++ b/DobieStation/DobieQt.vcxproj @@ -90,6 +90,7 @@ + @@ -106,6 +107,7 @@ + @@ -117,6 +119,7 @@ + diff --git a/DobieStation/DobieQt.vcxproj.filters b/DobieStation/DobieQt.vcxproj.filters index 750574d4b..cd96c6a95 100644 --- a/DobieStation/DobieQt.vcxproj.filters +++ b/DobieStation/DobieQt.vcxproj.filters @@ -43,6 +43,9 @@ Source + + Source + @@ -67,6 +70,9 @@ Moc + + Moc + @@ -97,5 +103,8 @@ Headers + + Headers + \ No newline at end of file diff --git a/src/qt/gamelist/gamelistmodel.cpp b/src/qt/gamelist/gamelistmodel.cpp index a9bf50b79..b2cd68f4a 100644 --- a/src/qt/gamelist/gamelistmodel.cpp +++ b/src/qt/gamelist/gamelistmodel.cpp @@ -1,5 +1,6 @@ #include #include +#include #include "settings.hpp" #include "gamelist/gamelistmodel.hpp" @@ -7,18 +8,19 @@ GameListModel::GameListModel(QObject* parent) : QAbstractTableModel(parent) { - for (auto& path : Settings::instance().rom_directories) - games.append(get_directory_entries(path)); - - sort_games(); + connect(&watcher, &GameListWatcher::game_loaded, this, &GameListModel::add_game); + connect(&watcher, &GameListWatcher::game_removed, this, &GameListModel::remove_game); + connect(&watcher, &GameListWatcher::directory_processed, [this]() { + emit directory_processed(); + }); connect(&Settings::instance(), &Settings::rom_directory_committed, - this, &GameListModel::add_path - ); - + &watcher, &GameListWatcher::add_directory); connect(&Settings::instance(), &Settings::rom_directory_uncommitted, - this, &GameListModel::remove_path - ); + &watcher, &GameListWatcher::remove_directory); + + for (const auto& path : Settings::instance().rom_directories) + watcher.add_directory(path); } QVariant GameListModel::data( @@ -31,15 +33,14 @@ QVariant GameListModel::data( if (role != Qt::DisplayRole) return QVariant(); - auto file = games.at(index.row()); - QFileInfo file_info(file); + const auto& game = m_games.at(index.row()); switch (index.column()) { case COLUMN_NAME: - return file_info.fileName(); + return game.name; case COLUMN_SIZE: - return get_formatted_data_size(file_info.size()); + return get_formatted_data_size(game.size); } return QVariant(); @@ -49,6 +50,9 @@ QVariant GameListModel::headerData( int section, Qt::Orientation orientation, int role ) const { + if (orientation == Qt::Vertical || role != Qt::DisplayRole) + return QVariant(); + switch (section) { case COLUMN_NAME: @@ -62,36 +66,41 @@ QVariant GameListModel::headerData( int GameListModel::rowCount(const QModelIndex& index) const { - return games.size(); + if (index.isValid()) + return 0; + + return m_games.size(); } int GameListModel::columnCount(const QModelIndex& index) const { - return 2; + return COLUMN_MAX; } -QStringList GameListModel::get_directory_entries(QString path) +GameInfo GameListModel::get_game_info(int index) { - const QStringList file_types({ - "*.iso", - "*.cso", - "*.elf", - "*.gsd", - "*.bin" - }); + return m_games[index]; +} - QDirIterator it(path, file_types, - QDir::Files, QDirIterator::Subdirectories - ); +GameListWatcher* GameListModel::get_watcher() +{ + return &watcher; +} - QStringList list; - while (it.hasNext()) - { - it.next(); - list.append(it.filePath()); - } +void GameListModel::add_game(const GameInfo game) +{ + beginInsertRows(QModelIndex(), m_games.size(), m_games.size()); + m_games.push_back(game); + endInsertRows(); +} + +void GameListModel::remove_game(const GameInfo game) +{ + auto index = m_games.indexOf(game); - return list; + beginRemoveRows(QModelIndex(), index, index); + m_games.removeAt(index); + endRemoveRows(); } QString GameListModel::get_formatted_data_size(uint64_t size) const @@ -117,43 +126,4 @@ QString GameListModel::get_formatted_data_size(uint64_t size) const #else return QLocale().formattedDataSize(size); #endif -} - -void GameListModel::sort_games() -{ - std::sort(games.begin(), games.end(), [&](const QString& file1, const QString& file2) { - auto file_name1 = QFileInfo(file1).fileName(); - auto file_name2 = QFileInfo(file2).fileName(); - - return file_name1.compare(file_name2, Qt::CaseInsensitive) < 0; - }); -} - -void GameListModel::add_path(const QString& path) -{ - QStringList new_games = get_directory_entries(path); - - beginInsertRows(QModelIndex(), 0, new_games.size() - 1); - games.append(new_games); - - sort_games(); - - games.removeDuplicates(); - endInsertRows(); -} - -void GameListModel::remove_path(const QString& path) -{ - QStringList remove_games = get_directory_entries(path); - - for (auto& game : remove_games) - { - int index = games.indexOf(game); - if (index == -1) - continue; - - beginRemoveRows(QModelIndex(), index, index); - games.removeAll(game); - endRemoveRows(); - } } \ No newline at end of file diff --git a/src/qt/gamelist/gamelistmodel.hpp b/src/qt/gamelist/gamelistmodel.hpp index aa3cf7d96..5b0588453 100644 --- a/src/qt/gamelist/gamelistmodel.hpp +++ b/src/qt/gamelist/gamelistmodel.hpp @@ -2,34 +2,45 @@ #define GAMELISTMODEL_HPP #include +#include "gamelist/gamelistwatcher.hpp" class GameListModel final : public QAbstractTableModel { Q_OBJECT -public: - enum - { - COLUMN_NAME, - COLUMN_SIZE - }; - - QStringList games; - - explicit GameListModel(QObject* parent = nullptr); - - QVariant data(const QModelIndex& index, - int role = Qt::DisplayRole) const override; - QVariant headerData(int section, Qt::Orientation, - int role = Qt::DisplayRole) const override; - int rowCount(const QModelIndex& index) const override; - int columnCount(const QModelIndex& index) const override; - - void add_path(const QString& path); - void remove_path(const QString& path); -private: - void sort_games(); - QStringList get_directory_entries(QString path); - QString get_formatted_data_size(uint64_t size) const; + + private: + QList m_games; + GameListWatcher watcher; + + public: + enum + { + COLUMN_NAME, + COLUMN_SIZE, + COLUMN_MAX + }; + + explicit GameListModel(QObject* parent = nullptr); + + QVariant data(const QModelIndex& index, + int role = Qt::DisplayRole) const override; + QVariant headerData(int section, Qt::Orientation, + int role = Qt::DisplayRole) const override; + int rowCount(const QModelIndex& index) const override; + int columnCount(const QModelIndex& index) const override; + + GameInfo get_game_info(int index); + GameListWatcher* get_watcher(); + + public slots: + void add_game(const GameInfo game); + void remove_game(const GameInfo game); + + signals: + void directory_processed(); + + private: + QString get_formatted_data_size(uint64_t size) const; }; #endif \ No newline at end of file diff --git a/src/qt/gamelist/gamelistwatcher.cpp b/src/qt/gamelist/gamelistwatcher.cpp new file mode 100644 index 000000000..e46c08a75 --- /dev/null +++ b/src/qt/gamelist/gamelistwatcher.cpp @@ -0,0 +1,103 @@ +#include +#include +#include +#include +#include + +#include "gamelist/gamelistwatcher.hpp" + +void IOTask::add_directory(const QString dir) +{ + const QStringList file_types({ + "*.iso", + "*.cso", + "*.elf", + "*.gsd", + "*.bin" + }); + + QDirIterator it(dir, file_types, + QDir::Files, QDirIterator::Subdirectories + ); + + QList list; + while (it.hasNext()) + { + it.next(); + + auto file_info = QFileInfo(it.filePath()); + + GameInfo info = {}; + info.path = it.filePath(); + info.name = file_info.baseName(); + info.size = file_info.size(); + + list.append(info); + emit game_found(info); + } + + m_path_map.insert(dir, list); + emit finished(); +} + +void IOTask::remove_directory(const QString dir) +{ + auto games = m_path_map.take(dir); + + for (const auto game : games) + emit game_removed(game); + + emit finished(); +} + +GameListWatcher::GameListWatcher(QObject* parent) +{ + // needed to communicate this type between threads + qRegisterMetaType("GameInfo"); + + m_task.moveToThread(&m_io_thread); + + connect(&m_io_thread, &QThread::started, []() { + qDebug() << "[gamelist] IO thread started"; + }); + connect(&m_io_thread, &QThread::finished, []() { + qDebug() << "[gamelist] IO thread shutdown"; + }); + + connect(this, &GameListWatcher::directory_added, &m_task, &IOTask::add_directory); + connect(this, &GameListWatcher::directory_removed, &m_task, &IOTask::remove_directory); + + connect(&m_task, &IOTask::game_found, [this](const GameInfo info) { + emit game_loaded(info); + }); + connect(&m_task, &IOTask::game_removed, [this](const GameInfo info) { + emit game_removed(info); + }); + connect(&m_task, &IOTask::finished, [this]() { + qDebug() << "[gamelist] IO task finished"; + emit directory_processed(); + }); +} + +void GameListWatcher::start() +{ + m_io_thread.start(); +} + +void GameListWatcher::add_directory(const QString& dir) +{ + qDebug() << "[gamelist] Adding path: " << dir; + emit directory_added(dir); +} + +void GameListWatcher::remove_directory(const QString& dir) +{ + qDebug() << "[gamelist] Removing path: " << dir; + emit directory_removed(dir); +} + +GameListWatcher::~GameListWatcher() +{ + m_io_thread.quit(); + m_io_thread.wait(); +} \ No newline at end of file diff --git a/src/qt/gamelist/gamelistwatcher.hpp b/src/qt/gamelist/gamelistwatcher.hpp new file mode 100644 index 000000000..a60b67ef7 --- /dev/null +++ b/src/qt/gamelist/gamelistwatcher.hpp @@ -0,0 +1,62 @@ +#ifndef GAMELISTWATCHER_HPP +#define GAMELISTWATCHER_HPP +#include +#include +#include + +struct GameInfo +{ + QString path; + QString name; + qint64 size; + + bool operator==(const GameInfo& other) const + { + return path == other.path; + } +}; + + +// Everything in IOTask executes on another thread +// with another event loop +class IOTask : public QObject +{ + Q_OBJECT + + private: + QMap> m_path_map; + public slots: + void add_directory(const QString dir); + void remove_directory(const QString dir); + signals: + void game_found(const GameInfo game); + void game_removed(const GameInfo game); + void finished(); +}; + +class GameListWatcher : public QObject +{ + Q_OBJECT + + private: + QThread m_io_thread; + IOTask m_task; + + public: + explicit GameListWatcher(QObject* parent = nullptr); + ~GameListWatcher(); + + void start(); + void add_directory(const QString& dir); + void remove_directory(const QString& dir); + + signals: + void game_loaded(const GameInfo info); + void game_updated(const GameInfo info); + void game_removed(const GameInfo info); + void directory_added(const QString dir); + void directory_removed(const QString dir); + void directory_processed(); +}; + +#endif \ No newline at end of file diff --git a/src/qt/gamelist/gamelistwidget.cpp b/src/qt/gamelist/gamelistwidget.cpp index e34628c9f..38337c8ac 100644 --- a/src/qt/gamelist/gamelistwidget.cpp +++ b/src/qt/gamelist/gamelistwidget.cpp @@ -1,13 +1,12 @@ #include -#include #include #include #include #include +#include #include "settings.hpp" #include "gamelist/gamelistwidget.hpp" -#include "gamelist/gamelistmodel.hpp" #include #include @@ -15,26 +14,21 @@ GameListWidget::GameListWidget(QWidget* parent) : QStackedWidget(parent) { - auto game_list_widget = new QTableView(this); - auto game_list_model = new GameListModel(this); - - game_list_widget->setModel(game_list_model); - game_list_widget->setShowGrid(false); - game_list_widget->setFrameStyle(QFrame::NoFrame); - game_list_widget->setAlternatingRowColors(true); - game_list_widget->setSelectionMode(QAbstractItemView::ExtendedSelection); - game_list_widget->setSelectionBehavior(QAbstractItemView::SelectRows); - game_list_widget->verticalHeader()->setDefaultSectionSize(40); - - auto header = game_list_widget->horizontalHeader(); + m_table_view = new QTableView(this); + m_model = new GameListModel(this); + + m_table_view->setModel(m_model); + m_table_view->setShowGrid(false); + m_table_view->setFrameStyle(QFrame::NoFrame); + m_table_view->setAlternatingRowColors(true); + m_table_view->setSelectionMode(QAbstractItemView::ExtendedSelection); + m_table_view->setSelectionBehavior(QAbstractItemView::SelectRows); + m_table_view->verticalHeader()->setDefaultSectionSize(40); + + auto header = m_table_view->horizontalHeader(); header->setMinimumSectionSize(40); header->setSectionResizeMode(GameListModel::COLUMN_NAME, QHeaderView::Stretch); - connect(game_list_widget, &QTableView::doubleClicked, [=](const QModelIndex& index) { - QString path = game_list_model->games.at(index.row()); - emit game_double_clicked(path); - }); - auto default_label = new QLabel(this); default_label->setAlignment(Qt::AlignHCenter); default_label->setText(tr( @@ -47,6 +41,14 @@ GameListWidget::GameListWidget(QWidget* parent) emit settings_requested(); }); + connect(m_model->get_watcher(), &GameListWatcher::directory_processed, + this, &GameListWidget::update_view); + + connect(m_table_view, &QTableView::doubleClicked, [=](const QModelIndex& index) { + GameInfo info = m_model->get_game_info(index.row()); + emit game_double_clicked(info.path); + }); + auto layout = new QVBoxLayout; layout->addWidget(default_label); layout->addWidget(default_button); @@ -56,27 +58,15 @@ GameListWidget::GameListWidget(QWidget* parent) default_widget->setLayout(layout); addWidget(default_widget); - addWidget(game_list_widget); + addWidget(m_table_view); - if (game_list_widget->model()->rowCount()) - show_gamelist_view(); - - connect(&Settings::instance(), &Settings::rom_directory_committed, - this, &GameListWidget::show_gamelist_view - ); - - connect(&Settings::instance(), &Settings::rom_directory_uncommitted, [=]() { - if (!game_list_widget->model()->rowCount()) - show_default_view(); - }); -} - -void GameListWidget::show_default_view() -{ - setCurrentIndex(VIEW::DEFAULT); + m_model->get_watcher()->start(); } -void GameListWidget::show_gamelist_view() +void GameListWidget::update_view() { - setCurrentIndex(VIEW::GAMELIST); + if(m_table_view->model()->rowCount() || currentIndex() != VIEW::GAMELIST) + setCurrentIndex(VIEW::GAMELIST); + else if(!m_table_view->model()->rowCount()) + setCurrentIndex(VIEW::DEFAULT); } \ No newline at end of file diff --git a/src/qt/gamelist/gamelistwidget.hpp b/src/qt/gamelist/gamelistwidget.hpp index 900e9b001..2c31e47ca 100644 --- a/src/qt/gamelist/gamelistwidget.hpp +++ b/src/qt/gamelist/gamelistwidget.hpp @@ -3,10 +3,16 @@ #include #include +#include + +#include "gamelist/gamelistmodel.hpp" class GameListWidget : public QStackedWidget { Q_OBJECT + private: + GameListModel* m_model; + QTableView* m_table_view; public: enum VIEW { @@ -14,9 +20,8 @@ class GameListWidget : public QStackedWidget GAMELIST }; GameListWidget(QWidget* parent = nullptr); - - void show_default_view(); - void show_gamelist_view(); + public slots: + void update_view(); signals: void game_double_clicked(QString path); void settings_requested(); From 934e57dc5dc7287cbfbd440045f035d1857ed0cf Mon Sep 17 00:00:00 2001 From: Kojin Date: Fri, 8 May 2020 10:03:16 -0400 Subject: [PATCH 3/7] qt: sorting via proxy model --- DobieStation/DobieQt.vcxproj | 3 +++ DobieStation/DobieQt.vcxproj.filters | 9 ++++++++ src/qt/gamelist/gamelistmodel.cpp | 34 +++++++++++++++++++++++++--- src/qt/gamelist/gamelistmodel.hpp | 1 + src/qt/gamelist/gamelistproxy.cpp | 30 ++++++++++++++++++++++++ src/qt/gamelist/gamelistproxy.hpp | 16 +++++++++++++ src/qt/gamelist/gamelistwatcher.cpp | 1 + src/qt/gamelist/gamelistwatcher.hpp | 1 + src/qt/gamelist/gamelistwidget.cpp | 10 ++++++-- src/qt/gamelist/gamelistwidget.hpp | 2 ++ 10 files changed, 102 insertions(+), 5 deletions(-) create mode 100644 src/qt/gamelist/gamelistproxy.cpp create mode 100644 src/qt/gamelist/gamelistproxy.hpp diff --git a/DobieStation/DobieQt.vcxproj b/DobieStation/DobieQt.vcxproj index 43c68ab34..87844e64d 100644 --- a/DobieStation/DobieQt.vcxproj +++ b/DobieStation/DobieQt.vcxproj @@ -91,6 +91,7 @@ + @@ -108,6 +109,7 @@ + @@ -120,6 +122,7 @@ + diff --git a/DobieStation/DobieQt.vcxproj.filters b/DobieStation/DobieQt.vcxproj.filters index cd96c6a95..0c613b5ab 100644 --- a/DobieStation/DobieQt.vcxproj.filters +++ b/DobieStation/DobieQt.vcxproj.filters @@ -46,6 +46,9 @@ Source + + Source + @@ -73,6 +76,9 @@ Moc + + Moc + @@ -106,5 +112,8 @@ Headers + + Headers + \ No newline at end of file diff --git a/src/qt/gamelist/gamelistmodel.cpp b/src/qt/gamelist/gamelistmodel.cpp index b2cd68f4a..eda9fc162 100644 --- a/src/qt/gamelist/gamelistmodel.cpp +++ b/src/qt/gamelist/gamelistmodel.cpp @@ -5,6 +5,14 @@ #include "settings.hpp" #include "gamelist/gamelistmodel.hpp" +static QMap s_file_type_desc{ + {"elf", "PS2 Executable"}, + {"iso", "ISO Image"}, + {"cso", "Compressed ISO"}, + {"gsd", "GSDump"}, + {"bin", "BIN/CUE"} +}; + GameListModel::GameListModel(QObject* parent) : QAbstractTableModel(parent) { @@ -30,7 +38,7 @@ QVariant GameListModel::data( // might be cool in the future // but for now let's just focus // on display role - if (role != Qt::DisplayRole) + if (!index.isValid()) return QVariant(); const auto& game = m_games.at(index.row()); @@ -38,9 +46,27 @@ QVariant GameListModel::data( switch (index.column()) { case COLUMN_NAME: - return game.name; + if(role == Qt::DisplayRole || role == Qt::InitialSortOrderRole) + return game.name; + break; + case COLUMN_TYPE: + if (role == Qt::DisplayRole) + return s_file_type_desc[game.type]; + + // sort by the actual type and not + // the description + if (role == Qt::InitialSortOrderRole) + return game.type; + break; case COLUMN_SIZE: - return get_formatted_data_size(game.size); + if(role == Qt::DisplayRole) + return get_formatted_data_size(game.size); + + // sort by the actual size and not + // the human readable string + if (role == Qt::InitialSortOrderRole) + return game.size; + break; } return QVariant(); @@ -57,6 +83,8 @@ QVariant GameListModel::headerData( { case COLUMN_NAME: return tr("Name"); + case COLUMN_TYPE: + return tr("Type"); case COLUMN_SIZE: return tr("Size"); } diff --git a/src/qt/gamelist/gamelistmodel.hpp b/src/qt/gamelist/gamelistmodel.hpp index 5b0588453..a0c3ccbda 100644 --- a/src/qt/gamelist/gamelistmodel.hpp +++ b/src/qt/gamelist/gamelistmodel.hpp @@ -17,6 +17,7 @@ class GameListModel final : public QAbstractTableModel { COLUMN_NAME, COLUMN_SIZE, + COLUMN_TYPE, COLUMN_MAX }; diff --git a/src/qt/gamelist/gamelistproxy.cpp b/src/qt/gamelist/gamelistproxy.cpp new file mode 100644 index 000000000..e6f69bde1 --- /dev/null +++ b/src/qt/gamelist/gamelistproxy.cpp @@ -0,0 +1,30 @@ +#include "gamelist/gamelistproxy.hpp" +#include "gamelist/gamelistmodel.hpp" + +GameListProxy::GameListProxy(QObject* parent) + : QSortFilterProxyModel(parent) +{ + setDynamicSortFilter(true); + setSortRole(Qt::InitialSortOrderRole); + setSortCaseSensitivity(Qt::CaseInsensitive); +} + +bool GameListProxy::lessThan(const QModelIndex& left, const QModelIndex& right) const +{ + if (left.data(Qt::InitialSortOrderRole) != right.data(Qt::InitialSortOrderRole)) + return QSortFilterProxyModel::lessThan(right, left); + + // if we are sorting by some other field than name + // and the field is otherwise equal, then sort by name + // (IE if we are sorting by type and both are ISO) + const auto& right_index = sourceModel()->index(right.row(), GameListModel::COLUMN_NAME); + const auto& left_index = sourceModel()->index(left.row(), GameListModel::COLUMN_NAME); + + const auto& right_title = right_index.data().toString(); + const auto& left_title = left_index.data().toString(); + + if (sortOrder() == Qt::AscendingOrder) + return left_title < right_title; + + return right_title < left_title; +} \ No newline at end of file diff --git a/src/qt/gamelist/gamelistproxy.hpp b/src/qt/gamelist/gamelistproxy.hpp new file mode 100644 index 000000000..97e506e31 --- /dev/null +++ b/src/qt/gamelist/gamelistproxy.hpp @@ -0,0 +1,16 @@ +#ifndef GAMELISTPROXY_HPP +#define GAMELISTPROXY_HPP + +#include + +class GameListProxy final : public QSortFilterProxyModel +{ + Q_OBJECT + + public: + explicit GameListProxy(QObject* parent = nullptr); + + protected: + bool lessThan(const QModelIndex& left, const QModelIndex& right) const override; +}; +#endif \ No newline at end of file diff --git a/src/qt/gamelist/gamelistwatcher.cpp b/src/qt/gamelist/gamelistwatcher.cpp index e46c08a75..4d6977770 100644 --- a/src/qt/gamelist/gamelistwatcher.cpp +++ b/src/qt/gamelist/gamelistwatcher.cpp @@ -31,6 +31,7 @@ void IOTask::add_directory(const QString dir) info.path = it.filePath(); info.name = file_info.baseName(); info.size = file_info.size(); + info.type = file_info.suffix().toLower(); list.append(info); emit game_found(info); diff --git a/src/qt/gamelist/gamelistwatcher.hpp b/src/qt/gamelist/gamelistwatcher.hpp index a60b67ef7..916068e1a 100644 --- a/src/qt/gamelist/gamelistwatcher.hpp +++ b/src/qt/gamelist/gamelistwatcher.hpp @@ -8,6 +8,7 @@ struct GameInfo { QString path; QString name; + QString type; qint64 size; bool operator==(const GameInfo& other) const diff --git a/src/qt/gamelist/gamelistwidget.cpp b/src/qt/gamelist/gamelistwidget.cpp index 38337c8ac..b6997c947 100644 --- a/src/qt/gamelist/gamelistwidget.cpp +++ b/src/qt/gamelist/gamelistwidget.cpp @@ -16,11 +16,15 @@ GameListWidget::GameListWidget(QWidget* parent) { m_table_view = new QTableView(this); m_model = new GameListModel(this); + m_proxy = new GameListProxy(this); + + m_proxy->setSourceModel(m_model); + m_table_view->setModel(m_proxy); - m_table_view->setModel(m_model); m_table_view->setShowGrid(false); m_table_view->setFrameStyle(QFrame::NoFrame); m_table_view->setAlternatingRowColors(true); + m_table_view->setSortingEnabled(true); m_table_view->setSelectionMode(QAbstractItemView::ExtendedSelection); m_table_view->setSelectionBehavior(QAbstractItemView::SelectRows); m_table_view->verticalHeader()->setDefaultSectionSize(40); @@ -45,7 +49,9 @@ GameListWidget::GameListWidget(QWidget* parent) this, &GameListWidget::update_view); connect(m_table_view, &QTableView::doubleClicked, [=](const QModelIndex& index) { - GameInfo info = m_model->get_game_info(index.row()); + auto proxy_index = m_proxy->mapToSource(index); + + GameInfo info = m_model->get_game_info(proxy_index.row()); emit game_double_clicked(info.path); }); diff --git a/src/qt/gamelist/gamelistwidget.hpp b/src/qt/gamelist/gamelistwidget.hpp index 2c31e47ca..945b74b93 100644 --- a/src/qt/gamelist/gamelistwidget.hpp +++ b/src/qt/gamelist/gamelistwidget.hpp @@ -6,12 +6,14 @@ #include #include "gamelist/gamelistmodel.hpp" +#include "gamelist/gamelistproxy.hpp" class GameListWidget : public QStackedWidget { Q_OBJECT private: GameListModel* m_model; + GameListProxy* m_proxy; QTableView* m_table_view; public: enum VIEW From 7b99e57f4c7853803f8035f1eb7cb938362e9a50 Mon Sep 17 00:00:00 2001 From: Ziemas Date: Fri, 8 May 2020 16:43:30 +0200 Subject: [PATCH 4/7] Cmake and include paths --- src/qt/CMakeLists.txt | 14 ++++++++++---- src/qt/gamelist/gamelistmodel.cpp | 6 +++--- src/qt/gamelist/gamelistmodel.hpp | 4 ++-- src/qt/gamelist/gamelistproxy.cpp | 6 +++--- src/qt/gamelist/gamelistwatcher.cpp | 4 ++-- src/qt/gamelist/gamelistwidget.cpp | 6 +++--- src/qt/gamelist/gamelistwidget.hpp | 6 +++--- 7 files changed, 26 insertions(+), 20 deletions(-) diff --git a/src/qt/CMakeLists.txt b/src/qt/CMakeLists.txt index c34015af7..758f97662 100644 --- a/src/qt/CMakeLists.txt +++ b/src/qt/CMakeLists.txt @@ -18,19 +18,25 @@ set(SOURCES emuwindow.cpp settingswindow.cpp renderwidget.cpp - gamelistwidget.cpp main.cpp settings.cpp - bios.cpp) + bios.cpp + gamelist/gamelistmodel.cpp + gamelist/gamelistproxy.cpp + gamelist/gamelistwatcher.cpp + gamelist/gamelistwidget.cpp) set(HEADERS emuthread.hpp emuwindow.hpp settingswindow.hpp renderwidget.hpp - gamelistwidget.hpp settings.hpp - bios.hpp) + bios.hpp + gamelist/gamelistmodel.hpp + gamelist/gamelistproxy.hpp + gamelist/gamelistwatcher.hpp + gamelist/gamelistwidget.hpp) add_executable(${TARGET} ${SOURCES} ${HEADERS}) set_target_properties(${TARGET} PROPERTIES OUTPUT_NAME "DobieStation") # Output as "DobieStation" instead of "DobieQt" diff --git a/src/qt/gamelist/gamelistmodel.cpp b/src/qt/gamelist/gamelistmodel.cpp index eda9fc162..30e441753 100644 --- a/src/qt/gamelist/gamelistmodel.cpp +++ b/src/qt/gamelist/gamelistmodel.cpp @@ -2,8 +2,8 @@ #include #include -#include "settings.hpp" -#include "gamelist/gamelistmodel.hpp" +#include "../settings.hpp" +#include "gamelistmodel.hpp" static QMap s_file_type_desc{ {"elf", "PS2 Executable"}, @@ -154,4 +154,4 @@ QString GameListModel::get_formatted_data_size(uint64_t size) const #else return QLocale().formattedDataSize(size); #endif -} \ No newline at end of file +} diff --git a/src/qt/gamelist/gamelistmodel.hpp b/src/qt/gamelist/gamelistmodel.hpp index a0c3ccbda..1735ee917 100644 --- a/src/qt/gamelist/gamelistmodel.hpp +++ b/src/qt/gamelist/gamelistmodel.hpp @@ -2,7 +2,7 @@ #define GAMELISTMODEL_HPP #include -#include "gamelist/gamelistwatcher.hpp" +#include "gamelistwatcher.hpp" class GameListModel final : public QAbstractTableModel { @@ -44,4 +44,4 @@ class GameListModel final : public QAbstractTableModel QString get_formatted_data_size(uint64_t size) const; }; -#endif \ No newline at end of file +#endif diff --git a/src/qt/gamelist/gamelistproxy.cpp b/src/qt/gamelist/gamelistproxy.cpp index e6f69bde1..17587e918 100644 --- a/src/qt/gamelist/gamelistproxy.cpp +++ b/src/qt/gamelist/gamelistproxy.cpp @@ -1,5 +1,5 @@ -#include "gamelist/gamelistproxy.hpp" -#include "gamelist/gamelistmodel.hpp" +#include "gamelistproxy.hpp" +#include "gamelistmodel.hpp" GameListProxy::GameListProxy(QObject* parent) : QSortFilterProxyModel(parent) @@ -27,4 +27,4 @@ bool GameListProxy::lessThan(const QModelIndex& left, const QModelIndex& right) return left_title < right_title; return right_title < left_title; -} \ No newline at end of file +} diff --git a/src/qt/gamelist/gamelistwatcher.cpp b/src/qt/gamelist/gamelistwatcher.cpp index 4d6977770..c2fbf052c 100644 --- a/src/qt/gamelist/gamelistwatcher.cpp +++ b/src/qt/gamelist/gamelistwatcher.cpp @@ -4,7 +4,7 @@ #include #include -#include "gamelist/gamelistwatcher.hpp" +#include "gamelistwatcher.hpp" void IOTask::add_directory(const QString dir) { @@ -101,4 +101,4 @@ GameListWatcher::~GameListWatcher() { m_io_thread.quit(); m_io_thread.wait(); -} \ No newline at end of file +} diff --git a/src/qt/gamelist/gamelistwidget.cpp b/src/qt/gamelist/gamelistwidget.cpp index b6997c947..1b6b94160 100644 --- a/src/qt/gamelist/gamelistwidget.cpp +++ b/src/qt/gamelist/gamelistwidget.cpp @@ -5,8 +5,8 @@ #include #include -#include "settings.hpp" -#include "gamelist/gamelistwidget.hpp" +#include "../settings.hpp" +#include "gamelistwidget.hpp" #include #include @@ -75,4 +75,4 @@ void GameListWidget::update_view() setCurrentIndex(VIEW::GAMELIST); else if(!m_table_view->model()->rowCount()) setCurrentIndex(VIEW::DEFAULT); -} \ No newline at end of file +} diff --git a/src/qt/gamelist/gamelistwidget.hpp b/src/qt/gamelist/gamelistwidget.hpp index 945b74b93..4f5dd03bf 100644 --- a/src/qt/gamelist/gamelistwidget.hpp +++ b/src/qt/gamelist/gamelistwidget.hpp @@ -5,8 +5,8 @@ #include #include -#include "gamelist/gamelistmodel.hpp" -#include "gamelist/gamelistproxy.hpp" +#include "gamelistmodel.hpp" +#include "gamelistproxy.hpp" class GameListWidget : public QStackedWidget { @@ -28,4 +28,4 @@ class GameListWidget : public QStackedWidget void game_double_clicked(QString path); void settings_requested(); }; -#endif \ No newline at end of file +#endif From 1d8d03bb0feb54b0ce720676df68ca5e0c20e6e5 Mon Sep 17 00:00:00 2001 From: Ziemas Date: Fri, 8 May 2020 16:48:38 +0200 Subject: [PATCH 5/7] Include cmath for qt workaround --- src/qt/gamelist/gamelistmodel.cpp | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/src/qt/gamelist/gamelistmodel.cpp b/src/qt/gamelist/gamelistmodel.cpp index 30e441753..2a042d93f 100644 --- a/src/qt/gamelist/gamelistmodel.cpp +++ b/src/qt/gamelist/gamelistmodel.cpp @@ -2,6 +2,11 @@ #include #include +// For old Qt workaround +#if QT_VERSION < QT_VERSION_CHECK(5, 10, 0) +#include +#endif + #include "../settings.hpp" #include "gamelistmodel.hpp" From 0164d2e77197fe7cff6217a06c17dc23f0c73b45 Mon Sep 17 00:00:00 2001 From: Ziemas Date: Fri, 8 May 2020 16:50:46 +0200 Subject: [PATCH 6/7] Add things to qmake --- DobieStation/application/application.pro | 10 ++++++++-- 1 file changed, 8 insertions(+), 2 deletions(-) diff --git a/DobieStation/application/application.pro b/DobieStation/application/application.pro index 084c84054..a8c9a4c5c 100644 --- a/DobieStation/application/application.pro +++ b/DobieStation/application/application.pro @@ -92,7 +92,10 @@ SOURCES += ../../src/qt/main.cpp \ ../../src/qt/renderwidget.cpp \ ../../src/qt/settingswindow.cpp \ ../../src/qt/bios.cpp \ - ../../src/qt/gamelistwidget.cpp \ + ../../src/qt/gamelist/gamelistmodel.cpp \ + ../../src/qt/gamelist/gamelistproxy.cpp \ + ../../src/qt/gamelist/gamelistwatcher.cpp \ + ../../src/qt/gamelist/gamelistwidget.cpp \ ../../src/core/ee/ee_jittrans.cpp \ ../../src/core/ee/ee_jit.cpp \ ../../src/core/ee/ee_jit64.cpp \ @@ -171,7 +174,10 @@ HEADERS += \ ../../src/qt/renderwidget.hpp \ ../../src/qt/settingswindow.hpp \ ../../src/qt/bios.hpp \ - ../../src/qt/gamelistwidget.hpp \ + ../../src/qt/gamelist/gamelistmodel.hpp \ + ../../src/qt/gamelist/gamelistproxy.hpp \ + ../../src/qt/gamelist/gamelistwatcher.hpp \ + ../../src/qt/gamelist/gamelistwidget.hpp \ ../../src/core/ee/ee_jittrans.hpp \ ../../src/core/ee/ee_jit.hpp \ ../../src/core/ee/ee_jit64.hpp \ From 0dfff418e52452a52371c46dfca506e2a9f3d650 Mon Sep 17 00:00:00 2001 From: Kojin Date: Sat, 9 May 2020 12:02:57 -0400 Subject: [PATCH 7/7] qt: add basic search to gamelist --- src/qt/gamelist/gamelistproxy.cpp | 1 + src/qt/gamelist/gamelistwatcher.cpp | 9 +++------ src/qt/gamelist/gamelistwidget.cpp | 30 +++++++++++++++++++++-------- 3 files changed, 26 insertions(+), 14 deletions(-) diff --git a/src/qt/gamelist/gamelistproxy.cpp b/src/qt/gamelist/gamelistproxy.cpp index 17587e918..d5f0dc4aa 100644 --- a/src/qt/gamelist/gamelistproxy.cpp +++ b/src/qt/gamelist/gamelistproxy.cpp @@ -7,6 +7,7 @@ GameListProxy::GameListProxy(QObject* parent) setDynamicSortFilter(true); setSortRole(Qt::InitialSortOrderRole); setSortCaseSensitivity(Qt::CaseInsensitive); + setFilterCaseSensitivity(Qt::CaseInsensitive); } bool GameListProxy::lessThan(const QModelIndex& left, const QModelIndex& right) const diff --git a/src/qt/gamelist/gamelistwatcher.cpp b/src/qt/gamelist/gamelistwatcher.cpp index c2fbf052c..c01a562a1 100644 --- a/src/qt/gamelist/gamelistwatcher.cpp +++ b/src/qt/gamelist/gamelistwatcher.cpp @@ -68,12 +68,9 @@ GameListWatcher::GameListWatcher(QObject* parent) connect(this, &GameListWatcher::directory_added, &m_task, &IOTask::add_directory); connect(this, &GameListWatcher::directory_removed, &m_task, &IOTask::remove_directory); - connect(&m_task, &IOTask::game_found, [this](const GameInfo info) { - emit game_loaded(info); - }); - connect(&m_task, &IOTask::game_removed, [this](const GameInfo info) { - emit game_removed(info); - }); + connect(&m_task, &IOTask::game_found, this, &GameListWatcher::game_loaded); + connect(&m_task, &IOTask::game_removed, this, &GameListWatcher::game_removed); + connect(&m_task, &IOTask::finished, [this]() { qDebug() << "[gamelist] IO task finished"; emit directory_processed(); diff --git a/src/qt/gamelist/gamelistwidget.cpp b/src/qt/gamelist/gamelistwidget.cpp index 1b6b94160..c55d102ad 100644 --- a/src/qt/gamelist/gamelistwidget.cpp +++ b/src/qt/gamelist/gamelistwidget.cpp @@ -4,6 +4,7 @@ #include #include #include +#include #include "../settings.hpp" #include "gamelistwidget.hpp" @@ -41,6 +42,24 @@ GameListWidget::GameListWidget(QWidget* parent) )); auto default_button = new QPushButton("&Open Settings", this); + + auto default_layout = new QVBoxLayout; + default_layout->addWidget(default_label); + default_layout->addWidget(default_button); + default_layout->setAlignment(Qt::AlignVCenter | Qt::AlignHCenter); + + auto gamelist_layout = new QVBoxLayout; + auto search_bar = new QLineEdit(this); + gamelist_layout->addWidget(search_bar); + gamelist_layout->addWidget(m_table_view); + gamelist_layout->setContentsMargins(0, 0, 0, 0); + + auto default_widget = new QWidget(this); + default_widget->setLayout(default_layout); + + auto gamelist_widget = new QWidget(this); + gamelist_widget->setLayout(gamelist_layout); + connect(default_button, &QPushButton::clicked, [=]() { emit settings_requested(); }); @@ -55,16 +74,11 @@ GameListWidget::GameListWidget(QWidget* parent) emit game_double_clicked(info.path); }); - auto layout = new QVBoxLayout; - layout->addWidget(default_label); - layout->addWidget(default_button); - layout->setAlignment(Qt::AlignVCenter | Qt::AlignHCenter); - - auto default_widget = new QWidget(this); - default_widget->setLayout(layout); + connect(search_bar, &QLineEdit::textChanged, + m_proxy, &QSortFilterProxyModel::setFilterFixedString); addWidget(default_widget); - addWidget(m_table_view); + addWidget(gamelist_widget); m_model->get_watcher()->start(); }