mirror of https://github.com/mgba-emu/mgba.git
Qt: Get submenus working with the shortcut editor
This commit is contained in:
parent
33c4b17941
commit
a1480e2698
|
@ -14,6 +14,7 @@ using namespace QGBA;
|
||||||
|
|
||||||
ShortcutController::ShortcutController(QObject* parent)
|
ShortcutController::ShortcutController(QObject* parent)
|
||||||
: QAbstractItemModel(parent)
|
: QAbstractItemModel(parent)
|
||||||
|
, m_rootMenu(nullptr)
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -21,23 +22,21 @@ QVariant ShortcutController::data(const QModelIndex& index, int role) const {
|
||||||
if (role != Qt::DisplayRole || !index.isValid()) {
|
if (role != Qt::DisplayRole || !index.isValid()) {
|
||||||
return QVariant();
|
return QVariant();
|
||||||
}
|
}
|
||||||
const QModelIndex& parent = index.parent();
|
int row = index.row();
|
||||||
if (parent.isValid()) {
|
const ShortcutItem* item = static_cast<const ShortcutItem*>(index.internalPointer());
|
||||||
const ShortcutMenu& menu = m_menus[parent.row()];
|
switch (index.column()) {
|
||||||
const ShortcutItem& item = menu.shortcuts()[index.row()];
|
case 0:
|
||||||
switch (index.column()) {
|
return item->visibleName();
|
||||||
case 0:
|
case 1:
|
||||||
return item.visibleName();
|
if (item->action()) {
|
||||||
case 1:
|
return item->action()->shortcut().toString(QKeySequence::NativeText);
|
||||||
return item.action()->shortcut().toString(QKeySequence::NativeText);
|
|
||||||
case 2:
|
|
||||||
if (item.button() >= 0) {
|
|
||||||
return item.button();
|
|
||||||
}
|
|
||||||
return QVariant();
|
|
||||||
}
|
}
|
||||||
} else if (index.column() == 0) {
|
break;
|
||||||
return m_menus[index.row()].visibleName();
|
case 2:
|
||||||
|
if (item->button() >= 0) {
|
||||||
|
return item->button();
|
||||||
|
}
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
return QVariant();
|
return QVariant();
|
||||||
}
|
}
|
||||||
|
@ -60,20 +59,22 @@ QVariant ShortcutController::headerData(int section, Qt::Orientation orientation
|
||||||
}
|
}
|
||||||
|
|
||||||
QModelIndex ShortcutController::index(int row, int column, const QModelIndex& parent) const {
|
QModelIndex ShortcutController::index(int row, int column, const QModelIndex& parent) const {
|
||||||
if (!parent.isValid()) {
|
const ShortcutItem* pmenu = &m_rootMenu;
|
||||||
return createIndex(row, column, -1);
|
if (parent.isValid()) {
|
||||||
|
pmenu = static_cast<ShortcutItem*>(parent.internalPointer());
|
||||||
}
|
}
|
||||||
return createIndex(row, column, parent.row());
|
return createIndex(row, column, const_cast<ShortcutItem*>(&pmenu->items()[row]));
|
||||||
}
|
}
|
||||||
|
|
||||||
QModelIndex ShortcutController::parent(const QModelIndex& index) const {
|
QModelIndex ShortcutController::parent(const QModelIndex& index) const {
|
||||||
if (!index.isValid()) {
|
if (!index.isValid() || !index.internalPointer()) {
|
||||||
return QModelIndex();
|
return QModelIndex();
|
||||||
}
|
}
|
||||||
if (index.internalId() == -1) {
|
ShortcutItem* item = static_cast<ShortcutItem*>(index.internalPointer());
|
||||||
|
if (!item->parent() || !item->parent()->parent()) {
|
||||||
return QModelIndex();
|
return QModelIndex();
|
||||||
}
|
}
|
||||||
return createIndex(index.internalId(), 0, -1);
|
return createIndex(item->parent()->parent()->items().indexOf(*item->parent()), 0, item->parent());
|
||||||
}
|
}
|
||||||
|
|
||||||
int ShortcutController::columnCount(const QModelIndex& index) const {
|
int ShortcutController::columnCount(const QModelIndex& index) const {
|
||||||
|
@ -81,58 +82,67 @@ int ShortcutController::columnCount(const QModelIndex& index) const {
|
||||||
}
|
}
|
||||||
|
|
||||||
int ShortcutController::rowCount(const QModelIndex& index) const {
|
int ShortcutController::rowCount(const QModelIndex& index) const {
|
||||||
if (index.parent().isValid()) {
|
if (!index.isValid()) {
|
||||||
return 0;
|
return m_rootMenu.items().count();
|
||||||
}
|
}
|
||||||
if (index.isValid()) {
|
const ShortcutItem* item = static_cast<const ShortcutItem*>(index.internalPointer());
|
||||||
return m_menus[index.row()].shortcuts().count();
|
return item->items().count();
|
||||||
}
|
|
||||||
return m_menus.count();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void ShortcutController::addAction(QMenu* menu, QAction* action, const QString& name) {
|
void ShortcutController::addAction(QMenu* menu, QAction* action, const QString& name) {
|
||||||
ShortcutMenu* smenu = nullptr;
|
ShortcutItem* smenu = m_menuMap[menu];
|
||||||
int row = 0;
|
|
||||||
for (auto iter = m_menus.end(); iter-- != m_menus.begin(); ++row) {
|
|
||||||
if (iter->menu() == menu) {
|
|
||||||
smenu = &(*iter);
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if (!smenu) {
|
if (!smenu) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
QModelIndex parent = createIndex(row, 0, -1);
|
ShortcutItem* pmenu = smenu->parent();
|
||||||
beginInsertRows(parent, smenu->shortcuts().count(), smenu->shortcuts().count());
|
int row = pmenu->items().indexOf(*smenu);
|
||||||
|
QModelIndex parent = createIndex(row, 0, smenu);
|
||||||
|
beginInsertRows(parent, smenu->items().count(), smenu->items().count());
|
||||||
smenu->addAction(action, name);
|
smenu->addAction(action, name);
|
||||||
endInsertRows();
|
endInsertRows();
|
||||||
emit dataChanged(createIndex(smenu->shortcuts().count() - 1, 0, row), createIndex(smenu->shortcuts().count() - 1, 2, row));
|
ShortcutItem* item = &smenu->items().last();
|
||||||
|
emit dataChanged(createIndex(smenu->items().count() - 1, 0, item), createIndex(smenu->items().count() - 1, 2, item));
|
||||||
}
|
}
|
||||||
|
|
||||||
void ShortcutController::addMenu(QMenu* menu) {
|
void ShortcutController::addMenu(QMenu* menu, QMenu* parentMenu) {
|
||||||
beginInsertRows(QModelIndex(), m_menus.count(), m_menus.count());
|
ShortcutItem* smenu = m_menuMap[parentMenu];
|
||||||
m_menus.append(ShortcutMenu(menu));
|
if (!smenu) {
|
||||||
|
smenu = &m_rootMenu;
|
||||||
|
}
|
||||||
|
QModelIndex parent;
|
||||||
|
ShortcutItem* pmenu = smenu->parent();
|
||||||
|
if (pmenu) {
|
||||||
|
int row = pmenu->items().indexOf(*smenu);
|
||||||
|
parent = createIndex(row, 0, smenu);
|
||||||
|
}
|
||||||
|
beginInsertRows(parent, smenu->items().count(), smenu->items().count());
|
||||||
|
smenu->addSubmenu(menu);
|
||||||
endInsertRows();
|
endInsertRows();
|
||||||
emit dataChanged(createIndex(m_menus.count() - 1, 0, -1), createIndex(m_menus.count() - 1, 0, -1));
|
ShortcutItem* item = &smenu->items().last();
|
||||||
|
emit dataChanged(createIndex(smenu->items().count() - 1, 0, item), createIndex(smenu->items().count() - 1, 2, item));
|
||||||
|
m_menuMap[menu] = item;
|
||||||
}
|
}
|
||||||
|
|
||||||
const QAction* ShortcutController::actionAt(const QModelIndex& index) const {
|
ShortcutController::ShortcutItem* ShortcutController::itemAt(const QModelIndex& index) {
|
||||||
if (!index.isValid()) {
|
if (!index.isValid()) {
|
||||||
return nullptr;
|
return nullptr;
|
||||||
}
|
}
|
||||||
const QModelIndex& parent = index.parent();
|
return static_cast<ShortcutItem*>(index.internalPointer());
|
||||||
if (!parent.isValid()) {
|
}
|
||||||
|
|
||||||
|
const ShortcutController::ShortcutItem* ShortcutController::itemAt(const QModelIndex& index) const {
|
||||||
|
if (!index.isValid()) {
|
||||||
return nullptr;
|
return nullptr;
|
||||||
}
|
}
|
||||||
if (parent.row() > m_menus.count()) {
|
return static_cast<const ShortcutItem*>(index.internalPointer());
|
||||||
|
}
|
||||||
|
|
||||||
|
const QAction* ShortcutController::actionAt(const QModelIndex& index) const {
|
||||||
|
const ShortcutItem* item = itemAt(index);
|
||||||
|
if (!item) {
|
||||||
return nullptr;
|
return nullptr;
|
||||||
}
|
}
|
||||||
const ShortcutMenu& menu = m_menus[parent.row()];
|
return item->action();
|
||||||
if (index.row() > menu.shortcuts().count()) {
|
|
||||||
return nullptr;
|
|
||||||
}
|
|
||||||
const ShortcutItem& item = menu.shortcuts()[index.row()];
|
|
||||||
return item.action();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void ShortcutController::updateKey(const QModelIndex& index, const QKeySequence& keySequence) {
|
void ShortcutController::updateKey(const QModelIndex& index, const QKeySequence& keySequence) {
|
||||||
|
@ -143,10 +153,9 @@ void ShortcutController::updateKey(const QModelIndex& index, const QKeySequence&
|
||||||
if (!parent.isValid()) {
|
if (!parent.isValid()) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
ShortcutMenu& menu = m_menus[parent.row()];
|
ShortcutItem* item = itemAt(index);
|
||||||
ShortcutItem& item = menu.shortcuts()[index.row()];
|
item->action()->setShortcut(keySequence);
|
||||||
item.action()->setShortcut(keySequence);
|
emit dataChanged(createIndex(index.row(), 0, index.internalPointer()), createIndex(index.row(), 2, index.internalPointer()));
|
||||||
emit dataChanged(createIndex(index.row(), 0, index.internalId()), createIndex(index.row(), 2, index.internalId()));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void ShortcutController::updateButton(const QModelIndex& index, int button) {
|
void ShortcutController::updateButton(const QModelIndex& index, int button) {
|
||||||
|
@ -157,15 +166,14 @@ void ShortcutController::updateButton(const QModelIndex& index, int button) {
|
||||||
if (!parent.isValid()) {
|
if (!parent.isValid()) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
ShortcutMenu& menu = m_menus[parent.row()];
|
ShortcutItem* item = itemAt(index);
|
||||||
ShortcutItem& item = menu.shortcuts()[index.row()];
|
int oldButton = item->button();
|
||||||
int oldButton = item.button();
|
item->setButton(button);
|
||||||
item.setButton(button);
|
|
||||||
if (oldButton >= 0) {
|
if (oldButton >= 0) {
|
||||||
m_buttons.take(oldButton);
|
m_buttons.take(oldButton);
|
||||||
}
|
}
|
||||||
m_buttons[button] = &item;
|
m_buttons[button] = item;
|
||||||
emit dataChanged(createIndex(index.row(), 0, index.internalId()), createIndex(index.row(), 2, index.internalId()));
|
emit dataChanged(createIndex(index.row(), 0, index.internalPointer()), createIndex(index.row(), 2, index.internalPointer()));
|
||||||
}
|
}
|
||||||
|
|
||||||
bool ShortcutController::eventFilter(QObject*, QEvent* event) {
|
bool ShortcutController::eventFilter(QObject*, QEvent* event) {
|
||||||
|
@ -184,24 +192,35 @@ bool ShortcutController::eventFilter(QObject*, QEvent* event) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
ShortcutController::ShortcutItem::ShortcutItem(QAction* action, const QString& name)
|
ShortcutController::ShortcutItem::ShortcutItem(QAction* action, const QString& name, ShortcutItem* parent)
|
||||||
: m_action(action)
|
: m_action(action)
|
||||||
|
, m_menu(nullptr)
|
||||||
, m_name(name)
|
, m_name(name)
|
||||||
, m_button(-1)
|
, m_button(-1)
|
||||||
|
, m_parent(parent)
|
||||||
{
|
{
|
||||||
m_visibleName = action->text()
|
m_visibleName = action->text()
|
||||||
.remove(QRegExp("&(?!&)"))
|
.remove(QRegExp("&(?!&)"))
|
||||||
.remove("...");
|
.remove("...");
|
||||||
}
|
}
|
||||||
|
|
||||||
ShortcutController::ShortcutMenu::ShortcutMenu(QMenu* menu)
|
ShortcutController::ShortcutItem::ShortcutItem(QMenu* menu, ShortcutItem* parent)
|
||||||
: m_menu(menu)
|
: m_action(nullptr)
|
||||||
|
, m_menu(menu)
|
||||||
|
, m_button(-1)
|
||||||
|
, m_parent(parent)
|
||||||
{
|
{
|
||||||
m_visibleName = menu->title()
|
if (menu) {
|
||||||
.remove(QRegExp("&(?!&)"))
|
m_visibleName = menu->title()
|
||||||
.remove("...");
|
.remove(QRegExp("&(?!&)"))
|
||||||
|
.remove("...");
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void ShortcutController::ShortcutMenu::addAction(QAction* action, const QString& name) {
|
void ShortcutController::ShortcutItem::addAction(QAction* action, const QString& name) {
|
||||||
m_shortcuts.append(ShortcutItem(action, name));
|
m_items.append(ShortcutItem(action, name, this));
|
||||||
|
}
|
||||||
|
|
||||||
|
void ShortcutController::ShortcutItem::addSubmenu(QMenu* menu) {
|
||||||
|
m_items.append(ShortcutItem(menu, this));
|
||||||
}
|
}
|
||||||
|
|
|
@ -17,6 +17,39 @@ namespace QGBA {
|
||||||
class ShortcutController : public QAbstractItemModel {
|
class ShortcutController : public QAbstractItemModel {
|
||||||
Q_OBJECT
|
Q_OBJECT
|
||||||
|
|
||||||
|
private:
|
||||||
|
class ShortcutItem {
|
||||||
|
public:
|
||||||
|
ShortcutItem(QAction* action, const QString& name, ShortcutItem* parent = nullptr);
|
||||||
|
ShortcutItem(QMenu* action, ShortcutItem* parent = nullptr);
|
||||||
|
|
||||||
|
QAction* action() { return m_action; }
|
||||||
|
const QAction* action() const { return m_action; }
|
||||||
|
QMenu* menu() { return m_menu; }
|
||||||
|
const QMenu* menu() const { return m_menu; }
|
||||||
|
const QString& visibleName() const { return m_visibleName; }
|
||||||
|
const QString& name() const { return m_name; }
|
||||||
|
QList<ShortcutItem>& items() { return m_items; }
|
||||||
|
const QList<ShortcutItem>& items() const { return m_items; }
|
||||||
|
ShortcutItem* parent() { return m_parent; }
|
||||||
|
const ShortcutItem* parent() const { return m_parent; }
|
||||||
|
void addAction(QAction* action, const QString& name);
|
||||||
|
void addSubmenu(QMenu* menu);
|
||||||
|
int button() const { return m_button; }
|
||||||
|
void setButton(int button) { m_button = button; }
|
||||||
|
|
||||||
|
bool operator==(const ShortcutItem& other) const { return m_menu == other.m_menu && m_action == other.m_action; }
|
||||||
|
|
||||||
|
private:
|
||||||
|
QAction* m_action;
|
||||||
|
QMenu* m_menu;
|
||||||
|
QString m_name;
|
||||||
|
QString m_visibleName;
|
||||||
|
int m_button;
|
||||||
|
QList<ShortcutItem> m_items;
|
||||||
|
ShortcutItem* m_parent;
|
||||||
|
};
|
||||||
|
|
||||||
public:
|
public:
|
||||||
ShortcutController(QObject* parent = nullptr);
|
ShortcutController(QObject* parent = nullptr);
|
||||||
|
|
||||||
|
@ -30,9 +63,12 @@ public:
|
||||||
virtual int rowCount(const QModelIndex& parent = QModelIndex()) const override;
|
virtual int rowCount(const QModelIndex& parent = QModelIndex()) const override;
|
||||||
|
|
||||||
void addAction(QMenu* menu, QAction* action, const QString& name);
|
void addAction(QMenu* menu, QAction* action, const QString& name);
|
||||||
void addMenu(QMenu* menu);
|
void addMenu(QMenu* menu, QMenu* parent = nullptr);
|
||||||
|
|
||||||
|
ShortcutItem* itemAt(const QModelIndex& index);
|
||||||
|
const ShortcutItem* itemAt(const QModelIndex& index) const;
|
||||||
const QAction* actionAt(const QModelIndex& index) const;
|
const QAction* actionAt(const QModelIndex& index) const;
|
||||||
|
|
||||||
void updateKey(const QModelIndex& index, const QKeySequence& keySequence);
|
void updateKey(const QModelIndex& index, const QKeySequence& keySequence);
|
||||||
void updateButton(const QModelIndex& index, int button);
|
void updateButton(const QModelIndex& index, int button);
|
||||||
|
|
||||||
|
@ -40,42 +76,8 @@ protected:
|
||||||
bool eventFilter(QObject*, QEvent*) override;
|
bool eventFilter(QObject*, QEvent*) override;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
class ShortcutItem {
|
ShortcutItem m_rootMenu;
|
||||||
public:
|
QMap<QMenu*, ShortcutItem*> m_menuMap;
|
||||||
ShortcutItem(QAction* action, const QString& name);
|
|
||||||
|
|
||||||
QAction* action() { return m_action; }
|
|
||||||
const QAction* action() const { return m_action; }
|
|
||||||
const QString& visibleName() const { return m_visibleName; }
|
|
||||||
const QString& name() const { return m_name; }
|
|
||||||
int button() const { return m_button; }
|
|
||||||
void setButton(int button) { m_button = button; }
|
|
||||||
|
|
||||||
private:
|
|
||||||
QAction* m_action;
|
|
||||||
QString m_name;
|
|
||||||
QString m_visibleName;
|
|
||||||
int m_button;
|
|
||||||
};
|
|
||||||
|
|
||||||
class ShortcutMenu {
|
|
||||||
public:
|
|
||||||
ShortcutMenu(QMenu* action);
|
|
||||||
|
|
||||||
QMenu* menu() { return m_menu; }
|
|
||||||
const QMenu* menu() const { return m_menu; }
|
|
||||||
const QString& visibleName() const { return m_visibleName; }
|
|
||||||
QList<ShortcutItem>& shortcuts() { return m_shortcuts; }
|
|
||||||
const QList<ShortcutItem>& shortcuts() const { return m_shortcuts; }
|
|
||||||
void addAction(QAction* action, const QString& name);
|
|
||||||
|
|
||||||
private:
|
|
||||||
QMenu* m_menu;
|
|
||||||
QString m_visibleName;
|
|
||||||
QList<ShortcutItem> m_shortcuts;
|
|
||||||
};
|
|
||||||
|
|
||||||
QList<ShortcutMenu> m_menus;
|
|
||||||
QMap<int, ShortcutItem*> m_buttons;
|
QMap<int, ShortcutItem*> m_buttons;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
@ -533,13 +533,14 @@ void Window::setupMenu(QMenuBar* menubar) {
|
||||||
QMenu* avMenu = menubar->addMenu(tr("Audio/&Video"));
|
QMenu* avMenu = menubar->addMenu(tr("Audio/&Video"));
|
||||||
m_shortcutController->addMenu(avMenu);
|
m_shortcutController->addMenu(avMenu);
|
||||||
QMenu* frameMenu = avMenu->addMenu(tr("Frame size"));
|
QMenu* frameMenu = avMenu->addMenu(tr("Frame size"));
|
||||||
|
m_shortcutController->addMenu(frameMenu, avMenu);
|
||||||
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);
|
||||||
connect(setSize, &QAction::triggered, [this, i]() {
|
connect(setSize, &QAction::triggered, [this, i]() {
|
||||||
showNormal();
|
showNormal();
|
||||||
resizeFrame(VIDEO_HORIZONTAL_PIXELS * i, VIDEO_VERTICAL_PIXELS * i);
|
resizeFrame(VIDEO_HORIZONTAL_PIXELS * i, VIDEO_VERTICAL_PIXELS * i);
|
||||||
});
|
});
|
||||||
frameMenu->addAction(setSize);
|
addControlledAction(frameMenu, setSize, tr("frame%1x").arg(QString::number(i)));
|
||||||
}
|
}
|
||||||
addControlledAction(frameMenu, frameMenu->addAction(tr("Fullscreen"), this, SLOT(toggleFullScreen()), QKeySequence("Ctrl+F")), "fullscreen");
|
addControlledAction(frameMenu, frameMenu->addAction(tr("Fullscreen"), this, SLOT(toggleFullScreen()), QKeySequence("Ctrl+F")), "fullscreen");
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue