diff options
author | J-P Nurmi <jpnurmi@qt.io> | 2017-06-01 23:36:57 +0200 |
---|---|---|
committer | J-P Nurmi <jpnurmi@qt.io> | 2017-06-13 09:34:39 +0000 |
commit | 92fcd0a3fb2ee0d1ba242607c1aa5a29864d3650 (patch) | |
tree | e55ace5afc75cfaa17f2571fda8cfae2d8f4e9f8 /src/quicktemplates2 | |
parent | 23a80af1b5d31621bf1d342706c9541dd5273b86 (diff) |
Add support for cascading sub-menus
This commit adds initial support for cascading sub-menus by allowing
one to nest declarative Menu declarations. A follow-up commit adds
support for adding, inserting, and removing menus programmatically.
[ChangeLog][Controls][Menu] Added support for cascading sub-menus.
Task-number: QTBUG-60351
Change-Id: I0eee4f74d92a97c09333fcc4348b019782448535
Reviewed-by: Qt CI Bot <qt_ci_bot@qt-project.org>
Reviewed-by: Mitch Curtis <mitch.curtis@qt.io>
Diffstat (limited to 'src/quicktemplates2')
-rw-r--r-- | src/quicktemplates2/qquickmenu.cpp | 273 | ||||
-rw-r--r-- | src/quicktemplates2/qquickmenu_p.h | 10 | ||||
-rw-r--r-- | src/quicktemplates2/qquickmenu_p_p.h | 21 | ||||
-rw-r--r-- | src/quicktemplates2/qquickmenuitem.cpp | 64 | ||||
-rw-r--r-- | src/quicktemplates2/qquickmenuitem_p.h | 8 | ||||
-rw-r--r-- | src/quicktemplates2/qquickmenuitem_p_p.h | 3 |
6 files changed, 349 insertions, 30 deletions
diff --git a/src/quicktemplates2/qquickmenu.cpp b/src/quicktemplates2/qquickmenu.cpp index fa6b88ef..64f293d8 100644 --- a/src/quicktemplates2/qquickmenu.cpp +++ b/src/quicktemplates2/qquickmenu.cpp @@ -131,17 +131,30 @@ QT_BEGIN_NAMESPACE } \endcode - Since QtQuick.Controls 2.3 (Qt 5.10), it is also possible to declare - Action objects inside Menu: + Since QtQuick.Controls 2.3 (Qt 5.10), it is also possible to create sub-menus + and declare Action objects inside Menu: \code Menu { Action { text: "Cut" } Action { text: "Copy" } Action { text: "Paste" } + + MenuSeparator { } + + Menu { + title: "Find/Replace" + Action { text: "Find Next" } + Action { text: "Find Previous" } + Action { text: "Replace" } + } } \endcode + Sub-menus are \l {cascade}{cascading} by default on desktop platforms + that have a mouse cursor available. Non-cascading menus are shown one + menu at a time, and centered over the parent menu. + Typically, menu items are statically declared as children of the menu, but Menu also provides API to \l {addItem}{add}, \l {insertItem}{insert}, \l {moveItem}{move} and \l {removeItem}{remove} items dynamically. The @@ -154,8 +167,24 @@ QT_BEGIN_NAMESPACE \sa {Customizing Menu}, {Menu Controls}, {Popup Controls} */ +static const QQuickPopup::ClosePolicy defaultMenuClosePolicy = + QQuickPopup::CloseOnEscape | QQuickPopup::CloseOnPressOutside | QQuickPopup::CloseOnReleaseOutside; +static const QQuickPopup::ClosePolicy cascadingSubMenuClosePolicy = + QQuickPopup::CloseOnEscape | QQuickPopup::CloseOnPressOutsideParent | QQuickPopup::CloseOnReleaseOutsideParent; + +static bool shouldCascade() +{ +#if QT_CONFIG(cursor) + return QGuiApplicationPrivate::platformIntegration()->hasCapability(QPlatformIntegration::MultipleWindows); +#else + return false; +#endif +} + QQuickMenuPrivate::QQuickMenuPrivate() - : contentItem(nullptr), + : cascade(shouldCascade()), + overlap(0), + contentItem(nullptr), contentModel(nullptr), delegate(nullptr) { @@ -184,7 +213,7 @@ void QQuickMenuPrivate::insertItem(int index, QQuickItem *item) Q_Q(QQuickMenu); QQuickMenuItemPrivate::get(menuItem)->setMenu(q); QObjectPrivate::connect(menuItem, &QQuickMenuItem::pressed, this, &QQuickMenuPrivate::onItemPressed); - QObject::connect(menuItem, &QQuickMenuItem::triggered, q, &QQuickPopup::close); + QObjectPrivate::connect(menuItem, &QQuickMenuItem::triggered, this, &QQuickMenuPrivate::onItemTriggered); QObjectPrivate::connect(menuItem, &QQuickItem::activeFocusChanged, this, &QQuickMenuPrivate::onItemActiveFocusChanged); QObjectPrivate::connect(menuItem, &QQuickControl::hoveredChanged, this, &QQuickMenuPrivate::onItemHovered); } @@ -205,16 +234,15 @@ void QQuickMenuPrivate::removeItem(int index, QQuickItem *item) QQuickMenuItem *menuItem = qobject_cast<QQuickMenuItem *>(item); if (menuItem) { - Q_Q(QQuickMenu); QQuickMenuItemPrivate::get(menuItem)->setMenu(nullptr); QObjectPrivate::disconnect(menuItem, &QQuickMenuItem::pressed, this, &QQuickMenuPrivate::onItemPressed); - QObject::disconnect(menuItem, &QQuickMenuItem::triggered, q, &QQuickPopup::close); + QObjectPrivate::disconnect(menuItem, &QQuickMenuItem::triggered, this, &QQuickMenuPrivate::onItemTriggered); QObjectPrivate::disconnect(menuItem, &QQuickItem::activeFocusChanged, this, &QQuickMenuPrivate::onItemActiveFocusChanged); QObjectPrivate::disconnect(menuItem, &QQuickControl::hoveredChanged, this, &QQuickMenuPrivate::onItemHovered); } } -QQuickItem *QQuickMenuPrivate::createItem(QQuickAction *action) +QQuickItem *QQuickMenuPrivate::beginCreateItem() { Q_Q(QQuickMenu); if (!delegate) @@ -227,15 +255,37 @@ QQuickItem *QQuickMenuPrivate::createItem(QQuickAction *action) context->setContextObject(q); QObject *object = delegate->beginCreate(context); - if (QQuickItem *item = qobject_cast<QQuickItem *>(object)) { - if (QQuickAbstractButton *button = qobject_cast<QQuickAbstractButton*>(object)) - button->setAction(action); - delegate->completeCreate(); - return item; - } + QQuickItem *item = qobject_cast<QQuickItem *>(object); + if (!item) + delete object; + + return item; +} + +void QQuickMenuPrivate::completeCreateItem() +{ + if (!delegate) + return; - delete object; - return nullptr; + delegate->completeCreate(); +} + +QQuickItem *QQuickMenuPrivate::createItem(QQuickMenu *menu) +{ + QQuickItem *item = beginCreateItem(); + if (QQuickMenuItem *menuItem = qobject_cast<QQuickMenuItem *>(item)) + QQuickMenuItemPrivate::get(menuItem)->setSubMenu(menu); + completeCreateItem(); + return item; +} + +QQuickItem *QQuickMenuPrivate::createItem(QQuickAction *action) +{ + QQuickItem *item = beginCreateItem(); + if (QQuickAbstractButton *button = qobject_cast<QQuickAbstractButton *>(item)) + button->setAction(action); + completeCreateItem(); + return item; } void QQuickMenuPrivate::resizeItem(QQuickItem *item) @@ -299,6 +349,12 @@ void QQuickMenuPrivate::itemGeometryChanged(QQuickItem *, QQuickGeometryChange, resizeItems(); } +bool QQuickMenuPrivate::blockInput(QQuickItem *item, const QPointF &point) const +{ + // keep the parent menu open when a cascading sub-menu (this menu) is interacted with + return (cascade && parentMenu && contains(point)) || QQuickPopupPrivate::blockInput(item, point); +} + void QQuickMenuPrivate::onItemPressed() { Q_Q(QQuickMenu); @@ -314,9 +370,40 @@ void QQuickMenuPrivate::onItemHovered() if (!button || !button->isHovered() || QQuickAbstractButtonPrivate::get(button)->touchId != -1) return; + QQuickMenuItem *oldCurrentItem = currentItem; + int index = contentModel->indexOf(button, nullptr); - if (index != -1) + if (index != -1) { setCurrentIndex(index); + if (oldCurrentItem != currentItem) { + if (oldCurrentItem) + closeSubMenu(oldCurrentItem->subMenu()); + if (currentItem) { + QQuickMenu *subMenu = currentItem->menu(); + if (subMenu && subMenu->cascade()) + openSubMenu(currentItem, false); + } + } + } +} + +void QQuickMenuPrivate::onItemTriggered() +{ + Q_Q(QQuickMenu); + QQuickMenuItem *item = qobject_cast<QQuickMenuItem *>(q->sender()); + if (!item) + return; + + if (item->subMenu()) { + openSubMenu(item, true); + } else { + // close the whole chain of menus + q->close(); + while (parentMenu) { + parentMenu->close(); + parentMenu = QQuickMenuPrivate::get(parentMenu)->parentMenu; + } + } } void QQuickMenuPrivate::onItemActiveFocusChanged() @@ -330,6 +417,67 @@ void QQuickMenuPrivate::onItemActiveFocusChanged() setCurrentIndex(indexOfItem); } +void QQuickMenuPrivate::openSubMenu(QQuickMenuItem *item, bool activate) +{ + Q_Q(QQuickMenu); + QQuickMenu *subMenu = item ? item->subMenu() : nullptr; + if (!subMenu) + return; + + if (cascade) { + subMenu->setParentItem(item); + subMenu->setClosePolicy(cascadingSubMenuClosePolicy); + if (popupItem->isMirrored()) { + subMenu->setTransformOrigin(QQuickPopup::TopRight); + subMenu->setPosition(QPointF(-subMenu->width() - q->leftPadding() + subMenu->overlap(), -subMenu->topPadding())); + } else { + subMenu->setTransformOrigin(QQuickPopup::TopLeft); + subMenu->setPosition(QPointF(item->width() + q->rightPadding() - subMenu->overlap(), -subMenu->topPadding())); + } + } else { + subMenu->setParentItem(parentItem); + subMenu->setClosePolicy(defaultMenuClosePolicy); + subMenu->setTransformOrigin(QQuickPopup::Center); + subMenu->setPosition(QPointF(q->x() + (q->width() - subMenu->width()) / 2, + q->y() + (q->height() - subMenu->height()) / 2)); + } + + QQuickMenuPrivate *p = QQuickMenuPrivate::get(subMenu); + p->parentMenu = q; + if (activate) + p->setCurrentIndex(0); + subMenu->setCascade(cascade); + subMenu->open(); + + // transfer focus to the sub-menu + if (focus) + subMenu->popupItem()->setFocus(true); + + if (!subMenu->cascade()) + q->close(); +} + +void QQuickMenuPrivate::closeSubMenu(QQuickMenu *subMenu) +{ + if (!subMenu || !subMenu->isVisible()) + return; + + // transfer focus back to the parent menu + QQuickMenu *parentMenu = QQuickMenuPrivate::get(subMenu)->parentMenu; + if (parentMenu && parentMenu->hasFocus()) { + parentMenu->popupItem()->setFocus(true); + if (!subMenu->cascade()) + parentMenu->open(); + } + + // close the whole chain of sub-menus + while (subMenu) { + QPointer<QQuickMenuItem> currentSubMenuItem = QQuickMenuPrivate::get(subMenu)->currentItem; + subMenu->close(); + subMenu = currentSubMenuItem ? currentSubMenuItem->subMenu() : nullptr; + } +} + int QQuickMenuPrivate::currentIndex() const { QVariant index = contentItem->property("currentIndex"); @@ -355,13 +503,15 @@ void QQuickMenuPrivate::setCurrentIndex(int index) void QQuickMenuPrivate::contentData_append(QQmlListProperty<QObject> *prop, QObject *obj) { - QQuickMenuPrivate *p = static_cast<QQuickMenuPrivate *>(prop->data); - QQuickMenu *q = static_cast<QQuickMenu *>(prop->object); + QQuickMenu *q = qobject_cast<QQuickMenu *>(prop->object); + QQuickMenuPrivate *p = QQuickMenuPrivate::get(q); QQuickItem *item = qobject_cast<QQuickItem *>(obj); if (!item) { if (QQuickAction *action = qobject_cast<QQuickAction *>(obj)) item = p->createItem(action); + else if (QQuickMenu *menu = qobject_cast<QQuickMenu *>(obj)) + item = p->createItem(menu); } if (item) { @@ -378,27 +528,27 @@ void QQuickMenuPrivate::contentData_append(QQmlListProperty<QObject> *prop, QObj int QQuickMenuPrivate::contentData_count(QQmlListProperty<QObject> *prop) { - QQuickMenuPrivate *p = static_cast<QQuickMenuPrivate *>(prop->data); - return p->contentData.count(); + QQuickMenu *q = static_cast<QQuickMenu *>(prop->object); + return QQuickMenuPrivate::get(q)->contentData.count(); } QObject *QQuickMenuPrivate::contentData_at(QQmlListProperty<QObject> *prop, int index) { - QQuickMenuPrivate *p = static_cast<QQuickMenuPrivate *>(prop->data); - return p->contentData.value(index); + QQuickMenu *q = static_cast<QQuickMenu *>(prop->object); + return QQuickMenuPrivate::get(q)->contentData.value(index); } void QQuickMenuPrivate::contentData_clear(QQmlListProperty<QObject> *prop) { - QQuickMenuPrivate *p = static_cast<QQuickMenuPrivate *>(prop->data); - p->contentData.clear(); + QQuickMenu *q = static_cast<QQuickMenu *>(prop->object); + QQuickMenuPrivate::get(q)->contentData.clear(); } QQuickMenu::QQuickMenu(QObject *parent) : QQuickPopup(*(new QQuickMenuPrivate), parent) { setFocus(true); - setClosePolicy(CloseOnEscape | CloseOnPressOutside | CloseOnReleaseOutside); + setClosePolicy(defaultMenuClosePolicy); } /*! @@ -568,8 +718,7 @@ QVariant QQuickMenu::contentModel() const */ QQmlListProperty<QObject> QQuickMenu::contentData() { - Q_D(QQuickMenu); - return QQmlListProperty<QObject>(this, d, + return QQmlListProperty<QObject>(this, nullptr, QQuickMenuPrivate::contentData_append, QQuickMenuPrivate::contentData_count, QQuickMenuPrivate::contentData_at, @@ -602,6 +751,64 @@ void QQuickMenu::setTitle(QString &title) /*! \since QtQuick.Controls 2.3 (Qt 5.10) + \qmlproperty bool QtQuick.Controls::Menu::cascade + + This property holds whether the menu cascades its sub-menus. + + The default value is platform-specific. Menus are cascading by default on + desktop platforms that have a mouse cursor available. Non-cascading menus + are shown one menu at a time, and centered over the parent menu. + + \note Changing the value of the property has no effect while the menu is open. + + \sa overlap +*/ +bool QQuickMenu::cascade() const +{ + Q_D(const QQuickMenu); + return d->cascade; +} + +void QQuickMenu::setCascade(bool cascade) +{ + Q_D(QQuickMenu); + if (d->cascade == cascade) + return; + d->cascade = cascade; + emit cascadeChanged(); +} + +/*! + \since QtQuick.Controls 2.3 (Qt 5.10) + \qmlproperty real QtQuick.Controls::Menu::overlap + + This property holds the amount of pixels by which the menu horizontally overlaps its parent menu. + + The property only has effect when the menu is used as a cascading sub-menu. + + The default value is style-specific. + + \note Changing the value of the property has no effect while the menu is open. + + \sa cascade +*/ +qreal QQuickMenu::overlap() const +{ + Q_D(const QQuickMenu); + return d->overlap; +} + +void QQuickMenu::setOverlap(qreal overlap) +{ + Q_D(QQuickMenu); + if (d->overlap == overlap) + return; + d->overlap = overlap; + emit cascadeChanged(); +} + +/*! + \since QtQuick.Controls 2.3 (Qt 5.10) \qmlproperty Component QtQuick.Controls::Menu::delegate This property holds the component that is used to create items @@ -758,7 +965,7 @@ void QQuickMenu::itemChange(QQuickItem::ItemChange change, const QQuickItem::Ite QQuickPopup::itemChange(change, data); if (change == QQuickItem::ItemVisibleHasChanged) { - if (!data.boolValue) { + if (!data.boolValue && d->cascade) { // Ensure that when the menu isn't visible, there's no current item // the next time it's opened. QQuickItem *focusItem = QQuickItemPrivate::get(d->contentItem)->subFocusItem; @@ -796,6 +1003,16 @@ void QQuickMenu::keyReleaseEvent(QKeyEvent *event) QMetaObject::invokeMethod(d->contentItem, "incrementCurrentIndex"); break; + case Qt::Key_Left: + case Qt::Key_Right: + if (d->popupItem->isMirrored() == (event->key() == Qt::Key_Right)) { + if (d->parentMenu && d->currentItem) + d->closeSubMenu(this); + } else { + d->openSubMenu(d->currentItem, true); + } + return; + default: break; } diff --git a/src/quicktemplates2/qquickmenu_p.h b/src/quicktemplates2/qquickmenu_p.h index 04186f1a..f7f56d45 100644 --- a/src/quicktemplates2/qquickmenu_p.h +++ b/src/quicktemplates2/qquickmenu_p.h @@ -65,6 +65,8 @@ class Q_QUICKTEMPLATES2_PRIVATE_EXPORT QQuickMenu : public QQuickPopup Q_PROPERTY(QVariant contentModel READ contentModel CONSTANT FINAL) Q_PROPERTY(QQmlListProperty<QObject> contentData READ contentData FINAL) Q_PROPERTY(QString title READ title WRITE setTitle NOTIFY titleChanged FINAL) + Q_PROPERTY(bool cascade READ cascade WRITE setCascade NOTIFY cascadeChanged FINAL REVISION 3) + Q_PROPERTY(qreal overlap READ overlap WRITE setOverlap NOTIFY overlapChanged FINAL REVISION 3) Q_PROPERTY(QQmlComponent *delegate READ delegate WRITE setDelegate NOTIFY delegateChanged FINAL REVISION 3) Q_CLASSINFO("DefaultProperty", "contentData") @@ -85,6 +87,12 @@ public: QString title() const; void setTitle(QString &title); + bool cascade() const; + void setCascade(bool cascade); + + qreal overlap() const; + void setOverlap(qreal overlap); + QQmlComponent *delegate() const; void setDelegate(QQmlComponent *delegate); @@ -98,6 +106,8 @@ protected: Q_SIGNALS: void titleChanged(const QString &title); + Q_REVISION(3) void cascadeChanged(); + Q_REVISION(3) void overlapChanged(); Q_REVISION(3) void delegateChanged(); protected: diff --git a/src/quicktemplates2/qquickmenu_p_p.h b/src/quicktemplates2/qquickmenu_p_p.h index b9e0512b..9fd10779 100644 --- a/src/quicktemplates2/qquickmenu_p_p.h +++ b/src/quicktemplates2/qquickmenu_p_p.h @@ -51,11 +51,11 @@ #include <QtCore/qvector.h> #include <QtCore/qpointer.h> +#include <QtQuickTemplates2/private/qquickmenu_p.h> #include <QtQuickTemplates2/private/qquickpopup_p_p.h> QT_BEGIN_NAMESPACE -class QQuickMenu; class QQuickAction; class QQmlComponent; class QQmlObjectModel; @@ -68,10 +68,20 @@ class Q_QUICKTEMPLATES2_PRIVATE_EXPORT QQuickMenuPrivate : public QQuickPopupPri public: QQuickMenuPrivate(); + static QQuickMenuPrivate *get(QQuickMenu *menu) + { + return menu->d_func(); + } + QQuickItem *itemAt(int index) const; void insertItem(int index, QQuickItem *item); void moveItem(int from, int to); void removeItem(int index, QQuickItem *item); + + QQuickItem *beginCreateItem(); + void completeCreateItem(); + + QQuickItem *createItem(QQuickMenu *menu); QQuickItem *createItem(QQuickAction *action); void resizeItem(QQuickItem *item); @@ -83,10 +93,16 @@ public: void itemDestroyed(QQuickItem *item) override; void itemGeometryChanged(QQuickItem *, QQuickGeometryChange change, const QRectF &diff) override; + bool blockInput(QQuickItem *item, const QPointF &point) const override; + void onItemPressed(); void onItemHovered(); + void onItemTriggered(); void onItemActiveFocusChanged(); + void openSubMenu(QQuickMenuItem *item, bool activate); + void closeSubMenu(QQuickMenu *subMenu); + int currentIndex() const; void setCurrentIndex(int index); @@ -95,6 +111,9 @@ public: static QObject *contentData_at(QQmlListProperty<QObject> *prop, int index); static void contentData_clear(QQmlListProperty<QObject> *prop); + bool cascade; + qreal overlap; + QPointer<QQuickMenu> parentMenu; QPointer<QQuickMenuItem> currentItem; QQuickItem *contentItem; // TODO: cleanup QVector<QObject *> contentData; diff --git a/src/quicktemplates2/qquickmenuitem.cpp b/src/quicktemplates2/qquickmenuitem.cpp index 3ef03caf..69a2b73b 100644 --- a/src/quicktemplates2/qquickmenuitem.cpp +++ b/src/quicktemplates2/qquickmenuitem.cpp @@ -36,6 +36,7 @@ #include "qquickmenuitem_p.h" #include "qquickmenuitem_p_p.h" +#include "qquickmenu_p.h" #include <QtGui/qpa/qplatformtheme.h> #include <QtQuick/private/qquickevents_p_p.h> @@ -89,7 +90,9 @@ QT_BEGIN_NAMESPACE QQuickMenuItemPrivate::QQuickMenuItemPrivate() : highlighted(false), - menu(nullptr) + arrow(nullptr), + menu(nullptr), + subMenu(nullptr) { } @@ -103,6 +106,24 @@ void QQuickMenuItemPrivate::setMenu(QQuickMenu *newMenu) emit q->menuChanged(); } +void QQuickMenuItemPrivate::setSubMenu(QQuickMenu *newSubMenu) +{ + Q_Q(QQuickMenuItem); + if (subMenu == newSubMenu) + return; + + if (subMenu) + QObject::disconnect(subMenu, &QQuickMenu::titleChanged, q, &QQuickAbstractButton::setText); + + if (newSubMenu) { + QObject::connect(newSubMenu, &QQuickMenu::titleChanged, q, &QQuickAbstractButton::setText); + q->setText(newSubMenu->title()); + } + + subMenu = newSubMenu; + emit q->subMenuChanged(); +} + /*! \qmlsignal void QtQuick.Controls::MenuItem::triggered() @@ -142,6 +163,33 @@ void QQuickMenuItem::setHighlighted(bool highlighted) /*! \since QtQuick.Controls 2.3 (Qt 5.10) + \qmlproperty Item QtQuick.Controls::MenuItem::arrow + + This property holds the sub-menu arrow item. + + \sa {Customizing MenuItem} +*/ +QQuickItem *QQuickMenuItem::arrow() const +{ + Q_D(const QQuickMenuItem); + return d->arrow; +} + +void QQuickMenuItem::setArrow(QQuickItem *arrow) +{ + Q_D(QQuickMenuItem); + if (d->arrow == arrow) + return; + + QQuickControlPrivate::destroyDelegate(d->arrow, this); + d->arrow = arrow; + if (arrow && !arrow->parentItem()) + arrow->setParentItem(this); + emit arrowChanged(); +} + +/*! + \since QtQuick.Controls 2.3 (Qt 5.10) \qmlproperty Menu QtQuick.Controls::MenuItem::menu \readonly @@ -154,6 +202,20 @@ QQuickMenu *QQuickMenuItem::menu() const return d->menu; } +/*! + \since QtQuick.Controls 2.3 (Qt 5.10) + \qmlproperty Menu QtQuick.Controls::MenuItem::subMenu + \readonly + + This property holds the sub-menu that this item presents in + the parent menu, or \c null if this item is not a sub-menu item. +*/ +QQuickMenu *QQuickMenuItem::subMenu() const +{ + Q_D(const QQuickMenuItem); + return d->subMenu; +} + QFont QQuickMenuItem::defaultFont() const { return QQuickControlPrivate::themeFont(QPlatformTheme::MenuItemFont); diff --git a/src/quicktemplates2/qquickmenuitem_p.h b/src/quicktemplates2/qquickmenuitem_p.h index 92b42488..7c469b6a 100644 --- a/src/quicktemplates2/qquickmenuitem_p.h +++ b/src/quicktemplates2/qquickmenuitem_p.h @@ -59,7 +59,9 @@ class Q_QUICKTEMPLATES2_PRIVATE_EXPORT QQuickMenuItem : public QQuickAbstractBut { Q_OBJECT Q_PROPERTY(bool highlighted READ isHighlighted WRITE setHighlighted NOTIFY highlightedChanged FINAL) + Q_PROPERTY(QQuickItem *arrow READ arrow WRITE setArrow NOTIFY arrowChanged FINAL REVISION 3) Q_PROPERTY(QQuickMenu *menu READ menu NOTIFY menuChanged FINAL REVISION 3) + Q_PROPERTY(QQuickMenu *subMenu READ subMenu NOTIFY subMenuChanged FINAL REVISION 3) public: explicit QQuickMenuItem(QQuickItem *parent = nullptr); @@ -67,12 +69,18 @@ public: bool isHighlighted() const; void setHighlighted(bool highlighted); + QQuickItem *arrow() const; + void setArrow(QQuickItem *arrow); + QQuickMenu *menu() const; + QQuickMenu *subMenu() const; Q_SIGNALS: void triggered(); void highlightedChanged(); + Q_REVISION(3) void arrowChanged(); Q_REVISION(3) void menuChanged(); + Q_REVISION(3) void subMenuChanged(); protected: QFont defaultFont() const override; diff --git a/src/quicktemplates2/qquickmenuitem_p_p.h b/src/quicktemplates2/qquickmenuitem_p_p.h index f1cded91..d8b86d6e 100644 --- a/src/quicktemplates2/qquickmenuitem_p_p.h +++ b/src/quicktemplates2/qquickmenuitem_p_p.h @@ -68,9 +68,12 @@ public: } void setMenu(QQuickMenu *menu); + void setSubMenu(QQuickMenu *subMenu); bool highlighted; + QQuickItem *arrow; QQuickMenu *menu; + QQuickMenu *subMenu; }; QT_END_NAMESPACE |