diff options
| -rw-r--r-- | src/citra_qt/configure_input.cpp | 169 | ||||
| -rw-r--r-- | src/citra_qt/configure_input.h | 47 |
2 files changed, 101 insertions, 115 deletions
diff --git a/src/citra_qt/configure_input.cpp b/src/citra_qt/configure_input.cpp index d321db71f..3e6803b8a 100644 --- a/src/citra_qt/configure_input.cpp +++ b/src/citra_qt/configure_input.cpp | |||
| @@ -5,15 +5,33 @@ | |||
| 5 | #include <memory> | 5 | #include <memory> |
| 6 | #include <utility> | 6 | #include <utility> |
| 7 | #include <QTimer> | 7 | #include <QTimer> |
| 8 | #include "citra_qt/config.h" | ||
| 8 | #include "citra_qt/configure_input.h" | 9 | #include "citra_qt/configure_input.h" |
| 9 | 10 | ||
| 11 | static QString getKeyName(Qt::Key key_code) { | ||
| 12 | switch (key_code) { | ||
| 13 | case Qt::Key_Shift: | ||
| 14 | return QObject::tr("Shift"); | ||
| 15 | case Qt::Key_Control: | ||
| 16 | return QObject::tr("Ctrl"); | ||
| 17 | case Qt::Key_Alt: | ||
| 18 | return QObject::tr("Alt"); | ||
| 19 | case Qt::Key_Meta: | ||
| 20 | case -1: | ||
| 21 | return ""; | ||
| 22 | default: | ||
| 23 | return QKeySequence(key_code).toString(); | ||
| 24 | } | ||
| 25 | } | ||
| 26 | |||
| 10 | ConfigureInput::ConfigureInput(QWidget* parent) | 27 | ConfigureInput::ConfigureInput(QWidget* parent) |
| 11 | : QWidget(parent), ui(std::make_unique<Ui::ConfigureInput>()) { | 28 | : QWidget(parent), ui(std::make_unique<Ui::ConfigureInput>()), |
| 29 | timer(std::make_unique<QTimer>()) { | ||
| 12 | 30 | ||
| 13 | ui->setupUi(this); | 31 | ui->setupUi(this); |
| 32 | setFocusPolicy(Qt::ClickFocus); | ||
| 14 | 33 | ||
| 15 | // Initialize mapping of input enum to UI button. | 34 | button_map = { |
| 16 | input_mapping = { | ||
| 17 | {Settings::NativeInput::Values::A, ui->buttonA}, | 35 | {Settings::NativeInput::Values::A, ui->buttonA}, |
| 18 | {Settings::NativeInput::Values::B, ui->buttonB}, | 36 | {Settings::NativeInput::Values::B, ui->buttonB}, |
| 19 | {Settings::NativeInput::Values::X, ui->buttonX}, | 37 | {Settings::NativeInput::Values::X, ui->buttonX}, |
| @@ -40,114 +58,89 @@ ConfigureInput::ConfigureInput(QWidget* parent) | |||
| 40 | {Settings::NativeInput::Values::CIRCLE_MODIFIER, ui->buttonCircleMod}, | 58 | {Settings::NativeInput::Values::CIRCLE_MODIFIER, ui->buttonCircleMod}, |
| 41 | }; | 59 | }; |
| 42 | 60 | ||
| 43 | // Attach handle click method to each button click. | 61 | for (const auto& entry : button_map) { |
| 44 | for (const auto& entry : input_mapping) { | 62 | const Settings::NativeInput::Values input_id = entry.first; |
| 45 | connect(entry.second, SIGNAL(released()), this, SLOT(handleClick())); | 63 | connect(entry.second, &QPushButton::released, |
| 64 | [this, input_id]() { handleClick(input_id); }); | ||
| 46 | } | 65 | } |
| 47 | connect(ui->buttonRestoreDefaults, SIGNAL(released()), this, SLOT(restoreDefaults())); | 66 | |
| 48 | setFocusPolicy(Qt::ClickFocus); | 67 | connect(ui->buttonRestoreDefaults, &QPushButton::released, [this]() { restoreDefaults(); }); |
| 49 | timer = new QTimer(this); | 68 | |
| 50 | timer->setSingleShot(true); | 69 | timer->setSingleShot(true); |
| 51 | connect(timer, &QTimer::timeout, this, [&]() { | 70 | connect(timer.get(), &QTimer::timeout, [this]() { |
| 52 | key_pressed = Qt::Key_Escape; | 71 | releaseKeyboard(); |
| 53 | setKey(); | 72 | releaseMouse(); |
| 73 | current_input_id = boost::none; | ||
| 74 | updateButtonLabels(); | ||
| 54 | }); | 75 | }); |
| 55 | this->setConfiguration(); | ||
| 56 | } | ||
| 57 | 76 | ||
| 58 | void ConfigureInput::handleClick() { | 77 | this->loadConfiguration(); |
| 59 | QPushButton* sender = qobject_cast<QPushButton*>(QObject::sender()); | ||
| 60 | previous_mapping = sender->text(); | ||
| 61 | sender->setText(tr("[waiting]")); | ||
| 62 | sender->setFocus(); | ||
| 63 | grabKeyboard(); | ||
| 64 | grabMouse(); | ||
| 65 | changing_button = sender; | ||
| 66 | timer->start(5000); // Cancel after 5 seconds | ||
| 67 | } | 78 | } |
| 68 | 79 | ||
| 69 | void ConfigureInput::applyConfiguration() { | 80 | void ConfigureInput::applyConfiguration() { |
| 70 | for (int i = 0; i < Settings::NativeInput::NUM_INPUTS; ++i) { | 81 | for (const auto& input_id : Settings::NativeInput::All) { |
| 71 | int value = getKeyValue(input_mapping[Settings::NativeInput::Values(i)]->text()); | 82 | const size_t index = static_cast<size_t>(input_id); |
| 72 | Settings::values.input_mappings[Settings::NativeInput::All[i]] = value; | 83 | Settings::values.input_mappings[index] = static_cast<int>(key_map[input_id]); |
| 73 | } | 84 | } |
| 74 | Settings::Apply(); | 85 | Settings::Apply(); |
| 75 | } | 86 | } |
| 76 | 87 | ||
| 77 | void ConfigureInput::setConfiguration() { | 88 | void ConfigureInput::loadConfiguration() { |
| 78 | for (int i = 0; i < Settings::NativeInput::NUM_INPUTS; ++i) { | 89 | for (const auto& input_id : Settings::NativeInput::All) { |
| 79 | QString keyValue = getKeyName(Settings::values.input_mappings[i]); | 90 | const size_t index = static_cast<size_t>(input_id); |
| 80 | input_mapping[Settings::NativeInput::Values(i)]->setText(keyValue); | 91 | key_map[input_id] = static_cast<Qt::Key>(Settings::values.input_mappings[index]); |
| 81 | } | 92 | } |
| 93 | updateButtonLabels(); | ||
| 82 | } | 94 | } |
| 83 | 95 | ||
| 84 | void ConfigureInput::keyPressEvent(QKeyEvent* event) { | 96 | void ConfigureInput::restoreDefaults() { |
| 85 | if (!changing_button) | 97 | for (const auto& input_id : Settings::NativeInput::All) { |
| 86 | return; | 98 | const size_t index = static_cast<size_t>(input_id); |
| 87 | if (!event || event->key() == Qt::Key_unknown) | 99 | key_map[input_id] = static_cast<Qt::Key>(Config::defaults[index].toInt()); |
| 88 | return; | 100 | } |
| 89 | key_pressed = event->key(); | 101 | updateButtonLabels(); |
| 90 | timer->stop(); | 102 | applyConfiguration(); |
| 91 | setKey(); | ||
| 92 | } | 103 | } |
| 93 | 104 | ||
| 94 | void ConfigureInput::setKey() { | 105 | void ConfigureInput::updateButtonLabels() { |
| 95 | const QString key_value = getKeyName(key_pressed); | 106 | for (const auto& input_id : Settings::NativeInput::All) { |
| 96 | if (key_pressed == Qt::Key_Escape) | 107 | button_map[input_id]->setText(getKeyName(key_map[input_id])); |
| 97 | changing_button->setText(previous_mapping); | 108 | } |
| 98 | else | ||
| 99 | changing_button->setText(key_value); | ||
| 100 | removeDuplicates(key_value); | ||
| 101 | key_pressed = Qt::Key_unknown; | ||
| 102 | releaseKeyboard(); | ||
| 103 | releaseMouse(); | ||
| 104 | changing_button = nullptr; | ||
| 105 | previous_mapping = nullptr; | ||
| 106 | } | 109 | } |
| 107 | 110 | ||
| 108 | QString ConfigureInput::getKeyName(int key_code) const { | 111 | void ConfigureInput::handleClick(Settings::NativeInput::Values input_id) { |
| 109 | if (key_code == Qt::Key_Shift) | 112 | QPushButton* button = button_map[input_id]; |
| 110 | return tr("Shift"); | 113 | button->setText(tr("[press key]")); |
| 111 | if (key_code == Qt::Key_Control) | 114 | button->setFocus(); |
| 112 | return tr("Ctrl"); | ||
| 113 | if (key_code == Qt::Key_Alt) | ||
| 114 | return tr("Alt"); | ||
| 115 | if (key_code == Qt::Key_Meta) | ||
| 116 | return ""; | ||
| 117 | if (key_code == -1) | ||
| 118 | return ""; | ||
| 119 | 115 | ||
| 120 | return QKeySequence(key_code).toString(); | 116 | current_input_id = input_id; |
| 121 | } | ||
| 122 | 117 | ||
| 123 | Qt::Key ConfigureInput::getKeyValue(const QString& text) const { | 118 | grabKeyboard(); |
| 124 | if (text == "Shift") | 119 | grabMouse(); |
| 125 | return Qt::Key_Shift; | 120 | timer->start(5000); // Cancel after 5 seconds |
| 126 | if (text == "Ctrl") | ||
| 127 | return Qt::Key_Control; | ||
| 128 | if (text == "Alt") | ||
| 129 | return Qt::Key_Alt; | ||
| 130 | if (text == "Meta") | ||
| 131 | return Qt::Key_unknown; | ||
| 132 | if (text == "") | ||
| 133 | return Qt::Key_unknown; | ||
| 134 | |||
| 135 | return Qt::Key(QKeySequence(text)[0]); | ||
| 136 | } | 121 | } |
| 137 | 122 | ||
| 138 | void ConfigureInput::removeDuplicates(const QString& newValue) { | 123 | void ConfigureInput::keyPressEvent(QKeyEvent* event) { |
| 139 | for (int i = 0; i < Settings::NativeInput::NUM_INPUTS; ++i) { | 124 | releaseKeyboard(); |
| 140 | if (changing_button != input_mapping[Settings::NativeInput::Values(i)]) { | 125 | releaseMouse(); |
| 141 | const QString oldValue = input_mapping[Settings::NativeInput::Values(i)]->text(); | 126 | |
| 142 | if (newValue == oldValue) | 127 | if (!current_input_id || !event) |
| 143 | input_mapping[Settings::NativeInput::Values(i)]->setText(""); | 128 | return; |
| 144 | } | 129 | |
| 145 | } | 130 | if (event->key() != Qt::Key_Escape) |
| 131 | setInput(*current_input_id, static_cast<Qt::Key>(event->key())); | ||
| 132 | |||
| 133 | updateButtonLabels(); | ||
| 134 | current_input_id = boost::none; | ||
| 135 | timer->stop(); | ||
| 146 | } | 136 | } |
| 147 | 137 | ||
| 148 | void ConfigureInput::restoreDefaults() { | 138 | void ConfigureInput::setInput(Settings::NativeInput::Values input_id, Qt::Key key_pressed) { |
| 149 | for (int i = 0; i < Settings::NativeInput::NUM_INPUTS; ++i) { | 139 | // Remove duplicates |
| 150 | const QString keyValue = getKeyName(Config::defaults[i].toInt()); | 140 | for (auto& pair : key_map) { |
| 151 | input_mapping[Settings::NativeInput::Values(i)]->setText(keyValue); | 141 | if (pair.second == key_pressed) |
| 142 | pair.second = Qt::Key_unknown; | ||
| 152 | } | 143 | } |
| 144 | |||
| 145 | key_map[input_id] = key_pressed; | ||
| 153 | } | 146 | } |
diff --git a/src/citra_qt/configure_input.h b/src/citra_qt/configure_input.h index 5183b904d..bc343db83 100644 --- a/src/citra_qt/configure_input.h +++ b/src/citra_qt/configure_input.h | |||
| @@ -7,7 +7,7 @@ | |||
| 7 | #include <memory> | 7 | #include <memory> |
| 8 | #include <QKeyEvent> | 8 | #include <QKeyEvent> |
| 9 | #include <QWidget> | 9 | #include <QWidget> |
| 10 | #include "citra_qt/config.h" | 10 | #include <boost/optional.hpp> |
| 11 | #include "core/settings.h" | 11 | #include "core/settings.h" |
| 12 | #include "ui_configure_input.h" | 12 | #include "ui_configure_input.h" |
| 13 | 13 | ||
| @@ -30,35 +30,28 @@ public: | |||
| 30 | 30 | ||
| 31 | private: | 31 | private: |
| 32 | std::unique_ptr<Ui::ConfigureInput> ui; | 32 | std::unique_ptr<Ui::ConfigureInput> ui; |
| 33 | std::map<Settings::NativeInput::Values, QPushButton*> input_mapping; | ||
| 34 | int key_pressed; | ||
| 35 | QPushButton* changing_button = nullptr; ///< button currently waiting for key press. | ||
| 36 | QString previous_mapping; | ||
| 37 | QTimer* timer; | ||
| 38 | 33 | ||
| 39 | /// Load configuration settings into button text | 34 | /// This input is currently awaiting configuration. |
| 40 | void setConfiguration(); | 35 | /// (i.e.: its corresponding QPushButton has been pressed.) |
| 36 | boost::optional<Settings::NativeInput::Values> current_input_id; | ||
| 37 | std::unique_ptr<QTimer> timer; | ||
| 41 | 38 | ||
| 42 | /// Check all inputs for duplicate keys. Clears out any other button with the same value as this | 39 | /// Each input is represented by a QPushButton. |
| 43 | /// button's new value. | 40 | std::map<Settings::NativeInput::Values, QPushButton*> button_map; |
| 44 | void removeDuplicates(const QString& newValue); | 41 | /// Each input is configured to respond to the press of a Qt::Key. |
| 45 | 42 | std::map<Settings::NativeInput::Values, Qt::Key> key_map; | |
| 46 | /// Handle key press event for input tab when a button is 'waiting'. | ||
| 47 | void keyPressEvent(QKeyEvent* event) override; | ||
| 48 | |||
| 49 | /// Convert key ASCII value to its' letter/name | ||
| 50 | QString getKeyName(int key_code) const; | ||
| 51 | |||
| 52 | /// Convert letter/name of key to its ASCII value. | ||
| 53 | Qt::Key getKeyValue(const QString& text) const; | ||
| 54 | |||
| 55 | /// Set button text to name of key pressed. | ||
| 56 | void setKey(); | ||
| 57 | |||
| 58 | private slots: | ||
| 59 | /// Event handler for all button released() event. | ||
| 60 | void handleClick(); | ||
| 61 | 43 | ||
| 44 | /// Load configuration settings. | ||
| 45 | void loadConfiguration(); | ||
| 62 | /// Restore all buttons to their default values. | 46 | /// Restore all buttons to their default values. |
| 63 | void restoreDefaults(); | 47 | void restoreDefaults(); |
| 48 | /// Update UI to reflect current configuration. | ||
| 49 | void updateButtonLabels(); | ||
| 50 | |||
| 51 | /// Called when the button corresponding to input_id was pressed. | ||
| 52 | void handleClick(Settings::NativeInput::Values input_id); | ||
| 53 | /// Handle key press events. | ||
| 54 | void keyPressEvent(QKeyEvent* event) override; | ||
| 55 | /// Configure input input_id to respond to key key_pressed. | ||
| 56 | void setInput(Settings::NativeInput::Values input_id, Qt::Key key_pressed); | ||
| 64 | }; | 57 | }; |