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)
|
||||
: QAbstractItemModel(parent)
|
||||
, m_rootMenu(nullptr)
|
||||
{
|
||||
}
|
||||
|
||||
|
@ -21,23 +22,21 @@ QVariant ShortcutController::data(const QModelIndex& index, int role) const {
|
|||
if (role != Qt::DisplayRole || !index.isValid()) {
|
||||
return QVariant();
|
||||
}
|
||||
const QModelIndex& parent = index.parent();
|
||||
if (parent.isValid()) {
|
||||
const ShortcutMenu& menu = m_menus[parent.row()];
|
||||
const ShortcutItem& item = menu.shortcuts()[index.row()];
|
||||
int row = index.row();
|
||||
const ShortcutItem* item = static_cast<const ShortcutItem*>(index.internalPointer());
|
||||
switch (index.column()) {
|
||||
case 0:
|
||||
return item.visibleName();
|
||||
return item->visibleName();
|
||||
case 1:
|
||||
return item.action()->shortcut().toString(QKeySequence::NativeText);
|
||||
if (item->action()) {
|
||||
return item->action()->shortcut().toString(QKeySequence::NativeText);
|
||||
}
|
||||
break;
|
||||
case 2:
|
||||
if (item.button() >= 0) {
|
||||
return item.button();
|
||||
if (item->button() >= 0) {
|
||||
return item->button();
|
||||
}
|
||||
return QVariant();
|
||||
}
|
||||
} else if (index.column() == 0) {
|
||||
return m_menus[index.row()].visibleName();
|
||||
break;
|
||||
}
|
||||
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 {
|
||||
if (!parent.isValid()) {
|
||||
return createIndex(row, column, -1);
|
||||
const ShortcutItem* pmenu = &m_rootMenu;
|
||||
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 {
|
||||
if (!index.isValid()) {
|
||||
if (!index.isValid() || !index.internalPointer()) {
|
||||
return QModelIndex();
|
||||
}
|
||||
if (index.internalId() == -1) {
|
||||
ShortcutItem* item = static_cast<ShortcutItem*>(index.internalPointer());
|
||||
if (!item->parent() || !item->parent()->parent()) {
|
||||
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 {
|
||||
|
@ -81,58 +82,67 @@ int ShortcutController::columnCount(const QModelIndex& index) const {
|
|||
}
|
||||
|
||||
int ShortcutController::rowCount(const QModelIndex& index) const {
|
||||
if (index.parent().isValid()) {
|
||||
return 0;
|
||||
if (!index.isValid()) {
|
||||
return m_rootMenu.items().count();
|
||||
}
|
||||
if (index.isValid()) {
|
||||
return m_menus[index.row()].shortcuts().count();
|
||||
}
|
||||
return m_menus.count();
|
||||
const ShortcutItem* item = static_cast<const ShortcutItem*>(index.internalPointer());
|
||||
return item->items().count();
|
||||
}
|
||||
|
||||
void ShortcutController::addAction(QMenu* menu, QAction* action, const QString& name) {
|
||||
ShortcutMenu* smenu = nullptr;
|
||||
int row = 0;
|
||||
for (auto iter = m_menus.end(); iter-- != m_menus.begin(); ++row) {
|
||||
if (iter->menu() == menu) {
|
||||
smenu = &(*iter);
|
||||
break;
|
||||
}
|
||||
}
|
||||
ShortcutItem* smenu = m_menuMap[menu];
|
||||
if (!smenu) {
|
||||
return;
|
||||
}
|
||||
QModelIndex parent = createIndex(row, 0, -1);
|
||||
beginInsertRows(parent, smenu->shortcuts().count(), smenu->shortcuts().count());
|
||||
ShortcutItem* pmenu = smenu->parent();
|
||||
int row = pmenu->items().indexOf(*smenu);
|
||||
QModelIndex parent = createIndex(row, 0, smenu);
|
||||
beginInsertRows(parent, smenu->items().count(), smenu->items().count());
|
||||
smenu->addAction(action, name);
|
||||
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) {
|
||||
beginInsertRows(QModelIndex(), m_menus.count(), m_menus.count());
|
||||
m_menus.append(ShortcutMenu(menu));
|
||||
void ShortcutController::addMenu(QMenu* menu, QMenu* parentMenu) {
|
||||
ShortcutItem* smenu = m_menuMap[parentMenu];
|
||||
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();
|
||||
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()) {
|
||||
return nullptr;
|
||||
}
|
||||
const QModelIndex& parent = index.parent();
|
||||
if (!parent.isValid()) {
|
||||
return static_cast<ShortcutItem*>(index.internalPointer());
|
||||
}
|
||||
|
||||
const ShortcutController::ShortcutItem* ShortcutController::itemAt(const QModelIndex& index) const {
|
||||
if (!index.isValid()) {
|
||||
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;
|
||||
}
|
||||
const ShortcutMenu& menu = m_menus[parent.row()];
|
||||
if (index.row() > menu.shortcuts().count()) {
|
||||
return nullptr;
|
||||
}
|
||||
const ShortcutItem& item = menu.shortcuts()[index.row()];
|
||||
return item.action();
|
||||
return item->action();
|
||||
}
|
||||
|
||||
void ShortcutController::updateKey(const QModelIndex& index, const QKeySequence& keySequence) {
|
||||
|
@ -143,10 +153,9 @@ void ShortcutController::updateKey(const QModelIndex& index, const QKeySequence&
|
|||
if (!parent.isValid()) {
|
||||
return;
|
||||
}
|
||||
ShortcutMenu& menu = m_menus[parent.row()];
|
||||
ShortcutItem& item = menu.shortcuts()[index.row()];
|
||||
item.action()->setShortcut(keySequence);
|
||||
emit dataChanged(createIndex(index.row(), 0, index.internalId()), createIndex(index.row(), 2, index.internalId()));
|
||||
ShortcutItem* item = itemAt(index);
|
||||
item->action()->setShortcut(keySequence);
|
||||
emit dataChanged(createIndex(index.row(), 0, index.internalPointer()), createIndex(index.row(), 2, index.internalPointer()));
|
||||
}
|
||||
|
||||
void ShortcutController::updateButton(const QModelIndex& index, int button) {
|
||||
|
@ -157,15 +166,14 @@ void ShortcutController::updateButton(const QModelIndex& index, int button) {
|
|||
if (!parent.isValid()) {
|
||||
return;
|
||||
}
|
||||
ShortcutMenu& menu = m_menus[parent.row()];
|
||||
ShortcutItem& item = menu.shortcuts()[index.row()];
|
||||
int oldButton = item.button();
|
||||
item.setButton(button);
|
||||
ShortcutItem* item = itemAt(index);
|
||||
int oldButton = item->button();
|
||||
item->setButton(button);
|
||||
if (oldButton >= 0) {
|
||||
m_buttons.take(oldButton);
|
||||
}
|
||||
m_buttons[button] = &item;
|
||||
emit dataChanged(createIndex(index.row(), 0, index.internalId()), createIndex(index.row(), 2, index.internalId()));
|
||||
m_buttons[button] = item;
|
||||
emit dataChanged(createIndex(index.row(), 0, index.internalPointer()), createIndex(index.row(), 2, index.internalPointer()));
|
||||
}
|
||||
|
||||
bool ShortcutController::eventFilter(QObject*, QEvent* event) {
|
||||
|
@ -184,24 +192,35 @@ bool ShortcutController::eventFilter(QObject*, QEvent* event) {
|
|||
return false;
|
||||
}
|
||||
|
||||
ShortcutController::ShortcutItem::ShortcutItem(QAction* action, const QString& name)
|
||||
ShortcutController::ShortcutItem::ShortcutItem(QAction* action, const QString& name, ShortcutItem* parent)
|
||||
: m_action(action)
|
||||
, m_menu(nullptr)
|
||||
, m_name(name)
|
||||
, m_button(-1)
|
||||
, m_parent(parent)
|
||||
{
|
||||
m_visibleName = action->text()
|
||||
.remove(QRegExp("&(?!&)"))
|
||||
.remove("...");
|
||||
}
|
||||
|
||||
ShortcutController::ShortcutMenu::ShortcutMenu(QMenu* menu)
|
||||
: m_menu(menu)
|
||||
ShortcutController::ShortcutItem::ShortcutItem(QMenu* menu, ShortcutItem* parent)
|
||||
: m_action(nullptr)
|
||||
, m_menu(menu)
|
||||
, m_button(-1)
|
||||
, m_parent(parent)
|
||||
{
|
||||
if (menu) {
|
||||
m_visibleName = menu->title()
|
||||
.remove(QRegExp("&(?!&)"))
|
||||
.remove("...");
|
||||
}
|
||||
}
|
||||
|
||||
void ShortcutController::ShortcutMenu::addAction(QAction* action, const QString& name) {
|
||||
m_shortcuts.append(ShortcutItem(action, name));
|
||||
void ShortcutController::ShortcutItem::addAction(QAction* action, const QString& 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 {
|
||||
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:
|
||||
ShortcutController(QObject* parent = nullptr);
|
||||
|
||||
|
@ -30,9 +63,12 @@ public:
|
|||
virtual int rowCount(const QModelIndex& parent = QModelIndex()) const override;
|
||||
|
||||
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;
|
||||
|
||||
void updateKey(const QModelIndex& index, const QKeySequence& keySequence);
|
||||
void updateButton(const QModelIndex& index, int button);
|
||||
|
||||
|
@ -40,42 +76,8 @@ protected:
|
|||
bool eventFilter(QObject*, QEvent*) override;
|
||||
|
||||
private:
|
||||
class ShortcutItem {
|
||||
public:
|
||||
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;
|
||||
ShortcutItem m_rootMenu;
|
||||
QMap<QMenu*, ShortcutItem*> m_menuMap;
|
||||
QMap<int, ShortcutItem*> m_buttons;
|
||||
};
|
||||
|
||||
|
|
|
@ -533,13 +533,14 @@ void Window::setupMenu(QMenuBar* menubar) {
|
|||
QMenu* avMenu = menubar->addMenu(tr("Audio/&Video"));
|
||||
m_shortcutController->addMenu(avMenu);
|
||||
QMenu* frameMenu = avMenu->addMenu(tr("Frame size"));
|
||||
m_shortcutController->addMenu(frameMenu, avMenu);
|
||||
for (int i = 1; i <= 6; ++i) {
|
||||
QAction* setSize = new QAction(tr("%1x").arg(QString::number(i)), avMenu);
|
||||
connect(setSize, &QAction::triggered, [this, i]() {
|
||||
showNormal();
|
||||
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");
|
||||
|
||||
|
|
Loading…
Reference in New Issue