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

Qt/Cocoa - Menu items are disabled when showing a top-level menu which was initially hidden

    XMLWordPrintable

Details

    • Bug
    • Resolution: Done
    • P2: Important
    • 4.8.4
    • 4.8.2
    • None
    • Qt/Cocoa 4.8.2 on OS X 10.7.4
    • d412f11cea4dc336c684aafcd8979d5cec751cb5

    Description

      If a top-level menu item is hidden (via menu->menuAction()->setVisible(false)) when its parent window is initially shown, the items in the menu remain disabled if the top-level menu item is later shown.

      If the item is visible when the item is initially shown, the problem does not occur.

      #include <QtGui/QApplication>
      #include <QtGui/QPushButton>
      #include <QtGui/QMenuBar>
      #include <QtGui/QMenu>
      #include <QtGui/QAction>
      
      int main(int argc, char** argv)
      {
      	QApplication app(argc, argv);
      
      	QWidget* widget = new QWidget;
      	widget->resize(300,200);
      
      	QMenuBar* menu = new QMenuBar(widget);
      
      	// Populate the menu bar with a menu which is initially hidden.
      	QMenu* testMenu = new QMenu("Test");
      	menu->addMenu(testMenu);
      	testMenu->menuAction()->setVisible(false);
      
      	QAction* testAction = new QAction("Test Action", testMenu);
      	testMenu->addAction(testAction);
      
      	// Add a button which shows the menu when pressed
      	QPushButton* button = new QPushButton("Show Menu", widget);
      	button->setCheckable(true);
      	QObject::connect(button, SIGNAL(toggled(bool)), testMenu->menuAction(), SLOT(setVisible(bool)));
      
      	// When the widget is shown, click the button to show the menu.  The 'Test Action' item
      	// will be disabled, though it should be enabled.
      
      	// Un-comment this line to show the menu when the window is initially shown.
      	// The problem will not occur in this case.
      
      	//button->setChecked(true);
      
      	widget->show();
      
      	return app.exec();
      }
      
      

      [NSMenuItem isEnabled] returns NO for the Test menu in this case, even though Qt sends it a [NSMenuItem setEnabled:YES] request. I believe this is because the top-level menu is using Cocoa's automatic menu item validation facility, though Qt turns this off using [NSMenuItem setAutoenablesItems:NO] for all other menus it creates itself.

      Cocoa calls [QCocoaMenuLoader validateMenuItem:] for the item, which returns [menuItem isEnabled], which is NO, even though the action is enabled.

      This patch fixes the issue, although I making a possibly unsafe assumption here that this method is only called for menu items which represent Qt actions:

      --- a/src/gui/kernel/qcocoamenuloader_mac.mm
      +++ b/src/gui/kernel/qcocoamenuloader_mac.mm
      @@ -268,7 +268,11 @@ QT_USE_NAMESPACE
               || [menuItem action] == @selector(unhideAllApplications:)) {
               return [NSApp validateMenuItem:menuItem];
           } else {
      -        return [menuItem isEnabled];
      +        if (QAction* action = reinterpret_cast<QAction*>([menuItem tag])) {
      +            return action->isEnabled();
      +        } else {
      +            return [menuItem isEnabled];
      +        }
           }
       }
      

      Attachments

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

        Activity

          People

            pamatila Pasi Matilainen (Inactive)
            robertknight Robert Knight
            Votes:
            1 Vote for this issue
            Watchers:
            4 Start watching this issue

            Dates

              Created:
              Updated:
              Resolved:

              Gerrit Reviews

                There are no open Gerrit changes