From e91327c86a863b9419fd3695b2400a52336ec3b5 Mon Sep 17 00:00:00 2001
From: Anon <makotech222@users.noreply.github.com>
Date: Fri, 29 Jul 2016 07:45:49 -0500
Subject: [PATCH] Input GUI: Add tab to remap controls (#1900)

---
 src/citra_qt/CMakeLists.txt       |   3 +
 src/citra_qt/config.cpp           |   9 +-
 src/citra_qt/config.h             |   6 +-
 src/citra_qt/configure.ui         |   8 +-
 src/citra_qt/configure_dialog.cpp |   1 +
 src/citra_qt/configure_input.cpp  | 149 ++++++++
 src/citra_qt/configure_input.h    |  63 ++++
 src/citra_qt/configure_input.ui   | 593 ++++++++++++++++++++++++++++++
 src/citra_qt/main.cpp             |   1 +
 9 files changed, 825 insertions(+), 8 deletions(-)
 create mode 100644 src/citra_qt/configure_input.cpp
 create mode 100644 src/citra_qt/configure_input.h
 create mode 100644 src/citra_qt/configure_input.ui

diff --git a/src/citra_qt/CMakeLists.txt b/src/citra_qt/CMakeLists.txt
index 017b43871f..4402ad9958 100644
--- a/src/citra_qt/CMakeLists.txt
+++ b/src/citra_qt/CMakeLists.txt
@@ -23,6 +23,7 @@ set(SRCS
             configure_dialog.cpp
             configure_general.cpp
             configure_system.cpp
+            configure_input.cpp
             game_list.cpp
             hotkeys.cpp
             main.cpp
@@ -54,6 +55,7 @@ set(HEADERS
             configure_dialog.h
             configure_general.h
             configure_system.h
+            configure_input.h
             game_list.h
             game_list_p.h
             hotkeys.h
@@ -72,6 +74,7 @@ set(UIS
             configure_debug.ui
             configure_general.ui
             configure_system.ui
+            configure_input.ui
             hotkeys.ui
             main.ui
             )
diff --git a/src/citra_qt/config.cpp b/src/citra_qt/config.cpp
index ba7edaff9c..0e5f285c02 100644
--- a/src/citra_qt/config.cpp
+++ b/src/citra_qt/config.cpp
@@ -3,14 +3,11 @@
 // Refer to the license.txt file included.
 
 #include <QSettings>
-#include <QString>
-#include <QStringList>
 
 #include "citra_qt/config.h"
 #include "citra_qt/ui_settings.h"
 
 #include "common/file_util.h"
-#include "core/settings.h"
 
 Config::Config() {
     // TODO: Don't hardcode the path; let the frontend decide where to put the config files.
@@ -21,7 +18,7 @@ Config::Config() {
     Reload();
 }
 
-static const std::array<QVariant, Settings::NativeInput::NUM_INPUTS> defaults = {
+const std::array<QVariant, Settings::NativeInput::NUM_INPUTS> Config::defaults = {
     // directly mapped keys
     Qt::Key_A, Qt::Key_S, Qt::Key_Z, Qt::Key_X,
     Qt::Key_Q, Qt::Key_W, Qt::Key_1, Qt::Key_2,
@@ -109,7 +106,7 @@ void Config::ReadValues() {
             UISettings::values.shortcuts.emplace_back(
                         UISettings::Shortcut(group + "/" + hotkey,
                                              UISettings::ContextualShortcut(qt_config->value("KeySeq").toString(),
-                                                                           qt_config->value("Context").toInt())));
+                                                                            qt_config->value("Context").toInt())));
             qt_config->endGroup();
         }
 
@@ -191,7 +188,7 @@ void Config::SaveValues() {
     qt_config->endGroup();
 
     qt_config->beginGroup("Shortcuts");
-    for (auto shortcut : UISettings::values.shortcuts ) {
+    for (auto shortcut : UISettings::values.shortcuts) {
         qt_config->setValue(shortcut.first + "/KeySeq", shortcut.second.first);
         qt_config->setValue(shortcut.first + "/Context", shortcut.second.second);
     }
diff --git a/src/citra_qt/config.h b/src/citra_qt/config.h
index dd0b2ef0b4..0cbdb707fa 100644
--- a/src/citra_qt/config.h
+++ b/src/citra_qt/config.h
@@ -1,10 +1,13 @@
-// Copyright 2014 Citra Emulator Project
+// Copyright 2014 Citra Emulator Project
 // Licensed under GPLv2 or any later version
 // Refer to the license.txt file included.
 
 #pragma once
 
 #include <string>
+#include <QVariant>
+
+#include "core/settings.h"
 
 class QSettings;
 
@@ -20,4 +23,5 @@ public:
 
     void Reload();
     void Save();
+    static const std::array<QVariant, Settings::NativeInput::NUM_INPUTS> defaults;
 };
diff --git a/src/citra_qt/configure.ui b/src/citra_qt/configure.ui
index 4a9c526501..15fe173235 100644
--- a/src/citra_qt/configure.ui
+++ b/src/citra_qt/configure.ui
@@ -29,7 +29,7 @@
        <string>System</string>
       </attribute>
      </widget>
-     <widget class="QWidget" name="inputTab">
+     <widget class="ConfigureInput" name="inputTab">
       <attribute name="title">
        <string>Input</string>
       </attribute>
@@ -80,6 +80,12 @@
    <header>configure_debug.h</header>
    <container>1</container>
   </customwidget>
+   <customwidget>
+     <class>ConfigureInput</class>
+     <extends>QWidget</extends>
+     <header>configure_input.h</header>
+     <container>1</container>
+   </customwidget>
  </customwidgets>
  <resources/>
  <connections>
diff --git a/src/citra_qt/configure_dialog.cpp b/src/citra_qt/configure_dialog.cpp
index 77c266d011..459fac4bb0 100644
--- a/src/citra_qt/configure_dialog.cpp
+++ b/src/citra_qt/configure_dialog.cpp
@@ -30,6 +30,7 @@ void ConfigureDialog::setConfiguration() {
 void ConfigureDialog::applyConfiguration() {
     ui->generalTab->applyConfiguration();
     ui->systemTab->applyConfiguration();
+    ui->inputTab->applyConfiguration();
     ui->audioTab->applyConfiguration();
     ui->debugTab->applyConfiguration();
 }
diff --git a/src/citra_qt/configure_input.cpp b/src/citra_qt/configure_input.cpp
new file mode 100644
index 0000000000..9c7a671748
--- /dev/null
+++ b/src/citra_qt/configure_input.cpp
@@ -0,0 +1,149 @@
+// Copyright 2016 Citra Emulator Project
+// Licensed under GPLv2 or any later version
+// Refer to the license.txt file included.
+
+#include <memory>
+#include <utility>
+#include <QTimer>
+
+#include "citra_qt/configure_input.h"
+
+ConfigureInput::ConfigureInput(QWidget* parent) : QWidget(parent), ui(std::make_unique<Ui::ConfigureInput>()) {
+    ui->setupUi(this);
+
+    // Initialize mapping of input enum to UI button.
+    input_mapping = {
+        { std::make_pair(Settings::NativeInput::Values::A, ui->buttonA) },
+        { std::make_pair(Settings::NativeInput::Values::B, ui->buttonB) },
+        { std::make_pair(Settings::NativeInput::Values::X, ui->buttonX) },
+        { std::make_pair(Settings::NativeInput::Values::Y, ui->buttonY) },
+        { std::make_pair(Settings::NativeInput::Values::L, ui->buttonL) },
+        { std::make_pair(Settings::NativeInput::Values::R, ui->buttonR) },
+        { std::make_pair(Settings::NativeInput::Values::ZL, ui->buttonZL) },
+        { std::make_pair(Settings::NativeInput::Values::ZR, ui->buttonZR) },
+        { std::make_pair(Settings::NativeInput::Values::START, ui->buttonStart) },
+        { std::make_pair(Settings::NativeInput::Values::SELECT, ui->buttonSelect) },
+        { std::make_pair(Settings::NativeInput::Values::HOME, ui->buttonHome) },
+        { std::make_pair(Settings::NativeInput::Values::DUP, ui->buttonDpadUp) },
+        { std::make_pair(Settings::NativeInput::Values::DDOWN, ui->buttonDpadDown) },
+        { std::make_pair(Settings::NativeInput::Values::DLEFT, ui->buttonDpadLeft) },
+        { std::make_pair(Settings::NativeInput::Values::DRIGHT, ui->buttonDpadRight) },
+        { std::make_pair(Settings::NativeInput::Values::CUP, ui->buttonCStickUp) },
+        { std::make_pair(Settings::NativeInput::Values::CDOWN, ui->buttonCStickDown) },
+        { std::make_pair(Settings::NativeInput::Values::CLEFT, ui->buttonCStickLeft) },
+        { std::make_pair(Settings::NativeInput::Values::CRIGHT, ui->buttonCStickRight) },
+        { std::make_pair(Settings::NativeInput::Values::CIRCLE_UP, ui->buttonCircleUp) },
+        { std::make_pair(Settings::NativeInput::Values::CIRCLE_DOWN, ui->buttonCircleDown) },
+        { std::make_pair(Settings::NativeInput::Values::CIRCLE_LEFT, ui->buttonCircleLeft) },
+        { std::make_pair(Settings::NativeInput::Values::CIRCLE_RIGHT, ui->buttonCircleRight) },
+        { std::make_pair(Settings::NativeInput::Values::CIRCLE_MODIFIER, ui->buttonCircleMod) },
+    };
+
+    // Attach handle click method to each button click.
+    for (const auto& entry : input_mapping) {
+        connect(entry.second, SIGNAL(released()), this, SLOT(handleClick()));
+    }
+    connect(ui->buttonRestoreDefaults, SIGNAL(released()), this, SLOT(restoreDefaults()));
+    setFocusPolicy(Qt::ClickFocus);
+    timer = new QTimer(this);
+    timer->setSingleShot(true);
+    connect(timer, &QTimer::timeout, this, [&]() { key_pressed = Qt::Key_Escape; setKey(); });
+    this->setConfiguration();
+}
+
+void ConfigureInput::handleClick() {
+    QPushButton* sender = qobject_cast<QPushButton*>(QObject::sender());
+    previous_mapping = sender->text();
+    sender->setText(tr("[waiting]"));
+    sender->setFocus();
+    grabKeyboard();
+    grabMouse();
+    changing_button = sender;
+    timer->start(5000); //Cancel after 5 seconds
+}
+
+void ConfigureInput::applyConfiguration() {
+    for (int i = 0; i < Settings::NativeInput::NUM_INPUTS; ++i) {
+        int value = getKeyValue(input_mapping[Settings::NativeInput::Values(i)]->text());
+        Settings::values.input_mappings[Settings::NativeInput::All[i]] = value;
+    }
+    Settings::Apply();
+}
+
+void ConfigureInput::setConfiguration() {
+    for (int i = 0; i < Settings::NativeInput::NUM_INPUTS; ++i) {
+        QString keyValue = getKeyName(Settings::values.input_mappings[i]);
+        input_mapping[Settings::NativeInput::Values(i)]->setText(keyValue);
+    }
+}
+
+void ConfigureInput::keyPressEvent(QKeyEvent* event) {
+    if (!changing_button)
+        return;
+    if (!event || event->key() == Qt::Key_unknown)
+        return;
+    key_pressed = event->key();
+    timer->stop();
+    setKey();
+}
+
+void ConfigureInput::setKey() {
+    const QString key_value = getKeyName(key_pressed);
+    if (key_pressed == Qt::Key_Escape)
+        changing_button->setText(previous_mapping);
+    else
+        changing_button->setText(key_value);
+    removeDuplicates(key_value);
+    key_pressed = Qt::Key_unknown;
+    releaseKeyboard();
+    releaseMouse();
+    changing_button = nullptr;
+    previous_mapping = nullptr;
+}
+
+QString ConfigureInput::getKeyName(int key_code) const {
+    if (key_code == Qt::Key_Shift)
+        return tr("Shift");
+    if (key_code == Qt::Key_Control)
+        return tr("Ctrl");
+    if (key_code == Qt::Key_Alt)
+        return tr("Alt");
+    if (key_code == Qt::Key_Meta)
+        return "";
+    if (key_code == -1)
+        return "";
+
+    return QKeySequence(key_code).toString();
+}
+
+Qt::Key ConfigureInput::getKeyValue(const QString& text) const {
+    if (text == "Shift")
+        return Qt::Key_Shift;
+    if (text == "Ctrl")
+        return Qt::Key_Control;
+    if (text == "Alt")
+        return Qt::Key_Alt;
+    if (text == "Meta")
+        return Qt::Key_unknown;
+    if (text == "")
+        return Qt::Key_unknown;
+
+    return Qt::Key(QKeySequence(text)[0]);
+}
+
+void ConfigureInput::removeDuplicates(const QString& newValue) {
+    for (int i = 0; i < Settings::NativeInput::NUM_INPUTS; ++i) {
+        if (changing_button != input_mapping[Settings::NativeInput::Values(i)]) {
+            const QString oldValue = input_mapping[Settings::NativeInput::Values(i)]->text();
+            if (newValue == oldValue)
+                input_mapping[Settings::NativeInput::Values(i)]->setText("");
+        }
+    }
+}
+
+void ConfigureInput::restoreDefaults() {
+    for (int i = 0; i < Settings::NativeInput::NUM_INPUTS; ++i) {
+        const QString keyValue = getKeyName(Config::defaults[i].toInt());
+        input_mapping[Settings::NativeInput::Values(i)]->setText(keyValue);
+    }
+}
diff --git a/src/citra_qt/configure_input.h b/src/citra_qt/configure_input.h
new file mode 100644
index 0000000000..fe8ea55802
--- /dev/null
+++ b/src/citra_qt/configure_input.h
@@ -0,0 +1,63 @@
+// Copyright 2016 Citra Emulator Project
+// Licensed under GPLv2 or any later version
+// Refer to the license.txt file included.
+
+#pragma once
+
+#include <QWidget>
+#include <QKeyEvent>
+
+#include "citra_qt/config.h"
+#include "core/settings.h"
+#include "ui_configure_input.h"
+
+class QPushButton;
+class QString;
+class QTimer;
+
+namespace Ui {
+    class ConfigureInput;
+}
+
+class ConfigureInput : public QWidget {
+    Q_OBJECT
+
+public:
+    explicit ConfigureInput(QWidget* parent = nullptr);
+
+    /// Save all button configurations to settings file
+    void applyConfiguration();
+
+private:
+    std::unique_ptr<Ui::ConfigureInput> ui;
+    std::map<Settings::NativeInput::Values, QPushButton*> input_mapping;
+    int key_pressed;
+    QPushButton* changing_button = nullptr; ///< button currently waiting for key press.
+    QString previous_mapping;
+    QTimer* timer;
+
+    /// Load configuration settings into button text
+    void setConfiguration();
+
+    /// Check all inputs for duplicate keys. Clears out any other button with the same value as this button's new value.
+    void removeDuplicates(const QString& newValue);
+
+    /// Handle key press event for input tab when a button is 'waiting'.
+    void keyPressEvent(QKeyEvent* event) override;
+
+    /// Convert key ASCII value to its' letter/name
+    QString getKeyName(int key_code) const;
+
+    /// Convert letter/name of key to its ASCII value.
+    Qt::Key getKeyValue(const QString& text) const;
+
+    /// Set button text to name of key pressed.
+    void setKey();
+
+private slots:
+    /// Event handler for all button released() event.
+    void handleClick();
+
+    /// Restore all buttons to their default values.
+    void restoreDefaults();
+};
diff --git a/src/citra_qt/configure_input.ui b/src/citra_qt/configure_input.ui
new file mode 100644
index 0000000000..a040d4df4c
--- /dev/null
+++ b/src/citra_qt/configure_input.ui
@@ -0,0 +1,593 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<ui version="4.0">
+ <class>ConfigureInput</class>
+ <widget class="QWidget" name="ConfigureInput">
+  <property name="geometry">
+   <rect>
+    <x>0</x>
+    <y>0</y>
+    <width>370</width>
+    <height>534</height>
+   </rect>
+  </property>
+  <property name="windowTitle">
+   <string>ConfigureInput</string>
+  </property>
+  <layout class="QVBoxLayout" name="verticalLayout_5">
+   <item>
+    <layout class="QGridLayout" name="gridLayout_7">
+     <item row="0" column="0">
+      <widget class="QGroupBox" name="faceButtons">
+       <property name="title">
+        <string>Face Buttons</string>
+       </property>
+       <property name="flat">
+        <bool>false</bool>
+       </property>
+       <property name="checkable">
+        <bool>false</bool>
+       </property>
+       <layout class="QGridLayout" name="gridLayout">
+        <item row="0" column="0">
+         <layout class="QVBoxLayout" name="verticalLayout">
+          <item>
+           <widget class="QLabel" name="label">
+            <property name="text">
+             <string>A:</string>
+            </property>
+           </widget>
+          </item>
+          <item>
+           <widget class="QPushButton" name="buttonA">
+            <property name="text">
+             <string/>
+            </property>
+           </widget>
+          </item>
+         </layout>
+        </item>
+        <item row="0" column="1">
+         <layout class="QVBoxLayout" name="verticalLayout_2">
+          <item>
+           <widget class="QLabel" name="label_2">
+            <property name="text">
+             <string>B:</string>
+            </property>
+           </widget>
+          </item>
+          <item>
+           <widget class="QPushButton" name="buttonB">
+            <property name="text">
+             <string/>
+            </property>
+           </widget>
+          </item>
+         </layout>
+        </item>
+        <item row="1" column="0">
+         <layout class="QVBoxLayout" name="verticalLayout_3">
+          <item>
+           <widget class="QLabel" name="label_3">
+            <property name="text">
+             <string>X:</string>
+            </property>
+           </widget>
+          </item>
+          <item>
+           <widget class="QPushButton" name="buttonX">
+            <property name="text">
+             <string/>
+            </property>
+           </widget>
+          </item>
+         </layout>
+        </item>
+        <item row="1" column="1">
+         <layout class="QVBoxLayout" name="verticalLayout_4">
+          <item>
+           <widget class="QLabel" name="label_4">
+            <property name="text">
+             <string>Y:</string>
+            </property>
+           </widget>
+          </item>
+          <item>
+           <widget class="QPushButton" name="buttonY">
+            <property name="text">
+             <string/>
+            </property>
+           </widget>
+          </item>
+         </layout>
+        </item>
+       </layout>
+      </widget>
+     </item>
+     <item row="0" column="1">
+      <widget class="QGroupBox" name="faceButtons_2">
+       <property name="title">
+        <string>Directional Pad</string>
+       </property>
+       <property name="flat">
+        <bool>false</bool>
+       </property>
+       <property name="checkable">
+        <bool>false</bool>
+       </property>
+       <layout class="QGridLayout" name="gridLayout_2">
+        <item row="1" column="0">
+         <layout class="QVBoxLayout" name="verticalLayout_12">
+          <item>
+           <widget class="QLabel" name="label_34">
+            <property name="text">
+             <string>Up:</string>
+            </property>
+           </widget>
+          </item>
+          <item>
+           <widget class="QPushButton" name="buttonDpadUp">
+            <property name="text">
+             <string/>
+            </property>
+           </widget>
+          </item>
+         </layout>
+        </item>
+        <item row="1" column="1">
+         <layout class="QVBoxLayout" name="verticalLayout_9">
+          <item>
+           <widget class="QLabel" name="label_35">
+            <property name="text">
+             <string>Down:</string>
+            </property>
+           </widget>
+          </item>
+          <item>
+           <widget class="QPushButton" name="buttonDpadDown">
+            <property name="text">
+             <string/>
+            </property>
+           </widget>
+          </item>
+         </layout>
+        </item>
+        <item row="0" column="0">
+         <layout class="QVBoxLayout" name="verticalLayout_10">
+          <item>
+           <widget class="QLabel" name="label_32">
+            <property name="text">
+             <string>Left:</string>
+            </property>
+           </widget>
+          </item>
+          <item>
+           <widget class="QPushButton" name="buttonDpadLeft">
+            <property name="text">
+             <string/>
+            </property>
+           </widget>
+          </item>
+         </layout>
+        </item>
+        <item row="0" column="1">
+         <layout class="QVBoxLayout" name="verticalLayout_11">
+          <item>
+           <widget class="QLabel" name="label_33">
+            <property name="text">
+             <string>Right:</string>
+            </property>
+           </widget>
+          </item>
+          <item>
+           <widget class="QPushButton" name="buttonDpadRight">
+            <property name="text">
+             <string/>
+            </property>
+           </widget>
+          </item>
+         </layout>
+        </item>
+       </layout>
+      </widget>
+     </item>
+     <item row="1" column="0">
+      <widget class="QGroupBox" name="faceButtons_3">
+       <property name="title">
+        <string>Shoulder Buttons</string>
+       </property>
+       <property name="flat">
+        <bool>false</bool>
+       </property>
+       <property name="checkable">
+        <bool>false</bool>
+       </property>
+       <layout class="QGridLayout" name="gridLayout_3">
+        <item row="0" column="0">
+         <layout class="QVBoxLayout" name="verticalLayout_13">
+          <item>
+           <widget class="QLabel" name="label_17">
+            <property name="text">
+             <string>L:</string>
+            </property>
+           </widget>
+          </item>
+          <item>
+           <widget class="QPushButton" name="buttonL">
+            <property name="text">
+             <string/>
+            </property>
+           </widget>
+          </item>
+         </layout>
+        </item>
+        <item row="0" column="1">
+         <layout class="QVBoxLayout" name="verticalLayout_14">
+          <item>
+           <widget class="QLabel" name="label_19">
+            <property name="text">
+             <string>R:</string>
+            </property>
+           </widget>
+          </item>
+          <item>
+           <widget class="QPushButton" name="buttonR">
+            <property name="text">
+             <string/>
+            </property>
+           </widget>
+          </item>
+         </layout>
+        </item>
+        <item row="1" column="0">
+         <layout class="QVBoxLayout" name="verticalLayout_15">
+          <item>
+           <widget class="QLabel" name="label_20">
+            <property name="text">
+             <string>ZL:</string>
+            </property>
+           </widget>
+          </item>
+          <item>
+           <widget class="QPushButton" name="buttonZL">
+            <property name="text">
+             <string/>
+            </property>
+           </widget>
+          </item>
+         </layout>
+        </item>
+        <item row="1" column="1">
+         <layout class="QVBoxLayout" name="verticalLayout_16">
+          <item>
+           <widget class="QLabel" name="label_18">
+            <property name="text">
+             <string>ZR:</string>
+            </property>
+           </widget>
+          </item>
+          <item>
+           <widget class="QPushButton" name="buttonZR">
+            <property name="text">
+             <string/>
+            </property>
+           </widget>
+          </item>
+         </layout>
+        </item>
+       </layout>
+       <zorder></zorder>
+      </widget>
+     </item>
+     <item row="1" column="1">
+      <widget class="QGroupBox" name="faceButtons_4">
+       <property name="title">
+        <string>Circle Pad</string>
+       </property>
+       <property name="flat">
+        <bool>false</bool>
+       </property>
+       <property name="checkable">
+        <bool>false</bool>
+       </property>
+       <layout class="QGridLayout" name="gridLayout_4">
+        <item row="0" column="0">
+         <layout class="QVBoxLayout" name="verticalLayout_17">
+          <item>
+           <widget class="QLabel" name="label_21">
+            <property name="text">
+             <string>Left:</string>
+            </property>
+           </widget>
+          </item>
+          <item>
+           <widget class="QPushButton" name="buttonCircleLeft">
+            <property name="text">
+             <string/>
+            </property>
+           </widget>
+          </item>
+         </layout>
+        </item>
+        <item row="0" column="1">
+         <layout class="QVBoxLayout" name="verticalLayout_18">
+          <item>
+           <widget class="QLabel" name="label_23">
+            <property name="text">
+             <string>Right:</string>
+            </property>
+           </widget>
+          </item>
+          <item>
+           <widget class="QPushButton" name="buttonCircleRight">
+            <property name="text">
+             <string/>
+            </property>
+           </widget>
+          </item>
+         </layout>
+        </item>
+        <item row="1" column="0">
+         <layout class="QVBoxLayout" name="verticalLayout_19">
+          <item>
+           <widget class="QLabel" name="label_24">
+            <property name="text">
+             <string>Up:</string>
+            </property>
+           </widget>
+          </item>
+          <item>
+           <widget class="QPushButton" name="buttonCircleUp">
+            <property name="text">
+             <string/>
+            </property>
+           </widget>
+          </item>
+         </layout>
+        </item>
+        <item row="1" column="1">
+         <layout class="QVBoxLayout" name="verticalLayout_20">
+          <item>
+           <widget class="QLabel" name="label_22">
+            <property name="text">
+             <string>Down:</string>
+            </property>
+           </widget>
+          </item>
+          <item>
+           <widget class="QPushButton" name="buttonCircleDown">
+            <property name="text">
+             <string/>
+            </property>
+           </widget>
+          </item>
+         </layout>
+        </item>
+       </layout>
+      </widget>
+     </item>
+     <item row="2" column="0">
+      <widget class="QGroupBox" name="faceButtons_5">
+       <property name="title">
+        <string>C-Stick</string>
+       </property>
+       <property name="flat">
+        <bool>false</bool>
+       </property>
+       <property name="checkable">
+        <bool>false</bool>
+       </property>
+       <layout class="QGridLayout" name="gridLayout_5">
+        <item row="0" column="0">
+         <layout class="QVBoxLayout" name="verticalLayout_21">
+          <item>
+           <widget class="QLabel" name="label_25">
+            <property name="text">
+             <string>Left:</string>
+            </property>
+           </widget>
+          </item>
+          <item>
+           <widget class="QPushButton" name="buttonCStickLeft">
+            <property name="text">
+             <string/>
+            </property>
+           </widget>
+          </item>
+         </layout>
+        </item>
+        <item row="0" column="1">
+         <layout class="QVBoxLayout" name="verticalLayout_22">
+          <item>
+           <widget class="QLabel" name="label_27">
+            <property name="text">
+             <string>Right:</string>
+            </property>
+           </widget>
+          </item>
+          <item>
+           <widget class="QPushButton" name="buttonCStickRight">
+            <property name="text">
+             <string/>
+            </property>
+           </widget>
+          </item>
+         </layout>
+        </item>
+        <item row="1" column="0">
+         <layout class="QVBoxLayout" name="verticalLayout_23">
+          <item>
+           <widget class="QLabel" name="label_28">
+            <property name="text">
+             <string>Up:</string>
+            </property>
+           </widget>
+          </item>
+          <item>
+           <widget class="QPushButton" name="buttonCStickUp">
+            <property name="text">
+             <string/>
+            </property>
+           </widget>
+          </item>
+         </layout>
+        </item>
+        <item row="1" column="1">
+         <layout class="QVBoxLayout" name="verticalLayout_24">
+          <item>
+           <widget class="QLabel" name="label_26">
+            <property name="text">
+             <string>Down:</string>
+            </property>
+           </widget>
+          </item>
+          <item>
+           <widget class="QPushButton" name="buttonCStickDown">
+            <property name="text">
+             <string/>
+            </property>
+           </widget>
+          </item>
+         </layout>
+        </item>
+       </layout>
+      </widget>
+     </item>
+     <item row="2" column="1">
+      <widget class="QGroupBox" name="faceButtons_6">
+       <property name="title">
+        <string>Misc.</string>
+       </property>
+       <property name="flat">
+        <bool>false</bool>
+       </property>
+       <property name="checkable">
+        <bool>false</bool>
+       </property>
+       <layout class="QGridLayout" name="gridLayout_6">
+        <item row="0" column="0">
+         <layout class="QVBoxLayout" name="verticalLayout_25">
+          <item>
+           <widget class="QLabel" name="label_29">
+            <property name="text">
+             <string>Start:</string>
+            </property>
+           </widget>
+          </item>
+          <item>
+           <widget class="QPushButton" name="buttonStart">
+            <property name="text">
+             <string/>
+            </property>
+           </widget>
+          </item>
+         </layout>
+        </item>
+        <item row="0" column="1">
+         <layout class="QVBoxLayout" name="verticalLayout_26">
+          <item>
+           <widget class="QLabel" name="label_30">
+            <property name="text">
+             <string>Select:</string>
+            </property>
+           </widget>
+          </item>
+          <item>
+           <widget class="QPushButton" name="buttonSelect">
+            <property name="text">
+             <string/>
+            </property>
+           </widget>
+          </item>
+         </layout>
+        </item>
+        <item row="1" column="0">
+         <layout class="QVBoxLayout" name="verticalLayout_27">
+          <item>
+           <widget class="QLabel" name="label_31">
+            <property name="text">
+             <string>Home:</string>
+            </property>
+           </widget>
+          </item>
+          <item>
+           <widget class="QPushButton" name="buttonHome">
+            <property name="text">
+             <string/>
+            </property>
+           </widget>
+          </item>
+         </layout>
+        </item>
+        <item row="1" column="1">
+         <layout class="QVBoxLayout" name="verticalLayout_28">
+          <item>
+           <widget class="QLabel" name="label_34">
+            <property name="text">
+             <string>Circle Mod:</string>
+            </property>
+           </widget>
+          </item>
+          <item>
+           <widget class="QPushButton" name="buttonCircleMod">
+            <property name="text">
+             <string/>
+            </property>
+           </widget>
+          </item>
+         </layout>
+        </item>
+       </layout>
+      </widget>
+     </item>
+    </layout>
+   </item>
+   <item>
+    <layout class="QHBoxLayout" name="horizontalLayout">
+     <item>
+      <spacer name="horizontalSpacer">
+       <property name="orientation">
+        <enum>Qt::Horizontal</enum>
+       </property>
+       <property name="sizeHint" stdset="0">
+        <size>
+         <width>40</width>
+         <height>20</height>
+        </size>
+       </property>
+      </spacer>
+     </item>
+     <item>
+      <widget class="QPushButton" name="buttonRestoreDefaults">
+       <property name="sizePolicy">
+        <sizepolicy hsizetype="Minimum" vsizetype="Fixed">
+         <horstretch>0</horstretch>
+         <verstretch>0</verstretch>
+        </sizepolicy>
+       </property>
+       <property name="sizeIncrement">
+        <size>
+         <width>0</width>
+         <height>0</height>
+        </size>
+       </property>
+       <property name="baseSize">
+        <size>
+         <width>0</width>
+         <height>0</height>
+        </size>
+       </property>
+       <property name="layoutDirection">
+        <enum>Qt::LeftToRight</enum>
+       </property>
+       <property name="text">
+        <string>Restore Defaults</string>
+       </property>
+      </widget>
+     </item>
+    </layout>
+   </item>
+  </layout>
+ </widget>
+ <resources/>
+ <connections/>
+</ui>
diff --git a/src/citra_qt/main.cpp b/src/citra_qt/main.cpp
index 6fe5d7a3f9..68a936087c 100644
--- a/src/citra_qt/main.cpp
+++ b/src/citra_qt/main.cpp
@@ -513,6 +513,7 @@ void GMainWindow::OnConfigure() {
     if (result == QDialog::Accepted)
     {
         configureDialog.applyConfiguration();
+        render_window->ReloadSetKeymaps();
         config->Save();
     }
 }