// Copyright (C) 2020 The Qt Company Ltd. // SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only #include "qquicklabsplatformmenuitemgroup_p.h" #include "qquicklabsplatformmenuitem_p.h" QT_BEGIN_NAMESPACE /*! \qmltype MenuItemGroup \inherits QtObject //! \nativetype QQuickLabsPlatformMenuItemGroup \inqmlmodule Qt.labs.platform \since 5.8 \brief A group for managing native menu items. The MenuItemGroup groups native menu items together. MenuItemGroup is exclusive by default. In an exclusive menu item group, only one item can be checked at any time; checking another item automatically unchecks the previously checked one. MenuItemGroup can be configured as non-exclusive, which is particularly useful for showing, hiding, enabling and disabling items together as a group. The most straight-forward way to use MenuItemGroup is to assign a list of items. \code Menu { id: verticalMenu title: qsTr("Vertical") MenuItemGroup { id: verticalGroup items: verticalMenu.items } MenuItem { text: qsTr("Top"); checkable: true } MenuItem { text: qsTr("Center"); checked: true } MenuItem { text: qsTr("Bottom"); checkable: true } } \endcode The same menu may sometimes contain items that should not be included in the same exclusive group. Such cases are best handled using the \l {MenuItem::group}{group} property. \code Menu { id: horizontalMenu title: qsTr("Horizontal") MenuItemGroup { id: horizontalGroup } MenuItem { checked: true text: qsTr("Left") group: horizontalGroup } MenuItem { checkable: true text: qsTr("Center") group: horizontalGroup } MenuItem { text: qsTr("Right") checkable: true group: horizontalGroup } MenuItem { separator: true } MenuItem { text: qsTr("Justify"); checkable: true } MenuItem { text: qsTr("Absolute"); checkable: true } } \endcode More advanced use cases can be handled using the addItem() and removeItem() methods. \labs \sa MenuItem */ /*! \qmlsignal Qt.labs.platform::MenuItemGroup::triggered(MenuItem item) This signal is emitted when an \a item in the group is triggered by the user. \sa MenuItem::triggered() */ /*! \qmlsignal Qt.labs.platform::MenuItemGroup::hovered(MenuItem item) This signal is emitted when an \a item in the group is hovered by the user. \sa MenuItem::hovered() */ QQuickLabsPlatformMenuItemGroup::QQuickLabsPlatformMenuItemGroup(QObject *parent) : QObject(parent), m_enabled(true), m_visible(true), m_exclusive(true), m_checkedItem(nullptr) { } QQuickLabsPlatformMenuItemGroup::~QQuickLabsPlatformMenuItemGroup() { clear(); } /*! \qmlproperty bool Qt.labs.platform::MenuItemGroup::enabled This property holds whether the group is enabled. The default value is \c true. The enabled state of the group affects the enabled state of each item in the group, except that explicitly disabled items are not enabled even if the group is enabled. */ bool QQuickLabsPlatformMenuItemGroup::isEnabled() const { return m_enabled; } void QQuickLabsPlatformMenuItemGroup::setEnabled(bool enabled) { if (m_enabled == enabled) return; m_enabled = enabled; emit enabledChanged(); for (QQuickLabsPlatformMenuItem *item : std::as_const(m_items)) { if (item->m_enabled) { item->sync(); emit item->enabledChanged(); } } } /*! \qmlproperty bool Qt.labs.platform::MenuItemGroup::visible This property holds whether the group is visible. The default value is \c true. The visibility of the group affects the visibility of each item in the group, except that explicitly hidden items are not visible even if the group is visible. */ bool QQuickLabsPlatformMenuItemGroup::isVisible() const { return m_visible; } void QQuickLabsPlatformMenuItemGroup::setVisible(bool visible) { if (m_visible == visible) return; m_visible = visible; emit visibleChanged(); for (QQuickLabsPlatformMenuItem *item : std::as_const(m_items)) { if (item->m_visible) { item->sync(); emit item->visibleChanged(); } } } /*! \qmlproperty bool Qt.labs.platform::MenuItemGroup::exclusive This property holds whether the group is exclusive. The default value is \c true. In an exclusive menu item group, only one item can be checked at any time; checking another item automatically unchecks the previously checked one. */ bool QQuickLabsPlatformMenuItemGroup::isExclusive() const { return m_exclusive; } void QQuickLabsPlatformMenuItemGroup::setExclusive(bool exclusive) { if (m_exclusive == exclusive) return; m_exclusive = exclusive; emit exclusiveChanged(); for (QQuickLabsPlatformMenuItem *item : std::as_const(m_items)) item->sync(); } /*! \qmlproperty MenuItem Qt.labs.platform::MenuItemGroup::checkedItem This property holds the currently checked item in the group, or \c null if no item is checked. */ QQuickLabsPlatformMenuItem *QQuickLabsPlatformMenuItemGroup::checkedItem() const { return m_checkedItem; } void QQuickLabsPlatformMenuItemGroup::setCheckedItem(QQuickLabsPlatformMenuItem *item) { if (m_checkedItem == item) return; if (m_checkedItem) m_checkedItem->setChecked(false); m_checkedItem = item; emit checkedItemChanged(); if (item) item->setChecked(true); } /*! \qmlproperty list Qt.labs.platform::MenuItemGroup::items This property holds the list of items in the group. */ QQmlListProperty QQuickLabsPlatformMenuItemGroup::items() { return QQmlListProperty(this, nullptr, items_append, items_count, items_at, items_clear); } /*! \qmlmethod void Qt.labs.platform::MenuItemGroup::addItem(MenuItem item) Adds an \a item to the group. */ void QQuickLabsPlatformMenuItemGroup::addItem(QQuickLabsPlatformMenuItem *item) { if (!item || m_items.contains(item)) return; m_items.append(item); item->setGroup(this); connect(item, &QQuickLabsPlatformMenuItem::checkedChanged, this, &QQuickLabsPlatformMenuItemGroup::updateCurrent); connect(item, &QQuickLabsPlatformMenuItem::triggered, this, &QQuickLabsPlatformMenuItemGroup::activateItem); connect(item, &QQuickLabsPlatformMenuItem::hovered, this, &QQuickLabsPlatformMenuItemGroup::hoverItem); if (m_exclusive && item->isChecked()) setCheckedItem(item); emit itemsChanged(); } /*! \qmlmethod void Qt.labs.platform::MenuItemGroup::removeItem(MenuItem item) Removes an \a item from the group. */ void QQuickLabsPlatformMenuItemGroup::removeItem(QQuickLabsPlatformMenuItem *item) { if (!item || !m_items.contains(item)) return; m_items.removeOne(item); item->setGroup(nullptr); disconnect(item, &QQuickLabsPlatformMenuItem::checkedChanged, this, &QQuickLabsPlatformMenuItemGroup::updateCurrent); disconnect(item, &QQuickLabsPlatformMenuItem::triggered, this, &QQuickLabsPlatformMenuItemGroup::activateItem); disconnect(item, &QQuickLabsPlatformMenuItem::hovered, this, &QQuickLabsPlatformMenuItemGroup::hoverItem); if (m_checkedItem == item) setCheckedItem(nullptr); emit itemsChanged(); } /*! \qmlmethod void Qt.labs.platform::MenuItemGroup::clear() Removes all items from the group. */ void QQuickLabsPlatformMenuItemGroup::clear() { if (m_items.isEmpty()) return; for (QQuickLabsPlatformMenuItem *item : std::as_const(m_items)) { item->setGroup(nullptr); disconnect(item, &QQuickLabsPlatformMenuItem::checkedChanged, this, &QQuickLabsPlatformMenuItemGroup::updateCurrent); disconnect(item, &QQuickLabsPlatformMenuItem::triggered, this, &QQuickLabsPlatformMenuItemGroup::activateItem); disconnect(item, &QQuickLabsPlatformMenuItem::hovered, this, &QQuickLabsPlatformMenuItemGroup::hoverItem); } setCheckedItem(nullptr); m_items.clear(); emit itemsChanged(); } QQuickLabsPlatformMenuItem *QQuickLabsPlatformMenuItemGroup::findCurrent() const { for (QQuickLabsPlatformMenuItem *item : m_items) { if (item->isChecked()) return item; } return nullptr; } void QQuickLabsPlatformMenuItemGroup::updateCurrent() { if (!m_exclusive) return; QQuickLabsPlatformMenuItem *item = qobject_cast(sender()); if (item && item->isChecked()) setCheckedItem(item); } void QQuickLabsPlatformMenuItemGroup::activateItem() { QQuickLabsPlatformMenuItem *item = qobject_cast(sender()); if (item) emit triggered(item); } void QQuickLabsPlatformMenuItemGroup::hoverItem() { QQuickLabsPlatformMenuItem *item = qobject_cast(sender()); if (item) emit hovered(item); } void QQuickLabsPlatformMenuItemGroup::items_append(QQmlListProperty *prop, QQuickLabsPlatformMenuItem *item) { QQuickLabsPlatformMenuItemGroup *group = static_cast(prop->object); group->addItem(item); } qsizetype QQuickLabsPlatformMenuItemGroup::items_count(QQmlListProperty *prop) { QQuickLabsPlatformMenuItemGroup *group = static_cast(prop->object); return group->m_items.size(); } QQuickLabsPlatformMenuItem *QQuickLabsPlatformMenuItemGroup::items_at(QQmlListProperty *prop, qsizetype index) { QQuickLabsPlatformMenuItemGroup *group = static_cast(prop->object); return group->m_items.value(index); } void QQuickLabsPlatformMenuItemGroup::items_clear(QQmlListProperty *prop) { QQuickLabsPlatformMenuItemGroup *group = static_cast(prop->object); group->clear(); } QT_END_NAMESPACE #include "moc_qquicklabsplatformmenuitemgroup_p.cpp"