all repos — mgba @ f0ff8d5f825f77d726d09fd33b75659c84dff970

mGBA Game Boy Advance Emulator

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}