summaryrefslogtreecommitdiffstats
path: root/src/widgets/widgets
diff options
context:
space:
mode:
authorMorten Sorvig <morten.sorvig@nokia.com>2011-09-06 14:10:50 +0200
committerMorten Johan Sørvig <morten.sorvig@nokia.com>2011-09-07 11:00:36 +0200
commitcee63e2c17c8e83a4366741da0cbd5fc852e5835 (patch)
tree75ccc2afe762a51984d6651d6ff6eb875b73cad6 /src/widgets/widgets
parente2be53891fe218c9a1a63c2d385d149d2b1f982f (diff)
Cocoa: QMenu refactor.
This change prepares for enabling native menus on OS X. Move code from src/widgets to cocoa: - qcocoaapplicaiton - qcocoaapplicaitondelegate - qcocoamenuloader - qcocoamenu - qmenu_mac - misc helpers to qcocoahelpers Create a QNSApplication and QCocoaApplicationDelegate at application startup. New Lighthouse API: - class QPlatformMenu - class QPlatformMenuBar - QPlatformIntegration::createPlatformMenu() - QPlatformIntegration::createPlatformMenuBar() Platforms that wants a native menu integration subclasses QPlatformMenu[|Bar] and implements the create function. The default implementation returns 0, which causes QMenu to use the standard Qt menus. This API is based on the current native menu abstraction that Mac, Wince and S60 uses in Qt 4. The main difference is that the platform classes are proper standalone classes and not #ifdeffed into QMenuPrivate. Change-Id: I3da41f80b0ae903a476937908b1f9b88014b7954 Reviewed-on: http://codereview.qt.nokia.com/4068 Reviewed-by: Morten Johan Sørvig <morten.sorvig@nokia.com>
Diffstat (limited to 'src/widgets/widgets')
-rw-r--r--src/widgets/widgets/qcocoamenu_mac.mm268
-rw-r--r--src/widgets/widgets/qcocoamenu_mac_p.h80
-rw-r--r--src/widgets/widgets/qmenu.cpp32
-rw-r--r--src/widgets/widgets/qmenu.h18
-rw-r--r--src/widgets/widgets/qmenu_mac.mm1284
-rw-r--r--src/widgets/widgets/qmenu_p.h75
-rw-r--r--src/widgets/widgets/qmenubar.cpp67
-rw-r--r--src/widgets/widgets/qmenubar.h7
-rw-r--r--src/widgets/widgets/qmenubar_p.h38
-rw-r--r--src/widgets/widgets/widgets.pri6
10 files changed, 57 insertions, 1818 deletions
diff --git a/src/widgets/widgets/qcocoamenu_mac.mm b/src/widgets/widgets/qcocoamenu_mac.mm
deleted file mode 100644
index 36e356cd4c..0000000000
--- a/src/widgets/widgets/qcocoamenu_mac.mm
+++ /dev/null
@@ -1,268 +0,0 @@
-/****************************************************************************
-**
-** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
-** All rights reserved.
-** Contact: Nokia Corporation (qt-info@nokia.com)
-**
-** This file is part of the QtGui module of the Qt Toolkit.
-**
-** $QT_BEGIN_LICENSE:LGPL$
-** GNU Lesser General Public License Usage
-** This file may be used under the terms of the GNU Lesser General Public
-** License version 2.1 as published by the Free Software Foundation and
-** appearing in the file LICENSE.LGPL included in the packaging of this
-** file. Please review the following information to ensure the GNU Lesser
-** General Public License version 2.1 requirements will be met:
-** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
-**
-** In addition, as a special exception, Nokia gives you certain additional
-** rights. These rights are described in the Nokia Qt LGPL Exception
-** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
-**
-** GNU General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU General
-** Public License version 3.0 as published by the Free Software Foundation
-** and appearing in the file LICENSE.GPL included in the packaging of this
-** file. Please review the following information to ensure the GNU General
-** Public License version 3.0 requirements will be met:
-** http://www.gnu.org/copyleft/gpl.html.
-**
-** Other Usage
-** Alternatively, this file may be used in accordance with the terms and
-** conditions contained in a signed written agreement between you and Nokia.
-**
-**
-**
-**
-**
-** $QT_END_LICENSE$
-**
-****************************************************************************/
-
-#include "qmacdefines_mac.h"
-#include "qapplication.h"
-#include "qvarlengtharray.h"
-#import <private/qcocoamenu_mac_p.h>
-#import <private/qcocoamenuloader_mac_p.h>
-#import <private/qcocoaapplication_mac_p.h>
-#include <private/qt_cocoa_helpers_mac_p.h>
-#include <private/qapplication_p.h>
-#include <private/qaction_p.h>
-#include <private/qcocoaapplication_mac_p.h>
-
-#include <QtWidgets/QMenu>
-
-QT_FORWARD_DECLARE_CLASS(QAction)
-QT_FORWARD_DECLARE_CLASS(QWidget)
-QT_FORWARD_DECLARE_CLASS(QApplication)
-QT_FORWARD_DECLARE_CLASS(QCoreApplication)
-QT_FORWARD_DECLARE_CLASS(QApplicationPrivate)
-QT_FORWARD_DECLARE_CLASS(QKeyEvent)
-QT_FORWARD_DECLARE_CLASS(QEvent)
-
-QT_BEGIN_NAMESPACE
-extern bool qt_sendSpontaneousEvent(QObject*, QEvent*); //qapplication.cpp
-extern void qt_mac_menu_collapseSeparators(NSMenu *menu, bool collapse);
-void qt_mac_clear_status_text(QAction *action);
-QT_END_NAMESPACE
-
-QT_USE_NAMESPACE
-
-@implementation QT_MANGLE_NAMESPACE(QCocoaMenu)
-
-- (id)initWithQMenu:(QMenu*)menu
-{
- self = [super init];
- if (self) {
- qmenu = menu;
- previousAction = 0;
- [self setAutoenablesItems:NO];
- [self setDelegate:self];
- }
- return self;
-}
-
-- (void)menu:(NSMenu*)menu willHighlightItem:(NSMenuItem*)item
-{
- Q_UNUSED(menu);
-
- if (!item) {
- if (previousAction) {
- qt_mac_clear_status_text(previousAction);
- previousAction = 0;
- }
- return;
- }
-
- if (QAction *action = reinterpret_cast<QAction *>([item tag])) {
- QMenu *qtmenu = static_cast<QT_MANGLE_NAMESPACE(QCocoaMenu) *>(menu)->qmenu;
- previousAction = action;
- action->activate(QAction::Hover);
- qt_mac_menu_emit_hovered(qtmenu, action);
- action->showStatusText(0); // 0 widget -> action's parent
- }
-}
-
-- (void)menuWillOpen:(NSMenu*)menu
-{
- while (QWidget *popup
- = QApplication::activePopupWidget())
- popup->close();
- QMenu *qtmenu = static_cast<QT_MANGLE_NAMESPACE(QCocoaMenu) *>(menu)->qmenu;
- qt_mac_emit_menuSignals(qtmenu, true);
- qt_mac_menu_collapseSeparators(menu, qtmenu->separatorsCollapsible());
-}
-
-- (void)menuDidClose:(NSMenu*)menu
-{
- qt_mac_emit_menuSignals(((QT_MANGLE_NAMESPACE(QCocoaMenu) *)menu)->qmenu, false);
- if (previousAction) {
- qt_mac_clear_status_text(previousAction);
- previousAction = 0;
- }
-}
-
-- (BOOL)hasShortcut:(NSMenu *)menu forKey:(NSString *)key forModifiers:(NSUInteger)modifier
- whichItem:(NSMenuItem**)outItem
-{
- for (NSMenuItem *item in [menu itemArray]) {
- if (![item isEnabled] || [item isHidden] || [item isSeparatorItem])
- continue;
- if ([item hasSubmenu]) {
- if ([self hasShortcut:[item submenu]
- forKey:key
- forModifiers:modifier whichItem:outItem]) {
- if (outItem)
- *outItem = item;
- return YES;
- }
- }
- NSString *menuKey = [item keyEquivalent];
- if (menuKey && NSOrderedSame == [menuKey compare:key]
- && (modifier == [item keyEquivalentModifierMask])) {
- if (outItem)
- *outItem = item;
- return YES;
- }
- }
- if (outItem)
- *outItem = 0;
- return NO;
-}
-
-NSString *qt_mac_removePrivateUnicode(NSString* string)
-{
- int len = [string length];
- if (len) {
- QVarLengthArray <unichar, 10> characters(len);
- bool changed = false;
- for (int i = 0; i<len; i++) {
- characters[i] = [string characterAtIndex:i];
- // check if they belong to key codes in private unicode range
- // currently we need to handle only the NSDeleteFunctionKey
- if (characters[i] == NSDeleteFunctionKey) {
- characters[i] = NSDeleteCharacter;
- changed = true;
- }
- }
- if (changed)
- return [NSString stringWithCharacters:characters.data() length:len];
- }
- return string;
-}
-
-- (BOOL)menuHasKeyEquivalent:(NSMenu *)menu forEvent:(NSEvent *)event target:(id *)target action:(SEL *)action
-{
- // Check if the menu actually has a keysequence defined for this key event.
- // If it does, then we will first send the key sequence to the QWidget that has focus
- // since (in Qt's eyes) it needs to a chance at the key event first. If the widget
- // accepts the key event, we then return YES, but set the target and action to be nil,
- // which means that the action should not be triggered, and instead dispatch the event ourselves.
- // In every other case we return NO, which means that Cocoa can do as it pleases
- // (i.e., fire the menu action).
- NSMenuItem *whichItem;
- // Change the private unicode keys to the ones used in setting the "Key Equivalents"
- NSString *characters = qt_mac_removePrivateUnicode([event characters]);
- if ([self hasShortcut:menu
- forKey:characters
- // Interested only in Shift, Cmd, Ctrl & Alt Keys, so ignoring masks like, Caps lock, Num Lock ...
- forModifiers:([event modifierFlags] & (NSShiftKeyMask | NSControlKeyMask | NSCommandKeyMask | NSAlternateKeyMask))
- whichItem:&whichItem]) {
- QWidget *widget = 0;
- QAction *qaction = 0;
- if (whichItem && [whichItem tag]) {
- qaction = reinterpret_cast<QAction *>([whichItem tag]);
- }
- if (qApp->activePopupWidget())
- widget = (qApp->activePopupWidget()->focusWidget() ?
- qApp->activePopupWidget()->focusWidget() : qApp->activePopupWidget());
- else if (QApplicationPrivate::focus_widget)
- widget = QApplicationPrivate::focus_widget;
- // If we could not find any receivers, pass it to the active window
- if (!widget)
- widget = qApp->activeWindow();
- if (qaction && widget) {
- int key = qaction->shortcut();
- QKeyEvent accel_ev(QEvent::ShortcutOverride, (key & (~Qt::KeyboardModifierMask)),
- Qt::KeyboardModifiers(key & Qt::KeyboardModifierMask));
- accel_ev.ignore();
- qt_sendSpontaneousEvent(widget, &accel_ev);
- if (accel_ev.isAccepted()) {
- qWarning("Unimplemented: qt_dispatchKeyEvent");
-#if 0
- qt_dispatchKeyEvent(event, widget);
-#endif
- *target = nil;
- *action = nil;
- return YES;
- }
- }
- }
- return NO;
-}
-
-- (NSInteger)indexOfItemWithTarget:(id)anObject andAction:(SEL)actionSelector
-{
- NSInteger index = [super indexOfItemWithTarget:anObject andAction:actionSelector];
- static SEL selForOFCP = NSSelectorFromString(@"orderFrontCharacterPalette:");
- if (index == -1 && selForOFCP == actionSelector) {
- // Check if the 'orderFrontCharacterPalette' SEL exists for QCocoaMenuLoader object
- QT_MANGLE_NAMESPACE(QCocoaMenuLoader) *loader = [NSApp QT_MANGLE_NAMESPACE(qt_qcocoamenuLoader)];
- return [super indexOfItemWithTarget:loader andAction:actionSelector];
- }
- return index;
-}
-
-@end
-
-QT_BEGIN_NAMESPACE
-extern int qt_mac_menus_open_count; // qmenu_mac.mm
-
-void qt_mac_emit_menuSignals(QMenu *menu, bool show)
-{
- if (!menu)
- return;
- int delta;
- if (show) {
- emit menu->aboutToShow();
- delta = 1;
- } else {
- emit menu->aboutToHide();
- delta = -1;
- }
- qt_mac_menus_open_count += delta;
-}
-
-void qt_mac_clear_status_text(QAction *action)
-{
- action->d_func()->showStatusText(0, QString());
-}
-
-void qt_mac_menu_emit_hovered(QMenu *menu, QAction *action)
-{
- emit menu->hovered(action);
-}
-
-
-QT_END_NAMESPACE
-
diff --git a/src/widgets/widgets/qcocoamenu_mac_p.h b/src/widgets/widgets/qcocoamenu_mac_p.h
deleted file mode 100644
index 392060c90a..0000000000
--- a/src/widgets/widgets/qcocoamenu_mac_p.h
+++ /dev/null
@@ -1,80 +0,0 @@
-/****************************************************************************
-**
-** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
-** All rights reserved.
-** Contact: Nokia Corporation (qt-info@nokia.com)
-**
-** This file is part of the QtGui module of the Qt Toolkit.
-**
-** $QT_BEGIN_LICENSE:LGPL$
-** GNU Lesser General Public License Usage
-** This file may be used under the terms of the GNU Lesser General Public
-** License version 2.1 as published by the Free Software Foundation and
-** appearing in the file LICENSE.LGPL included in the packaging of this
-** file. Please review the following information to ensure the GNU Lesser
-** General Public License version 2.1 requirements will be met:
-** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
-**
-** In addition, as a special exception, Nokia gives you certain additional
-** rights. These rights are described in the Nokia Qt LGPL Exception
-** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
-**
-** GNU General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU General
-** Public License version 3.0 as published by the Free Software Foundation
-** and appearing in the file LICENSE.GPL included in the packaging of this
-** file. Please review the following information to ensure the GNU General
-** Public License version 3.0 requirements will be met:
-** http://www.gnu.org/copyleft/gpl.html.
-**
-** Other Usage
-** Alternatively, this file may be used in accordance with the terms and
-** conditions contained in a signed written agreement between you and Nokia.
-**
-**
-**
-**
-**
-** $QT_END_LICENSE$
-**
-****************************************************************************/
-
-//
-// W A R N I N G
-// -------------
-//
-// This file is not part of the Qt API. It exists purely as an
-// implementation detail. This header file may change from version to
-// version without notice, or even be removed.
-//
-// We mean it.
-//
-
-#include "qmacdefines_mac.h"
-#import <Cocoa/Cocoa.h>
-
-QT_FORWARD_DECLARE_CLASS(QMenu)
-QT_FORWARD_DECLARE_CLASS(QAction)
-
-#if MAC_OS_X_VERSION_MAX_ALLOWED <= MAC_OS_X_VERSION_10_5
-
-@protocol NSMenuDelegate <NSObject>
-- (void)menu:(NSMenu*)menu willHighlightItem:(NSMenuItem*)item;
-- (void)menuWillOpen:(NSMenu*)menu;
-- (void)menuDidClose:(NSMenu*)menu;
-- (BOOL)hasShortcut:(NSMenu *)menu forKey:(NSString *)key forModifiers:(NSUInteger)modifier
- whichItem:(NSMenuItem**)outItem;
-@end
-
-#endif
-
-@interface QT_MANGLE_NAMESPACE(QCocoaMenu) : NSMenu <NSMenuDelegate>
-{
- QMenu *qmenu;
- QAction *previousAction;
-}
-- (id)initWithQMenu:(QMenu*)menu;
-- (BOOL)menuHasKeyEquivalent:(NSMenu *)menu forEvent:(NSEvent *)event target:(id *)target action:(SEL *)action;
-- (NSInteger)indexOfItemWithTarget:(id)anObject andAction:(SEL)actionSelector;
-@end
-
diff --git a/src/widgets/widgets/qmenu.cpp b/src/widgets/widgets/qmenu.cpp
index bcf7c574f0..cfcf0dc9ed 100644
--- a/src/widgets/widgets/qmenu.cpp
+++ b/src/widgets/widgets/qmenu.cpp
@@ -164,6 +164,8 @@ void QMenuPrivate::init()
scroll->scrollFlags = QMenuPrivate::QMenuScroller::ScrollNone;
}
+ platformMenu = QGuiApplicationPrivate::platformIntegration()->createPlatformMenu(q);
+
#ifdef QT_SOFTKEYS_ENABLED
selectAction = QSoftKeyManager::createKeyedAction(QSoftKeyManager::SelectSoftKey, Qt::Key_Select, q);
cancelAction = QSoftKeyManager::createKeyedAction(QSoftKeyManager::CancelSoftKey, Qt::Key_Back, q);
@@ -2367,10 +2369,8 @@ void QMenu::changeEvent(QEvent *e)
if (d->tornPopup) // torn-off menu
d->tornPopup->setEnabled(isEnabled());
d->menuAction->setEnabled(isEnabled());
-#ifdef Q_OS_MAC
- if (d->mac_menu)
- d->setMacMenuEnabled(isEnabled());
-#endif
+ if (d->platformMenu)
+ d->platformMenu->setMenuEnabled(isEnabled());
}
QWidget::changeEvent(e);
}
@@ -2923,16 +2923,14 @@ void QMenu::actionEvent(QActionEvent *e)
d->widgetItems.remove(e->action());
}
-#ifdef Q_OS_MAC
- if (d->mac_menu) {
+ if (d->platformMenu) {
if (e->type() == QEvent::ActionAdded)
- d->mac_menu->addAction(e->action(), d->mac_menu->findAction(e->before()), d);
+ d->platformMenu->addAction(e->action(), e->before());
else if (e->type() == QEvent::ActionRemoved)
- d->mac_menu->removeAction(e->action());
+ d->platformMenu->removeAction(e->action());
else if (e->type() == QEvent::ActionChanged)
- d->mac_menu->syncAction(e->action());
+ d->platformMenu->syncAction(e->action());
}
-#endif
#if defined(Q_WS_WINCE) && !defined(QT_NO_MENUBAR)
if (!d->wce_menu)
@@ -3093,6 +3091,14 @@ void QMenu::setNoReplayFor(QWidget *noReplayFor)
#endif
}
+/*!\internal
+*/
+QPlatformMenu *QMenu::platformMenu()
+{
+
+ return d_func()->platformMenu;
+}
+
/*!
\property QMenu::separatorsCollapsible
\since 4.2
@@ -3123,10 +3129,8 @@ void QMenu::setSeparatorsCollapsible(bool collapse)
d->updateActionRects();
update();
}
-#ifdef Q_OS_MAC
- if (d->mac_menu)
- d->syncSeparatorsCollapsible(collapse);
-#endif
+ if (d->platformMenu)
+ d->platformMenu->syncSeparatorsCollapsible(collapse);
}
#ifdef QT3_SUPPORT
diff --git a/src/widgets/widgets/qmenu.h b/src/widgets/widgets/qmenu.h
index 84a1f1ef14..8d7e281fd4 100644
--- a/src/widgets/widgets/qmenu.h
+++ b/src/widgets/widgets/qmenu.h
@@ -46,10 +46,7 @@
#include <QtCore/qstring.h>
#include <QtWidgets/qicon.h>
#include <QtWidgets/qaction.h>
-#ifdef Q_OS_MAC
-#include "QtWidgets/qmacdefines_mac.h"
-#endif
-
+#include <QtWidgets/qplatformmenu_qpa.h>
#ifdef QT3_SUPPORT
#include <QtGui/qpixmap.h>
@@ -145,9 +142,7 @@ public:
void setIcon(const QIcon &icon);
void setNoReplayFor(QWidget *widget);
-#ifdef Q_OS_MAC
- OSMenuRef macMenu(OSMenuRef merge=0);
-#endif
+ QPlatformMenu *platformMenu();
#ifdef Q_WS_WINCE
HMENU wceMenu();
@@ -418,15 +413,8 @@ private:
friend class QComboBox;
friend class QAction;
friend class QToolButtonPrivate;
-
-#ifdef Q_OS_MAC
- friend void qt_mac_trayicon_activate_action(QMenu *, QAction *action);
- friend bool qt_mac_watchingAboutToShow(QMenu *);
- friend OSStatus qt_mac_menu_event(EventHandlerCallRef, EventRef, void *);
- friend bool qt_mac_activate_action(OSMenuRef, uint, QAction::ActionEvent, bool);
- friend void qt_mac_emit_menuSignals(QMenu *, bool);
+ friend void qt_mac_emit_menuSignals(QMenu *menu, bool show);
friend void qt_mac_menu_emit_hovered(QMenu *menu, QAction *action);
-#endif
};
#endif // QT_NO_MENU
diff --git a/src/widgets/widgets/qmenu_mac.mm b/src/widgets/widgets/qmenu_mac.mm
deleted file mode 100644
index 5fb364ec1b..0000000000
--- a/src/widgets/widgets/qmenu_mac.mm
+++ /dev/null
@@ -1,1284 +0,0 @@
-/****************************************************************************
-**
-** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
-** All rights reserved.
-** Contact: Nokia Corporation (qt-info@nokia.com)
-**
-** This file is part of the QtGui module of the Qt Toolkit.
-**
-** $QT_BEGIN_LICENSE:LGPL$
-** GNU Lesser General Public License Usage
-** This file may be used under the terms of the GNU Lesser General Public
-** License version 2.1 as published by the Free Software Foundation and
-** appearing in the file LICENSE.LGPL included in the packaging of this
-** file. Please review the following information to ensure the GNU Lesser
-** General Public License version 2.1 requirements will be met:
-** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
-**
-** In addition, as a special exception, Nokia gives you certain additional
-** rights. These rights are described in the Nokia Qt LGPL Exception
-** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
-**
-** GNU General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU General
-** Public License version 3.0 as published by the Free Software Foundation
-** and appearing in the file LICENSE.GPL included in the packaging of this
-** file. Please review the following information to ensure the GNU General
-** Public License version 3.0 requirements will be met:
-** http://www.gnu.org/copyleft/gpl.html.
-**
-** Other Usage
-** Alternatively, this file may be used in accordance with the terms and
-** conditions contained in a signed written agreement between you and Nokia.
-**
-**
-**
-**
-**
-** $QT_END_LICENSE$
-**
-****************************************************************************/
-
-#include <Cocoa/Cocoa.h>
-
-#include "qmenu.h"
-#include "qhash.h"
-#include <qdebug.h>
-#include "qapplication.h"
-#include <private/qt_mac_p.h>
-#include "qregexp.h"
-#include "qmainwindow.h"
-#include "qdockwidget.h"
-#include "qtoolbar.h"
-#include "qevent.h"
-#include "qstyle.h"
-#include "qwidgetaction.h"
-#include "qmacnativewidget_mac.h"
-
-#include <private/qapplication_p.h>
-#include <private/qcocoaapplication_mac_p.h>
-#include <private/qmenu_p.h>
-#include <private/qmenubar_p.h>
-#include <private/qcocoamenuloader_mac_p.h>
-#include <private/qcocoamenu_mac_p.h>
-#include <private/qt_cocoa_helpers_mac_p.h>
-
-QT_BEGIN_NAMESPACE
-
-/*****************************************************************************
- QMenu debug facilities
- *****************************************************************************/
-
-/*****************************************************************************
- QMenu globals
- *****************************************************************************/
-bool qt_mac_no_menubar_merge = false;
-bool qt_mac_quit_menu_item_enabled = true;
-int qt_mac_menus_open_count = 0;
-
-static OSMenuRef qt_mac_create_menu(QWidget *w);
-
-#ifndef QT_MAC_USE_COCOA
-static uint qt_mac_menu_static_cmd_id = 'QT00';
-const UInt32 kMenuCreatorQt = 'cute';
-enum {
- kMenuPropertyQAction = 'QAcT',
- kMenuPropertyQWidget = 'QWId',
- kMenuPropertyCausedQWidget = 'QCAU',
- kMenuPropertyMergeMenu = 'QApP',
- kMenuPropertyMergeList = 'QAmL',
- kMenuPropertyWidgetActionWidget = 'QWid',
- kMenuPropertyWidgetMenu = 'QWMe',
-
- kHICommandAboutQt = 'AOQT',
- kHICommandCustomMerge = 'AQt0'
-};
-#endif
-
-static struct {
- QPointer<QMenuBar> qmenubar;
- bool modal;
-} qt_mac_current_menubar = { 0, false };
-
-
-
-
-/*****************************************************************************
- Externals
- *****************************************************************************/
-extern OSViewRef qt_mac_hiview_for(const QWidget *w); //qwidget_mac.cpp
-extern HIViewRef qt_mac_hiview_for(OSWindowRef w); //qwidget_mac.cpp
-extern IconRef qt_mac_create_iconref(const QPixmap &px); //qpixmap_mac.cpp
-extern QWidget * mac_keyboard_grabber; //qwidget_mac.cpp
-extern bool qt_sendSpontaneousEvent(QObject*, QEvent*); //qapplication_xxx.cpp
-RgnHandle qt_mac_get_rgn(); //qregion_mac.cpp
-void qt_mac_dispose_rgn(RgnHandle r); //qregion_mac.cpp
-
-/*****************************************************************************
- QMenu utility functions
- *****************************************************************************/
-bool qt_mac_watchingAboutToShow(QMenu *menu)
-{
- return menu; /* && menu->receivers(SIGNAL(aboutToShow()));*/
-}
-
-static int qt_mac_CountMenuItems(OSMenuRef menu)
-{
- if (menu) {
- return [menu numberOfItems];
- }
- return 0;
-}
-
-void qt_mac_menu_collapseSeparators(NSMenu * theMenu, bool collapse)
-{
- QMacCocoaAutoReleasePool pool;
- OSMenuRef menu = static_cast<OSMenuRef>(theMenu);
- if (collapse) {
- bool previousIsSeparator = true; // setting to true kills all the separators placed at the top.
- NSMenuItem *previousItem = nil;
-
- NSArray *itemArray = [menu itemArray];
- for (unsigned int i = 0; i < [itemArray count]; ++i) {
- NSMenuItem *item = reinterpret_cast<NSMenuItem *>([itemArray objectAtIndex:i]);
- if ([item isSeparatorItem]) {
- [item setHidden:previousIsSeparator];
- }
-
- if (![item isHidden]) {
- previousItem = item;
- previousIsSeparator = ([previousItem isSeparatorItem]);
- }
- }
-
- // We now need to check the final item since we don't want any separators at the end of the list.
- if (previousItem && previousIsSeparator)
- [previousItem setHidden:YES];
- } else {
- NSArray *itemArray = [menu itemArray];
- for (unsigned int i = 0; i < [itemArray count]; ++i) {
- NSMenuItem *item = reinterpret_cast<NSMenuItem *>([itemArray objectAtIndex:i]);
- if (QAction *action = reinterpret_cast<QAction *>([item tag]))
- [item setHidden:!action->isVisible()];
- }
- }
-}
-
-#ifndef QT_NO_TRANSLATION
-static const char *application_menu_strings[] = {
- QT_TRANSLATE_NOOP("MAC_APPLICATION_MENU","Services"),
- QT_TRANSLATE_NOOP("MAC_APPLICATION_MENU","Hide %1"),
- QT_TRANSLATE_NOOP("MAC_APPLICATION_MENU","Hide Others"),
- QT_TRANSLATE_NOOP("MAC_APPLICATION_MENU","Show All"),
- QT_TRANSLATE_NOOP("MAC_APPLICATION_MENU","Preferences..."),
- QT_TRANSLATE_NOOP("MAC_APPLICATION_MENU","Quit %1"),
- QT_TRANSLATE_NOOP("MAC_APPLICATION_MENU","About %1")
- };
-
-QString qt_mac_applicationmenu_string(int type)
-{
- QString menuString = QString::fromLatin1(application_menu_strings[type]);
- QString translated = qApp->translate("QMenuBar", application_menu_strings[type]);
- if (translated != menuString)
- return translated;
- else
- return qApp->translate("MAC_APPLICATION_MENU",
- application_menu_strings[type]);
-}
-#endif
-
-
-static quint32 constructModifierMask(quint32 accel_key)
-{
- quint32 ret = 0;
- const bool dontSwap = qApp->testAttribute(Qt::AA_MacDontSwapCtrlAndMeta);
-#ifndef QT_MAC_USE_COCOA
- if ((accel_key & Qt::ALT) == Qt::ALT)
- ret |= kMenuOptionModifier;
- if ((accel_key & Qt::SHIFT) == Qt::SHIFT)
- ret |= kMenuShiftModifier;
- if (dontSwap) {
- if ((accel_key & Qt::META) != Qt::META)
- ret |= kMenuNoCommandModifier;
- if ((accel_key & Qt::CTRL) == Qt::CTRL)
- ret |= kMenuControlModifier;
- } else {
- if ((accel_key & Qt::CTRL) != Qt::CTRL)
- ret |= kMenuNoCommandModifier;
- if ((accel_key & Qt::META) == Qt::META)
- ret |= kMenuControlModifier;
- }
-#else
- if ((accel_key & Qt::CTRL) == Qt::CTRL)
- ret |= (dontSwap ? NSControlKeyMask : NSCommandKeyMask);
- if ((accel_key & Qt::META) == Qt::META)
- ret |= (dontSwap ? NSCommandKeyMask : NSControlKeyMask);
- if ((accel_key & Qt::ALT) == Qt::ALT)
- ret |= NSAlternateKeyMask;
- if ((accel_key & Qt::SHIFT) == Qt::SHIFT)
- ret |= NSShiftKeyMask;
-#endif
- return ret;
-}
-
-static void cancelAllMenuTracking()
-{
- QMacCocoaAutoReleasePool pool;
- NSMenu *mainMenu = [NSApp mainMenu];
- [mainMenu cancelTracking];
- for (NSMenuItem *item in [mainMenu itemArray]) {
- if ([item submenu]) {
- [[item submenu] cancelTracking];
- }
- }
-}
-
-static bool actualMenuItemVisibility(const QMenuBarPrivate::QMacMenuBarPrivate *mbp,
- const QMacMenuAction *action)
-{
- bool visible = action->action->isVisible();
- if (visible && action->action->text() == QString(QChar(0x14)))
- return false;
- if (visible && action->action->menu() && !action->action->menu()->actions().isEmpty() &&
- !qt_mac_CountMenuItems(action->action->menu()->macMenu(mbp->apple_menu)) &&
- !qt_mac_watchingAboutToShow(action->action->menu())) {
- return false;
- }
- return visible;
-}
-
-static inline void syncNSMenuItemVisiblity(NSMenuItem *menuItem, bool actionVisibility)
-{
- [menuItem setHidden:NO];
- [menuItem setHidden:YES];
- [menuItem setHidden:!actionVisibility];
-}
-
-static inline void syncNSMenuItemEnabled(NSMenuItem *menuItem, bool enabled)
-{
- [menuItem setEnabled:NO];
- [menuItem setEnabled:YES];
- [menuItem setEnabled:enabled];
-}
-
-static inline void syncMenuBarItemsVisiblity(const QMenuBarPrivate::QMacMenuBarPrivate *mac_menubar)
-{
- const QList<QMacMenuAction *> &menubarActions = mac_menubar->actionItems;
- for (int i = 0; i < menubarActions.size(); ++i) {
- const QMacMenuAction *action = menubarActions.at(i);
- syncNSMenuItemVisiblity(action->menuItem, actualMenuItemVisibility(mac_menubar, action));
- }
-}
-
-static inline QT_MANGLE_NAMESPACE(QCocoaMenuLoader) *getMenuLoader()
-{
- return [NSApp QT_MANGLE_NAMESPACE(qt_qcocoamenuLoader)];
-}
-
-static NSMenuItem *createNSMenuItem(const QString &title)
-{
- NSMenuItem *item = [[NSMenuItem alloc]
- initWithTitle:qt_mac_QStringToNSString(title)
- action:@selector(qtDispatcherToQAction:) keyEquivalent:@""];
- [item setTarget:nil];
- return item;
-}
-
-// helper that recurses into a menu structure and en/dis-ables them
-void qt_mac_set_modal_state_helper_recursive(OSMenuRef menu, OSMenuRef merge, bool on)
-{
- bool modalWindowOnScreen = qApp->activeModalWidget() != 0;
- for (NSMenuItem *item in [menu itemArray]) {
- OSMenuRef submenu = [item submenu];
- if (submenu != merge) {
- if (submenu)
- qt_mac_set_modal_state_helper_recursive(submenu, merge, on);
- if (!on) {
- // The item should follow what the QAction has.
- if ([item tag]) {
- QAction *action = reinterpret_cast<QAction *>([item tag]);
- syncNSMenuItemEnabled(item, action->isEnabled());
- } else {
- syncNSMenuItemEnabled(item, YES);
- }
- // We sneak in some extra code here to handle a menu problem:
- // If there is no window on screen, we cannot set 'nil' as
- // menu item target, because then cocoa will disable the item
- // (guess it assumes that there will be no first responder to
- // catch the trigger anyway?) OTOH, If we have a modal window,
- // then setting the menu loader as target will make cocoa not
- // deliver the trigger because the loader is then seen as modally
- // shaddowed). So either way there are shortcomings. Instead, we
- // decide the target as late as possible:
- [item setTarget:modalWindowOnScreen ? nil : getMenuLoader()];
- } else {
- syncNSMenuItemEnabled(item, NO);
- }
- }
- }
-}
-
-//toggling of modal state
-static void qt_mac_set_modal_state(OSMenuRef menu, bool on)
-{
- OSMenuRef merge = QMenuPrivate::mergeMenuHash.value(menu);
- qt_mac_set_modal_state_helper_recursive(menu, merge, on);
- // I'm ignoring the special items now, since they should get handled via a syncAction()
-}
-
-bool qt_mac_menubar_is_open()
-{
- return qt_mac_menus_open_count > 0;
-}
-
-QMacMenuAction::~QMacMenuAction()
-{
- [menu release];
- // Update the menu item if this action still owns it. For some items
- // (like 'Quit') ownership will be transferred between all menu bars...
- if (action && action.data() == reinterpret_cast<QAction *>([menuItem tag])) {
- QAction::MenuRole role = action->menuRole();
- // Check if the item is owned by Qt, and should be hidden to keep it from causing
- // problems. Do it for everything but the quit menu item since that should always
- // be visible.
- if (role > QAction::ApplicationSpecificRole && role < QAction::QuitRole) {
- [menuItem setHidden:YES];
- } else if (role == QAction::TextHeuristicRole
- && menuItem != [getMenuLoader() quitMenuItem]) {
- [menuItem setHidden:YES];
- }
- [menuItem setTag:nil];
- }
- [menuItem release];
-}
-
-static NSMenuItem *qt_mac_menu_merge_action(OSMenuRef merge, QMacMenuAction *action)
-{
- if (qt_mac_no_menubar_merge || action->action->menu() || action->action->isSeparator()
- || action->action->menuRole() == QAction::NoRole)
- return 0;
-
- QString t = qt_mac_removeMnemonics(action->action->text().toLower());
- int st = t.lastIndexOf(QLatin1Char('\t'));
- if (st != -1)
- t.remove(st, t.length()-st);
- t.replace(QRegExp(QString::fromLatin1("\\.*$")), QLatin1String("")); //no ellipses
- //now the fun part
- NSMenuItem *ret = 0;
- QT_MANGLE_NAMESPACE(QCocoaMenuLoader) *loader = getMenuLoader();
-
- switch (action->action->menuRole()) {
- case QAction::NoRole:
- ret = 0;
- break;
- case QAction::ApplicationSpecificRole:
- ret = [loader appSpecificMenuItem];
- break;
- case QAction::AboutRole:
- ret = [loader aboutMenuItem];
- break;
- case QAction::AboutQtRole:
- ret = [loader aboutQtMenuItem];
- break;
- case QAction::QuitRole:
- ret = [loader quitMenuItem];
- break;
- case QAction::PreferencesRole:
- ret = [loader preferencesMenuItem];
- break;
- case QAction::TextHeuristicRole: {
- QString aboutString = QMenuBar::tr("About").toLower();
- if (t.startsWith(aboutString) || t.endsWith(aboutString)) {
- if (t.indexOf(QRegExp(QString::fromLatin1("qt$"), Qt::CaseInsensitive)) == -1) {
- ret = [loader aboutMenuItem];
- } else {
- ret = [loader aboutQtMenuItem];
- }
- } else if (t.startsWith(QMenuBar::tr("Config").toLower())
- || t.startsWith(QMenuBar::tr("Preference").toLower())
- || t.startsWith(QMenuBar::tr("Options").toLower())
- || t.startsWith(QMenuBar::tr("Setting").toLower())
- || t.startsWith(QMenuBar::tr("Setup").toLower())) {
- ret = [loader preferencesMenuItem];
- } else if (t.startsWith(QMenuBar::tr("Quit").toLower())
- || t.startsWith(QMenuBar::tr("Exit").toLower())) {
- ret = [loader quitMenuItem];
- }
- }
- break;
- }
-
- if (QMenuMergeList *list = QMenuPrivate::mergeMenuItemsHash.value(merge)) {
- for(int i = 0; i < list->size(); ++i) {
- const QMenuMergeItem &item = list->at(i);
- if (item.menuItem == ret && item.action)
- return 0;
- }
- }
-
- return ret;
-}
-
-static QString qt_mac_menu_merge_text(QMacMenuAction *action)
-{
- QString ret;
- extern QString qt_mac_applicationmenu_string(int type);
- QT_MANGLE_NAMESPACE(QCocoaMenuLoader) *loader = getMenuLoader();
- if (action->action->menuRole() == QAction::ApplicationSpecificRole)
- ret = action->action->text();
- else if (action->menuItem == [loader aboutMenuItem]) {
- ret = qt_mac_applicationmenu_string(6).arg(qAppName());
- } else if (action->menuItem == [loader aboutQtMenuItem]) {
- if (action->action->text() == QString("About Qt"))
- ret = QMenuBar::tr("About Qt");
- else
- ret = action->action->text();
- } else if (action->menuItem == [loader preferencesMenuItem]) {
- ret = qt_mac_applicationmenu_string(4);
- } else if (action->menuItem == [loader quitMenuItem]) {
- ret = qt_mac_applicationmenu_string(5).arg(qAppName());
- }
- return ret;
-}
-
-static QKeySequence qt_mac_menu_merge_accel(QMacMenuAction *action)
-{
- QKeySequence ret;
- QT_MANGLE_NAMESPACE(QCocoaMenuLoader) *loader = getMenuLoader();
- if (action->action->menuRole() == QAction::ApplicationSpecificRole)
- ret = action->action->shortcut();
- else if (action->menuItem == [loader preferencesMenuItem])
- ret = QKeySequence(QKeySequence::Preferences);
- else if (action->menuItem == [loader quitMenuItem])
- ret = QKeySequence(QKeySequence::Quit);
- return ret;
-}
-
-void Q_WIDGETS_EXPORT qt_mac_set_menubar_icons(bool b)
-{ QApplication::instance()->setAttribute(Qt::AA_DontShowIconsInMenus, !b); }
-void Q_WIDGETS_EXPORT qt_mac_set_native_menubar(bool b)
-{ QApplication::instance()->setAttribute(Qt::AA_DontUseNativeMenuBar, !b); }
-void Q_WIDGETS_EXPORT qt_mac_set_menubar_merge(bool b) { qt_mac_no_menubar_merge = !b; }
-
-/*****************************************************************************
- QMenu bindings
- *****************************************************************************/
-QMenuPrivate::QMacMenuPrivate::QMacMenuPrivate() : menu(0)
-{
-}
-
-QMenuPrivate::QMacMenuPrivate::~QMacMenuPrivate()
-{
- QMacCocoaAutoReleasePool pool;
- while (actionItems.size()) {
- QMacMenuAction *action = actionItems.takeFirst();
- if (QMenuMergeList *list = mergeMenuItemsHash.value(action->menu)) {
- int i = 0;
- while (i < list->size()) {
- const QMenuMergeItem &item = list->at(i);
- if (item.action == action)
- list->removeAt(i);
- else
- ++i;
- }
- }
- delete action;
- }
- mergeMenuHash.remove(menu);
- mergeMenuItemsHash.remove(menu);
- [menu release];
-}
-
-void
-QMenuPrivate::QMacMenuPrivate::addAction(QAction *a, QMacMenuAction *before, QMenuPrivate *qmenu)
-{
- QMacMenuAction *action = new QMacMenuAction;
- action->action = a;
- action->ignore_accel = 0;
- action->merged = 0;
- action->menu = 0;
- addAction(action, before, qmenu);
-}
-
-void
-QMenuPrivate::QMacMenuPrivate::addAction(QMacMenuAction *action, QMacMenuAction *before, QMenuPrivate *qmenu)
-{
- QMacCocoaAutoReleasePool pool;
- Q_UNUSED(qmenu);
- if (!action)
- return;
- int before_index = actionItems.indexOf(before);
- if (before_index < 0) {
- before = 0;
- before_index = actionItems.size();
- }
- actionItems.insert(before_index, action);
-
- [menu retain];
- [action->menu release];
- action->menu = menu;
-
- /* When the action is considered a mergable action it
- will stay that way, until removed.. */
- if (!qt_mac_no_menubar_merge) {
- OSMenuRef merge = QMenuPrivate::mergeMenuHash.value(menu);
- if (merge) {
- if (NSMenuItem *cmd = qt_mac_menu_merge_action(merge, action)) {
- action->merged = 1;
- [merge retain];
- [action->menu release];
- action->menu = merge;
- [cmd retain];
- [cmd setAction:@selector(qtDispatcherToQAction:)];
- [cmd setTarget:nil];
- [action->menuItem release];
- action->menuItem = cmd;
- QMenuMergeList *list = QMenuPrivate::mergeMenuItemsHash.value(merge);
- if (!list) {
- list = new QMenuMergeList;
- QMenuPrivate::mergeMenuItemsHash.insert(merge, list);
- }
- list->append(QMenuMergeItem(cmd, action));
- }
- }
- }
-
- NSMenuItem *newItem = action->menuItem;
- if (newItem == 0) {
- newItem = createNSMenuItem(action->action->text());
- action->menuItem = newItem;
- if (before) {
- [menu insertItem:newItem atIndex:qMax(before_index, 0)];
- } else {
- [menu addItem:newItem];
- }
-
- QWidget *widget = qmenu ? qmenu->widgetItems.value(action->action) : 0;
- if (widget) {
- qWarning("QMacMenuPrivate: Widgets in menus not implemented.");
-#if 0
-
- QMacNativeWidget *container = new QMacNativeWidget(0);
- container->resize(widget->sizeHint());
- widget->setAttribute(Qt::WA_LayoutUsesWidgetRect);
- widget->setParent(container);
-
- NSView *containerView = qt_mac_nativeview_for(container);
- [containerView setAutoresizesSubviews:YES];
- [containerView setAutoresizingMask:NSViewWidthSizable];
- [qt_mac_nativeview_for(widget) setAutoresizingMask:NSViewWidthSizable];
-
- [newItem setView:containerView];
- container->show();
- widget->show();
-#endif
- }
-
- } else {
- [newItem setEnabled:!QApplicationPrivate::modalState()];
- }
- [newItem setTag:long(static_cast<QAction *>(action->action))];
- syncAction(action);
-}
-
-// return an autoreleased string given a QKeySequence (currently only looks at the first one).
-NSString *keySequenceToKeyEqivalent(const QKeySequence &accel)
-{
- qWarning("Unimplemented: keySequenceToKeyEqivalent");
- return @"";
-#if 0
- quint32 accel_key = (accel[0] & ~(Qt::MODIFIER_MASK | Qt::UNICODE_ACCEL));
- extern QChar qtKey2CocoaKey(Qt::Key key);
- QChar cocoa_key = qtKey2CocoaKey(Qt::Key(accel_key));
- if (cocoa_key.isNull())
- cocoa_key = QChar(accel_key).toLower().unicode();
- return [NSString stringWithCharacters:&cocoa_key.unicode() length:1];
-#endif
-}
-
-// return the cocoa modifier mask for the QKeySequence (currently only looks at the first one).
-NSUInteger keySequenceModifierMask(const QKeySequence &accel)
-{
- return constructModifierMask(accel[0]);
-}
-
-void
-QMenuPrivate::QMacMenuPrivate::syncAction(QMacMenuAction *action)
-{
- if (!action)
- return;
-
- NSMenuItem *item = action->menuItem;
- if (!item)
- return;
-
- QMacCocoaAutoReleasePool pool;
- NSMenu *menu = [item menu];
- bool actionVisible = action->action->isVisible();
- [item setHidden:!actionVisible];
- if (!actionVisible)
- return;
-
- int itemIndex = [menu indexOfItem:item];
- Q_ASSERT(itemIndex != -1);
- if (action->action->isSeparator()) {
- action->menuItem = [NSMenuItem separatorItem];
- [action->menuItem retain];
- [menu insertItem: action->menuItem atIndex:itemIndex];
- [menu removeItem:item];
- [item release];
- item = action->menuItem;
- return;
- } else if ([item isSeparatorItem]) {
- // I'm no longer a separator...
- action->menuItem = createNSMenuItem(action->action->text());
- [menu insertItem:action->menuItem atIndex:itemIndex];
- [menu removeItem:item];
- [item release];
- item = action->menuItem;
- }
-
- //find text (and accel)
- action->ignore_accel = 0;
- QString text = action->action->text();
- QKeySequence accel = action->action->shortcut();
- {
- int st = text.lastIndexOf(QLatin1Char('\t'));
- if (st != -1) {
- action->ignore_accel = 1;
- accel = QKeySequence(text.right(text.length()-(st+1)));
- text.remove(st, text.length()-st);
- }
- }
- {
- QString cmd_text = qt_mac_menu_merge_text(action);
- if (!cmd_text.isEmpty()) {
- text = cmd_text;
- accel = qt_mac_menu_merge_accel(action);
- }
- }
- // Show multiple key sequences as part of the menu text.
- if (accel.count() > 1)
- text += QLatin1String(" (") + accel.toString(QKeySequence::NativeText) + QLatin1String(")");
-
-#if 0
- QString finalString = qt_mac_removeMnemonics(text);
-#else
- QString finalString = qt_mac_removeMnemonics(text);
-#endif
- // Cocoa Font and title
- if (action->action->font().resolve()) {
- const QFont &actionFont = action->action->font();
- NSFont *customMenuFont = [NSFont fontWithName:qt_mac_QStringToNSString(actionFont.family())
- size:actionFont.pointSize()];
- NSArray *keys = [NSArray arrayWithObjects:NSFontAttributeName, nil];
- NSArray *objects = [NSArray arrayWithObjects:customMenuFont, nil];
- NSDictionary *attributes = [NSDictionary dictionaryWithObjects:objects forKeys:keys];
- NSAttributedString *str = [[[NSAttributedString alloc] initWithString:qt_mac_QStringToNSString(finalString)
- attributes:attributes] autorelease];
- [item setAttributedTitle: str];
- } else {
- [item setTitle: qt_mac_QStringToNSString(finalString)];
- }
-
- if (action->action->menuRole() == QAction::AboutRole || action->action->menuRole() == QAction::QuitRole)
- [item setTitle:qt_mac_QStringToNSString(text)];
- else
- [item setTitle:qt_mac_QStringToNSString(qt_mac_removeMnemonics(text))];
-
- // Cocoa Enabled
- [item setEnabled: action->action->isEnabled()];
-
- // Cocoa icon
- NSImage *nsimage = 0;
- if (!action->action->icon().isNull() && action->action->isIconVisibleInMenu()) {
- nsimage = static_cast<NSImage *>(qt_mac_create_nsimage(action->action->icon().pixmap(16, QIcon::Normal)));
- }
- [item setImage:nsimage];
- [nsimage release];
-
- if (action->action->menu()) { //submenu
- NSMenu *subMenu = static_cast<NSMenu *>(action->action->menu()->macMenu());
- if ([subMenu supermenu] && [subMenu supermenu] != [item menu]) {
- // The menu is already a sub-menu of another one. Cocoa will throw an exception,
- // in such cases. For the time being, a new QMenu with same set of actions is the
- // only workaround.
- action->action->setEnabled(false);
- } else {
- [item setSubmenu:subMenu];
- }
- } else { //respect some other items
- [item setSubmenu:0];
- // No key equivalent set for multiple key QKeySequence.
- if (accel.count() == 1) {
- [item setKeyEquivalent:keySequenceToKeyEqivalent(accel)];
- [item setKeyEquivalentModifierMask:keySequenceModifierMask(accel)];
- } else {
- [item setKeyEquivalent:@""];
- [item setKeyEquivalentModifierMask:NSCommandKeyMask];
- }
- }
- //mark glyph
- [item setState:action->action->isChecked() ? NSOnState : NSOffState];
-}
-
-void
-QMenuPrivate::QMacMenuPrivate::removeAction(QMacMenuAction *action)
-{
- if (!action)
- return;
- QMacCocoaAutoReleasePool pool;
- if (action->merged) {
- if (reinterpret_cast<QAction *>([action->menuItem tag]) == action->action) {
- QT_MANGLE_NAMESPACE(QCocoaMenuLoader) *loader = getMenuLoader();
- [action->menuItem setEnabled:false];
- if (action->menuItem != [loader quitMenuItem]
- && action->menuItem != [loader preferencesMenuItem]) {
- [[action->menuItem menu] removeItem:action->menuItem];
- }
- }
- } else {
- [[action->menuItem menu] removeItem:action->menuItem];
- }
- actionItems.removeAll(action);
-}
-
-OSMenuRef
-QMenuPrivate::macMenu(OSMenuRef merge)
-{
- Q_UNUSED(merge);
- Q_Q(QMenu);
- if (mac_menu && mac_menu->menu)
- return mac_menu->menu;
- if (!mac_menu)
- mac_menu = new QMacMenuPrivate;
- mac_menu->menu = qt_mac_create_menu(q);
- if (merge) {
- mergeMenuHash.insert(mac_menu->menu, merge);
- }
- QList<QAction*> items = q->actions();
- for(int i = 0; i < items.count(); i++)
- mac_menu->addAction(items[i], 0, this);
- syncSeparatorsCollapsible(collapsibleSeparators);
- return mac_menu->menu;
-}
-
-/*!
- \internal
-*/
-void
-QMenuPrivate::syncSeparatorsCollapsible(bool collapse)
-{
- qt_mac_menu_collapseSeparators(mac_menu->menu, collapse);
-}
-
-
-
-/*!
- \internal
-*/
-void QMenuPrivate::setMacMenuEnabled(bool enable)
-{
- if (!macMenu(0))
- return;
-
- QMacCocoaAutoReleasePool pool;
- if (enable) {
- for (int i = 0; i < mac_menu->actionItems.count(); ++i) {
- QMacMenuAction *menuItem = mac_menu->actionItems.at(i);
- if (menuItem && menuItem->action && menuItem->action->isEnabled()) {
- [menuItem->menuItem setEnabled:true];
- }
- }
- } else {
- NSMenu *menu = mac_menu->menu;
- for (NSMenuItem *item in [menu itemArray]) {
- [item setEnabled:false];
- }
- }
-}
-
-/*!
- \internal
-
- This function will return the OSMenuRef used to create the native menu bar
- bindings.
-
- If Qt is built against Carbon, the OSMenuRef is a MenuRef that can be used
- with Carbon's Menu Manager API.
-
- If Qt is built against Cocoa, the OSMenuRef is a NSMenu pointer.
-
- \warning This function is not portable.
-
- \sa QMenuBar::macMenu()
-*/
-OSMenuRef QMenu::macMenu(OSMenuRef merge) { return d_func()->macMenu(merge); }
-
-/*****************************************************************************
- QMenuBar bindings
- *****************************************************************************/
-typedef QHash<QWidget *, QMenuBar *> MenuBarHash;
-Q_GLOBAL_STATIC(MenuBarHash, menubars)
-static QMenuBar *fallback = 0;
-QMenuBarPrivate::QMacMenuBarPrivate::QMacMenuBarPrivate() : menu(0), apple_menu(0)
-{
-}
-
-QMenuBarPrivate::QMacMenuBarPrivate::~QMacMenuBarPrivate()
-{
- for(QList<QMacMenuAction*>::Iterator it = actionItems.begin(); it != actionItems.end(); ++it)
- delete (*it);
- [apple_menu release];
- [menu release];
-}
-
-void
-QMenuBarPrivate::QMacMenuBarPrivate::addAction(QAction *a, QMacMenuAction *before)
-{
- if (a->isSeparator() || !menu)
- return;
- QMacMenuAction *action = new QMacMenuAction;
- action->action = a;
- action->ignore_accel = 1;
- addAction(action, before);
-}
-
-void
-QMenuBarPrivate::QMacMenuBarPrivate::addAction(QMacMenuAction *action, QMacMenuAction *before)
-{
- if (!action || !menu)
- return;
-
- int before_index = actionItems.indexOf(before);
- if (before_index < 0) {
- before = 0;
- before_index = actionItems.size();
- }
- actionItems.insert(before_index, action);
-
- MenuItemIndex index = actionItems.size()-1;
-
- action->menu = menu;
- QMacCocoaAutoReleasePool pool;
- [action->menu retain];
- NSMenuItem *newItem = createNSMenuItem(action->action->text());
- action->menuItem = newItem;
-
- if (before) {
- [menu insertItem:newItem atIndex:qMax(1, before_index + 1)];
- index = before_index;
- } else {
- [menu addItem:newItem];
- }
- [newItem setTag:long(static_cast<QAction *>(action->action))];
- syncAction(action);
-}
-
-void
-QMenuBarPrivate::QMacMenuBarPrivate::syncAction(QMacMenuAction *action)
-{
- if (!action || !menu)
- return;
-
- QMacCocoaAutoReleasePool pool;
- NSMenuItem *item = action->menuItem;
-
- OSMenuRef submenu = 0;
- bool release_submenu = false;
- if (action->action->menu()) {
- if ((submenu = action->action->menu()->macMenu(apple_menu))) {
- if ([submenu supermenu] && [submenu supermenu] != [item menu])
- return;
- else
- [item setSubmenu:submenu];
- }
- }
-
- if (submenu) {
- bool visible = actualMenuItemVisibility(this, action);
- [item setSubmenu: submenu];
- [submenu setTitle:qt_mac_QStringToNSString(qt_mac_removeMnemonics(action->action->text()))];
- syncNSMenuItemVisiblity(item, visible);
- if (release_submenu) { //no pointers to it
- [submenu release];
- }
- } else {
- qWarning("QMenu: No OSMenuRef created for popup menu");
- }
-}
-
-void
-QMenuBarPrivate::QMacMenuBarPrivate::removeAction(QMacMenuAction *action)
-{
- if (!action || !menu)
- return;
- QMacCocoaAutoReleasePool pool;
- [action->menu removeItem:action->menuItem];
- actionItems.removeAll(action);
-}
-
-bool QMenuBarPrivate::macWidgetHasNativeMenubar(QWidget *widget)
-{
- // This function is different from q->isNativeMenuBar(), as
- // it returns true only if a native menu bar is actually
- // _created_.
- if (!widget)
- return false;
- return menubars()->contains(widget->window());
-}
-
-void
-QMenuBarPrivate::macCreateMenuBar(QWidget *parent)
-{
- Q_Q(QMenuBar);
- static int dontUseNativeMenuBar = -1;
- // We call the isNativeMenuBar function here
- // because that will make sure that local overrides
- // are dealt with correctly. q->isNativeMenuBar() will, if not
- // overridden, depend on the attribute Qt::AA_DontUseNativeMenuBar:
- bool qt_mac_no_native_menubar = !q->isNativeMenuBar();
- if (qt_mac_no_native_menubar == false && dontUseNativeMenuBar < 0) {
- // The menubar is set to be native. Let's check (one time only
- // for all menubars) if this is OK with the rest of the environment.
- // As a result, Qt::AA_DontUseNativeMenuBar is set. NB: the application
- // might still choose to not respect, or change, this flag.
- bool isPlugin = QApplication::testAttribute(Qt::AA_MacPluginApplication);
- bool environmentSaysNo = !qgetenv("QT_MAC_NO_NATIVE_MENUBAR").isEmpty();
- dontUseNativeMenuBar = isPlugin || environmentSaysNo;
- QApplication::instance()->setAttribute(Qt::AA_DontUseNativeMenuBar, dontUseNativeMenuBar);
- qt_mac_no_native_menubar = !q->isNativeMenuBar();
- }
- if (qt_mac_no_native_menubar == false) {
- // INVARIANT: Use native menubar.
- QMenuBar::macUpdateMenuBar();
- if (!parent && !fallback) {
- fallback = q;
- mac_menubar = new QMacMenuBarPrivate;
- } else if (parent && parent->isWindow()) {
- menubars()->insert(q->window(), q);
- mac_menubar = new QMacMenuBarPrivate;
- }
- }
-}
-
-void QMenuBarPrivate::macDestroyMenuBar()
-{
- Q_Q(QMenuBar);
- QMacCocoaAutoReleasePool pool;
- if (fallback == q)
- fallback = 0;
- delete mac_menubar;
- QWidget *tlw = q->window();
- menubars()->remove(tlw);
- mac_menubar = 0;
-
- if (!qt_mac_current_menubar.qmenubar || qt_mac_current_menubar.qmenubar == q) {
- QT_MANGLE_NAMESPACE(QCocoaMenuLoader) *loader = getMenuLoader();
- [loader removeActionsFromAppMenu];
- QMenuBar::macUpdateMenuBar();
- }
-}
-
-OSMenuRef QMenuBarPrivate::macMenu()
-{
- Q_Q(QMenuBar);
- if (!q->isNativeMenuBar() || !mac_menubar) {
- return 0;
- } else if (!mac_menubar->menu) {
- mac_menubar->menu = qt_mac_create_menu(q);
- ProcessSerialNumber mine, front;
- if (GetCurrentProcess(&mine) == noErr && GetFrontProcess(&front) == noErr) {
- if (!qt_mac_no_menubar_merge && !mac_menubar->apple_menu) {
- mac_menubar->apple_menu = qt_mac_create_menu(q);
- [mac_menubar->apple_menu setTitle:qt_mac_QStringToNSString(QString(QChar(0x14)))];
- NSMenuItem *apple_menuItem = [[NSMenuItem alloc] init];
- [apple_menuItem setSubmenu:mac_menubar->menu];
- [mac_menubar->apple_menu addItem:apple_menuItem];
- [apple_menuItem release];
- }
- if (mac_menubar->apple_menu) {
- QMenuPrivate::mergeMenuHash.insert(mac_menubar->menu, mac_menubar->apple_menu);
- }
- QList<QAction*> items = q->actions();
- for(int i = 0; i < items.count(); i++)
- mac_menubar->addAction(items[i]);
- }
- }
- return mac_menubar->menu;
-}
-
-/*!
- \internal
-
- This function will return the OSMenuRef used to create the native menu bar
- bindings. This OSMenuRef is then set as the root menu for the Menu
- Manager.
-
- \warning This function is not portable.
-
- \sa QMenu::macMenu()
-*/
-OSMenuRef QMenuBar::macMenu() { return d_func()->macMenu(); }
-
-/* !
- \internal
- Ancestor function that crosses windows (QWidget::isAncestorOf
- only considers widgets within the same window).
-*/
-static bool qt_mac_is_ancestor(QWidget* possibleAncestor, QWidget *child)
-{
- if (!possibleAncestor)
- return false;
-
- QWidget * current = child->parentWidget();
- while (current != 0) {
- if (current == possibleAncestor)
- return true;
- current = current->parentWidget();
- }
- return false;
-}
-
-/* !
- \internal
- Returns true if the entries of menuBar should be disabled,
- based on the modality type of modalWidget.
-*/
-static bool qt_mac_should_disable_menu(QMenuBar *menuBar)
-{
- QWidget *modalWidget = qApp->activeModalWidget();
- if (!modalWidget)
- return false;
-
- if (menuBar && menuBar == menubars()->value(modalWidget))
- // The menu bar is owned by the modal widget.
- // In that case we should enable it:
- return false;
-
- // When there is an application modal window on screen, the entries of
- // the menubar should be disabled. The exception in Qt is that if the
- // modal window is the only window on screen, then we enable the menu bar.
- QWidget *w = modalWidget;
- QWidgetList topLevelWidgets = QApplication::topLevelWidgets();
- while (w) {
- if (w->isVisible() && w->windowModality() == Qt::ApplicationModal) {
- for (int i=0; i<topLevelWidgets.size(); ++i) {
- QWidget *top = topLevelWidgets.at(i);
- if (w != top && top->isVisible()) {
- // INVARIANT: we found another visible window
- // on screen other than our modalWidget. We therefore
- // disable the menu bar to follow normal modality logic:
- return true;
- }
- }
- // INVARIANT: We have only one window on screen that happends
- // to be application modal. We choose to enable the menu bar
- // in that case to e.g. enable the quit menu item.
- return false;
- }
- w = w->parentWidget();
- }
-
- // INVARIANT: modalWidget is window modal. Disable menu entries
- // if the menu bar belongs to an ancestor of modalWidget. If menuBar
- // is nil, we understand it as the default menu bar set by the nib:
- return menuBar ? qt_mac_is_ancestor(menuBar->parentWidget(), modalWidget) : false;
-}
-
-static QWidget *findWindowThatShouldDisplayMenubar()
-{
- QWidget *w = qApp->activeWindow();
- if (!w) {
- // We have no active window on screen. Try to
- // find a window from the list of top levels:
- QWidgetList tlws = QApplication::topLevelWidgets();
- for(int i = 0; i < tlws.size(); ++i) {
- QWidget *tlw = tlws.at(i);
- if ((tlw->isVisible() && tlw->windowType() != Qt::Tool &&
- tlw->windowType() != Qt::Popup)) {
- w = tlw;
- break;
- }
- }
- }
- return w;
-}
-
-static QMenuBar *findMenubarForWindow(QWidget *w)
-{
- QMenuBar *mb = 0;
- if (w) {
- mb = menubars()->value(w);
-#ifndef QT_NO_MAINWINDOW
- QDockWidget *dw = qobject_cast<QDockWidget *>(w);
- if (!mb && dw) {
- QMainWindow *mw = qobject_cast<QMainWindow *>(dw->parentWidget());
- if (mw && (mb = menubars()->value(mw)))
- w = mw;
- }
-#endif
- while(w && !mb)
- mb = menubars()->value((w = w->parentWidget()));
- }
-
- if (!mb) {
- // We could not find a menu bar for the window. Lets
- // check if we have a global (parentless) menu bar instead:
- mb = fallback;
- }
-
- return mb;
-}
-
-void qt_mac_clear_menubar()
-{
- if (QApplication::testAttribute(Qt::AA_MacPluginApplication))
- return;
-
- QMacCocoaAutoReleasePool pool;
- QT_MANGLE_NAMESPACE(QCocoaMenuLoader) *loader = getMenuLoader();
- NSMenu *menu = [loader menu];
- [loader ensureAppMenuInMenu:menu];
- [NSApp setMainMenu:menu];
- const bool modal = qt_mac_should_disable_menu(0);
- if (qt_mac_current_menubar.qmenubar || modal != qt_mac_current_menubar.modal)
- qt_mac_set_modal_state(menu, modal);
- qt_mac_current_menubar.qmenubar = 0;
- qt_mac_current_menubar.modal = modal;
-}
-
-/*!
- \internal
-
- This function will update the current menu bar and set it as the
- active menu bar in the Menu Manager.
-
- \warning This function is not portable.
-
- \sa QMenu::macMenu(), QMenuBar::macMenu()
-*/
-bool QMenuBar::macUpdateMenuBar()
-{
- QMacCocoaAutoReleasePool pool;
- qWarning("Unimplemented: QMenuBar::macUpdateMenuBar");
- //qt_cocoaPostMessage(getMenuLoader(), @selector(qtUpdateMenubar));
-
- return true;
-}
-
-bool QMenuBarPrivate::macUpdateMenuBarImmediatly()
-{
- bool ret = false;
- cancelAllMenuTracking();
- QWidget *w = findWindowThatShouldDisplayMenubar();
- QMenuBar *mb = findMenubarForWindow(w);
- extern bool qt_mac_app_fullscreen; //qapplication_mac.mm
-
- // We need to see if we are in full screen mode, if so we need to
- // switch the full screen mode to be able to show or hide the menubar.
- if(w && mb) {
- // This case means we are creating a menubar, check if full screen
- if(w->isFullScreen()) {
- // Ok, switch to showing the menubar when hovering over it.
- SetSystemUIMode(kUIModeAllHidden, kUIOptionAutoShowMenuBar);
- qt_mac_app_fullscreen = true;
- }
- } else if(w) {
- // Removing a menubar
- if(w->isFullScreen()) {
- // Ok, switch to not showing the menubar when hovering on it
- SetSystemUIMode(kUIModeAllHidden, 0);
- qt_mac_app_fullscreen = true;
- }
- }
-
- if (mb && mb->isNativeMenuBar()) {
- bool modal = QApplicationPrivate::modalState();
- QMacCocoaAutoReleasePool pool;
- if (OSMenuRef menu = mb->macMenu()) {
- QT_MANGLE_NAMESPACE(QCocoaMenuLoader) *loader = getMenuLoader();
- [loader ensureAppMenuInMenu:menu];
- [NSApp setMainMenu:menu];
- syncMenuBarItemsVisiblity(mb->d_func()->mac_menubar);
-
- if (OSMenuRef tmpMerge = QMenuPrivate::mergeMenuHash.value(menu)) {
- if (QMenuMergeList *mergeList
- = QMenuPrivate::mergeMenuItemsHash.value(tmpMerge)) {
- const int mergeListSize = mergeList->size();
-
- for (int i = 0; i < mergeListSize; ++i) {
- const QMenuMergeItem &mergeItem = mergeList->at(i);
- // Ideally we would call QMenuPrivate::syncAction, but that requires finding
- // the original QMen and likely doing more work than we need.
- // For example, enabled is handled below.
- [mergeItem.menuItem setTag:reinterpret_cast<long>(
- static_cast<QAction *>(mergeItem.action->action))];
- [mergeItem.menuItem setHidden:!(mergeItem.action->action->isVisible())];
- }
- }
- }
- // Check if menu is modally shaddowed and should be disabled:
- modal = qt_mac_should_disable_menu(mb);
- if (mb != qt_mac_current_menubar.qmenubar || modal != qt_mac_current_menubar.modal)
- qt_mac_set_modal_state(menu, modal);
- }
- qt_mac_current_menubar.qmenubar = mb;
- qt_mac_current_menubar.modal = modal;
- ret = true;
- } else if (qt_mac_current_menubar.qmenubar && qt_mac_current_menubar.qmenubar->isNativeMenuBar()) {
- // INVARIANT: The currently active menu bar (if any) is not native. But we do have a
- // native menu bar from before. So we need to decide whether or not is should be enabled:
- const bool modal = qt_mac_should_disable_menu(qt_mac_current_menubar.qmenubar);
- if (modal != qt_mac_current_menubar.modal) {
- ret = true;
- if (OSMenuRef menu = qt_mac_current_menubar.qmenubar->macMenu()) {
- QT_MANGLE_NAMESPACE(QCocoaMenuLoader) *loader = getMenuLoader();
- [loader ensureAppMenuInMenu:menu];
- [NSApp setMainMenu:menu];
- syncMenuBarItemsVisiblity(qt_mac_current_menubar.qmenubar->d_func()->mac_menubar);
- qt_mac_set_modal_state(menu, modal);
- }
- qt_mac_current_menubar.modal = modal;
- }
- }
-
- if (!ret) {
- qt_mac_clear_menubar();
- }
- return ret;
-}
-
-QHash<OSMenuRef, OSMenuRef> QMenuPrivate::mergeMenuHash;
-QHash<OSMenuRef, QMenuMergeList*> QMenuPrivate::mergeMenuItemsHash;
-
-bool QMenuPrivate::QMacMenuPrivate::merged(const QAction *action) const
-{
- if (OSMenuRef merge = mergeMenuHash.value(menu)) {
- if (QMenuMergeList *list = mergeMenuItemsHash.value(merge)) {
- for(int i = 0; i < list->size(); ++i) {
- const QMenuMergeItem &item = list->at(i);
- if (item.action->action == action)
- return true;
- }
- }
- }
- return false;
-}
-
-//creation of the OSMenuRef
-static OSMenuRef qt_mac_create_menu(QWidget *w)
-{
- OSMenuRef ret;
- if (QMenu *qmenu = qobject_cast<QMenu *>(w)){
- ret = [[QT_MANGLE_NAMESPACE(QCocoaMenu) alloc] initWithQMenu:qmenu];
- } else {
- ret = [[NSMenu alloc] init];
- }
- return ret;
-}
-
-
-
-QT_END_NAMESPACE
-
diff --git a/src/widgets/widgets/qmenu_p.h b/src/widgets/widgets/qmenu_p.h
index cfe1ecf2b9..bd360f5e25 100644
--- a/src/widgets/widgets/qmenu_p.h
+++ b/src/widgets/widgets/qmenu_p.h
@@ -83,37 +83,6 @@ void qt_symbian_show_submenu(CEikMenuPane* menuPane, int id);
class QTornOffMenu;
class QEventLoop;
-#ifdef Q_OS_MAC
-# ifdef __OBJC__
-QT_END_NAMESPACE
-@class NSMenuItem;
-QT_BEGIN_NAMESPACE
-# else
-typedef void NSMenuItem;
-# endif //__OBJC__
-struct QMacMenuAction {
- QMacMenuAction()
- : menuItem(0)
- , ignore_accel(0), merged(0), menu(0)
- {
- }
- ~QMacMenuAction();
- NSMenuItem *menuItem;
- uchar ignore_accel : 1;
- uchar merged : 1;
- QPointer<QAction> action;
- OSMenuRef menu;
-};
-
-struct QMenuMergeItem
-{
- inline QMenuMergeItem(NSMenuItem *c, QMacMenuAction *a) : menuItem(c), action(a) { }
- NSMenuItem *menuItem;
- QMacMenuAction *action;
-};
-typedef QList<QMenuMergeItem> QMenuMergeList;
-#endif // Q_OS_MAC
-
#ifdef Q_WS_WINCE
struct QWceMenuAction {
uint command;
@@ -144,13 +113,8 @@ public:
cancelAction(0),
#endif
scroll(0), eventLoop(0), tearoff(0), tornoff(0), tearoffHighlighted(0),
- hasCheckableItems(0), sloppyAction(0), doChildEffects(false)
-#ifdef QT3_SUPPORT
- ,emitHighlighted(false)
-#endif
-#ifdef Q_OS_MAC
- ,mac_menu(0)
-#endif
+ hasCheckableItems(0), sloppyAction(0), doChildEffects(false), platformMenu(0)
+
#if defined(Q_WS_WINCE) && !defined(QT_NO_MENUBAR)
,wce_menu(0)
#endif
@@ -161,9 +125,7 @@ public:
~QMenuPrivate()
{
delete scroll;
-#ifdef Q_OS_MAC
- delete mac_menu;
-#endif
+ delete platformMenu;
#if defined(Q_WS_WINCE) && !defined(QT_NO_MENUBAR)
delete wce_menu;
#endif
@@ -293,36 +255,7 @@ public:
//menu fading/scrolling effects
bool doChildEffects;
-#ifdef Q_OS_MAC
- //mac menu binding
- struct QMacMenuPrivate {
- QList<QMacMenuAction*> actionItems;
- OSMenuRef menu;
- QMacMenuPrivate();
- ~QMacMenuPrivate();
-
- bool merged(const QAction *action) const;
- void addAction(QAction *, QMacMenuAction* =0, QMenuPrivate *qmenu = 0);
- void addAction(QMacMenuAction *, QMacMenuAction* =0, QMenuPrivate *qmenu = 0);
- void syncAction(QMacMenuAction *);
- inline void syncAction(QAction *a) { syncAction(findAction(a)); }
- void removeAction(QMacMenuAction *);
- inline void removeAction(QAction *a) { removeAction(findAction(a)); }
- inline QMacMenuAction *findAction(QAction *a) {
- for(int i = 0; i < actionItems.size(); i++) {
- QMacMenuAction *act = actionItems[i];
- if(a == act->action)
- return act;
- }
- return 0;
- }
- } *mac_menu;
- OSMenuRef macMenu(OSMenuRef merge);
- void setMacMenuEnabled(bool enable = true);
- void syncSeparatorsCollapsible(bool collapsible);
- static QHash<OSMenuRef, OSMenuRef> mergeMenuHash;
- static QHash<OSMenuRef, QMenuMergeList*> mergeMenuItemsHash;
-#endif
+ QPlatformMenu *platformMenu;
QPointer<QAction> actionAboutToTrigger;
#ifdef QT3_SUPPORT
diff --git a/src/widgets/widgets/qmenubar.cpp b/src/widgets/widgets/qmenubar.cpp
index 1b8f1f8176..1caa112f1b 100644
--- a/src/widgets/widgets/qmenubar.cpp
+++ b/src/widgets/widgets/qmenubar.cpp
@@ -55,6 +55,7 @@
#include <qtoolbar.h>
#include <qtoolbutton.h>
#include <qwhatsthis.h>
+#include "private/qguiapplication_p.h"
#ifndef QT_NO_MENUBAR
@@ -728,11 +729,11 @@ void QMenuBarPrivate::init()
Q_Q(QMenuBar);
q->setSizePolicy(QSizePolicy::MinimumExpanding, QSizePolicy::Minimum);
q->setAttribute(Qt::WA_CustomWhatsThis);
-#ifdef Q_OS_MAC
- macCreateMenuBar(q->parentWidget());
- if(mac_menubar)
+
+ platformMenuBar = QGuiApplicationPrivate::platformIntegration()->createPlatformMenuBar(q);
+
+ if (platformMenuBar)
q->hide();
-#endif
#ifdef Q_WS_WINCE
if (qt_wince_is_mobile()) {
wceCreateMenuBar(q->parentWidget());
@@ -808,10 +809,10 @@ QMenuBar::QMenuBar(QWidget *parent, const char *name) : QWidget(*new QMenuBarPri
*/
QMenuBar::~QMenuBar()
{
-#ifdef Q_OS_MAC
Q_D(QMenuBar);
- d->macDestroyMenuBar();
-#endif
+ delete d->platformMenuBar;
+ d->platformMenuBar = 0;
+
#ifdef Q_WS_WINCE
Q_D(QMenuBar);
if (qt_wince_is_mobile())
@@ -1275,25 +1276,23 @@ void QMenuBar::actionEvent(QActionEvent *e)
{
Q_D(QMenuBar);
d->itemsDirty = true;
-#if defined (Q_OS_MAC) || defined(Q_OS_WINCE) || defined(Q_WS_S60)
- if (isNativeMenuBar()) {
-#ifdef Q_OS_MAC
- QMenuBarPrivate::QMacMenuBarPrivate *nativeMenuBar = d->mac_menubar;
-#elif defined(Q_WS_S60)
+
+ if (d->platformMenuBar) {
+ QPlatformMenuBar *nativeMenuBar = d->platformMenuBar;
+#if defined(Q_WS_S60)
QMenuBarPrivate::QSymbianMenuBarPrivate *nativeMenuBar = d->symbian_menubar;
-#else
+#elif defined(Q_WS_WINCE)
QMenuBarPrivate::QWceMenuBarPrivate *nativeMenuBar = d->wce_menubar;
#endif
if (!nativeMenuBar)
return;
if(e->type() == QEvent::ActionAdded)
- nativeMenuBar->addAction(e->action(), nativeMenuBar->findAction(e->before()));
+ nativeMenuBar->addAction(e->action(), e->before());
else if(e->type() == QEvent::ActionRemoved)
nativeMenuBar->removeAction(e->action());
else if(e->type() == QEvent::ActionChanged)
nativeMenuBar->syncAction(e->action());
}
-#endif
if(e->type() == QEvent::ActionAdded) {
connect(e->action(), SIGNAL(triggered()), this, SLOT(_q_actionTriggered()));
@@ -1372,15 +1371,8 @@ void QMenuBarPrivate::handleReparent()
oldParent = newParent;
oldWindow = newWindow;
-#ifdef Q_OS_MAC
- if (q->isNativeMenuBar() && !macWidgetHasNativeMenubar(newParent)) {
- // If the new parent got a native menubar from before, keep that
- // menubar rather than replace it with this one (because a parents
- // menubar has precedence over children menubars).
- macDestroyMenuBar();
- macCreateMenuBar(newParent);
- }
-#endif
+ if (platformMenuBar)
+ platformMenuBar->handleReparent(newParent);
#ifdef Q_WS_WINCE
if (qt_wince_is_mobile() && wce_menubar)
@@ -1925,27 +1917,18 @@ void QMenuBar::setNativeMenuBar(bool nativeMenuBar)
Q_D(QMenuBar);
if (d->nativeMenuBar == -1 || (nativeMenuBar != bool(d->nativeMenuBar))) {
d->nativeMenuBar = nativeMenuBar;
-#ifdef Q_OS_MAC
+
if (!d->nativeMenuBar) {
- extern void qt_mac_clear_menubar();
- qt_mac_clear_menubar();
- d->macDestroyMenuBar();
- const QList<QAction *> &menubarActions = actions();
- for (int i = 0; i < menubarActions.size(); ++i) {
- const QAction *action = menubarActions.at(i);
- if (QMenu *menu = action->menu()) {
- delete menu->d_func()->mac_menu;
- menu->d_func()->mac_menu = 0;
- }
- }
+ delete d->platformMenuBar;
+ d->platformMenuBar = 0;
} else {
- d->macCreateMenuBar(parentWidget());
+ if (!d->platformMenuBar)
+ d->platformMenuBar = QGuiApplicationPrivate::platformIntegration()->createPlatformMenuBar(this);
}
- macUpdateMenuBar();
+
updateGeometry();
if (!d->nativeMenuBar && parentWidget())
setVisible(true);
-#endif
}
}
@@ -1958,6 +1941,12 @@ bool QMenuBar::isNativeMenuBar() const
return d->nativeMenuBar;
}
+QPlatformMenuBar *QMenuBar::platformMenuBar()
+{
+ Q_D(const QMenuBar);
+ return d->platformMenuBar;
+}
+
/*!
\since 4.4
diff --git a/src/widgets/widgets/qmenubar.h b/src/widgets/widgets/qmenubar.h
index 990027f16a..e7e8f78958 100644
--- a/src/widgets/widgets/qmenubar.h
+++ b/src/widgets/widgets/qmenubar.h
@@ -110,11 +110,6 @@ public:
void setCornerWidget(QWidget *w, Qt::Corner corner = Qt::TopRightCorner);
QWidget *cornerWidget(Qt::Corner corner = Qt::TopRightCorner) const;
-#ifdef Q_OS_MAC
- OSMenuRef macMenu();
- static bool macUpdateMenuBar();
-#endif
-
#ifdef Q_WS_WINCE
void setDefaultAction(QAction *);
QAction *defaultAction() const;
@@ -125,7 +120,7 @@ public:
bool isNativeMenuBar() const;
void setNativeMenuBar(bool nativeMenuBar);
-
+ QPlatformMenuBar *platformMenuBar();
public Q_SLOTS:
virtual void setVisible(bool visible);
diff --git a/src/widgets/widgets/qmenubar_p.h b/src/widgets/widgets/qmenubar_p.h
index e42162a48e..5f482c228e 100644
--- a/src/widgets/widgets/qmenubar_p.h
+++ b/src/widgets/widgets/qmenubar_p.h
@@ -78,13 +78,10 @@ class QMenuBarPrivate : public QWidgetPrivate
public:
QMenuBarPrivate() : itemsDirty(0), currentAction(0), mouseDown(0),
closePopupMode(0), defaultPopDown(1), popupState(0), keyboardState(0), altPressed(0),
- nativeMenuBar(-1), doChildEffects(false)
+ nativeMenuBar(-1), doChildEffects(false), platformMenuBar(0)
#ifdef QT3_SUPPORT
, doAutoResize(false)
#endif
-#ifdef Q_OS_MAC
- , mac_menubar(0)
-#endif
#ifdef Q_WS_WINCE
, wce_menubar(0), wceClassicMenu(false)
@@ -96,9 +93,7 @@ public:
{ }
~QMenuBarPrivate()
{
-#ifdef Q_OS_MAC
- delete mac_menubar;
-#endif
+ delete platformMenuBar;
#ifdef Q_WS_WINCE
delete wce_menubar;
#endif
@@ -173,35 +168,8 @@ public:
#ifdef QT3_SUPPORT
bool doAutoResize;
#endif
-#ifdef Q_OS_MAC
- //mac menubar binding
- struct QMacMenuBarPrivate {
- QList<QMacMenuAction*> actionItems;
- OSMenuRef menu, apple_menu;
- QMacMenuBarPrivate();
- ~QMacMenuBarPrivate();
+ QPlatformMenuBar *platformMenuBar;
- void addAction(QAction *, QMacMenuAction* =0);
- void addAction(QMacMenuAction *, QMacMenuAction* =0);
- void syncAction(QMacMenuAction *);
- inline void syncAction(QAction *a) { syncAction(findAction(a)); }
- void removeAction(QMacMenuAction *);
- inline void removeAction(QAction *a) { removeAction(findAction(a)); }
- inline QMacMenuAction *findAction(QAction *a) {
- for(int i = 0; i < actionItems.size(); i++) {
- QMacMenuAction *act = actionItems[i];
- if(a == act->action)
- return act;
- }
- return 0;
- }
- } *mac_menubar;
- static bool macUpdateMenuBarImmediatly();
- bool macWidgetHasNativeMenubar(QWidget *widget);
- void macCreateMenuBar(QWidget *);
- void macDestroyMenuBar();
- OSMenuRef macMenu();
-#endif
#ifdef Q_WS_WINCE
void wceCreateMenuBar(QWidget *);
void wceDestroyMenuBar();
diff --git a/src/widgets/widgets/widgets.pri b/src/widgets/widgets/widgets.pri
index a272540aa8..cc4a61f493 100644
--- a/src/widgets/widgets/widgets.pri
+++ b/src/widgets/widgets/widgets.pri
@@ -155,12 +155,6 @@ SOURCES += \
widgets/qmacnativewidget_mac.mm \
}
-mac {
- OBJECTIVE_SOURCES += widgets/qmenu_mac.mm \
- widgets/qcocoamenu_mac.mm \
- platforms/mac/qt_widget_helpers_mac.mm
-}
-
wince*: {
SOURCES += widgets/qmenu_wince.cpp
HEADERS += widgets/qmenu_wince_resource_p.h