Skip to content

Commit

Permalink
Qt: Serialize icon & theme, properly set them
Browse files Browse the repository at this point in the history
  • Loading branch information
wheremyfoodat committed Dec 1, 2024
1 parent 95cc79e commit 6f90c25
Show file tree
Hide file tree
Showing 8 changed files with 128 additions and 26 deletions.
3 changes: 2 additions & 1 deletion CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down Expand Up @@ -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(
Expand Down
4 changes: 3 additions & 1 deletion include/config.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@

#include "audio/dsp_core.hpp"
#include "renderer.hpp"
#include "frontend_settings.hpp"

struct AudioDeviceConfig {
float volumeRaw = 1.0f;
Expand Down Expand Up @@ -86,8 +87,9 @@ struct EmulatorConfig {

WindowSettings windowSettings;
AudioDeviceConfig audioDeviceConfig;
FrontendSettings frontendSettings;

EmulatorConfig(const std::filesystem::path& path);
void load();
void save();
};
};
30 changes: 30 additions & 0 deletions include/frontend_settings.hpp
Original file line number Diff line number Diff line change
@@ -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);
};
22 changes: 5 additions & 17 deletions include/panda_qt/config_window.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@
#include <utility>

#include "emulator.hpp"
#include "frontend_settings.hpp"

class ConfigWindow : public QDialog {
Q_OBJECT
Expand All @@ -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;
Expand All @@ -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);
Expand Down
13 changes: 13 additions & 0 deletions src/config.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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() {
Expand Down Expand Up @@ -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();
Expand Down
59 changes: 59 additions & 0 deletions src/frontend_settings.cpp
Original file line number Diff line number Diff line change
@@ -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";
}
}
20 changes: 13 additions & 7 deletions src/panda_qt/config_window.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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);
Expand Down Expand Up @@ -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"));
Expand Down Expand Up @@ -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"));
Expand Down
3 changes: 3 additions & 0 deletions src/panda_qt/main_window.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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;
}
}
Expand Down

0 comments on commit 6f90c25

Please sign in to comment.