citra-qt: Add base support for hotkey reconfiguration + UI (whole of PR citra-emu/citra#3786)
* Adds a new Hotkeys tab in the Controls group. * Right click to reconfigure. * See the original PR for more details & screenshots.
This commit is contained in:
parent
95a57a2fe3
commit
5fa25fcf13
22 changed files with 559 additions and 306 deletions
|
@ -3,7 +3,9 @@
|
|||
// Refer to the license.txt file included.
|
||||
|
||||
#include <algorithm>
|
||||
#include <array>
|
||||
#include <unordered_map>
|
||||
#include <QKeySequence>
|
||||
#include <QSettings>
|
||||
#include "citra_qt/configuration/config.h"
|
||||
#include "citra_qt/ui_settings.h"
|
||||
|
@ -318,20 +320,46 @@ void Config::ReadValues() {
|
|||
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(ReadSetting("KeySeq").toString(),
|
||||
ReadSetting("Context").toInt())));
|
||||
qt_config->endGroup();
|
||||
}
|
||||
const std::array<UISettings::Shortcut, 14> default_hotkeys{
|
||||
{{"Load File", "Main Window",
|
||||
UISettings::ContextualShortcut(QKeySequence(QKeySequence::Open).toString(),
|
||||
Qt::WindowShortcut)},
|
||||
{"Exit Citra", "Main Window",
|
||||
UISettings::ContextualShortcut("Ctrl+Q", Qt::WindowShortcut)},
|
||||
{"Continue/Pause Emulation", "Main Window",
|
||||
UISettings::ContextualShortcut("F4", Qt::WindowShortcut)},
|
||||
{"Stop Emulation", "Main Window",
|
||||
UISettings::ContextualShortcut("F5", Qt::WindowShortcut)},
|
||||
{"Restart Emulation", "Main Window",
|
||||
UISettings::ContextualShortcut("F6", Qt::WindowShortcut)},
|
||||
{"Swap Screens", "Main Window", UISettings::ContextualShortcut("F9", Qt::WindowShortcut)},
|
||||
{"Toggle Screen Layout", "Main Window",
|
||||
UISettings::ContextualShortcut("F10", Qt::WindowShortcut)},
|
||||
{"Toggle Filter Bar", "Main Window",
|
||||
UISettings::ContextualShortcut("Ctrl+F", Qt::WindowShortcut)},
|
||||
{"Toggle Status Bar", "Main Window",
|
||||
UISettings::ContextualShortcut("Ctrl+S", Qt::WindowShortcut)},
|
||||
{"Fullscreen", "Main Window",
|
||||
UISettings::ContextualShortcut(QKeySequence(QKeySequence::FullScreen).toString(),
|
||||
Qt::WindowShortcut)},
|
||||
{"Exit Fullscreen", "Main Window",
|
||||
UISettings::ContextualShortcut("Escape", Qt::WindowShortcut)},
|
||||
{"Toggle Speed Limit", "Main Window",
|
||||
UISettings::ContextualShortcut("Ctrl+Z", Qt::ApplicationShortcut)},
|
||||
{"Increase Speed Limit", "Main Window",
|
||||
UISettings::ContextualShortcut("+", Qt::ApplicationShortcut)},
|
||||
{"Decrease Speed Limit", "Main Window",
|
||||
UISettings::ContextualShortcut("-", Qt::ApplicationShortcut)}}};
|
||||
|
||||
for (int i = 0; i < default_hotkeys.size(); i++) {
|
||||
qt_config->beginGroup(default_hotkeys[i].group);
|
||||
qt_config->beginGroup(default_hotkeys[i].name);
|
||||
UISettings::values.shortcuts.push_back(
|
||||
{default_hotkeys[i].name, default_hotkeys[i].group,
|
||||
UISettings::ContextualShortcut(
|
||||
qt_config->value("KeySeq", default_hotkeys[i].shortcut.first).toString(),
|
||||
qt_config->value("Context", default_hotkeys[i].shortcut.second).toInt())});
|
||||
qt_config->endGroup();
|
||||
qt_config->endGroup();
|
||||
}
|
||||
qt_config->endGroup();
|
||||
|
@ -564,8 +592,12 @@ void Config::SaveValues() {
|
|||
|
||||
qt_config->beginGroup("Shortcuts");
|
||||
for (auto shortcut : UISettings::values.shortcuts) {
|
||||
WriteSetting(shortcut.first + "/KeySeq", shortcut.second.first);
|
||||
WriteSetting(shortcut.first + "/Context", shortcut.second.second);
|
||||
qt_config->beginGroup(shortcut.group);
|
||||
qt_config->beginGroup(shortcut.name);
|
||||
WriteSetting("KeySeq", shortcut.shortcut.first);
|
||||
WriteSetting("Context", shortcut.shortcut.second);
|
||||
qt_config->endGroup();
|
||||
qt_config->endGroup();
|
||||
}
|
||||
qt_config->endGroup();
|
||||
|
||||
|
|
|
@ -38,6 +38,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>
|
||||
|
@ -118,6 +123,12 @@
|
|||
<header>configuration/configure_input.h</header>
|
||||
<container>1</container>
|
||||
</customwidget>
|
||||
<customwidget>
|
||||
<class>ConfigureHotkeys</class>
|
||||
<extends>QWidget</extends>
|
||||
<header>configuration/configure_hotkeys.h</header>
|
||||
<container>1</container>
|
||||
</customwidget>
|
||||
<customwidget>
|
||||
<class>ConfigureGraphics</class>
|
||||
<extends>QWidget</extends>
|
||||
|
|
|
@ -13,15 +13,25 @@
|
|||
ConfigureDialog::ConfigureDialog(QWidget* parent, const HotkeyRegistry& registry)
|
||||
: QDialog(parent), ui(new Ui::ConfigureDialog) {
|
||||
ui->setupUi(this);
|
||||
ui->generalTab->PopulateHotkeyList(registry);
|
||||
ui->hotkeysTab->Populate(registry);
|
||||
|
||||
this->PopulateSelectionList();
|
||||
connect(ui->uiTab, &ConfigureUi::languageChanged, this, &ConfigureDialog::onLanguageChanged);
|
||||
connect(ui->selectorList, &QListWidget::itemSelectionChanged, this,
|
||||
&ConfigureDialog::UpdateVisibleTabs);
|
||||
|
||||
adjustSize();
|
||||
|
||||
ui->selectorList->setCurrentRow(0);
|
||||
|
||||
connect(ui->inputTab, &ConfigureInput::InputKeysChanged, ui->hotkeysTab,
|
||||
&ConfigureHotkeys::OnInputKeysChanged);
|
||||
connect(ui->hotkeysTab, &ConfigureHotkeys::HotkeysChanged, ui->inputTab,
|
||||
&ConfigureInput::OnHotkeysChanged);
|
||||
connect(ui->hotkeysTab, &ConfigureHotkeys::HotkeysChanged, this,
|
||||
[this]() { emit UpdateHotkeys(); });
|
||||
|
||||
// Synchronise lists upon initialisation
|
||||
ui->inputTab->EmitInputKeysChanged();
|
||||
ui->hotkeysTab->EmitHotkeysChanged();
|
||||
}
|
||||
|
||||
ConfigureDialog::~ConfigureDialog() = default;
|
||||
|
@ -38,11 +48,12 @@ void ConfigureDialog::setConfiguration() {
|
|||
ui->uiTab->setConfiguration();
|
||||
}
|
||||
|
||||
void ConfigureDialog::applyConfiguration() {
|
||||
void ConfigureDialog::applyConfiguration(HotkeyRegistry& registry) {
|
||||
ui->generalTab->applyConfiguration();
|
||||
ui->systemTab->applyConfiguration();
|
||||
ui->inputTab->applyConfiguration();
|
||||
ui->inputTab->ApplyProfile();
|
||||
ui->hotkeysTab->applyConfiguration(registry);
|
||||
ui->graphicsTab->applyConfiguration();
|
||||
ui->audioTab->applyConfiguration();
|
||||
ui->cameraTab->applyConfiguration();
|
||||
|
@ -61,7 +72,7 @@ void ConfigureDialog::PopulateSelectionList() {
|
|||
{QT_TR_NOOP("General"), QT_TR_NOOP("Web"), QT_TR_NOOP("Debug"), QT_TR_NOOP("UI")}},
|
||||
{tr("System"), {QT_TR_NOOP("System"), QT_TR_NOOP("Audio"), QT_TR_NOOP("Camera")}},
|
||||
{tr("Graphics"), {QT_TR_NOOP("Graphics")}},
|
||||
{tr("Controls"), {QT_TR_NOOP("Input")}}}};
|
||||
{tr("Controls"), {QT_TR_NOOP("Input"), QT_TR_NOOP("Hotkeys")}}}};
|
||||
|
||||
for (const auto& entry : items) {
|
||||
auto* item = new QListWidgetItem(entry.first);
|
||||
|
@ -91,6 +102,7 @@ void ConfigureDialog::retranslateUi() {
|
|||
ui->generalTab->retranslateUi();
|
||||
ui->systemTab->retranslateUi();
|
||||
ui->inputTab->retranslateUi();
|
||||
ui->hotkeysTab->retranslateUi();
|
||||
ui->graphicsTab->retranslateUi();
|
||||
ui->audioTab->retranslateUi();
|
||||
ui->cameraTab->retranslateUi();
|
||||
|
@ -105,9 +117,11 @@ void ConfigureDialog::UpdateVisibleTabs() {
|
|||
return;
|
||||
|
||||
const QHash<QString, QWidget*> widgets = {
|
||||
{"General", ui->generalTab}, {"System", ui->systemTab}, {"Input", ui->inputTab},
|
||||
{"Graphics", ui->graphicsTab}, {"Audio", ui->audioTab}, {"Camera", ui->cameraTab},
|
||||
{"Debug", ui->debugTab}, {"Web", ui->webTab}, {"UI", ui->uiTab}};
|
||||
{tr("General"), ui->generalTab}, {tr("System"), ui->systemTab},
|
||||
{tr("Input"), ui->inputTab}, {tr("Hotkeys"), ui->hotkeysTab},
|
||||
{tr("Graphics"), ui->graphicsTab}, {tr("Audio"), ui->audioTab},
|
||||
{tr("Camera"), ui->cameraTab}, {tr("Debug"), ui->debugTab},
|
||||
{tr("Web"), ui->webTab}, {tr("UI"), ui->uiTab}};
|
||||
|
||||
ui->tabWidget->clear();
|
||||
|
||||
|
|
|
@ -20,15 +20,16 @@ public:
|
|||
explicit ConfigureDialog(QWidget* parent, const HotkeyRegistry& registry);
|
||||
~ConfigureDialog() override;
|
||||
|
||||
void applyConfiguration();
|
||||
void UpdateVisibleTabs();
|
||||
void PopulateSelectionList();
|
||||
void applyConfiguration(HotkeyRegistry& registry);
|
||||
|
||||
private slots:
|
||||
void onLanguageChanged(const QString& locale);
|
||||
|
||||
signals:
|
||||
void languageChanged(const QString& locale);
|
||||
void UpdateHotkeys();
|
||||
|
||||
private:
|
||||
void setConfiguration();
|
||||
|
|
|
@ -32,10 +32,6 @@ void ConfigureGeneral::setConfiguration() {
|
|||
ui->region_combobox->setCurrentIndex(Settings::values.region_value + 1);
|
||||
}
|
||||
|
||||
void ConfigureGeneral::PopulateHotkeyList(const HotkeyRegistry& registry) {
|
||||
ui->hotkeysDialog->Populate(registry);
|
||||
}
|
||||
|
||||
void ConfigureGeneral::ResetDefaults() {
|
||||
QMessageBox::StandardButton answer = QMessageBox::question(
|
||||
this, tr("Citra"),
|
||||
|
@ -60,5 +56,4 @@ void ConfigureGeneral::applyConfiguration() {
|
|||
|
||||
void ConfigureGeneral::retranslateUi() {
|
||||
ui->retranslateUi(this);
|
||||
ui->hotkeysDialog->retranslateUi();
|
||||
}
|
||||
|
|
|
@ -20,7 +20,6 @@ public:
|
|||
explicit ConfigureGeneral(QWidget* parent = nullptr);
|
||||
~ConfigureGeneral() override;
|
||||
|
||||
void PopulateHotkeyList(const HotkeyRegistry& registry);
|
||||
void ResetDefaults();
|
||||
void applyConfiguration();
|
||||
void retranslateUi();
|
||||
|
|
|
@ -7,7 +7,7 @@
|
|||
<x>0</x>
|
||||
<y>0</y>
|
||||
<width>345</width>
|
||||
<height>504</height>
|
||||
<height>357</height>
|
||||
</rect>
|
||||
</property>
|
||||
<property name="windowTitle">
|
||||
|
@ -21,17 +21,13 @@
|
|||
<property name="title">
|
||||
<string>General</string>
|
||||
</property>
|
||||
<layout class="QHBoxLayout" name="horizontalLayout_3">
|
||||
<layout class="QVBoxLayout" name="verticalLayout_5">
|
||||
<item>
|
||||
<layout class="QVBoxLayout" name="verticalLayout_2">
|
||||
<item>
|
||||
<widget class="QCheckBox" name="toggle_check_exit">
|
||||
<property name="text">
|
||||
<string>Confirm exit while emulation is running</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
<widget class="QCheckBox" name="toggle_check_exit">
|
||||
<property name="text">
|
||||
<string>Confirm exit while emulation is running</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
</widget>
|
||||
|
@ -41,24 +37,20 @@
|
|||
<property name="title">
|
||||
<string>Updates</string>
|
||||
</property>
|
||||
<layout class="QHBoxLayout" name="horizontalLayout_update">
|
||||
<layout class="QVBoxLayout" name="verticalLayout_4">
|
||||
<item>
|
||||
<layout class="QVBoxLayout" name="verticalLayout_update">
|
||||
<item>
|
||||
<widget class="QCheckBox" name="toggle_update_check">
|
||||
<property name="text">
|
||||
<string>Check for updates on start</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QCheckBox" name="toggle_auto_update">
|
||||
<property name="text">
|
||||
<string>Silently auto update after closing</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
<widget class="QCheckBox" name="toggle_update_check">
|
||||
<property name="text">
|
||||
<string>Check for updates on start</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QCheckBox" name="toggle_auto_update">
|
||||
<property name="text">
|
||||
<string>Silently auto update after closing</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
</widget>
|
||||
|
@ -68,81 +60,57 @@
|
|||
<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>Auto-select</string>
|
||||
</property>
|
||||
</item>
|
||||
<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>
|
||||
<layout class="QGridLayout" name="gridLayout">
|
||||
<item row="0" column="0">
|
||||
<widget class="QLabel" name="label">
|
||||
<property name="text">
|
||||
<string>Region:</string>
|
||||
</property>
|
||||
</widget>
|
||||
</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 row="0" column="1">
|
||||
<widget class="QComboBox" name="region_combobox">
|
||||
<item>
|
||||
<widget class="GHotkeysDialog" name="hotkeysDialog" native="true"/>
|
||||
<property name="text">
|
||||
<string>Auto-select</string>
|
||||
</property>
|
||||
</item>
|
||||
</layout>
|
||||
<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>
|
||||
</widget>
|
||||
|
@ -158,14 +126,6 @@
|
|||
</item>
|
||||
</layout>
|
||||
</widget>
|
||||
<customwidgets>
|
||||
<customwidget>
|
||||
<class>GHotkeysDialog</class>
|
||||
<extends>QWidget</extends>
|
||||
<header>hotkeys.h</header>
|
||||
<container>1</container>
|
||||
</customwidget>
|
||||
</customwidgets>
|
||||
<resources/>
|
||||
<connections/>
|
||||
</ui>
|
||||
|
|
130
src/citra_qt/configuration/configure_hotkeys.cpp
Normal file
130
src/citra_qt/configuration/configure_hotkeys.cpp
Normal file
|
@ -0,0 +1,130 @@
|
|||
// Copyright 2017 Citra Emulator Project
|
||||
// Licensed under GPLv2 or any later version
|
||||
// Refer to the license.txt file included.
|
||||
|
||||
#include <QMessageBox>
|
||||
#include "citra_qt/configuration/configure_hotkeys.h"
|
||||
#include "citra_qt/hotkeys.h"
|
||||
#include "citra_qt/util/sequence_dialog/sequence_dialog.h"
|
||||
#include "core/settings.h"
|
||||
#include "ui_configure_hotkeys.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")});
|
||||
|
||||
ui->hotkey_list->setSelectionMode(QTreeView::SingleSelection);
|
||||
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);
|
||||
ui->hotkey_list->setEditTriggers(QTreeView::NoEditTriggers);
|
||||
}
|
||||
|
||||
ConfigureHotkeys::~ConfigureHotkeys() {}
|
||||
|
||||
void ConfigureHotkeys::EmitHotkeysChanged() {
|
||||
emit HotkeysChanged(GetUsedKeyList());
|
||||
}
|
||||
|
||||
QList<QKeySequence> ConfigureHotkeys::GetUsedKeyList() {
|
||||
QList<QKeySequence> list;
|
||||
for (int r = 0; r < model->rowCount(); r++) {
|
||||
QStandardItem* parent = model->item(r, 0);
|
||||
for (int r2 = 0; r2 < parent->rowCount(); r2++) {
|
||||
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) {
|
||||
QStandardItem* parent_item = new QStandardItem(group.first);
|
||||
parent_item->setEditable(false);
|
||||
for (const auto& hotkey : group.second) {
|
||||
QStandardItem* action = new QStandardItem(hotkey.first);
|
||||
QStandardItem* 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::OnInputKeysChanged(QList<QKeySequence> new_key_list) {
|
||||
input_keys_list = new_key_list;
|
||||
}
|
||||
|
||||
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(), QKeySequence::NativeText)) {
|
||||
model->setData(index, previous_key);
|
||||
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 input_keys_list.contains(key_sequence) || GetUsedKeyList().contains(key_sequence);
|
||||
}
|
||||
|
||||
void ConfigureHotkeys::applyConfiguration(HotkeyRegistry& registry) {
|
||||
for (int key_id = 0; key_id < model->rowCount(); key_id++) {
|
||||
QStandardItem* parent = model->item(key_id, 0);
|
||||
for (int key_column_id = 0; key_column_id < parent->rowCount(); key_column_id++) {
|
||||
QStandardItem* action = parent->child(key_column_id, 0);
|
||||
QStandardItem* keyseq = parent->child(key_column_id, 1);
|
||||
for (auto key_iterator = registry.hotkey_groups.begin();
|
||||
key_iterator != registry.hotkey_groups.end(); ++key_iterator) {
|
||||
if (key_iterator->first == parent->text()) {
|
||||
for (auto it2 = key_iterator->second.begin(); it2 != key_iterator->second.end();
|
||||
++it2) {
|
||||
if (it2->first == action->text()) {
|
||||
it2->second.keyseq = QKeySequence(keyseq->text());
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
registry.SaveHotkeys();
|
||||
Settings::Apply();
|
||||
}
|
||||
|
||||
void ConfigureHotkeys::retranslateUi() {
|
||||
ui->retranslateUi(this);
|
||||
}
|
48
src/citra_qt/configuration/configure_hotkeys.h
Normal file
48
src/citra_qt/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 <QStandardItemModel>
|
||||
#include <QWidget>
|
||||
#include "common/param_package.h"
|
||||
#include "core/settings.h"
|
||||
|
||||
namespace Ui {
|
||||
class ConfigureHotkeys;
|
||||
}
|
||||
|
||||
class HotkeyRegistry;
|
||||
|
||||
class ConfigureHotkeys : public QWidget {
|
||||
Q_OBJECT
|
||||
|
||||
public:
|
||||
explicit ConfigureHotkeys(QWidget* parent = nullptr);
|
||||
~ConfigureHotkeys();
|
||||
|
||||
void applyConfiguration(HotkeyRegistry& registry);
|
||||
void retranslateUi();
|
||||
|
||||
void EmitHotkeysChanged();
|
||||
|
||||
void Populate(const HotkeyRegistry& registry);
|
||||
|
||||
public slots:
|
||||
void OnInputKeysChanged(QList<QKeySequence> new_key_list);
|
||||
|
||||
signals:
|
||||
void HotkeysChanged(QList<QKeySequence> new_key_list);
|
||||
|
||||
private:
|
||||
void Configure(QModelIndex index);
|
||||
bool IsUsedKey(QKeySequence key_sequence);
|
||||
QList<QKeySequence> GetUsedKeyList();
|
||||
|
||||
std::unique_ptr<Ui::ConfigureHotkeys> ui;
|
||||
|
||||
QList<QKeySequence> input_keys_list;
|
||||
QStandardItemModel* model;
|
||||
};
|
35
src/citra_qt/configuration/configure_hotkeys.ui
Normal file
35
src/citra_qt/configuration/configure_hotkeys.ui
Normal file
|
@ -0,0 +1,35 @@
|
|||
<?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"/>
|
||||
</item>
|
||||
</layout>
|
||||
</item>
|
||||
</layout>
|
||||
</widget>
|
||||
<resources/>
|
||||
<connections/>
|
||||
</ui>
|
|
@ -276,6 +276,30 @@ void ConfigureInput::ApplyProfile() {
|
|||
Settings::values.current_input_profile_index = ui->profile->currentIndex();
|
||||
}
|
||||
|
||||
void ConfigureInput::EmitInputKeysChanged() {
|
||||
emit InputKeysChanged(GetUsedKeyboardKeys());
|
||||
}
|
||||
|
||||
void ConfigureInput::OnHotkeysChanged(QList<QKeySequence> new_key_list) {
|
||||
hotkey_list = new_key_list;
|
||||
}
|
||||
|
||||
QList<QKeySequence> ConfigureInput::GetUsedKeyboardKeys() {
|
||||
QList<QKeySequence> list;
|
||||
for (int button = 0; button < Settings::NativeButton::NumButtons; button++) {
|
||||
auto button_param = buttons_param[button];
|
||||
|
||||
if (button_param.Get("engine", "") == "keyboard") {
|
||||
list << QKeySequence(button_param.Get("code", 0));
|
||||
}
|
||||
}
|
||||
|
||||
// TODO(adityaruplaha): Add home button to list when we finally emulate it
|
||||
// Button ID of home button is 14: Reffered from citra_qt/configuration/config.cpp
|
||||
list.removeOne(list.indexOf(QKeySequence(buttons_param[14].Get("code", 0))));
|
||||
return list;
|
||||
}
|
||||
|
||||
void ConfigureInput::loadConfiguration() {
|
||||
std::transform(Settings::values.current_input_profile.buttons.begin(),
|
||||
Settings::values.current_input_profile.buttons.end(), buttons_param.begin(),
|
||||
|
@ -332,11 +356,14 @@ void ConfigureInput::updateButtonLabels() {
|
|||
}
|
||||
analog_map_stick[analog_id]->setText(tr("Set Analog Stick"));
|
||||
}
|
||||
|
||||
EmitInputKeysChanged();
|
||||
}
|
||||
|
||||
void ConfigureInput::handleClick(QPushButton* button,
|
||||
std::function<void(const Common::ParamPackage&)> new_input_setter,
|
||||
InputCommon::Polling::DeviceType type) {
|
||||
previous_key_code = QKeySequence(button->text())[0];
|
||||
button->setText(tr("[press key]"));
|
||||
button->setFocus();
|
||||
|
||||
|
@ -378,16 +405,26 @@ void ConfigureInput::keyPressEvent(QKeyEvent* event) {
|
|||
if (!input_setter || !event)
|
||||
return;
|
||||
|
||||
if (event->key() != Qt::Key_Escape) {
|
||||
if (event->key() != Qt::Key_Escape && event->key() != previous_key_code) {
|
||||
if (want_keyboard_keys) {
|
||||
// Check if key is already bound
|
||||
if (hotkey_list.contains(QKeySequence(event->key())) ||
|
||||
GetUsedKeyboardKeys().contains(QKeySequence(event->key()))) {
|
||||
setPollingResult({}, true);
|
||||
QMessageBox::critical(this, tr("Error!"),
|
||||
tr("You're using a key that's already bound."));
|
||||
return;
|
||||
}
|
||||
setPollingResult(Common::ParamPackage{InputCommon::GenerateKeyboardParam(event->key())},
|
||||
false);
|
||||
} else {
|
||||
// Escape key wasn't pressed and we don't want any keyboard keys, so don't stop polling
|
||||
// Escape key wasn't pressed and we don't want any keyboard keys, so don't stop
|
||||
// polling
|
||||
return;
|
||||
}
|
||||
}
|
||||
setPollingResult({}, true);
|
||||
previous_key_code = 0;
|
||||
}
|
||||
|
||||
void ConfigureInput::retranslateUi() {
|
||||
|
|
|
@ -11,6 +11,7 @@
|
|||
#include <string>
|
||||
#include <unordered_map>
|
||||
#include <QKeyEvent>
|
||||
#include <QKeySequence>
|
||||
#include <QWidget>
|
||||
#include "common/param_package.h"
|
||||
#include "core/settings.h"
|
||||
|
@ -38,6 +39,13 @@ public:
|
|||
|
||||
/// Load configuration settings.
|
||||
void loadConfiguration();
|
||||
void EmitInputKeysChanged();
|
||||
|
||||
public slots:
|
||||
void OnHotkeysChanged(QList<QKeySequence> new_key_list);
|
||||
|
||||
signals:
|
||||
void InputKeysChanged(QList<QKeySequence> new_key_list);
|
||||
|
||||
// Save the current input profile index
|
||||
void ApplyProfile();
|
||||
|
@ -72,10 +80,16 @@ private:
|
|||
|
||||
std::vector<std::unique_ptr<InputCommon::Polling::DevicePoller>> device_pollers;
|
||||
|
||||
/// Keys currently registered as hotkeys
|
||||
QList<QKeySequence> hotkey_list;
|
||||
|
||||
/// A flag to indicate if keyboard keys are okay when configuring an input. If this is false,
|
||||
/// keyboard events are ignored.
|
||||
bool want_keyboard_keys = false;
|
||||
|
||||
/// Generates list of all used keys
|
||||
QList<QKeySequence> GetUsedKeyboardKeys();
|
||||
|
||||
/// Restore all buttons to their default values.
|
||||
void restoreDefaults();
|
||||
/// Clear all input configuration
|
||||
|
@ -89,6 +103,9 @@ private:
|
|||
std::function<void(const Common::ParamPackage&)> new_input_setter,
|
||||
InputCommon::Polling::DeviceType type);
|
||||
|
||||
/// The key code of the previous state of the key being currently bound.
|
||||
int previous_key_code;
|
||||
|
||||
/// Finish polling and configure input using the input_setter
|
||||
void setPollingResult(const Common::ParamPackage& params, bool abort);
|
||||
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue