Qt: Get submenus working with the shortcut editor

This commit is contained in:
Jeffrey Pfau 2015-01-04 15:46:35 -08:00
parent 33c4b17941
commit a1480e2698
3 changed files with 131 additions and 109 deletions

View File

@ -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()];
switch (index.column()) {
case 0:
return item.visibleName();
case 1:
return item.action()->shortcut().toString(QKeySequence::NativeText);
case 2:
if (item.button() >= 0) {
return item.button();
}
return QVariant();
int row = index.row();
const ShortcutItem* item = static_cast<const ShortcutItem*>(index.internalPointer());
switch (index.column()) {
case 0:
return item->visibleName();
case 1:
if (item->action()) {
return item->action()->shortcut().toString(QKeySequence::NativeText);
}
} else if (index.column() == 0) {
return m_menus[index.row()].visibleName();
break;
case 2:
if (item->button() >= 0) {
return item->button();
}
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)
{
m_visibleName = menu->title()
.remove(QRegExp("&(?!&)"))
.remove("...");
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));
}

View File

@ -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;
};

View File

@ -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");