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 <QCoreApplication>
13#include <QFontMetrics>
14#include <QKeyEvent>
15
16using namespace QGBA;
17
18KeyEditor::KeyEditor(QWidget* parent)
19 : QLineEdit(parent)
20 , m_direction(GamepadAxisEvent::NEUTRAL)
21 , m_hatDirection(GamepadHatEvent::CENTER)
22{
23 setAlignment(Qt::AlignCenter);
24 setFocusPolicy(Qt::ClickFocus);
25 m_lastKey.setSingleShot(true);
26}
27
28void KeyEditor::setValue(int key) {
29 m_key = key;
30 if (m_button) {
31 updateButtonText();
32 } else {
33 if (key < 0) {
34 setText(tr("---"));
35 } else {
36 QKeySequence seq(key);
37 switch (key) {
38#ifndef Q_OS_MAC
39 case Qt::Key_Shift:
40 setText(QCoreApplication::translate("QShortcut", "Shift"));
41 break;
42 case Qt::Key_Control:
43 setText(QCoreApplication::translate("QShortcut", "Control"));
44 break;
45 case Qt::Key_Alt:
46 setText(QCoreApplication::translate("QShortcut", "Alt"));
47 break;
48 case Qt::Key_Meta:
49 setText(QCoreApplication::translate("QShortcut", "Meta"));
50 break;
51#endif
52 case Qt::Key_Super_L:
53 setText(tr("Super (L)"));
54 break;
55 case Qt::Key_Super_R:
56 setText(tr("Super (R)"));
57 break;
58 case Qt::Key_Menu:
59 setText(tr("Menu"));
60 break;
61 default:
62 setText(QKeySequence(key).toString(QKeySequence::NativeText));
63 break;
64 }
65 }
66 }
67 emit valueChanged(key);
68}
69
70void KeyEditor::setValueKey(int key) {
71 m_button = false;
72 setValue(key);
73}
74
75void KeyEditor::setValueButton(int button) {
76 m_button = true;
77 setValue(button);
78}
79
80void KeyEditor::setValueAxis(int axis, GamepadAxisEvent::Direction direction) {
81 m_button = true;
82 m_axis = axis;
83 m_direction = direction;
84 updateButtonText();
85 emit axisChanged(axis, m_direction);
86}
87
88void KeyEditor::setValueHat(int hat, GamepadHatEvent::Direction direction) {
89 m_button = true;
90 m_hat = hat;
91 m_hatDirection = direction;
92 updateButtonText();
93 emit hatChanged(hat, m_hatDirection);
94}
95
96void KeyEditor::clearButton() {
97 m_button = true;
98 setValue(-1);
99}
100
101void KeyEditor::clearAxis() {
102 m_button = true;
103 m_axis = -1;
104 m_direction = GamepadAxisEvent::NEUTRAL;
105 updateButtonText();
106 emit axisChanged(m_axis, m_direction);
107}
108
109void KeyEditor::clearHat() {
110 m_button = true;
111 m_hat = -1;
112 m_hatDirection = GamepadHatEvent::CENTER;
113 updateButtonText();
114 emit hatChanged(m_hat, m_hatDirection);
115}
116
117QSize KeyEditor::sizeHint() const {
118 QSize hint = QLineEdit::sizeHint();
119 QFontMetrics fm(font());
120 hint.setWidth(fm.height() * 4);
121 return hint;
122}
123
124void KeyEditor::keyPressEvent(QKeyEvent* event) {
125 if (!m_button) {
126 if (m_key < 0 || !m_lastKey.isActive()) {
127 m_key = 0;
128 }
129 m_lastKey.start(KEY_TIME);
130 if (m_key) {
131 if (ShortcutController::isModifierKey(m_key)) {
132 switch (event->key()) {
133 case Qt::Key_Shift:
134 setValue(Qt::ShiftModifier);
135 break;
136 case Qt::Key_Control:
137 setValue(Qt::ControlModifier);
138 break;
139 case Qt::Key_Alt:
140 setValue(Qt::AltModifier);
141 break;
142 case Qt::Key_Meta:
143 setValue(Qt::MetaModifier);
144 break;
145 }
146 }
147 if (ShortcutController::isModifierKey(event->key())) {
148 switch (event->key()) {
149 case Qt::Key_Shift:
150 setValue(m_key | Qt::ShiftModifier);
151 break;
152 case Qt::Key_Control:
153 setValue(m_key | Qt::ControlModifier);
154 break;
155 case Qt::Key_Alt:
156 setValue(m_key | Qt::AltModifier);
157 break;
158 case Qt::Key_Meta:
159 setValue(m_key | Qt::MetaModifier);
160 break;
161 }
162 } else {
163 setValue(event->key() | (m_key & (Qt::ShiftModifier | Qt::ControlModifier | Qt::AltModifier | Qt::MetaModifier)));
164 }
165 } else {
166 setValue(event->key());
167 }
168 }
169 event->accept();
170}
171
172bool KeyEditor::event(QEvent* event) {
173 if (!m_button) {
174 if (event->type() == QEvent::KeyPress) {
175 QKeyEvent* keyEvent = static_cast<QKeyEvent*>(event);
176 if (keyEvent->key() != Qt::Key_Tab && keyEvent->key() != Qt::Key_Backtab) {
177 return QWidget::event(event);
178 }
179 if (!(keyEvent->modifiers() & ~Qt::ShiftModifier)) {
180 keyPressEvent(keyEvent);
181 keyEvent->accept();
182 return true;
183 }
184 }
185 } else {
186 if (event->type() == GamepadButtonEvent::Down()) {
187 setValueButton(static_cast<GamepadButtonEvent*>(event)->value());
188 event->accept();
189 return true;
190 }
191 if (event->type() == GamepadHatEvent::Down()) {
192 GamepadHatEvent* ghe = static_cast<GamepadHatEvent*>(event);
193 setValueHat(ghe->hatId(), ghe->direction());
194 event->accept();
195 return true;
196 }
197 if (event->type() == GamepadAxisEvent::Type()) {
198 GamepadAxisEvent* gae = static_cast<GamepadAxisEvent*>(event);
199 if (gae->isNew()) {
200 setValueAxis(gae->axis(), gae->direction());
201 }
202 event->accept();
203 return true;
204 }
205 }
206 return QWidget::event(event);
207}
208
209void KeyEditor::updateButtonText() {
210 QStringList text;
211 if (m_hat >= 0) {
212 switch (m_hatDirection) {
213 case GamepadHatEvent::UP:
214 text.append(QString("↑%0").arg(m_hat));
215 break;
216 case GamepadHatEvent::RIGHT:
217 text.append(QString("→%0").arg(m_hat));
218 break;
219 case GamepadHatEvent::DOWN:
220 text.append(QString("↓%0").arg(m_hat));
221 break;
222 case GamepadHatEvent::LEFT:
223 text.append(QString("←%0").arg(m_hat));
224 break;
225 default:
226 break;
227 }
228 }
229 if (m_key >= 0) {
230 text.append(QString::number(m_key));
231 }
232 if (m_direction != GamepadAxisEvent::NEUTRAL) {
233 text.append((m_direction == GamepadAxisEvent::NEGATIVE ? "-" : "+") + QString::number(m_axis));
234 }
235 if (text.isEmpty()) {
236 setText(tr("---"));
237 } else {
238 setText(text.join("/"));
239 }
240}