1 // Copyright 2016 Citra Emulator Project
2 // Licensed under GPLv2 or any later version
3 // Refer to the license.txt file included.
4 
5 #pragma once
6 
7 #include <array>
8 #include <functional>
9 #include <memory>
10 #include <optional>
11 #include <string>
12 #include <unordered_map>
13 #include <QKeySequence>
14 #include <QWidget>
15 #include "common/param_package.h"
16 #include "core/settings.h"
17 #include "input_common/main.h"
18 
19 class QKeyEvent;
20 class QLabel;
21 class QPushButton;
22 class QSlider;
23 class QString;
24 class QTimer;
25 
26 namespace Ui {
27 class ConfigureInput;
28 }
29 
30 class ConfigureInput : public QWidget {
31     Q_OBJECT
32 
33 public:
34     explicit ConfigureInput(QWidget* parent = nullptr);
35     ~ConfigureInput() override;
36 
37     /// Save all button configurations to settings file
38     void ApplyConfiguration();
39     void RetranslateUI();
40 
41     /// Load configuration settings.
42     void LoadConfiguration();
43     void EmitInputKeysChanged();
44 
45     /// Save the current input profile index
46     void ApplyProfile();
47 public slots:
48     void OnHotkeysChanged(QList<QKeySequence> new_key_list);
49 
50 signals:
51     void InputKeysChanged(QList<QKeySequence> new_key_list);
52 
53 private:
54     std::unique_ptr<Ui::ConfigureInput> ui;
55 
56     std::unique_ptr<QTimer> timeout_timer;
57     std::unique_ptr<QTimer> poll_timer;
58 
59     /// This will be the the setting function when an input is awaiting configuration.
60     std::optional<std::function<void(const Common::ParamPackage&)>> input_setter;
61 
62     std::array<Common::ParamPackage, Settings::NativeButton::NumButtons> buttons_param;
63     std::array<Common::ParamPackage, Settings::NativeAnalog::NumAnalogs> analogs_param;
64 
65     static constexpr int ANALOG_SUB_BUTTONS_NUM = 5;
66 
67     /// Each button input is represented by a QPushButton.
68     std::array<QPushButton*, Settings::NativeButton::NumButtons> button_map;
69 
70     /// A group of five QPushButtons represent one analog input. The buttons each represent up,
71     /// down, left, right, and modifier, respectively.
72     std::array<std::array<QPushButton*, ANALOG_SUB_BUTTONS_NUM>, Settings::NativeAnalog::NumAnalogs>
73         analog_map_buttons;
74 
75     /// Analog inputs are also represented each with a single button, used to configure with an
76     /// actual analog stick
77     std::array<QPushButton*, Settings::NativeAnalog::NumAnalogs> analog_map_stick;
78     std::array<QSlider*, Settings::NativeAnalog::NumAnalogs>
79         analog_map_deadzone_and_modifier_slider;
80     std::array<QLabel*, Settings::NativeAnalog::NumAnalogs>
81         analog_map_deadzone_and_modifier_slider_label;
82 
83     static const std::array<std::string, ANALOG_SUB_BUTTONS_NUM> analog_sub_buttons;
84 
85     std::vector<std::unique_ptr<InputCommon::Polling::DevicePoller>> device_pollers;
86 
87     /**
88      * List of keys currently registered to hotkeys.
89      * These can't be bound to any input key.
90      * Synchronised with ConfigureHotkeys via signal-slot.
91      */
92     QList<QKeySequence> hotkey_list;
93 
94     /// A flag to indicate if keyboard keys are okay when configuring an input. If this is false,
95     /// keyboard events are ignored.
96     bool want_keyboard_keys = false;
97 
98     /// Generates list of all used keys
99     QList<QKeySequence> GetUsedKeyboardKeys();
100 
101     void MapFromButton(const Common::ParamPackage& params);
102     void AutoMap();
103 
104     /// Restore all buttons to their default values.
105     void RestoreDefaults();
106     /// Clear all input configuration
107     void ClearAll();
108 
109     /// Update UI to reflect current configuration.
110     void UpdateButtonLabels();
111 
112     /// Called when the button was pressed.
113     void HandleClick(QPushButton* button,
114                      std::function<void(const Common::ParamPackage&)> new_input_setter,
115                      InputCommon::Polling::DeviceType type);
116 
117     /// The key code of the previous state of the key being currently bound.
118     int previous_key_code;
119 
120     /// Finish polling and configure input using the input_setter
121     void SetPollingResult(const Common::ParamPackage& params, bool abort);
122 
123     /// Handle key press events.
124     void keyPressEvent(QKeyEvent* event) override;
125 
126     /// input profiles
127     void NewProfile();
128     void DeleteProfile();
129     void RenameProfile();
130 
131     bool IsProfileNameDuplicate(const QString& name) const;
132     void WarnProposedProfileNameIsDuplicate();
133 };
134