1// Copyright (C) 2020 The Qt Company Ltd.
2// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
3
4#include "qquicklabsplatformmenu_p.h"
5#include "qquicklabsplatformmenubar_p.h"
6#include "qquicklabsplatformmenuitem_p.h"
7#include "qquicklabsplatformiconloader_p.h"
8
9#include <QtCore/qloggingcategory.h>
10#include <QtGui/qicon.h>
11#include <QtGui/qcursor.h>
12#include <QtGui/qpa/qplatformtheme.h>
13#include <QtGui/private/qguiapplication_p.h>
14#include <QtGui/private/qhighdpiscaling_p.h>
15#include <QtQml/private/qqmlengine_p.h>
16#include <QtQml/private/qv4scopedvalue_p.h>
17#include <QtQml/private/qv4qobjectwrapper_p.h>
18#include <QtQuick/qquickrendercontrol.h>
19#include <QtQuick/qquickwindow.h>
20#include <QtQuick/qquickitem.h>
21
22#include "widgets/qwidgetplatform_p.h"
23
24#if QT_CONFIG(systemtrayicon)
25#include "qquicklabsplatformsystemtrayicon_p.h"
26#endif
27
28QT_BEGIN_NAMESPACE
29
30/*!
31 \qmltype Menu
32 \inherits QtObject
33//! \instantiates QQuickLabsPlatformMenu
34 \inqmlmodule Qt.labs.platform
35 \since 5.8
36 \brief A native menu.
37
38 The Menu type provides a QML API for native platform menu popups.
39
40 \image qtlabsplatform-menu.png
41
42 Menu can be used in a \l MenuBar, or as a stand-alone context menu.
43 The following example shows how to open a context menu on right mouse
44 click:
45
46 \code
47 MouseArea {
48 anchors.fill: parent
49 acceptedButtons: Qt.RightButton
50 onClicked: zoomMenu.open()
51 }
52
53 Menu {
54 id: zoomMenu
55
56 MenuItem {
57 text: qsTr("Zoom In")
58 shortcut: StandardKey.ZoomIn
59 onTriggered: zoomIn()
60 }
61
62 MenuItem {
63 text: qsTr("Zoom Out")
64 shortcut: StandardKey.ZoomOut
65 onTriggered: zoomOut()
66 }
67 }
68 \endcode
69
70 \section2 Submenus
71
72 To create submenus, declare a Menu as a child of another Menu:
73
74 \qml
75 Menu {
76 title: qsTr("Edit")
77
78 Menu {
79 title: qsTr("Advanced")
80
81 MenuItem {
82 text: qsTr("Auto-indent Selection")
83 onTriggered: autoIndentSelection()
84 }
85
86 MenuItem {
87 text: qsTr("Rewrap Paragraph")
88 onTriggered: rewrapParagraph()
89 }
90 }
91 }
92 \endqml
93
94 \section2 Dynamically generating menu items
95
96 You can dynamically generate menu items with \l Instantiator. The following
97 code shows how you can implement a "Recent Files" submenu, where the items
98 come from a list of files stored in settings:
99
100 \snippet qtlabsplatform-menu-instantiator.qml menu
101
102 \section2 Availability
103
104 A native platform menu is currently available on the following platforms:
105
106 \list
107 \li macOS
108 \li iOS
109 \li Android
110 \li Linux (only available as a stand-alone context menu when running with the GTK+ platform theme)
111 \endlist
112
113 \input includes/widgets.qdocinc 1
114
115 \labs
116
117 \sa MenuItem, MenuSeparator, MenuBar
118*/
119
120/*!
121 \qmlsignal Qt.labs.platform::Menu::aboutToShow()
122
123 This signal is emitted when the menu is about to be shown to the user.
124*/
125
126/*!
127 \qmlsignal Qt.labs.platform::Menu::aboutToHide()
128
129 This signal is emitted when the menu is about to be hidden from the user.
130*/
131
132Q_LOGGING_CATEGORY(qtLabsPlatformMenus, "qt.labs.platform.menus")
133
134QQuickLabsPlatformMenu::QQuickLabsPlatformMenu(QObject *parent)
135 : QObject(parent),
136 m_complete(false),
137 m_enabled(true),
138 m_visible(true),
139 m_minimumWidth(-1),
140 m_type(QPlatformMenu::DefaultMenu),
141 m_menuBar(nullptr),
142 m_parentMenu(nullptr),
143 m_systemTrayIcon(nullptr),
144 m_menuItem(nullptr),
145 m_iconLoader(nullptr),
146 m_handle(nullptr)
147{
148}
149
150QQuickLabsPlatformMenu::~QQuickLabsPlatformMenu()
151{
152 if (m_menuBar)
153 m_menuBar->removeMenu(menu: this);
154 if (m_parentMenu)
155 m_parentMenu->removeMenu(menu: this);
156
157 unparentSubmenus();
158
159 delete m_iconLoader;
160 m_iconLoader = nullptr;
161 delete m_handle;
162 m_handle = nullptr;
163}
164
165void QQuickLabsPlatformMenu::unparentSubmenus()
166{
167 for (QQuickLabsPlatformMenuItem *item : std::as_const(t&: m_items)) {
168 if (QQuickLabsPlatformMenu *subMenu = item->subMenu())
169 subMenu->setParentMenu(nullptr);
170 item->setMenu(nullptr);
171 }
172}
173
174QPlatformMenu *QQuickLabsPlatformMenu::handle() const
175{
176 return m_handle;
177}
178
179QPlatformMenu * QQuickLabsPlatformMenu::create()
180{
181 if (!m_handle) {
182 if (m_menuBar && m_menuBar->handle())
183 m_handle = m_menuBar->handle()->createMenu();
184 else if (m_parentMenu && m_parentMenu->handle())
185 m_handle = m_parentMenu->handle()->createSubMenu();
186#if QT_CONFIG(systemtrayicon)
187 else if (m_systemTrayIcon && m_systemTrayIcon->handle())
188 m_handle = m_systemTrayIcon->handle()->createMenu();
189#endif
190
191 // TODO: implement ^
192 // - QCocoaMenuBar::createMenu()
193 // - QCocoaMenu::createSubMenu()
194 // - QCocoaSystemTrayIcon::createMenu()
195 if (!m_handle)
196 m_handle = QGuiApplicationPrivate::platformTheme()->createPlatformMenu();
197
198 if (!m_handle)
199 m_handle = QWidgetPlatform::createMenu();
200
201 qCDebug(qtLabsPlatformMenus) << "Menu ->" << m_handle;
202
203 if (m_handle) {
204 connect(sender: m_handle, signal: &QPlatformMenu::aboutToShow, context: this, slot: &QQuickLabsPlatformMenu::aboutToShow);
205 connect(sender: m_handle, signal: &QPlatformMenu::aboutToHide, context: this, slot: &QQuickLabsPlatformMenu::aboutToHide);
206
207 for (QQuickLabsPlatformMenuItem *item : std::as_const(t&: m_items))
208 m_handle->insertMenuItem(menuItem: item->create(), before: nullptr);
209
210 if (m_menuItem) {
211 if (QPlatformMenuItem *handle = m_menuItem->create())
212 handle->setMenu(m_handle);
213 }
214 }
215 }
216 return m_handle;
217}
218
219void QQuickLabsPlatformMenu::destroy()
220{
221 if (!m_handle)
222 return;
223
224 // Ensure that all submenus are unparented before we are destroyed,
225 // so that they don't try to access a destroyed menu.
226 unparentSubmenus();
227
228 delete m_handle;
229 m_handle = nullptr;
230}
231
232void QQuickLabsPlatformMenu::sync()
233{
234 if (!m_complete || !create())
235 return;
236
237 m_handle->setText(m_title);
238 m_handle->setEnabled(m_enabled);
239 m_handle->setVisible(m_visible);
240 m_handle->setMinimumWidth(m_minimumWidth);
241 m_handle->setMenuType(m_type);
242 m_handle->setFont(m_font);
243
244 if (m_menuBar && m_menuBar->handle())
245 m_menuBar->handle()->syncMenu(menuItem: m_handle);
246#if QT_CONFIG(systemtrayicon)
247 else if (m_systemTrayIcon && m_systemTrayIcon->handle())
248 m_systemTrayIcon->handle()->updateMenu(menu: m_handle);
249#endif
250
251 for (QQuickLabsPlatformMenuItem *item : std::as_const(t&: m_items))
252 item->sync();
253}
254
255/*!
256 \qmldefault
257 \qmlproperty list<QtObject> Qt.labs.platform::Menu::data
258
259 This default property holds the list of all objects declared as children of
260 the menu. The data property includes objects that are not \l MenuItem instances,
261 such as \l Timer and \l QtObject.
262
263 \sa items
264*/
265QQmlListProperty<QObject> QQuickLabsPlatformMenu::data()
266{
267 return QQmlListProperty<QObject>(this, nullptr, data_append, data_count, data_at, data_clear);
268}
269
270/*!
271 \qmlproperty list<MenuItem> Qt.labs.platform::Menu::items
272
273 This property holds the list of items in the menu.
274*/
275QQmlListProperty<QQuickLabsPlatformMenuItem> QQuickLabsPlatformMenu::items()
276{
277 return QQmlListProperty<QQuickLabsPlatformMenuItem>(this, nullptr, items_append, items_count, items_at, items_clear);
278}
279
280/*!
281 \readonly
282 \qmlproperty MenuBar Qt.labs.platform::Menu::menuBar
283
284 This property holds the menubar that the menu belongs to, or \c null if the
285 menu is not in a menubar.
286*/
287QQuickLabsPlatformMenuBar *QQuickLabsPlatformMenu::menuBar() const
288{
289 return m_menuBar;
290}
291
292void QQuickLabsPlatformMenu::setMenuBar(QQuickLabsPlatformMenuBar *menuBar)
293{
294 if (m_menuBar == menuBar)
295 return;
296
297 m_menuBar = menuBar;
298 destroy();
299 emit menuBarChanged();
300}
301
302/*!
303 \readonly
304 \qmlproperty Menu Qt.labs.platform::Menu::parentMenu
305
306 This property holds the parent menu that the menu belongs to, or \c null if the
307 menu is not a sub-menu.
308*/
309QQuickLabsPlatformMenu *QQuickLabsPlatformMenu::parentMenu() const
310{
311 return m_parentMenu;
312}
313
314void QQuickLabsPlatformMenu::setParentMenu(QQuickLabsPlatformMenu *menu)
315{
316 if (m_parentMenu == menu)
317 return;
318
319 m_parentMenu = menu;
320 destroy();
321 emit parentMenuChanged();
322}
323
324#if QT_CONFIG(systemtrayicon)
325/*!
326 \readonly
327 \qmlproperty SystemTrayIcon Qt.labs.platform::Menu::systemTrayIcon
328
329 This property holds the system tray icon that the menu belongs to, or \c null
330 if the menu is not in a system tray icon.
331*/
332QQuickLabsPlatformSystemTrayIcon *QQuickLabsPlatformMenu::systemTrayIcon() const
333{
334 return m_systemTrayIcon;
335}
336
337void QQuickLabsPlatformMenu::setSystemTrayIcon(QQuickLabsPlatformSystemTrayIcon *icon)
338{
339 if (m_systemTrayIcon == icon)
340 return;
341
342 m_systemTrayIcon = icon;
343 destroy();
344 emit systemTrayIconChanged();
345}
346#endif
347
348/*!
349 \readonly
350 \qmlproperty MenuItem Qt.labs.platform::Menu::menuItem
351
352 This property holds the item that presents the menu (in a parent menu).
353*/
354QQuickLabsPlatformMenuItem *QQuickLabsPlatformMenu::menuItem() const
355{
356 if (!m_menuItem) {
357 QQuickLabsPlatformMenu *that = const_cast<QQuickLabsPlatformMenu *>(this);
358 m_menuItem = new QQuickLabsPlatformMenuItem(that);
359 m_menuItem->setSubMenu(that);
360 m_menuItem->setText(m_title);
361 m_menuItem->setIcon(icon());
362 m_menuItem->setVisible(m_visible);
363 m_menuItem->setEnabled(m_enabled);
364 m_menuItem->componentComplete();
365 }
366 return m_menuItem;
367}
368
369/*!
370 \qmlproperty bool Qt.labs.platform::Menu::enabled
371
372 This property holds whether the menu is enabled. The default value is \c true.
373*/
374bool QQuickLabsPlatformMenu::isEnabled() const
375{
376 return m_enabled;
377}
378
379void QQuickLabsPlatformMenu::setEnabled(bool enabled)
380{
381 if (m_enabled == enabled)
382 return;
383
384 if (m_menuItem)
385 m_menuItem->setEnabled(enabled);
386
387 m_enabled = enabled;
388 sync();
389 emit enabledChanged();
390}
391
392/*!
393 \qmlproperty bool Qt.labs.platform::Menu::visible
394
395 This property holds whether the menu is visible. The default value is \c true.
396*/
397bool QQuickLabsPlatformMenu::isVisible() const
398{
399 return m_visible;
400}
401
402void QQuickLabsPlatformMenu::setVisible(bool visible)
403{
404 if (m_visible == visible)
405 return;
406
407 if (m_menuItem)
408 m_menuItem->setVisible(visible);
409
410 m_visible = visible;
411 sync();
412 emit visibleChanged();
413}
414
415/*!
416 \qmlproperty int Qt.labs.platform::Menu::minimumWidth
417
418 This property holds the minimum width of the menu. The default value is \c -1 (no minimum width).
419*/
420int QQuickLabsPlatformMenu::minimumWidth() const
421{
422 return m_minimumWidth;
423}
424
425void QQuickLabsPlatformMenu::setMinimumWidth(int width)
426{
427 if (m_minimumWidth == width)
428 return;
429
430 m_minimumWidth = width;
431 sync();
432 emit minimumWidthChanged();
433}
434
435/*!
436 \qmlproperty enumeration Qt.labs.platform::Menu::type
437
438 This property holds the type of the menu.
439
440 Available values:
441 \value Menu.DefaultMenu A normal menu (default).
442 \value Menu.EditMenu An edit menu with pre-populated cut, copy and paste items.
443*/
444QPlatformMenu::MenuType QQuickLabsPlatformMenu::type() const
445{
446 return m_type;
447}
448
449void QQuickLabsPlatformMenu::setType(QPlatformMenu::MenuType type)
450{
451 if (m_type == type)
452 return;
453
454 m_type = type;
455 sync();
456 emit typeChanged();
457}
458
459/*!
460 \qmlproperty string Qt.labs.platform::Menu::title
461
462 This property holds the menu's title.
463*/
464QString QQuickLabsPlatformMenu::title() const
465{
466 return m_title;
467}
468
469void QQuickLabsPlatformMenu::setTitle(const QString &title)
470{
471 if (m_title == title)
472 return;
473
474 if (m_menuItem)
475 m_menuItem->setText(title);
476
477 m_title = title;
478 sync();
479 emit titleChanged();
480}
481
482/*!
483 \qmlproperty font Qt.labs.platform::Menu::font
484
485 This property holds the menu's font.
486
487 \sa title
488*/
489QFont QQuickLabsPlatformMenu::font() const
490{
491 return m_font;
492}
493
494void QQuickLabsPlatformMenu::setFont(const QFont& font)
495{
496 if (m_font == font)
497 return;
498
499 m_font = font;
500 sync();
501 emit fontChanged();
502}
503
504/*!
505 \since Qt.labs.platform 1.1 (Qt 5.12)
506 \qmlproperty url Qt.labs.platform::Menu::icon.source
507 \qmlproperty string Qt.labs.platform::Menu::icon.name
508 \qmlproperty bool Qt.labs.platform::Menu::icon.mask
509
510 This property holds the menu item's icon.
511*/
512QQuickLabsPlatformIcon QQuickLabsPlatformMenu::icon() const
513{
514 if (!m_iconLoader)
515 return QQuickLabsPlatformIcon();
516
517 return iconLoader()->icon();
518}
519
520void QQuickLabsPlatformMenu::setIcon(const QQuickLabsPlatformIcon &icon)
521{
522 if (iconLoader()->icon() == icon)
523 return;
524
525 if (m_menuItem)
526 m_menuItem->setIcon(icon);
527
528 iconLoader()->setIcon(icon);
529 emit iconChanged();
530}
531
532/*!
533 \qmlmethod void Qt.labs.platform::Menu::addItem(MenuItem item)
534
535 Adds an \a item to the end of the menu.
536*/
537void QQuickLabsPlatformMenu::addItem(QQuickLabsPlatformMenuItem *item)
538{
539 insertItem(index: m_items.size(), item);
540}
541
542/*!
543 \qmlmethod void Qt.labs.platform::Menu::insertItem(int index, MenuItem item)
544
545 Inserts an \a item at the specified \a index in the menu.
546*/
547void QQuickLabsPlatformMenu::insertItem(int index, QQuickLabsPlatformMenuItem *item)
548{
549 if (!item || m_items.contains(t: item))
550 return;
551
552 m_items.insert(i: index, t: item);
553 m_data.append(t: item);
554 item->setMenu(this);
555 if (m_handle && item->create()) {
556 QQuickLabsPlatformMenuItem *before = m_items.value(i: index + 1);
557 m_handle->insertMenuItem(menuItem: item->handle(), before: before ? before->create() : nullptr);
558 }
559 sync();
560 emit itemsChanged();
561}
562
563/*!
564 \qmlmethod void Qt.labs.platform::Menu::removeItem(MenuItem item)
565
566 Removes an \a item from the menu.
567*/
568void QQuickLabsPlatformMenu::removeItem(QQuickLabsPlatformMenuItem *item)
569{
570 if (!item || !m_items.removeOne(t: item))
571 return;
572
573 m_data.removeOne(t: item);
574 if (m_handle)
575 m_handle->removeMenuItem(menuItem: item->handle());
576 item->setMenu(nullptr);
577 sync();
578 emit itemsChanged();
579}
580
581/*!
582 \qmlmethod void Qt.labs.platform::Menu::addMenu(Menu submenu)
583
584 Adds a \a submenu to the end of the menu.
585*/
586void QQuickLabsPlatformMenu::addMenu(QQuickLabsPlatformMenu *menu)
587{
588 insertMenu(index: m_items.size(), menu);
589}
590
591/*!
592 \qmlmethod void Qt.labs.platform::Menu::insertMenu(int index, Menu submenu)
593
594 Inserts a \a submenu at the specified \a index in the menu.
595*/
596void QQuickLabsPlatformMenu::insertMenu(int index, QQuickLabsPlatformMenu *menu)
597{
598 if (!menu)
599 return;
600
601 menu->setParentMenu(this);
602 insertItem(index, item: menu->menuItem());
603}
604
605/*!
606 \qmlmethod void Qt.labs.platform::Menu::removeMenu(Menu submenu)
607
608 Removes a \a submenu from the menu.
609*/
610void QQuickLabsPlatformMenu::removeMenu(QQuickLabsPlatformMenu *menu)
611{
612 if (!menu)
613 return;
614
615 menu->setParentMenu(nullptr);
616 removeItem(item: menu->menuItem());
617}
618
619/*!
620 \qmlmethod void Qt.labs.platform::Menu::clear()
621
622 Removes all items from the menu.
623*/
624void QQuickLabsPlatformMenu::clear()
625{
626 if (m_items.isEmpty())
627 return;
628
629 for (QQuickLabsPlatformMenuItem *item : std::as_const(t&: m_items)) {
630 m_data.removeOne(t: item);
631 if (m_handle)
632 m_handle->removeMenuItem(menuItem: item->handle());
633 item->setMenu(nullptr);
634 delete item;
635 }
636
637 m_items.clear();
638 sync();
639 emit itemsChanged();
640}
641
642/*!
643 \qmlmethod void Qt.labs.platform::Menu::open(MenuItem item)
644
645 Opens the menu at the current mouse position, optionally aligned to a menu \a item.
646*/
647
648/*!
649 \qmlmethod void Qt.labs.platform::Menu::open(Item target, MenuItem item)
650
651 Opens the menu at the specified \a target item, optionally aligned to a menu \a item.
652*/
653void QQuickLabsPlatformMenu::open(QQmlV4Function *args)
654{
655 if (!m_handle)
656 return;
657
658 if (args->length() > 2) {
659 args->v4engine()->throwTypeError();
660 return;
661 }
662
663 QV4::ExecutionEngine *v4 = args->v4engine();
664 QV4::Scope scope(v4);
665
666 QQuickItem *targetItem = nullptr;
667 if (args->length() > 0) {
668 QV4::ScopedValue value(scope, (*args)[0]);
669 QV4::Scoped<QV4::QObjectWrapper> object(scope, value->as<QV4::QObjectWrapper>());
670 if (object)
671 targetItem = qobject_cast<QQuickItem *>(o: object->object());
672 }
673
674 QQuickLabsPlatformMenuItem *menuItem = nullptr;
675 if (args->length() > 1) {
676 QV4::ScopedValue value(scope, (*args)[1]);
677 QV4::Scoped<QV4::QObjectWrapper> object(scope, value->as<QV4::QObjectWrapper>());
678 if (object)
679 menuItem = qobject_cast<QQuickLabsPlatformMenuItem *>(object: object->object());
680 }
681
682 QPoint offset;
683 QWindow *window = findWindow(target: targetItem, offset: &offset);
684
685 QRect targetRect;
686 if (targetItem) {
687 QRectF sceneBounds = targetItem->mapRectToScene(rect: targetItem->boundingRect());
688 targetRect = sceneBounds.toAlignedRect().translated(p: offset);
689 } else {
690#if QT_CONFIG(cursor)
691 QPoint pos = QCursor::pos();
692 if (window)
693 pos = window->mapFromGlobal(pos);
694 targetRect.moveTo(p: pos);
695#endif
696 }
697 m_handle->showPopup(parentWindow: window,
698 targetRect: QHighDpi::toNativePixels(value: targetRect, context: window),
699 item: menuItem ? menuItem->handle() : nullptr);
700}
701
702/*!
703 \qmlmethod void Qt.labs.platform::Menu::close()
704
705 Closes the menu.
706*/
707void QQuickLabsPlatformMenu::close()
708{
709 if (m_handle)
710 m_handle->dismiss();
711}
712
713void QQuickLabsPlatformMenu::classBegin()
714{
715}
716
717void QQuickLabsPlatformMenu::componentComplete()
718{
719 m_complete = true;
720 if (m_handle && m_iconLoader)
721 m_iconLoader->setEnabled(true);
722 sync();
723}
724
725QQuickLabsPlatformIconLoader *QQuickLabsPlatformMenu::iconLoader() const
726{
727 if (!m_iconLoader) {
728 QQuickLabsPlatformMenu *that = const_cast<QQuickLabsPlatformMenu *>(this);
729 static int slot = staticMetaObject.indexOfSlot(slot: "updateIcon()");
730 m_iconLoader = new QQuickLabsPlatformIconLoader(slot, that);
731 m_iconLoader->setEnabled(m_complete);
732 }
733 return m_iconLoader;
734}
735
736static QWindow *effectiveWindow(QWindow *window, QPoint *offset)
737{
738 QQuickWindow *quickWindow = qobject_cast<QQuickWindow *>(object: window);
739 if (quickWindow) {
740 QWindow *renderWindow = QQuickRenderControl::renderWindowFor(win: quickWindow, offset);
741 if (renderWindow)
742 return renderWindow;
743 }
744 return window;
745}
746
747QWindow *QQuickLabsPlatformMenu::findWindow(QQuickItem *target, QPoint *offset) const
748{
749 if (target)
750 return effectiveWindow(window: target->window(), offset);
751
752 if (m_menuBar && m_menuBar->window())
753 return effectiveWindow(window: m_menuBar->window(), offset);
754
755 QObject *obj = parent();
756 while (obj) {
757 QWindow *window = qobject_cast<QWindow *>(o: obj);
758 if (window)
759 return effectiveWindow(window, offset);
760
761 QQuickItem *item = qobject_cast<QQuickItem *>(o: obj);
762 if (item && item->window())
763 return effectiveWindow(window: item->window(), offset);
764
765 obj = obj->parent();
766 }
767 return nullptr;
768}
769
770void QQuickLabsPlatformMenu::data_append(QQmlListProperty<QObject> *property, QObject *object)
771{
772 QQuickLabsPlatformMenu *menu = static_cast<QQuickLabsPlatformMenu *>(property->object);
773 if (QQuickLabsPlatformMenuItem *item = qobject_cast<QQuickLabsPlatformMenuItem *>(object))
774 menu->addItem(item);
775 else if (QQuickLabsPlatformMenu *subMenu = qobject_cast<QQuickLabsPlatformMenu *>(object))
776 menu->addMenu(menu: subMenu);
777 else
778 menu->m_data.append(t: object);
779}
780
781qsizetype QQuickLabsPlatformMenu::data_count(QQmlListProperty<QObject> *property)
782{
783 QQuickLabsPlatformMenu *menu = static_cast<QQuickLabsPlatformMenu *>(property->object);
784 return menu->m_data.size();
785}
786
787QObject *QQuickLabsPlatformMenu::data_at(QQmlListProperty<QObject> *property, qsizetype index)
788{
789 QQuickLabsPlatformMenu *menu = static_cast<QQuickLabsPlatformMenu *>(property->object);
790 return menu->m_data.value(i: index);
791}
792
793void QQuickLabsPlatformMenu::data_clear(QQmlListProperty<QObject> *property)
794{
795 QQuickLabsPlatformMenu *menu = static_cast<QQuickLabsPlatformMenu *>(property->object);
796 menu->m_data.clear();
797}
798
799void QQuickLabsPlatformMenu::items_append(QQmlListProperty<QQuickLabsPlatformMenuItem> *property, QQuickLabsPlatformMenuItem *item)
800{
801 QQuickLabsPlatformMenu *menu = static_cast<QQuickLabsPlatformMenu *>(property->object);
802 menu->addItem(item);
803}
804
805qsizetype QQuickLabsPlatformMenu::items_count(QQmlListProperty<QQuickLabsPlatformMenuItem> *property)
806{
807 QQuickLabsPlatformMenu *menu = static_cast<QQuickLabsPlatformMenu *>(property->object);
808 return menu->m_items.size();
809}
810
811QQuickLabsPlatformMenuItem *QQuickLabsPlatformMenu::items_at(QQmlListProperty<QQuickLabsPlatformMenuItem> *property, qsizetype index)
812{
813 QQuickLabsPlatformMenu *menu = static_cast<QQuickLabsPlatformMenu *>(property->object);
814 return menu->m_items.value(i: index);
815}
816
817void QQuickLabsPlatformMenu::items_clear(QQmlListProperty<QQuickLabsPlatformMenuItem> *property)
818{
819 QQuickLabsPlatformMenu *menu = static_cast<QQuickLabsPlatformMenu *>(property->object);
820 menu->clear();
821}
822
823void QQuickLabsPlatformMenu::updateIcon()
824{
825 if (!m_handle || !m_iconLoader)
826 return;
827
828 m_handle->setIcon(m_iconLoader->toQIcon());
829 sync();
830}
831
832QT_END_NAMESPACE
833
834#include "moc_qquicklabsplatformmenu_p.cpp"
835

source code of qtdeclarative/src/labs/platform/qquicklabsplatformmenu.cpp