From 5f9481dd3db85888472128b7ffd63305d83b68c4 Mon Sep 17 00:00:00 2001 From: Connor McLaughlin Date: Sun, 2 Aug 2020 03:03:25 +1000 Subject: [PATCH] Qt: Fix game list settings headings not being translatable --- src/duckstation-qt/CMakeLists.txt | 2 + src/duckstation-qt/duckstation-qt.vcxproj | 3 + .../duckstation-qt.vcxproj.filters | 5 +- .../gamelistsearchdirectoriesmodel.cpp | 178 +++++++++++++++++ .../gamelistsearchdirectoriesmodel.h | 41 ++++ src/duckstation-qt/gamelistsettingswidget.cpp | 187 +----------------- .../translations/duckstation-qt_pt.ts | 30 +-- 7 files changed, 244 insertions(+), 202 deletions(-) create mode 100644 src/duckstation-qt/gamelistsearchdirectoriesmodel.cpp create mode 100644 src/duckstation-qt/gamelistsearchdirectoriesmodel.h 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.