src/gui/widgets/qmenu.cpp
changeset 3 41300fa6a67c
parent 0 1918ee327afb
child 4 3b1da2848fc7
equal deleted inserted replaced
2:56cd8111b7f7 3:41300fa6a67c
    63 
    63 
    64 #include "qmenu_p.h"
    64 #include "qmenu_p.h"
    65 #include "qmenubar_p.h"
    65 #include "qmenubar_p.h"
    66 #include "qwidgetaction.h"
    66 #include "qwidgetaction.h"
    67 #include "qtoolbutton.h"
    67 #include "qtoolbutton.h"
       
    68 #include "qpushbutton.h"
       
    69 #include <private/qpushbutton_p.h>
    68 #include <private/qaction_p.h>
    70 #include <private/qaction_p.h>
    69 #include <private/qsoftkeymanager_p.h>
    71 #include <private/qsoftkeymanager_p.h>
    70 #ifdef QT3_SUPPORT
    72 #ifdef QT3_SUPPORT
    71 #include <qmenudata.h>
    73 #include <qmenudata.h>
    72 #endif // QT3_SUPPORT
    74 #endif // QT3_SUPPORT
   227 void QMenuPrivate::updateActionRects() const
   229 void QMenuPrivate::updateActionRects() const
   228 {
   230 {
   229     Q_Q(const QMenu);
   231     Q_Q(const QMenu);
   230     if (!itemsDirty)
   232     if (!itemsDirty)
   231         return;
   233         return;
   232 		
   234 
   233     q->ensurePolished();
   235     q->ensurePolished();
   234 
   236 
   235     //let's reinitialize the buffer
   237     //let's reinitialize the buffer
   236     actionRects.resize(actions.count());
   238     actionRects.resize(actions.count());
   237     actionRects.fill(QRect());
   239     actionRects.fill(QRect());
   271     ncols = 1;
   273     ncols = 1;
   272     sloppyAction = 0;
   274     sloppyAction = 0;
   273 
   275 
   274     for (int i = 0; i < actions.count(); ++i) {
   276     for (int i = 0; i < actions.count(); ++i) {
   275         QAction *action = actions.at(i);
   277         QAction *action = actions.at(i);
   276         if (action->isSeparator() || !action->isVisible() || widgetItems.at(i))
   278         if (action->isSeparator() || !action->isVisible() || widgetItems.contains(action))
   277             continue;
   279             continue;
   278         //..and some members
   280         //..and some members
   279         hasCheckableItems |= action->isCheckable();
   281         hasCheckableItems |= action->isCheckable();
   280         QIcon is = action->icon();
   282         QIcon is = action->icon();
   281         if (!is.isNull()) {
   283         if (!is.isNull()) {
   290         QAction *action = actions.at(i);
   292         QAction *action = actions.at(i);
   291 
   293 
   292         if (!action->isVisible() ||
   294         if (!action->isVisible() ||
   293             (collapsibleSeparators && previousWasSeparator && action->isSeparator()))
   295             (collapsibleSeparators && previousWasSeparator && action->isSeparator()))
   294             continue; // we continue, this action will get an empty QRect
   296             continue; // we continue, this action will get an empty QRect
   295         
   297 
   296         previousWasSeparator = action->isSeparator();
   298         previousWasSeparator = action->isSeparator();
   297 
   299 
   298         //let the style modify the above size..
   300         //let the style modify the above size..
   299         QStyleOptionMenuItem opt;
   301         QStyleOptionMenuItem opt;
   300         q->initStyleOption(&opt, action);
   302         q->initStyleOption(&opt, action);
   301         const QFontMetrics &fm = opt.fontMetrics;
   303         const QFontMetrics &fm = opt.fontMetrics;
   302 
   304 
   303         QSize sz;
   305         QSize sz;
   304         if (QWidget *w = widgetItems.at(i)) {
   306         if (QWidget *w = widgetItems.value(action)) {
   305           sz = w->sizeHint().expandedTo(w->minimumSize()).expandedTo(w->minimumSizeHint()).boundedTo(w->maximumSize());
   307           sz = w->sizeHint().expandedTo(w->minimumSize()).expandedTo(w->minimumSizeHint()).boundedTo(w->maximumSize());
   306         } else {
   308         } else {
   307             //calc what I think the size is..
   309             //calc what I think the size is..
   308             if (action->isSeparator()) {
   310             if (action->isSeparator()) {
   309                 sz = QSize(2, 2);
   311                 sz = QSize(2, 2);
   368         }
   370         }
   369         rect.translate(x, y);                        //move
   371         rect.translate(x, y);                        //move
   370         rect.setWidth(max_column_width); //uniform width
   372         rect.setWidth(max_column_width); //uniform width
   371 
   373 
   372         //we need to update the widgets geometry
   374         //we need to update the widgets geometry
   373         if (QWidget *widget = widgetItems.at(i)) {
   375         if (QWidget *widget = widgetItems.value(actions.at(i))) {
   374             widget->setGeometry(rect);
   376             widget->setGeometry(rect);
   375             widget->setVisible(actions.at(i)->isVisible());
   377             widget->setVisible(actions.at(i)->isVisible());
   376         }
   378         }
   377 
   379 
   378         y += rect.height();
   380         y += rect.height();
   415                 caused = m->d_func()->causedPopup.widget;
   417                 caused = m->d_func()->causedPopup.widget;
   416                 if (!m->d_func()->tornoff)
   418                 if (!m->d_func()->tornoff)
   417                     hideMenu(m, fadeMenus);
   419                     hideMenu(m, fadeMenus);
   418                 if (!fadeMenus) // Mac doesn't clear the action until after hidden.
   420                 if (!fadeMenus) // Mac doesn't clear the action until after hidden.
   419                     m->d_func()->setCurrentAction(0);
   421                     m->d_func()->setCurrentAction(0);
   420             } else {
   422             } else {                caused = 0;
   421 #ifndef QT_NO_TOOLBUTTON
       
   422                 if (qobject_cast<QToolButton*>(caused) == 0)
       
   423 #endif
       
   424                     qWarning("QMenu: Internal error");
       
   425                 caused = 0;
       
   426             }
   423             }
   427         }
   424         }
   428 #if defined(Q_WS_MAC)
   425 #if defined(Q_WS_MAC)
   429         if (fadeMenus) {
   426         if (fadeMenus) {
   430             QEventLoop eventLoop;
   427             QEventLoop eventLoop;
   581                     popupAction(currentAction, popup, activateFirst);
   578                     popupAction(currentAction, popup, activateFirst);
   582             }
   579             }
   583             q->update(actionRect(action));
   580             q->update(actionRect(action));
   584 
   581 
   585             if (reason == SelectedFromKeyboard) {
   582             if (reason == SelectedFromKeyboard) {
   586                 const int actionIndex = actions.indexOf(action);
   583                 QWidget *widget = widgetItems.value(action);
   587                 QWidget *widget = widgetItems.at(actionIndex);
       
   588                 if (widget) {
   584                 if (widget) {
   589                     if (widget->focusPolicy() != Qt::NoFocus)
   585                     if (widget->focusPolicy() != Qt::NoFocus)
   590                         widget->setFocus(Qt::TabFocusReason);
   586                         widget->setFocus(Qt::TabFocusReason);
   591                 } else {
   587                 } else {
   592                     //when the action has no QWidget, the QMenu itself should
   588                     //when the action has no QWidget, the QMenu itself should
   601             if (popup != -1)
   597             if (popup != -1)
   602                 hideActiveMenu = 0; //will be done "later"
   598                 hideActiveMenu = 0; //will be done "later"
   603         }
   599         }
   604 #ifndef QT_NO_STATUSTIP
   600 #ifndef QT_NO_STATUSTIP
   605     }  else if (previousAction) {
   601     }  else if (previousAction) {
   606         QWidget *w = causedPopup.widget;
   602         previousAction->d_func()->showStatusText(topCausedWidget(), QString());
   607         while (QMenu *m = qobject_cast<QMenu*>(w))
       
   608             w = m->d_func()->causedPopup.widget;
       
   609         if (w) {
       
   610             QString empty;
       
   611             QStatusTipEvent tip(empty);
       
   612             QApplication::sendEvent(w, &tip);
       
   613         }
       
   614 #endif
   603 #endif
   615     }
   604     }
   616     if (hideActiveMenu) {
   605     if (hideActiveMenu) {
   617         activeMenu = 0;
   606         activeMenu = 0;
   618 #ifndef QT_NO_EFFECTS
   607 #ifndef QT_NO_EFFECTS
   620         qFadeEffect(0);
   609         qFadeEffect(0);
   621         qScrollEffect(0);
   610         qScrollEffect(0);
   622 #endif
   611 #endif
   623         hideMenu(hideActiveMenu);
   612         hideMenu(hideActiveMenu);
   624     }
   613     }
       
   614 }
       
   615 
       
   616 //return the top causedPopup.widget that is not a QMenu
       
   617 QWidget *QMenuPrivate::topCausedWidget() const
       
   618 {
       
   619     QWidget* top = causedPopup.widget;
       
   620     while (QMenu* m = qobject_cast<QMenu *>(top))
       
   621         top = m->d_func()->causedPopup.widget;
       
   622     return top;
   625 }
   623 }
   626 
   624 
   627 QAction *QMenuPrivate::actionAt(QPoint p) const
   625 QAction *QMenuPrivate::actionAt(QPoint p) const
   628 {
   626 {
   629     if (!q_func()->rect().contains(p))     //sanity check
   627     if (!q_func()->rect().contains(p))     //sanity check
   650 
   648 
   651 void QMenuPrivate::_q_overrideMenuActionDestroyed()
   649 void QMenuPrivate::_q_overrideMenuActionDestroyed()
   652 {
   650 {
   653     menuAction=defaultMenuAction;
   651     menuAction=defaultMenuAction;
   654 }
   652 }
       
   653 
       
   654 
       
   655 void QMenuPrivate::updateLayoutDirection()
       
   656 {
       
   657     Q_Q(QMenu);
       
   658     //we need to mimic the cause of the popup's layout direction
       
   659     //to allow setting it on a mainwindow for example
       
   660     //we call setLayoutDirection_helper to not overwrite a user-defined value
       
   661     if (!q->testAttribute(Qt::WA_SetLayoutDirection)) {
       
   662         if (QWidget *w = causedPopup.widget)
       
   663             setLayoutDirection_helper(w->layoutDirection());
       
   664         else if (QWidget *w = q->parentWidget())
       
   665             setLayoutDirection_helper(w->layoutDirection());
       
   666         else
       
   667             setLayoutDirection_helper(QApplication::layoutDirection());
       
   668     }
       
   669 }
       
   670 
   655 
   671 
   656 /*!
   672 /*!
   657     Returns the action associated with this menu.
   673     Returns the action associated with this menu.
   658 */
   674 */
   659 QAction *QMenu::menuAction() const
   675 QAction *QMenu::menuAction() const
   798         for (int i = 0; i < actionRects.count(); ++i) {
   814         for (int i = 0; i < actionRects.count(); ++i) {
   799             QRect &current = actionRects[i];
   815             QRect &current = actionRects[i];
   800             current.moveTop(current.top() + delta);
   816             current.moveTop(current.top() + delta);
   801 
   817 
   802             //we need to update the widgets geometry
   818             //we need to update the widgets geometry
   803             if (QWidget *w = widgetItems.at(i))
   819             if (QWidget *w = widgetItems.value(actions.at(i)))
   804                 w->setGeometry(current);
   820                 w->setGeometry(current);
   805         }
   821         }
   806     }
   822     }
   807     scroll->scrollOffset += delta;
   823     scroll->scrollOffset += delta;
   808     scroll->scrollFlags = newScrollFlags;
   824     scroll->scrollFlags = newScrollFlags;
  1093             int actionIndex = indexOf(action) + 1;
  1109             int actionIndex = indexOf(action) + 1;
  1094             QAccessible::updateAccessibility(q, actionIndex, QAccessible::Focus);
  1110             QAccessible::updateAccessibility(q, actionIndex, QAccessible::Focus);
  1095             QAccessible::updateAccessibility(q, actionIndex, QAccessible::Selection);
  1111             QAccessible::updateAccessibility(q, actionIndex, QAccessible::Selection);
  1096         }
  1112         }
  1097 #endif
  1113 #endif
  1098         QWidget *w = causedPopup.widget;
  1114         action->showStatusText(topCausedWidget());
  1099         while (QMenu *m = qobject_cast<QMenu*>(w))
       
  1100             w = m->d_func()->causedPopup.widget;
       
  1101         action->showStatusText(w);
       
  1102     } else {
  1115     } else {
  1103         actionAboutToTrigger = 0;
  1116         actionAboutToTrigger = 0;
  1104     }
  1117     }
  1105 }
  1118 }
  1106 
  1119 
  1107 void QMenuPrivate::_q_actionTriggered()
  1120 void QMenuPrivate::_q_actionTriggered()
  1108 {
  1121 {
  1109     Q_Q(QMenu);
  1122     Q_Q(QMenu);
  1110     if (QAction *action = qobject_cast<QAction *>(q->sender())) {
  1123     if (QAction *action = qobject_cast<QAction *>(q->sender())) {
       
  1124         QWeakPointer<QAction> actionGuard = action;
  1111 #ifdef QT3_SUPPORT
  1125 #ifdef QT3_SUPPORT
  1112         //we store it here because the action might be deleted/changed by connected slots
  1126         //we store it here because the action might be deleted/changed by connected slots
  1113         const int id = q->findIdForAction(action);
  1127         const int id = q->findIdForAction(action);
  1114 #endif
  1128 #endif
  1115         emit q->triggered(action);
  1129         emit q->triggered(action);
  1116 #ifdef QT3_SUPPORT
  1130 #ifdef QT3_SUPPORT
  1117         emit q->activated(id);
  1131         emit q->activated(id);
  1118 #endif
  1132 #endif
  1119 
  1133 
  1120         if (!activationRecursionGuard) {
  1134         if (!activationRecursionGuard && actionGuard) {
  1121             //in case the action has not been activated by the mouse
  1135             //in case the action has not been activated by the mouse
  1122             //we check the parent hierarchy
  1136             //we check the parent hierarchy
  1123             QList< QPointer<QWidget> > list;
  1137             QList< QPointer<QWidget> > list;
  1124             for(QWidget *widget = q->parentWidget(); widget; ) {
  1138             for(QWidget *widget = q->parentWidget(); widget; ) {
  1125                 if (qobject_cast<QMenu*>(widget) 
  1139                 if (qobject_cast<QMenu*>(widget)
  1126 #ifndef QT_NO_MENUBAR
  1140 #ifndef QT_NO_MENUBAR
  1127                     || qobject_cast<QMenuBar*>(widget)
  1141                     || qobject_cast<QMenuBar*>(widget)
  1128 #endif
  1142 #endif
  1129                     ) {
  1143                     ) {
  1130                     list.append(widget);
  1144                     list.append(widget);
  1287 
  1301 
  1288     A menu consists of a list of action items. Actions are added with
  1302     A menu consists of a list of action items. Actions are added with
  1289     the addAction(), addActions() and insertAction() functions. An action
  1303     the addAction(), addActions() and insertAction() functions. An action
  1290     is represented vertically and rendered by QStyle. In addition, actions
  1304     is represented vertically and rendered by QStyle. In addition, actions
  1291     can have a text label, an optional icon drawn on the very left side,
  1305     can have a text label, an optional icon drawn on the very left side,
  1292     and shortcut key sequence such as "Ctrl+X". 
  1306     and shortcut key sequence such as "Ctrl+X".
  1293 
  1307 
  1294     The existing actions held by a menu can be found with actions().
  1308     The existing actions held by a menu can be found with actions().
  1295 
  1309 
  1296     There are four kinds of action items: separators, actions that
  1310     There are four kinds of action items: separators, actions that
  1297     show a submenu, widgets, and actions that perform an action.
  1311     show a submenu, widgets, and actions that perform an action.
  1390     Destroys the menu.
  1404     Destroys the menu.
  1391 */
  1405 */
  1392 QMenu::~QMenu()
  1406 QMenu::~QMenu()
  1393 {
  1407 {
  1394     Q_D(QMenu);
  1408     Q_D(QMenu);
  1395     for (int i = 0; i < d->widgetItems.count(); ++i) {
  1409     QHash<QAction *, QWidget *>::iterator it = d->widgetItems.begin();
  1396         if (QWidget *widget = d->widgetItems.at(i)) {
  1410     for (; it != d->widgetItems.end(); ++it) {
  1397             QWidgetAction *action = static_cast<QWidgetAction *>(d->actions.at(i));
  1411         if (QWidget *widget = it.value()) {
       
  1412             QWidgetAction *action = static_cast<QWidgetAction *>(it.key());
  1398             action->releaseWidget(widget);
  1413             action->releaseWidget(widget);
  1399             d->widgetItems[i] = 0;
  1414             *it = 0;
  1400         }
  1415         }
  1401     }
  1416     }
  1402 
  1417 
  1403     if (d->eventLoop)
  1418     if (d->eventLoop)
  1404         d->eventLoop->exit();
  1419         d->eventLoop->exit();
  1795         d->scroll->scrollFlags = QMenuPrivate::QMenuScroller::ScrollNone;
  1810         d->scroll->scrollFlags = QMenuPrivate::QMenuScroller::ScrollNone;
  1796     }
  1811     }
  1797     d->tearoffHighlighted = 0;
  1812     d->tearoffHighlighted = 0;
  1798     d->motions = 0;
  1813     d->motions = 0;
  1799     d->doChildEffects = true;
  1814     d->doChildEffects = true;
       
  1815     d->updateLayoutDirection();
  1800 
  1816 
  1801 #ifndef QT_NO_MENUBAR
  1817 #ifndef QT_NO_MENUBAR
  1802     // if this menu is part of a chain attached to a QMenuBar, set the
  1818     // if this menu is part of a chain attached to a QMenuBar, set the
  1803     // _NET_WM_WINDOW_TYPE_DROPDOWN_MENU X11 window type
  1819     // _NET_WM_WINDOW_TYPE_DROPDOWN_MENU X11 window type
  1804     QWidget* top = this;
  1820     setAttribute(Qt::WA_X11NetWmWindowTypeDropDownMenu, qobject_cast<QMenuBar *>(d->topCausedWidget()) != 0);
  1805     while (QMenu* m = qobject_cast<QMenu *>(top))
       
  1806         top = m->d_func()->causedPopup.widget;
       
  1807     setAttribute(Qt::WA_X11NetWmWindowTypeDropDownMenu, qobject_cast<QMenuBar *>(top) != 0);
       
  1808 #endif
  1821 #endif
  1809 
  1822 
  1810     ensurePolished(); // Get the right font
  1823     ensurePolished(); // Get the right font
  1811     emit aboutToShow();
  1824     emit aboutToShow();
       
  1825     const bool actionListChanged = d->itemsDirty;
  1812     d->updateActionRects();
  1826     d->updateActionRects();
  1813     QPoint pos = p;
  1827     QPoint pos;
       
  1828     QPushButton *causedButton = qobject_cast<QPushButton*>(d->causedPopup.widget);
       
  1829     if (actionListChanged && causedButton)
       
  1830         pos = QPushButtonPrivate::get(causedButton)->adjustedMenuPosition();
       
  1831     else
       
  1832         pos = p;
       
  1833 
  1814     QSize size = sizeHint();
  1834     QSize size = sizeHint();
  1815     QRect screen;
  1835     QRect screen;
  1816 #ifndef QT_NO_GRAPHICSVIEW
  1836 #ifndef QT_NO_GRAPHICSVIEW
  1817     bool isEmbedded = d->nearestGraphicsProxyWidget(this);
  1837     bool isEmbedded = d->nearestGraphicsProxyWidget(this);
  1818     if (isEmbedded)
  1838     if (isEmbedded)
  1876         //handle popup falling "off screen"
  1896         //handle popup falling "off screen"
  1877         if (isRightToLeft()) {
  1897         if (isRightToLeft()) {
  1878             if(snapToMouse) //position flowing left from the mouse
  1898             if(snapToMouse) //position flowing left from the mouse
  1879                 pos.setX(mouse.x()-size.width());
  1899                 pos.setX(mouse.x()-size.width());
  1880 
  1900 
       
  1901 #ifndef QT_NO_MENUBAR
       
  1902             //if in a menubar, it should be right-aligned
       
  1903             if (qobject_cast<QMenuBar*>(d->causedPopup.widget))
       
  1904                 pos.rx() -= size.width();
       
  1905 #endif //QT_NO_MENUBAR
       
  1906 
  1881             if (pos.x() < screen.left()+desktopFrame)
  1907             if (pos.x() < screen.left()+desktopFrame)
  1882                 pos.setX(qMax(p.x(), screen.left()+desktopFrame));
  1908                 pos.setX(qMax(p.x(), screen.left()+desktopFrame));
  1883             if (pos.x()+size.width()-1 > screen.right()-desktopFrame)
  1909             if (pos.x()+size.width()-1 > screen.right()-desktopFrame)
  1884                 pos.setX(qMax(p.x()-size.width(), screen.right()-desktopFrame-size.width()+1));
  1910                 pos.setX(qMax(p.x()-size.width(), screen.right()-desktopFrame-size.width()+1));
  1885         } else {
  1911         } else {
  1886             if (pos.x()+size.width()-1 > screen.right()-desktopFrame)
  1912             if (pos.x()+size.width()-1 > screen.right()-desktopFrame)
  1887                 pos.setX(qMin(p.x()+size.width(), screen.right()-desktopFrame-size.width()+1));
  1913                 pos.setX(screen.right()-desktopFrame-size.width()+1);
  1888             if (pos.x() < screen.left()+desktopFrame)
  1914             if (pos.x() < screen.left()+desktopFrame)
  1889                 pos.setX(qMax(p.x(), screen.left() + desktopFrame));
  1915                 pos.setX(screen.left() + desktopFrame);
  1890         }
  1916         }
  1891         if (pos.y() + size.height() - 1 > screen.bottom() - desktopFrame) {
  1917         if (pos.y() + size.height() - 1 > screen.bottom() - desktopFrame) {
  1892             if(snapToMouse)
  1918             if(snapToMouse)
  1893                 pos.setY(qMin(mouse.y() - (size.height() + desktopFrame), screen.bottom()-desktopFrame-size.height()+1));
  1919                 pos.setY(qMin(mouse.y() - (size.height() + desktopFrame), screen.bottom()-desktopFrame-size.height()+1));
  1894             else
  1920             else
  2145     //draw the items that need updating..
  2171     //draw the items that need updating..
  2146     for (int i = 0; i < d->actions.count(); ++i) {
  2172     for (int i = 0; i < d->actions.count(); ++i) {
  2147         QAction *action = d->actions.at(i);
  2173         QAction *action = d->actions.at(i);
  2148         QRect adjustedActionRect = d->actionRects.at(i);
  2174         QRect adjustedActionRect = d->actionRects.at(i);
  2149         if (!e->rect().intersects(adjustedActionRect)
  2175         if (!e->rect().intersects(adjustedActionRect)
  2150             || d->widgetItems.at(i))
  2176             || d->widgetItems.value(action))
  2151            continue;
  2177            continue;
  2152         //set the clip region to be extra safe (and adjust for the scrollers)
  2178         //set the clip region to be extra safe (and adjust for the scrollers)
  2153         QRegion adjustedActionReg(adjustedActionRect);
  2179         QRegion adjustedActionReg(adjustedActionRect);
  2154         emptyArea -= adjustedActionReg;
  2180         emptyArea -= adjustedActionReg;
  2155         p.setClipRegion(adjustedActionReg);
  2181         p.setClipRegion(adjustedActionReg);
  2278 
  2304 
  2279     if (action && action == d->currentAction) {
  2305     if (action && action == d->currentAction) {
  2280         if (action->menu())
  2306         if (action->menu())
  2281             action->menu()->d_func()->setFirstActionActive();
  2307             action->menu()->d_func()->setFirstActionActive();
  2282         else {
  2308         else {
  2283 #if defined(Q_WS_WIN) && !defined(QT_NO_MENUBAR)
  2309 #if defined(Q_WS_WIN)
  2284             //On Windows only context menus can be activated with the right button
  2310             //On Windows only context menus can be activated with the right button
  2285             bool isContextMenu = true;
  2311             if (e->button() == Qt::LeftButton || d->topCausedWidget() == 0)
  2286             const QWidget *cause = d->causedPopup.widget;
       
  2287             while (cause) {
       
  2288                 //if the popup was caused by either QMenuBar or a QToolButton, it is not a context menu
       
  2289                 if (qobject_cast<const QMenuBar *>(cause) || qobject_cast<const QToolButton *>(cause)) {
       
  2290                     isContextMenu = false;
       
  2291                     break;
       
  2292                 } else if (const QMenu *menu = qobject_cast<const QMenu *>(cause)) {
       
  2293                     cause = menu->d_func()->causedPopup.widget;
       
  2294                 } else {
       
  2295                     break;
       
  2296                 }
       
  2297             }
       
  2298             if (e->button() == Qt::LeftButton || isContextMenu)
       
  2299 #endif
  2312 #endif
  2300                 d->activateAction(action, QAction::Trigger);
  2313                 d->activateAction(action, QAction::Trigger);
  2301         }
  2314         }
  2302     } else if (d->hasMouseMoved(e->globalPos())) {
  2315     } else if (d->hasMouseMoved(e->globalPos())) {
  2303         d->hideUpToMenuBar();
  2316         d->hideUpToMenuBar();
  2342 bool
  2355 bool
  2343 QMenu::event(QEvent *e)
  2356 QMenu::event(QEvent *e)
  2344 {
  2357 {
  2345     Q_D(QMenu);
  2358     Q_D(QMenu);
  2346     switch (e->type()) {
  2359     switch (e->type()) {
       
  2360     case QEvent::Polish:
       
  2361         d->updateLayoutDirection();
       
  2362         break;
  2347     case QEvent::ShortcutOverride: {
  2363     case QEvent::ShortcutOverride: {
  2348             QKeyEvent *kev = static_cast<QKeyEvent*>(e);
  2364             QKeyEvent *kev = static_cast<QKeyEvent*>(e);
  2349             if (kev->key() == Qt::Key_Up || kev->key() == Qt::Key_Down
  2365             if (kev->key() == Qt::Key_Up || kev->key() == Qt::Key_Down
  2350                 || kev->key() == Qt::Key_Left || kev->key() == Qt::Key_Right
  2366                 || kev->key() == Qt::Key_Left || kev->key() == Qt::Key_Right
  2351                 || kev->key() == Qt::Key_Enter || kev->key() == Qt::Key_Return
  2367                 || kev->key() == Qt::Key_Enter || kev->key() == Qt::Key_Return
  2744                     d->activateAction(nextAction, QAction::Trigger);
  2760                     d->activateAction(nextAction, QAction::Trigger);
  2745                 }
  2761                 }
  2746             }
  2762             }
  2747         }
  2763         }
  2748         if (!key_consumed) {
  2764         if (!key_consumed) {
  2749             if (QWidget *caused = d->causedPopup.widget) {
       
  2750                 while(QMenu *m = qobject_cast<QMenu*>(caused))
       
  2751                     caused = m->d_func()->causedPopup.widget;
       
  2752 #ifndef QT_NO_MENUBAR
  2765 #ifndef QT_NO_MENUBAR
  2753                 if (QMenuBar *mb = qobject_cast<QMenuBar*>(caused)) {
  2766             if (QMenuBar *mb = qobject_cast<QMenuBar*>(d->topCausedWidget())) {
  2754                     QAction *oldAct = mb->d_func()->currentAction;
  2767                 QAction *oldAct = mb->d_func()->currentAction;
  2755                     QApplication::sendEvent(mb, e);
  2768                 QApplication::sendEvent(mb, e);
  2756                     if (mb->d_func()->currentAction != oldAct)
  2769                 if (mb->d_func()->currentAction != oldAct)
  2757                         key_consumed = true;
  2770                     key_consumed = true;
  2758                 }
       
  2759 #endif
       
  2760             }
  2771             }
       
  2772 #endif
  2761         }
  2773         }
  2762 
  2774 
  2763 #ifdef Q_OS_WIN32
  2775 #ifdef Q_OS_WIN32
  2764         if (key_consumed && (e->key() == Qt::Key_Control || e->key() == Qt::Key_Shift || e->key() == Qt::Key_Meta))
  2776         if (key_consumed && (e->key() == Qt::Key_Control || e->key() == Qt::Key_Shift || e->key() == Qt::Key_Meta))
  2765             QApplication::beep();
  2777             QApplication::beep();
  2856     if (e->type() == QEvent::ActionAdded) {
  2868     if (e->type() == QEvent::ActionAdded) {
  2857         if(!d->tornoff) {
  2869         if(!d->tornoff) {
  2858             connect(e->action(), SIGNAL(triggered()), this, SLOT(_q_actionTriggered()));
  2870             connect(e->action(), SIGNAL(triggered()), this, SLOT(_q_actionTriggered()));
  2859             connect(e->action(), SIGNAL(hovered()), this, SLOT(_q_actionHovered()));
  2871             connect(e->action(), SIGNAL(hovered()), this, SLOT(_q_actionHovered()));
  2860         }
  2872         }
  2861         QWidget *widget = 0;
  2873         if (QWidgetAction *wa = qobject_cast<QWidgetAction *>(e->action())) {
  2862         if (QWidgetAction *wa = qobject_cast<QWidgetAction *>(e->action()))
  2874             QWidget *widget = wa->requestWidget(this);
  2863             widget = wa->requestWidget(this);
  2875             if (widget)
  2864 
  2876                 d->widgetItems.insert(wa, widget);
  2865         int index = d->actions.indexOf(e->action());
  2877         }
  2866         Q_ASSERT(index != -1);
       
  2867         d->widgetItems.insert(index, widget);
       
  2868 
       
  2869     } else if (e->type() == QEvent::ActionRemoved) {
  2878     } else if (e->type() == QEvent::ActionRemoved) {
  2870         e->action()->disconnect(this);
  2879         e->action()->disconnect(this);
  2871         if (e->action() == d->currentAction)
  2880         if (e->action() == d->currentAction)
  2872             d->currentAction = 0;
  2881             d->currentAction = 0;
  2873         int index = d->actions.indexOf(e->before()) + 1;
       
  2874         if (QWidgetAction *wa = qobject_cast<QWidgetAction *>(e->action())) {
  2882         if (QWidgetAction *wa = qobject_cast<QWidgetAction *>(e->action())) {
  2875             if (QWidget *widget = d->widgetItems.at(index))
  2883             if (QWidget *widget = d->widgetItems.value(wa))
  2876                 wa->releaseWidget(widget);
  2884                 wa->releaseWidget(widget);
  2877         }
  2885         }
  2878         Q_ASSERT(index != -1);
  2886         d->widgetItems.remove(e->action());
  2879         d->widgetItems.removeAt(index);
       
  2880     }
  2887     }
  2881 
  2888 
  2882 #ifdef Q_WS_MAC
  2889 #ifdef Q_WS_MAC
  2883     if (d->mac_menu) {
  2890     if (d->mac_menu) {
  2884         if (e->type() == QEvent::ActionAdded)
  2891         if (e->type() == QEvent::ActionAdded)