Uploaded image for project: 'Qt'
  1. Qt
  2. QTBUG-86874

Menu item relocation sometimes fails with a global menu bar

    XMLWordPrintable

Details

    • Bug
    • Resolution: Unresolved
    • P2: Important
    • None
    • 5.14.2
    • GUI: Menus
    • None
    • macOS 10.15.6
    • macOS

    Description

      I’m on Qt 5.14.2, with a Qt Widgets based app that runs on both macOS and Linux.  I’m having trouble getting my menu bar to work.

      So that things work smoothly on Linux platforms where there is a menu bar in each main window, I have a menu bar in the .ui file that contains my main window.  That design works fine, on both platforms.  Where things have gotten bumpy is when I decided to try to make it so my app stays running even when the last document window is closed, as is fairly typical for macOS apps; this definitely makes sense for my app, where it would be common to close one window and then create a new window to continue working.  To make this happen, I call setQuitOnLastWindowClosed(false), at startup in main(), after creating QApplication and before parsing the command line and creating the initial main window.  This, in itself, seems to work fine; now the app doesn’t quit when the last window is closed.  I do this on macOS only, and the remainder of this question applies solely to macOS; on Linux my app quits when the last window is closed, and there is no problem.  (The bug may reproduce on Linux if you call setQuitOnLastWindowClosed(false), though; I haven't tried.)

      Since the menu bar is owned by the main windows in my app, when the last window is closed the menu bar reverts to a very minimal default state; all of the other menus disappear.  I want to have a full menu bar (perhaps minus a couple of main-window-specific menus) in that mode, so I’ve been trying to get a “global menu bar” working, as described in the QMenuBar doc (by making a QMenuBar object that has no parent).  I’ve tried this a couple of different ways, but I can’t get it to work completely.  The problem is always that some of the menu items that need to be moved into the application menu on macOS don’t move – they disappear.  Specifically, this happens to the About, Preferences, and Quit menu items.  The menu bar appears fine whenever a main window is open; the menu bar that gets created by that .ui file seems to work perfectly.  But the “global” menu bar that I create myself is missing those items.

      I’ve tried creating the global menu bar either when the last window closes (i.e., on demand), or at startup before the first main window is created; the behavior is the same either way.  I’ve tried creating the Quit menu item the easy way, with:

      fileMenu->addAction("Quit SLiMgui", this, &QtSLiMAppDelegate::dispatch_quit, Qt::CTRL + Qt::Key_Q);

      or the long way, creating the QAction and then setting its shortcut, connecting it, and finally adding it to fileMenu; the behavior is the same either way.  I’ve tried poking the menu bar after I’ve finished creating it, by calling toNSMenu(); makes no difference.  I’ve tried setting the menu role for the Quit item to QuitRole, before adding it to fileMenu, or leaving it as the default; makes no difference.

      In all cases, I can output the structure of the menu bar immediately after I create it and I see (showing just the File menu, where the Quit item gets added by my code):

      "File"
       "About SLiMgui"
       "Preferences..."
       ""
      ...
       ""
       "Quit SLiMgui"

      So the items in question are present, in the File menu where I put them.  But then when I click on the menu bar in my app, these menu items – about, preferences, and quit – are not in the File menu, nor are they in the application menu; they’re just gone.  They have been filtered out, somewhere down the road.

      Since this global menu bar stuff is macOS-specific code anyway (according to platform UI guidelines), I would happily just add the menu items to the application menu myself, avoiding Qt’s relocation logic.  However, as far as I can tell the QMenuBar object that I create doesn’t have an application menu in it; that seems to be private.  So Qt’s migration code isn’t doing the right thing, and I can find no way to just do the right thing on my own.

       

      Addendum: I asked about this on Qt-Interest, and someone suggested that the menu item relocation might in some way depend upon there being a main window still in existence, even if hidden.  So I tried commenting out my call to setAttribute(Qt::WA_DeleteOnClose) for my main windows, so they close but don't dealloc; and that did, indeed, make the menu item relocation work!  I then see the global menu bar I constructed, with the items correctly placed into the application menu.  HOWEVER, this is not a viable workaround, because it appears to trigger a different bug in Qt that causes a crash on quit (in code unrelated to menu stuff); I'm about to file another bug on that.  So, although having a hidden main window seems to work around this bug, I can't use it in practice.  I tried creating a minimal hidden main window as a "thunk", on app startup, just to facilitate correct menubar behavior without triggering the crash on quit; but for whatever reason, my "thunk" window didn't fix the menubar bug.

      So the upshot is: I am unable to get my Qt app to follow standard platform UI guidelines, because of this bug on one side and a crash on the other side.  Unfortunate.  If somebody gets into this bug enough to understand what's going on under the hood, and there's a workaround for it that is safer than the one I found, please comment here.

      Attachments

        No reviews matched the request. Check your Options in the drop-down menu of this sections header.

        Activity

          People

            qt.team.quick.subscriptions Qt Quick and Widgets Team
            bhaller Ben Haller
            Votes:
            0 Vote for this issue
            Watchers:
            1 Start watching this issue

            Dates

              Created:
              Updated:

              Gerrit Reviews

                There are no open Gerrit changes