5

Extraneous Information: I am attempting to build an application using Qt. This application features a QMdiArea and a child-window. My child-window will have a menu which can be integrated into the QMdiArea or segregated and attached to the child itself. Though, this is a bit more detail than needed...

Problem: I would like my child-widget to have a menu with a shortcut, "CTRL+W." But, because I am using a QMdiArea, the shortcut is already used causing:

QAction::eventFilter: Ambiguous shortcut overload: Ctrl+W

How can I get rid of this shortcut and claim it within my child widget instead?

Update: Here is what I've tried with no luck:

class MDI : public QMdiArea
{
    Q_OBJECT
    private:
    bool event(QEvent *tEvent)
    {
        if (tEvent->type() == QEvent::KeyPress)
        {
            QKeyEvent* ke = static_cast<QKeyEvent*>(tEvent);
            if (ke->key()== Qt::Key_W && ke->modifiers() & Qt::ControlModifier)
            emit KeyCW();
            return true;
        }
        return QMdiArea::event(tEvent);
    }
public:
signals:
    void KeyCW();
};

This works if I do something as simple as change Qt::Key_W to Qt::Key_L. The key-combo is received and event is thrown. With W, it just never happens. I've also tried moving event to QMainWindow as well as an eventFilter in the subwindow to QMdiArea. It seems that it is a little overly complicated to do something as simple as remove default key-handlers from within QMdiArea.

ymoreau
  • 3,402
  • 1
  • 22
  • 60
Serodis
  • 2,092
  • 4
  • 25
  • 34

5 Answers5

3

You can disable this shortcut like this:

for( QAction *action : subWindow->systemMenu()->actions() ) {
    if( action->shortcut() == QKeySequence( QKeySequence::Close ) ) {
        action->setShortcut( QKeySequence() );
        break;
    }
}
LoOny
  • 31
  • 2
2

You could get rid of the pre-defined close action of the QMdiSubWindow altogether by using Qt::CustomizeWindowHint as additional flag when adding the subwindow.

QMdiSubWindow *subWindow2 = mdiArea.addSubWindow(internalWidget2, 
                                                 Qt::Widget | Qt::CustomizeWindowHint | 
                                                 Qt::WindowMinMaxButtonsHint);
SingerOfTheFall
  • 29,228
  • 8
  • 68
  • 105
ivanhoe
  • 21
  • 2
0

Subclass QMdiArea and reimplement keyPressEvent(). That should work.

  void keyPressEvent(QKeyEvent* event){

    if(event->key() == Qt::Key_W and event->modifiers() & Qt::ControlModifier){
      // handle it
    }else{
      return QMdiArea::keyPressEvent(event);
    }
  }

You could also use event filters. I don't enough about your class hierarchy, but I hope you get the idea.

bool CustomMdiArea::eventFilter(QObject *object, QEvent *event){
     if(object == yourChildWindow && event->type() == QEvent::KeyPress) {
         QKeyEvent *keyEvent = static_cast<QKeyEvent *>(event);
         if(keyEvent->key() == Qt::Key_W and keyEvent->modifiers() & Qt::ControlModifier) {
             //handle it
             return true;
         }else{
             return false;
         }
     }
     return false;
 }
Arlen
  • 6,641
  • 4
  • 29
  • 61
  • So is there no way to disable the shortcut that QMdiArea created? Basically meaning that if I want use of the short-cut key I have to use signal/slot connections between the two? – Serodis Dec 22 '11 at 13:30
  • Also, if that is absolutely the only way, is there any harm in leaving the ambiguous shortcut? IE: Installing the shortcut onto the widgets menu? I really don't want to sacrifice the "Ctrl+W" shortcut reminder in the menu-bar, since that is the best way to tell a user a shortcuts function. – Serodis Dec 22 '11 at 13:46
  • To alter `QMdiArea`'s default behaviour in regards to a specific key event is to subclass it and reimplement `keyPressEvent()`. Another way is to use event filters. – Arlen Dec 22 '11 at 21:57
  • This problem seems to get deeper and deeper, I am completely confused. I thought about what you wrote, and in order to get that working, I would have to subclass QMdiArea and emit a signal to QMainWindow which would handle it from there. Well, I decided to try it, and... no luck. I can capture other keys, but still, even through the event member of QMdiArea, I never receive the key-combo CTRL+W. I am updating my post to show some code... – Serodis Dec 23 '11 at 00:36
0

From what I can tell, what I am looking for is not possible short of writing my own MDIArea.

The shortcut is set in QMdiSubWindowPrivate::createSystemMenu() during the construction of a QMdiSubWindow, I doubt that you can remove it without having to patch Qt libs.

Hopefully at some point someone will disprove this or QT will make changes. Meanwhile, it looks like we will all need to stay away from these pre-assigned shortcuts.

Serodis
  • 2,092
  • 4
  • 25
  • 34
0

I was able to work around this by setting the shortcut context for my close action. By setting it to Qt::WidgetShortcut, I no longer get the ambiguous shortcut overload. Here is how I'm setting up my close action now:

  closeAction = new QAction(tr("&Close"), this);
  closeAction->setShortcut(Qt::CTRL|Qt::Key_W);
  closeAction->setShortcutContext(Qt::WidgetShortcut);
  connect(closeAction, SIGNAL(triggered()), mdiArea, SLOT(closeActiveSubWindow()));
SingerOfTheFall
  • 29,228
  • 8
  • 68
  • 105
Dennis Munsie
  • 1,211
  • 12
  • 24