1 /****************************************************************************
3 ** Copyright (C) 2013 Digia Plc and/or its subsidiary(-ies).
4 ** Contact: http://www.qt-project.org/legal
6 ** This file is part of the QtGui module of the Qt Toolkit.
8 ** $QT_BEGIN_LICENSE:LGPL$
9 ** Commercial License Usage
10 ** Licensees holding valid commercial Qt licenses may use this file in
11 ** accordance with the commercial license agreement provided with the
12 ** Software or, alternatively, in accordance with the terms contained in
13 ** a written agreement between you and Digia. For licensing terms and
14 ** conditions see http://qt.digia.com/licensing. For further information
15 ** use the contact form at http://qt.digia.com/contact-us.
17 ** GNU Lesser General Public License Usage
18 ** Alternatively, this file may be used under the terms of the GNU Lesser
19 ** General Public License version 2.1 as published by the Free Software
20 ** Foundation and appearing in the file LICENSE.LGPL included in the
21 ** packaging of this file. Please review the following information to
22 ** ensure the GNU Lesser General Public License version 2.1 requirements
23 ** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
25 ** In addition, as a special exception, Digia gives you certain additional
26 ** rights. These rights are described in the Digia Qt LGPL Exception
27 ** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
29 ** GNU General Public License Usage
30 ** Alternatively, this file may be used under the terms of the GNU
31 ** General Public License version 3.0 as published by the Free Software
32 ** Foundation and appearing in the file LICENSE.GPL included in the
33 ** packaging of this file. Please review the following information to
34 ** ensure the GNU General Public License version 3.0 requirements will be
35 ** met: http://www.gnu.org/copyleft/gpl.html.
40 ****************************************************************************/
49 // This file is not part of the Qt API. It exists purely as an
50 // implementation detail. This header file may change from version to
51 // version without notice, or even be removed.
56 #include "QtGui/qmenubar.h"
57 #include "QtGui/qstyleoption.h"
58 #include "QtCore/qdatetime.h"
59 #include "QtCore/qmap.h"
60 #include "QtCore/qhash.h"
61 #include "QtCore/qbasictimer.h"
62 #include "private/qwidget_p.h"
66 #define QT_SYMBIAN_FIRST_MENU_ITEM 32000
67 #define QT_SYMBIAN_LAST_MENU_ITEM 41999 // 10000 items ought to be enough for anybody...
74 void qt_symbian_next_menu_from_action(QWidget* actionContainer);
75 void qt_symbian_show_toplevel(CEikMenuPane* menuPane);
76 void qt_symbian_show_submenu(CEikMenuPane* menuPane, int id);
88 typedef void NSMenuItem;
90 struct QMacMenuAction {
92 #ifndef QT_MAC_USE_COCOA
97 , ignore_accel(0), merged(0), menu(0)
101 #ifndef QT_MAC_USE_COCOA
104 NSMenuItem *menuItem;
106 uchar ignore_accel : 1;
108 QPointer<QAction> action;
112 struct QMenuMergeItem
114 #ifndef QT_MAC_USE_COCOA
115 inline QMenuMergeItem(MenuCommand c, QMacMenuAction *a) : command(c), action(a) { }
118 inline QMenuMergeItem(NSMenuItem *c, QMacMenuAction *a) : menuItem(c), action(a) { }
119 NSMenuItem *menuItem;
121 QMacMenuAction *action;
123 typedef QList<QMenuMergeItem> QMenuMergeList;
127 struct QWceMenuAction {
129 QPointer<QAction> action;
131 QWceMenuAction() : menuHandle(0), command(0) {}
135 struct QSymbianMenuAction {
138 CEikMenuPane* menuPane;
139 QPointer<QAction> action;
140 QSymbianMenuAction() : command(0) {}
144 class QMenuPrivate : public QWidgetPrivate
146 Q_DECLARE_PUBLIC(QMenu)
148 QMenuPrivate() : itemsDirty(0), maxIconWidth(0), tabWidth(0), ncols(0),
149 collapsibleSeparators(true), activationRecursionGuard(false), hasHadMouse(0), aboutToHide(0), motions(0),
151 #ifdef QT_KEYPAD_NAVIGATION
155 scroll(0), eventLoop(0), tearoff(0), tornoff(0), tearoffHighlighted(0),
156 hasCheckableItems(0), sloppyDelayTimer(0), sloppyAction(0), doChildEffects(false)
158 ,emitHighlighted(false)
163 #if defined(Q_WS_WINCE) && !defined(QT_NO_MENUBAR)
176 #if defined(Q_WS_WINCE) && !defined(QT_NO_MENUBAR)
186 static QMenuPrivate *get(QMenu *m) { return m->d_func(); }
187 int scrollerHeight() const;
190 mutable uint itemsDirty : 1;
191 mutable uint maxIconWidth, tabWidth;
192 QRect actionRect(QAction *) const;
194 mutable QVector<QRect> actionRects;
195 mutable QHash<QAction *, QWidget *> widgetItems;
196 void updateActionRects() const;
197 void updateActionRects(const QRect &screen) const;
198 QRect popupGeometry(const QWidget *widget) const;
199 QRect popupGeometry(int screen = -1) const;
200 mutable uint ncols : 4; //4 bits is probably plenty
201 uint collapsibleSeparators : 1;
202 QSize adjustMenuSizeForScreen(const QRect & screen);
203 int getLastVisibleAction() const;
205 bool activationRecursionGuard;
208 static QMenu *mouseDown;
209 QPoint mousePopupPos;
210 uint hasHadMouse : 1;
211 uint aboutToHide : 1;
213 QAction *currentAction;
214 #ifdef QT_KEYPAD_NAVIGATION
215 QAction *selectAction;
216 QAction *cancelAction;
218 QBasicTimer menuDelayTimer;
219 enum SelectionReason {
220 SelectedFromKeyboard,
221 SelectedFromElsewhere
223 QWidget *topCausedWidget() const;
224 QAction *actionAt(QPoint p) const;
225 void setFirstActionActive();
226 void setCurrentAction(QAction *, int popup = -1, SelectionReason reason = SelectedFromElsewhere, bool activateFirst = false);
227 void popupAction(QAction *, int, bool);
228 void setSyncAction();
231 struct QMenuScroller {
232 enum ScrollLocation { ScrollStay, ScrollBottom, ScrollTop, ScrollCenter };
233 enum ScrollDirection { ScrollNone=0, ScrollUp=0x01, ScrollDown=0x02 };
234 uint scrollFlags : 2, scrollDirection : 2;
236 QBasicTimer scrollTimer;
238 QMenuScroller() : scrollFlags(ScrollNone), scrollDirection(ScrollNone), scrollOffset(0) { }
241 void scrollMenu(QMenuScroller::ScrollLocation location, bool active=false);
242 void scrollMenu(QMenuScroller::ScrollDirection direction, bool page=false, bool active=false);
243 void scrollMenu(QAction *action, QMenuScroller::ScrollLocation location, bool active=false);
245 //synchronous operation (ie exec())
246 QEventLoop *eventLoop;
247 QPointer<QAction> syncAction;
250 QString searchBuffer;
251 QBasicTimer searchBufferTimer;
253 //passing of mouse events up the parent hierarchy
254 QPointer<QMenu> activeMenu;
255 bool mouseEventTaken(QMouseEvent *);
257 //used to walk up the popup list
259 QPointer<QWidget> widget;
260 QPointer<QAction> action;
262 virtual QList<QPointer<QWidget> > calcCausedStack() const;
263 QMenuCaused causedPopup;
264 void hideUpToMenuBar();
265 void hideMenu(QMenu *menu, bool justRegister = false);
268 inline QAction *actionAt(int i) const { return q_func()->actions().at(i); }
269 inline int indexOf(QAction *act) const { return q_func()->actions().indexOf(act); }
272 uint tearoff : 1, tornoff : 1, tearoffHighlighted : 1;
273 QPointer<QTornOffMenu> tornPopup;
275 mutable bool hasCheckableItems;
278 int sloppyDelayTimer;
279 mutable QAction *sloppyAction;
280 QRegion sloppyRegion;
283 QPointer<QAction> defaultAction;
286 QAction *defaultMenuAction;
288 void setOverrideMenuAction(QAction *);
289 void _q_overrideMenuActionDestroyed();
292 void activateAction(QAction *, QAction::ActionEvent, bool self=true);
293 void activateCausedStack(const QList<QPointer<QWidget> > &, QAction *, QAction::ActionEvent, bool);
295 void _q_actionTriggered();
296 void _q_actionHovered();
298 bool hasMouseMoved(const QPoint &globalPos);
300 void updateLayoutDirection();
302 //menu fading/scrolling effects
307 struct QMacMenuPrivate {
308 QList<QMacMenuAction*> actionItems;
313 bool merged(const QAction *action) const;
314 void addAction(QAction *, QMacMenuAction* =0, QMenuPrivate *qmenu = 0);
315 void addAction(QMacMenuAction *, QMacMenuAction* =0, QMenuPrivate *qmenu = 0);
316 void syncAction(QMacMenuAction *);
317 inline void syncAction(QAction *a) { syncAction(findAction(a)); }
318 void removeAction(QMacMenuAction *);
319 inline void removeAction(QAction *a) { removeAction(findAction(a)); }
320 inline QMacMenuAction *findAction(QAction *a) {
321 for(int i = 0; i < actionItems.size(); i++) {
322 QMacMenuAction *act = actionItems[i];
329 OSMenuRef macMenu(OSMenuRef merge);
330 #ifndef QT_MAC_USE_COCOA
331 void setMacMenuEnabled(bool enable = true);
333 void syncSeparatorsCollapsible(bool collapsible);
334 static QHash<OSMenuRef, OSMenuRef> mergeMenuHash;
335 static QHash<OSMenuRef, QMenuMergeList*> mergeMenuItemsHash;
338 QPointer<QAction> actionAboutToTrigger;
340 bool emitHighlighted;
343 #if defined(Q_WS_WINCE) && !defined(QT_NO_MENUBAR)
344 struct QWceMenuPrivate {
345 QList<QWceMenuAction*> actionItems;
349 void addAction(QAction *, QWceMenuAction* =0);
350 void addAction(QWceMenuAction *, QWceMenuAction* =0);
351 void syncAction(QWceMenuAction *);
352 inline void syncAction(QAction *a) { syncAction(findAction(a)); }
353 void removeAction(QWceMenuAction *);
355 inline void removeAction(QAction *a) { removeAction(findAction(a)); }
356 inline QWceMenuAction *findAction(QAction *a) {
357 for(int i = 0; i < actionItems.size(); i++) {
358 QWceMenuAction *act = actionItems[i];
366 QAction* wceCommands(uint command);
368 #if defined(Q_WS_S60)
369 struct QSymbianMenuPrivate {
370 QList<QSymbianMenuAction*> actionItems;
371 QSymbianMenuPrivate();
372 ~QSymbianMenuPrivate();
373 void addAction(QAction *, QSymbianMenuAction* =0);
374 void addAction(QSymbianMenuAction *, QSymbianMenuAction* =0);
375 void syncAction(QSymbianMenuAction *);
376 inline void syncAction(QAction *a) { syncAction(findAction(a)); }
377 void removeAction(QSymbianMenuAction *);
378 void rebuild(bool reCreate = false);
379 inline void removeAction(QAction *a) { removeAction(findAction(a)); }
380 inline QSymbianMenuAction *findAction(QAction *a) {
381 for(int i = 0; i < actionItems.size(); i++) {
382 QSymbianMenuAction *act = actionItems[i];
390 QPointer<QWidget> noReplayFor;