summaryrefslogtreecommitdiffstats
path: root/src/citra_qt
diff options
context:
space:
mode:
Diffstat (limited to 'src/citra_qt')
-rw-r--r--src/citra_qt/CMakeLists.txt18
-rw-r--r--src/citra_qt/bootmanager.cpp2
-rw-r--r--src/citra_qt/config.cpp91
-rw-r--r--src/citra_qt/configure.ui97
-rw-r--r--src/citra_qt/configure_debug.cpp31
-rw-r--r--src/citra_qt/configure_debug.h29
-rw-r--r--src/citra_qt/configure_debug.ui102
-rw-r--r--src/citra_qt/configure_dialog.cpp29
-rw-r--r--src/citra_qt/configure_dialog.h29
-rw-r--r--src/citra_qt/configure_general.cpp39
-rw-r--r--src/citra_qt/configure_general.h29
-rw-r--r--src/citra_qt/configure_general.ui173
-rw-r--r--src/citra_qt/debugger/graphics_breakpoints.cpp6
-rw-r--r--src/citra_qt/debugger/graphics_framebuffer.cpp6
-rw-r--r--src/citra_qt/debugger/graphics_tracing.cpp4
-rw-r--r--src/citra_qt/debugger/graphics_vertex_shader.cpp4
-rw-r--r--src/citra_qt/debugger/profiler.cpp39
-rw-r--r--src/citra_qt/debugger/profiler.h3
-rw-r--r--src/citra_qt/game_list.cpp29
-rw-r--r--src/citra_qt/game_list.h6
-rw-r--r--src/citra_qt/game_list_p.h106
-rw-r--r--src/citra_qt/hotkeys.cpp54
-rw-r--r--src/citra_qt/hotkeys.h8
-rw-r--r--src/citra_qt/hotkeys.ui47
-rw-r--r--src/citra_qt/main.cpp185
-rw-r--r--src/citra_qt/main.h8
-rw-r--r--src/citra_qt/main.ui51
-rw-r--r--src/citra_qt/ui_settings.cpp11
-rw-r--r--src/citra_qt/ui_settings.h47
29 files changed, 968 insertions, 315 deletions
diff --git a/src/citra_qt/CMakeLists.txt b/src/citra_qt/CMakeLists.txt
index 9b3eb2cd6..3f0099200 100644
--- a/src/citra_qt/CMakeLists.txt
+++ b/src/citra_qt/CMakeLists.txt
@@ -17,12 +17,16 @@ set(SRCS
debugger/profiler.cpp
debugger/ramview.cpp
debugger/registers.cpp
- game_list.cpp
util/spinbox.cpp
util/util.cpp
bootmanager.cpp
+ configure_debug.cpp
+ configure_dialog.cpp
+ configure_general.cpp
+ game_list.cpp
hotkeys.cpp
main.cpp
+ ui_settings.cpp
citra-qt.rc
Info.plist
)
@@ -44,12 +48,17 @@ set(HEADERS
debugger/profiler.h
debugger/ramview.h
debugger/registers.h
- game_list.h
util/spinbox.h
util/util.h
bootmanager.h
+ configure_debug.h
+ configure_dialog.h
+ configure_general.h
+ game_list.h
+ game_list_p.h
hotkeys.h
main.h
+ ui_settings.h
version.h
)
@@ -59,6 +68,9 @@ set(UIS
debugger/disassembler.ui
debugger/profiler.ui
debugger/registers.ui
+ configure.ui
+ configure_debug.ui
+ configure_general.ui
hotkeys.ui
main.ui
)
@@ -81,7 +93,7 @@ else()
endif()
target_link_libraries(citra-qt core video_core audio_core common qhexedit)
target_link_libraries(citra-qt ${OPENGL_gl_LIBRARY} ${CITRA_QT_LIBS})
-target_link_libraries(citra-qt ${PLATFORM_LIBRARIES})
+target_link_libraries(citra-qt ${PLATFORM_LIBRARIES} Threads::Threads)
if(${CMAKE_SYSTEM_NAME} MATCHES "Linux|FreeBSD|OpenBSD|NetBSD")
install(TARGETS citra-qt RUNTIME DESTINATION "${CMAKE_INSTALL_PREFIX}/bin")
diff --git a/src/citra_qt/bootmanager.cpp b/src/citra_qt/bootmanager.cpp
index 8e60b9cad..01b81c11c 100644
--- a/src/citra_qt/bootmanager.cpp
+++ b/src/citra_qt/bootmanager.cpp
@@ -71,7 +71,9 @@ void EmuThread::run() {
// Shutdown the core emulation
System::Shutdown();
+#if MICROPROFILE_ENABLED
MicroProfileOnThreadExit();
+#endif
render_window->moveContext();
}
diff --git a/src/citra_qt/config.cpp b/src/citra_qt/config.cpp
index 8e247ff5c..b5bb75537 100644
--- a/src/citra_qt/config.cpp
+++ b/src/citra_qt/config.cpp
@@ -7,12 +7,12 @@
#include <QStringList>
#include "citra_qt/config.h"
+#include "citra_qt/ui_settings.h"
#include "common/file_util.h"
#include "core/settings.h"
Config::Config() {
-
// TODO: Don't hardcode the path; let the frontend decide where to put the config files.
qt_config_loc = FileUtil::GetUserPath(D_CONFIG_IDX) + "qt-config.ini";
FileUtil::CreateFullPath(qt_config_loc);
@@ -45,12 +45,17 @@ void Config::ReadValues() {
qt_config->beginGroup("Renderer");
Settings::values.use_hw_renderer = qt_config->value("use_hw_renderer", false).toBool();
Settings::values.use_shader_jit = qt_config->value("use_shader_jit", true).toBool();
+ Settings::values.use_scaled_resolution = qt_config->value("use_scaled_resolution", false).toBool();
Settings::values.bg_red = qt_config->value("bg_red", 1.0).toFloat();
Settings::values.bg_green = qt_config->value("bg_green", 1.0).toFloat();
Settings::values.bg_blue = qt_config->value("bg_blue", 1.0).toFloat();
qt_config->endGroup();
+ qt_config->beginGroup("Audio");
+ Settings::values.sink_id = qt_config->value("output_engine", "auto").toString().toStdString();
+ qt_config->endGroup();
+
qt_config->beginGroup("Data Storage");
Settings::values.use_virtual_sd = qt_config->value("use_virtual_sd", true).toBool();
qt_config->endGroup();
@@ -67,6 +72,51 @@ void Config::ReadValues() {
Settings::values.use_gdbstub = qt_config->value("use_gdbstub", false).toBool();
Settings::values.gdbstub_port = qt_config->value("gdbstub_port", 24689).toInt();
qt_config->endGroup();
+
+ qt_config->beginGroup("UI");
+
+ qt_config->beginGroup("UILayout");
+ UISettings::values.geometry = qt_config->value("geometry").toByteArray();
+ UISettings::values.state = qt_config->value("state").toByteArray();
+ UISettings::values.renderwindow_geometry = qt_config->value("geometryRenderWindow").toByteArray();
+ UISettings::values.gamelist_header_state = qt_config->value("gameListHeaderState").toByteArray();
+ UISettings::values.microprofile_geometry = qt_config->value("microProfileDialogGeometry").toByteArray();
+ UISettings::values.microprofile_visible = qt_config->value("microProfileDialogVisible", false).toBool();
+ qt_config->endGroup();
+
+ qt_config->beginGroup("Paths");
+ UISettings::values.roms_path = qt_config->value("romsPath").toString();
+ UISettings::values.symbols_path = qt_config->value("symbolsPath").toString();
+ UISettings::values.gamedir = qt_config->value("gameListRootDir", ".").toString();
+ UISettings::values.gamedir_deepscan = qt_config->value("gameListDeepScan", false).toBool();
+ UISettings::values.recent_files = qt_config->value("recentFiles").toStringList();
+ qt_config->endGroup();
+
+ qt_config->beginGroup("Shortcuts");
+ QStringList groups = qt_config->childGroups();
+ for (auto group : groups) {
+ qt_config->beginGroup(group);
+
+ QStringList hotkeys = qt_config->childGroups();
+ for (auto hotkey : hotkeys) {
+ qt_config->beginGroup(hotkey);
+ UISettings::values.shortcuts.emplace_back(
+ UISettings::Shortcut(group + "/" + hotkey,
+ UISettings::ContextualShortcut(qt_config->value("KeySeq").toString(),
+ qt_config->value("Context").toInt())));
+ qt_config->endGroup();
+ }
+
+ qt_config->endGroup();
+ }
+ qt_config->endGroup();
+
+ UISettings::values.single_window_mode = qt_config->value("singleWindowMode", true).toBool();
+ UISettings::values.display_titlebar = qt_config->value("displayTitleBars", true).toBool();
+ UISettings::values.confirm_before_closing = qt_config->value("confirmClose",true).toBool();
+ UISettings::values.first_start = qt_config->value("firstStart", true).toBool();
+
+ qt_config->endGroup();
}
void Config::SaveValues() {
@@ -84,6 +134,7 @@ void Config::SaveValues() {
qt_config->beginGroup("Renderer");
qt_config->setValue("use_hw_renderer", Settings::values.use_hw_renderer);
qt_config->setValue("use_shader_jit", Settings::values.use_shader_jit);
+ qt_config->setValue("use_scaled_resolution", Settings::values.use_scaled_resolution);
// Cast to double because Qt's written float values are not human-readable
qt_config->setValue("bg_red", (double)Settings::values.bg_red);
@@ -91,6 +142,10 @@ void Config::SaveValues() {
qt_config->setValue("bg_blue", (double)Settings::values.bg_blue);
qt_config->endGroup();
+ qt_config->beginGroup("Audio");
+ qt_config->setValue("output_engine", QString::fromStdString(Settings::values.sink_id));
+ qt_config->endGroup();
+
qt_config->beginGroup("Data Storage");
qt_config->setValue("use_virtual_sd", Settings::values.use_virtual_sd);
qt_config->endGroup();
@@ -107,10 +162,44 @@ void Config::SaveValues() {
qt_config->setValue("use_gdbstub", Settings::values.use_gdbstub);
qt_config->setValue("gdbstub_port", Settings::values.gdbstub_port);
qt_config->endGroup();
+
+ qt_config->beginGroup("UI");
+
+ qt_config->beginGroup("UILayout");
+ qt_config->setValue("geometry", UISettings::values.geometry);
+ qt_config->setValue("state", UISettings::values.state);
+ qt_config->setValue("geometryRenderWindow", UISettings::values.renderwindow_geometry);
+ qt_config->setValue("gameListHeaderState", UISettings::values.gamelist_header_state);
+ qt_config->setValue("microProfileDialogGeometry", UISettings::values.microprofile_geometry);
+ qt_config->setValue("microProfileDialogVisible", UISettings::values.microprofile_visible);
+ qt_config->endGroup();
+
+ qt_config->beginGroup("Paths");
+ qt_config->setValue("romsPath", UISettings::values.roms_path);
+ qt_config->setValue("symbolsPath", UISettings::values.symbols_path);
+ qt_config->setValue("gameListRootDir", UISettings::values.gamedir);
+ qt_config->setValue("gameListDeepScan", UISettings::values.gamedir_deepscan);
+ qt_config->setValue("recentFiles", UISettings::values.recent_files);
+ qt_config->endGroup();
+
+ qt_config->beginGroup("Shortcuts");
+ for (auto shortcut : UISettings::values.shortcuts ) {
+ qt_config->setValue(shortcut.first + "/KeySeq", shortcut.second.first);
+ qt_config->setValue(shortcut.first + "/Context", shortcut.second.second);
+ }
+ qt_config->endGroup();
+
+ qt_config->setValue("singleWindowMode", UISettings::values.single_window_mode);
+ qt_config->setValue("displayTitleBars", UISettings::values.display_titlebar);
+ qt_config->setValue("confirmClose", UISettings::values.confirm_before_closing);
+ qt_config->setValue("firstStart", UISettings::values.first_start);
+
+ qt_config->endGroup();
}
void Config::Reload() {
ReadValues();
+ Settings::Apply();
}
void Config::Save() {
diff --git a/src/citra_qt/configure.ui b/src/citra_qt/configure.ui
new file mode 100644
index 000000000..6ae056ff9
--- /dev/null
+++ b/src/citra_qt/configure.ui
@@ -0,0 +1,97 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<ui version="4.0">
+ <class>ConfigureDialog</class>
+ <widget class="QDialog" name="ConfigureDialog">
+ <property name="geometry">
+ <rect>
+ <x>0</x>
+ <y>0</y>
+ <width>441</width>
+ <height>501</height>
+ </rect>
+ </property>
+ <property name="windowTitle">
+ <string>Citra Configuration</string>
+ </property>
+ <layout class="QVBoxLayout" name="verticalLayout">
+ <item>
+ <widget class="QTabWidget" name="tabWidget">
+ <property name="currentIndex">
+ <number>0</number>
+ </property>
+ <widget class="ConfigureGeneral" name="generalTab">
+ <attribute name="title">
+ <string>General</string>
+ </attribute>
+ </widget>
+ <widget class="QWidget" name="inputTab">
+ <attribute name="title">
+ <string>Input</string>
+ </attribute>
+ </widget>
+ <widget class="ConfigureDebug" name="debugTab">
+ <attribute name="title">
+ <string>Debug</string>
+ </attribute>
+ </widget>
+ </widget>
+ </item>
+ <item>
+ <widget class="QDialogButtonBox" name="buttonBox">
+ <property name="standardButtons">
+ <set>QDialogButtonBox::Cancel|QDialogButtonBox::Ok</set>
+ </property>
+ </widget>
+ </item>
+ </layout>
+ </widget>
+ <customwidgets>
+ <customwidget>
+ <class>ConfigureGeneral</class>
+ <extends>QWidget</extends>
+ <header>configure_general.h</header>
+ <container>1</container>
+ </customwidget>
+ <customwidget>
+ <class>ConfigureDebug</class>
+ <extends>QWidget</extends>
+ <header>configure_debug.h</header>
+ <container>1</container>
+ </customwidget>
+ </customwidgets>
+ <resources/>
+ <connections>
+ <connection>
+ <sender>buttonBox</sender>
+ <signal>accepted()</signal>
+ <receiver>ConfigureDialog</receiver>
+ <slot>accept()</slot>
+ <hints>
+ <hint type="sourcelabel">
+ <x>220</x>
+ <y>380</y>
+ </hint>
+ <hint type="destinationlabel">
+ <x>220</x>
+ <y>200</y>
+ </hint>
+ </hints>
+ </connection>
+ <connection>
+ <sender>buttonBox</sender>
+ <signal>rejected()</signal>
+ <receiver>ConfigureDialog</receiver>
+ <slot>reject()</slot>
+ <hints>
+ <hint type="sourcelabel">
+ <x>220</x>
+ <y>380</y>
+ </hint>
+ <hint type="destinationlabel">
+ <x>220</x>
+ <y>200</y>
+ </hint>
+ </hints>
+ </connection>
+ </connections>
+</ui>
diff --git a/src/citra_qt/configure_debug.cpp b/src/citra_qt/configure_debug.cpp
new file mode 100644
index 000000000..dc3d7b906
--- /dev/null
+++ b/src/citra_qt/configure_debug.cpp
@@ -0,0 +1,31 @@
+// Copyright 2016 Citra Emulator Project
+// Licensed under GPLv2 or any later version
+// Refer to the license.txt file included.
+
+#include "citra_qt/configure_debug.h"
+#include "ui_configure_debug.h"
+
+#include "core/settings.h"
+
+ConfigureDebug::ConfigureDebug(QWidget *parent) :
+ QWidget(parent),
+ ui(new Ui::ConfigureDebug)
+{
+ ui->setupUi(this);
+ this->setConfiguration();
+}
+
+ConfigureDebug::~ConfigureDebug() {
+}
+
+void ConfigureDebug::setConfiguration() {
+ ui->toogle_gdbstub->setChecked(Settings::values.use_gdbstub);
+ ui->gdbport_spinbox->setEnabled(Settings::values.use_gdbstub);
+ ui->gdbport_spinbox->setValue(Settings::values.gdbstub_port);
+}
+
+void ConfigureDebug::applyConfiguration() {
+ Settings::values.use_gdbstub = ui->toogle_gdbstub->isChecked();
+ Settings::values.gdbstub_port = ui->gdbport_spinbox->value();
+ Settings::Apply();
+}
diff --git a/src/citra_qt/configure_debug.h b/src/citra_qt/configure_debug.h
new file mode 100644
index 000000000..ab58ebbdc
--- /dev/null
+++ b/src/citra_qt/configure_debug.h
@@ -0,0 +1,29 @@
+// Copyright 2016 Citra Emulator Project
+// Licensed under GPLv2 or any later version
+// Refer to the license.txt file included.
+
+#pragma once
+
+#include <memory>
+#include <QWidget>
+
+namespace Ui {
+class ConfigureDebug;
+}
+
+class ConfigureDebug : public QWidget
+{
+ Q_OBJECT
+
+public:
+ explicit ConfigureDebug(QWidget *parent = nullptr);
+ ~ConfigureDebug();
+
+ void applyConfiguration();
+
+private:
+ void setConfiguration();
+
+private:
+ std::unique_ptr<Ui::ConfigureDebug> ui;
+};
diff --git a/src/citra_qt/configure_debug.ui b/src/citra_qt/configure_debug.ui
new file mode 100644
index 000000000..3ba7f44da
--- /dev/null
+++ b/src/citra_qt/configure_debug.ui
@@ -0,0 +1,102 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<ui version="4.0">
+ <class>ConfigureDebug</class>
+ <widget class="QWidget" name="ConfigureDebug">
+ <property name="geometry">
+ <rect>
+ <x>0</x>
+ <y>0</y>
+ <width>400</width>
+ <height>300</height>
+ </rect>
+ </property>
+ <property name="windowTitle">
+ <string>Form</string>
+ </property>
+ <layout class="QVBoxLayout" name="verticalLayout">
+ <item>
+ <layout class="QVBoxLayout" name="verticalLayout_3">
+ <item>
+ <widget class="QGroupBox" name="groupBox">
+ <property name="title">
+ <string>GDB</string>
+ </property>
+ <layout class="QVBoxLayout" name="verticalLayout_2">
+ <item>
+ <layout class="QHBoxLayout" name="horizontalLayout_3">
+ <item>
+ <widget class="QCheckBox" name="toogle_gdbstub">
+ <property name="text">
+ <string>Enable GDB Stub</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="QLabel" name="label">
+ <property name="text">
+ <string>Port:</string>
+ </property>
+ </widget>
+ </item>
+ <item>
+ <widget class="QSpinBox" name="gdbport_spinbox">
+ <property name="maximum">
+ <number>65536</number>
+ </property>
+ </widget>
+ </item>
+ </layout>
+ </item>
+ </layout>
+ </widget>
+ </item>
+ </layout>
+ </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>
+ <resources/>
+ <connections>
+ <connection>
+ <sender>toogle_gdbstub</sender>
+ <signal>toggled(bool)</signal>
+ <receiver>gdbport_spinbox</receiver>
+ <slot>setEnabled(bool)</slot>
+ <hints>
+ <hint type="sourcelabel">
+ <x>84</x>
+ <y>157</y>
+ </hint>
+ <hint type="destinationlabel">
+ <x>342</x>
+ <y>158</y>
+ </hint>
+ </hints>
+ </connection>
+ </connections>
+</ui>
diff --git a/src/citra_qt/configure_dialog.cpp b/src/citra_qt/configure_dialog.cpp
new file mode 100644
index 000000000..87c26c715
--- /dev/null
+++ b/src/citra_qt/configure_dialog.cpp
@@ -0,0 +1,29 @@
+// Copyright 2016 Citra Emulator Project
+// Licensed under GPLv2 or any later version
+// Refer to the license.txt file included.
+
+#include "citra_qt/config.h"
+#include "citra_qt/configure_dialog.h"
+#include "ui_configure.h"
+
+
+#include "core/settings.h"
+
+ConfigureDialog::ConfigureDialog(QWidget *parent) :
+ QDialog(parent),
+ ui(new Ui::ConfigureDialog)
+{
+ ui->setupUi(this);
+ this->setConfiguration();
+}
+
+ConfigureDialog::~ConfigureDialog() {
+}
+
+void ConfigureDialog::setConfiguration() {
+}
+
+void ConfigureDialog::applyConfiguration() {
+ ui->generalTab->applyConfiguration();
+ ui->debugTab->applyConfiguration();
+}
diff --git a/src/citra_qt/configure_dialog.h b/src/citra_qt/configure_dialog.h
new file mode 100644
index 000000000..89020eeb4
--- /dev/null
+++ b/src/citra_qt/configure_dialog.h
@@ -0,0 +1,29 @@
+// Copyright 2016 Citra Emulator Project
+// Licensed under GPLv2 or any later version
+// Refer to the license.txt file included.
+
+#pragma once
+
+#include <memory>
+#include <QDialog>
+
+namespace Ui {
+class ConfigureDialog;
+}
+
+class ConfigureDialog : public QDialog
+{
+ Q_OBJECT
+
+public:
+ explicit ConfigureDialog(QWidget *parent = nullptr);
+ ~ConfigureDialog();
+
+ void applyConfiguration();
+
+private:
+ void setConfiguration();
+
+private:
+ std::unique_ptr<Ui::ConfigureDialog> ui;
+};
diff --git a/src/citra_qt/configure_general.cpp b/src/citra_qt/configure_general.cpp
new file mode 100644
index 000000000..62648e665
--- /dev/null
+++ b/src/citra_qt/configure_general.cpp
@@ -0,0 +1,39 @@
+// Copyright 2016 Citra Emulator Project
+// Licensed under GPLv2 or any later version
+// Refer to the license.txt file included.
+
+#include "citra_qt/configure_general.h"
+#include "citra_qt/ui_settings.h"
+#include "ui_configure_general.h"
+
+#include "core/settings.h"
+
+ConfigureGeneral::ConfigureGeneral(QWidget *parent) :
+ QWidget(parent),
+ ui(new Ui::ConfigureGeneral)
+{
+ ui->setupUi(this);
+ this->setConfiguration();
+}
+
+ConfigureGeneral::~ConfigureGeneral() {
+}
+
+void ConfigureGeneral::setConfiguration() {
+ ui->toogle_deepscan->setChecked(UISettings::values.gamedir_deepscan);
+ ui->toogle_check_exit->setChecked(UISettings::values.confirm_before_closing);
+ ui->region_combobox->setCurrentIndex(Settings::values.region_value);
+ ui->toogle_hw_renderer->setChecked(Settings::values.use_hw_renderer);
+ ui->toogle_shader_jit->setChecked(Settings::values.use_shader_jit);
+ ui->toogle_scaled_resolution->setChecked(Settings::values.use_scaled_resolution);
+}
+
+void ConfigureGeneral::applyConfiguration() {
+ UISettings::values.gamedir_deepscan = ui->toogle_deepscan->isChecked();
+ UISettings::values.confirm_before_closing = ui->toogle_check_exit->isChecked();
+ Settings::values.region_value = ui->region_combobox->currentIndex();
+ Settings::values.use_hw_renderer = ui->toogle_hw_renderer->isChecked();
+ Settings::values.use_shader_jit = ui->toogle_shader_jit->isChecked();
+ Settings::values.use_scaled_resolution = ui->toogle_scaled_resolution->isChecked();
+ Settings::Apply();
+}
diff --git a/src/citra_qt/configure_general.h b/src/citra_qt/configure_general.h
new file mode 100644
index 000000000..a6c68e62d
--- /dev/null
+++ b/src/citra_qt/configure_general.h
@@ -0,0 +1,29 @@
+// Copyright 2016 Citra Emulator Project
+// Licensed under GPLv2 or any later version
+// Refer to the license.txt file included.
+
+#pragma once
+
+#include <memory>
+#include <QWidget>
+
+namespace Ui {
+class ConfigureGeneral;
+}
+
+class ConfigureGeneral : public QWidget
+{
+ Q_OBJECT
+
+public:
+ explicit ConfigureGeneral(QWidget *parent = nullptr);
+ ~ConfigureGeneral();
+
+ void applyConfiguration();
+
+private:
+ void setConfiguration();
+
+private:
+ std::unique_ptr<Ui::ConfigureGeneral> ui;
+};
diff --git a/src/citra_qt/configure_general.ui b/src/citra_qt/configure_general.ui
new file mode 100644
index 000000000..5eb309793
--- /dev/null
+++ b/src/citra_qt/configure_general.ui
@@ -0,0 +1,173 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<ui version="4.0">
+ <class>ConfigureGeneral</class>
+ <widget class="QWidget" name="ConfigureGeneral">
+ <property name="geometry">
+ <rect>
+ <x>0</x>
+ <y>0</y>
+ <width>300</width>
+ <height>377</height>
+ </rect>
+ </property>
+ <property name="windowTitle">
+ <string>Form</string>
+ </property>
+ <layout class="QHBoxLayout" name="horizontalLayout">
+ <item>
+ <layout class="QVBoxLayout" name="verticalLayout">
+ <item>
+ <widget class="QGroupBox" name="groupBox">
+ <property name="title">
+ <string>General</string>
+ </property>
+ <layout class="QHBoxLayout" name="horizontalLayout_3">
+ <item>
+ <layout class="QVBoxLayout" name="verticalLayout_2">
+ <item>
+ <widget class="QCheckBox" name="toogle_deepscan">
+ <property name="text">
+ <string>Recursive scan for game folder</string>
+ </property>
+ </widget>
+ </item>
+ <item>
+ <widget class="QCheckBox" name="toogle_check_exit">
+ <property name="text">
+ <string>Confirm exit while emulation is running</string>
+ </property>
+ </widget>
+ </item>
+ </layout>
+ </item>
+ </layout>
+ </widget>
+ </item>
+ <item>
+ <widget class="QGroupBox" name="groupBox_4">
+ <property name="title">
+ <string>Emulation</string>
+ </property>
+ <layout class="QHBoxLayout" name="horizontalLayout_5">
+ <item>
+ <layout class="QVBoxLayout" name="verticalLayout_6">
+ <item>
+ <layout class="QHBoxLayout" name="horizontalLayout_6">
+ <item>
+ <widget class="QLabel" name="label">
+ <property name="text">
+ <string>Region:</string>
+ </property>
+ </widget>
+ </item>
+ <item>
+ <widget class="QComboBox" name="region_combobox">
+ <item>
+ <property name="text">
+ <string notr="true">JPN</string>
+ </property>
+ </item>
+ <item>
+ <property name="text">
+ <string notr="true">USA</string>
+ </property>
+ </item>
+ <item>
+ <property name="text">
+ <string notr="true">EUR</string>
+ </property>
+ </item>
+ <item>
+ <property name="text">
+ <string notr="true">AUS</string>
+ </property>
+ </item>
+ <item>
+ <property name="text">
+ <string notr="true">CHN</string>
+ </property>
+ </item>
+ <item>
+ <property name="text">
+ <string notr="true">KOR</string>
+ </property>
+ </item>
+ <item>
+ <property name="text">
+ <string notr="true">TWN</string>
+ </property>
+ </item>
+ </widget>
+ </item>
+ </layout>
+ </item>
+ </layout>
+ </item>
+ </layout>
+ </widget>
+ </item>
+ <item>
+ <widget class="QGroupBox" name="groupBox_2">
+ <property name="title">
+ <string>Performance</string>
+ </property>
+ <layout class="QHBoxLayout" name="horizontalLayout_2">
+ <item>
+ <layout class="QVBoxLayout" name="verticalLayout_3">
+ <item>
+ <widget class="QCheckBox" name="toogle_hw_renderer">
+ <property name="text">
+ <string>Enable hardware renderer</string>
+ </property>
+ </widget>
+ </item>
+ <item>
+ <widget class="QCheckBox" name="toogle_shader_jit">
+ <property name="text">
+ <string>Enable shader JIT</string>
+ </property>
+ </widget>
+ </item>
+ <item>
+ <widget class="QCheckBox" name="toogle_scaled_resolution">
+ <property name="text">
+ <string>Enable scaled resolution</string>
+ </property>
+ </widget>
+ </item>
+ </layout>
+ </item>
+ </layout>
+ </widget>
+ </item>
+ <item>
+ <widget class="QGroupBox" name="groupBox_3">
+ <property name="title">
+ <string>Hotkeys</string>
+ </property>
+ <layout class="QHBoxLayout" name="horizontalLayout_4">
+ <item>
+ <layout class="QVBoxLayout" name="verticalLayout_4">
+ <item>
+ <widget class="GHotkeysDialog" name="widget" native="true"/>
+ </item>
+ </layout>
+ </item>
+ </layout>
+ </widget>
+ </item>
+ </layout>
+ </item>
+ </layout>
+ </widget>
+ <customwidgets>
+ <customwidget>
+ <class>GHotkeysDialog</class>
+ <extends>QWidget</extends>
+ <header>hotkeys.h</header>
+ <container>1</container>
+ </customwidget>
+ </customwidgets>
+ <resources/>
+ <connections/>
+</ui>
diff --git a/src/citra_qt/debugger/graphics_breakpoints.cpp b/src/citra_qt/debugger/graphics_breakpoints.cpp
index 819ec7707..fe66918a8 100644
--- a/src/citra_qt/debugger/graphics_breakpoints.cpp
+++ b/src/citra_qt/debugger/graphics_breakpoints.cpp
@@ -44,7 +44,7 @@ QVariant BreakPointModel::data(const QModelIndex& index, int role) const
{ Pica::DebugContext::Event::PicaCommandProcessed, tr("Pica command processed") },
{ Pica::DebugContext::Event::IncomingPrimitiveBatch, tr("Incoming primitive batch") },
{ Pica::DebugContext::Event::FinishedPrimitiveBatch, tr("Finished primitive batch") },
- { Pica::DebugContext::Event::VertexLoaded, tr("Vertex loaded") },
+ { Pica::DebugContext::Event::VertexShaderInvocation, tr("Vertex shader invocation") },
{ Pica::DebugContext::Event::IncomingDisplayTransfer, tr("Incoming display transfer") },
{ Pica::DebugContext::Event::GSPCommandProcessed, tr("GSP command processed") },
{ Pica::DebugContext::Event::BufferSwapped, tr("Buffers swapped") }
@@ -75,7 +75,7 @@ QVariant BreakPointModel::data(const QModelIndex& index, int role) const
case Role_IsEnabled:
{
auto context = context_weak.lock();
- return context && context->breakpoints[event].enabled;
+ return context && context->breakpoints[(int)event].enabled;
}
default:
@@ -110,7 +110,7 @@ bool BreakPointModel::setData(const QModelIndex& index, const QVariant& value, i
if (!context)
return false;
- context->breakpoints[event].enabled = value == Qt::Checked;
+ context->breakpoints[(int)event].enabled = value == Qt::Checked;
QModelIndex changed_index = createIndex(index.row(), 0);
emit dataChanged(changed_index, changed_index);
return true;
diff --git a/src/citra_qt/debugger/graphics_framebuffer.cpp b/src/citra_qt/debugger/graphics_framebuffer.cpp
index c30e75933..68cff78b2 100644
--- a/src/citra_qt/debugger/graphics_framebuffer.cpp
+++ b/src/citra_qt/debugger/graphics_framebuffer.cpp
@@ -346,5 +346,11 @@ u32 GraphicsFramebufferWidget::BytesPerPixel(GraphicsFramebufferWidget::Format f
case Format::RGBA4:
case Format::D16:
return 2;
+ default:
+ UNREACHABLE_MSG("GraphicsFramebufferWidget::BytesPerPixel: this "
+ "should not be reached as this function should "
+ "be given a format which is in "
+ "GraphicsFramebufferWidget::Format. Instead got %i",
+ static_cast<int>(format));
}
}
diff --git a/src/citra_qt/debugger/graphics_tracing.cpp b/src/citra_qt/debugger/graphics_tracing.cpp
index e06498744..1402f8e79 100644
--- a/src/citra_qt/debugger/graphics_tracing.cpp
+++ b/src/citra_qt/debugger/graphics_tracing.cpp
@@ -2,6 +2,9 @@
// Licensed under GPLv2 or any later version
// Refer to the license.txt file included.
+#include <algorithm>
+#include <array>
+#include <iterator>
#include <memory>
#include <boost/range/algorithm/copy.hpp>
@@ -18,6 +21,7 @@
#include "core/hw/gpu.h"
#include "core/hw/lcd.h"
+#include "core/tracer/recorder.h"
#include "nihstro/float24.h"
diff --git a/src/citra_qt/debugger/graphics_vertex_shader.cpp b/src/citra_qt/debugger/graphics_vertex_shader.cpp
index d648d4640..6e8d7ef42 100644
--- a/src/citra_qt/debugger/graphics_vertex_shader.cpp
+++ b/src/citra_qt/debugger/graphics_vertex_shader.cpp
@@ -365,7 +365,7 @@ GraphicsVertexShaderWidget::GraphicsVertexShaderWidget(std::shared_ptr< Pica::De
input_data[i]->setValidator(new QDoubleValidator(input_data[i]));
}
- breakpoint_warning = new QLabel(tr("(data only available at VertexLoaded breakpoints)"));
+ breakpoint_warning = new QLabel(tr("(data only available at vertex shader invocation breakpoints)"));
// TODO: Add some button for jumping to the shader entry point
@@ -454,7 +454,7 @@ GraphicsVertexShaderWidget::GraphicsVertexShaderWidget(std::shared_ptr< Pica::De
void GraphicsVertexShaderWidget::OnBreakPointHit(Pica::DebugContext::Event event, void* data) {
auto input = static_cast<Pica::Shader::InputVertex*>(data);
- if (event == Pica::DebugContext::Event::VertexLoaded) {
+ if (event == Pica::DebugContext::Event::VertexShaderInvocation) {
Reload(true, data);
} else {
// No vertex data is retrievable => invalidate currently stored vertex data
diff --git a/src/citra_qt/debugger/profiler.cpp b/src/citra_qt/debugger/profiler.cpp
index 4f6ba0e1f..7bb010f77 100644
--- a/src/citra_qt/debugger/profiler.cpp
+++ b/src/citra_qt/debugger/profiler.cpp
@@ -9,13 +9,16 @@
#include "citra_qt/debugger/profiler.h"
#include "citra_qt/util/util.h"
+#include "common/common_types.h"
#include "common/microprofile.h"
#include "common/profiler_reporting.h"
// Include the implementation of the UI in this file. This isn't in microprofile.cpp because the
// non-Qt frontends don't need it (and don't implement the UI drawing hooks either).
+#if MICROPROFILE_ENABLED
#define MICROPROFILEUI_IMPL 1
#include "common/microprofileui.h"
+#endif
using namespace Common::Profiling;
@@ -34,21 +37,9 @@ static QVariant GetDataForColumn(int col, const AggregatedDuration& duration)
}
}
-static const TimingCategoryInfo* GetCategoryInfo(int id)
-{
- const auto& categories = GetProfilingManager().GetTimingCategoriesInfo();
- if ((size_t)id >= categories.size()) {
- return nullptr;
- } else {
- return &categories[id];
- }
-}
-
ProfilerModel::ProfilerModel(QObject* parent) : QAbstractItemModel(parent)
{
updateProfilingInfo();
- const auto& categories = GetProfilingManager().GetTimingCategoriesInfo();
- results.time_per_category.resize(categories.size());
}
QVariant ProfilerModel::headerData(int section, Qt::Orientation orientation, int role) const
@@ -85,7 +76,7 @@ int ProfilerModel::rowCount(const QModelIndex& parent) const
if (parent.isValid()) {
return 0;
} else {
- return static_cast<int>(results.time_per_category.size() + 2);
+ return 2;
}
}
@@ -104,17 +95,6 @@ QVariant ProfilerModel::data(const QModelIndex& index, int role) const
} else {
return GetDataForColumn(index.column(), results.interframe_time);
}
- } else {
- if (index.column() == 0) {
- const TimingCategoryInfo* info = GetCategoryInfo(index.row() - 2);
- return info != nullptr ? QString(info->name) : QVariant();
- } else {
- if (index.row() - 2 < (int)results.time_per_category.size()) {
- return GetDataForColumn(index.column(), results.time_per_category[index.row() - 2]);
- } else {
- return QVariant();
- }
- }
}
}
@@ -148,6 +128,8 @@ void ProfilerWidget::setProfilingInfoUpdateEnabled(bool enable)
}
}
+#if MICROPROFILE_ENABLED
+
class MicroProfileWidget : public QWidget {
public:
MicroProfileWidget(QWidget* parent = nullptr);
@@ -171,6 +153,8 @@ private:
QTimer update_timer;
};
+#endif
+
MicroProfileDialog::MicroProfileDialog(QWidget* parent)
: QWidget(parent, Qt::Dialog)
{
@@ -180,6 +164,8 @@ MicroProfileDialog::MicroProfileDialog(QWidget* parent)
// Remove the "?" button from the titlebar and enable the maximize button
setWindowFlags(windowFlags() & ~Qt::WindowContextHelpButtonHint | Qt::WindowMaximizeButtonHint);
+#if MICROPROFILE_ENABLED
+
MicroProfileWidget* widget = new MicroProfileWidget(this);
QLayout* layout = new QVBoxLayout(this);
@@ -191,6 +177,7 @@ MicroProfileDialog::MicroProfileDialog(QWidget* parent)
setFocusProxy(widget);
widget->setFocusPolicy(Qt::StrongFocus);
widget->setFocus();
+#endif
}
QAction* MicroProfileDialog::toggleViewAction() {
@@ -218,6 +205,9 @@ void MicroProfileDialog::hideEvent(QHideEvent* ev) {
QWidget::hideEvent(ev);
}
+
+#if MICROPROFILE_ENABLED
+
/// There's no way to pass a user pointer to MicroProfile, so this variable is used to make the
/// QPainter available inside the drawing callbacks.
static QPainter* mp_painter = nullptr;
@@ -337,3 +327,4 @@ void MicroProfileDrawLine2D(u32 vertices_length, float* vertices, u32 hex_color)
mp_painter->drawPolyline(point_buf.data(), vertices_length);
point_buf.clear();
}
+#endif
diff --git a/src/citra_qt/debugger/profiler.h b/src/citra_qt/debugger/profiler.h
index 036054740..3b38ed8ec 100644
--- a/src/citra_qt/debugger/profiler.h
+++ b/src/citra_qt/debugger/profiler.h
@@ -7,8 +7,10 @@
#include <QAbstractItemModel>
#include <QDockWidget>
#include <QTimer>
+
#include "ui_profiler.h"
+#include "common/microprofile.h"
#include "common/profiler_reporting.h"
class ProfilerModel : public QAbstractItemModel
@@ -49,6 +51,7 @@ private:
QTimer update_timer;
};
+
class MicroProfileDialog : public QWidget {
Q_OBJECT
diff --git a/src/citra_qt/game_list.cpp b/src/citra_qt/game_list.cpp
index 1f8d69a03..d4ac9c96e 100644
--- a/src/citra_qt/game_list.cpp
+++ b/src/citra_qt/game_list.cpp
@@ -8,6 +8,7 @@
#include "game_list.h"
#include "game_list_p.h"
+#include "ui_settings.h"
#include "core/loader/loader.h"
@@ -33,8 +34,8 @@ GameList::GameList(QWidget* parent)
tree_view->setUniformRowHeights(true);
item_model->insertColumns(0, COLUMN_COUNT);
- item_model->setHeaderData(COLUMN_FILE_TYPE, Qt::Horizontal, "File type");
item_model->setHeaderData(COLUMN_NAME, Qt::Horizontal, "Name");
+ item_model->setHeaderData(COLUMN_FILE_TYPE, Qt::Horizontal, "File type");
item_model->setHeaderData(COLUMN_SIZE, Qt::Horizontal, "Size");
connect(tree_view, SIGNAL(activated(const QModelIndex&)), this, SLOT(ValidateEntry(const QModelIndex&)));
@@ -66,7 +67,7 @@ void GameList::ValidateEntry(const QModelIndex& item)
if (file_path.isEmpty())
return;
- std::string std_file_path = file_path.toStdString();
+ std::string std_file_path(file_path.toStdString());
if (!FileUtil::Exists(std_file_path) || FileUtil::IsDirectory(std_file_path))
return;
emit GameChosen(file_path);
@@ -100,19 +101,19 @@ void GameList::PopulateAsync(const QString& dir_path, bool deep_scan)
current_worker = std::move(worker);
}
-void GameList::SaveInterfaceLayout(QSettings& settings)
+void GameList::SaveInterfaceLayout()
{
- settings.beginGroup("UILayout");
- settings.setValue("gameListHeaderState", tree_view->header()->saveState());
- settings.endGroup();
+ UISettings::values.gamelist_header_state = tree_view->header()->saveState();
}
-void GameList::LoadInterfaceLayout(QSettings& settings)
+void GameList::LoadInterfaceLayout()
{
auto header = tree_view->header();
- settings.beginGroup("UILayout");
- header->restoreState(settings.value("gameListHeaderState").toByteArray());
- settings.endGroup();
+ if (!header->restoreState(UISettings::values.gamelist_header_state)) {
+ // We are using the name column to display icons and titles
+ // so make it as large as possible as default.
+ header->resizeSection(COLUMN_NAME, header->width());
+ }
item_model->sort(header->sortIndicatorSection(), header->sortIndicatorOrder());
}
@@ -146,9 +147,15 @@ void GameListWorker::AddFstEntriesToGameList(const std::string& dir_path, bool d
LOG_WARNING(Frontend, "Filetype and extension of file %s do not match.", physical_name.c_str());
}
+ std::vector<u8> smdh;
+ std::unique_ptr<Loader::AppLoader> loader = Loader::GetLoader(FileUtil::IOFile(physical_name, "rb"), filetype, filename_filename, physical_name);
+
+ if (loader)
+ loader->ReadIcon(smdh);
+
emit EntryReady({
+ new GameListItemPath(QString::fromStdString(physical_name), smdh),
new GameListItem(QString::fromStdString(Loader::GetFileTypeString(filetype))),
- new GameListItemPath(QString::fromStdString(physical_name)),
new GameListItemSize(FileUtil::GetSize(physical_name)),
});
}
diff --git a/src/citra_qt/game_list.h b/src/citra_qt/game_list.h
index 0950d9622..198674f04 100644
--- a/src/citra_qt/game_list.h
+++ b/src/citra_qt/game_list.h
@@ -20,8 +20,8 @@ class GameList : public QWidget {
public:
enum {
- COLUMN_FILE_TYPE,
COLUMN_NAME,
+ COLUMN_FILE_TYPE,
COLUMN_SIZE,
COLUMN_COUNT, // Number of columns
};
@@ -31,8 +31,8 @@ public:
void PopulateAsync(const QString& dir_path, bool deep_scan);
- void SaveInterfaceLayout(QSettings& settings);
- void LoadInterfaceLayout(QSettings& settings);
+ void SaveInterfaceLayout();
+ void LoadInterfaceLayout();
public slots:
void AddEntry(QList<QStandardItem*> entry_items);
diff --git a/src/citra_qt/game_list_p.h b/src/citra_qt/game_list_p.h
index 820012bce..284f5da81 100644
--- a/src/citra_qt/game_list_p.h
+++ b/src/citra_qt/game_list_p.h
@@ -6,13 +6,85 @@
#include <atomic>
+#include <QImage>
#include <QRunnable>
#include <QStandardItem>
#include <QString>
#include "citra_qt/util/util.h"
#include "common/string_util.h"
+#include "common/color.h"
+#include "core/loader/loader.h"
+
+#include "video_core/utils.h"
+
+/**
+ * Tests if data is a valid SMDH by its length and magic number.
+ * @param smdh_data data buffer to test
+ * @return bool test result
+ */
+static bool IsValidSMDH(const std::vector<u8>& smdh_data) {
+ if (smdh_data.size() < sizeof(Loader::SMDH))
+ return false;
+
+ u32 magic;
+ memcpy(&magic, smdh_data.data(), 4);
+
+ return Loader::MakeMagic('S', 'M', 'D', 'H') == magic;
+}
+
+/**
+ * Gets game icon from SMDH
+ * @param sdmh SMDH data
+ * @param large If true, returns large icon (48x48), otherwise returns small icon (24x24)
+ * @return QPixmap game icon
+ */
+static QPixmap GetIconFromSMDH(const Loader::SMDH& smdh, bool large) {
+ u32 size;
+ const u8* icon_data;
+
+ if (large) {
+ size = 48;
+ icon_data = smdh.large_icon.data();
+ } else {
+ size = 24;
+ icon_data = smdh.small_icon.data();
+ }
+
+ QImage icon(size, size, QImage::Format::Format_RGB888);
+ for (u32 x = 0; x < size; ++x) {
+ for (u32 y = 0; y < size; ++y) {
+ u32 coarse_y = y & ~7;
+ auto v = Color::DecodeRGB565(
+ icon_data + VideoCore::GetMortonOffset(x, y, 2) + coarse_y * size * 2);
+ icon.setPixel(x, y, qRgb(v.r(), v.g(), v.b()));
+ }
+ }
+ return QPixmap::fromImage(icon);
+}
+
+/**
+ * Gets the default icon (for games without valid SMDH)
+ * @param large If true, returns large icon (48x48), otherwise returns small icon (24x24)
+ * @return QPixmap default icon
+ */
+static QPixmap GetDefaultIcon(bool large) {
+ int size = large ? 48 : 24;
+ QPixmap icon(size, size);
+ icon.fill(Qt::transparent);
+ return icon;
+}
+
+/**
+ * Gets the short game title fromn SMDH
+ * @param sdmh SMDH data
+ * @param language title language
+ * @return QString short title
+ */
+static QString GetShortTitleFromSMDH(const Loader::SMDH& smdh, Loader::SMDH::TitleLanguage language) {
+ return QString::fromUtf16(smdh.titles[static_cast<int>(language)].short_title.data());
+}
class GameListItem : public QStandardItem {
@@ -27,29 +99,43 @@ public:
* A specialization of GameListItem for path values.
* This class ensures that for every full path value it holds, a correct string representation
* of just the filename (with no extension) will be displayed to the user.
+ * If this class recieves valid SMDH data, it will also display game icons and titles.
*/
class GameListItemPath : public GameListItem {
public:
static const int FullPathRole = Qt::UserRole + 1;
+ static const int TitleRole = Qt::UserRole + 2;
GameListItemPath(): GameListItem() {}
- GameListItemPath(const QString& game_path): GameListItem()
+ GameListItemPath(const QString& game_path, const std::vector<u8>& smdh_data): GameListItem()
{
setData(game_path, FullPathRole);
+
+ if (!IsValidSMDH(smdh_data)) {
+ // SMDH is not valid, set a default icon
+ setData(GetDefaultIcon(true), Qt::DecorationRole);
+ return;
+ }
+
+ Loader::SMDH smdh;
+ memcpy(&smdh, smdh_data.data(), sizeof(Loader::SMDH));
+
+ // Get icon from SMDH
+ setData(GetIconFromSMDH(smdh, true), Qt::DecorationRole);
+
+ // Get title form SMDH
+ setData(GetShortTitleFromSMDH(smdh, Loader::SMDH::TitleLanguage::English), TitleRole);
}
- void setData(const QVariant& value, int role) override
- {
- // By specializing setData for FullPathRole, we can ensure that the two string
- // representations of the data are always accurate and in the correct format.
- if (role == FullPathRole) {
+ QVariant data(int role) const override {
+ if (role == Qt::DisplayRole) {
std::string filename;
- Common::SplitPath(value.toString().toStdString(), nullptr, &filename, nullptr);
- GameListItem::setData(QString::fromStdString(filename), Qt::DisplayRole);
- GameListItem::setData(value, FullPathRole);
+ Common::SplitPath(data(FullPathRole).toString().toStdString(), nullptr, &filename, nullptr);
+ QString title = data(TitleRole).toString();
+ return QString::fromStdString(filename) + (title.isEmpty() ? "" : "\n " + title);
} else {
- GameListItem::setData(value, role);
+ return GameListItem::data(role);
}
}
};
diff --git a/src/citra_qt/hotkeys.cpp b/src/citra_qt/hotkeys.cpp
index ed6b12fc4..41f95c63d 100644
--- a/src/citra_qt/hotkeys.cpp
+++ b/src/citra_qt/hotkeys.cpp
@@ -4,11 +4,12 @@
#include <map>
+#include <QtGlobal>
#include <QKeySequence>
-#include <QSettings>
#include <QShortcut>
#include "citra_qt/hotkeys.h"
+#include "citra_qt/ui_settings.h"
struct Hotkey
{
@@ -24,54 +25,39 @@ typedef std::map<QString, HotkeyMap> HotkeyGroupMap;
HotkeyGroupMap hotkey_groups;
-void SaveHotkeys(QSettings& settings)
+void SaveHotkeys()
{
- settings.beginGroup("Shortcuts");
-
+ UISettings::values.shortcuts.clear();
for (auto group : hotkey_groups)
{
- settings.beginGroup(group.first);
for (auto hotkey : group.second)
{
- settings.beginGroup(hotkey.first);
- settings.setValue(QString("KeySeq"), hotkey.second.keyseq.toString());
- settings.setValue(QString("Context"), hotkey.second.context);
- settings.endGroup();
+ UISettings::values.shortcuts.emplace_back(
+ UISettings::Shortcut(group.first + "/" + hotkey.first,
+ UISettings::ContextualShortcut(hotkey.second.keyseq.toString(),
+ hotkey.second.context)));
}
- settings.endGroup();
}
- settings.endGroup();
}
-void LoadHotkeys(QSettings& settings)
+void LoadHotkeys()
{
- settings.beginGroup("Shortcuts");
-
// Make sure NOT to use a reference here because it would become invalid once we call beginGroup()
- QStringList groups = settings.childGroups();
- for (auto group : groups)
+ for (auto shortcut : UISettings::values.shortcuts)
{
- settings.beginGroup(group);
+ QStringList cat = shortcut.first.split("/");
+ Q_ASSERT(cat.size() >= 2);
- QStringList hotkeys = settings.childGroups();
- for (auto hotkey : hotkeys)
+ // RegisterHotkey assigns default keybindings, so use old values as default parameters
+ Hotkey& hk = hotkey_groups[cat[0]][cat[1]];
+ if (!shortcut.second.first.isEmpty())
{
- settings.beginGroup(hotkey);
-
- // RegisterHotkey assigns default keybindings, so use old values as default parameters
- Hotkey& hk = hotkey_groups[group][hotkey];
- hk.keyseq = QKeySequence::fromString(settings.value("KeySeq", hk.keyseq.toString()).toString());
- hk.context = (Qt::ShortcutContext)settings.value("Context", hk.context).toInt();
- if (hk.shortcut)
- hk.shortcut->setKey(hk.keyseq);
-
- settings.endGroup();
+ hk.keyseq = QKeySequence::fromString(shortcut.second.first);
+ hk.context = (Qt::ShortcutContext)shortcut.second.second;
}
-
- settings.endGroup();
+ if (hk.shortcut)
+ hk.shortcut->setKey(hk.keyseq);
}
-
- settings.endGroup();
}
void RegisterHotkey(const QString& group, const QString& action, const QKeySequence& default_keyseq, Qt::ShortcutContext default_context)
@@ -94,7 +80,7 @@ QShortcut* GetHotkey(const QString& group, const QString& action, QWidget* widge
}
-GHotkeysDialog::GHotkeysDialog(QWidget* parent): QDialog(parent)
+GHotkeysDialog::GHotkeysDialog(QWidget* parent): QWidget(parent)
{
ui.setupUi(this);
diff --git a/src/citra_qt/hotkeys.h b/src/citra_qt/hotkeys.h
index 2fe635882..38aa5f012 100644
--- a/src/citra_qt/hotkeys.h
+++ b/src/citra_qt/hotkeys.h
@@ -2,6 +2,8 @@
// Licensed under GPLv2 or any later version
// Refer to the license.txt file included.
+#pragma once
+
#include "ui_hotkeys.h"
class QDialog;
@@ -33,16 +35,16 @@ QShortcut* GetHotkey(const QString& group, const QString& action, QWidget* widge
*
* @note Each hotkey group will be stored a settings group; For each hotkey inside that group, a settings group will be created to store the key sequence and the hotkey context.
*/
-void SaveHotkeys(QSettings& settings);
+void SaveHotkeys();
/**
* Loads hotkeys from the settings file.
*
* @note Yet unregistered hotkeys which are present in the settings will automatically be registered.
*/
-void LoadHotkeys(QSettings& settings);
+void LoadHotkeys();
-class GHotkeysDialog : public QDialog
+class GHotkeysDialog : public QWidget
{
Q_OBJECT
diff --git a/src/citra_qt/hotkeys.ui b/src/citra_qt/hotkeys.ui
index 38a9a14d1..050fe064e 100644
--- a/src/citra_qt/hotkeys.ui
+++ b/src/citra_qt/hotkeys.ui
@@ -1,7 +1,7 @@
<?xml version="1.0" encoding="UTF-8"?>
<ui version="4.0">
<class>hotkeys</class>
- <widget class="QDialog" name="hotkeys">
+ <widget class="QWidget" name="hotkeys">
<property name="geometry">
<rect>
<x>0</x>
@@ -39,51 +39,8 @@
</column>
</widget>
</item>
- <item>
- <widget class="QDialogButtonBox" name="buttonBox">
- <property name="orientation">
- <enum>Qt::Horizontal</enum>
- </property>
- <property name="standardButtons">
- <set>QDialogButtonBox::Cancel|QDialogButtonBox::Ok|QDialogButtonBox::Reset</set>
- </property>
- </widget>
- </item>
</layout>
</widget>
<resources/>
- <connections>
- <connection>
- <sender>buttonBox</sender>
- <signal>accepted()</signal>
- <receiver>hotkeys</receiver>
- <slot>accept()</slot>
- <hints>
- <hint type="sourcelabel">
- <x>248</x>
- <y>254</y>
- </hint>
- <hint type="destinationlabel">
- <x>157</x>
- <y>274</y>
- </hint>
- </hints>
- </connection>
- <connection>
- <sender>buttonBox</sender>
- <signal>rejected()</signal>
- <receiver>hotkeys</receiver>
- <slot>reject()</slot>
- <hints>
- <hint type="sourcelabel">
- <x>316</x>
- <y>260</y>
- </hint>
- <hint type="destinationlabel">
- <x>286</x>
- <y>274</y>
- </hint>
- </hints>
- </connection>
- </connections>
+ <connections/>
</ui>
diff --git a/src/citra_qt/main.cpp b/src/citra_qt/main.cpp
index 32cceaf7e..f1ab29755 100644
--- a/src/citra_qt/main.cpp
+++ b/src/citra_qt/main.cpp
@@ -3,6 +3,7 @@
// Refer to the license.txt file included.
#include <clocale>
+#include <memory>
#include <thread>
#include <QDesktopWidget>
@@ -13,9 +14,11 @@
#include "citra_qt/bootmanager.h"
#include "citra_qt/config.h"
+#include "citra_qt/configure_dialog.h"
#include "citra_qt/game_list.h"
#include "citra_qt/hotkeys.h"
#include "citra_qt/main.h"
+#include "citra_qt/ui_settings.h"
// Debugger
#include "citra_qt/debugger/callstack.h"
@@ -30,7 +33,6 @@
#include "citra_qt/debugger/ramview.h"
#include "citra_qt/debugger/registers.h"
-#include "common/make_unique.h"
#include "common/microprofile.h"
#include "common/platform.h"
#include "common/scm_rev.h"
@@ -50,12 +52,10 @@
#include "video_core/video_core.h"
-GMainWindow::GMainWindow() : emu_thread(nullptr)
+GMainWindow::GMainWindow() : config(new Config()), emu_thread(nullptr)
{
Pica::g_debug_context = Pica::DebugContext::Construct();
- Config config;
-
ui.setupUi(this);
statusBar()->hide();
@@ -69,8 +69,10 @@ GMainWindow::GMainWindow() : emu_thread(nullptr)
addDockWidget(Qt::BottomDockWidgetArea, profilerWidget);
profilerWidget->hide();
+#if MICROPROFILE_ENABLED
microProfileDialog = new MicroProfileDialog(this);
microProfileDialog->hide();
+#endif
disasmWidget = new DisassemblerWidget(this, emu_thread.get());
addDockWidget(Qt::BottomDockWidgetArea, disasmWidget);
@@ -110,7 +112,9 @@ GMainWindow::GMainWindow() : emu_thread(nullptr)
QMenu* debug_menu = ui.menu_View->addMenu(tr("Debugging"));
debug_menu->addAction(profilerWidget->toggleViewAction());
+#if MICROPROFILE_ENABLED
debug_menu->addAction(microProfileDialog->toggleViewAction());
+#endif
debug_menu->addAction(disasmWidget->toggleViewAction());
debug_menu->addAction(registersWidget->toggleViewAction());
debug_menu->addAction(callstackWidget->toggleViewAction());
@@ -133,33 +137,20 @@ GMainWindow::GMainWindow() : emu_thread(nullptr)
setGeometry(x, y, w, h);
// Restore UI state
- QSettings settings;
-
- settings.beginGroup("UILayout");
- restoreGeometry(settings.value("geometry").toByteArray());
- restoreState(settings.value("state").toByteArray());
- render_window->restoreGeometry(settings.value("geometryRenderWindow").toByteArray());
- microProfileDialog->restoreGeometry(settings.value("microProfileDialogGeometry").toByteArray());
- microProfileDialog->setVisible(settings.value("microProfileDialogVisible").toBool());
- settings.endGroup();
-
- game_list->LoadInterfaceLayout(settings);
-
- ui.action_Use_Gdbstub->setChecked(Settings::values.use_gdbstub);
- SetGdbstubEnabled(ui.action_Use_Gdbstub->isChecked());
-
- GDBStub::SetServerPort(static_cast<u32>(Settings::values.gdbstub_port));
-
- ui.action_Use_Hardware_Renderer->setChecked(Settings::values.use_hw_renderer);
- SetHardwareRendererEnabled(ui.action_Use_Hardware_Renderer->isChecked());
+ restoreGeometry(UISettings::values.geometry);
+ restoreState(UISettings::values.state);
+ render_window->restoreGeometry(UISettings::values.renderwindow_geometry);
+#if MICROPROFILE_ENABLED
+ microProfileDialog->restoreGeometry(UISettings::values.microprofile_geometry);
+ microProfileDialog->setVisible(UISettings::values.microprofile_visible);
+#endif
- ui.action_Use_Shader_JIT->setChecked(Settings::values.use_shader_jit);
- SetShaderJITEnabled(ui.action_Use_Shader_JIT->isChecked());
+ game_list->LoadInterfaceLayout();
- ui.action_Single_Window_Mode->setChecked(settings.value("singleWindowMode", true).toBool());
+ ui.action_Single_Window_Mode->setChecked(UISettings::values.single_window_mode);
ToggleWindowMode();
- ui.actionDisplay_widget_title_bars->setChecked(settings.value("displayTitleBars", true).toBool());
+ ui.actionDisplay_widget_title_bars->setChecked(UISettings::values.display_titlebar);
OnDisplayTitleBars(ui.actionDisplay_widget_title_bars->isChecked());
// Prepare actions for recent files
@@ -172,21 +163,16 @@ GMainWindow::GMainWindow() : emu_thread(nullptr)
}
UpdateRecentFiles();
- confirm_before_closing = settings.value("confirmClose", true).toBool();
-
// Setup connections
- connect(game_list, SIGNAL(GameChosen(QString)), this, SLOT(OnGameListLoadFile(QString)));
- connect(ui.action_Load_File, SIGNAL(triggered()), this, SLOT(OnMenuLoadFile()));
+ connect(game_list, SIGNAL(GameChosen(QString)), this, SLOT(OnGameListLoadFile(QString)), Qt::DirectConnection);
+ connect(ui.action_Configure, SIGNAL(triggered()), this, SLOT(OnConfigure()));
+ connect(ui.action_Load_File, SIGNAL(triggered()), this, SLOT(OnMenuLoadFile()),Qt::DirectConnection);
connect(ui.action_Load_Symbol_Map, SIGNAL(triggered()), this, SLOT(OnMenuLoadSymbolMap()));
connect(ui.action_Select_Game_List_Root, SIGNAL(triggered()), this, SLOT(OnMenuSelectGameListRoot()));
connect(ui.action_Start, SIGNAL(triggered()), this, SLOT(OnStartGame()));
connect(ui.action_Pause, SIGNAL(triggered()), this, SLOT(OnPauseGame()));
connect(ui.action_Stop, SIGNAL(triggered()), this, SLOT(OnStopGame()));
- connect(ui.action_Use_Hardware_Renderer, SIGNAL(triggered(bool)), this, SLOT(SetHardwareRendererEnabled(bool)));
- connect(ui.action_Use_Shader_JIT, SIGNAL(triggered(bool)), this, SLOT(SetShaderJITEnabled(bool)));
- connect(ui.action_Use_Gdbstub, SIGNAL(triggered(bool)), this, SLOT(SetGdbstubEnabled(bool)));
connect(ui.action_Single_Window_Mode, SIGNAL(triggered(bool)), this, SLOT(ToggleWindowMode()));
- connect(ui.action_Hotkeys, SIGNAL(triggered()), this, SLOT(OnOpenHotkeysDialog()));
connect(this, SIGNAL(EmulationStarting(EmuThread*)), disasmWidget, SLOT(OnEmulationStarting(EmuThread*)));
connect(this, SIGNAL(EmulationStopping()), disasmWidget, SLOT(OnEmulationStopping()));
@@ -201,7 +187,7 @@ GMainWindow::GMainWindow() : emu_thread(nullptr)
// Setup hotkeys
RegisterHotkey("Main Window", "Load File", QKeySequence::Open);
RegisterHotkey("Main Window", "Start Emulation");
- LoadHotkeys(settings);
+ LoadHotkeys();
connect(GetHotkey("Main Window", "Load File", this), SIGNAL(activated()), this, SLOT(OnMenuLoadFile()));
connect(GetHotkey("Main Window", "Start Emulation", this), SIGNAL(activated()), this, SLOT(OnStartGame()));
@@ -211,7 +197,7 @@ GMainWindow::GMainWindow() : emu_thread(nullptr)
show();
- game_list->PopulateAsync(settings.value("gameListRootDir", ".").toString(), settings.value("gameListDeepScan", false).toBool());
+ game_list->PopulateAsync(UISettings::values.gamedir, UISettings::values.gamedir_deepscan);
QStringList args = QApplication::arguments();
if (args.length() >= 2) {
@@ -319,7 +305,7 @@ void GMainWindow::BootGame(const std::string& filename) {
return;
// Create and start the emulation thread
- emu_thread = Common::make_unique<EmuThread>(render_window);
+ emu_thread = std::make_unique<EmuThread>(render_window);
emit EmulationStarting(emu_thread.get());
render_window->moveContext();
emu_thread->start();
@@ -375,32 +361,24 @@ void GMainWindow::ShutdownGame() {
emulation_running = false;
}
-void GMainWindow::StoreRecentFile(const std::string& filename)
-{
- QSettings settings;
- QStringList recent_files = settings.value("recentFiles").toStringList();
- recent_files.prepend(QString::fromStdString(filename));
- recent_files.removeDuplicates();
- while (recent_files.size() > max_recent_files_item) {
- recent_files.removeLast();
+void GMainWindow::StoreRecentFile(const std::string& filename) {
+ UISettings::values.recent_files.prepend(QString::fromStdString(filename));
+ UISettings::values.recent_files.removeDuplicates();
+ while (UISettings::values.recent_files.size() > max_recent_files_item) {
+ UISettings::values.recent_files.removeLast();
}
- settings.setValue("recentFiles", recent_files);
-
UpdateRecentFiles();
}
void GMainWindow::UpdateRecentFiles() {
- QSettings settings;
- QStringList recent_files = settings.value("recentFiles").toStringList();
-
- unsigned int num_recent_files = std::min(recent_files.size(), static_cast<int>(max_recent_files_item));
+ unsigned int num_recent_files = std::min(UISettings::values.recent_files.size(), static_cast<int>(max_recent_files_item));
for (unsigned int i = 0; i < num_recent_files; i++) {
- QString text = QString("&%1. %2").arg(i + 1).arg(QFileInfo(recent_files[i]).fileName());
+ QString text = QString("&%1. %2").arg(i + 1).arg(QFileInfo(UISettings::values.recent_files[i]).fileName());
actions_recent_files[i]->setText(text);
- actions_recent_files[i]->setData(recent_files[i]);
- actions_recent_files[i]->setToolTip(recent_files[i]);
+ actions_recent_files[i]->setData(UISettings::values.recent_files[i]);
+ actions_recent_files[i]->setToolTip(UISettings::values.recent_files[i]);
actions_recent_files[i]->setVisible(true);
}
@@ -417,40 +395,32 @@ void GMainWindow::UpdateRecentFiles() {
}
void GMainWindow::OnGameListLoadFile(QString game_path) {
- BootGame(game_path.toLocal8Bit().data());
+ BootGame(game_path.toStdString());
}
void GMainWindow::OnMenuLoadFile() {
- QSettings settings;
- QString rom_path = settings.value("romsPath", QString()).toString();
-
- QString filename = QFileDialog::getOpenFileName(this, tr("Load File"), rom_path, tr("3DS executable (*.3ds *.3dsx *.elf *.axf *.cci *.cxi)"));
+ QString filename = QFileDialog::getOpenFileName(this, tr("Load File"), UISettings::values.roms_path, tr("3DS executable (*.3ds *.3dsx *.elf *.axf *.cci *.cxi)"));
if (!filename.isEmpty()) {
- settings.setValue("romsPath", QFileInfo(filename).path());
+ UISettings::values.roms_path = QFileInfo(filename).path();
- BootGame(filename.toLocal8Bit().data());
+ BootGame(filename.toStdString());
}
}
void GMainWindow::OnMenuLoadSymbolMap() {
- QSettings settings;
- QString symbol_path = settings.value("symbolsPath", QString()).toString();
-
- QString filename = QFileDialog::getOpenFileName(this, tr("Load Symbol Map"), symbol_path, tr("Symbol map (*)"));
+ QString filename = QFileDialog::getOpenFileName(this, tr("Load Symbol Map"), UISettings::values.symbols_path, tr("Symbol map (*)"));
if (!filename.isEmpty()) {
- settings.setValue("symbolsPath", QFileInfo(filename).path());
+ UISettings::values.symbols_path = QFileInfo(filename).path();
- LoadSymbolMap(filename.toLocal8Bit().data());
+ LoadSymbolMap(filename.toStdString());
}
}
void GMainWindow::OnMenuSelectGameListRoot() {
- QSettings settings;
-
QString dir_path = QFileDialog::getExistingDirectory(this, tr("Select Directory"));
if (!dir_path.isEmpty()) {
- settings.setValue("gameListRootDir", dir_path);
- game_list->PopulateAsync(dir_path, settings.value("gameListDeepScan").toBool());
+ UISettings::values.gamedir = dir_path;
+ game_list->PopulateAsync(dir_path, UISettings::values.gamedir_deepscan);
}
}
@@ -461,15 +431,12 @@ void GMainWindow::OnMenuRecentFile() {
QString filename = action->data().toString();
QFileInfo file_info(filename);
if (file_info.exists()) {
- BootGame(filename.toLocal8Bit().data());
+ BootGame(filename.toStdString());
} else {
// Display an error message and remove the file from the list.
QMessageBox::information(this, tr("File not found"), tr("File \"%1\" not found").arg(filename));
- QSettings settings;
- QStringList recent_files = settings.value("recentFiles").toStringList();
- recent_files.removeOne(filename);
- settings.setValue("recentFiles", recent_files);
+ UISettings::values.recent_files.removeOne(filename);
UpdateRecentFiles();
}
}
@@ -496,31 +463,6 @@ void GMainWindow::OnStopGame() {
ShutdownGame();
}
-void GMainWindow::OnOpenHotkeysDialog() {
- GHotkeysDialog dialog(this);
- dialog.exec();
-}
-
-void GMainWindow::SetHardwareRendererEnabled(bool enabled) {
- VideoCore::g_hw_renderer_enabled = enabled;
-
- Config config;
- Settings::values.use_hw_renderer = enabled;
- config.Save();
-}
-
-void GMainWindow::SetGdbstubEnabled(bool enabled) {
- GDBStub::ToggleServer(enabled);
-}
-
-void GMainWindow::SetShaderJITEnabled(bool enabled) {
- VideoCore::g_shader_jit_enabled = enabled;
-
- Config config;
- Settings::values.use_shader_jit = enabled;
- config.Save();
-}
-
void GMainWindow::ToggleWindowMode() {
if (ui.action_Single_Window_Mode->isChecked()) {
// Render in the main window...
@@ -547,11 +489,17 @@ void GMainWindow::ToggleWindowMode() {
}
void GMainWindow::OnConfigure() {
- //GControllerConfigDialog* dialog = new GControllerConfigDialog(controller_ports, this);
+ ConfigureDialog configureDialog(this);
+ auto result = configureDialog.exec();
+ if (result == QDialog::Accepted)
+ {
+ configureDialog.applyConfiguration();
+ config->Save();
+ }
}
bool GMainWindow::ConfirmClose() {
- if (emu_thread == nullptr || !confirm_before_closing)
+ if (emu_thread == nullptr || !UISettings::values.confirm_before_closing)
return true;
auto answer = QMessageBox::question(this, tr("Citra"),
@@ -566,23 +514,19 @@ void GMainWindow::closeEvent(QCloseEvent* event) {
return;
}
- // Save window layout
- QSettings settings(QSettings::IniFormat, QSettings::UserScope, "Citra team", "Citra");
-
- settings.beginGroup("UILayout");
- settings.setValue("geometry", saveGeometry());
- settings.setValue("state", saveState());
- settings.setValue("geometryRenderWindow", render_window->saveGeometry());
- settings.setValue("microProfileDialogGeometry", microProfileDialog->saveGeometry());
- settings.setValue("microProfileDialogVisible", microProfileDialog->isVisible());
- settings.endGroup();
+ UISettings::values.geometry = saveGeometry();
+ UISettings::values.state = saveState();
+ UISettings::values.renderwindow_geometry = render_window->saveGeometry();
+#if MICROPROFILE_ENABLED
+ UISettings::values.microprofile_geometry = microProfileDialog->saveGeometry();
+ UISettings::values.microprofile_visible = microProfileDialog->isVisible();
+#endif
+ UISettings::values.single_window_mode = ui.action_Single_Window_Mode->isChecked();
+ UISettings::values.display_titlebar = ui.actionDisplay_widget_title_bars->isChecked();
+ UISettings::values.first_start = false;
- settings.setValue("singleWindowMode", ui.action_Single_Window_Mode->isChecked());
- settings.setValue("displayTitleBars", ui.actionDisplay_widget_title_bars->isChecked());
- settings.setValue("firstStart", false);
- settings.setValue("confirmClose", confirm_before_closing);
- game_list->SaveInterfaceLayout(settings);
- SaveHotkeys(settings);
+ game_list->SaveInterfaceLayout();
+ SaveHotkeys();
// Shutdown session if the emu thread is active...
if (emu_thread != nullptr)
@@ -607,7 +551,6 @@ int main(int argc, char* argv[]) {
});
// Init settings params
- QSettings::setDefaultFormat(QSettings::IniFormat);
QCoreApplication::setOrganizationName("Citra team");
QCoreApplication::setApplicationName("Citra");
diff --git a/src/citra_qt/main.h b/src/citra_qt/main.h
index 6e4e56689..477db5c5c 100644
--- a/src/citra_qt/main.h
+++ b/src/citra_qt/main.h
@@ -10,6 +10,7 @@
#include "ui_main.h"
+class Config;
class GameList;
class GImageInfo;
class GRenderWindow;
@@ -104,12 +105,8 @@ private slots:
/// Called whenever a user selects the "File->Select Game List Root" menu item
void OnMenuSelectGameListRoot();
void OnMenuRecentFile();
- void OnOpenHotkeysDialog();
void OnConfigure();
void OnDisplayTitleBars(bool);
- void SetHardwareRendererEnabled(bool);
- void SetGdbstubEnabled(bool);
- void SetShaderJITEnabled(bool);
void ToggleWindowMode();
private:
@@ -118,6 +115,8 @@ private:
GRenderWindow* render_window;
GameList* game_list;
+ std::unique_ptr<Config> config;
+
// Whether emulation is currently running in Citra.
bool emulation_running = false;
std::unique_ptr<EmuThread> emu_thread;
@@ -131,7 +130,6 @@ private:
GPUCommandListWidget* graphicsCommandsWidget;
QAction* actions_recent_files[max_recent_files_item];
- bool confirm_before_closing;
};
#endif // _CITRA_QT_MAIN_HXX_
diff --git a/src/citra_qt/main.ui b/src/citra_qt/main.ui
index 1e8a07cfb..441e0b81e 100644
--- a/src/citra_qt/main.ui
+++ b/src/citra_qt/main.ui
@@ -45,7 +45,7 @@
<x>0</x>
<y>0</y>
<width>1081</width>
- <height>22</height>
+ <height>19</height>
</rect>
</property>
<widget class="QMenu" name="menu_File">
@@ -73,9 +73,6 @@
<addaction name="action_Pause"/>
<addaction name="action_Stop"/>
<addaction name="separator"/>
- <addaction name="action_Use_Hardware_Renderer"/>
- <addaction name="action_Use_Shader_JIT"/>
- <addaction name="action_Use_Gdbstub"/>
<addaction name="action_Configure"/>
</widget>
<widget class="QMenu" name="menu_View">
@@ -84,7 +81,6 @@
</property>
<addaction name="action_Single_Window_Mode"/>
<addaction name="actionDisplay_widget_title_bars"/>
- <addaction name="action_Hotkeys"/>
</widget>
<widget class="QMenu" name="menu_Help">
<property name="title">
@@ -150,35 +146,6 @@
<string>Single Window Mode</string>
</property>
</action>
- <action name="action_Hotkeys">
- <property name="text">
- <string>Configure &amp;Hotkeys ...</string>
- </property>
- </action>
- <action name="action_Use_Hardware_Renderer">
- <property name="checkable">
- <bool>true</bool>
- </property>
- <property name="text">
- <string>Use Hardware Renderer</string>
- </property>
- </action>
- <action name="action_Use_Shader_JIT">
- <property name="checkable">
- <bool>true</bool>
- </property>
- <property name="text">
- <string>Use Shader JIT</string>
- </property>
- </action>
- <action name="action_Use_Gdbstub">
- <property name="checkable">
- <bool>true</bool>
- </property>
- <property name="text">
- <string>Use Gdbstub</string>
- </property>
- </action>
<action name="action_Configure">
<property name="text">
<string>Configure ...</string>
@@ -220,22 +187,6 @@
</hints>
</connection>
<connection>
- <sender>action_Configure</sender>
- <signal>triggered()</signal>
- <receiver>MainWindow</receiver>
- <slot>OnConfigure()</slot>
- <hints>
- <hint type="sourcelabel">
- <x>-1</x>
- <y>-1</y>
- </hint>
- <hint type="destinationlabel">
- <x>540</x>
- <y>364</y>
- </hint>
- </hints>
- </connection>
- <connection>
<sender>actionDisplay_widget_title_bars</sender>
<signal>triggered(bool)</signal>
<receiver>MainWindow</receiver>
diff --git a/src/citra_qt/ui_settings.cpp b/src/citra_qt/ui_settings.cpp
new file mode 100644
index 000000000..5f2215899
--- /dev/null
+++ b/src/citra_qt/ui_settings.cpp
@@ -0,0 +1,11 @@
+// Copyright 2016 Citra Emulator Project
+// Licensed under GPLv2 or any later version
+// Refer to the license.txt file included.
+
+#include "ui_settings.h"
+
+namespace UISettings {
+
+Values values = {};
+
+}
diff --git a/src/citra_qt/ui_settings.h b/src/citra_qt/ui_settings.h
new file mode 100644
index 000000000..62db4a73e
--- /dev/null
+++ b/src/citra_qt/ui_settings.h
@@ -0,0 +1,47 @@
+// Copyright 2016 Citra Emulator Project
+// Licensed under GPLv2 or any later version
+// Refer to the license.txt file included.
+
+#pragma once
+
+#include <QByteArray>
+#include <QStringList>
+#include <QString>
+
+#include <vector>
+
+namespace UISettings {
+
+using ContextualShortcut = std::pair<QString, int> ;
+using Shortcut = std::pair<QString, ContextualShortcut>;
+
+struct Values {
+ QByteArray geometry;
+ QByteArray state;
+
+ QByteArray renderwindow_geometry;
+
+ QByteArray gamelist_header_state;
+
+ QByteArray microprofile_geometry;
+ bool microprofile_visible;
+
+ bool single_window_mode;
+ bool display_titlebar;
+
+ bool confirm_before_closing;
+ bool first_start;
+
+ QString roms_path;
+ QString symbols_path;
+ QString gamedir;
+ bool gamedir_deepscan;
+ QStringList recent_files;
+
+ // Shortcut name <Shortcut, context>
+ std::vector<Shortcut> shortcuts;
+};
+
+extern Values values;
+
+}