/****************************************************************************
**
** Copyright (C) 2017 The Qt Company Ltd.
** Contact: http://www.qt.io/licensing/
**
** This file is part of the Qt Labs Platform module of the Qt Toolkit.
**
** $QT_BEGIN_LICENSE:LGPL3$
** Commercial License Usage
** Licensees holding valid commercial Qt licenses may use this file in
** accordance with the commercial license agreement provided with the
** Software or, alternatively, in accordance with the terms contained in
** a written agreement between you and The Qt Company. For licensing terms
** and conditions see http://www.qt.io/terms-conditions. For further
** information use the contact form at http://www.qt.io/contact-us.
**
** GNU Lesser General Public License Usage
** Alternatively, this file may be used under the terms of the GNU Lesser
** General Public License version 3 as published by the Free Software
** Foundation and appearing in the file LICENSE.LGPLv3 included in the
** packaging of this file. Please review the following information to
** ensure the GNU Lesser General Public License version 3 requirements
** will be met: https://www.gnu.org/licenses/lgpl.html.
**
** GNU General Public License Usage
** Alternatively, this file may be used under the terms of the GNU
** General Public License version 2.0 or later as published by the Free
** Software Foundation and appearing in the file LICENSE.GPL included in
** the packaging of this file. Please review the following information to
** ensure the GNU General Public License version 2.0 requirements will be
** met: http://www.gnu.org/licenses/gpl-2.0.html.
**
** $QT_END_LICENSE$
**
****************************************************************************/

#include "qquickplatformmenu_p.h"
#include "qquickplatformmenubar_p.h"
#include "qquickplatformmenuitem_p.h"
#include "qquickplatformiconloader_p.h"

#include <QtCore/qloggingcategory.h>
#include <QtGui/qicon.h>
#include <QtGui/qcursor.h>
#include <QtGui/qpa/qplatformtheme.h>
#include <QtGui/private/qguiapplication_p.h>
#include <QtGui/private/qhighdpiscaling_p.h>
#include <QtQml/private/qqmlengine_p.h>
#include <QtQml/private/qv4scopedvalue_p.h>
#include <QtQml/private/qv4qobjectwrapper_p.h>
#include <QtQuick/qquickrendercontrol.h>
#include <QtQuick/qquickwindow.h>
#include <QtQuick/qquickitem.h>

#include "widgets/qwidgetplatform_p.h"

#if QT_CONFIG(systemtrayicon)
#include "qquickplatformsystemtrayicon_p.h"
#endif

QT_BEGIN_NAMESPACE

/*!
    \qmltype Menu
    \inherits QtObject
//! \instantiates QQuickPlatformMenu
    \inqmlmodule Qt.labs.platform
    \since 5.8
    \brief A native menu.

    The Menu type provides a QML API for native platform menu popups.

    \image qtlabsplatform-menu.png

    Menu can be used in a \l MenuBar, or as a stand-alone context menu.
    The following example shows how to open a context menu on right mouse
    click:

    \code
    MouseArea {
        anchors.fill: parent
        acceptedButtons: Qt.RightButton
        onClicked: zoomMenu.open()
    }

    Menu {
        id: zoomMenu

        MenuItem {
            text: qsTr("Zoom In")
            shortcut: StandardKey.ZoomIn
            onTriggered: zoomIn()
        }

        MenuItem {
            text: qsTr("Zoom Out")
            shortcut: StandardKey.ZoomOut
            onTriggered: zoomOut()
        }
    }
    \endcode

    \section2 Submenus

    To create submenus, declare a Menu as a child of another Menu:

    \qml
    Menu {
        title: qsTr("Edit")

        Menu {
            title: qsTr("Advanced")

            MenuItem {
                text: qsTr("Auto-indent Selection")
                onTriggered: autoIndentSelection()
            }

            MenuItem {
                text: qsTr("Rewrap Paragraph")
                onTriggered: rewrapParagraph()
            }
        }
    }
    \endqml

    \section2 Dynamically Generating Menu Items

    It is possible to dynamically generate menu items. One of the easiest ways
    to do so is with \l[QtQml]{Instantiator}. For example, to implement a
    "Recent Files" submenu, where the items are based on a list of files stored
    in settings, the following code could be used:

    \qml
    Menu {
        title: qsTr("File")

        Menu {
            id: recentFilesSubMenu
            title: qsTr("Recent Files")
            enabled: recentFilesInstantiator.count > 0

            Instantiator {
                id: recentFilesInstantiator
                model: settings.recentFiles
                delegate: MenuItem {
                    text: settings.displayableFilePath(modelData)
                    onTriggered: loadFile(modelData)
                }

                onObjectAdded: recentFilesSubMenu.insertItem(index, object)
                onObjectRemoved: recentFilesSubMenu.removeItem(object)
            }

            MenuSeparator {}

            MenuItem {
                text: qsTr("Clear Recent Files")
                onTriggered: settings.clearRecentFiles()
            }
        }
    }
    \endqml

    \section2 Availability

    A native platform menu is currently available on the following platforms:

    \list
    \li macOS
    \li iOS
    \li Android
    \li Linux (only available as a stand-alone context menu when running with the GTK+ platform theme)
    \endlist

    \input includes/widgets.qdocinc 1

    \labs

    \sa MenuItem, MenuSeparator, MenuBar
*/

/*!
    \qmlsignal Qt.labs.platform::Menu::aboutToShow()

    This signal is emitted when the menu is about to be shown to the user.
*/

/*!
    \qmlsignal Qt.labs.platform::Menu::aboutToHide()

    This signal is emitted when the menu is about to be hidden from the user.
*/

Q_DECLARE_LOGGING_CATEGORY(qtLabsPlatformMenus)

QQuickPlatformMenu::QQuickPlatformMenu(QObject *parent)
    : QObject(parent),
      m_complete(false),
      m_enabled(true),
      m_visible(true),
      m_minimumWidth(-1),
      m_type(QPlatformMenu::DefaultMenu),
      m_menuBar(nullptr),
      m_parentMenu(nullptr),
      m_systemTrayIcon(nullptr),
      m_menuItem(nullptr),
      m_iconLoader(nullptr),
      m_handle(nullptr)
{
}

QQuickPlatformMenu::~QQuickPlatformMenu()
{
    if (m_menuBar)
        m_menuBar->removeMenu(this);
    if (m_parentMenu)
        m_parentMenu->removeMenu(this);

    unparentSubmenus();

    delete m_iconLoader;
    m_iconLoader = nullptr;
    delete m_handle;
    m_handle = nullptr;
}

void QQuickPlatformMenu::unparentSubmenus()
{
    for (QQuickPlatformMenuItem *item : qAsConst(m_items)) {
        if (QQuickPlatformMenu *subMenu = item->subMenu())
            subMenu->setParentMenu(nullptr);
        item->setMenu(nullptr);
    }
}

QPlatformMenu *QQuickPlatformMenu::handle() const
{
    return m_handle;
}

QPlatformMenu * QQuickPlatformMenu::create()
{
    if (!m_handle) {
        if (m_menuBar && m_menuBar->handle())
            m_handle = m_menuBar->handle()->createMenu();
        else if (m_parentMenu && m_parentMenu->handle())
            m_handle = m_parentMenu->handle()->createSubMenu();
#if QT_CONFIG(systemtrayicon)
        else if (m_systemTrayIcon && m_systemTrayIcon->handle())
            m_handle = m_systemTrayIcon->handle()->createMenu();
#endif

        // TODO: implement ^
        // - QCocoaMenuBar::createMenu()
        // - QCocoaMenu::createSubMenu()
        // - QCocoaSystemTrayIcon::createMenu()
        if (!m_handle)
            m_handle = QGuiApplicationPrivate::platformTheme()->createPlatformMenu();

        if (!m_handle)
            m_handle = QWidgetPlatform::createMenu();

        qCDebug(qtLabsPlatformMenus) << "Menu ->" << m_handle;

        if (m_handle) {
            connect(m_handle, &QPlatformMenu::aboutToShow, this, &QQuickPlatformMenu::aboutToShow);
            connect(m_handle, &QPlatformMenu::aboutToHide, this, &QQuickPlatformMenu::aboutToHide);

            for (QQuickPlatformMenuItem *item : qAsConst(m_items))
                m_handle->insertMenuItem(item->create(), nullptr);

            if (m_menuItem) {
                if (QPlatformMenuItem *handle = m_menuItem->create())
                    handle->setMenu(m_handle);
            }
        }
    }
    return m_handle;
}

void QQuickPlatformMenu::destroy()
{
    if (!m_handle)
        return;

    // Ensure that all submenus are unparented before we are destroyed,
    // so that they don't try to access a destroyed menu.
    unparentSubmenus();

    delete m_handle;
    m_handle = nullptr;
}

void QQuickPlatformMenu::sync()
{
    if (!m_complete || !create())
        return;

    m_handle->setText(m_title);
    m_handle->setEnabled(m_enabled);
    m_handle->setVisible(m_visible);
    m_handle->setMinimumWidth(m_minimumWidth);
    m_handle->setMenuType(m_type);
    m_handle->setFont(m_font);

    if (m_menuBar && m_menuBar->handle())
        m_menuBar->handle()->syncMenu(m_handle);
#if QT_CONFIG(systemtrayicon)
    else if (m_systemTrayIcon && m_systemTrayIcon->handle())
        m_systemTrayIcon->handle()->updateMenu(m_handle);
#endif

    for (QQuickPlatformMenuItem *item : qAsConst(m_items))
        item->sync();
}

/*!
    \default
    \qmlproperty list<Object> Qt.labs.platform::Menu::data

    This default property holds the list of all objects declared as children of
    the menu. The data property includes objects that are not \l MenuItem instances,
    such as \l Timer and \l QtObject.

    \sa items
*/
QQmlListProperty<QObject> QQuickPlatformMenu::data()
{
    return QQmlListProperty<QObject>(this, nullptr, data_append, data_count, data_at, data_clear);
}

/*!
    \qmlproperty list<MenuItem> Qt.labs.platform::Menu::items

    This property holds the list of items in the menu.
*/
QQmlListProperty<QQuickPlatformMenuItem> QQuickPlatformMenu::items()
{
    return QQmlListProperty<QQuickPlatformMenuItem>(this, nullptr, items_append, items_count, items_at, items_clear);
}

/*!
    \readonly
    \qmlproperty MenuBar Qt.labs.platform::Menu::menuBar

    This property holds the menubar that the menu belongs to, or \c null if the
    menu is not in a menubar.
*/
QQuickPlatformMenuBar *QQuickPlatformMenu::menuBar() const
{
    return m_menuBar;
}

void QQuickPlatformMenu::setMenuBar(QQuickPlatformMenuBar *menuBar)
{
    if (m_menuBar == menuBar)
        return;

    m_menuBar = menuBar;
    destroy();
    emit menuBarChanged();
}

/*!
    \readonly
    \qmlproperty Menu Qt.labs.platform::Menu::parentMenu

    This property holds the parent menu that the menu belongs to, or \c null if the
    menu is not a sub-menu.
*/
QQuickPlatformMenu *QQuickPlatformMenu::parentMenu() const
{
    return m_parentMenu;
}

void QQuickPlatformMenu::setParentMenu(QQuickPlatformMenu *menu)
{
    if (m_parentMenu == menu)
        return;

    m_parentMenu = menu;
    destroy();
    emit parentMenuChanged();
}

/*!
    \readonly
    \qmlproperty SystemTrayIcon Qt.labs.platform::Menu::systemTrayIcon

    This property holds the system tray icon that the menu belongs to, or \c null
    if the menu is not in a system tray icon.
*/
QQuickPlatformSystemTrayIcon *QQuickPlatformMenu::systemTrayIcon() const
{
    return m_systemTrayIcon;
}

void QQuickPlatformMenu::setSystemTrayIcon(QQuickPlatformSystemTrayIcon *icon)
{
    if (m_systemTrayIcon == icon)
        return;

    m_systemTrayIcon = icon;
    destroy();
    emit systemTrayIconChanged();
}

/*!
    \readonly
    \qmlproperty MenuItem Qt.labs.platform::Menu::menuItem

    This property holds the item that presents the menu (in a parent menu).
*/
QQuickPlatformMenuItem *QQuickPlatformMenu::menuItem() const
{
    if (!m_menuItem) {
        QQuickPlatformMenu *that = const_cast<QQuickPlatformMenu *>(this);
        m_menuItem = new QQuickPlatformMenuItem(that);
        m_menuItem->setSubMenu(that);
        m_menuItem->setText(m_title);
        m_menuItem->setIconName(iconName());
        m_menuItem->setIconSource(iconSource());
        m_menuItem->setVisible(m_visible);
        m_menuItem->setEnabled(m_enabled);
        m_menuItem->componentComplete();
    }
    return m_menuItem;
}

/*!
    \qmlproperty bool Qt.labs.platform::Menu::enabled

    This property holds whether the menu is enabled. The default value is \c true.
*/
bool QQuickPlatformMenu::isEnabled() const
{
    return m_enabled;
}

void QQuickPlatformMenu::setEnabled(bool enabled)
{
    if (m_enabled == enabled)
        return;

    if (m_menuItem)
        m_menuItem->setEnabled(enabled);

    m_enabled = enabled;
    sync();
    emit enabledChanged();
}

/*!
    \qmlproperty bool Qt.labs.platform::Menu::visible

    This property holds whether the menu is visible. The default value is \c true.
*/
bool QQuickPlatformMenu::isVisible() const
{
    return m_visible;
}

void QQuickPlatformMenu::setVisible(bool visible)
{
    if (m_visible == visible)
        return;

    if (m_menuItem)
        m_menuItem->setVisible(visible);

    m_visible = visible;
    sync();
    emit visibleChanged();
}

/*!
    \qmlproperty int Qt.labs.platform::Menu::minimumWidth

    This property holds the minimum width of the menu. The default value is \c -1 (no minimum width).
*/
int QQuickPlatformMenu::minimumWidth() const
{
    return m_minimumWidth;
}

void QQuickPlatformMenu::setMinimumWidth(int width)
{
    if (m_minimumWidth == width)
        return;

    m_minimumWidth = width;
    sync();
    emit minimumWidthChanged();
}

/*!
    \qmlproperty enumeration Qt.labs.platform::Menu::type

    This property holds the type of the menu.

    Available values:
    \value Menu.DefaultMenu A normal menu (default).
    \value Menu.EditMenu An edit menu with pre-populated cut, copy and paste items.
*/
QPlatformMenu::MenuType QQuickPlatformMenu::type() const
{
    return m_type;
}

void QQuickPlatformMenu::setType(QPlatformMenu::MenuType type)
{
    if (m_type == type)
        return;

    m_type = type;
    sync();
    emit typeChanged();
}

/*!
    \qmlproperty string Qt.labs.platform::Menu::title

    This property holds the menu's title.
*/
QString QQuickPlatformMenu::title() const
{
    return m_title;
}

void QQuickPlatformMenu::setTitle(const QString &title)
{
    if (m_title == title)
        return;

    if (m_menuItem)
        m_menuItem->setText(title);

    m_title = title;
    sync();
    emit titleChanged();
}

/*!
    \qmlproperty url Qt.labs.platform::Menu::iconSource
    \deprecated Use icon.source instead
*/
QUrl QQuickPlatformMenu::iconSource() const
{
    return icon().source();
}

void QQuickPlatformMenu::setIconSource(const QUrl& source)
{
    QQuickPlatformIcon newIcon = icon();
    if (source == newIcon.source())
        return;

    if (m_menuItem)
        m_menuItem->setIconSource(source);

    newIcon.setSource(source);
    iconLoader()->setIcon(newIcon);
    emit iconSourceChanged();
}

/*!
    \qmlproperty string Qt.labs.platform::Menu::iconName
    \deprecated Use icon.name instead
*/
QString QQuickPlatformMenu::iconName() const
{
    return icon().name();
}

void QQuickPlatformMenu::setIconName(const QString& name)
{
    QQuickPlatformIcon newIcon = icon();
    if (name == newIcon.name())
        return;

    if (m_menuItem)
        m_menuItem->setIconName(name);

    newIcon.setName(name);
    iconLoader()->setIcon(newIcon);
    emit iconNameChanged();}

/*!
    \qmlproperty font Qt.labs.platform::Menu::font

    This property holds the menu's font.

    \sa text
*/
QFont QQuickPlatformMenu::font() const
{
    return m_font;
}

void QQuickPlatformMenu::setFont(const QFont& font)
{
    if (m_font == font)
        return;

    m_font = font;
    sync();
    emit fontChanged();
}

/*!
    \since Qt.labs.platform 1.1 (Qt 5.12)
    \qmlpropertygroup Qt.labs.platform::MenuItem::icon
    \qmlproperty url Qt.labs.platform::MenuItem::icon.source
    \qmlproperty string Qt.labs.platform::MenuItem::icon.name
    \qmlproperty bool Qt.labs.platform::MenuItem::icon.mask

    This property holds the menu item's icon.
*/
QQuickPlatformIcon QQuickPlatformMenu::icon() const
{
    if (!m_iconLoader)
        return QQuickPlatformIcon();

    return iconLoader()->icon();
}

void QQuickPlatformMenu::setIcon(const QQuickPlatformIcon &icon)
{
    if (iconLoader()->icon() == icon)
        return;

    if (m_menuItem)
        m_menuItem->setIcon(icon);

    iconLoader()->setIcon(icon);
    emit iconChanged();
}

/*!
    \qmlmethod void Qt.labs.platform::Menu::addItem(MenuItem item)

    Adds an \a item to the end of the menu.
*/
void QQuickPlatformMenu::addItem(QQuickPlatformMenuItem *item)
{
    insertItem(m_items.count(), item);
}

/*!
    \qmlmethod void Qt.labs.platform::Menu::insertItem(int index, MenuItem item)

    Inserts an \a item at the specified \a index in the menu.
*/
void QQuickPlatformMenu::insertItem(int index, QQuickPlatformMenuItem *item)
{
    if (!item || m_items.contains(item))
        return;

    m_items.insert(index, item);
    m_data.append(item);
    item->setMenu(this);
    if (m_handle && item->create()) {
        QQuickPlatformMenuItem *before = m_items.value(index + 1);
        m_handle->insertMenuItem(item->handle(), before ? before->create() : nullptr);
    }
    sync();
    emit itemsChanged();
}

/*!
    \qmlmethod void Qt.labs.platform::Menu::removeItem(MenuItem item)

    Removes an \a item from the menu.
*/
void QQuickPlatformMenu::removeItem(QQuickPlatformMenuItem *item)
{
    if (!item || !m_items.removeOne(item))
        return;

    m_data.removeOne(item);
    if (m_handle)
        m_handle->removeMenuItem(item->handle());
    item->setMenu(nullptr);
    sync();
    emit itemsChanged();
}

/*!
    \qmlmethod void Qt.labs.platform::Menu::addMenu(Menu submenu)

    Adds a \a submenu to the end of the menu.
*/
void QQuickPlatformMenu::addMenu(QQuickPlatformMenu *menu)
{
    insertMenu(m_items.count(), menu);
}

/*!
    \qmlmethod void Qt.labs.platform::Menu::insertMenu(int index, Menu submenu)

    Inserts a \a submenu at the specified \a index in the menu.
*/
void QQuickPlatformMenu::insertMenu(int index, QQuickPlatformMenu *menu)
{
    if (!menu)
        return;

    menu->setParentMenu(this);
    insertItem(index, menu->menuItem());
}

/*!
    \qmlmethod void Qt.labs.platform::Menu::removeMenu(Menu submenu)

    Removes a \a submenu from the menu.
*/
void QQuickPlatformMenu::removeMenu(QQuickPlatformMenu *menu)
{
    if (!menu)
        return;

    menu->setParentMenu(nullptr);
    removeItem(menu->menuItem());
}

/*!
    \qmlmethod void Qt.labs.platform::Menu::clear()

    Removes all items from the menu.
*/
void QQuickPlatformMenu::clear()
{
    if (m_items.isEmpty())
        return;

    for (QQuickPlatformMenuItem *item : qAsConst(m_items)) {
        m_data.removeOne(item);
        if (m_handle)
            m_handle->removeMenuItem(item->handle());
        item->setMenu(nullptr);
        delete item;
    }

    m_items.clear();
    sync();
    emit itemsChanged();
}

/*!
    \qmlmethod void Qt.labs.platform::Menu::open(MenuItem item)

    Opens the menu at the current mouse position, optionally aligned to a menu \a item.
*/

/*!
    \qmlmethod void Qt.labs.platform::Menu::open(Item target, MenuItem item)

    Opens the menu at the specified \a target item, optionally aligned to a menu \a item.
*/
void QQuickPlatformMenu::open(QQmlV4Function *args)
{
    if (!m_handle)
        return;

    if (args->length() > 2) {
        args->v4engine()->throwTypeError();
        return;
    }

    QV4::ExecutionEngine *v4 = args->v4engine();
    QV4::Scope scope(v4);

    QQuickItem *targetItem = nullptr;
    if (args->length() > 0) {
        QV4::ScopedValue value(scope, (*args)[0]);
        QV4::Scoped<QV4::QObjectWrapper> object(scope, value->as<QV4::QObjectWrapper>());
        if (object)
            targetItem = qobject_cast<QQuickItem *>(object->object());
    }

    QQuickPlatformMenuItem *menuItem = nullptr;
    if (args->length() > 1) {
        QV4::ScopedValue value(scope, (*args)[1]);
        QV4::Scoped<QV4::QObjectWrapper> object(scope, value->as<QV4::QObjectWrapper>());
        if (object)
            menuItem = qobject_cast<QQuickPlatformMenuItem *>(object->object());
    }

    QPoint offset;
    QWindow *window = findWindow(targetItem, &offset);

    QRect targetRect;
    if (targetItem) {
        QRectF sceneBounds = targetItem->mapRectToScene(targetItem->boundingRect());
        targetRect = sceneBounds.toAlignedRect().translated(offset);
    } else {
#if QT_CONFIG(cursor)
        QPoint pos = QCursor::pos();
        if (window)
            pos = window->mapFromGlobal(pos);
        targetRect.moveTo(pos);
#endif
    }
    m_handle->showPopup(window,
                        QHighDpi::toNativePixels(targetRect, window),
                        menuItem ? menuItem->handle() : nullptr);
}

/*!
    \qmlmethod void Qt.labs.platform::Menu::close()

    Closes the menu.
*/
void QQuickPlatformMenu::close()
{
    if (m_handle)
        m_handle->dismiss();
}

void QQuickPlatformMenu::classBegin()
{
}

void QQuickPlatformMenu::componentComplete()
{
    m_complete = true;
    if (m_handle && m_iconLoader)
        m_iconLoader->setEnabled(true);
    sync();
}

QQuickPlatformIconLoader *QQuickPlatformMenu::iconLoader() const
{
    if (!m_iconLoader) {
        QQuickPlatformMenu *that = const_cast<QQuickPlatformMenu *>(this);
        static int slot = staticMetaObject.indexOfSlot("updateIcon()");
        m_iconLoader = new QQuickPlatformIconLoader(slot, that);
        m_iconLoader->setEnabled(m_complete);
    }
    return m_iconLoader;
}

static QWindow *effectiveWindow(QWindow *window, QPoint *offset)
{
    QQuickWindow *quickWindow = qobject_cast<QQuickWindow *>(window);
    if (quickWindow) {
        QWindow *renderWindow = QQuickRenderControl::renderWindowFor(quickWindow, offset);
        if (renderWindow)
            return renderWindow;
    }
    return window;
}

QWindow *QQuickPlatformMenu::findWindow(QQuickItem *target, QPoint *offset) const
{
    if (target)
        return effectiveWindow(target->window(), offset);

    if (m_menuBar && m_menuBar->window())
        return effectiveWindow(m_menuBar->window(), offset);

    QObject *obj = parent();
    while (obj) {
        QWindow *window = qobject_cast<QWindow *>(obj);
        if (window)
            return effectiveWindow(window, offset);

        QQuickItem *item = qobject_cast<QQuickItem *>(obj);
        if (item && item->window())
            return effectiveWindow(item->window(), offset);

        obj = obj->parent();
    }
    return nullptr;
}

void QQuickPlatformMenu::data_append(QQmlListProperty<QObject> *property, QObject *object)
{
    QQuickPlatformMenu *menu = static_cast<QQuickPlatformMenu *>(property->object);
    if (QQuickPlatformMenuItem *item = qobject_cast<QQuickPlatformMenuItem *>(object))
        menu->addItem(item);
    else if (QQuickPlatformMenu *subMenu = qobject_cast<QQuickPlatformMenu *>(object))
        menu->addMenu(subMenu);
    else
        menu->m_data.append(object);
}

int QQuickPlatformMenu::data_count(QQmlListProperty<QObject> *property)
{
    QQuickPlatformMenu *menu = static_cast<QQuickPlatformMenu *>(property->object);
    return menu->m_data.count();
}

QObject *QQuickPlatformMenu::data_at(QQmlListProperty<QObject> *property, int index)
{
    QQuickPlatformMenu *menu = static_cast<QQuickPlatformMenu *>(property->object);
    return menu->m_data.value(index);
}

void QQuickPlatformMenu::data_clear(QQmlListProperty<QObject> *property)
{
    QQuickPlatformMenu *menu = static_cast<QQuickPlatformMenu *>(property->object);
    menu->m_data.clear();
}

void QQuickPlatformMenu::items_append(QQmlListProperty<QQuickPlatformMenuItem> *property, QQuickPlatformMenuItem *item)
{
    QQuickPlatformMenu *menu = static_cast<QQuickPlatformMenu *>(property->object);
    menu->addItem(item);
}

int QQuickPlatformMenu::items_count(QQmlListProperty<QQuickPlatformMenuItem> *property)
{
    QQuickPlatformMenu *menu = static_cast<QQuickPlatformMenu *>(property->object);
    return menu->m_items.count();
}

QQuickPlatformMenuItem *QQuickPlatformMenu::items_at(QQmlListProperty<QQuickPlatformMenuItem> *property, int index)
{
    QQuickPlatformMenu *menu = static_cast<QQuickPlatformMenu *>(property->object);
    return menu->m_items.value(index);
}

void QQuickPlatformMenu::items_clear(QQmlListProperty<QQuickPlatformMenuItem> *property)
{
    QQuickPlatformMenu *menu = static_cast<QQuickPlatformMenu *>(property->object);
    menu->clear();
}

void QQuickPlatformMenu::updateIcon()
{
    if (!m_handle || !m_iconLoader)
        return;

    m_handle->setIcon(m_iconLoader->toQIcon());
    sync();
}

QT_END_NAMESPACE
