blob: 3b0be52610b8b9af42b7b8decd40bc0e2cf8b0e8 [file] [log] [blame]
/****************************************************************************
**
** Copyright (C) 2016 The Qt Company Ltd.
** Contact: https://www.qt.io/licensing/
**
** This file is part of the test suite of the Qt Toolkit.
**
** $QT_BEGIN_LICENSE:BSD$
** Commercial License Usage
** Licensees holding valid commercial Qt licenses may use this file in
** accordance with the commercial license agreement provided with the
** Software or, alternatively, in accordance with the terms contained in
** a written agreement between you and The Qt Company. For licensing terms
** and conditions see https://www.qt.io/terms-conditions. For further
** information use the contact form at https://www.qt.io/contact-us.
**
** BSD License Usage
** Alternatively, you may use this file under the terms of the BSD license
** as follows:
**
** "Redistribution and use in source and binary forms, with or without
** modification, are permitted provided that the following conditions are
** met:
** * Redistributions of source code must retain the above copyright
** notice, this list of conditions and the following disclaimer.
** * Redistributions in binary form must reproduce the above copyright
** notice, this list of conditions and the following disclaimer in
** the documentation and/or other materials provided with the
** distribution.
** * Neither the name of The Qt Company Ltd nor the names of its
** contributors may be used to endorse or promote products derived
** from this software without specific prior written permission.
**
**
** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE."
**
** $QT_END_LICENSE$
**
****************************************************************************/
import QtTest 1.0
import QtQuick 2.1
import QtQuick.Controls 1.1
import QtQuick.Controls.Private 1.0
import QtQuick.Extras 1.4
import QtQuick.Extras.Private 1.0
import QtQuick.Extras.Private.CppUtils 1.0
// Have to have Item here otherwise mouse clicks don't work.
Item {
id: container
width: 400
height: 400
TestCase {
id: testcase
name: "Tests_PieMenu"
when: windowShown
anchors.fill: parent
readonly property real menuWidth: 200
readonly property real menuHeight: 200
SignalSpy {
id: currentIndexSignalSpy
}
SignalSpy {
id: actionSignalSpy
}
SignalSpy {
id: selectedAngleChangedSpy
}
Component {
id: pieMenuComponent
PieMenu {}
}
function cleanup() {
currentIndexSignalSpy.clear();
actionSignalSpy.clear();
selectedAngleChangedSpy.clear();
}
function mouseButtonToString(button) {
return button === Qt.LeftButton ? "Qt.LeftButton" : "Qt.RightButton";
}
function triggerModeToString(triggerMode) {
return triggerMode === TriggerMode.TriggerOnPress ? "TriggerOnPress"
: (triggerMode === TriggerMode.TriggerOnRelease ? "TriggerOnRelease" : "TriggerOnClick");
}
function test_instance() {
var pieMenu = createTemporaryObject(pieMenuComponent, container);
verify(pieMenu, "PieMenu: failed to create an instance");
verify(pieMenu.__style);
compare(pieMenu.triggerMode, TriggerMode.TriggerOnClick);
pieMenu.destroy();
// Ensure setting visible = true; visible = false; in onCompleted doesn't cause any problems.
var visibleOnCompletedComponent = Qt.createComponent("PieMenuVisibleOnCompleted.qml");
tryCompare(visibleOnCompletedComponent, "status", Component.Ready);
pieMenu = createTemporaryObject(visibleOnCompletedComponent, container);
verify(pieMenu, "PieMenu: failed to create an instance");
pieMenu.destroy();
// Ensure constructing a menu as a property (and hence no parent)
// with visible = true doesn't cause any problems.
var visibleButNoParentComponent = Qt.createComponent("PieMenuVisibleButNoParent.qml");
tryCompare(visibleButNoParentComponent, "status", Component.Ready);
pieMenu = createTemporaryObject(visibleButNoParentComponent, container);
verify(pieMenu, "PieMenu: failed to create an instance");
pieMenu.destroy();
}
function test_triggerMode() {
var pieMenuComponent = Qt.createComponent("PieMenu3Items.qml");
tryCompare(pieMenuComponent, "status", Component.Ready);
var root = createTemporaryObject(pieMenuComponent, container);
var mouseArea = root.mouseArea;
var pieMenu = root.pieMenu;
currentIndexSignalSpy.signalName = "currentIndexChanged"
currentIndexSignalSpy.target = pieMenu;
actionSignalSpy.signalName = "actionTriggered";
actionSignalSpy.target = root;
compare(pieMenu.triggerMode, TriggerMode.TriggerOnClick);
var triggerModes = [
TriggerMode.TriggerOnClick,
TriggerMode.TriggerOnPress,
TriggerMode.TriggerOnRelease
];
// Our root mouse area will accept either left click or right click,
// and the menu should accept either to select items or close it.
var buttonVariations = [
[Qt.LeftButton, Qt.LeftButton],
[Qt.RightButton, Qt.RightButton],
[Qt.LeftButton, Qt.RightButton],
[Qt.RightButton, Qt.LeftButton]
];
for (var modeIndex = 0; modeIndex < triggerModes.length; ++modeIndex) {
for (var i = 0; i < buttonVariations.length; ++i) {
var openButton = buttonVariations[i][0];
var closeButton = buttonVariations[i][1];
pieMenu.triggerMode = triggerModes[modeIndex];
compare(pieMenu.triggerMode, triggerModes[modeIndex]);
// Make the menu visible.
if (pieMenu.triggerMode !== TriggerMode.TriggerOnRelease) {
mouseClick(root, 0, 0, openButton);
} else {
mousePress(root, 0, 0, openButton);
}
tryCompare(pieMenu, "visible", true);
// Click/press outside the menu to close it.
switch (pieMenu.triggerMode) {
case TriggerMode.TriggerOnClick:
mouseClick(root, 0, 0, closeButton);
tryCompare(currentIndexSignalSpy, "count", 0);
compare(pieMenu.visible, false, "Menu isn't closed when clicking "
+ mouseButtonToString(closeButton) + " outside (triggerMode: "
+ triggerModeToString(pieMenu.triggerMode) + ", openButton: "
+ mouseButtonToString(openButton) + ")");
break;
case TriggerMode.TriggerOnPress:
mousePress(root, 0, 0, closeButton);
tryCompare(currentIndexSignalSpy, "count", 0);
compare(pieMenu.visible, false, "Menu isn't closed when pressing "
+ mouseButtonToString(closeButton) + " outside (triggerMode: "
+ triggerModeToString(pieMenu.triggerMode) + ", openButton: "
+ mouseButtonToString(openButton) + ")");
mouseRelease(root, 0, 0, closeButton);
tryCompare(currentIndexSignalSpy, "count", 0);
compare(pieMenu.visible, false, "Menu shouldn't be opened when releasing "
+ mouseButtonToString(closeButton) + " outside (triggerMode: "
+ triggerModeToString(pieMenu.triggerMode) + ", openButton: "
+ mouseButtonToString(openButton) + ")");
break;
case TriggerMode.TriggerOnRelease:
mouseRelease(root, 0, 0, closeButton);
tryCompare(currentIndexSignalSpy, "count", 0);
compare(pieMenu.visible, false, "Menu is closed when releasing "
+ mouseButtonToString(closeButton) + " outside");
break;
}
// Make the menu visible again.
if (pieMenu.triggerMode !== TriggerMode.TriggerOnRelease) {
mouseClick(root, 0, 0, openButton);
} else {
mousePress(root, 0, 0, openButton);
}
tryCompare(pieMenu, "visible", true);
switch (pieMenu.triggerMode) {
case TriggerMode.TriggerOnClick:
// Click on a section of the menu (index 1); it should trigger the item and then close the menu.
mouseClick(root, pieMenu.x + pieMenu.width / 2, pieMenu.y + pieMenu.height / 4, closeButton);
// The current index changes once when the item is selected (1) and once when the menu closes (-1).
tryCompare(currentIndexSignalSpy, "count", 2);
compare(actionSignalSpy.count, 1);
compare(actionSignalSpy.signalArguments[0][0], 1);
compare(pieMenu.currentIndex, -1);
compare(pieMenu.visible, false);
break;
case TriggerMode.TriggerOnPress:
// Press on a section of the menu (index 1); it should trigger the item and then close the menu.
mousePress(root, pieMenu.x + pieMenu.width / 2, pieMenu.y + pieMenu.height / 4, closeButton);
// The current index changes once when the item is selected (1) and once when the menu closes (-1).
tryCompare(currentIndexSignalSpy, "count", 2);
compare(actionSignalSpy.count, 1);
compare(actionSignalSpy.signalArguments[0][0], 1);
compare(pieMenu.currentIndex, -1);
compare(pieMenu.visible, false);
mouseRelease(root, pieMenu.x + pieMenu.width / 2, pieMenu.y + pieMenu.height / 4, closeButton);
// None of these should change after releasing.
tryCompare(currentIndexSignalSpy, "count", 2);
compare(actionSignalSpy.count, 1);
compare(pieMenu.currentIndex, -1);
compare(pieMenu.visible, false);
break;
case TriggerMode.TriggerOnRelease:
// Click/press on a section of the menu (index 1); it should trigger the item and then close the menu.
mouseRelease(root, pieMenu.x + pieMenu.width / 2, pieMenu.y + pieMenu.height / 4, closeButton);
// The current index changes once when the item is selected (1) and once when the menu closes (-1).
tryCompare(currentIndexSignalSpy, "count", 2);
compare(actionSignalSpy.count, 1);
compare(actionSignalSpy.signalArguments[0][0], 1);
compare(pieMenu.currentIndex, -1);
compare(pieMenu.visible, false);
}
currentIndexSignalSpy.clear();
actionSignalSpy.clear();
}
}
pieMenuComponent.destroy()
}
function test_selectionAngle_data() {
var data = [];
var dataRow = {};
dataRow.startAngle = -90;
dataRow.endAngle = 90;
dataRow.mouseX = 1;
dataRow.mouseY = 1;
dataRow.expectedAngle = -Math.PI / 4;
dataRow.expectedCurrentIndex = -1;
dataRow.tag = "startAngle=" + dataRow.startAngle + ", endAngle=" + dataRow.endAngle + ", top left";
data.push(dataRow);
dataRow = {};
dataRow.startAngle = -90;
dataRow.endAngle = 90;
dataRow.mouseX = menuWidth - 1;
dataRow.mouseY = menuHeight - 1;
dataRow.expectedAngle = Math.PI * 0.75;
dataRow.expectedCurrentIndex = -1;
dataRow.tag = "startAngle=" + dataRow.startAngle + ", endAngle=" + dataRow.endAngle + ", bottom right";
data.push(dataRow);
dataRow = {};
dataRow.startAngle = -90;
dataRow.endAngle = -270;
dataRow.mouseX = menuWidth / 2 - 1;
dataRow.mouseY = menuHeight * 0.75;
dataRow.expectedAngle = -3.1215953196166426;
dataRow.expectedCurrentIndex = 1;
dataRow.tag = "startAngle=" + dataRow.startAngle + ", endAngle=" + dataRow.endAngle + ", bottom left edge";
data.push(dataRow);
dataRow = {};
dataRow.startAngle = -90;
dataRow.endAngle = -270;
dataRow.mouseX = menuWidth / 2 + 1;
dataRow.mouseY = menuHeight * 0.75;
dataRow.expectedAngle = 3.1215953196166426;
dataRow.expectedCurrentIndex = 1;
dataRow.tag = "startAngle=" + dataRow.startAngle + ", endAngle=" + dataRow.endAngle + ", bottom right edge";
data.push(dataRow);
dataRow = {};
dataRow.startAngle = 0;
dataRow.endAngle = 190;
dataRow.mouseX = menuWidth / 2 - 1;
dataRow.mouseY = menuHeight * 0.75;
dataRow.expectedAngle = -3.1215953196166426;
dataRow.expectedCurrentIndex = 2;
dataRow.tag = "startAngle=" + dataRow.startAngle + ", endAngle=" + dataRow.endAngle + ", bottom left edge";
data.push(dataRow);
dataRow = {};
dataRow.startAngle = 0;
dataRow.endAngle = -90;
dataRow.mouseX = menuWidth / 4;
dataRow.mouseY = menuHeight / 2 - 1;
dataRow.expectedAngle = -1.550798992821746;
dataRow.expectedCurrentIndex = 2;
dataRow.tag = "startAngle=" + dataRow.startAngle + ", endAngle=" + dataRow.endAngle + ", section 2";
data.push(dataRow);
dataRow = {};
dataRow.startAngle = 0;
dataRow.endAngle = -90;
dataRow.mouseX = menuWidth / 4;
dataRow.mouseY = menuHeight / 4;
dataRow.expectedAngle = -0.7853981633974483;
dataRow.expectedCurrentIndex = 1;
dataRow.tag = "startAngle=" + dataRow.startAngle + ", endAngle=" + dataRow.endAngle + ", section 1";
data.push(dataRow);
dataRow = {};
dataRow.startAngle = 0;
dataRow.endAngle = -90;
dataRow.mouseX = menuWidth / 2 - 1;
dataRow.mouseY = menuHeight / 4;
dataRow.expectedAngle = -0.01999733397315053;
dataRow.expectedCurrentIndex = 0;
dataRow.tag = "startAngle=" + dataRow.startAngle + ", endAngle=" + dataRow.endAngle + ", section 0";
data.push(dataRow);
dataRow = {};
dataRow.startAngle = -190;
dataRow.endAngle = -90;
dataRow.mouseX = menuWidth / 2 + 1;
dataRow.mouseY = menuHeight * 0.75;
dataRow.expectedAngle = 3.1215953196166426;
dataRow.expectedCurrentIndex = 0;
dataRow.tag = "startAngle=" + dataRow.startAngle + ", endAngle=" + dataRow.endAngle + ", bottom right edge";
data.push(dataRow);
dataRow = {};
dataRow.startAngle = -90;
dataRow.endAngle = -190;
dataRow.mouseX = menuWidth / 2 + 1;
dataRow.mouseY = menuHeight * 0.75;
dataRow.expectedAngle = 3.1215953196166426;
dataRow.expectedCurrentIndex = 2;
dataRow.tag = "startAngle=" + dataRow.startAngle + ", endAngle=" + dataRow.endAngle + ", bottom right edge";
data.push(dataRow);
return data;
}
function test_selectionAngle(data) {
if (Settings.hasTouchScreen)
skip("Fails with touch screens");
var pieMenuComponent = Qt.createComponent("PieMenu3Items.qml");
tryCompare(pieMenuComponent, "status", Component.Ready);
var root = createTemporaryObject(pieMenuComponent, container);
var mouseArea = root.mouseArea;
var pieMenu = root.pieMenu;
compare(pieMenu.selectionAngle, 0);
pieMenu.__style.startAngle = data.startAngle;
pieMenu.__style.endAngle = data.endAngle;
waitForRendering(root);
root.forceActiveFocus();
// Don't allow bounds snapping by always opening within bounds.
mouseClick(root, menuWidth / 2, menuHeight / 2);
tryCompare(pieMenu, "visible", true);
mouseMove(root, data.mouseX, data.mouseY);
compare(pieMenu.selectionAngle, data.expectedAngle);
compare(pieMenu.currentIndex, data.expectedCurrentIndex);
pieMenuComponent.destroy()
}
function test_sectionAngles_data() {
var data = [];
var angleOrigin = 90;
var dataRow = {};
dataRow.startAngle = -90;
dataRow.endAngle = 90;
dataRow.section = 0;
dataRow.expectedSectionSize = MathUtils.degToRadOffset(60 + angleOrigin);
dataRow.expectedSectionStartAngle = MathUtils.degToRadOffset(-90);
dataRow.expectedSectionCenterAngle = MathUtils.degToRadOffset(-60);
dataRow.expectedSectionEndAngle = MathUtils.degToRadOffset(-30);
dataRow.tag = "startAngle=" + dataRow.startAngle + ", endAngle=" + dataRow.endAngle + ", section=" + dataRow.section;
data.push(dataRow);
dataRow = {};
dataRow.startAngle = 270;
dataRow.endAngle = 90;
dataRow.section = 0;
dataRow.expectedSectionSize = MathUtils.degToRadOffset(-60 + angleOrigin);
dataRow.expectedSectionStartAngle = MathUtils.degToRadOffset(270);
dataRow.expectedSectionCenterAngle = MathUtils.degToRadOffset(240);
dataRow.expectedSectionEndAngle = MathUtils.degToRadOffset(210);
dataRow.tag = "startAngle=" + dataRow.startAngle + ", endAngle=" + dataRow.endAngle + ", section=" + dataRow.section;
data.push(dataRow);
return data;
}
function test_sectionAngles(data) {
var pieMenuComponent = Qt.createComponent("PieMenu3Items.qml");
tryCompare(pieMenuComponent, "status", Component.Ready);
var root = createTemporaryObject(pieMenuComponent, container);
var pieMenu = root.pieMenu;
pieMenu.__style.startAngle = data.startAngle;
pieMenu.__style.endAngle = data.endAngle;
compare(pieMenu.__protectedScope.sectionSize, data.expectedSectionSize);
compare(pieMenu.__protectedScope.sectionStartAngle(data.section), data.expectedSectionStartAngle);
compare(pieMenu.__protectedScope.sectionCenterAngle(data.section), data.expectedSectionCenterAngle);
compare(pieMenu.__protectedScope.sectionEndAngle(data.section), data.expectedSectionEndAngle);
pieMenuComponent.destroy()
}
function test_bounds_data() {
return [
{ tag: "noSnapCenter", mouseX: container.width / 2, mouseY: container.height / 2,
expectedX: container.width / 2 - 100, expectedY: container.height / 2 - 100 },
{ tag: "noSnapNearLeft", mouseX: 100, mouseY: container.height / 2,
expectedX: 0, expectedY: container.height / 2 - 100 },
{ tag: "noSnapNearRight", mouseX: container.width - 100, mouseY: container.height / 2,
expectedX: container.width - menuWidth, expectedY: container.height / 2 - 100 },
{ tag: "noSnapNearTop", mouseX: container.width / 2, mouseY: 100,
expectedX: container.width / 2 - 100, expectedY: 0 },
{ tag: "noSnapNearBottom", mouseX: container.width / 2, mouseY: container.height - 100,
expectedX: container.width / 2 - 100, expectedY: container.height - menuHeight },
{ tag: "noSnapNearTopLeft", mouseX: 100, mouseY: 100,
expectedX: 0, expectedY: 0 },
{ tag: "noSnapNearTopRight", mouseX: container.width - 100, mouseY: 100,
expectedX: container.width - menuWidth, expectedY: 0 },
{ tag: "noSnapNearBottomRight", mouseX: container.width - 100, mouseY: container.height - 100,
expectedX: container.width - menuWidth, expectedY: container.height - menuHeight },
{ tag: "noSnapNearBottomLeft", mouseX: 100, mouseY: container.height - 100,
expectedX: 0, expectedY: container.height - menuHeight },
{ tag: "leftEdge", mouseX: 10, mouseY: container.height / 2,
expectedX: 0, expectedY: container.height / 2 - 100 },
{ tag: "rightEdge", mouseX: container.width - 10, mouseY: container.height / 2,
expectedX: container.width - menuHeight, expectedY: container.height / 2 - 100 },
{ tag: "topEdge", mouseX: container.width / 2, mouseY: 10,
expectedX: container.width / 2 - 100, expectedY: 0 },
// The default start and end angles mean that the bottom edge won't snap.
{ tag: "bottomEdge", mouseX: container.width / 2, mouseY: container.height - 10,
expectedX: container.width / 2 - 100, expectedY: container.height - 100 - 10 },
{ tag: "topLeftCorner", mouseX: 10, mouseY: 10,
expectedX: 0, expectedY: 0 },
{ tag: "topRightCorner", mouseX: container.width - 10, mouseY: 10,
expectedX: container.width - menuHeight, expectedY: 0 },
{ tag: "bottomRightCorner", mouseX: container.width - 10, mouseY: container.height - 10,
expectedX: container.width - menuHeight, expectedY: container.height - 100 - 10 },
{ tag: "bottomLeftCorner", mouseX: 10, mouseY: container.height - 10,
expectedX: 0, expectedY: container.height - 100 - 10 }
]
}
function test_bounds(data) {
var pieMenuComponent = Qt.createComponent("PieMenu3Items.qml");
tryCompare(pieMenuComponent, "status", Component.Ready);
var root = createTemporaryObject(pieMenuComponent, container);
var mouseArea = root.mouseArea;
var pieMenu = root.pieMenu;
var rootParent = pieMenu;
while (rootParent.parent) {
rootParent = rootParent.parent;
}
// Necessary due to QTBUG-36938
rootParent.width = 400;
rootParent.height = 400;
var originalStartAngle = pieMenu.__style.startAngle;
var originalEndAngle = pieMenu.__style.endAngle;
mouseClick(root, data.mouseX, data.mouseY);
tryCompare(pieMenu, "visible", true);
compare(pieMenu.x, data.expectedX);
compare(pieMenu.y, data.expectedY);
// Angles shouldn't change.
compare(pieMenu.__style.startAngle, originalStartAngle);
compare(pieMenu.__style.endAngle, originalEndAngle);
// Cancel the menu. Even if it's at the top left, this will land on the cancel area.
mouseClick(root, pieMenu.x + pieMenu.width / 2, pieMenu.y + pieMenu.height / 2);
compare(pieMenu.visible, false);
// Angles shouldn't change.
compare(pieMenu.__style.startAngle, originalStartAngle);
compare(pieMenu.__style.endAngle, originalEndAngle);
pieMenuComponent.destroy()
}
function test_hideItem_data() {
return [
{ tag: "hideFirst", indexVisibility: [false, true, true], expectedIndexHits: [0, 1, 1], expectedText: ["item1", "item1", "item2"] },
{ tag: "hideSecond", indexVisibility: [true, false, true], expectedIndexHits: [0, 1, 1], expectedText: ["item0", "item0", "item2"] },
{ tag: "hideThird", indexVisibility: [true, true, false], expectedIndexHits: [0, 1, 1], expectedText: ["item0", "item0", "item1"] },
];
}
function test_hideItem(data) {
if (Settings.hasTouchScreen)
skip("Fails with touch screens");
var pieMenuComponent = Qt.createComponent("PieMenu3Items.qml");
tryCompare(pieMenuComponent, "status", Component.Ready);
var root = createTemporaryObject(pieMenuComponent, container);
var mouseArea = root.mouseArea;
var pieMenu = root.pieMenu;
var originalStartAngle = pieMenu.__style.startAngle;
var originalEndAngle = pieMenu.__style.endAngle;
// Store the positions at which we should click before we remove any items.
var mousePositions = [Qt.point(40, 70), Qt.point(90, 30), Qt.point(160, 70)];
while (pieMenu.menuItems.length > 0) {
pieMenu.removeItem(pieMenu.menuItems[pieMenu.menuItems.length - 1]);
}
for (var i = 0; i < data.indexVisibility.length; ++i) {
var item = pieMenu.addItem("item" + i);
item.triggered.connect(function (){ root.actionTriggered(data.expectedIndexHits[i]) })
item.visible = data.indexVisibility[i];
}
// Angles shouldn't change.
compare(pieMenu.__style.startAngle, originalStartAngle);
compare(pieMenu.__style.endAngle, originalEndAngle);
for (i = 0; i < data.indexVisibility.length; ++i) {
actionSignalSpy.signalName = "actionTriggered";
actionSignalSpy.target = root;
compare(pieMenu.visible, false);
// Make the menu visible.
mouseClick(root, 100, 100, Qt.LeftButton);
tryCompare(pieMenu, "visible", true);
var pos = mousePositions[i];
mouseMove(root, pos.x, pos.y);
// Not all styles have titles.
if (pieMenu.__style.title)
tryCompare(pieMenu.__panel.titleItem, "text", data.expectedText[i]);
mouseClick(root, pos.x, pos.y, Qt.LeftButton);
tryCompare(pieMenu, "visible", false);
compare(actionSignalSpy.count, 1);
compare(actionSignalSpy.signalArguments[0][0], data.expectedIndexHits[i]);
actionSignalSpy.clear();
}
pieMenuComponent.destroy()
}
function test_addItem() {
var pieMenu = createTemporaryObject(pieMenuComponent, container);
verify(pieMenu);
compare(pieMenu.menuItems.length, 0);
pieMenu.addItem("Action 1");
compare(pieMenu.menuItems.length, 1);
}
function test_insertItem() {
var pieMenu = createTemporaryObject(pieMenuComponent, container);
verify(pieMenu);
compare(pieMenu.menuItems.length, 0);
pieMenu.insertItem(0, "Action 1");
compare(pieMenu.menuItems.length, 1);
compare(pieMenu.menuItems[0].text, "Action 1");
pieMenu.insertItem(1, "Action 2");
compare(pieMenu.menuItems.length, 2);
compare(pieMenu.menuItems[0].text, "Action 1");
compare(pieMenu.menuItems[1].text, "Action 2");
}
function test_removeItem() {
var pieMenuComponent = Qt.createComponent("PieMenu3Items.qml");
tryCompare(pieMenuComponent, "status", Component.Ready);
var root = createTemporaryObject(pieMenuComponent, container);
var pieMenu = root.pieMenu;
var originalLength = pieMenu.menuItems.length;
for (var i = 0; i < originalLength; ++i) {
pieMenu.removeItem(pieMenu.menuItems[pieMenu.menuItems.length - 1]);
compare(pieMenu.menuItems.length, originalLength - (i + 1));
}
pieMenuComponent.destroy()
}
function debugMousePosition(pieMenu, mouseX, mouseY, positionText) {
var rectItem = createTemporaryQmlObject("import QtQuick 2.0; Rectangle { width: 10; height: 10; radius: 5; color: 'red' }", pieMenu);
rectItem.x = mouseX - rectItem.width / 2;
rectItem.y = mouseY - rectItem.height / 2;
var textItem = createTemporaryQmlObject("import QtQuick 2.0; Text {}", rectItem);
textItem.text = positionText;
textItem.font.pixelSize = 8;
textItem.anchors.centerIn = textItem.parent;
}
function test_selectionItemOnMouseMove_QTRD3024() {
if (Settings.hasTouchScreen)
skip("Fails with touch screens");
// Check when an item is hovered by the mouse, it gets made current
// as expected and the current item is cleared when the mouse moves outside the menu
var pieMenuComponent = Qt.createComponent("PieMenu3Items.qml");
tryCompare(pieMenuComponent, "status", Component.Ready);
var root = createTemporaryObject(pieMenuComponent, container);
var mouseArea = root.mouseArea;
var pieMenu = root.pieMenu;
// Make the menu visible at (0,0)
waitForRendering(root);
root.forceActiveFocus();
mouseClick(root, 0, 0);
tryCompare(pieMenu, "visible", true);
// Move the mouse over the menu
mouseMove(root, 0, 0);
compare(pieMenu.currentIndex, -1);
// We would use a data function for this, but we need access to properties
// of the style that change with each style.
var data = [];
var xCenter = pieMenu.width / 2;
var yCenter = pieMenu.height / 2;
var startAngleFunction = pieMenu.__protectedScope.sectionStartAngle;
var centerAngleFunction = pieMenu.__protectedScope.sectionCenterAngle;
var endAngleFunction = pieMenu.__protectedScope.sectionEndAngle;
var pos = MathUtils.centerAlongCircle(xCenter, yCenter, 0, 0, centerAngleFunction(0), 90)
data.push({ name: "inside", mouseX: pos.x, mouseY: pos.y, expectedCurrentIndex: 0 });
pos = MathUtils.centerAlongCircle(xCenter, yCenter, 0, 0, startAngleFunction(0) + MathUtils.degToRad(1), pieMenu.__style.cancelRadius + 10);
data.push({ name: "bottom", mouseX: pos.x, mouseY: pos.y, expectedCurrentIndex: 0 });
pos = MathUtils.centerAlongCircle(xCenter, yCenter, 0, 0, centerAngleFunction(0), pieMenu.__style.cancelRadius + 10);
data.push({ name: "outside", mouseX: pos.x, mouseY: pos.y, expectedCurrentIndex: 0 });
pos = MathUtils.centerAlongCircle(xCenter, yCenter, 0, 0, endAngleFunction(0) - MathUtils.degToRad(1), pieMenu.__style.radius - 1);
data.push({ name: "close to second", mouseX: pos.x, mouseY: pos.y, expectedCurrentIndex: 0 });
pos = MathUtils.centerAlongCircle(xCenter, yCenter, 0, 0, centerAngleFunction(1), pieMenu.__style.radius - 1);
data.push({ name: "outside", mouseX: pos.x, mouseY: pos.y, expectedCurrentIndex: 1 });
pos = MathUtils.centerAlongCircle(xCenter, yCenter, 0, 0, centerAngleFunction(1) - MathUtils.degToRad(10),
pieMenu.__style.cancelRadius + (pieMenu.__style.radius - pieMenu.__style.cancelRadius) / 2);
data.push({ name: "inside", mouseX: pos.x, mouseY: pos.y, expectedCurrentIndex: 1 });
pos = MathUtils.centerAlongCircle(xCenter, yCenter, 0, 0, startAngleFunction(1) + MathUtils.degToRad(1),
pieMenu.__style.radius - 1);
data.push({ name: "close to first", mouseX: pos.x, mouseY: pos.y, expectedCurrentIndex: 1 });
pos = MathUtils.centerAlongCircle(xCenter, yCenter, 0, 0, centerAngleFunction(1), pieMenu.__style.cancelRadius + 10);
data.push({ name: "low center", mouseX: 100, mouseY: 50, expectedCurrentIndex: 1 });
for (var i = 0; i < data.length; ++i) {
var mouseX = data[i].mouseX;
var mouseY = data[i].mouseY;
var expectedCurrentIndex = data[i].expectedCurrentIndex;
// Illustrates the positions.
// debugMousePosition(pieMenu, mouseX, mouseY, i);
// wait(1000)
mouseMove(root, mouseX, mouseY);
compare(pieMenu.currentIndex, expectedCurrentIndex, data[i].name + ": current index should be "
+ expectedCurrentIndex + " when mouse is at " + mouseX + ", " + mouseY);
}
pieMenuComponent.destroy()
}
function test_QTRD3027() {
// Check that an item's selection is cleared when the mouse moves outside
// its boundaries without changing the selectionAngle
if (Settings.hasTouchScreen)
skip("Fails with touch screens");
var pieMenuComponent = Qt.createComponent("PieMenu3Items.qml");
tryCompare(pieMenuComponent, "status", Component.Ready);
var root = createTemporaryObject(pieMenuComponent, container);
var mouseArea = root.mouseArea;
var pieMenu = root.pieMenu;
// Make the menu visible at (0,0)
root.forceActiveFocus();
mouseClick(root, 0, 0);
tryCompare(pieMenu, "visible", true);
// Move the mouse over the menu
mouseMove(root, 0, 0)
compare(pieMenu.currentIndex, -1)
// Move over middle item
mouseMove(root, 100, 50)
compare(pieMenu.currentIndex, 1)
selectedAngleChangedSpy.signalName = "selectionAngleChanged"
selectedAngleChangedSpy.target = pieMenu;
// Move outside the middle item without changing angle
mouseMove(root, 100, 98)
compare(pieMenu.currentIndex, -1)
compare(selectedAngleChangedSpy.count, 0)
pieMenuComponent.destroy()
}
function test_rotatedBoundingItem() {
if (Settings.hasTouchScreen)
skip("Fails with touch screens");
var pieMenuComponent = Qt.createComponent("PieMenuRotatedBoundingItem.qml");
tryCompare(pieMenuComponent, "status", Component.Ready);
var root = createTemporaryObject(pieMenuComponent, container);
var mouseArea = root.mouseArea;
var pieMenu = root.pieMenu;
mouseClick(root, root.width / 2, root.height / 2, Qt.RightButton);
tryCompare(pieMenu, "visible", true);
mouseMove(root, 230, 145);
// Not all styles have titles.
if (pieMenu.__style.title)
tryCompare(pieMenu.__panel.titleItem, "text", "Action 1");
actionSignalSpy.signalName = "actionTriggered";
actionSignalSpy.target = root;
mouseClick(root, 230, 145);
compare(actionSignalSpy.count, 1);
compare(actionSignalSpy.signalArguments[0][0], 0);
pieMenuComponent.destroy()
}
function test_boundingItem() {
var oldContainerWidth = container.width;
var oldContainerHeight = container.height;
container.width = 560;
container.height = 560;
// Tests boundingItem when there are nested margins.
var pieMenuComponent = Qt.createComponent("PieMenuBoundingItem.qml");
tryCompare(pieMenuComponent, "status", Component.Ready);
var root = createTemporaryObject(pieMenuComponent, container);
var mouseArea = root.mouseArea;
var pieMenu = root.pieMenu;
var mouseAreaAbsolutePos = mouseArea.mapToItem(root, 0, 0);
mouseClick(root, mouseAreaAbsolutePos.x + mouseArea.width / 2, mouseAreaAbsolutePos.y, Qt.RightButton);
compare(pieMenu.visible, true);
compare(pieMenu.y, -root.margins);
mouseClick(root, 0, 0);
compare(pieMenu.visible, false);
var mouseAreaCenterAbsolutePos = mouseArea.mapToItem(root, mouseArea.width / 2, mouseArea.height / 2);
mouseClick(root, mouseAreaCenterAbsolutePos.x, mouseAreaCenterAbsolutePos.y, Qt.RightButton);
compare(pieMenu.visible, true);
compare(pieMenu.mapToItem(root, 0, 0).x, mouseAreaCenterAbsolutePos.x - pieMenu.width / 2);
compare(pieMenu.mapToItem(root, 0, 0).y, mouseAreaCenterAbsolutePos.y - pieMenu.height / 2);
container.width = oldContainerWidth;
container.height = oldContainerHeight;
pieMenuComponent.destroy()
}
function test_longPressTriggerOnClick() {
// Tests that a menu that is opened on press or long press does not
// get closed by a release event when the triggerMode requires a
// press before the release (TriggerOnClick).
var pieMenuComponent = Qt.createComponent("PieMenu3ItemsLongPress.qml");
tryCompare(pieMenuComponent, "status", Component.Ready);
var root = createTemporaryObject(pieMenuComponent, container);
var pieMenu = root.pieMenu;
mousePress(root, 0, 0, Qt.LeftButton);
tryCompare(pieMenu, "visible", true);
compare(pieMenu.__mouseThief.receivedPressEvent, false);
compare(pieMenu.__protectedScope.pressedIndex, -1);
mouseRelease(root, 0, 0, Qt.LeftButton);
compare(pieMenu.visible, true);
compare(pieMenu.__mouseThief.receivedPressEvent, false);
compare(pieMenu.__protectedScope.pressedIndex, -1);
mousePress(root, 0, 0, Qt.LeftButton);
compare(pieMenu.visible, true);
compare(pieMenu.__mouseThief.receivedPressEvent, true);
compare(pieMenu.__protectedScope.pressedIndex, -1);
mouseRelease(root, 0, 0, Qt.LeftButton);
compare(pieMenu.visible, false);
compare(pieMenu.__mouseThief.receivedPressEvent, false);
compare(pieMenu.__protectedScope.pressedIndex, -1);
pieMenuComponent.destroy()
}
function test_keepMenuOpenWhenTriggered() {
// This functionality is used in the flat example.
var pieMenuComponent = Qt.createComponent("PieMenu3ItemsKeepOpen.qml");
tryCompare(pieMenuComponent, "status", Component.Ready);
var root = createTemporaryObject(pieMenuComponent, container);
var pieMenu = root.pieMenu;
actionSignalSpy.signalName = "actionTriggered";
actionSignalSpy.target = root;
mouseClick(root, 0, 0, Qt.LeftButton);
tryCompare(pieMenu, "visible", true);
mouseClick(root, pieMenu.x + pieMenu.width / 4, pieMenu.y + pieMenu.height / 4, Qt.LeftButton);
tryCompare(pieMenu, "visible", true);
compare(actionSignalSpy.count, 1);
compare(actionSignalSpy.signalArguments[0][0], 0);
actionSignalSpy.clear();
mouseClick(root, pieMenu.x + pieMenu.width / 2, pieMenu.y + pieMenu.height / 4, Qt.LeftButton);
tryCompare(pieMenu, "visible", true);
compare(actionSignalSpy.count, 1);
compare(actionSignalSpy.signalArguments[0][0], 1);
actionSignalSpy.clear();
mouseClick(root, pieMenu.x + pieMenu.width * 0.75, pieMenu.y + pieMenu.height / 4, Qt.LeftButton);
tryCompare(pieMenu, "visible", true);
compare(actionSignalSpy.count, 1);
compare(actionSignalSpy.signalArguments[0][0], 2);
pieMenuComponent.destroy()
}
function test_pressedIndex() {
var pieMenuComponent = Qt.createComponent("PieMenu3Items.qml");
tryCompare(pieMenuComponent, "status", Component.Ready);
var root = createTemporaryObject(pieMenuComponent, container);
var pieMenu = root.pieMenu;
actionSignalSpy.signalName = "actionTriggered";
actionSignalSpy.target = root;
mouseClick(root, 0, 0, Qt.LeftButton);
tryCompare(pieMenu, "visible", true);
compare(pieMenu.__protectedScope.pressedIndex, -1);
mousePress(root, pieMenu.x + pieMenu.width / 4, pieMenu.y + pieMenu.height / 4, Qt.LeftButton);
tryCompare(pieMenu, "visible", true);
compare(pieMenu.__protectedScope.pressedIndex, 0);
mouseRelease(root, pieMenu.x + pieMenu.width / 4, pieMenu.y + pieMenu.height / 4, Qt.LeftButton);
tryCompare(pieMenu, "visible", false);
compare(actionSignalSpy.count, 1);
compare(actionSignalSpy.signalArguments[0][0], 0);
compare(pieMenu.__protectedScope.pressedIndex, -1);
pieMenuComponent.destroy()
}
}
}