Qt: Remove tree structure from InputItem

This commit is contained in:
Vicki Pfau 2017-06-27 20:18:37 -07:00
parent 96fcf9d267
commit 94b756ca9b
11 changed files with 204 additions and 241 deletions

View File

@ -87,7 +87,7 @@ InputController::~InputController() {
#endif #endif
} }
void InputController::rebuildIndex(const InputItem* index) { void InputController::rebuildIndex(const InputIndex* index) {
m_inputIndex.rebuild(index); m_inputIndex.rebuild(index);
rebindKey(GBA_KEY_A); rebindKey(GBA_KEY_A);

View File

@ -46,7 +46,7 @@ public:
~InputController(); ~InputController();
InputIndex* inputIndex() { return &m_inputIndex; } InputIndex* inputIndex() { return &m_inputIndex; }
void rebuildIndex(const InputItem* = nullptr); void rebuildIndex(const InputIndex* = nullptr);
void setConfiguration(ConfigController* config); void setConfiguration(ConfigController* config);
void saveConfiguration(); void saveConfiguration();

View File

@ -18,36 +18,31 @@ void InputIndex::clone(InputIndex* root, bool actions) {
if (!actions) { if (!actions) {
clone(const_cast<const InputIndex*>(root)); clone(const_cast<const InputIndex*>(root));
} else { } else {
m_root.clear(); qDeleteAll(m_items);
onSubitems(root->root(), [this](InputItem* item, InputItem* parent, QVariant accum) -> QVariant { m_items.clear();
InputItem* newParent = qvariant_cast<InputItem*>(accum); for (auto& item : root->m_items) {
InputItem* newItem = newParent->addItem(*item); InputItem* newItem = new InputItem(*item);
m_items.append(newItem);
itemAdded(newItem); itemAdded(newItem);
return QVariant::fromValue(newItem); }
}, QVariant::fromValue(&m_root));
} }
rebuild();
} }
void InputIndex::clone(const InputIndex* root) { void InputIndex::clone(const InputIndex* root) {
m_root.clear(); qDeleteAll(m_items);
onSubitems(root->root(), [this](const InputItem* item, const InputItem* parent, QVariant accum) -> QVariant { m_items.clear();
InputItem* newParent = qvariant_cast<InputItem*>(accum); for (auto& item : root->m_items) {
InputItem* newItem = newParent->addItem(*item); InputItem* newItem = new InputItem(*item);
m_items.append(newItem);
itemAdded(newItem); itemAdded(newItem);
return QVariant::fromValue(newItem); }
}, QVariant::fromValue(&m_root)); rebuild();
} }
void InputIndex::rebuild(const InputIndex* root) { void InputIndex::rebuild(const InputIndex* root) {
rebuild(root->root());
}
void InputIndex::rebuild(const InputItem* root) {
const InputItem* sourceRoot;
if (!root) { if (!root) {
sourceRoot = &m_root; root = this;
} else {
sourceRoot = root;
} }
m_names.clear(); m_names.clear();
@ -56,10 +51,9 @@ void InputIndex::rebuild(const InputItem* root) {
m_buttons.clear(); m_buttons.clear();
m_axes.clear(); m_axes.clear();
onSubitems(sourceRoot, [this](const InputItem* item, const InputItem* parent, QVariant accum) -> QVariant { for (auto& item : root->m_items) {
InputItem* newParent = qvariant_cast<InputItem*>(accum);
InputItem* newItem = nullptr; InputItem* newItem = nullptr;
for (auto iter : newParent->items()) { for (auto &iter : m_items) {
if (*iter == *item) { if (*iter == *item) {
newItem = iter; newItem = iter;
break; break;
@ -70,8 +64,7 @@ void InputIndex::rebuild(const InputItem* root) {
newItem->setAxis(item->axis(), item->direction()); newItem->setAxis(item->axis(), item->direction());
itemAdded(newItem); itemAdded(newItem);
return QVariant::fromValue(newItem); }
}, QVariant::fromValue(&m_root));
} }
InputItem* InputIndex::itemAt(const QString& name) { InputItem* InputIndex::itemAt(const QString& name) {
@ -244,32 +237,11 @@ int InputIndex::toModifierKey(int key) {
return modifiers; return modifiers;
} }
void InputIndex::onSubitems(InputItem* item, std::function<void(InputItem*)> func) {
for (InputItem* subitem : item->items()) {
func(subitem);
onSubitems(subitem, func);
}
}
void InputIndex::onSubitems(InputItem* item, std::function<QVariant(InputItem*, InputItem*, QVariant)> func, QVariant accum) {
for (InputItem* subitem : item->items()) {
QVariant newAccum = func(subitem, item, accum);
onSubitems(subitem, func, newAccum);
}
}
void InputIndex::onSubitems(const InputItem* item, std::function<QVariant(const InputItem*, const InputItem*, QVariant)> func, QVariant accum) {
for (const InputItem* subitem : item->items()) {
QVariant newAccum = func(subitem, item, accum);
onSubitems(subitem, func, newAccum);
}
}
void InputIndex::loadProfile(const QString& profile) { void InputIndex::loadProfile(const QString& profile) {
m_profileName = profile; m_profileName = profile;
m_profile = InputProfile::findProfile(profile); m_profile = InputProfile::findProfile(profile);
onSubitems(&m_root, [this](InputItem* item) { for (auto& item : m_items) {
loadGamepadShortcuts(item); loadGamepadShortcuts(item);
}); }
} }

View File

@ -32,11 +32,13 @@ public:
void clone(InputIndex* root, bool actions = false); void clone(InputIndex* root, bool actions = false);
void clone(const InputIndex* root); void clone(const InputIndex* root);
void rebuild(const InputIndex* root); void rebuild(const InputIndex* root = nullptr);
void rebuild(const InputItem* root = nullptr);
const QList<InputItem*>& items() const { return m_items; }
template<typename... Args> InputItem* addItem(Args... params) { template<typename... Args> InputItem* addItem(Args... params) {
InputItem* newItem = m_root.addItem(params...); InputItem* newItem = new InputItem(params...);
m_items.append(newItem);
itemAdded(newItem); itemAdded(newItem);
return newItem; return newItem;
} }
@ -55,21 +57,15 @@ public:
static bool isModifierKey(int key); static bool isModifierKey(int key);
static int toModifierKey(int key); static int toModifierKey(int key);
InputItem* root() { return &m_root; }
const InputItem* root() const { return &m_root; }
void loadProfile(const QString& profile); void loadProfile(const QString& profile);
private: private:
bool loadShortcuts(InputItem*); bool loadShortcuts(InputItem*);
void loadGamepadShortcuts(InputItem*); void loadGamepadShortcuts(InputItem*);
void onSubitems(InputItem*, std::function<void(InputItem*)> func);
void onSubitems(InputItem*, std::function<QVariant(InputItem*, InputItem* parent, QVariant accum)> func, QVariant accum = QVariant());
void onSubitems(const InputItem*, std::function<QVariant(const InputItem*, const InputItem* parent, QVariant accum)> func, QVariant accum = QVariant());
void itemAdded(InputItem*); void itemAdded(InputItem*);
InputItem m_root; QList<InputItem*> m_items;
QMap<QString, InputItem*> m_names; QMap<QString, InputItem*> m_names;
QMap<const QMenu*, InputItem*> m_menus; QMap<const QMenu*, InputItem*> m_menus;

View File

@ -10,86 +10,71 @@
using namespace QGBA; using namespace QGBA;
InputItem::InputItem() InputItem::InputItem()
: QObject(nullptr)
, m_parent(nullptr)
{ {
} }
InputItem::InputItem(QAction* action, const QString& name, InputItem* parent) InputItem::InputItem(QAction* action, const QString& name, QMenu* parent)
: QObject(parent) : QObject(parent)
, m_action(action) , m_action(action)
, m_shortcut(action->shortcut().isEmpty() ? 0 : action->shortcut()[0]) , m_shortcut(action->shortcut().isEmpty() ? 0 : action->shortcut()[0])
, m_name(name) , m_name(name)
, m_parent(parent) , m_menu(parent)
{ {
m_visibleName = action->text() m_visibleName = action->text()
.remove(QRegExp("&(?!&)")) .remove(QRegExp("&(?!&)"))
.remove("..."); .remove("...");
} }
InputItem::InputItem(QMenu* menu, const QString& name, InputItem* parent) InputItem::InputItem(InputItem::Functions functions, const QString& visibleName, const QString& name, QMenu* parent)
: QObject(parent)
, m_menu(menu)
, m_name(name)
, m_parent(parent)
{
m_visibleName = menu->title()
.remove(QRegExp("&(?!&)"))
.remove("...");
}
InputItem::InputItem(InputItem::Functions functions, const QString& visibleName, const QString& name, InputItem* parent)
: QObject(parent) : QObject(parent)
, m_functions(functions) , m_functions(functions)
, m_name(name) , m_name(name)
, m_visibleName(visibleName) , m_visibleName(visibleName)
, m_parent(parent) , m_menu(parent)
{ {
} }
InputItem::InputItem(int key, const QString& visibleName, const QString& name, InputItem* parent) InputItem::InputItem(int key, const QString& visibleName, const QString& name, QMenu* parent)
: QObject(parent) : QObject(parent)
, m_key(key) , m_key(key)
, m_name(name) , m_name(name)
, m_visibleName(visibleName) , m_visibleName(visibleName)
, m_parent(parent) , m_menu(parent)
{ {
} }
InputItem::InputItem(const QString& visibleName, const QString& name, InputItem* parent) InputItem::InputItem(const QString& visibleName, const QString& name, QMenu* parent)
: QObject(parent) : QObject(parent)
, m_name(name) , m_name(name)
, m_visibleName(visibleName) , m_visibleName(visibleName)
, m_parent(parent) , m_menu(parent)
{ {
} }
InputItem::InputItem(const InputItem& other, InputItem* parent) InputItem::InputItem(const InputItem& other)
: QObject(parent) : QObject(other.m_menu)
, m_menu(other.m_menu)
, m_name(other.m_name) , m_name(other.m_name)
, m_visibleName(other.m_visibleName) , m_visibleName(other.m_visibleName)
, m_shortcut(other.m_shortcut) , m_shortcut(other.m_shortcut)
, m_button(other.m_button) , m_button(other.m_button)
, m_axis(other.m_axis) , m_axis(other.m_axis)
, m_direction(other.m_direction) , m_direction(other.m_direction)
, m_parent(parent) , m_menu(other.m_menu)
{ {
} }
InputItem::InputItem(InputItem& other, InputItem* parent) InputItem::InputItem(InputItem& other)
: QObject(parent) : QObject(other.m_menu)
, m_action(other.m_action) , m_action(other.m_action)
, m_functions(other.m_functions) , m_functions(other.m_functions)
, m_key(other.m_key) , m_key(other.m_key)
, m_menu(other.m_menu)
, m_name(other.m_name) , m_name(other.m_name)
, m_visibleName(other.m_visibleName) , m_visibleName(other.m_visibleName)
, m_shortcut(other.m_shortcut) , m_shortcut(other.m_shortcut)
, m_button(other.m_button) , m_button(other.m_button)
, m_axis(other.m_axis) , m_axis(other.m_axis)
, m_direction(other.m_direction) , m_direction(other.m_direction)
, m_parent(parent) , m_menu(other.m_menu)
{ {
} }
@ -120,11 +105,6 @@ void InputItem::setAxis(int axis, GamepadAxisEvent::Direction direction) {
emit axisBound(this, axis, direction); emit axisBound(this, axis, direction);
} }
void InputItem::clear() {
qDeleteAll(m_items);
m_items.clear();
}
void InputItem::trigger(bool active) { void InputItem::trigger(bool active) {
if (active) { if (active) {
if (m_functions.first) { if (m_functions.first) {

View File

@ -18,42 +18,30 @@ namespace QGBA {
class InputItem : public QObject { class InputItem : public QObject {
Q_OBJECT Q_OBJECT
private: public:
typedef QPair<std::function<void ()>, std::function<void ()>> Functions; typedef QPair<std::function<void ()>, std::function<void ()>> Functions;
InputItem(QAction* action, const QString& name, InputItem* parent = nullptr); InputItem(QAction* action, const QString& name, QMenu* parent = nullptr);
InputItem(QMenu* menu, const QString& name, InputItem* parent = nullptr);
InputItem(Functions functions, const QString& visibleName, const QString& name, InputItem(Functions functions, const QString& visibleName, const QString& name,
InputItem* parent = nullptr); QMenu* parent = nullptr);
InputItem(int key, const QString& name, const QString& visibleName, InputItem* parent = nullptr); InputItem(int key, const QString& name, const QString& visibleName, QMenu* parent = nullptr);
InputItem(const QString& visibleName, const QString& name, InputItem* parent = nullptr); InputItem(const QString& visibleName, const QString& name, QMenu* parent = nullptr);
public:
InputItem(); InputItem();
InputItem(InputItem&, InputItem* parent = nullptr); InputItem(InputItem&);
InputItem(const InputItem&, InputItem* parent = nullptr); InputItem(const InputItem&);
QAction* action() { return m_action; } QAction* action() { return m_action; }
const QAction* action() const { return m_action; } const QAction* action() const { return m_action; }
QMenu* menu() { return m_menu; }
const QMenu* menu() const { return m_menu; }
Functions functions() const { return m_functions; } Functions functions() const { return m_functions; }
int key() const { return m_key; } int key() const { return m_key; }
QMenu* menu() { return m_menu; }
const QMenu* menu() const { return m_menu; }
const QString& visibleName() const { return m_visibleName; } const QString& visibleName() const { return m_visibleName; }
const QString& name() const { return m_name; } const QString& name() const { return m_name; }
QList<InputItem*>& items() { return m_items; }
const QList<InputItem*>& items() const { return m_items; }
InputItem* parent() { return m_parent; }
const InputItem* parent() const { return m_parent; }
template<typename... Args> InputItem* addItem(Args... params) {
InputItem* item = new InputItem(params..., this);
m_items.append(item);
emit childAdded(this, item);
return item;
}
int shortcut() const { return m_shortcut; } int shortcut() const { return m_shortcut; }
void setShortcut(int sequence); void setShortcut(int sequence);
void clearShortcut(); void clearShortcut();
@ -66,8 +54,6 @@ public:
GamepadAxisEvent::Direction direction() const { return m_direction; } GamepadAxisEvent::Direction direction() const { return m_direction; }
void setAxis(int axis, GamepadAxisEvent::Direction direction); void setAxis(int axis, GamepadAxisEvent::Direction direction);
void clear();
bool operator==(const InputItem& other) const { bool operator==(const InputItem& other) const {
return m_name == other.m_name; return m_name == other.m_name;
} }
@ -94,8 +80,6 @@ private:
int m_button = -1; int m_button = -1;
int m_axis = -1; int m_axis = -1;
GamepadAxisEvent::Direction m_direction = GamepadAxisEvent::NEUTRAL; GamepadAxisEvent::Direction m_direction = GamepadAxisEvent::NEUTRAL;
QList<InputItem*> m_items;
InputItem* m_parent;
}; };
} }

View File

@ -14,10 +14,22 @@
using namespace QGBA; using namespace QGBA;
QString InputModel::InputModelItem::visibleName() const {
if (item) {
return item->visibleName();
}
if (menu) {
return menu->title()
.remove(QRegExp("&(?!&)"))
.remove("...");
}
return QString();
}
InputModel::InputModel(const InputIndex& index, QObject* parent) InputModel::InputModel(const InputIndex& index, QObject* parent)
: QAbstractItemModel(parent) : QAbstractItemModel(parent)
{ {
m_root.clone(&index); clone(index);
} }
InputModel::InputModel(QObject* parent) InputModel::InputModel(QObject* parent)
@ -27,7 +39,28 @@ InputModel::InputModel(QObject* parent)
void InputModel::clone(const InputIndex& index) { void InputModel::clone(const InputIndex& index) {
emit beginResetModel(); emit beginResetModel();
m_root.clone(&index); m_index.clone(&index);
m_menus.clear();
m_topLevelMenus.clear();
QList<const QMenu*> menus;
for (auto& item : m_index.items()) {
const QMenu* menu = item->menu();
if (!menus.contains(menu)) {
menus.append(menu);
m_menus.insert(menu);
}
}
for (auto& menu : menus) {
if (m_menus.contains(menu->parent())) {
m_tree[menu->parent()].append(menu);
} else {
m_topLevelMenus.append(menu);
}
}
for (auto& item : m_index.items()) {
const QMenu* menu = item->menu();
m_tree[menu].append(item);
}
emit endResetModel(); emit endResetModel();
} }
@ -36,25 +69,31 @@ QVariant InputModel::data(const QModelIndex& index, int role) const {
return QVariant(); return QVariant();
} }
int row = index.row(); int row = index.row();
const InputItem* item = static_cast<const InputItem*>(index.internalPointer()); const InputModelItem* item = static_cast<const InputModelItem*>(index.internalPointer());
switch (index.column()) { switch (index.column()) {
case 0: case 0:
return item->visibleName(); return item->visibleName();
case 1: case 1:
return QKeySequence(item->shortcut()).toString(QKeySequence::NativeText); if (item->item) {
case 2: return QKeySequence(item->item->shortcut()).toString(QKeySequence::NativeText);
if (item->button() >= 0) {
return item->button();
} }
if (item->axis() >= 0) { break;
case 2:
if (!item->item) {
break;
}
if (item->item->button() >= 0) {
return item->item->button();
}
if (item->item->axis() >= 0) {
char d = '\0'; char d = '\0';
if (item->direction() == GamepadAxisEvent::POSITIVE) { if (item->item->direction() == GamepadAxisEvent::POSITIVE) {
d = '+'; d = '+';
} }
if (item->direction() == GamepadAxisEvent::NEGATIVE) { if (item->item->direction() == GamepadAxisEvent::NEGATIVE) {
d = '-'; d = '-';
} }
return QString("%1%2").arg(d).arg(item->axis()); return QString("%1%2").arg(d).arg(item->item->axis());
} }
break; break;
} }
@ -79,26 +118,39 @@ QVariant InputModel::headerData(int section, Qt::Orientation orientation, int ro
} }
QModelIndex InputModel::index(int row, int column, const QModelIndex& parent) const { QModelIndex InputModel::index(int row, int column, const QModelIndex& parent) const {
const InputItem* pmenu = m_root.root();
if (parent.isValid()) { if (parent.isValid()) {
pmenu = static_cast<InputItem*>(parent.internalPointer()); InputModelItem* p = static_cast<InputModelItem*>(parent.internalPointer());
return createIndex(row, column, const_cast<InputModelItem*>(&m_tree[p->obj][row]));
} }
return createIndex(row, column, const_cast<InputItem*>(pmenu->items()[row])); return createIndex(row, column, const_cast<InputModelItem*>(&m_topLevelMenus[row]));
} }
QModelIndex InputModel::parent(const QModelIndex& index) const { QModelIndex InputModel::parent(const QModelIndex& index) const {
if (!index.isValid() || !index.internalPointer()) { if (!index.isValid() || !index.internalPointer()) {
return QModelIndex(); return QModelIndex();
} }
InputItem* item = static_cast<InputItem*>(index.internalPointer()); const QObject* obj = static_cast<const InputModelItem*>(index.internalPointer())->obj;
return this->index(item->parent()); if (m_menus.contains(obj->parent())) {
return this->index(obj->parent());
} else {
return QModelIndex();
}
} }
QModelIndex InputModel::index(InputItem* item, int row) const { QModelIndex InputModel::index(const QObject* item, int column) const {
if (!item || !item->parent()) { if (!item || !item->parent()) {
return QModelIndex(); return QModelIndex();
} }
return createIndex(item->parent()->items().indexOf(item), row, item); const QObject* parent = item->parent();
if (m_tree.contains(parent)) {
int index = m_tree[parent].indexOf(item);
return createIndex(index, column, const_cast<InputModelItem*>(&m_tree[parent][index]));
}
if (m_topLevelMenus.contains(item)) {
int index = m_topLevelMenus.indexOf(item);
return createIndex(index, column, const_cast<InputModelItem*>(&m_topLevelMenus[index]));
}
return QModelIndex();
} }
int InputModel::columnCount(const QModelIndex& index) const { int InputModel::columnCount(const QModelIndex& index) const {
@ -106,37 +158,27 @@ int InputModel::columnCount(const QModelIndex& index) const {
} }
int InputModel::rowCount(const QModelIndex& index) const { int InputModel::rowCount(const QModelIndex& index) const {
if (!index.isValid()) { if (!index.isValid() || !index.internalPointer()) {
return m_root.root()->items().count(); return m_topLevelMenus.count();
} }
const InputItem* item = static_cast<const InputItem*>(index.internalPointer()); const QObject* obj = static_cast<const InputModelItem*>(index.internalPointer())->obj;
return item->items().count(); if (!m_tree.contains(obj)) {
return 0;
}
return m_tree[obj].count();
} }
InputItem* InputModel::itemAt(const QModelIndex& index) { InputItem* InputModel::itemAt(const QModelIndex& index) {
if (!index.isValid()) { if (!index.isValid() || !index.internalPointer()) {
return nullptr; return nullptr;
} }
if (index.internalPointer()) { return static_cast<InputModelItem*>(index.internalPointer())->item;
return static_cast<InputItem*>(index.internalPointer());
}
if (!index.parent().isValid()) {
return nullptr;
}
InputItem* pmenu = static_cast<InputItem*>(index.parent().internalPointer());
return pmenu->items()[index.row()];
} }
const InputItem* InputModel::itemAt(const QModelIndex& index) const { const InputItem* InputModel::itemAt(const QModelIndex& index) const {
if (!index.isValid()) { if (!index.isValid() || !index.internalPointer()) {
return nullptr; return nullptr;
} }
if (index.internalPointer()) { return static_cast<const InputModelItem*>(index.internalPointer())->item;
return static_cast<InputItem*>(index.internalPointer());
}
if (!index.parent().isValid()) {
return nullptr;
}
InputItem* pmenu = static_cast<InputItem*>(index.parent().internalPointer());
return pmenu->items()[index.row()];
} }

View File

@ -11,6 +11,8 @@
#include "InputIndex.h" #include "InputIndex.h"
#include <QAbstractItemModel> #include <QAbstractItemModel>
#include <QMenu>
#include <QSet>
#include <functional> #include <functional>
@ -48,12 +50,28 @@ public:
InputItem* itemAt(const QModelIndex& index); InputItem* itemAt(const QModelIndex& index);
const InputItem* itemAt(const QModelIndex& index) const; const InputItem* itemAt(const QModelIndex& index) const;
InputItem* root() { return m_root.root(); } InputIndex* inputIndex() { return &m_index; }
private: private:
QModelIndex index(InputItem* item, int column = 0) const; struct InputModelItem {
InputModelItem(InputItem* i) : item(i), obj(i) {}
InputModelItem(const QMenu* i) : menu(i), obj(i) {}
InputModelItem(const QObject* i) : obj(i) {}
InputIndex m_root; InputItem* item = nullptr;
const QMenu* menu = nullptr;
const QObject* obj;
QString visibleName() const;
bool operator==(const InputModelItem& other) { return obj == other.obj; }
};
QModelIndex index(const QObject* item, int column = 0) const;
InputIndex m_index;
QList<InputModelItem> m_topLevelMenus;
QSet<const QObject*> m_menus;
QMap<const QObject*, QList<InputModelItem>> m_tree;
QString m_profileName; QString m_profileName;
}; };

View File

@ -28,7 +28,7 @@ public:
void setModel(InputIndex* model); void setModel(InputIndex* model);
void setInputController(InputController* input); void setInputController(InputController* input);
const InputItem* root() { return m_model.root(); } const InputIndex* root() { return m_model.inputIndex(); }
protected: protected:
virtual bool event(QEvent*) override; virtual bool event(QEvent*) override;

View File

@ -920,7 +920,6 @@ void Window::setupMenu(QMenuBar* menubar) {
installEventFilter(&m_inputController); installEventFilter(&m_inputController);
QMenu* fileMenu = menubar->addMenu(tr("&File")); QMenu* fileMenu = menubar->addMenu(tr("&File"));
m_inputController.inputIndex()->addItem(fileMenu, "file");
addControlledAction(fileMenu, fileMenu->addAction(tr("Load &ROM..."), this, SLOT(selectROM()), QKeySequence::Open), addControlledAction(fileMenu, fileMenu->addAction(tr("Load &ROM..."), this, SLOT(selectROM()), QKeySequence::Open),
"loadROM"); "loadROM");
#ifdef USE_SQLITE3 #ifdef USE_SQLITE3
@ -975,8 +974,6 @@ void Window::setupMenu(QMenuBar* menubar) {
QMenu* quickLoadMenu = fileMenu->addMenu(tr("Quick load")); QMenu* quickLoadMenu = fileMenu->addMenu(tr("Quick load"));
QMenu* quickSaveMenu = fileMenu->addMenu(tr("Quick save")); QMenu* quickSaveMenu = fileMenu->addMenu(tr("Quick save"));
m_inputController.inputIndex()->addItem(quickLoadMenu, "quickLoadMenu");
m_inputController.inputIndex()->addItem(quickSaveMenu, "quickSaveMenu");
QAction* quickLoad = new QAction(tr("Load recent"), quickLoadMenu); QAction* quickLoad = new QAction(tr("Load recent"), quickLoadMenu);
connect(quickLoad, &QAction::triggered, m_controller, &GameController::loadState); connect(quickLoad, &QAction::triggered, m_controller, &GameController::loadState);
@ -1062,7 +1059,6 @@ void Window::setupMenu(QMenuBar* menubar) {
#endif #endif
QMenu* emulationMenu = menubar->addMenu(tr("&Emulation")); QMenu* emulationMenu = menubar->addMenu(tr("&Emulation"));
InputItem* emulationMenuItem = m_inputController.inputIndex()->addItem(emulationMenu, "emulation");
QAction* reset = new QAction(tr("&Reset"), emulationMenu); QAction* reset = new QAction(tr("&Reset"), emulationMenu);
reset->setShortcut(tr("Ctrl+R")); reset->setShortcut(tr("Ctrl+R"));
connect(reset, &QAction::triggered, m_controller, &GameController::reset); connect(reset, &QAction::triggered, m_controller, &GameController::reset);
@ -1103,11 +1099,11 @@ void Window::setupMenu(QMenuBar* menubar) {
emulationMenu->addSeparator(); emulationMenu->addSeparator();
emulationMenuItem->addItem(qMakePair([this]() { m_inputController.inputIndex()->addItem(qMakePair([this]() {
m_controller->setTurbo(true, false); m_controller->setTurbo(true, false);
}, [this]() { }, [this]() {
m_controller->setTurbo(false, false); m_controller->setTurbo(false, false);
}), tr("Fast forward (held)"), "holdFastForward")->setShortcut(QKeySequence(Qt::Key_Tab)[0]); }), tr("Fast forward (held)"), "holdFastForward", emulationMenu)->setShortcut(QKeySequence(Qt::Key_Tab)[0]);
QAction* turbo = new QAction(tr("&Fast forward"), emulationMenu); QAction* turbo = new QAction(tr("&Fast forward"), emulationMenu);
turbo->setCheckable(true); turbo->setCheckable(true);
@ -1129,11 +1125,11 @@ void Window::setupMenu(QMenuBar* menubar) {
} }
m_config->updateOption("fastForwardRatio"); m_config->updateOption("fastForwardRatio");
emulationMenuItem->addItem(qMakePair([this]() { m_inputController.inputIndex()->addItem(qMakePair([this]() {
m_controller->startRewinding(); m_controller->startRewinding();
}, [this]() { }, [this]() {
m_controller->stopRewinding(); m_controller->stopRewinding();
}), tr("Rewind (held)"), "holdRewind")->setShortcut(QKeySequence("`")[0]); }), tr("Rewind (held)"), "holdRewind", emulationMenu)->setShortcut(QKeySequence("`")[0]);
QAction* rewind = new QAction(tr("Re&wind"), emulationMenu); QAction* rewind = new QAction(tr("Re&wind"), emulationMenu);
rewind->setShortcut(tr("~")); rewind->setShortcut(tr("~"));
@ -1168,7 +1164,6 @@ void Window::setupMenu(QMenuBar* menubar) {
emulationMenu->addSeparator(); emulationMenu->addSeparator();
QMenu* solarMenu = emulationMenu->addMenu(tr("Solar sensor")); QMenu* solarMenu = emulationMenu->addMenu(tr("Solar sensor"));
m_inputController.inputIndex()->addItem(solarMenu, "luminance");
QAction* solarIncrease = new QAction(tr("Increase solar level"), solarMenu); QAction* solarIncrease = new QAction(tr("Increase solar level"), solarMenu);
connect(solarIncrease, &QAction::triggered, m_controller, &GameController::increaseLuminanceLevel); connect(solarIncrease, &QAction::triggered, m_controller, &GameController::increaseLuminanceLevel);
addControlledAction(solarMenu, solarIncrease, "increaseLuminanceLevel"); addControlledAction(solarMenu, solarIncrease, "increaseLuminanceLevel");
@ -1195,9 +1190,7 @@ void Window::setupMenu(QMenuBar* menubar) {
} }
QMenu* avMenu = menubar->addMenu(tr("Audio/&Video")); QMenu* avMenu = menubar->addMenu(tr("Audio/&Video"));
InputItem* avMenuItem = m_inputController.inputIndex()->addItem(avMenu, "av");
QMenu* frameMenu = avMenu->addMenu(tr("Frame size")); QMenu* frameMenu = avMenu->addMenu(tr("Frame size"));
InputItem* frameMenuItem = avMenuItem->addItem(frameMenu, "frameSize");
for (int i = 1; i <= 6; ++i) { for (int i = 1; i <= 6; ++i) {
QAction* setSize = new QAction(tr("%1x").arg(QString::number(i)), avMenu); QAction* setSize = new QAction(tr("%1x").arg(QString::number(i)), avMenu);
setSize->setCheckable(true); setSize->setCheckable(true);
@ -1219,7 +1212,7 @@ void Window::setupMenu(QMenuBar* menubar) {
setSize->blockSignals(enableSignals); setSize->blockSignals(enableSignals);
}); });
m_frameSizes[i] = setSize; m_frameSizes[i] = setSize;
addControlledAction(frameMenuItem, setSize, QString("frame%1x").arg(QString::number(i))); addControlledAction(frameMenu, setSize, QString("frame%1x").arg(QString::number(i)));
} }
QKeySequence fullscreenKeys; QKeySequence fullscreenKeys;
#ifdef Q_OS_WIN #ifdef Q_OS_WIN
@ -1227,7 +1220,7 @@ void Window::setupMenu(QMenuBar* menubar) {
#else #else
fullscreenKeys = QKeySequence("Ctrl+F"); fullscreenKeys = QKeySequence("Ctrl+F");
#endif #endif
addControlledAction(frameMenuItem, frameMenu->addAction(tr("Toggle fullscreen"), this, SLOT(toggleFullScreen()), fullscreenKeys), "fullscreen"); addControlledAction(frameMenu, frameMenu->addAction(tr("Toggle fullscreen"), this, SLOT(toggleFullScreen()), fullscreenKeys), "fullscreen");
ConfigOption* lockAspectRatio = m_config->addOption("lockAspectRatio"); ConfigOption* lockAspectRatio = m_config->addOption("lockAspectRatio");
lockAspectRatio->addBoolean(tr("Lock aspect ratio"), avMenu); lockAspectRatio->addBoolean(tr("Lock aspect ratio"), avMenu);
@ -1332,13 +1325,9 @@ void Window::setupMenu(QMenuBar* menubar) {
avMenu->addSeparator(); avMenu->addSeparator();
m_videoLayers = avMenu->addMenu(tr("Video layers")); m_videoLayers = avMenu->addMenu(tr("Video layers"));
avMenuItem->addItem(m_videoLayers, "videoLayers");
m_audioChannels = avMenu->addMenu(tr("Audio channels")); m_audioChannels = avMenu->addMenu(tr("Audio channels"));
avMenuItem->addItem(m_audioChannels, "audioChannels");
QMenu* toolsMenu = menubar->addMenu(tr("&Tools")); QMenu* toolsMenu = menubar->addMenu(tr("&Tools"));
m_inputController.inputIndex()->addItem(toolsMenu, "tools");
QAction* viewLogs = new QAction(tr("View &logs..."), toolsMenu); QAction* viewLogs = new QAction(tr("View &logs..."), toolsMenu);
connect(viewLogs, &QAction::triggered, m_logView, &QWidget::show); connect(viewLogs, &QAction::triggered, m_logView, &QWidget::show);
addControlledAction(toolsMenu, viewLogs, "viewLogs"); addControlledAction(toolsMenu, viewLogs, "viewLogs");
@ -1475,133 +1464,131 @@ void Window::setupMenu(QMenuBar* menubar) {
QAction* exitFullScreen = new QAction(tr("Exit fullscreen"), frameMenu); QAction* exitFullScreen = new QAction(tr("Exit fullscreen"), frameMenu);
connect(exitFullScreen, &QAction::triggered, this, &Window::exitFullScreen); connect(exitFullScreen, &QAction::triggered, this, &Window::exitFullScreen);
exitFullScreen->setShortcut(QKeySequence("Esc")); exitFullScreen->setShortcut(QKeySequence("Esc"));
addHiddenAction(frameMenuItem, exitFullScreen, "exitFullScreen"); addHiddenAction(frameMenu, exitFullScreen, "exitFullScreen");
QMenu* autofireMenu = new QMenu(tr("Autofire"), this); QMenu* autofireMenu = new QMenu(tr("Autofire"), this);
InputItem* autofireMenuItem = m_inputController.inputIndex()->addItem(autofireMenu, "autofire");
autofireMenuItem->addItem(qMakePair([this]() { m_inputController.inputIndex()->addItem(qMakePair([this]() {
m_controller->setAutofire(GBA_KEY_A, true); m_controller->setAutofire(GBA_KEY_A, true);
}, [this]() { }, [this]() {
m_controller->setAutofire(GBA_KEY_A, false); m_controller->setAutofire(GBA_KEY_A, false);
}), tr("Autofire A"), "autofireA"); }), tr("Autofire A"), "autofireA", autofireMenu);
autofireMenuItem->addItem(qMakePair([this]() { m_inputController.inputIndex()->addItem(qMakePair([this]() {
m_controller->setAutofire(GBA_KEY_B, true); m_controller->setAutofire(GBA_KEY_B, true);
}, [this]() { }, [this]() {
m_controller->setAutofire(GBA_KEY_B, false); m_controller->setAutofire(GBA_KEY_B, false);
}), tr("Autofire B"), "autofireB"); }), tr("Autofire B"), "autofireB", autofireMenu);
autofireMenuItem->addItem(qMakePair([this]() { m_inputController.inputIndex()->addItem(qMakePair([this]() {
m_controller->setAutofire(GBA_KEY_L, true); m_controller->setAutofire(GBA_KEY_L, true);
}, [this]() { }, [this]() {
m_controller->setAutofire(GBA_KEY_L, false); m_controller->setAutofire(GBA_KEY_L, false);
}), tr("Autofire L"), "autofireL"); }), tr("Autofire L"), "autofireL", autofireMenu);
autofireMenuItem->addItem(qMakePair([this]() { m_inputController.inputIndex()->addItem(qMakePair([this]() {
m_controller->setAutofire(GBA_KEY_R, true); m_controller->setAutofire(GBA_KEY_R, true);
}, [this]() { }, [this]() {
m_controller->setAutofire(GBA_KEY_R, false); m_controller->setAutofire(GBA_KEY_R, false);
}), tr("Autofire R"), "autofireR"); }), tr("Autofire R"), "autofireR", autofireMenu);
autofireMenuItem->addItem(qMakePair([this]() { m_inputController.inputIndex()->addItem(qMakePair([this]() {
m_controller->setAutofire(GBA_KEY_START, true); m_controller->setAutofire(GBA_KEY_START, true);
}, [this]() { }, [this]() {
m_controller->setAutofire(GBA_KEY_START, false); m_controller->setAutofire(GBA_KEY_START, false);
}), tr("Autofire Start"), "autofireStart"); }), tr("Autofire Start"), "autofireStart", autofireMenu);
autofireMenuItem->addItem(qMakePair([this]() { m_inputController.inputIndex()->addItem(qMakePair([this]() {
m_controller->setAutofire(GBA_KEY_SELECT, true); m_controller->setAutofire(GBA_KEY_SELECT, true);
}, [this]() { }, [this]() {
m_controller->setAutofire(GBA_KEY_SELECT, false); m_controller->setAutofire(GBA_KEY_SELECT, false);
}), tr("Autofire Select"), "autofireSelect"); }), tr("Autofire Select"), "autofireSelect", autofireMenu);
autofireMenuItem->addItem(qMakePair([this]() { m_inputController.inputIndex()->addItem(qMakePair([this]() {
m_controller->setAutofire(GBA_KEY_UP, true); m_controller->setAutofire(GBA_KEY_UP, true);
}, [this]() { }, [this]() {
m_controller->setAutofire(GBA_KEY_UP, false); m_controller->setAutofire(GBA_KEY_UP, false);
}), tr("Autofire Up"), "autofireUp"); }), tr("Autofire Up"), "autofireUp", autofireMenu);
autofireMenuItem->addItem(qMakePair([this]() { m_inputController.inputIndex()->addItem(qMakePair([this]() {
m_controller->setAutofire(GBA_KEY_RIGHT, true); m_controller->setAutofire(GBA_KEY_RIGHT, true);
}, [this]() { }, [this]() {
m_controller->setAutofire(GBA_KEY_RIGHT, false); m_controller->setAutofire(GBA_KEY_RIGHT, false);
}), tr("Autofire Right"), "autofireRight"); }), tr("Autofire Right"), "autofireRight", autofireMenu);
autofireMenuItem->addItem(qMakePair([this]() { m_inputController.inputIndex()->addItem(qMakePair([this]() {
m_controller->setAutofire(GBA_KEY_DOWN, true); m_controller->setAutofire(GBA_KEY_DOWN, true);
}, [this]() { }, [this]() {
m_controller->setAutofire(GBA_KEY_DOWN, false); m_controller->setAutofire(GBA_KEY_DOWN, false);
}), tr("Autofire Down"), "autofireDown"); }), tr("Autofire Down"), "autofireDown", autofireMenu);
autofireMenuItem->addItem(qMakePair([this]() { m_inputController.inputIndex()->addItem(qMakePair([this]() {
m_controller->setAutofire(GBA_KEY_LEFT, true); m_controller->setAutofire(GBA_KEY_LEFT, true);
}, [this]() { }, [this]() {
m_controller->setAutofire(GBA_KEY_LEFT, false); m_controller->setAutofire(GBA_KEY_LEFT, false);
}), tr("Autofire Left"), "autofireLeft"); }), tr("Autofire Left"), "autofireLeft", autofireMenu);
QMenu* bindingsMenu = new QMenu(tr("Bindings"), this); QMenu* bindingsMenu = new QMenu(tr("Bindings"), this);
InputItem* bindingsMenuItem = m_inputController.inputIndex()->addItem(bindingsMenu, "bindings");
bindingsMenuItem->addItem(qMakePair([this]() { m_inputController.inputIndex()->addItem(qMakePair([this]() {
m_controller->keyPressed(GBA_KEY_A); m_controller->keyPressed(GBA_KEY_A);
}, [this]() { }, [this]() {
m_controller->keyReleased(GBA_KEY_A); m_controller->keyReleased(GBA_KEY_A);
}), tr("A"), "keyA"); }), tr("A"), "keyA", bindingsMenu);
bindingsMenuItem->addItem(qMakePair([this]() { m_inputController.inputIndex()->addItem(qMakePair([this]() {
m_controller->keyPressed(GBA_KEY_B); m_controller->keyPressed(GBA_KEY_B);
}, [this]() { }, [this]() {
m_controller->keyReleased(GBA_KEY_B); m_controller->keyReleased(GBA_KEY_B);
}), tr("B"), "keyB"); }), tr("B"), "keyB", bindingsMenu);
bindingsMenuItem->addItem(qMakePair([this]() { m_inputController.inputIndex()->addItem(qMakePair([this]() {
m_controller->keyPressed(GBA_KEY_START); m_controller->keyPressed(GBA_KEY_START);
}, [this]() { }, [this]() {
m_controller->keyReleased(GBA_KEY_START); m_controller->keyReleased(GBA_KEY_START);
}), tr("Start"), "keyStart"); }), tr("Start"), "keyStart", bindingsMenu);
bindingsMenuItem->addItem(qMakePair([this]() { m_inputController.inputIndex()->addItem(qMakePair([this]() {
m_controller->keyPressed(GBA_KEY_SELECT); m_controller->keyPressed(GBA_KEY_SELECT);
}, [this]() { }, [this]() {
m_controller->keyReleased(GBA_KEY_SELECT); m_controller->keyReleased(GBA_KEY_SELECT);
}), tr("Select"), "keySelect"); }), tr("Select"), "keySelect", bindingsMenu);
bindingsMenuItem->addItem(qMakePair([this]() { m_inputController.inputIndex()->addItem(qMakePair([this]() {
m_controller->keyPressed(GBA_KEY_L); m_controller->keyPressed(GBA_KEY_L);
}, [this]() { }, [this]() {
m_controller->keyReleased(GBA_KEY_L); m_controller->keyReleased(GBA_KEY_L);
}), tr("L"), "keyL"); }), tr("L"), "keyL", bindingsMenu);
bindingsMenuItem->addItem(qMakePair([this]() { m_inputController.inputIndex()->addItem(qMakePair([this]() {
m_controller->keyPressed(GBA_KEY_R); m_controller->keyPressed(GBA_KEY_R);
}, [this]() { }, [this]() {
m_controller->keyReleased(GBA_KEY_R); m_controller->keyReleased(GBA_KEY_R);
}), tr("R"), "keyR"); }), tr("R"), "keyR", bindingsMenu);
bindingsMenuItem->addItem(qMakePair([this]() { m_inputController.inputIndex()->addItem(qMakePair([this]() {
m_controller->keyPressed(GBA_KEY_UP); m_controller->keyPressed(GBA_KEY_UP);
}, [this]() { }, [this]() {
m_controller->keyReleased(GBA_KEY_UP); m_controller->keyReleased(GBA_KEY_UP);
}), tr("Up"), "keyUp"); }), tr("Up"), "keyUp", bindingsMenu);
bindingsMenuItem->addItem(qMakePair([this]() { m_inputController.inputIndex()->addItem(qMakePair([this]() {
m_controller->keyPressed(GBA_KEY_DOWN); m_controller->keyPressed(GBA_KEY_DOWN);
}, [this]() { }, [this]() {
m_controller->keyReleased(GBA_KEY_DOWN); m_controller->keyReleased(GBA_KEY_DOWN);
}), tr("Down"), "keyDown"); }), tr("Down"), "keyDown", bindingsMenu);
bindingsMenuItem->addItem(qMakePair([this]() { m_inputController.inputIndex()->addItem(qMakePair([this]() {
m_controller->keyPressed(GBA_KEY_LEFT); m_controller->keyPressed(GBA_KEY_LEFT);
}, [this]() { }, [this]() {
m_controller->keyReleased(GBA_KEY_LEFT); m_controller->keyReleased(GBA_KEY_LEFT);
}), tr("Left"), "keyLeft"); }), tr("Left"), "keyLeft", bindingsMenu);
bindingsMenuItem->addItem(qMakePair([this]() { m_inputController.inputIndex()->addItem(qMakePair([this]() {
m_controller->keyPressed(GBA_KEY_RIGHT); m_controller->keyPressed(GBA_KEY_RIGHT);
}, [this]() { }, [this]() {
m_controller->keyReleased(GBA_KEY_RIGHT); m_controller->keyReleased(GBA_KEY_RIGHT);
}), tr("Right"), "keyRight"); }), tr("Right"), "keyRight", bindingsMenu);
for (QAction* action : m_gameActions) { for (QAction* action : m_gameActions) {
action->setDisabled(true); action->setDisabled(true);
@ -1659,22 +1646,8 @@ QAction* Window::addControlledAction(QMenu* menu, QAction* action, const QString
return action; return action;
} }
QAction* Window::addControlledAction(InputItem* parent, QAction* action, const QString& name) {
addHiddenAction(parent, action, name);
parent->menu()->addAction(action);
return action;
}
QAction* Window::addHiddenAction(QMenu* menu, QAction* action, const QString& name) { QAction* Window::addHiddenAction(QMenu* menu, QAction* action, const QString& name) {
InputItem* parent = m_inputController.inputIndex()->itemForMenu(menu); m_inputController.inputIndex()->addItem(action, name, menu);
parent->addItem(action, name);
action->setShortcutContext(Qt::WidgetShortcut);
addAction(action);
return action;
}
QAction* Window::addHiddenAction(InputItem* parent, QAction* action, const QString& name) {
parent->addItem(action, name);
action->setShortcutContext(Qt::WidgetShortcut); action->setShortcutContext(Qt::WidgetShortcut);
addAction(action); addAction(action);
return action; return action;

View File

@ -143,9 +143,7 @@ private:
template <typename T> std::function<void()> openTView(); template <typename T> std::function<void()> openTView();
QAction* addControlledAction(QMenu* menu, QAction* action, const QString& name); QAction* addControlledAction(QMenu* menu, QAction* action, const QString& name);
QAction* addControlledAction(InputItem* parent, QAction* action, const QString& name);
QAction* addHiddenAction(QMenu* menu, QAction* action, const QString& name); QAction* addHiddenAction(QMenu* menu, QAction* action, const QString& name);
QAction* addHiddenAction(InputItem* parent, QAction* action, const QString& name);
void updateTitle(float fps = -1); void updateTitle(float fps = -1);