all repos — mgba @ 4fd170ac38a9c312f3dd1d0dd912d2c761f60fdb

mGBA Game Boy Advance Emulator

src/platform/qt/input/InputIndex.cpp (view raw)

  1/* Copyright (c) 2013-2017 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 "InputIndex.h"
  7
  8#include "ConfigController.h"
  9
 10using namespace QGBA;
 11
 12void InputIndex::setConfigController(ConfigController* controller) {
 13	m_config = controller;
 14	for (auto& item : m_items) {
 15		loadShortcuts(item);
 16	}
 17}
 18
 19void InputIndex::clone(InputIndex* root, bool actions) {
 20	if (!actions) {
 21		clone(const_cast<const InputIndex*>(root));
 22	} else {
 23		qDeleteAll(m_items);
 24		m_items.clear();
 25		for (auto& item : root->m_items) {
 26			InputItem* newItem = new InputItem(*item);
 27			m_items.append(newItem);
 28			itemAdded(newItem);
 29		}
 30	}
 31	rebuild();
 32}
 33
 34void InputIndex::clone(const InputIndex* root) {
 35	qDeleteAll(m_items);
 36	m_items.clear();
 37	for (auto& item : root->m_items) {
 38		InputItem* newItem = new InputItem(*item);
 39		m_items.append(newItem);
 40		itemAdded(newItem);
 41	}
 42	rebuild();
 43}
 44
 45void InputIndex::rebuild(const InputIndex* root) {
 46	if (!root) {
 47		root = this;
 48	}
 49
 50	m_names.clear();
 51	m_menus.clear();
 52	m_shortcuts.clear();
 53	m_buttons.clear();
 54	m_axes.clear();
 55
 56	for (auto& item : root->m_items) {
 57		InputItem* newItem = nullptr;
 58		for (auto &iter : m_items) {
 59			if (*iter == *item) {
 60				newItem = iter;
 61				break;
 62			}
 63		}
 64		if (!newItem) {
 65			continue;
 66		}
 67		if (item->hasShortcut()) {
 68			newItem->setShortcut(item->shortcut());
 69		}
 70		if (item->hasButton()) {
 71			newItem->setButton(item->button());
 72		}
 73		if (item->hasAxis()) {
 74			newItem->setAxis(item->axis(), item->direction());
 75		}
 76
 77		itemAdded(newItem);
 78	}
 79}
 80
 81InputItem* InputIndex::itemAt(const QString& name) {
 82	return m_names[name];
 83}
 84
 85const InputItem* InputIndex::itemAt(const QString& name) const {
 86	return m_names[name];
 87}
 88
 89InputItem* InputIndex::itemForMenu(const QMenu* menu) {
 90	InputItem* item = m_menus[menu];
 91	return item;
 92}
 93
 94const InputItem* InputIndex::itemForMenu(const QMenu* menu) const {
 95	const InputItem* item = m_menus[menu];
 96	return item;
 97}
 98
 99InputItem* InputIndex::itemForShortcut(int shortcut) {
100	return m_shortcuts[shortcut];
101}
102
103InputItem* InputIndex::itemForButton(int button) {
104	return m_buttons[button];
105}
106
107InputItem* InputIndex::itemForAxis(int axis, GamepadAxisEvent::Direction direction) {
108	return m_axes[qMakePair(axis, direction)];
109}
110
111bool InputIndex::loadShortcuts(InputItem* item) {
112	if (item->name().isNull()) {
113		return false;
114	}
115	loadGamepadShortcuts(item);
116	QVariant shortcut = m_config->getQtOption(item->name(), KEY_SECTION);
117	if (!shortcut.isNull()) {
118		if (shortcut.toString().endsWith("+")) {
119			item->setShortcut(toModifierShortcut(shortcut.toString()));
120		} else {
121			item->setShortcut(QKeySequence(shortcut.toString())[0]);
122		}
123		return true;
124	}
125	return false;
126}
127
128void InputIndex::loadGamepadShortcuts(InputItem* item) {
129	if (item->name().isNull()) {
130		return;
131	}
132	QVariant button = m_config->getQtOption(item->name(), BUTTON_SECTION);
133	if (!button.isNull()) {
134		item->setButton(button.toInt());
135	}
136
137	QVariant axis = m_config->getQtOption(item->name(), AXIS_SECTION);
138	int oldAxis = item->axis();
139	if (oldAxis >= 0) {
140		item->setAxis(-1, GamepadAxisEvent::NEUTRAL);
141	}
142	if (!axis.isNull()) {
143		QString axisDesc = axis.toString();
144		if (axisDesc.size() >= 2) {
145			GamepadAxisEvent::Direction direction = GamepadAxisEvent::NEUTRAL;
146			if (axisDesc[0] == '-') {
147				direction = GamepadAxisEvent::NEGATIVE;
148			}
149			if (axisDesc[0] == '+') {
150				direction = GamepadAxisEvent::POSITIVE;
151			}
152			bool ok;
153			int axis = axisDesc.mid(1).toInt(&ok);
154			if (ok) {
155				item->setAxis(axis, direction);
156			}
157		}
158	}
159}
160
161int InputIndex::toModifierShortcut(const QString& shortcut) {
162	// Qt doesn't seem to work with raw modifier shortcuts!
163	QStringList modifiers = shortcut.split('+');
164	int value = 0;
165	for (const auto& mod : modifiers) {
166		if (mod == QLatin1String("Shift")) {
167			value |= Qt::ShiftModifier;
168			continue;
169		}
170		if (mod == QLatin1String("Ctrl")) {
171			value |= Qt::ControlModifier;
172			continue;
173		}
174		if (mod == QLatin1String("Alt")) {
175			value |= Qt::AltModifier;
176			continue;
177		}
178		if (mod == QLatin1String("Meta")) {
179			value |= Qt::MetaModifier;
180			continue;
181		}
182	}
183	return value;
184}
185
186void InputIndex::itemAdded(InputItem* child) {
187	const QMenu* menu = child->menu();
188	if (menu) {
189		m_menus[menu] = child;
190	}
191	m_names[child->name()] = child;
192
193	if (child->shortcut() > 0) {
194		m_shortcuts[child->shortcut()] = child;
195	}
196	if (child->button() >= 0) {
197		m_buttons[child->button()] = child;
198	}
199	if (child->direction() != GamepadAxisEvent::NEUTRAL) {
200		m_axes[qMakePair(child->axis(), child->direction())] = child;
201	}
202}
203
204bool InputIndex::isModifierKey(int key) {
205	switch (key) {
206	case Qt::Key_Shift:
207	case Qt::Key_Control:
208	case Qt::Key_Alt:
209	case Qt::Key_Meta:
210		return true;
211	default:
212		return false;
213	}
214}
215
216int InputIndex::toModifierKey(int key) {
217	int modifiers = key & (Qt::ShiftModifier | Qt::ControlModifier | Qt::AltModifier | Qt::MetaModifier);
218	key ^= modifiers;
219	switch (key) {
220	case Qt::Key_Shift:
221		modifiers |= Qt::ShiftModifier;
222		break;
223	case Qt::Key_Control:
224		modifiers |= Qt::ControlModifier;
225		break;
226	case Qt::Key_Alt:
227		modifiers |= Qt::AltModifier;
228		break;
229	case Qt::Key_Meta:
230		modifiers |= Qt::MetaModifier;
231		break;
232	default:
233		break;
234	}
235	return modifiers;
236}
237
238void InputIndex::saveConfig() {
239	for (auto& item : m_items) {
240		if (item->hasShortcut()) {
241			m_config->setQtOption(item->name(), QKeySequence(item->shortcut()).toString(), KEY_SECTION);
242		}
243		if (item->hasButton()) {
244			m_config->setQtOption(item->name(), item->button(), BUTTON_SECTION);
245		}
246		if (item->hasAxis()) {
247			m_config->setQtOption(item->name(), QString("%1%2").arg(GamepadAxisEvent::POSITIVE ? '+' : '-').arg(item->axis()), AXIS_SECTION);
248		}
249	}
250}