diff options
Diffstat (limited to 'tests/auto/quickcontrols2/qquickmenu')
26 files changed, 0 insertions, 3194 deletions
diff --git a/tests/auto/quickcontrols2/qquickmenu/BLACKLIST b/tests/auto/quickcontrols2/qquickmenu/BLACKLIST deleted file mode 100644 index fed4c6e561..0000000000 --- a/tests/auto/quickcontrols2/qquickmenu/BLACKLIST +++ /dev/null @@ -1,7 +0,0 @@ -# QTBUG-98491 -[disableWhenTriggered] -macos - -# QTBUG-98491 -[subMenuPosition] -macos diff --git a/tests/auto/quickcontrols2/qquickmenu/CMakeLists.txt b/tests/auto/quickcontrols2/qquickmenu/CMakeLists.txt deleted file mode 100644 index aa5518b31b..0000000000 --- a/tests/auto/quickcontrols2/qquickmenu/CMakeLists.txt +++ /dev/null @@ -1,57 +0,0 @@ -# Copyright (C) 2022 The Qt Company Ltd. -# SPDX-License-Identifier: BSD-3-Clause - -# Generated from qquickmenu.pro. - -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) -endif() - -##################################################################### -## tst_qquickmenu Test: -##################################################################### - -# Collect test data -file(GLOB_RECURSE test_data_glob - RELATIVE ${CMAKE_CURRENT_SOURCE_DIR} - data/*) -list(APPEND test_data ${test_data_glob}) - -qt_internal_add_test(tst_qquickmenu - SOURCES - tst_qquickmenu.cpp - DEFINES - QQC2_IMPORT_PATH=\\\"${CMAKE_CURRENT_SOURCE_DIR}/../../../../src/quickcontrols2\\\" - LIBRARIES - Qt::CorePrivate - Qt::Gui - Qt::GuiPrivate - Qt::QmlPrivate - Qt::QuickControls2 - Qt::QuickControls2Private - Qt::QuickControlsTestUtilsPrivate - Qt::QuickPrivate - Qt::QuickTemplates2Private - Qt::QuickTest - Qt::QuickTestUtilsPrivate - Qt::TestPrivate - TESTDATA ${test_data} -) - -#### Keys ignored in scope 1:.:.:qquickmenu.pro:<TRUE>: -# OTHER_FILES = "data/*.qml" - -## Scopes: -##################################################################### - -qt_internal_extend_target(tst_qquickmenu CONDITION ANDROID OR IOS - DEFINES - QT_QMLTEST_DATADIR=\\\":/data\\\" -) - -qt_internal_extend_target(tst_qquickmenu CONDITION NOT ANDROID AND NOT IOS - DEFINES - QT_QMLTEST_DATADIR=\\\"${CMAKE_CURRENT_SOURCE_DIR}/data\\\" -) diff --git a/tests/auto/quickcontrols2/qquickmenu/data/actionShortcuts.qml b/tests/auto/quickcontrols2/qquickmenu/data/actionShortcuts.qml deleted file mode 100644 index 3d839b98d4..0000000000 --- a/tests/auto/quickcontrols2/qquickmenu/data/actionShortcuts.qml +++ /dev/null @@ -1,50 +0,0 @@ -// Copyright (C) 2022 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 menu: menu - property alias subMenu: subMenu - property alias buttonMenu: buttonMenu - - Menu { - id: menu - objectName: "menu" - - Action { - objectName: text - text: "action1" - shortcut: "A" - } - - Menu { - id: subMenu - objectName: "subMenu" - - Action { - objectName: text - text: "subAction1" - shortcut: "B" - } - } - } - - Button { - text: "Menu button" - - Menu { - id: buttonMenu - - Action { - objectName: text - text: "buttonMenuAction1" - shortcut: "C" - } - } - } -} diff --git a/tests/auto/quickcontrols2/qquickmenu/data/actions.qml b/tests/auto/quickcontrols2/qquickmenu/data/actions.qml deleted file mode 100644 index 0c4449d888..0000000000 --- a/tests/auto/quickcontrols2/qquickmenu/data/actions.qml +++ /dev/null @@ -1,20 +0,0 @@ -// Copyright (C) 2017 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 menu: menu - - Menu { - id: menu - Action { text: "action1" } - MenuItem { text: "menuitem2" } - Action { text: "action3" } - MenuItem { text: "menuitem4" } - } -} diff --git a/tests/auto/quickcontrols2/qquickmenu/data/addItem.qml b/tests/auto/quickcontrols2/qquickmenu/data/addItem.qml deleted file mode 100644 index 5678210e25..0000000000 --- a/tests/auto/quickcontrols2/qquickmenu/data/addItem.qml +++ /dev/null @@ -1,24 +0,0 @@ -// Copyright (C) 2017 The Qt Company Ltd. -// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR BSD-3-Clause - -import QtQuick -import QtQuick.Controls - -ApplicationWindow { - width: 200 - height: 200 - - property alias menu: menu - - MenuItem { - id: newMenuItem - text: qsTr("New") - } - - Menu { - id: menu - y: parent.height - - Component.onCompleted: addItem(newMenuItem) - } -} diff --git a/tests/auto/quickcontrols2/qquickmenu/data/applicationWindowScrollable.qml b/tests/auto/quickcontrols2/qquickmenu/data/applicationWindowScrollable.qml deleted file mode 100644 index eb8140eea5..0000000000 --- a/tests/auto/quickcontrols2/qquickmenu/data/applicationWindowScrollable.qml +++ /dev/null @@ -1,26 +0,0 @@ -// Copyright (C) 2018 The Qt Company Ltd. -// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR BSD-3-Clause - -import QtQuick -import QtQuick.Controls - -ApplicationWindow { - title: "Test Application Window" - width: 300 - height: 300 - - property alias menu: menu - - Menu { - id: menu - - Repeater { - model: 20 - - delegate: MenuItem { - objectName: text - text: (index + 1) - } - } - } -} diff --git a/tests/auto/quickcontrols2/qquickmenu/data/applicationwindow.qml b/tests/auto/quickcontrols2/qquickmenu/data/applicationwindow.qml deleted file mode 100644 index 1b42ee6965..0000000000 --- a/tests/auto/quickcontrols2/qquickmenu/data/applicationwindow.qml +++ /dev/null @@ -1,46 +0,0 @@ -// Copyright (C) 2017 The Qt Company Ltd. -// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR BSD-3-Clause - -import QtQuick -import QtQuick.Controls - -ApplicationWindow { - title: "Test Application Window" - width: 400 - height: 400 - - property alias emptyMenu: emptyMenu - property alias menu: menu - property alias menuButton: menuButton - property Overlay overlay: menu.Overlay.overlay - - Menu { - id: emptyMenu - } - - Menu { - id: menu - cascade: true - - MenuItem { - objectName: "firstMenuItem" - text: "A" - } - MenuItem { - objectName: "secondMenuItem" - text: "B" - } - MenuItem { - objectName: "thirdMenuItem" - text: "C" - } - } - - Button { - id: menuButton - x: 250 - visible: false - text: "Open Menu" - onClicked: menu.open() - } -} diff --git a/tests/auto/quickcontrols2/qquickmenu/data/customMenuCullItems.qml b/tests/auto/quickcontrols2/qquickmenu/data/customMenuCullItems.qml deleted file mode 100644 index 0f56ecdd87..0000000000 --- a/tests/auto/quickcontrols2/qquickmenu/data/customMenuCullItems.qml +++ /dev/null @@ -1,55 +0,0 @@ -import QtQuick -import QtQuick.Controls -import QtQuick.Layouts - -ApplicationWindow { - width: 200 - height: 200 - property alias menu: menu - - Menu { - id: menu - - contentItem: FocusScope { - implicitHeight: view.implicitHeight - Button { - anchors { - top: parent.top - topMargin: 5 - horizontalCenter: parent.horizontalCenter - } - z: 1 - text: "Button Up" - visible: view.interactive - } - ListView { - id: view - width: parent.width - implicitHeight: Math.min(contentHeight, 300) - model: menu.contentModel - - clip: true - currentIndex: menu.currentIndex - ScrollIndicator.vertical: ScrollIndicator {} - } - Button { - anchors { - bottom: parent.bottom - bottomMargin: 5 - horizontalCenter: parent.horizontalCenter - } - z: 1 - text: "Button Down" - visible: view.interactive - } - } - - Repeater { - model: 20 - MenuItem { - objectName: "Item: " + modelData - text: objectName - } - } - } -} diff --git a/tests/auto/quickcontrols2/qquickmenu/data/customMenuUseRepeaterAsTheContentItem.qml b/tests/auto/quickcontrols2/qquickmenu/data/customMenuUseRepeaterAsTheContentItem.qml deleted file mode 100644 index bfa8f66be5..0000000000 --- a/tests/auto/quickcontrols2/qquickmenu/data/customMenuUseRepeaterAsTheContentItem.qml +++ /dev/null @@ -1,65 +0,0 @@ -import QtQuick -import QtQuick.Controls -import QtQuick.Layouts - -ApplicationWindow { - width: 200 - height: 200 - property alias menu: menu - - Menu { - id: menu - visible: true - - contentItem: FocusScope { - implicitHeight: flickable.height - - Button { - anchors { - top: parent.top - topMargin: 5 - horizontalCenter: parent.horizontalCenter - } - z: 1 - text: "Button Up" - } - - Flickable { - id: flickable - width: parent.width - height: Math.min(contentHeight, 300) - contentHeight: repeaterLayout.implicitHeight - clip: true - - ScrollIndicator.vertical: ScrollIndicator {} - - ColumnLayout { - id: repeaterLayout - width: parent.width - - Repeater { - model: menu.contentModel - } - } - } - - Button { - anchors { - bottom: parent.bottom - bottomMargin: 5 - horizontalCenter: parent.horizontalCenter - } - z: 1 - text: "Button Down" - } - } - - Repeater { - model: 20 - MenuItem { - objectName: "Item: " + modelData - text: objectName - } - } - } -} diff --git a/tests/auto/quickcontrols2/qquickmenu/data/delegateFromSeparateComponent.qml b/tests/auto/quickcontrols2/qquickmenu/data/delegateFromSeparateComponent.qml deleted file mode 100644 index 44a7d8d54a..0000000000 --- a/tests/auto/quickcontrols2/qquickmenu/data/delegateFromSeparateComponent.qml +++ /dev/null @@ -1,60 +0,0 @@ -// Copyright (C) 2018 The Qt Company Ltd. -// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR BSD-3-Clause - -import QtQuick -import QtQuick.Controls - -ApplicationWindow { - width: 800 - height: 800 - - property alias menu: menu - - Component { - id: menuItemComponent - - MenuItem { - contentItem: Text { - text: parent.text - color: "blue" - } - background: Rectangle { - color: "#00ff00" - } - } - } - - Menu { - id: menu - title: "Root Menu" - - Action { - text: "Action Item 1" - } - Menu { - title: "Sub-menu" - delegate: menuItemComponent - - Action { - text: "Sub-menu Action Item 1" - } - Menu { - title: "Sub-sub-menu" - delegate: menuItemComponent - - Action { - text: "Sub-sub-menu Action Item 1" - } - } - Action { - text: "Sub-menu Action Item 2" - } - } - Action { - text: "Action Item 2" - } - - delegate: menuItemComponent - visible: true - } -} diff --git a/tests/auto/quickcontrols2/qquickmenu/data/disableWhenTriggered.qml b/tests/auto/quickcontrols2/qquickmenu/data/disableWhenTriggered.qml deleted file mode 100644 index e59026677a..0000000000 --- a/tests/auto/quickcontrols2/qquickmenu/data/disableWhenTriggered.qml +++ /dev/null @@ -1,74 +0,0 @@ -// Copyright (C) 2018 The Qt Company Ltd. -// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR BSD-3-Clause - -import QtQuick -import QtQuick.Controls - -ApplicationWindow { - width: 400 - height: 400 - - Action { - id: actionOutsideMenu - text: "Action declared outside menu" - onTriggered: enabled = false - } - - menuBar: MenuBar { - Menu { - title: "Menu" - objectName: title - - Action { - text: "Action" - objectName: text - onTriggered: enabled = false - } - MenuItem { - objectName: "MenuItem with Action" - action: Action { - text: "Action declared inside MenuItem" - objectName: text - onTriggered: enabled = false - } - } - MenuItem { - objectName: "MenuItem with Action declared outside menu" - action: actionOutsideMenu - } - MenuItem { - text: "MenuItem with no Action" - objectName: text - onTriggered: enabled = false - } - - Menu { - title: "Submenu" - objectName: title - - Action { - text: "Sub-Action" - objectName: text - onTriggered: enabled = false - } - MenuItem { - objectName: "Sub-MenuItem with Action declared inside" - action: Action { - text: "Action declared inside Sub-MenuItem" - objectName: text - onTriggered: enabled = false - } - } - MenuItem { - objectName: "Sub-MenuItem with Action declared outside menu" - action: actionOutsideMenu - } - MenuItem { - text: "Sub-MenuItem with no Action" - objectName: text - onTriggered: enabled = false - } - } - } - } -} diff --git a/tests/auto/quickcontrols2/qquickmenu/data/disabledMenuItemKeyNavigation.qml b/tests/auto/quickcontrols2/qquickmenu/data/disabledMenuItemKeyNavigation.qml deleted file mode 100644 index c9c893bb9c..0000000000 --- a/tests/auto/quickcontrols2/qquickmenu/data/disabledMenuItemKeyNavigation.qml +++ /dev/null @@ -1,27 +0,0 @@ -// Copyright (C) 2019 The Qt Company Ltd. -// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR BSD-3-Clause - -import QtQuick -import QtQuick.Controls - -ApplicationWindow { - width: 200 - height: 200 - - property alias menu: menu - - Menu { - id: menu - - MenuItem { - text: qsTr("Enabled 1") - } - MenuItem { - text: qsTr("Disabled 1") - enabled: false - } - MenuItem { - text: qsTr("Enabled 2") - } - } -} diff --git a/tests/auto/quickcontrols2/qquickmenu/data/giveMenuItemFocusOnButtonPress.qml b/tests/auto/quickcontrols2/qquickmenu/data/giveMenuItemFocusOnButtonPress.qml deleted file mode 100644 index 1db3e351bc..0000000000 --- a/tests/auto/quickcontrols2/qquickmenu/data/giveMenuItemFocusOnButtonPress.qml +++ /dev/null @@ -1,50 +0,0 @@ -// Copyright (C) 2020 The Qt Company Ltd. -// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR BSD-3-Clause - -import QtQuick -import QtQuick.Controls - -ApplicationWindow { - width: 640 - height: 480 - - property alias menuButton: menuButton - property alias menu: menu - - signal menuButtonClicked - - Button { - id: menuButton - text: "Open menu" - - // Buttons do not emit clicked() for enter/return, hence the Keys usage. - // The signal is just for the test to ensure that the return was actually handled. - Keys.onReturnPressed: { - menuButtonClicked() - menu.open() - } - } - - Menu { - id: menu - parent: menuButton - - onOpened: command1.forceActiveFocus() - - MenuItem { - id: command1 - objectName: text - text: "Command 1" - } - - MenuItem { - objectName: text - text: "Command 2" - } - - MenuItem { - objectName: text - text: "Command 3" - } - } -} diff --git a/tests/auto/quickcontrols2/qquickmenu/data/menuItemWidths.qml b/tests/auto/quickcontrols2/qquickmenu/data/menuItemWidths.qml deleted file mode 100644 index ff99abd399..0000000000 --- a/tests/auto/quickcontrols2/qquickmenu/data/menuItemWidths.qml +++ /dev/null @@ -1,56 +0,0 @@ -// Copyright (C) 2019 The Qt Company Ltd. -// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR BSD-3-Clause - -import QtQuick -import QtQuick.Controls - -ApplicationWindow { - width: 600 - height: 600 - - property alias menu: menu - - Menu { - id: menu - MenuItem { - objectName: "MenuItem" - text: "MenuItem" - } - MenuSeparator { - objectName: "MenuSeparator" - } - Menu { - title: "Sub-menu" - objectName: "Sub-menu" - - MenuItem { - objectName: "SubMenuItem" - text: "SubMenuItem" - } - } - Rectangle { - objectName: "CustomSeparator" - height: 2 - color: "salmon" - } - Rectangle { - // Use a binding to test retranslate(), which re-evaluates all bindings. - implicitWidth: someValue - objectName: "CustomRectangleSeparator" - height: 2 - color: "salmon" - - property int someValue: 120 - } - Control { - objectName: "CustomControlSeparator" - implicitWidth: someOtherValue - height: 2 - background: Rectangle { - color: "navajowhite" - } - - property int someOtherValue: 180 - } - } -} diff --git a/tests/auto/quickcontrols2/qquickmenu/data/menuSeparator.qml b/tests/auto/quickcontrols2/qquickmenu/data/menuSeparator.qml deleted file mode 100644 index b13cd534fd..0000000000 --- a/tests/auto/quickcontrols2/qquickmenu/data/menuSeparator.qml +++ /dev/null @@ -1,37 +0,0 @@ -// Copyright (C) 2017 The Qt Company Ltd. -// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR BSD-3-Clause - -import QtQuick -import QtQuick.Controls - -ApplicationWindow { - width: 200 - height: 200 - - property alias menu: menu - - MenuItem { - id: newMenuItem - text: qsTr("New") - } - - MenuSeparator { - id: menuSeparator - } - - MenuItem { - id: saveMenuItem - text: qsTr("Save") - } - - Menu { - id: menu - cascade: true - - Component.onCompleted: { - addItem(newMenuItem) - addItem(menuSeparator) - addItem(saveMenuItem) - } - } -} diff --git a/tests/auto/quickcontrols2/qquickmenu/data/mnemonics.qml b/tests/auto/quickcontrols2/qquickmenu/data/mnemonics.qml deleted file mode 100644 index 8929b00275..0000000000 --- a/tests/auto/quickcontrols2/qquickmenu/data/mnemonics.qml +++ /dev/null @@ -1,40 +0,0 @@ -// Copyright (C) 2017 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 menu: menu - property alias action: action - property alias menuItem: menuItem - property alias subMenu: subMenu - property alias subMenuItem: subMenuItem - - Menu { - id: menu - - Action { - id: action - text: "&Action" - } - - MenuItem { - id: menuItem - text: "Menu &Item" - } - - Menu { - id: subMenu - title: "Sub &Menu" - - MenuItem { - id: subMenuItem - text: "&Sub Menu Item" - } - } - } -} diff --git a/tests/auto/quickcontrols2/qquickmenu/data/order.qml b/tests/auto/quickcontrols2/qquickmenu/data/order.qml deleted file mode 100644 index 185c9e45c3..0000000000 --- a/tests/auto/quickcontrols2/qquickmenu/data/order.qml +++ /dev/null @@ -1,34 +0,0 @@ -// Copyright (C) 2017 The Qt Company Ltd. -// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR BSD-3-Clause - -import QtQuick -import QtQuick.Controls - -ApplicationWindow { - width: 200 - height: 200 - - property alias menu: menu - - Component { - id: menuItem - MenuItem { } - } - - Menu { - id: menu - property alias repeater: repeater - MenuItem { text: "static_1" } - Repeater { - id: repeater - model: 2 - MenuItem { text: "repeated_" + (index + 2) } - } - MenuItem { text: "static_4" } - Component.onCompleted: { - addItem(menuItem.createObject(menu.contentItem, {text: "dynamic_5"})) - addItem(menuItem.createObject(menu.contentItem, {text: "dynamic_6"})) - insertItem(0, menuItem.createObject(menu.contentItem, {text: "dynamic_0"})) - } - } -} diff --git a/tests/auto/quickcontrols2/qquickmenu/data/popup.qml b/tests/auto/quickcontrols2/qquickmenu/data/popup.qml deleted file mode 100644 index 8201c9e03f..0000000000 --- a/tests/auto/quickcontrols2/qquickmenu/data/popup.qml +++ /dev/null @@ -1,77 +0,0 @@ -// Copyright (C) 2017 The Qt Company Ltd. -// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR BSD-3-Clause - -import QtQuick -import QtQuick.Controls - -ApplicationWindow { - width: 500 - height: 600 - - property alias menu: menu - property alias menuItem1: menuItem1 - property alias menuItem2: menuItem2 - property alias menuItem3: menuItem3 - property alias button: button - - function popupAtCursor() { - menu.popup() - } - - function popupAtPos(pos) { - menu.popup(pos) - } - - function popupAtCoord(x, y) { - menu.popup(x, y) - } - - function popupItemAtCursor(item) { - menu.popup(item) - } - - function popupItemAtPos(pos, item) { - menu.popup(pos, item) - } - - function popupItemAtCoord(x, y, item) { - menu.popup(x, y, item) - } - - function popupAtParentCursor(parent) { - menu.popup(parent) - } - - function popupAtParentPos(parent, pos) { - menu.popup(parent, pos) - } - - function popupAtParentCoord(parent, x, y) { - menu.popup(parent, x, y) - } - - function popupItemAtParentCursor(parent, item) { - menu.popup(parent, item) - } - - function popupItemAtParentPos(parent, pos, item) { - menu.popup(parent, pos, item) - } - - function popupItemAtParentCoord(parent, x, y, item) { - menu.popup(parent, x, y, item) - } - - Menu { - id: menu - MenuItem { id: menuItem1; text: "Foo" } - MenuItem { id: menuItem2; text: "Bar" } - MenuItem { id: menuItem3; text: "Baz" } - } - - Button { - id: button - text: "Button" - anchors.centerIn: parent - } -} diff --git a/tests/auto/quickcontrols2/qquickmenu/data/pressAndHold.qml b/tests/auto/quickcontrols2/qquickmenu/data/pressAndHold.qml deleted file mode 100644 index ac0f394604..0000000000 --- a/tests/auto/quickcontrols2/qquickmenu/data/pressAndHold.qml +++ /dev/null @@ -1,26 +0,0 @@ -// Copyright (C) 2017 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 menu: menu - - MouseArea { - anchors.fill: parent - onPressAndHold: menu.open() - } - - Menu { - id: menu - x: (parent.width - width) / 2 - y: (parent.height - height) / 2 - MenuItem { text: "One" } - MenuItem { text: "Two" } - MenuItem { text: "Three" } - } -} diff --git a/tests/auto/quickcontrols2/qquickmenu/data/removeTakeItem.qml b/tests/auto/quickcontrols2/qquickmenu/data/removeTakeItem.qml deleted file mode 100644 index aa321cb3a9..0000000000 --- a/tests/auto/quickcontrols2/qquickmenu/data/removeTakeItem.qml +++ /dev/null @@ -1,40 +0,0 @@ -// Copyright (C) 2017 The Qt Company Ltd. -// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR BSD-3-Clause - -import QtQuick -import QtQuick.Controls - -ApplicationWindow { - width: 200 - height: 200 - - property alias menu: menu - property alias menuItem1: menuItem1 - property alias menuItem2: menuItem2 - property alias menuItem3: menuItem3 - - function takeSecondItem() { - return menu.takeItem(1) - } - - function removeFirstItem() { - menu.removeItem(menuItem1) - } - - function removeNullItem() { - menu.removeItem(null) - } - - Menu { - id: menu - MenuItem { - id: menuItem1 - } - MenuItem { - id: menuItem2 - } - MenuItem { - id: menuItem3 - } - } -} diff --git a/tests/auto/quickcontrols2/qquickmenu/data/repeater.qml b/tests/auto/quickcontrols2/qquickmenu/data/repeater.qml deleted file mode 100644 index 3c056a1d38..0000000000 --- a/tests/auto/quickcontrols2/qquickmenu/data/repeater.qml +++ /dev/null @@ -1,22 +0,0 @@ -// Copyright (C) 2017 The Qt Company Ltd. -// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR BSD-3-Clause - -import QtQuick -import QtQuick.Controls - -ApplicationWindow { - width: 200 - height: 200 - - property alias menu: menu - property alias repeater: repeater - - Menu { - id: menu - Repeater { - id: repeater - model: 5 - MenuItem { property int idx: index } - } - } -} diff --git a/tests/auto/quickcontrols2/qquickmenu/data/scrollableWithPadding.qml b/tests/auto/quickcontrols2/qquickmenu/data/scrollableWithPadding.qml deleted file mode 100644 index 842cb33bfd..0000000000 --- a/tests/auto/quickcontrols2/qquickmenu/data/scrollableWithPadding.qml +++ /dev/null @@ -1,32 +0,0 @@ -// Copyright (C) 2020 The Qt Company Ltd. -// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR BSD-3-Clause - -import QtQuick -import QtQuick.Controls -import QtQuick.Window - -Window { - title: "Test Window" - width: 300 - height: dummyItem.height * 10 - - property alias menu: menu - MenuItem { - id: dummyItem - objectName: "Dummy" - text: objectName - } - - Menu { - id: menu - topPadding: 10 - Repeater { - model: 10 - - delegate: MenuItem { - objectName: text - text: (index + 1) - } - } - } -} diff --git a/tests/auto/quickcontrols2/qquickmenu/data/subMenuDisabled.qml b/tests/auto/quickcontrols2/qquickmenu/data/subMenuDisabled.qml deleted file mode 100644 index 4d5db0bd67..0000000000 --- a/tests/auto/quickcontrols2/qquickmenu/data/subMenuDisabled.qml +++ /dev/null @@ -1,32 +0,0 @@ -// Copyright (C) 2019 The Qt Company Ltd. -// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR BSD-3-Clause - -import QtQuick -import QtQuick.Controls - -ApplicationWindow { - width: 600 - height: 400 - - property alias mainMenu: mainMenu - property alias subMenu: subMenu - - Menu { - id: mainMenu - title: "Menu" - - Menu { - id: subMenu - title: "Sub Menu" - MenuItem { - id: subMenuItem1 - text: "Sub Menu Item 1" - enabled: false - } - MenuItem { - id: subMenuItem2 - text: "Sub Menu Item 2" - } - } - } -} diff --git a/tests/auto/quickcontrols2/qquickmenu/data/subMenus.qml b/tests/auto/quickcontrols2/qquickmenu/data/subMenus.qml deleted file mode 100644 index 280fd404e8..0000000000 --- a/tests/auto/quickcontrols2/qquickmenu/data/subMenus.qml +++ /dev/null @@ -1,90 +0,0 @@ -// Copyright (C) 2017 The Qt Company Ltd. -// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR BSD-3-Clause - -import QtQuick -import QtQuick.Controls - -ApplicationWindow { - width: 600 - height: 400 - - property alias mainMenu: mainMenu - property alias subMenu1: subMenu1 - property alias subMenu2: subMenu2 - property alias subSubMenu1: subSubMenu1 - - Menu { - id: mainMenu - MenuItem { - id: mainMenuItem1 - objectName: "mainMenuItem1" - text: "Main 1" - } - - Menu { - overlap: 0 - id: subMenu1 - objectName: "subMenu1" - title: "Sub Menu 1" - - MenuItem { - id: subMenuItem1 - objectName: "subMenuItem1" - text: "Sub 1" - } - - MenuItem { - id: subMenuItem2 - objectName: "subMenuItem2" - text: "Sub 2" - } - - Menu { - overlap: 0 - id: subSubMenu1 - objectName: "subSubMenu1" - title: "Sub Sub Menu 1" - - MenuItem { - id: subSubMenuItem1 - objectName: "subSubMenuItem1" - text: "Sub Sub 1" - } - MenuItem { - id: subSubMenuItem2 - objectName: "subSubMenuItem2" - text: "Sub Sub 2" - } - } - } - - MenuItem { - id: mainMenuItem2 - objectName: "mainMenuItem2" - text: "Main 2" - } - - Menu { - id: subMenu2 - objectName: "subMenu2" - title: "Sub Menu 2" - - MenuItem { - id: subMenuItem3 - objectName: "subMenuItem3" - text: "Sub 3" - } - MenuItem { - id: subMenuItem4 - objectName: "subMenuItem4" - text: "Sub 4" - } - } - - MenuItem { - id: mainMenuItem3 - objectName: "mainMenuItem3" - text: "Main 3" - } - } -} diff --git a/tests/auto/quickcontrols2/qquickmenu/data/windowScrollable.qml b/tests/auto/quickcontrols2/qquickmenu/data/windowScrollable.qml deleted file mode 100644 index 97a06da63d..0000000000 --- a/tests/auto/quickcontrols2/qquickmenu/data/windowScrollable.qml +++ /dev/null @@ -1,27 +0,0 @@ -// Copyright (C) 2018 The Qt Company Ltd. -// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR BSD-3-Clause - -import QtQuick -import QtQuick.Controls -import QtQuick.Window - -Window { - title: "Test Window" - width: 300 - height: 300 - - property alias menu: menu - - Menu { - id: menu - - Repeater { - model: 20 - - delegate: MenuItem { - objectName: text - text: (index + 1) - } - } - } -} diff --git a/tests/auto/quickcontrols2/qquickmenu/tst_qquickmenu.cpp b/tests/auto/quickcontrols2/qquickmenu/tst_qquickmenu.cpp deleted file mode 100644 index 6a1d1ab803..0000000000 --- a/tests/auto/quickcontrols2/qquickmenu/tst_qquickmenu.cpp +++ /dev/null @@ -1,2120 +0,0 @@ -// Copyright (C) 2017 The Qt Company Ltd. -// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0 - -#include <QtTest/qtest.h> -#include <QtTest/qsignalspy.h> -#include <QtGui/qcursor.h> -#if QT_CONFIG(shortcut) -#include <QtGui/qkeysequence.h> -#endif -#include <QtGui/qstylehints.h> -#include <QtGui/qpa/qplatformintegration.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 <QtQuickTestUtils/private/qmlutils_p.h> -#include <QtQuickTestUtils/private/visualtestutils_p.h> -#include <QtQuickControlsTestUtils/private/controlstestutils_p.h> -#include <QtQuickControlsTestUtils/private/qtest_quickcontrols_p.h> - -#include <QtQuickTemplates2/private/qquickaction_p.h> -#include <QtQuickTemplates2/private/qquickapplicationwindow_p.h> -#include <QtQuickTemplates2/private/qquickoverlay_p.h> -#include <QtQuickTemplates2/private/qquickbutton_p.h> -#include <QtQuickTemplates2/private/qquickicon_p.h> -#include <QtQuickTemplates2/private/qquickmenu_p.h> -#include <QtQuickTemplates2/private/qquickmenuitem_p.h> -#include <QtQuickTemplates2/private/qquickmenuseparator_p.h> - -using namespace QQuickVisualTestUtils; -using namespace QQuickControlsTestUtils; - -class tst_QQuickMenu : public QQmlDataTest -{ - Q_OBJECT - -public: - tst_QQuickMenu(); - -private slots: - void defaults(); - void count(); - void mouse(); - void pressAndHold(); - void contextMenuKeyboard(); - void disabledMenuItemKeyNavigation(); - void mnemonics(); - void menuButton(); - void addItem(); - void menuSeparator(); - void repeater(); - void order(); -#if QT_CONFIG(cursor) - void popup(); -#endif - void actions(); -#if QT_CONFIG(shortcut) - void actionShortcuts(); -#endif - void removeTakeItem(); - void subMenuMouse_data(); - void subMenuMouse(); - void subMenuDisabledMouse_data(); - void subMenuDisabledMouse(); - void subMenuKeyboard_data(); - void subMenuKeyboard(); - void subMenuDisabledKeyboard_data(); - void subMenuDisabledKeyboard(); - void subMenuPosition_data(); - void subMenuPosition(); - void subMenuWithIcon(); - void addRemoveSubMenus(); - void scrollable_data(); - void scrollable(); - void disableWhenTriggered_data(); - void disableWhenTriggered(); - void menuItemWidth_data(); - void menuItemWidth(); - void menuItemWidthAfterMenuWidthChanged_data(); - void menuItemWidthAfterMenuWidthChanged(); - void menuItemWidthAfterImplicitWidthChanged_data(); - void menuItemWidthAfterImplicitWidthChanged(); - void menuItemWidthAfterRetranslate(); - void giveMenuItemFocusOnButtonPress(); - void customMenuCullItems(); - void customMenuUseRepeaterAsTheContentItem(); - -private: - static bool hasWindowActivation(); -}; - -tst_QQuickMenu::tst_QQuickMenu() - : QQmlDataTest(QT_QMLTEST_DATADIR) -{ -} - -bool tst_QQuickMenu::hasWindowActivation() -{ - return (QGuiApplicationPrivate::platformIntegration()->hasCapability(QPlatformIntegration::WindowActivation)); -} - -void tst_QQuickMenu::defaults() -{ - QQuickControlsApplicationHelper helper(this, QLatin1String("applicationwindow.qml")); - QVERIFY2(helper.ready, helper.failureMessage()); - - QQuickMenu *emptyMenu = helper.appWindow->property("emptyMenu").value<QQuickMenu*>(); - QCOMPARE(emptyMenu->isVisible(), false); - QVERIFY(emptyMenu->hasFocus()); - QCOMPARE(emptyMenu->currentIndex(), -1); - QCOMPARE(emptyMenu->contentItem()->property("currentIndex"), QVariant(-1)); - QCOMPARE(emptyMenu->count(), 0); -} - -void tst_QQuickMenu::count() -{ - QQuickControlsApplicationHelper helper(this, QLatin1String("applicationwindow.qml")); - QVERIFY2(helper.ready, helper.failureMessage()); - - QQuickMenu *menu = helper.window->property("emptyMenu").value<QQuickMenu*>(); - QVERIFY(menu); - - QSignalSpy countSpy(menu, &QQuickMenu::countChanged); - QVERIFY(countSpy.isValid()); - - menu->addItem(new QQuickItem); - QCOMPARE(menu->count(), 1); - QCOMPARE(countSpy.size(), 1); - - menu->insertItem(0, new QQuickItem); - QCOMPARE(menu->count(), 2); - QCOMPARE(countSpy.size(), 2); - - menu->removeItem(menu->itemAt(1)); - QCOMPARE(menu->count(), 1); - QCOMPARE(countSpy.size(), 3); - - QScopedPointer<QQuickItem> item(menu->takeItem(0)); - QVERIFY(item); - QCOMPARE(menu->count(), 0); - QCOMPARE(countSpy.size(), 4); -} - -void tst_QQuickMenu::mouse() -{ - if (!hasWindowActivation()) - QSKIP("Window activation is not supported"); - - if ((QGuiApplication::platformName() == QLatin1String("offscreen")) - || (QGuiApplication::platformName() == QLatin1String("minimal"))) - QSKIP("Mouse hovering not functional on offscreen/minimal platforms"); - - QQuickControlsApplicationHelper helper(this, QLatin1String("applicationwindow.qml")); - QVERIFY2(helper.ready, helper.failureMessage()); - - QQuickApplicationWindow *window = helper.appWindow; - centerOnScreen(window); - moveMouseAway(window); - window->show(); - QVERIFY(QTest::qWaitForWindowActive(window)); - - QQuickMenu *menu = window->property("menu").value<QQuickMenu*>(); - QVERIFY(menu); - menu->open(); - QVERIFY(menu->isVisible()); - QQuickOverlay *overlay = window->property("overlay").value<QQuickOverlay*>(); - QVERIFY(overlay); - QVERIFY(overlay->childItems().contains(menu->contentItem()->parentItem())); - QTRY_VERIFY(menu->isOpened()); - - QQuickItem *firstItem = menu->itemAt(0); - QSignalSpy clickedSpy(firstItem, SIGNAL(clicked())); - QSignalSpy triggeredSpy(firstItem, SIGNAL(triggered())); - QSignalSpy visibleSpy(menu, SIGNAL(visibleChanged())); - - // Ensure that presses cause the current index to change, - // so that the highlight acts as a way of illustrating press state. - QTest::mousePress(window, Qt::LeftButton, Qt::NoModifier, - QPoint(menu->x() + menu->leftPadding() + firstItem->width() / 2, menu->y() + menu->topPadding() + firstItem->height() / 2)); - QVERIFY(firstItem->hasActiveFocus()); - QCOMPARE(menu->currentIndex(), 0); - QCOMPARE(menu->contentItem()->property("currentIndex"), QVariant(0)); - QVERIFY(menu->isVisible()); - - QTest::mouseRelease(window, Qt::LeftButton, Qt::NoModifier, - QPoint(menu->x() + menu->leftPadding() + firstItem->width() / 2, menu->y() + menu->topPadding() + firstItem->height() / 2)); - QCOMPARE(clickedSpy.size(), 1); - QCOMPARE(triggeredSpy.size(), 1); - QTRY_COMPARE(visibleSpy.size(), 1); - QVERIFY(!menu->isVisible()); - QVERIFY(!overlay->childItems().contains(menu->contentItem())); - QCOMPARE(menu->currentIndex(), -1); - QCOMPARE(menu->contentItem()->property("currentIndex"), QVariant(-1)); - - menu->open(); - QCOMPARE(visibleSpy.size(), 2); - QVERIFY(menu->isVisible()); - QVERIFY(overlay->childItems().contains(menu->contentItem()->parentItem())); - QTRY_VERIFY(menu->isOpened()); - - // Ensure that we have enough space to click outside of the menu. - QVERIFY(window->width() > menu->contentItem()->width()); - QVERIFY(window->height() > menu->contentItem()->height()); - QTest::mouseClick(window, Qt::LeftButton, Qt::NoModifier, - QPoint(menu->contentItem()->x() + menu->contentItem()->width() + 1, - menu->contentItem()->y() + menu->contentItem()->height() + 1)); - QTRY_COMPARE(visibleSpy.size(), 3); - QVERIFY(!menu->isVisible()); - QVERIFY(!overlay->childItems().contains(menu->contentItem()->parentItem())); - - menu->open(); - QCOMPARE(visibleSpy.size(), 4); - QVERIFY(menu->isVisible()); - QVERIFY(overlay->childItems().contains(menu->contentItem()->parentItem())); - QTRY_VERIFY(menu->isOpened()); - - // Hover-highlighting does not work on Android -#ifndef Q_OS_ANDROID - // Hover-highlight through the menu items one by one - QQuickItem *prevHoverItem = nullptr; - QQuickItem *listView = menu->contentItem(); - for (int y = menu->topPadding(); y < listView->height(); ++y) { - QQuickItem *hoverItem = nullptr; - QVERIFY(QMetaObject::invokeMethod(listView, "itemAt", Q_RETURN_ARG(QQuickItem *, hoverItem), Q_ARG(qreal, 0), Q_ARG(qreal, listView->property("contentY").toReal() + y))); - if (!hoverItem || !hoverItem->isVisible() || hoverItem == prevHoverItem) - continue; - QTest::mouseMove(window, QPoint( - menu->x() + menu->leftPadding() + hoverItem->x() + hoverItem->width() / 2, - menu->y() + menu->topPadding() + hoverItem->y() + hoverItem->height() / 2)); - QTRY_VERIFY(hoverItem->property("highlighted").toBool()); - if (prevHoverItem) - QVERIFY(!prevHoverItem->property("highlighted").toBool()); - prevHoverItem = hoverItem; - } -#endif - - // Try pressing within the menu and releasing outside of it; it should close. - // TODO: won't work until QQuickPopup::releasedOutside() actually gets emitted -// QTest::mousePress(window, Qt::LeftButton, Qt::NoModifier, QPoint(firstItem->width() / 2, firstItem->height() / 2)); -// QVERIFY(firstItem->hasActiveFocus()); -// QCOMPARE(menu->contentItem()->property("currentIndex"), QVariant(0)); -// QVERIFY(menu->isVisible()); -// QCOMPARE(triggeredSpy.count(), 1); - -// QTest::mouseRelease(window, Qt::LeftButton, Qt::NoModifier, QPoint(menu->contentItem()->width() + 1, firstItem->height() / 2)); -// QCOMPARE(clickedSpy.count(), 1); -// QCOMPARE(triggeredSpy.count(), 1); -// QCOMPARE(visibleSpy.count(), 5); -// QVERIFY(!menu->isVisible()); -// QVERIFY(!overlay->childItems().contains(menu->contentItem())); -// QCOMPARE(menu->contentItem()->property("currentIndex"), QVariant(-1)); -} - -void tst_QQuickMenu::pressAndHold() -{ - QQuickControlsApplicationHelper helper(this, QLatin1String("pressAndHold.qml")); - QVERIFY2(helper.ready, helper.failureMessage()); - - QQuickWindow *window = helper.window; - window->show(); - QVERIFY(QTest::qWaitForWindowExposed(window)); - - QQuickMenu *menu = window->property("menu").value<QQuickMenu *>(); - QVERIFY(menu); - - QTest::mousePress(window, Qt::LeftButton, Qt::NoModifier, QPoint(1, 1)); - QTRY_VERIFY(menu->isVisible()); - - QTest::mouseRelease(window, Qt::LeftButton, Qt::NoModifier, QPoint(1, 1)); - QVERIFY(menu->isVisible()); - - QTest::mouseClick(window, Qt::LeftButton, Qt::NoModifier, QPoint(1, 1)); - QTRY_VERIFY(!menu->isVisible()); -} - -void tst_QQuickMenu::contextMenuKeyboard() -{ - if (!hasWindowActivation()) - QSKIP("Window activation is not supported"); - - if (QGuiApplication::styleHints()->tabFocusBehavior() != Qt::TabFocusAllControls) - QSKIP("This platform only allows tab focus for text controls"); - - QQuickControlsApplicationHelper helper(this, QLatin1String("applicationwindow.qml")); - QVERIFY2(helper.ready, helper.failureMessage()); - - QQuickApplicationWindow *window = helper.appWindow; - centerOnScreen(window); - moveMouseAway(window); - window->show(); - window->requestActivate(); - QVERIFY(QTest::qWaitForWindowActive(window)); - QVERIFY(QGuiApplication::focusWindow() == window); - - QQuickMenu *menu = window->property("menu").value<QQuickMenu*>(); - QCOMPARE(menu->currentIndex(), -1); - QCOMPARE(menu->contentItem()->property("currentIndex"), QVariant(-1)); - - QQuickMenuItem *firstItem = qobject_cast<QQuickMenuItem *>(menu->itemAt(0)); - QVERIFY(firstItem); - QSignalSpy visibleSpy(menu, SIGNAL(visibleChanged())); - - QVERIFY(menu->hasFocus()); - menu->open(); - QCOMPARE(visibleSpy.size(), 1); - QVERIFY(menu->isVisible()); - QVERIFY(menu->hasActiveFocus()); - QQuickOverlay *overlay = window->property("overlay").value<QQuickOverlay*>(); - QVERIFY(overlay); - QVERIFY(overlay->childItems().contains(menu->contentItem()->parentItem())); - QTRY_VERIFY(menu->isOpened()); - QVERIFY(!firstItem->hasActiveFocus()); - QVERIFY(!firstItem->property("highlighted").toBool()); - QCOMPARE(menu->currentIndex(), -1); - QCOMPARE(menu->contentItem()->property("currentIndex"), QVariant(-1)); - - QTest::keyClick(window, Qt::Key_Tab); - QVERIFY(firstItem->hasActiveFocus()); - QVERIFY(firstItem->hasVisualFocus()); - QVERIFY(firstItem->isHighlighted()); - QCOMPARE(firstItem->focusReason(), Qt::TabFocusReason); - QCOMPARE(menu->currentIndex(), 0); - QCOMPARE(menu->contentItem()->property("currentIndex"), QVariant(0)); - - QQuickMenuItem *secondItem = qobject_cast<QQuickMenuItem *>(menu->itemAt(1)); - QVERIFY(secondItem); - QTest::keyClick(window, Qt::Key_Tab); - QVERIFY(!firstItem->hasActiveFocus()); - QVERIFY(!firstItem->hasVisualFocus()); - QVERIFY(!firstItem->isHighlighted()); - QVERIFY(secondItem->hasActiveFocus()); - QVERIFY(secondItem->hasVisualFocus()); - QVERIFY(secondItem->isHighlighted()); - QCOMPARE(secondItem->focusReason(), Qt::TabFocusReason); - QCOMPARE(menu->currentIndex(), 1); - QCOMPARE(menu->contentItem()->property("currentIndex"), QVariant(1)); - - QSignalSpy secondTriggeredSpy(secondItem, SIGNAL(triggered())); - QTest::keyClick(window, Qt::Key_Space); - QCOMPARE(secondTriggeredSpy.size(), 1); - QTRY_COMPARE(visibleSpy.size(), 2); - QVERIFY(!menu->isVisible()); - QVERIFY(!overlay->childItems().contains(menu->contentItem())); - QVERIFY(!firstItem->hasActiveFocus()); - QVERIFY(!firstItem->hasVisualFocus()); - QVERIFY(!firstItem->isHighlighted()); - QVERIFY(!secondItem->hasActiveFocus()); - QVERIFY(!secondItem->hasVisualFocus()); - QVERIFY(!secondItem->isHighlighted()); - QCOMPARE(menu->currentIndex(), -1); - QCOMPARE(menu->contentItem()->property("currentIndex"), QVariant(-1)); - - // Enter/return should also work. - // Open the menu. - menu->open(); - QCOMPARE(visibleSpy.size(), 3); - QVERIFY(menu->isVisible()); - QTRY_VERIFY(menu->isOpened()); - // Give the first item focus. - QTest::keyClick(window, Qt::Key_Tab); - QVERIFY(firstItem->hasActiveFocus()); - QVERIFY(firstItem->hasVisualFocus()); - QVERIFY(firstItem->isHighlighted()); - QCOMPARE(firstItem->focusReason(), Qt::TabFocusReason); - QCOMPARE(menu->currentIndex(), 0); - QCOMPARE(menu->contentItem()->property("currentIndex"), QVariant(0)); - // Press enter. - QSignalSpy firstTriggeredSpy(firstItem, SIGNAL(triggered())); - QTest::keyClick(window, Qt::Key_Return); - QCOMPARE(firstTriggeredSpy.size(), 1); - QTRY_COMPARE(visibleSpy.size(), 4); - QVERIFY(!menu->isVisible()); - QVERIFY(!overlay->childItems().contains(menu->contentItem())); - QVERIFY(!firstItem->hasActiveFocus()); - QVERIFY(!firstItem->hasVisualFocus()); - QVERIFY(!firstItem->isHighlighted()); - QVERIFY(!secondItem->hasActiveFocus()); - QVERIFY(!secondItem->hasVisualFocus()); - QVERIFY(!secondItem->isHighlighted()); - QCOMPARE(menu->currentIndex(), -1); - QCOMPARE(menu->contentItem()->property("currentIndex"), QVariant(-1)); - - menu->open(); - QCOMPARE(visibleSpy.size(), 5); - QVERIFY(menu->isVisible()); - QVERIFY(overlay->childItems().contains(menu->contentItem()->parentItem())); - QTRY_VERIFY(menu->isOpened()); - QVERIFY(!firstItem->hasActiveFocus()); - QVERIFY(!firstItem->hasVisualFocus()); - QVERIFY(!firstItem->isHighlighted()); - QVERIFY(!secondItem->hasActiveFocus()); - QVERIFY(!secondItem->hasVisualFocus()); - QVERIFY(!secondItem->isHighlighted()); - QCOMPARE(menu->currentIndex(), -1); - QCOMPARE(menu->contentItem()->property("currentIndex"), QVariant(-1)); - - QTest::keyClick(window, Qt::Key_Down); - QVERIFY(firstItem->hasActiveFocus()); - QVERIFY(firstItem->hasVisualFocus()); - QVERIFY(firstItem->isHighlighted()); - QCOMPARE(firstItem->focusReason(), Qt::TabFocusReason); - - QTest::keyClick(window, Qt::Key_Down); - QVERIFY(secondItem->hasActiveFocus()); - QVERIFY(secondItem->hasVisualFocus()); - QVERIFY(secondItem->isHighlighted()); - QCOMPARE(secondItem->focusReason(), Qt::TabFocusReason); - - QTest::keyClick(window, Qt::Key_Down); - QQuickMenuItem *thirdItem = qobject_cast<QQuickMenuItem *>(menu->itemAt(2)); - QVERIFY(thirdItem); - QVERIFY(!firstItem->hasActiveFocus()); - QVERIFY(!firstItem->hasVisualFocus()); - QVERIFY(!firstItem->isHighlighted()); - QVERIFY(!secondItem->hasActiveFocus()); - QVERIFY(!secondItem->hasVisualFocus()); - QVERIFY(!secondItem->isHighlighted()); - QVERIFY(thirdItem->hasActiveFocus()); - QVERIFY(thirdItem->hasVisualFocus()); - QVERIFY(thirdItem->isHighlighted()); - QCOMPARE(thirdItem->focusReason(), Qt::TabFocusReason); - - // Key navigation shouldn't wrap by default. - QTest::keyClick(window, Qt::Key_Down); - QVERIFY(!firstItem->hasActiveFocus()); - QVERIFY(!firstItem->hasVisualFocus()); - QVERIFY(!firstItem->isHighlighted()); - QVERIFY(!secondItem->hasActiveFocus()); - QVERIFY(!secondItem->hasVisualFocus()); - QVERIFY(!secondItem->isHighlighted()); - QVERIFY(thirdItem->hasActiveFocus()); - QVERIFY(thirdItem->hasVisualFocus()); - QVERIFY(thirdItem->isHighlighted()); - QCOMPARE(thirdItem->focusReason(), Qt::TabFocusReason); - - QTest::keyClick(window, Qt::Key_Up); - QVERIFY(!firstItem->hasActiveFocus()); - QVERIFY(!firstItem->hasVisualFocus()); - QVERIFY(!firstItem->isHighlighted()); - QVERIFY(secondItem->hasActiveFocus()); - QVERIFY(secondItem->hasVisualFocus()); - QVERIFY(secondItem->isHighlighted()); - QCOMPARE(secondItem->focusReason(), Qt::BacktabFocusReason); - QVERIFY(!thirdItem->hasActiveFocus()); - QVERIFY(!thirdItem->hasVisualFocus()); - QVERIFY(!thirdItem->isHighlighted()); - - QTest::keyClick(window, Qt::Key_Backtab); - QVERIFY(firstItem->hasActiveFocus()); - QVERIFY(firstItem->hasVisualFocus()); - QVERIFY(firstItem->isHighlighted()); - QCOMPARE(firstItem->focusReason(), Qt::BacktabFocusReason); - QVERIFY(!secondItem->hasActiveFocus()); - QVERIFY(!secondItem->hasVisualFocus()); - QVERIFY(!secondItem->isHighlighted()); - QVERIFY(!thirdItem->hasActiveFocus()); - QVERIFY(!thirdItem->hasVisualFocus()); - QVERIFY(!thirdItem->isHighlighted()); - - QTest::keyClick(window, Qt::Key_Escape); - QTRY_COMPARE(visibleSpy.size(), 6); - QVERIFY(!menu->isVisible()); -} - -// QTBUG-70181 -void tst_QQuickMenu::disabledMenuItemKeyNavigation() -{ - if (!hasWindowActivation()) - QSKIP("Window activation is not supported"); - - if (QGuiApplication::styleHints()->tabFocusBehavior() != Qt::TabFocusAllControls) - QSKIP("This platform only allows tab focus for text controls"); - - QQuickControlsApplicationHelper helper(this, QLatin1String("disabledMenuItemKeyNavigation.qml")); - QVERIFY2(helper.ready, helper.failureMessage()); - - QQuickApplicationWindow *window = helper.appWindow; - centerOnScreen(window); - moveMouseAway(window); - window->show(); - window->requestActivate(); - QVERIFY(QTest::qWaitForWindowActive(window)); - QVERIFY(QGuiApplication::focusWindow() == window); - - QQuickMenu *menu = window->property("menu").value<QQuickMenu*>(); - QCOMPARE(menu->currentIndex(), -1); - QCOMPARE(menu->contentItem()->property("currentIndex"), QVariant(-1)); - - QQuickMenuItem *firstItem = qobject_cast<QQuickMenuItem *>(menu->itemAt(0)); - QVERIFY(firstItem); - - QQuickMenuItem *secondItem = qobject_cast<QQuickMenuItem *>(menu->itemAt(1)); - QVERIFY(secondItem); - - QQuickMenuItem *thirdItem = qobject_cast<QQuickMenuItem *>(menu->itemAt(2)); - QVERIFY(thirdItem); - - menu->setFocus(true); - menu->open(); - QVERIFY(menu->isVisible()); - QTRY_VERIFY(menu->isOpened()); - QVERIFY(!firstItem->hasActiveFocus()); - QVERIFY(!firstItem->property("highlighted").toBool()); - QCOMPARE(menu->currentIndex(), -1); - - QTest::keyClick(window, Qt::Key_Tab); - QVERIFY(firstItem->hasActiveFocus()); - QVERIFY(firstItem->hasVisualFocus()); - QVERIFY(firstItem->isHighlighted()); - QCOMPARE(firstItem->focusReason(), Qt::TabFocusReason); - QCOMPARE(menu->currentIndex(), 0); - - // Shouldn't be possible to give focus to a disabled menu item. - QTest::keyClick(window, Qt::Key_Down); - QVERIFY(!secondItem->hasActiveFocus()); - QVERIFY(!secondItem->hasVisualFocus()); - QVERIFY(!secondItem->isHighlighted()); - QVERIFY(thirdItem->hasActiveFocus()); - QVERIFY(thirdItem->hasVisualFocus()); - QVERIFY(thirdItem->isHighlighted()); - QCOMPARE(thirdItem->focusReason(), Qt::TabFocusReason); - - QTest::keyClick(window, Qt::Key_Up); - QVERIFY(firstItem->hasActiveFocus()); - QVERIFY(firstItem->hasVisualFocus()); - QVERIFY(firstItem->isHighlighted()); - QCOMPARE(firstItem->focusReason(), Qt::BacktabFocusReason); - - QTest::keyClick(window, Qt::Key_Escape); - QTRY_VERIFY(!menu->isVisible()); -} - -void tst_QQuickMenu::mnemonics() -{ - if (!hasWindowActivation()) - QSKIP("Window activation is not supported"); - -#ifdef Q_OS_MACOS - QSKIP("Mnemonics are not used on macOS"); -#endif - - QQuickControlsApplicationHelper helper(this, QLatin1String("mnemonics.qml")); - QVERIFY2(helper.ready, helper.failureMessage()); - - QQuickWindow *window = helper.window; - window->show(); - window->requestActivate(); - QVERIFY(QTest::qWaitForWindowActive(window)); - - MnemonicKeySimulator keySim(window); - - QQuickMenu *menu = window->property("menu").value<QQuickMenu *>(); - QQuickAction *action = window->property("action").value<QQuickAction *>(); - QQuickMenuItem *menuItem = window->property("menuItem").value<QQuickMenuItem *>(); - QQuickMenu *subMenu = window->property("subMenu").value<QQuickMenu *>(); - QQuickMenuItem *subMenuItem = window->property("subMenuItem").value<QQuickMenuItem *>(); - QVERIFY(menu && action && menuItem && subMenu && subMenuItem); - - keySim.press(Qt::Key_Alt); - menu->open(); - QTRY_VERIFY(menu->isOpened()); - - QSignalSpy actionSpy(action, &QQuickAction::triggered); - QVERIFY(actionSpy.isValid()); - keySim.click(Qt::Key_A); // "&Action" - QCOMPARE(actionSpy.size(), 1); - - menu->open(); - QTRY_VERIFY(menu->isOpened()); - - QSignalSpy menuItemSpy(menuItem, &QQuickMenuItem::triggered); - QVERIFY(menuItemSpy.isValid()); - keySim.click(Qt::Key_I); // "Menu &Item" - keySim.release(Qt::Key_Alt); - QCOMPARE(menuItemSpy.size(), 1); - - keySim.press(Qt::Key_Alt); - menu->open(); - QTRY_VERIFY(menu->isOpened()); - - keySim.click(Qt::Key_M); // "Sub &Menu" - QTRY_VERIFY(subMenu->isOpened()); - - QSignalSpy subMenuItemSpy(subMenuItem, &QQuickMenuItem::triggered); - QVERIFY(subMenuItemSpy.isValid()); - keySim.click(Qt::Key_S); // "&Sub Menu Item" - keySim.release(Qt::Key_Alt); - QCOMPARE(subMenuItemSpy.size(), 1); -} - -void tst_QQuickMenu::menuButton() -{ - if (!hasWindowActivation()) - QSKIP("Window activation is not supported"); - - if (QGuiApplication::styleHints()->tabFocusBehavior() != Qt::TabFocusAllControls) - QSKIP("This platform only allows tab focus for text controls"); - - QQuickControlsApplicationHelper helper(this, QLatin1String("applicationwindow.qml")); - QVERIFY2(helper.ready, helper.failureMessage()); - - QQuickApplicationWindow *window = helper.appWindow; - window->show(); - window->requestActivate(); - QVERIFY(QTest::qWaitForWindowActive(window)); - QVERIFY(QGuiApplication::focusWindow() == window); - - QQuickMenu *menu = window->property("menu").value<QQuickMenu*>(); - QQuickButton *menuButton = window->property("menuButton").value<QQuickButton*>(); - QSignalSpy visibleSpy(menu, SIGNAL(visibleChanged())); - - menuButton->setVisible(true); - QTest::mouseClick(window, Qt::LeftButton, Qt::NoModifier, - menuButton->mapToScene(QPointF(menuButton->width() / 2, menuButton->height() / 2)).toPoint()); - QCOMPARE(visibleSpy.size(), 1); - QVERIFY(menu->isVisible()); - QTRY_VERIFY(menu->isOpened()); - - QTest::keyClick(window, Qt::Key_Tab); - QQuickItem *firstItem = menu->itemAt(0); - QVERIFY(firstItem->hasActiveFocus()); -} - -void tst_QQuickMenu::addItem() -{ - QQuickControlsApplicationHelper helper(this, QLatin1String("addItem.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(); - QVERIFY(menu->isVisible()); - - QQuickItem *menuItem = menu->itemAt(0); - QVERIFY(menuItem); - QTRY_VERIFY(!QQuickItemPrivate::get(menuItem)->culled); // QTBUG-53262 - - QTest::mouseClick(window, Qt::LeftButton, Qt::NoModifier, - menuItem->mapToScene(QPointF(menuItem->width() / 2, menuItem->height() / 2)).toPoint()); - QTRY_VERIFY(!menu->isVisible()); -} - -void tst_QQuickMenu::menuSeparator() -{ - if (!hasWindowActivation()) - QSKIP("Window activation is not supported"); - - QQuickControlsApplicationHelper helper(this, QLatin1String("menuSeparator.qml")); - QVERIFY2(helper.ready, helper.failureMessage()); - QQuickWindow *window = helper.window; - centerOnScreen(window); - moveMouseAway(window); - window->show(); - QVERIFY(QTest::qWaitForWindowActive(window)); - - QQuickMenu *menu = window->property("menu").value<QQuickMenu*>(); - QVERIFY(menu); - menu->open(); - QVERIFY(menu->isVisible()); - - QQuickMenuItem *newMenuItem = qobject_cast<QQuickMenuItem*>(menu->itemAt(0)); - QVERIFY(newMenuItem); - QCOMPARE(newMenuItem->text(), QStringLiteral("New")); - - QQuickMenuSeparator *menuSeparator = qobject_cast<QQuickMenuSeparator*>(menu->itemAt(1)); - QVERIFY(menuSeparator); - - QQuickMenuItem *saveMenuItem = qobject_cast<QQuickMenuItem*>(menu->itemAt(2)); - QVERIFY(saveMenuItem); - QCOMPARE(saveMenuItem->text(), QStringLiteral("Save")); - QTRY_VERIFY(!QQuickItemPrivate::get(saveMenuItem)->culled); // QTBUG-53262 - QTRY_VERIFY(menu->isOpened()); - - // Clicking on items should still close the menu. - QTest::mouseClick(window, Qt::LeftButton, Qt::NoModifier, - newMenuItem->mapToScene(QPointF(newMenuItem->width() / 2, newMenuItem->height() / 2)).toPoint()); - QTRY_VERIFY(!menu->isVisible()); - - menu->open(); - QTRY_VERIFY(menu->isOpened()); - - // Clicking on a separator shouldn't close the menu. - QTest::mouseClick(window, Qt::LeftButton, Qt::NoModifier, - menuSeparator->mapToScene(QPointF(menuSeparator->width() / 2, menuSeparator->height() / 2)).toPoint()); - QVERIFY(menu->isVisible()); - - // Clicking on items should still close the menu. - QTest::mouseClick(window, Qt::LeftButton, Qt::NoModifier, - saveMenuItem->mapToScene(QPointF(saveMenuItem->width() / 2, saveMenuItem->height() / 2)).toPoint()); - QTRY_VERIFY(!menu->isVisible()); - - moveMouseAway(window); - - menu->open(); - QVERIFY(menu->isVisible()); - QTRY_VERIFY(menu->isOpened()); - - // Key navigation skips separators - QTest::keyClick(window, Qt::Key_Down); - QVERIFY(newMenuItem->hasActiveFocus()); - QVERIFY(newMenuItem->hasVisualFocus()); - QCOMPARE(newMenuItem->focusReason(), Qt::TabFocusReason); - - QTest::keyClick(window, Qt::Key_Down); - QVERIFY(saveMenuItem->hasActiveFocus()); - QVERIFY(saveMenuItem->hasVisualFocus()); - QCOMPARE(saveMenuItem->focusReason(), Qt::TabFocusReason); - - QTest::keyClick(window, Qt::Key_Down); - QVERIFY(saveMenuItem->hasActiveFocus()); - QVERIFY(saveMenuItem->hasVisualFocus()); - QCOMPARE(saveMenuItem->focusReason(), Qt::TabFocusReason); - - QTest::keyClick(window, Qt::Key_Up); - QVERIFY(newMenuItem->hasActiveFocus()); - QVERIFY(newMenuItem->hasVisualFocus()); - QCOMPARE(newMenuItem->focusReason(), Qt::BacktabFocusReason); - - QTest::keyClick(window, Qt::Key_Up); - QVERIFY(newMenuItem->hasActiveFocus()); - QVERIFY(newMenuItem->hasVisualFocus()); - QCOMPARE(newMenuItem->focusReason(), Qt::BacktabFocusReason); -} - -void tst_QQuickMenu::repeater() -{ - QQuickControlsApplicationHelper helper(this, QLatin1String("repeater.qml")); - QVERIFY2(helper.ready, helper.failureMessage()); - QQuickWindow *window = helper.window; - window->show(); - QVERIFY(QTest::qWaitForWindowExposed(window)); - - QQuickMenu *menu = window->property("menu").value<QQuickMenu*>(); - QVERIFY(menu); - menu->open(); - QVERIFY(menu->isVisible()); - - QObject *repeater = window->property("repeater").value<QObject*>(); - QVERIFY(repeater); - - int count = repeater->property("count").toInt(); - QCOMPARE(count, 5); - - for (int i = 0; i < count; ++i) { - QQuickItem *item = menu->itemAt(i); - QVERIFY(item); - QCOMPARE(item->property("idx").toInt(), i); - - QQuickItem *repeaterItem = nullptr; - QVERIFY(QMetaObject::invokeMethod(repeater, "itemAt", Q_RETURN_ARG(QQuickItem*, repeaterItem), Q_ARG(int, i))); - QCOMPARE(item, repeaterItem); - } - - repeater->setProperty("model", 3); - - count = repeater->property("count").toInt(); - QCOMPARE(count, 3); - - for (int i = 0; i < count; ++i) { - QQuickItem *item = menu->itemAt(i); - QVERIFY(item); - QCOMPARE(item->property("idx").toInt(), i); - - QQuickItem *repeaterItem = nullptr; - QVERIFY(QMetaObject::invokeMethod(repeater, "itemAt", Q_RETURN_ARG(QQuickItem*, repeaterItem), Q_ARG(int, i))); - QCOMPARE(item, repeaterItem); - } -} - -void tst_QQuickMenu::order() -{ - QQuickControlsApplicationHelper helper(this, QLatin1String("order.qml")); - QVERIFY2(helper.ready, helper.failureMessage()); - QQuickWindow *window = helper.window; - window->show(); - QVERIFY(QTest::qWaitForWindowExposed(window)); - - QQuickMenu *menu = window->property("menu").value<QQuickMenu*>(); - QVERIFY(menu); - menu->open(); - QVERIFY(menu->isVisible()); - - const QStringList texts = {"dynamic_0", "static_1", "repeated_2", "repeated_3", "static_4", "dynamic_5", "dynamic_6"}; - - for (int i = 0; i < texts.size(); ++i) { - QQuickItem *item = menu->itemAt(i); - QVERIFY(item); - QCOMPARE(item->property("text").toString(), texts.at(i)); - } -} - -#if QT_CONFIG(cursor) -void tst_QQuickMenu::popup() -{ -#if defined(Q_OS_ANDROID) - QSKIP("Setting cursor position is not supported on Android"); -#endif - if (QGuiApplication::platformName().startsWith(QLatin1String("wayland"))) - QSKIP("Setting cursor position is not supported on Wayland"); - - // Try moving the cursor from the current position - // Skip if it fails since the test relies on moving the cursor - const QPoint point = QCursor::pos() + QPoint(1, 1); - QCursor::setPos(point); - if (!QTest::qWaitFor([point]{ return QCursor::pos() == point; })) - QSKIP("Setting cursor position is not supported on this platform"); - - QQuickControlsApplicationHelper helper(this, QLatin1String("popup.qml")); - QVERIFY2(helper.ready, helper.failureMessage()); - QQuickApplicationWindow *window = helper.appWindow; - centerOnScreen(window); - moveMouseAway(window); - window->show(); - QVERIFY(QTest::qWaitForWindowExposed(window)); - - QQuickMenu *menu = window->property("menu").value<QQuickMenu *>(); - QVERIFY(menu); - - QQuickMenuItem *menuItem1 = window->property("menuItem1").value<QQuickMenuItem *>(); - QVERIFY(menuItem1); - - QQuickMenuItem *menuItem2 = window->property("menuItem2").value<QQuickMenuItem *>(); - QVERIFY(menuItem2); - - QQuickMenuItem *menuItem3 = window->property("menuItem3").value<QQuickMenuItem *>(); - QVERIFY(menuItem3); - - QQuickItem *button = window->property("button").value<QQuickItem *>(); - QVERIFY(button); - - QPoint oldCursorPos = QCursor::pos(); - QPoint cursorPos = window->mapToGlobal(QPoint(11, 22)); - QCursor::setPos(cursorPos); - QTRY_COMPARE(QCursor::pos(), cursorPos); - - QVERIFY(QMetaObject::invokeMethod(window, "popupAtCursor")); - QCOMPARE(menu->parentItem(), window->contentItem()); - QCOMPARE(menu->currentIndex(), -1); - QCOMPARE(menu->contentItem()->property("currentIndex").toInt(), -1); - const qreal elevenOrLeftMargin = qMax(qreal(11), menu->leftMargin()); - const qreal twentyTwoOrTopMargin = qMax(qreal(22), menu->topMargin()); - // If the Menu has large margins, it may be moved to stay within them. - // QTBUG-75503: QTRY_COMPARE doesn't use qFuzzyCompare() in all cases, - // meaning a lot of these comparisons could trigger a 10 second wait; - // use QTRY_VERIFY and qFuzzyCompare instead. - QTRY_VERIFY(qFuzzyCompare(menu->x(), elevenOrLeftMargin)); - QTRY_VERIFY(qFuzzyCompare(menu->y(), twentyTwoOrTopMargin)); - menu->close(); - - QVERIFY(QMetaObject::invokeMethod(window, "popupAtPos", Q_ARG(QVariant, QPointF(33, 44)))); - QCOMPARE(menu->parentItem(), window->contentItem()); - QCOMPARE(menu->currentIndex(), -1); - QCOMPARE(menu->contentItem()->property("currentIndex").toInt(), -1); - QTRY_VERIFY(qFuzzyCompare(menu->x(), qMax(qreal(33), menu->leftMargin()))); - QTRY_VERIFY(qFuzzyCompare(menu->y(), qMax(qreal(44), menu->topMargin()))); - menu->close(); - - QVERIFY(QMetaObject::invokeMethod(window, "popupAtCoord", Q_ARG(QVariant, 55), Q_ARG(QVariant, 66))); - QCOMPARE(menu->parentItem(), window->contentItem()); - QCOMPARE(menu->currentIndex(), -1); - QCOMPARE(menu->contentItem()->property("currentIndex").toInt(), -1); - QTRY_VERIFY(qFuzzyCompare(menu->x(), qMax(qreal(55), menu->leftMargin()))); - QTRY_VERIFY(qFuzzyCompare(menu->y(), qMax(qreal(66), menu->topMargin()))); - menu->close(); - - menu->setParentItem(nullptr); - QVERIFY(QMetaObject::invokeMethod(window, "popupAtParentCursor", Q_ARG(QVariant, QVariant::fromValue(button)))); - QCOMPARE(menu->parentItem(), button); - QCOMPARE(menu->currentIndex(), -1); - QCOMPARE(menu->contentItem()->property("currentIndex").toInt(), -1); - QTRY_VERIFY(qFuzzyCompare(menu->x(), button->mapFromScene(QPointF(elevenOrLeftMargin, twentyTwoOrTopMargin)).x())); - QTRY_VERIFY(qFuzzyCompare(menu->y(), button->mapFromScene(QPointF(elevenOrLeftMargin, twentyTwoOrTopMargin)).y())); - menu->close(); - - menu->setParentItem(nullptr); - QVERIFY(QMetaObject::invokeMethod(window, "popupAtParentPos", Q_ARG(QVariant, QVariant::fromValue(button)), Q_ARG(QVariant, QPointF(-11, -22)))); - QCOMPARE(menu->parentItem(), button); - QCOMPARE(menu->currentIndex(), -1); - QCOMPARE(menu->contentItem()->property("currentIndex").toInt(), -1); - // Don't need to worry about margins here because we're opening close - // to the center of the window. - QTRY_VERIFY(qFuzzyCompare(menu->x(), -11)); - QTRY_VERIFY(qFuzzyCompare(menu->y(), -22)); - QCOMPARE(menu->popupItem()->position(), button->mapToScene(QPointF(-11, -22))); - menu->close(); - - menu->setParentItem(nullptr); - QVERIFY(QMetaObject::invokeMethod(window, "popupAtParentCoord", Q_ARG(QVariant, QVariant::fromValue(button)), Q_ARG(QVariant, -33), Q_ARG(QVariant, -44))); - QCOMPARE(menu->parentItem(), button); - QCOMPARE(menu->currentIndex(), -1); - QCOMPARE(menu->contentItem()->property("currentIndex").toInt(), -1); - QTRY_VERIFY(qFuzzyCompare(menu->x(), -33)); - QTRY_VERIFY(qFuzzyCompare(menu->y(), -44)); - QCOMPARE(menu->popupItem()->position(), button->mapToScene(QPointF(-33, -44))); - menu->close(); - - const qreal twelveOrLeftMargin = qMax(qreal(12), menu->leftMargin()); - cursorPos = window->mapToGlobal(QPoint(twelveOrLeftMargin, window->height() / 2)); - QCursor::setPos(cursorPos); - QTRY_COMPARE(QCursor::pos(), cursorPos); - - const QList<QQuickMenuItem *> menuItems = QList<QQuickMenuItem *>() << menuItem1 << menuItem2 << menuItem3; - for (QQuickMenuItem *menuItem : menuItems) { - menu->resetParentItem(); - - QVERIFY(QMetaObject::invokeMethod(window, "popupItemAtCursor", Q_ARG(QVariant, QVariant::fromValue(menuItem)))); - QCOMPARE(menu->currentIndex(), menuItems.indexOf(menuItem)); - QCOMPARE(menu->contentItem()->property("currentIndex").toInt(), menuItems.indexOf(menuItem)); - QTRY_VERIFY(qFuzzyCompare(menu->x(), twelveOrLeftMargin)); - QTRY_VERIFY(qFuzzyCompare(menu->y(), window->height() / 2 - menu->topPadding() - menuItem->y())); - menu->close(); - - QVERIFY(QMetaObject::invokeMethod(window, "popupItemAtPos", Q_ARG(QVariant, QPointF(33, window->height() / 3)), Q_ARG(QVariant, QVariant::fromValue(menuItem)))); - QCOMPARE(menu->currentIndex(), menuItems.indexOf(menuItem)); - QCOMPARE(menu->contentItem()->property("currentIndex").toInt(), menuItems.indexOf(menuItem)); - QTRY_VERIFY(qFuzzyCompare(menu->x(), 33)); - QTRY_VERIFY(qFuzzyCompare(menu->y(), window->height() / 3 - menu->topPadding() - menuItem->y())); - menu->close(); - - QVERIFY(QMetaObject::invokeMethod(window, "popupItemAtCoord", Q_ARG(QVariant, 55), Q_ARG(QVariant, window->height() / 3 * 2), Q_ARG(QVariant, QVariant::fromValue(menuItem)))); - QCOMPARE(menu->currentIndex(), menuItems.indexOf(menuItem)); - QCOMPARE(menu->contentItem()->property("currentIndex").toInt(), menuItems.indexOf(menuItem)); - QTRY_VERIFY(qFuzzyCompare(menu->x(), 55)); - QTRY_COMPARE_WITH_TIMEOUT(menu->y(), window->height() / 3 * 2 - menu->topPadding() - menuItem->y(), 500); - menu->close(); - - menu->setParentItem(nullptr); - QVERIFY(QMetaObject::invokeMethod(window, "popupItemAtParentCursor", Q_ARG(QVariant, QVariant::fromValue(button)), Q_ARG(QVariant, QVariant::fromValue(menuItem)))); - QCOMPARE(menu->parentItem(), button); - QCOMPARE(menu->currentIndex(), menuItems.indexOf(menuItem)); - QCOMPARE(menu->contentItem()->property("currentIndex").toInt(), menuItems.indexOf(menuItem)); - QTRY_VERIFY(qFuzzyCompare(menu->x(), button->mapFromScene(QPoint(twelveOrLeftMargin, window->height() / 2)).x())); - QTRY_VERIFY(qFuzzyCompare(menu->y(), button->mapFromScene(QPoint(twelveOrLeftMargin, window->height() / 2)).y() - menu->topPadding() - menuItem->y())); - menu->close(); - - menu->setParentItem(nullptr); - QVERIFY(QMetaObject::invokeMethod(window, "popupItemAtParentPos", Q_ARG(QVariant, QVariant::fromValue(button)), Q_ARG(QVariant, QPointF(-11, -22)), Q_ARG(QVariant, QVariant::fromValue(menuItem)))); - QCOMPARE(menu->parentItem(), button); - QCOMPARE(menu->currentIndex(), menuItems.indexOf(menuItem)); - QCOMPARE(menu->contentItem()->property("currentIndex").toInt(), menuItems.indexOf(menuItem)); - QTRY_VERIFY(qFuzzyCompare(menu->x(), -11)); - QTRY_VERIFY(qFuzzyCompare(menu->y(), -22 - menu->topPadding() - menuItem->y())); - QCOMPARE(menu->popupItem()->position(), button->mapToScene(QPointF(-11, -22 - menu->topPadding() - menuItem->y()))); - menu->close(); - - menu->setParentItem(nullptr); - QVERIFY(QMetaObject::invokeMethod(window, "popupItemAtParentCoord", Q_ARG(QVariant, QVariant::fromValue(button)), Q_ARG(QVariant, -33), Q_ARG(QVariant, -44), Q_ARG(QVariant, QVariant::fromValue(menuItem)))); - QCOMPARE(menu->parentItem(), button); - QCOMPARE(menu->currentIndex(), menuItems.indexOf(menuItem)); - QCOMPARE(menu->contentItem()->property("currentIndex").toInt(), menuItems.indexOf(menuItem)); - QTRY_VERIFY(qFuzzyCompare(menu->x(), -33)); - QTRY_VERIFY(qFuzzyCompare(menu->y(), -44 - menu->topPadding() - menuItem->y())); - QCOMPARE(menu->popupItem()->position(), button->mapToScene(QPointF(-33, -44 - menu->topPadding() - menuItem->y()))); - menu->close(); - } - - QCursor::setPos(oldCursorPos); - QTRY_COMPARE(QCursor::pos(), oldCursorPos); -} -#endif // QT_CONFIG(cursor) - -void tst_QQuickMenu::actions() -{ - QQuickControlsApplicationHelper helper(this, QLatin1String("actions.qml")); - QVERIFY2(helper.ready, helper.failureMessage()); - QQuickWindow *window = helper.window; - window->show(); - QVERIFY(QTest::qWaitForWindowExposed(window)); - - QQuickMenu *menu = window->property("menu").value<QQuickMenu *>(); - QVERIFY(menu); - - QPointer<QQuickAction> action1 = menu->actionAt(0); - QVERIFY(!action1.isNull()); - - QPointer<QQuickAction> action3 = menu->actionAt(2); - QVERIFY(!action3.isNull()); - - QVERIFY(!menu->actionAt(1)); - QVERIFY(!menu->actionAt(3)); - - QPointer<QQuickMenuItem> menuItem1 = qobject_cast<QQuickMenuItem *>(menu->itemAt(0)); - QVERIFY(!menuItem1.isNull()); - QCOMPARE(menuItem1->action(), action1.data()); - QCOMPARE(menuItem1->text(), "action1"); - - QPointer<QQuickMenuItem> menuItem2 = qobject_cast<QQuickMenuItem *>(menu->itemAt(1)); - QVERIFY(!menuItem2.isNull()); - QVERIFY(!menuItem2->action()); - QCOMPARE(menuItem2->text(), "menuitem2"); - - QPointer<QQuickMenuItem> menuItem3 = qobject_cast<QQuickMenuItem *>(menu->itemAt(2)); - QVERIFY(!menuItem3.isNull()); - QCOMPARE(menuItem3->action(), action3.data()); - QCOMPARE(menuItem3->text(), "action3"); - - QPointer<QQuickMenuItem> menuItem4 = qobject_cast<QQuickMenuItem *>(menu->itemAt(3)); - QVERIFY(!menuItem4.isNull()); - QVERIFY(!menuItem4->action()); - QCOMPARE(menuItem4->text(), "menuitem4"); - - // takeAction(int) does not destroy the action, but does destroy the respective item - QCOMPARE(menu->takeAction(0), action1.data()); - QVERIFY(!menu->itemAt(3)); - QCoreApplication::sendPostedEvents(action1, QEvent::DeferredDelete); - QVERIFY(!action1.isNull()); - QCoreApplication::sendPostedEvents(menuItem1, QEvent::DeferredDelete); - QVERIFY(menuItem1.isNull()); - - // takeAction(int) does not destroy an item that doesn't have an action - QVERIFY(!menuItem2->subMenu()); - QVERIFY(!menu->takeAction(0)); - QCoreApplication::sendPostedEvents(menuItem2, QEvent::DeferredDelete); - QVERIFY(!menuItem2.isNull()); - - // addAction(Action) re-creates the respective item in the menu - menu->addAction(action1); - menuItem1 = qobject_cast<QQuickMenuItem *>(menu->itemAt(3)); - QVERIFY(!menuItem1.isNull()); - QCOMPARE(menuItem1->action(), action1.data()); - - // removeAction(Action) destroys both the action and the respective item - menu->removeAction(action1); - QVERIFY(!menu->itemAt(3)); - QCoreApplication::sendPostedEvents(action1, QEvent::DeferredDelete); - QVERIFY(action1.isNull()); - QCoreApplication::sendPostedEvents(menuItem1, QEvent::DeferredDelete); - QVERIFY(menuItem1.isNull()); -} - -#if QT_CONFIG(shortcut) -void tst_QQuickMenu::actionShortcuts() -{ - if (!hasWindowActivation()) - QSKIP("Window activation is not supported"); - - QQuickControlsApplicationHelper helper(this, QLatin1String("actionShortcuts.qml")); - QVERIFY2(helper.ready, helper.failureMessage()); - QQuickWindow *window = helper.window; - window->show(); - QVERIFY(QTest::qWaitForWindowActive(window)); - - // Try the menu's shortcut. - QQuickMenu *menu = window->property("menu").value<QQuickMenu *>(); - QVERIFY(menu); - QPointer<QQuickAction> action1 = menu->actionAt(0); - QVERIFY(action1); - QCOMPARE(action1->shortcut(), QKeySequence(Qt::Key_A)); - - QSignalSpy action1TriggeredSpy(action1, SIGNAL(triggered())); - QVERIFY(action1TriggeredSpy.isValid()); - - QTest::keyClick(window, Qt::Key_A); - QCOMPARE(action1TriggeredSpy.size(), 1); - - // Try the sub-menu. - QQuickMenu *subMenu = window->property("subMenu").value<QQuickMenu *>(); - QVERIFY(subMenu); - QPointer<QQuickAction> subMenuAction1 = subMenu->actionAt(0); - QVERIFY(subMenuAction1); - QCOMPARE(subMenuAction1->shortcut(), QKeySequence(Qt::Key_B)); - - QSignalSpy subMenuAction1TriggeredSpy(subMenuAction1, SIGNAL(triggered())); - QVERIFY(subMenuAction1TriggeredSpy.isValid()); - - QTest::keyClick(window, Qt::Key_B); - QCOMPARE(subMenuAction1TriggeredSpy.size(), 1); - - // Try the button menu. - QQuickMenu *buttonMenu = window->property("buttonMenu").value<QQuickMenu *>(); - QVERIFY(buttonMenu); - QPointer<QQuickAction> buttonMenuAction1 = buttonMenu->actionAt(0); - QVERIFY(buttonMenuAction1); - QCOMPARE(buttonMenuAction1->shortcut(), QKeySequence(Qt::Key_C)); - - QSignalSpy buttonMenuAction1TriggeredSpy(buttonMenuAction1, SIGNAL(triggered())); - QVERIFY(buttonMenuAction1TriggeredSpy.isValid()); - - QTest::keyClick(window, Qt::Key_C); - QCOMPARE(buttonMenuAction1TriggeredSpy.size(), 1); -} -#endif - -void tst_QQuickMenu::removeTakeItem() -{ - QQuickControlsApplicationHelper helper(this, QLatin1String("removeTakeItem.qml")); - QVERIFY2(helper.ready, helper.failureMessage()); - QQuickWindow *window = helper.window; - window->show(); - QVERIFY(QTest::qWaitForWindowExposed(window)); - - QQuickMenu *menu = window->property("menu").value<QQuickMenu *>(); - QVERIFY(menu); - - QPointer<QQuickMenuItem> menuItem1 = window->property("menuItem1").value<QQuickMenuItem *>(); - QVERIFY(!menuItem1.isNull()); - QCOMPARE(menuItem1->menu(), menu); - - QPointer<QQuickMenuItem> menuItem2 = window->property("menuItem2").value<QQuickMenuItem *>(); - QVERIFY(!menuItem2.isNull()); - QCOMPARE(menuItem2->menu(), menu); - - QPointer<QQuickMenuItem> menuItem3 = window->property("menuItem3").value<QQuickMenuItem *>(); - QVERIFY(!menuItem3.isNull()); - QCOMPARE(menuItem3->menu(), menu); - - // takeItem(int) does not destroy - QVariant ret; - QVERIFY(QMetaObject::invokeMethod(window, "takeSecondItem", Q_RETURN_ARG(QVariant, ret))); - QCOMPARE(ret.value<QQuickMenuItem *>(), menuItem2); - QVERIFY(!menuItem2->menu()); - QCoreApplication::sendPostedEvents(menuItem2, QEvent::DeferredDelete); - QVERIFY(!menuItem2.isNull()); - - // removeItem(Item) destroys - QVERIFY(QMetaObject::invokeMethod(window, "removeFirstItem")); - QVERIFY(!menuItem1->menu()); - QCoreApplication::sendPostedEvents(menuItem1, QEvent::DeferredDelete); - QVERIFY(menuItem1.isNull()); - - // removeItem(null) must not call removeItem(0) - QVERIFY(QMetaObject::invokeMethod(window, "removeNullItem")); - QCOMPARE(menuItem3->menu(), menu); - QCoreApplication::sendPostedEvents(menuItem3, QEvent::DeferredDelete); - QVERIFY(!menuItem3.isNull()); -} - -void tst_QQuickMenu::subMenuMouse_data() -{ - QTest::addColumn<bool>("cascade"); - - QTest::newRow("cascading") << true; - QTest::newRow("non-cascading") << false; -} - -void tst_QQuickMenu::subMenuMouse() -{ - if ((QGuiApplication::platformName() == QLatin1String("offscreen")) - || (QGuiApplication::platformName() == QLatin1String("minimal"))) - QSKIP("Mouse hovering not functional on offscreen/minimal platforms"); - - QFETCH(bool, cascade); - - QQuickControlsApplicationHelper helper(this, QLatin1String("subMenus.qml")); - QVERIFY2(helper.ready, helper.failureMessage()); - QQuickApplicationWindow *window = helper.appWindow; - centerOnScreen(window); - moveMouseAway(window); - window->show(); - QVERIFY(QTest::qWaitForWindowExposed(window)); - - QQuickMenu *mainMenu = window->property("mainMenu").value<QQuickMenu *>(); - QVERIFY(mainMenu); - mainMenu->setCascade(cascade); - QCOMPARE(mainMenu->cascade(), cascade); - - QQuickMenu *subMenu1 = window->property("subMenu1").value<QQuickMenu *>(); - QVERIFY(subMenu1); - subMenu1->setCascade(cascade); - QCOMPARE(subMenu1->cascade(), cascade); - - QQuickMenu *subMenu2 = window->property("subMenu2").value<QQuickMenu *>(); - QVERIFY(subMenu2); - subMenu2->setCascade(cascade); - QCOMPARE(subMenu2->cascade(), cascade); - - QQuickMenu *subSubMenu1 = window->property("subSubMenu1").value<QQuickMenu *>(); - QVERIFY(subSubMenu1); - subSubMenu1->setCascade(cascade); - QCOMPARE(subSubMenu1->cascade(), cascade); - - mainMenu->open(); - QVERIFY(mainMenu->isVisible()); - QTRY_VERIFY(mainMenu->isOpened()); - QVERIFY(!subMenu1->isVisible()); - QVERIFY(!subMenu2->isVisible()); - QVERIFY(!subSubMenu1->isVisible()); - - // open the sub-menu with mouse click - QQuickMenuItem *subMenu1Item = qobject_cast<QQuickMenuItem *>(mainMenu->itemAt(1)); - QVERIFY(subMenu1Item); - QCOMPARE(subMenu1Item->subMenu(), subMenu1); - QTest::mouseClick(window, Qt::LeftButton, Qt::NoModifier, subMenu1Item->mapToScene(QPoint(1, 1)).toPoint()); - QTRY_COMPARE(mainMenu->isVisible(), cascade); - QVERIFY(subMenu1->isVisible()); - QTRY_VERIFY(subMenu1->isOpened()); - QVERIFY(!subMenu2->isVisible()); - QVERIFY(!subSubMenu1->isVisible()); - - // on Android mouse hover will not open and close sub-menus -#ifndef Q_OS_ANDROID - // open the cascading sub-sub-menu with mouse hover - QQuickMenuItem *subSubMenu1Item = qobject_cast<QQuickMenuItem *>(subMenu1->itemAt(2)); - QVERIFY(subSubMenu1Item); - QCOMPARE(subSubMenu1Item->subMenu(), subSubMenu1); - QTest::mouseMove(window, subSubMenu1Item->mapToScene(QPoint(1, 1)).toPoint()); - QCOMPARE(mainMenu->isVisible(), cascade); - QVERIFY(subMenu1->isVisible()); - QVERIFY(!subMenu2->isVisible()); - QVERIFY(!subSubMenu1->isVisible()); - if (cascade) { - QTRY_VERIFY(subSubMenu1->isVisible()); - QTRY_VERIFY(subSubMenu1->isOpened()); - } - - // close the sub-sub-menu with mouse hover over another parent menu item - QQuickMenuItem *subMenuItem1 = qobject_cast<QQuickMenuItem *>(subMenu1->itemAt(0)); - QVERIFY(subMenuItem1); - QVERIFY(!subMenuItem1->subMenu()); - QTest::mouseMove(window, subMenuItem1->mapToScene(QPoint(1, 1)).toPoint()); - QCOMPARE(mainMenu->isVisible(), cascade); - QVERIFY(subMenu1->isVisible()); - QVERIFY(!subMenu2->isVisible()); - QTRY_VERIFY(!subSubMenu1->isVisible()); - - // re-open the sub-sub-menu with mouse hover - QTest::mouseMove(window, subSubMenu1Item->mapToScene(QPoint(1, 1)).toPoint()); - QCOMPARE(mainMenu->isVisible(), cascade); - QVERIFY(subMenu1->isVisible()); - QVERIFY(!subMenu2->isVisible()); - if (!cascade) { - QVERIFY(!subSubMenu1->isVisible()); - } else { - QTRY_VERIFY(subSubMenu1->isVisible()); - QTRY_VERIFY(subSubMenu1->isOpened()); - } - - // close sub-menu and sub-sub-menu with mouse hover in the main menu - QQuickMenuItem *mainMenuItem1 = qobject_cast<QQuickMenuItem *>(mainMenu->itemAt(0)); - QVERIFY(mainMenuItem1); - QTest::mouseMove(window, mainMenuItem1->mapToScene(QPoint(1, 1)).toPoint()); - QCOMPARE(mainMenu->isVisible(), cascade); - QTRY_COMPARE(subMenu1->isVisible(), !cascade); - QVERIFY(!subMenu2->isVisible()); - QVERIFY(!subSubMenu1->isVisible()); -#else - QQuickMenuItem *mainMenuItem1 = qobject_cast<QQuickMenuItem *>(mainMenu->itemAt(0)); - QVERIFY(mainMenuItem1); -#endif // !Q_OS_ANDROID - - // close all menus by click triggering an item - QTest::mouseClick(window, Qt::LeftButton, Qt::NoModifier, mainMenuItem1->mapToScene(QPoint(1, 1)).toPoint()); - QTRY_VERIFY(!mainMenu->isVisible()); - QTRY_VERIFY(!subMenu1->isVisible()); - QVERIFY(!subMenu2->isVisible()); - QVERIFY(!subSubMenu1->isVisible()); -} - -void tst_QQuickMenu::subMenuDisabledMouse_data() -{ - subMenuMouse_data(); -} - -// QTBUG-69540 -void tst_QQuickMenu::subMenuDisabledMouse() -{ - if ((QGuiApplication::platformName() == QLatin1String("offscreen")) - || (QGuiApplication::platformName() == QLatin1String("minimal"))) - QSKIP("Mouse hovering not functional on offscreen/minimal platforms"); - - QFETCH(bool, cascade); - - QQuickControlsApplicationHelper helper(this, QLatin1String("subMenuDisabled.qml")); - QVERIFY2(helper.ready, helper.failureMessage()); - QQuickApplicationWindow *window = helper.appWindow; - centerOnScreen(window); - moveMouseAway(window); - window->show(); - QVERIFY(QTest::qWaitForWindowExposed(window)); - - QQuickMenu *mainMenu = window->property("mainMenu").value<QQuickMenu *>(); - QVERIFY(mainMenu); - mainMenu->setCascade(cascade); - QCOMPARE(mainMenu->cascade(), cascade); - - QQuickMenuItem *menuItem1 = qobject_cast<QQuickMenuItem *>(mainMenu->itemAt(0)); - QVERIFY(menuItem1); - - QQuickMenu *subMenu = window->property("subMenu").value<QQuickMenu *>(); - QVERIFY(subMenu); - - mainMenu->open(); - QTRY_VERIFY(mainMenu->isOpened()); - QVERIFY(!menuItem1->isHighlighted()); - QVERIFY(!subMenu->isVisible()); - - // Hover-highlighting does not work on Android -#ifndef Q_OS_ANDROID - // Generate a hover event to set the current index - QTest::mouseMove(window, menuItem1->mapToScene(QPoint(2, 2)).toPoint()); - QTRY_VERIFY(menuItem1->isHighlighted()); -#endif - // Open the sub-menu with a mouse click. - QTest::mouseClick(window, Qt::LeftButton, Qt::NoModifier, menuItem1->mapToScene(QPoint(1, 1)).toPoint()); - // Need to use the TRY variant here, - // as e.g. Material, iOS style menus have transitions and don't open/close immediately. - QTRY_COMPARE(mainMenu->isVisible(), cascade); - QTRY_VERIFY(subMenu->isOpened()); - QTRY_VERIFY(menuItem1->isHighlighted()); - // Now the sub-menu is open. The current behavior is that the first menu item - // in the new menu is highlighted; make sure that we choose the next item if - // the first is disabled. - QQuickMenuItem *subMenuItem1 = qobject_cast<QQuickMenuItem *>(subMenu->itemAt(0)); - QVERIFY(subMenuItem1); - QQuickMenuItem *subMenuItem2 = qobject_cast<QQuickMenuItem *>(subMenu->itemAt(1)); - QVERIFY(subMenuItem2); - QVERIFY(!subMenuItem1->isHighlighted()); - QVERIFY(subMenuItem2->isHighlighted()); - - // Close all menus by clicking on the item that isn't disabled. - QTest::mouseClick(window, Qt::LeftButton, Qt::NoModifier, subMenuItem2->mapToScene(QPoint(1, 1)).toPoint()); - QTRY_VERIFY(!mainMenu->isVisible()); - QTRY_VERIFY(!subMenu->isVisible()); -} - -void tst_QQuickMenu::subMenuKeyboard_data() -{ - QTest::addColumn<bool>("cascade"); - QTest::addColumn<bool>("mirrored"); - - QTest::newRow("cascading") << true << false; - QTest::newRow("cascading,mirrored") << true << true; - QTest::newRow("non-cascading") << false << false; - QTest::newRow("non-cascading,mirrored") << false << true; -} - -void tst_QQuickMenu::subMenuKeyboard() -{ - if (!hasWindowActivation()) - QSKIP("Window activation is not supported"); - - QFETCH(bool, cascade); - QFETCH(bool, mirrored); - - QQuickControlsApplicationHelper helper(this, QLatin1String("subMenus.qml")); - QVERIFY2(helper.ready, helper.failureMessage()); - QQuickApplicationWindow *window = helper.appWindow; - centerOnScreen(window); - moveMouseAway(window); - window->show(); - QVERIFY(QTest::qWaitForWindowActive(window)); - - if (mirrored) { - QQmlExpression mirroringExpression(qmlContext(window), window, - "LayoutMirroring.childrenInherit = true; LayoutMirroring.enabled = true"); - QVERIFY2(mirroringExpression.evaluate().isValid(), qPrintable(mirroringExpression.error().toString())); - } - - QQuickMenu *mainMenu = window->property("mainMenu").value<QQuickMenu *>(); - QVERIFY(mainMenu); - mainMenu->setCascade(cascade); - QCOMPARE(mainMenu->cascade(), cascade); - - QQuickMenu *subMenu1 = window->property("subMenu1").value<QQuickMenu *>(); - QVERIFY(subMenu1); - - QQuickMenu *subMenu2 = window->property("subMenu2").value<QQuickMenu *>(); - QVERIFY(subMenu2); - - QQuickMenu *subSubMenu1 = window->property("subSubMenu1").value<QQuickMenu *>(); - QVERIFY(subSubMenu1); - - mainMenu->open(); - QVERIFY(mainMenu->isVisible()); - QTRY_VERIFY(mainMenu->isOpened()); - QVERIFY(!subMenu1->isVisible()); - QVERIFY(!subMenu2->isVisible()); - QVERIFY(!subSubMenu1->isVisible()); - - // navigate to the sub-menu item and trigger it to open the sub-menu - QQuickMenuItem *subMenu1Item = qobject_cast<QQuickMenuItem *>(mainMenu->itemAt(1)); - QVERIFY(subMenu1Item); - QVERIFY(!subMenu1Item->isHighlighted()); - QCOMPARE(subMenu1Item->subMenu(), subMenu1); - QTest::keyClick(window, Qt::Key_Down); - QTest::keyClick(window, Qt::Key_Down); - QVERIFY(subMenu1Item->isHighlighted()); - QTest::keyClick(window, Qt::Key_Space); - QTRY_COMPARE(mainMenu->isVisible(), cascade); - QVERIFY(subMenu1->isVisible()); - QTRY_VERIFY(subMenu1->isOpened()); - QVERIFY(!subMenu2->isVisible()); - QVERIFY(!subSubMenu1->isVisible()); - - // navigate to the sub-sub-menu item and open it with the arrow key - QQuickMenuItem *subSubMenu1Item = qobject_cast<QQuickMenuItem *>(subMenu1->itemAt(2)); - QVERIFY(subSubMenu1Item); - QVERIFY(!subSubMenu1Item->isHighlighted()); - QCOMPARE(subSubMenu1Item->subMenu(), subSubMenu1); - QTest::keyClick(window, Qt::Key_Down); - QTest::keyClick(window, Qt::Key_Down); - QTest::keyClick(window, Qt::Key_Down); - QVERIFY(subSubMenu1Item->isHighlighted()); - QTRY_COMPARE(mainMenu->isVisible(), cascade); - QVERIFY(subMenu1->isVisible()); - QVERIFY(!subMenu2->isVisible()); - QVERIFY(!subSubMenu1->isVisible()); - QTest::keyClick(window, mirrored ? Qt::Key_Left : Qt::Key_Right); - QCOMPARE(mainMenu->isVisible(), cascade); - QTRY_COMPARE(subMenu1->isVisible(), cascade); - QVERIFY(!subMenu2->isVisible()); - QVERIFY(subSubMenu1->isVisible()); - QTRY_VERIFY(subSubMenu1->isOpened()); - - // navigate within the sub-sub-menu - QQuickMenuItem *subSubMenuItem1 = qobject_cast<QQuickMenuItem *>(subSubMenu1->itemAt(0)); - QVERIFY(subSubMenuItem1); - QQuickMenuItem *subSubMenuItem2 = qobject_cast<QQuickMenuItem *>(subSubMenu1->itemAt(1)); - QVERIFY(subSubMenuItem2); - QVERIFY(subSubMenuItem1->isHighlighted()); - QVERIFY(!subSubMenuItem2->isHighlighted()); - QTest::keyClick(window, Qt::Key_Down); - QVERIFY(!subSubMenuItem1->isHighlighted()); - QVERIFY(subSubMenuItem2->isHighlighted()); - - // navigate to the parent menu with the arrow key - QTest::keyClick(window, mirrored ? Qt::Key_Right : Qt::Key_Left); - QVERIFY(subSubMenu1Item->isHighlighted()); - QCOMPARE(mainMenu->isVisible(), cascade); - QVERIFY(subMenu1->isVisible()); - QVERIFY(!subMenu2->isVisible()); - QTRY_VERIFY(!subSubMenu1->isVisible()); - - // navigate within the sub-menu - QQuickMenuItem *subMenuItem1 = qobject_cast<QQuickMenuItem *>(subMenu1->itemAt(0)); - QVERIFY(subMenuItem1); - QQuickMenuItem *subMenuItem2 = qobject_cast<QQuickMenuItem *>(subMenu1->itemAt(1)); - QVERIFY(subMenuItem2); - QVERIFY(!subMenuItem1->isHighlighted()); - QVERIFY(!subMenuItem2->isHighlighted()); - QVERIFY(subSubMenu1Item->isHighlighted()); - QTest::keyClick(window, Qt::Key_Up); - QVERIFY(!subMenuItem1->isHighlighted()); - QVERIFY(subMenuItem2->isHighlighted()); - QVERIFY(!subSubMenu1Item->isHighlighted()); - - // close the menus with esc - QTest::keyClick(window, Qt::Key_Escape); - QCOMPARE(mainMenu->isVisible(), cascade); - QTRY_VERIFY(!subMenu1->isVisible()); - QVERIFY(!subMenu2->isVisible()); - QVERIFY(!subSubMenu1->isVisible()); - QTest::keyClick(window, Qt::Key_Escape); - QTRY_VERIFY(!mainMenu->isVisible()); - QVERIFY(!subMenu1->isVisible()); - QVERIFY(!subMenu2->isVisible()); - QVERIFY(!subSubMenu1->isVisible()); -} - -void tst_QQuickMenu::subMenuDisabledKeyboard_data() -{ - subMenuKeyboard_data(); -} - -// QTBUG-69540 -void tst_QQuickMenu::subMenuDisabledKeyboard() -{ - if (!hasWindowActivation()) - QSKIP("Window activation is not supported"); - - QFETCH(bool, cascade); - QFETCH(bool, mirrored); - - QQuickControlsApplicationHelper helper(this, QLatin1String("subMenuDisabled.qml")); - QVERIFY2(helper.ready, helper.failureMessage()); - QQuickApplicationWindow *window = helper.appWindow; - centerOnScreen(window); - moveMouseAway(window); - window->show(); - QVERIFY(QTest::qWaitForWindowActive(window)); - - if (mirrored) { - QQmlExpression mirroringExpression(qmlContext(window), window, - "LayoutMirroring.childrenInherit = true; LayoutMirroring.enabled = true"); - QVERIFY2(mirroringExpression.evaluate().isValid(), qPrintable(mirroringExpression.error().toString())); - } - - QQuickMenu *mainMenu = window->property("mainMenu").value<QQuickMenu *>(); - QVERIFY(mainMenu); - mainMenu->setCascade(cascade); - QCOMPARE(mainMenu->cascade(), cascade); - - QQuickMenuItem *menuItem1 = qobject_cast<QQuickMenuItem *>(mainMenu->itemAt(0)); - QVERIFY(menuItem1); - - QQuickMenu *subMenu = window->property("subMenu").value<QQuickMenu *>(); - QVERIFY(subMenu); - - mainMenu->open(); - QVERIFY(mainMenu->isVisible()); - QTRY_VERIFY(mainMenu->isOpened()); - QVERIFY(!menuItem1->isHighlighted()); - QVERIFY(!subMenu->isVisible()); - - // Highlight the top-level menu item. - QTest::keyClick(window, Qt::Key_Down); - QVERIFY(menuItem1->isHighlighted()); - - QQuickMenuItem *subMenuItem1 = qobject_cast<QQuickMenuItem *>(subMenu->itemAt(0)); - QVERIFY(subMenuItem1); - QQuickMenuItem *subMenuItem2 = qobject_cast<QQuickMenuItem *>(subMenu->itemAt(1)); - QVERIFY(subMenuItem2); - - // Open the sub-menu. - QTest::keyClick(window, mirrored ? Qt::Key_Left : Qt::Key_Right); - // The first sub-menu item is disabled, so it should highlight the second one. - QVERIFY(!subMenuItem1->isHighlighted()); - QVERIFY(subMenuItem2->isHighlighted()); - - // Close the menus with escape. - QTest::keyClick(window, Qt::Key_Escape); - QTRY_COMPARE(mainMenu->isVisible(), cascade); - QTRY_VERIFY(!subMenu->isVisible()); - QTest::keyClick(window, Qt::Key_Escape); - QTRY_VERIFY(!mainMenu->isVisible()); - QVERIFY(!subMenu->isVisible()); -} - -/* - QCOMPARE() compares doubles with 1-in-1e12 precision, which is too fine for these tests. - Casting to floats, compared with 1-in-1e5 precision, gives more robust results. -*/ -#define FLOAT_EQ(u, v) QCOMPARE(float(u), float(v)) - -void tst_QQuickMenu::subMenuPosition_data() -{ - QTest::addColumn<bool>("cascade"); - QTest::addColumn<bool>("flip"); - QTest::addColumn<bool>("mirrored"); - QTest::addColumn<qreal>("overlap"); - - QTest::newRow("cascading") << true << false << false << 0.0; - QTest::newRow("cascading,flip") << true << true << false << 0.0; - QTest::newRow("cascading,overlap") << true << false << false << 10.0; - QTest::newRow("cascading,flip,overlap") << true << true << false << 10.0; - QTest::newRow("cascading,mirrored") << true << false << true << 0.0; - QTest::newRow("cascading,mirrored,flip") << true << true << true << 0.0; - QTest::newRow("cascading,mirrored,overlap") << true << false << true << 10.0; - QTest::newRow("cascading,mirrored,flip,overlap") << true << true << true << 10.0; - QTest::newRow("non-cascading") << false << false << false << 0.0; -} - -void tst_QQuickMenu::subMenuPosition() -{ - QFETCH(bool, cascade); - QFETCH(bool, flip); - QFETCH(bool, mirrored); - QFETCH(qreal, overlap); - - QQuickControlsApplicationHelper helper(this, QLatin1String("subMenus.qml")); - QVERIFY2(helper.ready, helper.failureMessage()); - QQuickApplicationWindow *window = helper.appWindow; - - // Ensure that the default size of the window fits three menus side by side. - QQuickMenu *mainMenu = window->property("mainMenu").value<QQuickMenu *>(); - QVERIFY(mainMenu); - window->setWidth(mainMenu->width() * 3 + mainMenu->leftMargin() + mainMenu->rightMargin()); - - // the default size of the window fits three menus side by side. - // when testing flipping, we resize the window so that the first - // sub-menu fits, but the second doesn't - if (flip) - window->setWidth(window->width() - mainMenu->width()); - - centerOnScreen(window); - moveMouseAway(window); -#ifndef Q_OS_ANDROID - window->show(); -#else - // On Android the desired size does not fit into the screen, so we just - // call showNormal. This will make the window larger than the screen, but - // all the geometry calculations will be correct. Otherwise we'll get - // unpredictable results - window->showNormal(); -#endif - QVERIFY(QTest::qWaitForWindowExposed(window)); - - if (mirrored) { - QQmlExpression mirroringExpression(qmlContext(window), window, - "LayoutMirroring.childrenInherit = true; LayoutMirroring.enabled = true"); - QVERIFY2(mirroringExpression.evaluate().isValid(), qPrintable(mirroringExpression.error().toString())); - } - - mainMenu->setCascade(cascade); - QCOMPARE(mainMenu->cascade(), cascade); - mainMenu->setOverlap(overlap); - QCOMPARE(mainMenu->overlap(), overlap); - - QQuickMenu *subMenu1 = window->property("subMenu1").value<QQuickMenu *>(); - QVERIFY(subMenu1); - subMenu1->setCascade(cascade); - QCOMPARE(subMenu1->cascade(), cascade); - subMenu1->setOverlap(overlap); - QCOMPARE(subMenu1->overlap(), overlap); - - QQuickMenu *subMenu2 = window->property("subMenu2").value<QQuickMenu *>(); - QVERIFY(subMenu2); - subMenu2->setCascade(cascade); - QCOMPARE(subMenu2->cascade(), cascade); - subMenu2->setOverlap(overlap); - QCOMPARE(subMenu2->overlap(), overlap); - - QQuickMenu *subSubMenu1 = window->property("subSubMenu1").value<QQuickMenu *>(); - QVERIFY(subSubMenu1); - subSubMenu1->setCascade(cascade); - QCOMPARE(subSubMenu1->cascade(), cascade); - subSubMenu1->setOverlap(overlap); - QCOMPARE(subSubMenu1->overlap(), overlap); - - // choose the main menu position so that there's room for the - // sub-menus to cascade to the left when mirrored - if (mirrored) - mainMenu->setX(window->width() - mainMenu->width()); - - mainMenu->open(); - QVERIFY(mainMenu->isVisible()); - QTRY_VERIFY(mainMenu->isOpened()); - QVERIFY(!subMenu1->isVisible()); - QVERIFY(!subMenu2->isVisible()); - QVERIFY(!subSubMenu1->isVisible()); - - // open the sub-menu (never flips) - QQuickMenuItem *subMenu1Item = qobject_cast<QQuickMenuItem *>(mainMenu->itemAt(1)); - QVERIFY(subMenu1Item); - QCOMPARE(subMenu1Item->subMenu(), subMenu1); - emit subMenu1Item->triggered(); - QTRY_COMPARE(mainMenu->isVisible(), cascade); - QVERIFY(subMenu1->isVisible()); - QTRY_VERIFY(subMenu1->isOpened()); - QVERIFY(!subMenu2->isVisible()); - QVERIFY(!subSubMenu1->isVisible()); - - if (cascade) { - QCOMPARE(subMenu1->parentItem(), subMenu1Item); - // vertically aligned to the parent menu item - // We cast to float here because we want to use its larger tolerance for equality (because it has less precision than double). - FLOAT_EQ(subMenu1->popupItem()->y(), mainMenu->popupItem()->y() + subMenu1Item->y()); - if (mirrored) { - // on the left of the parent menu - FLOAT_EQ(subMenu1->popupItem()->x(), mainMenu->popupItem()->x() - subMenu1->width() + overlap); - } else { - // on the right of the parent menu - FLOAT_EQ(subMenu1->popupItem()->x(), mainMenu->popupItem()->x() + mainMenu->width() - overlap); - } - } else { - QCOMPARE(subMenu1->parentItem(), mainMenu->parentItem()); - // centered over the parent menu - FLOAT_EQ(subMenu1->popupItem()->x(), mainMenu->popupItem()->x() + (mainMenu->width() - subMenu1->width()) / 2); - FLOAT_EQ(subMenu1->popupItem()->y(), mainMenu->popupItem()->y() + (mainMenu->height() - subMenu1->height()) / 2); - } - - // open the sub-sub-menu (can flip) - QQuickMenuItem *subSubMenu1Item = qobject_cast<QQuickMenuItem *>(subMenu1->itemAt(2)); - QVERIFY(subSubMenu1Item); - QCOMPARE(subSubMenu1Item->subMenu(), subSubMenu1); - emit subSubMenu1Item->triggered(); - QTRY_COMPARE(mainMenu->isVisible(), cascade); - QTRY_COMPARE(subMenu1->isVisible(), cascade); - QVERIFY(!subMenu2->isVisible()); - QVERIFY(subSubMenu1->isVisible()); - QTRY_VERIFY(subSubMenu1->isOpened()); - - if (cascade) { - QCOMPARE(subSubMenu1->parentItem(), subSubMenu1Item); - // vertically aligned to the parent menu item - FLOAT_EQ(subSubMenu1->popupItem()->y(), subMenu1->popupItem()->y() + subSubMenu1Item->y()); - if (mirrored != flip) { - // on the left of the parent menu - FLOAT_EQ(subSubMenu1->popupItem()->x(), subMenu1->popupItem()->x() - subSubMenu1->width() + overlap); - } else { - // on the right of the parent menu - FLOAT_EQ(subSubMenu1->popupItem()->x(), subMenu1->popupItem()->x() + subMenu1->width() - overlap); - } - } else { - QCOMPARE(subSubMenu1->parentItem(), subMenu1->parentItem()); - // centered over the parent menu - FLOAT_EQ(subSubMenu1->popupItem()->x(), subMenu1->popupItem()->x() + (subMenu1->width() - subSubMenu1->width()) / 2); - FLOAT_EQ(subSubMenu1->popupItem()->y(), subMenu1->popupItem()->y() + (subMenu1->height() - subSubMenu1->height()) / 2); - } -} - -#undef FLOAT_EQ - -void tst_QQuickMenu::subMenuWithIcon() -{ - QQuickControlsApplicationHelper helper(this, QLatin1String("subMenus.qml")); - QVERIFY2(helper.ready, helper.failureMessage()); - QQuickApplicationWindow *window = helper.appWindow; - - QQuickMenu *mainMenu = window->property("mainMenu").value<QQuickMenu *>(); - QVERIFY(mainMenu); - - QQuickMenu *subMenu = window->property("subMenu1").value<QQuickMenu *>(); - QVERIFY(subMenu); - - const int iconWidth = 14; - const int iconHeight = 20; - const QUrl iconSource("qrc:/qt-project.org/imports/QtQuick/Controls/Basic/images/check.png"); - - QQuickIcon icon; - icon.setSource(iconSource); - icon.setWidth(iconWidth); - icon.setHeight(iconHeight); - - subMenu->setIcon(icon); - QCOMPARE(subMenu->icon().source(), iconSource); - QCOMPARE(subMenu->icon().width(), iconWidth); - QCOMPARE(subMenu->icon().height(), iconHeight); - - QQuickMenuItem *subMenuItem = qobject_cast<QQuickMenuItem *>(mainMenu->itemAt(1)); - QVERIFY(subMenuItem); - QCOMPARE(subMenuItem->icon().source(), iconSource); - QCOMPARE(subMenuItem->icon().width(), iconWidth); - QCOMPARE(subMenuItem->icon().height(), iconHeight); -} - -void tst_QQuickMenu::addRemoveSubMenus() -{ - QQuickControlsApplicationHelper helper(this, QLatin1String("subMenus.qml")); - QVERIFY2(helper.ready, helper.failureMessage()); - QQuickWindow *window = helper.window; - window->show(); - QVERIFY(QTest::qWaitForWindowExposed(window)); - - QQuickMenu *mainMenu = window->property("mainMenu").value<QQuickMenu *>(); - QVERIFY(mainMenu); - - QVERIFY(!mainMenu->menuAt(0)); - - QPointer<QQuickMenu> subMenu1 = window->property("subMenu1").value<QQuickMenu *>(); - QVERIFY(!subMenu1.isNull()); - QCOMPARE(mainMenu->menuAt(1), subMenu1.data()); - - QVERIFY(!mainMenu->menuAt(2)); - - QPointer<QQuickMenu> subMenu2 = window->property("subMenu2").value<QQuickMenu *>(); - QVERIFY(!subMenu2.isNull()); - QCOMPARE(mainMenu->menuAt(3), subMenu2.data()); - - QVERIFY(!mainMenu->menuAt(4)); - - QPointer<QQuickMenu> subSubMenu1 = window->property("subSubMenu1").value<QQuickMenu *>(); - QVERIFY(!subSubMenu1.isNull()); - - // takeMenu(int) does not destroy the menu, but does destroy the respective item in the parent menu - QPointer<QQuickMenuItem> subSubMenu1Item = qobject_cast<QQuickMenuItem *>(subMenu1->itemAt(2)); - QVERIFY(subSubMenu1Item); - QCOMPARE(subSubMenu1Item->subMenu(), subSubMenu1.data()); - QCOMPARE(subMenu1->takeMenu(2), subSubMenu1.data()); - QVERIFY(!subMenu1->itemAt(2)); - QCoreApplication::sendPostedEvents(subSubMenu1, QEvent::DeferredDelete); - QVERIFY(!subSubMenu1.isNull()); - QCoreApplication::sendPostedEvents(subSubMenu1Item, QEvent::DeferredDelete); - QVERIFY(subSubMenu1Item.isNull()); - - // takeMenu(int) does not destroy an item that doesn't present a menu - QPointer<QQuickMenuItem> subMenuItem1 = qobject_cast<QQuickMenuItem *>(subMenu1->itemAt(0)); - QVERIFY(subMenuItem1); - QVERIFY(!subMenuItem1->subMenu()); - QVERIFY(!subMenu1->takeMenu(0)); - QCoreApplication::sendPostedEvents(subMenuItem1, QEvent::DeferredDelete); - QVERIFY(!subMenuItem1.isNull()); - - // addMenu(Menu) re-creates the respective item in the parent menu - subMenu1->addMenu(subSubMenu1); - subSubMenu1Item = qobject_cast<QQuickMenuItem *>(subMenu1->itemAt(2)); - QVERIFY(!subSubMenu1Item.isNull()); - - // removeMenu(Menu) destroys both the menu and the respective item in the parent menu - subMenu1->removeMenu(subSubMenu1); - QVERIFY(!subMenu1->itemAt(2)); - QCoreApplication::sendPostedEvents(subSubMenu1, QEvent::DeferredDelete); - QVERIFY(subSubMenu1.isNull()); - QCoreApplication::sendPostedEvents(subSubMenu1Item, QEvent::DeferredDelete); - QVERIFY(subSubMenu1Item.isNull()); -} - -void tst_QQuickMenu::scrollable_data() -{ - QTest::addColumn<QString>("qmlFilePath"); - - QTest::addRow("Window") << QString::fromLatin1("windowScrollable.qml"); - QTest::addRow("ApplicationWindow") << QString::fromLatin1("applicationWindowScrollable.qml"); - QTest::addRow("WithPadding") << QString::fromLatin1("scrollableWithPadding.qml"); -} - -void tst_QQuickMenu::scrollable() -{ - QFETCH(QString, qmlFilePath); - - QQuickControlsApplicationHelper helper(this, qmlFilePath); - QVERIFY2(helper.ready, helper.failureMessage()); - QQuickWindow *window = helper.window; -#ifndef Q_OS_ANDROID - window->show(); -#else - window->showNormal(); -#endif - QVERIFY(QTest::qWaitForWindowExposed(window)); - - QQuickMenu *menu = window->property("menu").value<QQuickMenu*>(); - menu->open(); - QVERIFY(menu->isVisible()); - - QQuickItem *contentItem = menu->contentItem(); - QCOMPARE(contentItem->property("interactive").toBool(), true); -} - -void tst_QQuickMenu::disableWhenTriggered_data() -{ - QTest::addColumn<int>("menuItemIndex"); - QTest::addColumn<int>("subMenuItemIndex"); - - QTest::addRow("Action") << 0 << -1; - QTest::addRow("MenuItem with Action") << 1 << -1; - QTest::addRow("MenuItem with Action declared outside menu") << 2 << -1; - QTest::addRow("MenuItem with no Action") << 3 << -1; - - QTest::addRow("Sub-Action") << 4 << 0; - QTest::addRow("Sub-MenuItem with Action declared inside") << 4 << 1; - QTest::addRow("Sub-MenuItem with Action declared outside menu") << 4 << 2; - QTest::addRow("Sub-MenuItem with no Action") << 4 << 3; -} - -// Tests that the menu is dismissed when a menu item sets "enabled = false" in onTriggered(). -void tst_QQuickMenu::disableWhenTriggered() -{ - if ((QGuiApplication::platformName() == QLatin1String("offscreen")) - || (QGuiApplication::platformName() == QLatin1String("minimal"))) - QSKIP("Mouse hovering not functional on offscreen/minimal platforms"); - - QFETCH(int, menuItemIndex); - QFETCH(int, subMenuItemIndex); - - QQuickControlsApplicationHelper helper(this, QLatin1String("disableWhenTriggered.qml")); - QVERIFY2(helper.ready, helper.failureMessage()); - QQuickWindow *window = helper.window; - window->show(); - QVERIFY(QTest::qWaitForWindowExposed(window)); - - QQuickMenu *menu = window->findChild<QQuickMenu*>("Menu"); - QVERIFY(menu); - - menu->open(); - QVERIFY(menu->isVisible()); - QTRY_VERIFY(menu->isOpened()); - - QPointer<QQuickMenuItem> menuItem = qobject_cast<QQuickMenuItem*>(menu->itemAt(menuItemIndex)); - QVERIFY(menuItem); - - if (subMenuItemIndex == -1) { - // Click a top-level menu item. - QTest::mouseClick(window, Qt::LeftButton, Qt::NoModifier, - menuItem->mapToScene(QPointF(menuItem->width() / 2, menuItem->height() / 2)).toPoint()); - QCOMPARE(menuItem->isEnabled(), false); - QTRY_VERIFY(!menu->isVisible()); - } else { - // Click a sub-menu item. - QPointer<QQuickMenu> subMenu = menuItem->subMenu(); - QVERIFY(subMenu); - - QPointer<QQuickMenuItem> subMenuItem = qobject_cast<QQuickMenuItem*>(subMenu->itemAt(subMenuItemIndex)); - QVERIFY(subMenuItem); - - // First, open the sub-menu. -#if !defined(Q_OS_ANDROID) and !defined(Q_OS_WEBOS) - QTest::mouseMove(window, menuItem->mapToScene(QPoint(1, 1)).toPoint()); -#else - // On Android and webOS mouseHover does not open sub-menu, so just click on it - QTest::mouseClick(window, Qt::LeftButton, Qt::NoModifier, - menuItem->mapToScene(QPointF(menuItem->width() / 2, menuItem->height() / 2)).toPoint()); -#endif - - QTRY_VERIFY(subMenu->isVisible()); -#ifndef Q_OS_ANDROID - QVERIFY(menuItem->isHovered()); - QTRY_VERIFY(subMenu->contentItem()->property("contentHeight").toReal() > 0.0); -#endif - - // Click the item. - QTest::mouseClick(window, Qt::LeftButton, Qt::NoModifier, - subMenuItem->mapToScene(QPointF(subMenuItem->width() / 2, subMenuItem->height() / 2)).toPoint()); - QCOMPARE(subMenuItem->isEnabled(), false); - QTRY_VERIFY(!menu->isVisible()); - } -} - -void tst_QQuickMenu::menuItemWidth_data() -{ - QTest::addColumn<bool>("mirrored"); - - QTest::newRow("non-mirrored") << false; - QTest::newRow("mirrored") << true; -} - -void tst_QQuickMenu::menuItemWidth() -{ - QFETCH(bool, mirrored); - - QQuickControlsApplicationHelper helper(this, QLatin1String("menuItemWidths.qml")); - QVERIFY2(helper.ready, helper.failureMessage()); - QQuickApplicationWindow *window = helper.appWindow; - window->show(); - QVERIFY(QTest::qWaitForWindowExposed(window)); - - if (mirrored) { - QQmlExpression mirroringExpression(qmlContext(window), window, - "LayoutMirroring.childrenInherit = true; LayoutMirroring.enabled = true"); - QVERIFY2(mirroringExpression.evaluate().isValid(), qPrintable(mirroringExpression.error().toString())); - } - - QQuickMenu *menu = window->property("menu").value<QQuickMenu *>(); - QVERIFY(menu); - menu->open(); - QTRY_VERIFY(menu->isOpened()); - for (int i = 0; i < menu->count(); ++i) - QCOMPARE(menu->itemAt(i)->width(), menu->availableWidth()); -} - -void tst_QQuickMenu::menuItemWidthAfterMenuWidthChanged_data() -{ - QTest::addColumn<bool>("mirrored"); - - QTest::newRow("non-mirrored") << false; - QTest::newRow("mirrored") << true; -} - -void tst_QQuickMenu::menuItemWidthAfterMenuWidthChanged() -{ - QFETCH(bool, mirrored); - - QQuickControlsApplicationHelper helper(this, QLatin1String("menuItemWidths.qml")); - QVERIFY2(helper.ready, helper.failureMessage()); - QQuickApplicationWindow *window = helper.appWindow; - window->show(); - QVERIFY(QTest::qWaitForWindowExposed(window)); - - if (mirrored) { - QQmlExpression mirroringExpression(qmlContext(window), window, - "LayoutMirroring.childrenInherit = true; LayoutMirroring.enabled = true"); - QVERIFY2(mirroringExpression.evaluate().isValid(), qPrintable(mirroringExpression.error().toString())); - } - - QQuickMenu *menu = window->property("menu").value<QQuickMenu *>(); - QVERIFY(menu); - menu->open(); - QTRY_VERIFY(menu->isOpened()); - for (int i = 0; i < menu->count(); ++i) { - // Check that the width of menu items is correct before we resize the menu. - const QQuickItem *item = menu->itemAt(i); - QVERIFY2(qFuzzyCompare(item->width(), menu->availableWidth()), - qPrintable(QString::fromLatin1("Expected width of %1 to be %2, but it's %3") - .arg(item->objectName()).arg(menu->availableWidth()).arg(item->width()))); - } - - menu->setWidth(menu->width() + 10); - - // Check that the width of menu items is correct after we resize the menu. - for (int i = 0; i < menu->count(); ++i) { - // Check that the width of menu items is correct after we resize the menu. - const QQuickItem *item = menu->itemAt(i); - QVERIFY2(qFuzzyCompare(item->width(), menu->availableWidth()), - qPrintable(QString::fromLatin1("Expected width of %1 to be %2, but it's %3") - .arg(item->objectName()).arg(menu->availableWidth()).arg(item->width()))); - } -} - -void tst_QQuickMenu::menuItemWidthAfterImplicitWidthChanged_data() -{ - QTest::addColumn<bool>("mirrored"); - - QTest::newRow("non-mirrored") << false; - QTest::newRow("mirrored") << true; -} - -void tst_QQuickMenu::menuItemWidthAfterImplicitWidthChanged() -{ - QFETCH(bool, mirrored); - - QQuickControlsApplicationHelper helper(this, QLatin1String("menuItemWidths.qml")); - QVERIFY2(helper.ready, helper.failureMessage()); - QQuickApplicationWindow *window = helper.appWindow; - window->show(); - QVERIFY(QTest::qWaitForWindowExposed(window)); - - if (mirrored) { - QQmlExpression mirroringExpression(qmlContext(window), window, - "LayoutMirroring.childrenInherit = true; LayoutMirroring.enabled = true"); - QVERIFY2(mirroringExpression.evaluate().isValid(), qPrintable(mirroringExpression.error().toString())); - } - - QQuickMenu *menu = window->property("menu").value<QQuickMenu *>(); - QVERIFY(menu); - menu->open(); - QTRY_VERIFY(menu->isOpened()); - // Check that the width of the menu item is correct before we change its font size. - QQuickMenuItem *menuItem = qobject_cast<QQuickMenuItem*>(menu->itemAt(0)); - QCOMPARE(menuItem->width(), menu->availableWidth()); - - // Add some text to increase the implicitWidth of the MenuItem. - const qreal oldImplicitWidth = menuItem->implicitWidth(); - for (int i = 0; menuItem->implicitWidth() <= oldImplicitWidth; ++i) { - menuItem->setText(menuItem->text() + QLatin1String("---")); - if (i == 100) - QFAIL("Shouldn't need 100 iterations to increase MenuItem's implicitWidth; something is wrong here"); - } - - // Check that the width of the menu item is correct after we change its font size. - QCOMPARE(menuItem->width(), menu->availableWidth()); -} - -void tst_QQuickMenu::menuItemWidthAfterRetranslate() -{ - QQuickControlsApplicationHelper helper(this, QLatin1String("menuItemWidths.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->isOpened()); - for (int i = 0; i < menu->count(); ++i) { - // Check that the width of each menu item is correct before we retranslate. - const QQuickItem *item = menu->itemAt(i); - QVERIFY2(qFuzzyCompare(item->width(), menu->availableWidth()), - qPrintable(QString::fromLatin1("Expected width of %1 to be %2, but it's %3") - .arg(item->objectName()).arg(menu->availableWidth()).arg(item->width()))); - } - - // Call retranslate() and cause all bindings to be re-evaluated. - helper.engine.retranslate(); - - for (int i = 0; i < menu->count(); ++i) { - // Check that the width of each menu item is correct after we retranslate. - const QQuickItem *item = menu->itemAt(i); - QVERIFY2(qFuzzyCompare(item->width(), menu->availableWidth()), - qPrintable(QString::fromLatin1("Expected width of %1 to be %2, but it's %3") - .arg(item->objectName()).arg(menu->availableWidth()).arg(item->width()))); - } -} - -void tst_QQuickMenu::giveMenuItemFocusOnButtonPress() -{ - if (!hasWindowActivation()) - QSKIP("Window activation is not supported"); - - QQuickControlsApplicationHelper helper(this, QLatin1String("giveMenuItemFocusOnButtonPress.qml")); - QVERIFY2(helper.ready, helper.failureMessage()); - QQuickApplicationWindow *window = helper.appWindow; - window->show(); - QVERIFY(QTest::qWaitForWindowActive(window)); - - // Press enter on the button to open the menu. - QQuickButton *menuButton = window->property("menuButton").value<QQuickButton*>(); - QVERIFY(menuButton); - menuButton->forceActiveFocus(); - QVERIFY(menuButton->hasActiveFocus()); - - QSignalSpy clickedSpy(window, SIGNAL(menuButtonClicked())); - QVERIFY(clickedSpy.isValid()); - - QTest::keyClick(window, Qt::Key_Return); - QCOMPARE(clickedSpy.size(), 1); - - // The menu should still be open. - QQuickMenu *menu = window->property("menu").value<QQuickMenu*>(); - QVERIFY(menu); - QTRY_VERIFY(menu->isOpened()); -} - -void tst_QQuickMenu::customMenuCullItems() -{ - QQuickControlsApplicationHelper helper(this, QLatin1String("customMenuCullItems.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->isOpened()); - - QQuickItem *menuItemFirst = menu->itemAt(0); - QQuickItem *menuItemLast = menu->itemAt(menu->count() - 1); - QVERIFY(menuItemFirst); - QVERIFY(menuItemLast); - QTRY_VERIFY(!QQuickItemPrivate::get(menuItemFirst)->culled); - QTRY_VERIFY(QQuickItemPrivate::get(menuItemLast)->culled); -} - -void tst_QQuickMenu::customMenuUseRepeaterAsTheContentItem() -{ - QQuickControlsApplicationHelper helper(this, QLatin1String("customMenuUseRepeaterAsTheContentItem.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()); - - QQuickItem *menuItemFirst = menu->itemAt(0); - QQuickItem *menuItemLast = menu->itemAt(menu->count() - 1); - QTRY_VERIFY(!QQuickItemPrivate::get(menuItemFirst)->culled); - QTRY_VERIFY(!QQuickItemPrivate::get(menuItemLast)->culled); -} - -QTEST_QUICKCONTROLS_MAIN(tst_QQuickMenu) - -#include "tst_qquickmenu.moc" |