diff options
Diffstat (limited to 'src/gui/widgets/qmenu_p.h')
-rw-r--r-- | src/gui/widgets/qmenu_p.h | 368 |
1 files changed, 368 insertions, 0 deletions
diff --git a/src/gui/widgets/qmenu_p.h b/src/gui/widgets/qmenu_p.h new file mode 100644 index 0000000..61cc3db --- /dev/null +++ b/src/gui/widgets/qmenu_p.h @@ -0,0 +1,368 @@ +/**************************************************************************** +** +** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies). +** Contact: Qt Software Information (qt-info@nokia.com) +** +** This file is part of the QtGui module of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** No Commercial Usage +** This file contains pre-release code and may not be distributed. +** You may use this file in accordance with the terms and conditions +** contained in the either Technology Preview License Agreement or the +** Beta Release License Agreement. +** +** GNU Lesser General Public License Usage +** Alternatively, 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.0, 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. +** +** If you are unsure which license is appropriate for your use, please +** contact the sales department at qt-sales@nokia.com. +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#ifndef QMENU_P_H +#define QMENU_P_H + +// +// 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 "QtGui/qmenubar.h" +#include "QtGui/qstyleoption.h" +#include "QtCore/qdatetime.h" +#include "QtCore/qmap.h" +#include "QtCore/qhash.h" +#include "QtCore/qbasictimer.h" +#include "private/qwidget_p.h" + +QT_BEGIN_NAMESPACE + +#ifndef QT_NO_MENU + +class QTornOffMenu; +class QEventLoop; + +#ifdef Q_WS_MAC +# ifdef __OBJC__ +QT_END_NAMESPACE +@class NSMenuItem; +QT_BEGIN_NAMESPACE +# else +typedef void NSMenuItem; +# endif //__OBJC__ +struct QMacMenuAction { + QMacMenuAction() +#ifndef QT_MAC_USE_COCOA + : command(0) +#else + : menuItem(0) +#endif + , ignore_accel(0), merged(0), menu(0) + { + } + ~QMacMenuAction(); +#ifndef QT_MAC_USE_COCOA + uint command; +#else + NSMenuItem *menuItem; +#endif + uchar ignore_accel : 1; + uchar merged : 1; + QPointer<QAction> action; + OSMenuRef menu; +}; + +struct QMenuMergeItem +{ +#ifndef QT_MAC_USE_COCOA + inline QMenuMergeItem(MenuCommand c, QMacMenuAction *a) : command(c), action(a) { } + MenuCommand command; +#else + inline QMenuMergeItem(NSMenuItem *c, QMacMenuAction *a) : menuItem(c), action(a) { } + NSMenuItem *menuItem; +#endif + QMacMenuAction *action; +}; +typedef QList<QMenuMergeItem> QMenuMergeList; +#endif + +#ifdef Q_OS_WINCE +struct QWceMenuAction { + uint command; + QPointer<QAction> action; + HMENU menuHandle; + QWceMenuAction() : menuHandle(0), command(0) {} +}; +#endif +#ifdef Q_OS_SYMBIAN +class CEikMenuPane; +struct QSymbianMenuAction { + uint command; + int parent; + CEikMenuPane* menuPane; + QPointer<QAction> action; + QSymbianMenuAction() : command(0) {} +}; +#endif + +class QMenuPrivate : public QWidgetPrivate +{ + Q_DECLARE_PUBLIC(QMenu) +public: + QMenuPrivate() : itemsDirty(0), maxIconWidth(0), tabWidth(0), ncols(0), + collapsibleSeparators(true), hasHadMouse(0), aboutToHide(0), motions(0), + currentAction(0), scroll(0), eventLoop(0), tearoff(0), tornoff(0), tearoffHighlighted(0), + hasCheckableItems(0), sloppyAction(0) +#ifdef Q_WS_MAC + ,mac_menu(0) +#endif +#if defined(Q_OS_WINCE) && !defined(QT_NO_MENUBAR) + ,wce_menu(0) +#endif +#ifdef Q_OS_SYMBIAN + ,symbian_menu(0) +#endif +#ifdef QT3_SUPPORT + ,emitHighlighted(false) +#endif + { } + ~QMenuPrivate() + { + delete scroll; +#ifdef Q_WS_MAC + delete mac_menu; +#endif +#if defined(Q_OS_WINCE) && !defined(QT_NO_MENUBAR) + delete wce_menu; +#endif +#ifdef Q_OS_SYMBIAN + delete symbian_menu; +#endif + + } + void init(); + + //item calculations + mutable uint itemsDirty : 1; + mutable uint maxIconWidth, tabWidth; + QRect actionRect(QAction *) const; + mutable QMap<QAction*, QRect> actionRects; + mutable QList<QAction*> actionList; + mutable QHash<QAction *, QWidget *> widgetItems; + void calcActionRects(QMap<QAction*, QRect> &actionRects, QList<QAction*> &actionList) const; + void updateActions(); + QRect popupGeometry(int screen=-1) const; + QList<QAction *> filterActions(const QList<QAction *> &actions) const; + uint ncols : 4; //4 bits is probably plenty + uint collapsibleSeparators : 1; + + uint activationRecursionGuard : 1; + + //selection + static QPointer<QMenu> mouseDown; + QPoint mousePopupPos; + uint hasHadMouse : 1; + uint aboutToHide : 1; + int motions; + QAction *currentAction; + static QBasicTimer menuDelayTimer; + enum SelectionReason { + SelectedFromKeyboard, + SelectedFromElsewhere + }; + QAction *actionAt(QPoint p) const; + void setFirstActionActive(); + void setCurrentAction(QAction *, int popup = -1, SelectionReason reason = SelectedFromElsewhere, bool activateFirst = false); + void popupAction(QAction *, int, bool); + void setSyncAction(); + + //scrolling support + struct QMenuScroller { + enum ScrollLocation { ScrollStay, ScrollBottom, ScrollTop, ScrollCenter }; + enum ScrollDirection { ScrollNone=0, ScrollUp=0x01, ScrollDown=0x02 }; + uint scrollFlags : 2, scrollDirection : 2; + int scrollOffset; + QBasicTimer *scrollTimer; + + QMenuScroller() : scrollFlags(ScrollNone), scrollDirection(ScrollNone), scrollOffset(0), scrollTimer(0) { } + ~QMenuScroller() { delete scrollTimer; } + } *scroll; + void scrollMenu(QMenuScroller::ScrollLocation location, bool active=false); + void scrollMenu(QMenuScroller::ScrollDirection direction, bool page=false, bool active=false); + void scrollMenu(QAction *action, QMenuScroller::ScrollLocation location, bool active=false); + + //synchronous operation (ie exec()) + QEventLoop *eventLoop; + QPointer<QAction> syncAction; + + //search buffer + QString searchBuffer; + QBasicTimer searchBufferTimer; + + //passing of mouse events up the parent heirarchy + QPointer<QMenu> activeMenu; + bool mouseEventTaken(QMouseEvent *); + + //used to walk up the popup list + struct QMenuCaused { + QPointer<QWidget> widget; + QPointer<QAction> action; + }; + virtual QList<QPointer<QWidget> > calcCausedStack() const; + QMenuCaused causedPopup; + void hideUpToMenuBar(); + void hideMenu(QMenu *menu); + + //index mappings + inline QAction *actionAt(int i) const { return q_func()->actions().at(i); } + inline int indexOf(QAction *act) const { return q_func()->actions().indexOf(act); } + + //tear off support + uint tearoff : 1, tornoff : 1, tearoffHighlighted : 1; + QPointer<QTornOffMenu> tornPopup; + + mutable bool hasCheckableItems; + + //sloppy selection + static QBasicTimer sloppyDelayTimer; + QAction *sloppyAction; + QRegion sloppyRegion; + + //default action + QPointer<QAction> defaultAction; + + QAction *menuAction; + QAction *defaultMenuAction; + + void setOverrideMenuAction(QAction *); + void _q_overrideMenuActionDestroyed(); + + //firing of events + void activateAction(QAction *, QAction::ActionEvent, bool self=true); + void activateCausedStack(const QList<QPointer<QWidget> > &, QAction *, QAction::ActionEvent, bool); + + void _q_actionTriggered(); + void _q_actionHovered(); + + bool hasMouseMoved(const QPoint &globalPos); + + //menu fading/scrolling effects + bool doChildEffects; + +#ifdef Q_WS_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); + static QHash<OSMenuRef, OSMenuRef> mergeMenuHash; + static QHash<OSMenuRef, QMenuMergeList*> mergeMenuItemsHash; +#endif + + QPointer<QAction> actionAboutToTrigger; +#ifdef QT3_SUPPORT + bool emitHighlighted; +#endif + +#if defined(Q_OS_WINCE) && !defined(QT_NO_MENUBAR) + struct QWceMenuPrivate { + QList<QWceMenuAction*> actionItems; + HMENU menuHandle; + QWceMenuPrivate(); + ~QWceMenuPrivate(); + void addAction(QAction *, QWceMenuAction* =0); + void addAction(QWceMenuAction *, QWceMenuAction* =0); + void syncAction(QWceMenuAction *); + inline void syncAction(QAction *a) { syncAction(findAction(a)); } + void removeAction(QWceMenuAction *); + void rebuild(bool reCreate = false); + inline void removeAction(QAction *a) { removeAction(findAction(a)); } + inline QWceMenuAction *findAction(QAction *a) { + for(int i = 0; i < actionItems.size(); i++) { + QWceMenuAction *act = actionItems[i]; + if(a == act->action) + return act; + } + return 0; + } + } *wce_menu; + HMENU wceMenu(bool create = false); + QAction* wceCommands(uint command); +#endif +#if defined(Q_OS_SYMBIAN) + struct QSymbianMenuPrivate { + QList<QSymbianMenuAction*> actionItems; + QSymbianMenuPrivate(); + ~QSymbianMenuPrivate(); + void addAction(QAction *, QSymbianMenuAction* =0); + void addAction(QSymbianMenuAction *, QSymbianMenuAction* =0); + void syncAction(QSymbianMenuAction *); + inline void syncAction(QAction *a) { syncAction(findAction(a)); } + void removeAction(QSymbianMenuAction *); + void rebuild(bool reCreate = false); + inline void removeAction(QAction *a) { removeAction(findAction(a)); } + inline QSymbianMenuAction *findAction(QAction *a) { + for(int i = 0; i < actionItems.size(); i++) { + QSymbianMenuAction *act = actionItems[i]; + if(a == act->action) + return act; + } + return 0; + } + } *symbian_menu; + bool symbianCommands(int command); +#endif + QPointer<QWidget> noReplayFor; +}; + +#endif // QT_NO_MENU + +QT_END_NAMESPACE + +#endif // QMENU_P_H |