6#include <QtWidgets/private/qtwidgetsglobal_p.h>
7#include <QtWidgets/private/qwidgetwindow_p.h>
9#include "qactiongroup.h"
16#include <qpa/qplatformtheme.h>
18#if QT_CONFIG(accessibility)
22# include <private/qeffects_p.h>
24#if QT_CONFIG(whatsthis)
33#if QT_CONFIG(toolbutton)
41#include <private/qpushbutton_p.h>
42#include <private/qaction_p.h>
43#include <private/qguiapplication_p.h>
44#include <qpa/qplatformtheme.h>
45#include <private/qstyle_p.h>
60 QTornOffMenuPrivate(
QMenu *
p) : causedMenu(
p), initialized(
false) {
64 causedStack =
p->d_func()->calcCausedStack();
67 void setMenuSize(
const QSize &menuSize) {
70 const QPoint p = (!initialized) ? causedMenu->pos() :
q->pos();
79 size.setHeight(
screen.height() - desktopFrame * 2 - titleBarHeight);
81 q->setFixedSize(
size);
105#if QT_CONFIG(style_stylesheet)
108 if (
style() !=
p->style())
118 d->initialized =
true;
123 if (
menu !=
d->causedMenu)
125 auto action =
static_cast<QAction *
>(act->action());
135 if (
d->initialized) {
161#if QT_CONFIG(whatsthis)
167 setOverrideMenuAction(
nullptr);
169 if (!tornPopup.isNull())
170 tornPopup->updateWindowTitle();
178 sloppyState.initialize(
q);
179 delayState.initialize(
q);
214 beforeItem = menuItem;
246#if QT_CONFIG(shortcut)
247 item->setShortcut(action->shortcut());
256 if (action->
menu()) {
257 if (!action->
menu()->platformMenu())
259 item->setMenu(action->
menu()->platformMenu());
261 item->setMenu(
nullptr);
273 copyActionToPlatformItem(action, menuItem);
295 if (useFullScreenForPopup())
308 ret += qtmenu->d_func()->causedStack;
310 widget = qmenu->d_func()->causedPopup.widget;
319#if QT_CONFIG(menubar)
320 return qobject_cast<const QMenuBar *>(topCausedWidget()) ==
nullptr;
328 updateActionRects(popupGeometry());
341 actionRects.fill(
QRect());
343 int lastVisibleAction = getLastVisibleAction();
354 const int base_y = vmargin + fw + topmargin + (
scroll ?
scroll->scrollOffset : 0) + tearoffHeight;
355 const int column_max_y =
screen.height() - 2 * deskFw - (vmargin + bottommargin + fw);
356 int max_column_width = 0;
362 hasCheckableItems =
false;
373 maxIconWidth = qMax<uint>(maxIconWidth, icone + 4);
379 bool previousWasSeparator =
true;
380#if QT_CONFIG(shortcut)
381 const bool contextMenu = isContextMenu();
383 for(
int i = 0;
i <= lastVisibleAction;
i++) {
390 (collapsibleSeparators && previousWasSeparator && isPlainSeparator))
393 previousWasSeparator = isPlainSeparator;
397 q->initStyleOption(&
opt, action);
401 if (
QWidget *
w = widgetItems.value(action)) {
402 sz =
w->sizeHint().
expandedTo(
w->minimumSize()).expandedTo(
w->minimumSizeHint()).boundedTo(
w->maximumSize());
413#if QT_CONFIG(shortcut)
435 max_column_width =
qMax(max_column_width, sz.
width());
448 max_column_width += tabWidth;
451 const int min_column_width =
q->minimumWidth() - (sfcMargin + leftmargin + rightmargin + 2 * (fw + hmargin));
452 max_column_width =
qMax(min_column_width, max_column_width);
456 int x = hmargin + fw + leftmargin;
464 x += max_column_width + hmargin;
485 for (;lastVisibleAction >= 0; --lastVisibleAction) {
489 if (action->
isSeparator() && collapsibleSeparators)
494 return lastVisibleAction;
507 return actionRects.at(
index);
515 QWidget *caused = causedPopup.widget;
518#if QT_CONFIG(menubar)
519 if (
QMenuBar *mb = qobject_cast<QMenuBar*>(caused)) {
520 mb->d_func()->setCurrentAction(
nullptr);
521 mb->d_func()->setKeyboardMode(
false);
525 if (
QMenu *
m = qobject_cast<QMenu*>(caused)) {
526 caused =
m->d_func()->causedPopup.widget;
527 if (!
m->d_func()->tornoff)
530 m->d_func()->setCurrentAction(
nullptr);
531 }
else { caused =
nullptr;
535 setCurrentAction(
nullptr);
553 q->installEventFilter(
this);
563 return deleteLater =
true;
568 bool deleteLater =
false;
571#if QT_CONFIG(effects)
576 && currentAction && currentAction == actionAboutToTrigger
582 const Reposter deleteDeleteLate(
menu);
595 if (activeMenu ==
menu)
596 activeMenu =
nullptr;
597 menu->d_func()->causedPopup.action =
nullptr;
599 menu->d_func()->causedPopup.widget =
nullptr;
606 if (
parent->windowHandle())
607 return parent->windowHandle();
610 if (
const QWindow *
w =
q->windowHandle()) {
611 if (
w->transientParent())
612 return w->transientParent();
615 if (causedPopup.widget) {
616 if (
const QWidget *
w = causedPopup.widget.data()) {
618 return ww->windowHandle();
631 q->internalDelayedPopup();
632 else if (action->
menu() && !action->
menu()->isVisible())
633 delayState.start(delay, action);
634 else if (!action->
menu())
636 if (activateFirst && action->
menu())
637 action->
menu()->d_func()->setFirstActionActive();
647 QAction *current = currentAction;
651 if (
QMenu *
m = qobject_cast<QMenu*>(caused)) {
652 caused =
m->d_func()->causedPopup.widget;
653 if (
m->d_func()->eventLoop)
654 m->d_func()->syncAction = current;
670 if (
scroll &&
scroll->scrollFlags & QMenuScroller::ScrollUp) {
672 if (saccum >
scroll->scrollOffset - scrollerHeight())
679 setCurrentAction(act);
689 tearoffHighlighted = 0;
698 if (reason != SelectedFromKeyboard) {
699 if (
QMenu *
menu = qobject_cast<QMenu*>(causedPopup.widget)) {
700 if (causedPopup.action &&
menu->d_func()->activeMenu ==
q)
702 if (hasReceievedEnter &&
menu->d_func()->currentAction != causedPopup.action)
703 menu->d_func()->setCurrentAction(causedPopup.action, 0, reason,
false);
708 q->
update(actionRect(currentAction));
710 QMenu *hideActiveMenu = activeMenu;
711 QAction *previousAction = currentAction;
713 currentAction = action;
722 popupAction(currentAction,
popup, activateFirst);
724 q->update(actionRect(action));
726 if (reason == SelectedFromKeyboard) {
735 if (!
q->hasFocus()) {
741#if QT_CONFIG(statustip)
742 }
else if (previousAction) {
746 if (hideActiveMenu && previousAction != currentAction) {
748#if QT_CONFIG(effects)
753 hideMenu(hideActiveMenu);
754 }
else if (!currentAction || !currentAction->menu()) {
755 sloppyState.startTimerIfNotRunning();
763 m_first_mouse =
true;
764 m_init_guard =
false;
765 m_use_reset_action =
true;
766 m_uni_dir_discarded_count = 0;
768 m_reset_action =
nullptr;
769 m_origin_action =
nullptr;
770 m_action_rect =
QRect();
774 m_sub_menu =
nullptr;
781 if (m_discard_state_when_entering_parent && m_sub_menu == menuPriv->
activeMenu) {
786 m_parent->childEnter();
793 m_parent->childEnter();
798 if (!m_dont_start_time_on_leave) {
800 m_parent->childLeave();
801 startTimerIfNotRunning();
808 startTimerIfNotRunning();
810 m_parent->childLeave();
818 m_use_reset_action =
true;
820 m_action_rect = actionRect;
823 m_sub_menu = subMenu;
825 m_reset_action = resetAction;
826 m_origin_action = resetAction;
838 : toReset(sloppyState)
859 if (!reallyHasMouse) {
863 reallyHasMouse = m_menu->frameGeometry().contains(lastCursorPos);
875 if (hasParentActiveDelayTimer() || !m_menu->isVisible())
881 if (reallyHasMouse) {
882 if (m_use_reset_action)
893 while (
QMenu*
m = qobject_cast<QMenu *>(
top))
894 top =
m->d_func()->causedPopup.widget;
903 for(
int i = 0;
i < actionRects.size();
i++) {
904 if (actionRects.at(
i).contains(
p))
934 if (
QWidget *
w = causedPopup.widget)
935 setLayoutDirection_helper(
w->layoutDirection());
937 setLayoutDirection_helper(
w->layoutDirection());
986 if (tearoffHighlighted)
1002 return (
q->rect().adjusted(hmargin + fw + leftmargin, vmargin + fw + topmargin,
1003 -(hmargin + fw + rightmargin), -(vmargin + fw + bottommargin)));
1015 if (!
e->rect().intersects(
rect()))
1022 menuPrivate->drawScroller(&
p, scrollType,
QRect(0, 0,
width(), menuPrivate->scrollerHeight()));
1028 menuPrivate->drawTearOff(&
p,
rect);
1049 return d_func()->menuAction;
1072 return d_func()->menuAction->text();
1077 d_func()->menuAction->setText(
text);
1091 return d_func()->menuAction->icon();
1096 d_func()->menuAction->setIcon(
icon);
1116 newOffset = topScroll - saccum;
1126 newOffset = ((
q->height() / 2) - botScroll) - (saccum - topScroll);
1128 newOffset = (
q->height() - botScroll) - saccum;
1133 newOffset -= fw * 2;
1140 int saccum = newOffset;
1143 if (saccum >
q->height()) {
1160 newOffset -= vmargin;
1164 if (
q->height() <
screen.height()-(desktopFrame*2)-1) {
1165 QRect geom =
q->geometry();
1168 if (newHeight > geom.
height())
1172 if (newTop < desktopFrame+
screen.top())
1173 newTop = desktopFrame+
screen.top();
1174 if (newTop < geom.
top()) {
1182 if (geom.
top() < desktopFrame+
screen.top())
1184 if (geom !=
q->geometry()) {
1187 q->geometry().top() - geom.
top() >= -newOffset)
1190 q->setGeometry(geom);
1204 w->setGeometry(current);
1263 const int offset = topScroll ? topScroll-vmargin : 0;
1267 if (saccum <= scroll->scrollOffset-
offset) {
1273 bool scrolled =
false;
1277 if (saccum <= scroll->scrollOffset-
offset) {
1278 const int scrollerArea =
q->height() - botScroll - fw*2;
1282 if (visible > scrollerArea - topScroll) {
1303 QPoint pos =
q->mapFromGlobal(
e->globalPosition().toPoint());
1313 bool isScroll =
false;
1314 if (
pos.x() >= 0 &&
pos.x() <
q->width()) {
1341 q->update(tearRect);
1357 if (
q->frameGeometry().contains(
e->globalPosition().toPoint()))
1361 bool passOnEvent =
false;
1362 QWidget *next_widget =
nullptr;
1363 QPointF cpos = caused->mapFromGlobal(
e->globalPosition());
1364#if QT_CONFIG(menubar)
1365 if (
QMenuBar *mb = qobject_cast<QMenuBar*>(caused)) {
1366 passOnEvent = mb->rect().contains(cpos.
toPoint());
1369 if (
QMenu *
m = qobject_cast<QMenu*>(caused)) {
1370 passOnEvent =
m->rect().contains(cpos.
toPoint());
1371 next_widget =
m->d_func()->causedPopup.widget;
1375 QMouseEvent new_e(
e->type(), cpos, caused->mapTo(caused->topLevelWidget(), cpos),
e->globalPosition(),
1376 e->button(),
e->buttons(),
e->modifiers(),
1377 e->source(),
e->pointingDevice());
1382 caused = next_widget;
1401 auto boolBlocker =
qScopeGuard([
this, activationRecursionGuardReset]{
1405 for(
int i = 0;
i < causedStack.size(); ++
i) {
1410 if (
QMenu *qmenu = qobject_cast<QMenu*>(
widget)) {
1411 widget = qmenu->d_func()->causedPopup.widget;
1413 emit qmenu->triggered(action);
1415 emit qmenu->hovered(action);
1417#if QT_CONFIG(menubar)
1418 }
else if (
QMenuBar *qmenubar = qobject_cast<QMenuBar*>(
widget)) {
1420 emit qmenubar->triggered(action);
1422 emit qmenubar->hovered(action);
1433#if QT_CONFIG(whatsthis)
1449#if QT_CONFIG(whatsthis)
1450 if (!inWhatsThisMode)
1458 if (
QMenu *qmenu = qobject_cast<QMenu*>(
widget)) {
1461 widget = qmenu->d_func()->causedPopup.widget;
1468#if QT_CONFIG(whatsthis)
1469 if (inWhatsThisMode) {
1485#if QT_CONFIG(accessibility)
1486 if (QAccessible::isActive()) {
1487 int actionIndex =
indexOf(action);
1488 QAccessibleEvent focusEvent(
q, QAccessible::Focus);
1489 focusEvent.setChild(actionIndex);
1490 QAccessible::updateAccessibility(&focusEvent);
1502 if (
QAction *action = qobject_cast<QAction *>(
q->sender())) {
1506 emit q->triggered(action);
1512 if (qobject_cast<QMenu*>(
widget)
1513#if QT_CONFIG(menubar)
1514 || qobject_cast<QMenuBar*>(
widget)
1525 if (qobject_cast<QWidgetAction*>(action))
1534 if (
QAction * action = qobject_cast<QAction *>(
q->sender())) {
1535 emit q->hovered(action);
1543 emit q->aboutToShow();
1552 moveWidgetToPlatformItem(
widget, menuItem);
1587 if (
window()->isActiveWindow())
1590 && (!action->
menu() || action->
menu()->isEnabled()))
1598 if (
d->currentAction &&
d->currentAction == action && !
d->currentAction->isSeparator()) {
1603 option->menuHasCheckableItems =
d->hasCheckableItems;
1615 else if (
d->defaultAction == action)
1622#ifndef QT_NO_SHORTCUT
1624 && textAndAccel.
indexOf(u
'\t') == -1) {
1630 option->text = textAndAccel;
1631 option->reservedShortcutWidth =
d->tabWidth;
1632 option->maxIconWidth =
d->maxIconWidth;
1744 d->menuAction->setText(
title);
1762 if (!
d->widgetItems.isEmpty()) {
1764 for (;
it !=
d->widgetItems.end(); ++
it) {
1774 d->eventLoop->exit();
1778#if QT_DEPRECATED_SINCE(6, 4)
1785#if QT_CONFIG(shortcut)
1835#if QT_CONFIG(shortcut)
2044 d_func()->defaultAction = act;
2054 return d_func()->defaultAction;
2073 if (
d->tearoff ==
b)
2079 d->itemsDirty =
true;
2086 return d_func()->tearoff;
2098 if (d_func()->tornPopup)
2099 return d_func()->tornPopup->isVisible();
2117 d->tornPopup->setGeometry(
pos.
x(),
pos.
y(),
s.width(),
s.height());
2118 d->tornPopup->show();
2145 d->tornPopup->close();
2150 d->tornPopup =
nullptr;
2161 d->setCurrentAction(act, 0);
2162 if (
d->scroll && act)
2173 return d_func()->currentAction;
2207 for(
int i = 0;
i < acts.
size();
i++) {
2209 if (acts[
i]->
parent() ==
this && acts[
i]->d_func()->associatedObjects.
isEmpty())
2223 return d_func()->ncols;
2241 return d_func()->actionRect(act);
2250 d->updateActionRects();
2253 for (
int i = 0;
i <
d->actionRects.size(); ++
i) {
2291 d->popup(
p, atAction);
2308 q->ensurePolished();
2315 bool screenSet =
false;
2321 }
else if (
QMenu *parentMenu = qobject_cast<QMenu *>(
parent)) {
2347#if QT_CONFIG(menubar)
2353 emit q->aboutToShow();
2357#if QT_CONFIG(graphicsview)
2368 if (actionListChanged && causedButton)
2373 const QSize menuSizeHint(
q->sizeHint());
2376 if (positionFunction)
2377 pos = positionFunction(menuSizeHint);
2388 adjustToDesktop =
true;
2391#ifdef QT_KEYPAD_NAVIGATION
2392 if (!atAction && QApplicationPrivate::keypadNavigationEnabled()) {
2409 }
else if (atAction) {
2412 if (action == atAction) {
2413 int newY =
pos.y() - above_height;
2414 if (
scroll && newY < desktopFrame) {
2418 newY = desktopFrame;
2427 size.setHeight(below_height);
2440 if (adjustToDesktop) {
2442 if (
q->isRightToLeft()) {
2444 pos.setX(mouse.
x() -
size.width());
2446#if QT_CONFIG(menubar)
2452 if (
pos.x() <
screen.left() + desktopFrame)
2454 if (
pos.x() +
size.width() - 1 >
screen.right() - desktopFrame)
2457 if (
pos.x() +
size.width() - 1 >
screen.right() - desktopFrame)
2459 if (
pos.x() <
screen.left() + desktopFrame)
2462 if (
pos.y() +
size.height() - 1 >
screen.bottom() - desktopFrame) {
2464 pos.setY(
qMin(mouse.
y() - (
size.height() + desktopFrame),
screen.bottom()-desktopFrame-
size.height()+1));
2469 if (
pos.y() <
screen.top() + desktopFrame)
2471 if (
pos.y() + menuSizeHint.
height() - 1 >
screen.bottom() - desktopFrame) {
2475 size.setHeight(
screen.bottom() - (desktopFrame * 2) -
y);
2485 QRect parentActionRect(caused->d_func()->actionRect(caused->d_func()->currentAction));
2488 if (
q->isRightToLeft()) {
2489 if ((
pos.x() + menuSizeHint.
width() > parentActionRect.
left() - subMenuOffset)
2490 && (
pos.x() < parentActionRect.
right()))
2492 pos.rx() = parentActionRect.
left() - menuSizeHint.
width();
2494 pos.rx() = parentActionRect.
right();
2499 if ((
pos.x() < parentActionRect.
right() + subMenuOffset)
2500 && (
pos.x() + menuSizeHint.
width() > parentActionRect.
left()))
2502 pos.rx() = parentActionRect.
right();
2504 pos.rx() = parentActionRect.
left() - menuSizeHint.
width();
2511#if QT_CONFIG(effects)
2514 if (
q->isRightToLeft()) {
2515 if ((snapToMouse && (
pos.x() +
size.width() / 2 > mouse.
x())) ||
2519 if ((snapToMouse && (
pos.x() +
size.width() / 2 < mouse.
x())) ||
2524#if QT_CONFIG(menubar)
2525 if ((snapToMouse && (
pos.y() +
size.height() / 2 < mouse.
y())) ||
2532#if QT_CONFIG(menubar)
2535 mb->d_func()->doChildEffects =
false;
2540 m->d_func()->doChildEffects =
false;
2563#if QT_CONFIG(accessibility)
2564 QAccessibleEvent
event(
q, QAccessible::PopupMenuStart);
2565 QAccessible::updateAccessibility(&
event);
2630 return d->exec(
p, action);
2636 q->ensurePolished();
2640 popup(
p, action, positionFunction);
2690 d->eventLoop->exit();
2691 d->setCurrentAction(
nullptr);
2692#if QT_CONFIG(accessibility)
2693 QAccessibleEvent
event(
this, QAccessible::PopupMenuEnd);
2694 QAccessible::updateAccessibility(&
event);
2696#if QT_CONFIG(menubar)
2697 if (
QMenuBar *mb = qobject_cast<QMenuBar*>(
d->causedPopup.widget))
2698 mb->d_func()->setCurrentAction(
nullptr);
2702 d->hasHadMouse =
false;
2704 d->hideMenu(
d->activeMenu);
2705 d->causedPopup.widget =
nullptr;
2706 d->causedPopup.action =
nullptr;
2708 d->scroll->scrollTimer.stop();
2717 d->updateActionRects();
2734 QRect scrollUpRect, scrollDownRect;
2735 const int leftmargin = fw + hmargin +
d->leftmargin;
2736 const int topmargin = fw + vmargin +
d->topmargin;
2737 const int bottommargin = fw + vmargin +
d->bottommargin;
2738 const int contentWidth =
width() - (fw + hmargin) * 2 -
d->leftmargin -
d->rightmargin;
2741 scrollUpRect.
setRect(leftmargin, topmargin, contentWidth,
d->scrollerHeight());
2744 scrollDownRect.
setRect(leftmargin,
height() -
d->scrollerHeight() - bottommargin,
2745 contentWidth,
d->scrollerHeight());
2751 tearOffRect.
setRect(leftmargin, topmargin, contentWidth,
2754 tearOffRect.
translate(0,
d->scrollerHeight());
2758 QRect scrollUpTearOffRect = scrollUpRect.
united(tearOffRect);
2759 for (
int i = 0;
i <
d->actions.size(); ++
i) {
2761 QRect actionRect =
d->actionRects.at(
i);
2762 if (!
e->rect().intersects(actionRect)
2763 ||
d->widgetItems.value(action))
2766 emptyArea -=
QRegion(actionRect);
2768 QRect adjustedActionRect = actionRect;
2769 if (!scrollUpTearOffRect.
isEmpty() && adjustedActionRect.
bottom() <= scrollUpTearOffRect.
top())
2772 if (!scrollDownRect.
isEmpty() && adjustedActionRect.
top() >= scrollDownRect.
bottom())
2775 if (adjustedActionRect.
intersects(scrollUpTearOffRect)) {
2776 if (adjustedActionRect.
bottom() <= scrollUpTearOffRect.
bottom())
2779 adjustedActionRect.
setTop(scrollUpTearOffRect.
bottom()+1);
2782 if (adjustedActionRect.
intersects(scrollDownRect)) {
2783 if (adjustedActionRect.
top() >= scrollDownRect.
top())
2789 QRegion adjustedActionReg(adjustedActionRect);
2790 p.setClipRegion(adjustedActionReg);
2798 emptyArea -=
QRegion(scrollUpTearOffRect);
2799 emptyArea -=
QRegion(scrollDownRect);
2801 if (
d->scrollUpTearOffItem ||
d->scrollDownItem) {
2802 if (
d->scrollUpTearOffItem)
2803 d->scrollUpTearOffItem->updateScrollerRects(scrollUpTearOffRect);
2804 if (
d->scrollDownItem)
2805 d->scrollDownItem->updateScrollerRects(scrollDownRect);
2811 d->drawTearOff(&
p, tearOffRect);
2821 p.setClipRegion(borderReg);
2822 emptyArea -= borderReg;
2833 p.setClipRegion(emptyArea);
2842#if QT_CONFIG(wheelevent)
2846void QMenu::wheelEvent(QWheelEvent *
e)
2850 d->scrollMenu(
e->angleDelta().y() > 0 ?
2861 if (
d->aboutToHide ||
d->mouseEventTaken(
e))
2867 if ((
e->position().toPoint().isNull() && !
e->globalPosition().isNull()) || !
rect().
contains(
e->position().toPoint())) {
2869 &&
QRect(
d->noReplayFor->mapToGlobal(
QPoint()),
d->noReplayFor->size()).
contains(
e->globalPosition().toPoint()))
2872 d->syncAction =
nullptr;
2873 d->hideUpToMenuBar();
2878 QAction *action =
d->actionAt(
e->position().toPoint());
2879 d->setCurrentAction(action, 20);
2889 if (
d->aboutToHide ||
d->mouseEventTaken(
e))
2898 QAction *action =
d->actionAt(
e->position().toPoint());
2900 if (action && action ==
d->currentAction) {
2901 if (!action->
menu()) {
2902#if defined(Q_OS_WIN)
2908 }
else if ((!action || action->
isEnabled()) &&
d->hasMouseMoved(
e->globalPosition().toPoint())) {
2909 d->hideUpToMenuBar();
2927 d->scroll =
nullptr;
2928 }
else if (!
d->scroll) {
2936 if (!
d->platformMenu.isNull())
2949 switch (
e->type()) {
2951 d->updateLayoutDirection();
2958#ifndef QT_NO_SHORTCUT
2976 bool canPopup =
true;
2979 if (canPopup &&
d->delayState.timer.isActive()) {
2980 d->delayState.stop();
2981 internalDelayedPopup();
2993 d->updateActionRects();
2997 d->updateActionRects();
2998 d->sloppyState.reset();
2999 if (
d->currentAction)
3000 d->popupAction(
d->currentAction, 0,
false);
3004#if QT_CONFIG(tooltip)
3006 if (
d->toolTipsVisible) {
3009 const QString toolTip = action->d_func()->tooltip;
3019#if QT_CONFIG(whatsthis)
3021 e->setAccepted(
d->whatsThis.size());
3051 d->updateActionRects();
3066 bool key_consumed =
false;
3069 key_consumed =
true;
3074 key_consumed =
true;
3079 key_consumed =
true;
3080 if (
d->currentAction &&
d->scroll) {
3088 key_consumed =
true;
3089 if (
d->currentAction &&
d->scroll) {
3098 key_consumed =
true;
3099 QAction *nextAction =
nullptr;
3101 if (!
d->currentAction) {
3103 for(
int i = 0;
i <
d->actions.size(); ++
i) {
3105 if (
d->actionRects.at(
i).isNull())
3115 for(
int i =
d->actions.size()-1;
i >= 0; --
i) {
3117 if (
d->actionRects.at(
i).isNull())
3128 for(
int i = 0,
y = 0; !nextAction &&
i <
d->actions.size();
i++) {
3130 if (act ==
d->currentAction) {
3132 for(
int next_i =
i-1;
true; next_i--) {
3138 next_i =
d->actionRects.size()-1;
3141 if (
next ==
d->currentAction)
3143 if (
d->actionRects.at(next_i).isNull())
3145 if (
next->isSeparator() ||
3146 (!
next->isEnabled() &&
3151 int topVisible =
d->scrollerHeight();
3154 if (((
y +
d->scroll->scrollOffset) - topVisible) <=
d->actionRects.at(next_i).height())
3159 if (!nextAction &&
d->tearoff)
3160 d->tearoffHighlighted = 1;
3162 y +=
d->actionRects.at(
i).height();
3163 for(
int next_i =
i+1;
true; next_i++) {
3164 if (next_i ==
d->actionRects.size()) {
3172 if (
next ==
d->currentAction)
3174 if (
d->actionRects.at(next_i).isNull())
3176 if (
next->isSeparator() ||
3177 (!
next->isEnabled() &&
3182 int bottomVisible =
height() -
d->scrollerHeight();
3184 bottomVisible -=
d->scrollerHeight();
3187 if ((
y +
d->scroll->scrollOffset +
d->actionRects.at(next_i).height()) > bottomVisible)
3195 y +=
d->actionRects.at(
i).height();
3200 d->scroll->scrollTimer.stop();
3201 d->scrollMenu(nextAction, scroll_loc);
3208 if (
d->currentAction &&
d->currentAction->isEnabled() &&
d->currentAction->menu()) {
3209 d->popupAction(
d->currentAction, 0,
true);
3210 key_consumed =
true;
3215 if (
d->currentAction && !
d->scroll) {
3216 QAction *nextAction =
nullptr;
3218 QRect actionR =
d->actionRect(
d->currentAction);
3219 for(
int x = actionR.
left()-1; !nextAction &&
x >= 0;
x--)
3222 QRect actionR =
d->actionRect(
d->currentAction);
3223 for(
int x = actionR.
right()+1; !nextAction &&
x <
width();
x++)
3228 key_consumed =
true;
3231 if (!key_consumed &&
key ==
Qt::Key_Left && qobject_cast<QMenu*>(
d->causedPopup.widget)) {
3236 key_consumed =
true;
3244 key_consumed =
true;
3248#if QT_CONFIG(menubar)
3250 mb->d_func()->setKeyboardMode(
false);
3261#ifdef QT_KEYPAD_NAVIGATION
3266 if (!
d->currentAction) {
3267 d->setFirstActionActive();
3268 key_consumed =
true;
3274 if (
d->currentAction->menu())
3275 d->popupAction(
d->currentAction, 0,
true);
3278 key_consumed =
true;
3281#if QT_CONFIG(whatsthis)
3283 if (!
d->currentAction ||
d->currentAction->whatsThis().isNull())
3290 key_consumed =
false;
3293 if (!key_consumed && (
3295#ifndef QT_NO_SHORTCUT
3298#ifdef QT_KEYPAD_NAVIGATION
3302 key_consumed =
true;
3310#if QT_CONFIG(menubar)
3311 if (
QMenuBar *mb = qobject_cast<QMenuBar*>(caused)) {
3312 mb->d_func()->setCurrentAction(
d->menuAction);
3313 mb->d_func()->setKeyboardMode(
true);
3319 if (!key_consumed) {
3321 e->text().size()==1) {
3322 bool activateAction =
false;
3323 QAction *nextAction =
nullptr;
3325 int best_match_count = 0;
3326 d->searchBufferTimer.start(2000,
this);
3327 d->searchBuffer +=
e->text();
3328 for(
int i = 0;
i <
d->actions.size(); ++
i) {
3329 int match_count = 0;
3330 if (
d->actionRects.at(
i).isNull())
3334 for(
int c = 0;
c <
d->searchBuffer.size(); ++
c) {
3338 if (match_count > best_match_count) {
3339 best_match_count = match_count;
3344#ifndef QT_NO_SHORTCUT
3347 QAction *
first =
nullptr, *currentSelected =
nullptr, *firstAfterCurrent =
nullptr;
3348 QChar c =
e->text().at(0).toUpper();
3349 for(
int i = 0;
i <
d->actions.size(); ++
i) {
3350 if (
d->actionRects.at(
i).isNull())
3354 int key = sequence[0].toCombined() & 0xffff;
3355 if (
key ==
c.unicode()) {
3359 if (act ==
d->currentAction)
3360 currentSelected = act;
3361 else if (!firstAfterCurrent && currentSelected)
3362 firstAfterCurrent = act;
3365 if (clashCount == 1)
3366 activateAction =
true;
3367 if (clashCount >= 1) {
3368 if (clashCount == 1 || !currentSelected || !firstAfterCurrent)
3371 nextAction = firstAfterCurrent;
3376 key_consumed =
true;
3380 if (!nextAction->
menu() && activateAction) {
3386 if (!key_consumed) {
3387#if QT_CONFIG(menubar)
3388 if (
QMenuBar *mb = qobject_cast<QMenuBar*>(
d->topCausedWidget())) {
3389 QAction *oldAct = mb->d_func()->currentAction;
3391 if (mb->d_func()->currentAction != oldAct)
3392 key_consumed =
true;
3414 if (!
isVisible() ||
d->aboutToHide ||
d->mouseEventTaken(
e))
3418 if (!
d->hasMouseMoved(
e->globalPosition().toPoint()))
3421 d->hasHadMouse =
d->hasHadMouse ||
rect().
contains(
e->position().toPoint());
3423 QAction *action =
d->actionAt(
e->position().toPoint());
3424 if ((!action || action->
isSeparator()) && !
d->sloppyState.enabled()) {
3426 || (!
d->currentAction || !
d->currentAction->menu() || !
d->currentAction->menu()->isVisible())) {
3427 d->setCurrentAction(action);
3436 d->activeMenu->d_func()->setCurrentAction(
nullptr);
3440 d->setCurrentAction(action,
d->mousePopupDelay);
3442 d->sloppyState.reset();
3443 d->hideMenu(
d->activeMenu);
3453 d->hasReceievedEnter =
true;
3454 d->sloppyState.enter();
3464 d->hasReceievedEnter =
false;
3465 if (!
d->activeMenu &&
d->currentAction)
3476 if (
d->scroll &&
d->scroll->scrollTimer.timerId() ==
e->timerId()) {
3479 d->scroll->scrollTimer.stop();
3480 }
else if (
d->delayState.timer.timerId() ==
e->timerId()) {
3481 if (
d->currentAction && !
d->currentAction->menu())
3483 d->delayState.stop();
3484 d->sloppyState.stopTimer();
3485 internalDelayedPopup();
3486 }
else if (
d->sloppyState.isTimerId(
e->timerId())) {
3487 d->sloppyState.timeout();
3488 }
else if (
d->searchBufferTimer.timerId() ==
e->timerId()) {
3489 d->searchBuffer.clear();
3502 d->tornPopup->syncWithMenu(
this,
e);
3507 && !qobject_cast<QMenuBar*>(
e->action()->parent())
3515 if (
QWidgetAction *wa = qobject_cast<QWidgetAction *>(
e->action())) {
3518 d->widgetItems.insert(wa,
widget);
3520 if (!
d->scrollUpTearOffItem)
3521 d->scrollUpTearOffItem =
3523 if (!
d->scrollDownItem)
3530 e->action()->disconnect(
this);
3531 if (
e->action() ==
d->currentAction)
3532 d->currentAction =
nullptr;
3533 if (
QWidgetAction *wa = qobject_cast<QWidgetAction *>(
e->action())) {
3535 wa->releaseWidget(
widget);
3537 d->widgetItems.remove(
static_cast<QAction *
>(
e->action()));
3540 if (!
d->platformMenu.isNull()) {
3541 auto action =
static_cast<QAction *
>(
e->action());
3544 ?
d->platformMenu->menuItemForTag(
reinterpret_cast<quintptr>(
e->before()))
3546 d->insertActionInPlatformMenu(action, beforeItem);
3549 d->platformMenu->removeMenuItem(menuItem);
3554 d->copyActionToPlatformItem(action, menuItem);
3555 d->platformMenu->syncMenuItem(menuItem);
3559 d->platformMenu->syncSeparatorsCollapsible(
d->collapsibleSeparators);
3571void QMenu::internalDelayedPopup()
3576 if (
d->activeMenu->menuAction() !=
d->currentAction)
3580 if (!
d->currentAction || !
d->currentAction->isEnabled() || !
d->currentAction->menu() ||
3581 !
d->currentAction->menu()->isEnabled() ||
d->currentAction->menu()->isVisible())
3585 d->activeMenu =
d->currentAction->menu();
3586 d->activeMenu->d_func()->causedPopup.widget =
this;
3587 d->activeMenu->d_func()->causedPopup.action =
d->currentAction;
3590#if QT_CONFIG(graphicsview)
3599 const QRect actionRect(
d->actionRect(
d->currentAction));
3601 if (subMenuPos.x() >
screen.right())
3604 const auto &subMenuActions =
d->activeMenu->actions();
3605 if (!subMenuActions.isEmpty()) {
3607 const auto subMenuActionRect =
d->activeMenu->actionGeometry(subMenuActions.first());
3608 subMenuPos.ry() -= subMenuActionRect.top();
3611 d->activeMenu->popup(subMenuPos);
3612 d->sloppyState.setSubMenuPopup(actionRect,
d->currentAction,
d->activeMenu);
3614#if !defined(Q_OS_DARWIN)
3677 d_func()->noReplayFor = noReplayFor;
3685 return d_func()->platformMenu;
3693 d_func()->syncPlatformMenu();
3711 return d->collapsibleSeparators;
3717 if (
d->collapsibleSeparators == collapse)
3720 d->collapsibleSeparators = collapse;
3723 d->updateActionRects();
3726 if (!
d->platformMenu.isNull())
3727 d->platformMenu->syncSeparatorsCollapsible(collapse);
3744 return d->toolTipsVisible;
3759#include "moc_qmenu.cpp"
The QActionEvent class provides an event that is generated when a QAction is added,...
bool isExclusive() const
Returns true if the group is exclusive.
The QAction class provides an abstraction for user commands that can be added to different user inter...
ActionEvent
This enum type is used when calling QAction::activate()
T menu() const
Returns the menu contained by this action.
void hovered()
This signal is emitted when an action is highlighted by the user; for example, when the user pauses w...
bool isSeparator() const
Returns true if this action is a separator action; otherwise it returns false.
QActionGroup * actionGroup() const
Returns the action group for this action.
void setMenu(T m)
Sets the menu contained by this action to the specified menu.
bool isShortcutVisibleInContextMenu() const
void setSeparator(bool b)
If b is true then this action will be considered a separator.
QString whatsThis
the action's "What's This?" help text
QFont font
the action's font
bool showStatusText(QObject *object=nullptr)
Updates the relevant status bar for the UI represented by object by sending a QStatusTipEvent.
bool isIconVisibleInMenu() const
void activate(ActionEvent event)
Sends the relevant signals for ActionEvent event.
QString text
the action's descriptive text
void changed()
This signal is emitted when an action has changed.
MenuRole menuRole
the action's menu role
void trigger()
This is a convenience slot that calls activate(Trigger).
QIcon icon
the action's icon
static QStyle * style()
Returns the application's style object.
static void beep()
Sounds the bell, using the default volume and sound.
static bool isEffectEnabled(Qt::UIEffect)
Returns true if effect is enabled; otherwise returns false.
static QWidget * focusWidget()
Returns the application widget that has the keyboard input focus, or \nullptr if no widget in this ap...
static QWidget * activePopupWidget()
Returns the active popup widget.
int startDragDistance
the minimum distance required for a drag and drop operation to start.
void start(int msec, QObject *obj)
\obsolete Use chrono overload instead.
void stop()
Stops the timer.
bool isActive() const noexcept
Returns true if the timer is running and has not been stopped; otherwise returns false.
static bool sendEvent(QObject *receiver, QEvent *event)
Sends event event directly to receiver receiver, using the notify() function.
static QPoint pos()
Returns the position of the cursor (hot spot) of the primary screen in global screen coordinates.
int exec(ProcessEventsFlags flags=AllEvents)
Enters the main event loop and waits until exit() is called.
\reentrant \inmodule QtGui
int height() const
Returns the height of the font.
QRect boundingRect(QChar) const
Returns the rectangle that is covered by ink if character ch were to be drawn at the origin of the co...
int horizontalAdvance(const QString &, int len=-1) const
Returns the horizontal advance in pixels of the first len characters of text.
QFont resolve(const QFont &) const
Returns a new QFont that has attributes copied from other that have not been previously set on this f...
int midLineWidth
the width of the mid-line
int lineWidth
the line width
void setEnabled(bool enabled)
If enabled is true, the item is enabled; otherwise, it is disabled.
void setVisible(bool visible)
If visible is true, the item is made visible.
static struct QGuiApplicationPrivate::QLastCursorPosition lastCursorPosition
static QPlatformTheme * platformTheme()
Qt::LayoutDirection layoutDirection
the default layout direction for this application
static QScreen * screenAt(const QPoint &point)
Returns the screen at point, or \nullptr if outside of any screen.
T value(const Key &key) const noexcept
The QHelpEvent class provides an event that is used to request helpful information about a particular...
const QPoint & globalPos() const
Returns the mouse cursor position when the event was generated in global coordinates.
const QPoint & pos() const
Returns the mouse cursor position when the event was generated, relative to the widget to which the e...
The QHideEvent class provides an event which is sent after a widget is hidden.
The QIcon class provides scalable icons in different modes and states.
bool isNull() const
Returns true if the icon is empty; otherwise returns false.
The QKeyEvent class describes a key event.
int key() const
Returns the code of the key that was pressed or released.
The QKeySequence class encapsulates a key sequence as used by shortcuts.
static QKeySequence mnemonic(const QString &text)
Returns the shortcut key sequence for the mnemonic in text, or an empty key sequence if no mnemonics ...
bool isEmpty() const
Returns true if the key sequence is empty; otherwise returns false.
QString toString(SequenceFormat format=PortableText) const
qsizetype size() const noexcept
bool isEmpty() const noexcept
const_reference at(qsizetype i) const noexcept
std::reverse_iterator< const_iterator > const_reverse_iterator
reverse_iterator rbegin()
void append(parameter_type t)
QObject * parent() const
Returns a pointer to the parent object.
static QMetaObject::Connection connect(const QObject *sender, const char *signal, const QObject *receiver, const char *member, Qt::ConnectionType=Qt::AutoConnection)
\threadsafe
virtual bool eventFilter(QObject *watched, QEvent *event)
Filters events if this object has been installed as an event filter for the watched object.
static bool disconnect(const QObject *sender, const char *signal, const QObject *receiver, const char *member)
\threadsafe
void destroyed(QObject *=nullptr)
This signal is emitted immediately before the object obj is destroyed, after any instances of QPointe...
The QPaintEvent class contains event parameters for paint events.
The QPainter class performs low-level painting on widgets and other paint devices.
void setClipRect(const QRectF &, Qt::ClipOperation op=Qt::ReplaceClip)
Enables clipping, and sets the clip region to the given rectangle using the given clip operation.
\inmodule QtCore\reentrant
constexpr qreal y() const noexcept
Returns the y coordinate of this point.
constexpr QPoint toPoint() const
Rounds the coordinates of this point to the nearest integer, and returns a QPoint object with the rou...
\inmodule QtCore\reentrant
constexpr int x() const noexcept
Returns the x coordinate of this point.
constexpr int y() const noexcept
Returns the y coordinate of this point.
bool isNull() const
Returns true if the referenced object has been destroyed or if there is no referenced object; otherwi...
\inmodule QtCore\reentrant
constexpr bool isEmpty() const noexcept
Returns true if the rectangle is empty, otherwise returns false.
bool intersects(const QRect &r) const noexcept
Returns true if this rectangle intersects with the given rectangle (i.e., there is at least one pixel...
constexpr void moveTopLeft(const QPoint &p) noexcept
Moves the rectangle, leaving the top-left corner at the given position.
constexpr int height() const noexcept
Returns the height of the rectangle.
constexpr bool isNull() const noexcept
Returns true if the rectangle is a null rectangle, otherwise returns false.
constexpr int bottom() const noexcept
Returns the y-coordinate of the rectangle's bottom edge.
constexpr QPoint topLeft() const noexcept
Returns the position of the rectangle's top-left corner.
constexpr int top() const noexcept
Returns the y-coordinate of the rectangle's top edge.
constexpr void setBottom(int pos) noexcept
Sets the bottom edge of the rectangle to the given y coordinate.
bool contains(const QRect &r, bool proper=false) const noexcept
This is an overloaded member function, provided for convenience. It differs from the above function o...
constexpr int left() const noexcept
Returns the x-coordinate of the rectangle's left edge.
constexpr void setRect(int x, int y, int w, int h) noexcept
Sets the coordinates of the rectangle's top-left corner to ({x}, {y}), and its size to the given widt...
constexpr int x() const noexcept
Returns the x-coordinate of the rectangle's left edge.
constexpr void setWidth(int w) noexcept
Sets the width of the rectangle to the given width.
constexpr void translate(int dx, int dy) noexcept
Moves the rectangle dx along the x axis and dy along the y axis, relative to the current position.
constexpr int width() const noexcept
Returns the width of the rectangle.
QRect united(const QRect &other) const noexcept
constexpr int y() const noexcept
Returns the y-coordinate of the rectangle's top edge.
constexpr void setHeight(int h) noexcept
Sets the height of the rectangle to the given height.
constexpr void moveTop(int pos) noexcept
Moves the rectangle vertically, leaving the rectangle's top edge at the given y coordinate.
constexpr QPoint center() const noexcept
Returns the center point of the rectangle.
constexpr int right() const noexcept
Returns the x-coordinate of the rectangle's right edge.
constexpr void setTop(int pos) noexcept
Sets the top edge of the rectangle to the given y coordinate.
The QRegion class specifies a clip region for a painter.
The QScreen class is used to query screen properties. \inmodule QtGui.
QRect availableGeometry
the screen's available geometry in pixels
QRect geometry
the screen's geometry in pixels
Exception-safe wrapper around QObject::blockSignals().
void unblock() noexcept
Temporarily restores the QObject::signalsBlocked() state to what it was before this QSignalBlocker's ...
constexpr int height() const noexcept
Returns the height.
constexpr int width() const noexcept
Returns the width.
constexpr QSize expandedTo(const QSize &) const noexcept
Returns a size holding the maximum width and height of this size and the given otherSize.
constexpr void setWidth(int w) noexcept
Sets the width to the given width.
constexpr bool isEmpty() const noexcept
Returns true if either of the width and height is less than or equal to 0; otherwise returns false.
constexpr void setHeight(int h) noexcept
Sets the height to the given height.
\macro QT_RESTRICTED_CAST_FROM_ASCII
qsizetype size() const
Returns the number of characters in this string.
bool isEmpty() const
Returns true if the string has no characters; otherwise returns false.
static QString static QString qsizetype indexOf(QChar c, qsizetype from=0, Qt::CaseSensitivity cs=Qt::CaseSensitive) const
QString trimmed() const &
The QStyleHintReturnMask class provides style hints that return a QRegion.
\variable QStyleOptionFocusRect::backgroundColor
The QStyleOption class stores the parameters used by QStyle functions.
void initFrom(const QWidget *w)
The QStylePainter class is a convenience class for drawing QStyle elements inside a widget.
static bool useFullScreenForPopup()
The QStyle class is an abstract base class that encapsulates the look and feel of a GUI.
virtual QSize sizeFromContents(ContentsType ct, const QStyleOption *opt, const QSize &contentsSize, const QWidget *w=nullptr) const =0
Returns the size of the element described by the specified option and type, based on the provided con...
@ SH_MenuBar_AltKeyNavigation
@ SH_Menu_FlashTriggeredItem
@ SH_Menu_SubMenuPopupDelay
@ SH_Menu_SupportsSections
@ SH_Menu_AllowActiveAndDisabled
@ SH_Menu_FillScreenWithScroll
@ SH_Menu_SpaceActivatesItem
virtual int styleHint(StyleHint stylehint, const QStyleOption *opt=nullptr, const QWidget *widget=nullptr, QStyleHintReturn *returnData=nullptr) const =0
Returns an integer representing the specified style hint for the given widget described by the provid...
@ PM_MenuDesktopFrameWidth
virtual int pixelMetric(PixelMetric metric, const QStyleOption *option=nullptr, const QWidget *widget=nullptr) const =0
Returns the value of the given pixel metric.
bool singleShot
whether the timer is a single-shot timer
static void enterWhatsThisMode()
This function switches the user interface into "What's This?" mode.
static void showText(const QPoint &pos, const QString &text, QWidget *w=nullptr)
Shows text as a "What's This?" window, at global position pos.
static bool inWhatsThisMode()
Returns true if the user interface is in "What's This?" mode; otherwise returns false.
ResetOnDestroy(QMenuSloppyState *sloppyState, bool *guard)
QMenuSloppyState * toReset
QSet< QString >::iterator it
Combined button and popup list for selecting options.
@ WA_X11NetWmWindowTypePopupMenu
@ WA_X11NetWmWindowTypeDropDownMenu
@ WA_X11NetWmWindowTypeMenu
DBusConnection const char DBusError DBusBusType DBusError return DBusConnection DBusHandleMessageFunction void DBusFreeFunction return DBusConnection return DBusConnection return const char DBusError return DBusConnection DBusMessage dbus_uint32_t return DBusConnection dbus_bool_t DBusConnection DBusAddWatchFunction DBusRemoveWatchFunction DBusWatchToggledFunction void DBusFreeFunction return DBusConnection DBusDispatchStatusFunction void DBusFreeFunction DBusTimeout return DBusTimeout return DBusWatch return DBusWatch unsigned int return DBusError const DBusError return const DBusMessage return DBusMessage return DBusMessage return DBusMessage return DBusMessage return DBusMessage return DBusMessageIter int const void return DBusMessageIter DBusMessageIter return DBusMessageIter void DBusMessageIter void int return DBusMessage DBusMessageIter return DBusMessageIter return DBusMessageIter DBusMessageIter const char const char const char const char return DBusMessage return DBusMessage const char return DBusMessage dbus_bool_t return DBusMessage dbus_uint32_t return DBusMessage void
void qScrollEffect(QWidget *w, QEffects::DirFlags orient, int time)
void qFadeEffect(QWidget *w, int time)
constexpr const T & qMin(const T &a, const T &b)
constexpr const T & qMax(const T &a, const T &b)
static bool contains(const QJsonArray &haystack, unsigned needle)
GLboolean GLboolean GLboolean b
GLint GLint GLint GLint GLint x
[0]
GLfloat GLfloat GLfloat w
[0]
GLboolean GLboolean GLboolean GLboolean a
[7]
GLenum GLuint GLintptr GLsizeiptr size
[1]
GLdouble GLdouble GLdouble GLdouble top
GLenum GLuint GLintptr offset
GLdouble GLdouble GLdouble GLdouble q
QScopeGuard< typename std::decay< F >::type > qScopeGuard(F &&f)
[qScopeGuard]
#define QT_CONFIG(feature)
static QT_BEGIN_NAMESPACE void init(QTextBoundaryFinder::BoundaryType type, QStringView str, QCharAttributes *attributes)
Q_GUI_EXPORT QPoint toPoint() const noexcept
qsizetype indexOf(const AT &t, qsizetype from=0) const noexcept
bool contains(const AT &t) const noexcept
IUIAutomationTreeWalker __RPC__deref_out_opt IUIAutomationElement ** parent