src/platform/qt/KeyEditor.cpp (view raw)
1/* Copyright (c) 2013-2014 Jeffrey Pfau
2 *
3 * This Source Code Form is subject to the terms of the Mozilla Public
4 * License, v. 2.0. If a copy of the MPL was not distributed with this
5 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
6#include "KeyEditor.h"
7
8#include "GamepadAxisEvent.h"
9#include "GamepadButtonEvent.h"
10#include "ShortcutController.h"
11
12#include <QFontMetrics>
13#include <QKeyEvent>
14
15using namespace QGBA;
16
17KeyEditor::KeyEditor(QWidget* parent)
18 : QLineEdit(parent)
19 , m_key(-1)
20 , m_axis(-1)
21 , m_hat(-1)
22 , m_button(false)
23 , m_direction(GamepadAxisEvent::NEUTRAL)
24 , m_hatDirection(GamepadHatEvent::CENTER)
25{
26 setAlignment(Qt::AlignCenter);
27 setFocusPolicy(Qt::ClickFocus);
28 m_lastKey.setSingleShot(true);
29}
30
31void KeyEditor::setValue(int key) {
32 m_key = key;
33 if (m_button) {
34 updateButtonText();
35 } else {
36 if (key < 0) {
37 setText(tr("---"));
38 } else {
39 setText(QKeySequence(key).toString(QKeySequence::NativeText));
40 }
41 }
42 emit valueChanged(key);
43}
44
45void KeyEditor::setValueKey(int key) {
46 m_button = false;
47 setValue(key);
48}
49
50void KeyEditor::setValueButton(int button) {
51 m_button = true;
52 setValue(button);
53}
54
55void KeyEditor::setValueAxis(int axis, int32_t value) {
56 m_button = true;
57 m_axis = axis;
58 m_direction = value < 0 ? GamepadAxisEvent::NEGATIVE : GamepadAxisEvent::POSITIVE;
59 updateButtonText();
60 emit axisChanged(axis, m_direction);
61}
62
63void KeyEditor::setValueHat(int hat, GamepadHatEvent::Direction direction) {
64 m_button = true;
65 m_hat = hat;
66 m_hatDirection = direction;
67 updateButtonText();
68 emit hatChanged(hat, m_hatDirection);
69}
70
71void KeyEditor::clearButton() {
72 m_button = true;
73 setValue(-1);
74}
75
76void KeyEditor::clearAxis() {
77 m_button = true;
78 m_axis = -1;
79 m_direction = GamepadAxisEvent::NEUTRAL;
80 updateButtonText();
81 emit axisChanged(m_axis, m_direction);
82}
83
84void KeyEditor::clearHat() {
85 m_button = true;
86 m_hat = -1;
87 m_hatDirection = GamepadHatEvent::CENTER;
88 updateButtonText();
89 emit hatChanged(m_hat, m_hatDirection);
90}
91
92QSize KeyEditor::sizeHint() const {
93 QSize hint = QLineEdit::sizeHint();
94 QFontMetrics fm(font());
95 hint.setWidth(fm.height() * 4);
96 return hint;
97}
98
99void KeyEditor::keyPressEvent(QKeyEvent* event) {
100 if (!m_button) {
101 if (m_key < 0 || !m_lastKey.isActive()) {
102 m_key = 0;
103 }
104 m_lastKey.start(KEY_TIME);
105 if (m_key) {
106 if (ShortcutController::isModifierKey(m_key)) {
107 switch (event->key()) {
108 case Qt::Key_Shift:
109 setValue(Qt::ShiftModifier);
110 break;
111 case Qt::Key_Control:
112 setValue(Qt::ControlModifier);
113 break;
114 case Qt::Key_Alt:
115 setValue(Qt::AltModifier);
116 break;
117 case Qt::Key_Meta:
118 setValue(Qt::MetaModifier);
119 break;
120 }
121 }
122 if (ShortcutController::isModifierKey(event->key())) {
123 switch (event->key()) {
124 case Qt::Key_Shift:
125 setValue(m_key | Qt::ShiftModifier);
126 break;
127 case Qt::Key_Control:
128 setValue(m_key | Qt::ControlModifier);
129 break;
130 case Qt::Key_Alt:
131 setValue(m_key | Qt::AltModifier);
132 break;
133 case Qt::Key_Meta:
134 setValue(m_key | Qt::MetaModifier);
135 break;
136 }
137 } else {
138 setValue(event->key() | (m_key & (Qt::ShiftModifier | Qt::ControlModifier | Qt::AltModifier | Qt::MetaModifier)));
139 }
140 } else {
141 setValue(event->key());
142 }
143 }
144 event->accept();
145}
146
147bool KeyEditor::event(QEvent* event) {
148 if (!m_button) {
149 if (event->type() == QEvent::KeyPress) {
150 QKeyEvent* keyEvent = static_cast<QKeyEvent*>(event);
151 if (keyEvent->key() != Qt::Key_Tab && keyEvent->key() != Qt::Key_Backtab) {
152 return QWidget::event(event);
153 }
154 if (!(keyEvent->modifiers() & ~Qt::ShiftModifier)) {
155 keyPressEvent(keyEvent);
156 keyEvent->accept();
157 return true;
158 }
159 }
160 } else {
161 if (event->type() == GamepadButtonEvent::Down()) {
162 setValueButton(static_cast<GamepadButtonEvent*>(event)->value());
163 event->accept();
164 return true;
165 }
166 if (event->type() == GamepadHatEvent::Down()) {
167 GamepadHatEvent* ghe = static_cast<GamepadHatEvent*>(event);
168 setValueHat(ghe->hatId(), ghe->direction());
169 event->accept();
170 return true;
171 }
172 if (event->type() == GamepadAxisEvent::Type()) {
173 GamepadAxisEvent* gae = static_cast<GamepadAxisEvent*>(event);
174 if (gae->isNew()) {
175 setValueAxis(gae->axis(), gae->direction());
176 }
177 event->accept();
178 return true;
179 }
180 }
181 return QWidget::event(event);
182}
183
184void KeyEditor::updateButtonText() {
185 QStringList text;
186 if (m_hat >= 0) {
187 switch (m_hatDirection) {
188 case GamepadHatEvent::UP:
189 text.append(QString("↑%0").arg(m_hat));
190 break;
191 case GamepadHatEvent::RIGHT:
192 text.append(QString("→%0").arg(m_hat));
193 break;
194 case GamepadHatEvent::DOWN:
195 text.append(QString("↓%0").arg(m_hat));
196 break;
197 case GamepadHatEvent::LEFT:
198 text.append(QString("←%0").arg(m_hat));
199 break;
200 default:
201 break;
202 }
203 }
204 if (m_key >= 0) {
205 text.append(QString::number(m_key));
206 }
207 if (m_direction != GamepadAxisEvent::NEUTRAL) {
208 text.append((m_direction == GamepadAxisEvent::NEGATIVE ? "-" : "+") + QString::number(m_axis));
209 }
210 if (text.isEmpty()) {
211 setText(tr("---"));
212 } else {
213 setText(text.join("/"));
214 }
215}