Qt
Internal/Contributor docs for the Qt SDK. <b>Note:</b> These are NOT official API docs; those are found <a href='https://doc.qt.io/'>here</a>.
Loading...
Searching...
No Matches
qmenu.cpp
Go to the documentation of this file.
1// Copyright (C) 2016 The Qt Company Ltd.
2// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
3
4#include "qmenu.h"
5
6#include <QtWidgets/private/qtwidgetsglobal_p.h>
7#include <QtWidgets/private/qwidgetwindow_p.h>
8
9#include "qactiongroup.h"
10#include "qdebug.h"
11#include "qstyle.h"
12#include "qevent.h"
13#include "qtimer.h"
14#include "qlayout.h"
15#include "qstylepainter.h"
16#include <qpa/qplatformtheme.h>
17#include "qapplication.h"
18#if QT_CONFIG(accessibility)
19# include "qaccessible.h"
20#endif
21#if QT_CONFIG(effects)
22# include <private/qeffects_p.h>
23#endif
24#if QT_CONFIG(whatsthis)
25# include <qwhatsthis.h>
26#endif
27
28#include "qmenu_p.h"
29#if QT_CONFIG(menubar)
30#include "qmenubar_p.h"
31#endif
32#include "qwidgetaction.h"
33#if QT_CONFIG(toolbutton)
34#include "qtoolbutton.h"
35#endif
36#include "qpushbutton.h"
37#if QT_CONFIG(tooltip)
38#include "qtooltip.h"
39#endif
40#include <qwindow.h>
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>
46
48
50
51/* QMenu code */
52// internal class used for the torn off popup
53class QTornOffMenu : public QMenu
54{
56 class QTornOffMenuPrivate : public QMenuPrivate
57 {
58 Q_DECLARE_PUBLIC(QTornOffMenu)
59 public:
60 QTornOffMenuPrivate(QMenu *p) : causedMenu(p), initialized(false) {
61 tornoff = 1;
62 causedPopup.widget = nullptr;
63 causedPopup.action = p->d_func()->causedPopup.action;
64 causedStack = p->d_func()->calcCausedStack();
65 }
66
67 void setMenuSize(const QSize &menuSize) {
68 Q_Q(QTornOffMenu);
69 QSize size = menuSize;
70 const QPoint p = (!initialized) ? causedMenu->pos() : q->pos();
72 const int desktopFrame = q->style()->pixelMetric(QStyle::PM_MenuDesktopFrameWidth, nullptr, q);
73 const int titleBarHeight = q->style()->pixelMetric(QStyle::PM_TitleBarHeight, nullptr, q);
74 if (scroll && (size.height() > screen.height() - titleBarHeight || size.width() > screen.width())) {
75 const int fw = q->style()->pixelMetric(QStyle::PM_MenuPanelWidth, nullptr, q);
76 const int hmargin = q->style()->pixelMetric(QStyle::PM_MenuHMargin, nullptr, q);
78 size.setWidth(qMin(actionRects.at(getLastVisibleAction()).right() + fw + hmargin + rightmargin + 1, screen.width()));
79 size.setHeight(screen.height() - desktopFrame * 2 - titleBarHeight);
80 }
81 q->setFixedSize(size);
82 }
83
84 QList<QPointer<QWidget>> calcCausedStack() const override { return causedStack; }
85 QPointer<QMenu> causedMenu;
86 QList<QPointer<QWidget>> causedStack;
87 bool initialized;
88 };
89
90public:
91 QTornOffMenu(QMenu *p) : QMenu(*(new QTornOffMenuPrivate(p)))
92 {
93 Q_D(QTornOffMenu);
94 // make the torn-off menu a sibling of p (instead of a child)
95 QWidget *parentWidget = d->causedStack.isEmpty() ? p : d->causedStack.constLast();
96 if (!parentWidget && p)
104 setEnabled(p->isEnabled());
105#if QT_CONFIG(style_stylesheet)
106 setStyleSheet(p->styleSheet());
107#endif
108 if (style() != p->style())
109 setStyle(p->style());
110 setContentsMargins(p->contentsMargins());
111 setLayoutDirection(p->layoutDirection());
112 //QObject::connect(this, SIGNAL(triggered(QAction*)), this, SLOT(onTrigger(QAction*)));
113 //QObject::connect(this, SIGNAL(hovered(QAction*)), this, SLOT(onHovered(QAction*)));
114 QList<QAction*> items = p->actions();
115 for(int i = 0; i < items.size(); i++)
117 d->setMenuSize(sizeHint());
118 d->initialized = true;
119 }
121 {
122 Q_D(QTornOffMenu);
123 if (menu != d->causedMenu)
124 return;
125 auto action = static_cast<QAction *>(act->action());
126 if (act->type() == QEvent::ActionAdded) {
127 insertAction(static_cast<QAction *>(act->before()), action);
128 } else if (act->type() == QEvent::ActionRemoved)
129 removeAction(action);
130 }
131 void actionEvent(QActionEvent *e) override
132 {
133 Q_D(QTornOffMenu);
135 if (d->initialized) {
136 d->setMenuSize(sizeHint());
137 }
138 }
139
141 {
142 Q_D(QTornOffMenu);
143 if (!d->causedMenu)
144 return;
145 const QString &cleanTitle = QPlatformTheme::removeMnemonics(d->causedMenu->title()).trimmed();
146 setWindowTitle(cleanTitle);
147 }
148
149public slots:
150 void onTrigger(QAction *action) { d_func()->activateAction(action, QAction::Trigger, false); }
151 void onHovered(QAction *action) { d_func()->activateAction(action, QAction::Hover, false); }
152
153private:
154 Q_DECLARE_PRIVATE(QTornOffMenu)
155 friend class QMenuPrivate;
156};
157
159{
160 Q_Q(QMenu);
161#if QT_CONFIG(whatsthis)
162 q->setAttribute(Qt::WA_CustomWhatsThis);
163#endif
165 defaultMenuAction = menuAction = new QAction(q);
166 menuAction->setMenu(q); // this calls setOverrideMenuAction
167 setOverrideMenuAction(nullptr);
169 if (!tornPopup.isNull())
170 tornPopup->updateWindowTitle();
171 });
172 q->setMouseTracking(q->style()->styleHint(QStyle::SH_Menu_MouseTracking, nullptr, q));
173 if (q->style()->styleHint(QStyle::SH_Menu_Scrollable, nullptr, q)) {
176 }
177
178 sloppyState.initialize(q);
179 delayState.initialize(q);
180 mousePopupDelay = q->style()->styleHint(QStyle::SH_Menu_SubMenuPopupDelay, nullptr, q);
181}
182
184{
185 Q_Q(QMenu);
186 if (platformMenu.isNull())
187 q->setPlatformMenu(QGuiApplicationPrivate::platformTheme()->createPlatformMenu());
188 return platformMenu.data();
189}
190
192{
193 Q_Q(QMenu);
194 if (!platformMenu.isNull() && !platformMenu->parent())
195 delete platformMenu.data();
196
198 if (!platformMenu.isNull()) {
199 QObject::connect(platformMenu, SIGNAL(aboutToShow()), q, SLOT(_q_platformMenuAboutToShow()));
201 }
202}
203
205{
206 Q_Q(QMenu);
207 if (platformMenu.isNull())
208 return;
209
210 QPlatformMenuItem *beforeItem = nullptr;
211 const QList<QAction*> actions = q->actions();
213 QPlatformMenuItem *menuItem = insertActionInPlatformMenu(*it, beforeItem);
214 beforeItem = menuItem;
215 }
216 platformMenu->syncSeparatorsCollapsible(collapsibleSeparators);
217 platformMenu->setEnabled(q->isEnabled());
218}
219
220static QWidget *getParentWidget(const QAction *action)
221{
222 auto result = action->parent();
223 while (result && !qobject_cast<QWidget *>(result))
224 result = result->parent();
225 return static_cast<QWidget *>(result);
226}
227
229{
230 item->setText(action->text());
231 item->setIsSeparator(action->isSeparator());
232 if (action->isIconVisibleInMenu()) {
233 item->setIcon(action->icon());
234 if (QWidget *w = getParentWidget(action)) {
236 opt.initFrom(w);
237 item->setIconSize(w->style()->pixelMetric(QStyle::PM_SmallIconSize, &opt, w));
238 } else {
240 item->setIconSize(QApplication::style()->pixelMetric(QStyle::PM_SmallIconSize, &opt, nullptr));
241 }
242 } else {
243 item->setIcon(QIcon());
244 }
245 item->setVisible(action->isVisible());
246#if QT_CONFIG(shortcut)
247 item->setShortcut(action->shortcut());
248#endif
249 item->setCheckable(action->isCheckable());
250 item->setChecked(action->isChecked());
251 item->setHasExclusiveGroup(action->actionGroup() && action->actionGroup()->isExclusive());
252 item->setFont(action->font());
253 item->setRole((QPlatformMenuItem::MenuRole) action->menuRole());
254 item->setEnabled(action->isEnabled());
255
256 if (action->menu()) {
257 if (!action->menu()->platformMenu())
258 action->menu()->setPlatformMenu(platformMenu->createSubMenu());
259 item->setMenu(action->menu()->platformMenu());
260 } else {
261 item->setMenu(nullptr);
262 }
263}
264
266{
268 Q_ASSERT(menuItem);
269
270 menuItem->setTag(reinterpret_cast<quintptr>(action));
273 copyActionToPlatformItem(action, menuItem);
274 platformMenu->insertMenuItem(menuItem, beforeItem);
275
276 return menuItem;
277}
278
280{
281 Q_Q(const QMenu);
282 return q->style()->pixelMetric(QStyle::PM_MenuScrollerHeight, nullptr, q);
283}
284
285// Windows and KDE allow menus to cover the taskbar, while GNOME and macOS
286// don't. Torn-off menus are again different
288{
289 return !tornoff && QStylePrivate::useFullScreenForPopup();
290}
291
293{
294 Q_Q(const QMenu);
295 if (screen == nullptr
296#if QT_CONFIG(graphicsview)
297 && q->graphicsProxyWidget() == nullptr
298#endif
299 ) {
300 screen = q->isVisible() ? q->screen() : popupScreen.data();
301 }
302 if (useFullScreenForPopup())
303 return screen ? screen->geometry()
307}
308
309QList<QPointer<QWidget>> QMenuPrivate::calcCausedStack() const
310{
311 QList<QPointer<QWidget>> ret;
312 for(QWidget *widget = causedPopup.widget; widget; ) {
313 ret.append(widget);
314 if (QTornOffMenu *qtmenu = qobject_cast<QTornOffMenu*>(widget))
315 ret += qtmenu->d_func()->causedStack;
316 if (QMenu *qmenu = qobject_cast<QMenu*>(widget))
317 widget = qmenu->d_func()->causedPopup.widget;
318 else
319 break;
320 }
321 return ret;
322}
323
325{
326#if QT_CONFIG(menubar)
327 return qobject_cast<const QMenuBar *>(topCausedWidget()) == nullptr;
328#else
329 return true;
330#endif
331}
332
334{
335 updateActionRects(popupGeometry());
336}
337
339{
340 Q_Q(const QMenu);
341 if (!itemsDirty)
342 return;
343
344 q->ensurePolished();
345
346 //let's reinitialize the buffer
347 actionRects.resize(actions.size());
348 actionRects.fill(QRect());
349
350 int lastVisibleAction = getLastVisibleAction();
351
352 QStyle *style = q->style();
354 opt.initFrom(q);
355 const int hmargin = style->pixelMetric(QStyle::PM_MenuHMargin, &opt, q),
358 const int fw = style->pixelMetric(QStyle::PM_MenuPanelWidth, &opt, q);
360 const int tearoffHeight = tearoff ? style->pixelMetric(QStyle::PM_MenuTearoffHeight, &opt, q) : 0;
361 const int base_y = vmargin + fw + topmargin + (scroll ? scroll->scrollOffset : 0) + tearoffHeight;
362 const int column_max_y = screen.height() - 2 * deskFw - (vmargin + bottommargin + fw);
363 int max_column_width = 0;
364 int y = base_y;
365
366 //for compatibility now - will have to refactor this away
367 tabWidth = 0;
368 maxIconWidth = 0;
369 hasCheckableItems = false;
370 ncols = 1;
371
372 for (int i = 0; i < actions.size(); ++i) {
373 QAction *action = actions.at(i);
374 if (action->isSeparator() || !action->isVisible() || widgetItems.contains(action))
375 continue;
376 //..and some members
377 hasCheckableItems |= action->isCheckable();
378 QIcon is = action->icon();
379 if (!is.isNull()) {
380 maxIconWidth = qMax<uint>(maxIconWidth, icone + 4);
381 }
382 }
383
384 //calculate size
385 QFontMetrics qfm = q->fontMetrics();
386 bool previousWasSeparator = true; // this is true to allow removing the leading separators
387#if QT_CONFIG(shortcut)
388 const bool contextMenu = isContextMenu();
389#endif
390 for(int i = 0; i <= lastVisibleAction; i++) {
391 QAction *action = actions.at(i);
392 const bool isSection = action->isSeparator() && (!action->text().isEmpty() || !action->icon().isNull());
393 const bool isPlainSeparator = (isSection && !q->style()->styleHint(QStyle::SH_Menu_SupportsSections))
394 || (action->isSeparator() && !isSection);
395
396 if (!action->isVisible() ||
397 (collapsibleSeparators && previousWasSeparator && isPlainSeparator))
398 continue; // we continue, this action will get an empty QRect
399
400 previousWasSeparator = isPlainSeparator;
401
402 //let the style modify the above size..
404 q->initStyleOption(&opt, action);
405 const QFontMetrics &fm = opt.fontMetrics;
406
407 QSize sz;
408 if (QWidget *w = widgetItems.value(action)) {
409 sz = w->sizeHint().expandedTo(w->minimumSize()).expandedTo(w->minimumSizeHint()).boundedTo(w->maximumSize());
410 } else {
411 //calc what I think the size is..
412 if (action->isSeparator()) {
413 sz = QSize(2, 2);
414 } else {
415 QString s = action->text();
416 qsizetype t = s.indexOf(u'\t');
417 if (t != -1) {
418 tabWidth = qMax(int(tabWidth), qfm.horizontalAdvance(s.mid(t+1)));
419 s = s.left(t);
420#if QT_CONFIG(shortcut)
421 } else if (action->isShortcutVisibleInContextMenu() || !contextMenu) {
422 QKeySequence seq = action->shortcut();
423 if (!seq.isEmpty())
424 tabWidth = qMax(int(tabWidth), qfm.horizontalAdvance(seq.toString(QKeySequence::NativeText)));
425#endif
426 }
427 sz.setWidth(fm.boundingRect(QRect(), Qt::TextSingleLine | Qt::TextShowMnemonic, s).width());
428 sz.setHeight(qMax(fm.height(), qfm.height()));
429
430 QIcon is = action->icon();
431 if (!is.isNull()) {
432 QSize is_sz = QSize(icone, icone);
433 if (is_sz.height() > sz.height())
434 sz.setHeight(is_sz.height());
435 }
436 }
438 }
439
440
441 if (!sz.isEmpty()) {
442 max_column_width = qMax(max_column_width, sz.width());
443 //wrapping
444 if (!scroll && y + sz.height() > column_max_y) {
445 ncols++;
446 y = base_y;
447 } else {
448 y += sz.height();
449 }
450 //update the item
451 actionRects[i] = QRect(0, 0, sz.width(), sz.height());
452 }
453 }
454
455 max_column_width += tabWidth; //finally add in the tab width
456 if (!tornoff || scroll) { // exclude non-scrollable tear-off menu since the tear-off menu has a fixed size
457 const int sfcMargin = style->sizeFromContents(QStyle::CT_Menu, &opt, QSize(0, 0), q).width();
458 const int min_column_width = q->minimumWidth() - (sfcMargin + leftmargin + rightmargin + 2 * (fw + hmargin));
459 max_column_width = qMax(min_column_width, max_column_width);
460 }
461
462 //calculate position
463 int x = hmargin + fw + leftmargin;
464 y = base_y;
465
466 for(int i = 0; i < actions.size(); i++) {
467 QRect &rect = actionRects[i];
468 if (rect.isNull())
469 continue;
470 if (!scroll && y + rect.height() > column_max_y) {
471 x += max_column_width + hmargin;
472 y = base_y;
473 }
474 rect.translate(x, y); //move
475 rect.setWidth(max_column_width); //uniform width
476
477 //we need to update the widgets geometry
478 if (QWidget *widget = widgetItems.value(actions.at(i))) {
481 }
482
483 y += rect.height();
484 }
485 itemsDirty = 0;
486}
487
489{
490 //let's try to get the last visible action
491 int lastVisibleAction = actions.size() - 1;
492 for (;lastVisibleAction >= 0; --lastVisibleAction) {
493 const QAction *action = actions.at(lastVisibleAction);
494 if (action->isVisible()) {
495 //removing trailing separators
496 if (action->isSeparator() && collapsibleSeparators)
497 continue;
498 break;
499 }
500 }
501 return lastVisibleAction;
502}
503
504
506{
507 int index = actions.indexOf(act);
508 if (index == -1)
509 return QRect();
510
511 updateActionRects();
512
513 //we found the action
514 return actionRects.at(index);
515}
516
518{
519 Q_Q(QMenu);
520 bool fadeMenus = q->style()->styleHint(QStyle::SH_Menu_FadeOutOnHide);
521 if (!tornoff) {
522 QWidget *caused = causedPopup.widget;
523 hideMenu(q); //hide after getting causedPopup
524 while(caused) {
525#if QT_CONFIG(menubar)
526 if (QMenuBar *mb = qobject_cast<QMenuBar*>(caused)) {
527 mb->d_func()->setCurrentAction(nullptr);
528 mb->d_func()->setKeyboardMode(false);
529 caused = nullptr;
530 } else
531#endif
532 if (QMenu *m = qobject_cast<QMenu*>(caused)) {
533 caused = m->d_func()->causedPopup.widget;
534 if (!m->d_func()->tornoff)
535 hideMenu(m);
536 if (!fadeMenus) // Mac doesn't clear the action until after hidden.
537 m->d_func()->setCurrentAction(nullptr);
538 } else { caused = nullptr;
539 }
540 }
541 }
542 setCurrentAction(nullptr);
543}
544
546{
547 if (!menu)
548 return;
549
550 // See two execs below. They may trigger an akward situation
551 // when 'menu' (also known as 'q' or 'this' in the many functions
552 // around) to become a dangling pointer if the loop manages
553 // to execute 'deferred delete' ... posted while executing
554 // this same loop. Not good!
555 struct Reposter : QObject
556 {
557 Reposter(QMenu *menu) : q(menu)
558 {
559 Q_ASSERT(q);
560 q->installEventFilter(this);
561 }
562 ~Reposter()
563 {
564 if (deleteLater)
565 q->deleteLater();
566 }
567 bool eventFilter(QObject *obj, QEvent *event) override
568 {
569 if (obj == q && event->type() == QEvent::DeferredDelete)
570 return deleteLater = true;
571
573 }
574 QMenu *q = nullptr;
575 bool deleteLater = false;
576 };
577
578#if QT_CONFIG(effects)
579 // If deleteLater has been called and the event loop spins, while waiting
580 // for visual effects to happen, menu might become stale.
581 // To prevent a QSignalBlocker from restoring a stale object, block and restore signals manually.
582 QPointer<QMenu> stillAlive(menu);
583 const bool signalsBlocked = menu->signalsBlocked();
584 menu->blockSignals(true);
585
586 aboutToHide = true;
587 // Flash item which is about to trigger (if any).
589 && currentAction && currentAction == actionAboutToTrigger
590 && menu->actions().contains(currentAction)) {
591 QEventLoop eventLoop;
592 QAction *activeAction = currentAction;
593
594 menu->setActiveAction(nullptr);
595 const Reposter deleteDeleteLate(menu);
596 QTimer::singleShot(60, &eventLoop, SLOT(quit()));
597 eventLoop.exec();
598
599 if (!stillAlive)
600 return;
601
602 // Select and wait 20 ms.
604 QTimer::singleShot(20, &eventLoop, SLOT(quit()));
605 eventLoop.exec();
606 }
607
608 aboutToHide = false;
609
610 if (stillAlive)
612 else
613 return;
614
615#endif // QT_CONFIG(effects)
616 if (activeMenu == menu)
617 activeMenu = nullptr;
618
619 menu->d_func()->causedPopup.action = nullptr;
620 menu->close();
621 menu->d_func()->causedPopup.widget = nullptr;
622}
623
625{
626 Q_Q(const QMenu);
627 if (const QWidget *parent = q->nativeParentWidget()) {
628 if (parent->windowHandle())
629 return parent->windowHandle();
630 }
631
632 if (const QWindow *w = q->windowHandle()) {
633 if (w->transientParent())
634 return w->transientParent();
635 }
636
637 if (causedPopup.widget) {
638 if (const QWidget *w = causedPopup.widget.data()) {
639 if (const QWidget *ww = w->window())
640 return ww->windowHandle();
641 }
642 }
643
644 return nullptr;
645}
646
647void QMenuPrivate::popupAction(QAction *action, int delay, bool activateFirst)
648{
649 Q_Q(QMenu);
650 if (action) {
651 if (action->isEnabled()) {
652 if (!delay)
653 q->internalDelayedPopup();
654 else if (action->menu() && !action->menu()->isVisible())
655 delayState.start(delay, action);
656 else if (!action->menu())
657 delayState.stop();
658 if (activateFirst && action->menu())
659 action->menu()->d_func()->setFirstActionActive();
660 }
661 } else if (QMenu *menu = activeMenu) { //hide the current item
662 hideMenu(menu);
663 }
664}
665
667{
668 Q_Q(QMenu);
669 QAction *current = currentAction;
670 if (current && (!current->isEnabled() || current->menu() || current->isSeparator()))
671 current = nullptr;
672 for(QWidget *caused = q; caused;) {
673 if (QMenu *m = qobject_cast<QMenu*>(caused)) {
674 caused = m->d_func()->causedPopup.widget;
675 if (m->d_func()->eventLoop)
676 m->d_func()->syncAction = current; // synchronous operation
677 } else {
678 break;
679 }
680 }
681}
682
683
685{
686 Q_Q(QMenu);
687 updateActionRects();
688 for(int i = 0, saccum = 0; i < actions.size(); i++) {
689 const QRect &rect = actionRects.at(i);
690 if (rect.isNull())
691 continue;
692 if (scroll && scroll->scrollFlags & QMenuScroller::ScrollUp) {
693 saccum -= rect.height();
694 if (saccum > scroll->scrollOffset - scrollerHeight())
695 continue;
696 }
697 QAction *act = actions.at(i);
698 if (!act->isSeparator() &&
699 (q->style()->styleHint(QStyle::SH_Menu_AllowActiveAndDisabled, nullptr, q)
700 || act->isEnabled())) {
701 setCurrentAction(act);
702 break;
703 }
704 }
705}
706
707// popup == -1 means do not popup, 0 means immediately, others mean use a timer
708void QMenuPrivate::setCurrentAction(QAction *action, int popup, SelectionReason reason, bool activateFirst)
709{
710 Q_Q(QMenu);
711 tearoffHighlighted = 0;
712
713 if (action
714 && (action->isSeparator()
715 || (!action->isEnabled() && !q->style()->styleHint(QStyle::SH_Menu_AllowActiveAndDisabled, nullptr, q))))
716 action = nullptr;
717
718 // Reselect the currently active action in case mouse moved over other menu items when
719 // moving from sub menu action to sub menu (QTBUG-20094).
720 if (reason != SelectedFromKeyboard) {
721 if (QMenu *menu = qobject_cast<QMenu*>(causedPopup.widget)) {
722 if (causedPopup.action && menu->d_func()->activeMenu == q)
723 // Reselect parent menu action only if mouse is over a menu and parent menu action is not already selected (QTBUG-47987)
724 if (hasReceievedEnter && menu->d_func()->currentAction != causedPopup.action)
725 menu->d_func()->setCurrentAction(causedPopup.action, 0, reason, false);
726 }
727 }
728
729 if (currentAction)
730 q->update(actionRect(currentAction));
731
732 QMenu *hideActiveMenu = activeMenu;
733 QAction *previousAction = currentAction;
734
735 currentAction = action;
736 if (action) {
737 if (!action->isSeparator()) {
738 activateAction(action, QAction::Hover);
739 if (popup != -1) {
740 // if the menu is visible then activate the required action,
741 // otherwise we just mark the action as currentAction
742 // and activate it when the menu will be popuped.
743 if (q->isVisible())
744 popupAction(currentAction, popup, activateFirst);
745 }
746 q->update(actionRect(action));
747
748 if (reason == SelectedFromKeyboard) {
749 QWidget *widget = widgetItems.value(action);
750 if (widget) {
753 } else {
754 //when the action has no QWidget, the QMenu itself should
755 // get the focus
756 // Since the menu is a pop-up, it uses the popup reason.
757 if (!q->hasFocus()) {
758 q->setFocus(Qt::PopupFocusReason);
759 }
760 }
761 }
762 }
763#if QT_CONFIG(statustip)
764 } else if (previousAction) {
765 previousAction->d_func()->showStatusText(topCausedWidget(), QString());
766#endif
767 }
768 if (hideActiveMenu && previousAction != currentAction) {
769 if (popup == -1) {
770#if QT_CONFIG(effects)
771 // kill any running effect
772 qFadeEffect(nullptr);
773 qScrollEffect(nullptr);
774#endif
775 hideMenu(hideActiveMenu);
776 } else if (!currentAction || !currentAction->menu()) {
777 sloppyState.startTimerIfNotRunning();
778 }
779 }
780}
781
783{
784 m_enabled = false;
785 m_first_mouse = true;
786 m_init_guard = false;
787 m_use_reset_action = true;
788 m_uni_dir_discarded_count = 0;
789 m_time.stop();
790 m_reset_action = nullptr;
791 m_origin_action = nullptr;
792 m_action_rect = QRect();
793 m_previous_point = QPointF();
794 if (m_sub_menu) {
795 QMenuPrivate::get(m_sub_menu)->sloppyState.m_parent = nullptr;
796 m_sub_menu = nullptr;
797 }
798}
800{
801 QMenuPrivate *menuPriv = QMenuPrivate::get(m_menu);
802
803 if (m_discard_state_when_entering_parent && m_sub_menu == menuPriv->activeMenu) {
804 menuPriv->hideMenu(m_sub_menu);
805 reset();
806 }
807 if (m_parent)
808 m_parent->childEnter();
809}
810
812{
813 stopTimer();
814 if (m_parent)
815 m_parent->childEnter();
816}
817
819{
820 if (!m_dont_start_time_on_leave) {
821 if (m_parent)
822 m_parent->childLeave();
823 startTimerIfNotRunning();
824 }
825}
826
828{
829 if (m_enabled && !QMenuPrivate::get(m_menu)->hasReceievedEnter) {
830 startTimerIfNotRunning();
831 if (m_parent)
832 m_parent->childLeave();
833 }
834}
835
836void QMenuSloppyState::setSubMenuPopup(const QRect &actionRect, QAction *resetAction, QMenu *subMenu)
837{
838 m_enabled = true;
839 m_init_guard = true;
840 m_use_reset_action = true;
841 m_time.stop();
842 m_action_rect = actionRect;
843 if (m_sub_menu)
844 QMenuPrivate::get(m_sub_menu)->sloppyState.m_parent = nullptr;
845 m_sub_menu = subMenu;
846 QMenuPrivate::get(subMenu)->sloppyState.m_parent = this;
847 m_reset_action = resetAction;
848 m_origin_action = resetAction;
849}
850
852{
853 return m_parent && m_parent->m_menu && QMenuPrivate::get(m_parent->m_menu)->delayState.timer.isActive();
854}
855
857{
858public:
859 ResetOnDestroy(QMenuSloppyState *sloppyState, bool *guard)
860 : toReset(sloppyState)
861 , guard(guard)
862 {
863 *guard = false;
864 }
865
867 {
868 if (!*guard)
869 toReset->reset();
870 }
871
873 bool *guard;
874};
875
877{
878 QMenuPrivate *menu_priv = QMenuPrivate::get(m_menu);
879
880 bool reallyHasMouse = menu_priv->hasReceievedEnter;
881 if (!reallyHasMouse) {
882 // Check whether the menu really has a mouse, because only active popup
883 // menu gets the enter/leave events. Currently Cocoa is an exception.
884 const QPoint lastCursorPos = QGuiApplicationPrivate::lastCursorPosition.toPoint();
885 reallyHasMouse = m_menu->frameGeometry().contains(lastCursorPos);
886 }
887
888 if (menu_priv->currentAction == m_reset_action
889 && reallyHasMouse
890 && (menu_priv->currentAction
891 && menu_priv->currentAction->menu() == menu_priv->activeMenu)) {
892 return;
893 }
894
895 ResetOnDestroy resetState(this, &m_init_guard);
896
897 if (hasParentActiveDelayTimer() || !m_menu->isVisible())
898 return;
899
900 if (m_sub_menu)
901 menu_priv->hideMenu(m_sub_menu);
902
903 if (reallyHasMouse) {
904 if (m_use_reset_action)
905 menu_priv->setCurrentAction(m_reset_action, 0);
906 } else {
907 menu_priv->setCurrentAction(nullptr, 0);
908 }
909}
910
911//return the top causedPopup.widget that is not a QMenu
913{
914 QWidget* top = causedPopup.widget;
915 while (QMenu* m = qobject_cast<QMenu *>(top))
916 top = m->d_func()->causedPopup.widget;
917 return top;
918}
919
921{
922 if (!rect().contains(p)) //sanity check
923 return nullptr;
924
925 for(int i = 0; i < actionRects.size(); i++) {
926 if (actionRects.at(i).contains(p))
927 return actions.at(i);
928 }
929 return nullptr;
930}
931
933{
934 Q_Q(QMenu);
935 QObject::disconnect(menuAction, SIGNAL(destroyed()), q, SLOT(_q_overrideMenuActionDestroyed()));
936 if (a) {
937 menuAction = a;
938 QObject::connect(a, SIGNAL(destroyed()), q, SLOT(_q_overrideMenuActionDestroyed()));
939 } else { //we revert back to the default action created by the QMenu itself
940 menuAction = defaultMenuAction;
941 }
942}
943
945{
946 menuAction=defaultMenuAction;
947}
948
950{
951 Q_Q(QMenu);
952 //we need to mimic the cause of the popup's layout direction
953 //to allow setting it on a mainwindow for example
954 //we call setLayoutDirection_helper to not overwrite a user-defined value
955 if (!q->testAttribute(Qt::WA_SetLayoutDirection)) {
956 if (QWidget *w = causedPopup.widget)
957 setLayoutDirection_helper(w->layoutDirection());
958 else if (QWidget *w = q->parentWidget())
959 setLayoutDirection_helper(w->layoutDirection());
960 else
961 setLayoutDirection_helper(QGuiApplication::layoutDirection());
962 }
963}
964
966{
967 if (!painter || rect.isEmpty())
968 return;
969
970 if (!scroll || !(scroll->scrollFlags & (QMenuPrivate::QMenuScroller::ScrollUp
972 return;
973
974 Q_Q(QMenu);
975 QStyleOptionMenuItem menuOpt;
976 menuOpt.initFrom(q);
977 menuOpt.state = QStyle::State_None;
978 menuOpt.checkType = QStyleOptionMenuItem::NotCheckable;
979 menuOpt.maxIconWidth = 0;
980 menuOpt.reservedShortcutWidth = 0;
981 menuOpt.rect = rect;
982 menuOpt.menuItemType = QStyleOptionMenuItem::Scroller;
983 menuOpt.state |= QStyle::State_Enabled;
985 menuOpt.state |= QStyle::State_DownArrow;
986
987 painter->setClipRect(menuOpt.rect);
988 q->style()->drawControl(QStyle::CE_MenuScroller, &menuOpt, painter, q);
989}
990
992{
993 if (!painter || rect.isEmpty())
994 return;
995
996 if (!tearoff)
997 return;
998
999 Q_Q(QMenu);
1000 QStyleOptionMenuItem menuOpt;
1001 menuOpt.initFrom(q);
1002 menuOpt.state = QStyle::State_None;
1003 menuOpt.checkType = QStyleOptionMenuItem::NotCheckable;
1004 menuOpt.maxIconWidth = 0;
1005 menuOpt.reservedShortcutWidth = 0;
1006 menuOpt.rect = rect;
1007 menuOpt.menuItemType = QStyleOptionMenuItem::TearOff;
1008 if (tearoffHighlighted)
1009 menuOpt.state |= QStyle::State_Selected;
1010
1011 painter->setClipRect(menuOpt.rect);
1012 q->style()->drawControl(QStyle::CE_MenuTearoff, &menuOpt, painter, q);
1013}
1014
1016{
1017 Q_Q(const QMenu);
1018 QStyle *style = q->style();
1019 QStyleOption opt(0);
1020 opt.initFrom(q);
1021 const int hmargin = style->pixelMetric(QStyle::PM_MenuHMargin, &opt, q);
1022 const int vmargin = style->pixelMetric(QStyle::PM_MenuVMargin, &opt, q);
1023 const int fw = style->pixelMetric(QStyle::PM_MenuPanelWidth, &opt, q);
1024 return (q->rect().adjusted(hmargin + fw + leftmargin, vmargin + fw + topmargin,
1025 -(hmargin + fw + rightmargin), -(vmargin + fw + bottommargin)));
1026}
1027
1029 : QWidget(parent, f), menuPrivate(mPrivate), scrollType(type)
1030{
1031 if (parent)
1032 setMouseTracking(parent->style()->styleHint(QStyle::SH_Menu_MouseTracking, nullptr, parent));
1033}
1034
1036{
1037 if (!e->rect().intersects(rect()))
1038 return;
1039
1040 QPainter p(this);
1041 QWidget *parent = parentWidget();
1042
1043 //paint scroll up / down arrows
1044 menuPrivate->drawScroller(&p, scrollType, QRect(0, 0, width(), menuPrivate->scrollerHeight()));
1045 //paint the tear off
1047 QRect rect(0, 0, width(), parent->style()->pixelMetric(QStyle::PM_MenuTearoffHeight, nullptr, parent));
1048 if (menuPrivate->scroll && menuPrivate->scroll->scrollFlags & QMenuPrivate::QMenuScroller::ScrollUp)
1049 rect.translate(0, menuPrivate->scrollerHeight());
1050 menuPrivate->drawTearOff(&p, rect);
1051 }
1052}
1053
1055{
1056 if (rect.isEmpty())
1057 setVisible(false);
1058 else {
1059 setGeometry(rect);
1060 raise();
1061 setVisible(true);
1062 }
1063}
1064
1065
1070{
1071 return d_func()->menuAction;
1072}
1073
1093{
1094 return d_func()->menuAction->text();
1095}
1096
1098{
1099 d_func()->menuAction->setText(text);
1100}
1101
1112{
1113 return d_func()->menuAction->icon();
1114}
1115
1117{
1118 d_func()->menuAction->setIcon(icon);
1119}
1120
1121
1122//actually performs the scrolling
1124{
1125 Q_Q(QMenu);
1126 if (!scroll || !scroll->scrollFlags)
1127 return;
1129 int newOffset = 0;
1130 const int topScroll = (scroll->scrollFlags & QMenuScroller::ScrollUp) ? scrollerHeight() : 0;
1131 const int botScroll = (scroll->scrollFlags & QMenuScroller::ScrollDown) ? scrollerHeight() : 0;
1132 const int vmargin = q->style()->pixelMetric(QStyle::PM_MenuVMargin, nullptr, q);
1133 const int fw = q->style()->pixelMetric(QStyle::PM_MenuPanelWidth, nullptr, q);
1134
1136 for(int i = 0, saccum = 0; i < actions.size(); i++) {
1137 if (actions.at(i) == action) {
1138 newOffset = topScroll - saccum;
1139 break;
1140 }
1141 saccum += actionRects.at(i).height();
1142 }
1143 } else {
1144 for(int i = 0, saccum = 0; i < actions.size(); i++) {
1145 saccum += actionRects.at(i).height();
1146 if (actions.at(i) == action) {
1148 newOffset = ((q->height() / 2) - botScroll) - (saccum - topScroll);
1149 else
1150 newOffset = (q->height() - botScroll) - saccum;
1151 break;
1152 }
1153 }
1154 if (newOffset)
1155 newOffset -= fw * 2;
1156 }
1157
1158 //figure out which scroll flags
1159 uint newScrollFlags = QMenuScroller::ScrollNone;
1160 if (newOffset < 0) //easy and cheap one
1161 newScrollFlags |= QMenuScroller::ScrollUp;
1162 int saccum = newOffset;
1163 for(int i = 0; i < actionRects.size(); i++) {
1164 saccum += actionRects.at(i).height();
1165 if (saccum > q->height()) {
1166 newScrollFlags |= QMenuScroller::ScrollDown;
1167 break;
1168 }
1169 }
1170
1171 if (!(newScrollFlags & QMenuScroller::ScrollDown) && (scroll->scrollFlags & QMenuScroller::ScrollDown)) {
1172 newOffset = q->height() - (saccum - newOffset) - fw*2 - vmargin - topmargin - bottommargin; //last item at bottom
1173 if (tearoff)
1174 newOffset -= q->style()->pixelMetric(QStyle::PM_MenuTearoffHeight, nullptr, q);
1175 }
1176
1177 if (!(newScrollFlags & QMenuScroller::ScrollUp) && (scroll->scrollFlags & QMenuScroller::ScrollUp)) {
1178 newOffset = 0; //first item at top
1179 }
1180
1181 if (newScrollFlags & QMenuScroller::ScrollUp)
1182 newOffset -= vmargin;
1183
1185 const int desktopFrame = q->style()->pixelMetric(QStyle::PM_MenuDesktopFrameWidth, nullptr, q);
1186 if (q->height() < screen.height()-(desktopFrame*2)-1) {
1187 QRect geom = q->geometry();
1188 if (newOffset > scroll->scrollOffset && (scroll->scrollFlags & newScrollFlags & QMenuScroller::ScrollUp)) { //scroll up
1189 const int newHeight = geom.height()-(newOffset-scroll->scrollOffset);
1190 if (newHeight > geom.height())
1191 geom.setHeight(newHeight);
1192 } else if (scroll->scrollFlags & newScrollFlags & QMenuScroller::ScrollDown) {
1193 int newTop = geom.top() + (newOffset-scroll->scrollOffset);
1194 if (newTop < desktopFrame+screen.top())
1195 newTop = desktopFrame+screen.top();
1196 if (newTop < geom.top()) {
1197 geom.setTop(newTop);
1198 newOffset = 0;
1199 newScrollFlags &= ~QMenuScroller::ScrollUp;
1200 }
1201 }
1202 if (geom.bottom() > screen.bottom() - desktopFrame)
1203 geom.setBottom(screen.bottom() - desktopFrame);
1204 if (geom.top() < desktopFrame+screen.top())
1205 geom.setTop(desktopFrame+screen.top());
1206 if (geom != q->geometry()) {
1207#if 0
1208 if (newScrollFlags & QMenuScroller::ScrollDown &&
1209 q->geometry().top() - geom.top() >= -newOffset)
1210 newScrollFlags &= ~QMenuScroller::ScrollDown;
1211#endif
1212 q->setGeometry(geom);
1213 }
1214 }
1215
1216 //actually update flags
1217 const int delta = qMin(0, newOffset) - scroll->scrollOffset; //make sure the new offset is always negative
1218 if (!itemsDirty && delta) {
1219 //we've scrolled so we need to update the action rects
1220 for (int i = 0; i < actionRects.size(); ++i) {
1221 QRect &current = actionRects[i];
1222 current.moveTop(current.top() + delta);
1223
1224 //we need to update the widgets geometry
1226 w->setGeometry(current);
1227 }
1228 }
1229 scroll->scrollOffset += delta;
1230 scroll->scrollFlags = newScrollFlags;
1231 if (active)
1232 setCurrentAction(action);
1233
1234 q->update(); //issue an update so we see all the new state..
1235}
1236
1238{
1239 Q_Q(QMenu);
1242 for(int i = actions.size()-1; i >= 0; --i) {
1243 QAction *act = actions.at(i);
1244 if (actionRects.at(i).isNull())
1245 continue;
1246 if (!act->isSeparator() &&
1247 (q->style()->styleHint(QStyle::SH_Menu_AllowActiveAndDisabled, nullptr, q)
1248 || act->isEnabled())) {
1251 else if (active)
1253 break;
1254 }
1255 }
1256 } else if (location == QMenuScroller::ScrollTop) {
1257 for(int i = 0; i < actions.size(); ++i) {
1258 QAction *act = actions.at(i);
1259 if (actionRects.at(i).isNull())
1260 continue;
1261 if (!act->isSeparator() &&
1262 (q->style()->styleHint(QStyle::SH_Menu_AllowActiveAndDisabled, nullptr, q)
1263 || act->isEnabled())) {
1266 else if (active)
1268 break;
1269 }
1270 }
1271 }
1272}
1273
1274//only directional
1276{
1277 Q_Q(QMenu);
1278 if (!scroll || !(scroll->scrollFlags & direction)) //not really possible...
1279 return;
1281 const int topScroll = (scroll->scrollFlags & QMenuScroller::ScrollUp) ? scrollerHeight() : 0;
1282 const int botScroll = (scroll->scrollFlags & QMenuScroller::ScrollDown) ? scrollerHeight() : 0;
1283 const int vmargin = q->style()->pixelMetric(QStyle::PM_MenuVMargin, nullptr, q);
1284 const int fw = q->style()->pixelMetric(QStyle::PM_MenuPanelWidth, nullptr, q);
1285 const int offset = topScroll ? topScroll-vmargin : 0;
1287 for(int i = 0, saccum = 0; i < actions.size(); i++) {
1288 saccum -= actionRects.at(i).height();
1289 if (saccum <= scroll->scrollOffset-offset) {
1291 break;
1292 }
1293 }
1294 } else if (direction == QMenuScroller::ScrollDown) {
1295 bool scrolled = false;
1296 for(int i = 0, saccum = 0; i < actions.size(); i++) {
1297 const int iHeight = actionRects.at(i).height();
1298 saccum -= iHeight;
1299 if (saccum <= scroll->scrollOffset-offset) {
1300 const int scrollerArea = q->height() - botScroll - fw*2;
1301 int visible = (scroll->scrollOffset-offset) - saccum;
1302 for(i++ ; i < actions.size(); i++) {
1303 visible += actionRects.at(i).height();
1304 if (visible > scrollerArea - topScroll) {
1305 scrolled = true;
1307 break;
1308 }
1309 }
1310 break;
1311 }
1312 }
1313 if (!scrolled) {
1314 scroll->scrollFlags &= ~QMenuScroller::ScrollDown;
1315 q->update();
1316 }
1317 }
1318}
1319
1320/* This is poor-mans eventfilters. This avoids the use of
1321 eventFilter (which can be nasty for users of QMenuBar's). */
1323{
1324 Q_Q(QMenu);
1325 QPoint pos = q->mapFromGlobal(e->globalPosition().toPoint());
1326
1327 QStyle *style = q->style();
1328 QStyleOption opt(0);
1329 opt.initFrom(q);
1330 const int hmargin = style->pixelMetric(QStyle::PM_MenuHMargin, &opt, q);
1331 const int vmargin = style->pixelMetric(QStyle::PM_MenuVMargin, &opt, q);
1332 const int fw = style->pixelMetric(QStyle::PM_MenuPanelWidth, &opt, q);
1333
1334 if (scroll && !activeMenu) { //let the scroller "steal" the event
1335 bool isScroll = false;
1336 if (pos.x() >= 0 && pos.x() < q->width()) {
1338 if (scroll->scrollFlags & dir) {
1340 isScroll = (pos.y() <= scrollerHeight() + fw + vmargin + topmargin);
1341 else if (dir == QMenuScroller::ScrollDown)
1342 isScroll = (pos.y() >= q->height() - scrollerHeight() - fw - vmargin - bottommargin);
1343 if (isScroll) {
1344 scroll->scrollDirection = dir;
1345 break;
1346 }
1347 }
1348 }
1349 }
1350 if (isScroll) {
1351 scroll->scrollTimer.start(50, q);
1352 return true;
1353 } else {
1354 scroll->scrollTimer.stop();
1355 }
1356 }
1357
1358 if (tearoff) { //let the tear off thingie "steal" the event..
1359 QRect tearRect(leftmargin + hmargin + fw, topmargin + vmargin + fw, q->width() - fw * 2 - hmargin * 2 -leftmargin - rightmargin,
1360 q->style()->pixelMetric(QStyle::PM_MenuTearoffHeight, &opt, q));
1362 tearRect.translate(0, scrollerHeight());
1363 q->update(tearRect);
1364 if (tearRect.contains(pos) && hasMouseMoved(e->globalPosition().toPoint())) {
1365 setCurrentAction(nullptr);
1367 if (e->type() == QEvent::MouseButtonRelease) {
1368 if (!tornPopup)
1369 tornPopup = new QTornOffMenu(q);
1370 tornPopup->setGeometry(q->geometry());
1371 tornPopup->show();
1373 }
1374 return true;
1375 }
1377 }
1378
1379 if (q->frameGeometry().contains(e->globalPosition().toPoint()))
1380 return false; //otherwise if the event is in our rect we want it..
1381
1382 for(QWidget *caused = causedPopup.widget; caused;) {
1383 bool passOnEvent = false;
1384 QWidget *next_widget = nullptr;
1385 QPointF cpos = caused->mapFromGlobal(e->globalPosition());
1386#if QT_CONFIG(menubar)
1387 if (QMenuBar *mb = qobject_cast<QMenuBar*>(caused)) {
1388 passOnEvent = mb->rect().contains(cpos.toPoint());
1389 } else
1390#endif
1391 if (QMenu *m = qobject_cast<QMenu*>(caused)) {
1392 passOnEvent = m->rect().contains(cpos.toPoint());
1393 next_widget = m->d_func()->causedPopup.widget;
1394 }
1395 if (passOnEvent) {
1396 if (e->type() != QEvent::MouseButtonRelease || mouseDown == caused) {
1397 QMouseEvent new_e(e->type(), cpos, caused->mapTo(caused->topLevelWidget(), cpos), e->globalPosition(),
1398 e->button(), e->buttons(), e->modifiers(),
1399 e->source(), e->pointingDevice());
1400 QCoreApplication::sendEvent(caused, &new_e);
1401 return true;
1402 }
1403 }
1404 caused = next_widget;
1405 if (!caused)
1406 sloppyState.leave(); // Start timers
1407 }
1408 return false;
1409}
1410
1411void QMenuPrivate::activateCausedStack(const QList<QPointer<QWidget>> &causedStack, QAction *action,
1412 QAction::ActionEvent action_e, bool self)
1413{
1414 Q_Q(QMenu);
1415 // can't use QBoolBlocker here
1416 const bool activationRecursionGuardReset = activationRecursionGuard;
1418 QPointer<QMenu> guard(q);
1419 if (self)
1420 action->activate(action_e);
1421 if (!guard)
1422 return;
1423 auto boolBlocker = qScopeGuard([this, activationRecursionGuardReset]{
1424 activationRecursionGuard = activationRecursionGuardReset;
1425 });
1426
1427 for(int i = 0; i < causedStack.size(); ++i) {
1428 QPointer<QWidget> widget = causedStack.at(i);
1429 if (!widget)
1430 continue;
1431 //fire
1432 if (QMenu *qmenu = qobject_cast<QMenu*>(widget)) {
1433 widget = qmenu->d_func()->causedPopup.widget;
1434 if (action_e == QAction::Trigger) {
1435 emit qmenu->triggered(action);
1436 } else if (action_e == QAction::Hover) {
1437 emit qmenu->hovered(action);
1438 }
1439#if QT_CONFIG(menubar)
1440 } else if (QMenuBar *qmenubar = qobject_cast<QMenuBar*>(widget)) {
1441 if (action_e == QAction::Trigger) {
1442 emit qmenubar->triggered(action);
1443 } else if (action_e == QAction::Hover) {
1444 emit qmenubar->hovered(action);
1445 }
1446 break; //nothing more..
1447#endif
1448 }
1449 }
1450}
1451
1453{
1454 Q_Q(QMenu);
1455#if QT_CONFIG(whatsthis)
1456 bool inWhatsThisMode = QWhatsThis::inWhatsThisMode();
1457#endif
1458 if (!action || !q->isEnabled()
1459 || (action_e == QAction::Trigger
1460#if QT_CONFIG(whatsthis)
1461 && !inWhatsThisMode
1462#endif
1463 && (action->isSeparator() ||!action->isEnabled())))
1464 return;
1465
1466 /* I have to save the caused stack here because it will be undone after popup execution (ie in the hide).
1467 Then I iterate over the list to actually send the events. --Sam
1468 */
1469 const QList<QPointer<QWidget>> causedStack = calcCausedStack();
1470 if (action_e == QAction::Trigger) {
1471#if QT_CONFIG(whatsthis)
1472 if (!inWhatsThisMode)
1473 actionAboutToTrigger = action;
1474#endif
1475
1476 if (q->testAttribute(Qt::WA_DontShowOnScreen)) {
1478 } else {
1480 if (QMenu *qmenu = qobject_cast<QMenu*>(widget)) {
1481 if (qmenu == q)
1483 widget = qmenu->d_func()->causedPopup.widget;
1484 } else {
1485 break;
1486 }
1487 }
1488 }
1489
1490#if QT_CONFIG(whatsthis)
1491 if (inWhatsThisMode) {
1492 QString s = action->whatsThis();
1493 if (s.isEmpty())
1494 s = whatsThis;
1495 QWhatsThis::showText(q->mapToGlobal(actionRect(action).center()), s, q);
1496 return;
1497 }
1498#endif
1499 }
1500
1501 QPointer<QMenu> thisGuard(q);
1502 activateCausedStack(causedStack, action, action_e, self);
1503 if (!thisGuard)
1504 return;
1505
1506 if (action_e == QAction::Hover) {
1507#if QT_CONFIG(accessibility)
1508 if (QAccessible::isActive()) {
1509 int actionIndex = indexOf(action);
1510 QAccessibleEvent focusEvent(q, QAccessible::Focus);
1511 focusEvent.setChild(actionIndex);
1512 QAccessible::updateAccessibility(&focusEvent);
1513 }
1514#endif
1516 } else {
1517 actionAboutToTrigger = nullptr;
1518 }
1519}
1520
1522{
1523 Q_Q(QMenu);
1524 if (QAction *action = qobject_cast<QAction *>(q->sender())) {
1525 QPointer<QAction> actionGuard = action;
1526 if (platformMenu && widgetItems.value(action))
1528 emit q->triggered(action);
1529 if (!activationRecursionGuard && actionGuard) {
1530 //in case the action has not been activated by the mouse
1531 //we check the parent hierarchy
1532 QList<QPointer<QWidget>> list;
1533 for(QWidget *widget = q->parentWidget(); widget; ) {
1534 if (qobject_cast<QMenu*>(widget)
1535#if QT_CONFIG(menubar)
1536 || qobject_cast<QMenuBar*>(widget)
1537#endif
1538 ) {
1541 } else {
1542 break;
1543 }
1544 }
1545 activateCausedStack(list, action, QAction::Trigger, false);
1546 // if a widget action fires, we need to hide the menu explicitly
1547 if (qobject_cast<QWidgetAction*>(action))
1549 }
1550 }
1551}
1552
1554{
1555 Q_Q(QMenu);
1556 if (QAction * action = qobject_cast<QAction *>(q->sender())) {
1557 emit q->hovered(action);
1558 }
1559}
1560
1562{
1563 Q_Q(QMenu);
1564
1565 emit q->aboutToShow();
1566
1567#ifdef Q_OS_MACOS
1568 if (platformMenu) {
1569 const auto actions = q->actions();
1570 for (QAction *action : actions) {
1571 if (QWidget *widget = widgetItems.value(action))
1572 if (widget->parent() == q) {
1573 QPlatformMenuItem *menuItem = platformMenu->menuItemForTag(reinterpret_cast<quintptr>(action));
1574 moveWidgetToPlatformItem(widget, menuItem);
1575 platformMenu->syncMenuItem(menuItem);
1576 }
1577 }
1578 }
1579#endif
1580}
1581
1583{
1584 //determines if the mouse has moved (ie its initial position has
1585 //changed by more than QApplication::startDragDistance()
1586 //or if there were at least 6 mouse motions)
1587 return motions > 6 ||
1588 QApplication::startDragDistance() < (mousePopupPos - globalPos).manhattanLength();
1589}
1590
1591
1600{
1601 if (!option || !action)
1602 return;
1603
1604 Q_D(const QMenu);
1605 option->initFrom(this);
1606 option->palette = palette();
1607 option->state = QStyle::State_None;
1608
1609 if (window()->isActiveWindow())
1610 option->state |= QStyle::State_Active;
1611 if (isEnabled() && action->isEnabled()
1612 && (!action->menu() || action->menu()->isEnabled()))
1613 option->state |= QStyle::State_Enabled;
1614 else
1615 option->palette.setCurrentColorGroup(QPalette::Disabled);
1616
1617 option->font = action->font().resolve(font());
1618 option->fontMetrics = QFontMetrics(option->font);
1619
1620 if (d->currentAction && d->currentAction == action && !d->currentAction->isSeparator()) {
1623 }
1624
1625 option->menuHasCheckableItems = d->hasCheckableItems;
1626 if (!action->isCheckable()) {
1628 } else {
1629 option->checkType = (action->actionGroup() && action->actionGroup()->isExclusive())
1631 option->checked = action->isChecked();
1632 }
1633 if (action->menu())
1634 option->menuItemType = QStyleOptionMenuItem::SubMenu;
1635 else if (action->isSeparator())
1637 else if (d->defaultAction == action)
1639 else
1640 option->menuItemType = QStyleOptionMenuItem::Normal;
1641 if (action->isIconVisibleInMenu())
1642 option->icon = action->icon();
1643 QString textAndAccel = action->text();
1644#ifndef QT_NO_SHORTCUT
1645 if ((action->isShortcutVisibleInContextMenu() || !d->isContextMenu())
1646 && textAndAccel.indexOf(u'\t') == -1) {
1647 QKeySequence seq = action->shortcut();
1648 if (!seq.isEmpty())
1649 textAndAccel += u'\t' + seq.toString(QKeySequence::NativeText);
1650 }
1651#endif
1652 option->text = textAndAccel;
1653 option->reservedShortcutWidth = d->tabWidth;
1654 option->maxIconWidth = d->maxIconWidth;
1655 option->menuRect = rect();
1656}
1657
1747 : QWidget(*new QMenuPrivate, parent, Qt::Popup)
1748{
1749 Q_D(QMenu);
1750 d->init();
1751}
1752
1763 : QMenu(parent)
1764{
1765 Q_D(QMenu);
1766 d->menuAction->setText(title);
1767}
1768
1771QMenu::QMenu(QMenuPrivate &dd, QWidget *parent)
1772 : QWidget(dd, parent, Qt::Popup)
1773{
1774 Q_D(QMenu);
1775 d->init();
1776}
1777
1782{
1783 Q_D(QMenu);
1784 if (!d->widgetItems.isEmpty()) { // avoid detach on shared null hash
1786 for (; it != d->widgetItems.end(); ++it) {
1787 if (QWidget *widget = it.value()) {
1788 QWidgetAction *action = static_cast<QWidgetAction *>(it.key());
1789 action->releaseWidget(widget);
1790 *it = 0;
1791 }
1792 }
1793 }
1794
1795 if (d->eventLoop)
1796 d->eventLoop->exit();
1798}
1799
1800#if QT_DEPRECATED_SINCE(6, 4)
1807#if QT_CONFIG(shortcut)
1808QAction *QMenu::addAction(const QString &text, const QObject *receiver, const char* member, const QKeySequence &shortcut)
1809{
1810 return QWidget::addAction(text, shortcut, receiver, member);
1811}
1812#endif
1813
1857#if QT_CONFIG(shortcut)
1858QAction *QMenu::addAction(const QIcon &icon, const QString &text, const QObject *receiver,
1859 const char* member, const QKeySequence &shortcut)
1860{
1861 QAction *action = new QAction(icon, text, this);
1862 action->setShortcut(shortcut);
1863 QObject::connect(action, SIGNAL(triggered(bool)), receiver, member);
1864 addAction(action);
1865 return action;
1866}
1867#endif
1868#endif // QT_DEPRECATED_SINCE(6, 4)
1869
1878{
1879 QAction *action = menu->menuAction();
1880 addAction(action);
1881 return action;
1882}
1883
1891{
1892 QMenu *menu = new QMenu(title, this);
1894 return menu;
1895}
1896
1904{
1905 QMenu *menu = new QMenu(title, this);
1906 menu->setIcon(icon);
1908 return menu;
1909}
1910
1922{
1923 QAction *action = new QAction(this);
1924 action->setSeparator(true);
1925 addAction(action);
1926 return action;
1927}
1928
1946{
1947 QAction *action = new QAction(text, this);
1948 action->setSeparator(true);
1949 addAction(action);
1950 return action;
1951}
1952
1970{
1971 QAction *action = new QAction(icon, text, this);
1972 action->setSeparator(true);
1973 addAction(action);
1974 return action;
1975}
1976
1984{
1985 QAction *action = menu->menuAction();
1986 insertAction(before, action);
1987 return action;
1988}
1989
2001{
2002 QAction *action = new QAction(this);
2003 action->setSeparator(true);
2004 insertAction(before, action);
2005 return action;
2006}
2007
2026{
2027 QAction *action = new QAction(text, this);
2028 action->setSeparator(true);
2029 insertAction(before, action);
2030 return action;
2031}
2032
2050{
2051 QAction *action = new QAction(icon, text, this);
2052 action->setSeparator(true);
2053 insertAction(before, action);
2054 return action;
2055}
2056
2065{
2066 d_func()->defaultAction = act;
2067}
2068
2075{
2076 return d_func()->defaultAction;
2077}
2078
2093{
2094 Q_D(QMenu);
2095 if (d->tearoff == b)
2096 return;
2097 if (!b)
2099 d->tearoff = b;
2100
2101 d->itemsDirty = true;
2102 if (isVisible())
2103 resize(sizeHint());
2104}
2105
2107{
2108 return d_func()->tearoff;
2109}
2110
2119{
2120 if (d_func()->tornPopup)
2121 return d_func()->tornPopup->isVisible();
2122 return false;
2123}
2124
2134{
2135 Q_D(QMenu);
2136 if (!d->tornPopup)
2137 d->tornPopup = new QTornOffMenu(this);
2138 const QSize &s = sizeHint();
2139 d->tornPopup->setGeometry(pos.x(), pos.y(), s.width(), s.height());
2140 d->tornPopup->show();
2141}
2142
2156
2164{
2165 Q_D(QMenu);
2166 if (d->tornPopup) {
2167 d->tornPopup->close();
2168 // QTornOffMenu sets WA_DeleteOnClose, so we
2169 // should consider the torn-off menu deleted.
2170 // This way showTearOffMenu() will not try to
2171 // reuse the dying torn-off menu.
2172 d->tornPopup = nullptr;
2173 }
2174}
2175
2176
2181{
2182 Q_D(QMenu);
2183 d->setCurrentAction(act, 0);
2184 if (d->scroll && act)
2186}
2187
2188
2194{
2195 return d_func()->currentAction;
2196}
2197
2207bool QMenu::isEmpty() const
2208{
2209 bool ret = true;
2210 for(int i = 0; ret && i < actions().size(); ++i) {
2211 const QAction *action = actions().at(i);
2212 if (!action->isSeparator() && action->isVisible()) {
2213 ret = false;
2214 }
2215 }
2216 return ret;
2217}
2218
2226{
2227 QList<QAction*> acts = actions();
2228
2229 for(int i = 0; i < acts.size(); i++) {
2230 removeAction(acts[i]);
2231 if (acts[i]->parent() == this && acts[i]->d_func()->associatedObjects.isEmpty())
2232 delete acts[i];
2233 }
2234}
2235
2244{
2245 return d_func()->ncols;
2246}
2247
2252{
2253 if (QAction *ret = d_func()->actionAt(pt))
2254 return ret;
2255 return nullptr;
2256}
2257
2262{
2263 return d_func()->actionRect(act);
2264}
2265
2270{
2271 Q_D(const QMenu);
2272 d->updateActionRects();
2273
2274 QSize s;
2275 for (int i = 0; i < d->actionRects.size(); ++i) {
2276 const QRect &rect = d->actionRects.at(i);
2277 if (rect.isNull())
2278 continue;
2279 if (rect.bottom() >= s.height())
2280 s.setHeight(rect.y() + rect.height());
2281 if (rect.right() >= s.width())
2282 s.setWidth(rect.x() + rect.width());
2283 }
2284 // Note that the action rects calculated above already include
2285 // the top and left margins, so we only need to add margins for
2286 // the bottom and right.
2287 QStyleOption opt(0);
2288 opt.initFrom(this);
2289 const int fw = style()->pixelMetric(QStyle::PM_MenuPanelWidth, &opt, this);
2290 s.rwidth() += style()->pixelMetric(QStyle::PM_MenuHMargin, &opt, this) + fw + d->rightmargin;
2291 s.rheight() += style()->pixelMetric(QStyle::PM_MenuVMargin, &opt, this) + fw + d->bottommargin;
2292
2293 return style()->sizeFromContents(QStyle::CT_Menu, &opt, s, this);
2294}
2295
2310void QMenu::popup(const QPoint &p, QAction *atAction)
2311{
2312 Q_D(QMenu);
2313 d->popup(p, atAction);
2314}
2315
2316void QMenuPrivate::popup(const QPoint &p, QAction *atAction, PositionFunction positionFunction)
2317{
2318 Q_Q(QMenu);
2320 QScopeGuard popupScreenGuard([this](){ popupScreen.clear(); });
2321
2322 if (scroll) { // reset scroll state from last popup
2323 if (scroll->scrollOffset)
2324 itemsDirty = 1; // sizeHint will be incorrect if there is previous scroll
2325 scroll->scrollOffset = 0;
2327 }
2329 motions = 0;
2330 doChildEffects = true;
2332
2333 q->ensurePolished(); // Get the right font
2334
2335 // Ensure that we get correct sizeHints by placing this window on the correct screen.
2336 // However if the QMenu was constructed with a Qt::Desktop widget as its parent,
2337 // then initialScreenIndex was set, so we should respect that for the lifetime of this menu.
2338 // However if eventLoop exists, then exec() already did this by calling createWinId(); so leave it alone. (QTBUG-76162)
2339 if (!eventLoop) {
2340 bool screenSet = false;
2342 if (screen) {
2343 if (setScreen(screen))
2344 itemsDirty = true;
2345 screenSet = true;
2346 } else if (QMenu *parentMenu = qobject_cast<QMenu *>(parent)) {
2347 // a submenu is always opened from an open parent menu,
2348 // so show it on the same screen where the parent is. (QTBUG-76162)
2349 if (setScreen(parentMenu->screen()))
2350 itemsDirty = true;
2351 screenSet = true;
2352 }
2353 if (!screenSet && setScreenForPoint(p))
2354 itemsDirty = true;
2355 }
2356
2357 const bool contextMenu = isContextMenu();
2358 if (lastContextMenu != contextMenu) {
2359 itemsDirty = true;
2360 lastContextMenu = contextMenu;
2361 }
2362
2363 // Until QWidget::metric accepts the screen set on a widget (without having a window handle)
2364 // we need to make sure we get a window handle. This must be done near here because
2365 // we want the screen to be correctly set and items to be marked dirty.
2366 // (and screen set could 'fail' on oldscreen == newScreen if created before causing the
2367 // itemsDirty not to be set though needed to get the correct size on first show).
2368 if (!windowHandle()) {
2369 createWinId();
2370 }
2371
2372#if QT_CONFIG(menubar)
2373 // if this menu is part of a chain attached to a QMenuBar, set the
2374 // _NET_WM_WINDOW_TYPE_DROPDOWN_MENU X11 window type
2375 q->setAttribute(Qt::WA_X11NetWmWindowTypeDropDownMenu, qobject_cast<QMenuBar *>(topCausedWidget()) != nullptr);
2376#endif
2377
2378 emit q->aboutToShow();
2379 const bool actionListChanged = itemsDirty;
2380
2381 QRect screen;
2382#if QT_CONFIG(graphicsview)
2383 bool isEmbedded = !bypassGraphicsProxyWidget(q) && QMenuPrivate::nearestGraphicsProxyWidget(q);
2384 if (isEmbedded)
2386 else
2387#endif
2390
2391 QPoint pos;
2392 QPushButton *causedButton = qobject_cast<QPushButton*>(causedPopup.widget);
2393 if (actionListChanged && causedButton)
2394 pos = QPushButtonPrivate::get(causedButton)->adjustedMenuPosition();
2395 else
2396 pos = p;
2398
2399 const QSize menuSizeHint(q->sizeHint());
2400 QSize size = menuSizeHint;
2401
2402 if (positionFunction)
2403 pos = positionFunction(menuSizeHint);
2404
2405 const int desktopFrame = q->style()->pixelMetric(QStyle::PM_MenuDesktopFrameWidth, nullptr, q);
2406 bool adjustToDesktop = !q->window()->testAttribute(Qt::WA_DontShowOnScreen);
2407
2408 // if the screens have very different geometries and the menu is too big, we have to recalculate
2409 if ((size.height() > screen.height() || size.width() > screen.width()) ||
2410 // Layout is not right, we might be able to save horizontal space
2411 (ncols >1 && size.height() < screen.height())) {
2412 size.setWidth(qMin(menuSizeHint.width(), screen.width() - desktopFrame * 2));
2413 size.setHeight(qMin(menuSizeHint.height(), screen.height() - desktopFrame * 2));
2414 adjustToDesktop = true;
2415 }
2416
2417#ifdef QT_KEYPAD_NAVIGATION
2418 if (!atAction && QApplicationPrivate::keypadNavigationEnabled()) {
2419 // Try to have one item activated
2421 atAction = defaultAction;
2422 // TODO: This works for first level menus, not yet sub menus
2423 } else {
2424 for (QAction *action : std::as_const(actions))
2425 if (action->isEnabled()) {
2426 atAction = action;
2427 break;
2428 }
2429 }
2430 currentAction = atAction;
2431 }
2432#endif
2433 if (ncols > 1) {
2434 pos.setY(screen.top() + desktopFrame);
2435 } else if (atAction) {
2436 for (int i = 0, above_height = 0; i < actions.size(); i++) {
2437 QAction *action = actions.at(i);
2438 if (action == atAction) {
2439 int newY = pos.y() - above_height;
2440 if (scroll && newY < desktopFrame) {
2441 scroll->scrollFlags = scroll->scrollFlags
2443 scroll->scrollOffset = newY;
2444 newY = desktopFrame;
2445 }
2446 pos.setY(newY);
2447
2449 && !q->style()->styleHint(QStyle::SH_Menu_FillScreenWithScroll, nullptr, q)) {
2450 int below_height = above_height + scroll->scrollOffset;
2451 for (int i2 = i; i2 < actionRects.size(); i2++)
2452 below_height += actionRects.at(i2).height();
2453 size.setHeight(below_height);
2454 }
2455 break;
2456 } else {
2457 above_height += actionRects.at(i).height();
2458 }
2459 }
2460 }
2461
2462 QPoint mouse = QCursor::pos();
2463 mousePopupPos = mouse;
2464 const bool snapToMouse = !causedPopup.widget && (QRect(p.x() - 3, p.y() - 3, 6, 6).contains(mouse));
2465
2466 if (adjustToDesktop) {
2467 // handle popup falling "off screen"
2468 if (q->isRightToLeft()) {
2469 if (snapToMouse) // position flowing left from the mouse
2470 pos.setX(mouse.x() - size.width());
2471
2472#if QT_CONFIG(menubar)
2473 // if the menu is in a menubar or is a submenu, it should be right-aligned
2474 if (qobject_cast<QMenuBar*>(causedPopup.widget) || qobject_cast<QMenu*>(causedPopup.widget))
2475 pos.rx() -= size.width();
2476#endif // QT_CONFIG(menubar)
2477
2478 if (pos.x() < screen.left() + desktopFrame)
2479 pos.setX(qMax(p.x(), screen.left() + desktopFrame));
2480 if (pos.x() + size.width() - 1 > screen.right() - desktopFrame)
2481 pos.setX(qMax(p.x() - size.width(), screen.right() - desktopFrame - size.width() + 1));
2482 } else {
2483 if (pos.x() + size.width() - 1 > screen.right() - desktopFrame)
2484 pos.setX(screen.right() - desktopFrame - size.width() + 1);
2485 if (pos.x() < screen.left() + desktopFrame)
2486 pos.setX(screen.left() + desktopFrame);
2487 }
2488 if (pos.y() + size.height() - 1 > screen.bottom() - desktopFrame) {
2489 if (snapToMouse)
2490 pos.setY(qMin(mouse.y() - (size.height() + desktopFrame), screen.bottom()-desktopFrame-size.height()+1));
2491 else
2492 pos.setY(qMax(p.y() - (size.height() + desktopFrame), screen.bottom()-desktopFrame-size.height()+1));
2493 }
2494
2495 if (pos.y() < screen.top() + desktopFrame)
2496 pos.setY(screen.top() + desktopFrame);
2497 if (pos.y() + menuSizeHint.height() - 1 > screen.bottom() - desktopFrame) {
2498 if (scroll) {
2500 int y = qMax(screen.y(),pos.y());
2501 size.setHeight(screen.bottom() - (desktopFrame * 2) - y);
2502 } else {
2503 // Too big for screen, bias to see bottom of menu (for some reason)
2504 pos.setY(screen.bottom() - size.height() + 1);
2505 }
2506 }
2507 }
2508 const int subMenuOffset = q->style()->pixelMetric(QStyle::PM_SubMenuOverlap, nullptr, q);
2509 QMenu *caused = qobject_cast<QMenu*>(causedPopup.widget);
2510 if (caused && caused->geometry().width() + menuSizeHint.width() + subMenuOffset < screen.width()) {
2511 QRect parentActionRect(caused->d_func()->actionRect(caused->d_func()->currentAction));
2512 const QPoint actionTopLeft = caused->mapToGlobal(parentActionRect.topLeft());
2513 parentActionRect.moveTopLeft(actionTopLeft);
2514 if (q->isRightToLeft()) {
2515 if ((pos.x() + menuSizeHint.width() > parentActionRect.left() - subMenuOffset)
2516 && (pos.x() < parentActionRect.right()))
2517 {
2518 pos.rx() = parentActionRect.left() - menuSizeHint.width();
2519 if (pos.x() < screen.x())
2520 pos.rx() = parentActionRect.right();
2521 if (pos.x() + menuSizeHint.width() > screen.x() + screen.width())
2522 pos.rx() = screen.x();
2523 }
2524 } else {
2525 if ((pos.x() < parentActionRect.right() + subMenuOffset)
2526 && (pos.x() + menuSizeHint.width() > parentActionRect.left()))
2527 {
2528 pos.rx() = parentActionRect.right();
2529 if (pos.x() + menuSizeHint.width() > screen.x() + screen.width())
2530 pos.rx() = parentActionRect.left() - menuSizeHint.width();
2531 if (pos.x() < screen.x())
2532 pos.rx() = screen.x() + screen.width() - menuSizeHint.width();
2533 }
2534 }
2535 }
2537 q->setGeometry(QRect(pos, size));
2538#if QT_CONFIG(effects)
2539 int hGuess = q->isRightToLeft() ? QEffects::LeftScroll : QEffects::RightScroll;
2540 int vGuess = QEffects::DownScroll;
2541 if (q->isRightToLeft()) {
2542 if ((snapToMouse && (pos.x() + size.width() / 2 > mouse.x())) ||
2543 (qobject_cast<QMenu*>(causedPopup.widget) && pos.x() + size.width() / 2 > causedPopup.widget->x()))
2544 hGuess = QEffects::RightScroll;
2545 } else {
2546 if ((snapToMouse && (pos.x() + size.width() / 2 < mouse.x())) ||
2547 (qobject_cast<QMenu*>(causedPopup.widget) && pos.x() + size.width() / 2 < causedPopup.widget->x()))
2548 hGuess = QEffects::LeftScroll;
2549 }
2550
2551#if QT_CONFIG(menubar)
2552 if ((snapToMouse && (pos.y() + size.height() / 2 < mouse.y())) ||
2553 (qobject_cast<QMenuBar*>(causedPopup.widget) &&
2554 pos.y() + size.width() / 2 < causedPopup.widget->mapToGlobal(causedPopup.widget->pos()).y()))
2555 vGuess = QEffects::UpScroll;
2556#endif
2558 bool doChildEffects = true;
2559#if QT_CONFIG(menubar)
2560 if (QMenuBar *mb = qobject_cast<QMenuBar*>(causedPopup.widget)) {
2561 doChildEffects = mb->d_func()->doChildEffects;
2562 mb->d_func()->doChildEffects = false;
2563 } else
2564#endif
2565 if (QMenu *m = qobject_cast<QMenu*>(causedPopup.widget)) {
2566 doChildEffects = m->d_func()->doChildEffects;
2567 m->d_func()->doChildEffects = false;
2568 }
2569
2570 if (doChildEffects) {
2572 qFadeEffect(q);
2573 else if (causedPopup.widget)
2574 qScrollEffect(q, qobject_cast<QMenu*>(causedPopup.widget) ? hGuess : vGuess);
2575 else
2576 qScrollEffect(q, hGuess | vGuess);
2577 } else {
2578 // kill any running effect
2579 qFadeEffect(nullptr);
2580 qScrollEffect(nullptr);
2581
2582 q->show();
2583 }
2584 } else
2585#endif
2586 {
2587 q->show();
2588 }
2589
2590#if QT_CONFIG(accessibility)
2591 QAccessibleEvent event(q, QAccessible::PopupMenuStart);
2592 QAccessible::updateAccessibility(&event);
2593#endif
2594}
2595
2614{
2615 return exec(pos());
2616}
2617
2618
2655{
2656 Q_D(QMenu);
2657 return d->exec(p, action);
2658}
2659
2660QAction *QMenuPrivate::exec(const QPoint &p, QAction *action, PositionFunction positionFunction)
2661{
2662 Q_Q(QMenu);
2663 q->ensurePolished();
2664 q->createWinId();
2665 QEventLoop evtLoop;
2666 eventLoop = &evtLoop;
2667 popup(p, action, positionFunction);
2668
2669 QPointer<QObject> guard = q;
2670 (void) evtLoop.exec();
2671 if (guard.isNull())
2672 return nullptr;
2673
2674 action = syncAction;
2675 syncAction = nullptr;
2676 eventLoop = nullptr;
2678 return action;
2679}
2680
2703QAction *QMenu::exec(const QList<QAction *> &actions, const QPoint &pos, QAction *at, QWidget *parent)
2704{
2705 QMenu menu(parent);
2707 return menu.exec(pos, at);
2708}
2709
2714{
2715 Q_D(QMenu);
2716 emit aboutToHide();
2717 if (d->eventLoop)
2718 d->eventLoop->exit();
2719 d->setCurrentAction(nullptr);
2720#if QT_CONFIG(accessibility)
2721 QAccessibleEvent event(this, QAccessible::PopupMenuEnd);
2722 QAccessible::updateAccessibility(&event);
2723#endif
2724#if QT_CONFIG(menubar)
2725 if (QMenuBar *mb = qobject_cast<QMenuBar*>(d->causedPopup.widget))
2726 mb->d_func()->setCurrentAction(nullptr);
2727#endif
2728 if (QMenuPrivate::mouseDown == this)
2729 QMenuPrivate::mouseDown = nullptr;
2730 d->hasHadMouse = false;
2731 if (d->activeMenu)
2732 d->hideMenu(d->activeMenu);
2733 d->causedPopup.widget = nullptr;
2734 d->causedPopup.action = nullptr;
2735 if (d->scroll)
2736 d->scroll->scrollTimer.stop(); //make sure the timer stops
2737}
2738
2743{
2744 Q_D(QMenu);
2745 d->updateActionRects();
2746 QStylePainter p(this);
2747 QRegion emptyArea = QRegion(rect());
2748
2749 QStyleOptionMenuItem menuOpt;
2750 menuOpt.initFrom(this);
2751 menuOpt.state = QStyle::State_None;
2752 menuOpt.checkType = QStyleOptionMenuItem::NotCheckable;
2753 menuOpt.maxIconWidth = 0;
2754 menuOpt.reservedShortcutWidth = 0;
2755 p.drawPrimitive(QStyle::PE_PanelMenu, menuOpt);
2756
2757 //calculate the scroll up / down rect
2758 const int fw = style()->pixelMetric(QStyle::PM_MenuPanelWidth, nullptr, this);
2759 const int hmargin = style()->pixelMetric(QStyle::PM_MenuHMargin,nullptr, this);
2760 const int vmargin = style()->pixelMetric(QStyle::PM_MenuVMargin, nullptr, this);
2761
2762 QRect scrollUpRect, scrollDownRect;
2763 const int leftmargin = fw + hmargin + d->leftmargin;
2764 const int topmargin = fw + vmargin + d->topmargin;
2765 const int bottommargin = fw + vmargin + d->bottommargin;
2766 const int contentWidth = width() - (fw + hmargin) * 2 - d->leftmargin - d->rightmargin;
2767 if (d->scroll) {
2768 if (d->scroll->scrollFlags & QMenuPrivate::QMenuScroller::ScrollUp)
2769 scrollUpRect.setRect(leftmargin, topmargin, contentWidth, d->scrollerHeight());
2770
2771 if (d->scroll->scrollFlags & QMenuPrivate::QMenuScroller::ScrollDown)
2772 scrollDownRect.setRect(leftmargin, height() - d->scrollerHeight() - bottommargin,
2773 contentWidth, d->scrollerHeight());
2774 }
2775
2776 //calculate the tear off rect
2777 QRect tearOffRect;
2778 if (d->tearoff) {
2779 tearOffRect.setRect(leftmargin, topmargin, contentWidth,
2780 style()->pixelMetric(QStyle::PM_MenuTearoffHeight, nullptr, this));
2781 if (d->scroll && d->scroll->scrollFlags & QMenuPrivate::QMenuScroller::ScrollUp)
2782 tearOffRect.translate(0, d->scrollerHeight());
2783 }
2784
2785 //draw the items that need updating..
2786 QRect scrollUpTearOffRect = scrollUpRect.united(tearOffRect);
2787 for (int i = 0; i < d->actions.size(); ++i) {
2788 QAction *action = d->actions.at(i);
2789 QRect actionRect = d->actionRects.at(i);
2790 if (!e->rect().intersects(actionRect)
2791 || d->widgetItems.value(action))
2792 continue;
2793 //set the clip region to be extra safe (and adjust for the scrollers)
2794 emptyArea -= QRegion(actionRect);
2795
2796 QRect adjustedActionRect = actionRect;
2797 if (!scrollUpTearOffRect.isEmpty() && adjustedActionRect.bottom() <= scrollUpTearOffRect.top())
2798 continue;
2799
2800 if (!scrollDownRect.isEmpty() && adjustedActionRect.top() >= scrollDownRect.bottom())
2801 continue;
2802
2803 if (adjustedActionRect.intersects(scrollUpTearOffRect)) {
2804 if (adjustedActionRect.bottom() <= scrollUpTearOffRect.bottom())
2805 continue;
2806 else
2807 adjustedActionRect.setTop(scrollUpTearOffRect.bottom()+1);
2808 }
2809
2810 if (adjustedActionRect.intersects(scrollDownRect)) {
2811 if (adjustedActionRect.top() >= scrollDownRect.top())
2812 continue;
2813 else
2814 adjustedActionRect.setBottom(scrollDownRect.top()-1);
2815 }
2816
2817 QRegion adjustedActionReg(adjustedActionRect);
2818 p.setClipRegion(adjustedActionReg);
2819
2821 initStyleOption(&opt, action);
2822 opt.rect = actionRect;
2823 p.drawControl(QStyle::CE_MenuItem, opt);
2824 }
2825
2826 emptyArea -= QRegion(scrollUpTearOffRect);
2827 emptyArea -= QRegion(scrollDownRect);
2828
2829 if (d->scrollUpTearOffItem || d->scrollDownItem) {
2830 if (d->scrollUpTearOffItem)
2831 d->scrollUpTearOffItem->updateScrollerRects(scrollUpTearOffRect);
2832 if (d->scrollDownItem)
2833 d->scrollDownItem->updateScrollerRects(scrollDownRect);
2834 } else {
2835 //paint scroll up /down
2836 d->drawScroller(&p, QMenuPrivate::ScrollerTearOffItem::ScrollUp, scrollUpRect);
2837 d->drawScroller(&p, QMenuPrivate::ScrollerTearOffItem::ScrollDown, scrollDownRect);
2838 //paint the tear off..
2839 d->drawTearOff(&p, tearOffRect);
2840 }
2841
2842 //draw border
2843 if (fw) {
2844 QRegion borderReg;
2845 borderReg += QRect(0, 0, fw, height()); //left
2846 borderReg += QRect(width()-fw, 0, fw, height()); //right
2847 borderReg += QRect(0, 0, width(), fw); //top
2848 borderReg += QRect(0, height()-fw, width(), fw); //bottom
2849 p.setClipRegion(borderReg);
2850 emptyArea -= borderReg;
2852 frame.rect = rect();
2853 frame.palette = palette();
2854 frame.state = QStyle::State_None;
2856 frame.midLineWidth = 0;
2857 p.drawPrimitive(QStyle::PE_FrameMenu, frame);
2858 }
2859
2860 //finally the rest of the spaces
2861 p.setClipRegion(emptyArea);
2862 menuOpt.state = QStyle::State_None;
2863 menuOpt.menuItemType = QStyleOptionMenuItem::EmptyArea;
2864 menuOpt.checkType = QStyleOptionMenuItem::NotCheckable;
2865 menuOpt.rect = rect();
2866 menuOpt.menuRect = rect();
2867 p.drawControl(QStyle::CE_MenuEmptyArea, menuOpt);
2868}
2869
2870#if QT_CONFIG(wheelevent)
2874void QMenu::wheelEvent(QWheelEvent *e)
2875{
2876 Q_D(QMenu);
2877 if (d->scroll && rect().contains(e->position().toPoint()))
2878 d->scrollMenu(e->angleDelta().y() > 0 ?
2879 QMenuPrivate::QMenuScroller::ScrollUp : QMenuPrivate::QMenuScroller::ScrollDown);
2880}
2881#endif
2882
2887{
2888 Q_D(QMenu);
2889 if (d->aboutToHide || d->mouseEventTaken(e))
2890 return;
2891 // Workaround for XCB on multiple screens which doesn't have offset. If the menu is open on one screen
2892 // and mouse clicks on second screen, e->pos() is QPoint(0,0) and the menu doesn't hide. This trick makes
2893 // possible to hide the menu when mouse clicks on another screen (e->screenPos() returns correct value).
2894 // Only when mouse clicks in QPoint(0,0) on second screen, the menu doesn't hide.
2895 if ((e->position().toPoint().isNull() && !e->globalPosition().isNull()) || !rect().contains(e->position().toPoint())) {
2896 if (d->noReplayFor
2897 && QRect(d->noReplayFor->mapToGlobal(QPoint()), d->noReplayFor->size()).contains(e->globalPosition().toPoint()))
2899 if (d->eventLoop) // synchronous operation
2900 d->syncAction = nullptr;
2901 d->hideUpToMenuBar();
2902 return;
2903 }
2905
2906 QAction *action = d->actionAt(e->position().toPoint());
2907 d->setCurrentAction(action, 20);
2908 update();
2909}
2910
2915{
2916 Q_D(QMenu);
2917 if (d->aboutToHide || d->mouseEventTaken(e))
2918 return;
2919 if (QMenuPrivate::mouseDown != this) {
2920 QMenuPrivate::mouseDown = nullptr;
2921 return;
2922 }
2923
2924 QMenuPrivate::mouseDown = nullptr;
2925 d->setSyncAction();
2926 QAction *action = d->actionAt(e->position().toPoint());
2927
2928 if (action && action == d->currentAction) {
2929 if (!action->menu()) {
2930#if defined(Q_OS_WIN)
2931 //On Windows only context menus can be activated with the right button
2932 if (e->button() == Qt::LeftButton || d->topCausedWidget() == 0)
2933#endif
2934 d->activateAction(action, QAction::Trigger);
2935 }
2936 } else if ((!action || action->isEnabled()) && d->hasMouseMoved(e->globalPosition().toPoint())) {
2937 d->hideUpToMenuBar();
2938 }
2939}
2940
2945{
2946 Q_D(QMenu);
2947 if (e->type() == QEvent::StyleChange || e->type() == QEvent::FontChange ||
2949 d->itemsDirty = 1;
2950 setMouseTracking(style()->styleHint(QStyle::SH_Menu_MouseTracking, nullptr, this));
2951 if (isVisible())
2952 resize(sizeHint());
2953 if (!style()->styleHint(QStyle::SH_Menu_Scrollable, nullptr, this)) {
2954 delete d->scroll;
2955 d->scroll = nullptr;
2956 } else if (!d->scroll) {
2957 d->scroll = new QMenuPrivate::QMenuScroller;
2959 }
2960 } else if (e->type() == QEvent::EnabledChange) {
2961 if (d->tornPopup) // torn-off menu
2962 d->tornPopup->setEnabled(isEnabled());
2963 d->menuAction->setEnabled(isEnabled());
2964 if (!d->platformMenu.isNull())
2965 d->platformMenu->setEnabled(isEnabled());
2966 }
2968}
2969
2970
2975{
2976 Q_D(QMenu);
2977 switch (e->type()) {
2978 case QEvent::Polish:
2979 d->updateLayoutDirection();
2980 break;
2982 QKeyEvent *kev = static_cast<QKeyEvent *>(e);
2983 if (kev->key() == Qt::Key_Up || kev->key() == Qt::Key_Down
2984 || kev->key() == Qt::Key_Left || kev->key() == Qt::Key_Right
2985 || kev->key() == Qt::Key_Enter || kev->key() == Qt::Key_Return
2986#ifndef QT_NO_SHORTCUT
2987 || kev->matches(QKeySequence::Cancel)
2988#endif
2989 ) {
2990 e->accept();
2991 return true;
2992 }
2993 }
2994 break;
2995 case QEvent::KeyPress: {
2996 QKeyEvent *ke = static_cast<QKeyEvent *>(e);
2997 if (ke->key() == Qt::Key_Tab || ke->key() == Qt::Key_Backtab) {
2998 keyPressEvent(ke);
2999 return true;
3000 }
3001 } break;
3003 case QEvent::ContextMenu: {
3004 bool canPopup = true;
3005 if (e->type() == QEvent::MouseButtonPress)
3006 canPopup = (static_cast<QMouseEvent*>(e)->button() == Qt::LeftButton);
3007 if (canPopup && d->delayState.timer.isActive()) {
3008 d->delayState.stop();
3009 internalDelayedPopup();
3010 }
3011 }
3012 break;
3013 case QEvent::Resize: {
3014 QStyleHintReturnMask menuMask;
3016 option.initFrom(this);
3017 if (style()->styleHint(QStyle::SH_Menu_Mask, &option, this, &menuMask)) {
3018 setMask(menuMask.region);
3019 }
3020 d->itemsDirty = 1;
3021 d->updateActionRects();
3022 break; }
3023 case QEvent::Show:
3024 QMenuPrivate::mouseDown = nullptr;
3025 d->updateActionRects();
3026 d->sloppyState.reset();
3027 if (d->currentAction)
3028 d->popupAction(d->currentAction, 0, false);
3029 if (isWindow() && window() && window()->windowHandle() && !window()->windowHandle()->transientParent())
3030 window()->windowHandle()->setTransientParent(d->transientParentWindow());
3031 break;
3032#if QT_CONFIG(tooltip)
3033 case QEvent::ToolTip:
3034 if (d->toolTipsVisible) {
3035 const QHelpEvent *ev = static_cast<const QHelpEvent*>(e);
3036 if (const QAction *action = actionAt(ev->pos())) {
3037 const QString toolTip = action->d_func()->tooltip;
3038 if (!toolTip.isEmpty())
3039 QToolTip::showText(ev->globalPos(), toolTip, this);
3040 else
3042 return true;
3043 }
3044 }
3045 break;
3046#endif // QT_CONFIG(tooltip)
3047#if QT_CONFIG(whatsthis)
3049 e->setAccepted(d->whatsThis.size());
3050 if (QAction *action = d->actionAt(static_cast<QHelpEvent*>(e)->pos())) {
3051 if (action->whatsThis().size() || action->menu())
3052 e->accept();
3053 }
3054 return true;
3055#endif
3056 default:
3057 break;
3058 }
3059 return QWidget::event(e);
3060}
3061
3066{
3067 setFocus();
3069 keyPressEvent(&ev);
3070 return true;
3071}
3072
3077{
3078 Q_D(QMenu);
3079 d->updateActionRects();
3080 int key = e->key();
3081 if (isRightToLeft()) { // in reverse mode open/close key for submenues are reversed
3082 if (key == Qt::Key_Left)
3084 else if (key == Qt::Key_Right)
3085 key = Qt::Key_Left;
3086 }
3087#ifndef Q_OS_MAC
3088 if (key == Qt::Key_Tab) //means down
3089 key = Qt::Key_Down;
3090 if (key == Qt::Key_Backtab) //means up
3091 key = Qt::Key_Up;
3092#endif
3093
3094 bool key_consumed = false;
3095 switch(key) {
3096 case Qt::Key_Home:
3097 key_consumed = true;
3098 if (d->scroll)
3099 d->scrollMenu(QMenuPrivate::QMenuScroller::ScrollTop, true);
3100 break;
3101 case Qt::Key_End:
3102 key_consumed = true;
3103 if (d->scroll)
3105 break;
3106 case Qt::Key_PageUp:
3107 key_consumed = true;
3108 if (d->currentAction && d->scroll) {
3109 if (d->scroll->scrollFlags & QMenuPrivate::QMenuScroller::ScrollUp)
3110 d->scrollMenu(QMenuPrivate::QMenuScroller::ScrollUp, true, true);
3111 else
3112 d->scrollMenu(QMenuPrivate::QMenuScroller::ScrollTop, true);
3113 }
3114 break;
3115 case Qt::Key_PageDown:
3116 key_consumed = true;
3117 if (d->currentAction && d->scroll) {
3118 if (d->scroll->scrollFlags & QMenuPrivate::QMenuScroller::ScrollDown)
3119 d->scrollMenu(QMenuPrivate::QMenuScroller::ScrollDown, true, true);
3120 else
3122 }
3123 break;
3124 case Qt::Key_Up:
3125 case Qt::Key_Down: {
3126 key_consumed = true;
3127 QAction *nextAction = nullptr;
3129 if (!d->currentAction) {
3130 if (key == Qt::Key_Down) {
3131 for(int i = 0; i < d->actions.size(); ++i) {
3132 QAction *act = d->actions.at(i);
3133 if (d->actionRects.at(i).isNull())
3134 continue;
3135 if (!act->isSeparator() &&
3136 (style()->styleHint(QStyle::SH_Menu_AllowActiveAndDisabled, nullptr, this)
3137 || act->isEnabled())) {
3138 nextAction = act;
3139 break;
3140 }
3141 }
3142 } else {
3143 for(int i = d->actions.size()-1; i >= 0; --i) {
3144 QAction *act = d->actions.at(i);
3145 if (d->actionRects.at(i).isNull())
3146 continue;
3147 if (!act->isSeparator() &&
3149 || act->isEnabled())) {
3150 nextAction = act;
3151 break;
3152 }
3153 }
3154 }
3155 } else {
3156 for(int i = 0, y = 0; !nextAction && i < d->actions.size(); i++) {
3157 QAction *act = d->actions.at(i);
3158 if (act == d->currentAction) {
3159 if (key == Qt::Key_Up) {
3160 for(int next_i = i-1; true; next_i--) {
3161 if (next_i == -1) {
3162 if (!style()->styleHint(QStyle::SH_Menu_SelectionWrap, nullptr, this))
3163 break;
3164 if (d->scroll)
3166 next_i = d->actionRects.size()-1;
3167 }
3168 QAction *next = d->actions.at(next_i);
3169 if (next == d->currentAction)
3170 break;
3171 if (d->actionRects.at(next_i).isNull())
3172 continue;
3173 if (next->isSeparator() ||
3174 (!next->isEnabled() &&
3176 continue;
3177 nextAction = next;
3178 if (d->scroll && (d->scroll->scrollFlags & QMenuPrivate::QMenuScroller::ScrollUp)) {
3179 int topVisible = d->scrollerHeight();
3180 if (d->tearoff)
3181 topVisible += style()->pixelMetric(QStyle::PM_MenuTearoffHeight, nullptr, this);
3182 if (((y + d->scroll->scrollOffset) - topVisible) <= d->actionRects.at(next_i).height())
3184 }
3185 break;
3186 }
3187 if (!nextAction && d->tearoff)
3188 d->tearoffHighlighted = 1;
3189 } else {
3190 y += d->actionRects.at(i).height();
3191 for(int next_i = i+1; true; next_i++) {
3192 if (next_i == d->actionRects.size()) {
3193 if (!style()->styleHint(QStyle::SH_Menu_SelectionWrap, nullptr, this))
3194 break;
3195 if (d->scroll)
3197 next_i = 0;
3198 }
3199 QAction *next = d->actions.at(next_i);
3200 if (next == d->currentAction)
3201 break;
3202 if (d->actionRects.at(next_i).isNull())
3203 continue;
3204 if (next->isSeparator() ||
3205 (!next->isEnabled() &&
3206 !style()->styleHint(QStyle::SH_Menu_AllowActiveAndDisabled, nullptr, this)))
3207 continue;
3208 nextAction = next;
3209 if (d->scroll && (d->scroll->scrollFlags & QMenuPrivate::QMenuScroller::ScrollDown)) {
3210 int bottomVisible = height() - d->scrollerHeight();
3211 if (d->scroll->scrollFlags & QMenuPrivate::QMenuScroller::ScrollUp)
3212 bottomVisible -= d->scrollerHeight();
3213 if (d->tearoff)
3214 bottomVisible -= style()->pixelMetric(QStyle::PM_MenuTearoffHeight, nullptr, this);
3215 if ((y + d->scroll->scrollOffset + d->actionRects.at(next_i).height()) > bottomVisible)
3217 }
3218 break;
3219 }
3220 }
3221 break;
3222 }
3223 y += d->actionRects.at(i).height();
3224 }
3225 }
3226 if (nextAction) {
3227 if (d->scroll && scroll_loc != QMenuPrivate::QMenuScroller::ScrollStay) {
3228 d->scroll->scrollTimer.stop();
3229 d->scrollMenu(nextAction, scroll_loc);
3230 }
3231 d->setCurrentAction(nextAction, /*popup*/-1, QMenuPrivate::SelectedFromKeyboard);
3232 }
3233 break; }
3234
3235 case Qt::Key_Right:
3236 if (d->currentAction && d->currentAction->isEnabled() && d->currentAction->menu()) {
3237 d->popupAction(d->currentAction, 0, true);
3238 key_consumed = true;
3239 break;
3240 }
3241 Q_FALLTHROUGH();
3242 case Qt::Key_Left: {
3243 if (d->currentAction && !d->scroll) {
3244 QAction *nextAction = nullptr;
3245 if (key == Qt::Key_Left) {
3246 QRect actionR = d->actionRect(d->currentAction);
3247 for(int x = actionR.left()-1; !nextAction && x >= 0; x--)
3248 nextAction = d->actionAt(QPoint(x, actionR.center().y()));
3249 } else {
3250 QRect actionR = d->actionRect(d->currentAction);
3251 for(int x = actionR.right()+1; !nextAction && x < width(); x++)
3252 nextAction = d->actionAt(QPoint(x, actionR.center().y()));
3253 }
3254 if (nextAction) {
3255 d->setCurrentAction(nextAction, /*popup*/-1, QMenuPrivate::SelectedFromKeyboard);
3256 key_consumed = true;
3257 }
3258 }
3259 if (!key_consumed && key == Qt::Key_Left && qobject_cast<QMenu*>(d->causedPopup.widget)) {
3260 QPointer<QWidget> caused = d->causedPopup.widget;
3261 d->hideMenu(this);
3262 if (caused)
3263 caused->setFocus();
3264 key_consumed = true;
3265 }
3266 break; }
3267
3268 case Qt::Key_Alt:
3269 if (d->tornoff)
3270 break;
3271
3272 key_consumed = true;
3274 {
3275 d->hideMenu(this);
3276#if QT_CONFIG(menubar)
3277 if (QMenuBar *mb = qobject_cast<QMenuBar*>(QApplication::focusWidget())) {
3278 mb->d_func()->setKeyboardMode(false);
3279 }
3280#endif
3281 }
3282 break;
3283
3284 case Qt::Key_Space:
3285 if (!style()->styleHint(QStyle::SH_Menu_SpaceActivatesItem, nullptr, this))
3286 break;
3287 // for motif, fall through
3288 Q_FALLTHROUGH();
3289#ifdef QT_KEYPAD_NAVIGATION
3290 case Qt::Key_Select:
3291#endif
3292 case Qt::Key_Return:
3293 case Qt::Key_Enter: {
3294 if (!d->currentAction) {
3295 d->setFirstActionActive();
3296 key_consumed = true;
3297 break;
3298 }
3299
3300 d->setSyncAction();
3301
3302 if (d->currentAction->menu())
3303 d->popupAction(d->currentAction, 0, true);
3304 else
3305 d->activateAction(d->currentAction, QAction::Trigger);
3306 key_consumed = true;
3307 break; }
3308
3309#if QT_CONFIG(whatsthis)
3310 case Qt::Key_F1:
3311 if (!d->currentAction || d->currentAction->whatsThis().isNull())
3312 break;
3314 d->activateAction(d->currentAction, QAction::Trigger);
3315 return;
3316#endif
3317 default:
3318 key_consumed = false;
3319 }
3320
3321 if (!key_consumed && (
3322 false
3323#ifndef QT_NO_SHORTCUT
3324 || e->matches(QKeySequence::Cancel)
3325#endif
3326#ifdef QT_KEYPAD_NAVIGATION
3327 || e->key() == Qt::Key_Back
3328#endif
3329 )) {
3330 key_consumed = true;
3331 if (d->tornoff) {
3332 close();
3333 return;
3334 }
3335 {
3336 QPointer<QWidget> caused = d->causedPopup.widget;
3337 d->hideMenu(this); // hide after getting causedPopup
3338#if QT_CONFIG(menubar)
3339 if (QMenuBar *mb = qobject_cast<QMenuBar*>(caused)) {
3340 mb->d_func()->setCurrentAction(d->menuAction);
3341 mb->d_func()->setKeyboardMode(true);
3342 }
3343#endif
3344 }
3345 }
3346
3347 if (!key_consumed) { // send to menu bar
3348 if ((!e->modifiers() || e->modifiers() == Qt::AltModifier || e->modifiers() == Qt::ShiftModifier) &&
3349 e->text().size()==1) {
3350 bool activateAction = false;
3351 QAction *nextAction = nullptr;
3352 if (style()->styleHint(QStyle::SH_Menu_KeyboardSearch, nullptr, this) && !e->modifiers()) {
3353 int best_match_count = 0;
3354 d->searchBufferTimer.start(2000, this);
3355 d->searchBuffer += e->text();
3356 for(int i = 0; i < d->actions.size(); ++i) {
3357 int match_count = 0;
3358 if (d->actionRects.at(i).isNull())
3359 continue;
3360 QAction *act = d->actions.at(i);
3361 const QString act_text = act->text();
3362 for(int c = 0; c < d->searchBuffer.size(); ++c) {
3363 if (act_text.indexOf(d->searchBuffer.at(c), 0, Qt::CaseInsensitive) != -1)
3364 ++match_count;
3365 }
3366 if (match_count > best_match_count) {
3367 best_match_count = match_count;
3368 nextAction = act;
3369 }
3370 }
3371 }
3372#ifndef QT_NO_SHORTCUT
3373 else {
3374 int clashCount = 0;
3375 QAction *first = nullptr, *currentSelected = nullptr, *firstAfterCurrent = nullptr;
3376 QChar c = e->text().at(0).toUpper();
3377 for(int i = 0; i < d->actions.size(); ++i) {
3378 if (d->actionRects.at(i).isNull())
3379 continue;
3380 QAction *act = d->actions.at(i);
3381 QKeySequence sequence = QKeySequence::mnemonic(act->text());
3382 int key = sequence[0].toCombined() & 0xffff; // suspicious
3383 if (key == c.unicode()) {
3384 clashCount++;
3385 if (!first)
3386 first = act;
3387 if (act == d->currentAction)
3388 currentSelected = act;
3389 else if (!firstAfterCurrent && currentSelected)
3390 firstAfterCurrent = act;
3391 }
3392 }
3393 if (clashCount == 1)
3394 activateAction = true;
3395 if (clashCount >= 1) {
3396 if (clashCount == 1 || !currentSelected || !firstAfterCurrent)
3397 nextAction = first;
3398 else
3399 nextAction = firstAfterCurrent;
3400 }
3401 }
3402#endif
3403 if (nextAction) {
3404 key_consumed = true;
3405 if (d->scroll)
3406 d->scrollMenu(nextAction, QMenuPrivate::QMenuScroller::ScrollCenter, false);
3407 d->setCurrentAction(nextAction, 0, QMenuPrivate::SelectedFromElsewhere, true);
3408 if (!nextAction->menu() && activateAction) {
3409 d->setSyncAction();
3410 d->activateAction(nextAction, QAction::Trigger);
3411 }
3412 }
3413 }
3414 if (!key_consumed) {
3415#if QT_CONFIG(menubar)
3416 if (QMenuBar *mb = qobject_cast<QMenuBar*>(d->topCausedWidget())) {
3417 QAction *oldAct = mb->d_func()->currentAction;
3419 if (mb->d_func()->currentAction != oldAct)
3420 key_consumed = true;
3421 }
3422#endif
3423 }
3424
3425#ifdef Q_OS_WIN32
3426 if (key_consumed && (e->key() == Qt::Key_Control || e->key() == Qt::Key_Shift || e->key() == Qt::Key_Meta))
3428#endif // Q_OS_WIN32
3429 }
3430 if (key_consumed)
3431 e->accept();
3432 else
3433 e->ignore();
3434}
3435
3440{
3441 Q_D(QMenu);
3442 if (!isVisible() || d->aboutToHide || d->mouseEventTaken(e))
3443 return;
3444
3445 d->motions++;
3446 if (!d->hasMouseMoved(e->globalPosition().toPoint()))
3447 return;
3448
3449 d->hasHadMouse = d->hasHadMouse || rect().contains(e->position().toPoint());
3450
3451 QAction *action = d->actionAt(e->position().toPoint());
3452 if ((!action || action->isSeparator()) && !d->sloppyState.enabled()) {
3453 if (d->hasHadMouse
3454 || (!d->currentAction || !d->currentAction->menu() || !d->currentAction->menu()->isVisible())) {
3455 d->setCurrentAction(action);
3456 }
3457 return;
3458 }
3459
3460 if (e->buttons())
3462
3463 if (d->activeMenu)
3464 d->activeMenu->d_func()->setCurrentAction(nullptr);
3465
3466 QMenuSloppyState::MouseEventResult sloppyEventResult = d->sloppyState.processMouseEvent(e->position(), action, d->currentAction);
3467 if (sloppyEventResult == QMenuSloppyState::EventShouldBePropagated) {
3468 d->setCurrentAction(action, d->mousePopupDelay);
3469 } else if (sloppyEventResult == QMenuSloppyState::EventDiscardsSloppyState) {
3470 d->sloppyState.reset();
3471 d->hideMenu(d->activeMenu);
3472 }
3473}
3474
3479{
3480 Q_D(QMenu);
3481 d->hasReceievedEnter = true;
3482 d->sloppyState.enter();
3483 d->motions = -1; // force us to ignore the generate mouse move in mouseMoveEvent()
3484}
3485
3490{
3491 Q_D(QMenu);
3492 d->hasReceievedEnter = false;
3493 if (!d->activeMenu && d->currentAction)
3494 setActiveAction(nullptr);
3495}
3496
3500void
3502{
3503 Q_D(QMenu);
3504 if (d->scroll && d->scroll->scrollTimer.timerId() == e->timerId()) {
3505 d->scrollMenu((QMenuPrivate::QMenuScroller::ScrollDirection)d->scroll->scrollDirection);
3506 if (d->scroll->scrollFlags == QMenuPrivate::QMenuScroller::ScrollNone)
3507 d->scroll->scrollTimer.stop();
3508 } else if (d->delayState.timer.timerId() == e->timerId()) {
3509 if (d->currentAction && !d->currentAction->menu())
3510 return;
3511 d->delayState.stop();
3512 d->sloppyState.stopTimer();
3513 internalDelayedPopup();
3514 } else if (d->sloppyState.isTimerId(e->timerId())) {
3515 d->sloppyState.timeout();
3516 } else if (d->searchBufferTimer.timerId() == e->timerId()) {
3517 d->searchBuffer.clear();
3518 }
3519}
3520
3525{
3526 Q_D(QMenu);
3527 d->itemsDirty = 1;
3529 if (d->tornPopup)
3530 d->tornPopup->syncWithMenu(this, e);
3531 if (e->type() == QEvent::ActionAdded) {
3532
3533 if (!d->tornoff
3534#if QT_CONFIG(menubar)
3535 && !qobject_cast<QMenuBar*>(e->action()->parent())
3536#endif
3537 ) {
3538 // Only connect if the action was not directly added by QMenuBar::addAction(const QString &text)
3539 // to avoid the signal being emitted twice
3540 connect(e->action(), SIGNAL(triggered()), this, SLOT(_q_actionTriggered()), Qt::UniqueConnection);
3541 connect(e->action(), SIGNAL(hovered()), this, SLOT(_q_actionHovered()), Qt::UniqueConnection);
3542 }
3543 if (QWidgetAction *wa = qobject_cast<QWidgetAction *>(e->action())) {
3544 QWidget *widget = wa->requestWidget(this);
3545 if (widget) {
3546 d->widgetItems.insert(wa, widget);
3547 if (d->scroll) {
3548 if (!d->scrollUpTearOffItem)
3549 d->scrollUpTearOffItem =
3551 if (!d->scrollDownItem)
3552 d->scrollDownItem =
3554 }
3555 }
3556 }
3557 } else if (e->type() == QEvent::ActionRemoved) {
3558 e->action()->disconnect(this);
3559 if (e->action() == d->currentAction)
3560 d->currentAction = nullptr;
3561 if (QWidgetAction *wa = qobject_cast<QWidgetAction *>(e->action())) {
3562 if (QWidget *widget = d->widgetItems.value(wa))
3563 wa->releaseWidget(widget);
3564 }
3565 d->widgetItems.remove(static_cast<QAction *>(e->action()));
3566 }
3567
3568 if (!d->platformMenu.isNull()) {
3569 auto action = static_cast<QAction *>(e->action());
3570 if (e->type() == QEvent::ActionAdded) {
3571 QPlatformMenuItem *beforeItem = e->before()
3572 ? d->platformMenu->menuItemForTag(reinterpret_cast<quintptr>(e->before()))
3573 : nullptr;
3574 d->insertActionInPlatformMenu(action, beforeItem);
3575 } else if (e->type() == QEvent::ActionRemoved) {
3576 QPlatformMenuItem *menuItem = d->platformMenu->menuItemForTag(reinterpret_cast<quintptr>(e->action()));
3577 d->platformMenu->removeMenuItem(menuItem);
3578 delete menuItem;
3579 } else if (e->type() == QEvent::ActionChanged) {
3580 QPlatformMenuItem *menuItem = d->platformMenu->menuItemForTag(reinterpret_cast<quintptr>(e->action()));
3581 if (menuItem) {
3582 d->copyActionToPlatformItem(action, menuItem);
3583 d->platformMenu->syncMenuItem(menuItem);
3584 }
3585 }
3586
3587 d->platformMenu->syncSeparatorsCollapsible(d->collapsibleSeparators);
3588 }
3589
3590 if (isVisible()) {
3591 resize(sizeHint());
3592 update();
3593 }
3594}
3595
3599void QMenu::internalDelayedPopup()
3600{
3601 Q_D(QMenu);
3602 //hide the current item
3603 if (QMenu *menu = d->activeMenu) {
3604 if (d->activeMenu->menuAction() != d->currentAction)
3605 d->hideMenu(menu);
3606 }
3607
3608 if (!d->currentAction || !d->currentAction->isEnabled() || !d->currentAction->menu() ||
3609 !d->currentAction->menu()->isEnabled() || d->currentAction->menu()->isVisible())
3610 return;
3611
3612 //setup
3613 d->activeMenu = d->currentAction->menu();
3614 d->activeMenu->d_func()->causedPopup.widget = this;
3615 d->activeMenu->d_func()->causedPopup.action = d->currentAction;
3616
3617 QRect screen;
3618#if QT_CONFIG(graphicsview)
3619 bool isEmbedded = !bypassGraphicsProxyWidget(this) && QMenuPrivate::nearestGraphicsProxyWidget(this);
3620 if (isEmbedded)
3621 screen = d->popupGeometry();
3622 else
3623#endif
3624 screen = d->popupGeometry(QGuiApplication::screenAt(pos()));
3625
3626 int subMenuOffset = style()->pixelMetric(QStyle::PM_SubMenuOverlap, nullptr, this);
3627 const QRect actionRect(d->actionRect(d->currentAction));
3628 QPoint subMenuPos(mapToGlobal(QPoint(actionRect.right() + subMenuOffset + 1, actionRect.top())));
3629 if (subMenuPos.x() > screen.right())
3630 subMenuPos.setX(geometry().left());
3631
3632 const auto &subMenuActions = d->activeMenu->actions();
3633 if (!subMenuActions.isEmpty()) {
3634 // Offset by the submenu's 1st action position to align with the current action
3635 const auto subMenuActionRect = d->activeMenu->actionGeometry(subMenuActions.first());
3636 subMenuPos.ry() -= subMenuActionRect.top();
3637 }
3638
3639 d->activeMenu->popup(subMenuPos);
3640 d->sloppyState.setSubMenuPopup(actionRect, d->currentAction, d->activeMenu);
3641
3642#if !defined(Q_OS_DARWIN)
3643 // Send the leave event to the current menu - only active popup menu gets
3644 // mouse enter/leave events. Currently Cocoa is an exception, so disable
3645 // it there to avoid event duplication.
3646 if (underMouse()) {
3649 }
3650#endif
3651}
3652
3704{
3705 d_func()->noReplayFor = noReplayFor;
3706}
3707
3711{
3712
3713 return d_func()->platformMenu;
3714}
3715
3719{
3720 d_func()->setPlatformMenu(platformMenu);
3721 d_func()->syncPlatformMenu();
3722}
3723
3737{
3738 Q_D(const QMenu);
3739 return d->collapsibleSeparators;
3740}
3741
3743{
3744 Q_D(QMenu);
3745 if (d->collapsibleSeparators == collapse)
3746 return;
3747
3748 d->collapsibleSeparators = collapse;
3749 d->itemsDirty = 1;
3750 if (isVisible()) {
3751 d->updateActionRects();
3752 update();
3753 }
3754 if (!d->platformMenu.isNull())
3755 d->platformMenu->syncSeparatorsCollapsible(collapse);
3756}
3757
3770{
3771 Q_D(const QMenu);
3772 return d->toolTipsVisible;
3773}
3774
3776{
3777 Q_D(QMenu);
3778 if (d->toolTipsVisible == visible)
3779 return;
3780
3781 d->toolTipsVisible = visible;
3782}
3783
3785
3786// for private slots
3787#include "moc_qmenu.cpp"
3788#include "qmenu.moc"
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...
Definition qaction.h:30
ActionEvent
This enum type is used when calling QAction::activate()
Definition qaction.h:175
@ Trigger
Definition qaction.h:175
@ Hover
Definition qaction.h:175
T menu() const
Returns the menu contained by this action.
Definition qaction.h:186
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.
Definition qaction.cpp:585
bool isVisible() const
Definition qaction.cpp:1018
QActionGroup * actionGroup() const
Returns the action group for this action.
Definition qaction.cpp:493
void setMenu(T m)
Sets the menu contained by this action to the specified menu.
Definition qaction.h:191
bool isShortcutVisibleInContextMenu() const
Definition qaction.cpp:1290
void setSeparator(bool b)
If b is true then this action will be considered a separator.
Definition qaction.cpp:569
bool isCheckable() const
Definition qaction.cpp:847
QString whatsThis
the action's "What's This?" help text
Definition qaction.h:43
QFont font
the action's font
Definition qaction.h:44
bool showStatusText(QObject *object=nullptr)
Updates the relevant status bar for the UI represented by object by sending a QStatusTipEvent.
Definition qaction.cpp:736
bool isIconVisibleInMenu() const
Definition qaction.cpp:1254
void activate(ActionEvent event)
Sends the relevant signals for ActionEvent event.
Definition qaction.cpp:1082
QString text
the action's descriptive text
Definition qaction.h:39
void changed()
This signal is emitted when an action has changed.
MenuRole menuRole
the action's menu role
Definition qaction.h:52
bool isChecked() const
Definition qaction.cpp:892
void trigger()
This is a convenience slot that calls activate(Trigger).
Definition qaction.h:210
QIcon icon
the action's icon
Definition qaction.h:38
bool isEnabled() const
Definition qaction.cpp:971
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.
\inmodule QtCore
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.
Definition qcursor.cpp:188
\inmodule QtGui
Definition qevent.h:165
\inmodule QtCore
Definition qeventloop.h:16
int exec(ProcessEventsFlags flags=AllEvents)
Enters the main event loop and waits until exit() is called.
\inmodule QtCore
Definition qcoreevent.h:45
virtual void setAccepted(bool accepted)
Definition qcoreevent.h:307
@ QueryWhatsThis
Definition qcoreevent.h:169
@ ActionRemoved
Definition qcoreevent.h:153
@ EnabledChange
Definition qcoreevent.h:134
@ ActionAdded
Definition qcoreevent.h:152
@ LayoutDirectionChange
Definition qcoreevent.h:124
@ ShortcutOverride
Definition qcoreevent.h:158
@ DeferredDelete
Definition qcoreevent.h:100
@ StyleChange
Definition qcoreevent.h:136
@ ActionChanged
Definition qcoreevent.h:151
@ FontChange
Definition qcoreevent.h:133
@ KeyPress
Definition qcoreevent.h:64
@ MouseButtonPress
Definition qcoreevent.h:60
@ ContextMenu
Definition qcoreevent.h:119
@ MouseButtonRelease
Definition qcoreevent.h:61
Type type() const
Returns the event type.
Definition qcoreevent.h:304
void ignore()
Clears the accept flag parameter of the event object, the equivalent of calling setAccepted(false).
Definition qcoreevent.h:311
void accept()
Sets the accept flag of the event object, the equivalent of calling setAccepted(true).
Definition qcoreevent.h:310
\reentrant \inmodule QtGui
QFont resolve(const QFont &) const
Returns a new QFont that has attributes copied from other that have not been previously set on this f...
Definition qfont.cpp:1893
int midLineWidth
the width of the mid-line
Definition qframe.h:23
int lineWidth
the line width
Definition qframe.h:22
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.
\inmodule QtCore
Definition qhash.h:1103
T value(const Key &key) const noexcept
Definition qhash.h:1054
The QHelpEvent class provides an event that is used to request helpful information about a particular...
Definition qevent.h:788
const QPoint & pos() const
Returns the mouse cursor position when the event was generated, relative to the widget to which the e...
Definition qevent.h:798
The QHideEvent class provides an event which is sent after a widget is hidden.
Definition qevent.h:586
The QIcon class provides scalable icons in different modes and states.
Definition qicon.h:20
bool isNull() const
Returns true if the icon is empty; otherwise returns false.
Definition qicon.cpp:1019
Qt::KeyboardModifiers modifiers() const
Returns the keyboard modifier flags that existed immediately before the event occurred.
Definition qevent.h:56
The QKeyEvent class describes a key event.
Definition qevent.h:424
Qt::KeyboardModifiers modifiers() const
Returns the keyboard modifier flags that existed immediately after the event occurred.
Definition qevent.cpp:1468
QString text() const
Returns the Unicode text that this key generated.
Definition qevent.h:443
int key() const
Returns the code of the key that was pressed or released.
Definition qevent.h:434
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
Definition qlist.h:75
qsizetype size() const noexcept
Definition qlist.h:397
const_reference at(qsizetype i) const noexcept
Definition qlist.h:446
std::reverse_iterator< const_iterator > const_reverse_iterator
Definition qlist.h:252
reverse_iterator rend()
Definition qlist.h:635
reverse_iterator rbegin()
Definition qlist.h:634
void append(parameter_type t)
Definition qlist.h:458
The QMenuBar class provides a horizontal menu bar.
Definition qmenubar.h:20
ScrollerTearOffItem(Type type, QMenuPrivate *mPrivate, QWidget *parent=nullptr, Qt::WindowFlags f=Qt::WindowFlags())
Definition qmenu.cpp:1028
void updateScrollerRects(const QRect &rect)
Definition qmenu.cpp:1054
void paintEvent(QPaintEvent *e) override
This event handler can be reimplemented in a subclass to receive paint events passed in event.
Definition qmenu.cpp:1035
void updateLayoutDirection()
Definition qmenu.cpp:949
struct QMenuPrivate::QMenuScroller * scroll
QPointer< QPlatformMenu > platformMenu
Definition qmenu_p.h:442
quint8 ncols
Definition qmenu_p.h:474
QEventLoop * eventLoop
Definition qmenu_p.h:389
QList< QRect > actionRects
Definition qmenu_p.h:317
void _q_actionTriggered()
Definition qmenu.cpp:1521
void hideUpToMenuBar()
Definition qmenu.cpp:517
@ SelectedFromElsewhere
Definition qmenu_p.h:363
@ SelectedFromKeyboard
Definition qmenu_p.h:362
void scrollMenu(QMenuScroller::ScrollLocation location, bool active=false)
Definition qmenu.cpp:1237
int getLastVisibleAction() const
Definition qmenu.cpp:488
void popupAction(QAction *, int, bool)
Definition qmenu.cpp:647
void activateCausedStack(const QList< QPointer< QWidget > > &, QAction *, QAction::ActionEvent, bool)
Definition qmenu.cpp:1411
static QMenu * mouseDown
Definition qmenu_p.h:328
void popup(const QPoint &p, QAction *atAction, PositionFunction positionFunction={})
Definition qmenu.cpp:2316
std::function< QPoint(const QSize &)> PositionFunction
Definition qmenu_p.h:274
void updateActionRects() const
Definition qmenu.cpp:333
bool tearoffHighlighted
Definition qmenu_p.h:494
QPointer< QTornOffMenu > tornPopup
Definition qmenu_p.h:416
QPoint mousePopupPos
Definition qmenu_p.h:329
void setSyncAction()
Definition qmenu.cpp:666
int indexOf(QAction *act) const
Definition qmenu_p.h:413
QPointer< QAction > syncAction
Definition qmenu_p.h:390
void syncPlatformMenu()
Definition qmenu.cpp:204
bool lastContextMenu
Definition qmenu_p.h:483
QPlatformMenuItem * insertActionInPlatformMenu(const QAction *action, QPlatformMenuItem *beforeItem)
Definition qmenu.cpp:265
int scrollerHeight() const
Definition qmenu.cpp:279
QPlatformMenu * createPlatformMenu()
Definition qmenu.cpp:183
void setFirstActionActive()
Definition qmenu.cpp:684
void hideMenu(QMenu *menu)
Definition qmenu.cpp:545
void _q_overrideMenuActionDestroyed()
Definition qmenu.cpp:944
bool mouseEventTaken(QMouseEvent *)
Definition qmenu.cpp:1322
bool isContextMenu() const
Definition qmenu.cpp:324
void _q_platformMenuAboutToShow()
Definition qmenu.cpp:1561
QPointer< QAction > defaultAction
Definition qmenu_p.h:421
virtual QList< QPointer< QWidget > > calcCausedStack() const
Definition qmenu.cpp:309
void drawScroller(QPainter *painter, ScrollerTearOffItem::Type type, const QRect &rect)
Definition qmenu.cpp:965
QRect actionRect(QAction *) const
Definition qmenu.cpp:505
QRect rect() const
Definition qmenu.cpp:1015
bool useFullScreenForPopup() const
Definition qmenu.cpp:287
void activateAction(QAction *, QAction::ActionEvent, bool self=true)
Definition qmenu.cpp:1452
void copyActionToPlatformItem(const QAction *action, QPlatformMenuItem *item)
Definition qmenu.cpp:228
QMenuSloppyState sloppyState
Definition qmenu_p.h:418
QHash< QAction *, QWidget * > widgetItems
Definition qmenu_p.h:318
bool tearoff
Definition qmenu_p.h:492
bool itemsDirty
Definition qmenu_p.h:481
QPointer< QAction > actionAboutToTrigger
Definition qmenu_p.h:444
void setOverrideMenuAction(QAction *)
Definition qmenu.cpp:932
bool activationRecursionGuard
Definition qmenu_p.h:472
QAction * actionAt(QPoint p) const
Definition qmenu.cpp:920
QWidget * topCausedWidget() const
Definition qmenu.cpp:912
static QMenuPrivate * get(QMenu *m)
Definition qmenu_p.h:309
QPointer< QScreen > popupScreen
Definition qmenu_p.h:479
QWindow * transientParentWindow() const
Definition qmenu.cpp:624
void drawTearOff(QPainter *painter, const QRect &rect)
Definition qmenu.cpp:991
bool tornoff
Definition qmenu_p.h:493
QPointer< QMenu > activeMenu
Definition qmenu_p.h:397
QAction * currentAction
Definition qmenu_p.h:331
QAction * exec(const QPoint &p, QAction *action, PositionFunction positionFunction={})
Definition qmenu.cpp:2660
void setCurrentAction(QAction *, int popup=-1, SelectionReason reason=SelectedFromElsewhere, bool activateFirst=false)
Definition qmenu.cpp:708
void _q_actionHovered()
Definition qmenu.cpp:1553
QRect popupGeometry(QScreen *screen=nullptr) const
Definition qmenu.cpp:292
QMenuCaused causedPopup
Definition qmenu_p.h:406
bool doChildEffects
Definition qmenu_p.h:496
bool hasMouseMoved(const QPoint &globalPos)
Definition qmenu.cpp:1582
void setPlatformMenu(QPlatformMenu *menu)
Definition qmenu.cpp:191
void childEnter()
Definition qmenu.cpp:811
bool hasParentActiveDelayTimer() const
Definition qmenu.cpp:851
void childLeave()
Definition qmenu.cpp:827
@ EventDiscardsSloppyState
Definition qmenu_p.h:122
@ EventShouldBePropagated
Definition qmenu_p.h:121
void setSubMenuPopup(const QRect &actionRect, QAction *resetAction, QMenu *subMenu)
Definition qmenu.cpp:836
The QMenu class provides a menu widget for use in menu bars, context menus, and other popup menus.
Definition qmenu.h:26
QAction * insertMenu(QAction *before, QMenu *menu)
This convenience function inserts menu before action before and returns the menus menuAction().
Definition qmenu.cpp:1983
bool isTearOffEnabled() const
Definition qmenu.cpp:2106
QMenu(QWidget *parent=nullptr)
Constructs a menu with parent parent.
Definition qmenu.cpp:1746
QString title
The title of the menu.
Definition qmenu.h:32
void changeEvent(QEvent *) override
\reimp
Definition qmenu.cpp:2944
bool isEmpty() const
Definition qmenu.cpp:2207
QAction * actionAt(const QPoint &) const
Returns the item at pt; returns \nullptr if there is no item there.
Definition qmenu.cpp:2251
bool toolTipsVisible
whether tooltips of menu actions should be visible
Definition qmenu.h:35
void timerEvent(QTimerEvent *) override
\reimp
Definition qmenu.cpp:3501
QAction * exec()
Executes this menu synchronously.
Definition qmenu.cpp:2613
void mouseMoveEvent(QMouseEvent *) override
\reimp
Definition qmenu.cpp:3439
void hovered(QAction *action)
This signal is emitted when a menu action is highlighted; action is the action that caused the signal...
QSize sizeHint() const override
\reimp
Definition qmenu.cpp:2269
void triggered(QAction *action)
This signal is emitted when an action in this menu is triggered.
QPlatformMenu * platformMenu()
Definition qmenu.cpp:3710
void setTearOffEnabled(bool)
Definition qmenu.cpp:2092
QAction * insertSeparator(QAction *before)
This convenience function creates a new separator action, i.e.
Definition qmenu.cpp:2000
void mouseReleaseEvent(QMouseEvent *) override
\reimp
Definition qmenu.cpp:2914
int columnCount() const
If a menu does not fit on the screen it lays itself out so that it does fit.
Definition qmenu.cpp:2243
void setPlatformMenu(QPlatformMenu *platformMenu)
Definition qmenu.cpp:3718
void actionEvent(QActionEvent *) override
\reimp
Definition qmenu.cpp:3524
friend class QTornOffMenu
Definition qmenu.h:224
void setActiveAction(QAction *act)
Sets the currently highlighted action to act.
Definition qmenu.cpp:2180
void paintEvent(QPaintEvent *) override
\reimp
Definition qmenu.cpp:2742
void hideTearOffMenu()
This function will forcibly hide the torn off menu making it disappear from the user's desktop.
Definition qmenu.cpp:2163
void aboutToShow()
This signal is emitted just before the menu is shown to the user.
QRect actionGeometry(QAction *) const
Returns the geometry of action act.
Definition qmenu.cpp:2261
void clear()
Removes all the menu's actions.
Definition qmenu.cpp:2225
QIcon icon
The icon of the menu.
Definition qmenu.h:33
void setIcon(const QIcon &icon)
Definition qmenu.cpp:1116
void popup(const QPoint &pos, QAction *at=nullptr)
Displays the menu so that the action atAction will be at the specified global position p.
Definition qmenu.cpp:2310
QAction * addSection(const QString &text)
Definition qmenu.cpp:1945
void hideEvent(QHideEvent *) override
\reimp
Definition qmenu.cpp:2713
void leaveEvent(QEvent *) override
\reimp
Definition qmenu.cpp:3489
bool separatorsCollapsible
whether consecutive separators should be collapsed
Definition qmenu.h:34
bool focusNextPrevChild(bool next) override
\reimp
Definition qmenu.cpp:3065
bool isTearOffMenuVisible() const
When a menu is torn off a second menu is shown to display the menu contents in a new window.
Definition qmenu.cpp:2118
bool event(QEvent *) override
\reimp
Definition qmenu.cpp:2974
~QMenu()
Destroys the menu.
Definition qmenu.cpp:1781
QAction * insertSection(QAction *before, const QString &text)
Definition qmenu.cpp:2025
void aboutToHide()
virtual void initStyleOption(QStyleOptionMenuItem *option, const QAction *action) const
Initialize option with the values from this menu and information from action.
Definition qmenu.cpp:1599
void enterEvent(QEnterEvent *) override
\reimp
Definition qmenu.cpp:3478
void showTearOffMenu()
This is an overloaded member function, provided for convenience. It differs from the above function o...
Definition qmenu.cpp:2152
QAction * defaultAction() const
Returns the current default action.
Definition qmenu.cpp:2074
QAction * addSeparator()
This convenience function creates a new separator action, i.e.
Definition qmenu.cpp:1921
void setTitle(const QString &title)
Definition qmenu.cpp:1097
QAction * addMenu(QMenu *menu)
This convenience function adds menu as a submenu to this menu.
Definition qmenu.cpp:1877
void keyPressEvent(QKeyEvent *) override
\reimp
Definition qmenu.cpp:3076
QAction * activeAction() const
Returns the currently highlighted action, or \nullptr if no action is currently highlighted.
Definition qmenu.cpp:2193
void setDefaultAction(QAction *)
This sets the default action to act.
Definition qmenu.cpp:2064
void setToolTipsVisible(bool visible)
Definition qmenu.cpp:3775
void addAction(QAction *action)
Appends the action action to this widget's list of actions.
Definition qwidget.cpp:3117
void setNoReplayFor(QWidget *widget)
Definition qmenu.cpp:3703
void setSeparatorsCollapsible(bool collapse)
Definition qmenu.cpp:3742
void mousePressEvent(QMouseEvent *) override
\reimp
Definition qmenu.cpp:2886
QAction * menuAction() const
Returns the action associated with this menu.
Definition qmenu.cpp:1069
\inmodule QtGui
Definition qevent.h:196
Qt::MouseEventSource source() const
Definition qevent.cpp:801
QObject * parent
Definition qobject.h:73
\inmodule QtCore
Definition qobject.h:103
QObject * parent() const
Returns a pointer to the parent object.
Definition qobject.h:346
static QMetaObject::Connection connect(const QObject *sender, const char *signal, const QObject *receiver, const char *member, Qt::ConnectionType=Qt::AutoConnection)
\threadsafe
Definition qobject.cpp:2960
virtual bool eventFilter(QObject *watched, QEvent *event)
Filters events if this object has been installed as an event filter for the watched object.
Definition qobject.cpp:1555
static bool disconnect(const QObject *sender, const char *signal, const QObject *receiver, const char *member)
\threadsafe
Definition qobject.cpp:3236
bool signalsBlocked() const noexcept
Returns true if signals are blocked; otherwise returns false.
Definition qobject.h:135
bool blockSignals(bool b) noexcept
If block is true, signals emitted by this object are blocked (i.e., emitting a signal will not invoke...
Definition qobject.cpp:1585
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.
Definition qevent.h:486
const QRect & rect() const
Returns the rectangle that needs to be updated.
Definition qevent.h:492
The QPainter class performs low-level painting on widgets and other paint devices.
Definition qpainter.h:46
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.
@ Disabled
Definition qpalette.h:49
virtual void setTag(quintptr tag)
virtual QPlatformMenu * createSubMenu() const
virtual QPlatformMenuItem * createMenuItem() const
virtual void insertMenuItem(QPlatformMenuItem *menuItem, QPlatformMenuItem *before)=0
virtual void syncSeparatorsCollapsible(bool enable)=0
virtual void syncMenuItem(QPlatformMenuItem *menuItem)=0
virtual void setEnabled(bool enabled)=0
virtual void dismiss()
virtual QPlatformMenuItem * menuItemForTag(quintptr tag) const =0
static QString removeMnemonics(const QString &original)
\inmodule QtCore\reentrant
Definition qpoint.h:217
constexpr qreal y() const noexcept
Returns the y coordinate of this point.
Definition qpoint.h:348
constexpr QPoint toPoint() const
Rounds the coordinates of this point to the nearest integer, and returns a QPoint object with the rou...
Definition qpoint.h:404
bool isNull() const noexcept
Returns true if both the x and y coordinates are set to 0.0 (ignoring the sign); otherwise returns fa...
Definition qpoint.h:338
\inmodule QtCore\reentrant
Definition qpoint.h:25
constexpr int & rx() noexcept
Returns a reference to the x coordinate of this point.
Definition qpoint.h:155
constexpr int x() const noexcept
Returns the x coordinate of this point.
Definition qpoint.h:130
constexpr int y() const noexcept
Returns the y coordinate of this point.
Definition qpoint.h:135
const QPointingDevice * pointingDevice() const
Returns the source device from which this event originates.
Definition qevent.cpp:330
void clear() noexcept
Definition qpointer.h:87
static QPushButtonPrivate * get(QPushButton *b)
The QPushButton widget provides a command button.
Definition qpushbutton.h:20
\inmodule QtCore\reentrant
Definition qrect.h:30
constexpr bool isEmpty() const noexcept
Returns true if the rectangle is empty, otherwise returns false.
Definition qrect.h:167
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...
Definition qrect.cpp:1069
constexpr int height() const noexcept
Returns the height of the rectangle.
Definition qrect.h:239
constexpr bool isNull() const noexcept
Returns true if the rectangle is a null rectangle, otherwise returns false.
Definition qrect.h:164
constexpr int bottom() const noexcept
Returns the y-coordinate of the rectangle's bottom edge.
Definition qrect.h:182
constexpr int top() const noexcept
Returns the y-coordinate of the rectangle's top edge.
Definition qrect.h:176
constexpr void setBottom(int pos) noexcept
Sets the bottom edge of the rectangle to the given y coordinate.
Definition qrect.h:200
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...
Definition qrect.cpp:855
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...
Definition qrect.h:346
constexpr int x() const noexcept
Returns the x-coordinate of the rectangle's left edge.
Definition qrect.h:185
constexpr void setWidth(int w) noexcept
Sets the width of the rectangle to the given width.
Definition qrect.h:381
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.
Definition qrect.h:245
constexpr int width() const noexcept
Returns the width of the rectangle.
Definition qrect.h:236
QRect united(const QRect &other) const noexcept
Definition qrect.h:420
constexpr int y() const noexcept
Returns the y-coordinate of the rectangle's top edge.
Definition qrect.h:188
constexpr void setHeight(int h) noexcept
Sets the height of the rectangle to the given height.
Definition qrect.h:384
constexpr void moveTop(int pos) noexcept
Moves the rectangle vertically, leaving the rectangle's top edge at the given y coordinate.
Definition qrect.h:289
constexpr int right() const noexcept
Returns the x-coordinate of the rectangle's right edge.
Definition qrect.h:179
constexpr void setTop(int pos) noexcept
Sets the top edge of the rectangle to the given y coordinate.
Definition qrect.h:194
The QRegion class specifies a clip region for a painter.
Definition qregion.h:27
The QScreen class is used to query screen properties. \inmodule QtGui.
Definition qscreen.h:32
QRect availableGeometry
the screen's available geometry in pixels
Definition qscreen.h:46
QRect geometry
the screen's geometry in pixels
Definition qscreen.h:45
iterator begin()
Definition qset.h:136
iterator end()
Definition qset.h:140
QPointF globalPosition() const
Returns the position of the point in this event on the screen or virtual desktop.
Definition qevent.h:123
QPointF position() const
Returns the position of the point in this event, relative to the widget or item that received the eve...
Definition qevent.h:119
Qt::MouseButton button() const
Returns the button that caused the event.
Definition qevent.h:116
Qt::MouseButtons buttons() const
Returns the button state when the event was generated.
Definition qevent.h:117
\inmodule QtCore
Definition qsize.h:25
constexpr int height() const noexcept
Returns the height.
Definition qsize.h:133
constexpr int width() const noexcept
Returns the width.
Definition qsize.h:130
constexpr QSize expandedTo(const QSize &) const noexcept
Returns a size holding the maximum width and height of this size and the given otherSize.
Definition qsize.h:192
constexpr void setWidth(int w) noexcept
Sets the width to the given width.
Definition qsize.h:136
constexpr bool isEmpty() const noexcept
Returns true if either of the width and height is less than or equal to 0; otherwise returns false.
Definition qsize.h:124
constexpr void setHeight(int h) noexcept
Sets the height to the given height.
Definition qsize.h:139
\macro QT_RESTRICTED_CAST_FROM_ASCII
Definition qstring.h:129
qsizetype indexOf(QLatin1StringView s, qsizetype from=0, Qt::CaseSensitivity cs=Qt::CaseSensitive) const
Definition qstring.cpp:4517
bool isEmpty() const noexcept
Returns true if the string has no characters; otherwise returns false.
Definition qstring.h:192
qsizetype size() const noexcept
Returns the number of characters in this string.
Definition qstring.h:186
const QChar at(qsizetype i) const
Returns the character at the given index position in the string.
Definition qstring.h:1226
The QStyleHintReturnMask class provides style hints that return a QRegion.
\variable QStyleOptionFocusRect::backgroundColor
\variable QStyleOptionProgressBar::minimum
The QStyleOption class stores the parameters used by QStyle functions.
QFontMetrics fontMetrics
void initFrom(const QWidget *w)
The QStylePainter class is a convenience class for drawing QStyle elements inside a widget.
static bool useFullScreenForPopup()
Definition qstyle.cpp:2420
The QStyle class is an abstract base class that encapsulates the look and feel of a GUI.
Definition qstyle.h:29
@ State_Sunken
Definition qstyle.h:69
@ State_Active
Definition qstyle.h:83
@ State_Enabled
Definition qstyle.h:67
@ State_DownArrow
Definition qstyle.h:73
@ State_Selected
Definition qstyle.h:82
@ State_None
Definition qstyle.h:66
@ CT_Menu
Definition qstyle.h:557
@ CT_MenuItem
Definition qstyle.h:554
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_Menu_Scrollable
Definition qstyle.h:615
@ SH_Menu_Mask
Definition qstyle.h:665
@ SH_MenuBar_AltKeyNavigation
Definition qstyle.h:603
@ SH_Menu_MouseTracking
Definition qstyle.h:605
@ SH_Menu_FlashTriggeredItem
Definition qstyle.h:666
@ SH_Menu_SubMenuPopupDelay
Definition qstyle.h:601
@ SH_Menu_KeyboardSearch
Definition qstyle.h:651
@ SH_Menu_SupportsSections
Definition qstyle.h:682
@ SH_Menu_SelectionWrap
Definition qstyle.h:658
@ SH_Menu_AllowActiveAndDisabled
Definition qstyle.h:599
@ SH_Menu_FillScreenWithScroll
Definition qstyle.h:630
@ SH_Menu_FadeOutOnHide
Definition qstyle.h:667
@ SH_Menu_SpaceActivatesItem
Definition qstyle.h:600
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...
@ CE_MenuItem
Definition qstyle.h:190
@ CE_MenuEmptyArea
Definition qstyle.h:195
@ CE_MenuTearoff
Definition qstyle.h:194
@ CE_MenuScroller
Definition qstyle.h:191
@ PM_MenuVMargin
Definition qstyle.h:452
@ PM_MenuPanelWidth
Definition qstyle.h:453
@ PM_TitleBarHeight
Definition qstyle.h:448
@ PM_MenuTearoffHeight
Definition qstyle.h:454
@ PM_MenuDesktopFrameWidth
Definition qstyle.h:455
@ PM_MenuHMargin
Definition qstyle.h:451
@ PM_SmallIconSize
Definition qstyle.h:495
@ PM_SubMenuOverlap
Definition qstyle.h:527
@ PM_MenuScrollerHeight
Definition qstyle.h:450
@ PE_PanelMenu
Definition qstyle.h:159
@ PE_FrameMenu
Definition qstyle.h:109
virtual int pixelMetric(PixelMetric metric, const QStyleOption *option=nullptr, const QWidget *widget=nullptr) const =0
Returns the value of the given pixel metric.
\inmodule QtCore
Definition qcoreevent.h:366
int timerId() const
Returns the unique timer identifier, which is the same identifier as returned from QObject::startTime...
Definition qcoreevent.h:370
bool singleShot
whether the timer is a single-shot timer
Definition qtimer.h:22
static void showText(const QPoint &pos, const QString &text, QWidget *w=nullptr, const QRect &rect={}, int msecShowTime=-1)
Shows text as a tool tip, with the global position pos as the point of interest.
Definition qtooltip.cpp:439
static void hideText()
Definition qtooltip.h:19
void onTrigger(QAction *action)
Definition qmenu.cpp:150
void updateWindowTitle()
Definition qmenu.cpp:140
void onHovered(QAction *action)
Definition qmenu.cpp:151
void actionEvent(QActionEvent *e) override
\reimp
Definition qmenu.cpp:131
QTornOffMenu(QMenu *p)
Definition qmenu.cpp:91
void syncWithMenu(QMenu *menu, QActionEvent *act)
Definition qmenu.cpp:120
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.
The QWidgetAction class extends QAction by an interface for inserting custom widgets into action base...
void releaseWidget(QWidget *widget)
Releases the specified widget.
bool setScreen(QScreen *screen)
Definition qwidget.cpp:2420
QList< QAction * > actions
Definition qwidget_p.h:709
bool setScreenForPoint(const QPoint &pos)
Definition qwidget.cpp:2405
short bottommargin
Definition qwidget_p.h:696
short rightmargin
Definition qwidget_p.h:695
void setVisible(bool)
Definition qwidget.cpp:8274
static QRect screenGeometry(const QWidget *widget)
Definition qwidget_p.h:469
QTLWExtra * topData() const
Definition qwidget_p.h:861
static QRect availableScreenGeometry(const QWidget *widget)
Definition qwidget_p.h:474
void createWinId()
Definition qwidget.cpp:2370
QWindow * windowHandle(WindowHandleMode mode=WindowHandleMode::Direct) const
Definition qwidget.cpp:1055
The QWidget class is the base class of all user interface objects.
Definition qwidget.h:99
void setAttribute(Qt::WidgetAttribute, bool on=true)
Sets the attribute attribute on this widget if on is true; otherwise clears the attribute.
QWidget * window() const
Returns the window for this widget, i.e.
Definition qwidget.cpp:4313
void setGeometry(int x, int y, int w, int h)
This is an overloaded member function, provided for convenience. It differs from the above function o...
Definition qwidget.h:886
void scroll(int dx, int dy)
Scrolls the widget including its children dx pixels to the right and dy downward.
void setContentsMargins(int left, int top, int right, int bottom)
Sets the margins around the contents of the widget to have the sizes left, top, right,...
Definition qwidget.cpp:7590
void setParent(QWidget *parent)
Sets the parent of the widget to parent, and resets the window flags.
void setMask(const QBitmap &)
Causes only the pixels of the widget for which bitmap has a corresponding 1 bit to be visible.
void setStyle(QStyle *)
Sets the widget's GUI style to style.
Definition qwidget.cpp:2630
QPointF mapToGlobal(const QPointF &) const
Translates the widget coordinate pos to global screen coordinates.
void setEnabled(bool)
Definition qwidget.cpp:3358
QRect geometry
the geometry of the widget relative to its parent and excluding the window frame
Definition qwidget.h:106
QPalette palette
the widget's palette
Definition qwidget.h:132
int width
the width of the widget excluding any window frame
Definition qwidget.h:114
void setMouseTracking(bool enable)
Definition qwidget.h:853
QPoint pos
the position of the widget within its parent widget
Definition qwidget.h:111
bool close()
Closes this widget.
Definition qwidget.cpp:8562
int height
the height of the widget excluding any window frame
Definition qwidget.h:115
QList< QAction * > actions() const
Returns the (possibly empty) list of this widget's actions.
Definition qwidget.cpp:3207
QRect rect
the internal geometry of the widget excluding any window frame
Definition qwidget.h:116
void setFocus()
This is an overloaded member function, provided for convenience. It differs from the above function o...
Definition qwidget.h:423
void setLayoutDirection(Qt::LayoutDirection direction)
Definition qwidget.cpp:4879
void show()
Shows the widget and its child widgets.
Definition qwidget.cpp:7875
virtual void setVisible(bool visible)
Definition qwidget.cpp:8255
void insertAction(QAction *before, QAction *action)
Inserts the action action to this widget's list of actions, before the action before.
Definition qwidget.cpp:3142
int x
the x coordinate of the widget relative to its parent including any window frame
Definition qwidget.h:109
bool isEnabled() const
Definition qwidget.h:814
void update()
Updates the widget unless updates are disabled or the widget is hidden.
QWindow * windowHandle() const
If this is a native widget, return the associated QWindow.
Definition qwidget.cpp:2483
virtual void changeEvent(QEvent *)
This event handler can be reimplemented to handle state changes.
Definition qwidget.cpp:9382
bool isRightToLeft() const
Definition qwidget.h:419
void addActions(const QList< QAction * > &actions)
Appends the actions actions to this widget's list of actions.
Definition qwidget.cpp:3127
void setWindowTitle(const QString &)
Definition qwidget.cpp:6105
bool event(QEvent *event) override
This is the main event handler; it handles event event.
Definition qwidget.cpp:8866
QStyle * style() const
Definition qwidget.cpp:2600
void resize(int w, int h)
This is an overloaded member function, provided for convenience. It differs from the above function o...
Definition qwidget.h:883
bool underMouse() const
Returns true if the widget is under the mouse cursor; otherwise returns false.
Definition qwidget.h:859
Qt::FocusPolicy focusPolicy
the way the widget accepts keyboard focus
Definition qwidget.h:140
QWidget * parentWidget() const
Returns the parent of this widget, or \nullptr if it does not have any parent widget.
Definition qwidget.h:904
bool isWindow() const
Returns true if the widget is an independent window, otherwise returns false.
Definition qwidget.h:811
QScreen * screen() const
Returns the screen the widget is on.
Definition qwidget.cpp:2496
void setStyleSheet(const QString &styleSheet)
Definition qwidget.cpp:2555
void removeAction(QAction *action)
Removes the action action from this widget's list of actions.
Definition qwidget.cpp:3186
bool isVisible() const
Definition qwidget.h:874
void addAction(QAction *action)
Appends the action action to this widget's list of actions.
Definition qwidget.cpp:3117
bool visible
whether the widget is visible
Definition qwidget.h:144
\inmodule QtGui
Definition qwindow.h:63
ResetOnDestroy(QMenuSloppyState *sloppyState, bool *guard)
Definition qmenu.cpp:859
bool * guard
Definition qmenu.cpp:873
QMenuSloppyState * toReset
Definition qmenu.cpp:872
QOpenGLWidget * widget
[1]
QString text
QPushButton * button
[2]
QSet< QString >::iterator it
direction
QStyleOptionButton opt
short next
Definition keywords.cpp:445
Combined button and popup list for selecting options.
Definition qcompare.h:63
@ LeftButton
Definition qnamespace.h:58
@ WA_X11NetWmWindowTypePopupMenu
Definition qnamespace.h:394
@ WA_SetLayoutDirection
Definition qnamespace.h:323
@ WA_CustomWhatsThis
Definition qnamespace.h:313
@ WA_X11NetWmWindowTypeDropDownMenu
Definition qnamespace.h:393
@ WA_Resized
Definition qnamespace.h:308
@ WA_DontShowOnScreen
Definition qnamespace.h:383
@ WA_NoMouseReplay
Definition qnamespace.h:320
@ WA_X11NetWmWindowTypeMenu
Definition qnamespace.h:389
@ WA_DeleteOnClose
Definition qnamespace.h:321
@ NoFocus
Definition qnamespace.h:107
@ TextSingleLine
Definition qnamespace.h:170
@ TextShowMnemonic
Definition qnamespace.h:173
@ UI_FadeMenu
@ UI_AnimateMenu
@ Key_Tab
Definition qnamespace.h:664
@ Key_Select
@ Key_Shift
Definition qnamespace.h:683
@ Key_Return
Definition qnamespace.h:667
@ Key_Right
Definition qnamespace.h:679
@ Key_Enter
Definition qnamespace.h:668
@ Key_PageUp
Definition qnamespace.h:681
@ Key_Space
Definition qnamespace.h:513
@ Key_Backtab
Definition qnamespace.h:665
@ Key_Left
Definition qnamespace.h:677
@ Key_Control
Definition qnamespace.h:684
@ Key_Alt
Definition qnamespace.h:686
@ Key_Up
Definition qnamespace.h:678
@ Key_Down
Definition qnamespace.h:680
@ Key_Meta
Definition qnamespace.h:685
@ Key_F1
Definition qnamespace.h:690
@ Key_PageDown
Definition qnamespace.h:682
@ Key_Back
Definition qnamespace.h:846
@ Key_Home
Definition qnamespace.h:675
@ Key_End
Definition qnamespace.h:676
@ ShiftModifier
@ NoModifier
@ AltModifier
@ CaseInsensitive
@ QueuedConnection
@ UniqueConnection
@ Window
Definition qnamespace.h:207
@ Tool
Definition qnamespace.h:212
@ PopupFocusReason
@ TabFocusReason
NSMenu QCocoaMenu * platformMenu
#define Q_FALLTHROUGH()
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)
Definition qeffects.cpp:525
void qFadeEffect(QWidget *w, int time)
Definition qeffects.cpp:547
return ret
static QWidget * getParentWidget(const QAction *action)
Definition qmenu.cpp:220
constexpr const T & qMin(const T &a, const T &b)
Definition qminmax.h:40
constexpr const T & qMax(const T &a, const T &b)
Definition qminmax.h:42
#define SLOT(a)
Definition qobjectdefs.h:52
#define SIGNAL(a)
Definition qobjectdefs.h:53
static bool contains(const QJsonArray &haystack, unsigned needle)
Definition qopengl.cpp:116
GLint location
GLboolean GLboolean GLboolean b
GLint GLint GLint GLint GLint x
[0]
const GLfloat * m
GLuint64 key
GLfloat GLfloat GLfloat w
[0]
GLboolean GLboolean GLboolean GLboolean a
[7]
GLenum GLuint GLintptr GLsizeiptr size
[1]
GLuint index
[2]
GLuint GLuint end
GLdouble GLdouble GLdouble GLdouble top
GLdouble GLdouble right
GLfloat GLfloat f
GLint GLsizei width
GLint left
GLenum type
GLenum GLuint GLintptr offset
GLint first
GLint y
struct _cl_event * event
GLhandleARB obj
[2]
GLdouble s
[6]
Definition qopenglext.h:235
GLboolean reset
const GLubyte * c
GLdouble GLdouble t
Definition qopenglext.h:243
GLdouble GLdouble GLdouble GLdouble q
Definition qopenglext.h:259
GLuint64EXT * result
[6]
GLfloat GLfloat p
[1]
GLuint GLenum option
#define Q_ASSERT(cond)
Definition qrandom.cpp:47
QScopeGuard< typename std::decay< F >::type > qScopeGuard(F &&f)
[qScopeGuard]
Definition qscopeguard.h:60
QScreen * screen
[1]
Definition main.cpp:29
#define QT_CONFIG(feature)
static QT_BEGIN_NAMESPACE void init(QTextBoundaryFinder::BoundaryType type, QStringView str, QCharAttributes *attributes)
#define Q_OBJECT
#define slots
#define emit
size_t quintptr
Definition qtypes.h:167
ptrdiff_t qsizetype
Definition qtypes.h:165
unsigned int uint
Definition qtypes.h:34
static bool isEmbedded(const QWindow *w)
Definition qwidget.cpp:6612
static bool bypassGraphicsProxyWidget(const QWidget *p)
Definition qwidget_p.h:169
QList< int > list
[14]
QString title
[35]
QByteArray page
[45]
QString dir
[11]
QGraphicsItem * item
QList< QTreeWidgetItem * > items
QPainter painter(this)
[7]
aWidget window() -> setWindowTitle("New Window Title")
[2]
QFrame frame
[0]
QMenu menu
[5]
QAction * at
@ RightScroll
Definition qeffects_p.h:32
qsizetype indexOf(const AT &t, qsizetype from=0) const noexcept
Definition qlist.h:962
bool contains(const AT &t) const noexcept
Definition qlist.h:45
QPointer< QWidget > widget
Definition qmenu_p.h:402
QPointer< QAction > action
Definition qmenu_p.h:403
QScreen * initialScreen
Definition qwidget_p.h:112