yuzu: Make hotkeys configurable via the GUI
* Adds a new Hotkeys tab in the Controls group. * Double-click a Hotkey to rebind it.
This commit is contained in:
		
				
					committed by
					
						 fearlessTobi
						fearlessTobi
					
				
			
			
				
	
			
			
			
						parent
						
							06ac6460d3
						
					
				
				
					commit
					57a4a2ae0f
				
			| @@ -31,6 +31,8 @@ add_executable(yuzu | ||||
|     configuration/configure_general.h | ||||
|     configuration/configure_graphics.cpp | ||||
|     configuration/configure_graphics.h | ||||
|     configuration/configure_hotkeys.cpp | ||||
|     configuration/configure_hotkeys.h | ||||
|     configuration/configure_input.cpp | ||||
|     configuration/configure_input.h | ||||
|     configuration/configure_input_player.cpp | ||||
| @@ -78,6 +80,8 @@ add_executable(yuzu | ||||
|     ui_settings.h | ||||
|     util/limitable_input_dialog.cpp | ||||
|     util/limitable_input_dialog.h | ||||
|     util/sequence_dialog/sequence_dialog.cpp | ||||
|     util/sequence_dialog/sequence_dialog.h | ||||
|     util/spinbox.cpp | ||||
|     util/spinbox.h | ||||
|     util/util.cpp | ||||
| @@ -95,6 +99,7 @@ set(UIS | ||||
|     configuration/configure_gamelist.ui | ||||
|     configuration/configure_general.ui | ||||
|     configuration/configure_graphics.ui | ||||
|     configuration/configure_hotkeys.ui | ||||
|     configuration/configure_input.ui | ||||
|     configuration/configure_input_player.ui | ||||
|     configuration/configure_input_simple.ui | ||||
| @@ -105,7 +110,6 @@ set(UIS | ||||
|     configuration/configure_touchscreen_advanced.ui | ||||
|     configuration/configure_web.ui | ||||
|     compatdb.ui | ||||
|     hotkeys.ui | ||||
|     loading_screen.ui | ||||
|     main.ui | ||||
| ) | ||||
|   | ||||
| @@ -4,6 +4,7 @@ | ||||
|  | ||||
| #include <mutex> | ||||
| #include <QDialogButtonBox> | ||||
| #include <QHeaderView> | ||||
| #include <QLabel> | ||||
| #include <QLineEdit> | ||||
| #include <QScrollArea> | ||||
|   | ||||
| @@ -7,6 +7,7 @@ | ||||
| #include <vector> | ||||
| #include <QDialog> | ||||
| #include <QList> | ||||
| #include <QTreeView> | ||||
| #include "core/frontend/applets/profile_select.h" | ||||
|  | ||||
| class GMainWindow; | ||||
| @@ -16,7 +17,6 @@ class QLabel; | ||||
| class QScrollArea; | ||||
| class QStandardItem; | ||||
| class QStandardItemModel; | ||||
| class QTreeView; | ||||
| class QVBoxLayout; | ||||
|  | ||||
| class QtProfileSelectionDialog final : public QDialog { | ||||
|   | ||||
| @@ -2,6 +2,8 @@ | ||||
| // Licensed under GPLv2 or any later version | ||||
| // Refer to the license.txt file included. | ||||
|  | ||||
| #include <array> | ||||
| #include <QKeySequence> | ||||
| #include <QSettings> | ||||
| #include "common/file_util.h" | ||||
| #include "configure_input_simple.h" | ||||
| @@ -9,7 +11,6 @@ | ||||
| #include "core/hle/service/hid/controllers/npad.h" | ||||
| #include "input_common/main.h" | ||||
| #include "yuzu/configuration/config.h" | ||||
| #include "yuzu/ui_settings.h" | ||||
|  | ||||
| Config::Config() { | ||||
|     // TODO: Don't hardcode the path; let the frontend decide where to put the config files. | ||||
| @@ -17,7 +18,6 @@ Config::Config() { | ||||
|     FileUtil::CreateFullPath(qt_config_loc); | ||||
|     qt_config = | ||||
|         std::make_unique<QSettings>(QString::fromStdString(qt_config_loc), QSettings::IniFormat); | ||||
|  | ||||
|     Reload(); | ||||
| } | ||||
|  | ||||
| @@ -205,6 +205,27 @@ const std::array<int, Settings::NativeKeyboard::NumKeyboardMods> Config::default | ||||
|     Qt::Key_Control, Qt::Key_Shift, Qt::Key_AltGr, Qt::Key_ApplicationRight, | ||||
| }; | ||||
|  | ||||
| // This shouldn't have anything except static initializers (no functions). So | ||||
| // QKeySequnce(...).toString() is NOT ALLOWED HERE. | ||||
| // This must be in alphabetical order according to action name as it must have the same order as | ||||
| // UISetting::values.shortcuts, which is alphabetically ordered. | ||||
| const std::array<UISettings::Shortcut, 15> Config::default_hotkeys{ | ||||
|     {{"Capture Screenshot", "Main Window", {"Ctrl+P", Qt::ApplicationShortcut}}, | ||||
|      {"Continue/Pause Emulation", "Main Window", {"F4", Qt::WindowShortcut}}, | ||||
|      {"Decrease Speed Limit", "Main Window", {"-", Qt::ApplicationShortcut}}, | ||||
|      {"Exit yuzu", "Main Window", {"Ctrl+Q", Qt::WindowShortcut}}, | ||||
|      {"Exit Fullscreen", "Main Window", {"Esc", Qt::WindowShortcut}}, | ||||
|      {"Fullscreen", "Main Window", {"F11", Qt::WindowShortcut}}, | ||||
|      {"Increase Speed Limit", "Main Window", {"+", Qt::ApplicationShortcut}}, | ||||
|      {"Load Amiibo", "Main Window", {"F2", Qt::ApplicationShortcut}}, | ||||
|      {"Load File", "Main Window", {"Ctrl+O", Qt::WindowShortcut}}, | ||||
|      {"Restart Emulation", "Main Window", {"F6", Qt::WindowShortcut}}, | ||||
|      {"Stop Emulation", "Main Window", {"F5", Qt::WindowShortcut}}, | ||||
|      {"Toggle Filter Bar", "Main Window", {"Ctrl+F", Qt::WindowShortcut}}, | ||||
|      {"Toggle Speed Limit", "Main Window", {"Ctrl+Z", Qt::ApplicationShortcut}}, | ||||
|      {"Toggle Status Bar", "Main Window", {"Ctrl+S", Qt::WindowShortcut}}, | ||||
|      {"Change Docked Mode", "Main Window", {"F10", Qt::ApplicationShortcut}}}}; | ||||
|  | ||||
| void Config::ReadPlayerValues() { | ||||
|     for (std::size_t p = 0; p < Settings::values.players.size(); ++p) { | ||||
|         auto& player = Settings::values.players[p]; | ||||
| @@ -509,20 +530,15 @@ void Config::ReadValues() { | ||||
|     qt_config->endGroup(); | ||||
|  | ||||
|     qt_config->beginGroup("Shortcuts"); | ||||
|     QStringList groups = qt_config->childGroups(); | ||||
|     for (auto group : groups) { | ||||
|     for (auto [name, group, shortcut] : default_hotkeys) { | ||||
|         auto [keyseq, context] = shortcut; | ||||
|         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(ReadSetting("KeySeq").toString(), | ||||
|                                                ReadSetting("Context").toInt()))); | ||||
|             qt_config->endGroup(); | ||||
|         } | ||||
|  | ||||
|         qt_config->beginGroup(name); | ||||
|         UISettings::values.shortcuts.push_back( | ||||
|             {name, | ||||
|              group, | ||||
|              {ReadSetting("KeySeq", keyseq).toString(), ReadSetting("Context", context).toInt()}}); | ||||
|         qt_config->endGroup(); | ||||
|         qt_config->endGroup(); | ||||
|     } | ||||
|     qt_config->endGroup(); | ||||
| @@ -760,9 +776,16 @@ void Config::SaveValues() { | ||||
|     qt_config->endGroup(); | ||||
|  | ||||
|     qt_config->beginGroup("Shortcuts"); | ||||
|     for (auto shortcut : UISettings::values.shortcuts) { | ||||
|         WriteSetting(shortcut.first + "/KeySeq", shortcut.second.first); | ||||
|         WriteSetting(shortcut.first + "/Context", shortcut.second.second); | ||||
|     // Lengths of UISettings::values.shortcuts & default_hotkeys are same. | ||||
|     // However, their ordering must also be the same. | ||||
|     for (std::size_t i = 0; i < default_hotkeys.size(); i++) { | ||||
|         auto [name, group, shortcut] = UISettings::values.shortcuts[i]; | ||||
|         qt_config->beginGroup(group); | ||||
|         qt_config->beginGroup(name); | ||||
|         WriteSetting("KeySeq", shortcut.first, default_hotkeys[i].shortcut.first); | ||||
|         WriteSetting("Context", shortcut.second, default_hotkeys[i].shortcut.second); | ||||
|         qt_config->endGroup(); | ||||
|         qt_config->endGroup(); | ||||
|     } | ||||
|     qt_config->endGroup(); | ||||
|  | ||||
|   | ||||
| @@ -9,6 +9,7 @@ | ||||
| #include <string> | ||||
| #include <QVariant> | ||||
| #include "core/settings.h" | ||||
| #include "yuzu/ui_settings.h" | ||||
|  | ||||
| class QSettings; | ||||
|  | ||||
| @@ -47,6 +48,8 @@ private: | ||||
|     void WriteSetting(const QString& name, const QVariant& value); | ||||
|     void WriteSetting(const QString& name, const QVariant& value, const QVariant& default_value); | ||||
|  | ||||
|     static const std::array<UISettings::Shortcut, 15> default_hotkeys; | ||||
|  | ||||
|     std::unique_ptr<QSettings> qt_config; | ||||
|     std::string qt_config_loc; | ||||
| }; | ||||
|   | ||||
| @@ -7,9 +7,15 @@ | ||||
|     <x>0</x> | ||||
|     <y>0</y> | ||||
|     <width>382</width> | ||||
|     <height>241</height> | ||||
|     <height>650</height> | ||||
|    </rect> | ||||
|   </property> | ||||
|   <property name="minimumSize"> | ||||
|    <size> | ||||
|     <width>0</width> | ||||
|     <height>650</height> | ||||
|    </size> | ||||
|   </property> | ||||
|   <property name="windowTitle"> | ||||
|    <string>yuzu Configuration</string> | ||||
|   </property> | ||||
| @@ -62,6 +68,11 @@ | ||||
|          <string>Input</string> | ||||
|         </attribute> | ||||
|        </widget> | ||||
|        <widget class="ConfigureHotkeys" name="hotkeysTab"> | ||||
|         <attribute name="title"> | ||||
|          <string>Hotkeys</string> | ||||
|         </attribute> | ||||
|        </widget> | ||||
|        <widget class="ConfigureGraphics" name="graphicsTab"> | ||||
|         <attribute name="title"> | ||||
|          <string>Graphics</string> | ||||
| @@ -150,6 +161,12 @@ | ||||
|    <header>configuration/configure_input_simple.h</header> | ||||
|    <container>1</container> | ||||
|   </customwidget> | ||||
|   <customwidget> | ||||
|    <class>ConfigureHotkeys</class> | ||||
|    <extends>QWidget</extends> | ||||
|    <header>configuration/configure_hotkeys.h</header> | ||||
|    <container>1</container> | ||||
|   </customwidget> | ||||
|  </customwidgets> | ||||
|  <resources/> | ||||
|  <connections> | ||||
|   | ||||
| @@ -8,20 +8,22 @@ | ||||
| #include "ui_configure.h" | ||||
| #include "yuzu/configuration/config.h" | ||||
| #include "yuzu/configuration/configure_dialog.h" | ||||
| #include "yuzu/configuration/configure_input_player.h" | ||||
| #include "yuzu/hotkeys.h" | ||||
|  | ||||
| ConfigureDialog::ConfigureDialog(QWidget* parent, const HotkeyRegistry& registry) | ||||
|     : QDialog(parent), ui(new Ui::ConfigureDialog) { | ||||
| ConfigureDialog::ConfigureDialog(QWidget* parent, HotkeyRegistry& registry) | ||||
|     : QDialog(parent), registry(registry), ui(new Ui::ConfigureDialog) { | ||||
|     ui->setupUi(this); | ||||
|     ui->generalTab->PopulateHotkeyList(registry); | ||||
|     ui->hotkeysTab->Populate(registry); | ||||
|     this->setConfiguration(); | ||||
|     this->PopulateSelectionList(); | ||||
|     connect(ui->selectorList, &QListWidget::itemSelectionChanged, this, | ||||
|             &ConfigureDialog::UpdateVisibleTabs); | ||||
|  | ||||
|     adjustSize(); | ||||
|  | ||||
|     ui->selectorList->setCurrentRow(0); | ||||
|  | ||||
|     // Synchronise lists upon initialisation | ||||
|     ui->hotkeysTab->EmitHotkeysChanged(); | ||||
| } | ||||
|  | ||||
| ConfigureDialog::~ConfigureDialog() = default; | ||||
| @@ -34,6 +36,7 @@ void ConfigureDialog::applyConfiguration() { | ||||
|     ui->systemTab->applyConfiguration(); | ||||
|     ui->profileManagerTab->applyConfiguration(); | ||||
|     ui->inputTab->applyConfiguration(); | ||||
|     ui->hotkeysTab->applyConfiguration(registry); | ||||
|     ui->graphicsTab->applyConfiguration(); | ||||
|     ui->audioTab->applyConfiguration(); | ||||
|     ui->debugTab->applyConfiguration(); | ||||
| @@ -47,7 +50,7 @@ void ConfigureDialog::PopulateSelectionList() { | ||||
|         {{tr("General"), {tr("General"), tr("Web"), tr("Debug"), tr("Game List")}}, | ||||
|          {tr("System"), {tr("System"), tr("Profiles"), tr("Audio")}}, | ||||
|          {tr("Graphics"), {tr("Graphics")}}, | ||||
|          {tr("Controls"), {tr("Input")}}}}; | ||||
|          {tr("Controls"), {tr("Input"), tr("Hotkeys")}}}}; | ||||
|  | ||||
|     for (const auto& entry : items) { | ||||
|         auto* const item = new QListWidgetItem(entry.first); | ||||
| @@ -66,6 +69,7 @@ void ConfigureDialog::UpdateVisibleTabs() { | ||||
|                                                  {tr("System"), ui->systemTab}, | ||||
|                                                  {tr("Profiles"), ui->profileManagerTab}, | ||||
|                                                  {tr("Input"), ui->inputTab}, | ||||
|                                                  {tr("Hotkeys"), ui->hotkeysTab}, | ||||
|                                                  {tr("Graphics"), ui->graphicsTab}, | ||||
|                                                  {tr("Audio"), ui->audioTab}, | ||||
|                                                  {tr("Debug"), ui->debugTab}, | ||||
|   | ||||
| @@ -17,7 +17,7 @@ class ConfigureDialog : public QDialog { | ||||
|     Q_OBJECT | ||||
|  | ||||
| public: | ||||
|     explicit ConfigureDialog(QWidget* parent, const HotkeyRegistry& registry); | ||||
|     explicit ConfigureDialog(QWidget* parent, HotkeyRegistry& registry); | ||||
|     ~ConfigureDialog() override; | ||||
|  | ||||
|     void applyConfiguration(); | ||||
| @@ -28,4 +28,5 @@ private: | ||||
|     void PopulateSelectionList(); | ||||
|  | ||||
|     std::unique_ptr<Ui::ConfigureDialog> ui; | ||||
|     HotkeyRegistry& registry; | ||||
| }; | ||||
|   | ||||
| @@ -36,10 +36,6 @@ void ConfigureGeneral::setConfiguration() { | ||||
|     ui->enable_nfc->setChecked(Settings::values.enable_nfc); | ||||
| } | ||||
|  | ||||
| void ConfigureGeneral::PopulateHotkeyList(const HotkeyRegistry& registry) { | ||||
|     ui->widget->Populate(registry); | ||||
| } | ||||
|  | ||||
| void ConfigureGeneral::applyConfiguration() { | ||||
|     UISettings::values.gamedir_deepscan = ui->toggle_deepscan->isChecked(); | ||||
|     UISettings::values.confirm_before_closing = ui->toggle_check_exit->isChecked(); | ||||
|   | ||||
| @@ -20,7 +20,6 @@ public: | ||||
|     explicit ConfigureGeneral(QWidget* parent = nullptr); | ||||
|     ~ConfigureGeneral() override; | ||||
|  | ||||
|     void PopulateHotkeyList(const HotkeyRegistry& registry); | ||||
|     void applyConfiguration(); | ||||
|  | ||||
| private: | ||||
|   | ||||
| @@ -117,22 +117,6 @@ | ||||
|        </layout> | ||||
|       </widget> | ||||
|      </item> | ||||
|      <item> | ||||
|       <widget class="QGroupBox" name="HotKeysGroupBox"> | ||||
|        <property name="title"> | ||||
|         <string>Hotkeys</string> | ||||
|        </property> | ||||
|        <layout class="QHBoxLayout" name="HotKeysHorizontalLayout"> | ||||
|         <item> | ||||
|          <layout class="QVBoxLayout" name="HotKeysVerticalLayout"> | ||||
|           <item> | ||||
|            <widget class="GHotkeysDialog" name="widget" native="true"/> | ||||
|           </item> | ||||
|          </layout> | ||||
|         </item> | ||||
|        </layout> | ||||
|       </widget> | ||||
|      </item> | ||||
|      <item> | ||||
|       <spacer name="verticalSpacer"> | ||||
|        <property name="orientation"> | ||||
| @@ -150,14 +134,6 @@ | ||||
|    </item> | ||||
|   </layout> | ||||
|  </widget> | ||||
|  <customwidgets> | ||||
|   <customwidget> | ||||
|    <class>GHotkeysDialog</class> | ||||
|    <extends>QWidget</extends> | ||||
|    <header>hotkeys.h</header> | ||||
|    <container>1</container> | ||||
|   </customwidget> | ||||
|  </customwidgets> | ||||
|  <resources/> | ||||
|  <connections/> | ||||
| </ui> | ||||
|   | ||||
							
								
								
									
										121
									
								
								src/yuzu/configuration/configure_hotkeys.cpp
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										121
									
								
								src/yuzu/configuration/configure_hotkeys.cpp
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,121 @@ | ||||
| // Copyright 2017 Citra Emulator Project | ||||
| // Licensed under GPLv2 or any later version | ||||
| // Refer to the license.txt file included. | ||||
|  | ||||
| #include <QMessageBox> | ||||
| #include <QStandardItemModel> | ||||
| #include "core/settings.h" | ||||
| #include "ui_configure_hotkeys.h" | ||||
| #include "yuzu/configuration/configure_hotkeys.h" | ||||
| #include "yuzu/hotkeys.h" | ||||
| #include "yuzu/util/sequence_dialog/sequence_dialog.h" | ||||
|  | ||||
| ConfigureHotkeys::ConfigureHotkeys(QWidget* parent) | ||||
|     : QWidget(parent), ui(std::make_unique<Ui::ConfigureHotkeys>()) { | ||||
|     ui->setupUi(this); | ||||
|     setFocusPolicy(Qt::ClickFocus); | ||||
|  | ||||
|     model = new QStandardItemModel(this); | ||||
|     model->setColumnCount(3); | ||||
|     model->setHorizontalHeaderLabels({tr("Action"), tr("Hotkey"), tr("Context")}); | ||||
|  | ||||
|     connect(ui->hotkey_list, &QTreeView::doubleClicked, this, &ConfigureHotkeys::Configure); | ||||
|     ui->hotkey_list->setModel(model); | ||||
|  | ||||
|     // TODO(Kloen): Make context configurable as well (hiding the column for now) | ||||
|     ui->hotkey_list->hideColumn(2); | ||||
|  | ||||
|     ui->hotkey_list->setColumnWidth(0, 200); | ||||
|     ui->hotkey_list->resizeColumnToContents(1); | ||||
| } | ||||
|  | ||||
| ConfigureHotkeys::~ConfigureHotkeys() = default; | ||||
|  | ||||
| void ConfigureHotkeys::EmitHotkeysChanged() { | ||||
|     emit HotkeysChanged(GetUsedKeyList()); | ||||
| } | ||||
|  | ||||
| QList<QKeySequence> ConfigureHotkeys::GetUsedKeyList() const { | ||||
|     QList<QKeySequence> list; | ||||
|     for (int r = 0; r < model->rowCount(); r++) { | ||||
|         const QStandardItem* parent = model->item(r, 0); | ||||
|         for (int r2 = 0; r2 < parent->rowCount(); r2++) { | ||||
|             const QStandardItem* keyseq = parent->child(r2, 1); | ||||
|             list << QKeySequence::fromString(keyseq->text(), QKeySequence::NativeText); | ||||
|         } | ||||
|     } | ||||
|     return list; | ||||
| } | ||||
|  | ||||
| void ConfigureHotkeys::Populate(const HotkeyRegistry& registry) { | ||||
|     for (const auto& group : registry.hotkey_groups) { | ||||
|         auto* parent_item = new QStandardItem(group.first); | ||||
|         parent_item->setEditable(false); | ||||
|         for (const auto& hotkey : group.second) { | ||||
|             auto* action = new QStandardItem(hotkey.first); | ||||
|             auto* keyseq = | ||||
|                 new QStandardItem(hotkey.second.keyseq.toString(QKeySequence::NativeText)); | ||||
|             action->setEditable(false); | ||||
|             keyseq->setEditable(false); | ||||
|             parent_item->appendRow({action, keyseq}); | ||||
|         } | ||||
|         model->appendRow(parent_item); | ||||
|     } | ||||
|  | ||||
|     ui->hotkey_list->expandAll(); | ||||
| } | ||||
|  | ||||
| void ConfigureHotkeys::Configure(QModelIndex index) { | ||||
|     if (index.parent() == QModelIndex()) | ||||
|         return; | ||||
|  | ||||
|     index = index.sibling(index.row(), 1); | ||||
|     auto* model = ui->hotkey_list->model(); | ||||
|     auto previous_key = model->data(index); | ||||
|  | ||||
|     auto* hotkey_dialog = new SequenceDialog; | ||||
|     int return_code = hotkey_dialog->exec(); | ||||
|  | ||||
|     auto key_sequence = hotkey_dialog->GetSequence(); | ||||
|  | ||||
|     if (return_code == QDialog::Rejected || key_sequence.isEmpty()) | ||||
|         return; | ||||
|  | ||||
|     if (IsUsedKey(key_sequence) && key_sequence != QKeySequence(previous_key.toString())) { | ||||
|         QMessageBox::critical(this, tr("Error in inputted key"), | ||||
|                               tr("You're using a key that's already bound.")); | ||||
|     } else { | ||||
|         model->setData(index, key_sequence.toString(QKeySequence::NativeText)); | ||||
|         EmitHotkeysChanged(); | ||||
|     } | ||||
| } | ||||
|  | ||||
| bool ConfigureHotkeys::IsUsedKey(QKeySequence key_sequence) { | ||||
|     return GetUsedKeyList().contains(key_sequence); | ||||
| } | ||||
|  | ||||
| void ConfigureHotkeys::applyConfiguration(HotkeyRegistry& registry) { | ||||
|     for (int key_id = 0; key_id < model->rowCount(); key_id++) { | ||||
|         const QStandardItem* parent = model->item(key_id, 0); | ||||
|         for (int key_column_id = 0; key_column_id < parent->rowCount(); key_column_id++) { | ||||
|             const QStandardItem* action = parent->child(key_column_id, 0); | ||||
|             const QStandardItem* keyseq = parent->child(key_column_id, 1); | ||||
|             for (auto& [group, sub_actions] : registry.hotkey_groups) { | ||||
|                 if (group != parent->text()) | ||||
|                     continue; | ||||
|                 for (auto& [action_name, hotkey] : sub_actions) { | ||||
|                     if (action_name != action->text()) | ||||
|                         continue; | ||||
|                     hotkey.keyseq = QKeySequence(keyseq->text()); | ||||
|                 } | ||||
|             } | ||||
|         } | ||||
|     } | ||||
|  | ||||
|     registry.SaveHotkeys(); | ||||
|     Settings::Apply(); | ||||
| } | ||||
|  | ||||
| void ConfigureHotkeys::retranslateUi() { | ||||
|     ui->retranslateUi(this); | ||||
| } | ||||
							
								
								
									
										48
									
								
								src/yuzu/configuration/configure_hotkeys.h
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										48
									
								
								src/yuzu/configuration/configure_hotkeys.h
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,48 @@ | ||||
| // Copyright 2017 Citra Emulator Project | ||||
| // Licensed under GPLv2 or any later version | ||||
| // Refer to the license.txt file included. | ||||
|  | ||||
| #pragma once | ||||
|  | ||||
| #include <memory> | ||||
| #include <QWidget> | ||||
| #include "core/settings.h" | ||||
|  | ||||
| namespace Ui { | ||||
| class ConfigureHotkeys; | ||||
| } | ||||
|  | ||||
| class HotkeyRegistry; | ||||
| class QStandardItemModel; | ||||
|  | ||||
| class ConfigureHotkeys : public QWidget { | ||||
|     Q_OBJECT | ||||
|  | ||||
| public: | ||||
|     explicit ConfigureHotkeys(QWidget* parent = nullptr); | ||||
|     ~ConfigureHotkeys() override; | ||||
|  | ||||
|     void applyConfiguration(HotkeyRegistry& registry); | ||||
|     void retranslateUi(); | ||||
|  | ||||
|     void EmitHotkeysChanged(); | ||||
|  | ||||
|     /** | ||||
|      * Populates the hotkey list widget using data from the provided registry. | ||||
|      * Called everytime the Configure dialog is opened. | ||||
|      * @param registry The HotkeyRegistry whose data is used to populate the list. | ||||
|      */ | ||||
|     void Populate(const HotkeyRegistry& registry); | ||||
|  | ||||
| signals: | ||||
|     void HotkeysChanged(QList<QKeySequence> new_key_list); | ||||
|  | ||||
| private: | ||||
|     void Configure(QModelIndex index); | ||||
|     bool IsUsedKey(QKeySequence key_sequence); | ||||
|     QList<QKeySequence> GetUsedKeyList() const; | ||||
|  | ||||
|     std::unique_ptr<Ui::ConfigureHotkeys> ui; | ||||
|  | ||||
|     QStandardItemModel* model; | ||||
| }; | ||||
							
								
								
									
										42
									
								
								src/yuzu/configuration/configure_hotkeys.ui
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										42
									
								
								src/yuzu/configuration/configure_hotkeys.ui
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,42 @@ | ||||
| <?xml version="1.0" encoding="UTF-8"?> | ||||
| <ui version="4.0"> | ||||
|  <class>ConfigureHotkeys</class> | ||||
|  <widget class="QWidget" name="ConfigureHotkeys"> | ||||
|   <property name="geometry"> | ||||
|    <rect> | ||||
|     <x>0</x> | ||||
|     <y>0</y> | ||||
|     <width>363</width> | ||||
|     <height>388</height> | ||||
|    </rect> | ||||
|   </property> | ||||
|   <property name="windowTitle"> | ||||
|    <string>Hotkey Settings</string> | ||||
|   </property> | ||||
|   <layout class="QVBoxLayout" name="verticalLayout"> | ||||
|    <item> | ||||
|     <layout class="QVBoxLayout" name="verticalLayout_2"> | ||||
|      <item> | ||||
|       <widget class="QLabel" name="label_2"> | ||||
|        <property name="text"> | ||||
|         <string>Double-click on a binding to change it.</string> | ||||
|        </property> | ||||
|       </widget> | ||||
|      </item> | ||||
|      <item> | ||||
|       <widget class="QTreeView" name="hotkey_list"> | ||||
|        <property name="editTriggers"> | ||||
|         <set>QAbstractItemView::NoEditTriggers</set> | ||||
|        </property> | ||||
|        <property name="sortingEnabled"> | ||||
|         <bool>false</bool> | ||||
|        </property> | ||||
|       </widget> | ||||
|      </item> | ||||
|     </layout> | ||||
|    </item> | ||||
|   </layout> | ||||
|  </widget> | ||||
|  <resources/> | ||||
|  <connections/> | ||||
| </ui> | ||||
| @@ -2,7 +2,6 @@ | ||||
| // Licensed under GPLv2 or any later version | ||||
| // Refer to the license.txt file included. | ||||
|  | ||||
| #include <map> | ||||
| #include <QKeySequence> | ||||
| #include <QShortcut> | ||||
| #include <QTreeWidgetItem> | ||||
| @@ -13,47 +12,32 @@ | ||||
| HotkeyRegistry::HotkeyRegistry() = default; | ||||
| HotkeyRegistry::~HotkeyRegistry() = default; | ||||
|  | ||||
| void HotkeyRegistry::LoadHotkeys() { | ||||
|     // Make sure NOT to use a reference here because it would become invalid once we call | ||||
|     // beginGroup() | ||||
|     for (auto shortcut : UISettings::values.shortcuts) { | ||||
|         const QStringList cat = shortcut.first.split('/'); | ||||
|         Q_ASSERT(cat.size() >= 2); | ||||
|  | ||||
|         // RegisterHotkey assigns default keybindings, so use old values as default parameters | ||||
|         Hotkey& hk = hotkey_groups[cat[0]][cat[1]]; | ||||
|         if (!shortcut.second.first.isEmpty()) { | ||||
|             hk.keyseq = QKeySequence::fromString(shortcut.second.first); | ||||
|             hk.context = static_cast<Qt::ShortcutContext>(shortcut.second.second); | ||||
|         } | ||||
|         if (hk.shortcut) | ||||
|             hk.shortcut->setKey(hk.keyseq); | ||||
|     } | ||||
| } | ||||
|  | ||||
| void HotkeyRegistry::SaveHotkeys() { | ||||
|     UISettings::values.shortcuts.clear(); | ||||
|     for (const auto& group : hotkey_groups) { | ||||
|         for (const auto& hotkey : group.second) { | ||||
|             UISettings::values.shortcuts.emplace_back( | ||||
|                 UISettings::Shortcut(group.first + '/' + hotkey.first, | ||||
|                                      UISettings::ContextualShortcut(hotkey.second.keyseq.toString(), | ||||
|                                                                     hotkey.second.context))); | ||||
|             UISettings::values.shortcuts.push_back( | ||||
|                 {hotkey.first, group.first, | ||||
|                  UISettings::ContextualShortcut(hotkey.second.keyseq.toString(), | ||||
|                                                 hotkey.second.context)}); | ||||
|         } | ||||
|     } | ||||
| } | ||||
|  | ||||
| void HotkeyRegistry::RegisterHotkey(const QString& group, const QString& action, | ||||
|                                     const QKeySequence& default_keyseq, | ||||
|                                     Qt::ShortcutContext default_context) { | ||||
|     auto& hotkey_group = hotkey_groups[group]; | ||||
|     if (hotkey_group.find(action) != hotkey_group.end()) { | ||||
|         return; | ||||
| void HotkeyRegistry::LoadHotkeys() { | ||||
|     // Make sure NOT to use a reference here because it would become invalid once we call | ||||
|     // beginGroup() | ||||
|     for (auto shortcut : UISettings::values.shortcuts) { | ||||
|         Hotkey& hk = hotkey_groups[shortcut.group][shortcut.name]; | ||||
|         if (!shortcut.shortcut.first.isEmpty()) { | ||||
|             hk.keyseq = QKeySequence::fromString(shortcut.shortcut.first, QKeySequence::NativeText); | ||||
|             hk.context = static_cast<Qt::ShortcutContext>(shortcut.shortcut.second); | ||||
|         } | ||||
|         if (hk.shortcut) { | ||||
|             hk.shortcut->disconnect(); | ||||
|             hk.shortcut->setKey(hk.keyseq); | ||||
|         } | ||||
|     } | ||||
|  | ||||
|     auto& hotkey_action = hotkey_groups[group][action]; | ||||
|     hotkey_action.keyseq = default_keyseq; | ||||
|     hotkey_action.context = default_context; | ||||
| } | ||||
|  | ||||
| QShortcut* HotkeyRegistry::GetHotkey(const QString& group, const QString& action, QWidget* widget) { | ||||
| @@ -65,24 +49,11 @@ QShortcut* HotkeyRegistry::GetHotkey(const QString& group, const QString& action | ||||
|     return hk.shortcut; | ||||
| } | ||||
|  | ||||
| GHotkeysDialog::GHotkeysDialog(QWidget* parent) : QWidget(parent) { | ||||
|     ui.setupUi(this); | ||||
| QKeySequence HotkeyRegistry::GetKeySequence(const QString& group, const QString& action) { | ||||
|     return hotkey_groups[group][action].keyseq; | ||||
| } | ||||
|  | ||||
| void GHotkeysDialog::Populate(const HotkeyRegistry& registry) { | ||||
|     for (const auto& group : registry.hotkey_groups) { | ||||
|         QTreeWidgetItem* toplevel_item = new QTreeWidgetItem(QStringList(group.first)); | ||||
|         for (const auto& hotkey : group.second) { | ||||
|             QStringList columns; | ||||
|             columns << hotkey.first << hotkey.second.keyseq.toString(); | ||||
|             QTreeWidgetItem* item = new QTreeWidgetItem(columns); | ||||
|             toplevel_item->addChild(item); | ||||
|         } | ||||
|         ui.treeWidget->addTopLevelItem(toplevel_item); | ||||
|     } | ||||
|     // TODO: Make context configurable as well (hiding the column for now) | ||||
|     ui.treeWidget->setColumnCount(2); | ||||
|  | ||||
|     ui.treeWidget->resizeColumnToContents(0); | ||||
|     ui.treeWidget->resizeColumnToContents(1); | ||||
| Qt::ShortcutContext HotkeyRegistry::GetShortcutContext(const QString& group, | ||||
|                                                        const QString& action) { | ||||
|     return hotkey_groups[group][action].context; | ||||
| } | ||||
|   | ||||
| @@ -5,7 +5,6 @@ | ||||
| #pragma once | ||||
|  | ||||
| #include <map> | ||||
| #include "ui_hotkeys.h" | ||||
|  | ||||
| class QDialog; | ||||
| class QKeySequence; | ||||
| @@ -14,7 +13,7 @@ class QShortcut; | ||||
|  | ||||
| class HotkeyRegistry final { | ||||
| public: | ||||
|     friend class GHotkeysDialog; | ||||
|     friend class ConfigureHotkeys; | ||||
|  | ||||
|     explicit HotkeyRegistry(); | ||||
|     ~HotkeyRegistry(); | ||||
| @@ -49,22 +48,27 @@ public: | ||||
|     QShortcut* GetHotkey(const QString& group, const QString& action, QWidget* widget); | ||||
|  | ||||
|     /** | ||||
|      * Register a hotkey. | ||||
|      * Returns a QKeySequence object whose signal can be connected to QAction::setShortcut. | ||||
|      * | ||||
|      * @param group General group this hotkey belongs to (e.g. "Main Window", "Debugger") | ||||
|      * @param action Name of the action (e.g. "Start Emulation", "Load Image") | ||||
|      * @param default_keyseq Default key sequence to assign if the hotkey wasn't present in the | ||||
|      *                       settings file before | ||||
|      * @param default_context Default context to assign if the hotkey wasn't present in the settings | ||||
|      *                        file before | ||||
|      * @warning Both the group and action strings will be displayed in the hotkey settings dialog | ||||
|      * @param group  General group this hotkey belongs to (e.g. "Main Window", "Debugger"). | ||||
|      * @param action Name of the action (e.g. "Start Emulation", "Load Image"). | ||||
|      */ | ||||
|     void RegisterHotkey(const QString& group, const QString& action, | ||||
|                         const QKeySequence& default_keyseq = {}, | ||||
|                         Qt::ShortcutContext default_context = Qt::WindowShortcut); | ||||
|     QKeySequence GetKeySequence(const QString& group, const QString& action); | ||||
|  | ||||
|     /** | ||||
|      * Returns a Qt::ShortcutContext object who can be connected to other | ||||
|      * QAction::setShortcutContext. | ||||
|      * | ||||
|      * @param group  General group this shortcut context belongs to (e.g. "Main Window", | ||||
|      * "Debugger"). | ||||
|      * @param action Name of the action (e.g. "Start Emulation", "Load Image"). | ||||
|      */ | ||||
|     Qt::ShortcutContext GetShortcutContext(const QString& group, const QString& action); | ||||
|  | ||||
| private: | ||||
|     struct Hotkey { | ||||
|         Hotkey() : shortcut(nullptr), context(Qt::WindowShortcut) {} | ||||
|  | ||||
|         QKeySequence keyseq; | ||||
|         QShortcut* shortcut = nullptr; | ||||
|         Qt::ShortcutContext context = Qt::WindowShortcut; | ||||
| @@ -75,15 +79,3 @@ private: | ||||
|  | ||||
|     HotkeyGroupMap hotkey_groups; | ||||
| }; | ||||
|  | ||||
| class GHotkeysDialog : public QWidget { | ||||
|     Q_OBJECT | ||||
|  | ||||
| public: | ||||
|     explicit GHotkeysDialog(QWidget* parent = nullptr); | ||||
|  | ||||
|     void Populate(const HotkeyRegistry& registry); | ||||
|  | ||||
| private: | ||||
|     Ui::hotkeys ui; | ||||
| }; | ||||
|   | ||||
| @@ -1,46 +0,0 @@ | ||||
| <?xml version="1.0" encoding="UTF-8"?> | ||||
| <ui version="4.0"> | ||||
|  <class>hotkeys</class> | ||||
|  <widget class="QWidget" name="hotkeys"> | ||||
|   <property name="geometry"> | ||||
|    <rect> | ||||
|     <x>0</x> | ||||
|     <y>0</y> | ||||
|     <width>363</width> | ||||
|     <height>388</height> | ||||
|    </rect> | ||||
|   </property> | ||||
|   <property name="windowTitle"> | ||||
|    <string>Hotkey Settings</string> | ||||
|   </property> | ||||
|   <layout class="QVBoxLayout" name="verticalLayout"> | ||||
|    <item> | ||||
|     <widget class="QTreeWidget" name="treeWidget"> | ||||
|      <property name="selectionBehavior"> | ||||
|       <enum>QAbstractItemView::SelectItems</enum> | ||||
|      </property> | ||||
|      <property name="headerHidden"> | ||||
|       <bool>false</bool> | ||||
|      </property> | ||||
|      <column> | ||||
|       <property name="text"> | ||||
|        <string>Action</string> | ||||
|       </property> | ||||
|      </column> | ||||
|      <column> | ||||
|       <property name="text"> | ||||
|        <string>Hotkey</string> | ||||
|       </property> | ||||
|      </column> | ||||
|      <column> | ||||
|       <property name="text"> | ||||
|        <string>Context</string> | ||||
|       </property> | ||||
|      </column> | ||||
|     </widget> | ||||
|    </item> | ||||
|   </layout> | ||||
|  </widget> | ||||
|  <resources/> | ||||
|  <connections/> | ||||
| </ui> | ||||
| @@ -511,33 +511,34 @@ void GMainWindow::InitializeRecentFileMenuActions() { | ||||
| } | ||||
|  | ||||
| void GMainWindow::InitializeHotkeys() { | ||||
|     hotkey_registry.RegisterHotkey("Main Window", "Load File", QKeySequence::Open); | ||||
|     hotkey_registry.RegisterHotkey("Main Window", "Start Emulation"); | ||||
|     hotkey_registry.RegisterHotkey("Main Window", "Continue/Pause", QKeySequence(Qt::Key_F4)); | ||||
|     hotkey_registry.RegisterHotkey("Main Window", "Restart", QKeySequence(Qt::Key_F5)); | ||||
|     hotkey_registry.RegisterHotkey("Main Window", "Fullscreen", QKeySequence::FullScreen); | ||||
|     hotkey_registry.RegisterHotkey("Main Window", "Exit Fullscreen", QKeySequence(Qt::Key_Escape), | ||||
|                                    Qt::ApplicationShortcut); | ||||
|     hotkey_registry.RegisterHotkey("Main Window", "Toggle Speed Limit", QKeySequence("CTRL+Z"), | ||||
|                                    Qt::ApplicationShortcut); | ||||
|     hotkey_registry.RegisterHotkey("Main Window", "Increase Speed Limit", QKeySequence("+"), | ||||
|                                    Qt::ApplicationShortcut); | ||||
|     hotkey_registry.RegisterHotkey("Main Window", "Decrease Speed Limit", QKeySequence("-"), | ||||
|                                    Qt::ApplicationShortcut); | ||||
|     hotkey_registry.RegisterHotkey("Main Window", "Load Amiibo", QKeySequence(Qt::Key_F2), | ||||
|                                    Qt::ApplicationShortcut); | ||||
|     hotkey_registry.RegisterHotkey("Main Window", "Capture Screenshot", | ||||
|                                    QKeySequence(QKeySequence::Print)); | ||||
|     hotkey_registry.RegisterHotkey("Main Window", "Change Docked Mode", QKeySequence(Qt::Key_F10)); | ||||
|  | ||||
|     hotkey_registry.LoadHotkeys(); | ||||
|  | ||||
|     ui.action_Load_File->setShortcut(hotkey_registry.GetKeySequence("Main Window", "Load File")); | ||||
|     ui.action_Load_File->setShortcutContext( | ||||
|         hotkey_registry.GetShortcutContext("Main Window", "Load File")); | ||||
|  | ||||
|     ui.action_Exit->setShortcut(hotkey_registry.GetKeySequence("Main Window", "Exit yuzu")); | ||||
|     ui.action_Exit->setShortcutContext( | ||||
|         hotkey_registry.GetShortcutContext("Main Window", "Exit yuzu")); | ||||
|  | ||||
|     ui.action_Stop->setShortcut(hotkey_registry.GetKeySequence("Main Window", "Stop Emulation")); | ||||
|     ui.action_Stop->setShortcutContext( | ||||
|         hotkey_registry.GetShortcutContext("Main Window", "Stop Emulation")); | ||||
|  | ||||
|     ui.action_Show_Filter_Bar->setShortcut( | ||||
|         hotkey_registry.GetKeySequence("Main Window", "Toggle Filter Bar")); | ||||
|     ui.action_Show_Filter_Bar->setShortcutContext( | ||||
|         hotkey_registry.GetShortcutContext("Main Window", "Toggle Filter Bar")); | ||||
|  | ||||
|     ui.action_Show_Status_Bar->setShortcut( | ||||
|         hotkey_registry.GetKeySequence("Main Window", "Toggle Status Bar")); | ||||
|     ui.action_Show_Status_Bar->setShortcutContext( | ||||
|         hotkey_registry.GetShortcutContext("Main Window", "Toggle Status Bar")); | ||||
|  | ||||
|     connect(hotkey_registry.GetHotkey("Main Window", "Load File", this), &QShortcut::activated, | ||||
|             this, &GMainWindow::OnMenuLoadFile); | ||||
|     connect(hotkey_registry.GetHotkey("Main Window", "Start Emulation", this), | ||||
|             &QShortcut::activated, this, &GMainWindow::OnStartGame); | ||||
|     connect(hotkey_registry.GetHotkey("Main Window", "Continue/Pause", this), &QShortcut::activated, | ||||
|             this, [&] { | ||||
|     connect(hotkey_registry.GetHotkey("Main Window", "Continue/Pause Emulation", this), | ||||
|             &QShortcut::activated, this, [&] { | ||||
|                 if (emulation_running) { | ||||
|                     if (emu_thread->IsRunning()) { | ||||
|                         OnPauseGame(); | ||||
| @@ -546,8 +547,8 @@ void GMainWindow::InitializeHotkeys() { | ||||
|                     } | ||||
|                 } | ||||
|             }); | ||||
|     connect(hotkey_registry.GetHotkey("Main Window", "Restart", this), &QShortcut::activated, this, | ||||
|             [this] { | ||||
|     connect(hotkey_registry.GetHotkey("Main Window", "Restart Emulation", this), | ||||
|             &QShortcut::activated, this, [this] { | ||||
|                 if (!Core::System::GetInstance().IsPoweredOn()) | ||||
|                     return; | ||||
|                 BootGame(QString(game_path)); | ||||
| @@ -692,7 +693,6 @@ void GMainWindow::ConnectMenuEvents() { | ||||
|             &GMainWindow::ToggleWindowMode); | ||||
|     connect(ui.action_Display_Dock_Widget_Headers, &QAction::triggered, this, | ||||
|             &GMainWindow::OnDisplayTitleBars); | ||||
|     ui.action_Show_Filter_Bar->setShortcut(tr("CTRL+F")); | ||||
|     connect(ui.action_Show_Filter_Bar, &QAction::triggered, this, &GMainWindow::OnToggleFilterBar); | ||||
|     connect(ui.action_Show_Status_Bar, &QAction::triggered, statusBar(), &QStatusBar::setVisible); | ||||
|  | ||||
| @@ -1624,6 +1624,7 @@ void GMainWindow::OnConfigure() { | ||||
|     auto result = configureDialog.exec(); | ||||
|     if (result == QDialog::Accepted) { | ||||
|         configureDialog.applyConfiguration(); | ||||
|         InitializeHotkeys(); | ||||
|         if (UISettings::values.theme != old_theme) | ||||
|             UpdateUITheme(); | ||||
|         if (UISettings::values.enable_discord_presence != old_discord_presence) | ||||
|   | ||||
| @@ -120,7 +120,6 @@ private: | ||||
|     void InitializeWidgets(); | ||||
|     void InitializeDebugWidgets(); | ||||
|     void InitializeRecentFileMenuActions(); | ||||
|     void InitializeHotkeys(); | ||||
|  | ||||
|     void SetDefaultUIGeometry(); | ||||
|     void RestoreUIState(); | ||||
| @@ -195,6 +194,7 @@ private slots: | ||||
|     void OnAbout(); | ||||
|     void OnToggleFilterBar(); | ||||
|     void OnDisplayTitleBars(bool); | ||||
|     void InitializeHotkeys(); | ||||
|     void ToggleFullscreen(); | ||||
|     void ShowFullscreen(); | ||||
|     void HideFullscreen(); | ||||
|   | ||||
| @@ -12,5 +12,4 @@ const Themes themes{{ | ||||
| }}; | ||||
|  | ||||
| Values values = {}; | ||||
|  | ||||
| } // namespace UISettings | ||||
|   | ||||
| @@ -15,7 +15,12 @@ | ||||
| namespace UISettings { | ||||
|  | ||||
| using ContextualShortcut = std::pair<QString, int>; | ||||
| using Shortcut = std::pair<QString, ContextualShortcut>; | ||||
|  | ||||
| struct Shortcut { | ||||
|     QString name; | ||||
|     QString group; | ||||
|     ContextualShortcut shortcut; | ||||
| }; | ||||
|  | ||||
| using Themes = std::array<std::pair<const char*, const char*>, 2>; | ||||
| extern const Themes themes; | ||||
|   | ||||
							
								
								
									
										37
									
								
								src/yuzu/util/sequence_dialog/sequence_dialog.cpp
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										37
									
								
								src/yuzu/util/sequence_dialog/sequence_dialog.cpp
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,37 @@ | ||||
| // Copyright 2018 Citra Emulator Project | ||||
| // Licensed under GPLv2 or any later version | ||||
| // Refer to the license.txt file included. | ||||
|  | ||||
| #include <QDialogButtonBox> | ||||
| #include <QKeySequenceEdit> | ||||
| #include <QVBoxLayout> | ||||
| #include "yuzu/util/sequence_dialog/sequence_dialog.h" | ||||
|  | ||||
| SequenceDialog::SequenceDialog(QWidget* parent) : QDialog(parent) { | ||||
|     setWindowTitle(tr("Enter a hotkey")); | ||||
|     auto* layout = new QVBoxLayout(this); | ||||
|     key_sequence = new QKeySequenceEdit; | ||||
|     layout->addWidget(key_sequence); | ||||
|     auto* buttons = | ||||
|         new QDialogButtonBox(QDialogButtonBox::Ok | QDialogButtonBox::Cancel, Qt::Horizontal); | ||||
|     buttons->setCenterButtons(true); | ||||
|     layout->addWidget(buttons); | ||||
|     connect(buttons, &QDialogButtonBox::accepted, this, &QDialog::accept); | ||||
|     connect(buttons, &QDialogButtonBox::rejected, this, &QDialog::reject); | ||||
|     setWindowFlags(windowFlags() & ~Qt::WindowContextHelpButtonHint); | ||||
| } | ||||
|  | ||||
| SequenceDialog::~SequenceDialog() = default; | ||||
|  | ||||
| QKeySequence SequenceDialog::GetSequence() const { | ||||
|     // Only the first key is returned. The other 3, if present, are ignored. | ||||
|     return QKeySequence(key_sequence->keySequence()[0]); | ||||
| } | ||||
|  | ||||
| bool SequenceDialog::focusNextPrevChild(bool next) { | ||||
|     return false; | ||||
| } | ||||
|  | ||||
| void SequenceDialog::closeEvent(QCloseEvent*) { | ||||
|     reject(); | ||||
| } | ||||
							
								
								
									
										24
									
								
								src/yuzu/util/sequence_dialog/sequence_dialog.h
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										24
									
								
								src/yuzu/util/sequence_dialog/sequence_dialog.h
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,24 @@ | ||||
| // Copyright 2018 Citra Emulator Project | ||||
| // Licensed under GPLv2 or any later version | ||||
| // Refer to the license.txt file included. | ||||
|  | ||||
| #pragma once | ||||
|  | ||||
| #include <QDialog> | ||||
|  | ||||
| class QKeySequenceEdit; | ||||
|  | ||||
| class SequenceDialog : public QDialog { | ||||
|     Q_OBJECT | ||||
|  | ||||
| public: | ||||
|     explicit SequenceDialog(QWidget* parent = nullptr); | ||||
|     ~SequenceDialog() override; | ||||
|  | ||||
|     QKeySequence GetSequence() const; | ||||
|     void closeEvent(QCloseEvent*) override; | ||||
|  | ||||
| private: | ||||
|     QKeySequenceEdit* key_sequence; | ||||
|     bool focusNextPrevChild(bool next) override; | ||||
| }; | ||||
		Reference in New Issue
	
	Block a user