Qt 6.x
The Qt SDK
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();
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 (useFullScreenForPopup())
296 return screen ? screen->geometry()
300}
301
303{
305 for(QWidget *widget = causedPopup.widget; widget; ) {
306 ret.append(widget);
307 if (QTornOffMenu *qtmenu = qobject_cast<QTornOffMenu*>(widget))
308 ret += qtmenu->d_func()->causedStack;
309 if (QMenu *qmenu = qobject_cast<QMenu*>(widget))
310 widget = qmenu->d_func()->causedPopup.widget;
311 else
312 break;
313 }
314 return ret;
315}
316
318{
319#if QT_CONFIG(menubar)
320 return qobject_cast<const QMenuBar *>(topCausedWidget()) == nullptr;
321#else
322 return true;
323#endif
324}
325
327{
328 updateActionRects(popupGeometry());
329}
330
332{
333 Q_Q(const QMenu);
334 if (!itemsDirty)
335 return;
336
337 q->ensurePolished();
338
339 //let's reinitialize the buffer
340 actionRects.resize(actions.size());
341 actionRects.fill(QRect());
342
343 int lastVisibleAction = getLastVisibleAction();
344
345 QStyle *style = q->style();
347 opt.initFrom(q);
348 const int hmargin = style->pixelMetric(QStyle::PM_MenuHMargin, &opt, q),
351 const int fw = style->pixelMetric(QStyle::PM_MenuPanelWidth, &opt, q);
353 const int tearoffHeight = tearoff ? style->pixelMetric(QStyle::PM_MenuTearoffHeight, &opt, q) : 0;
354 const int base_y = vmargin + fw + topmargin + (scroll ? scroll->scrollOffset : 0) + tearoffHeight;
355 const int column_max_y = screen.height() - 2 * deskFw - (vmargin + bottommargin + fw);
356 int max_column_width = 0;
357 int y = base_y;
358
359 //for compatibility now - will have to refactor this away
360 tabWidth = 0;
361 maxIconWidth = 0;
362 hasCheckableItems = false;
363 ncols = 1;
364
365 for (int i = 0; i < actions.size(); ++i) {
366 QAction *action = actions.at(i);
367 if (action->isSeparator() || !action->isVisible() || widgetItems.contains(action))
368 continue;
369 //..and some members
370 hasCheckableItems |= action->isCheckable();
371 QIcon is = action->icon();
372 if (!is.isNull()) {
373 maxIconWidth = qMax<uint>(maxIconWidth, icone + 4);
374 }
375 }
376
377 //calculate size
378 QFontMetrics qfm = q->fontMetrics();
379 bool previousWasSeparator = true; // this is true to allow removing the leading separators
380#if QT_CONFIG(shortcut)
381 const bool contextMenu = isContextMenu();
382#endif
383 for(int i = 0; i <= lastVisibleAction; i++) {
384 QAction *action = actions.at(i);
385 const bool isSection = action->isSeparator() && (!action->text().isEmpty() || !action->icon().isNull());
386 const bool isPlainSeparator = (isSection && !q->style()->styleHint(QStyle::SH_Menu_SupportsSections))
387 || (action->isSeparator() && !isSection);
388
389 if (!action->isVisible() ||
390 (collapsibleSeparators && previousWasSeparator && isPlainSeparator))
391 continue; // we continue, this action will get an empty QRect
392
393 previousWasSeparator = isPlainSeparator;
394
395 //let the style modify the above size..
397 q->initStyleOption(&opt, action);
398 const QFontMetrics &fm = opt.fontMetrics;
399
400 QSize sz;
401 if (QWidget *w = widgetItems.value(action)) {
402 sz = w->sizeHint().expandedTo(w->minimumSize()).expandedTo(w->minimumSizeHint()).boundedTo(w->maximumSize());
403 } else {
404 //calc what I think the size is..
405 if (action->isSeparator()) {
406 sz = QSize(2, 2);
407 } else {
408 QString s = action->text();
409 qsizetype t = s.indexOf(u'\t');
410 if (t != -1) {
411 tabWidth = qMax(int(tabWidth), qfm.horizontalAdvance(s.mid(t+1)));
412 s = s.left(t);
413#if QT_CONFIG(shortcut)
414 } else if (action->isShortcutVisibleInContextMenu() || !contextMenu) {
415 QKeySequence seq = action->shortcut();
416 if (!seq.isEmpty())
417 tabWidth = qMax(int(tabWidth), qfm.horizontalAdvance(seq.toString(QKeySequence::NativeText)));
418#endif
419 }
421 sz.setHeight(qMax(fm.height(), qfm.height()));
422
423 QIcon is = action->icon();
424 if (!is.isNull()) {
425 QSize is_sz = QSize(icone, icone);
426 if (is_sz.height() > sz.height())
427 sz.setHeight(is_sz.height());
428 }
429 }
431 }
432
433
434 if (!sz.isEmpty()) {
435 max_column_width = qMax(max_column_width, sz.width());
436 //wrapping
437 if (!scroll && y + sz.height() > column_max_y) {
438 ncols++;
439 y = base_y;
440 } else {
441 y += sz.height();
442 }
443 //update the item
444 actionRects[i] = QRect(0, 0, sz.width(), sz.height());
445 }
446 }
447
448 max_column_width += tabWidth; //finally add in the tab width
449 if (!tornoff || scroll) { // exclude non-scrollable tear-off menu since the tear-off menu has a fixed size
450 const int sfcMargin = style->sizeFromContents(QStyle::CT_Menu, &opt, QSize(0, 0), q).width();
451 const int min_column_width = q->minimumWidth() - (sfcMargin + leftmargin + rightmargin + 2 * (fw + hmargin));
452 max_column_width = qMax(min_column_width, max_column_width);
453 }
454
455 //calculate position
456 int x = hmargin + fw + leftmargin;
457 y = base_y;
458
459 for(int i = 0; i < actions.size(); i++) {
460 QRect &rect = actionRects[i];
461 if (rect.isNull())
462 continue;
463 if (!scroll && y + rect.height() > column_max_y) {
464 x += max_column_width + hmargin;
465 y = base_y;
466 }
467 rect.translate(x, y); //move
468 rect.setWidth(max_column_width); //uniform width
469
470 //we need to update the widgets geometry
471 if (QWidget *widget = widgetItems.value(actions.at(i))) {
474 }
475
476 y += rect.height();
477 }
478 itemsDirty = 0;
479}
480
482{
483 //let's try to get the last visible action
484 int lastVisibleAction = actions.size() - 1;
485 for (;lastVisibleAction >= 0; --lastVisibleAction) {
486 const QAction *action = actions.at(lastVisibleAction);
487 if (action->isVisible()) {
488 //removing trailing separators
489 if (action->isSeparator() && collapsibleSeparators)
490 continue;
491 break;
492 }
493 }
494 return lastVisibleAction;
495}
496
497
499{
500 int index = actions.indexOf(act);
501 if (index == -1)
502 return QRect();
503
504 updateActionRects();
505
506 //we found the action
507 return actionRects.at(index);
508}
509
511{
512 Q_Q(QMenu);
513 bool fadeMenus = q->style()->styleHint(QStyle::SH_Menu_FadeOutOnHide);
514 if (!tornoff) {
515 QWidget *caused = causedPopup.widget;
516 hideMenu(q); //hide after getting causedPopup
517 while(caused) {
518#if QT_CONFIG(menubar)
519 if (QMenuBar *mb = qobject_cast<QMenuBar*>(caused)) {
520 mb->d_func()->setCurrentAction(nullptr);
521 mb->d_func()->setKeyboardMode(false);
522 caused = nullptr;
523 } else
524#endif
525 if (QMenu *m = qobject_cast<QMenu*>(caused)) {
526 caused = m->d_func()->causedPopup.widget;
527 if (!m->d_func()->tornoff)
528 hideMenu(m);
529 if (!fadeMenus) // Mac doesn't clear the action until after hidden.
530 m->d_func()->setCurrentAction(nullptr);
531 } else { caused = nullptr;
532 }
533 }
534 }
535 setCurrentAction(nullptr);
536}
537
539{
540 if (!menu)
541 return;
542
543 // See two execs below. They may trigger an akward situation
544 // when 'menu' (also known as 'q' or 'this' in the many functions
545 // around) to become a dangling pointer if the loop manages
546 // to execute 'deferred delete' ... posted while executing
547 // this same loop. Not good!
548 struct Reposter : QObject
549 {
550 Reposter(QMenu *menu) : q(menu)
551 {
552 Q_ASSERT(q);
553 q->installEventFilter(this);
554 }
555 ~Reposter()
556 {
557 if (deleteLater)
558 q->deleteLater();
559 }
560 bool eventFilter(QObject *obj, QEvent *event) override
561 {
562 if (obj == q && event->type() == QEvent::DeferredDelete)
563 return deleteLater = true;
564
566 }
567 QMenu *q = nullptr;
568 bool deleteLater = false;
569 };
570
571#if QT_CONFIG(effects)
572 QSignalBlocker blocker(menu);
573 aboutToHide = true;
574 // Flash item which is about to trigger (if any).
576 && currentAction && currentAction == actionAboutToTrigger
577 && menu->actions().contains(currentAction)) {
578 QEventLoop eventLoop;
579 QAction *activeAction = currentAction;
580
581 menu->setActiveAction(nullptr);
582 const Reposter deleteDeleteLate(menu);
583 QTimer::singleShot(60, &eventLoop, SLOT(quit()));
584 eventLoop.exec();
585
586 // Select and wait 20 ms.
588 QTimer::singleShot(20, &eventLoop, SLOT(quit()));
589 eventLoop.exec();
590 }
591
592 aboutToHide = false;
593 blocker.unblock();
594#endif // QT_CONFIG(effects)
595 if (activeMenu == menu)
596 activeMenu = nullptr;
597 menu->d_func()->causedPopup.action = nullptr;
598 menu->close();
599 menu->d_func()->causedPopup.widget = nullptr;
600}
601
603{
604 Q_Q(const QMenu);
605 if (const QWidget *parent = q->nativeParentWidget()) {
606 if (parent->windowHandle())
607 return parent->windowHandle();
608 }
609
610 if (const QWindow *w = q->windowHandle()) {
611 if (w->transientParent())
612 return w->transientParent();
613 }
614
615 if (causedPopup.widget) {
616 if (const QWidget *w = causedPopup.widget.data()) {
617 if (const QWidget *ww = w->window())
618 return ww->windowHandle();
619 }
620 }
621
622 return nullptr;
623}
624
625void QMenuPrivate::popupAction(QAction *action, int delay, bool activateFirst)
626{
627 Q_Q(QMenu);
628 if (action) {
629 if (action->isEnabled()) {
630 if (!delay)
631 q->internalDelayedPopup();
632 else if (action->menu() && !action->menu()->isVisible())
633 delayState.start(delay, action);
634 else if (!action->menu())
635 delayState.stop();
636 if (activateFirst && action->menu())
637 action->menu()->d_func()->setFirstActionActive();
638 }
639 } else if (QMenu *menu = activeMenu) { //hide the current item
640 hideMenu(menu);
641 }
642}
643
645{
646 Q_Q(QMenu);
647 QAction *current = currentAction;
648 if (current && (!current->isEnabled() || current->menu() || current->isSeparator()))
649 current = nullptr;
650 for(QWidget *caused = q; caused;) {
651 if (QMenu *m = qobject_cast<QMenu*>(caused)) {
652 caused = m->d_func()->causedPopup.widget;
653 if (m->d_func()->eventLoop)
654 m->d_func()->syncAction = current; // synchronous operation
655 } else {
656 break;
657 }
658 }
659}
660
661
663{
664 Q_Q(QMenu);
665 updateActionRects();
666 for(int i = 0, saccum = 0; i < actions.size(); i++) {
667 const QRect &rect = actionRects.at(i);
668 if (rect.isNull())
669 continue;
670 if (scroll && scroll->scrollFlags & QMenuScroller::ScrollUp) {
671 saccum -= rect.height();
672 if (saccum > scroll->scrollOffset - scrollerHeight())
673 continue;
674 }
675 QAction *act = actions.at(i);
676 if (!act->isSeparator() &&
677 (q->style()->styleHint(QStyle::SH_Menu_AllowActiveAndDisabled, nullptr, q)
678 || act->isEnabled())) {
679 setCurrentAction(act);
680 break;
681 }
682 }
683}
684
685// popup == -1 means do not popup, 0 means immediately, others mean use a timer
686void QMenuPrivate::setCurrentAction(QAction *action, int popup, SelectionReason reason, bool activateFirst)
687{
688 Q_Q(QMenu);
689 tearoffHighlighted = 0;
690
691 if (action
692 && (action->isSeparator()
693 || (!action->isEnabled() && !q->style()->styleHint(QStyle::SH_Menu_AllowActiveAndDisabled, nullptr, q))))
694 action = nullptr;
695
696 // Reselect the currently active action in case mouse moved over other menu items when
697 // moving from sub menu action to sub menu (QTBUG-20094).
698 if (reason != SelectedFromKeyboard) {
699 if (QMenu *menu = qobject_cast<QMenu*>(causedPopup.widget)) {
700 if (causedPopup.action && menu->d_func()->activeMenu == q)
701 // Reselect parent menu action only if mouse is over a menu and parent menu action is not already selected (QTBUG-47987)
702 if (hasReceievedEnter && menu->d_func()->currentAction != causedPopup.action)
703 menu->d_func()->setCurrentAction(causedPopup.action, 0, reason, false);
704 }
705 }
706
707 if (currentAction)
708 q->update(actionRect(currentAction));
709
710 QMenu *hideActiveMenu = activeMenu;
711 QAction *previousAction = currentAction;
712
713 currentAction = action;
714 if (action) {
715 if (!action->isSeparator()) {
716 activateAction(action, QAction::Hover);
717 if (popup != -1) {
718 // if the menu is visible then activate the required action,
719 // otherwise we just mark the action as currentAction
720 // and activate it when the menu will be popuped.
721 if (q->isVisible())
722 popupAction(currentAction, popup, activateFirst);
723 }
724 q->update(actionRect(action));
725
726 if (reason == SelectedFromKeyboard) {
727 QWidget *widget = widgetItems.value(action);
728 if (widget) {
731 } else {
732 //when the action has no QWidget, the QMenu itself should
733 // get the focus
734 // Since the menu is a pop-up, it uses the popup reason.
735 if (!q->hasFocus()) {
736 q->setFocus(Qt::PopupFocusReason);
737 }
738 }
739 }
740 }
741#if QT_CONFIG(statustip)
742 } else if (previousAction) {
743 previousAction->d_func()->showStatusText(topCausedWidget(), QString());
744#endif
745 }
746 if (hideActiveMenu && previousAction != currentAction) {
747 if (popup == -1) {
748#if QT_CONFIG(effects)
749 // kill any running effect
750 qFadeEffect(nullptr);
751 qScrollEffect(nullptr);
752#endif
753 hideMenu(hideActiveMenu);
754 } else if (!currentAction || !currentAction->menu()) {
755 sloppyState.startTimerIfNotRunning();
756 }
757 }
758}
759
761{
762 m_enabled = false;
763 m_first_mouse = true;
764 m_init_guard = false;
765 m_use_reset_action = true;
766 m_uni_dir_discarded_count = 0;
767 m_time.stop();
768 m_reset_action = nullptr;
769 m_origin_action = nullptr;
770 m_action_rect = QRect();
771 m_previous_point = QPointF();
772 if (m_sub_menu) {
773 QMenuPrivate::get(m_sub_menu)->sloppyState.m_parent = nullptr;
774 m_sub_menu = nullptr;
775 }
776}
778{
779 QMenuPrivate *menuPriv = QMenuPrivate::get(m_menu);
780
781 if (m_discard_state_when_entering_parent && m_sub_menu == menuPriv->activeMenu) {
782 menuPriv->hideMenu(m_sub_menu);
783 reset();
784 }
785 if (m_parent)
786 m_parent->childEnter();
787}
788
790{
791 stopTimer();
792 if (m_parent)
793 m_parent->childEnter();
794}
795
797{
798 if (!m_dont_start_time_on_leave) {
799 if (m_parent)
800 m_parent->childLeave();
801 startTimerIfNotRunning();
802 }
803}
804
806{
807 if (m_enabled && !QMenuPrivate::get(m_menu)->hasReceievedEnter) {
808 startTimerIfNotRunning();
809 if (m_parent)
810 m_parent->childLeave();
811 }
812}
813
814void QMenuSloppyState::setSubMenuPopup(const QRect &actionRect, QAction *resetAction, QMenu *subMenu)
815{
816 m_enabled = true;
817 m_init_guard = true;
818 m_use_reset_action = true;
819 m_time.stop();
820 m_action_rect = actionRect;
821 if (m_sub_menu)
822 QMenuPrivate::get(m_sub_menu)->sloppyState.m_parent = nullptr;
823 m_sub_menu = subMenu;
824 QMenuPrivate::get(subMenu)->sloppyState.m_parent = this;
825 m_reset_action = resetAction;
826 m_origin_action = resetAction;
827}
828
830{
831 return m_parent && m_parent->m_menu && QMenuPrivate::get(m_parent->m_menu)->delayState.timer.isActive();
832}
833
835{
836public:
837 ResetOnDestroy(QMenuSloppyState *sloppyState, bool *guard)
838 : toReset(sloppyState)
839 , guard(guard)
840 {
841 *guard = false;
842 }
843
845 {
846 if (!*guard)
847 toReset->reset();
848 }
849
851 bool *guard;
852};
853
855{
856 QMenuPrivate *menu_priv = QMenuPrivate::get(m_menu);
857
858 bool reallyHasMouse = menu_priv->hasReceievedEnter;
859 if (!reallyHasMouse) {
860 // Check whether the menu really has a mouse, because only active popup
861 // menu gets the enter/leave events. Currently Cocoa is an exception.
863 reallyHasMouse = m_menu->frameGeometry().contains(lastCursorPos);
864 }
865
866 if (menu_priv->currentAction == m_reset_action
867 && reallyHasMouse
868 && (menu_priv->currentAction
869 && menu_priv->currentAction->menu() == menu_priv->activeMenu)) {
870 return;
871 }
872
873 ResetOnDestroy resetState(this, &m_init_guard);
874
875 if (hasParentActiveDelayTimer() || !m_menu->isVisible())
876 return;
877
878 if (m_sub_menu)
879 menu_priv->hideMenu(m_sub_menu);
880
881 if (reallyHasMouse) {
882 if (m_use_reset_action)
883 menu_priv->setCurrentAction(m_reset_action, 0);
884 } else {
885 menu_priv->setCurrentAction(nullptr, 0);
886 }
887}
888
889//return the top causedPopup.widget that is not a QMenu
891{
892 QWidget* top = causedPopup.widget;
893 while (QMenu* m = qobject_cast<QMenu *>(top))
894 top = m->d_func()->causedPopup.widget;
895 return top;
896}
897
899{
900 if (!rect().contains(p)) //sanity check
901 return nullptr;
902
903 for(int i = 0; i < actionRects.size(); i++) {
904 if (actionRects.at(i).contains(p))
905 return actions.at(i);
906 }
907 return nullptr;
908}
909
911{
912 Q_Q(QMenu);
913 QObject::disconnect(menuAction, SIGNAL(destroyed()), q, SLOT(_q_overrideMenuActionDestroyed()));
914 if (a) {
915 menuAction = a;
916 QObject::connect(a, SIGNAL(destroyed()), q, SLOT(_q_overrideMenuActionDestroyed()));
917 } else { //we revert back to the default action created by the QMenu itself
918 menuAction = defaultMenuAction;
919 }
920}
921
923{
924 menuAction=defaultMenuAction;
925}
926
928{
929 Q_Q(QMenu);
930 //we need to mimic the cause of the popup's layout direction
931 //to allow setting it on a mainwindow for example
932 //we call setLayoutDirection_helper to not overwrite a user-defined value
933 if (!q->testAttribute(Qt::WA_SetLayoutDirection)) {
934 if (QWidget *w = causedPopup.widget)
935 setLayoutDirection_helper(w->layoutDirection());
936 else if (QWidget *w = q->parentWidget())
937 setLayoutDirection_helper(w->layoutDirection());
938 else
939 setLayoutDirection_helper(QGuiApplication::layoutDirection());
940 }
941}
942
944{
945 if (!painter || rect.isEmpty())
946 return;
947
948 if (!scroll || !(scroll->scrollFlags & (QMenuPrivate::QMenuScroller::ScrollUp
950 return;
951
952 Q_Q(QMenu);
953 QStyleOptionMenuItem menuOpt;
954 menuOpt.initFrom(q);
955 menuOpt.state = QStyle::State_None;
957 menuOpt.maxIconWidth = 0;
958 menuOpt.reservedShortcutWidth = 0;
959 menuOpt.rect = rect;
961 menuOpt.state |= QStyle::State_Enabled;
964
965 painter->setClipRect(menuOpt.rect);
966 q->style()->drawControl(QStyle::CE_MenuScroller, &menuOpt, painter, q);
967}
968
970{
971 if (!painter || rect.isEmpty())
972 return;
973
974 if (!tearoff)
975 return;
976
977 Q_Q(QMenu);
978 QStyleOptionMenuItem menuOpt;
979 menuOpt.initFrom(q);
980 menuOpt.state = QStyle::State_None;
982 menuOpt.maxIconWidth = 0;
983 menuOpt.reservedShortcutWidth = 0;
984 menuOpt.rect = rect;
986 if (tearoffHighlighted)
987 menuOpt.state |= QStyle::State_Selected;
988
989 painter->setClipRect(menuOpt.rect);
990 q->style()->drawControl(QStyle::CE_MenuTearoff, &menuOpt, painter, q);
991}
992
994{
995 Q_Q(const QMenu);
996 QStyle *style = q->style();
997 QStyleOption opt(0);
998 opt.initFrom(q);
999 const int hmargin = style->pixelMetric(QStyle::PM_MenuHMargin, &opt, q);
1000 const int vmargin = style->pixelMetric(QStyle::PM_MenuVMargin, &opt, q);
1001 const int fw = style->pixelMetric(QStyle::PM_MenuPanelWidth, &opt, q);
1002 return (q->rect().adjusted(hmargin + fw + leftmargin, vmargin + fw + topmargin,
1003 -(hmargin + fw + rightmargin), -(vmargin + fw + bottommargin)));
1004}
1005
1007 : QWidget(parent, f), menuPrivate(mPrivate), scrollType(type)
1008{
1009 if (parent)
1010 setMouseTracking(parent->style()->styleHint(QStyle::SH_Menu_MouseTracking, nullptr, parent));
1011}
1012
1014{
1015 if (!e->rect().intersects(rect()))
1016 return;
1017
1018 QPainter p(this);
1019 QWidget *parent = parentWidget();
1020
1021 //paint scroll up / down arrows
1022 menuPrivate->drawScroller(&p, scrollType, QRect(0, 0, width(), menuPrivate->scrollerHeight()));
1023 //paint the tear off
1025 QRect rect(0, 0, width(), parent->style()->pixelMetric(QStyle::PM_MenuTearoffHeight, nullptr, parent));
1026 if (menuPrivate->scroll && menuPrivate->scroll->scrollFlags & QMenuPrivate::QMenuScroller::ScrollUp)
1027 rect.translate(0, menuPrivate->scrollerHeight());
1028 menuPrivate->drawTearOff(&p, rect);
1029 }
1030}
1031
1033{
1034 if (rect.isEmpty())
1035 setVisible(false);
1036 else {
1037 setGeometry(rect);
1038 raise();
1039 setVisible(true);
1040 }
1041}
1042
1043
1048{
1049 return d_func()->menuAction;
1050}
1051
1071{
1072 return d_func()->menuAction->text();
1073}
1074
1076{
1077 d_func()->menuAction->setText(text);
1078}
1079
1090{
1091 return d_func()->menuAction->icon();
1092}
1093
1095{
1096 d_func()->menuAction->setIcon(icon);
1097}
1098
1099
1100//actually performs the scrolling
1102{
1103 Q_Q(QMenu);
1104 if (!scroll || !scroll->scrollFlags)
1105 return;
1107 int newOffset = 0;
1108 const int topScroll = (scroll->scrollFlags & QMenuScroller::ScrollUp) ? scrollerHeight() : 0;
1109 const int botScroll = (scroll->scrollFlags & QMenuScroller::ScrollDown) ? scrollerHeight() : 0;
1110 const int vmargin = q->style()->pixelMetric(QStyle::PM_MenuVMargin, nullptr, q);
1111 const int fw = q->style()->pixelMetric(QStyle::PM_MenuPanelWidth, nullptr, q);
1112
1114 for(int i = 0, saccum = 0; i < actions.size(); i++) {
1115 if (actions.at(i) == action) {
1116 newOffset = topScroll - saccum;
1117 break;
1118 }
1119 saccum += actionRects.at(i).height();
1120 }
1121 } else {
1122 for(int i = 0, saccum = 0; i < actions.size(); i++) {
1123 saccum += actionRects.at(i).height();
1124 if (actions.at(i) == action) {
1126 newOffset = ((q->height() / 2) - botScroll) - (saccum - topScroll);
1127 else
1128 newOffset = (q->height() - botScroll) - saccum;
1129 break;
1130 }
1131 }
1132 if (newOffset)
1133 newOffset -= fw * 2;
1134 }
1135
1136 //figure out which scroll flags
1137 uint newScrollFlags = QMenuScroller::ScrollNone;
1138 if (newOffset < 0) //easy and cheap one
1139 newScrollFlags |= QMenuScroller::ScrollUp;
1140 int saccum = newOffset;
1141 for(int i = 0; i < actionRects.size(); i++) {
1142 saccum += actionRects.at(i).height();
1143 if (saccum > q->height()) {
1144 newScrollFlags |= QMenuScroller::ScrollDown;
1145 break;
1146 }
1147 }
1148
1150 newOffset = q->height() - (saccum - newOffset) - fw*2 - vmargin - topmargin - bottommargin; //last item at bottom
1151 if (tearoff)
1152 newOffset -= q->style()->pixelMetric(QStyle::PM_MenuTearoffHeight, nullptr, q);
1153 }
1154
1155 if (!(newScrollFlags & QMenuScroller::ScrollUp) && (scroll->scrollFlags & QMenuScroller::ScrollUp)) {
1156 newOffset = 0; //first item at top
1157 }
1158
1159 if (newScrollFlags & QMenuScroller::ScrollUp)
1160 newOffset -= vmargin;
1161
1163 const int desktopFrame = q->style()->pixelMetric(QStyle::PM_MenuDesktopFrameWidth, nullptr, q);
1164 if (q->height() < screen.height()-(desktopFrame*2)-1) {
1165 QRect geom = q->geometry();
1166 if (newOffset > scroll->scrollOffset && (scroll->scrollFlags & newScrollFlags & QMenuScroller::ScrollUp)) { //scroll up
1167 const int newHeight = geom.height()-(newOffset-scroll->scrollOffset);
1168 if (newHeight > geom.height())
1169 geom.setHeight(newHeight);
1170 } else if (scroll->scrollFlags & newScrollFlags & QMenuScroller::ScrollDown) {
1171 int newTop = geom.top() + (newOffset-scroll->scrollOffset);
1172 if (newTop < desktopFrame+screen.top())
1173 newTop = desktopFrame+screen.top();
1174 if (newTop < geom.top()) {
1175 geom.setTop(newTop);
1176 newOffset = 0;
1177 newScrollFlags &= ~QMenuScroller::ScrollUp;
1178 }
1179 }
1180 if (geom.bottom() > screen.bottom() - desktopFrame)
1181 geom.setBottom(screen.bottom() - desktopFrame);
1182 if (geom.top() < desktopFrame+screen.top())
1183 geom.setTop(desktopFrame+screen.top());
1184 if (geom != q->geometry()) {
1185#if 0
1186 if (newScrollFlags & QMenuScroller::ScrollDown &&
1187 q->geometry().top() - geom.top() >= -newOffset)
1188 newScrollFlags &= ~QMenuScroller::ScrollDown;
1189#endif
1190 q->setGeometry(geom);
1191 }
1192 }
1193
1194 //actually update flags
1195 const int delta = qMin(0, newOffset) - scroll->scrollOffset; //make sure the new offset is always negative
1196 if (!itemsDirty && delta) {
1197 //we've scrolled so we need to update the action rects
1198 for (int i = 0; i < actionRects.size(); ++i) {
1199 QRect &current = actionRects[i];
1200 current.moveTop(current.top() + delta);
1201
1202 //we need to update the widgets geometry
1204 w->setGeometry(current);
1205 }
1206 }
1207 scroll->scrollOffset += delta;
1208 scroll->scrollFlags = newScrollFlags;
1209 if (active)
1210 setCurrentAction(action);
1211
1212 q->update(); //issue an update so we see all the new state..
1213}
1214
1216{
1217 Q_Q(QMenu);
1220 for(int i = actions.size()-1; i >= 0; --i) {
1221 QAction *act = actions.at(i);
1222 if (actionRects.at(i).isNull())
1223 continue;
1224 if (!act->isSeparator() &&
1225 (q->style()->styleHint(QStyle::SH_Menu_AllowActiveAndDisabled, nullptr, q)
1226 || act->isEnabled())) {
1229 else if (active)
1231 break;
1232 }
1233 }
1234 } else if (location == QMenuScroller::ScrollTop) {
1235 for(int i = 0; i < actions.size(); ++i) {
1236 QAction *act = actions.at(i);
1237 if (actionRects.at(i).isNull())
1238 continue;
1239 if (!act->isSeparator() &&
1240 (q->style()->styleHint(QStyle::SH_Menu_AllowActiveAndDisabled, nullptr, q)
1241 || act->isEnabled())) {
1244 else if (active)
1246 break;
1247 }
1248 }
1249 }
1250}
1251
1252//only directional
1254{
1255 Q_Q(QMenu);
1256 if (!scroll || !(scroll->scrollFlags & direction)) //not really possible...
1257 return;
1259 const int topScroll = (scroll->scrollFlags & QMenuScroller::ScrollUp) ? scrollerHeight() : 0;
1260 const int botScroll = (scroll->scrollFlags & QMenuScroller::ScrollDown) ? scrollerHeight() : 0;
1261 const int vmargin = q->style()->pixelMetric(QStyle::PM_MenuVMargin, nullptr, q);
1262 const int fw = q->style()->pixelMetric(QStyle::PM_MenuPanelWidth, nullptr, q);
1263 const int offset = topScroll ? topScroll-vmargin : 0;
1265 for(int i = 0, saccum = 0; i < actions.size(); i++) {
1266 saccum -= actionRects.at(i).height();
1267 if (saccum <= scroll->scrollOffset-offset) {
1269 break;
1270 }
1271 }
1272 } else if (direction == QMenuScroller::ScrollDown) {
1273 bool scrolled = false;
1274 for(int i = 0, saccum = 0; i < actions.size(); i++) {
1275 const int iHeight = actionRects.at(i).height();
1276 saccum -= iHeight;
1277 if (saccum <= scroll->scrollOffset-offset) {
1278 const int scrollerArea = q->height() - botScroll - fw*2;
1279 int visible = (scroll->scrollOffset-offset) - saccum;
1280 for(i++ ; i < actions.size(); i++) {
1281 visible += actionRects.at(i).height();
1282 if (visible > scrollerArea - topScroll) {
1283 scrolled = true;
1285 break;
1286 }
1287 }
1288 break;
1289 }
1290 }
1291 if (!scrolled) {
1292 scroll->scrollFlags &= ~QMenuScroller::ScrollDown;
1293 q->update();
1294 }
1295 }
1296}
1297
1298/* This is poor-mans eventfilters. This avoids the use of
1299 eventFilter (which can be nasty for users of QMenuBar's). */
1301{
1302 Q_Q(QMenu);
1303 QPoint pos = q->mapFromGlobal(e->globalPosition().toPoint());
1304
1305 QStyle *style = q->style();
1306 QStyleOption opt(0);
1307 opt.initFrom(q);
1308 const int hmargin = style->pixelMetric(QStyle::PM_MenuHMargin, &opt, q);
1309 const int vmargin = style->pixelMetric(QStyle::PM_MenuVMargin, &opt, q);
1310 const int fw = style->pixelMetric(QStyle::PM_MenuPanelWidth, &opt, q);
1311
1312 if (scroll && !activeMenu) { //let the scroller "steal" the event
1313 bool isScroll = false;
1314 if (pos.x() >= 0 && pos.x() < q->width()) {
1316 if (scroll->scrollFlags & dir) {
1318 isScroll = (pos.y() <= scrollerHeight() + fw + vmargin + topmargin);
1319 else if (dir == QMenuScroller::ScrollDown)
1320 isScroll = (pos.y() >= q->height() - scrollerHeight() - fw - vmargin - bottommargin);
1321 if (isScroll) {
1323 break;
1324 }
1325 }
1326 }
1327 }
1328 if (isScroll) {
1329 scroll->scrollTimer.start(50, q);
1330 return true;
1331 } else {
1333 }
1334 }
1335
1336 if (tearoff) { //let the tear off thingie "steal" the event..
1337 QRect tearRect(leftmargin + hmargin + fw, topmargin + vmargin + fw, q->width() - fw * 2 - hmargin * 2 -leftmargin - rightmargin,
1338 q->style()->pixelMetric(QStyle::PM_MenuTearoffHeight, &opt, q));
1340 tearRect.translate(0, scrollerHeight());
1341 q->update(tearRect);
1342 if (tearRect.contains(pos) && hasMouseMoved(e->globalPosition().toPoint())) {
1343 setCurrentAction(nullptr);
1345 if (e->type() == QEvent::MouseButtonRelease) {
1346 if (!tornPopup)
1347 tornPopup = new QTornOffMenu(q);
1348 tornPopup->setGeometry(q->geometry());
1349 tornPopup->show();
1351 }
1352 return true;
1353 }
1355 }
1356
1357 if (q->frameGeometry().contains(e->globalPosition().toPoint()))
1358 return false; //otherwise if the event is in our rect we want it..
1359
1360 for(QWidget *caused = causedPopup.widget; caused;) {
1361 bool passOnEvent = false;
1362 QWidget *next_widget = nullptr;
1363 QPointF cpos = caused->mapFromGlobal(e->globalPosition());
1364#if QT_CONFIG(menubar)
1365 if (QMenuBar *mb = qobject_cast<QMenuBar*>(caused)) {
1366 passOnEvent = mb->rect().contains(cpos.toPoint());
1367 } else
1368#endif
1369 if (QMenu *m = qobject_cast<QMenu*>(caused)) {
1370 passOnEvent = m->rect().contains(cpos.toPoint());
1371 next_widget = m->d_func()->causedPopup.widget;
1372 }
1373 if (passOnEvent) {
1374 if (e->type() != QEvent::MouseButtonRelease || mouseDown == caused) {
1375 QMouseEvent new_e(e->type(), cpos, caused->mapTo(caused->topLevelWidget(), cpos), e->globalPosition(),
1376 e->button(), e->buttons(), e->modifiers(),
1377 e->source(), e->pointingDevice());
1378 QCoreApplication::sendEvent(caused, &new_e);
1379 return true;
1380 }
1381 }
1382 caused = next_widget;
1383 if (!caused)
1384 sloppyState.leave(); // Start timers
1385 }
1386 return false;
1387}
1388
1390 QAction::ActionEvent action_e, bool self)
1391{
1392 Q_Q(QMenu);
1393 // can't use QBoolBlocker here
1394 const bool activationRecursionGuardReset = activationRecursionGuard;
1396 QPointer<QMenu> guard(q);
1397 if (self)
1398 action->activate(action_e);
1399 if (!guard)
1400 return;
1401 auto boolBlocker = qScopeGuard([this, activationRecursionGuardReset]{
1402 activationRecursionGuard = activationRecursionGuardReset;
1403 });
1404
1405 for(int i = 0; i < causedStack.size(); ++i) {
1406 QPointer<QWidget> widget = causedStack.at(i);
1407 if (!widget)
1408 continue;
1409 //fire
1410 if (QMenu *qmenu = qobject_cast<QMenu*>(widget)) {
1411 widget = qmenu->d_func()->causedPopup.widget;
1412 if (action_e == QAction::Trigger) {
1413 emit qmenu->triggered(action);
1414 } else if (action_e == QAction::Hover) {
1415 emit qmenu->hovered(action);
1416 }
1417#if QT_CONFIG(menubar)
1418 } else if (QMenuBar *qmenubar = qobject_cast<QMenuBar*>(widget)) {
1419 if (action_e == QAction::Trigger) {
1420 emit qmenubar->triggered(action);
1421 } else if (action_e == QAction::Hover) {
1422 emit qmenubar->hovered(action);
1423 }
1424 break; //nothing more..
1425#endif
1426 }
1427 }
1428}
1429
1431{
1432 Q_Q(QMenu);
1433#if QT_CONFIG(whatsthis)
1434 bool inWhatsThisMode = QWhatsThis::inWhatsThisMode();
1435#endif
1436 if (!action || !q->isEnabled()
1437 || (action_e == QAction::Trigger
1438#if QT_CONFIG(whatsthis)
1439 && !inWhatsThisMode
1440#endif
1441 && (action->isSeparator() ||!action->isEnabled())))
1442 return;
1443
1444 /* I have to save the caused stack here because it will be undone after popup execution (ie in the hide).
1445 Then I iterate over the list to actually send the events. --Sam
1446 */
1447 const QList<QPointer<QWidget>> causedStack = calcCausedStack();
1448 if (action_e == QAction::Trigger) {
1449#if QT_CONFIG(whatsthis)
1450 if (!inWhatsThisMode)
1451 actionAboutToTrigger = action;
1452#endif
1453
1454 if (q->testAttribute(Qt::WA_DontShowOnScreen)) {
1456 } else {
1458 if (QMenu *qmenu = qobject_cast<QMenu*>(widget)) {
1459 if (qmenu == q)
1461 widget = qmenu->d_func()->causedPopup.widget;
1462 } else {
1463 break;
1464 }
1465 }
1466 }
1467
1468#if QT_CONFIG(whatsthis)
1469 if (inWhatsThisMode) {
1470 QString s = action->whatsThis();
1471 if (s.isEmpty())
1472 s = whatsThis;
1473 QWhatsThis::showText(q->mapToGlobal(actionRect(action).center()), s, q);
1474 return;
1475 }
1476#endif
1477 }
1478
1479 QPointer<QMenu> thisGuard(q);
1480 activateCausedStack(causedStack, action, action_e, self);
1481 if (!thisGuard)
1482 return;
1483
1484 if (action_e == QAction::Hover) {
1485#if QT_CONFIG(accessibility)
1486 if (QAccessible::isActive()) {
1487 int actionIndex = indexOf(action);
1488 QAccessibleEvent focusEvent(q, QAccessible::Focus);
1489 focusEvent.setChild(actionIndex);
1490 QAccessible::updateAccessibility(&focusEvent);
1491 }
1492#endif
1494 } else {
1495 actionAboutToTrigger = nullptr;
1496 }
1497}
1498
1500{
1501 Q_Q(QMenu);
1502 if (QAction *action = qobject_cast<QAction *>(q->sender())) {
1503 QPointer<QAction> actionGuard = action;
1504 if (platformMenu && widgetItems.value(action))
1506 emit q->triggered(action);
1507 if (!activationRecursionGuard && actionGuard) {
1508 //in case the action has not been activated by the mouse
1509 //we check the parent hierarchy
1511 for(QWidget *widget = q->parentWidget(); widget; ) {
1512 if (qobject_cast<QMenu*>(widget)
1513#if QT_CONFIG(menubar)
1514 || qobject_cast<QMenuBar*>(widget)
1515#endif
1516 ) {
1519 } else {
1520 break;
1521 }
1522 }
1523 activateCausedStack(list, action, QAction::Trigger, false);
1524 // if a widget action fires, we need to hide the menu explicitly
1525 if (qobject_cast<QWidgetAction*>(action))
1527 }
1528 }
1529}
1530
1532{
1533 Q_Q(QMenu);
1534 if (QAction * action = qobject_cast<QAction *>(q->sender())) {
1535 emit q->hovered(action);
1536 }
1537}
1538
1540{
1541 Q_Q(QMenu);
1542
1543 emit q->aboutToShow();
1544
1545#ifdef Q_OS_MACOS
1546 if (platformMenu) {
1547 const auto actions = q->actions();
1548 for (QAction *action : actions) {
1549 if (QWidget *widget = widgetItems.value(action))
1550 if (widget->parent() == q) {
1551 QPlatformMenuItem *menuItem = platformMenu->menuItemForTag(reinterpret_cast<quintptr>(action));
1552 moveWidgetToPlatformItem(widget, menuItem);
1553 platformMenu->syncMenuItem(menuItem);
1554 }
1555 }
1556 }
1557#endif
1558}
1559
1561{
1562 //determines if the mouse has moved (ie its initial position has
1563 //changed by more than QApplication::startDragDistance()
1564 //or if there were at least 6 mouse motions)
1565 return motions > 6 ||
1566 QApplication::startDragDistance() < (mousePopupPos - globalPos).manhattanLength();
1567}
1568
1569
1578{
1579 if (!option || !action)
1580 return;
1581
1582 Q_D(const QMenu);
1583 option->initFrom(this);
1584 option->palette = palette();
1585 option->state = QStyle::State_None;
1586
1587 if (window()->isActiveWindow())
1588 option->state |= QStyle::State_Active;
1589 if (isEnabled() && action->isEnabled()
1590 && (!action->menu() || action->menu()->isEnabled()))
1591 option->state |= QStyle::State_Enabled;
1592 else
1593 option->palette.setCurrentColorGroup(QPalette::Disabled);
1594
1595 option->font = action->font().resolve(font());
1596 option->fontMetrics = QFontMetrics(option->font);
1597
1598 if (d->currentAction && d->currentAction == action && !d->currentAction->isSeparator()) {
1601 }
1602
1603 option->menuHasCheckableItems = d->hasCheckableItems;
1604 if (!action->isCheckable()) {
1606 } else {
1607 option->checkType = (action->actionGroup() && action->actionGroup()->isExclusive())
1609 option->checked = action->isChecked();
1610 }
1611 if (action->menu())
1612 option->menuItemType = QStyleOptionMenuItem::SubMenu;
1613 else if (action->isSeparator())
1615 else if (d->defaultAction == action)
1617 else
1618 option->menuItemType = QStyleOptionMenuItem::Normal;
1619 if (action->isIconVisibleInMenu())
1620 option->icon = action->icon();
1621 QString textAndAccel = action->text();
1622#ifndef QT_NO_SHORTCUT
1623 if ((action->isShortcutVisibleInContextMenu() || !d->isContextMenu())
1624 && textAndAccel.indexOf(u'\t') == -1) {
1625 QKeySequence seq = action->shortcut();
1626 if (!seq.isEmpty())
1627 textAndAccel += u'\t' + seq.toString(QKeySequence::NativeText);
1628 }
1629#endif
1630 option->text = textAndAccel;
1631 option->reservedShortcutWidth = d->tabWidth;
1632 option->maxIconWidth = d->maxIconWidth;
1633 option->menuRect = rect();
1634}
1635
1725 : QWidget(*new QMenuPrivate, parent, Qt::Popup)
1726{
1727 Q_D(QMenu);
1728 d->init();
1729}
1730
1741 : QMenu(parent)
1742{
1743 Q_D(QMenu);
1744 d->menuAction->setText(title);
1745}
1746
1750 : QWidget(dd, parent, Qt::Popup)
1751{
1752 Q_D(QMenu);
1753 d->init();
1754}
1755
1760{
1761 Q_D(QMenu);
1762 if (!d->widgetItems.isEmpty()) { // avoid detach on shared null hash
1763 QHash<QAction *, QWidget *>::iterator it = d->widgetItems.begin();
1764 for (; it != d->widgetItems.end(); ++it) {
1765 if (QWidget *widget = it.value()) {
1766 QWidgetAction *action = static_cast<QWidgetAction *>(it.key());
1767 action->releaseWidget(widget);
1768 *it = 0;
1769 }
1770 }
1771 }
1772
1773 if (d->eventLoop)
1774 d->eventLoop->exit();
1776}
1777
1778#if QT_DEPRECATED_SINCE(6, 4)
1785#if QT_CONFIG(shortcut)
1786QAction *QMenu::addAction(const QString &text, const QObject *receiver, const char* member, const QKeySequence &shortcut)
1787{
1788 return QWidget::addAction(text, shortcut, receiver, member);
1789}
1790#endif
1791
1835#if QT_CONFIG(shortcut)
1836QAction *QMenu::addAction(const QIcon &icon, const QString &text, const QObject *receiver,
1837 const char* member, const QKeySequence &shortcut)
1838{
1839 QAction *action = new QAction(icon, text, this);
1840 action->setShortcut(shortcut);
1841 QObject::connect(action, SIGNAL(triggered(bool)), receiver, member);
1842 addAction(action);
1843 return action;
1844}
1845#endif
1846#endif // QT_DEPRECATED_SINCE(6, 4)
1847
1856{
1857 QAction *action = menu->menuAction();
1858 addAction(action);
1859 return action;
1860}
1861
1869{
1870 QMenu *menu = new QMenu(title, this);
1872 return menu;
1873}
1874
1882{
1883 QMenu *menu = new QMenu(title, this);
1884 menu->setIcon(icon);
1886 return menu;
1887}
1888
1900{
1901 QAction *action = new QAction(this);
1902 action->setSeparator(true);
1903 addAction(action);
1904 return action;
1905}
1906
1924{
1925 QAction *action = new QAction(text, this);
1926 action->setSeparator(true);
1927 addAction(action);
1928 return action;
1929}
1930
1948{
1949 QAction *action = new QAction(icon, text, this);
1950 action->setSeparator(true);
1951 addAction(action);
1952 return action;
1953}
1954
1962{
1963 QAction *action = menu->menuAction();
1964 insertAction(before, action);
1965 return action;
1966}
1967
1979{
1980 QAction *action = new QAction(this);
1981 action->setSeparator(true);
1982 insertAction(before, action);
1983 return action;
1984}
1985
2004{
2005 QAction *action = new QAction(text, this);
2006 action->setSeparator(true);
2007 insertAction(before, action);
2008 return action;
2009}
2010
2028{
2029 QAction *action = new QAction(icon, text, this);
2030 action->setSeparator(true);
2031 insertAction(before, action);
2032 return action;
2033}
2034
2043{
2044 d_func()->defaultAction = act;
2045}
2046
2053{
2054 return d_func()->defaultAction;
2055}
2056
2071{
2072 Q_D(QMenu);
2073 if (d->tearoff == b)
2074 return;
2075 if (!b)
2077 d->tearoff = b;
2078
2079 d->itemsDirty = true;
2080 if (isVisible())
2081 resize(sizeHint());
2082}
2083
2085{
2086 return d_func()->tearoff;
2087}
2088
2097{
2098 if (d_func()->tornPopup)
2099 return d_func()->tornPopup->isVisible();
2100 return false;
2101}
2102
2112{
2113 Q_D(QMenu);
2114 if (!d->tornPopup)
2115 d->tornPopup = new QTornOffMenu(this);
2116 const QSize &s = sizeHint();
2117 d->tornPopup->setGeometry(pos.x(), pos.y(), s.width(), s.height());
2118 d->tornPopup->show();
2119}
2120
2131{
2133}
2134
2142{
2143 Q_D(QMenu);
2144 if (d->tornPopup) {
2145 d->tornPopup->close();
2146 // QTornOffMenu sets WA_DeleteOnClose, so we
2147 // should consider the torn-off menu deleted.
2148 // This way showTearOffMenu() will not try to
2149 // reuse the dying torn-off menu.
2150 d->tornPopup = nullptr;
2151 }
2152}
2153
2154
2159{
2160 Q_D(QMenu);
2161 d->setCurrentAction(act, 0);
2162 if (d->scroll && act)
2164}
2165
2166
2172{
2173 return d_func()->currentAction;
2174}
2175
2185bool QMenu::isEmpty() const
2186{
2187 bool ret = true;
2188 for(int i = 0; ret && i < actions().size(); ++i) {
2189 const QAction *action = actions().at(i);
2190 if (!action->isSeparator() && action->isVisible()) {
2191 ret = false;
2192 }
2193 }
2194 return ret;
2195}
2196
2204{
2205 QList<QAction*> acts = actions();
2206
2207 for(int i = 0; i < acts.size(); i++) {
2208 removeAction(acts[i]);
2209 if (acts[i]->parent() == this && acts[i]->d_func()->associatedObjects.isEmpty())
2210 delete acts[i];
2211 }
2212}
2213
2222{
2223 return d_func()->ncols;
2224}
2225
2230{
2231 if (QAction *ret = d_func()->actionAt(pt))
2232 return ret;
2233 return nullptr;
2234}
2235
2240{
2241 return d_func()->actionRect(act);
2242}
2243
2248{
2249 Q_D(const QMenu);
2250 d->updateActionRects();
2251
2252 QSize s;
2253 for (int i = 0; i < d->actionRects.size(); ++i) {
2254 const QRect &rect = d->actionRects.at(i);
2255 if (rect.isNull())
2256 continue;
2257 if (rect.bottom() >= s.height())
2258 s.setHeight(rect.y() + rect.height());
2259 if (rect.right() >= s.width())
2260 s.setWidth(rect.x() + rect.width());
2261 }
2262 // Note that the action rects calculated above already include
2263 // the top and left margins, so we only need to add margins for
2264 // the bottom and right.
2265 QStyleOption opt(0);
2266 opt.initFrom(this);
2267 const int fw = style()->pixelMetric(QStyle::PM_MenuPanelWidth, &opt, this);
2268 s.rwidth() += style()->pixelMetric(QStyle::PM_MenuHMargin, &opt, this) + fw + d->rightmargin;
2269 s.rheight() += style()->pixelMetric(QStyle::PM_MenuVMargin, &opt, this) + fw + d->bottommargin;
2270
2271 return style()->sizeFromContents(QStyle::CT_Menu, &opt, s, this);
2272}
2273
2288void QMenu::popup(const QPoint &p, QAction *atAction)
2289{
2290 Q_D(QMenu);
2291 d->popup(p, atAction);
2292}
2293
2294void QMenuPrivate::popup(const QPoint &p, QAction *atAction, PositionFunction positionFunction)
2295{
2296 Q_Q(QMenu);
2297 if (scroll) { // reset scroll state from last popup
2298 if (scroll->scrollOffset)
2299 itemsDirty = 1; // sizeHint will be incorrect if there is previous scroll
2300 scroll->scrollOffset = 0;
2302 }
2304 motions = 0;
2305 doChildEffects = true;
2307
2308 q->ensurePolished(); // Get the right font
2309
2310 // Ensure that we get correct sizeHints by placing this window on the correct screen.
2311 // However if the QMenu was constructed with a Qt::Desktop widget as its parent,
2312 // then initialScreenIndex was set, so we should respect that for the lifetime of this menu.
2313 // However if eventLoop exists, then exec() already did this by calling createWinId(); so leave it alone. (QTBUG-76162)
2314 if (!eventLoop) {
2315 bool screenSet = false;
2317 if (screen) {
2318 if (setScreen(screen))
2319 itemsDirty = true;
2320 screenSet = true;
2321 } else if (QMenu *parentMenu = qobject_cast<QMenu *>(parent)) {
2322 // a submenu is always opened from an open parent menu,
2323 // so show it on the same screen where the parent is. (QTBUG-76162)
2324 if (setScreen(parentMenu->screen()))
2325 itemsDirty = true;
2326 screenSet = true;
2327 }
2328 if (!screenSet && setScreenForPoint(p))
2329 itemsDirty = true;
2330 }
2331
2332 const bool contextMenu = isContextMenu();
2333 if (lastContextMenu != contextMenu) {
2334 itemsDirty = true;
2335 lastContextMenu = contextMenu;
2336 }
2337
2338 // Until QWidget::metric accepts the screen set on a widget (without having a window handle)
2339 // we need to make sure we get a window handle. This must be done near here because
2340 // we want the screen to be correctly set and items to be marked dirty.
2341 // (and screen set could 'fail' on oldscreen == newScreen if created before causing the
2342 // itemsDirty not to be set though needed to get the correct size on first show).
2343 if (!windowHandle()) {
2344 createWinId();
2345 }
2346
2347#if QT_CONFIG(menubar)
2348 // if this menu is part of a chain attached to a QMenuBar, set the
2349 // _NET_WM_WINDOW_TYPE_DROPDOWN_MENU X11 window type
2350 q->setAttribute(Qt::WA_X11NetWmWindowTypeDropDownMenu, qobject_cast<QMenuBar *>(topCausedWidget()) != nullptr);
2351#endif
2352
2353 emit q->aboutToShow();
2354 const bool actionListChanged = itemsDirty;
2355
2356 QRect screen;
2357#if QT_CONFIG(graphicsview)
2358 bool isEmbedded = !bypassGraphicsProxyWidget(q) && QMenuPrivate::nearestGraphicsProxyWidget(q);
2359 if (isEmbedded)
2361 else
2362#endif
2365
2366 QPoint pos;
2367 QPushButton *causedButton = qobject_cast<QPushButton*>(causedPopup.widget);
2368 if (actionListChanged && causedButton)
2369 pos = QPushButtonPrivate::get(causedButton)->adjustedMenuPosition();
2370 else
2371 pos = p;
2372
2373 const QSize menuSizeHint(q->sizeHint());
2374 QSize size = menuSizeHint;
2375
2376 if (positionFunction)
2377 pos = positionFunction(menuSizeHint);
2378
2379 const int desktopFrame = q->style()->pixelMetric(QStyle::PM_MenuDesktopFrameWidth, nullptr, q);
2380 bool adjustToDesktop = !q->window()->testAttribute(Qt::WA_DontShowOnScreen);
2381
2382 // if the screens have very different geometries and the menu is too big, we have to recalculate
2383 if ((size.height() > screen.height() || size.width() > screen.width()) ||
2384 // Layout is not right, we might be able to save horizontal space
2385 (ncols >1 && size.height() < screen.height())) {
2386 size.setWidth(qMin(menuSizeHint.width(), screen.width() - desktopFrame * 2));
2387 size.setHeight(qMin(menuSizeHint.height(), screen.height() - desktopFrame * 2));
2388 adjustToDesktop = true;
2389 }
2390
2391#ifdef QT_KEYPAD_NAVIGATION
2392 if (!atAction && QApplicationPrivate::keypadNavigationEnabled()) {
2393 // Try to have one item activated
2395 atAction = defaultAction;
2396 // TODO: This works for first level menus, not yet sub menus
2397 } else {
2398 for (QAction *action : std::as_const(actions))
2399 if (action->isEnabled()) {
2400 atAction = action;
2401 break;
2402 }
2403 }
2404 currentAction = atAction;
2405 }
2406#endif
2407 if (ncols > 1) {
2408 pos.setY(screen.top() + desktopFrame);
2409 } else if (atAction) {
2410 for (int i = 0, above_height = 0; i < actions.size(); i++) {
2411 QAction *action = actions.at(i);
2412 if (action == atAction) {
2413 int newY = pos.y() - above_height;
2414 if (scroll && newY < desktopFrame) {
2417 scroll->scrollOffset = newY;
2418 newY = desktopFrame;
2419 }
2420 pos.setY(newY);
2421
2423 && !q->style()->styleHint(QStyle::SH_Menu_FillScreenWithScroll, nullptr, q)) {
2424 int below_height = above_height + scroll->scrollOffset;
2425 for (int i2 = i; i2 < actionRects.size(); i2++)
2426 below_height += actionRects.at(i2).height();
2427 size.setHeight(below_height);
2428 }
2429 break;
2430 } else {
2431 above_height += actionRects.at(i).height();
2432 }
2433 }
2434 }
2435
2436 QPoint mouse = QCursor::pos();
2437 mousePopupPos = mouse;
2438 const bool snapToMouse = !causedPopup.widget && (QRect(p.x() - 3, p.y() - 3, 6, 6).contains(mouse));
2439
2440 if (adjustToDesktop) {
2441 // handle popup falling "off screen"
2442 if (q->isRightToLeft()) {
2443 if (snapToMouse) // position flowing left from the mouse
2444 pos.setX(mouse.x() - size.width());
2445
2446#if QT_CONFIG(menubar)
2447 // if the menu is in a menubar or is a submenu, it should be right-aligned
2448 if (qobject_cast<QMenuBar*>(causedPopup.widget) || qobject_cast<QMenu*>(causedPopup.widget))
2449 pos.rx() -= size.width();
2450#endif // QT_CONFIG(menubar)
2451
2452 if (pos.x() < screen.left() + desktopFrame)
2453 pos.setX(qMax(p.x(), screen.left() + desktopFrame));
2454 if (pos.x() + size.width() - 1 > screen.right() - desktopFrame)
2455 pos.setX(qMax(p.x() - size.width(), screen.right() - desktopFrame - size.width() + 1));
2456 } else {
2457 if (pos.x() + size.width() - 1 > screen.right() - desktopFrame)
2458 pos.setX(screen.right() - desktopFrame - size.width() + 1);
2459 if (pos.x() < screen.left() + desktopFrame)
2460 pos.setX(screen.left() + desktopFrame);
2461 }
2462 if (pos.y() + size.height() - 1 > screen.bottom() - desktopFrame) {
2463 if (snapToMouse)
2464 pos.setY(qMin(mouse.y() - (size.height() + desktopFrame), screen.bottom()-desktopFrame-size.height()+1));
2465 else
2466 pos.setY(qMax(p.y() - (size.height() + desktopFrame), screen.bottom()-desktopFrame-size.height()+1));
2467 }
2468
2469 if (pos.y() < screen.top() + desktopFrame)
2470 pos.setY(screen.top() + desktopFrame);
2471 if (pos.y() + menuSizeHint.height() - 1 > screen.bottom() - desktopFrame) {
2472 if (scroll) {
2474 int y = qMax(screen.y(),pos.y());
2475 size.setHeight(screen.bottom() - (desktopFrame * 2) - y);
2476 } else {
2477 // Too big for screen, bias to see bottom of menu (for some reason)
2478 pos.setY(screen.bottom() - size.height() + 1);
2479 }
2480 }
2481 }
2482 const int subMenuOffset = q->style()->pixelMetric(QStyle::PM_SubMenuOverlap, nullptr, q);
2483 QMenu *caused = qobject_cast<QMenu*>(causedPopup.widget);
2484 if (caused && caused->geometry().width() + menuSizeHint.width() + subMenuOffset < screen.width()) {
2485 QRect parentActionRect(caused->d_func()->actionRect(caused->d_func()->currentAction));
2486 const QPoint actionTopLeft = caused->mapToGlobal(parentActionRect.topLeft());
2487 parentActionRect.moveTopLeft(actionTopLeft);
2488 if (q->isRightToLeft()) {
2489 if ((pos.x() + menuSizeHint.width() > parentActionRect.left() - subMenuOffset)
2490 && (pos.x() < parentActionRect.right()))
2491 {
2492 pos.rx() = parentActionRect.left() - menuSizeHint.width();
2493 if (pos.x() < screen.x())
2494 pos.rx() = parentActionRect.right();
2495 if (pos.x() + menuSizeHint.width() > screen.x() + screen.width())
2496 pos.rx() = screen.x();
2497 }
2498 } else {
2499 if ((pos.x() < parentActionRect.right() + subMenuOffset)
2500 && (pos.x() + menuSizeHint.width() > parentActionRect.left()))
2501 {
2502 pos.rx() = parentActionRect.right();
2503 if (pos.x() + menuSizeHint.width() > screen.x() + screen.width())
2504 pos.rx() = parentActionRect.left() - menuSizeHint.width();
2505 if (pos.x() < screen.x())
2506 pos.rx() = screen.x() + screen.width() - menuSizeHint.width();
2507 }
2508 }
2509 }
2510 q->setGeometry(QRect(pos, size));
2511#if QT_CONFIG(effects)
2512 int hGuess = q->isRightToLeft() ? QEffects::LeftScroll : QEffects::RightScroll;
2513 int vGuess = QEffects::DownScroll;
2514 if (q->isRightToLeft()) {
2515 if ((snapToMouse && (pos.x() + size.width() / 2 > mouse.x())) ||
2516 (qobject_cast<QMenu*>(causedPopup.widget) && pos.x() + size.width() / 2 > causedPopup.widget->x()))
2517 hGuess = QEffects::RightScroll;
2518 } else {
2519 if ((snapToMouse && (pos.x() + size.width() / 2 < mouse.x())) ||
2520 (qobject_cast<QMenu*>(causedPopup.widget) && pos.x() + size.width() / 2 < causedPopup.widget->x()))
2521 hGuess = QEffects::LeftScroll;
2522 }
2523
2524#if QT_CONFIG(menubar)
2525 if ((snapToMouse && (pos.y() + size.height() / 2 < mouse.y())) ||
2526 (qobject_cast<QMenuBar*>(causedPopup.widget) &&
2527 pos.y() + size.width() / 2 < causedPopup.widget->mapToGlobal(causedPopup.widget->pos()).y()))
2528 vGuess = QEffects::UpScroll;
2529#endif
2531 bool doChildEffects = true;
2532#if QT_CONFIG(menubar)
2533 if (QMenuBar *mb = qobject_cast<QMenuBar*>(causedPopup.widget)) {
2534 doChildEffects = mb->d_func()->doChildEffects;
2535 mb->d_func()->doChildEffects = false;
2536 } else
2537#endif
2538 if (QMenu *m = qobject_cast<QMenu*>(causedPopup.widget)) {
2539 doChildEffects = m->d_func()->doChildEffects;
2540 m->d_func()->doChildEffects = false;
2541 }
2542
2543 if (doChildEffects) {
2545 qFadeEffect(q);
2546 else if (causedPopup.widget)
2547 qScrollEffect(q, qobject_cast<QMenu*>(causedPopup.widget) ? hGuess : vGuess);
2548 else
2549 qScrollEffect(q, hGuess | vGuess);
2550 } else {
2551 // kill any running effect
2552 qFadeEffect(nullptr);
2553 qScrollEffect(nullptr);
2554
2555 q->show();
2556 }
2557 } else
2558#endif
2559 {
2560 q->show();
2561 }
2562
2563#if QT_CONFIG(accessibility)
2564 QAccessibleEvent event(q, QAccessible::PopupMenuStart);
2565 QAccessible::updateAccessibility(&event);
2566#endif
2567}
2568
2587{
2588 return exec(pos());
2589}
2590
2591
2628{
2629 Q_D(QMenu);
2630 return d->exec(p, action);
2631}
2632
2633QAction *QMenuPrivate::exec(const QPoint &p, QAction *action, PositionFunction positionFunction)
2634{
2635 Q_Q(QMenu);
2636 q->ensurePolished();
2637 q->createWinId();
2638 QEventLoop evtLoop;
2639 eventLoop = &evtLoop;
2640 popup(p, action, positionFunction);
2641
2642 QPointer<QObject> guard = q;
2643 (void) evtLoop.exec();
2644 if (guard.isNull())
2645 return nullptr;
2646
2647 action = syncAction;
2648 syncAction = nullptr;
2649 eventLoop = nullptr;
2650 return action;
2651}
2652
2676{
2677 QMenu menu(parent);
2679 return menu.exec(pos, at);
2680}
2681
2686{
2687 Q_D(QMenu);
2688 emit aboutToHide();
2689 if (d->eventLoop)
2690 d->eventLoop->exit();
2691 d->setCurrentAction(nullptr);
2692#if QT_CONFIG(accessibility)
2693 QAccessibleEvent event(this, QAccessible::PopupMenuEnd);
2694 QAccessible::updateAccessibility(&event);
2695#endif
2696#if QT_CONFIG(menubar)
2697 if (QMenuBar *mb = qobject_cast<QMenuBar*>(d->causedPopup.widget))
2698 mb->d_func()->setCurrentAction(nullptr);
2699#endif
2700 if (QMenuPrivate::mouseDown == this)
2701 QMenuPrivate::mouseDown = nullptr;
2702 d->hasHadMouse = false;
2703 if (d->activeMenu)
2704 d->hideMenu(d->activeMenu);
2705 d->causedPopup.widget = nullptr;
2706 d->causedPopup.action = nullptr;
2707 if (d->scroll)
2708 d->scroll->scrollTimer.stop(); //make sure the timer stops
2709}
2710
2715{
2716 Q_D(QMenu);
2717 d->updateActionRects();
2718 QStylePainter p(this);
2719 QRegion emptyArea = QRegion(rect());
2720
2721 QStyleOptionMenuItem menuOpt;
2722 menuOpt.initFrom(this);
2723 menuOpt.state = QStyle::State_None;
2725 menuOpt.maxIconWidth = 0;
2726 menuOpt.reservedShortcutWidth = 0;
2727 p.drawPrimitive(QStyle::PE_PanelMenu, menuOpt);
2728
2729 //calculate the scroll up / down rect
2730 const int fw = style()->pixelMetric(QStyle::PM_MenuPanelWidth, nullptr, this);
2731 const int hmargin = style()->pixelMetric(QStyle::PM_MenuHMargin,nullptr, this);
2732 const int vmargin = style()->pixelMetric(QStyle::PM_MenuVMargin, nullptr, this);
2733
2734 QRect scrollUpRect, scrollDownRect;
2735 const int leftmargin = fw + hmargin + d->leftmargin;
2736 const int topmargin = fw + vmargin + d->topmargin;
2737 const int bottommargin = fw + vmargin + d->bottommargin;
2738 const int contentWidth = width() - (fw + hmargin) * 2 - d->leftmargin - d->rightmargin;
2739 if (d->scroll) {
2740 if (d->scroll->scrollFlags & QMenuPrivate::QMenuScroller::ScrollUp)
2741 scrollUpRect.setRect(leftmargin, topmargin, contentWidth, d->scrollerHeight());
2742
2743 if (d->scroll->scrollFlags & QMenuPrivate::QMenuScroller::ScrollDown)
2744 scrollDownRect.setRect(leftmargin, height() - d->scrollerHeight() - bottommargin,
2745 contentWidth, d->scrollerHeight());
2746 }
2747
2748 //calculate the tear off rect
2749 QRect tearOffRect;
2750 if (d->tearoff) {
2751 tearOffRect.setRect(leftmargin, topmargin, contentWidth,
2752 style()->pixelMetric(QStyle::PM_MenuTearoffHeight, nullptr, this));
2753 if (d->scroll && d->scroll->scrollFlags & QMenuPrivate::QMenuScroller::ScrollUp)
2754 tearOffRect.translate(0, d->scrollerHeight());
2755 }
2756
2757 //draw the items that need updating..
2758 QRect scrollUpTearOffRect = scrollUpRect.united(tearOffRect);
2759 for (int i = 0; i < d->actions.size(); ++i) {
2760 QAction *action = d->actions.at(i);
2761 QRect actionRect = d->actionRects.at(i);
2762 if (!e->rect().intersects(actionRect)
2763 || d->widgetItems.value(action))
2764 continue;
2765 //set the clip region to be extra safe (and adjust for the scrollers)
2766 emptyArea -= QRegion(actionRect);
2767
2768 QRect adjustedActionRect = actionRect;
2769 if (!scrollUpTearOffRect.isEmpty() && adjustedActionRect.bottom() <= scrollUpTearOffRect.top())
2770 continue;
2771
2772 if (!scrollDownRect.isEmpty() && adjustedActionRect.top() >= scrollDownRect.bottom())
2773 continue;
2774
2775 if (adjustedActionRect.intersects(scrollUpTearOffRect)) {
2776 if (adjustedActionRect.bottom() <= scrollUpTearOffRect.bottom())
2777 continue;
2778 else
2779 adjustedActionRect.setTop(scrollUpTearOffRect.bottom()+1);
2780 }
2781
2782 if (adjustedActionRect.intersects(scrollDownRect)) {
2783 if (adjustedActionRect.top() >= scrollDownRect.top())
2784 continue;
2785 else
2786 adjustedActionRect.setBottom(scrollDownRect.top()-1);
2787 }
2788
2789 QRegion adjustedActionReg(adjustedActionRect);
2790 p.setClipRegion(adjustedActionReg);
2791
2793 initStyleOption(&opt, action);
2794 opt.rect = actionRect;
2795 p.drawControl(QStyle::CE_MenuItem, opt);
2796 }
2797
2798 emptyArea -= QRegion(scrollUpTearOffRect);
2799 emptyArea -= QRegion(scrollDownRect);
2800
2801 if (d->scrollUpTearOffItem || d->scrollDownItem) {
2802 if (d->scrollUpTearOffItem)
2803 d->scrollUpTearOffItem->updateScrollerRects(scrollUpTearOffRect);
2804 if (d->scrollDownItem)
2805 d->scrollDownItem->updateScrollerRects(scrollDownRect);
2806 } else {
2807 //paint scroll up /down
2808 d->drawScroller(&p, QMenuPrivate::ScrollerTearOffItem::ScrollUp, scrollUpRect);
2809 d->drawScroller(&p, QMenuPrivate::ScrollerTearOffItem::ScrollDown, scrollDownRect);
2810 //paint the tear off..
2811 d->drawTearOff(&p, tearOffRect);
2812 }
2813
2814 //draw border
2815 if (fw) {
2816 QRegion borderReg;
2817 borderReg += QRect(0, 0, fw, height()); //left
2818 borderReg += QRect(width()-fw, 0, fw, height()); //right
2819 borderReg += QRect(0, 0, width(), fw); //top
2820 borderReg += QRect(0, height()-fw, width(), fw); //bottom
2821 p.setClipRegion(borderReg);
2822 emptyArea -= borderReg;
2824 frame.rect = rect();
2825 frame.palette = palette();
2826 frame.state = QStyle::State_None;
2828 frame.midLineWidth = 0;
2829 p.drawPrimitive(QStyle::PE_FrameMenu, frame);
2830 }
2831
2832 //finally the rest of the spaces
2833 p.setClipRegion(emptyArea);
2834 menuOpt.state = QStyle::State_None;
2837 menuOpt.rect = rect();
2838 menuOpt.menuRect = rect();
2839 p.drawControl(QStyle::CE_MenuEmptyArea, menuOpt);
2840}
2841
2842#if QT_CONFIG(wheelevent)
2846void QMenu::wheelEvent(QWheelEvent *e)
2847{
2848 Q_D(QMenu);
2849 if (d->scroll && rect().contains(e->position().toPoint()))
2850 d->scrollMenu(e->angleDelta().y() > 0 ?
2851 QMenuPrivate::QMenuScroller::ScrollUp : QMenuPrivate::QMenuScroller::ScrollDown);
2852}
2853#endif
2854
2859{
2860 Q_D(QMenu);
2861 if (d->aboutToHide || d->mouseEventTaken(e))
2862 return;
2863 // Workaround for XCB on multiple screens which doesn't have offset. If the menu is open on one screen
2864 // and mouse clicks on second screen, e->pos() is QPoint(0,0) and the menu doesn't hide. This trick makes
2865 // possible to hide the menu when mouse clicks on another screen (e->screenPos() returns correct value).
2866 // Only when mouse clicks in QPoint(0,0) on second screen, the menu doesn't hide.
2867 if ((e->position().toPoint().isNull() && !e->globalPosition().isNull()) || !rect().contains(e->position().toPoint())) {
2868 if (d->noReplayFor
2869 && QRect(d->noReplayFor->mapToGlobal(QPoint()), d->noReplayFor->size()).contains(e->globalPosition().toPoint()))
2871 if (d->eventLoop) // synchronous operation
2872 d->syncAction = nullptr;
2873 d->hideUpToMenuBar();
2874 return;
2875 }
2877
2878 QAction *action = d->actionAt(e->position().toPoint());
2879 d->setCurrentAction(action, 20);
2880 update();
2881}
2882
2887{
2888 Q_D(QMenu);
2889 if (d->aboutToHide || d->mouseEventTaken(e))
2890 return;
2891 if (QMenuPrivate::mouseDown != this) {
2892 QMenuPrivate::mouseDown = nullptr;
2893 return;
2894 }
2895
2896 QMenuPrivate::mouseDown = nullptr;
2897 d->setSyncAction();
2898 QAction *action = d->actionAt(e->position().toPoint());
2899
2900 if (action && action == d->currentAction) {
2901 if (!action->menu()) {
2902#if defined(Q_OS_WIN)
2903 //On Windows only context menus can be activated with the right button
2904 if (e->button() == Qt::LeftButton || d->topCausedWidget() == 0)
2905#endif
2906 d->activateAction(action, QAction::Trigger);
2907 }
2908 } else if ((!action || action->isEnabled()) && d->hasMouseMoved(e->globalPosition().toPoint())) {
2909 d->hideUpToMenuBar();
2910 }
2911}
2912
2917{
2918 Q_D(QMenu);
2919 if (e->type() == QEvent::StyleChange || e->type() == QEvent::FontChange ||
2920 e->type() == QEvent::LayoutDirectionChange) {
2921 d->itemsDirty = 1;
2922 setMouseTracking(style()->styleHint(QStyle::SH_Menu_MouseTracking, nullptr, this));
2923 if (isVisible())
2924 resize(sizeHint());
2925 if (!style()->styleHint(QStyle::SH_Menu_Scrollable, nullptr, this)) {
2926 delete d->scroll;
2927 d->scroll = nullptr;
2928 } else if (!d->scroll) {
2929 d->scroll = new QMenuPrivate::QMenuScroller;
2930 d->scroll->scrollFlags = QMenuPrivate::QMenuScroller::ScrollNone;
2931 }
2932 } else if (e->type() == QEvent::EnabledChange) {
2933 if (d->tornPopup) // torn-off menu
2934 d->tornPopup->setEnabled(isEnabled());
2935 d->menuAction->setEnabled(isEnabled());
2936 if (!d->platformMenu.isNull())
2937 d->platformMenu->setEnabled(isEnabled());
2938 }
2940}
2941
2942
2947{
2948 Q_D(QMenu);
2949 switch (e->type()) {
2950 case QEvent::Polish:
2951 d->updateLayoutDirection();
2952 break;
2954 QKeyEvent *kev = static_cast<QKeyEvent *>(e);
2955 if (kev->key() == Qt::Key_Up || kev->key() == Qt::Key_Down
2956 || kev->key() == Qt::Key_Left || kev->key() == Qt::Key_Right
2957 || kev->key() == Qt::Key_Enter || kev->key() == Qt::Key_Return
2958#ifndef QT_NO_SHORTCUT
2959 || kev->matches(QKeySequence::Cancel)
2960#endif
2961 ) {
2962 e->accept();
2963 return true;
2964 }
2965 }
2966 break;
2967 case QEvent::KeyPress: {
2968 QKeyEvent *ke = static_cast<QKeyEvent *>(e);
2969 if (ke->key() == Qt::Key_Tab || ke->key() == Qt::Key_Backtab) {
2970 keyPressEvent(ke);
2971 return true;
2972 }
2973 } break;
2975 case QEvent::ContextMenu: {
2976 bool canPopup = true;
2977 if (e->type() == QEvent::MouseButtonPress)
2978 canPopup = (static_cast<QMouseEvent*>(e)->button() == Qt::LeftButton);
2979 if (canPopup && d->delayState.timer.isActive()) {
2980 d->delayState.stop();
2981 internalDelayedPopup();
2982 }
2983 }
2984 break;
2985 case QEvent::Resize: {
2986 QStyleHintReturnMask menuMask;
2988 option.initFrom(this);
2989 if (style()->styleHint(QStyle::SH_Menu_Mask, &option, this, &menuMask)) {
2990 setMask(menuMask.region);
2991 }
2992 d->itemsDirty = 1;
2993 d->updateActionRects();
2994 break; }
2995 case QEvent::Show:
2996 QMenuPrivate::mouseDown = nullptr;
2997 d->updateActionRects();
2998 d->sloppyState.reset();
2999 if (d->currentAction)
3000 d->popupAction(d->currentAction, 0, false);
3001 if (isWindow() && window() && window()->windowHandle() && !window()->windowHandle()->transientParent())
3002 window()->windowHandle()->setTransientParent(d->transientParentWindow());
3003 break;
3004#if QT_CONFIG(tooltip)
3005 case QEvent::ToolTip:
3006 if (d->toolTipsVisible) {
3007 const QHelpEvent *ev = static_cast<const QHelpEvent*>(e);
3008 if (const QAction *action = actionAt(ev->pos())) {
3009 const QString toolTip = action->d_func()->tooltip;
3010 if (!toolTip.isEmpty())
3011 QToolTip::showText(ev->globalPos(), toolTip, this);
3012 else
3014 return true;
3015 }
3016 }
3017 break;
3018#endif // QT_CONFIG(tooltip)
3019#if QT_CONFIG(whatsthis)
3021 e->setAccepted(d->whatsThis.size());
3022 if (QAction *action = d->actionAt(static_cast<QHelpEvent*>(e)->pos())) {
3023 if (action->whatsThis().size() || action->menu())
3024 e->accept();
3025 }
3026 return true;
3027#endif
3028 default:
3029 break;
3030 }
3031 return QWidget::event(e);
3032}
3033
3038{
3039 setFocus();
3041 keyPressEvent(&ev);
3042 return true;
3043}
3044
3049{
3050 Q_D(QMenu);
3051 d->updateActionRects();
3052 int key = e->key();
3053 if (isRightToLeft()) { // in reverse mode open/close key for submenues are reversed
3054 if (key == Qt::Key_Left)
3056 else if (key == Qt::Key_Right)
3057 key = Qt::Key_Left;
3058 }
3059#ifndef Q_OS_MAC
3060 if (key == Qt::Key_Tab) //means down
3061 key = Qt::Key_Down;
3062 if (key == Qt::Key_Backtab) //means up
3063 key = Qt::Key_Up;
3064#endif
3065
3066 bool key_consumed = false;
3067 switch(key) {
3068 case Qt::Key_Home:
3069 key_consumed = true;
3070 if (d->scroll)
3071 d->scrollMenu(QMenuPrivate::QMenuScroller::ScrollTop, true);
3072 break;
3073 case Qt::Key_End:
3074 key_consumed = true;
3075 if (d->scroll)
3077 break;
3078 case Qt::Key_PageUp:
3079 key_consumed = true;
3080 if (d->currentAction && d->scroll) {
3081 if (d->scroll->scrollFlags & QMenuPrivate::QMenuScroller::ScrollUp)
3082 d->scrollMenu(QMenuPrivate::QMenuScroller::ScrollUp, true, true);
3083 else
3084 d->scrollMenu(QMenuPrivate::QMenuScroller::ScrollTop, true);
3085 }
3086 break;
3087 case Qt::Key_PageDown:
3088 key_consumed = true;
3089 if (d->currentAction && d->scroll) {
3090 if (d->scroll->scrollFlags & QMenuPrivate::QMenuScroller::ScrollDown)
3091 d->scrollMenu(QMenuPrivate::QMenuScroller::ScrollDown, true, true);
3092 else
3094 }
3095 break;
3096 case Qt::Key_Up:
3097 case Qt::Key_Down: {
3098 key_consumed = true;
3099 QAction *nextAction = nullptr;
3101 if (!d->currentAction) {
3102 if (key == Qt::Key_Down) {
3103 for(int i = 0; i < d->actions.size(); ++i) {
3104 QAction *act = d->actions.at(i);
3105 if (d->actionRects.at(i).isNull())
3106 continue;
3107 if (!act->isSeparator() &&
3108 (style()->styleHint(QStyle::SH_Menu_AllowActiveAndDisabled, nullptr, this)
3109 || act->isEnabled())) {
3110 nextAction = act;
3111 break;
3112 }
3113 }
3114 } else {
3115 for(int i = d->actions.size()-1; i >= 0; --i) {
3116 QAction *act = d->actions.at(i);
3117 if (d->actionRects.at(i).isNull())
3118 continue;
3119 if (!act->isSeparator() &&
3121 || act->isEnabled())) {
3122 nextAction = act;
3123 break;
3124 }
3125 }
3126 }
3127 } else {
3128 for(int i = 0, y = 0; !nextAction && i < d->actions.size(); i++) {
3129 QAction *act = d->actions.at(i);
3130 if (act == d->currentAction) {
3131 if (key == Qt::Key_Up) {
3132 for(int next_i = i-1; true; next_i--) {
3133 if (next_i == -1) {
3134 if (!style()->styleHint(QStyle::SH_Menu_SelectionWrap, nullptr, this))
3135 break;
3136 if (d->scroll)
3138 next_i = d->actionRects.size()-1;
3139 }
3140 QAction *next = d->actions.at(next_i);
3141 if (next == d->currentAction)
3142 break;
3143 if (d->actionRects.at(next_i).isNull())
3144 continue;
3145 if (next->isSeparator() ||
3146 (!next->isEnabled() &&
3148 continue;
3149 nextAction = next;
3150 if (d->scroll && (d->scroll->scrollFlags & QMenuPrivate::QMenuScroller::ScrollUp)) {
3151 int topVisible = d->scrollerHeight();
3152 if (d->tearoff)
3153 topVisible += style()->pixelMetric(QStyle::PM_MenuTearoffHeight, nullptr, this);
3154 if (((y + d->scroll->scrollOffset) - topVisible) <= d->actionRects.at(next_i).height())
3156 }
3157 break;
3158 }
3159 if (!nextAction && d->tearoff)
3160 d->tearoffHighlighted = 1;
3161 } else {
3162 y += d->actionRects.at(i).height();
3163 for(int next_i = i+1; true; next_i++) {
3164 if (next_i == d->actionRects.size()) {
3165 if (!style()->styleHint(QStyle::SH_Menu_SelectionWrap, nullptr, this))
3166 break;
3167 if (d->scroll)
3169 next_i = 0;
3170 }
3171 QAction *next = d->actions.at(next_i);
3172 if (next == d->currentAction)
3173 break;
3174 if (d->actionRects.at(next_i).isNull())
3175 continue;
3176 if (next->isSeparator() ||
3177 (!next->isEnabled() &&
3178 !style()->styleHint(QStyle::SH_Menu_AllowActiveAndDisabled, nullptr, this)))
3179 continue;
3180 nextAction = next;
3181 if (d->scroll && (d->scroll->scrollFlags & QMenuPrivate::QMenuScroller::ScrollDown)) {
3182 int bottomVisible = height() - d->scrollerHeight();
3183 if (d->scroll->scrollFlags & QMenuPrivate::QMenuScroller::ScrollUp)
3184 bottomVisible -= d->scrollerHeight();
3185 if (d->tearoff)
3186 bottomVisible -= style()->pixelMetric(QStyle::PM_MenuTearoffHeight, nullptr, this);
3187 if ((y + d->scroll->scrollOffset + d->actionRects.at(next_i).height()) > bottomVisible)
3189 }
3190 break;
3191 }
3192 }
3193 break;
3194 }
3195 y += d->actionRects.at(i).height();
3196 }
3197 }
3198 if (nextAction) {
3199 if (d->scroll && scroll_loc != QMenuPrivate::QMenuScroller::ScrollStay) {
3200 d->scroll->scrollTimer.stop();
3201 d->scrollMenu(nextAction, scroll_loc);
3202 }
3203 d->setCurrentAction(nextAction, /*popup*/-1, QMenuPrivate::SelectedFromKeyboard);
3204 }
3205 break; }
3206
3207 case Qt::Key_Right:
3208 if (d->currentAction && d->currentAction->isEnabled() && d->currentAction->menu()) {
3209 d->popupAction(d->currentAction, 0, true);
3210 key_consumed = true;
3211 break;
3212 }
3213 Q_FALLTHROUGH();
3214 case Qt::Key_Left: {
3215 if (d->currentAction && !d->scroll) {
3216 QAction *nextAction = nullptr;
3217 if (key == Qt::Key_Left) {
3218 QRect actionR = d->actionRect(d->currentAction);
3219 for(int x = actionR.left()-1; !nextAction && x >= 0; x--)
3220 nextAction = d->actionAt(QPoint(x, actionR.center().y()));
3221 } else {
3222 QRect actionR = d->actionRect(d->currentAction);
3223 for(int x = actionR.right()+1; !nextAction && x < width(); x++)
3224 nextAction = d->actionAt(QPoint(x, actionR.center().y()));
3225 }
3226 if (nextAction) {
3227 d->setCurrentAction(nextAction, /*popup*/-1, QMenuPrivate::SelectedFromKeyboard);
3228 key_consumed = true;
3229 }
3230 }
3231 if (!key_consumed && key == Qt::Key_Left && qobject_cast<QMenu*>(d->causedPopup.widget)) {
3232 QPointer<QWidget> caused = d->causedPopup.widget;
3233 d->hideMenu(this);
3234 if (caused)
3235 caused->setFocus();
3236 key_consumed = true;
3237 }
3238 break; }
3239
3240 case Qt::Key_Alt:
3241 if (d->tornoff)
3242 break;
3243
3244 key_consumed = true;
3246 {
3247 d->hideMenu(this);
3248#if QT_CONFIG(menubar)
3249 if (QMenuBar *mb = qobject_cast<QMenuBar*>(QApplication::focusWidget())) {
3250 mb->d_func()->setKeyboardMode(false);
3251 }
3252#endif
3253 }
3254 break;
3255
3256 case Qt::Key_Space:
3257 if (!style()->styleHint(QStyle::SH_Menu_SpaceActivatesItem, nullptr, this))
3258 break;
3259 // for motif, fall through
3260 Q_FALLTHROUGH();
3261#ifdef QT_KEYPAD_NAVIGATION
3262 case Qt::Key_Select:
3263#endif
3264 case Qt::Key_Return:
3265 case Qt::Key_Enter: {
3266 if (!d->currentAction) {
3267 d->setFirstActionActive();
3268 key_consumed = true;
3269 break;
3270 }
3271
3272 d->setSyncAction();
3273
3274 if (d->currentAction->menu())
3275 d->popupAction(d->currentAction, 0, true);
3276 else
3277 d->activateAction(d->currentAction, QAction::Trigger);
3278 key_consumed = true;
3279 break; }
3280
3281#if QT_CONFIG(whatsthis)
3282 case Qt::Key_F1:
3283 if (!d->currentAction || d->currentAction->whatsThis().isNull())
3284 break;
3286 d->activateAction(d->currentAction, QAction::Trigger);
3287 return;
3288#endif
3289 default:
3290 key_consumed = false;
3291 }
3292
3293 if (!key_consumed && (
3294 false
3295#ifndef QT_NO_SHORTCUT
3296 || e->matches(QKeySequence::Cancel)
3297#endif
3298#ifdef QT_KEYPAD_NAVIGATION
3299 || e->key() == Qt::Key_Back
3300#endif
3301 )) {
3302 key_consumed = true;
3303 if (d->tornoff) {
3304 close();
3305 return;
3306 }
3307 {
3308 QPointer<QWidget> caused = d->causedPopup.widget;
3309 d->hideMenu(this); // hide after getting causedPopup
3310#if QT_CONFIG(menubar)
3311 if (QMenuBar *mb = qobject_cast<QMenuBar*>(caused)) {
3312 mb->d_func()->setCurrentAction(d->menuAction);
3313 mb->d_func()->setKeyboardMode(true);
3314 }
3315#endif
3316 }
3317 }
3318
3319 if (!key_consumed) { // send to menu bar
3320 if ((!e->modifiers() || e->modifiers() == Qt::AltModifier || e->modifiers() == Qt::ShiftModifier) &&
3321 e->text().size()==1) {
3322 bool activateAction = false;
3323 QAction *nextAction = nullptr;
3324 if (style()->styleHint(QStyle::SH_Menu_KeyboardSearch, nullptr, this) && !e->modifiers()) {
3325 int best_match_count = 0;
3326 d->searchBufferTimer.start(2000, this);
3327 d->searchBuffer += e->text();
3328 for(int i = 0; i < d->actions.size(); ++i) {
3329 int match_count = 0;
3330 if (d->actionRects.at(i).isNull())
3331 continue;
3332 QAction *act = d->actions.at(i);
3333 const QString act_text = act->text();
3334 for(int c = 0; c < d->searchBuffer.size(); ++c) {
3335 if (act_text.indexOf(d->searchBuffer.at(c), 0, Qt::CaseInsensitive) != -1)
3336 ++match_count;
3337 }
3338 if (match_count > best_match_count) {
3339 best_match_count = match_count;
3340 nextAction = act;
3341 }
3342 }
3343 }
3344#ifndef QT_NO_SHORTCUT
3345 else {
3346 int clashCount = 0;
3347 QAction *first = nullptr, *currentSelected = nullptr, *firstAfterCurrent = nullptr;
3348 QChar c = e->text().at(0).toUpper();
3349 for(int i = 0; i < d->actions.size(); ++i) {
3350 if (d->actionRects.at(i).isNull())
3351 continue;
3352 QAction *act = d->actions.at(i);
3353 QKeySequence sequence = QKeySequence::mnemonic(act->text());
3354 int key = sequence[0].toCombined() & 0xffff; // suspicious
3355 if (key == c.unicode()) {
3356 clashCount++;
3357 if (!first)
3358 first = act;
3359 if (act == d->currentAction)
3360 currentSelected = act;
3361 else if (!firstAfterCurrent && currentSelected)
3362 firstAfterCurrent = act;
3363 }
3364 }
3365 if (clashCount == 1)
3366 activateAction = true;
3367 if (clashCount >= 1) {
3368 if (clashCount == 1 || !currentSelected || !firstAfterCurrent)
3369 nextAction = first;
3370 else
3371 nextAction = firstAfterCurrent;
3372 }
3373 }
3374#endif
3375 if (nextAction) {
3376 key_consumed = true;
3377 if (d->scroll)
3378 d->scrollMenu(nextAction, QMenuPrivate::QMenuScroller::ScrollCenter, false);
3379 d->setCurrentAction(nextAction, 0, QMenuPrivate::SelectedFromElsewhere, true);
3380 if (!nextAction->menu() && activateAction) {
3381 d->setSyncAction();
3382 d->activateAction(nextAction, QAction::Trigger);
3383 }
3384 }
3385 }
3386 if (!key_consumed) {
3387#if QT_CONFIG(menubar)
3388 if (QMenuBar *mb = qobject_cast<QMenuBar*>(d->topCausedWidget())) {
3389 QAction *oldAct = mb->d_func()->currentAction;
3391 if (mb->d_func()->currentAction != oldAct)
3392 key_consumed = true;
3393 }
3394#endif
3395 }
3396
3397#ifdef Q_OS_WIN32
3398 if (key_consumed && (e->key() == Qt::Key_Control || e->key() == Qt::Key_Shift || e->key() == Qt::Key_Meta))
3400#endif // Q_OS_WIN32
3401 }
3402 if (key_consumed)
3403 e->accept();
3404 else
3405 e->ignore();
3406}
3407
3412{
3413 Q_D(QMenu);
3414 if (!isVisible() || d->aboutToHide || d->mouseEventTaken(e))
3415 return;
3416
3417 d->motions++;
3418 if (!d->hasMouseMoved(e->globalPosition().toPoint()))
3419 return;
3420
3421 d->hasHadMouse = d->hasHadMouse || rect().contains(e->position().toPoint());
3422
3423 QAction *action = d->actionAt(e->position().toPoint());
3424 if ((!action || action->isSeparator()) && !d->sloppyState.enabled()) {
3425 if (d->hasHadMouse
3426 || (!d->currentAction || !d->currentAction->menu() || !d->currentAction->menu()->isVisible())) {
3427 d->setCurrentAction(action);
3428 }
3429 return;
3430 }
3431
3432 if (e->buttons())
3434
3435 if (d->activeMenu)
3436 d->activeMenu->d_func()->setCurrentAction(nullptr);
3437
3438 QMenuSloppyState::MouseEventResult sloppyEventResult = d->sloppyState.processMouseEvent(e->position(), action, d->currentAction);
3439 if (sloppyEventResult == QMenuSloppyState::EventShouldBePropagated) {
3440 d->setCurrentAction(action, d->mousePopupDelay);
3441 } else if (sloppyEventResult == QMenuSloppyState::EventDiscardsSloppyState) {
3442 d->sloppyState.reset();
3443 d->hideMenu(d->activeMenu);
3444 }
3445}
3446
3451{
3452 Q_D(QMenu);
3453 d->hasReceievedEnter = true;
3454 d->sloppyState.enter();
3455 d->motions = -1; // force us to ignore the generate mouse move in mouseMoveEvent()
3456}
3457
3462{
3463 Q_D(QMenu);
3464 d->hasReceievedEnter = false;
3465 if (!d->activeMenu && d->currentAction)
3466 setActiveAction(nullptr);
3467}
3468
3472void
3474{
3475 Q_D(QMenu);
3476 if (d->scroll && d->scroll->scrollTimer.timerId() == e->timerId()) {
3477 d->scrollMenu((QMenuPrivate::QMenuScroller::ScrollDirection)d->scroll->scrollDirection);
3478 if (d->scroll->scrollFlags == QMenuPrivate::QMenuScroller::ScrollNone)
3479 d->scroll->scrollTimer.stop();
3480 } else if (d->delayState.timer.timerId() == e->timerId()) {
3481 if (d->currentAction && !d->currentAction->menu())
3482 return;
3483 d->delayState.stop();
3484 d->sloppyState.stopTimer();
3485 internalDelayedPopup();
3486 } else if (d->sloppyState.isTimerId(e->timerId())) {
3487 d->sloppyState.timeout();
3488 } else if (d->searchBufferTimer.timerId() == e->timerId()) {
3489 d->searchBuffer.clear();
3490 }
3491}
3492
3497{
3498 Q_D(QMenu);
3499 d->itemsDirty = 1;
3501 if (d->tornPopup)
3502 d->tornPopup->syncWithMenu(this, e);
3503 if (e->type() == QEvent::ActionAdded) {
3504
3505 if (!d->tornoff
3506#if QT_CONFIG(menubar)
3507 && !qobject_cast<QMenuBar*>(e->action()->parent())
3508#endif
3509 ) {
3510 // Only connect if the action was not directly added by QMenuBar::addAction(const QString &text)
3511 // to avoid the signal being emitted twice
3512 connect(e->action(), SIGNAL(triggered()), this, SLOT(_q_actionTriggered()), Qt::UniqueConnection);
3513 connect(e->action(), SIGNAL(hovered()), this, SLOT(_q_actionHovered()), Qt::UniqueConnection);
3514 }
3515 if (QWidgetAction *wa = qobject_cast<QWidgetAction *>(e->action())) {
3516 QWidget *widget = wa->requestWidget(this);
3517 if (widget) {
3518 d->widgetItems.insert(wa, widget);
3519 if (d->scroll) {
3520 if (!d->scrollUpTearOffItem)
3521 d->scrollUpTearOffItem =
3523 if (!d->scrollDownItem)
3524 d->scrollDownItem =
3526 }
3527 }
3528 }
3529 } else if (e->type() == QEvent::ActionRemoved) {
3530 e->action()->disconnect(this);
3531 if (e->action() == d->currentAction)
3532 d->currentAction = nullptr;
3533 if (QWidgetAction *wa = qobject_cast<QWidgetAction *>(e->action())) {
3534 if (QWidget *widget = d->widgetItems.value(wa))
3535 wa->releaseWidget(widget);
3536 }
3537 d->widgetItems.remove(static_cast<QAction *>(e->action()));
3538 }
3539
3540 if (!d->platformMenu.isNull()) {
3541 auto action = static_cast<QAction *>(e->action());
3542 if (e->type() == QEvent::ActionAdded) {
3543 QPlatformMenuItem *beforeItem = e->before()
3544 ? d->platformMenu->menuItemForTag(reinterpret_cast<quintptr>(e->before()))
3545 : nullptr;
3546 d->insertActionInPlatformMenu(action, beforeItem);
3547 } else if (e->type() == QEvent::ActionRemoved) {
3548 QPlatformMenuItem *menuItem = d->platformMenu->menuItemForTag(reinterpret_cast<quintptr>(e->action()));
3549 d->platformMenu->removeMenuItem(menuItem);
3550 delete menuItem;
3551 } else if (e->type() == QEvent::ActionChanged) {
3552 QPlatformMenuItem *menuItem = d->platformMenu->menuItemForTag(reinterpret_cast<quintptr>(e->action()));
3553 if (menuItem) {
3554 d->copyActionToPlatformItem(action, menuItem);
3555 d->platformMenu->syncMenuItem(menuItem);
3556 }
3557 }
3558
3559 d->platformMenu->syncSeparatorsCollapsible(d->collapsibleSeparators);
3560 }
3561
3562 if (isVisible()) {
3563 resize(sizeHint());
3564 update();
3565 }
3566}
3567
3571void QMenu::internalDelayedPopup()
3572{
3573 Q_D(QMenu);
3574 //hide the current item
3575 if (QMenu *menu = d->activeMenu) {
3576 if (d->activeMenu->menuAction() != d->currentAction)
3577 d->hideMenu(menu);
3578 }
3579
3580 if (!d->currentAction || !d->currentAction->isEnabled() || !d->currentAction->menu() ||
3581 !d->currentAction->menu()->isEnabled() || d->currentAction->menu()->isVisible())
3582 return;
3583
3584 //setup
3585 d->activeMenu = d->currentAction->menu();
3586 d->activeMenu->d_func()->causedPopup.widget = this;
3587 d->activeMenu->d_func()->causedPopup.action = d->currentAction;
3588
3589 QRect screen;
3590#if QT_CONFIG(graphicsview)
3591 bool isEmbedded = !bypassGraphicsProxyWidget(this) && QMenuPrivate::nearestGraphicsProxyWidget(this);
3592 if (isEmbedded)
3593 screen = d->popupGeometry();
3594 else
3595#endif
3596 screen = d->popupGeometry(QGuiApplication::screenAt(pos()));
3597
3598 int subMenuOffset = style()->pixelMetric(QStyle::PM_SubMenuOverlap, nullptr, this);
3599 const QRect actionRect(d->actionRect(d->currentAction));
3600 QPoint subMenuPos(mapToGlobal(QPoint(actionRect.right() + subMenuOffset + 1, actionRect.top())));
3601 if (subMenuPos.x() > screen.right())
3602 subMenuPos.setX(geometry().left());
3603
3604 const auto &subMenuActions = d->activeMenu->actions();
3605 if (!subMenuActions.isEmpty()) {
3606 // Offset by the submenu's 1st action position to align with the current action
3607 const auto subMenuActionRect = d->activeMenu->actionGeometry(subMenuActions.first());
3608 subMenuPos.ry() -= subMenuActionRect.top();
3609 }
3610
3611 d->activeMenu->popup(subMenuPos);
3612 d->sloppyState.setSubMenuPopup(actionRect, d->currentAction, d->activeMenu);
3613
3614#if !defined(Q_OS_DARWIN)
3615 // Send the leave event to the current menu - only active popup menu gets
3616 // mouse enter/leave events. Currently Cocoa is an exception, so disable
3617 // it there to avoid event duplication.
3618 if (underMouse()) {
3621 }
3622#endif
3623}
3624
3676{
3677 d_func()->noReplayFor = noReplayFor;
3678}
3679
3683{
3684
3685 return d_func()->platformMenu;
3686}
3687
3691{
3692 d_func()->setPlatformMenu(platformMenu);
3693 d_func()->syncPlatformMenu();
3694}
3695
3709{
3710 Q_D(const QMenu);
3711 return d->collapsibleSeparators;
3712}
3713
3715{
3716 Q_D(QMenu);
3717 if (d->collapsibleSeparators == collapse)
3718 return;
3719
3720 d->collapsibleSeparators = collapse;
3721 d->itemsDirty = 1;
3722 if (isVisible()) {
3723 d->updateActionRects();
3724 update();
3725 }
3726 if (!d->platformMenu.isNull())
3727 d->platformMenu->syncSeparatorsCollapsible(collapse);
3728}
3729
3742{
3743 Q_D(const QMenu);
3744 return d->toolTipsVisible;
3745}
3746
3748{
3749 Q_D(QMenu);
3750 if (d->toolTipsVisible == visible)
3751 return;
3752
3753 d->toolTipsVisible = visible;
3754}
3755
3757
3758// for private slots
3759#include "moc_qmenu.cpp"
3760#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.
void start(int msec, QObject *obj)
\obsolete Use chrono overload instead.
void stop()
Stops the timer.
bool isActive() const noexcept
Returns true if the timer is running and has not been stopped; otherwise returns false.
Definition qbasictimer.h:34
\inmodule QtCore
Definition qchar.h:48
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:164
\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
@ 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
\reentrant \inmodule QtGui
int height() const
Returns the height of the font.
QRect boundingRect(QChar) const
Returns the rectangle that is covered by ink if character ch were to be drawn at the origin of the co...
int horizontalAdvance(const QString &, int len=-1) const
Returns the horizontal advance in pixels of the first len characters of text.
QFont resolve(const QFont &) const
Returns a new QFont that has attributes copied from other that have not been previously set on this f...
Definition qfont.cpp:1854
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:1093
T value(const Key &key) const noexcept
Definition qhash.h:1044
The QHelpEvent class provides an event that is used to request helpful information about a particular...
Definition qevent.h:787
const QPoint & globalPos() const
Returns the mouse cursor position when the event was generated in global coordinates.
Definition qevent.h:798
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:797
The QHideEvent class provides an event which is sent after a widget is hidden.
Definition qevent.h:585
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:973
The QKeyEvent class describes a key event.
Definition qevent.h:423
int key() const
Returns the code of the key that was pressed or released.
Definition qevent.h:433
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:74
qsizetype size() const noexcept
Definition qlist.h:386
bool isEmpty() const noexcept
Definition qlist.h:390
const_reference at(qsizetype i) const noexcept
Definition qlist.h:429
std::reverse_iterator< const_iterator > const_reverse_iterator
Definition qlist.h:253
reverse_iterator rend()
Definition qlist.h:618
reverse_iterator rbegin()
Definition qlist.h:617
void append(parameter_type t)
Definition qlist.h:441
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:1006
void updateScrollerRects(const QRect &rect)
Definition qmenu.cpp:1032
void paintEvent(QPaintEvent *e) override
This event handler can be reimplemented in a subclass to receive paint events passed in event.
Definition qmenu.cpp:1013
void updateLayoutDirection()
Definition qmenu.cpp:927
struct QMenuPrivate::QMenuScroller * scroll
QPointer< QPlatformMenu > platformMenu
Definition qmenu_p.h:440
quint8 ncols
Definition qmenu_p.h:472
QEventLoop * eventLoop
Definition qmenu_p.h:387
QList< QRect > actionRects
Definition qmenu_p.h:315
void _q_actionTriggered()
Definition qmenu.cpp:1499
void hideUpToMenuBar()
Definition qmenu.cpp:510
@ SelectedFromElsewhere
Definition qmenu_p.h:361
@ SelectedFromKeyboard
Definition qmenu_p.h:360
void scrollMenu(QMenuScroller::ScrollLocation location, bool active=false)
Definition qmenu.cpp:1215
int getLastVisibleAction() const
Definition qmenu.cpp:481
void popupAction(QAction *, int, bool)
Definition qmenu.cpp:625
void activateCausedStack(const QList< QPointer< QWidget > > &, QAction *, QAction::ActionEvent, bool)
Definition qmenu.cpp:1389
static QMenu * mouseDown
Definition qmenu_p.h:326
void popup(const QPoint &p, QAction *atAction, PositionFunction positionFunction={})
Definition qmenu.cpp:2294
std::function< QPoint(const QSize &)> PositionFunction
Definition qmenu_p.h:272
void updateActionRects() const
Definition qmenu.cpp:326
bool tearoffHighlighted
Definition qmenu_p.h:487
QPointer< QTornOffMenu > tornPopup
Definition qmenu_p.h:414
QPoint mousePopupPos
Definition qmenu_p.h:327
void setSyncAction()
Definition qmenu.cpp:644
int indexOf(QAction *act) const
Definition qmenu_p.h:411
QPointer< QAction > syncAction
Definition qmenu_p.h:388
void syncPlatformMenu()
Definition qmenu.cpp:204
bool lastContextMenu
Definition qmenu_p.h:476
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:662
void hideMenu(QMenu *menu)
Definition qmenu.cpp:538
void _q_overrideMenuActionDestroyed()
Definition qmenu.cpp:922
struct QMenuPrivate::DelayState delayState
bool mouseEventTaken(QMouseEvent *)
Definition qmenu.cpp:1300
bool isContextMenu() const
Definition qmenu.cpp:317
void _q_platformMenuAboutToShow()
Definition qmenu.cpp:1539
QPointer< QAction > defaultAction
Definition qmenu_p.h:419
virtual QList< QPointer< QWidget > > calcCausedStack() const
Definition qmenu.cpp:302
void drawScroller(QPainter *painter, ScrollerTearOffItem::Type type, const QRect &rect)
Definition qmenu.cpp:943
QRect actionRect(QAction *) const
Definition qmenu.cpp:498
QRect rect() const
Definition qmenu.cpp:993
bool useFullScreenForPopup() const
Definition qmenu.cpp:287
void activateAction(QAction *, QAction::ActionEvent, bool self=true)
Definition qmenu.cpp:1430
void copyActionToPlatformItem(const QAction *action, QPlatformMenuItem *item)
Definition qmenu.cpp:228
QMenuSloppyState sloppyState
Definition qmenu_p.h:416
QHash< QAction *, QWidget * > widgetItems
Definition qmenu_p.h:316
bool tearoff
Definition qmenu_p.h:485
bool itemsDirty
Definition qmenu_p.h:474
QPointer< QAction > actionAboutToTrigger
Definition qmenu_p.h:442
void setOverrideMenuAction(QAction *)
Definition qmenu.cpp:910
bool activationRecursionGuard
Definition qmenu_p.h:470
QAction * actionAt(QPoint p) const
Definition qmenu.cpp:898
QWidget * topCausedWidget() const
Definition qmenu.cpp:890
static QMenuPrivate * get(QMenu *m)
Definition qmenu_p.h:307
QWindow * transientParentWindow() const
Definition qmenu.cpp:602
void drawTearOff(QPainter *painter, const QRect &rect)
Definition qmenu.cpp:969
bool tornoff
Definition qmenu_p.h:486
QPointer< QMenu > activeMenu
Definition qmenu_p.h:395
QAction * currentAction
Definition qmenu_p.h:329
QAction * exec(const QPoint &p, QAction *action, PositionFunction positionFunction={})
Definition qmenu.cpp:2633
void setCurrentAction(QAction *, int popup=-1, SelectionReason reason=SelectedFromElsewhere, bool activateFirst=false)
Definition qmenu.cpp:686
void _q_actionHovered()
Definition qmenu.cpp:1531
QRect popupGeometry(QScreen *screen=nullptr) const
Definition qmenu.cpp:292
QMenuCaused causedPopup
Definition qmenu_p.h:404
bool doChildEffects
Definition qmenu_p.h:489
bool hasReceievedEnter
Definition qmenu_p.h:480
bool hasMouseMoved(const QPoint &globalPos)
Definition qmenu.cpp:1560
void setPlatformMenu(QPlatformMenu *menu)
Definition qmenu.cpp:191
void childEnter()
Definition qmenu.cpp:789
bool hasParentActiveDelayTimer() const
Definition qmenu.cpp:829
void childLeave()
Definition qmenu.cpp:805
@ EventDiscardsSloppyState
Definition qmenu_p.h:120
@ EventShouldBePropagated
Definition qmenu_p.h:119
void setSubMenuPopup(const QRect &actionRect, QAction *resetAction, QMenu *subMenu)
Definition qmenu.cpp:814
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:1961
bool isTearOffEnabled() const
Definition qmenu.cpp:2084
QMenu(QWidget *parent=nullptr)
Constructs a menu with parent parent.
Definition qmenu.cpp:1724
QString title
The title of the menu.
Definition qmenu.h:32
void changeEvent(QEvent *) override
\reimp
Definition qmenu.cpp:2916
bool isEmpty() const
Definition qmenu.cpp:2185
QAction * actionAt(const QPoint &) const
Returns the item at pt; returns \nullptr if there is no item there.
Definition qmenu.cpp:2229
bool toolTipsVisible
whether tooltips of menu actions should be visible
Definition qmenu.h:35
void timerEvent(QTimerEvent *) override
\reimp
Definition qmenu.cpp:3473
QAction * exec()
Executes this menu synchronously.
Definition qmenu.cpp:2586
void mouseMoveEvent(QMouseEvent *) override
\reimp
Definition qmenu.cpp:3411
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:2247
void triggered(QAction *action)
This signal is emitted when an action in this menu is triggered.
QPlatformMenu * platformMenu()
Definition qmenu.cpp:3682
void setTearOffEnabled(bool)
Definition qmenu.cpp:2070
QAction * insertSeparator(QAction *before)
This convenience function creates a new separator action, i.e.
Definition qmenu.cpp:1978
void mouseReleaseEvent(QMouseEvent *) override
\reimp
Definition qmenu.cpp:2886
int columnCount() const
If a menu does not fit on the screen it lays itself out so that it does fit.
Definition qmenu.cpp:2221
void setPlatformMenu(QPlatformMenu *platformMenu)
Definition qmenu.cpp:3690
void actionEvent(QActionEvent *) override
\reimp
Definition qmenu.cpp:3496
friend class QTornOffMenu
Definition qmenu.h:224
void setActiveAction(QAction *act)
Sets the currently highlighted action to act.
Definition qmenu.cpp:2158
void paintEvent(QPaintEvent *) override
\reimp
Definition qmenu.cpp:2714
void hideTearOffMenu()
This function will forcibly hide the torn off menu making it disappear from the user's desktop.
Definition qmenu.cpp:2141
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:2239
void clear()
Removes all the menu's actions.
Definition qmenu.cpp:2203
QIcon icon
The icon of the menu.
Definition qmenu.h:33
void setIcon(const QIcon &icon)
Definition qmenu.cpp:1094
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:2288
QAction * addSection(const QString &text)
Definition qmenu.cpp:1923
void hideEvent(QHideEvent *) override
\reimp
Definition qmenu.cpp:2685
void leaveEvent(QEvent *) override
\reimp
Definition qmenu.cpp:3461
bool separatorsCollapsible
whether consecutive separators should be collapsed
Definition qmenu.h:34
bool focusNextPrevChild(bool next) override
\reimp
Definition qmenu.cpp:3037
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:2096
bool event(QEvent *) override
\reimp
Definition qmenu.cpp:2946
~QMenu()
Destroys the menu.
Definition qmenu.cpp:1759
QAction * insertSection(QAction *before, const QString &text)
Definition qmenu.cpp:2003
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:1577
void enterEvent(QEnterEvent *) override
\reimp
Definition qmenu.cpp:3450
void showTearOffMenu()
This is an overloaded member function, provided for convenience. It differs from the above function o...
Definition qmenu.cpp:2130
QAction * defaultAction() const
Returns the current default action.
Definition qmenu.cpp:2052
QAction * addSeparator()
This convenience function creates a new separator action, i.e.
Definition qmenu.cpp:1899
void setTitle(const QString &title)
Definition qmenu.cpp:1075
QAction * addMenu(QMenu *menu)
This convenience function adds menu as a submenu to this menu.
Definition qmenu.cpp:1855
void keyPressEvent(QKeyEvent *) override
\reimp
Definition qmenu.cpp:3048
QAction * activeAction() const
Returns the currently highlighted action, or \nullptr if no action is currently highlighted.
Definition qmenu.cpp:2171
void setDefaultAction(QAction *)
This sets the default action to act.
Definition qmenu.cpp:2042
void setToolTipsVisible(bool visible)
Definition qmenu.cpp:3747
void addAction(QAction *action)
Appends the action action to this widget's list of actions.
Definition qwidget.cpp:3124
void setNoReplayFor(QWidget *widget)
Definition qmenu.cpp:3675
void setSeparatorsCollapsible(bool collapse)
Definition qmenu.cpp:3714
void mousePressEvent(QMouseEvent *) override
\reimp
Definition qmenu.cpp:2858
QAction * menuAction() const
Returns the action associated with this menu.
Definition qmenu.cpp:1047
\inmodule QtGui
Definition qevent.h:195
QObject * parent
Definition qobject.h:61
\inmodule QtCore
Definition qobject.h:90
QObject * parent() const
Returns a pointer to the parent object.
Definition qobject.h:311
static QMetaObject::Connection connect(const QObject *sender, const char *signal, const QObject *receiver, const char *member, Qt::ConnectionType=Qt::AutoConnection)
\threadsafe
Definition qobject.cpp:2823
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:1518
static bool disconnect(const QObject *sender, const char *signal, const QObject *receiver, const char *member)
\threadsafe
Definition qobject.cpp:3099
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:485
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:48
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:214
constexpr qreal y() const noexcept
Returns the y coordinate of this point.
Definition qpoint.h:338
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:394
\inmodule QtCore\reentrant
Definition qpoint.h:23
constexpr int x() const noexcept
Returns the x coordinate of this point.
Definition qpoint.h:127
constexpr int y() const noexcept
Returns the y coordinate of this point.
Definition qpoint.h:132
\inmodule QtCore
Definition qpointer.h:18
bool isNull() const
Returns true if the referenced object has been destroyed or if there is no referenced object; otherwi...
Definition qpointer.h:67
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:166
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:1065
constexpr void moveTopLeft(const QPoint &p) noexcept
Moves the rectangle, leaving the top-left corner at the given position.
Definition qrect.h:303
constexpr int height() const noexcept
Returns the height of the rectangle.
Definition qrect.h:238
constexpr bool isNull() const noexcept
Returns true if the rectangle is a null rectangle, otherwise returns false.
Definition qrect.h:163
constexpr int bottom() const noexcept
Returns the y-coordinate of the rectangle's bottom edge.
Definition qrect.h:181
constexpr QPoint topLeft() const noexcept
Returns the position of the rectangle's top-left corner.
Definition qrect.h:220
constexpr int top() const noexcept
Returns the y-coordinate of the rectangle's top edge.
Definition qrect.h:175
constexpr void setBottom(int pos) noexcept
Sets the bottom edge of the rectangle to the given y coordinate.
Definition qrect.h:199
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:851
constexpr int left() const noexcept
Returns the x-coordinate of the rectangle's left edge.
Definition qrect.h:172
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:345
constexpr int x() const noexcept
Returns the x-coordinate of the rectangle's left edge.
Definition qrect.h:184
constexpr void setWidth(int w) noexcept
Sets the width of the rectangle to the given width.
Definition qrect.h:380
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:244
constexpr int width() const noexcept
Returns the width of the rectangle.
Definition qrect.h:235
QRect united(const QRect &other) const noexcept
Definition qrect.h:419
constexpr int y() const noexcept
Returns the y-coordinate of the rectangle's top edge.
Definition qrect.h:187
constexpr void setHeight(int h) noexcept
Sets the height of the rectangle to the given height.
Definition qrect.h:383
constexpr void moveTop(int pos) noexcept
Moves the rectangle vertically, leaving the rectangle's top edge at the given y coordinate.
Definition qrect.h:288
constexpr QPoint center() const noexcept
Returns the center point of the rectangle.
Definition qrect.h:232
constexpr int right() const noexcept
Returns the x-coordinate of the rectangle's right edge.
Definition qrect.h:178
constexpr void setTop(int pos) noexcept
Sets the top edge of the rectangle to the given y coordinate.
Definition qrect.h:193
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
Exception-safe wrapper around QObject::blockSignals().
Definition qobject.h:443
void unblock() noexcept
Temporarily restores the QObject::signalsBlocked() state to what it was before this QSignalBlocker's ...
Definition qobject.h:514
\inmodule QtCore
Definition qsize.h:25
constexpr int height() const noexcept
Returns the height.
Definition qsize.h:132
constexpr int width() const noexcept
Returns the width.
Definition qsize.h:129
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:191
constexpr void setWidth(int w) noexcept
Sets the width to the given width.
Definition qsize.h:135
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:123
constexpr void setHeight(int h) noexcept
Sets the height to the given height.
Definition qsize.h:138
\macro QT_RESTRICTED_CAST_FROM_ASCII
Definition qstring.h:127
qsizetype size() const
Returns the number of characters in this string.
Definition qstring.h:182
bool isEmpty() const
Returns true if the string has no characters; otherwise returns false.
Definition qstring.h:1083
static QString static QString qsizetype indexOf(QChar c, qsizetype from=0, Qt::CaseSensitivity cs=Qt::CaseSensitive) const
Definition qstring.cpp:4420
QString trimmed() const &
Definition qstring.h:380
The QStyleHintReturnMask class provides style hints that return a QRegion.
\variable QStyleOptionFocusRect::backgroundColor
\variable QStyleOptionProgressBar::minimum
MenuItemType menuItemType
The QStyleOption class stores the parameters used by QStyle functions.
QFontMetrics fontMetrics
QStyle::State state
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:2421
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:555
@ CT_MenuItem
Definition qstyle.h:552
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:613
@ SH_Menu_Mask
Definition qstyle.h:663
@ SH_MenuBar_AltKeyNavigation
Definition qstyle.h:601
@ SH_Menu_MouseTracking
Definition qstyle.h:603
@ SH_Menu_FlashTriggeredItem
Definition qstyle.h:664
@ SH_Menu_SubMenuPopupDelay
Definition qstyle.h:599
@ SH_Menu_KeyboardSearch
Definition qstyle.h:649
@ SH_Menu_SupportsSections
Definition qstyle.h:680
@ SH_Menu_SelectionWrap
Definition qstyle.h:656
@ SH_Menu_AllowActiveAndDisabled
Definition qstyle.h:597
@ SH_Menu_FillScreenWithScroll
Definition qstyle.h:628
@ SH_Menu_FadeOutOnHide
Definition qstyle.h:665
@ SH_Menu_SpaceActivatesItem
Definition qstyle.h:598
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:493
@ PM_SubMenuOverlap
Definition qstyle.h:525
@ 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:359
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:427
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:2427
QList< QAction * > actions
Definition qwidget_p.h:701
bool setScreenForPoint(const QPoint &pos)
Definition qwidget.cpp:2412
short bottommargin
Definition qwidget_p.h:688
short rightmargin
Definition qwidget_p.h:687
void setVisible(bool)
Definition qwidget.cpp:8344
static QRect screenGeometry(const QWidget *widget)
Definition qwidget_p.h:463
QTLWExtra * topData() const
Definition qwidget_p.h:818
static QRect availableScreenGeometry(const QWidget *widget)
Definition qwidget_p.h:468
void createWinId()
Definition qwidget.cpp:2377
QWindow * windowHandle(WindowHandleMode mode=WindowHandleMode::Direct) const
Definition qwidget.cpp:1029
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:4320
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:7676
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:2637
QPointF mapToGlobal(const QPointF &) const
Translates the widget coordinate pos to global screen coordinates.
void setEnabled(bool)
Definition qwidget.cpp:3365
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:8608
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:3214
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:4886
void show()
Shows the widget and its child widgets.
Definition qwidget.cpp:7956
virtual void setVisible(bool visible)
Definition qwidget.cpp:8329
void insertAction(QAction *before, QAction *action)
Inserts the action action to this widget's list of actions, before the action before.
Definition qwidget.cpp:3149
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:2490
virtual void changeEvent(QEvent *)
This event handler can be reimplemented to handle state changes.
Definition qwidget.cpp:9428
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:3134
void setWindowTitle(const QString &)
Definition qwidget.cpp:6109
bool event(QEvent *event) override
This is the main event handler; it handles event event.
Definition qwidget.cpp:8912
QStyle * style() const
Definition qwidget.cpp:2607
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:2503
void setStyleSheet(const QString &styleSheet)
Definition qwidget.cpp:2562
void removeAction(QAction *action)
Removes the action action from this widget's list of actions.
Definition qwidget.cpp:3193
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:3124
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:837
bool * guard
Definition qmenu.cpp:851
QMenuSloppyState * toReset
Definition qmenu.cpp:850
QOpenGLWidget * widget
[1]
QString text
QPushButton * button
[2]
double e
QSet< QString >::iterator it
direction
QStyleOptionButton opt
short next
Definition keywords.cpp:445
Combined button and popup list for selecting options.
@ LeftButton
Definition qnamespace.h:57
@ WA_X11NetWmWindowTypePopupMenu
Definition qnamespace.h:393
@ WA_SetLayoutDirection
Definition qnamespace.h:322
@ WA_CustomWhatsThis
Definition qnamespace.h:312
@ WA_X11NetWmWindowTypeDropDownMenu
Definition qnamespace.h:392
@ WA_Resized
Definition qnamespace.h:307
@ WA_DontShowOnScreen
Definition qnamespace.h:382
@ WA_NoMouseReplay
Definition qnamespace.h:319
@ WA_X11NetWmWindowTypeMenu
Definition qnamespace.h:388
@ WA_DeleteOnClose
Definition qnamespace.h:320
@ NoFocus
Definition qnamespace.h:106
@ TextSingleLine
Definition qnamespace.h:169
@ TextShowMnemonic
Definition qnamespace.h:172
@ UI_FadeMenu
@ UI_AnimateMenu
@ Key_Tab
Definition qnamespace.h:659
@ Key_Select
@ Key_Shift
Definition qnamespace.h:678
@ Key_Return
Definition qnamespace.h:662
@ Key_Right
Definition qnamespace.h:674
@ Key_Enter
Definition qnamespace.h:663
@ Key_PageUp
Definition qnamespace.h:676
@ Key_Space
Definition qnamespace.h:512
@ Key_Backtab
Definition qnamespace.h:660
@ Key_Left
Definition qnamespace.h:672
@ Key_Control
Definition qnamespace.h:679
@ Key_Alt
Definition qnamespace.h:681
@ Key_Up
Definition qnamespace.h:673
@ Key_Down
Definition qnamespace.h:675
@ Key_Meta
Definition qnamespace.h:680
@ Key_F1
Definition qnamespace.h:685
@ Key_PageDown
Definition qnamespace.h:677
@ Key_Back
Definition qnamespace.h:841
@ Key_Home
Definition qnamespace.h:670
@ Key_End
Definition qnamespace.h:671
@ ShiftModifier
@ NoModifier
@ AltModifier
@ CaseInsensitive
@ QueuedConnection
@ UniqueConnection
@ Window
Definition qnamespace.h:206
@ Tool
Definition qnamespace.h:211
@ 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:524
void qFadeEffect(QWidget *w, int time)
Definition qeffects.cpp:546
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:51
#define SIGNAL(a)
Definition qobjectdefs.h:52
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]
GLboolean reset
const GLubyte * c
GLdouble GLdouble t
Definition qopenglext.h:243
GLdouble GLdouble GLdouble GLdouble q
Definition qopenglext.h:259
GLuint64EXT * result
[6]
GLdouble s
[6]
Definition qopenglext.h:235
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:72
ptrdiff_t qsizetype
Definition qtypes.h:70
unsigned int uint
Definition qtypes.h:29
static bool isEmbedded(const QWindow *w)
Definition qwidget.cpp:6637
QWidget * qobject_cast< QWidget * >(QObject *o)
Definition qwidget.h:786
static bool bypassGraphicsProxyWidget(const QWidget *p)
Definition qwidget_p.h:168
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
Q_GUI_EXPORT QPoint toPoint() const noexcept
qsizetype indexOf(const AT &t, qsizetype from=0) const noexcept
Definition qlist.h:955
bool contains(const AT &t) const noexcept
Definition qlist.h:44
QPointer< QWidget > widget
Definition qmenu_p.h:400
QPointer< QAction > action
Definition qmenu_p.h:401
QScreen * initialScreen
Definition qwidget_p.h:111
IUIAutomationTreeWalker __RPC__deref_out_opt IUIAutomationElement ** parent