Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

QT - QAction::eventFilter: Ambiguous shortcut overload

Tags:

c++

qt

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.

like image 832
user1360310 Avatar asked Apr 27 '12 06:04

user1360310


1 Answers

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!

like image 89
St0fF Avatar answered Sep 22 '22 06:09

St0fF