diff options
Diffstat (limited to 'src/widgets/widgets/qmenu.cpp')
-rw-r--r-- | src/widgets/widgets/qmenu.cpp | 177 |
1 files changed, 137 insertions, 40 deletions
diff --git a/src/widgets/widgets/qmenu.cpp b/src/widgets/widgets/qmenu.cpp index e81359feac..ea3e4c4488 100644 --- a/src/widgets/widgets/qmenu.cpp +++ b/src/widgets/widgets/qmenu.cpp @@ -102,9 +102,9 @@ class QTornOffMenu : public QMenu causedPopup.action = ((QTornOffMenu*)p)->d_func()->causedPopup.action; causedStack = ((QTornOffMenu*)p)->d_func()->calcCausedStack(); } - QList<QPointer<QWidget> > calcCausedStack() const Q_DECL_OVERRIDE { return causedStack; } + QVector<QPointer<QWidget> > calcCausedStack() const Q_DECL_OVERRIDE { return causedStack; } QPointer<QMenu> causedMenu; - QList<QPointer<QWidget> > causedStack; + QVector<QPointer<QWidget> > causedStack; }; public: QTornOffMenu(QMenu *p) : QMenu(*(new QTornOffMenuPrivate(p))) @@ -192,11 +192,10 @@ void QMenuPrivate::syncPlatformMenu() return; QPlatformMenuItem *beforeItem = Q_NULLPTR; - QListIterator<QAction*> it(q->actions()); - it.toBack(); - while (it.hasPrevious()) { + const QList<QAction*> actions = q->actions(); + for (QList<QAction*>::const_reverse_iterator it = actions.rbegin(), end = actions.rend(); it != end; ++it) { QPlatformMenuItem *menuItem = platformMenu->createMenuItem(); - QAction *action = it.previous(); + QAction *action = *it; menuItem->setTag(reinterpret_cast<quintptr>(action)); QObject::connect(menuItem, SIGNAL(activated()), action, SLOT(trigger()), Qt::QueuedConnection); QObject::connect(menuItem, SIGNAL(hovered()), action, SIGNAL(hovered()), Qt::QueuedConnection); @@ -236,9 +235,9 @@ QRect QMenuPrivate::popupGeometry(int screen) const } } -QList<QPointer<QWidget> > QMenuPrivate::calcCausedStack() const +QVector<QPointer<QWidget> > QMenuPrivate::calcCausedStack() const { - QList<QPointer<QWidget> > ret; + QVector<QPointer<QWidget> > ret; for(QWidget *widget = causedPopup.widget; widget; ) { ret.append(widget); if (QTornOffMenu *qtmenu = qobject_cast<QTornOffMenu*>(widget)) @@ -503,8 +502,8 @@ void QMenuPrivate::hideMenu(QMenu *menu) if (activeMenu == menu) activeMenu = 0; menu->d_func()->causedPopup.action = 0; - menu->d_func()->causedPopup.widget = 0; menu->close(); + menu->d_func()->causedPopup.widget = 0; if (previousMouseMenu.data() == menu) handleEnterLeaveEvents(&previousMouseMenu, Q_NULLPTR); } @@ -1110,8 +1109,7 @@ bool QMenuPrivate::mouseEventTaken(QMouseEvent *e) handleEnterLeaveEvents(&previousMouseMenu,qobject_cast<QMenu *>(caused)); if(e->type() != QEvent::MouseButtonRelease || mouseDown == caused) { QMouseEvent new_e(e->type(), cpos, caused->mapTo(caused->topLevelWidget(), cpos), e->screenPos(), - e->button(), e->buttons(), e->modifiers()); - QGuiApplicationPrivate::setMouseEventSource(&new_e, e->source()); + e->button(), e->buttons(), e->modifiers(), e->source()); QApplication::sendEvent(caused, &new_e); return true; } @@ -1123,7 +1121,7 @@ bool QMenuPrivate::mouseEventTaken(QMouseEvent *e) return false; } -void QMenuPrivate::activateCausedStack(const QList<QPointer<QWidget> > &causedStack, QAction *action, QAction::ActionEvent action_e, bool self) +void QMenuPrivate::activateCausedStack(const QVector<QPointer<QWidget> > &causedStack, QAction *action, QAction::ActionEvent action_e, bool self) { QBoolBlocker guard(activationRecursionGuard); if(self) @@ -1171,7 +1169,7 @@ void QMenuPrivate::activateAction(QAction *action, QAction::ActionEvent action_e /* I have to save the caused stack here because it will be undone after popup execution (ie in the hide). Then I iterate over the list to actually send the events. --Sam */ - const QList<QPointer<QWidget> > causedStack = calcCausedStack(); + const QVector<QPointer<QWidget> > causedStack = calcCausedStack(); if (action_e == QAction::Trigger) { #ifndef QT_NO_WHATSTHIS if (!inWhatsThisMode) @@ -1233,7 +1231,7 @@ void QMenuPrivate::_q_actionTriggered() if (!activationRecursionGuard && actionGuard) { //in case the action has not been activated by the mouse //we check the parent hierarchy - QList< QPointer<QWidget> > list; + QVector< QPointer<QWidget> > list; for(QWidget *widget = q->parentWidget(); widget; ) { if (qobject_cast<QMenu*>(widget) #ifndef QT_NO_MENUBAR @@ -1266,7 +1264,7 @@ void QMenuPrivate::_q_platformMenuAboutToShow() #ifdef Q_OS_OSX if (platformMenu) Q_FOREACH (QAction *action, q->actions()) - if (QWidget *widget = widgetItems.value(const_cast<QAction *>(action))) + if (QWidget *widget = widgetItems.value(action)) if (widget->parent() == q) { QPlatformMenuItem *menuItem = platformMenu->menuItemForTag(reinterpret_cast<quintptr>(action)); moveWidgetToPlatformItem(widget, menuItem); @@ -1444,7 +1442,7 @@ void QMenu::initStyleOption(QStyleOptionMenuItem *option, const QAction *action) addSeparator(), and addMenu(). \sa QMenuBar, {fowler}{GUI Design Handbook: Menu, Drop-Down and Pop-Up}, - {Application Example}, {Menus Example}, {Recent Files Example} + {Application Example}, {Menus Example} */ @@ -1572,6 +1570,100 @@ QAction *QMenu::addAction(const QString &text, const QObject *receiver, const ch return action; } +/*!\fn QAction *QMenu::addAction(const QString &text, const QObject *receiver, PointerToMemberFunction method, const QKeySequence &shortcut = 0) + + \since 5.6 + + \overload + + This convenience function creates a new action with the text \a + text and an optional shortcut \a shortcut. The action's + \l{QAction::triggered()}{triggered()} signal is connected to the + \a method of the \a receiver. The function adds the newly created + action to the menu's list of actions and returns it. + + QMenu takes ownership of the returned QAction. +*/ + +/*!\fn QAction *QMenu::addAction(const QString &text, Functor functor, const QKeySequence &shortcut = 0) + + \since 5.6 + + \overload + + This convenience function creates a new action with the text \a + text and an optional shortcut \a shortcut. The action's + \l{QAction::triggered()}{triggered()} signal is connected to the + \a functor. The function adds the newly created + action to the menu's list of actions and returns it. + + QMenu takes ownership of the returned QAction. +*/ + +/*!\fn QAction *QMenu::addAction(const QString &text, const QObject *context, Functor functor, const QKeySequence &shortcut = 0) + + \since 5.6 + + \overload + + This convenience function creates a new action with the text \a + text and an optional shortcut \a shortcut. The action's + \l{QAction::triggered()}{triggered()} signal is connected to the + \a functor. The function adds the newly created + action to the menu's list of actions and returns it. + + If \a context is destroyed, the functor will not be called. + + QMenu takes ownership of the returned QAction. +*/ + +/*!\fn QAction *QMenu::addAction(const QIcon &icon, const QString &text, const QObject *receiver, PointerToMemberFunction method, const QKeySequence &shortcut = 0) + + \since 5.6 + + \overload + + This convenience function creates a new action with an \a icon + and some \a text and an optional shortcut \a shortcut. The action's + \l{QAction::triggered()}{triggered()} signal is connected to the + \a method of the \a receiver. The function adds the newly created + action to the menu's list of actions and returns it. + + QMenu takes ownership of the returned QAction. +*/ + +/*!\fn QAction *QMenu::addAction(const QIcon &icon, const QString &text, Functor functor, const QKeySequence &shortcut = 0) + + \since 5.6 + + \overload + + This convenience function creates a new action with an \a icon + and some \a text and an optional shortcut \a shortcut. The action's + \l{QAction::triggered()}{triggered()} signal is connected to the + \a functor. The function adds the newly created + action to the menu's list of actions and returns it. + + QMenu takes ownership of the returned QAction. +*/ + +/*!\fn QAction *QMenu::addAction(const QIcon &icon, const QString &text, const QObject *context, Functor functor, const QKeySequence &shortcut = 0) + + \since 5.6 + + \overload + + This convenience function creates a new action with an \a icon + and some \a text and an optional shortcut \a shortcut. The action's + \l{QAction::triggered()}{triggered()} signal is connected to the + \a functor. The function adds the newly created + action to the menu's list of actions and returns it. + + If \a context is destroyed, the functor will not be called. + + QMenu takes ownership of the returned QAction. +*/ + /*! \overload @@ -2494,7 +2586,11 @@ void QMenu::mousePressEvent(QMouseEvent *e) Q_D(QMenu); if (d->aboutToHide || d->mouseEventTaken(e)) return; - if (!rect().contains(e->pos())) { + // Workaround for XCB on multiple screens which doesn't have offset. If the menu is open on one screen + // and mouse clicks on second screen, e->pos() is QPoint(0,0) and the menu doesn't hide. This trick makes + // possible to hide the menu when mouse clicks on another screen (e->screenPos() returns correct value). + // Only when mouse clicks in QPoint(0,0) on second screen, the menu doesn't hide. + if ((e->pos().isNull() && !e->screenPos().isNull()) || !rect().contains(e->pos())) { if (d->noReplayFor && QRect(d->noReplayFor->mapToGlobal(QPoint()), d->noReplayFor->size()).contains(e->globalPos())) setAttribute(Qt::WA_NoMouseReplay); @@ -2586,7 +2682,7 @@ QMenu::event(QEvent *e) if (kev->key() == Qt::Key_Up || kev->key() == Qt::Key_Down || kev->key() == Qt::Key_Left || kev->key() == Qt::Key_Right || kev->key() == Qt::Key_Enter || kev->key() == Qt::Key_Return - || kev->key() == Qt::Key_Escape) { + || kev->matches(QKeySequence::Cancel)) { e->accept(); return true; } @@ -2872,27 +2968,6 @@ void QMenu::keyPressEvent(QKeyEvent *e) } break; - case Qt::Key_Escape: -#ifdef QT_KEYPAD_NAVIGATION - case Qt::Key_Back: -#endif - key_consumed = true; - if (d->tornoff) { - close(); - return; - } - { - QPointer<QWidget> caused = d->causedPopup.widget; - d->hideMenu(this); // hide after getting causedPopup -#ifndef QT_NO_MENUBAR - if (QMenuBar *mb = qobject_cast<QMenuBar*>(caused)) { - mb->d_func()->setCurrentAction(d->menuAction); - mb->d_func()->setKeyboardMode(true); - } -#endif - } - break; - case Qt::Key_Space: if (!style()->styleHint(QStyle::SH_Menu_SpaceActivatesItem, 0, this)) break; @@ -2929,6 +3004,28 @@ void QMenu::keyPressEvent(QKeyEvent *e) key_consumed = false; } + if (!key_consumed && (e->matches(QKeySequence::Cancel) +#ifdef QT_KEYPAD_NAVIGATION + || e->key() == Qt::Key_Back +#endif + )) { + key_consumed = true; + if (d->tornoff) { + close(); + return; + } + { + QPointer<QWidget> caused = d->causedPopup.widget; + d->hideMenu(this); // hide after getting causedPopup +#ifndef QT_NO_MENUBAR + if (QMenuBar *mb = qobject_cast<QMenuBar*>(caused)) { + mb->d_func()->setCurrentAction(d->menuAction); + mb->d_func()->setKeyboardMode(true); + } +#endif + } + } + if (!key_consumed) { // send to menu bar if ((!e->modifiers() || e->modifiers() == Qt::AltModifier || e->modifiers() == Qt::ShiftModifier) && e->text().length()==1) { @@ -3049,7 +3146,7 @@ void QMenu::mouseMoveEvent(QMouseEvent *e) d->activeMenu->d_func()->setCurrentAction(0); QMenuSloppyState::MouseEventResult sloppyEventResult = d->sloppyState.processMouseEvent(e->localPos(), action, d->currentAction); - if (sloppyEventResult == QMenuSloppyState::EventShouldBePropogated) { + if (sloppyEventResult == QMenuSloppyState::EventShouldBePropagated) { d->setCurrentAction(action, d->mousePopupDelay); } else if (sloppyEventResult == QMenuSloppyState::EventDiscardsSloppyState) { d->sloppyState.reset(); |