all repos — mgba @ 33c4b179415269bb31f45b1875ff307b2b434448

mGBA Game Boy Advance Emulator

src/platform/qt/ShortcutController.cpp (view raw)

  1/* Copyright (c) 2013-2015 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 "ShortcutController.h"
  7
  8#include "GamepadButtonEvent.h"
  9
 10#include <QAction>
 11#include <QMenu>
 12
 13using namespace QGBA;
 14
 15ShortcutController::ShortcutController(QObject* parent)
 16	: QAbstractItemModel(parent)
 17{
 18}
 19
 20QVariant ShortcutController::data(const QModelIndex& index, int role) const {
 21	if (role != Qt::DisplayRole || !index.isValid()) {
 22		return QVariant();
 23	}
 24	const QModelIndex& parent = index.parent();
 25	if (parent.isValid()) {
 26		const ShortcutMenu& menu = m_menus[parent.row()];
 27		const ShortcutItem& item = menu.shortcuts()[index.row()];
 28		switch (index.column()) {
 29		case 0:
 30			return item.visibleName();
 31		case 1:
 32			return item.action()->shortcut().toString(QKeySequence::NativeText);
 33		case 2:
 34			if (item.button() >= 0) {
 35				return item.button();
 36			}
 37			return QVariant();
 38		}
 39	} else if (index.column() == 0) {
 40		return m_menus[index.row()].visibleName();
 41	}
 42	return QVariant();
 43}
 44
 45QVariant ShortcutController::headerData(int section, Qt::Orientation orientation, int role) const {
 46	if (role != Qt::DisplayRole) {
 47		return QAbstractItemModel::headerData(section, orientation, role);
 48	}
 49	if (orientation == Qt::Horizontal) {
 50		switch (section) {
 51		case 0:
 52			return tr("Action");
 53		case 1:
 54			return tr("Keyboard");
 55		case 2:
 56			return tr("Gamepad");
 57		}
 58	}
 59	return section;
 60}
 61
 62QModelIndex ShortcutController::index(int row, int column, const QModelIndex& parent) const {
 63	if (!parent.isValid()) {
 64		return createIndex(row, column, -1);
 65	}
 66	return createIndex(row, column, parent.row());
 67}
 68
 69QModelIndex ShortcutController::parent(const QModelIndex& index) const {
 70	if (!index.isValid()) {
 71		return QModelIndex();
 72	}
 73	if (index.internalId() == -1) {
 74		return QModelIndex();
 75	}
 76	return createIndex(index.internalId(), 0, -1);
 77}
 78
 79int ShortcutController::columnCount(const QModelIndex& index) const {
 80	return 3;
 81}
 82
 83int ShortcutController::rowCount(const QModelIndex& index) const {
 84	if (index.parent().isValid()) {
 85		return 0;
 86	}
 87	if (index.isValid()) {
 88		return m_menus[index.row()].shortcuts().count();
 89	}
 90	return m_menus.count();
 91}
 92
 93void ShortcutController::addAction(QMenu* menu, QAction* action, const QString& name) {
 94	ShortcutMenu* smenu = nullptr;
 95	int row = 0;
 96	for (auto iter = m_menus.end(); iter-- != m_menus.begin(); ++row) {
 97		if (iter->menu() == menu) {
 98			smenu = &(*iter);
 99			break;
100		}
101	}
102	if (!smenu) {
103		return;
104	}
105	QModelIndex parent = createIndex(row, 0, -1);
106	beginInsertRows(parent, smenu->shortcuts().count(), smenu->shortcuts().count());
107	smenu->addAction(action, name);
108	endInsertRows();
109	emit dataChanged(createIndex(smenu->shortcuts().count() - 1, 0, row), createIndex(smenu->shortcuts().count() - 1, 2, row));
110}
111
112void ShortcutController::addMenu(QMenu* menu) {
113	beginInsertRows(QModelIndex(), m_menus.count(), m_menus.count());
114	m_menus.append(ShortcutMenu(menu));
115	endInsertRows();
116	emit dataChanged(createIndex(m_menus.count() - 1, 0, -1), createIndex(m_menus.count() - 1, 0, -1));
117}
118
119const QAction* ShortcutController::actionAt(const QModelIndex& index) const {
120	if (!index.isValid()) {
121		return nullptr;
122	}
123	const QModelIndex& parent = index.parent();
124	if (!parent.isValid()) {
125		return nullptr;
126	}
127	if (parent.row() > m_menus.count()) {
128		return nullptr;
129	}
130	const ShortcutMenu& menu = m_menus[parent.row()];
131	if (index.row() > menu.shortcuts().count()) {
132		return nullptr;
133	}
134	const ShortcutItem& item = menu.shortcuts()[index.row()];
135	return item.action();
136}
137
138void ShortcutController::updateKey(const QModelIndex& index, const QKeySequence& keySequence) {
139	if (!index.isValid()) {
140		return;
141	}
142	const QModelIndex& parent = index.parent();
143	if (!parent.isValid()) {
144		return;
145	}
146	ShortcutMenu& menu = m_menus[parent.row()];
147	ShortcutItem& item = menu.shortcuts()[index.row()];
148	item.action()->setShortcut(keySequence);
149	emit dataChanged(createIndex(index.row(), 0, index.internalId()), createIndex(index.row(), 2, index.internalId()));
150}
151
152void ShortcutController::updateButton(const QModelIndex& index, int button) {
153	if (!index.isValid()) {
154		return;
155	}
156	const QModelIndex& parent = index.parent();
157	if (!parent.isValid()) {
158		return;
159	}
160	ShortcutMenu& menu = m_menus[parent.row()];
161	ShortcutItem& item = menu.shortcuts()[index.row()];
162	int oldButton = item.button();
163	item.setButton(button);
164	if (oldButton >= 0) {
165		m_buttons.take(oldButton);
166	}
167	m_buttons[button] = &item;
168	emit dataChanged(createIndex(index.row(), 0, index.internalId()), createIndex(index.row(), 2, index.internalId()));
169}
170
171bool ShortcutController::eventFilter(QObject*, QEvent* event) {
172	if (event->type() == GamepadButtonEvent::Down()) {
173		auto item = m_buttons.find(static_cast<GamepadButtonEvent*>(event)->value());
174		if (item == m_buttons.end()) {
175			return false;
176		}
177		QAction* action = item.value()->action();
178		if (action->isEnabled()) {
179			action->trigger();
180		}
181		event->accept();
182		return true;
183	}
184	return false;
185}
186
187ShortcutController::ShortcutItem::ShortcutItem(QAction* action, const QString& name)
188	: m_action(action)
189	, m_name(name)
190	, m_button(-1)
191{
192	m_visibleName = action->text()
193		.remove(QRegExp("&(?!&)"))
194		.remove("...");
195}
196
197ShortcutController::ShortcutMenu::ShortcutMenu(QMenu* menu)
198	: m_menu(menu)
199{
200	m_visibleName = menu->title()
201		.remove(QRegExp("&(?!&)"))
202		.remove("...");
203}
204
205void ShortcutController::ShortcutMenu::addAction(QAction* action, const QString& name) {
206	m_shortcuts.append(ShortcutItem(action, name));
207}