1 /****************************************************************************
3 ** Copyright (C) 2012 Nokia Corporation and/or its subsidiary(-ies).
4 ** All rights reserved.
5 ** Contact: Nokia Corporation (qt-info@nokia.com)
7 ** This file is part of the QtGui module of the Qt Toolkit.
9 ** $QT_BEGIN_LICENSE:LGPL$
10 ** GNU Lesser General Public License Usage
11 ** This file may be used under the terms of the GNU Lesser General Public
12 ** License version 2.1 as published by the Free Software Foundation and
13 ** appearing in the file LICENSE.LGPL included in the packaging of this
14 ** file. Please review the following information to ensure the GNU Lesser
15 ** General Public License version 2.1 requirements will be met:
16 ** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
18 ** In addition, as a special exception, Nokia gives you certain additional
19 ** rights. These rights are described in the Nokia Qt LGPL Exception
20 ** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
22 ** GNU General Public License Usage
23 ** Alternatively, this file may be used under the terms of the GNU General
24 ** Public License version 3.0 as published by the Free Software Foundation
25 ** and appearing in the file LICENSE.GPL included in the packaging of this
26 ** file. Please review the following information to ensure the GNU General
27 ** Public License version 3.0 requirements will be met:
28 ** http://www.gnu.org/copyleft/gpl.html.
31 ** Alternatively, this file may be used in accordance with the terms and
32 ** conditions contained in a signed written agreement between you and Nokia.
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 "QtWidgets/qmenubar.h"
57 #include "QtWidgets/qstyleoption.h"
59 #include "QtWidgets/qmacdefines_mac.h"
61 #include "QtCore/qdatetime.h"
62 #include "QtCore/qmap.h"
63 #include "QtCore/qhash.h"
64 #include "QtCore/qbasictimer.h"
65 #include "private/qwidget_p.h"
70 #define QT_SYMBIAN_FIRST_MENU_ITEM 32000
71 #define QT_SYMBIAN_LAST_MENU_ITEM 41999 // 10000 items ought to be enough for anybody...
78 void qt_symbian_next_menu_from_action(QWidget* actionContainer);
79 void qt_symbian_show_toplevel(CEikMenuPane* menuPane);
80 void qt_symbian_show_submenu(CEikMenuPane* menuPane, int id);
87 struct QWceMenuAction {
89 QPointer<QAction> action;
91 QWceMenuAction() : menuHandle(0), command(0) {}
95 struct QSymbianMenuAction {
98 CEikMenuPane* menuPane;
99 QPointer<QAction> action;
100 QSymbianMenuAction() : command(0) {}
104 class QMenuPrivate : public QWidgetPrivate
106 Q_DECLARE_PUBLIC(QMenu)
108 QMenuPrivate() : itemsDirty(0), maxIconWidth(0), tabWidth(0), ncols(0),
109 collapsibleSeparators(true), activationRecursionGuard(false), hasHadMouse(0), aboutToHide(0), motions(0),
111 #ifdef QT_KEYPAD_NAVIGATION
115 scroll(0), eventLoop(0), tearoff(0), tornoff(0), tearoffHighlighted(0),
116 hasCheckableItems(0), sloppyAction(0), doChildEffects(false), platformMenu(0)
118 #if defined(Q_WS_WINCE) && !defined(QT_NO_MENUBAR)
129 #if defined(Q_WS_WINCE) && !defined(QT_NO_MENUBAR)
139 static QMenuPrivate *get(QMenu *m) { return m->d_func(); }
140 int scrollerHeight() const;
143 mutable uint itemsDirty : 1;
144 mutable uint maxIconWidth, tabWidth;
145 QRect actionRect(QAction *) const;
147 mutable QVector<QRect> actionRects;
148 mutable QHash<QAction *, QWidget *> widgetItems;
149 void updateActionRects() const;
150 void updateActionRects(const QRect &screen) const;
151 QRect popupGeometry(const QWidget *widget) const;
152 QRect popupGeometry(int screen = -1) const;
153 mutable uint ncols : 4; //4 bits is probably plenty
154 uint collapsibleSeparators : 1;
155 QSize adjustMenuSizeForScreen(const QRect & screen);
156 int getLastVisibleAction() const;
158 bool activationRecursionGuard;
161 static QMenu *mouseDown;
162 QPoint mousePopupPos;
163 uint hasHadMouse : 1;
164 uint aboutToHide : 1;
166 QAction *currentAction;
167 #ifdef QT_KEYPAD_NAVIGATION
168 QAction *selectAction;
169 QAction *cancelAction;
171 QBasicTimer menuDelayTimer;
172 enum SelectionReason {
173 SelectedFromKeyboard,
174 SelectedFromElsewhere
176 QWidget *topCausedWidget() const;
177 QAction *actionAt(QPoint p) const;
178 void setFirstActionActive();
179 void setCurrentAction(QAction *, int popup = -1, SelectionReason reason = SelectedFromElsewhere, bool activateFirst = false);
180 void popupAction(QAction *, int, bool);
181 void setSyncAction();
184 struct QMenuScroller {
185 enum ScrollLocation { ScrollStay, ScrollBottom, ScrollTop, ScrollCenter };
186 enum ScrollDirection { ScrollNone=0, ScrollUp=0x01, ScrollDown=0x02 };
187 uint scrollFlags : 2, scrollDirection : 2;
189 QBasicTimer scrollTimer;
191 QMenuScroller() : scrollFlags(ScrollNone), scrollDirection(ScrollNone), scrollOffset(0) { }
194 void scrollMenu(QMenuScroller::ScrollLocation location, bool active=false);
195 void scrollMenu(QMenuScroller::ScrollDirection direction, bool page=false, bool active=false);
196 void scrollMenu(QAction *action, QMenuScroller::ScrollLocation location, bool active=false);
198 //synchronous operation (ie exec())
199 QEventLoop *eventLoop;
200 QPointer<QAction> syncAction;
203 QString searchBuffer;
204 QBasicTimer searchBufferTimer;
206 //passing of mouse events up the parent hierarchy
207 QPointer<QMenu> activeMenu;
208 bool mouseEventTaken(QMouseEvent *);
210 //used to walk up the popup list
212 QPointer<QWidget> widget;
213 QPointer<QAction> action;
215 virtual QList<QPointer<QWidget> > calcCausedStack() const;
216 QMenuCaused causedPopup;
217 void hideUpToMenuBar();
218 void hideMenu(QMenu *menu, bool justRegister = false);
221 inline QAction *actionAt(int i) const { return q_func()->actions().at(i); }
222 inline int indexOf(QAction *act) const { return q_func()->actions().indexOf(act); }
225 uint tearoff : 1, tornoff : 1, tearoffHighlighted : 1;
226 QPointer<QTornOffMenu> tornPopup;
228 mutable bool hasCheckableItems;
231 static int sloppyDelayTimer;
232 mutable QAction *sloppyAction;
233 QRegion sloppyRegion;
236 QPointer<QAction> defaultAction;
239 QAction *defaultMenuAction;
241 void setOverrideMenuAction(QAction *);
242 void _q_overrideMenuActionDestroyed();
245 void activateAction(QAction *, QAction::ActionEvent, bool self=true);
246 void activateCausedStack(const QList<QPointer<QWidget> > &, QAction *, QAction::ActionEvent, bool);
248 void _q_actionTriggered();
249 void _q_actionHovered();
251 bool hasMouseMoved(const QPoint &globalPos);
253 void updateLayoutDirection();
255 //menu fading/scrolling effects
258 QPlatformMenu *platformMenu;
260 QPointer<QAction> actionAboutToTrigger;
262 #if defined(Q_WS_WINCE) && !defined(QT_NO_MENUBAR)
263 struct QWceMenuPrivate {
264 QList<QWceMenuAction*> actionItems;
268 void addAction(QAction *, QWceMenuAction* =0);
269 void addAction(QWceMenuAction *, QWceMenuAction* =0);
270 void syncAction(QWceMenuAction *);
271 inline void syncAction(QAction *a) { syncAction(findAction(a)); }
272 void removeAction(QWceMenuAction *);
274 inline void removeAction(QAction *a) { removeAction(findAction(a)); }
275 inline QWceMenuAction *findAction(QAction *a) {
276 for(int i = 0; i < actionItems.size(); i++) {
277 QWceMenuAction *act = actionItems[i];
285 QAction* wceCommands(uint command);
287 #if defined(Q_WS_S60)
288 struct QSymbianMenuPrivate {
289 QList<QSymbianMenuAction*> actionItems;
290 QSymbianMenuPrivate();
291 ~QSymbianMenuPrivate();
292 void addAction(QAction *, QSymbianMenuAction* =0);
293 void addAction(QSymbianMenuAction *, QSymbianMenuAction* =0);
294 void syncAction(QSymbianMenuAction *);
295 inline void syncAction(QAction *a) { syncAction(findAction(a)); }
296 void removeAction(QSymbianMenuAction *);
297 void rebuild(bool reCreate = false);
298 inline void removeAction(QAction *a) { removeAction(findAction(a)); }
299 inline QSymbianMenuAction *findAction(QAction *a) {
300 for(int i = 0; i < actionItems.size(); i++) {
301 QSymbianMenuAction *act = actionItems[i];
309 QPointer<QWidget> noReplayFor;