all repos — mgba @ 686380b6c4d8acf219a704a8932668b11efc47c2

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_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}