Once again, non-modal dialogs and main windows problem

  • I have a main application window (derived from QMainWindow) and a self-designed help browser (also derived from QMainWindow but with the main application window as its parent). Dialogs (derived from QDialog) are sometimes opened from the main application window as non-modal dialogs with QDialog::show(). Each dialog can change the help topic by passing a context string when the user presses the F1 key. (EDIT: The dialogs should behave as if they were modal, except that I want to switch focus to the help window if it is open, or open it if not already open).

    So far, everything works. But when a dialog is open, and the help window is focussed, when changing back to the main window I would like to focus the dialog instead of the main window. My problem is that I need to override the QObject::event() function and trap the appropriate event type. Have tried QEvent::ActivationChange and compared the QApplication::focusWidget() result to the this pointer; although it does focus the dialog, it also prevents the user from focussing the help window.

    My next idea is to install an event filter on all of the children of the main window and trap the FocusIn event, but maybe there is an easier way to do this? To be clear, if I do not trap any events, I can change the focus between the help window and the application window, but when returning to the main window, the dialog does not receive the focus automatically, i.e. the user has to click on it.

  • @Robert-Hairgrove

    So basically you want to prevent the user from focusing the main MainWindow as long as there is one of your Help-Dialogs active?! (Only allow switching focus between your HelpWindow and its corresponding Dialog(s))

    You could set your HelpWindow on top of your MainWindow as modal window and then open your HelpDialog from your HelpMainWindow. So the HelpMainWindow blocks your main MainWindow and you can toggle focus between HelpWindow and its Dialog.

    Just an idea. Dont know if it works for you :-)

    I think preventing the user from focusing the MainWindow by using EventFilters and custom Events / locks might be quite difficult.

  • It turned out to be very simple, once I found the right event type (QEvent::WindowActivate).

    In the main application window class (SbblMainWindow here), I have a member active_dialog_ which is set when the dialog is created and reset to NULL when the dialog is closed. All I had to do was to override the event() function like this:

    bool SbblMainWindow::event(QEvent *ev)
      if (ev->type() == QEvent::WindowActivate) {
        if (active_dialog_) {
          return true;
      // EDIT: DON'T DO THIS!!
      // return false;
      // instead:
      return QMainWindow::event(ev);

    There was no need to install an extra event filter at all. Now the non-modal dialogs behave AS IF they were modal, but I can still switch the focus between the help viewer and the dialog, which is nicely hidden by the help viewer when necessary.

    I learned from this exercise that it is not wise to rely on the QEvent::FocusIn method for detecting window activation because this event is only concerned with keyboard focus.

    Marked as SOLVED now!

Log in to reply