aboutsummaryrefslogtreecommitdiffstats
path: root/tests
diff options
context:
space:
mode:
Diffstat (limited to 'tests')
-rw-r--r--tests/auto/qml/debugger/qqmldebugjs/data/breakPointIds.qml15
-rw-r--r--tests/auto/qml/debugger/qqmldebugjs/data/letConstLocals.qml16
-rw-r--r--tests/auto/qml/debugger/qqmldebugjs/tst_qqmldebugjs.cpp148
-rw-r--r--tests/auto/qml/debugger/qv4debugger/tst_qv4debugger.cpp12
-rw-r--r--tests/auto/qml/qqmlcomponent/tst_qqmlcomponent.cpp2
-rw-r--r--tests/auto/qml/qqmldelegatemodel/data/qtbug_86017.qml32
-rw-r--r--tests/auto/qml/qqmldelegatemodel/tst_qqmldelegatemodel.cpp15
-rw-r--r--tests/auto/qml/qqmllanguage/data/hangOnWarning.qml3
-rw-r--r--tests/auto/qml/qqmllanguage/tst_qqmllanguage.cpp12
-rw-r--r--tests/auto/qmltest/qmltest.pro1
-rw-r--r--tests/auto/quick/pointerhandlers/qquicktaphandler/data/simpleTapHandler.qml (renamed from tests/auto/qmltest/pixel/tst_pixel.qml)46
-rw-r--r--tests/auto/quick/pointerhandlers/qquicktaphandler/tst_qquicktaphandler.cpp55
-rw-r--r--tests/auto/quick/qquickpincharea/data/draggablePinchArea.qml70
-rw-r--r--tests/auto/quick/qquickpincharea/tst_qquickpincharea.cpp66
-rw-r--r--tests/auto/quick/qquicktableview/tst_qquicktableview.cpp78
-rw-r--r--tests/auto/quick/scenegraph/data/render_AlphaOverlapRebuild.qml115
-rw-r--r--tests/auto/quick/scenegraph/data/widebtn1.pngbin0 -> 1969 bytes
-rw-r--r--tests/auto/quick/scenegraph/data/widebtn2.pngbin0 -> 1965 bytes
-rw-r--r--tests/auto/quick/scenegraph/tst_scenegraph.cpp4
19 files changed, 628 insertions, 62 deletions
diff --git a/tests/auto/qml/debugger/qqmldebugjs/data/breakPointIds.qml b/tests/auto/qml/debugger/qqmldebugjs/data/breakPointIds.qml
new file mode 100644
index 0000000000..c3e7687831
--- /dev/null
+++ b/tests/auto/qml/debugger/qqmldebugjs/data/breakPointIds.qml
@@ -0,0 +1,15 @@
+import QtQml 2.15
+Timer {
+ Component.onCompleted: {
+ console.log('0')
+ console.log('1')
+ console.log('2')
+ console.log('3')
+ console.log('4')
+ console.log('5')
+ running = true
+ }
+
+ interval: 0
+ onTriggered: Qt.quit()
+}
diff --git a/tests/auto/qml/debugger/qqmldebugjs/data/letConstLocals.qml b/tests/auto/qml/debugger/qqmldebugjs/data/letConstLocals.qml
new file mode 100644
index 0000000000..1715992490
--- /dev/null
+++ b/tests/auto/qml/debugger/qqmldebugjs/data/letConstLocals.qml
@@ -0,0 +1,16 @@
+import QtQml 2.15
+
+Timer {
+ Component.onCompleted: {
+ var a = 97
+ var b = 98
+ var c = 99
+ let d = 100
+ const e = 101
+ console.log("onClicked") // Set breakpoint
+ running = true
+ }
+
+ interval: 0
+ onTriggered: Qt.quit()
+}
diff --git a/tests/auto/qml/debugger/qqmldebugjs/tst_qqmldebugjs.cpp b/tests/auto/qml/debugger/qqmldebugjs/tst_qqmldebugjs.cpp
index 91470e0651..43c81ee515 100644
--- a/tests/auto/qml/debugger/qqmldebugjs/tst_qqmldebugjs.cpp
+++ b/tests/auto/qml/debugger/qqmldebugjs/tst_qqmldebugjs.cpp
@@ -65,6 +65,8 @@ const char *STEPACTION_QMLFILE = "stepAction.qml";
const char *BREAKPOINTRELOCATION_QMLFILE = "breakpointRelocation.qml";
const char *ENCODEQMLSCOPE_QMLFILE = "encodeQmlScope.qml";
const char *BREAKONANCHOR_QMLFILE = "breakOnAnchor.qml";
+const char *BREAKPOINTIDS_QMLFILE = "breakPointIds.qml";
+const char *LETCONSTLOCALS_QMLFILE = "letConstLocals.qml";
#undef QVERIFY
#define QVERIFY(statement) \
@@ -156,6 +158,9 @@ private slots:
void encodeQmlScope();
void breakOnAnchor();
+ void breakPointIds();
+ void letConstLocals();
+
private:
ConnectResult init(bool qmlscene, const QString &qmlFile = QString(TEST_QMLFILE),
bool blockMode = true, bool restrictServices = false);
@@ -165,10 +170,11 @@ private:
void targetData();
bool waitForClientSignal(const char *signal, int timeout = 30000);
void checkVersionParameters();
+ int setBreakPoint(const QString &file, int sourceLine, bool enabled);
+ void clearBreakPoint(int id);
};
-
void tst_QQmlDebugJS::initTestCase()
{
QQmlDebugTest::initTestCase();
@@ -566,7 +572,8 @@ void tst_QQmlDebugJS::changeBreakpoint()
int sourceLine2 = 37;
int sourceLine1 = 38;
- QCOMPARE(init(qmlscene, CHANGEBREAKPOINT_QMLFILE), ConnectSuccess);
+ const QString file = QLatin1String(CHANGEBREAKPOINT_QMLFILE);
+ QCOMPARE(init(qmlscene, file), ConnectSuccess);
bool isStopped = false;
QObject::connect(m_client.data(), &QV4DebugClient::stopped, this, [&]() { isStopped = true; });
@@ -589,27 +596,13 @@ void tst_QQmlDebugJS::changeBreakpoint()
return breakpointsHit[0].toInt();
};
- auto setBreakPoint = [&](int sourceLine, bool enabled) {
- int id = -1;
- auto connection = QObject::connect(m_client.data(), &QV4DebugClient::result, [&]() {
- id = extractBody().value("breakpoint").toInt();
- });
-
- m_client->setBreakpoint(QLatin1String(CHANGEBREAKPOINT_QMLFILE), sourceLine, -1, enabled);
- bool success = QTest::qWaitFor([&]() { return id >= 0; });
- Q_UNUSED(success);
-
- QObject::disconnect(connection);
- return id;
- };
-
//The breakpoints are in a timer loop so we can set them after connect().
//Furthermore the breakpoints should be hit in the right order because setting of breakpoints
//can only occur in the QML event loop. (see QCOMPARE for sourceLine2 below)
- const int breakpoint1 = setBreakPoint(sourceLine1, false);
+ const int breakpoint1 = setBreakPoint(file, sourceLine1, false);
QVERIFY(breakpoint1 >= 0);
- const int breakpoint2 = setBreakPoint(sourceLine2, true);
+ const int breakpoint2 = setBreakPoint(file, sourceLine2, true);
QVERIFY(breakpoint2 >= 0);
auto verifyBreakpoint = [&](int sourceLine, int breakpointId) {
@@ -1026,6 +1019,96 @@ void tst_QQmlDebugJS::breakOnAnchor()
QCOMPARE(breaks, 2);
}
+void tst_QQmlDebugJS::breakPointIds()
+{
+ QString file(BREAKPOINTIDS_QMLFILE);
+ QCOMPARE(init(true, file), ConnectSuccess);
+
+ int breaks = 0;
+ int breakPointIds[] = { -1, -1, -1, -1, -1, -1};
+
+ QObject::connect(m_client.data(), &QV4DebugClient::stopped, this, [&]() {
+ const QJsonObject body = m_client->response().body.toObject();
+ QCOMPARE(body.value("sourceLine").toInt(), breaks + 4);
+ const QJsonArray breakpointsHit = body.value("breakpoints").toArray();
+ QVERIFY(breakpointsHit.size() > 0);
+ QCOMPARE(breakpointsHit[0].toInt(), breakPointIds[breaks]);
+ ++breaks;
+ m_client->continueDebugging(QV4DebugClient::Continue);
+ });
+
+ for (int i = 0; i < 6; ++i)
+ breakPointIds[i] = setBreakPoint(file, i + 4, true);
+
+ clearBreakPoint(breakPointIds[2]);
+ breakPointIds[2] = setBreakPoint(file, 6, true);
+
+ QTRY_COMPARE(m_process->state(), QProcess::Running);
+ m_client->connect();
+
+ QTRY_COMPARE(m_process->state(), QProcess::NotRunning);
+ QCOMPARE(m_process->exitStatus(), QProcess::NormalExit);
+
+ QCOMPARE(breaks, 6);
+}
+
+void tst_QQmlDebugJS::letConstLocals()
+{
+ QString file(LETCONSTLOCALS_QMLFILE);
+ QCOMPARE(init(true, file), ConnectSuccess);
+
+ QObject::connect(m_client.data(), &QV4DebugClient::stopped, this, [&]() {
+ m_client->frame();
+ });
+
+ int numScopes = 0;
+ QString expectedMembers = QStringLiteral("abcde");
+ QObject::connect(m_client.data(), &QV4DebugClient::result, this, [&]() {
+ const auto value = m_client->response();
+ if (value.command == QStringLiteral("frame")) {
+ const auto scopes = value.body.toObject().value(QStringLiteral("scopes")).toArray();
+ for (const auto &scope : scopes) {
+ const auto scopeObject = scope.toObject();
+ const int type = scopeObject.value("type").toInt();
+ if (type == 1 || type == 4) {
+ m_client->scope(scopeObject.value("index").toInt());
+ ++numScopes;
+ }
+ }
+ QVERIFY(numScopes > 0);
+ } else if (value.command == QStringLiteral("scope")) {
+ const auto props = value.body.toObject().value(QStringLiteral("object")).toObject()
+ .value(QStringLiteral("properties")).toArray();
+ for (const auto &prop : props) {
+ const auto propObj = prop.toObject();
+ const QString name = propObj.value(QStringLiteral("name")).toString();
+ if (name == QStringLiteral("onCompleted"))
+ continue;
+ QVERIFY(name.length() == 1);
+ auto i = expectedMembers.indexOf(name.at(0));
+ QVERIFY(i != -1);
+ expectedMembers.remove(i, 1);
+ QCOMPARE(propObj.value(QStringLiteral("type")).toString(),
+ QStringLiteral("number"));
+ QCOMPARE(propObj.value(QStringLiteral("value")).toInt(),
+ int(name.at(0).toLatin1()));
+ }
+ if (--numScopes == 0) {
+ QVERIFY(expectedMembers.isEmpty());
+ m_client->continueDebugging(QV4DebugClient::Continue);
+ }
+ }
+ });
+
+ setBreakPoint(file, 10, true);
+
+ QTRY_COMPARE(m_process->state(), QProcess::Running);
+ m_client->connect();
+
+ QTRY_COMPARE(m_process->state(), QProcess::NotRunning);
+ QCOMPARE(m_process->exitStatus(), QProcess::NormalExit);
+}
+
QList<QQmlDebugClient *> tst_QQmlDebugJS::createClients()
{
m_client = new QV4DebugClient(m_connection);
@@ -1054,6 +1137,35 @@ void tst_QQmlDebugJS::checkVersionParameters()
QCOMPARE(body.value("ChangeBreakpoint").toBool(), true);
}
+int tst_QQmlDebugJS::setBreakPoint(const QString &file, int sourceLine, bool enabled)
+{
+ int id = -1;
+ auto connection = QObject::connect(m_client.data(), &QV4DebugClient::result, [&]() {
+ id = m_client->response().body.toObject().value("breakpoint").toInt();
+ });
+
+ m_client->setBreakpoint(file, sourceLine, -1, enabled);
+ bool success = QTest::qWaitFor([&]() { return id >= 0; });
+ Q_UNUSED(success);
+
+ QObject::disconnect(connection);
+ return id;
+}
+
+void tst_QQmlDebugJS::clearBreakPoint(int id)
+{
+ bool ok = false;
+ auto connection = QObject::connect(m_client.data(), &QV4DebugClient::result, [&]() {
+ ok = true;
+ });
+
+ m_client->clearBreakpoint(id);
+ bool success = QTest::qWaitFor([&]() { return ok; });
+ Q_UNUSED(success);
+
+ QObject::disconnect(connection);
+}
+
QTEST_MAIN(tst_QQmlDebugJS)
#include "tst_qqmldebugjs.moc"
diff --git a/tests/auto/qml/debugger/qv4debugger/tst_qv4debugger.cpp b/tests/auto/qml/debugger/qv4debugger/tst_qv4debugger.cpp
index e3cbeb9891..e4e7728508 100644
--- a/tests/auto/qml/debugger/qv4debugger/tst_qv4debugger.cpp
+++ b/tests/auto/qml/debugger/qv4debugger/tst_qv4debugger.cpp
@@ -575,21 +575,29 @@ void tst_qv4debugger::readLocals()
QString script =
"var f = function(a, b) {\n"
" var c = a + b\n"
+ " let e = 'jaja'\n"
+ " const ff = 'nenene'\n"
" var d = a - b\n" // breakpoint, c should be set, d should be undefined
" return c === d\n"
"}\n"
"f(1, 2, 3);\n";
- debugger()->addBreakPoint("readLocals", 3);
+ debugger()->addBreakPoint("readLocals", 5);
evaluateJavaScript(script, "readLocals");
QVERIFY(m_debuggerAgent->m_wasPaused);
QVERIFY(m_debuggerAgent->m_capturedScope.size() > 1);
const TestAgent::NamedRefs &frame0 = m_debuggerAgent->m_capturedScope.at(0);
- QCOMPARE(frame0.size(), 5); // locals and parameters
+ QCOMPARE(frame0.size(), 7); // locals and parameters
QVERIFY(frame0.contains("c"));
QCOMPARE(frame0.type("c"), QStringLiteral("number"));
QCOMPARE(frame0.value("c").toDouble(), 3.0);
QVERIFY(frame0.contains("d"));
QCOMPARE(frame0.type("d"), QStringLiteral("undefined"));
+ QVERIFY(frame0.contains("e"));
+ QCOMPARE(frame0.type("e"), QStringLiteral("string"));
+ QCOMPARE(frame0.value("e").toString(), QStringLiteral("jaja"));
+ QVERIFY(frame0.contains("ff"));
+ QCOMPARE(frame0.type("ff"), QStringLiteral("string"));
+ QCOMPARE(frame0.value("ff").toString(), QStringLiteral("nenene"));
}
void tst_qv4debugger::readObject()
diff --git a/tests/auto/qml/qqmlcomponent/tst_qqmlcomponent.cpp b/tests/auto/qml/qqmlcomponent/tst_qqmlcomponent.cpp
index 43cbd93396..544569de5f 100644
--- a/tests/auto/qml/qqmlcomponent/tst_qqmlcomponent.cpp
+++ b/tests/auto/qml/qqmlcomponent/tst_qqmlcomponent.cpp
@@ -828,7 +828,7 @@ void tst_qqmlcomponent::testSetInitialProperties()
comp.createWithInitialProperties(QVariantMap { {"notThePropertiesYoureLookingFor", 42} })
};
QVERIFY(obj);
- QVERIFY(comp.errorString().contains("Could not set property notThePropertiesYoureLookingFor"));
+ QVERIFY(comp.errorString().contains("Setting initial properties failed: Item does not have a property called notThePropertiesYoureLookingFor"));
}
}
diff --git a/tests/auto/qml/qqmldelegatemodel/data/qtbug_86017.qml b/tests/auto/qml/qqmldelegatemodel/data/qtbug_86017.qml
new file mode 100644
index 0000000000..02d737e37f
--- /dev/null
+++ b/tests/auto/qml/qqmldelegatemodel/data/qtbug_86017.qml
@@ -0,0 +1,32 @@
+import QtQuick 2.8
+import QtQml.Models 2.1
+
+DelegateModel {
+ id: visualModel
+ model: ListModel {
+ id: myLM
+ ListElement {
+ name: "Apple"
+ }
+ ListElement {
+ name: "Orange"
+ }
+ }
+
+ filterOnGroup: "selected"
+
+ groups: [
+ DelegateModelGroup {
+ name: "selected"
+ includeByDefault: true
+ }
+ ]
+
+ delegate: Text {
+ Component.onCompleted: {
+ DelegateModel.inPersistedItems = true
+ DelegateModel.inSelected = false
+ }
+ text: "item " + index
+ }
+}
diff --git a/tests/auto/qml/qqmldelegatemodel/tst_qqmldelegatemodel.cpp b/tests/auto/qml/qqmldelegatemodel/tst_qqmldelegatemodel.cpp
index 71550a50f3..9bc359d243 100644
--- a/tests/auto/qml/qqmldelegatemodel/tst_qqmldelegatemodel.cpp
+++ b/tests/auto/qml/qqmldelegatemodel/tst_qqmldelegatemodel.cpp
@@ -45,6 +45,7 @@ private slots:
void valueWithoutCallingObjectFirst_data();
void valueWithoutCallingObjectFirst();
void filterOnGroup_removeWhenCompleted();
+ void qtbug_86017();
};
class AbstractItemModel : public QAbstractItemModel
@@ -147,6 +148,20 @@ void tst_QQmlDelegateModel::filterOnGroup_removeWhenCompleted()
QQmlDelegateModel *model = root->findChild<QQmlDelegateModel*>();
QVERIFY(model);
QTest::qWaitFor([=]{ return model->count() == 2; } );
+
+void tst_QQmlDelegateModel::qtbug_86017()
+{
+ QQmlEngine engine;
+ QQmlComponent component(&engine);
+ component.loadUrl(testFileUrl("qtbug_86017.qml"));
+ QScopedPointer<QObject> root(component.create());
+ QVERIFY2(root, qPrintable(component.errorString()));
+ QTRY_VERIFY(component.isReady());
+ QQmlDelegateModel *model = qobject_cast<QQmlDelegateModel*>(root.data());
+
+ QVERIFY(model);
+ QCOMPARE(model->count(), 2);
+ QCOMPARE(model->filterGroup(), "selected");
}
QTEST_MAIN(tst_QQmlDelegateModel)
diff --git a/tests/auto/qml/qqmllanguage/data/hangOnWarning.qml b/tests/auto/qml/qqmllanguage/data/hangOnWarning.qml
new file mode 100644
index 0000000000..51943c3839
--- /dev/null
+++ b/tests/auto/qml/qqmllanguage/data/hangOnWarning.qml
@@ -0,0 +1,3 @@
+import QtQml 2.15
+
+QtObject["foobar"] {}
diff --git a/tests/auto/qml/qqmllanguage/tst_qqmllanguage.cpp b/tests/auto/qml/qqmllanguage/tst_qqmllanguage.cpp
index de8b2ef7eb..94ecd6862a 100644
--- a/tests/auto/qml/qqmllanguage/tst_qqmllanguage.cpp
+++ b/tests/auto/qml/qqmllanguage/tst_qqmllanguage.cpp
@@ -334,6 +334,8 @@ private slots:
void accessNullPointerPropertyCache();
void bareInlineComponent();
+ void hangOnWarning();
+
private:
QQmlEngine engine;
QStringList defaultImportPathList;
@@ -5841,6 +5843,16 @@ void tst_qqmllanguage::bareInlineComponent()
QVERIFY(tab1Found);
}
+void tst_qqmllanguage::hangOnWarning()
+{
+ QTest::ignoreMessage(QtWarningMsg,
+ qPrintable(QStringLiteral("%1:3 : Ignored annotation")
+ .arg(testFileUrl("hangOnWarning.qml").toString())));
+ QQmlComponent component(&engine, testFileUrl("hangOnWarning.qml"));
+ QScopedPointer<QObject> object(component.create());
+ QVERIFY(object != nullptr);
+}
+
QTEST_MAIN(tst_qqmllanguage)
#include "tst_qqmllanguage.moc"
diff --git a/tests/auto/qmltest/qmltest.pro b/tests/auto/qmltest/qmltest.pro
index 8ad1541cbc..0b793269e9 100644
--- a/tests/auto/qmltest/qmltest.pro
+++ b/tests/auto/qmltest/qmltest.pro
@@ -15,7 +15,6 @@ SUBDIRS += \
listview \
objectmodel \
pathview \
- pixel \
positioners \
qqmlbinding \
qtbug46798 \
diff --git a/tests/auto/qmltest/pixel/tst_pixel.qml b/tests/auto/quick/pointerhandlers/qquicktaphandler/data/simpleTapHandler.qml
index e628fed1d8..1c18133f92 100644
--- a/tests/auto/qmltest/pixel/tst_pixel.qml
+++ b/tests/auto/quick/pointerhandlers/qquicktaphandler/data/simpleTapHandler.qml
@@ -1,6 +1,6 @@
/****************************************************************************
**
-** Copyright (C) 2016 The Qt Company Ltd.
+** Copyright (C) 2021 The Qt Company Ltd.
** Contact: https://www.qt.io/licensing/
**
** This file is part of the test suite of the Qt Toolkit.
@@ -26,40 +26,14 @@
**
****************************************************************************/
-import QtQuick 2.0
-import QtTest 1.1
-
-Rectangle {
- id:rect
- width: 40
- height: 40
- color:"red"
- TestCase {
- name: "Pixels"
- when: windowShown
-
- function test_pixel() {
- skip("test_pixel() is unstable, QTBUG-27671")
- var img = grabImage(rect);
- compare(img.pixel(20, 20), Qt.rgba(255, 0, 0, 255));
- compare(img.red(1,1), 255);
- compare(img.green(1,1), 0);
- compare(img.blue(1,1), 0);
- compare(img.alpha(1,1), 255);
-
- fuzzyCompare(img.red(1,1), 254, 2);
- fuzzyCompare(img.pixel(1,1), Qt.rgba(254, 0, 0, 254), 2);
- fuzzyCompare(img.pixel(1,1), "#FF0201", 2);
-
- rect.color = "blue";
- waitForRendering(rect);
- img = grabImage(rect);
- compare(img.pixel(20, 20), Qt.rgba(0, 0, 255, 255));
- compare(img.red(1,1), 0);
- compare(img.green(1,1), 0);
- compare(img.blue(1,1), 255);
- compare(img.alpha(1,1), 255);
- }
+import QtQuick 2.12
+Item {
+ id: root
+ width: 100
+ height: 100
+ property int tapCount: 0
+ TapHandler {
+ onTapped: { ++root.tapCount }
}
-} \ No newline at end of file
+}
diff --git a/tests/auto/quick/pointerhandlers/qquicktaphandler/tst_qquicktaphandler.cpp b/tests/auto/quick/pointerhandlers/qquicktaphandler/tst_qquicktaphandler.cpp
index 419afed3ac..52cef6248f 100644
--- a/tests/auto/quick/pointerhandlers/qquicktaphandler/tst_qquicktaphandler.cpp
+++ b/tests/auto/quick/pointerhandlers/qquicktaphandler/tst_qquicktaphandler.cpp
@@ -71,15 +71,25 @@ private slots:
void buttonsMultiTouch();
void componentUserBehavioralOverride();
void rightLongPressIgnoreWheel();
+ void nonTopLevelParentWindow();
private:
- void createView(QScopedPointer<QQuickView> &window, const char *fileName);
+ void createView(QScopedPointer<QQuickView> &window, const char *fileName,
+ QWindow *parent = nullptr);
QTouchDevice *touchDevice;
+ void mouseEvent(QEvent::Type type, Qt::MouseButton button, const QPoint &point,
+ QWindow *targetWindow, QWindow *mapToWindow);
};
-void tst_TapHandler::createView(QScopedPointer<QQuickView> &window, const char *fileName)
+void tst_TapHandler::createView(QScopedPointer<QQuickView> &window, const char *fileName,
+ QWindow *parent)
{
- window.reset(new QQuickView);
+ window.reset(new QQuickView(parent));
+ if (parent) {
+ parent->show();
+ QVERIFY(QTest::qWaitForWindowActive(parent));
+ }
+
window->setSource(testFileUrl(fileName));
QTRY_COMPARE(window->status(), QQuickView::Ready);
QQuickViewTestUtil::centerOnScreen(window.data());
@@ -90,6 +100,20 @@ void tst_TapHandler::createView(QScopedPointer<QQuickView> &window, const char *
QVERIFY(window->rootObject() != nullptr);
}
+void tst_TapHandler::mouseEvent(QEvent::Type type, Qt::MouseButton button, const QPoint &point,
+ QWindow *targetWindow, QWindow *mapToWindow)
+{
+ QVERIFY(targetWindow);
+ QVERIFY(mapToWindow);
+ auto buttons = button;
+ if (type == QEvent::MouseButtonRelease) {
+ buttons = Qt::NoButton;
+ }
+ QMouseEvent me(type, point, mapToWindow->mapToGlobal(point), button, buttons,
+ Qt::KeyboardModifiers());
+ QVERIFY(qApp->notify(targetWindow, &me));
+}
+
void tst_TapHandler::initTestCase()
{
// This test assumes that we don't get synthesized mouse events from QGuiApplication
@@ -745,6 +769,31 @@ void tst_TapHandler::rightLongPressIgnoreWheel()
QCOMPARE(tappedSpy.count(), 0);
}
+void tst_TapHandler::nonTopLevelParentWindow() // QTBUG-91716
+{
+ QScopedPointer<QQuickWindow> parentWindowPtr(new QQuickWindow);
+ auto parentWindow = parentWindowPtr.get();
+ parentWindow->setGeometry(400, 400, 250, 250);
+
+ QScopedPointer<QQuickView> windowPtr;
+ createView(windowPtr, "simpleTapHandler.qml", parentWindow);
+ auto window = windowPtr.get();
+ window->setGeometry(10, 10, 100, 100);
+
+ QQuickItem *root = window->rootObject();
+
+ auto p1 = QPoint(20, 20);
+ mouseEvent(QEvent::MouseButtonPress, Qt::LeftButton, p1, window, parentWindow);
+ mouseEvent(QEvent::MouseButtonRelease, Qt::LeftButton, p1, window, parentWindow);
+
+ QCOMPARE(root->property("tapCount").toInt(), 1);
+
+ QTest::touchEvent(window, touchDevice).press(0, p1, parentWindow).commit();
+ QTest::touchEvent(window, touchDevice).release(0, p1, parentWindow).commit();
+
+ QCOMPARE(root->property("tapCount").toInt(), 2);
+}
+
QTEST_MAIN(tst_TapHandler)
#include "tst_qquicktaphandler.moc"
diff --git a/tests/auto/quick/qquickpincharea/data/draggablePinchArea.qml b/tests/auto/quick/qquickpincharea/data/draggablePinchArea.qml
new file mode 100644
index 0000000000..3acf67b4b6
--- /dev/null
+++ b/tests/auto/quick/qquickpincharea/data/draggablePinchArea.qml
@@ -0,0 +1,70 @@
+import QtQuick 2.12
+
+Rectangle {
+ id: root
+ width: 600
+ height: 600
+
+ Rectangle {
+ objectName: "paContainer"
+ width: parent.width -100
+ height: parent.height - 100
+ border.color: "black"
+ anchors.centerIn: parent
+ transformOrigin: Item.Center
+
+ Rectangle {
+ width: 300
+ height: 300
+ color: "tomato"
+ PinchArea {
+ id: pa
+ anchors.fill: parent
+ pinch.target: parent
+ pinch.minimumScale: 0.5
+ pinch.maximumScale: 2
+ pinch.minimumRotation: -360
+ pinch.maximumRotation: 360
+ pinch.dragAxis: Pinch.XAndYAxis
+ pinch.minimumX: -100
+ pinch.maximumX: 300
+ pinch.minimumY: -100
+ pinch.maximumY: 300
+ }
+
+
+ Text { text: "this way up" }
+ }
+ }
+
+ // only for touch feedback / troubleshooting
+ Item {
+ id: glassPane
+ z: 10000
+ anchors.fill: parent
+
+ PointHandler {
+ id: ph1
+ target: Rectangle {
+ parent: glassPane
+ color: "green"
+ visible: ph1.active
+ x: ph1.point.position.x - width / 2
+ y: ph1.point.position.y - height / 2
+ width: 20; height: width; radius: width / 2
+ }
+ }
+
+ PointHandler {
+ id: ph2
+ target: Rectangle {
+ parent: glassPane
+ color: "blue"
+ visible: ph2.active
+ x: ph2.point.position.x - width / 2
+ y: ph2.point.position.y - height / 2
+ width: 20; height: width; radius: width / 2
+ }
+ }
+ }
+}
diff --git a/tests/auto/quick/qquickpincharea/tst_qquickpincharea.cpp b/tests/auto/quick/qquickpincharea/tst_qquickpincharea.cpp
index 5b7108d96b..367df96118 100644
--- a/tests/auto/quick/qquickpincharea/tst_qquickpincharea.cpp
+++ b/tests/auto/quick/qquickpincharea/tst_qquickpincharea.cpp
@@ -52,6 +52,8 @@ private slots:
void cancel();
void transformedPinchArea_data();
void transformedPinchArea();
+ void dragTransformedPinchArea_data();
+ void dragTransformedPinchArea();
private:
QQuickView *createView();
@@ -586,6 +588,70 @@ void tst_QQuickPinchArea::transformedPinchArea()
}
}
+void tst_QQuickPinchArea::dragTransformedPinchArea_data()
+{
+ QTest::addColumn<int>("rotation");
+ QTest::addColumn<QPoint>("p1");
+ QTest::addColumn<QPoint>("p2");
+ QTest::addColumn<QPoint>("delta");
+
+ QTest::newRow("unrotated")
+ << 0 << QPoint(100, 100) << QPoint(200, 100) << QPoint(40, 40);
+ QTest::newRow("20 deg")
+ << 20 << QPoint(100, 100) << QPoint(200, 100) << QPoint(40, 40);
+ QTest::newRow("90 deg")
+ << 90 << QPoint(100, 100) << QPoint(200, 100) << QPoint(0, 40);
+ QTest::newRow("180 deg")
+ << 180 << QPoint(100, 100) << QPoint(200, 100) << QPoint(40, 0);
+ QTest::newRow("225 deg")
+ << 210 << QPoint(200, 200) << QPoint(300, 200) << QPoint(80, 80);
+}
+
+void tst_QQuickPinchArea::dragTransformedPinchArea() // QTBUG-63673
+{
+ QFETCH(int, rotation);
+ QFETCH(QPoint, p1);
+ QFETCH(QPoint, p2);
+ QFETCH(QPoint, delta);
+ const int threshold = qApp->styleHints()->startDragDistance();
+
+ QQuickView *view = createView();
+ QScopedPointer<QQuickView> scope(view);
+ view->setSource(testFileUrl("draggablePinchArea.qml"));
+ view->show();
+ QVERIFY(QTest::qWaitForWindowExposed(view));
+ QVERIFY(view->rootObject());
+ QQuickPinchArea *pinchArea = view->rootObject()->findChild<QQuickPinchArea*>();
+ QVERIFY(pinchArea);
+ QQuickItem *pinchAreaTarget = pinchArea->parentItem();
+ QVERIFY(pinchAreaTarget);
+ QQuickItem *pinchAreaContainer = pinchAreaTarget->parentItem();
+ QVERIFY(pinchAreaContainer);
+ pinchAreaContainer->setRotation(rotation);
+
+ QTest::QTouchEventSequence pinchSequence = QTest::touchEvent(view, device);
+ // start pinch
+ pinchSequence.press(1, pinchArea->mapToScene(p1).toPoint(), view)
+ .press(2, pinchArea->mapToScene(p2).toPoint(), view).commit();
+ QQuickTouchUtils::flush(view);
+ pinchSequence.move(1, pinchArea->mapToScene(p1 + QPoint(threshold, threshold)).toPoint(), view)
+ .move(2, pinchArea->mapToScene(p2 + QPoint(threshold, threshold)).toPoint(), view).commit();
+ QQuickTouchUtils::flush(view);
+ pinchSequence.move(1, pinchArea->mapToScene(p1 + delta).toPoint(), view)
+ .move(2, pinchArea->mapToScene(p2 + delta).toPoint(), view).commit();
+ QQuickTouchUtils::flush(view);
+ QCOMPARE(pinchArea->pinch()->active(), true);
+ auto error = delta - QPoint(threshold, threshold) -
+ pinchAreaTarget->position().toPoint(); // expect 0, 0
+ QVERIFY(qAbs(error.x()) <= 1);
+ QVERIFY(qAbs(error.y()) <= 1);
+
+ // release pinch
+ pinchSequence.release(1, p1, view).release(2, p2, view).commit();
+ QQuickTouchUtils::flush(view);
+ QCOMPARE(pinchArea->pinch()->active(), false);
+}
+
QQuickView *tst_QQuickPinchArea::createView()
{
QQuickView *window = new QQuickView(nullptr);
diff --git a/tests/auto/quick/qquicktableview/tst_qquicktableview.cpp b/tests/auto/quick/qquicktableview/tst_qquicktableview.cpp
index d14c37d8e3..6d37fb44e3 100644
--- a/tests/auto/quick/qquicktableview/tst_qquicktableview.cpp
+++ b/tests/auto/quick/qquicktableview/tst_qquicktableview.cpp
@@ -169,6 +169,8 @@ private slots:
void checkTableviewInsideAsyncLoader();
void hideRowsAndColumns_data();
void hideRowsAndColumns();
+ void hideAndShowFirstColumn();
+ void hideAndShowFirstRow();
void checkThatRevisionedPropertiesCannotBeUsedInOldImports();
void checkSyncView_rootView_data();
void checkSyncView_rootView();
@@ -2413,6 +2415,82 @@ void tst_QQuickTableView::hideRowsAndColumns()
QVERIFY(!columnsToHideList.contains(column));
}
+void tst_QQuickTableView::hideAndShowFirstColumn()
+{
+ // Check that if we hide the first column, it will move
+ // the second column to the origin of the viewport. Then check
+ // that if we show the first column again, it will reappear at
+ // the origin of the viewport, and as such, pushing the second
+ // column to the right of it.
+ LOAD_TABLEVIEW("hiderowsandcolumns.qml");
+
+ const int modelSize = 5;
+ auto model = TestModelAsVariant(modelSize, modelSize);
+ tableView->setModel(model);
+
+ // Start by making the first column hidden
+ const auto columnsToHideList = QList<int>() << 0;
+ view->rootObject()->setProperty("columnsToHide", QVariant::fromValue(columnsToHideList));
+
+ WAIT_UNTIL_POLISHED;
+
+ const int expectedColumnCount = modelSize - columnsToHideList.count();
+ QCOMPARE(tableViewPrivate->loadedColumns.count(), expectedColumnCount);
+ QCOMPARE(tableViewPrivate->leftColumn(), 1);
+ QCOMPARE(tableView->contentX(), 0);
+ QCOMPARE(tableViewPrivate->loadedTableOuterRect.x(), 0);
+
+ // Make the first column in the model visible again
+ const auto emptyList = QList<int>();
+ view->rootObject()->setProperty("columnsToHide", QVariant::fromValue(emptyList));
+ tableView->forceLayout();
+
+ WAIT_UNTIL_POLISHED;
+
+ QCOMPARE(tableViewPrivate->loadedColumns.count(), modelSize);
+ QCOMPARE(tableViewPrivate->leftColumn(), 0);
+ QCOMPARE(tableView->contentX(), 0);
+ QCOMPARE(tableViewPrivate->loadedTableOuterRect.x(), 0);
+}
+
+void tst_QQuickTableView::hideAndShowFirstRow()
+{
+ // Check that if we hide the first row, it will move
+ // the second row to the origin of the viewport. Then check
+ // that if we show the first row again, it will reappear at
+ // the origin of the viewport, and as such, pushing the second
+ // row below it.
+ LOAD_TABLEVIEW("hiderowsandcolumns.qml");
+
+ const int modelSize = 5;
+ auto model = TestModelAsVariant(modelSize, modelSize);
+ tableView->setModel(model);
+
+ // Start by making the first row hidden
+ const auto rowsToHideList = QList<int>() << 0;
+ view->rootObject()->setProperty("rowsToHide", QVariant::fromValue(rowsToHideList));
+
+ WAIT_UNTIL_POLISHED;
+
+ const int expectedRowsCount = modelSize - rowsToHideList.count();
+ QCOMPARE(tableViewPrivate->loadedRows.count(), expectedRowsCount);
+ QCOMPARE(tableViewPrivate->topRow(), 1);
+ QCOMPARE(tableView->contentY(), 0);
+ QCOMPARE(tableViewPrivate->loadedTableOuterRect.y(), 0);
+
+ // Make the first row in the model visible again
+ const auto emptyList = QList<int>();
+ view->rootObject()->setProperty("rowsToHide", QVariant::fromValue(emptyList));
+ tableView->forceLayout();
+
+ WAIT_UNTIL_POLISHED;
+
+ QCOMPARE(tableViewPrivate->loadedRows.count(), modelSize);
+ QCOMPARE(tableViewPrivate->topRow(), 0);
+ QCOMPARE(tableView->contentY(), 0);
+ QCOMPARE(tableViewPrivate->loadedTableOuterRect.y(), 0);
+}
+
void tst_QQuickTableView::checkThatRevisionedPropertiesCannotBeUsedInOldImports()
{
// Check that if you use a QQmlAdaptorModel together with a Repeater, the
diff --git a/tests/auto/quick/scenegraph/data/render_AlphaOverlapRebuild.qml b/tests/auto/quick/scenegraph/data/render_AlphaOverlapRebuild.qml
new file mode 100644
index 0000000000..f06be8f553
--- /dev/null
+++ b/tests/auto/quick/scenegraph/data/render_AlphaOverlapRebuild.qml
@@ -0,0 +1,115 @@
+/****************************************************************************
+**
+** 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:GPL-EXCEPT$
+** 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.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 as published by the Free Software
+** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+import QtQuick 2.15
+
+/*
+ QTBUG-92984.
+
+ Have three Image (with semi-transparency) and two semi-transparent
+ Rectangle elements, and so all in the alpha render list, with images that
+ are big enough to not get atlased. (meaning the underlying nodes never get
+ merged, but the nodes for the Rectangle elements might)
+
+ Lay them out vertically below each other, with the two Rectangles on top of
+ the second and third Images, respectively. Then change (swap) the source
+ property of the Images. This triggers a rebuild in the batch renderer.
+
+ Verify that the results are still correct, i.e. that the two Rectangle
+ elements do not get merged. An incorrect result would be having the third
+ Image rendered on top of the corresponding Rectangle due the two Rectangles
+ (incorrectly) being in one merged batch. The Image should always be below,
+ regardless of which nodes get changed, invalidated, and how batches get
+ rebuilt.
+
+ The base-final sample set 1 just verifies that the Image changes from the
+ blueish to greenish. The important part is the second set of samples: this
+ checks that the red(ish) rectangle is still on top of the third Image. With
+ incorrect merging behavior the second final result would be the same as the
+ first final one (i.e. the "background" Image rendered, incorrectly, on top
+ of the Rectangle).
+
+ #samples: 4
+ PixelPos R G B Error-tolerance
+ #base: 30 115 0.24313 0.30588 0.99607 0.05
+ #base: 30 124 0.847059 0.062745 0.2 0.05
+ #final: 30 115 0.36078 0.99607 0.42745 0.05
+ #final: 30 124 0.870588 0.2 0.0862745 0.05
+*/
+
+RenderTestBase {
+ id: root
+
+ property string selectedItem: "item2"
+
+ Item {
+ width: 150; height: 50
+ Image {
+ width: parent.width
+ objectName: "item1"
+ source: "widebtn1.png"
+ }
+ }
+
+ Item {
+ y: 50; width: 150; height: 50
+ Image {
+ width: parent.width
+ objectName: "item2"
+ source: selectedItem == objectName ? "widebtn2.png" : "widebtn1.png"
+ }
+ Rectangle {
+ anchors.fill: parent
+ anchors.margins: 20
+ color: "red"
+ opacity: 0.8
+ }
+ }
+
+ Item {
+ y: 100; width: 150; height: 50
+ Image {
+ id: img3
+ width: parent.width
+ objectName: "item3"
+ source: selectedItem == objectName ? "widebtn2.png" : "widebtn1.png"
+ }
+ Rectangle {
+ width: parent.width + 50
+ anchors.centerIn: parent
+ height: img3.height - 40
+ color: "red"
+ opacity: 0.8
+ }
+ }
+
+ onEnterFinalStage: {
+ selectedItem = "item3";
+ finalStageComplete = true;
+ }
+}
diff --git a/tests/auto/quick/scenegraph/data/widebtn1.png b/tests/auto/quick/scenegraph/data/widebtn1.png
new file mode 100644
index 0000000000..1150b67a7a
--- /dev/null
+++ b/tests/auto/quick/scenegraph/data/widebtn1.png
Binary files differ
diff --git a/tests/auto/quick/scenegraph/data/widebtn2.png b/tests/auto/quick/scenegraph/data/widebtn2.png
new file mode 100644
index 0000000000..40afe08363
--- /dev/null
+++ b/tests/auto/quick/scenegraph/data/widebtn2.png
Binary files differ
diff --git a/tests/auto/quick/scenegraph/tst_scenegraph.cpp b/tests/auto/quick/scenegraph/tst_scenegraph.cpp
index 12f7efb7d5..cf85e262c0 100644
--- a/tests/auto/quick/scenegraph/tst_scenegraph.cpp
+++ b/tests/auto/quick/scenegraph/tst_scenegraph.cpp
@@ -402,7 +402,9 @@ void tst_SceneGraph::render_data()
<< "render_StackingOrder.qml"
<< "render_ImageFiltering.qml"
<< "render_bug37422.qml"
- << "render_OpacityThroughBatchRoot.qml";
+ << "render_OpacityThroughBatchRoot.qml"
+ << "render_AlphaOverlapRebuild.qml";
+
if (!m_brokenMipmapSupport)
files << "render_Mipmap.qml";