diff options
Diffstat (limited to 'src/yuzu')
28 files changed, 1471 insertions, 970 deletions
diff --git a/src/yuzu/CMakeLists.txt b/src/yuzu/CMakeLists.txt index a862b2610..656096c9f 100644 --- a/src/yuzu/CMakeLists.txt +++ b/src/yuzu/CMakeLists.txt @@ -133,11 +133,44 @@ file(GLOB COMPAT_LIST file(GLOB_RECURSE ICONS ${PROJECT_SOURCE_DIR}/dist/icons/*) file(GLOB_RECURSE THEMES ${PROJECT_SOURCE_DIR}/dist/qt_themes/*) +if (ENABLE_QT_TRANSLATION) + set(YUZU_QT_LANGUAGES "${PROJECT_SOURCE_DIR}/dist/languages" CACHE PATH "Path to the translation bundle for the Qt frontend") + option(GENERATE_QT_TRANSLATION "Generate en.ts as the translation source file" OFF) + + # Update source TS file if enabled + if (GENERATE_QT_TRANSLATION) + get_target_property(SRCS yuzu SOURCES) + qt5_create_translation(QM_FILES ${SRCS} ${UIS} ${YUZU_QT_LANGUAGES}/en.ts) + add_custom_target(translation ALL DEPENDS ${YUZU_QT_LANGUAGES}/en.ts) + endif() + + # Find all TS files except en.ts + file(GLOB_RECURSE LANGUAGES_TS ${YUZU_QT_LANGUAGES}/*.ts) + list(REMOVE_ITEM LANGUAGES_TS ${YUZU_QT_LANGUAGES}/en.ts) + + # Compile TS files to QM files + qt5_add_translation(LANGUAGES_QM ${LANGUAGES_TS}) + + # Build a QRC file from the QM file list + set(LANGUAGES_QRC ${CMAKE_CURRENT_BINARY_DIR}/languages.qrc) + file(WRITE ${LANGUAGES_QRC} "<RCC><qresource prefix=\"languages\">\n") + foreach (QM ${LANGUAGES_QM}) + get_filename_component(QM_FILE ${QM} NAME) + file(APPEND ${LANGUAGES_QRC} "<file>${QM_FILE}</file>\n") + endforeach (QM) + file(APPEND ${LANGUAGES_QRC} "</qresource></RCC>") + + # Add the QRC file to package in all QM files + qt5_add_resources(LANGUAGES ${LANGUAGES_QRC}) +else() + set(LANGUAGES) +endif() target_sources(yuzu PRIVATE ${COMPAT_LIST} ${ICONS} + ${LANGUAGES} ${THEMES} ) diff --git a/src/yuzu/configuration/config.cpp b/src/yuzu/configuration/config.cpp index 9e9b38214..59a193edd 100644 --- a/src/yuzu/configuration/config.cpp +++ b/src/yuzu/configuration/config.cpp @@ -611,6 +611,7 @@ void Config::ReadPathValues() { } } UISettings::values.recent_files = ReadSetting(QStringLiteral("recentFiles")).toStringList(); + UISettings::values.language = ReadSetting(QStringLiteral("language"), QString{}).toString(); qt_config->endGroup(); } @@ -661,6 +662,8 @@ void Config::ReadRendererValues() { ReadSettingGlobal(Settings::values.use_vsync, QStringLiteral("use_vsync"), true); ReadSettingGlobal(Settings::values.use_assembly_shaders, QStringLiteral("use_assembly_shaders"), false); + ReadSettingGlobal(Settings::values.use_asynchronous_shaders, + QStringLiteral("use_asynchronous_shaders"), false); ReadSettingGlobal(Settings::values.use_fast_gpu_time, QStringLiteral("use_fast_gpu_time"), true); ReadSettingGlobal(Settings::values.force_30fps_mode, QStringLiteral("force_30fps_mode"), false); @@ -1093,6 +1096,7 @@ void Config::SavePathValues() { } qt_config->endArray(); WriteSetting(QStringLiteral("recentFiles"), UISettings::values.recent_files); + WriteSetting(QStringLiteral("language"), UISettings::values.language, QString{}); qt_config->endGroup(); } @@ -1145,6 +1149,8 @@ void Config::SaveRendererValues() { WriteSettingGlobal(QStringLiteral("use_vsync"), Settings::values.use_vsync, true); WriteSettingGlobal(QStringLiteral("use_assembly_shaders"), Settings::values.use_assembly_shaders, false); + WriteSettingGlobal(QStringLiteral("use_asynchronous_shaders"), + Settings::values.use_asynchronous_shaders, false); WriteSettingGlobal(QStringLiteral("use_fast_gpu_time"), Settings::values.use_fast_gpu_time, true); WriteSettingGlobal(QStringLiteral("force_30fps_mode"), Settings::values.force_30fps_mode, @@ -1368,11 +1374,13 @@ void Config::WriteSettingGlobal(const QString& name, const QVariant& value, bool void Config::Reload() { ReadValues(); + Settings::Sanitize(); // To apply default value changes SaveValues(); Settings::Apply(); } void Config::Save() { + Settings::Sanitize(); SaveValues(); } diff --git a/src/yuzu/configuration/configuration_shared.cpp b/src/yuzu/configuration/configuration_shared.cpp index bb47c3933..f9becab6e 100644 --- a/src/yuzu/configuration/configuration_shared.cpp +++ b/src/yuzu/configuration/configuration_shared.cpp @@ -4,17 +4,20 @@ #include <QCheckBox> #include <QComboBox> +#include <QObject> +#include <QString> #include "core/settings.h" #include "yuzu/configuration/configuration_shared.h" #include "yuzu/configuration/configure_per_game.h" void ConfigurationShared::ApplyPerGameSetting(Settings::Setting<bool>* setting, - const QCheckBox* checkbox) { - if (checkbox->checkState() == Qt::PartiallyChecked) { + const QCheckBox* checkbox, + const CheckState& tracker) { + if (tracker == CheckState::Global) { setting->SetGlobal(true); } else { setting->SetGlobal(false); - setting->SetValue(checkbox->checkState() == Qt::Checked); + setting->SetValue(checkbox->checkState()); } } @@ -69,8 +72,69 @@ void ConfigurationShared::SetPerGameSetting( ConfigurationShared::USE_GLOBAL_OFFSET); } -void ConfigurationShared::InsertGlobalItem(QComboBox* combobox) { - const QString use_global_text = ConfigurePerGame::tr("Use global configuration"); +void ConfigurationShared::SetHighlight(QWidget* widget, const std::string& name, bool highlighted) { + if (highlighted) { + widget->setStyleSheet(QStringLiteral("QWidget#%1 { background-color:rgba(0,203,255,0.5) }") + .arg(QString::fromStdString(name))); + } else { + widget->setStyleSheet(QStringLiteral("QWidget#%1 { background-color:rgba(0,0,0,0) }") + .arg(QString::fromStdString(name))); + } + widget->show(); +} + +void ConfigurationShared::SetColoredTristate(QCheckBox* checkbox, const std::string& name, + const Settings::Setting<bool>& setting, + CheckState& tracker) { + if (setting.UsingGlobal()) { + tracker = CheckState::Global; + } else { + tracker = (setting.GetValue() == setting.GetValue(true)) ? CheckState::On : CheckState::Off; + } + SetHighlight(checkbox, name, tracker != CheckState::Global); + QObject::connect(checkbox, &QCheckBox::clicked, checkbox, + [checkbox, name, setting, &tracker]() { + tracker = static_cast<CheckState>((static_cast<int>(tracker) + 1) % + static_cast<int>(CheckState::Count)); + if (tracker == CheckState::Global) { + checkbox->setChecked(setting.GetValue(true)); + } + SetHighlight(checkbox, name, tracker != CheckState::Global); + }); +} + +void ConfigurationShared::SetColoredTristate(QCheckBox* checkbox, const std::string& name, + bool global, bool state, bool global_state, + CheckState& tracker) { + if (global) { + tracker = CheckState::Global; + } else { + tracker = (state == global_state) ? CheckState::On : CheckState::Off; + } + SetHighlight(checkbox, name, tracker != CheckState::Global); + QObject::connect(checkbox, &QCheckBox::clicked, checkbox, + [checkbox, name, global_state, &tracker]() { + tracker = static_cast<CheckState>((static_cast<int>(tracker) + 1) % + static_cast<int>(CheckState::Count)); + if (tracker == CheckState::Global) { + checkbox->setChecked(global_state); + } + SetHighlight(checkbox, name, tracker != CheckState::Global); + }); +} + +void ConfigurationShared::SetColoredComboBox(QComboBox* combobox, QWidget* target, + const std::string& target_name, int global) { + InsertGlobalItem(combobox, global); + QObject::connect(combobox, static_cast<void (QComboBox::*)(int)>(&QComboBox::activated), target, + [target, target_name](int index) { + ConfigurationShared::SetHighlight(target, target_name, index != 0); + }); +} + +void ConfigurationShared::InsertGlobalItem(QComboBox* combobox, int global_index) { + const QString use_global_text = + ConfigurePerGame::tr("Use global configuration (%1)").arg(combobox->itemText(global_index)); combobox->insertItem(ConfigurationShared::USE_GLOBAL_INDEX, use_global_text); combobox->insertSeparator(ConfigurationShared::USE_GLOBAL_SEPARATOR_INDEX); } diff --git a/src/yuzu/configuration/configuration_shared.h b/src/yuzu/configuration/configuration_shared.h index b11b1b950..003148c68 100644 --- a/src/yuzu/configuration/configuration_shared.h +++ b/src/yuzu/configuration/configuration_shared.h @@ -15,9 +15,17 @@ constexpr int USE_GLOBAL_INDEX = 0; constexpr int USE_GLOBAL_SEPARATOR_INDEX = 1; constexpr int USE_GLOBAL_OFFSET = 2; +enum class CheckState { + Off, + On, + Global, + Count, +}; + // Global-aware apply and set functions -void ApplyPerGameSetting(Settings::Setting<bool>* setting, const QCheckBox* checkbox); +void ApplyPerGameSetting(Settings::Setting<bool>* setting, const QCheckBox* checkbox, + const CheckState& tracker); void ApplyPerGameSetting(Settings::Setting<int>* setting, const QComboBox* combobox); void ApplyPerGameSetting(Settings::Setting<Settings::RendererBackend>* setting, const QComboBox* combobox); @@ -31,6 +39,14 @@ void SetPerGameSetting(QComboBox* combobox, void SetPerGameSetting(QComboBox* combobox, const Settings::Setting<Settings::GPUAccuracy>* setting); -void InsertGlobalItem(QComboBox* combobox); +void SetHighlight(QWidget* widget, const std::string& name, bool highlighted); +void SetColoredTristate(QCheckBox* checkbox, const std::string& name, + const Settings::Setting<bool>& setting, CheckState& tracker); +void SetColoredTristate(QCheckBox* checkbox, const std::string& name, bool global, bool state, + bool global_state, CheckState& tracker); +void SetColoredComboBox(QComboBox* combobox, QWidget* target, const std::string& target_name, + int global); + +void InsertGlobalItem(QComboBox* combobox, int global_index); } // namespace ConfigurationShared diff --git a/src/yuzu/configuration/configure_audio.cpp b/src/yuzu/configuration/configure_audio.cpp index cc021beec..fea632531 100644 --- a/src/yuzu/configuration/configure_audio.cpp +++ b/src/yuzu/configuration/configure_audio.cpp @@ -49,12 +49,9 @@ void ConfigureAudio::SetConfiguration() { ui->volume_slider->setValue(Settings::values.volume.GetValue() * ui->volume_slider->maximum()); - if (Settings::configuring_global) { - ui->toggle_audio_stretching->setChecked( - Settings::values.enable_audio_stretching.GetValue()); - } else { - ConfigurationShared::SetPerGameSetting(ui->toggle_audio_stretching, - &Settings::values.enable_audio_stretching); + ui->toggle_audio_stretching->setChecked(Settings::values.enable_audio_stretching.GetValue()); + + if (!Settings::configuring_global) { if (Settings::values.volume.UsingGlobal()) { ui->volume_combo_box->setCurrentIndex(0); ui->volume_slider->setEnabled(false); @@ -62,6 +59,8 @@ void ConfigureAudio::SetConfiguration() { ui->volume_combo_box->setCurrentIndex(1); ui->volume_slider->setEnabled(true); } + ConfigurationShared::SetHighlight(ui->volume_layout, "volume_layout", + !Settings::values.volume.UsingGlobal()); } SetVolumeIndicatorText(ui->volume_slider->sliderPosition()); } @@ -120,7 +119,8 @@ void ConfigureAudio::ApplyConfiguration() { } } else { ConfigurationShared::ApplyPerGameSetting(&Settings::values.enable_audio_stretching, - ui->toggle_audio_stretching); + ui->toggle_audio_stretching, + enable_audio_stretching); if (ui->volume_combo_box->currentIndex() == 0) { Settings::values.volume.SetGlobal(true); } else { @@ -173,9 +173,14 @@ void ConfigureAudio::SetupPerGameUI() { return; } - ui->toggle_audio_stretching->setTristate(true); + ConfigurationShared::SetColoredTristate(ui->toggle_audio_stretching, "toggle_audio_stretching", + Settings::values.enable_audio_stretching, + enable_audio_stretching); connect(ui->volume_combo_box, static_cast<void (QComboBox::*)(int)>(&QComboBox::activated), - this, [this](int index) { ui->volume_slider->setEnabled(index == 1); }); + this, [this](int index) { + ui->volume_slider->setEnabled(index == 1); + ConfigurationShared::SetHighlight(ui->volume_layout, "volume_layout", index == 1); + }); ui->output_sink_combo_box->setVisible(false); ui->output_sink_label->setVisible(false); diff --git a/src/yuzu/configuration/configure_audio.h b/src/yuzu/configuration/configure_audio.h index d84f4a682..9dbd3d93e 100644 --- a/src/yuzu/configuration/configure_audio.h +++ b/src/yuzu/configuration/configure_audio.h @@ -7,6 +7,10 @@ #include <memory> #include <QWidget> +namespace ConfigurationShared { +enum class CheckState; +} + namespace Ui { class ConfigureAudio; } @@ -37,4 +41,6 @@ private: void SetupPerGameUI(); std::unique_ptr<Ui::ConfigureAudio> ui; + + ConfigurationShared::CheckState enable_audio_stretching; }; diff --git a/src/yuzu/configuration/configure_audio.ui b/src/yuzu/configuration/configure_audio.ui index 862ccb988..9bd0cca96 100644 --- a/src/yuzu/configuration/configure_audio.ui +++ b/src/yuzu/configuration/configure_audio.ui @@ -56,80 +56,91 @@ </layout> </item> <item> - <layout class="QHBoxLayout" name="horizontalLayout_2"> - <property name="topMargin"> - <number>0</number> - </property> - <item> - <widget class="QComboBox" name="volume_combo_box"> - <item> + <widget class="QWidget" name="volume_layout" native="true"> + <layout class="QHBoxLayout" name="horizontalLayout_2"> + <property name="leftMargin"> + <number>0</number> + </property> + <property name="topMargin"> + <number>0</number> + </property> + <property name="rightMargin"> + <number>0</number> + </property> + <property name="bottomMargin"> + <number>0</number> + </property> + <item> + <widget class="QComboBox" name="volume_combo_box"> + <item> + <property name="text"> + <string>Use global volume</string> + </property> + </item> + <item> + <property name="text"> + <string>Set volume:</string> + </property> + </item> + </widget> + </item> + <item> + <widget class="QLabel" name="volume_label"> <property name="text"> - <string>Use global volume</string> + <string>Volume:</string> + </property> + </widget> + </item> + <item> + <spacer name="horizontalSpacer"> + <property name="orientation"> + <enum>Qt::Horizontal</enum> + </property> + <property name="sizeHint" stdset="0"> + <size> + <width>30</width> + <height>20</height> + </size> + </property> + </spacer> + </item> + <item> + <widget class="QSlider" name="volume_slider"> + <property name="sizePolicy"> + <sizepolicy hsizetype="Expanding" vsizetype="Fixed"> + <horstretch>0</horstretch> + <verstretch>0</verstretch> + </sizepolicy> + </property> + <property name="maximum"> + <number>100</number> + </property> + <property name="pageStep"> + <number>10</number> + </property> + <property name="orientation"> + <enum>Qt::Horizontal</enum> + </property> + </widget> + </item> + <item> + <widget class="QLabel" name="volume_indicator"> + <property name="minimumSize"> + <size> + <width>32</width> + <height>0</height> + </size> </property> - </item> - <item> <property name="text"> - <string>Set volume:</string> + <string>0 %</string> </property> - </item> - </widget> - </item> - <item> - <widget class="QLabel" name="volume_label"> - <property name="text"> - <string>Volume:</string> - </property> - </widget> - </item> - <item> - <spacer name="horizontalSpacer"> - <property name="orientation"> - <enum>Qt::Horizontal</enum> - </property> - <property name="sizeHint" stdset="0"> - <size> - <width>30</width> - <height>20</height> - </size> - </property> - </spacer> - </item> - <item> - <widget class="QSlider" name="volume_slider"> - <property name="sizePolicy"> - <sizepolicy hsizetype="Expanding" vsizetype="Fixed"> - <horstretch>0</horstretch> - <verstretch>0</verstretch> - </sizepolicy> - </property> - <property name="maximum"> - <number>100</number> - </property> - <property name="pageStep"> - <number>10</number> - </property> - <property name="orientation"> - <enum>Qt::Horizontal</enum> - </property> - </widget> - </item> - <item> - <widget class="QLabel" name="volume_indicator"> - <property name="minimumSize"> - <size> - <width>32</width> - <height>0</height> - </size> - </property> - <property name="text"> - <string>0 %</string> - </property> - <property name="alignment"> - <set>Qt::AlignCenter</set> - </property> - </widget> - </item> - </layout> + <property name="alignment"> + <set>Qt::AlignCenter</set> + </property> + </widget> + </item> + </layout> + </widget> </item> </layout> </widget> diff --git a/src/yuzu/configuration/configure_dialog.cpp b/src/yuzu/configuration/configure_dialog.cpp index a5afb354f..4e30dc51e 100644 --- a/src/yuzu/configuration/configure_dialog.cpp +++ b/src/yuzu/configuration/configure_dialog.cpp @@ -23,6 +23,7 @@ ConfigureDialog::ConfigureDialog(QWidget* parent, HotkeyRegistry& registry) SetConfiguration(); PopulateSelectionList(); + connect(ui->uiTab, &ConfigureUi::LanguageChanged, this, &ConfigureDialog::OnLanguageChanged); connect(ui->selectorList, &QListWidget::itemSelectionChanged, this, &ConfigureDialog::UpdateVisibleTabs); @@ -98,6 +99,14 @@ void ConfigureDialog::PopulateSelectionList() { } } +void ConfigureDialog::OnLanguageChanged(const QString& locale) { + emit LanguageChanged(locale); + // first apply the configuration, and then restore the display + ApplyConfiguration(); + RetranslateUI(); + SetConfiguration(); +} + void ConfigureDialog::UpdateVisibleTabs() { const auto items = ui->selectorList->selectedItems(); if (items.isEmpty()) { diff --git a/src/yuzu/configuration/configure_dialog.h b/src/yuzu/configuration/configure_dialog.h index 2d3bfc2da..4289bc225 100644 --- a/src/yuzu/configuration/configure_dialog.h +++ b/src/yuzu/configuration/configure_dialog.h @@ -22,6 +22,12 @@ public: void ApplyConfiguration(); +private slots: + void OnLanguageChanged(const QString& locale); + +signals: + void LanguageChanged(const QString& locale); + private: void changeEvent(QEvent* event) override; diff --git a/src/yuzu/configuration/configure_general.cpp b/src/yuzu/configuration/configure_general.cpp index 20316c9cc..c0dbd9855 100644 --- a/src/yuzu/configuration/configure_general.cpp +++ b/src/yuzu/configuration/configure_general.cpp @@ -19,9 +19,10 @@ ConfigureGeneral::ConfigureGeneral(QWidget* parent) SetConfiguration(); - connect(ui->toggle_frame_limit, &QCheckBox::stateChanged, ui->frame_limit, [this]() { - ui->frame_limit->setEnabled(ui->toggle_frame_limit->checkState() == Qt::Checked); - }); + if (Settings::configuring_global) { + connect(ui->toggle_frame_limit, &QCheckBox::clicked, ui->frame_limit, + [this]() { ui->frame_limit->setEnabled(ui->toggle_frame_limit->isChecked()); }); + } } ConfigureGeneral::~ConfigureGeneral() = default; @@ -40,17 +41,12 @@ void ConfigureGeneral::SetConfiguration() { ui->toggle_frame_limit->setChecked(Settings::values.use_frame_limit.GetValue()); ui->frame_limit->setValue(Settings::values.frame_limit.GetValue()); - if (!Settings::configuring_global) { - if (Settings::values.use_multi_core.UsingGlobal()) { - ui->use_multi_core->setCheckState(Qt::PartiallyChecked); - } - if (Settings::values.use_frame_limit.UsingGlobal()) { - ui->toggle_frame_limit->setCheckState(Qt::PartiallyChecked); - } + if (Settings::configuring_global) { + ui->frame_limit->setEnabled(Settings::values.use_frame_limit.GetValue()); + } else { + ui->frame_limit->setEnabled(Settings::values.use_frame_limit.GetValue() && + use_frame_limit != ConfigurationShared::CheckState::Global); } - - ui->frame_limit->setEnabled(ui->toggle_frame_limit->checkState() == Qt::Checked && - ui->toggle_frame_limit->isEnabled()); } void ConfigureGeneral::ApplyConfiguration() { @@ -71,9 +67,9 @@ void ConfigureGeneral::ApplyConfiguration() { } } else { ConfigurationShared::ApplyPerGameSetting(&Settings::values.use_multi_core, - ui->use_multi_core); + ui->use_multi_core, use_multi_core); - bool global_frame_limit = ui->toggle_frame_limit->checkState() == Qt::PartiallyChecked; + bool global_frame_limit = use_frame_limit == ConfigurationShared::CheckState::Global; Settings::values.use_frame_limit.SetGlobal(global_frame_limit); Settings::values.frame_limit.SetGlobal(global_frame_limit); if (!global_frame_limit) { @@ -109,6 +105,13 @@ void ConfigureGeneral::SetupPerGameUI() { ui->toggle_background_pause->setVisible(false); ui->toggle_hide_mouse->setVisible(false); - ui->toggle_frame_limit->setTristate(true); - ui->use_multi_core->setTristate(true); + ConfigurationShared::SetColoredTristate(ui->toggle_frame_limit, "toggle_frame_limit", + Settings::values.use_frame_limit, use_frame_limit); + ConfigurationShared::SetColoredTristate(ui->use_multi_core, "use_multi_core", + Settings::values.use_multi_core, use_multi_core); + + connect(ui->toggle_frame_limit, &QCheckBox::clicked, ui->frame_limit, [this]() { + ui->frame_limit->setEnabled(ui->toggle_frame_limit->isChecked() && + (use_frame_limit != ConfigurationShared::CheckState::Global)); + }); } diff --git a/src/yuzu/configuration/configure_general.h b/src/yuzu/configuration/configure_general.h index 9c785c22e..323ffbd8f 100644 --- a/src/yuzu/configuration/configure_general.h +++ b/src/yuzu/configuration/configure_general.h @@ -7,6 +7,10 @@ #include <memory> #include <QWidget> +namespace ConfigurationShared { +enum class CheckState; +} + class HotkeyRegistry; namespace Ui { @@ -31,4 +35,7 @@ private: void SetupPerGameUI(); std::unique_ptr<Ui::ConfigureGeneral> ui; + + ConfigurationShared::CheckState use_frame_limit; + ConfigurationShared::CheckState use_multi_core; }; diff --git a/src/yuzu/configuration/configure_graphics.cpp b/src/yuzu/configuration/configure_graphics.cpp index cb4706bd6..3e42531c3 100644 --- a/src/yuzu/configuration/configure_graphics.cpp +++ b/src/yuzu/configuration/configure_graphics.cpp @@ -31,8 +31,14 @@ ConfigureGraphics::ConfigureGraphics(QWidget* parent) SetConfiguration(); - connect(ui->api, qOverload<int>(&QComboBox::currentIndexChanged), this, - [this] { UpdateDeviceComboBox(); }); + connect(ui->api, qOverload<int>(&QComboBox::currentIndexChanged), this, [this] { + UpdateDeviceComboBox(); + if (!Settings::configuring_global) { + ConfigurationShared::SetHighlight(ui->api_layout, "api_layout", + ui->api->currentIndex() != + ConfigurationShared::USE_GLOBAL_INDEX); + } + }); connect(ui->device, qOverload<int>(&QComboBox::activated), this, [this](int device) { UpdateDeviceSelection(device); }); @@ -65,25 +71,26 @@ void ConfigureGraphics::SetConfiguration() { ui->api->setEnabled(runtime_lock); ui->use_asynchronous_gpu_emulation->setEnabled(runtime_lock); ui->use_disk_shader_cache->setEnabled(runtime_lock); + ui->use_disk_shader_cache->setChecked(Settings::values.use_disk_shader_cache.GetValue()); + ui->use_asynchronous_gpu_emulation->setChecked( + Settings::values.use_asynchronous_gpu_emulation.GetValue()); if (Settings::configuring_global) { ui->api->setCurrentIndex(static_cast<int>(Settings::values.renderer_backend.GetValue())); ui->aspect_ratio_combobox->setCurrentIndex(Settings::values.aspect_ratio.GetValue()); - ui->use_disk_shader_cache->setChecked(Settings::values.use_disk_shader_cache.GetValue()); - ui->use_asynchronous_gpu_emulation->setChecked( - Settings::values.use_asynchronous_gpu_emulation.GetValue()); } else { - ConfigurationShared::SetPerGameSetting(ui->use_disk_shader_cache, - &Settings::values.use_disk_shader_cache); - ConfigurationShared::SetPerGameSetting(ui->use_asynchronous_gpu_emulation, - &Settings::values.use_asynchronous_gpu_emulation); - ConfigurationShared::SetPerGameSetting(ui->api, &Settings::values.renderer_backend); + ConfigurationShared::SetHighlight(ui->api_layout, "api_layout", + !Settings::values.renderer_backend.UsingGlobal()); ConfigurationShared::SetPerGameSetting(ui->aspect_ratio_combobox, &Settings::values.aspect_ratio); ui->bg_combobox->setCurrentIndex(Settings::values.bg_red.UsingGlobal() ? 0 : 1); ui->bg_button->setEnabled(!Settings::values.bg_red.UsingGlobal()); + ConfigurationShared::SetHighlight(ui->ar_label, "ar_label", + !Settings::values.aspect_ratio.UsingGlobal()); + ConfigurationShared::SetHighlight(ui->bg_layout, "bg_layout", + !Settings::values.bg_red.UsingGlobal()); } UpdateBackgroundColorButton(QColor::fromRgbF(Settings::values.bg_red.GetValue(), @@ -135,9 +142,10 @@ void ConfigureGraphics::ApplyConfiguration() { ui->aspect_ratio_combobox); ConfigurationShared::ApplyPerGameSetting(&Settings::values.use_disk_shader_cache, - ui->use_disk_shader_cache); + ui->use_disk_shader_cache, use_disk_shader_cache); ConfigurationShared::ApplyPerGameSetting(&Settings::values.use_asynchronous_gpu_emulation, - ui->use_asynchronous_gpu_emulation); + ui->use_asynchronous_gpu_emulation, + use_asynchronous_gpu_emulation); if (ui->bg_combobox->currentIndex() == ConfigurationShared::USE_GLOBAL_INDEX) { Settings::values.bg_red.SetGlobal(true); @@ -241,10 +249,20 @@ void ConfigureGraphics::SetupPerGameUI() { } connect(ui->bg_combobox, static_cast<void (QComboBox::*)(int)>(&QComboBox::activated), this, - [this](int index) { ui->bg_button->setEnabled(index == 1); }); - - ui->use_disk_shader_cache->setTristate(true); - ui->use_asynchronous_gpu_emulation->setTristate(true); - ConfigurationShared::InsertGlobalItem(ui->aspect_ratio_combobox); - ConfigurationShared::InsertGlobalItem(ui->api); + [this](int index) { + ui->bg_button->setEnabled(index == 1); + ConfigurationShared::SetHighlight(ui->bg_layout, "bg_layout", index == 1); + }); + + ConfigurationShared::SetColoredTristate(ui->use_disk_shader_cache, "use_disk_shader_cache", + Settings::values.use_disk_shader_cache, + use_disk_shader_cache); + ConfigurationShared::SetColoredTristate( + ui->use_asynchronous_gpu_emulation, "use_asynchronous_gpu_emulation", + Settings::values.use_asynchronous_gpu_emulation, use_asynchronous_gpu_emulation); + + ConfigurationShared::SetColoredComboBox(ui->aspect_ratio_combobox, ui->ar_label, "ar_label", + Settings::values.aspect_ratio.GetValue(true)); + ConfigurationShared::InsertGlobalItem( + ui->api, static_cast<int>(Settings::values.renderer_backend.GetValue(true))); } diff --git a/src/yuzu/configuration/configure_graphics.h b/src/yuzu/configuration/configure_graphics.h index 24f01c739..b4961f719 100644 --- a/src/yuzu/configuration/configure_graphics.h +++ b/src/yuzu/configuration/configure_graphics.h @@ -10,6 +10,10 @@ #include <QWidget> #include "core/settings.h" +namespace ConfigurationShared { +enum class CheckState; +} + namespace Ui { class ConfigureGraphics; } @@ -42,6 +46,9 @@ private: std::unique_ptr<Ui::ConfigureGraphics> ui; QColor bg_color; + ConfigurationShared::CheckState use_disk_shader_cache; + ConfigurationShared::CheckState use_asynchronous_gpu_emulation; + std::vector<QString> vulkan_devices; u32 vulkan_device{}; }; diff --git a/src/yuzu/configuration/configure_graphics.ui b/src/yuzu/configuration/configure_graphics.ui index 62418fc14..62aa337e7 100644 --- a/src/yuzu/configuration/configure_graphics.ui +++ b/src/yuzu/configuration/configure_graphics.ui @@ -6,7 +6,7 @@ <rect> <x>0</x> <y>0</y> - <width>400</width> + <width>437</width> <height>321</height> </rect> </property> @@ -23,43 +23,56 @@ </property> <layout class="QVBoxLayout" name="verticalLayout_3"> <item> - <layout class="QHBoxLayout" name="horizontalLayout_4"> - <item> - <widget class="QLabel" name="label_2"> - <property name="text"> - <string>API:</string> - </property> - </widget> - </item> - <item> - <widget class="QComboBox" name="api"> - <item> + <widget class="QWidget" name="api_layout" native="true"> + <layout class="QGridLayout" name="gridLayout"> + <property name="leftMargin"> + <number>0</number> + </property> + <property name="topMargin"> + <number>0</number> + </property> + <property name="rightMargin"> + <number>0</number> + </property> + <property name="bottomMargin"> + <number>0</number> + </property> + <property name="horizontalSpacing"> + <number>6</number> + </property> + <item row="0" column="0"> + <widget class="QLabel" name="api_label"> <property name="text"> - <string notr="true">OpenGL</string> + <string>API:</string> </property> - </item> - <item> + </widget> + </item> + <item row="0" column="1"> + <widget class="QComboBox" name="api"> + <item> + <property name="text"> + <string notr="true">OpenGL</string> + </property> + </item> + <item> + <property name="text"> + <string notr="true">Vulkan</string> + </property> + </item> + </widget> + </item> + <item row="1" column="0"> + <widget class="QLabel" name="device_label"> <property name="text"> - <string notr="true">Vulkan</string> + <string>Device:</string> </property> - </item> - </widget> - </item> - </layout> - </item> - <item> - <layout class="QHBoxLayout" name="horizontalLayout_5"> - <item> - <widget class="QLabel" name="label_3"> - <property name="text"> - <string>Device:</string> - </property> - </widget> - </item> - <item> - <widget class="QComboBox" name="device"/> - </item> - </layout> + </widget> + </item> + <item row="1" column="1"> + <widget class="QComboBox" name="device"/> + </item> + </layout> + </widget> </item> </layout> </widget> @@ -85,96 +98,133 @@ </widget> </item> <item> - <layout class="QHBoxLayout" name="horizontalLayout_6"> - <item> - <widget class="QLabel" name="ar_label"> - <property name="text"> - <string>Aspect Ratio:</string> - </property> - </widget> - </item> - <item> - <widget class="QComboBox" name="aspect_ratio_combobox"> - <item> - <property name="text"> - <string>Default (16:9)</string> - </property> - </item> - <item> - <property name="text"> - <string>Force 4:3</string> - </property> - </item> - <item> - <property name="text"> - <string>Force 21:9</string> - </property> - </item> - <item> + <widget class="QWidget" name="aspect_ratio_layout" native="true"> + <layout class="QHBoxLayout" name="horizontalLayout_6"> + <property name="leftMargin"> + <number>0</number> + </property> + <property name="topMargin"> + <number>0</number> + </property> + <property name="rightMargin"> + <number>0</number> + </property> + <property name="bottomMargin"> + <number>0</number> + </property> + <item> + <widget class="QLabel" name="ar_label"> <property name="text"> - <string>Stretch to Window</string> + <string>Aspect Ratio:</string> </property> - </item> - </widget> - </item> - </layout> + </widget> + </item> + <item> + <widget class="QComboBox" name="aspect_ratio_combobox"> + <item> + <property name="text"> + <string>Default (16:9)</string> + </property> + </item> + <item> + <property name="text"> + <string>Force 4:3</string> + </property> + </item> + <item> + <property name="text"> + <string>Force 21:9</string> + </property> + </item> + <item> + <property name="text"> + <string>Stretch to Window</string> + </property> + </item> + </widget> + </item> + </layout> + </widget> </item> <item> - <layout class="QHBoxLayout" name="horizontalLayout_3"> - <item> - <widget class="QComboBox" name="bg_combobox"> - <property name="currentText"> - <string>Use global background color</string> - </property> - <property name="currentIndex"> - <number>0</number> - </property> - <property name="maxVisibleItems"> - <number>10</number> - </property> - <item> - <property name="text"> + <widget class="QWidget" name="bg_layout" native="true"> + <property name="sizePolicy"> + <sizepolicy hsizetype="Preferred" vsizetype="Preferred"> + <horstretch>0</horstretch> + <verstretch>0</verstretch> + </sizepolicy> + </property> + <layout class="QHBoxLayout" name="horizontalLayout_3"> + <property name="spacing"> + <number>6</number> + </property> + <property name="leftMargin"> + <number>0</number> + </property> + <property name="topMargin"> + <number>0</number> + </property> + <property name="rightMargin"> + <number>0</number> + </property> + <property name="bottomMargin"> + <number>0</number> + </property> + <item> + <widget class="QComboBox" name="bg_combobox"> + <property name="currentText"> <string>Use global background color</string> </property> - </item> - <item> + <property name="currentIndex"> + <number>0</number> + </property> + <property name="maxVisibleItems"> + <number>10</number> + </property> + <item> + <property name="text"> + <string>Use global background color</string> + </property> + </item> + <item> + <property name="text"> + <string>Set background color:</string> + </property> + </item> + </widget> + </item> + <item> + <widget class="QLabel" name="bg_label"> <property name="text"> - <string>Set background color:</string> + <string>Background Color:</string> </property> - </item> - </widget> - </item> - <item> - <widget class="QLabel" name="bg_label"> - <property name="text"> - <string>Background Color:</string> - </property> - </widget> - </item> - <item> - <spacer name="horizontalSpacer"> - <property name="orientation"> - <enum>Qt::Horizontal</enum> - </property> - <property name="sizeHint" stdset="0"> - <size> - <width>40</width> - <height>20</height> - </size> - </property> - </spacer> - </item> - <item> - <widget class="QPushButton" name="bg_button"> - <property name="maximumSize"> - <size> - <width>40</width> - <height>16777215</height> - </size> - </property> - </widget> - </item> - </layout> + </widget> + </item> + <item> + <spacer name="horizontalSpacer"> + <property name="orientation"> + <enum>Qt::Horizontal</enum> + </property> + <property name="sizeHint" stdset="0"> + <size> + <width>40</width> + <height>20</height> + </size> + </property> + </spacer> + </item> + <item> + <widget class="QPushButton" name="bg_button"> + <property name="maximumSize"> + <size> + <width>40</width> + <height>16777215</height> + </size> + </property> + </widget> + </item> + </layout> + </widget> </item> </layout> </widget> diff --git a/src/yuzu/configuration/configure_graphics_advanced.cpp b/src/yuzu/configuration/configure_graphics_advanced.cpp index 7c0fa7ec5..8b9180811 100644 --- a/src/yuzu/configuration/configure_graphics_advanced.cpp +++ b/src/yuzu/configuration/configure_graphics_advanced.cpp @@ -24,29 +24,29 @@ void ConfigureGraphicsAdvanced::SetConfiguration() { const bool runtime_lock = !Core::System::GetInstance().IsPoweredOn(); ui->use_vsync->setEnabled(runtime_lock); ui->use_assembly_shaders->setEnabled(runtime_lock); + ui->use_asynchronous_shaders->setEnabled(runtime_lock); ui->force_30fps_mode->setEnabled(runtime_lock); ui->anisotropic_filtering_combobox->setEnabled(runtime_lock); + ui->use_vsync->setChecked(Settings::values.use_vsync.GetValue()); + ui->use_assembly_shaders->setChecked(Settings::values.use_assembly_shaders.GetValue()); + ui->use_asynchronous_shaders->setChecked(Settings::values.use_asynchronous_shaders.GetValue()); + ui->use_fast_gpu_time->setChecked(Settings::values.use_fast_gpu_time.GetValue()); + ui->force_30fps_mode->setChecked(Settings::values.force_30fps_mode.GetValue()); + if (Settings::configuring_global) { ui->gpu_accuracy->setCurrentIndex( static_cast<int>(Settings::values.gpu_accuracy.GetValue())); - ui->use_vsync->setChecked(Settings::values.use_vsync.GetValue()); - ui->use_assembly_shaders->setChecked(Settings::values.use_assembly_shaders.GetValue()); - ui->use_fast_gpu_time->setChecked(Settings::values.use_fast_gpu_time.GetValue()); - ui->force_30fps_mode->setChecked(Settings::values.force_30fps_mode.GetValue()); ui->anisotropic_filtering_combobox->setCurrentIndex( Settings::values.max_anisotropy.GetValue()); } else { ConfigurationShared::SetPerGameSetting(ui->gpu_accuracy, &Settings::values.gpu_accuracy); - ConfigurationShared::SetPerGameSetting(ui->use_vsync, &Settings::values.use_vsync); - ConfigurationShared::SetPerGameSetting(ui->use_assembly_shaders, - &Settings::values.use_assembly_shaders); - ConfigurationShared::SetPerGameSetting(ui->use_fast_gpu_time, - &Settings::values.use_fast_gpu_time); - ConfigurationShared::SetPerGameSetting(ui->force_30fps_mode, - &Settings::values.force_30fps_mode); ConfigurationShared::SetPerGameSetting(ui->anisotropic_filtering_combobox, &Settings::values.max_anisotropy); + ConfigurationShared::SetHighlight(ui->label_gpu_accuracy, "label_gpu_accuracy", + !Settings::values.gpu_accuracy.UsingGlobal()); + ConfigurationShared::SetHighlight(ui->af_label, "af_label", + !Settings::values.max_anisotropy.UsingGlobal()); } } @@ -67,6 +67,14 @@ void ConfigureGraphicsAdvanced::ApplyConfiguration() { if (Settings::values.use_assembly_shaders.UsingGlobal()) { Settings::values.use_assembly_shaders.SetValue(ui->use_assembly_shaders->isChecked()); } + if (Settings::values.use_asynchronous_shaders.UsingGlobal()) { + Settings::values.use_asynchronous_shaders.SetValue( + ui->use_asynchronous_shaders->isChecked()); + } + if (Settings::values.use_asynchronous_shaders.UsingGlobal()) { + Settings::values.use_asynchronous_shaders.SetValue( + ui->use_asynchronous_shaders->isChecked()); + } if (Settings::values.use_fast_gpu_time.UsingGlobal()) { Settings::values.use_fast_gpu_time.SetValue(ui->use_fast_gpu_time->isChecked()); } @@ -80,13 +88,17 @@ void ConfigureGraphicsAdvanced::ApplyConfiguration() { } else { ConfigurationShared::ApplyPerGameSetting(&Settings::values.max_anisotropy, ui->anisotropic_filtering_combobox); - ConfigurationShared::ApplyPerGameSetting(&Settings::values.use_vsync, ui->use_vsync); + ConfigurationShared::ApplyPerGameSetting(&Settings::values.use_vsync, ui->use_vsync, + use_vsync); ConfigurationShared::ApplyPerGameSetting(&Settings::values.use_assembly_shaders, - ui->use_assembly_shaders); + ui->use_assembly_shaders, use_assembly_shaders); + ConfigurationShared::ApplyPerGameSetting(&Settings::values.use_asynchronous_shaders, + ui->use_asynchronous_shaders, + use_asynchronous_shaders); ConfigurationShared::ApplyPerGameSetting(&Settings::values.use_fast_gpu_time, - ui->use_fast_gpu_time); + ui->use_fast_gpu_time, use_fast_gpu_time); ConfigurationShared::ApplyPerGameSetting(&Settings::values.force_30fps_mode, - ui->force_30fps_mode); + ui->force_30fps_mode, force_30fps_mode); ConfigurationShared::ApplyPerGameSetting(&Settings::values.max_anisotropy, ui->anisotropic_filtering_combobox); @@ -117,6 +129,8 @@ void ConfigureGraphicsAdvanced::SetupPerGameUI() { ui->gpu_accuracy->setEnabled(Settings::values.gpu_accuracy.UsingGlobal()); ui->use_vsync->setEnabled(Settings::values.use_vsync.UsingGlobal()); ui->use_assembly_shaders->setEnabled(Settings::values.use_assembly_shaders.UsingGlobal()); + ui->use_asynchronous_shaders->setEnabled( + Settings::values.use_asynchronous_shaders.UsingGlobal()); ui->use_fast_gpu_time->setEnabled(Settings::values.use_fast_gpu_time.UsingGlobal()); ui->force_30fps_mode->setEnabled(Settings::values.force_30fps_mode.UsingGlobal()); ui->anisotropic_filtering_combobox->setEnabled( @@ -125,10 +139,22 @@ void ConfigureGraphicsAdvanced::SetupPerGameUI() { return; } - ConfigurationShared::InsertGlobalItem(ui->gpu_accuracy); - ui->use_vsync->setTristate(true); - ui->use_assembly_shaders->setTristate(true); - ui->use_fast_gpu_time->setTristate(true); - ui->force_30fps_mode->setTristate(true); - ConfigurationShared::InsertGlobalItem(ui->anisotropic_filtering_combobox); + ConfigurationShared::SetColoredTristate(ui->use_vsync, "use_vsync", Settings::values.use_vsync, + use_vsync); + ConfigurationShared::SetColoredTristate(ui->use_assembly_shaders, "use_assembly_shaders", + Settings::values.use_assembly_shaders, + use_assembly_shaders); + ConfigurationShared::SetColoredTristate( + ui->use_asynchronous_shaders, "use_asynchronous_shaders", + Settings::values.use_asynchronous_shaders, use_asynchronous_shaders); + ConfigurationShared::SetColoredTristate(ui->use_fast_gpu_time, "use_fast_gpu_time", + Settings::values.use_fast_gpu_time, use_fast_gpu_time); + ConfigurationShared::SetColoredTristate(ui->force_30fps_mode, "force_30fps_mode", + Settings::values.force_30fps_mode, force_30fps_mode); + ConfigurationShared::SetColoredComboBox( + ui->gpu_accuracy, ui->label_gpu_accuracy, "label_gpu_accuracy", + static_cast<int>(Settings::values.gpu_accuracy.GetValue(true))); + ConfigurationShared::SetColoredComboBox( + ui->anisotropic_filtering_combobox, ui->af_label, "af_label", + static_cast<int>(Settings::values.max_anisotropy.GetValue(true))); } diff --git a/src/yuzu/configuration/configure_graphics_advanced.h b/src/yuzu/configuration/configure_graphics_advanced.h index c043588ff..3c4f6f7bb 100644 --- a/src/yuzu/configuration/configure_graphics_advanced.h +++ b/src/yuzu/configuration/configure_graphics_advanced.h @@ -7,6 +7,10 @@ #include <memory> #include <QWidget> +namespace ConfigurationShared { +enum class CheckState; +} + namespace Ui { class ConfigureGraphicsAdvanced; } @@ -29,4 +33,10 @@ private: void SetupPerGameUI(); std::unique_ptr<Ui::ConfigureGraphicsAdvanced> ui; + + ConfigurationShared::CheckState use_vsync; + ConfigurationShared::CheckState use_assembly_shaders; + ConfigurationShared::CheckState use_asynchronous_shaders; + ConfigurationShared::CheckState use_fast_gpu_time; + ConfigurationShared::CheckState force_30fps_mode; }; diff --git a/src/yuzu/configuration/configure_graphics_advanced.ui b/src/yuzu/configuration/configure_graphics_advanced.ui index 0021607ac..6a0d29c27 100644 --- a/src/yuzu/configuration/configure_graphics_advanced.ui +++ b/src/yuzu/configuration/configure_graphics_advanced.ui @@ -6,7 +6,7 @@ <rect> <x>0</x> <y>0</y> - <width>400</width> + <width>404</width> <height>321</height> </rect> </property> @@ -23,34 +23,48 @@ </property> <layout class="QVBoxLayout" name="verticalLayout_3"> <item> - <layout class="QHBoxLayout" name="horizontalLayout_2"> - <item> - <widget class="QLabel" name="label_gpu_accuracy"> - <property name="text"> - <string>Accuracy Level:</string> - </property> - </widget> - </item> - <item> - <widget class="QComboBox" name="gpu_accuracy"> - <item> + <widget class="QWidget" name="gpu_accuracy_layout" native="true"> + <layout class="QHBoxLayout" name="horizontalLayout_2"> + <property name="leftMargin"> + <number>0</number> + </property> + <property name="topMargin"> + <number>0</number> + </property> + <property name="rightMargin"> + <number>0</number> + </property> + <property name="bottomMargin"> + <number>0</number> + </property> + <item> + <widget class="QLabel" name="label_gpu_accuracy"> <property name="text"> - <string notr="true">Normal</string> + <string>Accuracy Level:</string> </property> - </item> - <item> - <property name="text"> - <string notr="true">High</string> - </property> - </item> - <item> - <property name="text"> - <string notr="true">Extreme(very slow)</string> - </property> - </item> - </widget> - </item> - </layout> + </widget> + </item> + <item> + <widget class="QComboBox" name="gpu_accuracy"> + <item> + <property name="text"> + <string notr="true">Normal</string> + </property> + </item> + <item> + <property name="text"> + <string notr="true">High</string> + </property> + </item> + <item> + <property name="text"> + <string notr="true">Extreme(very slow)</string> + </property> + </item> + </widget> + </item> + </layout> + </widget> </item> <item> <widget class="QCheckBox" name="use_vsync"> @@ -73,6 +87,16 @@ </widget> </item> <item> + <widget class="QCheckBox" name="use_asynchronous_shaders"> + <property name="toolTip"> + <string>Enables asynchronous shader compilation, which may reduce shader stutter. This feature is experimental.</string> + </property> + <property name="text"> + <string>Use asynchronous shader building (experimental, OpenGL or Assembly shaders only)</string> + </property> + </widget> + </item> + <item> <widget class="QCheckBox" name="force_30fps_mode"> <property name="text"> <string>Force 30 FPS mode</string> @@ -87,44 +111,58 @@ </widget> </item> <item> - <layout class="QHBoxLayout" name="horizontalLayout_1"> - <item> - <widget class="QLabel" name="af_label"> - <property name="text"> - <string>Anisotropic Filtering:</string> - </property> - </widget> - </item> - <item> - <widget class="QComboBox" name="anisotropic_filtering_combobox"> - <item> - <property name="text"> - <string>Default</string> - </property> - </item> - <item> - <property name="text"> - <string>2x</string> - </property> - </item> - <item> + <widget class="QWidget" name="af_layout" native="true"> + <layout class="QHBoxLayout" name="horizontalLayout_1"> + <property name="leftMargin"> + <number>0</number> + </property> + <property name="topMargin"> + <number>0</number> + </property> + <property name="rightMargin"> + <number>0</number> + </property> + <property name="bottomMargin"> + <number>0</number> + </property> + <item> + <widget class="QLabel" name="af_label"> <property name="text"> - <string>4x</string> + <string>Anisotropic Filtering:</string> </property> - </item> - <item> - <property name="text"> - <string>8x</string> - </property> - </item> - <item> - <property name="text"> - <string>16x</string> - </property> - </item> - </widget> - </item> - </layout> + </widget> + </item> + <item> + <widget class="QComboBox" name="anisotropic_filtering_combobox"> + <item> + <property name="text"> + <string>Default</string> + </property> + </item> + <item> + <property name="text"> + <string>2x</string> + </property> + </item> + <item> + <property name="text"> + <string>4x</string> + </property> + </item> + <item> + <property name="text"> + <string>8x</string> + </property> + </item> + <item> + <property name="text"> + <string>16x</string> + </property> + </item> + </widget> + </item> + </layout> + </widget> </item> </layout> </widget> diff --git a/src/yuzu/configuration/configure_system.cpp b/src/yuzu/configuration/configure_system.cpp index 68e02738b..0c4daf147 100644 --- a/src/yuzu/configuration/configure_system.cpp +++ b/src/yuzu/configuration/configure_system.cpp @@ -67,21 +67,21 @@ void ConfigureSystem::SetConfiguration() { const auto rtc_time = Settings::values.custom_rtc.GetValue().value_or( std::chrono::seconds(QDateTime::currentSecsSinceEpoch())); + ui->rng_seed_checkbox->setChecked(Settings::values.rng_seed.GetValue().has_value()); + ui->rng_seed_edit->setEnabled(Settings::values.rng_seed.GetValue().has_value() && + Settings::values.rng_seed.UsingGlobal()); + ui->rng_seed_edit->setText(rng_seed); + + ui->custom_rtc_checkbox->setChecked(Settings::values.custom_rtc.GetValue().has_value()); + ui->custom_rtc_edit->setEnabled(Settings::values.custom_rtc.GetValue().has_value() && + Settings::values.rng_seed.UsingGlobal()); + ui->custom_rtc_edit->setDateTime(QDateTime::fromSecsSinceEpoch(rtc_time.count())); + if (Settings::configuring_global) { ui->combo_language->setCurrentIndex(Settings::values.language_index.GetValue()); ui->combo_region->setCurrentIndex(Settings::values.region_index.GetValue()); ui->combo_time_zone->setCurrentIndex(Settings::values.time_zone_index.GetValue()); ui->combo_sound->setCurrentIndex(Settings::values.sound_index.GetValue()); - - ui->rng_seed_checkbox->setChecked(Settings::values.rng_seed.GetValue().has_value()); - ui->rng_seed_edit->setEnabled(Settings::values.rng_seed.GetValue().has_value() && - Settings::values.rng_seed.UsingGlobal()); - ui->rng_seed_edit->setText(rng_seed); - - ui->custom_rtc_checkbox->setChecked(Settings::values.custom_rtc.GetValue().has_value()); - ui->custom_rtc_edit->setEnabled(Settings::values.custom_rtc.GetValue().has_value() && - Settings::values.rng_seed.UsingGlobal()); - ui->custom_rtc_edit->setDateTime(QDateTime::fromSecsSinceEpoch(rtc_time.count())); } else { ConfigurationShared::SetPerGameSetting(ui->combo_language, &Settings::values.language_index); @@ -90,27 +90,14 @@ void ConfigureSystem::SetConfiguration() { &Settings::values.time_zone_index); ConfigurationShared::SetPerGameSetting(ui->combo_sound, &Settings::values.sound_index); - if (Settings::values.rng_seed.UsingGlobal()) { - ui->rng_seed_checkbox->setCheckState(Qt::PartiallyChecked); - } else { - ui->rng_seed_checkbox->setCheckState( - Settings::values.rng_seed.GetValue().has_value() ? Qt::Checked : Qt::Unchecked); - ui->rng_seed_edit->setEnabled(Settings::values.rng_seed.GetValue().has_value()); - if (Settings::values.rng_seed.GetValue().has_value()) { - ui->rng_seed_edit->setText(rng_seed); - } - } - - if (Settings::values.custom_rtc.UsingGlobal()) { - ui->custom_rtc_checkbox->setCheckState(Qt::PartiallyChecked); - } else { - ui->custom_rtc_checkbox->setCheckState( - Settings::values.custom_rtc.GetValue().has_value() ? Qt::Checked : Qt::Unchecked); - ui->custom_rtc_edit->setEnabled(Settings::values.custom_rtc.GetValue().has_value()); - if (Settings::values.custom_rtc.GetValue().has_value()) { - ui->custom_rtc_edit->setDateTime(QDateTime::fromSecsSinceEpoch(rtc_time.count())); - } - } + ConfigurationShared::SetHighlight(ui->label_language, "label_language", + !Settings::values.language_index.UsingGlobal()); + ConfigurationShared::SetHighlight(ui->label_region, "label_region", + !Settings::values.region_index.UsingGlobal()); + ConfigurationShared::SetHighlight(ui->label_timezone, "label_timezone", + !Settings::values.time_zone_index.UsingGlobal()); + ConfigurationShared::SetHighlight(ui->label_sound, "label_sound", + !Settings::values.sound_index.UsingGlobal()); } } @@ -161,37 +148,44 @@ void ConfigureSystem::ApplyConfiguration() { ui->combo_time_zone); ConfigurationShared::ApplyPerGameSetting(&Settings::values.sound_index, ui->combo_sound); - switch (ui->rng_seed_checkbox->checkState()) { - case Qt::Checked: - Settings::values.rng_seed.SetGlobal(false); - Settings::values.rng_seed.SetValue(ui->rng_seed_edit->text().toULongLong(nullptr, 16)); - break; - case Qt::Unchecked: + switch (use_rng_seed) { + case ConfigurationShared::CheckState::On: + case ConfigurationShared::CheckState::Off: Settings::values.rng_seed.SetGlobal(false); - Settings::values.rng_seed.SetValue(std::nullopt); + if (ui->rng_seed_checkbox->isChecked()) { + Settings::values.rng_seed.SetValue( + ui->rng_seed_edit->text().toULongLong(nullptr, 16)); + } else { + Settings::values.rng_seed.SetValue(std::nullopt); + } break; - case Qt::PartiallyChecked: + case ConfigurationShared::CheckState::Global: Settings::values.rng_seed.SetGlobal(false); Settings::values.rng_seed.SetValue(std::nullopt); Settings::values.rng_seed.SetGlobal(true); break; + case ConfigurationShared::CheckState::Count: + break; } - switch (ui->custom_rtc_checkbox->checkState()) { - case Qt::Checked: - Settings::values.custom_rtc.SetGlobal(false); - Settings::values.custom_rtc.SetValue( - std::chrono::seconds(ui->custom_rtc_edit->dateTime().toSecsSinceEpoch())); - break; - case Qt::Unchecked: + switch (use_custom_rtc) { + case ConfigurationShared::CheckState::On: + case ConfigurationShared::CheckState::Off: Settings::values.custom_rtc.SetGlobal(false); - Settings::values.custom_rtc.SetValue(std::nullopt); + if (ui->custom_rtc_checkbox->isChecked()) { + Settings::values.custom_rtc.SetValue( + std::chrono::seconds(ui->custom_rtc_edit->dateTime().toSecsSinceEpoch())); + } else { + Settings::values.custom_rtc.SetValue(std::nullopt); + } break; - case Qt::PartiallyChecked: + case ConfigurationShared::CheckState::Global: Settings::values.custom_rtc.SetGlobal(false); Settings::values.custom_rtc.SetValue(std::nullopt); Settings::values.custom_rtc.SetGlobal(true); break; + case ConfigurationShared::CheckState::Count: + break; } } @@ -229,10 +223,23 @@ void ConfigureSystem::SetupPerGameUI() { return; } - ConfigurationShared::InsertGlobalItem(ui->combo_language); - ConfigurationShared::InsertGlobalItem(ui->combo_region); - ConfigurationShared::InsertGlobalItem(ui->combo_time_zone); - ConfigurationShared::InsertGlobalItem(ui->combo_sound); - ui->rng_seed_checkbox->setTristate(true); - ui->custom_rtc_checkbox->setTristate(true); + ConfigurationShared::SetColoredComboBox(ui->combo_language, ui->label_language, + "label_language", + Settings::values.language_index.GetValue(true)); + ConfigurationShared::SetColoredComboBox(ui->combo_region, ui->label_region, "label_region", + Settings::values.region_index.GetValue(true)); + ConfigurationShared::SetColoredComboBox(ui->combo_time_zone, ui->label_timezone, + "label_timezone", + Settings::values.time_zone_index.GetValue(true)); + ConfigurationShared::SetColoredComboBox(ui->combo_sound, ui->label_sound, "label_sound", + Settings::values.sound_index.GetValue(true)); + + ConfigurationShared::SetColoredTristate( + ui->rng_seed_checkbox, "rng_seed_checkbox", Settings::values.rng_seed.UsingGlobal(), + Settings::values.rng_seed.GetValue().has_value(), + Settings::values.rng_seed.GetValue(true).has_value(), use_rng_seed); + ConfigurationShared::SetColoredTristate( + ui->custom_rtc_checkbox, "custom_rtc_checkbox", Settings::values.custom_rtc.UsingGlobal(), + Settings::values.custom_rtc.GetValue().has_value(), + Settings::values.custom_rtc.GetValue(true).has_value(), use_custom_rtc); } diff --git a/src/yuzu/configuration/configure_system.h b/src/yuzu/configuration/configure_system.h index f317ef8b5..fc5cd2945 100644 --- a/src/yuzu/configuration/configure_system.h +++ b/src/yuzu/configuration/configure_system.h @@ -9,6 +9,10 @@ #include <QList> #include <QWidget> +namespace ConfigurationShared { +enum class CheckState; +} + namespace Ui { class ConfigureSystem; } @@ -41,4 +45,7 @@ private: int region_index = 0; int time_zone_index = 0; int sound_index = 0; + + ConfigurationShared::CheckState use_rng_seed; + ConfigurationShared::CheckState use_custom_rtc; }; diff --git a/src/yuzu/configuration/configure_system.ui b/src/yuzu/configuration/configure_system.ui index 9c8cca6dc..53b95658b 100644 --- a/src/yuzu/configuration/configure_system.ui +++ b/src/yuzu/configuration/configure_system.ui @@ -21,490 +21,494 @@ <property name="title"> <string>System Settings</string> </property> - <layout class="QGridLayout" name="gridLayout"> - <item row="3" column="0"> - <widget class="QLabel" name="label_sound"> - <property name="text"> - <string>Sound output mode</string> - </property> - </widget> - </item> - <item row="4" column="0"> - <widget class="QLabel" name="label_console_id"> - <property name="text"> - <string>Console ID:</string> - </property> - </widget> - </item> - <item row="0" column="1"> - <widget class="QComboBox" name="combo_language"> - <property name="toolTip"> - <string>Note: this can be overridden when region setting is auto-select</string> - </property> - <item> - <property name="text"> - <string>Japanese (日本語)</string> - </property> - </item> - <item> - <property name="text"> - <string>English</string> - </property> - </item> - <item> - <property name="text"> - <string>French (français)</string> - </property> - </item> - <item> - <property name="text"> - <string>German (Deutsch)</string> - </property> - </item> - <item> - <property name="text"> - <string>Italian (italiano)</string> - </property> - </item> - <item> - <property name="text"> - <string>Spanish (español)</string> - </property> - </item> - <item> - <property name="text"> - <string>Chinese</string> - </property> - </item> - <item> - <property name="text"> - <string>Korean (한국어)</string> - </property> - </item> - <item> - <property name="text"> - <string>Dutch (Nederlands)</string> - </property> - </item> - <item> - <property name="text"> - <string>Portuguese (português)</string> - </property> - </item> - <item> - <property name="text"> - <string>Russian (Русский)</string> - </property> - </item> - <item> - <property name="text"> - <string>Taiwanese</string> - </property> - </item> - <item> - <property name="text"> - <string>British English</string> - </property> - </item> - <item> - <property name="text"> - <string>Canadian French</string> - </property> - </item> - <item> - <property name="text"> - <string>Latin American Spanish</string> - </property> - </item> - <item> - <property name="text"> - <string>Simplified Chinese</string> - </property> - </item> - <item> - <property name="text"> - <string>Traditional Chinese (正體中文)</string> - </property> - </item> - </widget> - </item> - <item row="1" column="0"> - <widget class="QLabel" name="label_region"> - <property name="text"> - <string>Region:</string> - </property> - </widget> - </item> - <item row="1" column="1"> - <widget class="QComboBox" name="combo_region"> - <item> - <property name="text"> - <string>Japan</string> - </property> - </item> - <item> - <property name="text"> - <string>USA</string> - </property> - </item> - <item> - <property name="text"> - <string>Europe</string> - </property> - </item> - <item> - <property name="text"> - <string>Australia</string> - </property> - </item> - <item> - <property name="text"> - <string>China</string> - </property> - </item> - <item> - <property name="text"> - <string>Korea</string> - </property> - </item> - <item> - <property name="text"> - <string>Taiwan</string> - </property> - </item> - </widget> - </item> - <item row="2" column="0"> - <widget class="QLabel" name="label_timezone"> - <property name="text"> - <string>Time Zone:</string> - </property> - </widget> - </item> - <item row="2" column="1"> - <widget class="QComboBox" name="combo_time_zone"> - <item> - <property name="text"> - <string>Auto</string> - </property> - </item> - <item> - <property name="text"> - <string>Default</string> - </property> - </item> - <item> - <property name="text"> - <string>CET</string> - </property> - </item> - <item> - <property name="text"> - <string>CST6CDT</string> - </property> - </item> - <item> - <property name="text"> - <string>Cuba</string> - </property> - </item> - <item> - <property name="text"> - <string>EET</string> - </property> - </item> - <item> - <property name="text"> - <string>Egypt</string> - </property> - </item> - <item> - <property name="text"> - <string>Eire</string> - </property> - </item> - <item> - <property name="text"> - <string>EST</string> - </property> - </item> - <item> - <property name="text"> - <string>EST5EDT</string> - </property> - </item> - <item> - <property name="text"> - <string>GB</string> - </property> - </item> - <item> - <property name="text"> - <string>GB-Eire</string> - </property> - </item> - <item> - <property name="text"> - <string>GMT</string> - </property> - </item> - <item> - <property name="text"> - <string>GMT+0</string> - </property> - </item> - <item> - <property name="text"> - <string>GMT-0</string> - </property> - </item> - <item> - <property name="text"> - <string>GMT0</string> - </property> - </item> - <item> - <property name="text"> - <string>Greenwich</string> - </property> - </item> - <item> - <property name="text"> - <string>Hongkong</string> - </property> - </item> - <item> - <property name="text"> - <string>HST</string> - </property> - </item> - <item> - <property name="text"> - <string>Iceland</string> - </property> - </item> - <item> - <property name="text"> - <string>Iran</string> - </property> - </item> - <item> - <property name="text"> - <string>Israel</string> - </property> - </item> - <item> - <property name="text"> - <string>Jamaica</string> - </property> - </item> - <item> - <property name="text"> - <string>Japan</string> - </property> - </item> - <item> - <property name="text"> - <string>Kwajalein</string> - </property> - </item> - <item> - <property name="text"> - <string>Libya</string> - </property> - </item> - <item> - <property name="text"> - <string>MET</string> - </property> - </item> - <item> - <property name="text"> - <string>MST</string> - </property> - </item> - <item> - <property name="text"> - <string>MST7MDT</string> - </property> - </item> - <item> - <property name="text"> - <string>Navajo</string> - </property> - </item> - <item> - <property name="text"> - <string>NZ</string> - </property> - </item> - <item> - <property name="text"> - <string>NZ-CHAT</string> - </property> - </item> - <item> - <property name="text"> - <string>Poland</string> - </property> - </item> - <item> - <property name="text"> - <string>Portugal</string> - </property> - </item> - <item> - <property name="text"> - <string>PRC</string> - </property> - </item> - <item> - <property name="text"> - <string>PST8PDT</string> - </property> - </item> - <item> - <property name="text"> - <string>ROC</string> - </property> - </item> - <item> - <property name="text"> - <string>ROK</string> - </property> - </item> - <item> - <property name="text"> - <string>Singapore</string> - </property> - </item> - <item> - <property name="text"> - <string>Turkey</string> - </property> - </item> - <item> - <property name="text"> - <string>UCT</string> - </property> - </item> - <item> - <property name="text"> - <string>Universal</string> - </property> - </item> - <item> - <property name="text"> - <string>UTC</string> - </property> - </item> - <item> - <property name="text"> - <string>W-SU</string> - </property> - </item> - <item> - <property name="text"> - <string>WET</string> - </property> - </item> - <item> - <property name="text"> - <string>Zulu</string> - </property> - </item> - </widget> - </item> - <item row="6" column="0"> - <widget class="QCheckBox" name="rng_seed_checkbox"> - <property name="text"> - <string>RNG Seed</string> - </property> - </widget> - </item> - <item row="3" column="1"> - <widget class="QComboBox" name="combo_sound"> - <item> - <property name="text"> - <string>Mono</string> - </property> - </item> - <item> - <property name="text"> - <string>Stereo</string> - </property> - </item> - <item> - <property name="text"> - <string>Surround</string> - </property> - </item> - </widget> - </item> - <item row="0" column="0"> - <widget class="QLabel" name="label_language"> - <property name="text"> - <string>Language</string> - </property> - </widget> - </item> - <item row="4" column="1"> - <widget class="QPushButton" name="button_regenerate_console_id"> - <property name="sizePolicy"> - <sizepolicy hsizetype="Fixed" vsizetype="Fixed"> - <horstretch>0</horstretch> - <verstretch>0</verstretch> - </sizepolicy> - </property> - <property name="layoutDirection"> - <enum>Qt::RightToLeft</enum> - </property> - <property name="text"> - <string>Regenerate</string> - </property> - </widget> - </item> - <item row="5" column="0"> - <widget class="QCheckBox" name="custom_rtc_checkbox"> - <property name="text"> - <string>Custom RTC</string> - </property> - </widget> - </item> - <item row="5" column="1"> - <widget class="QDateTimeEdit" name="custom_rtc_edit"> - <property name="minimumDate"> - <date> - <year>1970</year> - <month>1</month> - <day>1</day> - </date> - </property> - <property name="displayFormat"> - <string>d MMM yyyy h:mm:ss AP</string> - </property> - </widget> - </item> - <item row="6" column="1"> - <widget class="QLineEdit" name="rng_seed_edit"> - <property name="sizePolicy"> - <sizepolicy hsizetype="Minimum" vsizetype="Fixed"> - <horstretch>0</horstretch> - <verstretch>0</verstretch> - </sizepolicy> - </property> - <property name="font"> - <font> - <family>Lucida Console</family> - </font> - </property> - <property name="inputMask"> - <string notr="true">HHHHHHHH</string> - </property> - <property name="maxLength"> - <number>8</number> - </property> - </widget> + <layout class="QVBoxLayout" name="verticalLayout_2"> + <item> + <layout class="QGridLayout" name="gridLayout_2"> + <item row="1" column="0"> + <widget class="QLabel" name="label_region"> + <property name="text"> + <string>Region:</string> + </property> + </widget> + </item> + <item row="2" column="1"> + <widget class="QComboBox" name="combo_time_zone"> + <item> + <property name="text"> + <string>Auto</string> + </property> + </item> + <item> + <property name="text"> + <string>Default</string> + </property> + </item> + <item> + <property name="text"> + <string>CET</string> + </property> + </item> + <item> + <property name="text"> + <string>CST6CDT</string> + </property> + </item> + <item> + <property name="text"> + <string>Cuba</string> + </property> + </item> + <item> + <property name="text"> + <string>EET</string> + </property> + </item> + <item> + <property name="text"> + <string>Egypt</string> + </property> + </item> + <item> + <property name="text"> + <string>Eire</string> + </property> + </item> + <item> + <property name="text"> + <string>EST</string> + </property> + </item> + <item> + <property name="text"> + <string>EST5EDT</string> + </property> + </item> + <item> + <property name="text"> + <string>GB</string> + </property> + </item> + <item> + <property name="text"> + <string>GB-Eire</string> + </property> + </item> + <item> + <property name="text"> + <string>GMT</string> + </property> + </item> + <item> + <property name="text"> + <string>GMT+0</string> + </property> + </item> + <item> + <property name="text"> + <string>GMT-0</string> + </property> + </item> + <item> + <property name="text"> + <string>GMT0</string> + </property> + </item> + <item> + <property name="text"> + <string>Greenwich</string> + </property> + </item> + <item> + <property name="text"> + <string>Hongkong</string> + </property> + </item> + <item> + <property name="text"> + <string>HST</string> + </property> + </item> + <item> + <property name="text"> + <string>Iceland</string> + </property> + </item> + <item> + <property name="text"> + <string>Iran</string> + </property> + </item> + <item> + <property name="text"> + <string>Israel</string> + </property> + </item> + <item> + <property name="text"> + <string>Jamaica</string> + </property> + </item> + <item> + <property name="text"> + <string>Japan</string> + </property> + </item> + <item> + <property name="text"> + <string>Kwajalein</string> + </property> + </item> + <item> + <property name="text"> + <string>Libya</string> + </property> + </item> + <item> + <property name="text"> + <string>MET</string> + </property> + </item> + <item> + <property name="text"> + <string>MST</string> + </property> + </item> + <item> + <property name="text"> + <string>MST7MDT</string> + </property> + </item> + <item> + <property name="text"> + <string>Navajo</string> + </property> + </item> + <item> + <property name="text"> + <string>NZ</string> + </property> + </item> + <item> + <property name="text"> + <string>NZ-CHAT</string> + </property> + </item> + <item> + <property name="text"> + <string>Poland</string> + </property> + </item> + <item> + <property name="text"> + <string>Portugal</string> + </property> + </item> + <item> + <property name="text"> + <string>PRC</string> + </property> + </item> + <item> + <property name="text"> + <string>PST8PDT</string> + </property> + </item> + <item> + <property name="text"> + <string>ROC</string> + </property> + </item> + <item> + <property name="text"> + <string>ROK</string> + </property> + </item> + <item> + <property name="text"> + <string>Singapore</string> + </property> + </item> + <item> + <property name="text"> + <string>Turkey</string> + </property> + </item> + <item> + <property name="text"> + <string>UCT</string> + </property> + </item> + <item> + <property name="text"> + <string>Universal</string> + </property> + </item> + <item> + <property name="text"> + <string>UTC</string> + </property> + </item> + <item> + <property name="text"> + <string>W-SU</string> + </property> + </item> + <item> + <property name="text"> + <string>WET</string> + </property> + </item> + <item> + <property name="text"> + <string>Zulu</string> + </property> + </item> + </widget> + </item> + <item row="1" column="1"> + <widget class="QComboBox" name="combo_region"> + <item> + <property name="text"> + <string>Japan</string> + </property> + </item> + <item> + <property name="text"> + <string>USA</string> + </property> + </item> + <item> + <property name="text"> + <string>Europe</string> + </property> + </item> + <item> + <property name="text"> + <string>Australia</string> + </property> + </item> + <item> + <property name="text"> + <string>China</string> + </property> + </item> + <item> + <property name="text"> + <string>Korea</string> + </property> + </item> + <item> + <property name="text"> + <string>Taiwan</string> + </property> + </item> + </widget> + </item> + <item row="2" column="0"> + <widget class="QLabel" name="label_timezone"> + <property name="text"> + <string>Time Zone:</string> + </property> + </widget> + </item> + <item row="0" column="1"> + <widget class="QComboBox" name="combo_language"> + <property name="toolTip"> + <string>Note: this can be overridden when region setting is auto-select</string> + </property> + <item> + <property name="text"> + <string>Japanese (日本語)</string> + </property> + </item> + <item> + <property name="text"> + <string>English</string> + </property> + </item> + <item> + <property name="text"> + <string>French (français)</string> + </property> + </item> + <item> + <property name="text"> + <string>German (Deutsch)</string> + </property> + </item> + <item> + <property name="text"> + <string>Italian (italiano)</string> + </property> + </item> + <item> + <property name="text"> + <string>Spanish (español)</string> + </property> + </item> + <item> + <property name="text"> + <string>Chinese</string> + </property> + </item> + <item> + <property name="text"> + <string>Korean (한국어)</string> + </property> + </item> + <item> + <property name="text"> + <string>Dutch (Nederlands)</string> + </property> + </item> + <item> + <property name="text"> + <string>Portuguese (português)</string> + </property> + </item> + <item> + <property name="text"> + <string>Russian (Русский)</string> + </property> + </item> + <item> + <property name="text"> + <string>Taiwanese</string> + </property> + </item> + <item> + <property name="text"> + <string>British English</string> + </property> + </item> + <item> + <property name="text"> + <string>Canadian French</string> + </property> + </item> + <item> + <property name="text"> + <string>Latin American Spanish</string> + </property> + </item> + <item> + <property name="text"> + <string>Simplified Chinese</string> + </property> + </item> + <item> + <property name="text"> + <string>Traditional Chinese (正體中文)</string> + </property> + </item> + </widget> + </item> + <item row="5" column="0"> + <widget class="QCheckBox" name="custom_rtc_checkbox"> + <property name="text"> + <string>Custom RTC</string> + </property> + </widget> + </item> + <item row="0" column="0"> + <widget class="QLabel" name="label_language"> + <property name="text"> + <string>Language</string> + </property> + </widget> + </item> + <item row="6" column="0"> + <widget class="QCheckBox" name="rng_seed_checkbox"> + <property name="text"> + <string>RNG Seed</string> + </property> + </widget> + </item> + <item row="3" column="1"> + <widget class="QComboBox" name="combo_sound"> + <item> + <property name="text"> + <string>Mono</string> + </property> + </item> + <item> + <property name="text"> + <string>Stereo</string> + </property> + </item> + <item> + <property name="text"> + <string>Surround</string> + </property> + </item> + </widget> + </item> + <item row="4" column="0"> + <widget class="QLabel" name="label_console_id"> + <property name="text"> + <string>Console ID:</string> + </property> + </widget> + </item> + <item row="3" column="0"> + <widget class="QLabel" name="label_sound"> + <property name="text"> + <string>Sound output mode</string> + </property> + </widget> + </item> + <item row="5" column="1"> + <widget class="QDateTimeEdit" name="custom_rtc_edit"> + <property name="minimumDate"> + <date> + <year>1970</year> + <month>1</month> + <day>1</day> + </date> + </property> + <property name="displayFormat"> + <string>d MMM yyyy h:mm:ss AP</string> + </property> + </widget> + </item> + <item row="6" column="1"> + <widget class="QLineEdit" name="rng_seed_edit"> + <property name="sizePolicy"> + <sizepolicy hsizetype="Minimum" vsizetype="Fixed"> + <horstretch>0</horstretch> + <verstretch>0</verstretch> + </sizepolicy> + </property> + <property name="font"> + <font> + <family>Lucida Console</family> + </font> + </property> + <property name="inputMask"> + <string notr="true">HHHHHHHH</string> + </property> + <property name="maxLength"> + <number>8</number> + </property> + </widget> + </item> + <item row="4" column="1"> + <widget class="QPushButton" name="button_regenerate_console_id"> + <property name="sizePolicy"> + <sizepolicy hsizetype="Fixed" vsizetype="Fixed"> + <horstretch>0</horstretch> + <verstretch>0</verstretch> + </sizepolicy> + </property> + <property name="layoutDirection"> + <enum>Qt::RightToLeft</enum> + </property> + <property name="text"> + <string>Regenerate</string> + </property> + </widget> + </item> + </layout> </item> </layout> </widget> diff --git a/src/yuzu/configuration/configure_ui.cpp b/src/yuzu/configuration/configure_ui.cpp index 94424ee44..24b6c5b72 100644 --- a/src/yuzu/configuration/configure_ui.cpp +++ b/src/yuzu/configuration/configure_ui.cpp @@ -5,6 +5,7 @@ #include <array> #include <utility> +#include <QDirIterator> #include "common/common_types.h" #include "core/settings.h" #include "ui_configure_ui.h" @@ -29,6 +30,8 @@ constexpr std::array row_text_names{ ConfigureUi::ConfigureUi(QWidget* parent) : QWidget(parent), ui(new Ui::ConfigureUi) { ui->setupUi(this); + InitializeLanguageComboBox(); + for (const auto& theme : UISettings::themes) { ui->theme_combobox->addItem(QString::fromUtf8(theme.first), QString::fromUtf8(theme.second)); @@ -72,6 +75,8 @@ void ConfigureUi::RequestGameListUpdate() { void ConfigureUi::SetConfiguration() { ui->theme_combobox->setCurrentIndex(ui->theme_combobox->findData(UISettings::values.theme)); + ui->language_combobox->setCurrentIndex( + ui->language_combobox->findData(UISettings::values.language)); ui->show_add_ons->setChecked(UISettings::values.show_add_ons); ui->icon_size_combobox->setCurrentIndex( ui->icon_size_combobox->findData(UISettings::values.icon_size)); @@ -100,6 +105,25 @@ void ConfigureUi::RetranslateUI() { } } +void ConfigureUi::InitializeLanguageComboBox() { + ui->language_combobox->addItem(tr("<System>"), QString{}); + ui->language_combobox->addItem(tr("English"), QStringLiteral("en")); + QDirIterator it(QStringLiteral(":/languages"), QDirIterator::NoIteratorFlags); + while (it.hasNext()) { + QString locale = it.next(); + locale.truncate(locale.lastIndexOf(QLatin1Char{'.'})); + locale.remove(0, locale.lastIndexOf(QLatin1Char{'/'}) + 1); + const QString lang = QLocale::languageToString(QLocale(locale).language()); + ui->language_combobox->addItem(lang, locale); + } + + // Unlike other configuration changes, interface language changes need to be reflected on the + // interface immediately. This is done by passing a signal to the main window, and then + // retranslating when passing back. + connect(ui->language_combobox, QOverload<int>::of(&QComboBox::currentIndexChanged), this, + &ConfigureUi::OnLanguageChanged); +} + void ConfigureUi::InitializeIconSizeComboBox() { for (const auto& size : default_icon_sizes) { ui->icon_size_combobox->addItem(QString::fromUtf8(size.second), size.first); @@ -147,3 +171,10 @@ void ConfigureUi::UpdateSecondRowComboBox(bool init) { ui->row_2_text_combobox->removeItem( ui->row_2_text_combobox->findData(ui->row_1_text_combobox->currentData())); } + +void ConfigureUi::OnLanguageChanged(int index) { + if (index == -1) + return; + + emit LanguageChanged(ui->language_combobox->itemData(index).toString()); +} diff --git a/src/yuzu/configuration/configure_ui.h b/src/yuzu/configuration/configure_ui.h index d471afe99..c30bcf6ff 100644 --- a/src/yuzu/configuration/configure_ui.h +++ b/src/yuzu/configuration/configure_ui.h @@ -20,6 +20,12 @@ public: void ApplyConfiguration(); +private slots: + void OnLanguageChanged(int index); + +signals: + void LanguageChanged(const QString& locale); + private: void RequestGameListUpdate(); @@ -28,6 +34,7 @@ private: void changeEvent(QEvent*) override; void RetranslateUI(); + void InitializeLanguageComboBox(); void InitializeIconSizeComboBox(); void InitializeRowComboBoxes(); diff --git a/src/yuzu/configuration/configure_ui.ui b/src/yuzu/configuration/configure_ui.ui index bd5c5d3c2..0b81747d7 100644 --- a/src/yuzu/configuration/configure_ui.ui +++ b/src/yuzu/configuration/configure_ui.ui @@ -13,112 +13,132 @@ <property name="windowTitle"> <string>Form</string> </property> - <layout class="QHBoxLayout" name="HorizontalLayout"> + <layout class="QVBoxLayout" name="verticalLayout"> <item> - <layout class="QVBoxLayout" name="VerticalLayout"> - <item> - <widget class="QGroupBox" name="GeneralGroupBox"> - <property name="title"> - <string>General</string> - </property> - <layout class="QHBoxLayout" name="horizontalLayout"> + <widget class="QGroupBox" name="general_groupBox"> + <property name="title"> + <string>General</string> + </property> + <layout class="QHBoxLayout" name="horizontalLayout"> + <item> + <layout class="QVBoxLayout" name="verticalLayout_2"> <item> - <layout class="QVBoxLayout" name="verticalLayout"> + <widget class="QLabel" name="label_change_language_info"> + <property name="text"> + <string>Note: Changing language will apply your configuration.</string> + </property> + <property name="wordWrap"> + <bool>true</bool> + </property> + </widget> + </item> + <item> + <layout class="QHBoxLayout" name="horizontalLayout_2"> + <item> + <widget class="QLabel" name="language_label"> + <property name="text"> + <string>Interface language:</string> + </property> + </widget> + </item> + <item> + <widget class="QComboBox" name="language_combobox"/> + </item> + </layout> + </item> + <item> + <layout class="QHBoxLayout" name="horizontalLayout_3"> + <item> + <widget class="QLabel" name="theme_label"> + <property name="text"> + <string>Theme:</string> + </property> + </widget> + </item> <item> - <layout class="QHBoxLayout" name="horizontalLayout_3"> - <item> - <widget class="QLabel" name="theme_label"> - <property name="text"> - <string>Theme:</string> - </property> - </widget> - </item> - <item> - <widget class="QComboBox" name="theme_combobox"/> - </item> - </layout> + <widget class="QComboBox" name="theme_combobox"/> </item> </layout> </item> </layout> - </widget> - </item> - <item> - <widget class="QGroupBox" name="GameListGroupBox"> - <property name="title"> - <string>Game List</string> - </property> - <layout class="QHBoxLayout" name="GameListHorizontalLayout"> + </item> + </layout> + </widget> + </item> + <item> + <widget class="QGroupBox" name="GameListGroupBox"> + <property name="title"> + <string>Game List</string> + </property> + <layout class="QHBoxLayout" name="GameListHorizontalLayout"> + <item> + <layout class="QVBoxLayout" name="GeneralVerticalLayout"> <item> - <layout class="QVBoxLayout" name="GeneralVerticalLayout"> + <widget class="QCheckBox" name="show_add_ons"> + <property name="text"> + <string>Show Add-Ons Column</string> + </property> + </widget> + </item> + <item> + <layout class="QHBoxLayout" name="icon_size_qhbox_layout_2"> <item> - <widget class="QCheckBox" name="show_add_ons"> + <widget class="QLabel" name="icon_size_label"> <property name="text"> - <string>Show Add-Ons Column</string> + <string>Icon Size:</string> </property> </widget> </item> <item> - <layout class="QHBoxLayout" name="icon_size_qhbox_layout_2"> - <item> - <widget class="QLabel" name="icon_size_label"> - <property name="text"> - <string>Icon Size:</string> - </property> - </widget> - </item> - <item> - <widget class="QComboBox" name="icon_size_combobox"/> - </item> - </layout> + <widget class="QComboBox" name="icon_size_combobox"/> </item> + </layout> + </item> + <item> + <layout class="QHBoxLayout" name="row_1_qhbox_layout"> <item> - <layout class="QHBoxLayout" name="row_1_qhbox_layout"> - <item> - <widget class="QLabel" name="row_1_label"> - <property name="text"> - <string>Row 1 Text:</string> - </property> - </widget> - </item> - <item> - <widget class="QComboBox" name="row_1_text_combobox"/> - </item> - </layout> + <widget class="QLabel" name="row_1_label"> + <property name="text"> + <string>Row 1 Text:</string> + </property> + </widget> </item> <item> - <layout class="QHBoxLayout" name="row_2_qhbox_layout"> - <item> - <widget class="QLabel" name="row_2_label"> - <property name="text"> - <string>Row 2 Text:</string> - </property> - </widget> - </item> - <item> - <widget class="QComboBox" name="row_2_text_combobox"/> - </item> - </layout> + <widget class="QComboBox" name="row_1_text_combobox"/> + </item> + </layout> + </item> + <item> + <layout class="QHBoxLayout" name="row_2_qhbox_layout"> + <item> + <widget class="QLabel" name="row_2_label"> + <property name="text"> + <string>Row 2 Text:</string> + </property> + </widget> + </item> + <item> + <widget class="QComboBox" name="row_2_text_combobox"/> </item> </layout> </item> </layout> - </widget> - </item> - <item> - <spacer name="verticalSpacer"> - <property name="orientation"> - <enum>Qt::Vertical</enum> - </property> - <property name="sizeHint" stdset="0"> - <size> - <width>20</width> - <height>40</height> - </size> - </property> - </spacer> - </item> - </layout> + </item> + </layout> + </widget> + </item> + <item> + <spacer name="verticalSpacer"> + <property name="orientation"> + <enum>Qt::Vertical</enum> + </property> + <property name="sizeHint" stdset="0"> + <size> + <width>20</width> + <height>40</height> + </size> + </property> + </spacer> </item> </layout> </widget> diff --git a/src/yuzu/debugger/wait_tree.cpp b/src/yuzu/debugger/wait_tree.cpp index 9bb0a0109..3439cb333 100644 --- a/src/yuzu/debugger/wait_tree.cpp +++ b/src/yuzu/debugger/wait_tree.cpp @@ -2,9 +2,11 @@ // Licensed under GPLv2 or any later version // Refer to the license.txt file included. +#include <array> #include <fmt/format.h> #include "yuzu/debugger/wait_tree.h" +#include "yuzu/uisettings.h" #include "yuzu/util/util.h" #include "common/assert.h" @@ -19,11 +21,40 @@ #include "core/hle/kernel/thread.h" #include "core/memory.h" +namespace { + +constexpr std::array<std::array<Qt::GlobalColor, 2>, 10> WaitTreeColors{{ + {Qt::GlobalColor::darkGreen, Qt::GlobalColor::green}, + {Qt::GlobalColor::darkGreen, Qt::GlobalColor::green}, + {Qt::GlobalColor::darkBlue, Qt::GlobalColor::cyan}, + {Qt::GlobalColor::lightGray, Qt::GlobalColor::lightGray}, + {Qt::GlobalColor::lightGray, Qt::GlobalColor::lightGray}, + {Qt::GlobalColor::darkRed, Qt::GlobalColor::red}, + {Qt::GlobalColor::darkYellow, Qt::GlobalColor::yellow}, + {Qt::GlobalColor::red, Qt::GlobalColor::red}, + {Qt::GlobalColor::darkCyan, Qt::GlobalColor::cyan}, + {Qt::GlobalColor::gray, Qt::GlobalColor::gray}, +}}; + +bool IsDarkTheme() { + const auto& theme = UISettings::values.theme; + return theme == QStringLiteral("qdarkstyle") || + theme == QStringLiteral("qdarkstyle_midnight_blue") || + theme == QStringLiteral("colorful_dark") || + theme == QStringLiteral("colorful_midnight_blue"); +} + +} // namespace + WaitTreeItem::WaitTreeItem() = default; WaitTreeItem::~WaitTreeItem() = default; QColor WaitTreeItem::GetColor() const { - return QColor(Qt::GlobalColor::black); + if (IsDarkTheme()) { + return QColor(Qt::GlobalColor::white); + } else { + return QColor(Qt::GlobalColor::black); + } } std::vector<std::unique_ptr<WaitTreeItem>> WaitTreeItem::GetChildren() const { @@ -263,36 +294,38 @@ QString WaitTreeThread::GetText() const { } QColor WaitTreeThread::GetColor() const { + const std::size_t color_index = IsDarkTheme() ? 1 : 0; + const auto& thread = static_cast<const Kernel::Thread&>(object); switch (thread.GetStatus()) { case Kernel::ThreadStatus::Running: - return QColor(Qt::GlobalColor::darkGreen); + return QColor(WaitTreeColors[0][color_index]); case Kernel::ThreadStatus::Ready: if (!thread.IsPaused()) { if (thread.WasRunning()) { - return QColor(Qt::GlobalColor::darkGreen); + return QColor(WaitTreeColors[1][color_index]); } else { - return QColor(Qt::GlobalColor::darkBlue); + return QColor(WaitTreeColors[2][color_index]); } } else { - return QColor(Qt::GlobalColor::lightGray); + return QColor(WaitTreeColors[3][color_index]); } case Kernel::ThreadStatus::Paused: - return QColor(Qt::GlobalColor::lightGray); + return QColor(WaitTreeColors[4][color_index]); case Kernel::ThreadStatus::WaitHLEEvent: case Kernel::ThreadStatus::WaitIPC: - return QColor(Qt::GlobalColor::darkRed); + return QColor(WaitTreeColors[5][color_index]); case Kernel::ThreadStatus::WaitSleep: - return QColor(Qt::GlobalColor::darkYellow); + return QColor(WaitTreeColors[6][color_index]); case Kernel::ThreadStatus::WaitSynch: case Kernel::ThreadStatus::WaitMutex: case Kernel::ThreadStatus::WaitCondVar: case Kernel::ThreadStatus::WaitArb: - return QColor(Qt::GlobalColor::red); + return QColor(WaitTreeColors[7][color_index]); case Kernel::ThreadStatus::Dormant: - return QColor(Qt::GlobalColor::darkCyan); + return QColor(WaitTreeColors[8][color_index]); case Kernel::ThreadStatus::Dead: - return QColor(Qt::GlobalColor::gray); + return QColor(WaitTreeColors[9][color_index]); default: return WaitTreeItem::GetColor(); } diff --git a/src/yuzu/main.cpp b/src/yuzu/main.cpp index d51cb2bcb..31a635176 100644 --- a/src/yuzu/main.cpp +++ b/src/yuzu/main.cpp @@ -94,6 +94,8 @@ static FileSys::VirtualFile VfsDirectoryCreateFileWrapper(const FileSys::Virtual #include "core/perf_stats.h" #include "core/settings.h" #include "core/telemetry_session.h" +#include "video_core/gpu.h" +#include "video_core/shader_notify.h" #include "yuzu/about_dialog.h" #include "yuzu/bootmanager.h" #include "yuzu/compatdb.h" @@ -189,6 +191,8 @@ GMainWindow::GMainWindow() provider(std::make_unique<FileSys::ManualContentProvider>()) { InitializeLogging(); + LoadTranslation(); + setAcceptDrops(true); ui.setupUi(this); statusBar()->hide(); @@ -279,17 +283,21 @@ GMainWindow::~GMainWindow() { } void GMainWindow::ProfileSelectorSelectProfile() { - QtProfileSelectionDialog dialog(this); - dialog.setWindowFlags(Qt::Dialog | Qt::CustomizeWindowHint | Qt::WindowTitleHint | - Qt::WindowSystemMenuHint | Qt::WindowCloseButtonHint); - dialog.setWindowModality(Qt::WindowModal); - if (dialog.exec() == QDialog::Rejected) { - emit ProfileSelectorFinishedSelection(std::nullopt); - return; + const Service::Account::ProfileManager manager; + int index = 0; + if (manager.GetUserCount() != 1) { + QtProfileSelectionDialog dialog(this); + dialog.setWindowFlags(Qt::Dialog | Qt::CustomizeWindowHint | Qt::WindowTitleHint | + Qt::WindowSystemMenuHint | Qt::WindowCloseButtonHint); + dialog.setWindowModality(Qt::WindowModal); + if (dialog.exec() == QDialog::Rejected) { + emit ProfileSelectorFinishedSelection(std::nullopt); + return; + } + index = dialog.GetIndex(); } - Service::Account::ProfileManager manager; - const auto uuid = manager.GetUser(static_cast<std::size_t>(dialog.GetIndex())); + const auto uuid = manager.GetUser(static_cast<std::size_t>(index)); if (!uuid.has_value()) { emit ProfileSelectorFinishedSelection(std::nullopt); return; @@ -494,6 +502,8 @@ void GMainWindow::InitializeWidgets() { message_label->setAlignment(Qt::AlignLeft); statusBar()->addPermanentWidget(message_label, 1); + shader_building_label = new QLabel(); + shader_building_label->setToolTip(tr("The amount of shaders currently being built")); emu_speed_label = new QLabel(); emu_speed_label->setToolTip( tr("Current emulation speed. Values higher or lower than 100% " @@ -506,7 +516,8 @@ void GMainWindow::InitializeWidgets() { tr("Time taken to emulate a Switch frame, not counting framelimiting or v-sync. For " "full-speed emulation this should be at most 16.67 ms.")); - for (auto& label : {emu_speed_label, game_fps_label, emu_frametime_label}) { + for (auto& label : + {shader_building_label, emu_speed_label, game_fps_label, emu_frametime_label}) { label->setVisible(false); label->setFrameStyle(QFrame::NoFrame); label->setContentsMargins(4, 0, 4, 0); @@ -1172,6 +1183,7 @@ void GMainWindow::ShutdownGame() { // Disable status bar updates status_bar_update_timer.stop(); + shader_building_label->setVisible(false); emu_speed_label->setVisible(false); game_fps_label->setVisible(false); emu_frametime_label->setVisible(false); @@ -2038,6 +2050,9 @@ void GMainWindow::OnConfigure() { const bool old_discord_presence = UISettings::values.enable_discord_presence; ConfigureDialog configure_dialog(this, hotkey_registry); + connect(&configure_dialog, &ConfigureDialog::LanguageChanged, this, + &GMainWindow::OnLanguageChanged); + const auto result = configure_dialog.exec(); if (result != QDialog::Accepted) { return; @@ -2182,6 +2197,17 @@ void GMainWindow::UpdateStatusBar() { } auto results = Core::System::GetInstance().GetAndResetPerfStats(); + auto& shader_notify = Core::System::GetInstance().GPU().ShaderNotify(); + const auto shaders_building = shader_notify.GetShadersBuilding(); + + if (shaders_building != 0) { + shader_building_label->setText( + tr("Building: %1 shader").arg(shaders_building) + + (shaders_building != 1 ? QString::fromStdString("s") : QString::fromStdString(""))); + shader_building_label->setVisible(true); + } else { + shader_building_label->setVisible(false); + } if (Settings::values.use_frame_limit.GetValue()) { emu_speed_label->setText(tr("Speed: %1% / %2%") @@ -2311,9 +2337,12 @@ void GMainWindow::OnReinitializeKeys(ReinitializeKeyBehavior behavior) { if (behavior == ReinitializeKeyBehavior::Warning) { const auto res = QMessageBox::information( this, tr("Confirm Key Rederivation"), - tr("You are about to force rederive all of your keys. \nIf you do not know what this " - "means or what you are doing, \nthis is a potentially destructive action. \nPlease " - "make sure this is what you want \nand optionally make backups.\n\nThis will delete " + tr("You are about to force rederive all of your keys. \nIf you do not know what " + "this " + "means or what you are doing, \nthis is a potentially destructive action. " + "\nPlease " + "make sure this is what you want \nand optionally make backups.\n\nThis will " + "delete " "your autogenerated key files and re-run the key derivation module."), QMessageBox::StandardButtons{QMessageBox::Ok, QMessageBox::Cancel}); @@ -2596,6 +2625,43 @@ void GMainWindow::UpdateUITheme() { QIcon::setThemeSearchPaths(theme_paths); } +void GMainWindow::LoadTranslation() { + // If the selected language is English, no need to install any translation + if (UISettings::values.language == QStringLiteral("en")) { + return; + } + + bool loaded; + + if (UISettings::values.language.isEmpty()) { + // If the selected language is empty, use system locale + loaded = translator.load(QLocale(), {}, {}, QStringLiteral(":/languages/")); + } else { + // Otherwise load from the specified file + loaded = translator.load(UISettings::values.language, QStringLiteral(":/languages/")); + } + + if (loaded) { + qApp->installTranslator(&translator); + } else { + UISettings::values.language = QStringLiteral("en"); + } +} + +void GMainWindow::OnLanguageChanged(const QString& locale) { + if (UISettings::values.language != QStringLiteral("en")) { + qApp->removeTranslator(&translator); + } + + UISettings::values.language = locale; + LoadTranslation(); + ui.retranslateUi(this); + UpdateWindowTitle(); + + if (emulation_running) + ui.action_Start->setText(tr("Continue")); +} + void GMainWindow::SetDiscordEnabled([[maybe_unused]] bool state) { #ifdef USE_DISCORD_PRESENCE if (state) { @@ -2624,8 +2690,8 @@ int main(int argc, char* argv[]) { #ifdef __APPLE__ // If you start a bundle (binary) on OSX without the Terminal, the working directory is "/". - // But since we require the working directory to be the executable path for the location of the - // user folder in the Qt Frontend, we need to cd into that working directory + // But since we require the working directory to be the executable path for the location of + // the user folder in the Qt Frontend, we need to cd into that working directory const std::string bin_path = FileUtil::GetBundleDirectory() + DIR_SEP + ".."; chdir(bin_path.c_str()); #endif diff --git a/src/yuzu/main.h b/src/yuzu/main.h index adff65fb5..db573d606 100644 --- a/src/yuzu/main.h +++ b/src/yuzu/main.h @@ -10,6 +10,7 @@ #include <QMainWindow> #include <QTimer> +#include <QTranslator> #include "common/common_types.h" #include "core/core.h" @@ -225,6 +226,7 @@ private slots: void OnCaptureScreenshot(); void OnCoreError(Core::System::ResultStatus, std::string); void OnReinitializeKeys(ReinitializeKeyBehavior behavior); + void OnLanguageChanged(const QString& locale); private: std::optional<u64> SelectRomFSDumpTarget(const FileSys::ContentProvider&, u64 program_id); @@ -237,6 +239,7 @@ private: void HideMouseCursor(); void ShowMouseCursor(); void OpenURL(const QUrl& url); + void LoadTranslation(); Ui::MainWindow ui; @@ -248,6 +251,7 @@ private: // Status bar elements QLabel* message_label = nullptr; + QLabel* shader_building_label = nullptr; QLabel* emu_speed_label = nullptr; QLabel* game_fps_label = nullptr; QLabel* emu_frametime_label = nullptr; @@ -284,6 +288,8 @@ private: HotkeyRegistry hotkey_registry; + QTranslator translator; + // Install progress dialog QProgressDialog* install_progress; diff --git a/src/yuzu/uisettings.cpp b/src/yuzu/uisettings.cpp index 738c4b2fc..a51175f36 100644 --- a/src/yuzu/uisettings.cpp +++ b/src/yuzu/uisettings.cpp @@ -11,6 +11,8 @@ const Themes themes{{ {"Light Colorful", "colorful"}, {"Dark", "qdarkstyle"}, {"Dark Colorful", "colorful_dark"}, + {"Midnight Blue", "qdarkstyle_midnight_blue"}, + {"Midnight Blue Colorful", "colorful_midnight_blue"}, }}; Values values = {}; diff --git a/src/yuzu/uisettings.h b/src/yuzu/uisettings.h index 830932d45..ac7b9aef6 100644 --- a/src/yuzu/uisettings.h +++ b/src/yuzu/uisettings.h @@ -24,7 +24,7 @@ struct Shortcut { ContextualShortcut shortcut; }; -using Themes = std::array<std::pair<const char*, const char*>, 4>; +using Themes = std::array<std::pair<const char*, const char*>, 6>; extern const Themes themes; struct GameDir { @@ -75,6 +75,7 @@ struct Values { bool game_dir_deprecated_deepscan; QVector<UISettings::GameDir> game_dirs; QStringList recent_files; + QString language; QString theme; |
