Qt: Serialize icon & theme, properly set them

This commit is contained in:
wheremyfoodat 2024-12-01 21:33:50 +02:00
parent 95cc79e0a3
commit 6f90c25fd2
8 changed files with 128 additions and 26 deletions

View file

@ -280,6 +280,7 @@ set(SOURCE_FILES src/emulator.cpp src/io_file.cpp src/config.cpp
src/core/memory.cpp src/renderer.cpp src/core/renderer_null/renderer_null.cpp
src/http_server.cpp src/stb_image_write.c src/core/cheats.cpp src/core/action_replay.cpp
src/discord_rpc.cpp src/lua.cpp src/memory_mapped_file.cpp src/miniaudio.cpp src/renderdoc.cpp
src/frontend_settings.cpp
)
set(CRYPTO_SOURCE_FILES src/core/crypto/aes_engine.cpp)
set(KERNEL_SOURCE_FILES src/core/kernel/kernel.cpp src/core/kernel/resource_limits.cpp
@ -361,7 +362,7 @@ set(HEADER_FILES include/emulator.hpp include/helpers.hpp include/termcolor.hpp
include/PICA/pica_vert_config.hpp include/sdl_sensors.hpp include/PICA/draw_acceleration.hpp include/renderdoc.hpp
include/align.hpp include/audio/aac_decoder.hpp include/PICA/pica_simd.hpp include/services/fonts.hpp
include/audio/audio_interpolation.hpp include/audio/hle_mixer.hpp include/audio/dsp_simd.hpp
include/services/dsp_firmware_db.hpp
include/services/dsp_firmware_db.hpp include/frontend_settings.hpp
)
cmrc_add_resource_library(

View file

@ -3,6 +3,7 @@
#include "audio/dsp_core.hpp"
#include "renderer.hpp"
#include "frontend_settings.hpp"
struct AudioDeviceConfig {
float volumeRaw = 1.0f;
@ -86,8 +87,9 @@ struct EmulatorConfig {
WindowSettings windowSettings;
AudioDeviceConfig audioDeviceConfig;
FrontendSettings frontendSettings;
EmulatorConfig(const std::filesystem::path& path);
void load();
void save();
};
};

View file

@ -0,0 +1,30 @@
#pragma once
#include <string>
// Some UI settings that aren't fully frontend-dependent. Note: Not all frontends will support the same settings.
// Note: Any enums should ideally be ordered in the same order we want to show them in UI dropdown menus, so that we can cast indices to enums
// directly.
struct FrontendSettings {
enum class Theme : int {
System = 0,
Light = 1,
Dark = 2,
GreetingsCat = 3,
Cream = 4,
};
// Different panda-themed window icons
enum class WindowIcon : int {
Rpog = 0,
Rsyn = 1,
};
Theme theme = Theme::Dark;
WindowIcon icon = WindowIcon::Rpog;
static Theme themeFromString(std::string inString);
static const char* themeToString(Theme theme);
static WindowIcon iconFromString(std::string inString);
static const char* iconToString(WindowIcon icon);
};

View file

@ -15,6 +15,7 @@
#include <utility>
#include "emulator.hpp"
#include "frontend_settings.hpp"
class ConfigWindow : public QDialog {
Q_OBJECT
@ -23,21 +24,8 @@ class ConfigWindow : public QDialog {
using ConfigCallback = std::function<void()>;
using IconCallback = std::function<void(const QString&)>;
enum class Theme : int {
System = 0,
Light = 1,
Dark = 2,
GreetingsCat = 3,
Cream = 4,
};
enum class WindowIcon : int {
Rpog = 0,
Rsyn = 1,
};
Theme currentTheme;
WindowIcon currentIcon;
using Theme = FrontendSettings::Theme;
using WindowIcon = FrontendSettings::WindowIcon;
QTextEdit* helpText = nullptr;
QListWidget* widgetList = nullptr;
@ -54,8 +42,8 @@ class ConfigWindow : public QDialog {
IconCallback updateIcon;
void addWidget(QWidget* widget, QString title, QString icon, QString helpText);
void setTheme(Theme theme);
void setIcon(WindowIcon icon);
void setTheme(FrontendSettings::Theme theme);
void setIcon(FrontendSettings::WindowIcon icon);
public:
ConfigWindow(ConfigCallback configCallback, IconCallback iconCallback, const EmulatorConfig& config, QWidget* parent = nullptr);

View file

@ -130,6 +130,16 @@ void EmulatorConfig::load() {
sdWriteProtected = toml::find_or<toml::boolean>(sd, "WriteProtectVirtualSD", false);
}
}
if (data.contains("UI")) {
auto uiResult = toml::expect<toml::value>(data.at("UI"));
if (uiResult.is_ok()) {
auto ui = uiResult.unwrap();
frontendSettings.theme = FrontendSettings::themeFromString(toml::find_or<std::string>(ui, "Theme", "dark"));
frontendSettings.icon = FrontendSettings::iconFromString(toml::find_or<std::string>(ui, "WindowIcon", "rpog"));
}
}
}
void EmulatorConfig::save() {
@ -186,6 +196,9 @@ void EmulatorConfig::save() {
data["SD"]["UseVirtualSD"] = sdCardInserted;
data["SD"]["WriteProtectVirtualSD"] = sdWriteProtected;
data["UI"]["Theme"] = std::string(FrontendSettings::themeToString(frontendSettings.theme));
data["UI"]["WindowIcon"] = std::string(FrontendSettings::iconToString(frontendSettings.icon));
std::ofstream file(path, std::ios::out);
file << data;
file.close();

59
src/frontend_settings.cpp Normal file
View file

@ -0,0 +1,59 @@
#include "frontend_settings.hpp"
#include <algorithm>
#include <cctype>
#include <unordered_map>
// Frontend setting serialization/deserialization functions
FrontendSettings::Theme FrontendSettings::themeFromString(std::string inString) {
// Transform to lower-case to make the setting case-insensitive
std::transform(inString.begin(), inString.end(), inString.begin(), [](unsigned char c) { return std::tolower(c); });
static const std::unordered_map<std::string, Theme> map = {
{"system", Theme::System}, {"light", Theme::Light}, {"dark", Theme::Dark}, {"greetingscat", Theme::GreetingsCat}, {"cream", Theme::Cream},
};
if (auto search = map.find(inString); search != map.end()) {
return search->second;
}
// Default to dark theme
return Theme::Dark;
}
const char* FrontendSettings::themeToString(Theme theme) {
switch (theme) {
case Theme::System: return "system";
case Theme::Light: return "light";
case Theme::GreetingsCat: return "greetingscat";
case Theme::Cream: return "cream";
case Theme::Dark:
default: return "dark";
}
}
FrontendSettings::WindowIcon FrontendSettings::iconFromString(std::string inString) { // Transform to lower-case to make the setting case-insensitive
std::transform(inString.begin(), inString.end(), inString.begin(), [](unsigned char c) { return std::tolower(c); });
static const std::unordered_map<std::string, WindowIcon> map = {
{"rpog", WindowIcon::Rpog}, {"rsyn", WindowIcon::Rsyn},
};
if (auto search = map.find(inString); search != map.end()) {
return search->second;
}
// Default to the icon rpog icon
return WindowIcon::Rpog;
}
const char* FrontendSettings::iconToString(WindowIcon icon) {
switch (icon) {
case WindowIcon::Rsyn: return "rsyn";
case WindowIcon::Rpog:
default: return "rpog";
}
}

View file

@ -8,8 +8,8 @@ ConfigWindow::ConfigWindow(ConfigCallback configCallback, IconCallback iconCallb
updateIcon = std::move(iconCallback);
// Set up theme selection
setTheme(Theme::Dark);
setIcon(WindowIcon::Rpog);
setTheme(config.frontendSettings.theme);
setIcon(config.frontendSettings.icon);
// Initialize the widget list and the widget container widgets
widgetList = new QListWidget(this);
@ -65,17 +65,25 @@ ConfigWindow::ConfigWindow(ConfigCallback configCallback, IconCallback iconCallb
themeSelect->addItem(tr("Dark"));
themeSelect->addItem(tr("Greetings Cat"));
themeSelect->addItem(tr("Cream"));
themeSelect->setCurrentIndex(static_cast<int>(currentTheme));
themeSelect->setCurrentIndex(static_cast<int>(config.frontendSettings.theme));
connect(themeSelect, &QComboBox::currentIndexChanged, this, [&](int index) {
config.frontendSettings.theme = static_cast<Theme>(index);
setTheme(static_cast<Theme>(index));
updateConfig();
});
guiLayout->addRow(tr("Color theme"), themeSelect);
QComboBox* iconSelect = new QComboBox();
iconSelect->addItem(tr("Happy panda"));
iconSelect->addItem(tr("Happy panda (colourful)"));
iconSelect->setCurrentIndex(static_cast<int>(currentIcon));
connect(iconSelect, &QComboBox::currentIndexChanged, this, [&](int index) { setIcon(static_cast<WindowIcon>(index)); });
iconSelect->setCurrentIndex(static_cast<int>(config.frontendSettings.icon));
connect(iconSelect, &QComboBox::currentIndexChanged, this, [&](int index) {
config.frontendSettings.icon = static_cast<WindowIcon>(index);
setIcon(static_cast<WindowIcon>(index));
updateConfig();
});
guiLayout->addRow(tr("Window icon"), iconSelect);
QCheckBox* showAppVersion = new QCheckBox(tr("Show version on window title"));
@ -286,8 +294,6 @@ ConfigWindow::ConfigWindow(ConfigCallback configCallback, IconCallback iconCallb
}
void ConfigWindow::setTheme(Theme theme) {
currentTheme = theme;
switch (theme) {
case Theme::Dark: {
QApplication::setStyle(QStyleFactory::create("Fusion"));

View file

@ -420,6 +420,9 @@ void MainWindow::dispatchMessage(const EmulatorMessage& message) {
case MessageType::UpdateConfig:
emu->getConfig() = configWindow->getConfig();
emu->reloadSettings();
// Save new settings to disk
emu->getConfig().save();
break;
}
}