all repos — mgba @ f6f3cb5d3d8b91dd603772ea0eebb2513562a0cf

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