QT - QAction::eventFilter: Ambiguous shortcut overload
c++, qt
Solution
I've had similar problems: 2 different widgets had the same shortcut for an action (different action between the widgets). As long as only one of the widgets was visible in the application, everything worked. As soon as both were visible, I got this "ambiguous shortcut overload" message.
The solution was: both action's contexts have to be set correctly to Qt::WidgetWithChildrenShortcut, then it worked fine - just according to current focus.
If only one action has the correct context, the one with the default context got triggered and the message was displayed.
If both actions had no context set (default), the Action created last was triggered and the message displayed.
So if you add an Action with a Shortcut anywhere, remember to think about the correct context and setting it, be restrictive!
Problem
Searching here and other placed like qtcentre I've seen this problem has come up but can't seem to get it working. I've got a MainWindow widget with a QSplitter which contains two Pane widgets (subclassed from QFrame). Each Pane has a menubar with identical associated QActions/Shortcuts. I've tried all combinations of ShortcutContexts with setShortcutContext(). WindowShortcut and ApplicationShortcut contexts give the expected "Ambiguous shortcut overload". While WidgetShortcut and WidgetWithChildrenShortcut both do nothing. If I activate the menus manually they of course work fine. I've also tried forcing focus on the parent widget with an overloaded enterEvent(). Any ideas? thanks. main.h ``` #include <QMainWindow> #include <QFrame> QT_BEGIN_NAMESPACE class QAction; class QMenu; class QHBoxLayout; class QSplitter; class QWidget; QT_END_NAMESPACE class Pane: public QFrame { Q_OBJECT public: Pane(QWidget* parent = 0); protected: void enterEvent(QEvent *event); void leaveEvent(QEvent *event); private: void createMenus(); QMenuBar * m_menuBar; private Q_SLOTS: void split(); }; class MainWindow : public QMainWindow { Q_OBJECT public: MainWindow(); private: void createActions(); void createMenus(); void setupUi(QMainWindow *MainWindow); QMenu *fileMenu; QAction *exitAct; QWidget *centralwidget; QHBoxLayout *horizontalLayout; QSplitter *splitter; QFrame *frame; QFrame *frame_2; }; ``` main.cpp ``` #include <iostream> #include <QApplication> #include <QMainWindow> #include <QSplitter> #include <QFrame> #include <QMenuBar> #include <QBoxLayout> #include "main.h" Pane::Pane(QWidget* parent) : QFrame(parent) { setFrameShape(QFrame::StyledPanel); setFrameShadow(QFrame::Raised); QVBoxLayout *layout = new QVBoxLayout; QFrame::setLayout(layout); m_menuBar = new QMenuBar; QWidget *m_widget = new QWidget; layout->addWidget(m_menuBar); layout->addWidget(m_widget); layout->setContentsMargins(2, 2, 2, 2); show(); createMenus(); } void Pane::enterEvent(QEvent *event) { std::cout << "enter" << std::endl; setFocus(); setStyleSheet("QFrame { border: 1px solid rgb(127, 127, 0); }"); if (focusWidget()) std::cout << "focuswidget = " << focusWidget()->objectName().toUtf8().constData() << std::endl; } void Pane::leaveEvent(QEvent *event) { std::cout << "leave" << std::endl; clearFocus(); setStyleSheet("QFrame { border: 1px solid rgb(64, 64, 64); }"); } void Pane::split() { std::cout << "split pane" << std::endl; } void Pane::createMenus() { QMenu *paneMenu = m_menuBar->addMenu(tr("&Pane")); QAction *paneSplitAct = new QAction(tr("Split"), this); paneSplitAct->setShortcut(Qt::Key_S); paneSplitAct->setShortcutContext(Qt::WidgetWithChildrenShortcut); paneSplitAct->setStatusTip(tr("Split Pane")); connect(paneSplitAct, SIGNAL(triggered()), this, SLOT(split())); paneMenu->addAction(paneSplitAct); } MainWindow::MainWindow() { setupUi(this); createActions(); createMenus(); } void MainWindow::createActions() { exitAct = new QAction(tr("E&xit"), this); exitAct->setShortcuts(QKeySequence::Quit); exitAct->setStatusTip(tr("Exit the application")); connect(exitAct, SIGNAL(triggered()), this, SLOT(close())); } void MainWindow::createMenus() { fileMenu = menuBar()->addMenu(tr("&File")); fileMenu->addAction(exitAct); } void MainWindow::setupUi(QMainWindow *MainWindow) { if (MainWindow->objectName().isEmpty()) MainWindow->setObjectName(QString::fromUtf8("MainWindow")); MainWindow->resize(800, 600); centralwidget = new QWidget(MainWindow); centralwidget->setObjectName(QString::fromUtf8("centralwidget")); horizontalLayout = new QHBoxLayout(centralwidget); horizontalLayout->setObjectName(QString::fromUtf8("horizontalLayout")); splitter = new QSplitter(centralwidget); splitter->setObjectName(QString::fromUtf8("splitter")); splitter->setOrientation(Qt::Horizontal); frame = new Pane(splitter); frame->setObjectName(QString::fromUtf8("frame")); splitter->addWidget(frame); frame_2 = new Pane(splitter); frame_2->setObjectName(QString::fromUtf8("frame_2")); splitter->addWidget(frame_2); horizontalLayout->addWidget(splitter); MainWindow->setCentralWidget(centralwidget); QMetaObject::connectSlotsByName(MainWindow); } int main(int argc, char *argv[]) { QApplication app(argc, argv); app.setOrganizationName("Trolltech"); app.setApplicationName("Application Example"); MainWindow mainWin; mainWin.show(); return app.exec(); } ``` main.pro ``` HEADERS = main.h SOURCES = main.cpp CONFIG += no_keywords ``` UPDATE: Adding an `addAction(paneSplitAct)` call at the end of `Pane::createMenus()` in conjunction with using `Qt::WidgetShortcut` context seems to give me what I want. From what I understand of the docs this is supposed to create a context menu in the widget. I don't appear to be getting one (right mouse click I assume) but that's ok since I don't want one. The `eventEvent()` and `leaveEvent()` overrides are still needed to set the focus correctly.