From 2d059906dbe85148be84caaf2940c2b6dd74141a Mon Sep 17 00:00:00 2001 From: spycrab Date: Fri, 13 Jul 2018 12:56:58 +0200 Subject: [PATCH] Qt/GameConfigWidget: Complete overhaul --- Source/Core/DolphinQt/CMakeLists.txt | 2 + .../Core/DolphinQt/Config/GameConfigEdit.cpp | 168 ++++++++ Source/Core/DolphinQt/Config/GameConfigEdit.h | 39 ++ .../Config/GameConfigHighlighter.cpp | 49 +++ .../DolphinQt/Config/GameConfigHighlighter.h | 29 ++ .../DolphinQt/Config/GameConfigWidget.cpp | 372 ++---------------- .../Core/DolphinQt/Config/GameConfigWidget.h | 40 +- Source/Core/DolphinQt/DolphinQt.vcxproj | 6 + 8 files changed, 338 insertions(+), 367 deletions(-) create mode 100644 Source/Core/DolphinQt/Config/GameConfigEdit.cpp create mode 100644 Source/Core/DolphinQt/Config/GameConfigEdit.h create mode 100644 Source/Core/DolphinQt/Config/GameConfigHighlighter.cpp create mode 100644 Source/Core/DolphinQt/Config/GameConfigHighlighter.h diff --git a/Source/Core/DolphinQt/CMakeLists.txt b/Source/Core/DolphinQt/CMakeLists.txt index 46f0880092a6..06212aee5ce9 100644 --- a/Source/Core/DolphinQt/CMakeLists.txt +++ b/Source/Core/DolphinQt/CMakeLists.txt @@ -28,6 +28,8 @@ add_executable(dolphin-emu Config/CheatWarningWidget.cpp Config/ControllersWindow.cpp Config/FilesystemWidget.cpp + Config/GameConfigEdit.cpp + Config/GameConfigHighlighter.cpp Config/GameConfigWidget.cpp Config/GeckoCodeWidget.cpp Config/Graphics/AdvancedWidget.cpp diff --git a/Source/Core/DolphinQt/Config/GameConfigEdit.cpp b/Source/Core/DolphinQt/Config/GameConfigEdit.cpp new file mode 100644 index 000000000000..940a2ed6f73c --- /dev/null +++ b/Source/Core/DolphinQt/Config/GameConfigEdit.cpp @@ -0,0 +1,168 @@ +// Copyright 2018 Dolphin Emulator Project +// Licensed under GPLv2+ +// Refer to the license.txt file included. + +#include "DolphinQt/Config/GameConfigEdit.h" + +#include +#include +#include +#include +#include +#include +#include +#include + +#include "DolphinQt/Config/GameConfigHighlighter.h" + +GameConfigEdit::GameConfigEdit(QWidget* parent, const QString& path) : m_path(path) +{ + LoadFile(); + + setAcceptRichText(false); + setContextMenuPolicy(Qt::CustomContextMenu); + + new GameConfigHighlighter(document()); + + m_keyword_map[QStringLiteral("Core")] = + tr("Section that contains most CPU and Hardware related settings."); + + m_keyword_map[QStringLiteral("CPUThread")] = tr( + "Controls whether or not Dual Core should be enabled. Can improve performance but can also " + "cause issues. Defaults to True"); + m_keyword_map[QStringLiteral("FastDiscSpeed")] = + tr("Shortens loading times but may break some games. Can have negative effects on performance. Defaults to False"); + m_keyword_map[QStringLiteral("MMU")] = tr("Controls whether or not the Memory Management Unit " + "should be emulated fully. Few games require it."); + m_keyword_map[QStringLiteral("DSPHLE")] = + tr("Controls whether to use high or low-level DSP emulation. Defaults to True"); + m_keyword_map[QStringLiteral("JITFollowBranch")] = + tr("Tries to translate branches ahead of time, improving performance in most cases. Defaults " + "to True"); + + m_keyword_map[QStringLiteral("Gecko")] = tr("Section that contains all Gecko cheat codes."); + m_keyword_map[QStringLiteral("ActionReplay")] = + tr("Section that contains all Action Replay cheat codes."); + m_keyword_map[QStringLiteral("Video_Settings")] = + tr("Section that contains all graphics related settings."); + + Connect(); +} + +void GameConfigEdit::LoadFile() +{ + QFile file(m_path); + if (!file.open(QIODevice::ReadOnly | QIODevice::Text)) + return; + + setPlainText(QString::fromStdString(file.readAll().toStdString())); +} + +#include + +void GameConfigEdit::SaveFile() +{ + if (!isVisible() || isReadOnly()) + return; + + QFile file(m_path); + + if (!file.open(QIODevice::WriteOnly | QIODevice::Truncate | QIODevice::Text)) + return; + + const std::string contents = toPlainText().toStdString(); + + file.write(contents.c_str(), contents.length()); +} + +void GameConfigEdit::Connect() +{ + connect(this, &QTextEdit::textChanged, this, &GameConfigEdit::SaveFile); + connect(this, &QTextEdit::selectionChanged, this, &GameConfigEdit::OnSelectionChanged); + connect(this, &QTextEdit::customContextMenuRequested, this, &GameConfigEdit::OnContextMenu); +} + +void GameConfigEdit::OnSelectionChanged() +{ + const QString& keyword = textCursor().selectedText(); + + if (m_keyword_map.count(keyword)) + QWhatsThis::showText(QCursor::pos(), m_keyword_map[keyword], this); +} + +void GameConfigEdit::AddBoolOption(QMenu* menu, const QString& name, const QString& section, + const QString& key) +{ + auto* option = menu->addMenu(name); + + option->addAction(tr("On"), this, + [this, section, key] { SetOption(section, key, QStringLiteral("True")); }); + option->addAction(tr("Off"), this, + [this, section, key] { SetOption(section, key, QStringLiteral("False")); }); +} + +void GameConfigEdit::SetOption(const QString& section, const QString& key, const QString& value) +{ + auto section_cursor = document()->find(QRegExp(QStringLiteral("^\\[%1\\]").arg(section)), 0); + + // Check if the section this belongs in can be found + if (!section_cursor.isNull()) + { + auto value_cursor = + document()->find(QRegExp(QStringLiteral("^%1 = .*").arg(key)), section_cursor); + + const QString new_line = QStringLiteral("%1 = %2").arg(key).arg(value); + + // Check if the value that has to be set already exists + if (!value_cursor.isNull()) + { + value_cursor.insertText(new_line); + } + else + { + section_cursor.clearSelection(); + section_cursor.insertText(QStringLiteral("\n") + new_line); + } + } + else + { + append(QStringLiteral("[%1]\n\n%2 = %3\n").arg(section).arg(key).arg(value)); + } +} + +void GameConfigEdit::OnContextMenu(const QPoint& pos) +{ + auto* menu = createStandardContextMenu(pos); + + menu->addSeparator(); + + menu->addAction(tr("Refresh"), this, &GameConfigEdit::LoadFile); + menu->addAction(tr("Open in External Editor"), this, &GameConfigEdit::OpenExternalEditor); + + if (!isReadOnly()) + { + menu->addSeparator(); + auto* core_menu = menu->addMenu(tr("Core")); + + AddBoolOption(core_menu, tr("Dual Core"), QStringLiteral("Core"), QStringLiteral("CPUThread")); + AddBoolOption(core_menu, tr("MMU"), QStringLiteral("Core"), QStringLiteral("MMU")); + } + + menu->exec(QCursor::pos()); +} + +void GameConfigEdit::OpenExternalEditor() +{ + QFile file(m_path); + + if (!file.exists()) + { + if (isReadOnly()) + return; + + file.open(QIODevice::WriteOnly); + file.close(); + } + + QDesktopServices::openUrl(QUrl::fromLocalFile(m_path)); +} diff --git a/Source/Core/DolphinQt/Config/GameConfigEdit.h b/Source/Core/DolphinQt/Config/GameConfigEdit.h new file mode 100644 index 000000000000..86c331c31ccc --- /dev/null +++ b/Source/Core/DolphinQt/Config/GameConfigEdit.h @@ -0,0 +1,39 @@ +// Copyright 2018 Dolphin Emulator Project +// Licensed under GPLv2+ +// Refer to the license.txt file included. + +#pragma once + +#include + +#include +#include +#include + +class GameConfigEdit : public QTextEdit +{ +public: + explicit GameConfigEdit(QWidget* parent, const QString& path); + +private: + void Connect(); + + void LoadFile(); + void SaveFile(); + + void OnSelectionChanged(); + void OnContextMenu(const QPoint& pos); + void OpenExternalEditor(); + + void SetReadOnly(bool read_only); + + void AddBoolOption(QMenu* menu, const QString& name, const QString& section, const QString& key); + + void SetOption(const QString& section, const QString& key, const QString& value); + + QTextEdit* m_edit; + + const QString m_path; + + QMap m_keyword_map; +}; diff --git a/Source/Core/DolphinQt/Config/GameConfigHighlighter.cpp b/Source/Core/DolphinQt/Config/GameConfigHighlighter.cpp new file mode 100644 index 000000000000..c04ba2787f35 --- /dev/null +++ b/Source/Core/DolphinQt/Config/GameConfigHighlighter.cpp @@ -0,0 +1,49 @@ +// Copyright 2018 Dolphin Emulator Project +// Licensed under GPLv2+ +// Refer to the license.txt file included. + +#include "DolphinQt/Config/GameConfigHighlighter.h" + +GameConfigHighlighter::GameConfigHighlighter(QTextDocument* parent) : QSyntaxHighlighter(parent) +{ + QTextCharFormat equal_format; + equal_format.setForeground(Qt::red); + + QTextCharFormat section_format; + section_format.setFontWeight(QFont::Bold); + + QTextCharFormat comment_format; + comment_format.setForeground(Qt::green); + comment_format.setFontItalic(true); + + QTextCharFormat const_format; + const_format.setFontWeight(QFont::Bold); + const_format.setForeground(Qt::blue); + + QTextCharFormat num_format; + num_format.setForeground(Qt::darkBlue); + + m_rules.append(HighlightingRule{QRegularExpression(QStringLiteral("=")), equal_format}); + m_rules.append(HighlightingRule{QRegularExpression(QStringLiteral("^\\[.*?\\]")), section_format}); + m_rules.append(HighlightingRule{QRegularExpression(QStringLiteral("\\bTrue\\b")), const_format}); + m_rules.append(HighlightingRule{QRegularExpression(QStringLiteral("\\bFalse\\b")), const_format}); + m_rules.append( + HighlightingRule{QRegularExpression(QStringLiteral("\\b[0-9a-fA-F]+\\b")), num_format}); + + m_rules.append(HighlightingRule{QRegularExpression(QStringLiteral("^#.*")), comment_format}); + m_rules.append(HighlightingRule{QRegularExpression(QStringLiteral("^\\$.*")), comment_format}); + m_rules.append(HighlightingRule{QRegularExpression(QStringLiteral("^\\*.*")), comment_format}); +} + +void GameConfigHighlighter::highlightBlock(const QString& text) +{ + for (const auto& rule : m_rules) + { + auto it = rule.pattern.globalMatch(text); + while (it.hasNext()) + { + auto match = it.next(); + setFormat(match.capturedStart(), match.capturedLength(), rule.format); + } + } +} diff --git a/Source/Core/DolphinQt/Config/GameConfigHighlighter.h b/Source/Core/DolphinQt/Config/GameConfigHighlighter.h new file mode 100644 index 000000000000..c8731ca9785f --- /dev/null +++ b/Source/Core/DolphinQt/Config/GameConfigHighlighter.h @@ -0,0 +1,29 @@ +// Copyright 2018 Dolphin Emulator Project +// Licensed under GPLv2+ +// Refer to the license.txt file included. + +#pragma once + +#include +#include +#include + +class GameConfigHighlighter : public QSyntaxHighlighter +{ + Q_OBJECT + +public: + GameConfigHighlighter(QTextDocument* parent = nullptr); + +protected: + void highlightBlock(const QString& text) override; + +private: + struct HighlightingRule + { + QRegularExpression pattern; + QTextCharFormat format; + }; + + QVector m_rules; +}; diff --git a/Source/Core/DolphinQt/Config/GameConfigWidget.cpp b/Source/Core/DolphinQt/Config/GameConfigWidget.cpp index c626515ce0b4..6308998f05d2 100644 --- a/Source/Core/DolphinQt/Config/GameConfigWidget.cpp +++ b/Source/Core/DolphinQt/Config/GameConfigWidget.cpp @@ -4,18 +4,8 @@ #include "DolphinQt/Config/GameConfigWidget.h" -#include -#include -#include -#include -#include #include -#include -#include -#include -#include -#include -#include +#include #include #include "Common/CommonPaths.h" @@ -24,352 +14,72 @@ #include "Core/ConfigLoaders/GameConfigLoader.h" #include "Core/ConfigManager.h" +#include "DolphinQt/Config/GameConfigEdit.h" #include "DolphinQt/Config/Graphics/GraphicsSlider.h" #include "UICommon/GameFile.h" -constexpr int DETERMINISM_NOT_SET_INDEX = 0; -constexpr int DETERMINISM_AUTO_INDEX = 1; -constexpr int DETERMINISM_NONE_INDEX = 2; -constexpr int DETERMINISM_FAKE_COMPLETION_INDEX = 3; - -constexpr const char* DETERMINISM_NOT_SET_STRING = ""; -constexpr const char* DETERMINISM_AUTO_STRING = "auto"; -constexpr const char* DETERMINISM_NONE_STRING = "none"; -constexpr const char* DETERMINISM_FAKE_COMPLETION_STRING = "fake-completion"; - -GameConfigWidget::GameConfigWidget(const UICommon::GameFile& game) : m_game(game) -{ - m_game_id = m_game.GetGameID(); - m_gameini_local_path = - QString::fromStdString(File::GetUserPath(D_GAMESETTINGS_IDX) + m_game_id + ".ini"); - - CreateWidgets(); - LoadSettings(); - ConnectWidgets(); -} - -void GameConfigWidget::CreateWidgets() +static void PopulateTab(QTabWidget* tab, const std::string& path, std::string game_id, + bool read_only) { - m_refresh_config = new QPushButton(tr("Refresh")); - m_edit_user_config = new QPushButton(tr("Edit User Config")); - m_view_default_config = new QPushButton(tr("View Default Config")); - - // Core - auto* core_box = new QGroupBox(tr("Core")); - auto* core_layout = new QGridLayout; - core_box->setLayout(core_layout); - - m_enable_dual_core = new QCheckBox(tr("Enable Dual Core")); - m_enable_mmu = new QCheckBox(tr("Enable MMU")); - m_enable_fprf = new QCheckBox(tr("Enable FPRF")); - m_sync_gpu = new QCheckBox(tr("Synchronize GPU thread")); - m_enable_fast_disc = new QCheckBox(tr("Speed up Disc Transfer Rate")); - m_use_dsp_hle = new QCheckBox(tr("DSP HLE Emulation (fast)")); - m_deterministic_dual_core = new QComboBox; - - for (const auto& item : {tr("Not Set"), tr("auto"), tr("none"), tr("fake-completion")}) - m_deterministic_dual_core->addItem(item); - - m_enable_mmu->setToolTip(tr( - "Enables the Memory Management Unit, needed for some games. (ON = Compatible, OFF = Fast)")); - - m_enable_fprf->setToolTip(tr("Enables Floating Point Result Flag calculation, needed for a few " - "games. (ON = Compatible, OFF = Fast)")); - m_sync_gpu->setToolTip(tr("Synchronizes the GPU and CPU threads to help prevent random freezes " - "in Dual core mode. (ON = Compatible, OFF = Fast)")); - m_enable_fast_disc->setToolTip(tr("Enable fast disc access. This can cause crashes and other " - "problems in some games. (ON = Fast, OFF = Compatible)")); - - core_layout->addWidget(m_enable_dual_core, 0, 0); - core_layout->addWidget(m_enable_mmu, 1, 0); - core_layout->addWidget(m_enable_fprf, 2, 0); - core_layout->addWidget(m_sync_gpu, 3, 0); - core_layout->addWidget(m_enable_fast_disc, 4, 0); - core_layout->addWidget(m_use_dsp_hle, 5, 0); - core_layout->addWidget(new QLabel(tr("Deterministic dual core:")), 6, 0); - core_layout->addWidget(m_deterministic_dual_core, 6, 1); - - // Stereoscopy - auto* stereoscopy_box = new QGroupBox(tr("Stereoscopy")); - auto* stereoscopy_layout = new QGridLayout; - stereoscopy_box->setLayout(stereoscopy_layout); - - m_depth_slider = new QSlider(Qt::Horizontal); - - m_depth_slider->setMinimum(100); - m_depth_slider->setMaximum(200); - - m_convergence_spin = new QSpinBox; - m_convergence_spin->setMinimum(0); - m_convergence_spin->setMaximum(INT32_MAX); - m_use_monoscopic_shadows = new QCheckBox(tr("Monoscopic Shadows")); - - m_depth_slider->setToolTip( - tr("This value is multiplied with the depth set in the graphics configuration.")); - m_convergence_spin->setToolTip( - tr("This value is added to the convergence value set in the graphics configuration.")); - m_use_monoscopic_shadows->setToolTip( - tr("Use a single depth buffer for both eyes. Needed for a few games.")); - - stereoscopy_layout->addWidget(new QLabel(tr("Depth Percentage:")), 0, 0); - stereoscopy_layout->addWidget(m_depth_slider, 0, 1); - stereoscopy_layout->addWidget(new QLabel(tr("Convergence:")), 1, 0); - stereoscopy_layout->addWidget(m_convergence_spin, 1, 1); - stereoscopy_layout->addWidget(m_use_monoscopic_shadows, 2, 0); - - auto* settings_box = new QGroupBox(tr("Game-Specific Settings")); - auto* settings_layout = new QVBoxLayout; - settings_box->setLayout(settings_layout); - - settings_layout->addWidget( - new QLabel(tr("These settings override core Dolphin settings.\nUndetermined means the game " - "uses Dolphin's setting."))); - settings_layout->addWidget(core_box); - settings_layout->addWidget(stereoscopy_box); - - auto* layout = new QGridLayout; - - layout->addWidget(settings_box, 0, 0, 1, -1); - - auto* button_layout = new QHBoxLayout; - button_layout->setMargin(0); - - layout->addLayout(button_layout, 1, 0, 1, -1); - - button_layout->addWidget(m_refresh_config); - button_layout->addWidget(m_edit_user_config); - button_layout->addWidget(m_view_default_config); - - for (QCheckBox* item : {m_enable_dual_core, m_enable_mmu, m_enable_fprf, m_sync_gpu, - m_enable_fast_disc, m_use_dsp_hle, m_use_monoscopic_shadows}) - item->setTristate(true); - - setLayout(layout); -} - -void GameConfigWidget::ConnectWidgets() -{ - // Buttons - connect(m_refresh_config, &QPushButton::pressed, this, &GameConfigWidget::LoadSettings); - connect(m_edit_user_config, &QPushButton::pressed, this, &GameConfigWidget::EditUserConfig); - connect(m_view_default_config, &QPushButton::pressed, this, &GameConfigWidget::ViewDefaultConfig); - - for (QCheckBox* box : {m_enable_dual_core, m_enable_mmu, m_enable_fprf, m_sync_gpu, - m_enable_fast_disc, m_use_dsp_hle, m_use_monoscopic_shadows}) - connect(box, &QCheckBox::stateChanged, this, &GameConfigWidget::SaveSettings); - - connect(m_deterministic_dual_core, - static_cast(&QComboBox::currentIndexChanged), this, - &GameConfigWidget::SaveSettings); - connect(m_depth_slider, static_cast(&QSlider::valueChanged), this, - &GameConfigWidget::SaveSettings); - connect(m_convergence_spin, static_cast(&QSpinBox::valueChanged), this, - &GameConfigWidget::SaveSettings); -} - -void GameConfigWidget::LoadCheckBox(QCheckBox* checkbox, const std::string& section, - const std::string& key) -{ - bool checked; - - if (m_gameini_local.GetOrCreateSection(section)->Get(key, &checked)) - return checkbox->setCheckState(checked ? Qt::Checked : Qt::Unchecked); - - if (m_gameini_default.GetOrCreateSection(section)->Get(key, &checked)) - return checkbox->setCheckState(checked ? Qt::Checked : Qt::Unchecked); - - checkbox->setCheckState(Qt::PartiallyChecked); -} - -void GameConfigWidget::SaveCheckBox(QCheckBox* checkbox, const std::string& section, - const std::string& key) -{ - // Delete any existing entries from the local gameini if checkbox is undetermined. - // Otherwise, write the current value to the local gameini if the value differs from the default - // gameini values. - // Delete any existing entry from the local gameini if the value does not differ from the default - // gameini value. - - if (checkbox->checkState() == Qt::PartiallyChecked) + while (!game_id.empty()) { - m_gameini_local.DeleteKey(section, key); - return; - } - - bool checked = checkbox->checkState() == Qt::Checked; - - if (m_gameini_default.Exists(section, key)) - { - bool default_value; - m_gameini_default.GetOrCreateSection(section)->Get(key, &default_value); - - if (default_value != checked) - m_gameini_local.GetOrCreateSection(section)->Set(key, checked); - else - m_gameini_local.DeleteKey(section, key); + const std::string ini_path = path + game_id + ".ini"; + if (File::Exists(ini_path)) + { + auto* edit = new GameConfigEdit(nullptr, QString::fromStdString(path + game_id + ".ini")); + edit->setReadOnly(read_only); + tab->addTab(edit, QString::fromStdString(game_id)); + } - return; + game_id = game_id.substr(0, game_id.size() - 1); } - - m_gameini_local.GetOrCreateSection(section)->Set(key, checked); } -void GameConfigWidget::LoadSettings() +GameConfigWidget::GameConfigWidget(const UICommon::GameFile& game) : m_game(game) { - // Reload config - m_gameini_local = SConfig::LoadLocalGameIni(m_game_id, m_game.GetRevision()); - m_gameini_default = SConfig::LoadDefaultGameIni(m_game_id, m_game.GetRevision()); - - // Load game-specific settings - - // Core - LoadCheckBox(m_enable_dual_core, "Core", "CPUThread"); - LoadCheckBox(m_enable_mmu, "Core", "MMU"); - LoadCheckBox(m_enable_fprf, "Core", "FPRF"); - LoadCheckBox(m_sync_gpu, "Core", "SyncGPU"); - LoadCheckBox(m_enable_fast_disc, "Core", "FastDiscSpeed"); - LoadCheckBox(m_use_dsp_hle, "Core", "DSPHLE"); - - std::string determinism_mode; + m_game_id = m_game.GetGameID(); - int determinism_index = DETERMINISM_NOT_SET_INDEX; + CreateWidgets(); + ConnectWidgets(); - m_gameini_default.GetIfExists("Core", "GPUDeterminismMode", &determinism_mode); - m_gameini_local.GetIfExists("Core", "GPUDeterminismMode", &determinism_mode); + PopulateTab(m_default_tab, File::GetSysDirectory() + "GameSettings/", m_game_id, true); + PopulateTab(m_local_tab, File::GetUserPath(D_GAMESETTINGS_IDX), m_game_id, false); - if (determinism_mode == DETERMINISM_AUTO_STRING) - { - determinism_index = DETERMINISM_AUTO_INDEX; - } - else if (determinism_mode == DETERMINISM_NONE_STRING) + // Always give the user the opportunity to create a new INI + if (m_local_tab->count() == 0) { - determinism_index = DETERMINISM_NONE_INDEX; + auto* edit = + new GameConfigEdit(nullptr, QString::fromStdString(File::GetUserPath(D_GAMESETTINGS_IDX) + + m_game_id + ".ini")); + m_local_tab->addTab(edit, QString::fromStdString(m_game_id)); } - else if (determinism_mode == DETERMINISM_FAKE_COMPLETION_STRING) - { - determinism_index = DETERMINISM_FAKE_COMPLETION_INDEX; - } - - m_deterministic_dual_core->setCurrentIndex(determinism_index); - - // Stereoscopy - int depth_percentage = 100; - - m_gameini_default.GetIfExists("Video_Stereoscopy", "StereoDepthPercentage", &depth_percentage); - m_gameini_local.GetIfExists("Video_Stereoscopy", "StereoDepthPercentage", &depth_percentage); - - m_depth_slider->setValue(depth_percentage); - - int convergence = 0; - - m_gameini_default.GetIfExists("Video_Stereoscopy", "StereoConvergence", &convergence); - m_gameini_local.GetIfExists("Video_Stereoscopy", "StereoConvergence", &convergence); - - m_convergence_spin->setValue(convergence); - - LoadCheckBox(m_use_monoscopic_shadows, "Video_Stereoscopy", "StereoEFBMonoDepth"); } -void GameConfigWidget::SaveSettings() +void GameConfigWidget::CreateWidgets() { - // Core - SaveCheckBox(m_enable_dual_core, "Core", "CPUThread"); - SaveCheckBox(m_enable_mmu, "Core", "MMU"); - SaveCheckBox(m_enable_fprf, "Core", "FPRF"); - SaveCheckBox(m_sync_gpu, "Core", "SyncGPU"); - SaveCheckBox(m_enable_fast_disc, "Core", "FastDiscSpeed"); - SaveCheckBox(m_use_dsp_hle, "Core", "DSPHLE"); - - int determinism_num = m_deterministic_dual_core->currentIndex(); - - std::string determinism_mode = DETERMINISM_NOT_SET_STRING; - - switch (determinism_num) - { - case DETERMINISM_AUTO_INDEX: - determinism_mode = DETERMINISM_AUTO_STRING; - break; - case DETERMINISM_NONE_INDEX: - determinism_mode = DETERMINISM_NONE_STRING; - break; - case DETERMINISM_FAKE_COMPLETION_INDEX: - determinism_mode = DETERMINISM_FAKE_COMPLETION_STRING; - break; - } + auto* layout = new QVBoxLayout; - if (determinism_mode != DETERMINISM_NOT_SET_STRING) - { - std::string default_mode = DETERMINISM_NOT_SET_STRING; - if (!(m_gameini_default.GetIfExists("Core", "GPUDeterminismMode", &default_mode) && - default_mode == determinism_mode)) - { - m_gameini_local.GetOrCreateSection("Core")->Set("GPUDeterminismMode", determinism_mode); - } - } - else - { - m_gameini_local.DeleteKey("Core", "GPUDeterminismMode"); - } + auto* default_group = new QGroupBox(tr("Default Config (Read Only)")); + auto* default_layout = new QVBoxLayout; + m_default_tab = new QTabWidget; - // Stereoscopy - int depth_percentage = m_depth_slider->value(); + default_group->setLayout(default_layout); + default_layout->addWidget(m_default_tab); - if (depth_percentage != 100) - { - int default_value = 0; - if (!(m_gameini_default.GetIfExists("Video_Stereoscopy", "StereoDepthPercentage", - &default_value) && - default_value == depth_percentage)) - { - m_gameini_local.GetOrCreateSection("Video_Stereoscopy") - ->Set("StereoDepthPercentage", depth_percentage); - } - } + auto* local_group = new QGroupBox(tr("User Config")); + auto* local_layout = new QVBoxLayout; + m_local_tab = new QTabWidget; - int convergence = m_convergence_spin->value(); - if (convergence != 0) - { - int default_value = 0; - if (!(m_gameini_default.GetIfExists("Video_Stereoscopy", "StereoConvergence", &default_value) && - default_value == convergence)) - { - m_gameini_local.GetOrCreateSection("Video_Stereoscopy") - ->Set("StereoConvergence", convergence); - } - } + local_group->setLayout(local_layout); + local_layout->addWidget(m_local_tab); - SaveCheckBox(m_use_monoscopic_shadows, "Video_Stereoscopy", "StereoEFBMonoDepth"); + layout->addWidget(default_group); + layout->addWidget(local_group); - bool success = m_gameini_local.Save(m_gameini_local_path.toStdString()); - - // If the resulting file is empty, delete it. Kind of a hack, but meh. - if (success && File::GetSize(m_gameini_local_path.toStdString()) == 0) - File::Delete(m_gameini_local_path.toStdString()); -} - -void GameConfigWidget::EditUserConfig() -{ - QFile file(m_gameini_local_path); - - if (!file.exists()) - { - file.open(QIODevice::WriteOnly); - file.close(); - } - - QDesktopServices::openUrl(QUrl::fromLocalFile(m_gameini_local_path)); + setLayout(layout); } -void GameConfigWidget::ViewDefaultConfig() +void GameConfigWidget::ConnectWidgets() { - for (const std::string& filename : - ConfigLoaders::GetGameIniFilenames(m_game_id, m_game.GetRevision())) - { - QString path = - QString::fromStdString(File::GetSysDirectory() + GAMESETTINGS_DIR DIR_SEP + filename); - - if (QFile(path).exists()) - QDesktopServices::openUrl(QUrl::fromLocalFile(path)); - } } diff --git a/Source/Core/DolphinQt/Config/GameConfigWidget.h b/Source/Core/DolphinQt/Config/GameConfigWidget.h index bb1c58d8030f..062f32046a2b 100644 --- a/Source/Core/DolphinQt/Config/GameConfigWidget.h +++ b/Source/Core/DolphinQt/Config/GameConfigWidget.h @@ -16,14 +16,7 @@ namespace UICommon class GameFile; } -class QCheckBox; -class QComboBox; -class QGroupBox; -class QLineEdit; -class QPushButton; -class QSlider; -class QSpinBox; -class QVBoxLayout; +class QTabWidget; class GameConfigWidget : public QWidget { @@ -34,37 +27,12 @@ class GameConfigWidget : public QWidget private: void CreateWidgets(); void ConnectWidgets(); - void LoadSettings(); - void SaveSettings(); - - void EditUserConfig(); - void ViewDefaultConfig(); - - void LoadCheckBox(QCheckBox* checkbox, const std::string& section, const std::string& key); - void SaveCheckBox(QCheckBox* checkbox, const std::string& section, const std::string& key); - - QPushButton* m_refresh_config; - QPushButton* m_edit_user_config; - QPushButton* m_view_default_config; - - // Core - QCheckBox* m_enable_dual_core; - QCheckBox* m_enable_mmu; - QCheckBox* m_enable_fprf; - QCheckBox* m_sync_gpu; - QCheckBox* m_enable_fast_disc; - QCheckBox* m_use_dsp_hle; - QComboBox* m_deterministic_dual_core; - - // Stereoscopy - QSlider* m_depth_slider; - QSpinBox* m_convergence_spin; - QCheckBox* m_use_monoscopic_shadows; + QString m_gameini_sys_path; QString m_gameini_local_path; - IniFile m_gameini_local; - IniFile m_gameini_default; + QTabWidget* m_default_tab; + QTabWidget* m_local_tab; const UICommon::GameFile& m_game; std::string m_game_id; diff --git a/Source/Core/DolphinQt/DolphinQt.vcxproj b/Source/Core/DolphinQt/DolphinQt.vcxproj index a1ddc418e935..5a6143809005 100644 --- a/Source/Core/DolphinQt/DolphinQt.vcxproj +++ b/Source/Core/DolphinQt/DolphinQt.vcxproj @@ -63,6 +63,8 @@ + + @@ -185,6 +187,8 @@ + + @@ -265,6 +269,8 @@ + +