aboutsummaryrefslogtreecommitdiffstats
path: root/tests/auto/quickcontrols/qquickmenu
diff options
context:
space:
mode:
Diffstat (limited to 'tests/auto/quickcontrols/qquickmenu')
-rw-r--r--tests/auto/quickcontrols/qquickmenu/CMakeLists.txt2
-rw-r--r--tests/auto/quickcontrols/qquickmenu/data/actionShortcuts.qml2
-rw-r--r--tests/auto/quickcontrols/qquickmenu/data/actions.qml2
-rw-r--r--tests/auto/quickcontrols/qquickmenu/data/addItem.qml2
-rw-r--r--tests/auto/quickcontrols/qquickmenu/data/applicationWindowScrollable.qml2
-rw-r--r--tests/auto/quickcontrols/qquickmenu/data/applicationwindow.qml2
-rw-r--r--tests/auto/quickcontrols/qquickmenu/data/delegateFromSeparateComponent.qml2
-rw-r--r--tests/auto/quickcontrols/qquickmenu/data/disableWhenTriggered.qml2
-rw-r--r--tests/auto/quickcontrols/qquickmenu/data/disabledMenuItemKeyNavigation.qml2
-rw-r--r--tests/auto/quickcontrols/qquickmenu/data/giveMenuItemFocusOnButtonPress.qml2
-rw-r--r--tests/auto/quickcontrols/qquickmenu/data/invalidUrlInImgTag.qml14
-rw-r--r--tests/auto/quickcontrols/qquickmenu/data/menuItemWidths.qml2
-rw-r--r--tests/auto/quickcontrols/qquickmenu/data/menuSeparator.qml2
-rw-r--r--tests/auto/quickcontrols/qquickmenu/data/mnemonics.qml2
-rw-r--r--tests/auto/quickcontrols/qquickmenu/data/nativeDynamicSubmenus.qml53
-rw-r--r--tests/auto/quickcontrols/qquickmenu/data/nativeEmptyMenu.qml51
-rw-r--r--tests/auto/quickcontrols/qquickmenu/data/nativeMenuSeparator.qml43
-rw-r--r--tests/auto/quickcontrols/qquickmenu/data/nativeMixedItems.qml69
-rw-r--r--tests/auto/quickcontrols/qquickmenu/data/nativeStatic.qml53
-rw-r--r--tests/auto/quickcontrols/qquickmenu/data/order.qml2
-rw-r--r--tests/auto/quickcontrols/qquickmenu/data/popup.qml2
-rw-r--r--tests/auto/quickcontrols/qquickmenu/data/pressAndHold.qml2
-rw-r--r--tests/auto/quickcontrols/qquickmenu/data/removeTakeItem.qml2
-rw-r--r--tests/auto/quickcontrols/qquickmenu/data/repeater.qml2
-rw-r--r--tests/auto/quickcontrols/qquickmenu/data/scrollableWithFixedHeight.qml27
-rw-r--r--tests/auto/quickcontrols/qquickmenu/data/scrollableWithPadding.qml2
-rw-r--r--tests/auto/quickcontrols/qquickmenu/data/subMenuDisabled.qml2
-rw-r--r--tests/auto/quickcontrols/qquickmenu/data/subMenus.qml2
-rw-r--r--tests/auto/quickcontrols/qquickmenu/data/windowScrollable.qml2
-rw-r--r--tests/auto/quickcontrols/qquickmenu/tst_qquickmenu.cpp735
30 files changed, 1043 insertions, 46 deletions
diff --git a/tests/auto/quickcontrols/qquickmenu/CMakeLists.txt b/tests/auto/quickcontrols/qquickmenu/CMakeLists.txt
index 0277c88446..92bb70af07 100644
--- a/tests/auto/quickcontrols/qquickmenu/CMakeLists.txt
+++ b/tests/auto/quickcontrols/qquickmenu/CMakeLists.txt
@@ -6,7 +6,7 @@
if (NOT QT_BUILD_STANDALONE_TESTS AND NOT QT_BUILDING_QT)
cmake_minimum_required(VERSION 3.16)
project(tst_qquickmenu LANGUAGES C CXX ASM)
- find_package(Qt6BuildInternals COMPONENTS STANDALONE_TEST)
+ find_package(Qt6BuildInternals REQUIRED COMPONENTS STANDALONE_TEST)
endif()
#####################################################################
diff --git a/tests/auto/quickcontrols/qquickmenu/data/actionShortcuts.qml b/tests/auto/quickcontrols/qquickmenu/data/actionShortcuts.qml
index 3d839b98d4..0fbc813250 100644
--- a/tests/auto/quickcontrols/qquickmenu/data/actionShortcuts.qml
+++ b/tests/auto/quickcontrols/qquickmenu/data/actionShortcuts.qml
@@ -1,5 +1,5 @@
// Copyright (C) 2022 The Qt Company Ltd.
-// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR BSD-3-Clause
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
import QtQuick
import QtQuick.Controls
diff --git a/tests/auto/quickcontrols/qquickmenu/data/actions.qml b/tests/auto/quickcontrols/qquickmenu/data/actions.qml
index 0c4449d888..6420531c12 100644
--- a/tests/auto/quickcontrols/qquickmenu/data/actions.qml
+++ b/tests/auto/quickcontrols/qquickmenu/data/actions.qml
@@ -1,5 +1,5 @@
// Copyright (C) 2017 The Qt Company Ltd.
-// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR BSD-3-Clause
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
import QtQuick
import QtQuick.Controls
diff --git a/tests/auto/quickcontrols/qquickmenu/data/addItem.qml b/tests/auto/quickcontrols/qquickmenu/data/addItem.qml
index 5678210e25..db9fdccd36 100644
--- a/tests/auto/quickcontrols/qquickmenu/data/addItem.qml
+++ b/tests/auto/quickcontrols/qquickmenu/data/addItem.qml
@@ -1,5 +1,5 @@
// Copyright (C) 2017 The Qt Company Ltd.
-// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR BSD-3-Clause
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
import QtQuick
import QtQuick.Controls
diff --git a/tests/auto/quickcontrols/qquickmenu/data/applicationWindowScrollable.qml b/tests/auto/quickcontrols/qquickmenu/data/applicationWindowScrollable.qml
index eb8140eea5..3c95846d21 100644
--- a/tests/auto/quickcontrols/qquickmenu/data/applicationWindowScrollable.qml
+++ b/tests/auto/quickcontrols/qquickmenu/data/applicationWindowScrollable.qml
@@ -1,5 +1,5 @@
// Copyright (C) 2018 The Qt Company Ltd.
-// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR BSD-3-Clause
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
import QtQuick
import QtQuick.Controls
diff --git a/tests/auto/quickcontrols/qquickmenu/data/applicationwindow.qml b/tests/auto/quickcontrols/qquickmenu/data/applicationwindow.qml
index 1b42ee6965..253e265a81 100644
--- a/tests/auto/quickcontrols/qquickmenu/data/applicationwindow.qml
+++ b/tests/auto/quickcontrols/qquickmenu/data/applicationwindow.qml
@@ -1,5 +1,5 @@
// Copyright (C) 2017 The Qt Company Ltd.
-// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR BSD-3-Clause
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
import QtQuick
import QtQuick.Controls
diff --git a/tests/auto/quickcontrols/qquickmenu/data/delegateFromSeparateComponent.qml b/tests/auto/quickcontrols/qquickmenu/data/delegateFromSeparateComponent.qml
index 44a7d8d54a..e0009bf94e 100644
--- a/tests/auto/quickcontrols/qquickmenu/data/delegateFromSeparateComponent.qml
+++ b/tests/auto/quickcontrols/qquickmenu/data/delegateFromSeparateComponent.qml
@@ -1,5 +1,5 @@
// Copyright (C) 2018 The Qt Company Ltd.
-// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR BSD-3-Clause
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
import QtQuick
import QtQuick.Controls
diff --git a/tests/auto/quickcontrols/qquickmenu/data/disableWhenTriggered.qml b/tests/auto/quickcontrols/qquickmenu/data/disableWhenTriggered.qml
index e59026677a..b745bcea11 100644
--- a/tests/auto/quickcontrols/qquickmenu/data/disableWhenTriggered.qml
+++ b/tests/auto/quickcontrols/qquickmenu/data/disableWhenTriggered.qml
@@ -1,5 +1,5 @@
// Copyright (C) 2018 The Qt Company Ltd.
-// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR BSD-3-Clause
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
import QtQuick
import QtQuick.Controls
diff --git a/tests/auto/quickcontrols/qquickmenu/data/disabledMenuItemKeyNavigation.qml b/tests/auto/quickcontrols/qquickmenu/data/disabledMenuItemKeyNavigation.qml
index c9c893bb9c..827729370f 100644
--- a/tests/auto/quickcontrols/qquickmenu/data/disabledMenuItemKeyNavigation.qml
+++ b/tests/auto/quickcontrols/qquickmenu/data/disabledMenuItemKeyNavigation.qml
@@ -1,5 +1,5 @@
// Copyright (C) 2019 The Qt Company Ltd.
-// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR BSD-3-Clause
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
import QtQuick
import QtQuick.Controls
diff --git a/tests/auto/quickcontrols/qquickmenu/data/giveMenuItemFocusOnButtonPress.qml b/tests/auto/quickcontrols/qquickmenu/data/giveMenuItemFocusOnButtonPress.qml
index 1db3e351bc..c4e8df236a 100644
--- a/tests/auto/quickcontrols/qquickmenu/data/giveMenuItemFocusOnButtonPress.qml
+++ b/tests/auto/quickcontrols/qquickmenu/data/giveMenuItemFocusOnButtonPress.qml
@@ -1,5 +1,5 @@
// Copyright (C) 2020 The Qt Company Ltd.
-// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR BSD-3-Clause
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
import QtQuick
import QtQuick.Controls
diff --git a/tests/auto/quickcontrols/qquickmenu/data/invalidUrlInImgTag.qml b/tests/auto/quickcontrols/qquickmenu/data/invalidUrlInImgTag.qml
new file mode 100644
index 0000000000..0bc6c92fd6
--- /dev/null
+++ b/tests/auto/quickcontrols/qquickmenu/data/invalidUrlInImgTag.qml
@@ -0,0 +1,14 @@
+import QtQuick
+import QtQuick.Controls
+
+ApplicationWindow {
+ width: 100
+ height: 100
+ property alias menu: menu
+ Menu {
+ id: menu
+ MenuItem{
+ text: "<img />"
+ }
+ }
+}
diff --git a/tests/auto/quickcontrols/qquickmenu/data/menuItemWidths.qml b/tests/auto/quickcontrols/qquickmenu/data/menuItemWidths.qml
index ff99abd399..ab8cce3833 100644
--- a/tests/auto/quickcontrols/qquickmenu/data/menuItemWidths.qml
+++ b/tests/auto/quickcontrols/qquickmenu/data/menuItemWidths.qml
@@ -1,5 +1,5 @@
// Copyright (C) 2019 The Qt Company Ltd.
-// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR BSD-3-Clause
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
import QtQuick
import QtQuick.Controls
diff --git a/tests/auto/quickcontrols/qquickmenu/data/menuSeparator.qml b/tests/auto/quickcontrols/qquickmenu/data/menuSeparator.qml
index b13cd534fd..570dcb3f4d 100644
--- a/tests/auto/quickcontrols/qquickmenu/data/menuSeparator.qml
+++ b/tests/auto/quickcontrols/qquickmenu/data/menuSeparator.qml
@@ -1,5 +1,5 @@
// Copyright (C) 2017 The Qt Company Ltd.
-// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR BSD-3-Clause
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
import QtQuick
import QtQuick.Controls
diff --git a/tests/auto/quickcontrols/qquickmenu/data/mnemonics.qml b/tests/auto/quickcontrols/qquickmenu/data/mnemonics.qml
index 8929b00275..3e072e130f 100644
--- a/tests/auto/quickcontrols/qquickmenu/data/mnemonics.qml
+++ b/tests/auto/quickcontrols/qquickmenu/data/mnemonics.qml
@@ -1,5 +1,5 @@
// Copyright (C) 2017 The Qt Company Ltd.
-// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR BSD-3-Clause
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
import QtQuick
import QtQuick.Controls
diff --git a/tests/auto/quickcontrols/qquickmenu/data/nativeDynamicSubmenus.qml b/tests/auto/quickcontrols/qquickmenu/data/nativeDynamicSubmenus.qml
new file mode 100644
index 0000000000..951cb7cb6c
--- /dev/null
+++ b/tests/auto/quickcontrols/qquickmenu/data/nativeDynamicSubmenus.qml
@@ -0,0 +1,53 @@
+// 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
+ popupType: Popup.Native
+
+ Action {
+ text: subMenu.objectName + "Action1"
+ }
+ }
+ }
+
+ Menu {
+ id: contextMenu
+ objectName: "menu"
+ popupType: Popup.Native
+ }
+}
diff --git a/tests/auto/quickcontrols/qquickmenu/data/nativeEmptyMenu.qml b/tests/auto/quickcontrols/qquickmenu/data/nativeEmptyMenu.qml
new file mode 100644
index 0000000000..0ae2c5dc66
--- /dev/null
+++ b/tests/auto/quickcontrols/qquickmenu/data/nativeEmptyMenu.qml
@@ -0,0 +1,51 @@
+// Copyright (C) 2023 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 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 }))
+ }
+
+ function removeAction(menu: T.Menu, index: int) {
+ menu.removeAction(menu.actionAt(index))
+ }
+
+ function addMenu(menu: T.Menu, title: string) {
+ menu.addMenu(menuComponent.createObject(null, { title: title }))
+ }
+
+ Component {
+ id: actionComponent
+
+ Action {
+ objectName: text
+ }
+ }
+
+ Component {
+ id: menuComponent
+
+ Menu {
+ objectName: title
+ }
+ }
+
+ Menu {
+ id: contextMenu
+ objectName: "menu"
+ popupType: Popup.Native
+ }
+}
diff --git a/tests/auto/quickcontrols/qquickmenu/data/nativeMenuSeparator.qml b/tests/auto/quickcontrols/qquickmenu/data/nativeMenuSeparator.qml
new file mode 100644
index 0000000000..54195af349
--- /dev/null
+++ b/tests/auto/quickcontrols/qquickmenu/data/nativeMenuSeparator.qml
@@ -0,0 +1,43 @@
+// Copyright (C) 2024 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR BSD-3-Clause
+
+import QtQuick
+import QtQuick.Controls
+
+ApplicationWindow {
+ width: 400
+ height: 400
+
+ property alias contextMenu: contextMenu
+
+ Menu {
+ id: contextMenu
+ objectName: "menu"
+ popupType: Popup.Native
+
+ Action {
+ objectName: text
+ text: "action1"
+ }
+
+ MenuSeparator {}
+
+ Menu {
+ id: subMenu
+ objectName: "subMenu"
+ popupType: Popup.Native
+
+ Action {
+ objectName: text
+ text: "subAction1"
+ }
+
+ MenuSeparator {}
+
+ Action {
+ objectName: text
+ text: "subAction2"
+ }
+ }
+ }
+}
diff --git a/tests/auto/quickcontrols/qquickmenu/data/nativeMixedItems.qml b/tests/auto/quickcontrols/qquickmenu/data/nativeMixedItems.qml
new file mode 100644
index 0000000000..119d8debec
--- /dev/null
+++ b/tests/auto/quickcontrols/qquickmenu/data/nativeMixedItems.qml
@@ -0,0 +1,69 @@
+// 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 insertRectangle(menu: T.Menu, index: int, color: color) {
+ menu.insertItem(index, rectangleComponent.createObject(null, { color: color }))
+ }
+
+ Component {
+ id: rectangleComponent
+
+ Rectangle {
+ objectName: "rectangle"
+ width: 32
+ height: 32
+ }
+ }
+
+ Component {
+ id: menuComponent
+
+ Menu {
+ objectName: title
+ popupType: contextMenu.popupType
+ }
+ }
+
+ Menu {
+ id: contextMenu
+ objectName: "menu"
+ popupType: contextMenu.popupType
+
+ Action {
+ objectName: text
+ text: "action"
+ }
+
+ MenuItem {
+ text: "menuItem"
+ objectName: text
+ }
+
+ Menu {
+ id: subMenu
+ title: "subMenu"
+ objectName: title
+ popupType: contextMenu.popupType
+
+ Action {
+ objectName: text
+ text: "subAction1"
+ }
+
+ Action {
+ objectName: text
+ text: "subAction2"
+ }
+ }
+ }
+}
diff --git a/tests/auto/quickcontrols/qquickmenu/data/nativeStatic.qml b/tests/auto/quickcontrols/qquickmenu/data/nativeStatic.qml
new file mode 100644
index 0000000000..32ba1f1829
--- /dev/null
+++ b/tests/auto/quickcontrols/qquickmenu/data/nativeStatic.qml
@@ -0,0 +1,53 @@
+// Copyright (C) 2023 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
+
+ Menu {
+ id: contextMenu
+ objectName: "menu"
+ popupType: Popup.Native
+
+ Action {
+ objectName: text
+ text: "action1"
+ shortcut: "A"
+ }
+
+ MenuItem {
+ objectName: text
+ action: Action {
+ text: "menuItemAction"
+ objectName: text
+ shortcut: "B"
+ }
+ }
+
+ Menu {
+ id: subMenu
+ title: "subMenu"
+ objectName: title
+ popupType: Popup.Native
+ // TODO: remove me when the defaults are true
+
+ Action {
+ objectName: text
+ text: "subAction1"
+ shortcut: "1"
+ }
+ }
+ }
+
+ TapHandler {
+ acceptedButtons: Qt.RightButton
+ onTapped: contextMenu.popup()
+ }
+}
diff --git a/tests/auto/quickcontrols/qquickmenu/data/order.qml b/tests/auto/quickcontrols/qquickmenu/data/order.qml
index 185c9e45c3..4e3ecb7b46 100644
--- a/tests/auto/quickcontrols/qquickmenu/data/order.qml
+++ b/tests/auto/quickcontrols/qquickmenu/data/order.qml
@@ -1,5 +1,5 @@
// Copyright (C) 2017 The Qt Company Ltd.
-// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR BSD-3-Clause
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
import QtQuick
import QtQuick.Controls
diff --git a/tests/auto/quickcontrols/qquickmenu/data/popup.qml b/tests/auto/quickcontrols/qquickmenu/data/popup.qml
index 8201c9e03f..b9e0fd136b 100644
--- a/tests/auto/quickcontrols/qquickmenu/data/popup.qml
+++ b/tests/auto/quickcontrols/qquickmenu/data/popup.qml
@@ -1,5 +1,5 @@
// Copyright (C) 2017 The Qt Company Ltd.
-// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR BSD-3-Clause
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
import QtQuick
import QtQuick.Controls
diff --git a/tests/auto/quickcontrols/qquickmenu/data/pressAndHold.qml b/tests/auto/quickcontrols/qquickmenu/data/pressAndHold.qml
index ac0f394604..5dde687181 100644
--- a/tests/auto/quickcontrols/qquickmenu/data/pressAndHold.qml
+++ b/tests/auto/quickcontrols/qquickmenu/data/pressAndHold.qml
@@ -1,5 +1,5 @@
// Copyright (C) 2017 The Qt Company Ltd.
-// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR BSD-3-Clause
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
import QtQuick
import QtQuick.Controls
diff --git a/tests/auto/quickcontrols/qquickmenu/data/removeTakeItem.qml b/tests/auto/quickcontrols/qquickmenu/data/removeTakeItem.qml
index aa321cb3a9..8d19f9df99 100644
--- a/tests/auto/quickcontrols/qquickmenu/data/removeTakeItem.qml
+++ b/tests/auto/quickcontrols/qquickmenu/data/removeTakeItem.qml
@@ -1,5 +1,5 @@
// Copyright (C) 2017 The Qt Company Ltd.
-// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR BSD-3-Clause
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
import QtQuick
import QtQuick.Controls
diff --git a/tests/auto/quickcontrols/qquickmenu/data/repeater.qml b/tests/auto/quickcontrols/qquickmenu/data/repeater.qml
index 3c056a1d38..0eddd9f868 100644
--- a/tests/auto/quickcontrols/qquickmenu/data/repeater.qml
+++ b/tests/auto/quickcontrols/qquickmenu/data/repeater.qml
@@ -1,5 +1,5 @@
// Copyright (C) 2017 The Qt Company Ltd.
-// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR BSD-3-Clause
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
import QtQuick
import QtQuick.Controls
diff --git a/tests/auto/quickcontrols/qquickmenu/data/scrollableWithFixedHeight.qml b/tests/auto/quickcontrols/qquickmenu/data/scrollableWithFixedHeight.qml
new file mode 100644
index 0000000000..c4f4906123
--- /dev/null
+++ b/tests/auto/quickcontrols/qquickmenu/data/scrollableWithFixedHeight.qml
@@ -0,0 +1,27 @@
+// Copyright (C) 2023 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
+
+import QtQuick
+import QtQuick.Controls
+import QtQuick.Window
+
+Window {
+ width: 300
+ height: 300
+
+ property alias menu: menu
+
+ Menu {
+ id: menu
+ anchors.centerIn: parent
+ height: 100
+ visible: true
+ Repeater {
+ model: 10
+ delegate: MenuItem {
+ objectName: text
+ text: (index + 1)
+ }
+ }
+ }
+}
diff --git a/tests/auto/quickcontrols/qquickmenu/data/scrollableWithPadding.qml b/tests/auto/quickcontrols/qquickmenu/data/scrollableWithPadding.qml
index 842cb33bfd..9945ee8128 100644
--- a/tests/auto/quickcontrols/qquickmenu/data/scrollableWithPadding.qml
+++ b/tests/auto/quickcontrols/qquickmenu/data/scrollableWithPadding.qml
@@ -1,5 +1,5 @@
// Copyright (C) 2020 The Qt Company Ltd.
-// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR BSD-3-Clause
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
import QtQuick
import QtQuick.Controls
diff --git a/tests/auto/quickcontrols/qquickmenu/data/subMenuDisabled.qml b/tests/auto/quickcontrols/qquickmenu/data/subMenuDisabled.qml
index 4d5db0bd67..abb29579a9 100644
--- a/tests/auto/quickcontrols/qquickmenu/data/subMenuDisabled.qml
+++ b/tests/auto/quickcontrols/qquickmenu/data/subMenuDisabled.qml
@@ -1,5 +1,5 @@
// Copyright (C) 2019 The Qt Company Ltd.
-// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR BSD-3-Clause
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
import QtQuick
import QtQuick.Controls
diff --git a/tests/auto/quickcontrols/qquickmenu/data/subMenus.qml b/tests/auto/quickcontrols/qquickmenu/data/subMenus.qml
index 280fd404e8..24d6d9396e 100644
--- a/tests/auto/quickcontrols/qquickmenu/data/subMenus.qml
+++ b/tests/auto/quickcontrols/qquickmenu/data/subMenus.qml
@@ -1,5 +1,5 @@
// Copyright (C) 2017 The Qt Company Ltd.
-// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR BSD-3-Clause
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
import QtQuick
import QtQuick.Controls
diff --git a/tests/auto/quickcontrols/qquickmenu/data/windowScrollable.qml b/tests/auto/quickcontrols/qquickmenu/data/windowScrollable.qml
index 97a06da63d..b927896741 100644
--- a/tests/auto/quickcontrols/qquickmenu/data/windowScrollable.qml
+++ b/tests/auto/quickcontrols/qquickmenu/data/windowScrollable.qml
@@ -1,5 +1,5 @@
// Copyright (C) 2018 The Qt Company Ltd.
-// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR BSD-3-Clause
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
import QtQuick
import QtQuick.Controls
diff --git a/tests/auto/quickcontrols/qquickmenu/tst_qquickmenu.cpp b/tests/auto/quickcontrols/qquickmenu/tst_qquickmenu.cpp
index ee7ec2c4d3..624a2092bc 100644
--- a/tests/auto/quickcontrols/qquickmenu/tst_qquickmenu.cpp
+++ b/tests/auto/quickcontrols/qquickmenu/tst_qquickmenu.cpp
@@ -1,5 +1,5 @@
// Copyright (C) 2017 The Qt Company Ltd.
-// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
#include <QtTest/qtest.h>
#include <QtTest/qsignalspy.h>
@@ -9,12 +9,14 @@
#endif
#include <QtGui/qstylehints.h>
#include <QtGui/qpa/qplatformintegration.h>
+#include <QtGui/qpa/qplatformtheme.h>
#include <QtGui/private/qguiapplication_p.h>
#include <QtQml/qqmlengine.h>
#include <QtQml/qqmlcomponent.h>
#include <QtQml/qqmlcontext.h>
#include <QtQuick/qquickview.h>
#include <QtQuick/private/qquickitem_p.h>
+#include <QtQuick/private/qquickrectangle_p.h>
#include <QtQuickTestUtils/private/qmlutils_p.h>
#include <QtQuickTestUtils/private/visualtestutils_p.h>
#include <QtQuickControlsTestUtils/private/controlstestutils_p.h>
@@ -26,12 +28,16 @@
#include <QtQuickTemplates2/private/qquickbutton_p.h>
#include <QtQuickTemplates2/private/qquickicon_p.h>
#include <QtQuickTemplates2/private/qquickmenu_p.h>
+#include <QtQuickTemplates2/private/qquickmenu_p_p.h>
#include <QtQuickTemplates2/private/qquickmenuitem_p.h>
#include <QtQuickTemplates2/private/qquickmenuseparator_p.h>
+#include <QtQuickTemplates2/private/qquicknativemenuitem_p.h>
using namespace QQuickVisualTestUtils;
using namespace QQuickControlsTestUtils;
+// Native menu tests are in "nativemenus".
+
class tst_QQuickMenu : public QQmlDataTest
{
Q_OBJECT
@@ -40,6 +46,8 @@ public:
tst_QQuickMenu();
private slots:
+ void init() final;
+
void defaults();
void count();
void mouse();
@@ -55,6 +63,7 @@ private slots:
#if QT_CONFIG(cursor)
void popup();
#endif
+ void openParentlessMenu();
void actions();
#if QT_CONFIG(shortcut)
void actionShortcuts();
@@ -86,19 +95,47 @@ private slots:
void giveMenuItemFocusOnButtonPress();
void customMenuCullItems();
void customMenuUseRepeaterAsTheContentItem();
+ void invalidUrlInImgTag();
+ void nativeStatic();
+ void nativeDynamicActions();
+ void nativeDynamicSubmenus();
+ void nativeMenuSeparator();
+ void dontUseNativeMenuWindowsChanges();
+ void nativeMixedItems();
+ void effectivePosition_data();
+ void effectivePosition();
+ void textPadding();
+ void resetCurrentIndexUponPopup_data();
+ void resetCurrentIndexUponPopup();
private:
- static bool hasWindowActivation();
+ bool nativeMenuSupported = false;
};
+// This allows us to use QQuickMenuItem's more descriptive operator<< output
+// for the QCOMPARE failure message. It doesn't seem possible to use toString
+// overloads or template specialization when types declared in QML are involved,
+// as is the case for the MenuItems created from Menu's delegate.
+#define COMPARE_MENUITEMS(actualMenuItem, expectedMenuItem) \
+QVERIFY2(actualMenuItem == expectedMenuItem, \
+ qPrintable(QString::fromLatin1("\n Actual: %1\n Expected: %2") \
+ .arg(QDebug::toString(actualMenuItem), QDebug::toString(expectedMenuItem))));
+
tst_QQuickMenu::tst_QQuickMenu()
: QQmlDataTest(QT_QMLTEST_DATADIR)
{
+ std::unique_ptr<QPlatformMenu> platformMenu(QGuiApplicationPrivate::platformTheme()->createPlatformMenu());
+ nativeMenuSupported = platformMenu != nullptr;
}
-bool tst_QQuickMenu::hasWindowActivation()
+void tst_QQuickMenu::init()
{
- return (QGuiApplicationPrivate::platformIntegration()->hasCapability(QPlatformIntegration::WindowActivation));
+ QQmlDataTest::init();
+
+ // By default we don't want to use native menus, as the majority of the tests
+ // were written before they were a thing. We instead explicitly set it where necessary.
+ QCoreApplication::setAttribute(Qt::AA_DontUseNativeMenuWindows);
+ QCoreApplication::setAttribute(Qt::AA_DontUseNativeMenuBar);
}
void tst_QQuickMenu::defaults()
@@ -145,8 +182,7 @@ void tst_QQuickMenu::count()
void tst_QQuickMenu::mouse()
{
- if (!hasWindowActivation())
- QSKIP("Window activation is not supported");
+ SKIP_IF_NO_WINDOW_ACTIVATION
if ((QGuiApplication::platformName() == QLatin1String("offscreen"))
|| (QGuiApplication::platformName() == QLatin1String("minimal")))
@@ -159,6 +195,7 @@ void tst_QQuickMenu::mouse()
centerOnScreen(window);
moveMouseAway(window);
window->show();
+ window->requestActivate();
QVERIFY(QTest::qWaitForWindowActive(window));
QQuickMenu *menu = window->property("menu").value<QQuickMenu*>();
@@ -277,8 +314,7 @@ void tst_QQuickMenu::pressAndHold()
void tst_QQuickMenu::contextMenuKeyboard()
{
- if (!hasWindowActivation())
- QSKIP("Window activation is not supported");
+ SKIP_IF_NO_WINDOW_ACTIVATION
if (QGuiApplication::styleHints()->tabFocusBehavior() != Qt::TabFocusAllControls)
QSKIP("This platform only allows tab focus for text controls");
@@ -467,8 +503,7 @@ void tst_QQuickMenu::contextMenuKeyboard()
// QTBUG-70181
void tst_QQuickMenu::disabledMenuItemKeyNavigation()
{
- if (!hasWindowActivation())
- QSKIP("Window activation is not supported");
+ SKIP_IF_NO_WINDOW_ACTIVATION
if (QGuiApplication::styleHints()->tabFocusBehavior() != Qt::TabFocusAllControls)
QSKIP("This platform only allows tab focus for text controls");
@@ -534,8 +569,7 @@ void tst_QQuickMenu::disabledMenuItemKeyNavigation()
void tst_QQuickMenu::mnemonics()
{
- if (!hasWindowActivation())
- QSKIP("Window activation is not supported");
+ SKIP_IF_NO_WINDOW_ACTIVATION
#ifdef Q_OS_MACOS
QSKIP("Mnemonics are not used on macOS");
@@ -592,8 +626,7 @@ void tst_QQuickMenu::mnemonics()
void tst_QQuickMenu::menuButton()
{
- if (!hasWindowActivation())
- QSKIP("Window activation is not supported");
+ SKIP_IF_NO_WINDOW_ACTIVATION
if (QGuiApplication::styleHints()->tabFocusBehavior() != Qt::TabFocusAllControls)
QSKIP("This platform only allows tab focus for text controls");
@@ -647,8 +680,7 @@ void tst_QQuickMenu::addItem()
void tst_QQuickMenu::menuSeparator()
{
- if (!hasWindowActivation())
- QSKIP("Window activation is not supported");
+ SKIP_IF_NO_WINDOW_ACTIVATION
QQuickControlsApplicationHelper helper(this, QLatin1String("menuSeparator.qml"));
QVERIFY2(helper.ready, helper.failureMessage());
@@ -656,6 +688,7 @@ void tst_QQuickMenu::menuSeparator()
centerOnScreen(window);
moveMouseAway(window);
window->show();
+ window->requestActivate();
QVERIFY(QTest::qWaitForWindowActive(window));
QQuickMenu *menu = window->property("menu").value<QQuickMenu*>();
@@ -964,6 +997,29 @@ void tst_QQuickMenu::popup()
}
#endif // QT_CONFIG(cursor)
+void tst_QQuickMenu::openParentlessMenu()
+{
+ // Check that we don't get a crash if the application sets a menu's parentItem
+ // to null. This will also result in the menu not showing at all, since it's
+ // no longer a part of the scene. Even if this limitiation is technically only
+ // relevant for non-native menus, we enforce it also for native menus to ensure
+ // that an application works the same on all platforms.
+ QQuickControlsApplicationHelper helper(this, QLatin1String("popup.qml"));
+ QVERIFY2(helper.ready, helper.failureMessage());
+ QQuickApplicationWindow *window = helper.appWindow;
+ centerOnScreen(window);
+ window->show();
+ QVERIFY(QTest::qWaitForWindowExposed(window));
+
+ QTest::ignoreMessage(QtWarningMsg, QRegularExpression("cannot show menu: parent is null"));
+
+ QQuickMenu *menu = window->property("menu").value<QQuickMenu *>();
+ QVERIFY(menu);
+ menu->setParentItem(nullptr);
+ menu->popup();
+ QVERIFY(!menu->isVisible());
+}
+
void tst_QQuickMenu::actions()
{
QQuickControlsApplicationHelper helper(this, QLatin1String("actions.qml"));
@@ -1036,13 +1092,13 @@ void tst_QQuickMenu::actions()
#if QT_CONFIG(shortcut)
void tst_QQuickMenu::actionShortcuts()
{
- if (!hasWindowActivation())
- QSKIP("Window activation is not supported");
+ SKIP_IF_NO_WINDOW_ACTIVATION
QQuickControlsApplicationHelper helper(this, QLatin1String("actionShortcuts.qml"));
QVERIFY2(helper.ready, helper.failureMessage());
QQuickWindow *window = helper.window;
window->show();
+ window->requestActivate();
QVERIFY(QTest::qWaitForWindowActive(window));
// Try the menu's shortcut.
@@ -1331,8 +1387,7 @@ void tst_QQuickMenu::subMenuKeyboard_data()
void tst_QQuickMenu::subMenuKeyboard()
{
- if (!hasWindowActivation())
- QSKIP("Window activation is not supported");
+ SKIP_IF_NO_WINDOW_ACTIVATION
QFETCH(bool, cascade);
QFETCH(bool, mirrored);
@@ -1343,6 +1398,7 @@ void tst_QQuickMenu::subMenuKeyboard()
centerOnScreen(window);
moveMouseAway(window);
window->show();
+ window->requestActivate();
QVERIFY(QTest::qWaitForWindowActive(window));
if (mirrored) {
@@ -1460,8 +1516,7 @@ void tst_QQuickMenu::subMenuDisabledKeyboard_data()
// QTBUG-69540
void tst_QQuickMenu::subMenuDisabledKeyboard()
{
- if (!hasWindowActivation())
- QSKIP("Window activation is not supported");
+ SKIP_IF_NO_WINDOW_ACTIVATION
QFETCH(bool, cascade);
QFETCH(bool, mirrored);
@@ -1472,6 +1527,7 @@ void tst_QQuickMenu::subMenuDisabledKeyboard()
centerOnScreen(window);
moveMouseAway(window);
window->show();
+ window->requestActivate();
QVERIFY(QTest::qWaitForWindowActive(window));
if (mirrored) {
@@ -1787,6 +1843,7 @@ void tst_QQuickMenu::scrollable_data()
QTest::addRow("Window") << QString::fromLatin1("windowScrollable.qml");
QTest::addRow("ApplicationWindow") << QString::fromLatin1("applicationWindowScrollable.qml");
QTest::addRow("WithPadding") << QString::fromLatin1("scrollableWithPadding.qml");
+ QTest::addRow("FixedHeight") << QString::fromLatin1("scrollableWithFixedHeight.qml");
}
void tst_QQuickMenu::scrollable()
@@ -2048,13 +2105,13 @@ void tst_QQuickMenu::menuItemWidthAfterRetranslate()
void tst_QQuickMenu::giveMenuItemFocusOnButtonPress()
{
- if (!hasWindowActivation())
- QSKIP("Window activation is not supported");
+ SKIP_IF_NO_WINDOW_ACTIVATION
QQuickControlsApplicationHelper helper(this, QLatin1String("giveMenuItemFocusOnButtonPress.qml"));
QVERIFY2(helper.ready, helper.failureMessage());
QQuickApplicationWindow *window = helper.appWindow;
window->show();
+ window->requestActivate();
QVERIFY(QTest::qWaitForWindowActive(window));
// Press enter on the button to open the menu.
@@ -2115,6 +2172,636 @@ void tst_QQuickMenu::customMenuUseRepeaterAsTheContentItem()
QTRY_VERIFY(!QQuickItemPrivate::get(menuItemLast)->culled);
}
+// QTBUG-116672 - Application loads menu containing invalid styled text
+// (img tag) without crash
+void tst_QQuickMenu::invalidUrlInImgTag()
+{
+ QTest::ignoreMessage(QtWarningMsg, "StyledText - Invalid base url in img tag");
+
+ QQuickControlsApplicationHelper helper(this, QLatin1String("invalidUrlInImgTag.qml"));
+ QVERIFY2(helper.ready, helper.failureMessage());
+ QQuickApplicationWindow *window = helper.appWindow;
+ window->show();
+ QVERIFY(QTest::qWaitForWindowExposed(window));
+
+ QQuickMenu *menu = window->property("menu").value<QQuickMenu*>();
+ QVERIFY(menu);
+ menu->open();
+ QTRY_VERIFY(menu->isVisible());
+
+ QQuickMenuItem *menuItemFirst = qobject_cast<QQuickMenuItem *>(menu->itemAt(0));
+ QVERIFY(menuItemFirst);
+}
+
+void tst_QQuickMenu::nativeStatic()
+{
+ QQuickControlsApplicationHelper helper(this, QLatin1String("nativeStatic.qml"));
+ QVERIFY2(helper.ready, helper.failureMessage());
+ QQuickApplicationWindow *window = helper.appWindow;
+ window->show();
+ QVERIFY(QTest::qWaitForWindowExposed(window));
+
+ QQuickMenu *contextMenu = window->property("contextMenu").value<QQuickMenu*>();
+ QVERIFY(contextMenu);
+ auto *contextMenuPrivate = QQuickMenuPrivate::get(contextMenu);
+ QVERIFY(contextMenuPrivate->useNativeMenu());
+
+ // Check that the actions of the parent menu can be accessed
+ // and are in the appropriate places in contentModel and contentData.
+ auto *action1 = contextMenu->actionAt(0);
+ QVERIFY(action1);
+ auto *action1MenuItem = qobject_cast<QQuickMenuItem *>(contextMenu->itemAt(0));
+ QVERIFY(action1MenuItem);
+ QCOMPARE(action1MenuItem->action(), action1);
+ COMPARE_MENUITEMS(qobject_cast<QQuickMenuItem *>(contextMenuPrivate->contentData.at(0)),
+ action1MenuItem);
+
+ auto *menuItem = qobject_cast<QQuickMenuItem *>(contextMenu->itemAt(1));
+ QVERIFY(menuItem);
+ QVERIFY(menuItem->action());
+ QCOMPARE(menuItem->action()->text(), "menuItemAction");
+ COMPARE_MENUITEMS(qobject_cast<QQuickMenuItem *>(contextMenuPrivate->contentData.at(1)), menuItem);
+
+ // Check that the sub-menu can be accessed and is in the
+ // appropriate place in contentData.
+ auto *subMenu = contextMenu->menuAt(2);
+ QVERIFY(subMenu);
+ auto *subMenuPrivate = QQuickMenuPrivate::get(subMenu);
+ auto *subMenuAction1 = subMenu->actionAt(0);
+ QVERIFY(subMenuAction1);
+ auto *subMenuAction1MenuItem = qobject_cast<QQuickMenuItem *>(subMenu->itemAt(0));
+ QVERIFY(subMenuAction1MenuItem);
+ QCOMPARE(subMenuAction1MenuItem->action(), subMenuAction1);
+ COMPARE_MENUITEMS(qobject_cast<QQuickMenuItem *>(subMenuPrivate->contentData.at(0)),
+ subMenuAction1MenuItem);
+}
+
+void tst_QQuickMenu::nativeDynamicActions()
+{
+ QQuickControlsApplicationHelper helper(this, QLatin1String("nativeEmptyMenu.qml"));
+ QVERIFY2(helper.ready, helper.failureMessage());
+ QQuickApplicationWindow *window = helper.appWindow;
+ window->show();
+ QVERIFY(QTest::qWaitForWindowExposed(window));
+
+ QQuickMenu *contextMenu = window->property("contextMenu").value<QQuickMenu*>();
+ QVERIFY(contextMenu);
+ auto *contextMenuPrivate = QQuickMenuPrivate::get(contextMenu);
+
+ // Check that items can be appended to an empty menu.
+ QCOMPARE(contextMenu->actionAt(0), nullptr);
+ QVERIFY(QMetaObject::invokeMethod(window, "addAction",
+ Q_ARG(QQuickMenu *, contextMenu), Q_ARG(QString, "action1")));
+ {
+ auto action1 = contextMenu->actionAt(0);
+ QVERIFY(action1);
+ QCOMPARE(action1->text(), "action1");
+ auto *action1MenuItem = qobject_cast<QQuickMenuItem *>(contextMenu->itemAt(0));
+ QVERIFY(action1MenuItem);
+ QCOMPARE(action1MenuItem->action(), action1);
+ COMPARE_MENUITEMS(qobject_cast<QQuickMenuItem *>(contextMenuPrivate->contentData.at(0)),
+ action1MenuItem);
+ }
+
+ // Check that actions can be appended after existing items in the parent menu.
+ QCOMPARE(contextMenu->actionAt(1), nullptr);
+ QVERIFY(QMetaObject::invokeMethod(window, "addAction",
+ Q_ARG(QQuickMenu *, contextMenu), Q_ARG(QString, "action2")));
+ {
+ auto action2 = contextMenu->actionAt(1);
+ QVERIFY(action2);
+ QCOMPARE(action2->text(), "action2");
+ auto *action2MenuItem = qobject_cast<QQuickMenuItem *>(contextMenu->itemAt(1));
+ QVERIFY(action2MenuItem);
+ QCOMPARE(action2MenuItem->action(), action2);
+ COMPARE_MENUITEMS(qobject_cast<QQuickMenuItem *>(contextMenuPrivate->contentData.at(1)),
+ action2MenuItem);
+ }
+
+ // Check that actions can be inserted before existing items in the parent menu.
+ QVERIFY(QMetaObject::invokeMethod(window, "insertAction",
+ Q_ARG(QQuickMenu *, contextMenu), Q_ARG(int, 0), Q_ARG(QString, "action0")));
+ {
+ auto action0 = contextMenu->actionAt(0);
+ QVERIFY(action0);
+ QCOMPARE(action0->text(), "action0");
+ auto *action0MenuItem = qobject_cast<QQuickMenuItem *>(contextMenu->itemAt(0));
+ QVERIFY(action0MenuItem);
+ QCOMPARE(action0MenuItem->action(), action0);
+ // New items are always appended to contentData, regardless of the actual insertion index
+ // in contentModel.
+ COMPARE_MENUITEMS(qobject_cast<QQuickMenuItem *>(contextMenuPrivate->contentData.at(2)),
+ action0MenuItem);
+ }
+}
+
+void tst_QQuickMenu::nativeDynamicSubmenus()
+{
+ QQuickControlsApplicationHelper helper(this, QLatin1String("nativeDynamicSubmenus.qml"));
+ QVERIFY2(helper.ready, helper.failureMessage());
+ QQuickApplicationWindow *window = helper.appWindow;
+ window->show();
+ QVERIFY(QTest::qWaitForWindowExposed(window));
+
+ QQuickMenu *contextMenu = window->property("contextMenu").value<QQuickMenu*>();
+ QVERIFY(contextMenu);
+ auto *contextMenuPrivate = QQuickMenuPrivate::get(contextMenu);
+
+ // 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);
+ QVERIFY(subMenu1);
+ QCOMPARE(subMenu1->title(), "subMenu1");
+ auto *subMenu1Private = QQuickMenuPrivate::get(subMenu1);
+ if (nativeMenuSupported) {
+ QVERIFY(subMenu1Private->handle);
+ QCOMPARE(subMenu1Private->nativeItems.size(), 1);
+ }
+ auto *subMenu1MenuItem = qobject_cast<QQuickMenuItem *>(contextMenu->itemAt(0));
+ QVERIFY(subMenu1MenuItem);
+ COMPARE_MENUITEMS(qobject_cast<QQuickMenuItem *>(contextMenuPrivate->contentData.at(0)),
+ subMenu1MenuItem);
+ QCOMPARE(contextMenuPrivate->contentData.size(), 1);
+ {
+ auto subMenuAction1 = subMenu1->actionAt(0);
+ QVERIFY(subMenuAction1);
+ QCOMPARE(subMenuAction1->text(), "subMenu1Action1");
+ auto *subMenuAction1MenuItem = qobject_cast<QQuickMenuItem *>(subMenu1->itemAt(0));
+ QVERIFY(subMenuAction1MenuItem);
+ QCOMPARE(subMenuAction1MenuItem->action(), subMenuAction1);
+ COMPARE_MENUITEMS(qobject_cast<QQuickMenuItem *>(subMenu1Private->contentData.at(0)),
+ subMenuAction1MenuItem);
+ if (nativeMenuSupported)
+ QCOMPARE(subMenu1Private->nativeItems.size(), 1);
+ }
+
+ // 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, "subMenu1Action2")));
+ {
+ auto subMenu1Action2 = subMenu1->actionAt(1);
+ QVERIFY(subMenu1Action2);
+ QCOMPARE(subMenu1Action2->text(), "subMenu1Action2");
+ auto *subMenu1Action2MenuItem = qobject_cast<QQuickMenuItem *>(subMenu1->itemAt(1));
+ QVERIFY(subMenu1Action2MenuItem);
+ QCOMPARE(subMenu1Action2MenuItem->action(), subMenu1Action2);
+ COMPARE_MENUITEMS(qobject_cast<QQuickMenuItem *>(subMenu1Private->contentData.at(1)),
+ subMenu1Action2MenuItem);
+ 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");
+ auto *subMenu1Action0MenuItem = qobject_cast<QQuickMenuItem *>(subMenu1->itemAt(0));
+ QVERIFY(subMenu1Action0MenuItem);
+ QCOMPARE(subMenu1Action0MenuItem->action(), subMenu1Action0);
+ // New items are always appended to contentData, regardless of the actual insertion index
+ // in contentModel.
+ COMPARE_MENUITEMS(qobject_cast<QQuickMenuItem *>(subMenu1Private->contentData.at(2)),
+ subMenu1Action0MenuItem);
+ QCOMPARE(subMenu1Private->contentData.size(), 3);
+ }
+
+ {
+ // Check that takeMenu works.
+ auto *takenSubMenu = contextMenu->takeMenu(0);
+ QCOMPARE(takenSubMenu, subMenu1);
+ QCOMPARE(contextMenuPrivate->contentData.size(), 0);
+ if (nativeMenuSupported) {
+ QVERIFY(!subMenu1Private->handle);
+ QCOMPARE(subMenu1Private->nativeItems.size(), 0);
+ }
+
+ // Check that the sub-menu can be added back in to the menu.
+ contextMenu->addMenu(takenSubMenu);
+ QCOMPARE(contextMenuPrivate->contentData.size(), 1);
+ auto *subMenu1MenuItem = qobject_cast<QQuickMenuItem *>(contextMenu->itemAt(0));
+ QVERIFY(subMenu1MenuItem);
+ QCOMPARE(subMenu1MenuItem->text(), "subMenu1");
+ if (nativeMenuSupported) {
+ QVERIFY(subMenu1Private->handle);
+ QCOMPARE(subMenu1Private->nativeItems.size(), 3);
+ }
+ QCOMPARE(subMenu1Private->contentData.size(), 3);
+
+ auto *subMenu1Action0MenuItem = qobject_cast<QQuickMenuItem *>(subMenu1->itemAt(0));
+ QVERIFY(subMenu1Action0MenuItem);
+ }
+
+ // Check that removeMenu works.
+ QVERIFY(contextMenu->menuAt(0));
+ contextMenu->removeMenu(contextMenu->menuAt(0));
+ QCOMPARE(contextMenuPrivate->contentData.size(), 0);
+}
+
+void tst_QQuickMenu::nativeMenuSeparator()
+{
+ QQuickControlsApplicationHelper helper(this, QLatin1String("nativeMenuSeparator.qml"));
+ QVERIFY2(helper.ready, helper.failureMessage());
+ QQuickApplicationWindow *window = helper.appWindow;
+ window->show();
+ QVERIFY(QTest::qWaitForWindowExposed(window));
+
+ // Check that separators in menus are where we expect them to be.
+ QQuickMenu *contextMenu = window->property("contextMenu").value<QQuickMenu*>();
+ QVERIFY(contextMenu);
+ auto *contextMenuSeparatorAsItem = contextMenu->itemAt(1);
+ QVERIFY(contextMenuSeparatorAsItem);
+ auto *contextMenuSeparator = qobject_cast<QQuickMenuSeparator *>(contextMenuSeparatorAsItem);
+ QVERIFY(contextMenuSeparator);
+ if (nativeMenuSupported) {
+ auto *contextMenuPrivate = QQuickMenuPrivate::get(contextMenu);
+ QCOMPARE(contextMenuPrivate->nativeItems.size(), 3);
+ auto *contextMenuSeparatorNativeItem = contextMenuPrivate->nativeItems.at(1);
+ QVERIFY(contextMenuSeparatorNativeItem);
+ QVERIFY(contextMenuSeparatorNativeItem->separator());
+ }
+
+ // Check that separators in sub-menus are where we expect them to be.
+ QQuickMenu *subMenu = window->property("contextMenu").value<QQuickMenu*>();
+ QVERIFY(subMenu);
+ auto *subMenuSeparatorAsItem = subMenu->itemAt(1);
+ QVERIFY(subMenuSeparatorAsItem);
+ auto *subMenuSeparator = qobject_cast<QQuickMenuSeparator *>(subMenuSeparatorAsItem);
+ QVERIFY(subMenuSeparator);
+ if (nativeMenuSupported) {
+ auto *subMenuPrivate = QQuickMenuPrivate::get(subMenu);
+ QCOMPARE(subMenuPrivate->nativeItems.size(), 3);
+ auto *subMenuSeparatorNativeItem = subMenuPrivate->nativeItems.at(1);
+ QVERIFY(subMenuSeparatorNativeItem);
+ QVERIFY(subMenuSeparatorNativeItem->separator());
+ }
+}
+
+void tst_QQuickMenu::dontUseNativeMenuWindowsChanges()
+{
+ QSKIP("QTBUG-125967 This test will need to be fixed, by using popupType: Popup.Native instead of AA_DontUseNativeMenuWindows.");
+
+ if (QSysInfo::productType() == QLatin1String("b2qt"))
+ QSKIP("b2qt doesn't support native menus");
+
+ QCoreApplication::setAttribute(Qt::AA_DontUseNativeMenuWindows, false);
+ QQuickControlsApplicationHelper helper(this, QLatin1String("nativeStatic.qml"));
+ QVERIFY2(helper.ready, helper.failureMessage());
+ QQuickApplicationWindow *window = helper.appWindow;
+ window->show();
+ QVERIFY(QTest::qWaitForWindowExposed(window));
+
+ QQuickMenu *contextMenu = window->property("contextMenu").value<QQuickMenu*>();
+ QVERIFY(contextMenu);
+ QCOMPARE(contextMenu->count(), 3);
+ // Sub-menus should respect the native-ness of their parents.
+ auto *subMenu = contextMenu->menuAt(2);
+ auto *subMenuPrivate = QQuickMenuPrivate::get(subMenu);
+ QVERIFY(subMenuPrivate->useNativeMenu());
+ if (nativeMenuSupported)
+ QVERIFY(subMenuPrivate->handle);
+ else
+ QVERIFY(!subMenuPrivate->handle);
+
+ // Ensure that the menu and its sub-menu have enough room to open.
+ if (window->width() / 2 <= contextMenu->width())
+ window->setWidth(contextMenu->width() * 2 + 1);
+ if (window->height() <= contextMenu->height())
+ window->setHeight(contextMenu->height() + 1);
+ QTRY_COMPARE(window->contentItem()->size(), window->size());
+
+ // We can't test that aboutToShow/aboutToHide is emitted for native menus
+ // because when they are shown, the event loop is blocked until they are closed.
+ // So we just check that a native menu is actually in use before going on to test
+ // non-native menus.
+ auto *contextMenuPrivate = QQuickMenuPrivate::get(contextMenu);
+ if (nativeMenuSupported)
+ QVERIFY(contextMenuPrivate->handle);
+ else
+ QVERIFY(!contextMenuPrivate->handle);
+
+ // We need to wait until the menu is opened before it picks up the changes,
+ // which is why we don't check the native handle here yet.
+ QCoreApplication::setAttribute(Qt::AA_DontUseNativeMenuWindows);
+ QVERIFY(!contextMenuPrivate->useNativeMenu());
+ QVERIFY(!subMenuPrivate->useNativeMenu());
+
+ // Check that we can open the menu by right-clicking (or just open it manually
+ // if the platform doesn't support (moving) QCursor).
+ QSignalSpy aboutToShowSpy(contextMenu, &QQuickMenu::aboutToShow);
+ QVERIFY(aboutToShowSpy.isValid());
+ bool couldMoveCursorPos = false;
+ const QPoint cursorPos(1, 1);
+#if QT_CONFIG(cursor)
+ // Try moving the cursor from the current position to test if the platform
+ // supports moving the cursor.
+ const QPoint point = QCursor::pos() + QPoint(1, 1);
+ QCursor::setPos(point);
+ if (QTest::qWaitFor([point]{ return QCursor::pos() == point; })) {
+ couldMoveCursorPos = true;
+ const QPoint globalCursorPos = window->mapToGlobal(cursorPos);
+ QCursor::setPos(globalCursorPos);
+ QTest::mouseClick(window, Qt::RightButton, Qt::NoModifier, cursorPos);
+ }
+#endif
+ if (!couldMoveCursorPos) {
+ contextMenu->setX(cursorPos.x());
+ contextMenu->setY(cursorPos.y());
+ contextMenu->open();
+ }
+ QVERIFY(contextMenu->isVisible());
+ QTRY_VERIFY(contextMenu->isOpened());
+ QCOMPARE(aboutToShowSpy.size(), 1);
+ // Now that it's open and has picked up the changes to Qt::AA_DontUseNativeMenuWindows, we can check it.
+ QVERIFY(!contextMenuPrivate->handle);
+ QVERIFY(!subMenuPrivate->handle);
+ // Check that it opened at the mouse cursor and actually has menu items.
+ QCOMPARE(contextMenu->x(), cursorPos.x());
+ QCOMPARE(contextMenu->y(), cursorPos.y());
+ auto *action1MenuItem = qobject_cast<QQuickMenuItem *>(contextMenu->itemAt(0));
+ QVERIFY(action1MenuItem);
+ QCOMPARE(action1MenuItem->text(), "action1");
+
+ // Test setting Qt::AA_DontUseNativeMenuWindows while visible has no effect
+ // (until it's re-opened, which we can't test because we can't test opening native menus).
+ QCoreApplication::setAttribute(Qt::AA_DontUseNativeMenuWindows, false);
+ QVERIFY(contextMenuPrivate->useNativeMenu());
+ QVERIFY(!contextMenuPrivate->handle);
+ QVERIFY(!subMenuPrivate->handle);
+
+ // Also check the submenu.
+ auto *subAction1MenuItem = qobject_cast<QQuickMenuItem *>(subMenu->itemAt(0));
+ QVERIFY(subAction1MenuItem);
+ QCOMPARE(subAction1MenuItem->text(), "subAction1");
+
+ // Test closing the non-native menu by clicking on an item.
+ QSignalSpy aboutToHideSpy(contextMenu, &QQuickMenu::aboutToHide);
+ QVERIFY(aboutToHideSpy.isValid());
+ QVERIFY(clickButton(action1MenuItem));
+ QVERIFY(!contextMenu->isOpened());
+ QTRY_VERIFY(!contextMenu->isVisible());
+ QCOMPARE(aboutToShowSpy.size(), 1);
+
+ // Although we can't open the native menu, we can at least check that
+ // attempting (the changes won't come into effect until it's re-opened)
+ // to make the menu native again doesn't e.g. crash.
+ QVERIFY(contextMenuPrivate->useNativeMenu());
+ QVERIFY(subMenuPrivate->useNativeMenu());
+ QVERIFY(!contextMenuPrivate->handle);
+ QVERIFY(!subMenuPrivate->handle);
+}
+
+// Check that non-menu items (e.g. Rectangles) can be inserted between menu items without issues.
+void tst_QQuickMenu::nativeMixedItems()
+{
+ QCoreApplication::setAttribute(Qt::AA_DontUseNativeMenuWindows, false);
+ QQuickControlsApplicationHelper helper(this, QLatin1String("nativeMixedItems.qml"));
+ QVERIFY2(helper.ready, helper.failureMessage());
+ QQuickApplicationWindow *window = helper.appWindow;
+ window->show();
+ QVERIFY(QTest::qWaitForWindowExposed(window));
+
+ QQuickMenu *contextMenu = window->property("contextMenu").value<QQuickMenu*>();
+ QVERIFY(contextMenu);
+
+ // Insert a Rectangle between the Action and MenuItem in the top-level menu.
+ QVERIFY(QMetaObject::invokeMethod(window, "insertRectangle",
+ Q_ARG(QQuickMenu *, contextMenu), Q_ARG(int, 1), Q_ARG(QColor, QColorConstants::Red)));
+ {
+ auto *action = contextMenu->actionAt(0);
+ QVERIFY(action);
+ QCOMPARE(action->text(), "action");
+ auto *rectangle = qobject_cast<QQuickRectangle *>(contextMenu->itemAt(1));
+ QVERIFY(rectangle);
+ QCOMPARE(rectangle->color(), QColorConstants::Red);
+ auto *menuItem = qobject_cast<QQuickMenuItem *>(contextMenu->itemAt(2));
+ QVERIFY(menuItem);
+ QCOMPARE(menuItem->text(), "menuItem");
+ auto *subMenu = contextMenu->menuAt(3);
+ QVERIFY(subMenu);
+ QCOMPARE(subMenu->title(), "subMenu");
+ }
+
+ // Insert a Rectangle at the end of all of the items (which were: {Action, Rectangle, MenuItem, Menu}).
+ QVERIFY(QMetaObject::invokeMethod(window, "insertRectangle",
+ Q_ARG(QQuickMenu *, contextMenu), Q_ARG(int, 4), Q_ARG(QColor, QColorConstants::Blue)));
+ {
+ auto *action = contextMenu->actionAt(0);
+ QVERIFY(action);
+ QCOMPARE(action->text(), "action");
+ auto *rectangle1 = qobject_cast<QQuickRectangle *>(contextMenu->itemAt(1));
+ QVERIFY(rectangle1);
+ QCOMPARE(rectangle1->color(), QColorConstants::Red);
+ auto *menuItem = qobject_cast<QQuickMenuItem *>(contextMenu->itemAt(2));
+ QVERIFY(menuItem);
+ QCOMPARE(menuItem->text(), "menuItem");
+ auto *subMenu = contextMenu->menuAt(3);
+ QVERIFY(subMenu);
+ QCOMPARE(subMenu->title(), "subMenu");
+ auto *rectangle2 = qobject_cast<QQuickRectangle *>(contextMenu->itemAt(4));
+ QVERIFY(rectangle2);
+ QCOMPARE(rectangle2->color(), QColorConstants::Blue);
+ }
+
+ // Check that the sub-menu can be accessed and is in the
+ // appropriate place in contentData.
+ auto *subMenu = contextMenu->menuAt(3);
+ QVERIFY(subMenu);
+ // Insert a Rectangle between the Action and MenuItem in the top-level menu.
+ QVERIFY(QMetaObject::invokeMethod(window, "insertRectangle",
+ Q_ARG(QQuickMenu *, subMenu), Q_ARG(int, 1), Q_ARG(QColor, QColorConstants::Green)));
+ {
+ auto *action1 = subMenu->actionAt(0);
+ QVERIFY(action1);
+ QCOMPARE(action1->text(), "subAction1");
+ auto *rectangle = qobject_cast<QQuickRectangle *>(subMenu->itemAt(1));
+ QVERIFY(rectangle);
+ QCOMPARE(rectangle->color(), QColorConstants::Green);
+ auto *action2 = subMenu->actionAt(2);
+ QVERIFY(action2);
+ QCOMPARE(action2->text(), "subAction2");
+ }
+}
+void tst_QQuickMenu::effectivePosition_data()
+{
+ QTest::addColumn<QQuickPopup::PopupType>("popupType");
+
+ QTest::newRow("Item") << QQuickPopup::Item;
+ QTest::newRow("Window") << QQuickPopup::Window;
+}
+
+void tst_QQuickMenu::effectivePosition()
+{
+ // Check that the top-left corner of the background delegate
+ // is placed at the requested menu position. For this test to make
+ // sense, the background delegate needs to be responsible for drawing
+ // the window frame (if any), which Qt::FramelessWindowHint implies.
+ QFETCH(QQuickPopup::PopupType, popupType);
+ SKIP_IF_NO_WINDOW_ACTIVATION
+
+ QQuickControlsApplicationHelper helper(this, QLatin1String("applicationwindow.qml"));
+ QVERIFY2(helper.ready, helper.failureMessage());
+
+ QQuickApplicationWindow *window = helper.appWindow;
+ centerOnScreen(window);
+ window->show();
+ window->requestActivate();
+ QVERIFY(QTest::qWaitForWindowActive(window));
+
+ QQuickMenu *menu = window->property("menu").value<QQuickMenu*>();
+ QVERIFY(menu);
+
+ // This test only makes sense when QQuickMenu is supposed to draw the
+ // window frame. If that changes, then this test will no longer be needed.
+ QVERIFY(QQuickMenuPrivate::get(menu)->popupWindowType() & Qt::FramelessWindowHint);
+
+ menu->setPopupType(popupType);
+
+ // Move the background delegate a bit into the popup, to simulate using a drop-shadow.
+ const QPointF insets = QPointF{20, 10};
+ menu->setLeftInset(insets.x());
+ menu->setTopInset(insets.y());
+
+ const QPointF requestedPos{100, 100};
+ menu->popup(requestedPos);
+ QTRY_VERIFY(menu->isOpened());
+
+ // Unless the popup was moved to fit inside the window (which should not
+ // be the case in this test), we report back to the application that it's
+ // placed at the requested position.
+ QTRY_COMPARE(menu->position(), requestedPos);
+ QCOMPARE(menu->x(), requestedPos.x());
+ QCOMPARE(menu->y(), requestedPos.y());
+
+ // But in reality, it's the background delegate that is placed at the
+ // requested position.
+ const auto background = menu->background();
+ QVERIFY(background);
+ const QPointF actualBgPos = background->mapToItem(menu->parentItem(), {0, 0});
+ QCOMPARE(actualBgPos, requestedPos);
+}
+
+void tst_QQuickMenu::textPadding()
+{
+ // Check that you can set implicitTextPadding on each MenuItem, and that
+ // textPadding will end up as the maximum implicitTextPadding among all the
+ // MenuItems in the same Menu.
+
+ QQuickControlsApplicationHelper helper(this, QLatin1String("nativeMixedItems.qml"));
+ QVERIFY2(helper.ready, helper.failureMessage());
+ QQuickApplicationWindow *window = helper.appWindow;
+ window->show();
+ QVERIFY(QTest::qWaitForWindowExposed(window));
+
+ QQuickMenu *contextMenu = window->property("contextMenu").value<QQuickMenu*>();
+ QVERIFY(contextMenu);
+ contextMenu->setPopupType(QQuickPopup::Item);
+
+ contextMenu->setVisible(true);
+
+ // Go through all MenuItems, and give them an implicitTextPadding of 0
+ for (int i = 0; i < contextMenu->count(); ++i) {
+ auto menuItem = qobject_cast<QQuickMenuItem *>(contextMenu->itemAt(i));
+ QVERIFY(menuItem);
+ menuItem->setImplicitTextPadding(0);
+ QCOMPARE(menuItem->implicitTextPadding(), 0);
+ }
+
+ // Check that all MenuItems now has a textPadding of 0
+ for (int i = 0; i < contextMenu->count(); ++i) {
+ auto menuItem = qobject_cast<QQuickMenuItem *>(contextMenu->itemAt(i));
+ QCOMPARE(menuItem->textPadding(), 0);
+ }
+
+ // Let the first MenuItem get a implicitTextPadding of 100. This will
+ // make all MenuItems get a textPadding of 100.
+ auto firstItem = qobject_cast<QQuickMenuItem *>(contextMenu->itemAt(0));
+ firstItem->setImplicitTextPadding(100);
+ QCOMPARE(firstItem->implicitTextPadding(), 100);
+ QCOMPARE(firstItem->textPadding(), 100);
+ for (int i = 1; i < contextMenu->count(); ++i) {
+ auto menuItem = qobject_cast<QQuickMenuItem *>(contextMenu->itemAt(i));
+ QCOMPARE(menuItem->implicitTextPadding(), 0);
+ QCOMPARE(menuItem->textPadding(), 100);
+ }
+
+ // Hide the MenuItem with implicitTextPadding set to 100. This
+ // should make all the MenuItems get a textPadding of 0 again.
+ firstItem->setVisible(false);
+ QCOMPARE(firstItem->implicitTextPadding(), 100);
+ for (int i = 0; i < contextMenu->count(); ++i) {
+ auto menuItem = qobject_cast<QQuickMenuItem *>(contextMenu->itemAt(i));
+ QCOMPARE(menuItem->textPadding(), 0);
+ }
+
+ // Show it again
+ firstItem->setVisible(true);
+ for (int i = 0; i < contextMenu->count(); ++i) {
+ auto menuItem = qobject_cast<QQuickMenuItem *>(contextMenu->itemAt(i));
+ QCOMPARE(menuItem->textPadding(), 100);
+ }
+}
+
+void tst_QQuickMenu::resetCurrentIndexUponPopup_data()
+{
+ QTest::addColumn<QQuickPopup::PopupType>("popupType");
+
+ QTest::newRow("Item") << QQuickPopup::Item;
+ QTest::newRow("Window") << QQuickPopup::Window;
+
+ // Note: a call to Menu.popup() will be a blocking call on many platforms
+ // when using native menus (e.g macOS and Windows). We can therefore not
+ // check a Menus internal state, nor make a MenuItem current, while it's visible.
+ // QTest::newRow("Native") << QQuickPopup::Native;
+}
+
+void tst_QQuickMenu::resetCurrentIndexUponPopup()
+{
+ // Check that currentIndex is reset back to -1 when
+ // a menu is repopened using the popup() function without
+ // providing a MenuItem as argument.
+ QFETCH(QQuickPopup::PopupType, popupType);
+ SKIP_IF_NO_WINDOW_ACTIVATION
+
+ QQuickControlsApplicationHelper helper(this, QLatin1String("applicationwindow.qml"));
+ QVERIFY2(helper.ready, helper.failureMessage());
+
+ QQuickApplicationWindow *window = helper.appWindow;
+ centerOnScreen(window);
+ window->show();
+ window->requestActivate();
+ QVERIFY(QTest::qWaitForWindowActive(window));
+
+ QQuickMenu *menu = window->property("menu").value<QQuickMenu*>();
+ QVERIFY(menu);
+
+ menu->setPopupType(popupType);
+
+ QCOMPARE(menu->currentIndex(), -1);
+ QCOMPARE(menu->contentItem()->property("currentIndex"), QVariant(-1));
+
+ menu->popup();
+ QTRY_VERIFY(menu->isOpened());
+ QCOMPARE(menu->currentIndex(), -1);
+ QCOMPARE(menu->contentItem()->property("currentIndex"), QVariant(-1));
+
+ menu->setCurrentIndex(1);
+ QCOMPARE(menu->currentIndex(), 1);
+ QCOMPARE(menu->contentItem()->property("currentIndex"), QVariant(1));
+
+ menu->close();
+ QTRY_VERIFY(!menu->isVisible());
+
+ menu->popup();
+ QTRY_VERIFY(menu->isOpened());
+ QCOMPARE(menu->currentIndex(), -1);
+ QCOMPARE(menu->contentItem()->property("currentIndex"), QVariant(-1));
+}
+
QTEST_QUICKCONTROLS_MAIN(tst_QQuickMenu)
#include "tst_qquickmenu.moc"