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();
290#if QT_CONFIG(wayland)
291 extendedWindowType = QNativeInterface::Private::QWaylandWindow::Menu;
295void QQuickMenuPrivate::init()
298 contentModel =
new QQmlObjectModel(q);
301QQuickMenu *QQuickMenuPrivate::rootMenu()
const
303 Q_Q(
const QQuickMenu);
304 const QQuickMenu *rootMenu = q;
305 const QObject *p = q->parent();
307 if (
auto menu = qobject_cast<
const QQuickMenu *>(p))
312 return const_cast<QQuickMenu *>(rootMenu);
315QQuickPopup::PopupType QQuickMenuPrivate::resolvedPopupType()
const
319 QQuickMenu *root = rootMenu();
320 QQuickMenuPrivate *root_d = QQuickMenuPrivate::get(rootMenu());
322#if QT_CONFIG(quicktemplates2_container)
323 if (
auto menuBar = QQuickMenuPrivate::get(root)->menuBar.get()) {
328 if (QQuickMenuBarPrivate::get(menuBar)->useNativeMenu(q_func()))
329 return QQuickPopup::Native;
334 if (root_d->maybeNativeHandle()) {
335 return QQuickPopup::Native;
336 }
else if (!root_d->triedToCreateNativeMenu) {
342 if (root->popupType() == QQuickPopup::Native
343 && !QGuiApplication::testAttribute(Qt::AA_DontUseNativeMenuWindows)) {
344 return QQuickPopup::Native;
352 const auto type = root_d->QQuickPopupPrivate::resolvedPopupType();
353 Q_ASSERT(type != QQuickPopup::Native);
357bool QQuickMenuPrivate::useNativeMenu()
const
359 return resolvedPopupType() == QQuickPopup::Native;
362QPlatformMenu *QQuickMenuPrivate::nativeHandle()
364 Q_ASSERT(handle || useNativeMenu());
365 if (!handle && !triedToCreateNativeMenu)
370QPlatformMenu *QQuickMenuPrivate::maybeNativeHandle()
const
375bool QQuickMenuPrivate::createNativeMenu()
379 qCDebug(lcNativeMenus) <<
"createNativeMenu called on" << q;
381 if (
auto menuBar = QQuickMenuPrivate::get(rootMenu())->menuBar) {
382#if QT_CONFIG(quicktemplates2_container)
383 auto menuBarPrivate = QQuickMenuBarPrivate::get(menuBar);
384 if (menuBarPrivate->useNativeMenuBar()) {
385 qCDebug(lcNativeMenus) <<
"- creating native menu from native menubar";
386 if (QPlatformMenuBar *menuBarHandle = menuBarPrivate->nativeHandle())
387 handle.reset(menuBarHandle->createMenu());
393 QPlatformMenu *parentMenuHandle(parentMenu ? get(parentMenu)->handle.get() :
nullptr);
394 if (parentMenu && parentMenuHandle) {
395 qCDebug(lcNativeMenus) <<
"- creating native sub-menu";
396 handle.reset(parentMenuHandle->createSubMenu());
398 qCDebug(lcNativeMenus) <<
"- creating native menu";
399 handle.reset(QGuiApplicationPrivate::platformTheme()->createPlatformMenu());
403 triedToCreateNativeMenu =
true;
408 q->connect(handle.get(), &QPlatformMenu::aboutToShow, q, [q,
this](){
409 emit q->aboutToShow();
411 emit q->visibleChanged();
412 emit q->openedChanged();
415 q->connect(handle.get(), &QPlatformMenu::aboutToHide, q, [q](){
416 qCDebug(lcNativeMenus) <<
"QPlatformMenu::aboutToHide called; about to call setVisible(false) on Menu";
417 emit q->aboutToHide();
423 q->connect(handle.get(), &QPlatformMenu::aboutToHide, q, [q,
this](){
425 emit q->visibleChanged();
426 emit q->openedChanged();
428 }, Qt::QueuedConnection);
430 recursivelyCreateNativeMenuItems(q);
431 syncWithNativeMenu();
438 if (nativeItems.isEmpty())
439 return QStringLiteral(
"(Empty)");
442 QTextStream debug(&str);
443 for (
const auto *nativeItem : nativeItems)
444 debug << nativeItem->debugText() <<
", ";
446 if (!nativeItems.isEmpty())
451void QQuickMenuPrivate::syncWithNativeMenu()
454 if (!complete || !handle)
457 qCDebug(lcNativeMenus).nospace() <<
"syncWithNativeMenu called on " << q
458 <<
" (complete: " << complete <<
" visible: " << visible <<
") - "
459 <<
"syncing " << nativeItems.size() <<
" item(s)...";
463 handle->setText(title);
464 handle->setEnabled(q->isEnabled());
465 handle->setMinimumWidth(q->implicitWidth());
467 handle->setFont(q->font());
485 for (QQuickNativeMenuItem *item : std::as_const(nativeItems)) {
486 qCDebug(lcNativeMenus) <<
"- syncing" << item <<
"action" << item->action()
487 <<
"sub-menu" << item->subMenu() << item->debugText();
491 qCDebug(lcNativeMenus) <<
"... finished syncing" << q;
495
496
497
498
499
500
501
502void QQuickMenuPrivate::removeNativeMenu()
505 const int qtyItemsToRemove = nativeItems.size();
506 if (qtyItemsToRemove != 0)
507 Q_ASSERT(q->count() == qtyItemsToRemove);
508 for (
int i = 0; i < qtyItemsToRemove; ++i)
510 Q_ASSERT(nativeItems.isEmpty());
517void QQuickMenuPrivate::syncWithUseNativeMenu()
522 if (q->isVisible() || parentMenu)
525 if (maybeNativeHandle() && !useNativeMenu()) {
529 }
else if (useNativeMenu()) {
530 Q_ASSERT(nativeItems.isEmpty());
538 QQuickWindow *quickWindow = qobject_cast<QQuickWindow *>(window);
540 QWindow *renderWindow = QQuickRenderControl::renderWindowFor(quickWindow, offset);
547void QQuickMenuPrivate::setNativeMenuVisible(
bool visible)
550 qCDebug(lcNativeMenus) <<
"setNativeMenuVisible called with visible" << visible;
552 emit q->aboutToShow();
554 emit q->aboutToHide();
556 this->visible = visible;
557 syncWithNativeMenu();
561 QWindow *window =
nullptr;
563 window = effectiveWindow(parentItem->window(), &offset);
565 lastDevicePixelRatio = window ? window->devicePixelRatio() : qGuiApp->devicePixelRatio();
567 const QPointF globalPos = parentItem->mapToGlobal(x, y);
568 const QPoint windowPos = window ? window->mapFromGlobal(globalPos.toPoint()) : parentItem->mapToScene(QPoint(x, y)).toPoint();
569 QRect targetRect(windowPos, QSize(0, 0));
570 auto *daPriv = QQuickItemPrivate::get(parentItem)->deliveryAgentPrivate();
577 if (QPointerEvent *openingEvent = daPriv->eventInDelivery()) {
578 auto *devPriv = QPointingDevicePrivate::get(
const_cast<QPointingDevice *>(openingEvent->pointingDevice()));
579 for (
const auto &pt : std::as_const(openingEvent->points())) {
580 qCDebug(lcNativeMenus) <<
"popup over" << window <<
"its DA" << daPriv->q_func() <<
"opening due to" << openingEvent
581 <<
"with grabbers" << openingEvent->exclusiveGrabber(pt) << openingEvent->passiveGrabbers(pt);
583 if (
auto *opener = openingEvent->exclusiveGrabber(pt))
584 devPriv->removeGrabber(opener,
true);
585 for (
auto passiveGrabber : openingEvent->passiveGrabbers(pt)) {
586 if (
auto *opener = passiveGrabber.get())
587 devPriv->removeGrabber(opener,
true);
591 handle->showPopup(window, QHighDpi::toNativeLocalPosition(targetRect, window),
599void QQuickMenuPrivate::makeEditMenu()
601 handle->setMenuType(QPlatformMenu::EditMenu);
604QQuickItem *QQuickMenuPrivate::itemAt(
int index)
const
606 return qobject_cast<QQuickItem *>(contentModel->get(index));
609void QQuickMenuPrivate::insertItem(
int index, QQuickItem *item)
611 qCDebug(lcMenu) <<
"insert called with index" << index <<
"item" << item;
614 contentData.append(item);
615 item->setParentItem(contentItem);
616 QQuickItemPrivate::get(item)->setCulled(
true);
619 QQuickItemPrivate::get(item)->addItemChangeListener(
this, QQuickItemPrivate::Destroyed | QQuickItemPrivate::Parent);
620 QQuickItemPrivate::get(item)->updateOrAddGeometryChangeListener(
this, QQuickGeometryChange::Width);
621 contentModel->insert(index, item);
623 QQuickMenuItem *menuItem = qobject_cast<QQuickMenuItem *>(item);
625 QQuickMenuItemPrivate::get(menuItem)->setMenu(q);
626 if (QQuickMenu *subMenu = menuItem->subMenu())
627 QQuickMenuPrivate::get(subMenu)->setParentMenu(q);
628 QObjectPrivate::connect(menuItem, &QQuickMenuItem::triggered,
this, &QQuickMenuPrivate::onItemTriggered);
629 QObjectPrivate::connect(menuItem, &QQuickMenuItem::implicitTextPaddingChanged,
this, &QQuickMenuPrivate::updateTextPadding);
630 QObjectPrivate::connect(menuItem, &QQuickMenuItem::visibleChanged,
this, &QQuickMenuPrivate::updateTextPadding);
631 QObjectPrivate::connect(menuItem, &QQuickItem::activeFocusChanged,
this, &QQuickMenuPrivate::onItemActiveFocusChanged);
632 QObjectPrivate::connect(menuItem, &QQuickControl::hoveredChanged,
this, &QQuickMenuPrivate::onItemHovered);
635 if (maybeNativeHandle() && complete)
636 maybeCreateAndInsertNativeItem(index, item);
638 if (lcMenu().isDebugEnabled())
639 printContentModelItems();
644void QQuickMenuPrivate::maybeCreateAndInsertNativeItem(
int index, QQuickItem *item)
648 Q_ASSERT_X(handle, Q_FUNC_INFO, qPrintable(QString::fromLatin1(
649 "Expected %1 to be using a native menu").arg(QDebug::toString(q))));
650 std::unique_ptr<QQuickNativeMenuItem> nativeMenuItem(QQuickNativeMenuItem::createFromNonNativeItem(q, item));
651 if (!nativeMenuItem) {
653 qmlWarning(q) <<
"Native menu failed to create a native menu item for item at index" << index;
657 nativeItems.insert(index, nativeMenuItem.get());
661 if (nativeMenuItem->handle()) {
662 QQuickNativeMenuItem *before = nativeItems.value(index + 1);
663 handle->insertMenuItem(nativeMenuItem->handle(), before ? before->handle() :
nullptr);
664 qCDebug(lcNativeMenus) <<
"inserted native menu item at index" << index
665 <<
"before" << (before ? before->debugText() : QStringLiteral(
"null"));
667 if (nativeMenuItem->subMenu() && QQuickMenuPrivate::get(nativeMenuItem->subMenu())->nativeItems.count()
668 < nativeMenuItem->subMenu()->count()) {
674 recursivelyCreateNativeMenuItems(nativeMenuItem->subMenu());
678 nativeMenuItem.release();
680 qCDebug(lcNativeMenus) <<
"nativeItems now contains the following items:"
681 << nativeMenuItemListToString(nativeItems);
684void QQuickMenuPrivate::moveItem(
int from,
int to)
686 contentModel->move(from, to);
688 if (maybeNativeHandle())
689 nativeItems.move(from, to);
693
694
695
696
697
698
699
700
701
702void QQuickMenuPrivate::removeItem(
int index, QQuickItem *item, DestructionPolicy destructionPolicy)
704 qCDebug(lcMenu) <<
"removeItem called with index" << index <<
"item" << item;
706 if (maybeNativeHandle())
707 removeNativeItem(index);
709 contentData.removeOne(item);
711 QQuickItemPrivate::get(item)->removeItemChangeListener(
this, QQuickItemPrivate::Destroyed | QQuickItemPrivate::Parent);
712 QQuickItemPrivate::get(item)->removeItemChangeListener(
this, QQuickItemPrivate::Geometry);
713 item->setParentItem(
nullptr);
714 contentModel->remove(index);
716 QQuickMenuItem *menuItem = qobject_cast<QQuickMenuItem *>(item);
718 QQuickMenuItemPrivate::get(menuItem)->setMenu(
nullptr);
719 if (QQuickMenu *subMenu = menuItem->subMenu())
720 QQuickMenuPrivate::get(subMenu)->setParentMenu(
nullptr);
721 QObjectPrivate::disconnect(menuItem, &QQuickMenuItem::triggered,
this, &QQuickMenuPrivate::onItemTriggered);
722 QObjectPrivate::disconnect(menuItem, &QQuickMenuItem::implicitTextPaddingChanged,
this, &QQuickMenuPrivate::updateTextPadding);
723 QObjectPrivate::disconnect(menuItem, &QQuickMenuItem::visibleChanged,
this, &QQuickMenuPrivate::updateTextPadding);
724 QObjectPrivate::disconnect(menuItem, &QQuickItem::activeFocusChanged,
this, &QQuickMenuPrivate::onItemActiveFocusChanged);
725 QObjectPrivate::disconnect(menuItem, &QQuickControl::hoveredChanged,
this, &QQuickMenuPrivate::onItemHovered);
728 if (destructionPolicy == DestructionPolicy::Destroy)
731 if (lcMenu().isDebugEnabled())
732 printContentModelItems();
736
737
738
739
740
741
742
743
744
745void QQuickMenuPrivate::removeNativeItem(
int index, SyncPolicy syncPolicy)
750 Q_ASSERT_X(index >= 0 && index < nativeItems.size(), Q_FUNC_INFO, qPrintable(QString::fromLatin1(
751 "index %1 is less than 0 or greater than or equal to %2").arg(index).arg(nativeItems.size())));
755 std::unique_ptr<QQuickNativeMenuItem> nativeItem(nativeItems.takeAt(index));
756 qCDebug(lcNativeMenus) <<
"removing native item" << nativeItem->debugText() <<
"at index" << index
757 <<
"from" << q_func() <<
"...";
758 QQuickMenu *subMenu = nativeItem->subMenu();
760 Q_ASSERT(nativeItem->handle());
761 auto *subMenuPrivate = QQuickMenuPrivate::get(subMenu);
762 while (!subMenuPrivate->nativeItems.isEmpty()) {
763 subMenuPrivate->removeNativeItem(0, SyncPolicy::DoNotSync);
767 Q_ASSERT(nativeItem->handle());
768 handle->removeMenuItem(nativeItem->handle());
769 if (syncPolicy == SyncPolicy::Sync)
770 syncWithNativeMenu();
773 auto *subMenuPrivate = QQuickMenuPrivate::get(subMenu);
779 subMenuPrivate->resetNativeData();
782 qCDebug(lcNativeMenus).nospace() <<
"... after removing item at index " << index
783 <<
", nativeItems now contains the following items: " << nativeMenuItemListToString(nativeItems);
786void QQuickMenuPrivate::resetNativeData()
788 qCDebug(lcNativeMenus) <<
"resetNativeData called on" << q_func();
790 triedToCreateNativeMenu =
false;
793void QQuickMenuPrivate::recursivelyCreateNativeMenuItems(QQuickMenu *menu)
795 auto *menuPrivate = QQuickMenuPrivate::get(menu);
798 if (!menuPrivate->triedToCreateNativeMenu)
799 menuPrivate->createNativeMenu();
801 const int qtyItemsToCreate = menuPrivate->contentModel->count();
802 if (menuPrivate->nativeItems.count() == qtyItemsToCreate)
805 qCDebug(lcNativeMenus) <<
"recursively creating" << qtyItemsToCreate <<
"menu item(s) for" << menu;
806 Q_ASSERT(menuPrivate->nativeItems.count() == 0);
807 for (
int i = 0; i < qtyItemsToCreate; ++i) {
808 QQuickItem *item = menu->itemAt(i);
809 menuPrivate->maybeCreateAndInsertNativeItem(i, item);
810 auto *menuItem = qobject_cast<QQuickMenuItem *>(item);
811 if (menuItem && menuItem->subMenu())
812 recursivelyCreateNativeMenuItems(menuItem->subMenu());
816void QQuickMenuPrivate::printContentModelItems()
const
818 qCDebug(lcMenu) <<
"contentModel now contains:";
819 for (
int i = 0; i < contentModel->count(); ++i)
820 qCDebug(lcMenu) <<
"-" << itemAt(i);
823QQuickItem *QQuickMenuPrivate::beginCreateItem()
829 QQmlContext *context = delegate->creationContext();
831 context = qmlContext(q);
833 QObject *object = delegate->beginCreate(context);
834 QQuickItem *item = qobject_cast<QQuickItem *>(object);
838 QQml_setParent_noEvent(item, q);
843void QQuickMenuPrivate::completeCreateItem()
848 delegate->completeCreate();
851QQuickItem *QQuickMenuPrivate::createItem(QQuickMenu *menu)
853 QQuickItem *item = beginCreateItem();
854 if (QQuickMenuItem *menuItem = qobject_cast<QQuickMenuItem *>(item))
855 QQuickMenuItemPrivate::get(menuItem)->setSubMenu(menu);
856 completeCreateItem();
860QQuickItem *QQuickMenuPrivate::createItem(QQuickAction *action)
862 QQuickItem *item = beginCreateItem();
863 if (QQuickAbstractButton *button = qobject_cast<QQuickAbstractButton *>(item))
864 button->setAction(action);
865 completeCreateItem();
869void QQuickMenuPrivate::resizeItem(QQuickItem *item)
871 if (!item || !contentItem)
874 QQuickItemPrivate *p = QQuickItemPrivate::get(item);
875 if (!p->widthValid()) {
876 item->setWidth(contentItem->width());
877 p->widthValidFlag =
false;
881void QQuickMenuPrivate::resizeItems()
886 for (
int i = 0; i < contentModel->count(); ++i)
887 resizeItem(itemAt(i));
890void QQuickMenuPrivate::itemChildAdded(QQuickItem *, QQuickItem *child)
893 if (!QQuickItemPrivate::get(child)->isTransparentForPositioner() && !contentData.contains(child))
894 insertItem(contentModel->count(), child);
897void QQuickMenuPrivate::itemParentChanged(QQuickItem *item, QQuickItem *parent)
901 removeItem(contentModel->indexOf(item,
nullptr), item);
904void QQuickMenuPrivate::itemSiblingOrderChanged(QQuickItem *)
908 QList<QQuickItem *> siblings = contentItem->childItems();
911 for (
int i = 0; i < siblings.size(); ++i) {
912 QQuickItem* sibling = siblings.at(i);
913 if (QQuickItemPrivate::get(sibling)->isTransparentForPositioner())
915 int index = contentModel->indexOf(sibling,
nullptr);
916 q->moveItem(index, to++);
920void QQuickMenuPrivate::itemDestroyed(QQuickItem *item)
922 if (item == contentItem) {
925 QQuickPopupPrivate::itemDestroyed(item);
927 int index = contentModel->indexOf(item,
nullptr);
929 removeItem(index, item);
934void QQuickMenuPrivate::itemGeometryChanged(QQuickItem *item, QQuickGeometryChange,
const QRectF &)
939 if (item == contentItem) {
950QQuickPopupPositioner *QQuickMenuPrivate::getPositioner()
954 positioner =
new QQuickMenuPositioner(q);
960 QQuickMenu *menu =
static_cast<QQuickMenu *>(popup());
961 QQuickMenuPrivate *menu_d = QQuickMenuPrivate::get(menu);
963 if (QQuickMenu *parentMenu = menu_d->parentMenu) {
964 if (menu_d->cascade) {
967 if (menu_d->popupItem->isMirrored()) {
968 const qreal distanceToFrame = parentMenu->leftPadding();
969 const qreal menuX = -menu->width() - distanceToFrame + menu->overlap();
970 menu->setPosition({menuX, -menu->topPadding()});
971 }
else if (menu_d->parentItem) {
972 const qreal distanceToFrame = parentMenu->rightPadding();
973 const qreal menuX = menu_d->parentItem->width() + distanceToFrame - menu->overlap();
974 menu->setPosition({menuX, -menu->topPadding()});
977 const qreal menuX = parentMenu->x() + (parentMenu->width() - menu->width()) / 2;
978 const qreal menuY = parentMenu->y() + (parentMenu->height() - menu->height()) / 2;
979 menu->setPosition({menuX, menuY});
983 QQuickPopupPositioner::reposition();
986bool QQuickMenuPrivate::prepareEnterTransition()
989 if (parentMenu && !cascade)
994 allowHorizontalFlip = cascade && parentMenu;
1006 auto *contentItemAsListView = qobject_cast<QQuickListView *>(contentItem);
1007 if (contentItemAsListView) {
1008 if (QQuickItemViewPrivate::get(contentItemAsListView)->currentChanges.hasPendingChanges())
1009 contentItemAsListView->forceLayout();
1012 if (!QQuickPopupPrivate::prepareEnterTransition())
1015 if (!hasClosePolicy) {
1016 if (cascade && parentMenu)
1017 closePolicy = cascadingSubMenuClosePolicy;
1019 q->resetClosePolicy();
1024bool QQuickMenuPrivate::prepareExitTransition()
1026 if (!QQuickPopupPrivate::prepareExitTransition())
1031 QQuickMenu *subMenu = currentSubMenu();
1033 QPointer<QQuickMenuItem> currentSubMenuItem = QQuickMenuPrivate::get(subMenu)->currentItem;
1035 subMenu = currentSubMenuItem ? currentSubMenuItem->subMenu() :
nullptr;
1040bool QQuickMenuPrivate::blockInput(QQuickItem *item,
const QPointF &point)
const
1043 return (cascade && parentMenu && contains(point)) || QQuickPopupPrivate::blockInput(item, point);
1046bool QQuickMenuPrivate::handlePress(QQuickItem *item,
const QPointF &point, ulong timestamp)
1050 return QQuickPopupPrivate::handlePress(item, point, timestamp)
1051 || (popupItem == item);
1056
1057
1058
1059
1060
1061
1062bool QQuickMenuPrivate::handleReleaseWithoutGrab(
const QEventPoint &eventPoint)
1064 const QPointF scenePos = eventPoint.scenePosition();
1065 if (!contains(scenePos))
1068 auto *list = qobject_cast<QQuickListView *>(contentItem);
1072 const QPointF listPos = list->mapFromScene(scenePos);
1074 auto *menuItem = qobject_cast<QQuickMenuItem *>(list->itemAt(listPos.x(), listPos.y()));
1075 if (menuItem && menuItem->isHighlighted()) {
1076 menuItem->animateClick();
1083void QQuickMenuPrivate::onItemHovered()
1086 QQuickAbstractButton *button = qobject_cast<QQuickAbstractButton *>(q->sender());
1087 if (!button || !button->isHovered() || !button->isEnabled() || QQuickAbstractButtonPrivate::get(button)->touchId != -1)
1090 QQuickMenuItem *oldCurrentItem = currentItem;
1092 int index = contentModel->indexOf(button,
nullptr);
1094 setCurrentIndex(index, Qt::OtherFocusReason);
1095 if (oldCurrentItem != currentItem) {
1096 if (oldCurrentItem) {
1097 QQuickMenu *subMenu = oldCurrentItem->subMenu();
1102 QQuickMenu *subMenu = currentItem->menu();
1103 if (subMenu && subMenu->cascade())
1110void QQuickMenuPrivate::onItemTriggered()
1113 QQuickMenuItem *item = qobject_cast<QQuickMenuItem *>(q->sender());
1117 if (QQuickMenu *subMenu = item->subMenu()) {
1118 auto subMenuPrivate = QQuickMenuPrivate::get(subMenu);
1119 subMenuPrivate->popup(subMenuPrivate->firstEnabledMenuItem());
1125void QQuickMenuPrivate::onItemActiveFocusChanged()
1128 QQuickItem *item = qobject_cast<QQuickItem*>(q->sender());
1129 if (!item->hasActiveFocus())
1132 int indexOfItem = contentModel->indexOf(item,
nullptr);
1133 QQuickControl *control = qobject_cast<QQuickControl *>(item);
1134 setCurrentIndex(indexOfItem, control ? control->focusReason() : Qt::OtherFocusReason);
1137void QQuickMenuPrivate::updateTextPadding()
1144 for (
int i = 0; i < q->count(); ++i) {
1145 if (
const auto menuItem = qobject_cast<QQuickMenuItem *>(itemAt(i)))
1146 if (menuItem->isVisible())
1147 padding = qMax(padding, menuItem->implicitTextPadding());
1150 if (padding == textPadding)
1153 textPadding = padding;
1155 for (
int i = 0; i < q->count(); ++i) {
1156 if (
const auto menuItem = qobject_cast<QQuickMenuItem *>(itemAt(i)))
1157 emit menuItem->textPaddingChanged();
1161QQuickMenu *QQuickMenuPrivate::currentSubMenu()
const
1166 return currentItem->subMenu();
1169void QQuickMenuPrivate::setParentMenu(QQuickMenu *parent)
1172 if (parentMenu == parent)
1176 QObject::disconnect(parentMenu.data(), &QQuickMenu::cascadeChanged, q, &QQuickMenu::setCascade);
1177 disconnect(parentMenu.data(), &QQuickMenu::parentChanged,
this, &QQuickMenuPrivate::resolveParentItem);
1180 QObject::connect(parent, &QQuickMenu::cascadeChanged, q, &QQuickMenu::setCascade);
1181 connect(parent, &QQuickMenu::parentChanged,
this, &QQuickMenuPrivate::resolveParentItem);
1184 parentMenu = parent;
1186 resolveParentItem();
1191 QQuickMenu *menu = QQuickMenuPrivate::get(subMenu)->parentMenu;
1192 for (
int i = 0; i < QQuickMenuPrivate::get(menu)->contentModel->count(); ++i) {
1193 QQuickMenuItem *item = qobject_cast<QQuickMenuItem *>(menu->itemAt(i));
1194 if (item && item->subMenu() == subMenu)
1200void QQuickMenuPrivate::resolveParentItem()
1204 q->resetParentItem();
1206 q->setParentItem(parentMenu->parentItem());
1208 q->setParentItem(findParentMenuItem(q));
1211void QQuickMenuPrivate::propagateKeyEvent(QKeyEvent *event)
1213 if (QQuickMenuItem *menuItem = qobject_cast<QQuickMenuItem *>(parentItem)) {
1214 if (QQuickMenu *menu = menuItem->menu())
1215 QQuickMenuPrivate::get(menu)->propagateKeyEvent(event);
1216#if QT_CONFIG(quicktemplates2_container)
1217 }
else if (QQuickMenuBarItem *menuBarItem = qobject_cast<QQuickMenuBarItem *>(parentItem)) {
1218 if (QQuickMenuBar *menuBar = menuBarItem->menuBar()) {
1220 QCoreApplication::sendEvent(menuBar, event);
1226void QQuickMenuPrivate::startHoverTimer()
1230 hoverTimer = q->startTimer(SUBMENU_DELAY);
1233void QQuickMenuPrivate::stopHoverTimer()
1239 q->killTimer(hoverTimer);
1243void QQuickMenuPrivate::setCurrentIndex(
int index, Qt::FocusReason reason)
1246 if (currentIndex == index)
1249 QQuickMenuItem *newCurrentItem = qobject_cast<QQuickMenuItem *>(itemAt(index));
1250 if (currentItem != newCurrentItem) {
1253 currentItem->setHighlighted(
false);
1254 if (!newCurrentItem && window) {
1255 QQuickItem *focusItem = QQuickItemPrivate::get(contentItem)->subFocusItem;
1257 auto *daPriv = QQuickWindowPrivate::get(window)->deliveryAgentPrivate();
1258 daPriv->clearFocusInScope(contentItem, focusItem, Qt::OtherFocusReason);
1262 if (newCurrentItem) {
1263 newCurrentItem->setHighlighted(
true);
1264 newCurrentItem->forceActiveFocus(reason);
1266 currentItem = newCurrentItem;
1269 currentIndex = index;
1270 emit q->currentIndexChanged();
1273bool QQuickMenuPrivate::activateNextItem()
1275 int index = currentIndex;
1276 int count = contentModel->count();
1277 while (++index < count) {
1278 QQuickItem *item = itemAt(index);
1279 if (!item || !item->activeFocusOnTab() || !item->isEnabled())
1281 setCurrentIndex(index, Qt::TabFocusReason);
1287bool QQuickMenuPrivate::activatePreviousItem()
1289 int index = currentIndex;
1290 while (--index >= 0) {
1291 QQuickItem *item = itemAt(index);
1292 if (!item || !item->activeFocusOnTab() || !item->isEnabled())
1294 setCurrentIndex(index, Qt::BacktabFocusReason);
1300QQuickMenuItem *QQuickMenuPrivate::firstEnabledMenuItem()
const
1302 for (
int i = 0; i < contentModel->count(); ++i) {
1303 QQuickItem *item = itemAt(i);
1304 if (!item || !item->isEnabled())
1307 QQuickMenuItem *menuItem = qobject_cast<QQuickMenuItem *>(item);
1316void QQuickMenuPrivate::contentData_append(QQmlListProperty<QObject> *prop, QObject *obj)
1318 QQuickMenu *q = qobject_cast<QQuickMenu *>(prop->object);
1319 QQuickMenuPrivate *p = QQuickMenuPrivate::get(q);
1321 QQuickItem *item = qobject_cast<QQuickItem *>(obj);
1323 if (QQuickAction *action = qobject_cast<QQuickAction *>(obj))
1324 item = p->createItem(action);
1325 else if (QQuickMenu *menu = qobject_cast<QQuickMenu *>(obj))
1326 item = p->createItem(menu);
1330 if (QQuickItemPrivate::get(item)->isTransparentForPositioner()) {
1331 QQuickItemPrivate::get(item)->addItemChangeListener(p, QQuickItemPrivate::SiblingOrder);
1332 item->setParentItem(p->contentItem);
1333 }
else if (p->contentModel->indexOf(item,
nullptr) == -1) {
1337 p->contentData.append(obj);
1341qsizetype QQuickMenuPrivate::contentData_count(QQmlListProperty<QObject> *prop)
1343 QQuickMenu *q =
static_cast<QQuickMenu *>(prop->object);
1344 return QQuickMenuPrivate::get(q)->contentData.size();
1347QObject *QQuickMenuPrivate::contentData_at(QQmlListProperty<QObject> *prop, qsizetype index)
1349 QQuickMenu *q =
static_cast<QQuickMenu *>(prop->object);
1350 return QQuickMenuPrivate::get(q)->contentData.value(index);
1353QPalette QQuickMenuPrivate::defaultPalette()
const
1355 return QQuickTheme::palette(QQuickTheme::Menu);
1358void QQuickMenuPrivate::contentData_clear(QQmlListProperty<QObject> *prop)
1360 QQuickMenu *q =
static_cast<QQuickMenu *>(prop->object);
1361 QQuickMenuPrivate::get(q)->contentData.clear();
1364void QQuickMenuPrivate::resetContentItem()
1367 QQuickItemPrivate::get(contentItem)->removeItemChangeListener(
this, QQuickItemPrivate::Children);
1368 QQuickItemPrivate::get(contentItem)->removeItemChangeListener(
this, QQuickItemPrivate::Destroyed);
1369 QQuickItemPrivate::get(contentItem)->removeItemChangeListener(
this, QQuickItemPrivate::Geometry);
1371 const auto children = contentItem->childItems();
1372 for (QQuickItem *child : std::as_const(children))
1373 QQuickItemPrivate::get(child)->removeItemChangeListener(
this, QQuickItemPrivate::SiblingOrder);
1374 contentItem =
nullptr;
1378QQuickMenu::QQuickMenu(QObject *parent)
1379 : QQuickPopup(*(
new QQuickMenuPrivate), parent)
1384 connect(d->contentModel, &QQmlObjectModel::countChanged,
this, &QQuickMenu::countChanged);
1387QQuickMenu::~QQuickMenu()
1390 qCDebug(lcNativeMenus) <<
"destroying" <<
this
1392 << d->contentModel->count()
1393 <<
"native item count:" << d->nativeItems.count();
1397 if (
auto *menuItem = qobject_cast<QQuickMenuItem *>(d->parentItem)) {
1398 if (menuItem->subMenu() ==
this) {
1399 auto *menuItemPriv = QQuickMenuItemPrivate::get(menuItem);
1400 menuItemPriv->setSubMenu(
nullptr);
1408 while (d->contentModel->count() > 0)
1409 d->removeItem(0, d->itemAt(0), QQuickMenuPrivate::DestructionPolicy::Destroy);
1411 d->resetContentItem();
1415
1416
1417
1418
1419QQuickItem *QQuickMenu::itemAt(
int index)
const
1421 Q_D(
const QQuickMenu);
1422 return d->itemAt(index);
1426
1427
1428
1429
1430
1431
1432
1433void QQuickMenu::addItem(QQuickItem *item)
1436 insertItem(d->contentModel->count(), item);
1440
1441
1442
1443
1444
1445
1446
1447void QQuickMenu::insertItem(
int index, QQuickItem *item)
1452 const int count = d->contentModel->count();
1453 if (index < 0 || index > count)
1456 int oldIndex = d->contentModel->indexOf(item,
nullptr);
1457 if (oldIndex != -1) {
1458 if (oldIndex < index)
1460 if (oldIndex != index) {
1461 d->moveItem(oldIndex, index);
1464 d->insertItem(index, item);
1469
1470
1471
1472
1473void QQuickMenu::moveItem(
int from,
int to)
1476 const int count = d->contentModel->count();
1477 if (from < 0 || from > count - 1)
1479 if (to < 0 || to > count - 1)
1483 d->moveItem(from, to);
1487
1488
1489
1490
1491
1492void QQuickMenu::removeItem(QQuickItem *item)
1498 const int index = d->contentModel->indexOf(item,
nullptr);
1502 d->removeItem(index, item, QQuickMenuPrivate::DestructionPolicy::Destroy);
1506
1507
1508
1509
1510
1511
1512
1513QQuickItem *QQuickMenu::takeItem(
int index)
1516 const int count = d->contentModel->count();
1517 if (index < 0 || index >= count)
1520 QQuickItem *item = itemAt(index);
1522 d->removeItem(index, item);
1527
1528
1529
1530
1531
1532
1533QQuickMenu *QQuickMenu::menuAt(
int index)
const
1535 Q_D(
const QQuickMenu);
1536 QQuickMenuItem *item = qobject_cast<QQuickMenuItem *>(d->itemAt(index));
1540 return item->subMenu();
1544
1545
1546
1547
1548
1549
1550void QQuickMenu::addMenu(QQuickMenu *menu)
1553 insertMenu(d->contentModel->count(), menu);
1557
1558
1559
1560
1561
1562
1563void QQuickMenu::insertMenu(
int index, QQuickMenu *menu)
1569 insertItem(index, d->createItem(menu));
1573
1574
1575
1576
1577
1578void QQuickMenu::removeMenu(QQuickMenu *menu)
1584 const int count = d->contentModel->count();
1585 for (
int i = 0; i < count; ++i) {
1586 QQuickMenuItem *item = qobject_cast<QQuickMenuItem *>(d->itemAt(i));
1587 if (!item || item->subMenu() != menu)
1594 menu->deleteLater();
1598
1599
1600
1601
1602
1603
1604
1605
1606QQuickMenu *QQuickMenu::takeMenu(
int index)
1609 QQuickMenuItem *item = qobject_cast<QQuickMenuItem *>(d->itemAt(index));
1613 QQuickMenu *subMenu = item->subMenu();
1617 d->removeItem(index, item);
1618 item->deleteLater();
1624
1625
1626
1627
1628
1629
1630QQuickAction *QQuickMenu::actionAt(
int index)
const
1632 Q_D(
const QQuickMenu);
1633 if (!
const_cast<QQuickMenuPrivate *>(d)->maybeNativeHandle()) {
1634 QQuickAbstractButton *item = qobject_cast<QQuickAbstractButton *>(d->itemAt(index));
1638 return item->action();
1640 if (index < 0 || index >= d->nativeItems.size())
1643 return d->nativeItems.at(index)->action();
1648
1649
1650
1651
1652
1653
1654void QQuickMenu::addAction(QQuickAction *action)
1657 insertAction(d->contentModel->count(), action);
1661
1662
1663
1664
1665
1666
1667void QQuickMenu::insertAction(
int index, QQuickAction *action)
1673 insertItem(index, d->createItem(action));
1677
1678
1679
1680
1681
1682void QQuickMenu::removeAction(QQuickAction *action)
1688 const int count = d->contentModel->count();
1689 for (
int i = 0; i < count; ++i) {
1690 QQuickMenuItem *item = qobject_cast<QQuickMenuItem *>(d->itemAt(i));
1691 if (!item || item->action() != action)
1698 action->deleteLater();
1702
1703
1704
1705
1706
1707
1708
1709
1710QQuickAction *QQuickMenu::takeAction(
int index)
1713 QQuickMenuItem *item = qobject_cast<QQuickMenuItem *>(d->itemAt(index));
1717 QQuickAction *action = item->action();
1721 d->removeItem(index, item);
1722 item->deleteLater();
1726bool QQuickMenu::isVisible()
const
1728 Q_D(
const QQuickMenu);
1729 if (d->maybeNativeHandle())
1731 return QQuickPopup::isVisible();
1734void QQuickMenu::setVisible(
bool visible)
1737 if (visible == d->visible)
1740 auto *window =
this->window();
1741 if (visible && window) {
1744 QQuickWindowPrivate::get(window)->rmbContextMenuEventEnabled =
false;
1749 if (!d->parentMenu) {
1750 QQuickOverlay *overlay = QQuickOverlay::overlay(window, parentItem());
1752 const QList<QQuickPopup *> allPopups = QQuickOverlayPrivate::get(overlay)->allPopups;
1753 for (
auto *popup : allPopups) {
1754 if (popup !=
this && qobject_cast<QQuickMenu *>(popup))
1761 if (visible && ((d->useNativeMenu() && !d->maybeNativeHandle())
1762 || (!d->useNativeMenu() && d->maybeNativeHandle()))) {
1766 qCDebug(lcNativeMenus) <<
"setVisible called - useNativeMenu:" << d->useNativeMenu()
1767 <<
"maybeNativeHandle:" << d->maybeNativeHandle();
1768 d->syncWithUseNativeMenu();
1770 if (d->maybeNativeHandle()) {
1771 d->setNativeMenuVisible(visible);
1777 QQuickPopup::setVisible(visible);
1781
1782
1783
1784
1785
1786
1787
1788
1789
1790
1791
1792
1793
1794
1795
1796
1797
1798
1799
1800
1801QVariant QQuickMenu::contentModel()
const
1803 Q_D(
const QQuickMenu);
1804 return QVariant::fromValue(d->contentModel);
1808
1809
1810
1811
1812
1813
1814
1815
1816
1817
1818
1819
1820
1821
1822QQmlListProperty<QObject> QQuickMenu::contentData()
1825 if (!d->contentItem)
1826 QQuickControlPrivate::get(d->popupItem)->executeContentItem();
1827 return QQmlListProperty<QObject>(
this,
nullptr,
1828 QQuickMenuPrivate::contentData_append,
1829 QQuickMenuPrivate::contentData_count,
1830 QQuickMenuPrivate::contentData_at,
1831 QQuickMenuPrivate::contentData_clear);
1835
1836
1837
1838
1839
1840
1841
1842
1843QString QQuickMenu::title()
const
1845 Q_D(
const QQuickMenu);
1849void QQuickMenu::setTitle(
const QString &title)
1852 if (title == d->title)
1856 d->handle->setText(title);
1857 emit titleChanged(title);
1861
1862
1863
1864
1865
1866
1867
1868
1869
1870
1871
1872
1873
1874
1875
1877QQuickIcon QQuickMenu::icon()
const
1879 Q_D(
const QQuickMenu);
1883void QQuickMenu::setIcon(
const QQuickIcon &icon)
1886 if (icon == d->icon)
1889 d->icon.ensureRelativeSourceResolved(
this);
1890 emit iconChanged(icon);
1894
1895
1896
1897
1898
1899
1900
1901
1902
1903
1904
1905
1906
1907
1908
1909bool QQuickMenu::cascade()
const
1911 Q_D(
const QQuickMenu);
1915void QQuickMenu::setCascade(
bool cascade)
1918 if (d->cascade == cascade)
1920 d->cascade = cascade;
1922 d->resolveParentItem();
1923 emit cascadeChanged(cascade);
1926void QQuickMenu::resetCascade()
1930 setCascade(d->parentMenu->cascade());
1932 setCascade(shouldCascade());
1936
1937
1938
1939
1940
1941
1942
1943
1944
1945
1946
1947
1948
1949
1950
1951qreal QQuickMenu::overlap()
const
1953 Q_D(
const QQuickMenu);
1957void QQuickMenu::setOverlap(qreal overlap)
1960 if (d->overlap == overlap)
1962 d->overlap = overlap;
1963 emit overlapChanged();
1967
1968
1969
1970
1971
1972
1973
1974
1975
1976
1977
1978
1979
1980
1981
1982
1983
1984
1985
1986
1987
1988QQmlComponent *QQuickMenu::delegate()
const
1990 Q_D(
const QQuickMenu);
1994void QQuickMenu::setDelegate(QQmlComponent *delegate)
1997 if (d->delegate == delegate)
2000 d->delegate = delegate;
2001 emit delegateChanged();
2005
2006
2007
2008
2009
2010
2011
2012
2013
2014
2015
2016int QQuickMenu::currentIndex()
const
2018 Q_D(
const QQuickMenu);
2019 return d->currentIndex;
2022void QQuickMenu::setCurrentIndex(
int index)
2025 d->setCurrentIndex(index, Qt::OtherFocusReason);
2029
2030
2031
2032
2033
2034
2035int QQuickMenu::count()
const
2037 Q_D(
const QQuickMenu);
2038 return d->contentModel->count();
2041void QQuickMenuPrivate::popup(QQuickItem *menuItem)
2046 QQmlNullableValue<QPointF> pos;
2047#if QT_CONFIG(cursor)
2048 if (parentItem && QGuiApplicationPrivate::platformIntegration()->hasCapability(QPlatformIntegration::MultipleWindows))
2049 pos = parentItem->mapFromGlobal(QCursor::pos());
2053 if (!pos.isValid() && parentItem)
2054 pos = QPointF((parentItem->width() - q->width()) / 2, (parentItem->height() - q->height()) / 2);
2056 q->popup(pos.isValid() ? pos.value() : QPointF(), menuItem);
2059void QQuickMenu::popup(
const QPointF &position, QQuickItem *menuItem)
2063#if QT_CONFIG(cursor)
2065 offset = d->popupItem->mapFromItem(menuItem, QPointF(0, 0)).y();
2067 setPosition(position - QPointF(0, offset));
2070 d->setCurrentIndex(d->contentModel->indexOf(menuItem,
nullptr), Qt::PopupFocusReason);
2072 d->setCurrentIndex(-1, Qt::PopupFocusReason);
2078
2079
2080
2081
2082
2083
2084
2085
2086
2087
2088
2089
2090
2093
2094
2095
2096
2097
2098
2099
2100
2101
2102
2103
2104
2105
2108
2109
2110
2111
2112
2113
2114
2115
2116
2117
2118
2119
2120
2122void QQuickMenu::popup(QQuickItem *parent, qreal x, qreal y, QQuickItem *menuItem)
2124 popup(parent, QPointF {x, y}, menuItem);
2127void QQuickMenu::popup(QQuickItem *parent,
const QPointF &position, QQuickItem *menuItem)
2130 if (parent && !d->popupItem->isAncestorOf(parent))
2131 setParentItem(parent);
2132 popup(position, menuItem);
2135void QQuickMenu::popup(QQuickItem *parent, QQuickItem *menuItem)
2138 QQuickItem *parentItem =
nullptr;
2139 if (parent && !d->popupItem->isAncestorOf(parent))
2140 parentItem = parent;
2142 setParentItem(parentItem);
2148void QQuickMenu::popup(QQuickItem *parent)
2151 QQuickItem *menuItem =
nullptr;
2153 if (!d->popupItem->isAncestorOf(parent))
2154 setParentItem(parent);
2155 if (d->popupItem->isAncestorOf(parent))
2161void QQuickMenu::popup(qreal x, qreal y, QQuickItem *menuItem)
2163 popup(QPointF {x, y}, menuItem);
2167
2168
2169
2170
2171
2172
2173
2174
2175
2176
2177
2178
2179
2180
2181void QQuickMenu::dismiss()
2183 QQuickMenu *menu =
this;
2186 menu = QQuickMenuPrivate::get(menu)->parentMenu;
2190void QQuickMenu::componentComplete()
2193 QQuickPopup::componentComplete();
2195 d->updateTextPadding();
2196 d->syncWithUseNativeMenu();
2199void QQuickMenu::contentItemChange(QQuickItem *newItem, QQuickItem *oldItem)
2202 QQuickPopup::contentItemChange(newItem, oldItem);
2205 QQuickItemPrivate::get(oldItem)->removeItemChangeListener(d, QQuickItemPrivate::Children);
2206 QQuickItemPrivate::get(oldItem)->removeItemChangeListener(d, QQuickItemPrivate::Destroyed);
2207 QQuickItemPrivate::get(oldItem)->removeItemChangeListener(d, QQuickItemPrivate::Geometry);
2210 QQuickItemPrivate::get(newItem)->addItemChangeListener(d, QQuickItemPrivate::Children);
2211 QQuickItemPrivate::get(newItem)->addItemChangeListener(d, QQuickItemPrivate::Destroyed);
2212 QQuickItemPrivate::get(newItem)->updateOrAddGeometryChangeListener(d, QQuickGeometryChange::Width);
2215 d->contentItem = newItem;
2218void QQuickMenu::itemChange(QQuickItem::ItemChange change,
const QQuickItem::ItemChangeData &data)
2221 QQuickPopup::itemChange(change, data);
2224 case QQuickItem::ItemVisibleHasChanged:
2225 if (!data.boolValue && d->cascade) {
2228 d->setCurrentIndex(-1, Qt::OtherFocusReason);
2236void QQuickMenu::keyPressEvent(QKeyEvent *event)
2239 QQuickPopup::keyPressEvent(event);
2247 switch (event->key()) {
2249 if (!d->activatePreviousItem())
2250 d->propagateKeyEvent(event);
2254 d->activateNextItem();
2260 if (d->popupItem->isMirrored() == (event->key() == Qt::Key_Right)) {
2261 if (d->parentMenu && d->currentItem) {
2263 d->parentMenu->open();
2268 if (QQuickMenu *subMenu = d->currentSubMenu()) {
2269 auto subMenuPrivate = QQuickMenuPrivate::get(subMenu);
2270 subMenuPrivate->popup(subMenuPrivate->firstEnabledMenuItem());
2274 if (!event->isAccepted())
2275 d->propagateKeyEvent(event);
2278#if QT_CONFIG(shortcut)
2282 if (!QKeySequence::mnemonic(QStringLiteral(
"&A")).isEmpty())
2291#if QT_CONFIG(shortcut)
2292 if (event->modifiers() == Qt::NoModifier) {
2293 for (
int i = 0; i < count(); ++i) {
2294 QQuickAbstractButton *item = qobject_cast<QQuickAbstractButton*>(d->itemAt(i));
2297 const QKeySequence keySequence = QKeySequence::mnemonic(item->text());
2298 if (keySequence.isEmpty())
2300 if (keySequence[0].key() == event->key()) {
2309void QQuickMenu::timerEvent(QTimerEvent *event)
2312 if (event->timerId() == d->hoverTimer) {
2313 if (QQuickMenu *subMenu = d->currentSubMenu())
2315 d->stopHoverTimer();
2318 QQuickPopup::timerEvent(event);
2321QFont QQuickMenu::defaultFont()
const
2323 return QQuickTheme::font(QQuickTheme::Menu);
2326#if QT_CONFIG(accessibility)
2327QAccessible::Role QQuickMenu::accessibleRole()
const
2329 return QAccessible::PopupMenu;
2335#include "moc_qquickmenu_p.cpp"
Combined button and popup list for selecting options.