diff --git a/src/duckstation-qt/CMakeLists.txt b/src/duckstation-qt/CMakeLists.txt
index 2d7549da3..d3bdea1c9 100644
--- a/src/duckstation-qt/CMakeLists.txt
+++ b/src/duckstation-qt/CMakeLists.txt
@@ -19,6 +19,8 @@ set(SRCS
controllersettingswidget.h
gamelistmodel.cpp
gamelistmodel.h
+ gamelistsearchdirectoriesmodel.cpp
+ gamelistsearchdirectoriesmodel.h
gamelistsettingswidget.cpp
gamelistsettingswidget.h
gamelistsettingswidget.ui
diff --git a/src/duckstation-qt/duckstation-qt.vcxproj b/src/duckstation-qt/duckstation-qt.vcxproj
index 175564251..7d7f67445 100644
--- a/src/duckstation-qt/duckstation-qt.vcxproj
+++ b/src/duckstation-qt/duckstation-qt.vcxproj
@@ -40,6 +40,7 @@
+
@@ -72,6 +73,7 @@
+
@@ -147,6 +149,7 @@
+
diff --git a/src/duckstation-qt/duckstation-qt.vcxproj.filters b/src/duckstation-qt/duckstation-qt.vcxproj.filters
index eb05dc600..0ffb89f82 100644
--- a/src/duckstation-qt/duckstation-qt.vcxproj.filters
+++ b/src/duckstation-qt/duckstation-qt.vcxproj.filters
@@ -43,12 +43,14 @@
+
+
-
+
@@ -81,6 +83,7 @@
+
diff --git a/src/duckstation-qt/gamelistsearchdirectoriesmodel.cpp b/src/duckstation-qt/gamelistsearchdirectoriesmodel.cpp
new file mode 100644
index 000000000..de2317307
--- /dev/null
+++ b/src/duckstation-qt/gamelistsearchdirectoriesmodel.cpp
@@ -0,0 +1,178 @@
+#include "gamelistsearchdirectoriesmodel.h"
+#include "qthostinterface.h"
+#include "qtutils.h"
+#include
+
+GameListSearchDirectoriesModel::GameListSearchDirectoriesModel(QtHostInterface* host_interface)
+ : m_host_interface(host_interface)
+{
+ loadFromSettings();
+}
+
+GameListSearchDirectoriesModel::~GameListSearchDirectoriesModel() = default;
+
+int GameListSearchDirectoriesModel::columnCount(const QModelIndex& parent) const
+{
+ if (parent.isValid())
+ return 0;
+
+ return 2;
+}
+
+QVariant GameListSearchDirectoriesModel::headerData(int section, Qt::Orientation orientation,
+ int role /*= Qt::DisplayRole*/) const
+{
+ if (orientation != Qt::Horizontal || role != Qt::DisplayRole)
+ return {};
+
+ if (section == 0)
+ return tr("Path");
+ else
+ return tr("Recursive");
+}
+
+int GameListSearchDirectoriesModel::rowCount(const QModelIndex& parent) const
+{
+ if (parent.isValid())
+ return 0;
+
+ return static_cast(m_entries.size());
+}
+
+QVariant GameListSearchDirectoriesModel::data(const QModelIndex& index, int role /*= Qt::DisplayRole*/) const
+{
+ if (!index.isValid())
+ return {};
+
+ const int row = index.row();
+ const int column = index.column();
+ if (row < 0 || row >= static_cast(m_entries.size()))
+ return {};
+
+ const Entry& entry = m_entries[row];
+ if (role == Qt::CheckStateRole)
+ {
+ if (column == 1)
+ return entry.recursive ? Qt::Checked : Qt::Unchecked;
+ }
+ else if (role == Qt::DisplayRole)
+ {
+ if (column == 0)
+ return entry.path;
+ }
+
+ return {};
+}
+
+bool GameListSearchDirectoriesModel::setData(const QModelIndex& index, const QVariant& value, int role)
+{
+ if (!index.isValid())
+ return false;
+
+ const int row = index.row();
+ const int column = index.column();
+ if (row < 0 || row >= static_cast(m_entries.size()))
+ return false;
+
+ if (column != 1 || role == Qt::CheckStateRole)
+ return false;
+
+ Entry& entry = m_entries[row];
+ entry.recursive = value == Qt::Checked;
+ saveToSettings();
+ m_host_interface->refreshGameList(false);
+ return true;
+}
+
+void GameListSearchDirectoriesModel::addEntry(const QString& path, bool recursive)
+{
+ auto existing = std::find_if(m_entries.begin(), m_entries.end(), [path](const Entry& e) { return e.path == path; });
+ if (existing != m_entries.end())
+ {
+ const int row = static_cast(existing - m_entries.begin());
+ existing->recursive = recursive;
+ dataChanged(index(row, 1), index(row, 1), QVector{Qt::CheckStateRole});
+ }
+ else
+ {
+ beginInsertRows(QModelIndex(), static_cast(m_entries.size()), static_cast(m_entries.size()));
+ m_entries.push_back({path, recursive});
+ endInsertRows();
+ }
+
+ saveToSettings();
+ m_host_interface->refreshGameList(false);
+}
+
+void GameListSearchDirectoriesModel::removeEntry(int row)
+{
+ if (row < 0 || row >= static_cast(m_entries.size()))
+ return;
+
+ beginRemoveRows(QModelIndex(), row, row);
+ m_entries.erase(m_entries.begin() + row);
+ endRemoveRows();
+
+ saveToSettings();
+ m_host_interface->refreshGameList(false);
+}
+
+bool GameListSearchDirectoriesModel::isEntryRecursive(int row) const
+{
+ return (row < 0 || row >= static_cast(m_entries.size())) ? false : m_entries[row].recursive;
+}
+
+void GameListSearchDirectoriesModel::setEntryRecursive(int row, bool recursive)
+{
+ if (row < 0 || row >= static_cast(m_entries.size()))
+ return;
+
+ m_entries[row].recursive = recursive;
+ emit dataChanged(index(row, 1), index(row, 1), {Qt::CheckStateRole});
+
+ saveToSettings();
+ m_host_interface->refreshGameList(false);
+}
+
+void GameListSearchDirectoriesModel::openEntryInExplorer(QWidget* parent, int row) const
+{
+ if (row < 0 || row >= static_cast(m_entries.size()))
+ return;
+
+ QtUtils::OpenURL(parent, QUrl::fromLocalFile(m_entries[row].path));
+}
+
+void GameListSearchDirectoriesModel::loadFromSettings()
+{
+ std::vector path_list = m_host_interface->GetSettingStringList("GameList", "Paths");
+ for (std::string& entry : path_list)
+ m_entries.push_back({QString::fromStdString(entry), false});
+
+ path_list = m_host_interface->GetSettingStringList("GameList", "RecursivePaths");
+ for (std::string& entry : path_list)
+ m_entries.push_back({QString::fromStdString(entry), true});
+}
+
+void GameListSearchDirectoriesModel::saveToSettings()
+{
+ std::vector paths;
+ std::vector recursive_paths;
+
+ for (const Entry& entry : m_entries)
+ {
+ if (entry.recursive)
+ recursive_paths.push_back(entry.path.toStdString());
+ else
+ paths.push_back(entry.path.toStdString());
+ }
+
+ if (paths.empty())
+ m_host_interface->RemoveSettingValue("GameList", "Paths");
+ else
+ m_host_interface->SetStringListSettingValue("GameList", "Paths", paths);
+
+ if (recursive_paths.empty())
+ m_host_interface->RemoveSettingValue("GameList", "RecursivePaths");
+ else
+ m_host_interface->SetStringListSettingValue("GameList", "RecursivePaths", recursive_paths);
+}
diff --git a/src/duckstation-qt/gamelistsearchdirectoriesmodel.h b/src/duckstation-qt/gamelistsearchdirectoriesmodel.h
new file mode 100644
index 000000000..4774a1288
--- /dev/null
+++ b/src/duckstation-qt/gamelistsearchdirectoriesmodel.h
@@ -0,0 +1,41 @@
+#pragma once
+#include
+#include
+#include
+
+class QtHostInterface;
+
+class GameListSearchDirectoriesModel : public QAbstractTableModel
+{
+ Q_OBJECT
+
+public:
+ GameListSearchDirectoriesModel(QtHostInterface* host_interface);
+ ~GameListSearchDirectoriesModel();
+
+ int columnCount(const QModelIndex& parent) const override;
+ QVariant headerData(int section, Qt::Orientation orientation, int role = Qt::DisplayRole) const override;
+ int rowCount(const QModelIndex& parent) const override;
+ QVariant data(const QModelIndex& index, int role = Qt::DisplayRole) const override;
+ bool setData(const QModelIndex& index, const QVariant& value, int role) override;
+
+ void addEntry(const QString& path, bool recursive);
+ void removeEntry(int row);
+
+ bool isEntryRecursive(int row) const;
+ void setEntryRecursive(int row, bool recursive);
+
+ void openEntryInExplorer(QWidget* parent, int row) const;
+ void loadFromSettings();
+ void saveToSettings();
+
+private:
+ struct Entry
+ {
+ QString path;
+ bool recursive;
+ };
+
+ QtHostInterface* m_host_interface;
+ std::vector m_entries;
+};
diff --git a/src/duckstation-qt/gamelistsettingswidget.cpp b/src/duckstation-qt/gamelistsettingswidget.cpp
index c73326dd2..43bf75435 100644
--- a/src/duckstation-qt/gamelistsettingswidget.cpp
+++ b/src/duckstation-qt/gamelistsettingswidget.cpp
@@ -2,6 +2,7 @@
#include "common/assert.h"
#include "common/string_util.h"
#include "core/game_list.h"
+#include "gamelistsearchdirectoriesmodel.h"
#include "qthostinterface.h"
#include "qtutils.h"
#include
@@ -21,192 +22,6 @@
static constexpr char REDUMP_DOWNLOAD_URL[] = "http://redump.org/datfile/psx/serial,version,description";
-class GameListSearchDirectoriesModel : public QAbstractTableModel
-{
-public:
- GameListSearchDirectoriesModel(QtHostInterface* host_interface) : m_host_interface(host_interface)
- {
- loadFromSettings();
- }
-
- ~GameListSearchDirectoriesModel() = default;
-
- int columnCount(const QModelIndex& parent) const override
- {
- if (parent.isValid())
- return 0;
-
- return 2;
- }
-
- QVariant headerData(int section, Qt::Orientation orientation, int role = Qt::DisplayRole) const override
- {
- if (orientation != Qt::Horizontal || role != Qt::DisplayRole)
- return {};
-
- if (section == 0)
- return tr("Path");
- else
- return tr("Recursive");
- }
-
- int rowCount(const QModelIndex& parent) const override
- {
- if (parent.isValid())
- return 0;
-
- return static_cast(m_entries.size());
- }
-
- QVariant data(const QModelIndex& index, int role = Qt::DisplayRole) const override
- {
- if (!index.isValid())
- return {};
-
- const int row = index.row();
- const int column = index.column();
- if (row < 0 || row >= static_cast(m_entries.size()))
- return {};
-
- const Entry& entry = m_entries[row];
- if (role == Qt::CheckStateRole)
- {
- if (column == 1)
- return entry.recursive ? Qt::Checked : Qt::Unchecked;
- }
- else if (role == Qt::DisplayRole)
- {
- if (column == 0)
- return entry.path;
- }
-
- return {};
- }
-
- bool setData(const QModelIndex& index, const QVariant& value, int role) override
- {
- if (!index.isValid())
- return false;
-
- const int row = index.row();
- const int column = index.column();
- if (row < 0 || row >= static_cast(m_entries.size()))
- return false;
-
- if (column != 1 || role == Qt::CheckStateRole)
- return false;
-
- Entry& entry = m_entries[row];
- entry.recursive = value == Qt::Checked;
- saveToSettings();
- m_host_interface->refreshGameList(false);
- return true;
- }
-
- void addEntry(const QString& path, bool recursive)
- {
- auto existing = std::find_if(m_entries.begin(), m_entries.end(), [path](const Entry& e) { return e.path == path; });
- if (existing != m_entries.end())
- {
- const int row = static_cast(existing - m_entries.begin());
- existing->recursive = recursive;
- dataChanged(index(row, 1), index(row, 1), QVector{Qt::CheckStateRole});
- }
- else
- {
- beginInsertRows(QModelIndex(), static_cast(m_entries.size()), static_cast(m_entries.size()));
- m_entries.push_back({path, recursive});
- endInsertRows();
- }
-
- saveToSettings();
- m_host_interface->refreshGameList(false);
- }
-
- void removeEntry(int row)
- {
- if (row < 0 || row >= static_cast(m_entries.size()))
- return;
-
- beginRemoveRows(QModelIndex(), row, row);
- m_entries.erase(m_entries.begin() + row);
- endRemoveRows();
-
- saveToSettings();
- m_host_interface->refreshGameList(false);
- }
-
- bool isEntryRecursive(int row) const
- {
- return (row < 0 || row >= static_cast(m_entries.size())) ? false : m_entries[row].recursive;
- }
-
- void setEntryRecursive(int row, bool recursive)
- {
- if (row < 0 || row >= static_cast(m_entries.size()))
- return;
-
- m_entries[row].recursive = recursive;
- emit dataChanged(index(row, 1), index(row, 1), {Qt::CheckStateRole});
-
- saveToSettings();
- m_host_interface->refreshGameList(false);
- }
-
- void openEntryInExplorer(QWidget* parent, int row) const
- {
- if (row < 0 || row >= static_cast(m_entries.size()))
- return;
-
- QtUtils::OpenURL(parent, QUrl::fromLocalFile(m_entries[row].path));
- }
-
- void loadFromSettings()
- {
- std::vector path_list = m_host_interface->GetSettingStringList("GameList", "Paths");
- for (std::string& entry : path_list)
- m_entries.push_back({QString::fromStdString(entry), false});
-
- path_list = m_host_interface->GetSettingStringList("GameList", "RecursivePaths");
- for (std::string& entry : path_list)
- m_entries.push_back({QString::fromStdString(entry), true});
- }
-
- void saveToSettings()
- {
- std::vector paths;
- std::vector recursive_paths;
-
- for (const Entry& entry : m_entries)
- {
- if (entry.recursive)
- recursive_paths.push_back(entry.path.toStdString());
- else
- paths.push_back(entry.path.toStdString());
- }
-
- if (paths.empty())
- m_host_interface->RemoveSettingValue("GameList", "Paths");
- else
- m_host_interface->SetStringListSettingValue("GameList", "Paths", paths);
-
- if (recursive_paths.empty())
- m_host_interface->RemoveSettingValue("GameList", "RecursivePaths");
- else
- m_host_interface->SetStringListSettingValue("GameList", "RecursivePaths", recursive_paths);
- }
-
-private:
- struct Entry
- {
- QString path;
- bool recursive;
- };
-
- QtHostInterface* m_host_interface;
- std::vector m_entries;
-};
-
GameListSettingsWidget::GameListSettingsWidget(QtHostInterface* host_interface, QWidget* parent /* = nullptr */)
: QWidget(parent), m_host_interface(host_interface)
{
diff --git a/src/duckstation-qt/translations/duckstation-qt_pt.ts b/src/duckstation-qt/translations/duckstation-qt_pt.ts
index efdcef835..089e27961 100644
--- a/src/duckstation-qt/translations/duckstation-qt_pt.ts
+++ b/src/duckstation-qt/translations/duckstation-qt_pt.ts
@@ -798,12 +798,12 @@
GameListSearchDirectoriesModel
-
+
Path
Caminho
-
+
Recursive
Recursivo
@@ -827,7 +827,7 @@
-
+
Remove
Remover
@@ -847,66 +847,66 @@
Atualizar Lista de Jogos
-
+
Open Directory...
-
+
Select Search Directory
Escolha o Diretório de Busca
-
+
Scan Recursively?
Ler Recursivamente?
-
+
Would you like to scan the directory "%1" recursively?
Scanning recursively takes more time, but will identify files in subdirectories.
Gostaria der ler o diretório recursivamente? Escanear o diretório desta forma demora mais tempo porém, identificará arquivos em sub-pastas.
-
+
Download database from redump.org?
-
+
Do you wish to download the disc database from redump.org?
This will download approximately 4 megabytes over your current internet connection.
Quer baixar o banco de dados do redump? Isto significa que serão baixados 4MB de informação.
-
+
Downloading %1...
Baixando %1...
-
+
Cancel
Cancelar
-
+
Download failed
Falha ao Baixar
-
+
Extracting...
Extraindo...
-
+
Extract failed
Falha na Extração
-
+
Extracting game database failed.
Extração do banco de dados falhou.