8#include <private/qtquicktemplates2-config_p.h>
9#if QT_CONFIG(quicktemplates2_container)
10#include "qquickmenubaritem_p.h"
11#include "qquickmenubar_p_p.h"
21#include <QtCore/qloggingcategory.h>
22#include <QtGui/qevent.h>
23#include <QtGui/qcursor.h>
24#if QT_CONFIG(shortcut)
25#include <QtGui/qkeysequence.h>
27#include <QtGui/qpa/qplatformintegration.h>
28#include <QtGui/qpa/qplatformtheme.h>
29#include <QtGui/private/qhighdpiscaling_p.h>
30#include <QtGui/private/qguiapplication_p.h>
31#include <QtQml/qqmlcontext.h>
32#include <QtQml/qqmlcomponent.h>
33#include <QtQml/private/qqmlengine_p.h>
34#include <QtQml/private/qv4scopedvalue_p.h>
35#include <QtQml/private/qv4variantobject_p.h>
36#include <QtQml/private/qv4qobjectwrapper_p.h>
37#include <private/qqmlobjectmodel_p.h>
38#include <QtQuick/private/qquickitem_p.h>
39#include <QtQuick/private/qquickitemchangelistener_p.h>
40#include <QtQuick/private/qquickitemview_p_p.h>
41#include <QtQuick/private/qquickevents_p_p.h>
42#include <QtQuick/private/qquicklistview_p.h>
43#include <QtQuick/private/qquickrendercontrol_p.h>
44#include <QtQuick/private/qquickwindow_p.h>
48Q_STATIC_LOGGING_CATEGORY(lcMenu,
"qt.quick.controls.menu")
49Q_STATIC_LOGGING_CATEGORY(lcNativeMenus,
"qt.quick.controls.nativemenus")
52static const int SUBMENU_DELAY = 225;
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
253
254
255
256
257
258
259
260
261
262
263
264
265
266
273 return QGuiApplicationPrivate::platformIntegration()->hasCapability(QPlatformIntegration::MultipleWindows);
287QQuickMenuPrivate::QQuickMenuPrivate()
289 cascade = shouldCascade();
292void QQuickMenuPrivate::init()
295 contentModel =
new QQmlObjectModel(q);
298QQuickMenu *QQuickMenuPrivate::rootMenu()
const
300 Q_Q(
const QQuickMenu);
301 const QQuickMenu *rootMenu = q;
302 const QObject *p = q->parent();
304 if (
auto menu = qobject_cast<
const QQuickMenu *>(p))
309 return const_cast<QQuickMenu *>(rootMenu);
312QQuickPopup::PopupType QQuickMenuPrivate::resolvedPopupType()
const
316 QQuickMenu *root = rootMenu();
317 QQuickMenuPrivate *root_d = QQuickMenuPrivate::get(rootMenu());
319#if QT_CONFIG(quicktemplates2_container)
320 if (
auto menuBar = QQuickMenuPrivate::get(root)->menuBar.get()) {
325 if (QQuickMenuBarPrivate::get(menuBar)->useNativeMenu(q_func()))
326 return QQuickPopup::Native;
331 if (root_d->maybeNativeHandle()) {
332 return QQuickPopup::Native;
333 }
else if (!root_d->triedToCreateNativeMenu) {
339 if (root->popupType() == QQuickPopup::Native
340 && !QGuiApplication::testAttribute(Qt::AA_DontUseNativeMenuWindows)) {
341 return QQuickPopup::Native;
349 const auto type = root_d->QQuickPopupPrivate::resolvedPopupType();
350 Q_ASSERT(type != QQuickPopup::Native);
354bool QQuickMenuPrivate::useNativeMenu()
const
356 return resolvedPopupType() == QQuickPopup::Native;
359QPlatformMenu *QQuickMenuPrivate::nativeHandle()
361 Q_ASSERT(handle || useNativeMenu());
362 if (!handle && !triedToCreateNativeMenu)
367QPlatformMenu *QQuickMenuPrivate::maybeNativeHandle()
const
372bool QQuickMenuPrivate::createNativeMenu()
376 qCDebug(lcNativeMenus) <<
"createNativeMenu called on" << q;
378 if (
auto menuBar = QQuickMenuPrivate::get(rootMenu())->menuBar) {
379#if QT_CONFIG(quicktemplates2_container)
380 auto menuBarPrivate = QQuickMenuBarPrivate::get(menuBar);
381 if (menuBarPrivate->useNativeMenuBar()) {
382 qCDebug(lcNativeMenus) <<
"- creating native menu from native menubar";
383 if (QPlatformMenuBar *menuBarHandle = menuBarPrivate->nativeHandle())
384 handle.reset(menuBarHandle->createMenu());
390 QPlatformMenu *parentMenuHandle(parentMenu ? get(parentMenu)->handle.get() :
nullptr);
391 if (parentMenu && parentMenuHandle) {
392 qCDebug(lcNativeMenus) <<
"- creating native sub-menu";
393 handle.reset(parentMenuHandle->createSubMenu());
395 qCDebug(lcNativeMenus) <<
"- creating native menu";
396 handle.reset(QGuiApplicationPrivate::platformTheme()->createPlatformMenu());
400 triedToCreateNativeMenu =
true;
405 q->connect(handle.get(), &QPlatformMenu::aboutToShow, q, [q,
this](){
406 emit q->aboutToShow();
408 emit q->visibleChanged();
409 emit q->openedChanged();
412 q->connect(handle.get(), &QPlatformMenu::aboutToHide, q, [q](){
413 qCDebug(lcNativeMenus) <<
"QPlatformMenu::aboutToHide called; about to call setVisible(false) on Menu";
414 emit q->aboutToHide();
420 q->connect(handle.get(), &QPlatformMenu::aboutToHide, q, [q,
this](){
422 emit q->visibleChanged();
423 emit q->openedChanged();
425 }, Qt::QueuedConnection);
427 recursivelyCreateNativeMenuItems(q);
428 syncWithNativeMenu();
435 if (nativeItems.isEmpty())
436 return QStringLiteral(
"(Empty)");
439 QTextStream debug(&str);
440 for (
const auto *nativeItem : nativeItems)
441 debug << nativeItem->debugText() <<
", ";
443 if (!nativeItems.isEmpty())
448void QQuickMenuPrivate::syncWithNativeMenu()
451 if (!complete || !handle)
454 qCDebug(lcNativeMenus).nospace() <<
"syncWithNativeMenu called on " << q
455 <<
" (complete: " << complete <<
" visible: " << visible <<
") - "
456 <<
"syncing " << nativeItems.size() <<
" item(s)...";
460 handle->setText(title);
461 handle->setEnabled(q->isEnabled());
462 handle->setMinimumWidth(q->implicitWidth());
464 handle->setFont(q->font());
482 for (QQuickNativeMenuItem *item : std::as_const(nativeItems)) {
483 qCDebug(lcNativeMenus) <<
"- syncing" << item <<
"action" << item->action()
484 <<
"sub-menu" << item->subMenu() << item->debugText();
488 qCDebug(lcNativeMenus) <<
"... finished syncing" << q;
492
493
494
495
496
497
498
499void QQuickMenuPrivate::removeNativeMenu()
502 const int qtyItemsToRemove = nativeItems.size();
503 if (qtyItemsToRemove != 0)
504 Q_ASSERT(q->count() == qtyItemsToRemove);
505 for (
int i = 0; i < qtyItemsToRemove; ++i)
507 Q_ASSERT(nativeItems.isEmpty());
514void QQuickMenuPrivate::syncWithUseNativeMenu()
519 if (q->isVisible() || parentMenu)
522 if (maybeNativeHandle() && !useNativeMenu()) {
526 }
else if (useNativeMenu()) {
527 Q_ASSERT(nativeItems.isEmpty());
535 QQuickWindow *quickWindow = qobject_cast<QQuickWindow *>(window);
537 QWindow *renderWindow = QQuickRenderControl::renderWindowFor(quickWindow, offset);
544void QQuickMenuPrivate::setNativeMenuVisible(
bool visible)
547 qCDebug(lcNativeMenus) <<
"setNativeMenuVisible called with visible" << visible;
549 emit q->aboutToShow();
551 emit q->aboutToHide();
553 this->visible = visible;
554 syncWithNativeMenu();
558 QWindow *window =
nullptr;
560 window = effectiveWindow(parentItem->window(), &offset);
562 lastDevicePixelRatio = window ? window->devicePixelRatio() : qGuiApp->devicePixelRatio();
564 const QPointF globalPos = parentItem->mapToGlobal(x, y);
565 const QPoint windowPos = window ? window->mapFromGlobal(globalPos.toPoint()) : parentItem->mapToScene(QPoint(x, y)).toPoint();
566 QRect targetRect(windowPos, QSize(0, 0));
567 auto *daPriv = QQuickItemPrivate::get(parentItem)->deliveryAgentPrivate();
574 if (QPointerEvent *openingEvent = daPriv->eventInDelivery()) {
575 auto *devPriv = QPointingDevicePrivate::get(
const_cast<QPointingDevice *>(openingEvent->pointingDevice()));
576 for (
const auto &pt : std::as_const(openingEvent->points())) {
577 qCDebug(lcNativeMenus) <<
"popup over" << window <<
"its DA" << daPriv->q_func() <<
"opening due to" << openingEvent
578 <<
"with grabbers" << openingEvent->exclusiveGrabber(pt) << openingEvent->passiveGrabbers(pt);
580 if (
auto *opener = openingEvent->exclusiveGrabber(pt))
581 devPriv->removeGrabber(opener,
true);
582 for (
auto passiveGrabber : openingEvent->passiveGrabbers(pt)) {
583 if (
auto *opener = passiveGrabber.get())
584 devPriv->removeGrabber(opener,
true);
588 handle->showPopup(window, QHighDpi::toNativeLocalPosition(targetRect, window),
596void QQuickMenuPrivate::makeEditMenu()
598 handle->setMenuType(QPlatformMenu::EditMenu);
601QQuickItem *QQuickMenuPrivate::itemAt(
int index)
const
603 return qobject_cast<QQuickItem *>(contentModel->get(index));
606void QQuickMenuPrivate::insertItem(
int index, QQuickItem *item)
608 qCDebug(lcMenu) <<
"insert called with index" << index <<
"item" << item;
611 contentData.append(item);
612 item->setParentItem(contentItem);
613 QQuickItemPrivate::get(item)->setCulled(
true);
616 QQuickItemPrivate::get(item)->addItemChangeListener(
this, QQuickItemPrivate::Destroyed | QQuickItemPrivate::Parent);
617 QQuickItemPrivate::get(item)->updateOrAddGeometryChangeListener(
this, QQuickGeometryChange::Width);
618 contentModel->insert(index, item);
620 QQuickMenuItem *menuItem = qobject_cast<QQuickMenuItem *>(item);
622 QQuickMenuItemPrivate::get(menuItem)->setMenu(q);
623 if (QQuickMenu *subMenu = menuItem->subMenu())
624 QQuickMenuPrivate::get(subMenu)->setParentMenu(q);
625 QObjectPrivate::connect(menuItem, &QQuickMenuItem::triggered,
this, &QQuickMenuPrivate::onItemTriggered);
626 QObjectPrivate::connect(menuItem, &QQuickMenuItem::implicitTextPaddingChanged,
this, &QQuickMenuPrivate::updateTextPadding);
627 QObjectPrivate::connect(menuItem, &QQuickMenuItem::visibleChanged,
this, &QQuickMenuPrivate::updateTextPadding);
628 QObjectPrivate::connect(menuItem, &QQuickItem::activeFocusChanged,
this, &QQuickMenuPrivate::onItemActiveFocusChanged);
629 QObjectPrivate::connect(menuItem, &QQuickControl::hoveredChanged,
this, &QQuickMenuPrivate::onItemHovered);
632 if (maybeNativeHandle() && complete)
633 maybeCreateAndInsertNativeItem(index, item);
635 if (lcMenu().isDebugEnabled())
636 printContentModelItems();
641void QQuickMenuPrivate::maybeCreateAndInsertNativeItem(
int index, QQuickItem *item)
645 Q_ASSERT_X(handle, Q_FUNC_INFO, qPrintable(QString::fromLatin1(
646 "Expected %1 to be using a native menu").arg(QDebug::toString(q))));
647 std::unique_ptr<QQuickNativeMenuItem> nativeMenuItem(QQuickNativeMenuItem::createFromNonNativeItem(q, item));
648 if (!nativeMenuItem) {
650 qmlWarning(q) <<
"Native menu failed to create a native menu item for item at index" << index;
654 nativeItems.insert(index, nativeMenuItem.get());
658 if (nativeMenuItem->handle()) {
659 QQuickNativeMenuItem *before = nativeItems.value(index + 1);
660 handle->insertMenuItem(nativeMenuItem->handle(), before ? before->handle() :
nullptr);
661 qCDebug(lcNativeMenus) <<
"inserted native menu item at index" << index
662 <<
"before" << (before ? before->debugText() : QStringLiteral(
"null"));
664 if (nativeMenuItem->subMenu() && QQuickMenuPrivate::get(nativeMenuItem->subMenu())->nativeItems.count()
665 < nativeMenuItem->subMenu()->count()) {
671 recursivelyCreateNativeMenuItems(nativeMenuItem->subMenu());
675 nativeMenuItem.release();
677 qCDebug(lcNativeMenus) <<
"nativeItems now contains the following items:"
678 << nativeMenuItemListToString(nativeItems);
681void QQuickMenuPrivate::moveItem(
int from,
int to)
683 contentModel->move(from, to);
685 if (maybeNativeHandle())
686 nativeItems.move(from, to);
690
691
692
693
694
695
696
697
698
699void QQuickMenuPrivate::removeItem(
int index, QQuickItem *item, DestructionPolicy destructionPolicy)
701 qCDebug(lcMenu) <<
"removeItem called with index" << index <<
"item" << item;
703 if (maybeNativeHandle())
704 removeNativeItem(index);
706 contentData.removeOne(item);
708 QQuickItemPrivate::get(item)->removeItemChangeListener(
this, QQuickItemPrivate::Destroyed | QQuickItemPrivate::Parent);
709 QQuickItemPrivate::get(item)->removeItemChangeListener(
this, QQuickItemPrivate::Geometry);
710 item->setParentItem(
nullptr);
711 contentModel->remove(index);
713 QQuickMenuItem *menuItem = qobject_cast<QQuickMenuItem *>(item);
715 QQuickMenuItemPrivate::get(menuItem)->setMenu(
nullptr);
716 if (QQuickMenu *subMenu = menuItem->subMenu())
717 QQuickMenuPrivate::get(subMenu)->setParentMenu(
nullptr);
718 QObjectPrivate::disconnect(menuItem, &QQuickMenuItem::triggered,
this, &QQuickMenuPrivate::onItemTriggered);
719 QObjectPrivate::disconnect(menuItem, &QQuickMenuItem::implicitTextPaddingChanged,
this, &QQuickMenuPrivate::updateTextPadding);
720 QObjectPrivate::disconnect(menuItem, &QQuickMenuItem::visibleChanged,
this, &QQuickMenuPrivate::updateTextPadding);
721 QObjectPrivate::disconnect(menuItem, &QQuickItem::activeFocusChanged,
this, &QQuickMenuPrivate::onItemActiveFocusChanged);
722 QObjectPrivate::disconnect(menuItem, &QQuickControl::hoveredChanged,
this, &QQuickMenuPrivate::onItemHovered);
725 if (destructionPolicy == DestructionPolicy::Destroy)
728 if (lcMenu().isDebugEnabled())
729 printContentModelItems();
733
734
735
736
737
738
739
740
741
742void QQuickMenuPrivate::removeNativeItem(
int index, SyncPolicy syncPolicy)
747 Q_ASSERT_X(index >= 0 && index < nativeItems.size(), Q_FUNC_INFO, qPrintable(QString::fromLatin1(
748 "index %1 is less than 0 or greater than or equal to %2").arg(index).arg(nativeItems.size())));
752 std::unique_ptr<QQuickNativeMenuItem> nativeItem(nativeItems.takeAt(index));
753 qCDebug(lcNativeMenus) <<
"removing native item" << nativeItem->debugText() <<
"at index" << index
754 <<
"from" << q_func() <<
"...";
755 QQuickMenu *subMenu = nativeItem->subMenu();
757 Q_ASSERT(nativeItem->handle());
758 auto *subMenuPrivate = QQuickMenuPrivate::get(subMenu);
759 while (!subMenuPrivate->nativeItems.isEmpty()) {
760 subMenuPrivate->removeNativeItem(0, SyncPolicy::DoNotSync);
764 Q_ASSERT(nativeItem->handle());
765 handle->removeMenuItem(nativeItem->handle());
766 if (syncPolicy == SyncPolicy::Sync)
767 syncWithNativeMenu();
770 auto *subMenuPrivate = QQuickMenuPrivate::get(subMenu);
776 subMenuPrivate->resetNativeData();
779 qCDebug(lcNativeMenus).nospace() <<
"... after removing item at index " << index
780 <<
", nativeItems now contains the following items: " << nativeMenuItemListToString(nativeItems);
783void QQuickMenuPrivate::resetNativeData()
785 qCDebug(lcNativeMenus) <<
"resetNativeData called on" << q_func();
787 triedToCreateNativeMenu =
false;
790void QQuickMenuPrivate::recursivelyCreateNativeMenuItems(QQuickMenu *menu)
792 auto *menuPrivate = QQuickMenuPrivate::get(menu);
795 if (!menuPrivate->triedToCreateNativeMenu)
796 menuPrivate->createNativeMenu();
798 const int qtyItemsToCreate = menuPrivate->contentModel->count();
799 if (menuPrivate->nativeItems.count() == qtyItemsToCreate)
802 qCDebug(lcNativeMenus) <<
"recursively creating" << qtyItemsToCreate <<
"menu item(s) for" << menu;
803 Q_ASSERT(menuPrivate->nativeItems.count() == 0);
804 for (
int i = 0; i < qtyItemsToCreate; ++i) {
805 QQuickItem *item = menu->itemAt(i);
806 menuPrivate->maybeCreateAndInsertNativeItem(i, item);
807 auto *menuItem = qobject_cast<QQuickMenuItem *>(item);
808 if (menuItem && menuItem->subMenu())
809 recursivelyCreateNativeMenuItems(menuItem->subMenu());
813void QQuickMenuPrivate::printContentModelItems()
const
815 qCDebug(lcMenu) <<
"contentModel now contains:";
816 for (
int i = 0; i < contentModel->count(); ++i)
817 qCDebug(lcMenu) <<
"-" << itemAt(i);
820QQuickItem *QQuickMenuPrivate::beginCreateItem()
826 QQmlContext *context = delegate->creationContext();
828 context = qmlContext(q);
830 QObject *object = delegate->beginCreate(context);
831 QQuickItem *item = qobject_cast<QQuickItem *>(object);
835 QQml_setParent_noEvent(item, q);
840void QQuickMenuPrivate::completeCreateItem()
845 delegate->completeCreate();
848QQuickItem *QQuickMenuPrivate::createItem(QQuickMenu *menu)
850 QQuickItem *item = beginCreateItem();
851 if (QQuickMenuItem *menuItem = qobject_cast<QQuickMenuItem *>(item))
852 QQuickMenuItemPrivate::get(menuItem)->setSubMenu(menu);
853 completeCreateItem();
857QQuickItem *QQuickMenuPrivate::createItem(QQuickAction *action)
859 QQuickItem *item = beginCreateItem();
860 if (QQuickAbstractButton *button = qobject_cast<QQuickAbstractButton *>(item))
861 button->setAction(action);
862 completeCreateItem();
866void QQuickMenuPrivate::resizeItem(QQuickItem *item)
868 if (!item || !contentItem)
871 QQuickItemPrivate *p = QQuickItemPrivate::get(item);
872 if (!p->widthValid()) {
873 item->setWidth(contentItem->width());
874 p->widthValidFlag =
false;
878void QQuickMenuPrivate::resizeItems()
883 for (
int i = 0; i < contentModel->count(); ++i)
884 resizeItem(itemAt(i));
887void QQuickMenuPrivate::itemChildAdded(QQuickItem *, QQuickItem *child)
890 if (!QQuickItemPrivate::get(child)->isTransparentForPositioner() && !contentData.contains(child))
891 insertItem(contentModel->count(), child);
894void QQuickMenuPrivate::itemParentChanged(QQuickItem *item, QQuickItem *parent)
898 removeItem(contentModel->indexOf(item,
nullptr), item);
901void QQuickMenuPrivate::itemSiblingOrderChanged(QQuickItem *)
905 QList<QQuickItem *> siblings = contentItem->childItems();
908 for (
int i = 0; i < siblings.size(); ++i) {
909 QQuickItem* sibling = siblings.at(i);
910 if (QQuickItemPrivate::get(sibling)->isTransparentForPositioner())
912 int index = contentModel->indexOf(sibling,
nullptr);
913 q->moveItem(index, to++);
917void QQuickMenuPrivate::itemDestroyed(QQuickItem *item)
919 if (item == contentItem) {
922 QQuickPopupPrivate::itemDestroyed(item);
924 int index = contentModel->indexOf(item,
nullptr);
926 removeItem(index, item);
931void QQuickMenuPrivate::itemGeometryChanged(QQuickItem *item, QQuickGeometryChange,
const QRectF &)
936 if (item == contentItem) {
947QQuickPopupPositioner *QQuickMenuPrivate::getPositioner()
951 positioner =
new QQuickMenuPositioner(q);
957 QQuickMenu *menu =
static_cast<QQuickMenu *>(popup());
958 QQuickMenuPrivate *menu_d = QQuickMenuPrivate::get(menu);
960 if (QQuickMenu *parentMenu = menu_d->parentMenu) {
961 if (menu_d->cascade) {
964 if (menu_d->popupItem->isMirrored()) {
965 const qreal distanceToFrame = parentMenu->leftPadding();
966 const qreal menuX = -menu->width() - distanceToFrame + menu->overlap();
967 menu->setPosition({menuX, -menu->topPadding()});
968 }
else if (menu_d->parentItem) {
969 const qreal distanceToFrame = parentMenu->rightPadding();
970 const qreal menuX = menu_d->parentItem->width() + distanceToFrame - menu->overlap();
971 menu->setPosition({menuX, -menu->topPadding()});
974 const qreal menuX = parentMenu->x() + (parentMenu->width() - menu->width()) / 2;
975 const qreal menuY = parentMenu->y() + (parentMenu->height() - menu->height()) / 2;
976 menu->setPosition({menuX, menuY});
980 QQuickPopupPositioner::reposition();
983bool QQuickMenuPrivate::prepareEnterTransition()
986 if (parentMenu && !cascade)
991 allowHorizontalFlip = cascade && parentMenu;
1003 auto *contentItemAsListView = qobject_cast<QQuickListView *>(contentItem);
1004 if (contentItemAsListView) {
1005 if (QQuickItemViewPrivate::get(contentItemAsListView)->currentChanges.hasPendingChanges())
1006 contentItemAsListView->forceLayout();
1009 if (!QQuickPopupPrivate::prepareEnterTransition())
1012 if (!hasClosePolicy) {
1013 if (cascade && parentMenu)
1014 closePolicy = cascadingSubMenuClosePolicy;
1016 q->resetClosePolicy();
1021bool QQuickMenuPrivate::prepareExitTransition()
1023 if (!QQuickPopupPrivate::prepareExitTransition())
1028 QQuickMenu *subMenu = currentSubMenu();
1030 QPointer<QQuickMenuItem> currentSubMenuItem = QQuickMenuPrivate::get(subMenu)->currentItem;
1032 subMenu = currentSubMenuItem ? currentSubMenuItem->subMenu() :
nullptr;
1037bool QQuickMenuPrivate::blockInput(QQuickItem *item,
const QPointF &point)
const
1040 return (cascade && parentMenu && contains(point)) || QQuickPopupPrivate::blockInput(item, point);
1043bool QQuickMenuPrivate::handlePress(QQuickItem *item,
const QPointF &point, ulong timestamp)
1047 return QQuickPopupPrivate::handlePress(item, point, timestamp)
1048 || (popupItem == item);
1053
1054
1055
1056
1057
1058
1059bool QQuickMenuPrivate::handleReleaseWithoutGrab(
const QEventPoint &eventPoint)
1061 const QPointF scenePos = eventPoint.scenePosition();
1062 if (!contains(scenePos))
1065 auto *list = qobject_cast<QQuickListView *>(contentItem);
1069 const QPointF listPos = list->mapFromScene(scenePos);
1071 auto *menuItem = qobject_cast<QQuickMenuItem *>(list->itemAt(listPos.x(), listPos.y()));
1072 if (menuItem && menuItem->isHighlighted()) {
1073 menuItem->animateClick();
1080void QQuickMenuPrivate::onItemHovered()
1083 QQuickAbstractButton *button = qobject_cast<QQuickAbstractButton *>(q->sender());
1084 if (!button || !button->isHovered() || !button->isEnabled() || QQuickAbstractButtonPrivate::get(button)->touchId != -1)
1087 QQuickMenuItem *oldCurrentItem = currentItem;
1089 int index = contentModel->indexOf(button,
nullptr);
1091 setCurrentIndex(index, Qt::OtherFocusReason);
1092 if (oldCurrentItem != currentItem) {
1093 if (oldCurrentItem) {
1094 QQuickMenu *subMenu = oldCurrentItem->subMenu();
1099 QQuickMenu *subMenu = currentItem->menu();
1100 if (subMenu && subMenu->cascade())
1107void QQuickMenuPrivate::onItemTriggered()
1110 QQuickMenuItem *item = qobject_cast<QQuickMenuItem *>(q->sender());
1114 if (QQuickMenu *subMenu = item->subMenu()) {
1115 auto subMenuPrivate = QQuickMenuPrivate::get(subMenu);
1116 subMenuPrivate->popup(subMenuPrivate->firstEnabledMenuItem());
1122void QQuickMenuPrivate::onItemActiveFocusChanged()
1125 QQuickItem *item = qobject_cast<QQuickItem*>(q->sender());
1126 if (!item->hasActiveFocus())
1129 int indexOfItem = contentModel->indexOf(item,
nullptr);
1130 QQuickControl *control = qobject_cast<QQuickControl *>(item);
1131 setCurrentIndex(indexOfItem, control ? control->focusReason() : Qt::OtherFocusReason);
1134void QQuickMenuPrivate::updateTextPadding()
1141 for (
int i = 0; i < q->count(); ++i) {
1142 if (
const auto menuItem = qobject_cast<QQuickMenuItem *>(itemAt(i)))
1143 if (menuItem->isVisible())
1144 padding = qMax(padding, menuItem->implicitTextPadding());
1147 if (padding == textPadding)
1150 textPadding = padding;
1152 for (
int i = 0; i < q->count(); ++i) {
1153 if (
const auto menuItem = qobject_cast<QQuickMenuItem *>(itemAt(i)))
1154 emit menuItem->textPaddingChanged();
1158QQuickMenu *QQuickMenuPrivate::currentSubMenu()
const
1163 return currentItem->subMenu();
1166void QQuickMenuPrivate::setParentMenu(QQuickMenu *parent)
1169 if (parentMenu == parent)
1173 QObject::disconnect(parentMenu.data(), &QQuickMenu::cascadeChanged, q, &QQuickMenu::setCascade);
1174 disconnect(parentMenu.data(), &QQuickMenu::parentChanged,
this, &QQuickMenuPrivate::resolveParentItem);
1177 QObject::connect(parent, &QQuickMenu::cascadeChanged, q, &QQuickMenu::setCascade);
1178 connect(parent, &QQuickMenu::parentChanged,
this, &QQuickMenuPrivate::resolveParentItem);
1181 parentMenu = parent;
1183 resolveParentItem();
1188 QQuickMenu *menu = QQuickMenuPrivate::get(subMenu)->parentMenu;
1189 for (
int i = 0; i < QQuickMenuPrivate::get(menu)->contentModel->count(); ++i) {
1190 QQuickMenuItem *item = qobject_cast<QQuickMenuItem *>(menu->itemAt(i));
1191 if (item && item->subMenu() == subMenu)
1197void QQuickMenuPrivate::resolveParentItem()
1201 q->resetParentItem();
1203 q->setParentItem(parentMenu->parentItem());
1205 q->setParentItem(findParentMenuItem(q));
1208void QQuickMenuPrivate::propagateKeyEvent(QKeyEvent *event)
1210 if (QQuickMenuItem *menuItem = qobject_cast<QQuickMenuItem *>(parentItem)) {
1211 if (QQuickMenu *menu = menuItem->menu())
1212 QQuickMenuPrivate::get(menu)->propagateKeyEvent(event);
1213#if QT_CONFIG(quicktemplates2_container)
1214 }
else if (QQuickMenuBarItem *menuBarItem = qobject_cast<QQuickMenuBarItem *>(parentItem)) {
1215 if (QQuickMenuBar *menuBar = menuBarItem->menuBar()) {
1217 QCoreApplication::sendEvent(menuBar, event);
1223void QQuickMenuPrivate::startHoverTimer()
1227 hoverTimer = q->startTimer(SUBMENU_DELAY);
1230void QQuickMenuPrivate::stopHoverTimer()
1236 q->killTimer(hoverTimer);
1240void QQuickMenuPrivate::setCurrentIndex(
int index, Qt::FocusReason reason)
1243 if (currentIndex == index)
1246 QQuickMenuItem *newCurrentItem = qobject_cast<QQuickMenuItem *>(itemAt(index));
1247 if (currentItem != newCurrentItem) {
1250 currentItem->setHighlighted(
false);
1251 if (!newCurrentItem && window) {
1252 QQuickItem *focusItem = QQuickItemPrivate::get(contentItem)->subFocusItem;
1254 auto *daPriv = QQuickWindowPrivate::get(window)->deliveryAgentPrivate();
1255 daPriv->clearFocusInScope(contentItem, focusItem, Qt::OtherFocusReason);
1259 if (newCurrentItem) {
1260 newCurrentItem->setHighlighted(
true);
1261 newCurrentItem->forceActiveFocus(reason);
1263 currentItem = newCurrentItem;
1266 currentIndex = index;
1267 emit q->currentIndexChanged();
1270bool QQuickMenuPrivate::activateNextItem()
1272 int index = currentIndex;
1273 int count = contentModel->count();
1274 while (++index < count) {
1275 QQuickItem *item = itemAt(index);
1276 if (!item || !item->activeFocusOnTab() || !item->isEnabled())
1278 setCurrentIndex(index, Qt::TabFocusReason);
1284bool QQuickMenuPrivate::activatePreviousItem()
1286 int index = currentIndex;
1287 while (--index >= 0) {
1288 QQuickItem *item = itemAt(index);
1289 if (!item || !item->activeFocusOnTab() || !item->isEnabled())
1291 setCurrentIndex(index, Qt::BacktabFocusReason);
1297QQuickMenuItem *QQuickMenuPrivate::firstEnabledMenuItem()
const
1299 for (
int i = 0; i < contentModel->count(); ++i) {
1300 QQuickItem *item = itemAt(i);
1301 if (!item || !item->isEnabled())
1304 QQuickMenuItem *menuItem = qobject_cast<QQuickMenuItem *>(item);
1313void QQuickMenuPrivate::contentData_append(QQmlListProperty<QObject> *prop, QObject *obj)
1315 QQuickMenu *q = qobject_cast<QQuickMenu *>(prop->object);
1316 QQuickMenuPrivate *p = QQuickMenuPrivate::get(q);
1318 QQuickItem *item = qobject_cast<QQuickItem *>(obj);
1320 if (QQuickAction *action = qobject_cast<QQuickAction *>(obj))
1321 item = p->createItem(action);
1322 else if (QQuickMenu *menu = qobject_cast<QQuickMenu *>(obj))
1323 item = p->createItem(menu);
1327 if (QQuickItemPrivate::get(item)->isTransparentForPositioner()) {
1328 QQuickItemPrivate::get(item)->addItemChangeListener(p, QQuickItemPrivate::SiblingOrder);
1329 item->setParentItem(p->contentItem);
1330 }
else if (p->contentModel->indexOf(item,
nullptr) == -1) {
1334 p->contentData.append(obj);
1338qsizetype QQuickMenuPrivate::contentData_count(QQmlListProperty<QObject> *prop)
1340 QQuickMenu *q =
static_cast<QQuickMenu *>(prop->object);
1341 return QQuickMenuPrivate::get(q)->contentData.size();
1344QObject *QQuickMenuPrivate::contentData_at(QQmlListProperty<QObject> *prop, qsizetype index)
1346 QQuickMenu *q =
static_cast<QQuickMenu *>(prop->object);
1347 return QQuickMenuPrivate::get(q)->contentData.value(index);
1350QPalette QQuickMenuPrivate::defaultPalette()
const
1352 return QQuickTheme::palette(QQuickTheme::Menu);
1355void QQuickMenuPrivate::contentData_clear(QQmlListProperty<QObject> *prop)
1357 QQuickMenu *q =
static_cast<QQuickMenu *>(prop->object);
1358 QQuickMenuPrivate::get(q)->contentData.clear();
1361void QQuickMenuPrivate::resetContentItem()
1364 QQuickItemPrivate::get(contentItem)->removeItemChangeListener(
this, QQuickItemPrivate::Children);
1365 QQuickItemPrivate::get(contentItem)->removeItemChangeListener(
this, QQuickItemPrivate::Destroyed);
1366 QQuickItemPrivate::get(contentItem)->removeItemChangeListener(
this, QQuickItemPrivate::Geometry);
1368 const auto children = contentItem->childItems();
1369 for (QQuickItem *child : std::as_const(children))
1370 QQuickItemPrivate::get(child)->removeItemChangeListener(
this, QQuickItemPrivate::SiblingOrder);
1371 contentItem =
nullptr;
1375QQuickMenu::QQuickMenu(QObject *parent)
1376 : QQuickPopup(*(
new QQuickMenuPrivate), parent)
1381 connect(d->contentModel, &QQmlObjectModel::countChanged,
this, &QQuickMenu::countChanged);
1384QQuickMenu::~QQuickMenu()
1387 qCDebug(lcNativeMenus) <<
"destroying" <<
this
1389 << d->contentModel->count()
1390 <<
"native item count:" << d->nativeItems.count();
1394 if (
auto *menuItem = qobject_cast<QQuickMenuItem *>(d->parentItem)) {
1395 if (menuItem->subMenu() ==
this) {
1396 auto *menuItemPriv = QQuickMenuItemPrivate::get(menuItem);
1397 menuItemPriv->setSubMenu(
nullptr);
1405 while (d->contentModel->count() > 0)
1406 d->removeItem(0, d->itemAt(0), QQuickMenuPrivate::DestructionPolicy::Destroy);
1408 d->resetContentItem();
1412
1413
1414
1415
1416QQuickItem *QQuickMenu::itemAt(
int index)
const
1418 Q_D(
const QQuickMenu);
1419 return d->itemAt(index);
1423
1424
1425
1426
1427
1428
1429
1430void QQuickMenu::addItem(QQuickItem *item)
1433 insertItem(d->contentModel->count(), item);
1437
1438
1439
1440
1441
1442
1443
1444void QQuickMenu::insertItem(
int index, QQuickItem *item)
1449 const int count = d->contentModel->count();
1450 if (index < 0 || index > count)
1453 int oldIndex = d->contentModel->indexOf(item,
nullptr);
1454 if (oldIndex != -1) {
1455 if (oldIndex < index)
1457 if (oldIndex != index) {
1458 d->moveItem(oldIndex, index);
1461 d->insertItem(index, item);
1466
1467
1468
1469
1470void QQuickMenu::moveItem(
int from,
int to)
1473 const int count = d->contentModel->count();
1474 if (from < 0 || from > count - 1)
1476 if (to < 0 || to > count - 1)
1480 d->moveItem(from, to);
1484
1485
1486
1487
1488
1489void QQuickMenu::removeItem(QQuickItem *item)
1495 const int index = d->contentModel->indexOf(item,
nullptr);
1499 d->removeItem(index, item, QQuickMenuPrivate::DestructionPolicy::Destroy);
1503
1504
1505
1506
1507
1508
1509
1510QQuickItem *QQuickMenu::takeItem(
int index)
1513 const int count = d->contentModel->count();
1514 if (index < 0 || index >= count)
1517 QQuickItem *item = itemAt(index);
1519 d->removeItem(index, item);
1524
1525
1526
1527
1528
1529
1530QQuickMenu *QQuickMenu::menuAt(
int index)
const
1532 Q_D(
const QQuickMenu);
1533 QQuickMenuItem *item = qobject_cast<QQuickMenuItem *>(d->itemAt(index));
1537 return item->subMenu();
1541
1542
1543
1544
1545
1546
1547void QQuickMenu::addMenu(QQuickMenu *menu)
1550 insertMenu(d->contentModel->count(), menu);
1554
1555
1556
1557
1558
1559
1560void QQuickMenu::insertMenu(
int index, QQuickMenu *menu)
1566 insertItem(index, d->createItem(menu));
1570
1571
1572
1573
1574
1575void QQuickMenu::removeMenu(QQuickMenu *menu)
1581 const int count = d->contentModel->count();
1582 for (
int i = 0; i < count; ++i) {
1583 QQuickMenuItem *item = qobject_cast<QQuickMenuItem *>(d->itemAt(i));
1584 if (!item || item->subMenu() != menu)
1591 menu->deleteLater();
1595
1596
1597
1598
1599
1600
1601
1602
1603QQuickMenu *QQuickMenu::takeMenu(
int index)
1606 QQuickMenuItem *item = qobject_cast<QQuickMenuItem *>(d->itemAt(index));
1610 QQuickMenu *subMenu = item->subMenu();
1614 d->removeItem(index, item);
1615 item->deleteLater();
1621
1622
1623
1624
1625
1626
1627QQuickAction *QQuickMenu::actionAt(
int index)
const
1629 Q_D(
const QQuickMenu);
1630 if (!
const_cast<QQuickMenuPrivate *>(d)->maybeNativeHandle()) {
1631 QQuickAbstractButton *item = qobject_cast<QQuickAbstractButton *>(d->itemAt(index));
1635 return item->action();
1637 if (index < 0 || index >= d->nativeItems.size())
1640 return d->nativeItems.at(index)->action();
1645
1646
1647
1648
1649
1650
1651void QQuickMenu::addAction(QQuickAction *action)
1654 insertAction(d->contentModel->count(), action);
1658
1659
1660
1661
1662
1663
1664void QQuickMenu::insertAction(
int index, QQuickAction *action)
1670 insertItem(index, d->createItem(action));
1674
1675
1676
1677
1678
1679void QQuickMenu::removeAction(QQuickAction *action)
1685 const int count = d->contentModel->count();
1686 for (
int i = 0; i < count; ++i) {
1687 QQuickMenuItem *item = qobject_cast<QQuickMenuItem *>(d->itemAt(i));
1688 if (!item || item->action() != action)
1695 action->deleteLater();
1699
1700
1701
1702
1703
1704
1705
1706
1707QQuickAction *QQuickMenu::takeAction(
int index)
1710 QQuickMenuItem *item = qobject_cast<QQuickMenuItem *>(d->itemAt(index));
1714 QQuickAction *action = item->action();
1718 d->removeItem(index, item);
1719 item->deleteLater();
1723bool QQuickMenu::isVisible()
const
1725 Q_D(
const QQuickMenu);
1726 if (d->maybeNativeHandle())
1728 return QQuickPopup::isVisible();
1731void QQuickMenu::setVisible(
bool visible)
1734 if (visible == d->visible)
1737 auto *window =
this->window();
1738 if (visible && window) {
1741 QQuickWindowPrivate::get(window)->rmbContextMenuEventEnabled =
false;
1746 if (!d->parentMenu) {
1747 QQuickOverlay *overlay = QQuickOverlay::overlay(window, parentItem());
1749 const QList<QQuickPopup *> allPopups = QQuickOverlayPrivate::get(overlay)->allPopups;
1750 for (
auto *popup : allPopups) {
1751 if (popup !=
this && qobject_cast<QQuickMenu *>(popup))
1758 if (visible && ((d->useNativeMenu() && !d->maybeNativeHandle())
1759 || (!d->useNativeMenu() && d->maybeNativeHandle()))) {
1763 qCDebug(lcNativeMenus) <<
"setVisible called - useNativeMenu:" << d->useNativeMenu()
1764 <<
"maybeNativeHandle:" << d->maybeNativeHandle();
1765 d->syncWithUseNativeMenu();
1767 if (d->maybeNativeHandle()) {
1768 d->setNativeMenuVisible(visible);
1774 QQuickPopup::setVisible(visible);
1778
1779
1780
1781
1782
1783
1784
1785
1786
1787
1788
1789
1790
1791
1792
1793
1794
1795
1796
1797
1798QVariant QQuickMenu::contentModel()
const
1800 Q_D(
const QQuickMenu);
1801 return QVariant::fromValue(d->contentModel);
1805
1806
1807
1808
1809
1810
1811
1812
1813
1814
1815
1816
1817
1818
1819QQmlListProperty<QObject> QQuickMenu::contentData()
1822 if (!d->contentItem)
1823 QQuickControlPrivate::get(d->popupItem)->executeContentItem();
1824 return QQmlListProperty<QObject>(
this,
nullptr,
1825 QQuickMenuPrivate::contentData_append,
1826 QQuickMenuPrivate::contentData_count,
1827 QQuickMenuPrivate::contentData_at,
1828 QQuickMenuPrivate::contentData_clear);
1832
1833
1834
1835
1836
1837
1838
1839
1840QString QQuickMenu::title()
const
1842 Q_D(
const QQuickMenu);
1846void QQuickMenu::setTitle(
const QString &title)
1849 if (title == d->title)
1853 d->handle->setText(title);
1854 emit titleChanged(title);
1858
1859
1860
1861
1862
1863
1864
1865
1866
1867
1868
1869
1870
1871
1872
1874QQuickIcon QQuickMenu::icon()
const
1876 Q_D(
const QQuickMenu);
1880void QQuickMenu::setIcon(
const QQuickIcon &icon)
1883 if (icon == d->icon)
1886 d->icon.ensureRelativeSourceResolved(
this);
1887 emit iconChanged(icon);
1891
1892
1893
1894
1895
1896
1897
1898
1899
1900
1901
1902
1903
1904
1905
1906bool QQuickMenu::cascade()
const
1908 Q_D(
const QQuickMenu);
1912void QQuickMenu::setCascade(
bool cascade)
1915 if (d->cascade == cascade)
1917 d->cascade = cascade;
1919 d->resolveParentItem();
1920 emit cascadeChanged(cascade);
1923void QQuickMenu::resetCascade()
1927 setCascade(d->parentMenu->cascade());
1929 setCascade(shouldCascade());
1933
1934
1935
1936
1937
1938
1939
1940
1941
1942
1943
1944
1945
1946
1947
1948qreal QQuickMenu::overlap()
const
1950 Q_D(
const QQuickMenu);
1954void QQuickMenu::setOverlap(qreal overlap)
1957 if (d->overlap == overlap)
1959 d->overlap = overlap;
1960 emit overlapChanged();
1964
1965
1966
1967
1968
1969
1970
1971
1972
1973
1974
1975
1976
1977
1978
1979
1980
1981
1982
1983
1984
1985QQmlComponent *QQuickMenu::delegate()
const
1987 Q_D(
const QQuickMenu);
1991void QQuickMenu::setDelegate(QQmlComponent *delegate)
1994 if (d->delegate == delegate)
1997 d->delegate = delegate;
1998 emit delegateChanged();
2002
2003
2004
2005
2006
2007
2008
2009
2010
2011
2012
2013int QQuickMenu::currentIndex()
const
2015 Q_D(
const QQuickMenu);
2016 return d->currentIndex;
2019void QQuickMenu::setCurrentIndex(
int index)
2022 d->setCurrentIndex(index, Qt::OtherFocusReason);
2026
2027
2028
2029
2030
2031
2032int QQuickMenu::count()
const
2034 Q_D(
const QQuickMenu);
2035 return d->contentModel->count();
2038void QQuickMenuPrivate::popup(QQuickItem *menuItem)
2043 QQmlNullableValue<QPointF> pos;
2044#if QT_CONFIG(cursor)
2045 if (parentItem && QGuiApplicationPrivate::platformIntegration()->hasCapability(QPlatformIntegration::MultipleWindows))
2046 pos = parentItem->mapFromGlobal(QCursor::pos());
2050 if (!pos.isValid() && parentItem)
2051 pos = QPointF((parentItem->width() - q->width()) / 2, (parentItem->height() - q->height()) / 2);
2053 q->popup(pos.isValid() ? pos.value() : QPointF(), menuItem);
2056void QQuickMenu::popup(
const QPointF &position, QQuickItem *menuItem)
2060#if QT_CONFIG(cursor)
2062 offset = d->popupItem->mapFromItem(menuItem, QPointF(0, 0)).y();
2064 setPosition(position - QPointF(0, offset));
2067 d->setCurrentIndex(d->contentModel->indexOf(menuItem,
nullptr), Qt::PopupFocusReason);
2069 d->setCurrentIndex(-1, Qt::PopupFocusReason);
2075
2076
2077
2078
2079
2080
2081
2082
2083
2084
2085
2086
2087
2090
2091
2092
2093
2094
2095
2096
2097
2098
2099
2100
2101
2102
2105
2106
2107
2108
2109
2110
2111
2112
2113
2114
2115
2116
2117
2119void QQuickMenu::popup(QQuickItem *parent, qreal x, qreal y, QQuickItem *menuItem)
2121 popup(parent, QPointF {x, y}, menuItem);
2124void QQuickMenu::popup(QQuickItem *parent,
const QPointF &position, QQuickItem *menuItem)
2127 if (parent && !d->popupItem->isAncestorOf(parent))
2128 setParentItem(parent);
2129 popup(position, menuItem);
2132void QQuickMenu::popup(QQuickItem *parent, QQuickItem *menuItem)
2135 QQuickItem *parentItem =
nullptr;
2136 if (parent && !d->popupItem->isAncestorOf(parent))
2137 parentItem = parent;
2139 setParentItem(parentItem);
2145void QQuickMenu::popup(QQuickItem *parent)
2148 QQuickItem *menuItem =
nullptr;
2150 if (!d->popupItem->isAncestorOf(parent))
2151 setParentItem(parent);
2152 if (d->popupItem->isAncestorOf(parent))
2158void QQuickMenu::popup(qreal x, qreal y, QQuickItem *menuItem)
2160 popup(QPointF {x, y}, menuItem);
2164
2165
2166
2167
2168
2169
2170
2171
2172
2173
2174
2175
2176
2177
2178void QQuickMenu::dismiss()
2180 QQuickMenu *menu =
this;
2183 menu = QQuickMenuPrivate::get(menu)->parentMenu;
2187void QQuickMenu::componentComplete()
2190 QQuickPopup::componentComplete();
2192 d->updateTextPadding();
2193 d->syncWithUseNativeMenu();
2196void QQuickMenu::contentItemChange(QQuickItem *newItem, QQuickItem *oldItem)
2199 QQuickPopup::contentItemChange(newItem, oldItem);
2202 QQuickItemPrivate::get(oldItem)->removeItemChangeListener(d, QQuickItemPrivate::Children);
2203 QQuickItemPrivate::get(newItem)->removeItemChangeListener(d, QQuickItemPrivate::Destroyed);
2204 QQuickItemPrivate::get(oldItem)->removeItemChangeListener(d, QQuickItemPrivate::Geometry);
2207 QQuickItemPrivate::get(newItem)->addItemChangeListener(d, QQuickItemPrivate::Children);
2208 QQuickItemPrivate::get(newItem)->addItemChangeListener(d, QQuickItemPrivate::Destroyed);
2209 QQuickItemPrivate::get(newItem)->updateOrAddGeometryChangeListener(d, QQuickGeometryChange::Width);
2212 d->contentItem = newItem;
2215void QQuickMenu::itemChange(QQuickItem::ItemChange change,
const QQuickItem::ItemChangeData &data)
2218 QQuickPopup::itemChange(change, data);
2221 case QQuickItem::ItemVisibleHasChanged:
2222 if (!data.boolValue && d->cascade) {
2225 d->setCurrentIndex(-1, Qt::OtherFocusReason);
2233void QQuickMenu::keyPressEvent(QKeyEvent *event)
2236 QQuickPopup::keyPressEvent(event);
2244 switch (event->key()) {
2246 if (!d->activatePreviousItem())
2247 d->propagateKeyEvent(event);
2251 d->activateNextItem();
2257 if (d->popupItem->isMirrored() == (event->key() == Qt::Key_Right)) {
2258 if (d->parentMenu && d->currentItem) {
2260 d->parentMenu->open();
2265 if (QQuickMenu *subMenu = d->currentSubMenu()) {
2266 auto subMenuPrivate = QQuickMenuPrivate::get(subMenu);
2267 subMenuPrivate->popup(subMenuPrivate->firstEnabledMenuItem());
2271 if (!event->isAccepted())
2272 d->propagateKeyEvent(event);
2275#if QT_CONFIG(shortcut)
2279 if (!QKeySequence::mnemonic(QStringLiteral(
"&A")).isEmpty())
2288#if QT_CONFIG(shortcut)
2289 if (event->modifiers() == Qt::NoModifier) {
2290 for (
int i = 0; i < count(); ++i) {
2291 QQuickAbstractButton *item = qobject_cast<QQuickAbstractButton*>(d->itemAt(i));
2294 const QKeySequence keySequence = QKeySequence::mnemonic(item->text());
2295 if (keySequence.isEmpty())
2297 if (keySequence[0].key() == event->key()) {
2306void QQuickMenu::timerEvent(QTimerEvent *event)
2309 if (event->timerId() == d->hoverTimer) {
2310 if (QQuickMenu *subMenu = d->currentSubMenu())
2312 d->stopHoverTimer();
2315 QQuickPopup::timerEvent(event);
2318QFont QQuickMenu::defaultFont()
const
2320 return QQuickTheme::font(QQuickTheme::Menu);
2323#if QT_CONFIG(accessibility)
2324QAccessible::Role QQuickMenu::accessibleRole()
const
2326 return QAccessible::PopupMenu;
2332#include "moc_qquickmenu_p.cpp"
Combined button and popup list for selecting options.