Important: Please read the Qt Code of Conduct - https://forum.qt.io/topic/113070/qt-code-of-conduct

Possible to allow QShortcut to work with modal QDialogs ?


  • Lifetime Qt Champion

    Hi
    I was wondering if anyone knew a trick to get a true app wide global hotkey.
    The following works until modal dialog is shown.

    I understand its correct to block all events as it does - but outside
    of assigning same shortcut to all dialog/re- parent or using event filters on QApp,

    is there another way to make it work ?
    I tried not assigning parent just in case it would belong to QApp instead.

    // this = mainwindow
     QShortcut* shortcut = new QShortcut( QKeySequence(Qt::AltModifier + Qt::Key_X), this); 
      shortcut->setContext(Qt::ApplicationShortcut);
      QObject::connect(shortcut, &QShortcut::activated, [this]() {
       ....
      });
    


  • Hi @mrjj ,

    The simplest solution I can see is to re-assign parent when showing the dialog. It requires to keep all shortcuts in a list but avoids re-creating them. Hope that's not what you meant with "assigning same shortcuts to all dialog".

    //.h
    QList<QShortcut *> m_shortcuts;
    
    // MainWindow constructor
     QShortcut* shortcut = new QShortcut( QKeySequence(Qt::AltModifier + Qt::Key_Y), this);
        shortcut->setContext(Qt::ApplicationShortcut);
        QObject::connect(shortcut, &QShortcut::activated, [this]() {
            qDebug() << "Shortcut ALT + Y activated ";
        });
        m_shortcuts.append(shortcut);
    
        shortcut = new QShortcut( QKeySequence(Qt::AltModifier + Qt::Key_X), this);
        shortcut->setContext(Qt::ApplicationShortcut);
        QObject::connect(shortcut, &QShortcut::activated, []() {
            qDebug() << "Shortcut ALT + X activated ";
        });
    
        m_shortcuts.append(shortcut);
    
    void MainWindow::showModalDialog()
    {
        QDialog *dialog = new QDialog(this);
        for(QShortcut *s : m_shortcuts){
            s->setParent(dialog);
        }
    
        dialog->exec();
    
        for(QShortcut *s : m_shortcuts){
            s->setParent(this);
        }
    }
    

  • Lifetime Qt Champion

    @Gojir4
    Hi
    Sadly it was what i meant with "assigning same shortcuts to all dialog". :)
    i should have said re-parenting.

    While idea is good, its not very practical in my use case as a dialog can also pop dialog and so on
    so having to loop the m_shortcuts all places where a dialog is born is a bit cumbersome even
    i do have a makeDialog function so its somewhat under control but it would also need access to m_shortcuts list.

    I saw someone using eventfilter . i think i will go down that road if i really want it.

    Its no critical and i posted just make sure i was not missing something obvious.
    like shortcut->setIgnoreModal kinda -ish :)



  • @Gojir4 , @mrjj

    @Gojir4 May I (politely) enquire whether you have tested this actually works (I don't know)? Because e.g. https://stackoverflow.com/a/4344518/489865 comment states:

    parent must be a pointer to existing widget. One can pass QApplication::desktop() as parent. It is worth to know that modal windows will block shortcuts even with application context.

    which might imply the shortcuts never work with dialogs?

    @mrjj Be aware that this solution does not scale if, say, you have your main dialog invoke a further dialog, which my app has a lot of...



  • @mrjj said in Possible to allow QShortcut to work with modal QDialogs ?:

    so having to loop the m_shortcuts all places where a dialog is born is a bit cumbersome even
    i do have a makeDialog function so its somewhat under control but it would also need access to m_shortcuts list.

    • Make the m_shortcuts list application-global instead of parent-widget-specific, as that's what you want anyway.

    • If you have derived all your dialogs from your own QDialog-derived-class (you have already done that, haven't you? :) ), put the logic for assigning & restoring the shortcuts in the dialog class instead of requiring the caller to do it? This also solves the nested-dialogs issue.



  • @mrjj OK, sad indeed :).

    @JonB Yes I have tested it and it works. I usually indicate when I post a code which is not tested or compiled.


  • Lifetime Qt Champion

    @JonB

    Yes, i always use a extra GUI base classes so i can add my own polymorphic behavior
    if needed later. (often is)
    So i could hide the loop away in BaseDialog so to speak.
    And just update the docs to tell the other to use Base always.

    Might not be so bad as i first thought :)

    thank you both


Log in to reply