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
252
253
254
255
256
257
258
259
260
261
262
263
264
265
272 return QGuiApplicationPrivate::platformIntegration()->hasCapability(QPlatformIntegration::MultipleWindows);
286QQuickMenuPrivate::QQuickMenuPrivate()
288 cascade = shouldCascade();
291void QQuickMenuPrivate::init()
294 contentModel =
new QQmlObjectModel(q);
297QQuickMenu *QQuickMenuPrivate::rootMenu()
const
299 Q_Q(
const QQuickMenu);
300 const QQuickMenu *rootMenu = q;
301 const QObject *p = q->parent();
303 if (
auto menu = qobject_cast<
const QQuickMenu *>(p))
308 return const_cast<QQuickMenu *>(rootMenu);
311QQuickPopup::PopupType QQuickMenuPrivate::resolvedPopupType()
const
315 QQuickMenu *root = rootMenu();
316 QQuickMenuPrivate *root_d = QQuickMenuPrivate::get(rootMenu());
318 if (
auto menuBar = QQuickMenuPrivate::get(root)->menuBar.get()) {
323 if (QQuickMenuBarPrivate::get(menuBar)->useNativeMenu(q_func()))
324 return QQuickPopup::Native;
327 if (root_d->maybeNativeHandle()) {
328 return QQuickPopup::Native;
329 }
else if (!root_d->triedToCreateNativeMenu) {
335 if (root->popupType() == QQuickPopup::Native
336 && !QGuiApplication::testAttribute(Qt::AA_DontUseNativeMenuWindows)) {
337 return QQuickPopup::Native;
345 const auto type = root_d->QQuickPopupPrivate::resolvedPopupType();
346 Q_ASSERT(type != QQuickPopup::Native);
350bool QQuickMenuPrivate::useNativeMenu()
const
352 return resolvedPopupType() == QQuickPopup::Native;
355QPlatformMenu *QQuickMenuPrivate::nativeHandle()
357 Q_ASSERT(handle || useNativeMenu());
358 if (!handle && !triedToCreateNativeMenu)
363QPlatformMenu *QQuickMenuPrivate::maybeNativeHandle()
const
368bool QQuickMenuPrivate::createNativeMenu()
372 qCDebug(lcNativeMenus) <<
"createNativeMenu called on" << q;
374 if (
auto menuBar = QQuickMenuPrivate::get(rootMenu())->menuBar) {
375 auto menuBarPrivate = QQuickMenuBarPrivate::get(menuBar);
376 if (menuBarPrivate->useNativeMenuBar()) {
377 qCDebug(lcNativeMenus) <<
"- creating native menu from native menubar";
378 if (QPlatformMenuBar *menuBarHandle = menuBarPrivate->nativeHandle())
379 handle.reset(menuBarHandle->createMenu());
384 QPlatformMenu *parentMenuHandle(parentMenu ? get(parentMenu)->handle.get() :
nullptr);
385 if (parentMenu && parentMenuHandle) {
386 qCDebug(lcNativeMenus) <<
"- creating native sub-menu";
387 handle.reset(parentMenuHandle->createSubMenu());
389 qCDebug(lcNativeMenus) <<
"- creating native menu";
390 handle.reset(QGuiApplicationPrivate::platformTheme()->createPlatformMenu());
394 triedToCreateNativeMenu =
true;
399 q->connect(handle.get(), &QPlatformMenu::aboutToShow, q, [q,
this](){
400 emit q->aboutToShow();
402 emit q->visibleChanged();
403 emit q->openedChanged();
406 q->connect(handle.get(), &QPlatformMenu::aboutToHide, q, [q](){
407 qCDebug(lcNativeMenus) <<
"QPlatformMenu::aboutToHide called; about to call setVisible(false) on Menu";
408 emit q->aboutToHide();
414 q->connect(handle.get(), &QPlatformMenu::aboutToHide, q, [q,
this](){
416 emit q->visibleChanged();
417 emit q->openedChanged();
419 }, Qt::QueuedConnection);
421 recursivelyCreateNativeMenuItems(q);
422 syncWithNativeMenu();
429 if (nativeItems.isEmpty())
430 return QStringLiteral(
"(Empty)");
433 QTextStream debug(&str);
434 for (
const auto *nativeItem : nativeItems)
435 debug << nativeItem->debugText() <<
", ";
437 if (!nativeItems.isEmpty())
442void QQuickMenuPrivate::syncWithNativeMenu()
445 if (!complete || !handle)
448 qCDebug(lcNativeMenus).nospace() <<
"syncWithNativeMenu called on " << q
449 <<
" (complete: " << complete <<
" visible: " << visible <<
") - "
450 <<
"syncing " << nativeItems.size() <<
" item(s)...";
454 handle->setText(title);
455 handle->setEnabled(q->isEnabled());
456 handle->setMinimumWidth(q->implicitWidth());
458 handle->setFont(q->font());
476 for (QQuickNativeMenuItem *item : std::as_const(nativeItems)) {
477 qCDebug(lcNativeMenus) <<
"- syncing" << item <<
"action" << item->action()
478 <<
"sub-menu" << item->subMenu() << item->debugText();
482 qCDebug(lcNativeMenus) <<
"... finished syncing" << q;
486
487
488
489
490
491
492
493void QQuickMenuPrivate::removeNativeMenu()
496 const int qtyItemsToRemove = nativeItems.size();
497 if (qtyItemsToRemove != 0)
498 Q_ASSERT(q->count() == qtyItemsToRemove);
499 for (
int i = 0; i < qtyItemsToRemove; ++i)
501 Q_ASSERT(nativeItems.isEmpty());
508void QQuickMenuPrivate::syncWithUseNativeMenu()
513 if (q->isVisible() || parentMenu)
516 if (maybeNativeHandle() && !useNativeMenu()) {
520 }
else if (useNativeMenu()) {
521 Q_ASSERT(nativeItems.isEmpty());
529 QQuickWindow *quickWindow = qobject_cast<QQuickWindow *>(window);
531 QWindow *renderWindow = QQuickRenderControl::renderWindowFor(quickWindow, offset);
538void QQuickMenuPrivate::setNativeMenuVisible(
bool visible)
541 qCDebug(lcNativeMenus) <<
"setNativeMenuVisible called with visible" << visible;
543 emit q->aboutToShow();
545 emit q->aboutToHide();
547 this->visible = visible;
548 syncWithNativeMenu();
552 QWindow *window =
nullptr;
554 window = effectiveWindow(parentItem->window(), &offset);
556 lastDevicePixelRatio = window ? window->devicePixelRatio() : qGuiApp->devicePixelRatio();
558 const QPointF globalPos = parentItem->mapToGlobal(x, y);
559 const QPoint windowPos = window ? window->mapFromGlobal(globalPos.toPoint()) : parentItem->mapToScene(QPoint(x, y)).toPoint();
560 QRect targetRect(windowPos, QSize(0, 0));
561 auto *daPriv = QQuickItemPrivate::get(parentItem)->deliveryAgentPrivate();
568 if (QPointerEvent *openingEvent = daPriv->eventInDelivery()) {
569 auto *devPriv = QPointingDevicePrivate::get(
const_cast<QPointingDevice *>(openingEvent->pointingDevice()));
570 for (
const auto &pt : std::as_const(openingEvent->points())) {
571 qCDebug(lcNativeMenus) <<
"popup over" << window <<
"its DA" << daPriv->q_func() <<
"opening due to" << openingEvent
572 <<
"with grabbers" << openingEvent->exclusiveGrabber(pt) << openingEvent->passiveGrabbers(pt);
574 if (
auto *opener = openingEvent->exclusiveGrabber(pt))
575 devPriv->removeGrabber(opener,
true);
576 for (
auto passiveGrabber : openingEvent->passiveGrabbers(pt)) {
577 if (
auto *opener = passiveGrabber.get())
578 devPriv->removeGrabber(opener,
true);
582 handle->showPopup(window, QHighDpi::toNativeLocalPosition(targetRect, window),
590void QQuickMenuPrivate::makeEditMenu()
592 handle->setMenuType(QPlatformMenu::EditMenu);
595QQuickItem *QQuickMenuPrivate::itemAt(
int index)
const
597 return qobject_cast<QQuickItem *>(contentModel->get(index));
600void QQuickMenuPrivate::insertItem(
int index, QQuickItem *item)
602 qCDebug(lcMenu) <<
"insert called with index" << index <<
"item" << item;
605 contentData.append(item);
606 item->setParentItem(contentItem);
607 QQuickItemPrivate::get(item)->setCulled(
true);
610 QQuickItemPrivate::get(item)->addItemChangeListener(
this, QQuickItemPrivate::Destroyed | QQuickItemPrivate::Parent);
611 QQuickItemPrivate::get(item)->updateOrAddGeometryChangeListener(
this, QQuickGeometryChange::Width);
612 contentModel->insert(index, item);
614 QQuickMenuItem *menuItem = qobject_cast<QQuickMenuItem *>(item);
616 QQuickMenuItemPrivate::get(menuItem)->setMenu(q);
617 if (QQuickMenu *subMenu = menuItem->subMenu())
618 QQuickMenuPrivate::get(subMenu)->setParentMenu(q);
619 QObjectPrivate::connect(menuItem, &QQuickMenuItem::triggered,
this, &QQuickMenuPrivate::onItemTriggered);
620 QObjectPrivate::connect(menuItem, &QQuickMenuItem::implicitTextPaddingChanged,
this, &QQuickMenuPrivate::updateTextPadding);
621 QObjectPrivate::connect(menuItem, &QQuickMenuItem::visibleChanged,
this, &QQuickMenuPrivate::updateTextPadding);
622 QObjectPrivate::connect(menuItem, &QQuickItem::activeFocusChanged,
this, &QQuickMenuPrivate::onItemActiveFocusChanged);
623 QObjectPrivate::connect(menuItem, &QQuickControl::hoveredChanged,
this, &QQuickMenuPrivate::onItemHovered);
626 if (maybeNativeHandle() && complete)
627 maybeCreateAndInsertNativeItem(index, item);
629 if (lcMenu().isDebugEnabled())
630 printContentModelItems();
635void QQuickMenuPrivate::maybeCreateAndInsertNativeItem(
int index, QQuickItem *item)
639 Q_ASSERT_X(handle, Q_FUNC_INFO, qPrintable(QString::fromLatin1(
640 "Expected %1 to be using a native menu").arg(QDebug::toString(q))));
641 std::unique_ptr<QQuickNativeMenuItem> nativeMenuItem(QQuickNativeMenuItem::createFromNonNativeItem(q, item));
642 if (!nativeMenuItem) {
644 qmlWarning(q) <<
"Native menu failed to create a native menu item for item at index" << index;
648 nativeItems.insert(index, nativeMenuItem.get());
652 if (nativeMenuItem->handle()) {
653 QQuickNativeMenuItem *before = nativeItems.value(index + 1);
654 handle->insertMenuItem(nativeMenuItem->handle(), before ? before->handle() :
nullptr);
655 qCDebug(lcNativeMenus) <<
"inserted native menu item at index" << index
656 <<
"before" << (before ? before->debugText() : QStringLiteral(
"null"));
658 if (nativeMenuItem->subMenu() && QQuickMenuPrivate::get(nativeMenuItem->subMenu())->nativeItems.count()
659 < nativeMenuItem->subMenu()->count()) {
665 recursivelyCreateNativeMenuItems(nativeMenuItem->subMenu());
669 nativeMenuItem.release();
671 qCDebug(lcNativeMenus) <<
"nativeItems now contains the following items:"
672 << nativeMenuItemListToString(nativeItems);
675void QQuickMenuPrivate::moveItem(
int from,
int to)
677 contentModel->move(from, to);
679 if (maybeNativeHandle())
680 nativeItems.move(from, to);
684
685
686
687
688
689
690
691
692
693void QQuickMenuPrivate::removeItem(
int index, QQuickItem *item, DestructionPolicy destructionPolicy)
695 qCDebug(lcMenu) <<
"removeItem called with index" << index <<
"item" << item;
697 if (maybeNativeHandle())
698 removeNativeItem(index);
700 contentData.removeOne(item);
702 QQuickItemPrivate::get(item)->removeItemChangeListener(
this, QQuickItemPrivate::Destroyed | QQuickItemPrivate::Parent);
703 QQuickItemPrivate::get(item)->removeItemChangeListener(
this, QQuickItemPrivate::Geometry);
704 item->setParentItem(
nullptr);
705 contentModel->remove(index);
707 QQuickMenuItem *menuItem = qobject_cast<QQuickMenuItem *>(item);
709 QQuickMenuItemPrivate::get(menuItem)->setMenu(
nullptr);
710 if (QQuickMenu *subMenu = menuItem->subMenu())
711 QQuickMenuPrivate::get(subMenu)->setParentMenu(
nullptr);
712 QObjectPrivate::disconnect(menuItem, &QQuickMenuItem::triggered,
this, &QQuickMenuPrivate::onItemTriggered);
713 QObjectPrivate::disconnect(menuItem, &QQuickMenuItem::implicitTextPaddingChanged,
this, &QQuickMenuPrivate::updateTextPadding);
714 QObjectPrivate::disconnect(menuItem, &QQuickMenuItem::visibleChanged,
this, &QQuickMenuPrivate::updateTextPadding);
715 QObjectPrivate::disconnect(menuItem, &QQuickItem::activeFocusChanged,
this, &QQuickMenuPrivate::onItemActiveFocusChanged);
716 QObjectPrivate::disconnect(menuItem, &QQuickControl::hoveredChanged,
this, &QQuickMenuPrivate::onItemHovered);
719 if (destructionPolicy == DestructionPolicy::Destroy)
722 if (lcMenu().isDebugEnabled())
723 printContentModelItems();
727
728
729
730
731
732
733
734
735
736void QQuickMenuPrivate::removeNativeItem(
int index, SyncPolicy syncPolicy)
741 Q_ASSERT_X(index >= 0 && index < nativeItems.size(), Q_FUNC_INFO, qPrintable(QString::fromLatin1(
742 "index %1 is less than 0 or greater than or equal to %2").arg(index).arg(nativeItems.size())));
746 std::unique_ptr<QQuickNativeMenuItem> nativeItem(nativeItems.takeAt(index));
747 qCDebug(lcNativeMenus) <<
"removing native item" << nativeItem->debugText() <<
"at index" << index
748 <<
"from" << q_func() <<
"...";
749 QQuickMenu *subMenu = nativeItem->subMenu();
751 Q_ASSERT(nativeItem->handle());
752 auto *subMenuPrivate = QQuickMenuPrivate::get(subMenu);
753 while (!subMenuPrivate->nativeItems.isEmpty()) {
754 subMenuPrivate->removeNativeItem(0, SyncPolicy::DoNotSync);
758 Q_ASSERT(nativeItem->handle());
759 handle->removeMenuItem(nativeItem->handle());
760 if (syncPolicy == SyncPolicy::Sync)
761 syncWithNativeMenu();
764 auto *subMenuPrivate = QQuickMenuPrivate::get(subMenu);
770 subMenuPrivate->resetNativeData();
773 qCDebug(lcNativeMenus).nospace() <<
"... after removing item at index " << index
774 <<
", nativeItems now contains the following items: " << nativeMenuItemListToString(nativeItems);
777void QQuickMenuPrivate::resetNativeData()
779 qCDebug(lcNativeMenus) <<
"resetNativeData called on" << q_func();
781 triedToCreateNativeMenu =
false;
784void QQuickMenuPrivate::recursivelyCreateNativeMenuItems(QQuickMenu *menu)
786 auto *menuPrivate = QQuickMenuPrivate::get(menu);
789 if (!menuPrivate->triedToCreateNativeMenu)
790 menuPrivate->createNativeMenu();
792 const int qtyItemsToCreate = menuPrivate->contentModel->count();
793 if (menuPrivate->nativeItems.count() == qtyItemsToCreate)
796 qCDebug(lcNativeMenus) <<
"recursively creating" << qtyItemsToCreate <<
"menu item(s) for" << menu;
797 Q_ASSERT(menuPrivate->nativeItems.count() == 0);
798 for (
int i = 0; i < qtyItemsToCreate; ++i) {
799 QQuickItem *item = menu->itemAt(i);
800 menuPrivate->maybeCreateAndInsertNativeItem(i, item);
801 auto *menuItem = qobject_cast<QQuickMenuItem *>(item);
802 if (menuItem && menuItem->subMenu())
803 recursivelyCreateNativeMenuItems(menuItem->subMenu());
807void QQuickMenuPrivate::printContentModelItems()
const
809 qCDebug(lcMenu) <<
"contentModel now contains:";
810 for (
int i = 0; i < contentModel->count(); ++i)
811 qCDebug(lcMenu) <<
"-" << itemAt(i);
814QQuickItem *QQuickMenuPrivate::beginCreateItem()
820 QQmlContext *context = delegate->creationContext();
822 context = qmlContext(q);
824 QObject *object = delegate->beginCreate(context);
825 QQuickItem *item = qobject_cast<QQuickItem *>(object);
829 QQml_setParent_noEvent(item, q);
834void QQuickMenuPrivate::completeCreateItem()
839 delegate->completeCreate();
842QQuickItem *QQuickMenuPrivate::createItem(QQuickMenu *menu)
844 QQuickItem *item = beginCreateItem();
845 if (QQuickMenuItem *menuItem = qobject_cast<QQuickMenuItem *>(item))
846 QQuickMenuItemPrivate::get(menuItem)->setSubMenu(menu);
847 completeCreateItem();
851QQuickItem *QQuickMenuPrivate::createItem(QQuickAction *action)
853 QQuickItem *item = beginCreateItem();
854 if (QQuickAbstractButton *button = qobject_cast<QQuickAbstractButton *>(item))
855 button->setAction(action);
856 completeCreateItem();
860void QQuickMenuPrivate::resizeItem(QQuickItem *item)
862 if (!item || !contentItem)
865 QQuickItemPrivate *p = QQuickItemPrivate::get(item);
866 if (!p->widthValid()) {
867 item->setWidth(contentItem->width());
868 p->widthValidFlag =
false;
872void QQuickMenuPrivate::resizeItems()
877 for (
int i = 0; i < contentModel->count(); ++i)
878 resizeItem(itemAt(i));
881void QQuickMenuPrivate::itemChildAdded(QQuickItem *, QQuickItem *child)
884 if (!QQuickItemPrivate::get(child)->isTransparentForPositioner() && !contentData.contains(child))
885 insertItem(contentModel->count(), child);
888void QQuickMenuPrivate::itemParentChanged(QQuickItem *item, QQuickItem *parent)
892 removeItem(contentModel->indexOf(item,
nullptr), item);
895void QQuickMenuPrivate::itemSiblingOrderChanged(QQuickItem *)
899 QList<QQuickItem *> siblings = contentItem->childItems();
902 for (
int i = 0; i < siblings.size(); ++i) {
903 QQuickItem* sibling = siblings.at(i);
904 if (QQuickItemPrivate::get(sibling)->isTransparentForPositioner())
906 int index = contentModel->indexOf(sibling,
nullptr);
907 q->moveItem(index, to++);
911void QQuickMenuPrivate::itemDestroyed(QQuickItem *item)
913 if (item == contentItem) {
916 QQuickPopupPrivate::itemDestroyed(item);
918 int index = contentModel->indexOf(item,
nullptr);
920 removeItem(index, item);
925void QQuickMenuPrivate::itemGeometryChanged(QQuickItem *item, QQuickGeometryChange,
const QRectF &)
930 if (item == contentItem) {
941QQuickPopupPositioner *QQuickMenuPrivate::getPositioner()
945 positioner =
new QQuickMenuPositioner(q);
951 QQuickMenu *menu =
static_cast<QQuickMenu *>(popup());
952 QQuickMenuPrivate *menu_d = QQuickMenuPrivate::get(menu);
954 if (QQuickMenu *parentMenu = menu_d->parentMenu) {
955 if (menu_d->cascade) {
958 if (menu_d->popupItem->isMirrored()) {
959 const qreal distanceToFrame = parentMenu->leftPadding();
960 const qreal menuX = -menu->width() - distanceToFrame + menu->overlap();
961 menu->setPosition({menuX, -menu->topPadding()});
962 }
else if (menu_d->parentItem) {
963 const qreal distanceToFrame = parentMenu->rightPadding();
964 const qreal menuX = menu_d->parentItem->width() + distanceToFrame - menu->overlap();
965 menu->setPosition({menuX, -menu->topPadding()});
968 const qreal menuX = parentMenu->x() + (parentMenu->width() - menu->width()) / 2;
969 const qreal menuY = parentMenu->y() + (parentMenu->height() - menu->height()) / 2;
970 menu->setPosition({menuX, menuY});
974 QQuickPopupPositioner::reposition();
977bool QQuickMenuPrivate::prepareEnterTransition()
980 if (parentMenu && !cascade)
985 allowHorizontalFlip = cascade && parentMenu;
997 auto *contentItemAsListView = qobject_cast<QQuickListView *>(contentItem);
998 if (contentItemAsListView) {
999 if (QQuickItemViewPrivate::get(contentItemAsListView)->currentChanges.hasPendingChanges())
1000 contentItemAsListView->forceLayout();
1003 if (!QQuickPopupPrivate::prepareEnterTransition())
1006 if (!hasClosePolicy) {
1007 if (cascade && parentMenu)
1008 closePolicy = cascadingSubMenuClosePolicy;
1010 q->resetClosePolicy();
1015bool QQuickMenuPrivate::prepareExitTransition()
1017 if (!QQuickPopupPrivate::prepareExitTransition())
1022 QQuickMenu *subMenu = currentSubMenu();
1024 QPointer<QQuickMenuItem> currentSubMenuItem = QQuickMenuPrivate::get(subMenu)->currentItem;
1026 subMenu = currentSubMenuItem ? currentSubMenuItem->subMenu() :
nullptr;
1031bool QQuickMenuPrivate::blockInput(QQuickItem *item,
const QPointF &point)
const
1034 return (cascade && parentMenu && contains(point)) || QQuickPopupPrivate::blockInput(item, point);
1037bool QQuickMenuPrivate::handlePress(QQuickItem *item,
const QPointF &point, ulong timestamp)
1041 return QQuickPopupPrivate::handlePress(item, point, timestamp)
1042 || (popupItem == item);
1047
1048
1049
1050
1051
1052
1053bool QQuickMenuPrivate::handleReleaseWithoutGrab(
const QEventPoint &eventPoint)
1055 const QPointF scenePos = eventPoint.scenePosition();
1056 if (!contains(scenePos))
1059 auto *list = qobject_cast<QQuickListView *>(contentItem);
1063 const QPointF listPos = list->mapFromScene(scenePos);
1065 auto *menuItem = qobject_cast<QQuickMenuItem *>(list->itemAt(listPos.x(), listPos.y()));
1066 if (menuItem && menuItem->isHighlighted()) {
1067 menuItem->animateClick();
1074void QQuickMenuPrivate::onItemHovered()
1077 QQuickAbstractButton *button = qobject_cast<QQuickAbstractButton *>(q->sender());
1078 if (!button || !button->isHovered() || !button->isEnabled() || QQuickAbstractButtonPrivate::get(button)->touchId != -1)
1081 QQuickMenuItem *oldCurrentItem = currentItem;
1083 int index = contentModel->indexOf(button,
nullptr);
1085 setCurrentIndex(index, Qt::OtherFocusReason);
1086 if (oldCurrentItem != currentItem) {
1087 if (oldCurrentItem) {
1088 QQuickMenu *subMenu = oldCurrentItem->subMenu();
1093 QQuickMenu *subMenu = currentItem->menu();
1094 if (subMenu && subMenu->cascade())
1101void QQuickMenuPrivate::onItemTriggered()
1104 QQuickMenuItem *item = qobject_cast<QQuickMenuItem *>(q->sender());
1108 if (QQuickMenu *subMenu = item->subMenu()) {
1109 auto subMenuPrivate = QQuickMenuPrivate::get(subMenu);
1110 subMenuPrivate->popup(subMenuPrivate->firstEnabledMenuItem());
1116void QQuickMenuPrivate::onItemActiveFocusChanged()
1119 QQuickItem *item = qobject_cast<QQuickItem*>(q->sender());
1120 if (!item->hasActiveFocus())
1123 int indexOfItem = contentModel->indexOf(item,
nullptr);
1124 QQuickControl *control = qobject_cast<QQuickControl *>(item);
1125 setCurrentIndex(indexOfItem, control ? control->focusReason() : Qt::OtherFocusReason);
1128void QQuickMenuPrivate::updateTextPadding()
1135 for (
int i = 0; i < q->count(); ++i) {
1136 if (
const auto menuItem = qobject_cast<QQuickMenuItem *>(itemAt(i)))
1137 if (menuItem->isVisible())
1138 padding = qMax(padding, menuItem->implicitTextPadding());
1141 if (padding == textPadding)
1144 textPadding = padding;
1146 for (
int i = 0; i < q->count(); ++i) {
1147 if (
const auto menuItem = qobject_cast<QQuickMenuItem *>(itemAt(i)))
1148 emit menuItem->textPaddingChanged();
1152QQuickMenu *QQuickMenuPrivate::currentSubMenu()
const
1157 return currentItem->subMenu();
1160void QQuickMenuPrivate::setParentMenu(QQuickMenu *parent)
1163 if (parentMenu == parent)
1167 QObject::disconnect(parentMenu.data(), &QQuickMenu::cascadeChanged, q, &QQuickMenu::setCascade);
1168 disconnect(parentMenu.data(), &QQuickMenu::parentChanged,
this, &QQuickMenuPrivate::resolveParentItem);
1171 QObject::connect(parent, &QQuickMenu::cascadeChanged, q, &QQuickMenu::setCascade);
1172 connect(parent, &QQuickMenu::parentChanged,
this, &QQuickMenuPrivate::resolveParentItem);
1175 parentMenu = parent;
1177 resolveParentItem();
1182 QQuickMenu *menu = QQuickMenuPrivate::get(subMenu)->parentMenu;
1183 for (
int i = 0; i < QQuickMenuPrivate::get(menu)->contentModel->count(); ++i) {
1184 QQuickMenuItem *item = qobject_cast<QQuickMenuItem *>(menu->itemAt(i));
1185 if (item && item->subMenu() == subMenu)
1191void QQuickMenuPrivate::resolveParentItem()
1195 q->resetParentItem();
1197 q->setParentItem(parentMenu->parentItem());
1199 q->setParentItem(findParentMenuItem(q));
1202void QQuickMenuPrivate::propagateKeyEvent(QKeyEvent *event)
1204 if (QQuickMenuItem *menuItem = qobject_cast<QQuickMenuItem *>(parentItem)) {
1205 if (QQuickMenu *menu = menuItem->menu())
1206 QQuickMenuPrivate::get(menu)->propagateKeyEvent(event);
1207#if QT_CONFIG(quicktemplates2_container)
1208 }
else if (QQuickMenuBarItem *menuBarItem = qobject_cast<QQuickMenuBarItem *>(parentItem)) {
1209 if (QQuickMenuBar *menuBar = menuBarItem->menuBar()) {
1211 QCoreApplication::sendEvent(menuBar, event);
1217void QQuickMenuPrivate::startHoverTimer()
1221 hoverTimer = q->startTimer(SUBMENU_DELAY);
1224void QQuickMenuPrivate::stopHoverTimer()
1230 q->killTimer(hoverTimer);
1234void QQuickMenuPrivate::setCurrentIndex(
int index, Qt::FocusReason reason)
1237 if (currentIndex == index)
1240 QQuickMenuItem *newCurrentItem = qobject_cast<QQuickMenuItem *>(itemAt(index));
1241 if (currentItem != newCurrentItem) {
1244 currentItem->setHighlighted(
false);
1245 if (!newCurrentItem && window) {
1246 QQuickItem *focusItem = QQuickItemPrivate::get(contentItem)->subFocusItem;
1248 auto *daPriv = QQuickWindowPrivate::get(window)->deliveryAgentPrivate();
1249 daPriv->clearFocusInScope(contentItem, focusItem, Qt::OtherFocusReason);
1253 if (newCurrentItem) {
1254 newCurrentItem->setHighlighted(
true);
1255 newCurrentItem->forceActiveFocus(reason);
1257 currentItem = newCurrentItem;
1260 currentIndex = index;
1261 emit q->currentIndexChanged();
1264bool QQuickMenuPrivate::activateNextItem()
1266 int index = currentIndex;
1267 int count = contentModel->count();
1268 while (++index < count) {
1269 QQuickItem *item = itemAt(index);
1270 if (!item || !item->activeFocusOnTab() || !item->isEnabled())
1272 setCurrentIndex(index, Qt::TabFocusReason);
1278bool QQuickMenuPrivate::activatePreviousItem()
1280 int index = currentIndex;
1281 while (--index >= 0) {
1282 QQuickItem *item = itemAt(index);
1283 if (!item || !item->activeFocusOnTab() || !item->isEnabled())
1285 setCurrentIndex(index, Qt::BacktabFocusReason);
1291QQuickMenuItem *QQuickMenuPrivate::firstEnabledMenuItem()
const
1293 for (
int i = 0; i < contentModel->count(); ++i) {
1294 QQuickItem *item = itemAt(i);
1295 if (!item || !item->isEnabled())
1298 QQuickMenuItem *menuItem = qobject_cast<QQuickMenuItem *>(item);
1307void QQuickMenuPrivate::contentData_append(QQmlListProperty<QObject> *prop, QObject *obj)
1309 QQuickMenu *q = qobject_cast<QQuickMenu *>(prop->object);
1310 QQuickMenuPrivate *p = QQuickMenuPrivate::get(q);
1312 QQuickItem *item = qobject_cast<QQuickItem *>(obj);
1314 if (QQuickAction *action = qobject_cast<QQuickAction *>(obj))
1315 item = p->createItem(action);
1316 else if (QQuickMenu *menu = qobject_cast<QQuickMenu *>(obj))
1317 item = p->createItem(menu);
1321 if (QQuickItemPrivate::get(item)->isTransparentForPositioner()) {
1322 QQuickItemPrivate::get(item)->addItemChangeListener(p, QQuickItemPrivate::SiblingOrder);
1323 item->setParentItem(p->contentItem);
1324 }
else if (p->contentModel->indexOf(item,
nullptr) == -1) {
1328 p->contentData.append(obj);
1332qsizetype QQuickMenuPrivate::contentData_count(QQmlListProperty<QObject> *prop)
1334 QQuickMenu *q =
static_cast<QQuickMenu *>(prop->object);
1335 return QQuickMenuPrivate::get(q)->contentData.size();
1338QObject *QQuickMenuPrivate::contentData_at(QQmlListProperty<QObject> *prop, qsizetype index)
1340 QQuickMenu *q =
static_cast<QQuickMenu *>(prop->object);
1341 return QQuickMenuPrivate::get(q)->contentData.value(index);
1344QPalette QQuickMenuPrivate::defaultPalette()
const
1346 return QQuickTheme::palette(QQuickTheme::Menu);
1349void QQuickMenuPrivate::contentData_clear(QQmlListProperty<QObject> *prop)
1351 QQuickMenu *q =
static_cast<QQuickMenu *>(prop->object);
1352 QQuickMenuPrivate::get(q)->contentData.clear();
1355void QQuickMenuPrivate::resetContentItem()
1358 QQuickItemPrivate::get(contentItem)->removeItemChangeListener(
this, QQuickItemPrivate::Children);
1359 QQuickItemPrivate::get(contentItem)->removeItemChangeListener(
this, QQuickItemPrivate::Destroyed);
1360 QQuickItemPrivate::get(contentItem)->removeItemChangeListener(
this, QQuickItemPrivate::Geometry);
1362 const auto children = contentItem->childItems();
1363 for (QQuickItem *child : std::as_const(children))
1364 QQuickItemPrivate::get(child)->removeItemChangeListener(
this, QQuickItemPrivate::SiblingOrder);
1365 contentItem =
nullptr;
1369QQuickMenu::QQuickMenu(QObject *parent)
1370 : QQuickPopup(*(
new QQuickMenuPrivate), parent)
1375 connect(d->contentModel, &QQmlObjectModel::countChanged,
this, &QQuickMenu::countChanged);
1378QQuickMenu::~QQuickMenu()
1381 qCDebug(lcNativeMenus) <<
"destroying" <<
this
1383 << d->contentModel->count()
1384 <<
"native item count:" << d->nativeItems.count();
1388 if (
auto *menuItem = qobject_cast<QQuickMenuItem *>(d->parentItem)) {
1389 if (menuItem->subMenu() ==
this) {
1390 auto *menuItemPriv = QQuickMenuItemPrivate::get(menuItem);
1391 menuItemPriv->setSubMenu(
nullptr);
1399 while (d->contentModel->count() > 0)
1400 d->removeItem(0, d->itemAt(0), QQuickMenuPrivate::DestructionPolicy::Destroy);
1402 d->resetContentItem();
1406
1407
1408
1409
1410QQuickItem *QQuickMenu::itemAt(
int index)
const
1412 Q_D(
const QQuickMenu);
1413 return d->itemAt(index);
1417
1418
1419
1420
1421
1422
1423
1424void QQuickMenu::addItem(QQuickItem *item)
1427 insertItem(d->contentModel->count(), item);
1431
1432
1433
1434
1435
1436
1437
1438void QQuickMenu::insertItem(
int index, QQuickItem *item)
1443 const int count = d->contentModel->count();
1444 if (index < 0 || index > count)
1447 int oldIndex = d->contentModel->indexOf(item,
nullptr);
1448 if (oldIndex != -1) {
1449 if (oldIndex < index)
1451 if (oldIndex != index) {
1452 d->moveItem(oldIndex, index);
1455 d->insertItem(index, item);
1460
1461
1462
1463
1464void QQuickMenu::moveItem(
int from,
int to)
1467 const int count = d->contentModel->count();
1468 if (from < 0 || from > count - 1)
1470 if (to < 0 || to > count - 1)
1474 d->moveItem(from, to);
1478
1479
1480
1481
1482
1483void QQuickMenu::removeItem(QQuickItem *item)
1489 const int index = d->contentModel->indexOf(item,
nullptr);
1493 d->removeItem(index, item, QQuickMenuPrivate::DestructionPolicy::Destroy);
1497
1498
1499
1500
1501
1502
1503
1504QQuickItem *QQuickMenu::takeItem(
int index)
1507 const int count = d->contentModel->count();
1508 if (index < 0 || index >= count)
1511 QQuickItem *item = itemAt(index);
1513 d->removeItem(index, item);
1518
1519
1520
1521
1522
1523
1524QQuickMenu *QQuickMenu::menuAt(
int index)
const
1526 Q_D(
const QQuickMenu);
1527 QQuickMenuItem *item = qobject_cast<QQuickMenuItem *>(d->itemAt(index));
1531 return item->subMenu();
1535
1536
1537
1538
1539
1540
1541void QQuickMenu::addMenu(QQuickMenu *menu)
1544 insertMenu(d->contentModel->count(), menu);
1548
1549
1550
1551
1552
1553
1554void QQuickMenu::insertMenu(
int index, QQuickMenu *menu)
1560 insertItem(index, d->createItem(menu));
1564
1565
1566
1567
1568
1569void QQuickMenu::removeMenu(QQuickMenu *menu)
1575 const int count = d->contentModel->count();
1576 for (
int i = 0; i < count; ++i) {
1577 QQuickMenuItem *item = qobject_cast<QQuickMenuItem *>(d->itemAt(i));
1578 if (!item || item->subMenu() != menu)
1585 menu->deleteLater();
1589
1590
1591
1592
1593
1594
1595
1596
1597QQuickMenu *QQuickMenu::takeMenu(
int index)
1600 QQuickMenuItem *item = qobject_cast<QQuickMenuItem *>(d->itemAt(index));
1604 QQuickMenu *subMenu = item->subMenu();
1608 d->removeItem(index, item);
1609 item->deleteLater();
1615
1616
1617
1618
1619
1620
1621QQuickAction *QQuickMenu::actionAt(
int index)
const
1623 Q_D(
const QQuickMenu);
1624 if (!
const_cast<QQuickMenuPrivate *>(d)->maybeNativeHandle()) {
1625 QQuickAbstractButton *item = qobject_cast<QQuickAbstractButton *>(d->itemAt(index));
1629 return item->action();
1631 if (index < 0 || index >= d->nativeItems.size())
1634 return d->nativeItems.at(index)->action();
1639
1640
1641
1642
1643
1644
1645void QQuickMenu::addAction(QQuickAction *action)
1648 insertAction(d->contentModel->count(), action);
1652
1653
1654
1655
1656
1657
1658void QQuickMenu::insertAction(
int index, QQuickAction *action)
1664 insertItem(index, d->createItem(action));
1668
1669
1670
1671
1672
1673void QQuickMenu::removeAction(QQuickAction *action)
1679 const int count = d->contentModel->count();
1680 for (
int i = 0; i < count; ++i) {
1681 QQuickMenuItem *item = qobject_cast<QQuickMenuItem *>(d->itemAt(i));
1682 if (!item || item->action() != action)
1689 action->deleteLater();
1693
1694
1695
1696
1697
1698
1699
1700
1701QQuickAction *QQuickMenu::takeAction(
int index)
1704 QQuickMenuItem *item = qobject_cast<QQuickMenuItem *>(d->itemAt(index));
1708 QQuickAction *action = item->action();
1712 d->removeItem(index, item);
1713 item->deleteLater();
1717bool QQuickMenu::isVisible()
const
1719 Q_D(
const QQuickMenu);
1720 if (d->maybeNativeHandle())
1722 return QQuickPopup::isVisible();
1725void QQuickMenu::setVisible(
bool visible)
1728 if (visible == d->visible)
1730 if (visible && !parentItem()) {
1731 qmlWarning(
this) <<
"cannot show menu: parent is null";
1737 auto *window =
this->window();
1739 QQuickWindowPrivate::get(window)->rmbContextMenuEventEnabled =
false;
1744 if (!d->parentMenu) {
1745 QQuickOverlay *overlay = QQuickOverlay::overlay(window);
1747 const QList<QQuickPopup *> allPopups = QQuickOverlayPrivate::get(overlay)->allPopups;
1748 for (
auto *popup : allPopups) {
1749 if (popup !=
this && qobject_cast<QQuickMenu *>(popup))
1756 if (visible && ((d->useNativeMenu() && !d->maybeNativeHandle())
1757 || (!d->useNativeMenu() && d->maybeNativeHandle()))) {
1761 qCDebug(lcNativeMenus) <<
"setVisible called - useNativeMenu:" << d->useNativeMenu()
1762 <<
"maybeNativeHandle:" << d->maybeNativeHandle();
1763 d->syncWithUseNativeMenu();
1765 if (d->maybeNativeHandle()) {
1766 d->setNativeMenuVisible(visible);
1772 QQuickPopup::setVisible(visible);
1776
1777
1778
1779
1780
1781
1782
1783
1784
1785
1786
1787
1788
1789
1790
1791
1792
1793
1794
1795
1796QVariant QQuickMenu::contentModel()
const
1798 Q_D(
const QQuickMenu);
1799 return QVariant::fromValue(d->contentModel);
1803
1804
1805
1806
1807
1808
1809
1810
1811
1812
1813
1814
1815
1816
1817QQmlListProperty<QObject> QQuickMenu::contentData()
1820 if (!d->contentItem)
1821 QQuickControlPrivate::get(d->popupItem)->executeContentItem();
1822 return QQmlListProperty<QObject>(
this,
nullptr,
1823 QQuickMenuPrivate::contentData_append,
1824 QQuickMenuPrivate::contentData_count,
1825 QQuickMenuPrivate::contentData_at,
1826 QQuickMenuPrivate::contentData_clear);
1830
1831
1832
1833
1834
1835
1836
1837
1838QString QQuickMenu::title()
const
1840 Q_D(
const QQuickMenu);
1844void QQuickMenu::setTitle(
const QString &title)
1847 if (title == d->title)
1851 d->handle->setText(title);
1852 emit titleChanged(title);
1856
1857
1858
1859
1860
1861
1862
1863
1864
1865
1866
1867
1868
1869
1870
1872QQuickIcon QQuickMenu::icon()
const
1874 Q_D(
const QQuickMenu);
1878void QQuickMenu::setIcon(
const QQuickIcon &icon)
1881 if (icon == d->icon)
1884 d->icon.ensureRelativeSourceResolved(
this);
1885 emit iconChanged(icon);
1889
1890
1891
1892
1893
1894
1895
1896
1897
1898
1899
1900
1901
1902
1903
1904bool QQuickMenu::cascade()
const
1906 Q_D(
const QQuickMenu);
1910void QQuickMenu::setCascade(
bool cascade)
1913 if (d->cascade == cascade)
1915 d->cascade = cascade;
1917 d->resolveParentItem();
1918 emit cascadeChanged(cascade);
1921void QQuickMenu::resetCascade()
1925 setCascade(d->parentMenu->cascade());
1927 setCascade(shouldCascade());
1931
1932
1933
1934
1935
1936
1937
1938
1939
1940
1941
1942
1943
1944
1945
1946qreal QQuickMenu::overlap()
const
1948 Q_D(
const QQuickMenu);
1952void QQuickMenu::setOverlap(qreal overlap)
1955 if (d->overlap == overlap)
1957 d->overlap = overlap;
1958 emit overlapChanged();
1962
1963
1964
1965
1966
1967
1968
1969
1970
1971
1972
1973
1974
1975
1976
1977
1978
1979
1980
1981
1982
1983QQmlComponent *QQuickMenu::delegate()
const
1985 Q_D(
const QQuickMenu);
1989void QQuickMenu::setDelegate(QQmlComponent *delegate)
1992 if (d->delegate == delegate)
1995 d->delegate = delegate;
1996 emit delegateChanged();
2000
2001
2002
2003
2004
2005
2006
2007
2008
2009
2010
2011int QQuickMenu::currentIndex()
const
2013 Q_D(
const QQuickMenu);
2014 return d->currentIndex;
2017void QQuickMenu::setCurrentIndex(
int index)
2020 d->setCurrentIndex(index, Qt::OtherFocusReason);
2024
2025
2026
2027
2028
2029
2030int QQuickMenu::count()
const
2032 Q_D(
const QQuickMenu);
2033 return d->contentModel->count();
2036void QQuickMenuPrivate::popup(QQuickItem *menuItem)
2041 QQmlNullableValue<QPointF> pos;
2042#if QT_CONFIG(cursor)
2043 if (parentItem && QGuiApplicationPrivate::platformIntegration()->hasCapability(QPlatformIntegration::MultipleWindows))
2044 pos = parentItem->mapFromGlobal(QCursor::pos());
2048 if (!pos.isValid() && parentItem)
2049 pos = QPointF((parentItem->width() - q->width()) / 2, (parentItem->height() - q->height()) / 2);
2051 q->popup(pos.isValid() ? pos.value() : QPointF(), menuItem);
2054void QQuickMenu::popup(
const QPointF &position, QQuickItem *menuItem)
2058#if QT_CONFIG(cursor)
2060 offset = d->popupItem->mapFromItem(menuItem, QPointF(0, 0)).y();
2062 setPosition(position - QPointF(0, offset));
2065 d->setCurrentIndex(d->contentModel->indexOf(menuItem,
nullptr), Qt::PopupFocusReason);
2067 d->setCurrentIndex(-1, Qt::PopupFocusReason);
2073
2074
2075
2076
2077
2078
2079
2080
2081
2082
2083
2084
2085
2088
2089
2090
2091
2092
2093
2094
2095
2096
2097
2098
2099
2100
2103
2104
2105
2106
2107
2108
2109
2110
2111
2112
2113
2114
2115
2117void QQuickMenu::popup(QQuickItem *parent, qreal x, qreal y, QQuickItem *menuItem)
2119 popup(parent, QPointF {x, y}, menuItem);
2122void QQuickMenu::popup(QQuickItem *parent,
const QPointF &position, QQuickItem *menuItem)
2125 if (parent && !d->popupItem->isAncestorOf(parent))
2126 setParentItem(parent);
2127 popup(position, menuItem);
2130void QQuickMenu::popup(QQuickItem *parent, QQuickItem *menuItem)
2133 QQuickItem *parentItem =
nullptr;
2134 if (parent && !d->popupItem->isAncestorOf(parent))
2135 parentItem = parent;
2137 setParentItem(parentItem);
2143void QQuickMenu::popup(QQuickItem *parent)
2146 QQuickItem *menuItem =
nullptr;
2148 if (!d->popupItem->isAncestorOf(parent))
2149 setParentItem(parent);
2150 if (d->popupItem->isAncestorOf(parent))
2156void QQuickMenu::popup(qreal x, qreal y, QQuickItem *menuItem)
2158 popup(QPointF {x, y}, menuItem);
2162
2163
2164
2165
2166
2167
2168
2169
2170
2171
2172
2173
2174
2175
2176void QQuickMenu::dismiss()
2178 QQuickMenu *menu =
this;
2181 menu = QQuickMenuPrivate::get(menu)->parentMenu;
2185void QQuickMenu::componentComplete()
2188 QQuickPopup::componentComplete();
2190 d->updateTextPadding();
2191 d->syncWithUseNativeMenu();
2194void QQuickMenu::contentItemChange(QQuickItem *newItem, QQuickItem *oldItem)
2197 QQuickPopup::contentItemChange(newItem, oldItem);
2200 QQuickItemPrivate::get(oldItem)->removeItemChangeListener(d, QQuickItemPrivate::Children);
2201 QQuickItemPrivate::get(newItem)->removeItemChangeListener(d, QQuickItemPrivate::Destroyed);
2202 QQuickItemPrivate::get(oldItem)->removeItemChangeListener(d, QQuickItemPrivate::Geometry);
2205 QQuickItemPrivate::get(newItem)->addItemChangeListener(d, QQuickItemPrivate::Children);
2206 QQuickItemPrivate::get(newItem)->addItemChangeListener(d, QQuickItemPrivate::Destroyed);
2207 QQuickItemPrivate::get(newItem)->updateOrAddGeometryChangeListener(d, QQuickGeometryChange::Width);
2210 d->contentItem = newItem;
2213void QQuickMenu::itemChange(QQuickItem::ItemChange change,
const QQuickItem::ItemChangeData &data)
2216 QQuickPopup::itemChange(change, data);
2219 case QQuickItem::ItemVisibleHasChanged:
2220 if (!data.boolValue && d->cascade) {
2223 d->setCurrentIndex(-1, Qt::OtherFocusReason);
2231void QQuickMenu::keyPressEvent(QKeyEvent *event)
2234 QQuickPopup::keyPressEvent(event);
2242 switch (event->key()) {
2244 if (!d->activatePreviousItem())
2245 d->propagateKeyEvent(event);
2249 d->activateNextItem();
2255 if (d->popupItem->isMirrored() == (event->key() == Qt::Key_Right)) {
2256 if (d->parentMenu && d->currentItem) {
2258 d->parentMenu->open();
2263 if (QQuickMenu *subMenu = d->currentSubMenu()) {
2264 auto subMenuPrivate = QQuickMenuPrivate::get(subMenu);
2265 subMenuPrivate->popup(subMenuPrivate->firstEnabledMenuItem());
2269 if (!event->isAccepted())
2270 d->propagateKeyEvent(event);
2273#if QT_CONFIG(shortcut)
2277 if (!QKeySequence::mnemonic(QStringLiteral(
"&A")).isEmpty())
2286#if QT_CONFIG(shortcut)
2287 if (event->modifiers() == Qt::NoModifier) {
2288 for (
int i = 0; i < count(); ++i) {
2289 QQuickAbstractButton *item = qobject_cast<QQuickAbstractButton*>(d->itemAt(i));
2292 const QKeySequence keySequence = QKeySequence::mnemonic(item->text());
2293 if (keySequence.isEmpty())
2295 if (keySequence[0].key() == event->key()) {
2304void QQuickMenu::timerEvent(QTimerEvent *event)
2307 if (event->timerId() == d->hoverTimer) {
2308 if (QQuickMenu *subMenu = d->currentSubMenu())
2310 d->stopHoverTimer();
2313 QQuickPopup::timerEvent(event);
2316QFont QQuickMenu::defaultFont()
const
2318 return QQuickTheme::font(QQuickTheme::Menu);
2321#if QT_CONFIG(accessibility)
2322QAccessible::Role QQuickMenu::accessibleRole()
const
2324 return QAccessible::PopupMenu;
2330#include "moc_qquickmenu_p.cpp"