diff options
Diffstat (limited to 'tests')
-rw-r--r-- | tests/auto/quickcontrols/nativemenus/data/dynamicSubmenus.qml | 51 | ||||
-rw-r--r-- | tests/auto/quickcontrols/nativemenus/tst_nativemenus.cpp | 56 | ||||
-rw-r--r-- | tests/manual/quickcontrols/menus/main.qml | 80 |
3 files changed, 166 insertions, 21 deletions
diff --git a/tests/auto/quickcontrols/nativemenus/data/dynamicSubmenus.qml b/tests/auto/quickcontrols/nativemenus/data/dynamicSubmenus.qml new file mode 100644 index 0000000000..c0326fb511 --- /dev/null +++ b/tests/auto/quickcontrols/nativemenus/data/dynamicSubmenus.qml @@ -0,0 +1,51 @@ +// Copyright (C) 2024 The Qt Company Ltd. +// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR BSD-3-Clause + +import QtQuick +import QtQuick.Templates as T +import QtQuick.Controls + +ApplicationWindow { + width: 400 + height: 400 + + property alias contextMenu: contextMenu + + function addSubMenu(title: string) { + contextMenu.addMenu(subMenuComponent.createObject(null, { title: title })) + } + + function addAction(menu: T.Menu, text: string) { + menu.addAction(actionComponent.createObject(null, { text: text })) + } + + function insertAction(menu: T.Menu, index: int, text: string) { + menu.insertAction(index, actionComponent.createObject(null, { text: text })) + } + + Component { + id: actionComponent + + Action { + objectName: text + } + } + + Component { + id: subMenuComponent + + Menu { + id: subMenu + objectName: title + + Action { + text: subMenu.objectName + "Action1" + } + } + } + + Menu { + id: contextMenu + objectName: "menu" + } +} diff --git a/tests/auto/quickcontrols/nativemenus/tst_nativemenus.cpp b/tests/auto/quickcontrols/nativemenus/tst_nativemenus.cpp index 4e1fe9dd70..1de581eb7a 100644 --- a/tests/auto/quickcontrols/nativemenus/tst_nativemenus.cpp +++ b/tests/auto/quickcontrols/nativemenus/tst_nativemenus.cpp @@ -148,7 +148,7 @@ void tst_NativeMenus::dynamicActions() void tst_NativeMenus::dynamicSubmenus() { - QQuickControlsApplicationHelper helper(this, QLatin1String("emptyMenu.qml")); + QQuickControlsApplicationHelper helper(this, QLatin1String("dynamicSubmenus.qml")); QVERIFY2(helper.ready, helper.failureMessage()); QQuickApplicationWindow *window = helper.appWindow; window->show(); @@ -158,19 +158,61 @@ void tst_NativeMenus::dynamicSubmenus() QVERIFY(contextMenu); auto *contextMenuPrivate = QQuickMenuPrivate::get(contextMenu); - // Check that sub-menus (with no menu items, yet) can be appended to an empty parent menu. - QVERIFY(QMetaObject::invokeMethod(window, "addMenu", - Q_ARG(QQuickMenu *, contextMenu), Q_ARG(QString, "subMenu1"))); + // We construct the sub-menu first in QML. At least on Windows, menu items + // added to an empty sub-menu won't show up (tested with Widgets): QTBUG-120494. + // So, this adds an already-populated menu as a sub-menu. + QVERIFY(QMetaObject::invokeMethod(window, "addSubMenu", Q_ARG(QString, "subMenu1"))); auto subMenu1 = contextMenu->menuAt(0); + auto *subMenu1Private = QQuickMenuPrivate::get(subMenu1); QVERIFY(subMenu1); QCOMPARE(subMenu1->title(), "subMenu1"); QCOMPARE(contextMenuPrivate->contentData.at(0), subMenu1); + QCOMPARE(contextMenuPrivate->contentData.size(), 1); + { + auto subMenuAction1 = subMenu1->actionAt(0); + QVERIFY(subMenuAction1); + QCOMPARE(subMenuAction1->text(), "subMenu1Action1"); + QCOMPARE(subMenu1Private->contentData.at(0), subMenuAction1); + } - // + // Check that actions can be appended after existing items in the sub-menu. + QCOMPARE(subMenu1->actionAt(1), nullptr); QVERIFY(QMetaObject::invokeMethod(window, "addAction", - Q_ARG(QQuickMenu *, subMenu1), Q_ARG(QString, "subMenuAction1"))); + Q_ARG(QQuickMenu *, subMenu1), Q_ARG(QString, "subMenu1Action2"))); + { + auto subMenu1Action2 = subMenu1->actionAt(1); + QVERIFY(subMenu1Action2); + QCOMPARE(subMenu1Action2->text(), "subMenu1Action2"); + QCOMPARE(subMenu1Private->contentData.at(1), subMenu1Action2); + QCOMPARE(subMenu1Private->contentData.size(), 2); + } + + // Check that actions can be inserted before existing items in the sub-menu. + QVERIFY(QMetaObject::invokeMethod(window, "insertAction", + Q_ARG(QQuickMenu *, subMenu1), Q_ARG(int, 0), Q_ARG(QString, "subMenu1Action0"))); + { + auto subMenu1Action0 = subMenu1->actionAt(0); + QVERIFY(subMenu1Action0); + QCOMPARE(subMenu1Action0->text(), "subMenu1Action0"); + QCOMPARE(subMenu1Private->contentData.at(0), subMenu1Action0); + QCOMPARE(subMenu1Private->contentData.size(), 3); + } + + { + // Check that takeMenu works. + auto *takenSubMenu = contextMenu->takeMenu(0); + QCOMPARE(takenSubMenu, subMenu1); + QCOMPARE(contextMenuPrivate->contentData.size(), 0); + + // Check that the sub-menu can be added back in to the menu. + contextMenu->addMenu(takenSubMenu); + QCOMPARE(contextMenuPrivate->contentData.size(), 1); + } - // TODO: insert another sub-menu action before the first one + // Check that removeMenu works. + QVERIFY(contextMenu->menuAt(0)); + contextMenu->removeMenu(contextMenu->menuAt(0)); + QCOMPARE(contextMenuPrivate->contentData.size(), 0); } // TODO: add a test that mixes items with native items diff --git a/tests/manual/quickcontrols/menus/main.qml b/tests/manual/quickcontrols/menus/main.qml index 804b5637bb..59dfbac3fc 100644 --- a/tests/manual/quickcontrols/menus/main.qml +++ b/tests/manual/quickcontrols/menus/main.qml @@ -64,6 +64,7 @@ ApplicationWindow { text: qsTr("Right click on the window background to open a context menu. " + "Right click on the TextArea to access its edit context menu.\n\n" + "Things to check:\n\n" + + "- Do the menu items trigger their actions (check console for output)?\n" + "- Do the Edit menu items (in the MenuBar menu and edit context menu)" + " work as expected with the TextArea?\n" + " - Are they enabled/disabled as expected?\n" @@ -77,14 +78,35 @@ ApplicationWindow { Layout.fillHeight: true } - RowLayout { - Button { - text: qsTr("Add context menu item") - onClicked: backgroundContextMenu.appendAction() - } - Button { - text: qsTr("Remove context menu item") - onClicked: backgroundContextMenu.removeLastAction() + GroupBox { + title: qsTr("Context menu") + + Layout.fillWidth: true + + RowLayout { + anchors.fill: parent + + Button { + text: qsTr("Add action") + onClicked: backgroundContextMenu.appendAction() + } + Button { + text: qsTr("Remove action") + onClicked: backgroundContextMenu.removeLastAction() + } + + Button { + text: qsTr("Add sub-menu action") + onClicked: subMenu.appendAction() + } + Button { + text: qsTr("Remove sub-menu action") + onClicked: subMenu.removeLastAction() + } + + Item { + Layout.fillWidth: true + } } } @@ -115,6 +137,10 @@ ApplicationWindow { Action {} } + component ContextAction: Action { + onTriggered: print("triggered", text) + } + Menu { id: backgroundContextMenu @@ -132,29 +158,55 @@ ApplicationWindow { backgroundContextMenu.removeAction(backgroundContextMenu.actionAt(backgroundContextMenu.contentData.length - 1)) } - Action { + ContextAction { text: qsTr("Context menu item 1") } - Action { + ContextAction { text: qsTr("Context menu item 2") } - Action { + ContextAction { text: qsTr("Context menu item 3") } + + // TODO: separator + + Menu { + id: subMenu + title: qsTr("Sub-menu") + + function appendAction() { + let action = actionComponent.createObject(null, { text: qsTr("Extra sub-menu item") }) + subMenu.addAction(action) + } + + function removeLastAction() { + subMenu.removeAction(subMenu.actionAt(subMenu.contentData.length - 1)) + } + + ContextAction { + text: qsTr("Sub-menu item 1") + } + ContextAction { + text: qsTr("Sub-menu item 2") + } + ContextAction { + text: qsTr("Sub-menu item 3") + } + } } Menu { id: editContextMenu - Action { + ContextAction { text: qsTr("Cut") enabled: textArea.selectedText.length > 0 } - Action { + ContextAction { text: qsTr("Copy") enabled: textArea.selectedText.length > 0 } - Action { + ContextAction { text: qsTr("Paste") enabled: textArea.activeFocus } |