summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
Diffstat (limited to '')
-rw-r--r--src/yuzu/CMakeLists.txt6
-rw-r--r--src/yuzu/applets/profile_select.cpp1
-rw-r--r--src/yuzu/applets/profile_select.h2
-rw-r--r--src/yuzu/configuration/config.cpp59
-rw-r--r--src/yuzu/configuration/config.h3
-rw-r--r--src/yuzu/configuration/configure.ui19
-rw-r--r--src/yuzu/configuration/configure_dialog.cpp16
-rw-r--r--src/yuzu/configuration/configure_dialog.h3
-rw-r--r--src/yuzu/configuration/configure_general.cpp4
-rw-r--r--src/yuzu/configuration/configure_general.h1
-rw-r--r--src/yuzu/configuration/configure_general.ui24
-rw-r--r--src/yuzu/configuration/configure_hotkeys.cpp121
-rw-r--r--src/yuzu/configuration/configure_hotkeys.h48
-rw-r--r--src/yuzu/configuration/configure_hotkeys.ui42
-rw-r--r--src/yuzu/hotkeys.cpp73
-rw-r--r--src/yuzu/hotkeys.h42
-rw-r--r--src/yuzu/hotkeys.ui46
-rw-r--r--src/yuzu/main.cpp53
-rw-r--r--src/yuzu/main.h2
-rw-r--r--src/yuzu/ui_settings.cpp1
-rw-r--r--src/yuzu/ui_settings.h7
-rw-r--r--src/yuzu/util/sequence_dialog/sequence_dialog.cpp37
-rw-r--r--src/yuzu/util/sequence_dialog/sequence_dialog.h24
23 files changed, 426 insertions, 208 deletions
diff --git a/src/yuzu/CMakeLists.txt b/src/yuzu/CMakeLists.txt
index 4cab599b4..732a1bf89 100644
--- a/src/yuzu/CMakeLists.txt
+++ b/src/yuzu/CMakeLists.txt
@@ -31,6 +31,8 @@ add_executable(yuzu
31 configuration/configure_general.h 31 configuration/configure_general.h
32 configuration/configure_graphics.cpp 32 configuration/configure_graphics.cpp
33 configuration/configure_graphics.h 33 configuration/configure_graphics.h
34 configuration/configure_hotkeys.cpp
35 configuration/configure_hotkeys.h
34 configuration/configure_input.cpp 36 configuration/configure_input.cpp
35 configuration/configure_input.h 37 configuration/configure_input.h
36 configuration/configure_input_player.cpp 38 configuration/configure_input_player.cpp
@@ -78,6 +80,8 @@ add_executable(yuzu
78 ui_settings.h 80 ui_settings.h
79 util/limitable_input_dialog.cpp 81 util/limitable_input_dialog.cpp
80 util/limitable_input_dialog.h 82 util/limitable_input_dialog.h
83 util/sequence_dialog/sequence_dialog.cpp
84 util/sequence_dialog/sequence_dialog.h
81 util/spinbox.cpp 85 util/spinbox.cpp
82 util/spinbox.h 86 util/spinbox.h
83 util/util.cpp 87 util/util.cpp
@@ -95,6 +99,7 @@ set(UIS
95 configuration/configure_gamelist.ui 99 configuration/configure_gamelist.ui
96 configuration/configure_general.ui 100 configuration/configure_general.ui
97 configuration/configure_graphics.ui 101 configuration/configure_graphics.ui
102 configuration/configure_hotkeys.ui
98 configuration/configure_input.ui 103 configuration/configure_input.ui
99 configuration/configure_input_player.ui 104 configuration/configure_input_player.ui
100 configuration/configure_input_simple.ui 105 configuration/configure_input_simple.ui
@@ -105,7 +110,6 @@ set(UIS
105 configuration/configure_touchscreen_advanced.ui 110 configuration/configure_touchscreen_advanced.ui
106 configuration/configure_web.ui 111 configuration/configure_web.ui
107 compatdb.ui 112 compatdb.ui
108 hotkeys.ui
109 loading_screen.ui 113 loading_screen.ui
110 main.ui 114 main.ui
111) 115)
diff --git a/src/yuzu/applets/profile_select.cpp b/src/yuzu/applets/profile_select.cpp
index 5c1b65a2c..3a0824547 100644
--- a/src/yuzu/applets/profile_select.cpp
+++ b/src/yuzu/applets/profile_select.cpp
@@ -4,6 +4,7 @@
4 4
5#include <mutex> 5#include <mutex>
6#include <QDialogButtonBox> 6#include <QDialogButtonBox>
7#include <QHeaderView>
7#include <QLabel> 8#include <QLabel>
8#include <QLineEdit> 9#include <QLineEdit>
9#include <QScrollArea> 10#include <QScrollArea>
diff --git a/src/yuzu/applets/profile_select.h b/src/yuzu/applets/profile_select.h
index 868573324..1c2922e54 100644
--- a/src/yuzu/applets/profile_select.h
+++ b/src/yuzu/applets/profile_select.h
@@ -7,6 +7,7 @@
7#include <vector> 7#include <vector>
8#include <QDialog> 8#include <QDialog>
9#include <QList> 9#include <QList>
10#include <QTreeView>
10#include "core/frontend/applets/profile_select.h" 11#include "core/frontend/applets/profile_select.h"
11 12
12class GMainWindow; 13class GMainWindow;
@@ -16,7 +17,6 @@ class QLabel;
16class QScrollArea; 17class QScrollArea;
17class QStandardItem; 18class QStandardItem;
18class QStandardItemModel; 19class QStandardItemModel;
19class QTreeView;
20class QVBoxLayout; 20class QVBoxLayout;
21 21
22class QtProfileSelectionDialog final : public QDialog { 22class QtProfileSelectionDialog final : public QDialog {
diff --git a/src/yuzu/configuration/config.cpp b/src/yuzu/configuration/config.cpp
index 4650f96a3..2e8ebfc12 100644
--- a/src/yuzu/configuration/config.cpp
+++ b/src/yuzu/configuration/config.cpp
@@ -2,6 +2,8 @@
2// Licensed under GPLv2 or any later version 2// Licensed under GPLv2 or any later version
3// Refer to the license.txt file included. 3// Refer to the license.txt file included.
4 4
5#include <array>
6#include <QKeySequence>
5#include <QSettings> 7#include <QSettings>
6#include "common/file_util.h" 8#include "common/file_util.h"
7#include "configure_input_simple.h" 9#include "configure_input_simple.h"
@@ -9,7 +11,6 @@
9#include "core/hle/service/hid/controllers/npad.h" 11#include "core/hle/service/hid/controllers/npad.h"
10#include "input_common/main.h" 12#include "input_common/main.h"
11#include "yuzu/configuration/config.h" 13#include "yuzu/configuration/config.h"
12#include "yuzu/ui_settings.h"
13 14
14Config::Config() { 15Config::Config() {
15 // TODO: Don't hardcode the path; let the frontend decide where to put the config files. 16 // TODO: Don't hardcode the path; let the frontend decide where to put the config files.
@@ -17,7 +18,6 @@ Config::Config() {
17 FileUtil::CreateFullPath(qt_config_loc); 18 FileUtil::CreateFullPath(qt_config_loc);
18 qt_config = 19 qt_config =
19 std::make_unique<QSettings>(QString::fromStdString(qt_config_loc), QSettings::IniFormat); 20 std::make_unique<QSettings>(QString::fromStdString(qt_config_loc), QSettings::IniFormat);
20
21 Reload(); 21 Reload();
22} 22}
23 23
@@ -205,6 +205,27 @@ const std::array<int, Settings::NativeKeyboard::NumKeyboardMods> Config::default
205 Qt::Key_Control, Qt::Key_Shift, Qt::Key_AltGr, Qt::Key_ApplicationRight, 205 Qt::Key_Control, Qt::Key_Shift, Qt::Key_AltGr, Qt::Key_ApplicationRight,
206}; 206};
207 207
208// This shouldn't have anything except static initializers (no functions). So
209// QKeySequnce(...).toString() is NOT ALLOWED HERE.
210// This must be in alphabetical order according to action name as it must have the same order as
211// UISetting::values.shortcuts, which is alphabetically ordered.
212const std::array<UISettings::Shortcut, 15> Config::default_hotkeys{
213 {{"Capture Screenshot", "Main Window", {"Ctrl+P", Qt::ApplicationShortcut}},
214 {"Continue/Pause Emulation", "Main Window", {"F4", Qt::WindowShortcut}},
215 {"Decrease Speed Limit", "Main Window", {"-", Qt::ApplicationShortcut}},
216 {"Exit yuzu", "Main Window", {"Ctrl+Q", Qt::WindowShortcut}},
217 {"Exit Fullscreen", "Main Window", {"Esc", Qt::WindowShortcut}},
218 {"Fullscreen", "Main Window", {"F11", Qt::WindowShortcut}},
219 {"Increase Speed Limit", "Main Window", {"+", Qt::ApplicationShortcut}},
220 {"Load Amiibo", "Main Window", {"F2", Qt::ApplicationShortcut}},
221 {"Load File", "Main Window", {"Ctrl+O", Qt::WindowShortcut}},
222 {"Restart Emulation", "Main Window", {"F6", Qt::WindowShortcut}},
223 {"Stop Emulation", "Main Window", {"F5", Qt::WindowShortcut}},
224 {"Toggle Filter Bar", "Main Window", {"Ctrl+F", Qt::WindowShortcut}},
225 {"Toggle Speed Limit", "Main Window", {"Ctrl+Z", Qt::ApplicationShortcut}},
226 {"Toggle Status Bar", "Main Window", {"Ctrl+S", Qt::WindowShortcut}},
227 {"Change Docked Mode", "Main Window", {"F10", Qt::ApplicationShortcut}}}};
228
208void Config::ReadPlayerValues() { 229void Config::ReadPlayerValues() {
209 for (std::size_t p = 0; p < Settings::values.players.size(); ++p) { 230 for (std::size_t p = 0; p < Settings::values.players.size(); ++p) {
210 auto& player = Settings::values.players[p]; 231 auto& player = Settings::values.players[p];
@@ -509,20 +530,15 @@ void Config::ReadValues() {
509 qt_config->endGroup(); 530 qt_config->endGroup();
510 531
511 qt_config->beginGroup("Shortcuts"); 532 qt_config->beginGroup("Shortcuts");
512 QStringList groups = qt_config->childGroups(); 533 for (auto [name, group, shortcut] : default_hotkeys) {
513 for (auto group : groups) { 534 auto [keyseq, context] = shortcut;
514 qt_config->beginGroup(group); 535 qt_config->beginGroup(group);
515 536 qt_config->beginGroup(name);
516 QStringList hotkeys = qt_config->childGroups(); 537 UISettings::values.shortcuts.push_back(
517 for (auto hotkey : hotkeys) { 538 {name,
518 qt_config->beginGroup(hotkey); 539 group,
519 UISettings::values.shortcuts.emplace_back(UISettings::Shortcut( 540 {ReadSetting("KeySeq", keyseq).toString(), ReadSetting("Context", context).toInt()}});
520 group + "/" + hotkey, 541 qt_config->endGroup();
521 UISettings::ContextualShortcut(ReadSetting("KeySeq").toString(),
522 ReadSetting("Context").toInt())));
523 qt_config->endGroup();
524 }
525
526 qt_config->endGroup(); 542 qt_config->endGroup();
527 } 543 }
528 qt_config->endGroup(); 544 qt_config->endGroup();
@@ -760,9 +776,16 @@ void Config::SaveValues() {
760 qt_config->endGroup(); 776 qt_config->endGroup();
761 777
762 qt_config->beginGroup("Shortcuts"); 778 qt_config->beginGroup("Shortcuts");
763 for (auto shortcut : UISettings::values.shortcuts) { 779 // Lengths of UISettings::values.shortcuts & default_hotkeys are same.
764 WriteSetting(shortcut.first + "/KeySeq", shortcut.second.first); 780 // However, their ordering must also be the same.
765 WriteSetting(shortcut.first + "/Context", shortcut.second.second); 781 for (std::size_t i = 0; i < default_hotkeys.size(); i++) {
782 auto [name, group, shortcut] = UISettings::values.shortcuts[i];
783 qt_config->beginGroup(group);
784 qt_config->beginGroup(name);
785 WriteSetting("KeySeq", shortcut.first, default_hotkeys[i].shortcut.first);
786 WriteSetting("Context", shortcut.second, default_hotkeys[i].shortcut.second);
787 qt_config->endGroup();
788 qt_config->endGroup();
766 } 789 }
767 qt_config->endGroup(); 790 qt_config->endGroup();
768 791
diff --git a/src/yuzu/configuration/config.h b/src/yuzu/configuration/config.h
index f4185db18..221d2364c 100644
--- a/src/yuzu/configuration/config.h
+++ b/src/yuzu/configuration/config.h
@@ -9,6 +9,7 @@
9#include <string> 9#include <string>
10#include <QVariant> 10#include <QVariant>
11#include "core/settings.h" 11#include "core/settings.h"
12#include "yuzu/ui_settings.h"
12 13
13class QSettings; 14class QSettings;
14 15
@@ -47,6 +48,8 @@ private:
47 void WriteSetting(const QString& name, const QVariant& value); 48 void WriteSetting(const QString& name, const QVariant& value);
48 void WriteSetting(const QString& name, const QVariant& value, const QVariant& default_value); 49 void WriteSetting(const QString& name, const QVariant& value, const QVariant& default_value);
49 50
51 static const std::array<UISettings::Shortcut, 15> default_hotkeys;
52
50 std::unique_ptr<QSettings> qt_config; 53 std::unique_ptr<QSettings> qt_config;
51 std::string qt_config_loc; 54 std::string qt_config_loc;
52}; 55};
diff --git a/src/yuzu/configuration/configure.ui b/src/yuzu/configuration/configure.ui
index 3f03f0b77..267717bc9 100644
--- a/src/yuzu/configuration/configure.ui
+++ b/src/yuzu/configuration/configure.ui
@@ -7,9 +7,15 @@
7 <x>0</x> 7 <x>0</x>
8 <y>0</y> 8 <y>0</y>
9 <width>382</width> 9 <width>382</width>
10 <height>241</height> 10 <height>650</height>
11 </rect> 11 </rect>
12 </property> 12 </property>
13 <property name="minimumSize">
14 <size>
15 <width>0</width>
16 <height>650</height>
17 </size>
18 </property>
13 <property name="windowTitle"> 19 <property name="windowTitle">
14 <string>yuzu Configuration</string> 20 <string>yuzu Configuration</string>
15 </property> 21 </property>
@@ -62,6 +68,11 @@
62 <string>Input</string> 68 <string>Input</string>
63 </attribute> 69 </attribute>
64 </widget> 70 </widget>
71 <widget class="ConfigureHotkeys" name="hotkeysTab">
72 <attribute name="title">
73 <string>Hotkeys</string>
74 </attribute>
75 </widget>
65 <widget class="ConfigureGraphics" name="graphicsTab"> 76 <widget class="ConfigureGraphics" name="graphicsTab">
66 <attribute name="title"> 77 <attribute name="title">
67 <string>Graphics</string> 78 <string>Graphics</string>
@@ -150,6 +161,12 @@
150 <header>configuration/configure_input_simple.h</header> 161 <header>configuration/configure_input_simple.h</header>
151 <container>1</container> 162 <container>1</container>
152 </customwidget> 163 </customwidget>
164 <customwidget>
165 <class>ConfigureHotkeys</class>
166 <extends>QWidget</extends>
167 <header>configuration/configure_hotkeys.h</header>
168 <container>1</container>
169 </customwidget>
153 </customwidgets> 170 </customwidgets>
154 <resources/> 171 <resources/>
155 <connections> 172 <connections>
diff --git a/src/yuzu/configuration/configure_dialog.cpp b/src/yuzu/configuration/configure_dialog.cpp
index 777050405..51bd1f121 100644
--- a/src/yuzu/configuration/configure_dialog.cpp
+++ b/src/yuzu/configuration/configure_dialog.cpp
@@ -8,20 +8,22 @@
8#include "ui_configure.h" 8#include "ui_configure.h"
9#include "yuzu/configuration/config.h" 9#include "yuzu/configuration/config.h"
10#include "yuzu/configuration/configure_dialog.h" 10#include "yuzu/configuration/configure_dialog.h"
11#include "yuzu/configuration/configure_input_player.h"
11#include "yuzu/hotkeys.h" 12#include "yuzu/hotkeys.h"
12 13
13ConfigureDialog::ConfigureDialog(QWidget* parent, const HotkeyRegistry& registry) 14ConfigureDialog::ConfigureDialog(QWidget* parent, HotkeyRegistry& registry)
14 : QDialog(parent), ui(new Ui::ConfigureDialog) { 15 : QDialog(parent), registry(registry), ui(new Ui::ConfigureDialog) {
15 ui->setupUi(this); 16 ui->setupUi(this);
16 ui->generalTab->PopulateHotkeyList(registry); 17 ui->hotkeysTab->Populate(registry);
17 this->setConfiguration(); 18 this->setConfiguration();
18 this->PopulateSelectionList(); 19 this->PopulateSelectionList();
19 connect(ui->selectorList, &QListWidget::itemSelectionChanged, this, 20 connect(ui->selectorList, &QListWidget::itemSelectionChanged, this,
20 &ConfigureDialog::UpdateVisibleTabs); 21 &ConfigureDialog::UpdateVisibleTabs);
21
22 adjustSize(); 22 adjustSize();
23
24 ui->selectorList->setCurrentRow(0); 23 ui->selectorList->setCurrentRow(0);
24
25 // Synchronise lists upon initialisation
26 ui->hotkeysTab->EmitHotkeysChanged();
25} 27}
26 28
27ConfigureDialog::~ConfigureDialog() = default; 29ConfigureDialog::~ConfigureDialog() = default;
@@ -34,6 +36,7 @@ void ConfigureDialog::applyConfiguration() {
34 ui->systemTab->applyConfiguration(); 36 ui->systemTab->applyConfiguration();
35 ui->profileManagerTab->applyConfiguration(); 37 ui->profileManagerTab->applyConfiguration();
36 ui->inputTab->applyConfiguration(); 38 ui->inputTab->applyConfiguration();
39 ui->hotkeysTab->applyConfiguration(registry);
37 ui->graphicsTab->applyConfiguration(); 40 ui->graphicsTab->applyConfiguration();
38 ui->audioTab->applyConfiguration(); 41 ui->audioTab->applyConfiguration();
39 ui->debugTab->applyConfiguration(); 42 ui->debugTab->applyConfiguration();
@@ -47,7 +50,7 @@ void ConfigureDialog::PopulateSelectionList() {
47 {{tr("General"), {tr("General"), tr("Web"), tr("Debug"), tr("Game List")}}, 50 {{tr("General"), {tr("General"), tr("Web"), tr("Debug"), tr("Game List")}},
48 {tr("System"), {tr("System"), tr("Profiles"), tr("Audio")}}, 51 {tr("System"), {tr("System"), tr("Profiles"), tr("Audio")}},
49 {tr("Graphics"), {tr("Graphics")}}, 52 {tr("Graphics"), {tr("Graphics")}},
50 {tr("Controls"), {tr("Input")}}}}; 53 {tr("Controls"), {tr("Input"), tr("Hotkeys")}}}};
51 54
52 for (const auto& entry : items) { 55 for (const auto& entry : items) {
53 auto* const item = new QListWidgetItem(entry.first); 56 auto* const item = new QListWidgetItem(entry.first);
@@ -66,6 +69,7 @@ void ConfigureDialog::UpdateVisibleTabs() {
66 {tr("System"), ui->systemTab}, 69 {tr("System"), ui->systemTab},
67 {tr("Profiles"), ui->profileManagerTab}, 70 {tr("Profiles"), ui->profileManagerTab},
68 {tr("Input"), ui->inputTab}, 71 {tr("Input"), ui->inputTab},
72 {tr("Hotkeys"), ui->hotkeysTab},
69 {tr("Graphics"), ui->graphicsTab}, 73 {tr("Graphics"), ui->graphicsTab},
70 {tr("Audio"), ui->audioTab}, 74 {tr("Audio"), ui->audioTab},
71 {tr("Debug"), ui->debugTab}, 75 {tr("Debug"), ui->debugTab},
diff --git a/src/yuzu/configuration/configure_dialog.h b/src/yuzu/configuration/configure_dialog.h
index 243d9fa09..2363ba584 100644
--- a/src/yuzu/configuration/configure_dialog.h
+++ b/src/yuzu/configuration/configure_dialog.h
@@ -17,7 +17,7 @@ class ConfigureDialog : public QDialog {
17 Q_OBJECT 17 Q_OBJECT
18 18
19public: 19public:
20 explicit ConfigureDialog(QWidget* parent, const HotkeyRegistry& registry); 20 explicit ConfigureDialog(QWidget* parent, HotkeyRegistry& registry);
21 ~ConfigureDialog() override; 21 ~ConfigureDialog() override;
22 22
23 void applyConfiguration(); 23 void applyConfiguration();
@@ -28,4 +28,5 @@ private:
28 void PopulateSelectionList(); 28 void PopulateSelectionList();
29 29
30 std::unique_ptr<Ui::ConfigureDialog> ui; 30 std::unique_ptr<Ui::ConfigureDialog> ui;
31 HotkeyRegistry& registry;
31}; 32};
diff --git a/src/yuzu/configuration/configure_general.cpp b/src/yuzu/configuration/configure_general.cpp
index 4116b6cd7..81a60da08 100644
--- a/src/yuzu/configuration/configure_general.cpp
+++ b/src/yuzu/configuration/configure_general.cpp
@@ -36,10 +36,6 @@ void ConfigureGeneral::setConfiguration() {
36 ui->enable_nfc->setChecked(Settings::values.enable_nfc); 36 ui->enable_nfc->setChecked(Settings::values.enable_nfc);
37} 37}
38 38
39void ConfigureGeneral::PopulateHotkeyList(const HotkeyRegistry& registry) {
40 ui->widget->Populate(registry);
41}
42
43void ConfigureGeneral::applyConfiguration() { 39void ConfigureGeneral::applyConfiguration() {
44 UISettings::values.gamedir_deepscan = ui->toggle_deepscan->isChecked(); 40 UISettings::values.gamedir_deepscan = ui->toggle_deepscan->isChecked();
45 UISettings::values.confirm_before_closing = ui->toggle_check_exit->isChecked(); 41 UISettings::values.confirm_before_closing = ui->toggle_check_exit->isChecked();
diff --git a/src/yuzu/configuration/configure_general.h b/src/yuzu/configuration/configure_general.h
index 59738af40..df41d995b 100644
--- a/src/yuzu/configuration/configure_general.h
+++ b/src/yuzu/configuration/configure_general.h
@@ -20,7 +20,6 @@ public:
20 explicit ConfigureGeneral(QWidget* parent = nullptr); 20 explicit ConfigureGeneral(QWidget* parent = nullptr);
21 ~ConfigureGeneral() override; 21 ~ConfigureGeneral() override;
22 22
23 void PopulateHotkeyList(const HotkeyRegistry& registry);
24 void applyConfiguration(); 23 void applyConfiguration();
25 24
26private: 25private:
diff --git a/src/yuzu/configuration/configure_general.ui b/src/yuzu/configuration/configure_general.ui
index dff0ad5d0..879ef747f 100644
--- a/src/yuzu/configuration/configure_general.ui
+++ b/src/yuzu/configuration/configure_general.ui
@@ -118,22 +118,6 @@
118 </widget> 118 </widget>
119 </item> 119 </item>
120 <item> 120 <item>
121 <widget class="QGroupBox" name="HotKeysGroupBox">
122 <property name="title">
123 <string>Hotkeys</string>
124 </property>
125 <layout class="QHBoxLayout" name="HotKeysHorizontalLayout">
126 <item>
127 <layout class="QVBoxLayout" name="HotKeysVerticalLayout">
128 <item>
129 <widget class="GHotkeysDialog" name="widget" native="true"/>
130 </item>
131 </layout>
132 </item>
133 </layout>
134 </widget>
135 </item>
136 <item>
137 <spacer name="verticalSpacer"> 121 <spacer name="verticalSpacer">
138 <property name="orientation"> 122 <property name="orientation">
139 <enum>Qt::Vertical</enum> 123 <enum>Qt::Vertical</enum>
@@ -150,14 +134,6 @@
150 </item> 134 </item>
151 </layout> 135 </layout>
152 </widget> 136 </widget>
153 <customwidgets>
154 <customwidget>
155 <class>GHotkeysDialog</class>
156 <extends>QWidget</extends>
157 <header>hotkeys.h</header>
158 <container>1</container>
159 </customwidget>
160 </customwidgets>
161 <resources/> 137 <resources/>
162 <connections/> 138 <connections/>
163</ui> 139</ui>
diff --git a/src/yuzu/configuration/configure_hotkeys.cpp b/src/yuzu/configuration/configure_hotkeys.cpp
new file mode 100644
index 000000000..bfb562535
--- /dev/null
+++ b/src/yuzu/configuration/configure_hotkeys.cpp
@@ -0,0 +1,121 @@
1// Copyright 2017 Citra Emulator Project
2// Licensed under GPLv2 or any later version
3// Refer to the license.txt file included.
4
5#include <QMessageBox>
6#include <QStandardItemModel>
7#include "core/settings.h"
8#include "ui_configure_hotkeys.h"
9#include "yuzu/configuration/configure_hotkeys.h"
10#include "yuzu/hotkeys.h"
11#include "yuzu/util/sequence_dialog/sequence_dialog.h"
12
13ConfigureHotkeys::ConfigureHotkeys(QWidget* parent)
14 : QWidget(parent), ui(std::make_unique<Ui::ConfigureHotkeys>()) {
15 ui->setupUi(this);
16 setFocusPolicy(Qt::ClickFocus);
17
18 model = new QStandardItemModel(this);
19 model->setColumnCount(3);
20 model->setHorizontalHeaderLabels({tr("Action"), tr("Hotkey"), tr("Context")});
21
22 connect(ui->hotkey_list, &QTreeView::doubleClicked, this, &ConfigureHotkeys::Configure);
23 ui->hotkey_list->setModel(model);
24
25 // TODO(Kloen): Make context configurable as well (hiding the column for now)
26 ui->hotkey_list->hideColumn(2);
27
28 ui->hotkey_list->setColumnWidth(0, 200);
29 ui->hotkey_list->resizeColumnToContents(1);
30}
31
32ConfigureHotkeys::~ConfigureHotkeys() = default;
33
34void ConfigureHotkeys::EmitHotkeysChanged() {
35 emit HotkeysChanged(GetUsedKeyList());
36}
37
38QList<QKeySequence> ConfigureHotkeys::GetUsedKeyList() const {
39 QList<QKeySequence> list;
40 for (int r = 0; r < model->rowCount(); r++) {
41 const QStandardItem* parent = model->item(r, 0);
42 for (int r2 = 0; r2 < parent->rowCount(); r2++) {
43 const QStandardItem* keyseq = parent->child(r2, 1);
44 list << QKeySequence::fromString(keyseq->text(), QKeySequence::NativeText);
45 }
46 }
47 return list;
48}
49
50void ConfigureHotkeys::Populate(const HotkeyRegistry& registry) {
51 for (const auto& group : registry.hotkey_groups) {
52 auto* parent_item = new QStandardItem(group.first);
53 parent_item->setEditable(false);
54 for (const auto& hotkey : group.second) {
55 auto* action = new QStandardItem(hotkey.first);
56 auto* keyseq =
57 new QStandardItem(hotkey.second.keyseq.toString(QKeySequence::NativeText));
58 action->setEditable(false);
59 keyseq->setEditable(false);
60 parent_item->appendRow({action, keyseq});
61 }
62 model->appendRow(parent_item);
63 }
64
65 ui->hotkey_list->expandAll();
66}
67
68void ConfigureHotkeys::Configure(QModelIndex index) {
69 if (index.parent() == QModelIndex())
70 return;
71
72 index = index.sibling(index.row(), 1);
73 auto* model = ui->hotkey_list->model();
74 auto previous_key = model->data(index);
75
76 auto* hotkey_dialog = new SequenceDialog;
77 int return_code = hotkey_dialog->exec();
78
79 auto key_sequence = hotkey_dialog->GetSequence();
80
81 if (return_code == QDialog::Rejected || key_sequence.isEmpty())
82 return;
83
84 if (IsUsedKey(key_sequence) && key_sequence != QKeySequence(previous_key.toString())) {
85 QMessageBox::critical(this, tr("Error in inputted key"),
86 tr("You're using a key that's already bound."));
87 } else {
88 model->setData(index, key_sequence.toString(QKeySequence::NativeText));
89 EmitHotkeysChanged();
90 }
91}
92
93bool ConfigureHotkeys::IsUsedKey(QKeySequence key_sequence) {
94 return GetUsedKeyList().contains(key_sequence);
95}
96
97void ConfigureHotkeys::applyConfiguration(HotkeyRegistry& registry) {
98 for (int key_id = 0; key_id < model->rowCount(); key_id++) {
99 const QStandardItem* parent = model->item(key_id, 0);
100 for (int key_column_id = 0; key_column_id < parent->rowCount(); key_column_id++) {
101 const QStandardItem* action = parent->child(key_column_id, 0);
102 const QStandardItem* keyseq = parent->child(key_column_id, 1);
103 for (auto& [group, sub_actions] : registry.hotkey_groups) {
104 if (group != parent->text())
105 continue;
106 for (auto& [action_name, hotkey] : sub_actions) {
107 if (action_name != action->text())
108 continue;
109 hotkey.keyseq = QKeySequence(keyseq->text());
110 }
111 }
112 }
113 }
114
115 registry.SaveHotkeys();
116 Settings::Apply();
117}
118
119void ConfigureHotkeys::retranslateUi() {
120 ui->retranslateUi(this);
121}
diff --git a/src/yuzu/configuration/configure_hotkeys.h b/src/yuzu/configuration/configure_hotkeys.h
new file mode 100644
index 000000000..cd203aad6
--- /dev/null
+++ b/src/yuzu/configuration/configure_hotkeys.h
@@ -0,0 +1,48 @@
1// Copyright 2017 Citra Emulator Project
2// Licensed under GPLv2 or any later version
3// Refer to the license.txt file included.
4
5#pragma once
6
7#include <memory>
8#include <QWidget>
9#include "core/settings.h"
10
11namespace Ui {
12class ConfigureHotkeys;
13}
14
15class HotkeyRegistry;
16class QStandardItemModel;
17
18class ConfigureHotkeys : public QWidget {
19 Q_OBJECT
20
21public:
22 explicit ConfigureHotkeys(QWidget* parent = nullptr);
23 ~ConfigureHotkeys() override;
24
25 void applyConfiguration(HotkeyRegistry& registry);
26 void retranslateUi();
27
28 void EmitHotkeysChanged();
29
30 /**
31 * Populates the hotkey list widget using data from the provided registry.
32 * Called everytime the Configure dialog is opened.
33 * @param registry The HotkeyRegistry whose data is used to populate the list.
34 */
35 void Populate(const HotkeyRegistry& registry);
36
37signals:
38 void HotkeysChanged(QList<QKeySequence> new_key_list);
39
40private:
41 void Configure(QModelIndex index);
42 bool IsUsedKey(QKeySequence key_sequence);
43 QList<QKeySequence> GetUsedKeyList() const;
44
45 std::unique_ptr<Ui::ConfigureHotkeys> ui;
46
47 QStandardItemModel* model;
48};
diff --git a/src/yuzu/configuration/configure_hotkeys.ui b/src/yuzu/configuration/configure_hotkeys.ui
new file mode 100644
index 000000000..0d0b70f38
--- /dev/null
+++ b/src/yuzu/configuration/configure_hotkeys.ui
@@ -0,0 +1,42 @@
1<?xml version="1.0" encoding="UTF-8"?>
2<ui version="4.0">
3 <class>ConfigureHotkeys</class>
4 <widget class="QWidget" name="ConfigureHotkeys">
5 <property name="geometry">
6 <rect>
7 <x>0</x>
8 <y>0</y>
9 <width>363</width>
10 <height>388</height>
11 </rect>
12 </property>
13 <property name="windowTitle">
14 <string>Hotkey Settings</string>
15 </property>
16 <layout class="QVBoxLayout" name="verticalLayout">
17 <item>
18 <layout class="QVBoxLayout" name="verticalLayout_2">
19 <item>
20 <widget class="QLabel" name="label_2">
21 <property name="text">
22 <string>Double-click on a binding to change it.</string>
23 </property>
24 </widget>
25 </item>
26 <item>
27 <widget class="QTreeView" name="hotkey_list">
28 <property name="editTriggers">
29 <set>QAbstractItemView::NoEditTriggers</set>
30 </property>
31 <property name="sortingEnabled">
32 <bool>false</bool>
33 </property>
34 </widget>
35 </item>
36 </layout>
37 </item>
38 </layout>
39 </widget>
40 <resources/>
41 <connections/>
42</ui> \ No newline at end of file
diff --git a/src/yuzu/hotkeys.cpp b/src/yuzu/hotkeys.cpp
index dce399774..4582e7f21 100644
--- a/src/yuzu/hotkeys.cpp
+++ b/src/yuzu/hotkeys.cpp
@@ -2,7 +2,6 @@
2// Licensed under GPLv2 or any later version 2// Licensed under GPLv2 or any later version
3// Refer to the license.txt file included. 3// Refer to the license.txt file included.
4 4
5#include <map>
6#include <QKeySequence> 5#include <QKeySequence>
7#include <QShortcut> 6#include <QShortcut>
8#include <QTreeWidgetItem> 7#include <QTreeWidgetItem>
@@ -13,47 +12,32 @@
13HotkeyRegistry::HotkeyRegistry() = default; 12HotkeyRegistry::HotkeyRegistry() = default;
14HotkeyRegistry::~HotkeyRegistry() = default; 13HotkeyRegistry::~HotkeyRegistry() = default;
15 14
16void HotkeyRegistry::LoadHotkeys() {
17 // Make sure NOT to use a reference here because it would become invalid once we call
18 // beginGroup()
19 for (auto shortcut : UISettings::values.shortcuts) {
20 const QStringList cat = shortcut.first.split('/');
21 Q_ASSERT(cat.size() >= 2);
22
23 // RegisterHotkey assigns default keybindings, so use old values as default parameters
24 Hotkey& hk = hotkey_groups[cat[0]][cat[1]];
25 if (!shortcut.second.first.isEmpty()) {
26 hk.keyseq = QKeySequence::fromString(shortcut.second.first);
27 hk.context = static_cast<Qt::ShortcutContext>(shortcut.second.second);
28 }
29 if (hk.shortcut)
30 hk.shortcut->setKey(hk.keyseq);
31 }
32}
33
34void HotkeyRegistry::SaveHotkeys() { 15void HotkeyRegistry::SaveHotkeys() {
35 UISettings::values.shortcuts.clear(); 16 UISettings::values.shortcuts.clear();
36 for (const auto& group : hotkey_groups) { 17 for (const auto& group : hotkey_groups) {
37 for (const auto& hotkey : group.second) { 18 for (const auto& hotkey : group.second) {
38 UISettings::values.shortcuts.emplace_back( 19 UISettings::values.shortcuts.push_back(
39 UISettings::Shortcut(group.first + '/' + hotkey.first, 20 {hotkey.first, group.first,
40 UISettings::ContextualShortcut(hotkey.second.keyseq.toString(), 21 UISettings::ContextualShortcut(hotkey.second.keyseq.toString(),
41 hotkey.second.context))); 22 hotkey.second.context)});
42 } 23 }
43 } 24 }
44} 25}
45 26
46void HotkeyRegistry::RegisterHotkey(const QString& group, const QString& action, 27void HotkeyRegistry::LoadHotkeys() {
47 const QKeySequence& default_keyseq, 28 // Make sure NOT to use a reference here because it would become invalid once we call
48 Qt::ShortcutContext default_context) { 29 // beginGroup()
49 auto& hotkey_group = hotkey_groups[group]; 30 for (auto shortcut : UISettings::values.shortcuts) {
50 if (hotkey_group.find(action) != hotkey_group.end()) { 31 Hotkey& hk = hotkey_groups[shortcut.group][shortcut.name];
51 return; 32 if (!shortcut.shortcut.first.isEmpty()) {
33 hk.keyseq = QKeySequence::fromString(shortcut.shortcut.first, QKeySequence::NativeText);
34 hk.context = static_cast<Qt::ShortcutContext>(shortcut.shortcut.second);
35 }
36 if (hk.shortcut) {
37 hk.shortcut->disconnect();
38 hk.shortcut->setKey(hk.keyseq);
39 }
52 } 40 }
53
54 auto& hotkey_action = hotkey_groups[group][action];
55 hotkey_action.keyseq = default_keyseq;
56 hotkey_action.context = default_context;
57} 41}
58 42
59QShortcut* HotkeyRegistry::GetHotkey(const QString& group, const QString& action, QWidget* widget) { 43QShortcut* HotkeyRegistry::GetHotkey(const QString& group, const QString& action, QWidget* widget) {
@@ -65,24 +49,11 @@ QShortcut* HotkeyRegistry::GetHotkey(const QString& group, const QString& action
65 return hk.shortcut; 49 return hk.shortcut;
66} 50}
67 51
68GHotkeysDialog::GHotkeysDialog(QWidget* parent) : QWidget(parent) { 52QKeySequence HotkeyRegistry::GetKeySequence(const QString& group, const QString& action) {
69 ui.setupUi(this); 53 return hotkey_groups[group][action].keyseq;
70} 54}
71 55
72void GHotkeysDialog::Populate(const HotkeyRegistry& registry) { 56Qt::ShortcutContext HotkeyRegistry::GetShortcutContext(const QString& group,
73 for (const auto& group : registry.hotkey_groups) { 57 const QString& action) {
74 QTreeWidgetItem* toplevel_item = new QTreeWidgetItem(QStringList(group.first)); 58 return hotkey_groups[group][action].context;
75 for (const auto& hotkey : group.second) {
76 QStringList columns;
77 columns << hotkey.first << hotkey.second.keyseq.toString();
78 QTreeWidgetItem* item = new QTreeWidgetItem(columns);
79 toplevel_item->addChild(item);
80 }
81 ui.treeWidget->addTopLevelItem(toplevel_item);
82 }
83 // TODO: Make context configurable as well (hiding the column for now)
84 ui.treeWidget->setColumnCount(2);
85
86 ui.treeWidget->resizeColumnToContents(0);
87 ui.treeWidget->resizeColumnToContents(1);
88} 59}
diff --git a/src/yuzu/hotkeys.h b/src/yuzu/hotkeys.h
index f38e6c002..4f526dc7e 100644
--- a/src/yuzu/hotkeys.h
+++ b/src/yuzu/hotkeys.h
@@ -5,7 +5,6 @@
5#pragma once 5#pragma once
6 6
7#include <map> 7#include <map>
8#include "ui_hotkeys.h"
9 8
10class QDialog; 9class QDialog;
11class QKeySequence; 10class QKeySequence;
@@ -14,7 +13,7 @@ class QShortcut;
14 13
15class HotkeyRegistry final { 14class HotkeyRegistry final {
16public: 15public:
17 friend class GHotkeysDialog; 16 friend class ConfigureHotkeys;
18 17
19 explicit HotkeyRegistry(); 18 explicit HotkeyRegistry();
20 ~HotkeyRegistry(); 19 ~HotkeyRegistry();
@@ -49,22 +48,27 @@ public:
49 QShortcut* GetHotkey(const QString& group, const QString& action, QWidget* widget); 48 QShortcut* GetHotkey(const QString& group, const QString& action, QWidget* widget);
50 49
51 /** 50 /**
52 * Register a hotkey. 51 * Returns a QKeySequence object whose signal can be connected to QAction::setShortcut.
53 * 52 *
54 * @param group General group this hotkey belongs to (e.g. "Main Window", "Debugger") 53 * @param group General group this hotkey belongs to (e.g. "Main Window", "Debugger").
55 * @param action Name of the action (e.g. "Start Emulation", "Load Image") 54 * @param action Name of the action (e.g. "Start Emulation", "Load Image").
56 * @param default_keyseq Default key sequence to assign if the hotkey wasn't present in the 55 */
57 * settings file before 56 QKeySequence GetKeySequence(const QString& group, const QString& action);
58 * @param default_context Default context to assign if the hotkey wasn't present in the settings 57
59 * file before 58 /**
60 * @warning Both the group and action strings will be displayed in the hotkey settings dialog 59 * Returns a Qt::ShortcutContext object who can be connected to other
60 * QAction::setShortcutContext.
61 *
62 * @param group General group this shortcut context belongs to (e.g. "Main Window",
63 * "Debugger").
64 * @param action Name of the action (e.g. "Start Emulation", "Load Image").
61 */ 65 */
62 void RegisterHotkey(const QString& group, const QString& action, 66 Qt::ShortcutContext GetShortcutContext(const QString& group, const QString& action);
63 const QKeySequence& default_keyseq = {},
64 Qt::ShortcutContext default_context = Qt::WindowShortcut);
65 67
66private: 68private:
67 struct Hotkey { 69 struct Hotkey {
70 Hotkey() : shortcut(nullptr), context(Qt::WindowShortcut) {}
71
68 QKeySequence keyseq; 72 QKeySequence keyseq;
69 QShortcut* shortcut = nullptr; 73 QShortcut* shortcut = nullptr;
70 Qt::ShortcutContext context = Qt::WindowShortcut; 74 Qt::ShortcutContext context = Qt::WindowShortcut;
@@ -75,15 +79,3 @@ private:
75 79
76 HotkeyGroupMap hotkey_groups; 80 HotkeyGroupMap hotkey_groups;
77}; 81};
78
79class GHotkeysDialog : public QWidget {
80 Q_OBJECT
81
82public:
83 explicit GHotkeysDialog(QWidget* parent = nullptr);
84
85 void Populate(const HotkeyRegistry& registry);
86
87private:
88 Ui::hotkeys ui;
89};
diff --git a/src/yuzu/hotkeys.ui b/src/yuzu/hotkeys.ui
deleted file mode 100644
index 050fe064e..000000000
--- a/src/yuzu/hotkeys.ui
+++ /dev/null
@@ -1,46 +0,0 @@
1<?xml version="1.0" encoding="UTF-8"?>
2<ui version="4.0">
3 <class>hotkeys</class>
4 <widget class="QWidget" name="hotkeys">
5 <property name="geometry">
6 <rect>
7 <x>0</x>
8 <y>0</y>
9 <width>363</width>
10 <height>388</height>
11 </rect>
12 </property>
13 <property name="windowTitle">
14 <string>Hotkey Settings</string>
15 </property>
16 <layout class="QVBoxLayout" name="verticalLayout">
17 <item>
18 <widget class="QTreeWidget" name="treeWidget">
19 <property name="selectionBehavior">
20 <enum>QAbstractItemView::SelectItems</enum>
21 </property>
22 <property name="headerHidden">
23 <bool>false</bool>
24 </property>
25 <column>
26 <property name="text">
27 <string>Action</string>
28 </property>
29 </column>
30 <column>
31 <property name="text">
32 <string>Hotkey</string>
33 </property>
34 </column>
35 <column>
36 <property name="text">
37 <string>Context</string>
38 </property>
39 </column>
40 </widget>
41 </item>
42 </layout>
43 </widget>
44 <resources/>
45 <connections/>
46</ui>
diff --git a/src/yuzu/main.cpp b/src/yuzu/main.cpp
index 41ba3c4c6..0bda2239f 100644
--- a/src/yuzu/main.cpp
+++ b/src/yuzu/main.cpp
@@ -511,33 +511,34 @@ void GMainWindow::InitializeRecentFileMenuActions() {
511} 511}
512 512
513void GMainWindow::InitializeHotkeys() { 513void GMainWindow::InitializeHotkeys() {
514 hotkey_registry.RegisterHotkey("Main Window", "Load File", QKeySequence::Open);
515 hotkey_registry.RegisterHotkey("Main Window", "Start Emulation");
516 hotkey_registry.RegisterHotkey("Main Window", "Continue/Pause", QKeySequence(Qt::Key_F4));
517 hotkey_registry.RegisterHotkey("Main Window", "Restart", QKeySequence(Qt::Key_F5));
518 hotkey_registry.RegisterHotkey("Main Window", "Fullscreen", QKeySequence::FullScreen);
519 hotkey_registry.RegisterHotkey("Main Window", "Exit Fullscreen", QKeySequence(Qt::Key_Escape),
520 Qt::ApplicationShortcut);
521 hotkey_registry.RegisterHotkey("Main Window", "Toggle Speed Limit", QKeySequence("CTRL+Z"),
522 Qt::ApplicationShortcut);
523 hotkey_registry.RegisterHotkey("Main Window", "Increase Speed Limit", QKeySequence("+"),
524 Qt::ApplicationShortcut);
525 hotkey_registry.RegisterHotkey("Main Window", "Decrease Speed Limit", QKeySequence("-"),
526 Qt::ApplicationShortcut);
527 hotkey_registry.RegisterHotkey("Main Window", "Load Amiibo", QKeySequence(Qt::Key_F2),
528 Qt::ApplicationShortcut);
529 hotkey_registry.RegisterHotkey("Main Window", "Capture Screenshot",
530 QKeySequence(QKeySequence::Print));
531 hotkey_registry.RegisterHotkey("Main Window", "Change Docked Mode", QKeySequence(Qt::Key_F10));
532
533 hotkey_registry.LoadHotkeys(); 514 hotkey_registry.LoadHotkeys();
534 515
516 ui.action_Load_File->setShortcut(hotkey_registry.GetKeySequence("Main Window", "Load File"));
517 ui.action_Load_File->setShortcutContext(
518 hotkey_registry.GetShortcutContext("Main Window", "Load File"));
519
520 ui.action_Exit->setShortcut(hotkey_registry.GetKeySequence("Main Window", "Exit yuzu"));
521 ui.action_Exit->setShortcutContext(
522 hotkey_registry.GetShortcutContext("Main Window", "Exit yuzu"));
523
524 ui.action_Stop->setShortcut(hotkey_registry.GetKeySequence("Main Window", "Stop Emulation"));
525 ui.action_Stop->setShortcutContext(
526 hotkey_registry.GetShortcutContext("Main Window", "Stop Emulation"));
527
528 ui.action_Show_Filter_Bar->setShortcut(
529 hotkey_registry.GetKeySequence("Main Window", "Toggle Filter Bar"));
530 ui.action_Show_Filter_Bar->setShortcutContext(
531 hotkey_registry.GetShortcutContext("Main Window", "Toggle Filter Bar"));
532
533 ui.action_Show_Status_Bar->setShortcut(
534 hotkey_registry.GetKeySequence("Main Window", "Toggle Status Bar"));
535 ui.action_Show_Status_Bar->setShortcutContext(
536 hotkey_registry.GetShortcutContext("Main Window", "Toggle Status Bar"));
537
535 connect(hotkey_registry.GetHotkey("Main Window", "Load File", this), &QShortcut::activated, 538 connect(hotkey_registry.GetHotkey("Main Window", "Load File", this), &QShortcut::activated,
536 this, &GMainWindow::OnMenuLoadFile); 539 this, &GMainWindow::OnMenuLoadFile);
537 connect(hotkey_registry.GetHotkey("Main Window", "Start Emulation", this), 540 connect(hotkey_registry.GetHotkey("Main Window", "Continue/Pause Emulation", this),
538 &QShortcut::activated, this, &GMainWindow::OnStartGame); 541 &QShortcut::activated, this, [&] {
539 connect(hotkey_registry.GetHotkey("Main Window", "Continue/Pause", this), &QShortcut::activated,
540 this, [&] {
541 if (emulation_running) { 542 if (emulation_running) {
542 if (emu_thread->IsRunning()) { 543 if (emu_thread->IsRunning()) {
543 OnPauseGame(); 544 OnPauseGame();
@@ -546,8 +547,8 @@ void GMainWindow::InitializeHotkeys() {
546 } 547 }
547 } 548 }
548 }); 549 });
549 connect(hotkey_registry.GetHotkey("Main Window", "Restart", this), &QShortcut::activated, this, 550 connect(hotkey_registry.GetHotkey("Main Window", "Restart Emulation", this),
550 [this] { 551 &QShortcut::activated, this, [this] {
551 if (!Core::System::GetInstance().IsPoweredOn()) 552 if (!Core::System::GetInstance().IsPoweredOn())
552 return; 553 return;
553 BootGame(QString(game_path)); 554 BootGame(QString(game_path));
@@ -692,7 +693,6 @@ void GMainWindow::ConnectMenuEvents() {
692 &GMainWindow::ToggleWindowMode); 693 &GMainWindow::ToggleWindowMode);
693 connect(ui.action_Display_Dock_Widget_Headers, &QAction::triggered, this, 694 connect(ui.action_Display_Dock_Widget_Headers, &QAction::triggered, this,
694 &GMainWindow::OnDisplayTitleBars); 695 &GMainWindow::OnDisplayTitleBars);
695 ui.action_Show_Filter_Bar->setShortcut(tr("CTRL+F"));
696 connect(ui.action_Show_Filter_Bar, &QAction::triggered, this, &GMainWindow::OnToggleFilterBar); 696 connect(ui.action_Show_Filter_Bar, &QAction::triggered, this, &GMainWindow::OnToggleFilterBar);
697 connect(ui.action_Show_Status_Bar, &QAction::triggered, statusBar(), &QStatusBar::setVisible); 697 connect(ui.action_Show_Status_Bar, &QAction::triggered, statusBar(), &QStatusBar::setVisible);
698 698
@@ -1624,6 +1624,7 @@ void GMainWindow::OnConfigure() {
1624 auto result = configureDialog.exec(); 1624 auto result = configureDialog.exec();
1625 if (result == QDialog::Accepted) { 1625 if (result == QDialog::Accepted) {
1626 configureDialog.applyConfiguration(); 1626 configureDialog.applyConfiguration();
1627 InitializeHotkeys();
1627 if (UISettings::values.theme != old_theme) 1628 if (UISettings::values.theme != old_theme)
1628 UpdateUITheme(); 1629 UpdateUITheme();
1629 if (UISettings::values.enable_discord_presence != old_discord_presence) 1630 if (UISettings::values.enable_discord_presence != old_discord_presence)
diff --git a/src/yuzu/main.h b/src/yuzu/main.h
index e07c892cf..90cd79bca 100644
--- a/src/yuzu/main.h
+++ b/src/yuzu/main.h
@@ -120,7 +120,6 @@ private:
120 void InitializeWidgets(); 120 void InitializeWidgets();
121 void InitializeDebugWidgets(); 121 void InitializeDebugWidgets();
122 void InitializeRecentFileMenuActions(); 122 void InitializeRecentFileMenuActions();
123 void InitializeHotkeys();
124 123
125 void SetDefaultUIGeometry(); 124 void SetDefaultUIGeometry();
126 void RestoreUIState(); 125 void RestoreUIState();
@@ -195,6 +194,7 @@ private slots:
195 void OnAbout(); 194 void OnAbout();
196 void OnToggleFilterBar(); 195 void OnToggleFilterBar();
197 void OnDisplayTitleBars(bool); 196 void OnDisplayTitleBars(bool);
197 void InitializeHotkeys();
198 void ToggleFullscreen(); 198 void ToggleFullscreen();
199 void ShowFullscreen(); 199 void ShowFullscreen();
200 void HideFullscreen(); 200 void HideFullscreen();
diff --git a/src/yuzu/ui_settings.cpp b/src/yuzu/ui_settings.cpp
index a314493fc..4bdc302e0 100644
--- a/src/yuzu/ui_settings.cpp
+++ b/src/yuzu/ui_settings.cpp
@@ -12,5 +12,4 @@ const Themes themes{{
12}}; 12}};
13 13
14Values values = {}; 14Values values = {};
15
16} // namespace UISettings 15} // namespace UISettings
diff --git a/src/yuzu/ui_settings.h b/src/yuzu/ui_settings.h
index 82aaeedb0..45e705b61 100644
--- a/src/yuzu/ui_settings.h
+++ b/src/yuzu/ui_settings.h
@@ -15,7 +15,12 @@
15namespace UISettings { 15namespace UISettings {
16 16
17using ContextualShortcut = std::pair<QString, int>; 17using ContextualShortcut = std::pair<QString, int>;
18using Shortcut = std::pair<QString, ContextualShortcut>; 18
19struct Shortcut {
20 QString name;
21 QString group;
22 ContextualShortcut shortcut;
23};
19 24
20using Themes = std::array<std::pair<const char*, const char*>, 2>; 25using Themes = std::array<std::pair<const char*, const char*>, 2>;
21extern const Themes themes; 26extern const Themes themes;
diff --git a/src/yuzu/util/sequence_dialog/sequence_dialog.cpp b/src/yuzu/util/sequence_dialog/sequence_dialog.cpp
new file mode 100644
index 000000000..d3edf6ec3
--- /dev/null
+++ b/src/yuzu/util/sequence_dialog/sequence_dialog.cpp
@@ -0,0 +1,37 @@
1// Copyright 2018 Citra Emulator Project
2// Licensed under GPLv2 or any later version
3// Refer to the license.txt file included.
4
5#include <QDialogButtonBox>
6#include <QKeySequenceEdit>
7#include <QVBoxLayout>
8#include "yuzu/util/sequence_dialog/sequence_dialog.h"
9
10SequenceDialog::SequenceDialog(QWidget* parent) : QDialog(parent) {
11 setWindowTitle(tr("Enter a hotkey"));
12 auto* layout = new QVBoxLayout(this);
13 key_sequence = new QKeySequenceEdit;
14 layout->addWidget(key_sequence);
15 auto* buttons =
16 new QDialogButtonBox(QDialogButtonBox::Ok | QDialogButtonBox::Cancel, Qt::Horizontal);
17 buttons->setCenterButtons(true);
18 layout->addWidget(buttons);
19 connect(buttons, &QDialogButtonBox::accepted, this, &QDialog::accept);
20 connect(buttons, &QDialogButtonBox::rejected, this, &QDialog::reject);
21 setWindowFlags(windowFlags() & ~Qt::WindowContextHelpButtonHint);
22}
23
24SequenceDialog::~SequenceDialog() = default;
25
26QKeySequence SequenceDialog::GetSequence() const {
27 // Only the first key is returned. The other 3, if present, are ignored.
28 return QKeySequence(key_sequence->keySequence()[0]);
29}
30
31bool SequenceDialog::focusNextPrevChild(bool next) {
32 return false;
33}
34
35void SequenceDialog::closeEvent(QCloseEvent*) {
36 reject();
37}
diff --git a/src/yuzu/util/sequence_dialog/sequence_dialog.h b/src/yuzu/util/sequence_dialog/sequence_dialog.h
new file mode 100644
index 000000000..969c77740
--- /dev/null
+++ b/src/yuzu/util/sequence_dialog/sequence_dialog.h
@@ -0,0 +1,24 @@
1// Copyright 2018 Citra Emulator Project
2// Licensed under GPLv2 or any later version
3// Refer to the license.txt file included.
4
5#pragma once
6
7#include <QDialog>
8
9class QKeySequenceEdit;
10
11class SequenceDialog : public QDialog {
12 Q_OBJECT
13
14public:
15 explicit SequenceDialog(QWidget* parent = nullptr);
16 ~SequenceDialog() override;
17
18 QKeySequence GetSequence() const;
19 void closeEvent(QCloseEvent*) override;
20
21private:
22 QKeySequenceEdit* key_sequence;
23 bool focusNextPrevChild(bool next) override;
24};