QT save fixes II (#3119)
Some checks are pending
Build and Release / reuse (push) Waiting to run
Build and Release / clang-format (push) Waiting to run
Build and Release / get-info (push) Waiting to run
Build and Release / windows-sdl (push) Blocked by required conditions
Build and Release / windows-qt (push) Blocked by required conditions
Build and Release / macos-sdl (push) Blocked by required conditions
Build and Release / macos-qt (push) Blocked by required conditions
Build and Release / linux-sdl (push) Blocked by required conditions
Build and Release / linux-qt (push) Blocked by required conditions
Build and Release / linux-sdl-gcc (push) Blocked by required conditions
Build and Release / linux-qt-gcc (push) Blocked by required conditions
Build and Release / pre-release (push) Blocked by required conditions

* added recentFiles save/load

* gui language

* fixups for language

* fixed language issue with savedata (it was saving based on gui language and not on console language)

* clang fix

* elf dirs added

* added theme
This commit is contained in:
georgemoralis 2025-06-20 12:28:32 +03:00 committed by GitHub
parent 423254692a
commit 43321fb45a
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
20 changed files with 188 additions and 266 deletions

View file

@ -81,10 +81,6 @@ static std::vector<GameInstallDir> settings_install_dirs = {};
std::vector<bool> install_dirs_enabled = {}; std::vector<bool> install_dirs_enabled = {};
std::filesystem::path settings_addon_install_dir = {}; std::filesystem::path settings_addon_install_dir = {};
std::filesystem::path save_data_path = {}; std::filesystem::path save_data_path = {};
u32 mw_themes = 0;
std::vector<std::string> m_elf_viewer;
std::vector<std::string> m_recent_files;
std::string emulator_language = "en_US";
static bool isFullscreen = false; static bool isFullscreen = false;
static std::string fullscreenMode = "Windowed"; static std::string fullscreenMode = "Windowed";
static bool isHDRAllowed = false; static bool isHDRAllowed = false;
@ -484,24 +480,6 @@ void setAddonInstallDir(const std::filesystem::path& dir) {
settings_addon_install_dir = dir; settings_addon_install_dir = dir;
} }
void setMainWindowTheme(u32 theme) {
mw_themes = theme;
}
void setElfViewer(const std::vector<std::string>& elfList) {
m_elf_viewer.resize(elfList.size());
m_elf_viewer = elfList;
}
void setRecentFiles(const std::vector<std::string>& recentFiles) {
m_recent_files.resize(recentFiles.size());
m_recent_files = recentFiles;
}
void setEmulatorLanguage(std::string language) {
emulator_language = language;
}
void setGameInstallDirs(const std::vector<std::filesystem::path>& dirs_config) { void setGameInstallDirs(const std::vector<std::filesystem::path>& dirs_config) {
settings_install_dirs.clear(); settings_install_dirs.clear();
for (const auto& dir : dirs_config) { for (const auto& dir : dirs_config) {
@ -543,22 +521,6 @@ std::filesystem::path getAddonInstallDir() {
return settings_addon_install_dir; return settings_addon_install_dir;
} }
u32 getMainWindowTheme() {
return mw_themes;
}
std::vector<std::string> getElfViewer() {
return m_elf_viewer;
}
std::vector<std::string> getRecentFiles() {
return m_recent_files;
}
std::string getEmulatorLanguage() {
return emulator_language;
}
u32 GetLanguage() { u32 GetLanguage() {
return m_language; return m_language;
} }
@ -668,7 +630,6 @@ void load(const std::filesystem::path& path) {
const toml::value& gui = data.at("GUI"); const toml::value& gui = data.at("GUI");
load_game_size = toml::find_or<bool>(gui, "loadGameSizeEnabled", true); load_game_size = toml::find_or<bool>(gui, "loadGameSizeEnabled", true);
mw_themes = toml::find_or<int>(gui, "theme", 0);
const auto install_dir_array = const auto install_dir_array =
toml::find_or<std::vector<std::u8string>>(gui, "installDirs", {}); toml::find_or<std::vector<std::u8string>>(gui, "installDirs", {});
@ -693,9 +654,6 @@ void load(const std::filesystem::path& path) {
save_data_path = toml::find_fs_path_or(gui, "saveDataPath", {}); save_data_path = toml::find_fs_path_or(gui, "saveDataPath", {});
settings_addon_install_dir = toml::find_fs_path_or(gui, "addonInstallDir", {}); settings_addon_install_dir = toml::find_fs_path_or(gui, "addonInstallDir", {});
m_elf_viewer = toml::find_or<std::vector<std::string>>(gui, "elfDirs", {});
m_recent_files = toml::find_or<std::vector<std::string>>(gui, "recentFiles", {});
emulator_language = toml::find_or<std::string>(gui, "emulatorLanguage", "en_US");
} }
if (data.contains("Settings")) { if (data.contains("Settings")) {
@ -708,19 +666,6 @@ void load(const std::filesystem::path& path) {
const toml::value& keys = data.at("Keys"); const toml::value& keys = data.at("Keys");
trophyKey = toml::find_or<std::string>(keys, "TrophyKey", ""); trophyKey = toml::find_or<std::string>(keys, "TrophyKey", "");
} }
// Check if the loaded language is in the allowed list
const std::vector<std::string> allowed_languages = {
"ar_SA", "da_DK", "de_DE", "el_GR", "en_US", "es_ES", "fa_IR", "fi_FI",
"fr_FR", "hu_HU", "id_ID", "it_IT", "ja_JP", "ko_KR", "lt_LT", "nb_NO",
"nl_NL", "pl_PL", "pt_BR", "pt_PT", "ro_RO", "ru_RU", "sq_AL", "sv_SE",
"tr_TR", "uk_UA", "vi_VN", "zh_CN", "zh_TW", "ca_ES", "sr_CS"};
if (std::find(allowed_languages.begin(), allowed_languages.end(), emulator_language) ==
allowed_languages.end()) {
emulator_language = "en_US"; // Default to en_US if not in the list
save(path);
}
} }
void sortTomlSections(toml::ordered_value& data) { void sortTomlSections(toml::ordered_value& data) {
@ -855,7 +800,6 @@ void save(const std::filesystem::path& path) {
data["GUI"]["addonInstallDir"] = data["GUI"]["addonInstallDir"] =
std::string{fmt::UTF(settings_addon_install_dir.u8string()).data}; std::string{fmt::UTF(settings_addon_install_dir.u8string()).data};
data["GUI"]["emulatorLanguage"] = emulator_language;
data["Settings"]["consoleLanguage"] = m_language; data["Settings"]["consoleLanguage"] = m_language;
// Sorting of TOML sections // Sorting of TOML sections
@ -864,42 +808,6 @@ void save(const std::filesystem::path& path) {
std::ofstream file(path, std::ios::binary); std::ofstream file(path, std::ios::binary);
file << data; file << data;
file.close(); file.close();
saveMainWindow(path);
}
void saveMainWindow(const std::filesystem::path& path) {
toml::ordered_value data;
std::error_code error;
if (std::filesystem::exists(path, error)) {
try {
std::ifstream ifs;
ifs.exceptions(std::ifstream::failbit | std::ifstream::badbit);
ifs.open(path, std::ios_base::binary);
data = toml::parse<toml::ordered_type_config>(
ifs, std::string{fmt::UTF(path.filename().u8string()).data});
} catch (const std::exception& ex) {
fmt::print("Exception trying to parse config file. Exception: {}\n", ex.what());
return;
}
} else {
if (error) {
fmt::print("Filesystem error: {}\n", error.message());
}
fmt::print("Saving new configuration file {}\n", fmt::UTF(path.u8string()));
}
data["GUI"]["theme"] = mw_themes;
data["GUI"]["elfDirs"] = m_elf_viewer;
data["GUI"]["recentFiles"] = m_recent_files;
// Sorting of TOML sections
sortTomlSections(data);
std::ofstream file(path, std::ios::binary);
file << data;
file.close();
} }
void setDefaultValues() { void setDefaultValues() {
@ -937,7 +845,6 @@ void setDefaultValues() {
vkHostMarkers = false; vkHostMarkers = false;
vkGuestMarkers = false; vkGuestMarkers = false;
rdocEnable = false; rdocEnable = false;
emulator_language = "en_US";
m_language = 1; m_language = 1;
gpuId = -1; gpuId = -1;
compatibilityData = false; compatibilityData = false;

View file

@ -18,77 +18,97 @@ enum HideCursorState : int { Never, Idle, Always };
void load(const std::filesystem::path& path); void load(const std::filesystem::path& path);
void save(const std::filesystem::path& path); void save(const std::filesystem::path& path);
void saveMainWindow(const std::filesystem::path& path);
std::string getTrophyKey(); std::string getTrophyKey();
void setTrophyKey(std::string key); void setTrophyKey(std::string key);
bool getIsFullscreen();
void setIsFullscreen(bool enable);
std::string getFullscreenMode();
void setFullscreenMode(std::string mode);
u32 getScreenWidth();
u32 getScreenHeight();
void setScreenWidth(u32 width);
void setScreenHeight(u32 height);
bool debugDump();
void setDebugDump(bool enable);
s32 getGpuId();
void setGpuId(s32 selectedGpuId);
bool allowHDR();
void setAllowHDR(bool enable);
bool collectShadersForDebug();
void setCollectShaderForDebug(bool enable);
bool showSplash();
void setShowSplash(bool enable);
std::string sideTrophy();
void setSideTrophy(std::string side);
bool nullGpu();
void setNullGpu(bool enable);
bool copyGPUCmdBuffers();
void setCopyGPUCmdBuffers(bool enable);
bool dumpShaders();
void setDumpShaders(bool enable);
u32 vblankDiv();
void setVblankDiv(u32 value);
bool getisTrophyPopupDisabled();
void setisTrophyPopupDisabled(bool disable);
s16 getCursorState();
void setCursorState(s16 cursorState);
bool vkValidationEnabled();
void setVkValidation(bool enable);
bool vkValidationSyncEnabled();
void setVkSyncValidation(bool enable);
bool getVkCrashDiagnosticEnabled();
void setVkCrashDiagnosticEnabled(bool enable);
bool getVkHostMarkersEnabled();
void setVkHostMarkersEnabled(bool enable);
bool getVkGuestMarkersEnabled();
void setVkGuestMarkersEnabled(bool enable);
bool getEnableDiscordRPC();
void setEnableDiscordRPC(bool enable);
bool isRdocEnabled();
void setRdocEnabled(bool enable);
std::string getLogType();
void setLogType(const std::string& type);
std::string getLogFilter();
void setLogFilter(const std::string& type);
double getTrophyNotificationDuration();
void setTrophyNotificationDuration(double newTrophyNotificationDuration);
int getCursorHideTimeout();
void setCursorHideTimeout(int newcursorHideTimeout);
void setSeparateLogFilesEnabled(bool enabled);
bool getSeparateLogFilesEnabled();
u32 GetLanguage();
void setLanguage(u32 language);
void setUseSpecialPad(bool use);
bool getUseSpecialPad();
void setSpecialPadClass(int type);
int getSpecialPadClass();
bool getPSNSignedIn();
void setPSNSignedIn(bool sign); // no ui setting
bool patchShaders(); // no set
bool fpsColor(); // no set
bool isNeoModeConsole();
void setNeoMode(bool enable); // no ui setting
bool isDevKitConsole(); // no set
bool vkValidationGpuEnabled(); // no set
bool getIsMotionControlsEnabled();
void setIsMotionControlsEnabled(bool use);
// TODO
bool GetLoadGameSizeEnabled(); bool GetLoadGameSizeEnabled();
std::filesystem::path GetSaveDataPath(); std::filesystem::path GetSaveDataPath();
void setLoadGameSizeEnabled(bool enable); void setLoadGameSizeEnabled(bool enable);
bool getIsFullscreen();
std::string getFullscreenMode();
bool isNeoModeConsole();
bool isDevKitConsole();
bool getisTrophyPopupDisabled();
bool getEnableDiscordRPC();
bool getCompatibilityEnabled(); bool getCompatibilityEnabled();
bool getCheckCompatibilityOnStartup(); bool getCheckCompatibilityOnStartup();
bool getPSNSignedIn();
std::string getLogFilter();
std::string getLogType();
std::string getUserName(); std::string getUserName();
std::string getChooseHomeTab(); std::string getChooseHomeTab();
s16 getCursorState();
int getCursorHideTimeout();
double getTrophyNotificationDuration();
std::string getBackButtonBehavior(); std::string getBackButtonBehavior();
bool getUseSpecialPad();
int getSpecialPadClass();
bool getIsMotionControlsEnabled();
bool GetUseUnifiedInputConfig(); bool GetUseUnifiedInputConfig();
void SetUseUnifiedInputConfig(bool use); void SetUseUnifiedInputConfig(bool use);
bool GetOverrideControllerColor(); bool GetOverrideControllerColor();
void SetOverrideControllerColor(bool enable); void SetOverrideControllerColor(bool enable);
int* GetControllerCustomColor(); int* GetControllerCustomColor();
void SetControllerCustomColor(int r, int b, int g); void SetControllerCustomColor(int r, int b, int g);
u32 getScreenWidth();
u32 getScreenHeight();
s32 getGpuId();
bool allowHDR();
bool debugDump();
bool collectShadersForDebug();
bool showSplash();
std::string sideTrophy();
bool nullGpu();
bool copyGPUCmdBuffers();
bool dumpShaders();
bool patchShaders();
bool isRdocEnabled();
bool fpsColor();
u32 vblankDiv();
void setDebugDump(bool enable);
void setCollectShaderForDebug(bool enable);
void setShowSplash(bool enable);
void setSideTrophy(std::string side);
void setNullGpu(bool enable);
void setAllowHDR(bool enable);
void setCopyGPUCmdBuffers(bool enable);
void setDumpShaders(bool enable);
void setVblankDiv(u32 value);
void setGpuId(s32 selectedGpuId);
void setScreenWidth(u32 width);
void setScreenHeight(u32 height);
void setIsFullscreen(bool enable);
void setFullscreenMode(std::string mode);
void setisTrophyPopupDisabled(bool disable);
void setEnableDiscordRPC(bool enable);
void setLanguage(u32 language);
void setNeoMode(bool enable);
void setUserName(const std::string& type); void setUserName(const std::string& type);
void setChooseHomeTab(const std::string& type); void setChooseHomeTab(const std::string& type);
void setGameInstallDirs(const std::vector<std::filesystem::path>& dirs_config); void setGameInstallDirs(const std::vector<std::filesystem::path>& dirs_config);
@ -96,57 +116,20 @@ void setAllGameInstallDirs(const std::vector<GameInstallDir>& dirs_config);
void setSaveDataPath(const std::filesystem::path& path); void setSaveDataPath(const std::filesystem::path& path);
void setCompatibilityEnabled(bool use); void setCompatibilityEnabled(bool use);
void setCheckCompatibilityOnStartup(bool use); void setCheckCompatibilityOnStartup(bool use);
void setPSNSignedIn(bool sign);
void setCursorState(s16 cursorState);
void setCursorHideTimeout(int newcursorHideTimeout);
void setTrophyNotificationDuration(double newTrophyNotificationDuration);
void setBackButtonBehavior(const std::string& type); void setBackButtonBehavior(const std::string& type);
void setUseSpecialPad(bool use);
void setSpecialPadClass(int type);
void setIsMotionControlsEnabled(bool use);
void setLogType(const std::string& type);
void setLogFilter(const std::string& type);
void setSeparateLogFilesEnabled(bool enabled);
bool getSeparateLogFilesEnabled();
void setVkValidation(bool enable);
void setVkSyncValidation(bool enable);
void setRdocEnabled(bool enable);
bool vkValidationEnabled();
bool vkValidationSyncEnabled();
bool vkValidationGpuEnabled();
bool getVkCrashDiagnosticEnabled();
bool getVkHostMarkersEnabled();
bool getVkGuestMarkersEnabled();
void setVkCrashDiagnosticEnabled(bool enable);
void setVkHostMarkersEnabled(bool enable);
void setVkGuestMarkersEnabled(bool enable);
// Gui // Gui
bool addGameInstallDir(const std::filesystem::path& dir, bool enabled = true); bool addGameInstallDir(const std::filesystem::path& dir, bool enabled = true);
void removeGameInstallDir(const std::filesystem::path& dir); void removeGameInstallDir(const std::filesystem::path& dir);
void setGameInstallDirEnabled(const std::filesystem::path& dir, bool enabled); void setGameInstallDirEnabled(const std::filesystem::path& dir, bool enabled);
void setAddonInstallDir(const std::filesystem::path& dir); void setAddonInstallDir(const std::filesystem::path& dir);
void setMainWindowTheme(u32 theme);
void setElfViewer(const std::vector<std::string>& elfList);
void setRecentFiles(const std::vector<std::string>& recentFiles);
void setEmulatorLanguage(std::string language);
const std::vector<std::filesystem::path> getGameInstallDirs(); const std::vector<std::filesystem::path> getGameInstallDirs();
const std::vector<bool> getGameInstallDirsEnabled(); const std::vector<bool> getGameInstallDirsEnabled();
std::filesystem::path getAddonInstallDir(); std::filesystem::path getAddonInstallDir();
u32 getMainWindowTheme();
std::vector<std::string> getElfViewer();
std::vector<std::string> getRecentFiles();
std::string getEmulatorLanguage();
void setDefaultValues(); void setDefaultValues();
// todo: name and function location pending // todo: name and function location pending
std::filesystem::path GetFoolproofKbmConfigFile(const std::string& game_id = ""); std::filesystem::path GetFoolproofKbmConfigFile(const std::string& game_id = "");
// settings
u32 GetLanguage();
}; // namespace Config }; // namespace Config

View file

@ -22,25 +22,25 @@ static Core::FileSys::MntPoints* g_mnt = Common::Singleton<Core::FileSys::MntPoi
namespace fs = std::filesystem; namespace fs = std::filesystem;
// clang-format off // clang-format off
static const std::unordered_map<std::string, std::string> default_title = { static const std::unordered_map<int, std::string> default_title = {
{"ja_JP", "セーブデータ"}, {0/*"ja_JP"*/, "セーブデータ"},
{"en_US", "Saved Data"}, {1/*"en_US"*/, "Saved Data"},
{"fr_FR", "Données sauvegardées"}, {2/*"fr_FR"*/, "Données sauvegardées"},
{"es_ES", "Datos guardados"}, {3/*"es_ES"*/, "Datos guardados"},
{"de_DE", "Gespeicherte Daten"}, {4/*"de_DE"*/, "Gespeicherte Daten"},
{"it_IT", "Dati salvati"}, {5/*"it_IT"*/, "Dati salvati"},
{"nl_NL", "Opgeslagen data"}, {6/*"nl_NL"*/, "Opgeslagen data"},
{"pt_PT", "Dados guardados"}, {7/*"pt_PT"*/, "Dados guardados"},
{"ru_RU", "Сохраненные данные"}, {8/*"ru_RU"*/, "Сохраненные данные"},
{"ko_KR", "저장 데이터"}, {9/*"ko_KR"*/, "저장 데이터"},
{"zh_CN", "保存数据"}, {10/*"zh_CN"*/, "保存数据"},
{"fi_FI", "Tallennetut tiedot"}, {12/*"fi_FI"*/, "Tallennetut tiedot"},
{"sv_SE", "Sparade data"}, {13/*"sv_SE"*/, "Sparade data"},
{"da_DK", "Gemte data"}, {14/*"da_DK"*/, "Gemte data"},
{"no_NO", "Lagrede data"}, {15/*"no_NO"*/, "Lagrede data"},
{"pl_PL", "Zapisane dane"}, {16/*"pl_PL"*/, "Zapisane dane"},
{"pt_BR", "Dados salvos"}, {17/*"pt_BR"*/, "Dados salvos"},
{"tr_TR", "Kayıtlı Veriler"}, {19/*"tr_TR"*/, "Kayıtlı Veriler"},
}; };
// clang-format on // clang-format on
@ -71,9 +71,9 @@ fs::path SaveInstance::GetParamSFOPath(const fs::path& dir_path) {
void SaveInstance::SetupDefaultParamSFO(PSF& param_sfo, std::string dir_name, void SaveInstance::SetupDefaultParamSFO(PSF& param_sfo, std::string dir_name,
std::string game_serial) { std::string game_serial) {
std::string locale = Config::getEmulatorLanguage(); int locale = Config::GetLanguage();
if (!default_title.contains(locale)) { if (!default_title.contains(locale)) {
locale = "en_US"; locale = 1; // default to en_US if not found
} }
#define P(type, key, ...) param_sfo.Add##type(std::string{key}, __VA_ARGS__) #define P(type, key, ...) param_sfo.Add##type(std::string{key}, __VA_ARGS__)

View file

@ -58,10 +58,7 @@ Emulator::Emulator() {
#endif #endif
} }
Emulator::~Emulator() { Emulator::~Emulator() {}
const auto config_dir = Common::FS::GetUserPath(Common::FS::PathType::UserDir);
Config::saveMainWindow(config_dir / "config.toml");
}
void Emulator::Run(std::filesystem::path file, const std::vector<std::string> args) { void Emulator::Run(std::filesystem::path file, const std::vector<std::string> args) {
if (std::filesystem::is_directory(file)) { if (std::filesystem::is_directory(file)) {

View file

@ -12,7 +12,8 @@
#include "main_window_themes.h" #include "main_window_themes.h"
#include "ui_about_dialog.h" #include "ui_about_dialog.h"
AboutDialog::AboutDialog(QWidget* parent) : QDialog(parent), ui(new Ui::AboutDialog) { AboutDialog::AboutDialog(std::shared_ptr<gui_settings> gui_settings, QWidget* parent)
: QDialog(parent), ui(new Ui::AboutDialog), m_gui_settings(std::move(gui_settings)) {
ui->setupUi(this); ui->setupUi(this);
preloadImages(); preloadImages();
@ -57,7 +58,7 @@ void AboutDialog::preloadImages() {
} }
void AboutDialog::updateImagesForCurrentTheme() { void AboutDialog::updateImagesForCurrentTheme() {
Theme currentTheme = static_cast<Theme>(Config::getMainWindowTheme()); Theme currentTheme = static_cast<Theme>(m_gui_settings->GetValue(gui::gen_theme).toInt());
bool isDarkTheme = (currentTheme == Theme::Dark || currentTheme == Theme::Green || bool isDarkTheme = (currentTheme == Theme::Dark || currentTheme == Theme::Green ||
currentTheme == Theme::Blue || currentTheme == Theme::Violet); currentTheme == Theme::Blue || currentTheme == Theme::Violet);
if (isDarkTheme) { if (isDarkTheme) {
@ -188,7 +189,7 @@ void AboutDialog::removeHoverEffect(QLabel* label) {
} }
bool AboutDialog::isDarkTheme() const { bool AboutDialog::isDarkTheme() const {
Theme currentTheme = static_cast<Theme>(Config::getMainWindowTheme()); Theme currentTheme = static_cast<Theme>(m_gui_settings->GetValue(gui::gen_theme).toInt());
return currentTheme == Theme::Dark || currentTheme == Theme::Green || return currentTheme == Theme::Dark || currentTheme == Theme::Green ||
currentTheme == Theme::Blue || currentTheme == Theme::Violet; currentTheme == Theme::Blue || currentTheme == Theme::Violet;
} }

View file

@ -8,6 +8,7 @@
#include <QLabel> #include <QLabel>
#include <QPixmap> #include <QPixmap>
#include <QUrl> #include <QUrl>
#include "gui_settings.h"
namespace Ui { namespace Ui {
class AboutDialog; class AboutDialog;
@ -17,7 +18,7 @@ class AboutDialog : public QDialog {
Q_OBJECT Q_OBJECT
public: public:
explicit AboutDialog(QWidget* parent = nullptr); explicit AboutDialog(std::shared_ptr<gui_settings> gui_settings, QWidget* parent = nullptr);
~AboutDialog(); ~AboutDialog();
bool eventFilter(QObject* obj, QEvent* event); bool eventFilter(QObject* obj, QEvent* event);
@ -33,4 +34,5 @@ private:
QPixmap originalImages[5]; QPixmap originalImages[5];
QPixmap invertedImages[5]; QPixmap invertedImages[5];
std::shared_ptr<gui_settings> m_gui_settings;
}; };

View file

@ -3,10 +3,12 @@
#include "elf_viewer.h" #include "elf_viewer.h"
ElfViewer::ElfViewer(QWidget* parent) : QTableWidget(parent) { ElfViewer::ElfViewer(std::shared_ptr<gui_settings> gui_settings, QWidget* parent)
dir_list_std = Config::getElfViewer(); : QTableWidget(parent), m_gui_settings(std::move(gui_settings)) {
for (const auto& str : dir_list_std) {
dir_list.append(QString::fromStdString(str)); list = gui_settings::Var2List(m_gui_settings->GetValue(gui::gen_elfDirs));
for (const auto& str : list) {
dir_list.append(str);
} }
CheckElfFolders(); CheckElfFolders();
@ -55,11 +57,11 @@ void ElfViewer::OpenElfFolder() {
} }
std::ranges::sort(m_elf_list); std::ranges::sort(m_elf_list);
OpenElfFiles(); OpenElfFiles();
dir_list_std.clear(); list.clear();
for (auto dir : dir_list) { for (auto dir : dir_list) {
dir_list_std.push_back(dir.toStdString()); list.push_back(dir);
} }
Config::setElfViewer(dir_list_std); m_gui_settings->SetValue(gui::gen_elfDirs, gui_settings::List2Var(list));
} else { } else {
// qDebug() << "Folder selection canceled."; // qDebug() << "Folder selection canceled.";
} }

View file

@ -11,7 +11,7 @@
class ElfViewer : public QTableWidget { class ElfViewer : public QTableWidget {
Q_OBJECT Q_OBJECT
public: public:
explicit ElfViewer(QWidget* parent = nullptr); explicit ElfViewer(std::shared_ptr<gui_settings> gui_settings, QWidget* parent = nullptr);
QStringList m_elf_list; QStringList m_elf_list;
private: private:
@ -21,7 +21,8 @@ private:
Core::Loader::Elf m_elf_file; Core::Loader::Elf m_elf_file;
QStringList dir_list; QStringList dir_list;
QStringList elf_headers_list; QStringList elf_headers_list;
std::vector<std::string> dir_list_std; QList<QString> list;
std::shared_ptr<gui_settings> m_gui_settings;
void SetTableItem(QTableWidget* game_list, int row, int column, QString itemStr) { void SetTableItem(QTableWidget* game_list, int row, int column, QString itemStr) {
QTableWidgetItem* item = new QTableWidgetItem(); QTableWidgetItem* item = new QTableWidgetItem();

View file

@ -34,7 +34,8 @@ GameGridFrame::GameGridFrame(std::shared_ptr<gui_settings> gui_settings,
connect(this->horizontalScrollBar(), &QScrollBar::valueChanged, this, connect(this->horizontalScrollBar(), &QScrollBar::valueChanged, this,
&GameGridFrame::RefreshGridBackgroundImage); &GameGridFrame::RefreshGridBackgroundImage);
connect(this, &QTableWidget::customContextMenuRequested, this, [=, this](const QPoint& pos) { connect(this, &QTableWidget::customContextMenuRequested, this, [=, this](const QPoint& pos) {
m_gui_context_menus.RequestGameMenu(pos, m_game_info->m_games, m_compat_info, this, false); m_gui_context_menus.RequestGameMenu(pos, m_game_info->m_games, m_compat_info,
m_gui_settings, this, false);
}); });
} }

View file

@ -75,7 +75,8 @@ GameListFrame::GameListFrame(std::shared_ptr<gui_settings> gui_settings,
}); });
connect(this, &QTableWidget::customContextMenuRequested, this, [=, this](const QPoint& pos) { connect(this, &QTableWidget::customContextMenuRequested, this, [=, this](const QPoint& pos) {
m_gui_context_menus.RequestGameMenu(pos, m_game_info->m_games, m_compat_info, this, true); m_gui_context_menus.RequestGameMenu(pos, m_game_info->m_games, m_compat_info,
m_gui_settings, this, true);
}); });
connect(this, &QTableWidget::cellClicked, this, [=, this](int row, int column) { connect(this, &QTableWidget::cellClicked, this, [=, this](int row, int column) {

View file

@ -32,8 +32,10 @@ class GuiContextMenus : public QObject {
public: public:
void RequestGameMenu(const QPoint& pos, QVector<GameInfo>& m_games, void RequestGameMenu(const QPoint& pos, QVector<GameInfo>& m_games,
std::shared_ptr<CompatibilityInfoClass> m_compat_info, std::shared_ptr<CompatibilityInfoClass> m_compat_info,
QTableWidget* widget, bool isList) { std::shared_ptr<gui_settings> settings, QTableWidget* widget,
bool isList) {
QPoint global_pos = widget->viewport()->mapToGlobal(pos); QPoint global_pos = widget->viewport()->mapToGlobal(pos);
std::shared_ptr<gui_settings> m_gui_settings = std::move(settings);
int itemID = 0; int itemID = 0;
if (isList) { if (isList) {
itemID = widget->currentRow(); itemID = widget->currentRow();
@ -357,7 +359,7 @@ public:
QString gameName = QString::fromStdString(m_games[itemID].name); QString gameName = QString::fromStdString(m_games[itemID].name);
TrophyViewer* trophyViewer = TrophyViewer* trophyViewer =
new TrophyViewer(trophyPath, gameTrpPath, gameName, allTrophyGames); new TrophyViewer(m_gui_settings, trophyPath, gameTrpPath, gameName, allTrophyGames);
trophyViewer->show(); trophyViewer->show();
connect(widget->parent(), &QWidget::destroyed, trophyViewer, connect(widget->parent(), &QWidget::destroyed, trophyViewer,
[trophyViewer]() { trophyViewer->deleteLater(); }); [trophyViewer]() { trophyViewer->deleteLater(); });

View file

@ -17,6 +17,12 @@ const QString game_grid = "game_grid";
const gui_value gen_checkForUpdates = gui_value(general_settings, "checkForUpdates", false); const gui_value gen_checkForUpdates = gui_value(general_settings, "checkForUpdates", false);
const gui_value gen_showChangeLog = gui_value(general_settings, "showChangeLog", false); const gui_value gen_showChangeLog = gui_value(general_settings, "showChangeLog", false);
const gui_value gen_updateChannel = gui_value(general_settings, "updateChannel", "Release"); const gui_value gen_updateChannel = gui_value(general_settings, "updateChannel", "Release");
const gui_value gen_recentFiles =
gui_value(main_window, "recentFiles", QVariant::fromValue(QList<QString>()));
const gui_value gen_guiLanguage = gui_value(general_settings, "guiLanguage", "en_US");
const gui_value gen_elfDirs =
gui_value(main_window, "elfDirs", QVariant::fromValue(QList<QString>()));
const gui_value gen_theme = gui_value(general_settings, "theme", 0);
// main window settings // main window settings
const gui_value mw_geometry = gui_value(main_window, "geometry", QByteArray()); const gui_value mw_geometry = gui_value(main_window, "geometry", QByteArray());

View file

@ -39,8 +39,6 @@ MainWindow::MainWindow(QWidget* parent) : QMainWindow(parent), ui(new Ui::MainWi
MainWindow::~MainWindow() { MainWindow::~MainWindow() {
SaveWindowState(); SaveWindowState();
const auto config_dir = Common::FS::GetUserPath(Common::FS::PathType::UserDir);
Config::saveMainWindow(config_dir / "config.toml");
} }
bool MainWindow::Init() { bool MainWindow::Init() {
@ -297,7 +295,7 @@ void MainWindow::CreateDockWindows() {
m_game_list_frame->setObjectName("gamelist"); m_game_list_frame->setObjectName("gamelist");
m_game_grid_frame.reset(new GameGridFrame(m_gui_settings, m_game_info, m_compat_info, this)); m_game_grid_frame.reset(new GameGridFrame(m_gui_settings, m_game_info, m_compat_info, this));
m_game_grid_frame->setObjectName("gamegridlist"); m_game_grid_frame->setObjectName("gamegridlist");
m_elf_viewer.reset(new ElfViewer(this)); m_elf_viewer.reset(new ElfViewer(m_gui_settings, this));
m_elf_viewer->setObjectName("elflist"); m_elf_viewer->setObjectName("elflist");
int table_mode = m_gui_settings->GetValue(gui::gl_mode).toInt(); int table_mode = m_gui_settings->GetValue(gui::gl_mode).toInt();
@ -492,7 +490,7 @@ void MainWindow::CreateConnects() {
#endif #endif
connect(ui->aboutAct, &QAction::triggered, this, [this]() { connect(ui->aboutAct, &QAction::triggered, this, [this]() {
auto aboutDialog = new AboutDialog(this); auto aboutDialog = new AboutDialog(m_gui_settings, this);
aboutDialog->exec(); aboutDialog->exec();
}); });
@ -771,14 +769,14 @@ void MainWindow::CreateConnects() {
QString gameName = QString::fromStdString(firstGame.name); QString gameName = QString::fromStdString(firstGame.name);
TrophyViewer* trophyViewer = TrophyViewer* trophyViewer =
new TrophyViewer(trophyPath, gameTrpPath, gameName, allTrophyGames); new TrophyViewer(m_gui_settings, trophyPath, gameTrpPath, gameName, allTrophyGames);
trophyViewer->show(); trophyViewer->show();
}); });
// Themes // Themes
connect(ui->setThemeDark, &QAction::triggered, &m_window_themes, [this]() { connect(ui->setThemeDark, &QAction::triggered, &m_window_themes, [this]() {
m_window_themes.SetWindowTheme(Theme::Dark, ui->mw_searchbar); m_window_themes.SetWindowTheme(Theme::Dark, ui->mw_searchbar);
Config::setMainWindowTheme(static_cast<int>(Theme::Dark)); m_gui_settings->SetValue(gui::gen_theme, static_cast<int>(Theme::Dark));
if (isIconBlack) { if (isIconBlack) {
SetUiIcons(false); SetUiIcons(false);
isIconBlack = false; isIconBlack = false;
@ -786,7 +784,7 @@ void MainWindow::CreateConnects() {
}); });
connect(ui->setThemeLight, &QAction::triggered, &m_window_themes, [this]() { connect(ui->setThemeLight, &QAction::triggered, &m_window_themes, [this]() {
m_window_themes.SetWindowTheme(Theme::Light, ui->mw_searchbar); m_window_themes.SetWindowTheme(Theme::Light, ui->mw_searchbar);
Config::setMainWindowTheme(static_cast<int>(Theme::Light)); m_gui_settings->SetValue(gui::gen_theme, static_cast<int>(Theme::Light));
if (!isIconBlack) { if (!isIconBlack) {
SetUiIcons(true); SetUiIcons(true);
isIconBlack = true; isIconBlack = true;
@ -794,7 +792,7 @@ void MainWindow::CreateConnects() {
}); });
connect(ui->setThemeGreen, &QAction::triggered, &m_window_themes, [this]() { connect(ui->setThemeGreen, &QAction::triggered, &m_window_themes, [this]() {
m_window_themes.SetWindowTheme(Theme::Green, ui->mw_searchbar); m_window_themes.SetWindowTheme(Theme::Green, ui->mw_searchbar);
Config::setMainWindowTheme(static_cast<int>(Theme::Green)); m_gui_settings->SetValue(gui::gen_theme, static_cast<int>(Theme::Green));
if (isIconBlack) { if (isIconBlack) {
SetUiIcons(false); SetUiIcons(false);
isIconBlack = false; isIconBlack = false;
@ -802,7 +800,7 @@ void MainWindow::CreateConnects() {
}); });
connect(ui->setThemeBlue, &QAction::triggered, &m_window_themes, [this]() { connect(ui->setThemeBlue, &QAction::triggered, &m_window_themes, [this]() {
m_window_themes.SetWindowTheme(Theme::Blue, ui->mw_searchbar); m_window_themes.SetWindowTheme(Theme::Blue, ui->mw_searchbar);
Config::setMainWindowTheme(static_cast<int>(Theme::Blue)); m_gui_settings->SetValue(gui::gen_theme, static_cast<int>(Theme::Blue));
if (isIconBlack) { if (isIconBlack) {
SetUiIcons(false); SetUiIcons(false);
isIconBlack = false; isIconBlack = false;
@ -810,7 +808,7 @@ void MainWindow::CreateConnects() {
}); });
connect(ui->setThemeViolet, &QAction::triggered, &m_window_themes, [this]() { connect(ui->setThemeViolet, &QAction::triggered, &m_window_themes, [this]() {
m_window_themes.SetWindowTheme(Theme::Violet, ui->mw_searchbar); m_window_themes.SetWindowTheme(Theme::Violet, ui->mw_searchbar);
Config::setMainWindowTheme(static_cast<int>(Theme::Violet)); m_gui_settings->SetValue(gui::gen_theme, static_cast<int>(Theme::Violet));
if (isIconBlack) { if (isIconBlack) {
SetUiIcons(false); SetUiIcons(false);
isIconBlack = false; isIconBlack = false;
@ -818,7 +816,7 @@ void MainWindow::CreateConnects() {
}); });
connect(ui->setThemeGruvbox, &QAction::triggered, &m_window_themes, [this]() { connect(ui->setThemeGruvbox, &QAction::triggered, &m_window_themes, [this]() {
m_window_themes.SetWindowTheme(Theme::Gruvbox, ui->mw_searchbar); m_window_themes.SetWindowTheme(Theme::Gruvbox, ui->mw_searchbar);
Config::setMainWindowTheme(static_cast<int>(Theme::Gruvbox)); m_gui_settings->SetValue(gui::gen_theme, static_cast<int>(Theme::Gruvbox));
if (isIconBlack) { if (isIconBlack) {
SetUiIcons(false); SetUiIcons(false);
isIconBlack = false; isIconBlack = false;
@ -826,7 +824,7 @@ void MainWindow::CreateConnects() {
}); });
connect(ui->setThemeTokyoNight, &QAction::triggered, &m_window_themes, [this]() { connect(ui->setThemeTokyoNight, &QAction::triggered, &m_window_themes, [this]() {
m_window_themes.SetWindowTheme(Theme::TokyoNight, ui->mw_searchbar); m_window_themes.SetWindowTheme(Theme::TokyoNight, ui->mw_searchbar);
Config::setMainWindowTheme(static_cast<int>(Theme::TokyoNight)); m_gui_settings->SetValue(gui::gen_theme, static_cast<int>(Theme::TokyoNight));
if (isIconBlack) { if (isIconBlack) {
SetUiIcons(false); SetUiIcons(false);
isIconBlack = false; isIconBlack = false;
@ -834,7 +832,7 @@ void MainWindow::CreateConnects() {
}); });
connect(ui->setThemeOled, &QAction::triggered, &m_window_themes, [this]() { connect(ui->setThemeOled, &QAction::triggered, &m_window_themes, [this]() {
m_window_themes.SetWindowTheme(Theme::Oled, ui->mw_searchbar); m_window_themes.SetWindowTheme(Theme::Oled, ui->mw_searchbar);
Config::setMainWindowTheme(static_cast<int>(Theme::Oled)); m_gui_settings->SetValue(gui::gen_theme, static_cast<int>(Theme::Oled));
if (isIconBlack) { if (isIconBlack) {
SetUiIcons(false); SetUiIcons(false);
isIconBlack = false; isIconBlack = false;
@ -981,7 +979,7 @@ void MainWindow::InstallDirectory() {
} }
void MainWindow::SetLastUsedTheme() { void MainWindow::SetLastUsedTheme() {
Theme lastTheme = static_cast<Theme>(Config::getMainWindowTheme()); Theme lastTheme = static_cast<Theme>(m_gui_settings->GetValue(gui::gen_theme).toInt());
m_window_themes.SetWindowTheme(lastTheme, ui->mw_searchbar); m_window_themes.SetWindowTheme(lastTheme, ui->mw_searchbar);
switch (lastTheme) { switch (lastTheme) {
@ -1122,33 +1120,32 @@ void MainWindow::HandleResize(QResizeEvent* event) {
} }
void MainWindow::AddRecentFiles(QString filePath) { void MainWindow::AddRecentFiles(QString filePath) {
std::vector<std::string> vec = Config::getRecentFiles(); QList<QString> list = gui_settings::Var2List(m_gui_settings->GetValue(gui::gen_recentFiles));
if (!vec.empty()) { if (!list.empty()) {
if (filePath.toStdString() == vec.at(0)) { if (filePath == list.at(0)) {
return; return;
} }
auto it = std::find(vec.begin(), vec.end(), filePath.toStdString()); auto it = std::find(list.begin(), list.end(), filePath);
if (it != vec.end()) { if (it != list.end()) {
vec.erase(it); list.erase(it);
} }
} }
vec.insert(vec.begin(), filePath.toStdString()); list.insert(list.begin(), filePath);
if (vec.size() > 6) { if (list.size() > 6) {
vec.pop_back(); list.pop_back();
} }
Config::setRecentFiles(vec); m_gui_settings->SetValue(gui::gen_recentFiles, gui_settings::List2Var(list));
const auto config_dir = Common::FS::GetUserPath(Common::FS::PathType::UserDir);
Config::saveMainWindow(config_dir / "config.toml");
CreateRecentGameActions(); // Refresh the QActions. CreateRecentGameActions(); // Refresh the QActions.
} }
void MainWindow::CreateRecentGameActions() { void MainWindow::CreateRecentGameActions() {
m_recent_files_group = new QActionGroup(this); m_recent_files_group = new QActionGroup(this);
ui->menuRecent->clear(); ui->menuRecent->clear();
std::vector<std::string> vec = Config::getRecentFiles(); QList<QString> list = gui_settings::Var2List(m_gui_settings->GetValue(gui::gen_recentFiles));
for (int i = 0; i < vec.size(); i++) {
for (int i = 0; i < list.size(); i++) {
QAction* recentFileAct = new QAction(this); QAction* recentFileAct = new QAction(this);
recentFileAct->setText(QString::fromStdString(vec.at(i))); recentFileAct->setText(list.at(i));
ui->menuRecent->addAction(recentFileAct); ui->menuRecent->addAction(recentFileAct);
m_recent_files_group->addAction(recentFileAct); m_recent_files_group->addAction(recentFileAct);
} }
@ -1165,7 +1162,7 @@ void MainWindow::CreateRecentGameActions() {
} }
void MainWindow::LoadTranslation() { void MainWindow::LoadTranslation() {
auto language = QString::fromStdString(Config::getEmulatorLanguage()); auto language = m_gui_settings->GetValue(gui::gen_guiLanguage).toString();
const QString base_dir = QStringLiteral(":/translations"); const QString base_dir = QStringLiteral(":/translations");
QString base_path = QStringLiteral("%1/%2.qm").arg(base_dir).arg(language); QString base_path = QStringLiteral("%1/%2.qm").arg(base_dir).arg(language);
@ -1190,8 +1187,8 @@ void MainWindow::LoadTranslation() {
} }
} }
void MainWindow::OnLanguageChanged(const std::string& locale) { void MainWindow::OnLanguageChanged(const QString& locale) {
Config::setEmulatorLanguage(locale); m_gui_settings->SetValue(gui::gen_guiLanguage, locale);
LoadTranslation(); LoadTranslation();
} }

View file

@ -47,7 +47,7 @@ private Q_SLOTS:
void ShowGameList(); void ShowGameList();
void RefreshGameTable(); void RefreshGameTable();
void HandleResize(QResizeEvent* event); void HandleResize(QResizeEvent* event);
void OnLanguageChanged(const std::string& locale); void OnLanguageChanged(const QString& locale);
void toggleLabelsUnderIcons(); void toggleLabelsUnderIcons();
private: private:

View file

@ -75,3 +75,17 @@ void settings::SetValue(const QString& key, const QString& name, const QVariant&
} }
} }
} }
QVariant settings::List2Var(const QList<QString>& list) {
QByteArray ba;
QDataStream stream(&ba, QIODevice::WriteOnly);
stream << list;
return QVariant(ba);
}
QList<QString> settings::Var2List(const QVariant& var) {
QList<QString> list;
QByteArray ba = var.toByteArray();
QDataStream stream(&ba, QIODevice::ReadOnly);
stream >> list;
return list;
}

View file

@ -35,6 +35,8 @@ public:
QVariant GetValue(const QString& key, const QString& name, const QVariant& def) const; QVariant GetValue(const QString& key, const QString& name, const QVariant& def) const;
QVariant GetValue(const gui_value& entry) const; QVariant GetValue(const gui_value& entry) const;
static QVariant List2Var(const QList<QString>& list);
static QList<QString> Var2List(const QVariant& var);
public Q_SLOTS: public Q_SLOTS:
/** Remove entry */ /** Remove entry */

View file

@ -594,7 +594,7 @@ void SettingsDialog::OnLanguageChanged(int index) {
ui->retranslateUi(this); ui->retranslateUi(this);
emit LanguageChanged(ui->emulatorLanguageComboBox->itemData(index).toString().toStdString()); emit LanguageChanged(ui->emulatorLanguageComboBox->itemData(index).toString());
} }
void SettingsDialog::OnCursorStateChanged(s16 index) { void SettingsDialog::OnCursorStateChanged(s16 index) {
@ -886,4 +886,5 @@ void SettingsDialog::setDefaultValues() {
} else { } else {
m_gui_settings->SetValue(gui::gen_updateChannel, "Nightly"); m_gui_settings->SetValue(gui::gen_updateChannel, "Nightly");
} }
m_gui_settings->SetValue(gui::gen_guiLanguage, "en_US");
} }

View file

@ -32,7 +32,7 @@ public:
int exec() override; int exec() override;
signals: signals:
void LanguageChanged(const std::string& locale); void LanguageChanged(const QString& locale);
void CompatibilityChanged(); void CompatibilityChanged();
void BackgroundOpacityChanged(int opacity); void BackgroundOpacityChanged(int opacity);

View file

@ -104,14 +104,16 @@ void TrophyViewer::updateTableFilters() {
} }
} }
TrophyViewer::TrophyViewer(QString trophyPath, QString gameTrpPath, QString gameName, TrophyViewer::TrophyViewer(std::shared_ptr<gui_settings> gui_settings, QString trophyPath,
QString gameTrpPath, QString gameName,
const QVector<TrophyGameInfo>& allTrophyGames) const QVector<TrophyGameInfo>& allTrophyGames)
: QMainWindow(), allTrophyGames_(allTrophyGames), currentGameName_(gameName) { : QMainWindow(), allTrophyGames_(allTrophyGames), currentGameName_(gameName),
m_gui_settings(std::move(gui_settings)) {
this->setWindowTitle(tr("Trophy Viewer") + " - " + currentGameName_); this->setWindowTitle(tr("Trophy Viewer") + " - " + currentGameName_);
this->setAttribute(Qt::WA_DeleteOnClose); this->setAttribute(Qt::WA_DeleteOnClose);
tabWidget = new QTabWidget(this); tabWidget = new QTabWidget(this);
auto lan = Config::getEmulatorLanguage(); auto lan = m_gui_settings->GetValue(gui::gen_guiLanguage).toString();
if (lan == "en_US" || lan == "zh_CN" || lan == "zh_TW" || lan == "ja_JP" || lan == "ko_KR" || if (lan == "en_US" || lan == "zh_CN" || lan == "zh_TW" || lan == "ja_JP" || lan == "ko_KR" ||
lan == "lt_LT" || lan == "nb_NO" || lan == "nl_NL") { lan == "lt_LT" || lan == "nb_NO" || lan == "nl_NL") {
useEuropeanDateFormat = false; useEuropeanDateFormat = false;
@ -463,7 +465,7 @@ void TrophyViewer::SetTableItem(QTableWidget* parent, int row, int column, QStri
item->setTextAlignment(Qt::AlignCenter); item->setTextAlignment(Qt::AlignCenter);
item->setFont(QFont("Arial", 12, QFont::Bold)); item->setFont(QFont("Arial", 12, QFont::Bold));
Theme theme = static_cast<Theme>(Config::getMainWindowTheme()); Theme theme = static_cast<Theme>(m_gui_settings->GetValue(gui::gen_theme).toInt());
if (theme == Theme::Light) { if (theme == Theme::Light) {
item->setForeground(QBrush(Qt::black)); item->setForeground(QBrush(Qt::black));

View file

@ -23,6 +23,7 @@
#include "common/types.h" #include "common/types.h"
#include "core/file_format/trp.h" #include "core/file_format/trp.h"
#include "gui_settings.h"
struct TrophyGameInfo { struct TrophyGameInfo {
QString name; QString name;
@ -34,7 +35,8 @@ class TrophyViewer : public QMainWindow {
Q_OBJECT Q_OBJECT
public: public:
explicit TrophyViewer( explicit TrophyViewer(
QString trophyPath, QString gameTrpPath, QString gameName = "", std::shared_ptr<gui_settings> gui_settings, QString trophyPath, QString gameTrpPath,
QString gameName = "",
const QVector<TrophyGameInfo>& allTrophyGames = QVector<TrophyGameInfo>()); const QVector<TrophyGameInfo>& allTrophyGames = QVector<TrophyGameInfo>());
void updateTrophyInfo(); void updateTrophyInfo();
@ -77,4 +79,5 @@ private:
} }
return "Unknown"; return "Unknown";
} }
std::shared_ptr<gui_settings> m_gui_settings;
}; };