diff options
author | Frederik Gladhorn <frederik.gladhorn@digia.com> | 2014-05-09 16:25:58 +0200 |
---|---|---|
committer | Gunnar Sletta <gunnar.sletta@jollamobile.com> | 2014-05-10 11:53:47 +0200 |
commit | 66646dd8c37adb488a79ab274b2396a649674e6d (patch) | |
tree | b0f5ac752a52cec3de1d47692e09295197622dcd /tests | |
parent | da15ea0f3b5805db657f13060c21efa78f10cde2 (diff) | |
parent | d82a17b929dd88fe76258b0f801beaa1b2ee343e (diff) |
Merge remote-tracking branch 'origin/stable' into dev
Conflicts:
.qmake.conf
src/plugins/accessible/quick/quick.pro
src/quick/items/qquickpincharea.cpp
src/quick/scenegraph/coreapi/qsgbatchrenderer.cpp
src/quick/scenegraph/qsgthreadedrenderloop.cpp
Manually adjusted for TestHTTPServer constructor change:
tests/auto/quick/qquickimage/tst_qquickimage.cpp
Change-Id: I5e58a7c08ea92d6fc5e3bce98571c54f7b2ce08f
Diffstat (limited to 'tests')
90 files changed, 2724 insertions, 222 deletions
diff --git a/tests/auto/qml/debugger/qqmlprofilerservice/tst_qqmlprofilerservice.cpp b/tests/auto/qml/debugger/qqmlprofilerservice/tst_qqmlprofilerservice.cpp index 6dbdc83b08..a918e23a05 100644 --- a/tests/auto/qml/debugger/qqmlprofilerservice/tst_qqmlprofilerservice.cpp +++ b/tests/auto/qml/debugger/qqmlprofilerservice/tst_qqmlprofilerservice.cpp @@ -208,7 +208,9 @@ void QQmlProfilerClient::messageReceived(const QByteArray &message) switch (data.detailType) { case QQmlProfilerClient::AnimationFrame: { - stream >> data.framerate >> data.animationcount; + int threadId; + stream >> data.framerate >> data.animationcount >> threadId; + QVERIFY(threadId >= 0); QVERIFY(data.framerate != -1); QVERIFY(data.animationcount != -1); break; @@ -396,6 +398,7 @@ void tst_QQmlProfilerService::nonBlockingConnect() m_client->setTraceState(true); m_client->setTraceState(false); QVERIFY2(QQmlDebugTest::waitForSignal(m_client, SIGNAL(complete())), "No trace received in time."); + QVERIFY(m_client->traceMessages.count()); // must start with "StartTrace" QCOMPARE(m_client->traceMessages.first().messageType, (int)QQmlProfilerClient::Event); @@ -422,7 +425,8 @@ void tst_QQmlProfilerService::pixmapCacheData() m_client->setTraceState(false); QVERIFY2(QQmlDebugTest::waitForSignal(m_client, SIGNAL(complete())), "No trace received in time."); - QVERIFY(m_client->traceMessages.count() >= 20); + QVERIFY2(m_client->traceMessages.count() >= 20, + QString::number(m_client->traceMessages.count()).toUtf8().constData()); // must start with "StartTrace" QCOMPARE(m_client->traceMessages.first().messageType, (int)QQmlProfilerClient::Event); @@ -495,7 +499,8 @@ void tst_QQmlProfilerService::profileOnExit() m_client->setTraceState(true); QVERIFY2(QQmlDebugTest::waitForSignal(m_client, SIGNAL(complete())), "No trace received in time."); - QVERIFY(m_client->traceMessages.count() >= 2); + QVERIFY2(m_client->traceMessages.count() >= 2, + QString::number(m_client->traceMessages.count()).toUtf8().constData()); // must start with "StartTrace" QCOMPARE(m_client->traceMessages.first().messageType, (int)QQmlProfilerClient::Event); @@ -514,7 +519,8 @@ void tst_QQmlProfilerService::controlFromJS() m_client->setTraceState(false); QVERIFY2(QQmlDebugTest::waitForSignal(m_client, SIGNAL(complete())), "No trace received in time."); - QVERIFY(m_client->traceMessages.count() >= 2); + QVERIFY2(m_client->traceMessages.count() >= 2, + QString::number(m_client->traceMessages.count()).toUtf8().constData()); // must start with "StartTrace" QCOMPARE(m_client->traceMessages.first().messageType, (int)QQmlProfilerClient::Event); @@ -537,22 +543,26 @@ void tst_QQmlProfilerService::signalSourceLocation() m_client->setTraceState(false); QVERIFY2(QQmlDebugTest::waitForSignal(m_client, SIGNAL(complete())), "No trace received in time."); - QVERIFY(m_client->traceMessages.count() >= 20); + QVERIFY2(m_client->traceMessages.count() >= 20, + QString::number(m_client->traceMessages.count()).toUtf8().constData()); + // must start with "StartTrace" QCOMPARE(m_client->traceMessages.first().messageType, (int)QQmlProfilerClient::Event); QCOMPARE(m_client->traceMessages.first().detailType, (int)QQmlProfilerClient::StartTrace); - QVERIFY(m_client->traceMessages[14].messageType == QQmlProfilerClient::RangeLocation); - QVERIFY(m_client->traceMessages[14].detailType == QQmlProfilerClient::HandlingSignal); - QVERIFY(m_client->traceMessages[14].detailData.endsWith("signalSourceLocation.qml")); - QVERIFY(m_client->traceMessages[14].line == 8); - QVERIFY(m_client->traceMessages[14].column == 28); + QCOMPARE(m_client->traceMessages[14].messageType, (int)QQmlProfilerClient::RangeLocation); + QCOMPARE(m_client->traceMessages[14].detailType, (int)QQmlProfilerClient::HandlingSignal); + QVERIFY2(m_client->traceMessages[14].detailData.endsWith("signalSourceLocation.qml"), + m_client->traceMessages[14].detailData.toUtf8().constData()); + QCOMPARE(m_client->traceMessages[14].line, 8); + QCOMPARE(m_client->traceMessages[14].column, 28); - QVERIFY(m_client->traceMessages[19].messageType == QQmlProfilerClient::RangeLocation); - QVERIFY(m_client->traceMessages[19].detailType == QQmlProfilerClient::HandlingSignal); - QVERIFY(m_client->traceMessages[19].detailData.endsWith("signalSourceLocation.qml")); - QVERIFY(m_client->traceMessages[19].line == 7); - QVERIFY(m_client->traceMessages[19].column == 21); + QCOMPARE(m_client->traceMessages[19].messageType, (int)QQmlProfilerClient::RangeLocation); + QCOMPARE(m_client->traceMessages[19].detailType, (int)QQmlProfilerClient::HandlingSignal); + QVERIFY2(m_client->traceMessages[19].detailData.endsWith("signalSourceLocation.qml"), + m_client->traceMessages[19].detailData.toUtf8().constData()); + QCOMPARE(m_client->traceMessages[19].line, 7); + QCOMPARE(m_client->traceMessages[19].column, 21); // must end with "EndTrace" QCOMPARE(m_client->traceMessages.last().messageType, (int)QQmlProfilerClient::Event); @@ -571,26 +581,29 @@ void tst_QQmlProfilerService::javascript() m_client->setTraceState(false); QVERIFY2(QQmlDebugTest::waitForSignal(m_client, SIGNAL(complete())), "No trace received in time."); - QVERIFY(m_client->traceMessages.count() >= 36); + QVERIFY2(m_client->traceMessages.count() >= 36, + QString::number(m_client->traceMessages.count()).toUtf8().constData()); // must start with "StartTrace" QCOMPARE(m_client->traceMessages.first().messageType, (int)QQmlProfilerClient::Event); QCOMPARE(m_client->traceMessages.first().detailType, (int)QQmlProfilerClient::StartTrace); - QVERIFY(m_client->traceMessages[32].messageType == QQmlProfilerClient::RangeStart); - QVERIFY(m_client->traceMessages[32].detailType == QQmlProfilerClient::Javascript); + QCOMPARE(m_client->traceMessages[32].messageType, (int)QQmlProfilerClient::RangeStart); + QCOMPARE(m_client->traceMessages[32].detailType, (int)QQmlProfilerClient::Javascript); - QVERIFY(m_client->traceMessages[33].messageType == QQmlProfilerClient::RangeLocation); - QVERIFY(m_client->traceMessages[33].detailType == QQmlProfilerClient::Javascript); - QVERIFY(m_client->traceMessages[33].detailData.endsWith("javascript.qml")); - QVERIFY(m_client->traceMessages[33].line == 4); - QVERIFY(m_client->traceMessages[33].column == 5); + QCOMPARE(m_client->traceMessages[33].messageType, (int)QQmlProfilerClient::RangeLocation); + QCOMPARE(m_client->traceMessages[33].detailType, (int)QQmlProfilerClient::Javascript); + QVERIFY2(m_client->traceMessages[33].detailData.endsWith("javascript.qml"), + m_client->traceMessages[33].detailData.toUtf8().constData()); + QCOMPARE(m_client->traceMessages[33].line, 4); + QCOMPARE(m_client->traceMessages[33].column, 5); - QVERIFY(m_client->traceMessages[34].messageType == QQmlProfilerClient::RangeData); - QVERIFY(m_client->traceMessages[34].detailType == QQmlProfilerClient::Javascript); - QVERIFY(m_client->traceMessages[34].detailData == "something"); + QCOMPARE(m_client->traceMessages[34].messageType, (int)QQmlProfilerClient::RangeData); + QCOMPARE(m_client->traceMessages[34].detailType, (int)QQmlProfilerClient::Javascript); + QVERIFY2(m_client->traceMessages[34].detailData == "something", + m_client->traceMessages[34].detailData.toUtf8().constData()); - QVERIFY(m_client->traceMessages[35].messageType == QQmlProfilerClient::RangeEnd); - QVERIFY(m_client->traceMessages[35].detailType == QQmlProfilerClient::Javascript); + QCOMPARE(m_client->traceMessages[35].messageType, (int)QQmlProfilerClient::RangeEnd); + QCOMPARE(m_client->traceMessages[35].detailType, (int)QQmlProfilerClient::Javascript); // must end with "EndTrace" QCOMPARE(m_client->traceMessages.last().messageType, (int)QQmlProfilerClient::Event); diff --git a/tests/auto/qml/qjsengine/tst_qjsengine.cpp b/tests/auto/qml/qjsengine/tst_qjsengine.cpp index 53e86268a6..b2723b02fd 100644 --- a/tests/auto/qml/qjsengine/tst_qjsengine.cpp +++ b/tests/auto/qml/qjsengine/tst_qjsengine.cpp @@ -48,6 +48,7 @@ #include <qstandarditemmodel.h> #include <QtCore/qnumeric.h> #include <qqmlengine.h> +#include <qqmlcomponent.h> #include <stdlib.h> #include <private/qv4alloca_p.h> @@ -115,7 +116,8 @@ private slots: void jsForInStatement_prototypeProperties(); void jsForInStatement_mutateWhileIterating(); void jsForInStatement_arrays(); - void jsForInStatement_nullAndUndefined(); + void jsForInStatement_constant(); + void with_constant(); void stringObjects(); void jsStringPrototypeReplaceBugs(); void getterSetterThisObject_global(); @@ -150,6 +152,11 @@ private slots: void regexpLastMatch(); void indexedAccesses(); + void prototypeChainGc(); + void prototypeChainGc_QTBUG38299(); + + void dynamicProperties(); + signals: void testSignal(); }; @@ -162,6 +169,9 @@ tst_QJSEngine::~tst_QJSEngine() { } +Q_DECLARE_METATYPE(Qt::KeyboardModifier) +Q_DECLARE_METATYPE(Qt::KeyboardModifiers) + class OverloadedSlots : public QObject { Q_OBJECT @@ -174,6 +184,7 @@ signals: void slotWithoutArgCalled(); void slotWithSingleArgCalled(const QString &arg); void slotWithArgumentsCalled(const QString &arg1, const QString &arg2, const QString &arg3); + void slotWithOverloadedArgumentsCalled(const QString &arg, Qt::KeyboardModifier modifier, Qt::KeyboardModifiers moreModifiers); public slots: void slotToCall() { emit slotWithoutArgCalled(); } @@ -182,6 +193,10 @@ public slots: { slotWithArgumentsCalled(arg, arg2, arg3); } + void slotToCall(const QString &arg, Qt::KeyboardModifier modifier, Qt::KeyboardModifiers blah = Qt::ShiftModifier) + { + emit slotWithOverloadedArgumentsCalled(arg, modifier, blah); + } }; void tst_QJSEngine::callQObjectSlot() @@ -227,6 +242,18 @@ void tst_QJSEngine::callQObjectSlot() QCOMPARE(arguments.at(1).toString(), QString("arg2")); QCOMPARE(arguments.at(2).toString(), QString("arg3")); } + + { + QSignalSpy spy(&dummy, SIGNAL(slotWithOverloadedArgumentsCalled(QString, Qt::KeyboardModifier, Qt::KeyboardModifiers))); + eng.evaluate(QStringLiteral("dummy.slotToCall('arg', %1);").arg(QString::number(Qt::ControlModifier))); + QCOMPARE(spy.count(), 1); + + const QList<QVariant> arguments = spy.first(); + QCOMPARE(arguments.at(0).toString(), QString("arg")); + QCOMPARE(arguments.at(1).toInt(), int(Qt::ControlModifier)); + QCOMPARE(int(qvariant_cast<Qt::KeyboardModifiers>(arguments.at(2))), int(Qt::ShiftModifier)); + + } } void tst_QJSEngine::constructWithParent() @@ -1011,6 +1038,8 @@ void tst_QJSEngine::evaluate_data() QTest::newRow("/a/g") << QString("/a/g") << -1 << false << -1; QTest::newRow("/a/gim") << QString("/a/gim") << -1 << false << -1; QTest::newRow("/a/gimp") << QString("/a/gimp") << 1 << true << 1; + QTest::newRow("empty-array-concat") << QString("var a = []; var b = [1]; var c = a.concat(b); ") << 1 << false << -1; + QTest::newRow("object-literal") << QString("var a = {\"0\":\"#\",\"2\":\"#\",\"5\":\"#\",\"8\":\"#\",\"6\":\"#\",\"12\":\"#\",\"13\":\"#\",\"16\":\"#\",\"18\":\"#\",\"39\":\"#\",\"40\":\"#\"}") << 1 << false << -1; } void tst_QJSEngine::evaluate() @@ -1207,6 +1236,14 @@ void tst_QJSEngine::valueConversion_QVariant() QCOMPARE(qjsvalue_cast<QVariant>(QJSValue(123)), QVariant(123)); QVERIFY(eng.toScriptValue(QVariant(QMetaType::VoidStar, 0)).isNull()); + + { + QVariantMap map; + map.insert("42", "the answer to life the universe and everything"); + QJSValue val = eng.toScriptValue(map); + QVERIFY(val.isObject()); + QCOMPARE(val.property(42).toString(), map.value(QStringLiteral("42")).toString()); + } } void tst_QJSEngine::valueConversion_basic2() @@ -1982,7 +2019,7 @@ void tst_QJSEngine::jsForInStatement_arrays() } } -void tst_QJSEngine::jsForInStatement_nullAndUndefined() +void tst_QJSEngine::jsForInStatement_constant() { QJSEngine eng; { @@ -1995,6 +2032,34 @@ void tst_QJSEngine::jsForInStatement_nullAndUndefined() QVERIFY(ret.isBool()); QVERIFY(ret.toBool()); } + { + QJSValue ret = eng.evaluate("r = false; for (var p in 1) r = true; r"); + QVERIFY(ret.isBool()); + QVERIFY(!ret.toBool()); + } + { + QJSValue ret = eng.evaluate("r = false; for (var p in 'abc') r = true; r"); + QVERIFY(ret.isBool()); + QVERIFY(ret.toBool()); + } +} + +void tst_QJSEngine::with_constant() +{ + QJSEngine eng; + { + QJSValue ret = eng.evaluate("r = false; with(null) { r= true; } r"); + QVERIFY(ret.isError()); + } + { + QJSValue ret = eng.evaluate("r = false; with(undefined) { r= true; } r"); + QVERIFY(ret.isError()); + } + { + QJSValue ret = eng.evaluate("r = false; with(1) { r= true; } r"); + QVERIFY(ret.isBool()); + QVERIFY(ret.toBool()); + } } void tst_QJSEngine::stringObjects() @@ -2883,6 +2948,69 @@ void tst_QJSEngine::indexedAccesses() QVERIFY(v.isUndefined()); } +void tst_QJSEngine::prototypeChainGc() +{ + QJSEngine engine; + + QJSValue getProto = engine.evaluate("Object.getPrototypeOf"); + + QJSValue factory = engine.evaluate("function() { return Object.create(Object.create({})); }"); + QVERIFY(factory.isCallable()); + QJSValue obj = factory.call(); + engine.collectGarbage(); + + QJSValue proto = getProto.call(QJSValueList() << obj); + proto = getProto.call(QJSValueList() << proto); + QVERIFY(proto.isObject()); +} + +void tst_QJSEngine::prototypeChainGc_QTBUG38299() +{ + QJSEngine engine; + engine.evaluate("var mapping = {" + "'prop1': \"val1\",\n" + "'prop2': \"val2\"\n" + "}\n" + "\n" + "delete mapping.prop2\n" + "delete mapping.prop1\n" + "\n"); + // Don't hang! + engine.collectGarbage(); +} + +void tst_QJSEngine::dynamicProperties() +{ + { + QJSEngine engine; + QObject *obj = new QObject; + QJSValue wrapper = engine.newQObject(obj); + wrapper.setProperty("someRandomProperty", 42); + QCOMPARE(wrapper.property("someRandomProperty").toInt(), 42); + QVERIFY(!qmlContext(obj)); + } + { + QQmlEngine qmlEngine; + QQmlComponent component(&qmlEngine); + component.setData("import QtQml 2.0; QtObject { property QtObject subObject: QtObject {} }", QUrl()); + QObject *root = component.create(0); + QVERIFY(root); + QVERIFY(qmlContext(root)); + + QJSValue wrapper = qmlEngine.newQObject(root); + wrapper.setProperty("someRandomProperty", 42); + QVERIFY(!wrapper.hasProperty("someRandomProperty")); + + QObject *subObject = qvariant_cast<QObject*>(root->property("subObject")); + QVERIFY(subObject); + QVERIFY(qmlContext(subObject)); + + wrapper = qmlEngine.newQObject(subObject); + wrapper.setProperty("someRandomProperty", 42); + QVERIFY(!wrapper.hasProperty("someRandomProperty")); + } +} + QTEST_MAIN(tst_QJSEngine) #include "tst_qjsengine.moc" diff --git a/tests/auto/qml/qml.pro b/tests/auto/qml/qml.pro index 74369685f5..c909a2d35a 100644 --- a/tests/auto/qml/qml.pro +++ b/tests/auto/qml/qml.pro @@ -68,7 +68,7 @@ qtHaveModule(widgets) { SUBDIRS += $$PUBLICTESTS SUBDIRS += $$METATYPETESTS -SUBDIRS += debugger +!winrt: SUBDIRS += debugger # no QProcess on winrt contains(QT_CONFIG, private_tests) { SUBDIRS += $$PRIVATETESTS diff --git a/tests/auto/qml/qqmlconnections/tst_qqmlconnections.cpp b/tests/auto/qml/qqmlconnections/tst_qqmlconnections.cpp index dbf48779d6..1cd1583f22 100644 --- a/tests/auto/qml/qqmlconnections/tst_qqmlconnections.cpp +++ b/tests/auto/qml/qqmlconnections/tst_qqmlconnections.cpp @@ -251,10 +251,9 @@ void tst_qqmlconnections::rewriteErrors() { QQmlEngine engine; QQmlComponent c(&engine, testFileUrl("rewriteError-unnamed.qml")); + QTest::ignoreMessage(QtWarningMsg, (c.url().toString() + ":5:35: QML Connections: Signal uses unnamed parameter followed by named parameter.").toLatin1()); TestObject *obj = qobject_cast<TestObject*>(c.create()); QVERIFY(obj != 0); - - QTest::ignoreMessage(QtWarningMsg, (c.url().toString() + ":5:35: QML Connections: Signal uses unnamed parameter followed by named parameter.").toLatin1()); obj->unnamedArgumentSignal(1, .5, "hello"); QCOMPARE(obj->ran(), false); @@ -264,10 +263,10 @@ void tst_qqmlconnections::rewriteErrors() { QQmlEngine engine; QQmlComponent c(&engine, testFileUrl("rewriteError-global.qml")); + QTest::ignoreMessage(QtWarningMsg, (c.url().toString() + ":5:35: QML Connections: Signal parameter \"parseInt\" hides global variable.").toLatin1()); TestObject *obj = qobject_cast<TestObject*>(c.create()); QVERIFY(obj != 0); - QTest::ignoreMessage(QtWarningMsg, (c.url().toString() + ":5:35: QML Connections: Signal parameter \"parseInt\" hides global variable.").toLatin1()); obj->signalWithGlobalName(10); QCOMPARE(obj->ran(), false); diff --git a/tests/auto/qml/qqmlecmascript/data/SubObject.qml b/tests/auto/qml/qqmlecmascript/data/SubObject.qml new file mode 100644 index 0000000000..4658edd1db --- /dev/null +++ b/tests/auto/qml/qqmlecmascript/data/SubObject.qml @@ -0,0 +1,8 @@ +import QtQml 2.0 +QtObject { + property int testValue: -1 + property int subValue; + onSubValueChanged: { + testValue = this.someExpression + } +} diff --git a/tests/auto/qml/qqmlecmascript/data/Types.js b/tests/auto/qml/qqmlecmascript/data/Types.js new file mode 100644 index 0000000000..8da80a9565 --- /dev/null +++ b/tests/auto/qml/qqmlecmascript/data/Types.js @@ -0,0 +1,3 @@ +.pragma library + +var Foo = 0; diff --git a/tests/auto/qml/qqmlecmascript/data/contextObjectOnLazyBindings.qml b/tests/auto/qml/qqmlecmascript/data/contextObjectOnLazyBindings.qml new file mode 100644 index 0000000000..33b21c74a8 --- /dev/null +++ b/tests/auto/qml/qqmlecmascript/data/contextObjectOnLazyBindings.qml @@ -0,0 +1,10 @@ +import QtQml 2.0 +QtObject { + property SubObject subObject: SubObject { + subValue: 20; + property int someExpression: { + return someValue; + } + } + property int someValue: 42 +} diff --git a/tests/auto/qml/qqmlecmascript/data/importedScriptsAccessOnObjectWithInvalidContext.qml b/tests/auto/qml/qqmlecmascript/data/importedScriptsAccessOnObjectWithInvalidContext.qml new file mode 100644 index 0000000000..74310c6d6b --- /dev/null +++ b/tests/auto/qml/qqmlecmascript/data/importedScriptsAccessOnObjectWithInvalidContext.qml @@ -0,0 +1,42 @@ +import QtQuick 2.0 + +import "Types.js" as Types + +Rectangle { + id: root + property bool success: false + + color: "white" + height: 100 + width: 100 + + signal modelChanged + + Timer { + id: timer + interval: 100 + onTriggered: { + root.modelChanged(); + root.success = true; + } + } + + Loader{ + id: weekPage + sourceComponent: Component { + Item{ + function createAllDayEvents() { + if (3 == Types.Foo) { + console.log("Hello") + } + } + } + } + onLoaded: root.modelChanged.connect(item.createAllDayEvents); + } + + Component.onCompleted: { + weekPage.sourceComponent = null + timer.running = true + } +} diff --git a/tests/auto/qml/qqmlecmascript/tst_qqmlecmascript.cpp b/tests/auto/qml/qqmlecmascript/tst_qqmlecmascript.cpp index 2809124028..770d6b8197 100644 --- a/tests/auto/qml/qqmlecmascript/tst_qqmlecmascript.cpp +++ b/tests/auto/qml/qqmlecmascript/tst_qqmlecmascript.cpp @@ -320,6 +320,8 @@ private slots: void singletonWithEnum(); void lazyBindingEvaluation(); void varPropertyAccessOnObjectWithInvalidContext(); + void importedScriptsAccessOnObjectWithInvalidContext(); + void contextObjectOnLazyBindings(); private: // static void propertyVarWeakRefCallback(v8::Persistent<v8::Value> object, void* parameter); @@ -2316,7 +2318,7 @@ static inline bool evaluate_value(QV8Engine *engine, const QV4::ValueRef o, ctx->catchException(); return false; } - return Runtime::strictEqual(value, result); + return QV4::Runtime::strictEqual(value, result); } static inline QV4::ReturnedValue evaluate(QV8Engine *engine, const QV4::ValueRef o, @@ -7579,6 +7581,28 @@ void tst_qqmlecmascript::varPropertyAccessOnObjectWithInvalidContext() QVERIFY(obj->property("success") == true); } +void tst_qqmlecmascript::importedScriptsAccessOnObjectWithInvalidContext() +{ + QQmlComponent component(&engine, testFileUrl("importedScriptsAccessOnObjectWithInvalidContext.qml")); + QScopedPointer<QObject> obj(component.create()); + if (obj.isNull()) + qDebug() << component.errors().first().toString(); + QVERIFY(!obj.isNull()); + QTRY_VERIFY(obj->property("success") == true); +} + +void tst_qqmlecmascript::contextObjectOnLazyBindings() +{ + QQmlComponent component(&engine, testFileUrl("contextObjectOnLazyBindings.qml")); + QScopedPointer<QObject> obj(component.create()); + if (obj.isNull()) + qDebug() << component.errors().first().toString(); + QVERIFY(!obj.isNull()); + QObject *subObject = qvariant_cast<QObject*>(obj->property("subObject")); + QVERIFY(subObject); + QCOMPARE(subObject->property("testValue").toInt(), int(42)); +} + QTEST_MAIN(tst_qqmlecmascript) #include "tst_qqmlecmascript.moc" diff --git a/tests/auto/qml/qqmlincubator/data/objectDeleted.qml b/tests/auto/qml/qqmlincubator/data/objectDeleted.qml index f00f975923..c9f6f8b564 100644 --- a/tests/auto/qml/qqmlincubator/data/objectDeleted.qml +++ b/tests/auto/qml/qqmlincubator/data/objectDeleted.qml @@ -2,7 +2,9 @@ import QtQuick 2.0 import Qt.test 1.0 Item { - SelfRegistering { - value: 11 + SelfRegisteringOuter { + value: SelfRegistering { + value: 11 + } } } diff --git a/tests/auto/qml/qqmlincubator/testtypes.cpp b/tests/auto/qml/qqmlincubator/testtypes.cpp index d926b6ae9b..b35636dd86 100644 --- a/tests/auto/qml/qqmlincubator/testtypes.cpp +++ b/tests/auto/qml/qqmlincubator/testtypes.cpp @@ -58,6 +58,25 @@ void SelfRegisteringType::clearMe() m_me = 0; } +SelfRegisteringOuterType *SelfRegisteringOuterType::m_me = 0; +bool SelfRegisteringOuterType::beenDeleted = false; +SelfRegisteringOuterType::SelfRegisteringOuterType() +: m_v(0) +{ + m_me = this; + beenDeleted = false; +} + +SelfRegisteringOuterType::~SelfRegisteringOuterType() +{ + beenDeleted = true; +} + +SelfRegisteringOuterType *SelfRegisteringOuterType::me() +{ + return m_me; +} + CompletionRegisteringType *CompletionRegisteringType::m_me = 0; CompletionRegisteringType::CompletionRegisteringType() { @@ -131,6 +150,7 @@ void CompletionCallbackType::registerCallback(callback c, void *d) void registerTypes() { qmlRegisterType<SelfRegisteringType>("Qt.test", 1,0, "SelfRegistering"); + qmlRegisterType<SelfRegisteringOuterType>("Qt.test", 1,0, "SelfRegisteringOuter"); qmlRegisterType<CompletionRegisteringType>("Qt.test", 1,0, "CompletionRegistering"); qmlRegisterType<CallbackRegisteringType>("Qt.test", 1,0, "CallbackRegistering"); qmlRegisterType<CompletionCallbackType>("Qt.test", 1,0, "CompletionCallback"); diff --git a/tests/auto/qml/qqmlincubator/testtypes.h b/tests/auto/qml/qqmlincubator/testtypes.h index fedff61510..8202cdd9dc 100644 --- a/tests/auto/qml/qqmlincubator/testtypes.h +++ b/tests/auto/qml/qqmlincubator/testtypes.h @@ -63,6 +63,27 @@ private: int m_v; }; +class SelfRegisteringOuterType : public QObject +{ +Q_OBJECT +Q_PROPERTY(QObject* value READ value WRITE setValue); +public: + SelfRegisteringOuterType(); + ~SelfRegisteringOuterType(); + + static bool beenDeleted; + + QObject *value() const { return m_v; } + void setValue(QObject *v) { m_v = v; } + + static SelfRegisteringOuterType *me(); + +private: + static SelfRegisteringOuterType *m_me; + + QObject *m_v; +}; + class CallbackRegisteringType : public QObject { Q_OBJECT diff --git a/tests/auto/qml/qqmlincubator/tst_qqmlincubator.cpp b/tests/auto/qml/qqmlincubator/tst_qqmlincubator.cpp index d6d0b0402a..0b9872f94c 100644 --- a/tests/auto/qml/qqmlincubator/tst_qqmlincubator.cpp +++ b/tests/auto/qml/qqmlincubator/tst_qqmlincubator.cpp @@ -52,6 +52,8 @@ #include <QQmlComponent> #include <QQmlIncubator> #include "../../shared/util.h" +#include <private/qqmlincubator_p.h> +#include <private/qqmlobjectcreator_p.h> class tst_qqmlincubator : public QQmlDataTest { @@ -141,35 +143,50 @@ void tst_qqmlincubator::incubationMode() void tst_qqmlincubator::objectDeleted() { - SelfRegisteringType::clearMe(); + { + QQmlEngine engine; + QQmlIncubationController controller; + engine.setIncubationController(&controller); + SelfRegisteringType::clearMe(); - QQmlComponent component(&engine, testFileUrl("objectDeleted.qml")); - QVERIFY(component.isReady()); + QQmlComponent component(&engine, testFileUrl("objectDeleted.qml")); + QVERIFY(component.isReady()); - QQmlIncubator incubator; - component.create(incubator); + QQmlIncubator incubator; + component.create(incubator); - QCOMPARE(incubator.status(), QQmlIncubator::Loading); - QVERIFY(SelfRegisteringType::me() == 0); + QCOMPARE(incubator.status(), QQmlIncubator::Loading); + QVERIFY(SelfRegisteringType::me() == 0); - while (SelfRegisteringType::me() == 0 && incubator.isLoading()) { - bool b = false; - controller.incubateWhile(&b); - } + while (SelfRegisteringOuterType::me() == 0 && incubator.isLoading()) { + bool b = false; + controller.incubateWhile(&b); + } - QVERIFY(SelfRegisteringType::me() != 0); - QVERIFY(incubator.isLoading()); + QVERIFY(SelfRegisteringOuterType::me() != 0); + QVERIFY(incubator.isLoading()); - delete SelfRegisteringType::me(); + while (SelfRegisteringType::me() == 0 && incubator.isLoading()) { + bool b = false; + controller.incubateWhile(&b); + } - { - bool b = true; - controller.incubateWhile(&b); - } + // We have to cheat and manually remove it from the creator->allCreatedObjects + // otherwise we will do a double delete + QQmlIncubatorPrivate *incubatorPriv = QQmlIncubatorPrivate::get(&incubator); + incubatorPriv->creator->allCreatedObjects().pop(); + delete SelfRegisteringType::me(); - QVERIFY(incubator.isError()); - VERIFY_ERRORS(incubator, "objectDeleted.errors.txt"); - QVERIFY(incubator.object() == 0); + { + bool b = true; + controller.incubateWhile(&b); + } + + QVERIFY(incubator.isError()); + VERIFY_ERRORS(incubator, "objectDeleted.errors.txt"); + QVERIFY(incubator.object() == 0); + } + QVERIFY(SelfRegisteringOuterType::beenDeleted); } void tst_qqmlincubator::clear() @@ -1111,6 +1128,10 @@ void tst_qqmlincubator::selfDelete() QVERIFY(SelfRegisteringType::me() != 0); QVERIFY(incubator->isLoading()); + // We have to cheat and manually remove it from the creator->allCreatedObjects + // otherwise we will do a double delete + QQmlIncubatorPrivate *incubatorPriv = QQmlIncubatorPrivate::get(incubator); + incubatorPriv->creator->allCreatedObjects().pop(); delete SelfRegisteringType::me(); { diff --git a/tests/auto/qml/qqmllanguage/data/SubType.qml b/tests/auto/qml/qqmllanguage/data/SubType.qml new file mode 100644 index 0000000000..0698ae2349 --- /dev/null +++ b/tests/auto/qml/qqmllanguage/data/SubType.qml @@ -0,0 +1,3 @@ +import QtQml 2.0 +QtObject { +} diff --git a/tests/auto/qml/qqmllanguage/data/assignNullStrings.qml b/tests/auto/qml/qqmllanguage/data/assignNullStrings.qml new file mode 100644 index 0000000000..5e1c3a9b03 --- /dev/null +++ b/tests/auto/qml/qqmllanguage/data/assignNullStrings.qml @@ -0,0 +1,9 @@ +import Test 1.0 +MyTypeObject { + stringProperty: "" + byteArrayProperty: "" + function assignNullStringsFromJs() { + stringProperty = "" + byteArrayProperty = "" + } +} diff --git a/tests/auto/qml/qqmllanguage/data/customParserProperties.qml b/tests/auto/qml/qqmllanguage/data/customParserProperties.qml new file mode 100644 index 0000000000..5d72edb8e5 --- /dev/null +++ b/tests/auto/qml/qqmllanguage/data/customParserProperties.qml @@ -0,0 +1,7 @@ +import Test 1.0 +import QtQml 2.0 +SimpleObjectWithCustomParser { + intProperty: 42 + property string qmlString: "Hello" + property var someObject: QtObject {} +} diff --git a/tests/auto/qml/qqmllanguage/data/idProperty.qml b/tests/auto/qml/qqmllanguage/data/idProperty.qml index bf048ea60a..dbb242804a 100644 --- a/tests/auto/qml/qqmllanguage/data/idProperty.qml +++ b/tests/auto/qml/qqmllanguage/data/idProperty.qml @@ -5,4 +5,8 @@ MyContainer { MyTypeObject { id: "myObjectId" } + + MyTypeObject { + selfGroupProperty.id: "name.with.dots" + } } diff --git a/tests/auto/qml/qqmllanguage/data/nonexistantProperty.7.errors.txt b/tests/auto/qml/qqmllanguage/data/nonexistantProperty.7.errors.txt new file mode 100644 index 0000000000..d62dbd703d --- /dev/null +++ b/tests/auto/qml/qqmllanguage/data/nonexistantProperty.7.errors.txt @@ -0,0 +1 @@ +3:5:Cannot assign to non-existent property "nonExistantGrouped" diff --git a/tests/auto/qml/qqmllanguage/data/nonexistantProperty.7.qml b/tests/auto/qml/qqmllanguage/data/nonexistantProperty.7.qml new file mode 100644 index 0000000000..3b66a5f6c7 --- /dev/null +++ b/tests/auto/qml/qqmllanguage/data/nonexistantProperty.7.qml @@ -0,0 +1,4 @@ +import Test 1.0 +MyQmlObject { + nonExistantGrouped.blah: MyQmlObject {} +} diff --git a/tests/auto/qml/qqmllanguage/data/rootObjectInCreationNotForSubObjects.qml b/tests/auto/qml/qqmllanguage/data/rootObjectInCreationNotForSubObjects.qml new file mode 100644 index 0000000000..afba278ade --- /dev/null +++ b/tests/auto/qml/qqmllanguage/data/rootObjectInCreationNotForSubObjects.qml @@ -0,0 +1,7 @@ +import QtQml 2.0 +import Test 1.0 +RootObjectInCreationTester { + subObject: SubType { + property int testValue: 42; + } +} diff --git a/tests/auto/qml/qqmllanguage/data/scriptString7.qml b/tests/auto/qml/qqmllanguage/data/scriptString7.qml new file mode 100644 index 0000000000..a9d5b47e2b --- /dev/null +++ b/tests/auto/qml/qqmllanguage/data/scriptString7.qml @@ -0,0 +1,6 @@ +import Test 1.0 + +MyTypeObject { + intProperty: 100; + scriptProperty: intProperty; +} diff --git a/tests/auto/qml/qqmllanguage/data/{subdir}/Test.qml b/tests/auto/qml/qqmllanguage/data/{subdir}/Test.qml new file mode 100644 index 0000000000..f789a905f2 --- /dev/null +++ b/tests/auto/qml/qqmllanguage/data/{subdir}/Test.qml @@ -0,0 +1,2 @@ +import QtQuick 2.0 +Rectangle { } diff --git a/tests/auto/qml/qqmllanguage/testtypes.cpp b/tests/auto/qml/qqmllanguage/testtypes.cpp index fad5c1e65d..8ffa327cf2 100644 --- a/tests/auto/qml/qqmllanguage/testtypes.cpp +++ b/tests/auto/qml/qqmllanguage/testtypes.cpp @@ -92,6 +92,9 @@ void registerTypes() qmlRegisterType<MyCreateableDerivedClass,1>("Test", 1, 1, "MyCreateableDerivedClass"); qmlRegisterCustomType<CustomBinding>("Test", 1, 0, "CustomBinding", new CustomBindingParser); + qmlRegisterCustomType<SimpleObjectWithCustomParser>("Test", 1, 0, "SimpleObjectWithCustomParser", new SimpleObjectCustomParser); + + qmlRegisterType<RootObjectInCreationTester>("Test", 1, 0, "RootObjectInCreationTester"); } QVariant myCustomVariantTypeConverter(const QString &data) @@ -102,9 +105,8 @@ QVariant myCustomVariantTypeConverter(const QString &data) } -QByteArray CustomBindingParser::compile(const QV4::CompiledData::QmlUnit *qmlUnit, int objectIndex, const QList<const QV4::CompiledData::Binding *> &bindings) +QByteArray CustomBindingParser::compile(const QV4::CompiledData::QmlUnit *qmlUnit, const QList<const QV4::CompiledData::Binding *> &bindings) { - Q_UNUSED(objectIndex) QByteArray result; QDataStream ds(&result, QIODevice::WriteOnly); @@ -123,7 +125,7 @@ QByteArray CustomBindingParser::compile(const QV4::CompiledData::QmlUnit *qmlUni return result; } -void CustomBindingParser::setCustomData(QObject *object, const QByteArray &data) +void CustomBindingParser::setCustomData(QObject *object, const QByteArray &data, QQmlCompiledData*) { CustomBinding *customBinding = qobject_cast<CustomBinding*>(object); Q_ASSERT(customBinding); @@ -155,10 +157,9 @@ void CustomBinding::componentComplete() } } -QByteArray EnumSupportingCustomParser::compile(const QV4::CompiledData::QmlUnit *qmlUnit, int objectIndex, const QList<const QV4::CompiledData::Binding *> &bindings) +QByteArray EnumSupportingCustomParser::compile(const QV4::CompiledData::QmlUnit *qmlUnit, const QList<const QV4::CompiledData::Binding *> &bindings) { Q_UNUSED(qmlUnit) - Q_UNUSED(objectIndex) if (bindings.count() != 1) { error(bindings.first(), QStringLiteral("Custom parser invoked incorrectly for unit test")); @@ -189,3 +190,35 @@ QByteArray EnumSupportingCustomParser::compile(const QV4::CompiledData::QmlUnit return QByteArray(); } + + +QByteArray SimpleObjectCustomParser::compile(const QV4::CompiledData::QmlUnit *, const QList<const QV4::CompiledData::Binding *> &bindings) +{ + return QByteArray::number(bindings.count()); +} + +void SimpleObjectCustomParser::setCustomData(QObject *object, const QByteArray &data, QQmlCompiledData*) +{ + SimpleObjectWithCustomParser *o = qobject_cast<SimpleObjectWithCustomParser*>(object); + Q_ASSERT(o); + bool ok = false; + o->setCustomBindingsCount(data.toInt(&ok)); + Q_ASSERT(ok); +} + + +MyQmlObject::MyQmlObject() + : m_value(-1) + , m_interface(0) + , m_qmlobject(0) + , m_childAddedEventCount(0) +{ + qRegisterMetaType<MyCustomVariantType>("MyCustomVariantType"); +} + +bool MyQmlObject::event(QEvent *event) +{ + if (event->type() == QEvent::ChildAdded) + m_childAddedEventCount++; + return QObject::event(event); +} diff --git a/tests/auto/qml/qqmllanguage/testtypes.h b/tests/auto/qml/qqmllanguage/testtypes.h index a1e2b76bd1..1c13a2e21c 100644 --- a/tests/auto/qml/qqmllanguage/testtypes.h +++ b/tests/auto/qml/qqmllanguage/testtypes.h @@ -119,7 +119,7 @@ class MyQmlObject : public QObject, public MyInterface Q_INTERFACES(MyInterface) public: - MyQmlObject() : m_value(-1), m_interface(0), m_qmlobject(0) { qRegisterMetaType<MyCustomVariantType>("MyCustomVariantType"); } + MyQmlObject(); int value() const { return m_value; } void setValue(int v) { m_value = v; } @@ -161,6 +161,8 @@ public: QJSValue qjsvalue() const { return m_qjsvalue; } void setQJSValue(const QJSValue &value) { m_qjsvalue = value; emit qjsvalueChanged(); } + int childAddedEventCount() const { return m_childAddedEventCount; } + public slots: void basicSlot() { qWarning("MyQmlObject::basicSlot"); } void basicSlotWithArgs(int v) { qWarning("MyQmlObject::basicSlotWithArgs(%d)", v); } @@ -173,6 +175,9 @@ signals: void signalWithDefaultArg(int parameter = 5); void qjsvalueChanged(); +protected: + virtual bool event(QEvent *event); + private: friend class tst_qqmllanguage; int m_value; @@ -181,6 +186,7 @@ private: MyCustomVariantType m_custom; int m_propertyWithNotify; QJSValue m_qjsvalue; + int m_childAddedEventCount; }; QML_DECLARE_TYPE(MyQmlObject) QML_DECLARE_TYPEINFO(MyQmlObject, QML_HAS_ATTACHED_PROPERTIES) @@ -230,6 +236,7 @@ class MyTypeObject : public QObject Q_PROPERTY(MyMirroredEnum mirroredEnumProperty READ mirroredEnumProperty WRITE setMirroredEnumProperty NOTIFY mirroredEnumPropertyChanged) Q_PROPERTY(MyEnumContainer::RelatedEnum relatedEnumProperty READ relatedEnumProperty WRITE setRelatedEnumProperty) Q_PROPERTY(QString stringProperty READ stringProperty WRITE setStringProperty NOTIFY stringPropertyChanged) + Q_PROPERTY(QByteArray byteArrayProperty READ byteArrayProperty WRITE setByteArrayProperty NOTIFY byteArrayPropertyChanged) Q_PROPERTY(uint uintProperty READ uintProperty WRITE setUintProperty NOTIFY uintPropertyChanged) Q_PROPERTY(int intProperty READ intProperty WRITE setIntProperty NOTIFY intPropertyChanged) Q_PROPERTY(qreal realProperty READ realProperty WRITE setRealProperty NOTIFY realPropertyChanged) @@ -351,6 +358,15 @@ public: emit stringPropertyChanged(); } + QByteArray byteArrayPropertyValue; + QByteArray byteArrayProperty() const { + return byteArrayPropertyValue; + } + void setByteArrayProperty(const QByteArray &v) { + byteArrayPropertyValue = v; + emit byteArrayPropertyChanged(); + } + uint uintPropertyValue; uint uintProperty() const { return uintPropertyValue; @@ -564,6 +580,7 @@ signals: void qtEnumPropertyChanged(); void mirroredEnumPropertyChanged(); void stringPropertyChanged(); + void byteArrayPropertyChanged(); void uintPropertyChanged(); void intPropertyChanged(); void realPropertyChanged(); @@ -722,15 +739,15 @@ class MyCustomParserType : public QObject class MyCustomParserTypeParser : public QQmlCustomParser { public: - QByteArray compile(const QV4::CompiledData::QmlUnit *, int, const QList<const QV4::CompiledData::Binding *> &) { return QByteArray(); } - void setCustomData(QObject *, const QByteArray &) {} + QByteArray compile(const QV4::CompiledData::QmlUnit *, const QList<const QV4::CompiledData::Binding *> &) { return QByteArray(); } + void setCustomData(QObject *, const QByteArray &, QQmlCompiledData*) {} }; class EnumSupportingCustomParser : public QQmlCustomParser { public: - QByteArray compile(const QV4::CompiledData::QmlUnit *qmlUnit, int objectIndex, const QList<const QV4::CompiledData::Binding *> &bindings); - void setCustomData(QObject *, const QByteArray &) {} + QByteArray compile(const QV4::CompiledData::QmlUnit *qmlUnit, const QList<const QV4::CompiledData::Binding *> &bindings); + void setCustomData(QObject *, const QByteArray &, QQmlCompiledData*) {} }; class MyParserStatus : public QObject, public QQmlParserStatus @@ -1100,8 +1117,52 @@ public: class CustomBindingParser : public QQmlCustomParser { - virtual QByteArray compile(const QV4::CompiledData::QmlUnit *qmlUnit, int objectIndex, const QList<const QV4::CompiledData::Binding *> &bindings); - virtual void setCustomData(QObject *object, const QByteArray &data); + virtual QByteArray compile(const QV4::CompiledData::QmlUnit *qmlUnit, const QList<const QV4::CompiledData::Binding *> &bindings); + virtual void setCustomData(QObject *object, const QByteArray &data, QQmlCompiledData *); +}; + +class SimpleObjectWithCustomParser : public QObject +{ + Q_OBJECT + Q_PROPERTY(int intProperty READ intProperty WRITE setIntProperty) +public: + SimpleObjectWithCustomParser() + : m_intProperty(0) + , m_customBindingsCount(0) + {} + + int intProperty() const { return m_intProperty; } + void setIntProperty(int value) { m_intProperty = value; } + + void setCustomBindingsCount(int count) { m_customBindingsCount = count; } + int customBindingsCount() const { return m_customBindingsCount; } + +private: + int m_intProperty; + int m_customBindingsCount; +}; + +class SimpleObjectCustomParser : public QQmlCustomParser +{ + virtual QByteArray compile(const QV4::CompiledData::QmlUnit *, const QList<const QV4::CompiledData::Binding *> &bindings); + virtual void setCustomData(QObject *object, const QByteArray &data, QQmlCompiledData *); +}; + +class RootObjectInCreationTester : public QObject +{ + Q_OBJECT + Q_PROPERTY(QObject *subObject READ subObject WRITE setSubObject FINAL) + Q_CLASSINFO("DeferredPropertyNames", "subObject"); +public: + RootObjectInCreationTester() + : obj(0) + {} + + QObject *subObject() const { return obj; } + void setSubObject(QObject *o) { obj = o; } + +private: + QObject *obj; }; void registerTypes(); diff --git a/tests/auto/qml/qqmllanguage/tst_qqmllanguage.cpp b/tests/auto/qml/qqmllanguage/tst_qqmllanguage.cpp index cf43352c40..be417df325 100644 --- a/tests/auto/qml/qqmllanguage/tst_qqmllanguage.cpp +++ b/tests/auto/qml/qqmllanguage/tst_qqmllanguage.cpp @@ -65,6 +65,17 @@ DEFINE_BOOL_CONFIG_OPTION(qmlCheckTypes, QML_CHECK_TYPES) +static inline bool isCaseSensitiveFileSystem(const QString &path) { + Q_UNUSED(path) +#if defined(Q_OS_MAC) + return pathconf(path.toLatin1().constData(), _PC_CASE_SENSITIVE); +#elif defined(Q_OS_WIN) + return false; +#else + return true; +#endif +} + /* This test case covers QML language issues. This covers everything that does not involve evaluating ECMAScript expressions and bindings. @@ -99,6 +110,7 @@ private slots: void assignLiteralToVariant(); void assignLiteralToVar(); void assignLiteralToJSValue(); + void assignNullStrings(); void bindJSValueToVar(); void bindJSValueToVariant(); void bindJSValueToType(); @@ -218,10 +230,15 @@ private slots: void customParserBindingScopes(); void customParserEvaluateEnum(); + void customParserProperties(); void preservePropertyCacheOnGroupObjects(); void propertyCacheInSync(); + void rootObjectInCreationNotForSubObjects(); + + void noChildEvents(); + private: QQmlEngine engine; QStringList defaultImportPathList; @@ -328,6 +345,7 @@ void tst_qqmllanguage::errors_data() QTest::newRow("nonexistantProperty.4") << "nonexistantProperty.4.qml" << "nonexistantProperty.4.errors.txt" << false; QTest::newRow("nonexistantProperty.5") << "nonexistantProperty.5.qml" << "nonexistantProperty.5.errors.txt" << false; QTest::newRow("nonexistantProperty.6") << "nonexistantProperty.6.qml" << "nonexistantProperty.6.errors.txt" << false; + QTest::newRow("nonexistantProperty.7") << "nonexistantProperty.7.qml" << "nonexistantProperty.7.errors.txt" << false; QTest::newRow("wrongType (string for int)") << "wrongType.1.qml" << "wrongType.1.errors.txt" << false; QTest::newRow("wrongType (int for bool)") << "wrongType.2.qml" << "wrongType.2.errors.txt" << false; @@ -493,13 +511,11 @@ void tst_qqmllanguage::errors_data() QTest::newRow("notAvailable") << "notAvailable.qml" << "notAvailable.errors.txt" << false; QTest::newRow("singularProperty") << "singularProperty.qml" << "singularProperty.errors.txt" << false; QTest::newRow("singularProperty.2") << "singularProperty.2.qml" << "singularProperty.2.errors.txt" << false; - QTest::newRow("incorrectCase") << "incorrectCase.qml" -#if defined(Q_OS_MAC) || defined(Q_OS_WIN32) - << "incorrectCase.errors.insensitive.txt" -#else - << "incorrectCase.errors.sensitive.txt" -#endif - << false; + + const QString expectedError = isCaseSensitiveFileSystem(dataDirectory()) ? + QStringLiteral("incorrectCase.errors.sensitive.txt") : + QStringLiteral("incorrectCase.errors.insensitive.txt"); + QTest::newRow("incorrectCase") << "incorrectCase.qml" << expectedError << false; QTest::newRow("metaobjectRevision.1") << "metaobjectRevision.1.qml" << "metaobjectRevision.1.errors.txt" << false; QTest::newRow("metaobjectRevision.2") << "metaobjectRevision.2.qml" << "metaobjectRevision.2.errors.txt" << false; @@ -859,6 +875,19 @@ void tst_qqmllanguage::assignLiteralToJSValue() } } +void tst_qqmllanguage::assignNullStrings() +{ + QQmlComponent component(&engine, testFileUrl("assignNullStrings.qml")); + VERIFY_ERRORS(0); + MyTypeObject *object = qobject_cast<MyTypeObject *>(component.create()); + QVERIFY(object != 0); + QVERIFY(object->stringProperty().isNull()); + QVERIFY(object->byteArrayProperty().isNull()); + QMetaObject::invokeMethod(object, "assignNullStringsFromJs", Qt::DirectConnection); + QVERIFY(object->stringProperty().isNull()); + QVERIFY(object->byteArrayProperty().isNull()); +} + void tst_qqmllanguage::bindJSValueToVar() { QQmlComponent component(&engine, testFileUrl("assignLiteralToJSValue.qml")); @@ -1175,12 +1204,17 @@ void tst_qqmllanguage::idProperty() VERIFY_ERRORS(0); MyContainer *object = qobject_cast<MyContainer *>(component.create()); QVERIFY(object != 0); - QCOMPARE(object->getChildren()->count(), 1); + QCOMPARE(object->getChildren()->count(), 2); MyTypeObject *child = qobject_cast<MyTypeObject *>(object->getChildren()->at(0)); QVERIFY(child != 0); QCOMPARE(child->id(), QString("myObjectId")); QCOMPARE(object->property("object"), QVariant::fromValue((QObject *)child)); + + child = + qobject_cast<MyTypeObject *>(object->getChildren()->at(1)); + QVERIFY(child != 0); + QCOMPARE(child->id(), QString("name.with.dots")); } // Tests automatic connection to notify signals if "onBlahChanged" syntax is used @@ -1874,6 +1908,28 @@ void tst_qqmllanguage::scriptString() QVERIFY(object != 0); QCOMPARE(object->scriptProperty().isUndefinedLiteral(), true); } + { + QQmlComponent component(&engine, testFileUrl("scriptString7.qml")); + VERIFY_ERRORS(0); + + MyTypeObject *object = qobject_cast<MyTypeObject*>(component.create()); + QVERIFY(object != 0); + QQmlScriptString ss = object->scriptProperty(); + + { + QQmlExpression expr(ss, /*context*/0, object); + QCOMPARE(expr.evaluate().toInt(), int(100)); + } + + { + SimpleObjectWithCustomParser testScope; + QVERIFY(testScope.metaObject()->indexOfProperty("intProperty") != object->metaObject()->indexOfProperty("intProperty")); + + testScope.setIntProperty(42); + QQmlExpression expr(ss, /*context*/0, &testScope); + QCOMPARE(expr.evaluate().toInt(), int(42)); + } + } } // Check that default property assignments are correctly spliced into explicit @@ -2208,6 +2264,11 @@ void tst_qqmllanguage::importsLocal_data() "Test {}" << (!qmlCheckTypes()?"TestType":"") << (!qmlCheckTypes()?"":"Test is ambiguous. Found in org/qtproject/Test/ and in subdir/"); + QTest::newRow("file URL survives percent-encoding") + << "import \"" + QUrl::fromLocalFile(QDir::currentPath() + "/{subdir}").toString() + "\"\n" + "Test {}" + << "QQuickRectangle" + << ""; } void tst_qqmllanguage::importsLocal() @@ -2574,12 +2635,9 @@ void tst_qqmllanguage::importIncorrectCase() QList<QQmlError> errors = component.errors(); QCOMPARE(errors.count(), 1); -#if defined(Q_OS_MAC) || defined(Q_OS_WIN) - QString expectedError = QLatin1String("File name case mismatch"); -#else - QString expectedError = QLatin1String("File not found"); -#endif - + const QString expectedError = isCaseSensitiveFileSystem(dataDirectory()) ? + QStringLiteral("File not found") : + QStringLiteral("File name case mismatch"); QCOMPARE(errors.at(0).description(), expectedError); engine.setImportPathList(defaultImportPathList); @@ -3591,6 +3649,20 @@ void tst_qqmllanguage::customParserEvaluateEnum() QVERIFY(!o.isNull()); } +void tst_qqmllanguage::customParserProperties() +{ + QQmlComponent component(&engine, testFile("customParserProperties.qml")); + VERIFY_ERRORS(0); + QScopedPointer<QObject> o(component.create()); + QVERIFY(!o.isNull()); + SimpleObjectWithCustomParser *testObject = qobject_cast<SimpleObjectWithCustomParser*>(o.data()); + QVERIFY(testObject); + QCOMPARE(testObject->customBindingsCount(), 0); + QCOMPARE(testObject->intProperty(), 42); + QCOMPARE(testObject->property("qmlString").toString(), QStringLiteral("Hello")); + QVERIFY(!testObject->property("someObject").isNull()); +} + void tst_qqmllanguage::preservePropertyCacheOnGroupObjects() { QQmlComponent component(&engine, testFile("preservePropertyCacheOnGroupObjects.qml")); @@ -3630,6 +3702,41 @@ void tst_qqmllanguage::propertyCacheInSync() QCOMPARE(anchors->property("margins").toInt(), 50); } +void tst_qqmllanguage::rootObjectInCreationNotForSubObjects() +{ + QQmlComponent component(&engine, testFile("rootObjectInCreationNotForSubObjects.qml")); + VERIFY_ERRORS(0); + QScopedPointer<QObject> o(component.create()); + QVERIFY(!o.isNull()); + + // QQmlComponent should have set this back to false anyway + QQmlData *ddata = QQmlData::get(o.data()); + QVERIFY(!ddata->rootObjectInCreation); + + QObject *subObject = qvariant_cast<QObject*>(o->property("subObject")); + QVERIFY(!subObject); + + qmlExecuteDeferred(o.data()); + + subObject = qvariant_cast<QObject*>(o->property("subObject")); + QVERIFY(subObject); + + ddata = QQmlData::get(subObject); + // This should never have been set in the first place as there is no + // QQmlComponent to set it back to false. + QVERIFY(!ddata->rootObjectInCreation); +} + +void tst_qqmllanguage::noChildEvents() +{ + QQmlComponent component(&engine); + component.setData("import QtQml 2.0; import Test 1.0; MyQmlObject { property QtObject child: QtObject {} }", QUrl()); + VERIFY_ERRORS(0); + MyQmlObject *object = qobject_cast<MyQmlObject*>(component.create()); + QVERIFY(object != 0); + QCOMPARE(object->childAddedEventCount(), 0); +} + QTEST_MAIN(tst_qqmllanguage) #include "tst_qqmllanguage.moc" diff --git a/tests/auto/qml/qqmllistmodel/tst_qqmllistmodel.cpp b/tests/auto/qml/qqmllistmodel/tst_qqmllistmodel.cpp index bdc0646b8e..9b57eeffa9 100644 --- a/tests/auto/qml/qqmllistmodel/tst_qqmllistmodel.cpp +++ b/tests/auto/qml/qqmllistmodel/tst_qqmllistmodel.cpp @@ -101,6 +101,8 @@ private slots: void static_types_data(); void static_i18n(); void static_i18n_data(); + void dynamic_i18n(); + void dynamic_i18n_data(); void static_nestedElements(); void static_nestedElements_data(); void dynamic_data(); @@ -296,17 +298,17 @@ void tst_qqmllistmodel::static_i18n_data() QTest::newRow("QT_TR_NOOP extra param") << QString::fromUtf8("ListElement { foo: QT_TR_NOOP(\"hello\",\"world\") }") << QVariant(QString()) - << QString("ListElement: improperly specified QT_TR_NOOP"); + << QString("ListElement: cannot use script for property value"); QTest::newRow("QT_TRANSLATE_NOOP missing params") << "ListElement { foo: QT_TRANSLATE_NOOP() }" << QVariant(QString()) - << QString("ListElement: improperly specified QT_TRANSLATE_NOOP"); + << QString("ListElement: cannot use script for property value"); QTest::newRow("QT_TRID_NOOP missing param") << QString::fromUtf8("ListElement { foo: QT_TRID_NOOP() }") << QVariant(QString()) - << QString("ListElement: improperly specified QT_TRID_NOOP"); + << QString("ListElement: cannot use script for property value"); } void tst_qqmllistmodel::static_i18n() @@ -341,6 +343,54 @@ void tst_qqmllistmodel::static_i18n() delete obj; } +void tst_qqmllistmodel::dynamic_i18n_data() +{ + QTest::addColumn<QString>("qml"); + QTest::addColumn<QVariant>("value"); + QTest::addColumn<QString>("error"); + + QTest::newRow("qsTr") + << QString::fromUtf8("ListElement { foo: qsTr(\"test\") }") + << QVariant(QString::fromUtf8("test")) + << QString("ListElement: cannot use script for property value"); + + QTest::newRow("qsTrId") + << "ListElement { foo: qsTrId(\"qtn_test\") }" + << QVariant(QString("qtn_test")) + << QString("ListElement: cannot use script for property value"); +} + +void tst_qqmllistmodel::dynamic_i18n() +{ + QFETCH(QString, qml); + QFETCH(QVariant, value); + QFETCH(QString, error); + + qml = "import QtQuick 2.0\nItem { property variant test: model.get(0).foo; ListModel { id: model; " + qml + " } }"; + + QQmlEngine engine; + QQmlComponent component(&engine); + component.setData(qml.toUtf8(), + QUrl::fromLocalFile(QString("dummy.qml"))); + + if (!error.isEmpty()) { + QVERIFY(component.isError()); + QCOMPARE(component.errors().at(0).description(), error); + return; + } + + QVERIFY(!component.isError()); + + QObject *obj = component.create(); + QVERIFY(obj != 0); + + QVariant actual = obj->property("test"); + + QCOMPARE(actual, value); + QCOMPARE(actual.toString(), value.toString()); + + delete obj; +} void tst_qqmllistmodel::static_nestedElements() { QFETCH(int, elementCount); @@ -528,6 +578,8 @@ void tst_qqmllistmodel::dynamic_data() QTest::newRow("nested-count") << "{append({'foo':123,'bars':[{'a':1},{'a':2},{'a':3}]}); get(0).bars.count}" << 3 << "" << dr; QTest::newRow("nested-clear") << "{append({'foo':123,'bars':[{'a':1},{'a':2},{'a':3}]}); get(0).bars.clear(); get(0).bars.count}" << 0 << "" << dr; } + + QTest::newRow("jsarray") << "{append({'foo':['1', '2', '3']});get(0).foo.get(0)}" << 0 << "" << false; } void tst_qqmllistmodel::dynamic() diff --git a/tests/auto/qml/qqmllocale/tst_qqmllocale.cpp b/tests/auto/qml/qqmllocale/tst_qqmllocale.cpp index 0eb38d92e6..9653cac988 100644 --- a/tests/auto/qml/qqmllocale/tst_qqmllocale.cpp +++ b/tests/auto/qml/qqmllocale/tst_qqmllocale.cpp @@ -932,7 +932,6 @@ void tst_qqmllocale::dateFromLocaleString_data() void tst_qqmllocale::dateFromLocaleString() { - QSKIP("Needs fixes in our date time parser"); QFETCH(QString, locale); QFETCH(QString, format); @@ -977,7 +976,6 @@ void tst_qqmllocale::dateFromLocaleDateString_data() void tst_qqmllocale::dateFromLocaleDateString() { - QSKIP("Needs fixes in our date time parser"); QFETCH(QString, locale); QFETCH(QString, format); @@ -1022,7 +1020,6 @@ void tst_qqmllocale::dateFromLocaleTimeString_data() void tst_qqmllocale::dateFromLocaleTimeString() { - QSKIP("Needs fixes in our date time parser"); QFETCH(QString, locale); QFETCH(QString, format); diff --git a/tests/auto/qml/qqmlxmlhttprequest/data/stateChangeCallingContext.qml b/tests/auto/qml/qqmlxmlhttprequest/data/stateChangeCallingContext.qml index f44f4f926c..b35c31d513 100644 --- a/tests/auto/qml/qqmlxmlhttprequest/data/stateChangeCallingContext.qml +++ b/tests/auto/qml/qqmlxmlhttprequest/data/stateChangeCallingContext.qml @@ -8,7 +8,7 @@ Item { SequentialAnimation { id: anim - PauseAnimation { duration: 525 } // delay mode is 500 msec. + PauseAnimation { duration: 1000 } // delay mode is 500 msec. ScriptAction { script: loadcomponent(0) } PauseAnimation { duration: 525 } // delay mode is 500 msec. ScriptAction { script: loadcomponent(1) } diff --git a/tests/auto/qml/qqmlxmlhttprequest/qqmlxmlhttprequest.pro b/tests/auto/qml/qqmlxmlhttprequest/qqmlxmlhttprequest.pro index f1fbfde0ec..fcfdf23d33 100644 --- a/tests/auto/qml/qqmlxmlhttprequest/qqmlxmlhttprequest.pro +++ b/tests/auto/qml/qqmlxmlhttprequest/qqmlxmlhttprequest.pro @@ -2,8 +2,6 @@ CONFIG += testcase TARGET = tst_qqmlxmlhttprequest macx:CONFIG -= app_bundle -CONFIG+=insignificant_test # QTQAINFRA-573 - INCLUDEPATH += ../../shared/ HEADERS += ../../shared/testhttpserver.h diff --git a/tests/auto/qml/qquickfolderlistmodel/data/resetfiltering/test1.html b/tests/auto/qml/qquickfolderlistmodel/data/resetfiltering/test1.html new file mode 100644 index 0000000000..4da4639310 --- /dev/null +++ b/tests/auto/qml/qquickfolderlistmodel/data/resetfiltering/test1.html @@ -0,0 +1 @@ +<P>This file contains some HTML.</P> diff --git a/tests/auto/qml/qquickfolderlistmodel/data/resetfiltering/test2.html b/tests/auto/qml/qquickfolderlistmodel/data/resetfiltering/test2.html new file mode 100644 index 0000000000..4da4639310 --- /dev/null +++ b/tests/auto/qml/qquickfolderlistmodel/data/resetfiltering/test2.html @@ -0,0 +1 @@ +<P>This file contains some HTML.</P> diff --git a/tests/auto/qml/qquickfolderlistmodel/tst_qquickfolderlistmodel.cpp b/tests/auto/qml/qquickfolderlistmodel/tst_qquickfolderlistmodel.cpp index a6e6345223..4296ae4f09 100644 --- a/tests/auto/qml/qquickfolderlistmodel/tst_qquickfolderlistmodel.cpp +++ b/tests/auto/qml/qquickfolderlistmodel/tst_qquickfolderlistmodel.cpp @@ -73,6 +73,7 @@ private slots: void basicProperties(); void showFiles(); void resetFiltering(); + void nameFilters(); void refresh(); void cdUp(); #ifdef Q_OS_WIN32 @@ -169,26 +170,50 @@ void tst_qquickfolderlistmodel::resetFiltering() QAbstractListModel *flm = qobject_cast<QAbstractListModel*>(component.create()); QVERIFY(flm != 0); + flm->setProperty("folder", testFileUrl("resetfiltering")); + // _q_directoryUpdated may be triggered if model was empty before, but there won't be a rowsRemoved signal + QTRY_COMPARE(flm->property("count").toInt(),3); // all files visible + + flm->setProperty("folder", testFileUrl("resetfiltering/innerdir")); + // _q_directoryChanged is triggered so it's a total model refresh + QTRY_COMPARE(flm->property("count").toInt(),1); // should just be "test2.txt" visible + + flm->setProperty("folder", testFileUrl("resetfiltering")); + // _q_directoryChanged is triggered so it's a total model refresh + QTRY_COMPARE(flm->property("count").toInt(),3); // all files visible +} + +void tst_qquickfolderlistmodel::nameFilters() +{ + // see QTBUG-36576 + QQmlComponent component(&engine, testFileUrl("resetFiltering.qml")); + checkNoErrors(component); + + QAbstractListModel *flm = qobject_cast<QAbstractListModel*>(component.create()); + QVERIFY(flm != 0); + connect(flm, SIGNAL(rowsRemoved(QModelIndex,int,int)), this, SLOT(removed(QModelIndex,int,int))); + QTRY_VERIFY(flm->rowCount() > 0); flm->setProperty("folder", testFileUrl("resetfiltering")); - QTRY_COMPARE(flm->property("count").toInt(),1); // should just be "test.txt" visible + QTRY_COMPARE(flm->property("count").toInt(),3); // all files visible + int count = flm->rowCount(); + flm->setProperty("nameFilters", QStringList() << "*.txt"); + // _q_directoryUpdated triggered with range 0:1 + QTRY_COMPARE(flm->property("count").toInt(),1); + QCOMPARE(flm->data(flm->index(0),FileNameRole), QVariant("test.txt")); QCOMPARE(removeStart, 0); QCOMPARE(removeEnd, count-1); - flm->setProperty("folder", testFileUrl("resetfiltering/innerdir")); - QTRY_COMPARE(flm->property("count").toInt(),1); // should just be "test2.txt" visible - count = flm->rowCount(); - QCOMPARE(removeStart, 0); - QCOMPARE(removeEnd, count-1); + flm->setProperty("nameFilters", QStringList() << "*.html"); + QTRY_COMPARE(flm->property("count").toInt(),2); + QCOMPARE(flm->data(flm->index(0),FileNameRole), QVariant("test1.html")); + QCOMPARE(flm->data(flm->index(1),FileNameRole), QVariant("test2.html")); - flm->setProperty("folder", testFileUrl("resetfiltering")); - QTRY_COMPARE(flm->property("count").toInt(),1); // should just be "test.txt" visible - count = flm->rowCount(); - QCOMPARE(removeStart, 0); - QCOMPARE(removeEnd, count-1); + flm->setProperty("nameFilters", QStringList()); + QTRY_COMPARE(flm->property("count").toInt(),3); // all files visible } void tst_qquickfolderlistmodel::refresh() diff --git a/tests/auto/qml/qv4debugger/tst_qv4debugger.cpp b/tests/auto/qml/qv4debugger/tst_qv4debugger.cpp index 15a6acc272..b7e5cf48e0 100644 --- a/tests/auto/qml/qv4debugger/tst_qv4debugger.cpp +++ b/tests/auto/qml/qv4debugger/tst_qv4debugger.cpp @@ -48,6 +48,9 @@ using namespace QV4; using namespace QV4::Debugging; +typedef QV4::ReturnedValue (*InjectedFunction)(QV4::CallContext*); +Q_DECLARE_METATYPE(InjectedFunction) + static bool waitForSignal(QObject* obj, const char* signal, int timeout = 10000) { QEventLoop loop; @@ -80,9 +83,7 @@ public: QV4::ExecutionEngine *v4Engine() { return QV8Engine::getV4(this); } - typedef QV4::ReturnedValue (*InjectedFunction)(QV4::CallContext*); - - Q_INVOKABLE void injectFunction(const QString &functionName, TestEngine::InjectedFunction injectedFunction) + Q_INVOKABLE void injectFunction(const QString &functionName, InjectedFunction injectedFunction) { QV4::ExecutionEngine *v4 = v4Engine(); QV4::Scope scope(v4); @@ -96,7 +97,6 @@ signals: void evaluateFinished(); }; -Q_DECLARE_METATYPE(TestEngine::InjectedFunction) namespace { class TestCollector: public QV4::Debugging::Debugger::Collector @@ -404,7 +404,7 @@ void tst_qv4debugger::removeBreakPointForNextInstruction() "var i = 42;"; QMetaObject::invokeMethod(m_engine, "injectFunction", Qt::BlockingQueuedConnection, - Q_ARG(QString, "someCall"), Q_ARG(TestEngine::InjectedFunction, someCall)); + Q_ARG(QString, "someCall"), Q_ARG(InjectedFunction, someCall)); m_debuggerAgent->addBreakPoint("removeBreakPointForNextInstruction", 2); diff --git a/tests/auto/qmldevtools/compile/tst_compile.cpp b/tests/auto/qmldevtools/compile/tst_compile.cpp index 6b13d1b4bb..31b5c02250 100644 --- a/tests/auto/qmldevtools/compile/tst_compile.cpp +++ b/tests/auto/qmldevtools/compile/tst_compile.cpp @@ -44,6 +44,10 @@ #include <private/qqmljsparser_p.h> #include <private/qqmljsastvisitor_p.h> #include <private/qqmljsast_p.h> +#include <private/qqmlirbuilder_p.h> +#include <private/qv4value_inl_p.h> +#include <private/qv4codegen_p.h> +#include <private/qqmldirparser_p.h> int main() { diff --git a/tests/auto/qmltest/animators/tst_mixed.qml b/tests/auto/qmltest/animators/tst_mixed.qml new file mode 100644 index 0000000000..1eb0cf019f --- /dev/null +++ b/tests/auto/qmltest/animators/tst_mixed.qml @@ -0,0 +1,179 @@ +/**************************************************************************** +** +** Copyright (C) 2014 Jolla Ltd, author: <gunnar.sletta@jollamobile.com> +** Contact: http://www.qt-project.org/legal +** +** This file is part of the test suite of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** 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 Digia. For licensing terms and +** conditions see http://qt.digia.com/licensing. For further information +** use the contact form at http://qt.digia.com/contact-us. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 2.1 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 2.1 requirements +** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** In addition, as a special exception, Digia gives you certain additional +** rights. These rights are described in the Digia Qt LGPL Exception +** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 3.0 as published by the Free Software +** Foundation and appearing in the file LICENSE.GPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU General Public License version 3.0 requirements will be +** met: http://www.gnu.org/copyleft/gpl.html. +** +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +import QtQuick 2.2 +import QtTest 1.0 + +Item { + id: root; + width: 200 + height: 200 + + TestCase { + id: testCase + name: "animators-mixed" + when: !rootAnimation.running + function test_endresult() { + compare(box.rootStart, 2); + compare(box.rootEnd, 2); + + compare(parallelWithOneSequential.before, 4); + compare(parallelWithOneSequential.scaleUpdates, 4); + + compare(parallelWithTwoSequentialNormalEndsLast.beforeAnimator, 4); + compare(parallelWithTwoSequentialNormalEndsLast.scaleUpdates, 4); + compare(parallelWithTwoSequentialNormalEndsLast.afterAnimator, 4); + compare(parallelWithTwoSequentialNormalEndsLast.beforePause, 4); + compare(parallelWithTwoSequentialNormalEndsLast.afterPause, 4); + + compare(parallelWithTwoSequentialNormalEndsFirst.beforeAnimator, 4); + compare(parallelWithTwoSequentialNormalEndsFirst.scaleUpdates, 4); + compare(parallelWithTwoSequentialNormalEndsFirst.afterAnimator, 4); + compare(parallelWithTwoSequentialNormalEndsFirst.beforePause, 4); + compare(parallelWithTwoSequentialNormalEndsFirst.afterPause, 4); + + } + } + + Box { + id: box + + property int rootStart : 0 + property int rootEnd : 0; + + SequentialAnimation { + id: rootAnimation + + running: true + loops: 2 + + ScriptAction { script: box.rootStart++; } + + ParallelAnimation { + id: parallelWithOneSequential + property int before : 0; + property int scaleUpdates : 0; + loops: 2 + SequentialAnimation { + ScriptAction { script: { + parallelWithOneSequential.before++; + box.scale = 1; + box.scaleChangeCounter = 0; + } + } + ScaleAnimator { target: box; from: 1; to: 2; duration: 100; } + ScriptAction { script: { + parallelWithOneSequential.scaleUpdates += box.scaleChangeCounter; + } + } + } + } + + ParallelAnimation { + id: parallelWithTwoSequentialNormalEndsLast + property int beforeAnimator : 0; + property int scaleUpdates : 0; + property int afterAnimator : 0; + property int beforePause : 0; + property int afterPause : 0; + loops: 2 + SequentialAnimation { + ScriptAction { script: { + parallelWithTwoSequentialNormalEndsLast.beforeAnimator++; + box.scale = 1; + box.scaleChangeCounter = 0; + } + } + ScaleAnimator { target: box; from: 1; to: 2; duration: 100; } + ScriptAction { script: { + parallelWithTwoSequentialNormalEndsLast.scaleUpdates += box.scaleChangeCounter; + parallelWithTwoSequentialNormalEndsLast.afterAnimator++; + } + } + } + SequentialAnimation { + ScriptAction { script: { + parallelWithTwoSequentialNormalEndsLast.beforePause++ + } + } + PauseAnimation { duration: 200 } + ScriptAction { script: { + parallelWithTwoSequentialNormalEndsLast.afterPause++ + } + } + } + } + + ParallelAnimation { + id: parallelWithTwoSequentialNormalEndsFirst + property int beforeAnimator : 0; + property int scaleUpdates : 0; + property int afterAnimator : 0; + property int beforePause : 0; + property int afterPause : 0; + loops: 2 + SequentialAnimation { + ScriptAction { script: { + parallelWithTwoSequentialNormalEndsFirst.beforeAnimator++; + box.scale = 1; + box.scaleChangeCounter = 0; + } + } + ScaleAnimator { target: box; from: 1; to: 2; duration: 200; } + ScriptAction { script: { + parallelWithTwoSequentialNormalEndsFirst.scaleUpdates += box.scaleChangeCounter; + parallelWithTwoSequentialNormalEndsFirst.afterAnimator++; + } + } + } + SequentialAnimation { + ScriptAction { script: parallelWithTwoSequentialNormalEndsFirst.beforePause++ } + PauseAnimation { duration: 100 } + ScriptAction { script: parallelWithTwoSequentialNormalEndsFirst.afterPause++ } + } + } + + ScriptAction { script: box.rootEnd++; } + } + + } + +} diff --git a/tests/auto/qmltest/animators/tst_on.qml b/tests/auto/qmltest/animators/tst_on.qml index 7930dc5be3..b3fc719dcc 100644 --- a/tests/auto/qmltest/animators/tst_on.qml +++ b/tests/auto/qmltest/animators/tst_on.qml @@ -1,6 +1,6 @@ /**************************************************************************** ** -** Copyright (C) 2013 Digia Plc and/or its subsidiary(-ies). +** Copyright (C) 2014 Digia Plc and/or its subsidiary(-ies). ** Contact: http://www.qt-project.org/legal ** ** This file is part of the test suite of the Qt Toolkit. @@ -54,7 +54,7 @@ Item { && !anims.running && !animr.running && !animo.running; function test_endresult() { - compare(box.xChangeCounter, 1); + tryCompare(box, 'xChangeCounter', 1); compare(box.yChangeCounter, 1); compare(box.scaleChangeCounter, 1); compare(box.rotationChangeCounter, 1); diff --git a/tests/auto/qmltest/listview/tst_listview.qml b/tests/auto/qmltest/listview/tst_listview.qml index 0589e7c46b..03be57909f 100644 --- a/tests/auto/qmltest/listview/tst_listview.qml +++ b/tests/auto/qmltest/listview/tst_listview.qml @@ -102,6 +102,23 @@ Item { } } + ListView { + id: listViewDelegateModelAfterCreate + anchors.fill: parent + property int createdDelegates: 0 + } + + Component { + id: delegateModelAfterCreateComponent + Rectangle { + width: 140 + height: 140 + border.color: "black" + color: "red" + Component.onCompleted: listViewDelegateModelAfterCreate.createdDelegates++; + } + } + ListModel { id: emptymodel } ListModel { id: manyitems } ListModel { id: firstmodel; ListElement { name: "FirstModelElement0" } } @@ -249,5 +266,11 @@ Item { asyncListViewLoaderView.currentIndex = 4; } } + + function test_set_delegate_model_after_list_creation() { + listViewDelegateModelAfterCreate.delegate = delegateModelAfterCreateComponent; + listViewDelegateModelAfterCreate.model = 40; + verify(listViewDelegateModelAfterCreate.createdDelegates > 0); + } } } diff --git a/tests/auto/qmltest/pathview/tst_pathview.qml b/tests/auto/qmltest/pathview/tst_pathview.qml new file mode 100644 index 0000000000..820034c960 --- /dev/null +++ b/tests/auto/qmltest/pathview/tst_pathview.qml @@ -0,0 +1,35 @@ +import QtQuick 2.1 +import QtTest 1.0 + +Item { + id: top + + PathView { + id: pathViewDelegateModelAfterCreate + anchors.fill: parent + property int createdDelegates: 0 + path: Path { startX: 120; startY: 100 } + } + + Component { + id: delegateModelAfterCreateComponent + Rectangle { + width: 140 + height: 140 + border.color: "black" + color: "red" + Component.onCompleted: pathViewDelegateModelAfterCreate.createdDelegates++; + } + } + + TestCase { + name: "PathView" + when: windowShown + + function test_set_delegate_model_after_path_creation() { + pathViewDelegateModelAfterCreate.delegate = delegateModelAfterCreateComponent; + pathViewDelegateModelAfterCreate.model = 40; + verify(pathViewDelegateModelAfterCreate.createdDelegates > 0); + } + } +} diff --git a/tests/auto/quick/qquickaccessible/tst_qquickaccessible.cpp b/tests/auto/quick/qquickaccessible/tst_qquickaccessible.cpp index 54eb3509bd..7d50e130f2 100644 --- a/tests/auto/quick/qquickaccessible/tst_qquickaccessible.cpp +++ b/tests/auto/quick/qquickaccessible/tst_qquickaccessible.cpp @@ -131,6 +131,8 @@ void tst_QQuickAccessible::initTestCase() QQmlDataTest::initTestCase(); QTestAccessibility::initialize(); QPlatformIntegration *pfIntegration = QGuiApplicationPrivate::platformIntegration(); + if (!pfIntegration->accessibility()) + QSKIP("This platform does not support accessibility"); pfIntegration->accessibility()->setActive(true); } diff --git a/tests/auto/quick/qquickcanvasitem/data/CanvasTestCase.qml b/tests/auto/quick/qquickcanvasitem/data/CanvasTestCase.qml index e299147b36..70682bed0b 100644 --- a/tests/auto/quick/qquickcanvasitem/data/CanvasTestCase.qml +++ b/tests/auto/quick/qquickcanvasitem/data/CanvasTestCase.qml @@ -16,7 +16,6 @@ TestCase { if (type === "2d") return [ { tag:"image threaded", properties:{width:100, height:100, renderTarget:Canvas.Image, renderStrategy:Canvas.Threaded}}, - { tag:"image canvas invisible", properties:{visible: false, width:100, height:100, renderTarget:Canvas.Image, renderStrategy:Canvas.Threaded}}, // { tag:"image cooperative", properties:{width:100, height:100, renderTarget:Canvas.Image, renderStrategy:Canvas.Cooperative}}, { tag:"image immediate", properties:{width:100, height:100, renderTarget:Canvas.Image, renderStrategy:Canvas.Immediate}}, // { tag:"fbo cooperative", properties:{width:100, height:100, renderTarget:Canvas.FramebufferObject, renderStrategy:Canvas.Cooperative}}, diff --git a/tests/auto/quick/qquickcanvasitem/data/tst_canvas.qml b/tests/auto/quick/qquickcanvasitem/data/tst_canvas.qml index b92f6354a5..d90eb3971e 100644 --- a/tests/auto/quick/qquickcanvasitem/data/tst_canvas.qml +++ b/tests/auto/quick/qquickcanvasitem/data/tst_canvas.qml @@ -180,20 +180,28 @@ CanvasTestCase { tryCompare(c, "availableChangedCount", 1); //scene graph could be available immediately //in this case, we force waiting a short while until the init paint finished - if (c.visible) { - tryCompare(c, "paintedCount", 1); - } else { - tryCompare(c, "paintedCount", 0); - } + tryCompare(c, "paintedCount", 1); ctx.fillRect(0, 0, c.width, c.height); c.toDataURL(); - if (c.visible) { - tryCompare(c, "paintCount", 1); - tryCompare(c, "paintedCount", 2); - } else { - tryCompare(c, "paintCount", 0); - tryCompare(c, "paintedCount", 1); - } + tryCompare(c, "paintedCount", 2); + tryCompare(c, "paintCount", 1); + // implicit repaint when visible and resized + testCase.visible = true; + c.width += 1; + c.height += 1; + tryCompare(c, "paintCount", 2); + tryCompare(c, "paintedCount", 2); + // allow explicit repaint even when hidden + testCase.visible = false; + c.requestPaint(); + tryCompare(c, "paintCount", 3); + tryCompare(c, "paintedCount", 2); + // no implicit repaint when resized but hidden + c.width += 1; + c.height += 1; + waitForRendering(c); + compare(c.paintCount, 3); + tryCompare(c, "paintedCount", 2); c.destroy(); } function test_loadImage(row) { diff --git a/tests/auto/quick/qquickgridview/data/boundZValues.qml b/tests/auto/quick/qquickgridview/data/boundZValues.qml new file mode 100644 index 0000000000..7a1ca48a81 --- /dev/null +++ b/tests/auto/quick/qquickgridview/data/boundZValues.qml @@ -0,0 +1,46 @@ +import QtQuick 2.0 + +Rectangle { + width: 240 + height: 320 + + GridView { + id: grid + + property real itemZ: 342 + property real headerZ: 341 + property real footerZ: 340 + property real highlightZ: 339 + + anchors.fill: parent + objectName: "grid" + model: ListModel { ListElement { text: "text" } } + currentIndex: 0 + + delegate: Text { + objectName: "wrapper" + font.pointSize: 20 + text: index + z: grid.itemZ + } + + header: Rectangle { + width: 240 + height: 30 + z: grid.headerZ + } + + footer: Rectangle { + width: 240 + height: 30 + z: grid.footerZ + } + + highlight: Rectangle { + width: 240 + height: 30 + z: grid.highlightZ + } + } +} + diff --git a/tests/auto/quick/qquickgridview/data/constantZValues.qml b/tests/auto/quick/qquickgridview/data/constantZValues.qml new file mode 100644 index 0000000000..7cf564a12e --- /dev/null +++ b/tests/auto/quick/qquickgridview/data/constantZValues.qml @@ -0,0 +1,46 @@ +import QtQuick 2.0 + +Rectangle { + width: 240 + height: 320 + + GridView { + id: grid + + property real itemZ: 241 + property real headerZ: 242 + property real footerZ: 243 + property real highlightZ: 244 + + anchors.fill: parent + objectName: "grid" + model: ListModel { ListElement { text: "text" } } + currentIndex: 0 + + delegate: Text { + objectName: "wrapper" + font.pointSize: 20 + text: index + z: 241 + } + + header: Rectangle { + width: 240 + height: 30 + z: 242 + } + + footer: Rectangle { + width: 240 + height: 30 + z: 243 + } + + highlight: Rectangle { + width: 240 + height: 30 + z: 244 + } + } +} + diff --git a/tests/auto/quick/qquickgridview/data/initialZValues.qml b/tests/auto/quick/qquickgridview/data/defaultZValues.qml index 9768b2c695..53f11bb2da 100644 --- a/tests/auto/quick/qquickgridview/data/initialZValues.qml +++ b/tests/auto/quick/qquickgridview/data/defaultZValues.qml @@ -7,11 +7,15 @@ Rectangle { GridView { id: grid - property real initialZ: 342 + property real itemZ: 1 + property real headerZ: 1 + property real footerZ: 1 + property real highlightZ: 0 anchors.fill: parent objectName: "grid" - model: ListModel {} + model: ListModel { ListElement { text: "text" } } + currentIndex: 0 delegate: Text { objectName: "wrapper" @@ -22,13 +26,11 @@ Rectangle { header: Rectangle { width: 240 height: 30 - z: grid.initialZ } footer: Rectangle { width: 240 height: 30 - z: grid.initialZ } } } diff --git a/tests/auto/quick/qquickgridview/tst_qquickgridview.cpp b/tests/auto/quick/qquickgridview/tst_qquickgridview.cpp index f4eec18690..890174e2a8 100644 --- a/tests/auto/quick/qquickgridview/tst_qquickgridview.cpp +++ b/tests/auto/quick/qquickgridview/tst_qquickgridview.cpp @@ -121,6 +121,7 @@ private slots: void footer(); void footer_data(); void initialZValues(); + void initialZValues_data(); void header(); void header_data(); void extents(); @@ -3200,8 +3201,9 @@ void tst_QQuickGridView::footer_data() void tst_QQuickGridView::initialZValues() { + QFETCH(QString, fileName); QQuickView *window = createView(); - window->setSource(testFileUrl("initialZValues.qml")); + window->setSource(testFileUrl(fileName)); qApp->processEvents(); QQuickGridView *gridview = findItem<QQuickGridView>(window->rootObject(), "grid"); @@ -3209,15 +3211,29 @@ void tst_QQuickGridView::initialZValues() QQuickItem *contentItem = gridview->contentItem(); QTRY_VERIFY(contentItem != 0); + QVERIFY(gridview->currentItem()); + QTRY_COMPARE(gridview->currentItem()->z(), gridview->property("itemZ").toReal()); + QVERIFY(gridview->headerItem()); - QTRY_COMPARE(gridview->headerItem()->z(), gridview->property("initialZ").toReal()); + QTRY_COMPARE(gridview->headerItem()->z(), gridview->property("headerZ").toReal()); QVERIFY(gridview->footerItem()); - QTRY_COMPARE(gridview->footerItem()->z(), gridview->property("initialZ").toReal()); + QTRY_COMPARE(gridview->footerItem()->z(), gridview->property("footerZ").toReal()); + + QVERIFY(gridview->highlightItem()); + QTRY_COMPARE(gridview->highlightItem()->z(), gridview->property("highlightZ").toReal()); delete window; } +void tst_QQuickGridView::initialZValues_data() +{ + QTest::addColumn<QString>("fileName"); + QTest::newRow("defaults") << "defaultZValues.qml"; + QTest::newRow("constants") << "constantZValues.qml"; + QTest::newRow("bindings") << "boundZValues.qml"; +} + void tst_QQuickGridView::header() { QFETCH(QQuickGridView::Flow, flow); diff --git a/tests/auto/quick/qquickimage/data/heart-highdpi@2x.png b/tests/auto/quick/qquickimage/data/heart-highdpi@2x.png Binary files differnew file mode 100644 index 0000000000..abe97fee4b --- /dev/null +++ b/tests/auto/quick/qquickimage/data/heart-highdpi@2x.png diff --git a/tests/auto/quick/qquickimage/tst_qquickimage.cpp b/tests/auto/quick/qquickimage/tst_qquickimage.cpp index b73dcdfcde..7951cb07cf 100644 --- a/tests/auto/quick/qquickimage/tst_qquickimage.cpp +++ b/tests/auto/quick/qquickimage/tst_qquickimage.cpp @@ -105,6 +105,7 @@ private slots: void progressAndStatusChanges(); void sourceSizeChanges(); void correctStatus(); + void highdpi(); private: QQmlEngine engine; @@ -307,6 +308,10 @@ void tst_qquickimage::mirror() qreal height = 250; foreach (QQuickImage::FillMode fillMode, fillModes) { +#if defined(Q_OS_BLACKBERRY) + QWindow dummy; // On BlackBerry first window is always full screen, + dummy.showFullScreen(); // so make test window a second window. +#endif QQuickView *window = new QQuickView; window->setSource(testFileUrl("mirror.qml")); @@ -315,7 +320,7 @@ void tst_qquickimage::mirror() obj->setFillMode(fillMode); obj->setProperty("mirror", true); - window->show(); + window->showNormal(); QVERIFY(QTest::qWaitForWindowExposed(window)); QImage screenshot = window->grabWindow(); @@ -928,6 +933,49 @@ void tst_qquickimage::correctStatus() delete obj; } +void tst_qquickimage::highdpi() +{ + TestHTTPServer server; + QVERIFY2(server.listen(SERVER_PORT), qPrintable(server.errorString())); + server.serveDirectory(dataDirectory()); + + QString componentStr = "import QtQuick 2.0\nImage { source: srcImage ; }"; + QQmlComponent component(&engine); + component.setData(componentStr.toLatin1(), QUrl::fromLocalFile("")); + QQmlContext *ctxt = engine.rootContext(); + + // Testing "@2x" high-dpi image loading: + // The basic case is as follows. Suppose you have foo.png, + // which is a 64x64 png that fits in a QML layout. Now, + // on a high-dpi system that pixmap would not provide + // enough pixels. To fix this the app developer provides + // a 128x128 foo@2x.png, which Qt automatically loads. + // The image continues to be referred to as "foo.png" in + // the QML sources, and reports a size of 64x64. + // + + // Load "heart-highdpi@2x.png", which is a 300x300 png. As a 2x scale image it + // should render and report a geometry of 150x150. + ctxt->setContextProperty("srcImage", testFileUrl("heart-highdpi@2x.png")); + + QQuickImage *obj = qobject_cast<QQuickImage*>(component.create()); + QVERIFY(obj != 0); + + QCOMPARE(obj->width(), 150.0); + QCOMPARE(obj->height(), 150.0); + QCOMPARE(obj->paintedWidth(), 150.0); + QCOMPARE(obj->paintedHeight(), 150.0); + + // Load a normal 1x image. + ctxt->setContextProperty("srcImage", testFileUrl("heart.png")); + QCOMPARE(obj->width(), 300.0); + QCOMPARE(obj->height(), 300.0); + QCOMPARE(obj->paintedWidth(), 300.0); + QCOMPARE(obj->paintedHeight(), 300.0); + + delete obj; +} + QTEST_MAIN(tst_qquickimage) #include "tst_qquickimage.moc" diff --git a/tests/auto/quick/qquickitem/data/visualParentOwnershipWindow.qml b/tests/auto/quick/qquickitem/data/visualParentOwnershipWindow.qml new file mode 100644 index 0000000000..30fc844d7a --- /dev/null +++ b/tests/auto/quick/qquickitem/data/visualParentOwnershipWindow.qml @@ -0,0 +1,15 @@ +import QtQuick 2.0 +import QtQuick.Window 2.1 + +Window { + Component { + id: factory + Item {} + } + + property Item keepAliveProperty; + + function createItemWithoutParent() { + return factory.createObject(/*parent*/ null); + } +} diff --git a/tests/auto/quick/qquickitem/tst_qquickitem.cpp b/tests/auto/quick/qquickitem/tst_qquickitem.cpp index 8db515432a..40327b0666 100644 --- a/tests/auto/quick/qquickitem/tst_qquickitem.cpp +++ b/tests/auto/quick/qquickitem/tst_qquickitem.cpp @@ -170,6 +170,7 @@ private slots: void acceptedMouseButtons(); void visualParentOwnership(); + void visualParentOwnershipWindow(); private: @@ -1189,8 +1190,9 @@ static inline QByteArray msgItem(const QQuickItem *item) void tst_qquickitem::mouseGrab() { -#if defined(Q_OS_WIN) && defined(QT_OPENGL_ES_2) - QSKIP("Fails in the CI for ANGLE builds on Windows, QTBUG-32664"); +#ifdef Q_OS_WIN + if (QOpenGLContext::openGLModuleType() == QOpenGLContext::LibGLES) + QSKIP("Fails in the CI for ANGLE builds on Windows, QTBUG-32664"); #endif QQuickWindow window; window.setFramePosition(QPoint(100, 100)); @@ -1824,6 +1826,63 @@ void tst_qquickitem::visualParentOwnership() } } +void tst_qquickitem::visualParentOwnershipWindow() +{ + QQmlEngine engine; + QQmlComponent component(&engine, testFileUrl("visualParentOwnershipWindow.qml")); + + QQuickWindow *window = qobject_cast<QQuickWindow*>(component.create()); + QVERIFY(window); + QQuickItem *root = window->contentItem(); + + QVariant newObject; + { + QVERIFY(QMetaObject::invokeMethod(window, "createItemWithoutParent", Q_RETURN_ARG(QVariant, newObject))); + QPointer<QQuickItem> newItem = qvariant_cast<QQuickItem*>(newObject); + QVERIFY(!newItem.isNull()); + + QVERIFY(!newItem->parent()); + QVERIFY(!newItem->parentItem()); + + newItem->setParentItem(root); + + gc(engine); + + QVERIFY(!newItem.isNull()); + newItem->setParentItem(0); + + gc(engine); + QVERIFY(newItem.isNull()); + } + { + QVERIFY(QMetaObject::invokeMethod(window, "createItemWithoutParent", Q_RETURN_ARG(QVariant, newObject))); + QPointer<QQuickItem> firstItem = qvariant_cast<QQuickItem*>(newObject); + QVERIFY(!firstItem.isNull()); + + firstItem->setParentItem(root); + + QVERIFY(QMetaObject::invokeMethod(window, "createItemWithoutParent", Q_RETURN_ARG(QVariant, newObject))); + QPointer<QQuickItem> secondItem = qvariant_cast<QQuickItem*>(newObject); + QVERIFY(!firstItem.isNull()); + + secondItem->setParentItem(firstItem); + + gc(engine); + + delete firstItem; + + window->setProperty("keepAliveProperty", newObject); + + gc(engine); + QVERIFY(!secondItem.isNull()); + + window->setProperty("keepAliveProperty", QVariant()); + + gc(engine); + QVERIFY(secondItem.isNull()); + } +} + QTEST_MAIN(tst_qquickitem) #include "tst_qquickitem.moc" diff --git a/tests/auto/quick/qquickitem2/data/activeFocusOnTab9.qml b/tests/auto/quick/qquickitem2/data/activeFocusOnTab9.qml new file mode 100644 index 0000000000..09bb73639a --- /dev/null +++ b/tests/auto/quick/qquickitem2/data/activeFocusOnTab9.qml @@ -0,0 +1,50 @@ +import QtQuick 2.1 + +Item { + id: main + objectName: "main" + width: 300 + height: 300 + TextInput { + id: textinput1 + objectName: "textinput1" + width: 300 + height: 75 + activeFocusOnTab: true + text: "Text Input 1" + anchors.top: parent.top + anchors.left: parent.left + } + TextInput { + id: textinput2 + objectName: "textinput2" + width: 300 + height: 75 + activeFocusOnTab: true + text: "Text Input 2" + readOnly: true + anchors.top: textinput1.bottom + anchors.left: parent.left + } + TextEdit { + id: textedit1 + objectName: "textedit1" + width: 300 + height: 75 + activeFocusOnTab: true + text: "Text Edit 1" + anchors.top: textinput2.bottom + anchors.left: parent.left + } + TextEdit { + id: textedit2 + objectName: "textedit2" + width: 300 + height: 75 + activeFocusOnTab: true + text: "Text Edit 2" + readOnly: true + anchors.top: textedit1.bottom + anchors.left: parent.left + } +} diff --git a/tests/auto/quick/qquickitem2/data/keysforward.qml b/tests/auto/quick/qquickitem2/data/keysforward.qml new file mode 100644 index 0000000000..f0cb4d9508 --- /dev/null +++ b/tests/auto/quick/qquickitem2/data/keysforward.qml @@ -0,0 +1,84 @@ +/**************************************************************************** +** +** Copyright (C) 2014 Digia Plc and/or its subsidiary(-ies). +** Contact: http://www.qt-project.org/legal +** +** This file is part of the test suite of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** 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 Digia. For licensing terms and +** conditions see http://qt.digia.com/licensing. For further information +** use the contact form at http://qt.digia.com/contact-us. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 2.1 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 2.1 requirements +** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** In addition, as a special exception, Digia gives you certain additional +** rights. These rights are described in the Digia Qt LGPL Exception +** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 3.0 as published by the Free Software +** Foundation and appearing in the file LICENSE.GPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU General Public License version 3.0 requirements will be +** met: http://www.gnu.org/copyleft/gpl.html. +** +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +import QtQuick 2.0 + +Item { + id: root + + property alias source: source + property alias primaryTarget: primaryTarget + property alias secondaryTarget: secondaryTarget + + property var pressedKeys: [] + property var releasedKeys: [] + Keys.onPressed: { var keys = pressedKeys; keys.push(event.key); pressedKeys = keys } + Keys.onReleased: { var keys = releasedKeys; keys.push(event.key); releasedKeys = keys } + + Item { + id: primaryTarget + objectName: "primary" + property var pressedKeys: [] + property var releasedKeys: [] + Keys.forwardTo: secondaryTarget + Keys.onPressed: { event.accepted = event.key === Qt.Key_P; var keys = pressedKeys; keys.push(event.key); pressedKeys = keys } + Keys.onReleased: { event.accepted = event.key === Qt.Key_P; var keys = releasedKeys; keys.push(event.key); releasedKeys = keys } + + Item { + id: source + objectName: "source" + property var pressedKeys: [] + property var releasedKeys: [] + Keys.forwardTo: primaryTarget + Keys.onPressed: { var keys = pressedKeys; keys.push(event.key); pressedKeys = keys } + Keys.onReleased: { var keys = releasedKeys; keys.push(event.key); releasedKeys = keys } + } + } + + Item { + id: secondaryTarget + objectName: "secondary" + property var pressedKeys: [] + property var releasedKeys: [] + Keys.onPressed: { event.accepted = event.key === Qt.Key_S; var keys = pressedKeys; keys.push(event.key); pressedKeys = keys } + Keys.onReleased: { event.accepted = event.key === Qt.Key_S; var keys = releasedKeys; keys.push(event.key); releasedKeys = keys } + } +} diff --git a/tests/auto/quick/qquickitem2/tst_qquickitem.cpp b/tests/auto/quick/qquickitem2/tst_qquickitem.cpp index 10f4aa2c83..9d2188253a 100644 --- a/tests/auto/quick/qquickitem2/tst_qquickitem.cpp +++ b/tests/auto/quick/qquickitem2/tst_qquickitem.cpp @@ -73,6 +73,8 @@ private slots: void activeFocusOnTab6(); void activeFocusOnTab7(); void activeFocusOnTab8(); + void activeFocusOnTab9(); + void activeFocusOnTab10(); void nextItemInFocusChain(); void nextItemInFocusChain2(); @@ -83,6 +85,7 @@ private slots: void standardKeys(); void keysProcessingOrder(); void keysim(); + void keysForward(); void keyNavigation_data(); void keyNavigation(); void keyNavigation_RightToLeft(); @@ -856,6 +859,140 @@ void tst_QQuickItem::activeFocusOnTab8() delete window; } +void tst_QQuickItem::activeFocusOnTab9() +{ + if (qt_tab_all_widgets()) + QSKIP("This function doesn't support iterating all."); + + QQuickView *window = new QQuickView(0); + window->setBaseSize(QSize(300,300)); + + window->setSource(testFileUrl("activeFocusOnTab9.qml")); + window->show(); + window->requestActivate(); + QVERIFY(QTest::qWaitForWindowActive(window)); + QVERIFY(QGuiApplication::focusWindow() == window); + + QQuickItem *content = window->contentItem(); + QVERIFY(content); + QVERIFY(content->hasActiveFocus()); + + QQuickItem *textinput1 = findItem<QQuickItem>(window->rootObject(), "textinput1"); + QVERIFY(textinput1); + QQuickItem *textedit1 = findItem<QQuickItem>(window->rootObject(), "textedit1"); + QVERIFY(textedit1); + + QVERIFY(!textinput1->hasActiveFocus()); + textinput1->forceActiveFocus(); + QVERIFY(textinput1->hasActiveFocus()); + + // Tab: textinput1->textedit1 + QKeyEvent key(QEvent::KeyPress, Qt::Key_Tab, Qt::NoModifier, "", false, 1); + QGuiApplication::sendEvent(window, &key); + QVERIFY(key.isAccepted()); + + QVERIFY(textedit1->hasActiveFocus()); + + // BackTab: textedit1->textinput1 + key = QKeyEvent(QEvent::KeyPress, Qt::Key_Tab, Qt::ShiftModifier, "", false, 1); + QGuiApplication::sendEvent(window, &key); + QVERIFY(key.isAccepted()); + + QVERIFY(textinput1->hasActiveFocus()); + + // BackTab: textinput1->textedit1 + key = QKeyEvent(QEvent::KeyPress, Qt::Key_Tab, Qt::ShiftModifier, "", false, 1); + QGuiApplication::sendEvent(window, &key); + QVERIFY(key.isAccepted()); + + QVERIFY(textedit1->hasActiveFocus()); + + delete window; +} + +void tst_QQuickItem::activeFocusOnTab10() +{ + if (!qt_tab_all_widgets()) + QSKIP("This function doesn't support NOT iterating all."); + + QQuickView *window = new QQuickView(0); + window->setBaseSize(QSize(300,300)); + + window->setSource(testFileUrl("activeFocusOnTab9.qml")); + window->show(); + window->requestActivate(); + QVERIFY(QTest::qWaitForWindowActive(window)); + QVERIFY(QGuiApplication::focusWindow() == window); + + QQuickItem *content = window->contentItem(); + QVERIFY(content); + QVERIFY(content->hasActiveFocus()); + + QQuickItem *textinput1 = findItem<QQuickItem>(window->rootObject(), "textinput1"); + QVERIFY(textinput1); + QQuickItem *textedit1 = findItem<QQuickItem>(window->rootObject(), "textedit1"); + QVERIFY(textedit1); + QQuickItem *textinput2 = findItem<QQuickItem>(window->rootObject(), "textinput2"); + QVERIFY(textinput2); + QQuickItem *textedit2 = findItem<QQuickItem>(window->rootObject(), "textedit2"); + QVERIFY(textedit2); + + QVERIFY(!textinput1->hasActiveFocus()); + textinput1->forceActiveFocus(); + QVERIFY(textinput1->hasActiveFocus()); + + // Tab: textinput1->textinput2 + QKeyEvent key(QEvent::KeyPress, Qt::Key_Tab, Qt::NoModifier, "", false, 1); + QGuiApplication::sendEvent(window, &key); + QVERIFY(key.isAccepted()); + + QVERIFY(textinput2->hasActiveFocus()); + + // Tab: textinput2->textedit1 + key = QKeyEvent(QEvent::KeyPress, Qt::Key_Tab, Qt::NoModifier, "", false, 1); + QGuiApplication::sendEvent(window, &key); + QVERIFY(key.isAccepted()); + + QVERIFY(textedit1->hasActiveFocus()); + + // BackTab: textedit1->textinput2 + key = QKeyEvent(QEvent::KeyPress, Qt::Key_Tab, Qt::ShiftModifier, "", false, 1); + QGuiApplication::sendEvent(window, &key); + QVERIFY(key.isAccepted()); + + QVERIFY(textinput2->hasActiveFocus()); + + // BackTab: textinput2->textinput1 + key = QKeyEvent(QEvent::KeyPress, Qt::Key_Tab, Qt::ShiftModifier, "", false, 1); + QGuiApplication::sendEvent(window, &key); + QVERIFY(key.isAccepted()); + + QVERIFY(textinput1->hasActiveFocus()); + + // BackTab: textinput1->textedit2 + key = QKeyEvent(QEvent::KeyPress, Qt::Key_Tab, Qt::ShiftModifier, "", false, 1); + QGuiApplication::sendEvent(window, &key); + QVERIFY(key.isAccepted()); + + QVERIFY(textedit2->hasActiveFocus()); + + // BackTab: textedit2->textedit1 + key = QKeyEvent(QEvent::KeyPress, Qt::Key_Tab, Qt::ShiftModifier, "", false, 1); + QGuiApplication::sendEvent(window, &key); + QVERIFY(key.isAccepted()); + + QVERIFY(textedit1->hasActiveFocus()); + + // BackTab: textedit1->textinput2 + key = QKeyEvent(QEvent::KeyPress, Qt::Key_Tab, Qt::ShiftModifier, "", false, 1); + QGuiApplication::sendEvent(window, &key); + QVERIFY(key.isAccepted()); + + QVERIFY(textinput2->hasActiveFocus()); + + delete window; +} + void tst_QQuickItem::nextItemInFocusChain() { if (!qt_tab_all_widgets()) @@ -1268,6 +1405,78 @@ void tst_QQuickItem::keysim() delete window; } +void tst_QQuickItem::keysForward() +{ + QQuickView window; + window.setBaseSize(QSize(240,320)); + + window.setSource(testFileUrl("keysforward.qml")); + window.show(); + window.requestActivate(); + QVERIFY(QTest::qWaitForWindowActive(&window)); + QVERIFY(QGuiApplication::focusWindow() == &window); + + QQuickItem *rootItem = qobject_cast<QQuickItem *>(window.rootObject()); + QVERIFY(rootItem); + QQuickItem *sourceItem = rootItem->property("source").value<QQuickItem *>(); + QVERIFY(sourceItem); + QQuickItem *primaryTarget = rootItem->property("primaryTarget").value<QQuickItem *>(); + QVERIFY(primaryTarget); + QQuickItem *secondaryTarget = rootItem->property("secondaryTarget").value<QQuickItem *>(); + QVERIFY(secondaryTarget); + + // primary target accepts/consumes Key_P + QKeyEvent pressKeyP(QEvent::KeyPress, Qt::Key_P, Qt::NoModifier, "P"); + QCoreApplication::sendEvent(sourceItem, &pressKeyP); + QCOMPARE(rootItem->property("pressedKeys").toList(), QVariantList()); + QCOMPARE(sourceItem->property("pressedKeys").toList(), QVariantList()); + QCOMPARE(primaryTarget->property("pressedKeys").toList(), QVariantList() << Qt::Key_P); + QCOMPARE(secondaryTarget->property("pressedKeys").toList(), QVariantList() << Qt::Key_P); + QVERIFY(pressKeyP.isAccepted()); + + QKeyEvent releaseKeyP(QEvent::KeyRelease, Qt::Key_P, Qt::NoModifier, "P"); + QCoreApplication::sendEvent(sourceItem, &releaseKeyP); + QCOMPARE(rootItem->property("releasedKeys").toList(), QVariantList()); + QCOMPARE(sourceItem->property("releasedKeys").toList(), QVariantList()); + QCOMPARE(primaryTarget->property("releasedKeys").toList(), QVariantList() << Qt::Key_P); + QCOMPARE(secondaryTarget->property("releasedKeys").toList(), QVariantList() << Qt::Key_P); + QVERIFY(releaseKeyP.isAccepted()); + + // secondary target accepts/consumes Key_S + QKeyEvent pressKeyS(QEvent::KeyPress, Qt::Key_S, Qt::NoModifier, "S"); + QCoreApplication::sendEvent(sourceItem, &pressKeyS); + QCOMPARE(rootItem->property("pressedKeys").toList(), QVariantList()); + QCOMPARE(sourceItem->property("pressedKeys").toList(), QVariantList()); + QCOMPARE(primaryTarget->property("pressedKeys").toList(), QVariantList() << Qt::Key_P); + QCOMPARE(secondaryTarget->property("pressedKeys").toList(), QVariantList() << Qt::Key_P << Qt::Key_S); + QVERIFY(pressKeyS.isAccepted()); + + QKeyEvent releaseKeyS(QEvent::KeyRelease, Qt::Key_S, Qt::NoModifier, "S"); + QCoreApplication::sendEvent(sourceItem, &releaseKeyS); + QCOMPARE(rootItem->property("releasedKeys").toList(), QVariantList()); + QCOMPARE(sourceItem->property("releasedKeys").toList(), QVariantList()); + QCOMPARE(primaryTarget->property("releasedKeys").toList(), QVariantList() << Qt::Key_P); + QCOMPARE(secondaryTarget->property("releasedKeys").toList(), QVariantList() << Qt::Key_P << Qt::Key_S); + QVERIFY(releaseKeyS.isAccepted()); + + // neither target accepts/consumes Key_Q + QKeyEvent pressKeyQ(QEvent::KeyPress, Qt::Key_Q, Qt::NoModifier, "Q"); + QCoreApplication::sendEvent(sourceItem, &pressKeyQ); + QCOMPARE(rootItem->property("pressedKeys").toList(), QVariantList()); + QCOMPARE(sourceItem->property("pressedKeys").toList(), QVariantList() << Qt::Key_Q); + QCOMPARE(primaryTarget->property("pressedKeys").toList(), QVariantList() << Qt::Key_P << Qt::Key_Q); + QCOMPARE(secondaryTarget->property("pressedKeys").toList(), QVariantList() << Qt::Key_P << Qt::Key_S << Qt::Key_Q); + QVERIFY(!pressKeyQ.isAccepted()); + + QKeyEvent releaseKeyQ(QEvent::KeyRelease, Qt::Key_Q, Qt::NoModifier, "Q"); + QCoreApplication::sendEvent(sourceItem, &releaseKeyQ); + QCOMPARE(rootItem->property("releasedKeys").toList(), QVariantList()); + QCOMPARE(sourceItem->property("releasedKeys").toList(), QVariantList() << Qt::Key_Q); + QCOMPARE(primaryTarget->property("releasedKeys").toList(), QVariantList() << Qt::Key_P << Qt::Key_Q); + QCOMPARE(secondaryTarget->property("releasedKeys").toList(), QVariantList() << Qt::Key_P << Qt::Key_S << Qt::Key_Q); + QVERIFY(!releaseKeyQ.isAccepted()); +} + QQuickItemPrivate *childPrivate(QQuickItem *rootItem, const char * itemString) { QQuickItem *item = findItem<QQuickItem>(rootItem, QString(QLatin1String(itemString))); diff --git a/tests/auto/quick/qquickitemlayer/tst_qquickitemlayer.cpp b/tests/auto/quick/qquickitemlayer/tst_qquickitemlayer.cpp index 4f103bd1fa..b5980929a6 100644 --- a/tests/auto/quick/qquickitemlayer/tst_qquickitemlayer.cpp +++ b/tests/auto/quick/qquickitemlayer/tst_qquickitemlayer.cpp @@ -55,10 +55,14 @@ public: QImage runTest(const QString &fileName) { +#if defined(Q_OS_BLACKBERRY) + QWindow dummy; // On BlackBerry first window is always full screen, + dummy.showFullScreen(); // so make test window a second window. +#endif QQuickView view; view.setSource(testFileUrl(fileName)); - view.show(); + view.showNormal(); QTest::qWaitForWindowExposed(&view); return view.grabWindow(); diff --git a/tests/auto/quick/qquicklistview/data/boundZValues.qml b/tests/auto/quick/qquicklistview/data/boundZValues.qml new file mode 100644 index 0000000000..10810e540d --- /dev/null +++ b/tests/auto/quick/qquicklistview/data/boundZValues.qml @@ -0,0 +1,55 @@ +import QtQuick 2.0 + +Rectangle { + width: 240 + height: 320 + + ListView { + id: list + + property real itemZ: 342 + property real headerZ: 341 + property real footerZ: 340 + property real highlightZ: 339 + property real sectionZ: 338 + + anchors.fill: parent + objectName: "list" + model: ListModel { ListElement { text: "text" } } + currentIndex: 0 + + delegate: Text { + objectName: "wrapper" + font.pointSize: 20 + text: index + z: list.itemZ + } + + header: Rectangle { + width: 240 + height: 30 + z: list.headerZ + } + + footer: Rectangle { + width: 240 + height: 30 + z: list.footerZ + } + + highlight: Rectangle { + width: 240 + height: 30 + z: list.highlightZ + } + + section.property: "text" + section.delegate: Text { + objectName: "section" + font.pointSize: 20 + text: section + z: list.sectionZ + } + } +} + diff --git a/tests/auto/quick/qquicklistview/data/constantZValues.qml b/tests/auto/quick/qquicklistview/data/constantZValues.qml new file mode 100644 index 0000000000..48917fed4f --- /dev/null +++ b/tests/auto/quick/qquicklistview/data/constantZValues.qml @@ -0,0 +1,55 @@ +import QtQuick 2.0 + +Rectangle { + width: 240 + height: 320 + + ListView { + id: list + + property real itemZ: 241 + property real headerZ: 242 + property real footerZ: 243 + property real highlightZ: 244 + property real sectionZ: 245 + + anchors.fill: parent + objectName: "list" + model: ListModel { ListElement { text: "text" } } + currentIndex: 0 + + delegate: Text { + objectName: "wrapper" + font.pointSize: 20 + text: index + z: 241 + } + + header: Rectangle { + width: 240 + height: 30 + z: 242 + } + + footer: Rectangle { + width: 240 + height: 30 + z: 243 + } + + highlight: Rectangle { + width: 240 + height: 30 + z: 244 + } + + section.property: "text" + section.delegate: Text { + objectName: "section" + font.pointSize: 20 + text: section + z: 245 + } + } +} + diff --git a/tests/auto/quick/qquicklistview/data/defaultZValues.qml b/tests/auto/quick/qquicklistview/data/defaultZValues.qml new file mode 100644 index 0000000000..7326340ae4 --- /dev/null +++ b/tests/auto/quick/qquicklistview/data/defaultZValues.qml @@ -0,0 +1,49 @@ +import QtQuick 2.0 + +Rectangle { + width: 240 + height: 320 + + ListView { + id: list + + property real itemZ: 1 + property real headerZ: 1 + property real footerZ: 1 + property real highlightZ: 0 + property real sectionZ: 2 + + anchors.fill: parent + objectName: "list" + model: ListModel { ListElement { text: "text" } } + currentIndex: 0 + + delegate: Text { + objectName: "wrapper" + font.pointSize: 20 + text: index + } + + header: Rectangle { + width: 240 + height: 30 + } + + footer: Rectangle { + width: 240 + height: 30 + } + + highlight: Rectangle { + width: 240 + height: 30 + } + + section.property: "text" + section.delegate: Text { + objectName: "section" + font.pointSize: 20 + text: section + } + } +} diff --git a/tests/auto/quick/qquicklistview/data/initialZValues.qml b/tests/auto/quick/qquicklistview/data/initialZValues.qml deleted file mode 100644 index 3a8e78debb..0000000000 --- a/tests/auto/quick/qquicklistview/data/initialZValues.qml +++ /dev/null @@ -1,35 +0,0 @@ -import QtQuick 2.0 - -Rectangle { - width: 240 - height: 320 - - ListView { - id: list - - property real initialZ: 342 - - anchors.fill: parent - objectName: "list" - model: ListModel {} - - delegate: Text { - objectName: "wrapper" - font.pointSize: 20 - text: index - } - - header: Rectangle { - width: 240 - height: 30 - z: list.initialZ - } - - footer: Rectangle { - width: 240 - height: 30 - z: list.initialZ - } - } -} - diff --git a/tests/auto/quick/qquicklistview/data/outsideViewportChangeNotAffectingView.qml b/tests/auto/quick/qquicklistview/data/outsideViewportChangeNotAffectingView.qml index 7903c392d1..c57cde5eda 100644 --- a/tests/auto/quick/qquicklistview/data/outsideViewportChangeNotAffectingView.qml +++ b/tests/auto/quick/qquicklistview/data/outsideViewportChangeNotAffectingView.qml @@ -42,13 +42,16 @@ import QtQuick 2.1 import QtTest 1.0 Item { + width: 300 + height: 542 + function resizeThirdItem(size) { resizingListModel.setProperty(3, "size", size) } ListView { - width: 300 - height: 542 + id: list + anchors.fill: parent model: ListModel { id: resizingListModel ListElement { size: 300; } @@ -62,6 +65,9 @@ Item { width: parent.width color: index % 2 == 0 ? "red" : "blue" height: size + Text { anchors.centerIn: parent; text: index } } } + + Text { text: list.contentY; color: "white" } } diff --git a/tests/auto/quick/qquicklistview/data/roundingErrors.qml b/tests/auto/quick/qquicklistview/data/roundingErrors.qml new file mode 100644 index 0000000000..aebdce04c3 --- /dev/null +++ b/tests/auto/quick/qquicklistview/data/roundingErrors.qml @@ -0,0 +1,130 @@ +/**************************************************************************** +** +** Copyright (C) 2014 Digia Plc and/or its subsidiary(-ies). +** Contact: http://www.qt-project.org/legal +** +** This file is part of the test suite of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:BSD$ +** 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 Digia Plc and its Subsidiary(-ies) 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 QtQuick 2.0 +import QtQml.Models 2.1 + +ListView { + id: listview + + width: 600 + height: 200 + + spacing: 8 + orientation: ListView.Horizontal + + Component.onCompleted: { + var colors = ["blue", "green", "red", "yellow", "orange", "purple", "cyan", + "magenta", "chartreuse", "aquamarine", "indigo", "lightsteelblue", + "violet", "grey", "springgreen", "salmon", "blanchedalmond", + "forestgreen", "pink", "navy", "goldenrod", "crimson", "teal" ] + for (var i = 0; i < 100; ++i) + colorModel.append( { nid: i, color: colors[i%colors.length] } ) + } + + model: DelegateModel { + id: visualModel + + model: ListModel { + id: colorModel + } + + delegate: MouseArea { + id: delegateRoot + objectName: model.nid + + width: 107.35 + height: 63.35 + + drag.target: icon + + Rectangle{ + id: icon + width: delegateRoot.width + height: delegateRoot.height + anchors.horizontalCenter: parent.horizontalCenter + anchors.verticalCenter: parent.verticalCenter + color: model.color + + Drag.active: delegateRoot.drag.active + Drag.source: delegateRoot + Drag.hotSpot.x: 36 + Drag.hotSpot.y: 36 + + Text { + id: text + anchors.fill: parent + font.pointSize: 40 + text: model.nid + horizontalAlignment: Qt.AlignHCenter + verticalAlignment: Qt.AlignVCenter + } + + states: [ + State { + when: icon.Drag.active + ParentChange { + target: icon + parent: delegateRoot.ListView.view + } + + AnchorChanges { + target: icon + anchors.horizontalCenter: undefined + anchors.verticalCenter: undefined + } + } + ] + } + } + } + + DropArea { + anchors.fill: parent + onPositionChanged: { + var to = listview.indexAt(drag.x + listview.contentX, 0) + if (to !== -1) { + var from = drag.source.DelegateModel.itemsIndex + if (from !== to) + visualModel.items.move(from, to) + drag.accept() + } + } + } +} diff --git a/tests/auto/quick/qquicklistview/qquicklistview.pro b/tests/auto/quick/qquicklistview/qquicklistview.pro index 4ac47679da..2ae04d32fe 100644 --- a/tests/auto/quick/qquicklistview/qquicklistview.pro +++ b/tests/auto/quick/qquicklistview/qquicklistview.pro @@ -17,4 +17,3 @@ TESTDATA = data/* QT += core-private gui-private qml-private quick-private testlib DEFINES += QT_DISABLE_DEPRECATED_BEFORE=0 -mac:CONFIG += insignificant_test # QTBUG-27740 diff --git a/tests/auto/quick/qquicklistview/tst_qquicklistview.cpp b/tests/auto/quick/qquicklistview/tst_qquicklistview.cpp index efd0fa8103..29755e3890 100644 --- a/tests/auto/quick/qquicklistview/tst_qquicklistview.cpp +++ b/tests/auto/quick/qquicklistview/tst_qquicklistview.cpp @@ -147,6 +147,7 @@ private slots: void modelChanges(); void manualHighlight(); void initialZValues(); + void initialZValues_data(); void header(); void header_data(); void header_delayItemCreation(); @@ -223,6 +224,9 @@ private slots: void QTBUG_36481(); void QTBUG_35920(); + void roundingErrors(); + void roundingErrors_data(); + private: template <class T> void items(const QUrl &source); template <class T> void changed(const QUrl &source); @@ -3346,9 +3350,9 @@ void tst_QQuickListView::modelChanges() void tst_QQuickListView::QTBUG_9791() { QQuickView *window = createView(); - window->setSource(testFileUrl("strictlyenforcerange.qml")); - qApp->processEvents(); + window->show(); + QVERIFY(QTest::qWaitForWindowExposed(window)); QQuickListView *listview = qobject_cast<QQuickListView*>(window->rootObject()); QTRY_VERIFY(listview != 0); @@ -3465,8 +3469,9 @@ void tst_QQuickListView::QTBUG_11105() void tst_QQuickListView::initialZValues() { + QFETCH(QString, fileName); QQuickView *window = createView(); - window->setSource(testFileUrl("initialZValues.qml")); + window->setSource(testFileUrl(fileName)); qApp->processEvents(); QQuickListView *listview = findItem<QQuickListView>(window->rootObject(), "list"); @@ -3474,15 +3479,33 @@ void tst_QQuickListView::initialZValues() QQuickItem *contentItem = listview->contentItem(); QTRY_VERIFY(contentItem != 0); + QVERIFY(listview->currentItem()); + QTRY_COMPARE(listview->currentItem()->z(), listview->property("itemZ").toReal()); + QVERIFY(listview->headerItem()); - QTRY_COMPARE(listview->headerItem()->z(), listview->property("initialZ").toReal()); + QTRY_COMPARE(listview->headerItem()->z(), listview->property("headerZ").toReal()); QVERIFY(listview->footerItem()); - QTRY_COMPARE(listview->footerItem()->z(), listview->property("initialZ").toReal()); + QTRY_COMPARE(listview->footerItem()->z(), listview->property("footerZ").toReal()); + + QVERIFY(listview->highlightItem()); + QTRY_COMPARE(listview->highlightItem()->z(), listview->property("highlightZ").toReal()); + + QQuickText *sectionItem = 0; + QTRY_VERIFY(sectionItem = findItem<QQuickText>(contentItem, "section")); + QTRY_COMPARE(sectionItem->z(), listview->property("sectionZ").toReal()); delete window; } +void tst_QQuickListView::initialZValues_data() +{ + QTest::addColumn<QString>("fileName"); + QTest::newRow("defaults") << "defaultZValues.qml"; + QTest::newRow("constants") << "constantZValues.qml"; + QTest::newRow("bindings") << "boundZValues.qml"; +} + void tst_QQuickListView::header() { QFETCH(QQuickListView::Orientation, orientation); @@ -7027,9 +7050,7 @@ void tst_QQuickListView::outsideViewportChangeNotAffectingView() window->show(); QVERIFY(QTest::qWaitForWindowExposed(window)); - flick(window, QPoint(20, 200), QPoint(20, 20), 10); - - QTRY_COMPARE(listview->isFlicking(), false); + listview->setContentY(1250); QTRY_COMPARE(listview->indexAt(0, listview->contentY()), 4); QTRY_COMPARE(listview->itemAt(0, listview->contentY())->y(), 1200.); @@ -7127,12 +7148,12 @@ void tst_QQuickListView::displayMargin() void tst_QQuickListView::highlightItemGeometryChanges() { - QQmlEngine engine; - QQmlComponent component(&engine, testFileUrl("HighlightResize.qml")); - - QScopedPointer<QObject> object(component.create()); + QScopedPointer<QQuickView> window(createView()); + window->setSource(testFileUrl("HighlightResize.qml")); + window->show(); + QVERIFY(QTest::qWaitForWindowExposed(window.data())); - QQuickListView *listview = qobject_cast<QQuickListView *>(object.data()); + QQuickListView *listview = qobject_cast<QQuickListView *>(window->rootObject()); QVERIFY(listview); QCOMPARE(listview->count(), 5); @@ -7183,6 +7204,63 @@ void tst_QQuickListView::QTBUG_35920() QTest::mouseRelease(window.data(), Qt::LeftButton, 0, QPoint(10,100)); } +void tst_QQuickListView::roundingErrors() +{ + QFETCH(bool, pixelAligned); + + QScopedPointer<QQuickView> window(createView()); + window->setSource(testFileUrl("roundingErrors.qml")); + window->show(); + QVERIFY(QTest::qWaitForWindowExposed(window.data())); + + QQuickListView *listview = qobject_cast<QQuickListView *>(window->rootObject()); + QVERIFY(listview); + listview->setPixelAligned(pixelAligned); + listview->positionViewAtIndex(20, QQuickListView::Beginning); + + QQuickItem *content = listview->contentItem(); + QVERIFY(content); + + const QPoint viewPos(150, 36); + const QPointF contentPos = content->mapFromItem(listview, viewPos); + + QPointer<QQuickItem> item = listview->itemAt(contentPos.x(), contentPos.y()); + QVERIFY(item); + + // QTBUG-37339: drag an item and verify that it doesn't + // get prematurely released due to rounding errors + QTest::mousePress(window.data(), Qt::LeftButton, 0, viewPos); + for (int i = 0; i < 150; i += 5) { + QTest::mouseMove(window.data(), viewPos - QPoint(i, 0)); + QVERIFY(item); + } + QTest::mouseRelease(window.data(), Qt::LeftButton, 0, QPoint(0, 36)); + + // maintain position relative to the right edge + listview->setLayoutDirection(Qt::RightToLeft); + const qreal contentX = listview->contentX(); + listview->setContentX(contentX + 0.2); + QCOMPARE(listview->contentX(), pixelAligned ? qRound(contentX + 0.2) : contentX + 0.2); + listview->setWidth(listview->width() - 0.2); + QCOMPARE(listview->contentX(), pixelAligned ? qRound(contentX + 0.2) : contentX + 0.2); + + // maintain position relative to the bottom edge + listview->setOrientation(QQuickListView::Vertical); + listview->setVerticalLayoutDirection(QQuickListView::BottomToTop); + const qreal contentY = listview->contentY(); + listview->setContentY(contentY + 0.2); + QCOMPARE(listview->contentY(), pixelAligned ? qRound(contentY + 0.2) : contentY + 0.2); + listview->setHeight(listview->height() - 0.2); + QCOMPARE(listview->contentY(), pixelAligned ? qRound(contentY + 0.2) : contentY + 0.2); +} + +void tst_QQuickListView::roundingErrors_data() +{ + QTest::addColumn<bool>("pixelAligned"); + QTest::newRow("pixelAligned=true") << true; + QTest::newRow("pixelAligned=false") << false; +} + QTEST_MAIN(tst_QQuickListView) #include "tst_qquicklistview.moc" diff --git a/tests/auto/quick/qquicksmoothedanimation/tst_qquicksmoothedanimation.cpp b/tests/auto/quick/qquicksmoothedanimation/tst_qquicksmoothedanimation.cpp index 650ce09dfa..7642583bb1 100644 --- a/tests/auto/quick/qquicksmoothedanimation/tst_qquicksmoothedanimation.cpp +++ b/tests/auto/quick/qquicksmoothedanimation/tst_qquicksmoothedanimation.cpp @@ -61,6 +61,7 @@ private slots: void behavior(); void deleteOnUpdate(); void zeroDuration(); + void noStart(); private: QQmlEngine engine; @@ -263,6 +264,27 @@ void tst_qquicksmoothedanimation::zeroDuration() delete rect; } +//verify that an empty SmoothedAnimation does not fire up the animation system +//and keep it running forever +void tst_qquicksmoothedanimation::noStart() +{ + QQmlEngine engine; + QQmlComponent c(&engine, testFileUrl("smoothedanimation1.qml")); + QQuickSmoothedAnimation *obj = qobject_cast<QQuickSmoothedAnimation*>(c.create()); + + QVERIFY(obj != 0); + + obj->start(); + QCOMPARE(obj->isRunning(), false); + QTest::qWait(100); + QCOMPARE(obj->isRunning(), false); + //this could fail if the test is being run in parallel with other tests + //or if an earlier test failed and didn't clean up (left an animation running) + //QCOMPARE(QUnifiedTimer::instance()->runningAnimationCount(), 0); + + delete obj; +} + QTEST_MAIN(tst_qquicksmoothedanimation) #include "tst_qquicksmoothedanimation.moc" diff --git a/tests/auto/quick/qquickstates/data/QTBUG-38492.qml b/tests/auto/quick/qquickstates/data/QTBUG-38492.qml new file mode 100644 index 0000000000..d6d6d81fd3 --- /dev/null +++ b/tests/auto/quick/qquickstates/data/QTBUG-38492.qml @@ -0,0 +1,16 @@ +import QtQuick 2.0 + +Item { + id: root + property string text; + + states: [ + State { + name: 'apply' + PropertyChanges { + target: root + text: qsTr("Test") + } + } + ] +} diff --git a/tests/auto/quick/qquickstates/tst_qquickstates.cpp b/tests/auto/quick/qquickstates/tst_qquickstates.cpp index 0c9b75636f..6b46ab1fae 100644 --- a/tests/auto/quick/qquickstates/tst_qquickstates.cpp +++ b/tests/auto/quick/qquickstates/tst_qquickstates.cpp @@ -148,6 +148,7 @@ private slots: void QTBUG_14830(); void avoidFastForward(); void revertListBug(); + void QTBUG_38492(); }; void tst_qquickstates::initTestCase() @@ -1626,6 +1627,21 @@ void tst_qquickstates::revertListBug() QCOMPARE(rect2->parentItem(), origParent2); //QTBUG-22583 causes rect2's parent item to be origParent1 } +void tst_qquickstates::QTBUG_38492() +{ + QQmlEngine engine; + + QQmlComponent rectComponent(&engine, testFileUrl("QTBUG-38492.qml")); + QQuickItem *item = qobject_cast<QQuickItem*>(rectComponent.create()); + QVERIFY(item != 0); + + QQuickItemPrivate::get(item)->setState("apply"); + + QCOMPARE(item->property("text").toString(), QString("Test")); + + delete item; +} + QTEST_MAIN(tst_qquickstates) #include "tst_qquickstates.moc" diff --git a/tests/auto/quick/qquickstyledtext/tst_qquickstyledtext.cpp b/tests/auto/quick/qquickstyledtext/tst_qquickstyledtext.cpp index a2e05ba883..be46f362d6 100644 --- a/tests/auto/quick/qquickstyledtext/tst_qquickstyledtext.cpp +++ b/tests/auto/quick/qquickstyledtext/tst_qquickstyledtext.cpp @@ -126,26 +126,26 @@ void tst_qquickstyledtext::textOutput_data() QTest::newRow("paragraph closed") << "text<p>more text</p>more text" << QLatin1String("text") + QChar(QChar::LineSeparator) + QLatin1String("more text") + QChar(QChar::LineSeparator) + QLatin1String("more text") << FormatList() << false; QTest::newRow("paragraph closed bold") << "<b>text<p>more text</p>more text</b>" << QLatin1String("text") + QChar(QChar::LineSeparator) + QLatin1String("more text") + QChar(QChar::LineSeparator) + QLatin1String("more text") << (FormatList() << Format(Format::Bold, 0, 24)) << false; QTest::newRow("unknown tag") << "<a href='#'><foo>underline</foo></a> not" << "underline not" << (FormatList() << Format(Format::Underline, 0, 9)) << false; - QTest::newRow("ordered list") << "<ol><li>one<li>two" << QChar(QChar::LineSeparator) + QString(6, QChar::Nbsp) + QLatin1String("1.") + QString(2, QChar::Nbsp) + QLatin1String("one") + QChar(QChar::LineSeparator) + QString(6, QChar::Nbsp) + QLatin1String("2.") + QString(2, QChar::Nbsp) + QLatin1String("two") << FormatList() << false; - QTest::newRow("ordered list closed") << "<ol><li>one</li><li>two</li></ol>" << QChar(QChar::LineSeparator) + QString(6, QChar::Nbsp) + QLatin1String("1.") + QString(2, QChar::Nbsp) + QLatin1String("one") + QChar(QChar::LineSeparator) + QString(6, QChar::Nbsp) + QLatin1String("2.") + QString(2, QChar::Nbsp) + QLatin1String("two") + QChar(QChar::LineSeparator) << FormatList() << false; - QTest::newRow("ordered list alpha") << "<ol type=\"a\"><li>one</li><li>two</li></ol>" << QChar(QChar::LineSeparator) + QString(6, QChar::Nbsp) + QLatin1String("a.") + QString(2, QChar::Nbsp) + QLatin1String("one") + QChar(QChar::LineSeparator) + QString(6, QChar::Nbsp) + QLatin1String("b.") + QString(2, QChar::Nbsp) + QLatin1String("two") + QChar(QChar::LineSeparator) << FormatList() << false; - QTest::newRow("ordered list upper alpha") << "<ol type=\"A\"><li>one</li><li>two</li></ol>" << QChar(QChar::LineSeparator) + QString(6, QChar::Nbsp) + QLatin1String("A.") + QString(2, QChar::Nbsp) + QLatin1String("one") + QChar(QChar::LineSeparator) + QString(6, QChar::Nbsp) + QLatin1String("B.") + QString(2, QChar::Nbsp) + QLatin1String("two") + QChar(QChar::LineSeparator) << FormatList() << false; - QTest::newRow("ordered list roman") << "<ol type=\"i\"><li>one</li><li>two</li></ol>" << QChar(QChar::LineSeparator) + QString(6, QChar::Nbsp) + QLatin1String("i.") + QString(2, QChar::Nbsp) + QLatin1String("one") + QChar(QChar::LineSeparator) + QString(6, QChar::Nbsp) + QLatin1String("ii.") + QString(2, QChar::Nbsp) + QLatin1String("two") + QChar(QChar::LineSeparator) << FormatList() << false; - QTest::newRow("ordered list upper roman") << "<ol type=\"I\"><li>one</li><li>two</li></ol>" << QChar(QChar::LineSeparator) + QString(6, QChar::Nbsp) + QLatin1String("I.") + QString(2, QChar::Nbsp) + QLatin1String("one") + QChar(QChar::LineSeparator) + QString(6, QChar::Nbsp) + QLatin1String("II.") + QString(2, QChar::Nbsp) + QLatin1String("two") + QChar(QChar::LineSeparator) << FormatList() << false; - QTest::newRow("ordered list bad") << "<ol type=\"z\"><li>one</li><li>two</li></ol>" << QChar(QChar::LineSeparator) + QString(6, QChar::Nbsp) + QLatin1String("1.") + QString(2, QChar::Nbsp) + QLatin1String("one") + QChar(QChar::LineSeparator) + QString(6, QChar::Nbsp) + QLatin1String("2.") + QString(2, QChar::Nbsp) + QLatin1String("two") + QChar(QChar::LineSeparator) << FormatList() << false; - QTest::newRow("unordered list") << "<ul><li>one<li>two" << QChar(QChar::LineSeparator) + QString(6, QChar::Nbsp) + bullet + QString(2, QChar::Nbsp) + QLatin1String("one") + QChar(QChar::LineSeparator) + QString(6, QChar::Nbsp) + bullet + QString(2, QChar::Nbsp) + QLatin1String("two") << FormatList() << false; - QTest::newRow("unordered list closed") << "<ul><li>one</li><li>two</li></ul>" << QChar(QChar::LineSeparator) + QString(6, QChar::Nbsp) + bullet + QString(2, QChar::Nbsp) + QLatin1String("one") + QChar(QChar::LineSeparator) + QString(6, QChar::Nbsp) + bullet + QString(2, QChar::Nbsp) + QLatin1String("two") + QChar(QChar::LineSeparator) << FormatList() << false; - QTest::newRow("unordered list disc") << "<ul type=\"disc\"><li>one</li><li>two</li></ul>" << QChar(QChar::LineSeparator) + QString(6, QChar::Nbsp) + disc + QString(2, QChar::Nbsp) + QLatin1String("one") + QChar(QChar::LineSeparator) + QString(6, QChar::Nbsp) + disc + QString(2, QChar::Nbsp) + QLatin1String("two") + QChar(QChar::LineSeparator) << FormatList() << false; - QTest::newRow("unordered list square") << "<ul type=\"square\"><li>one</li><li>two</li></ul>" << QChar(QChar::LineSeparator) + QString(6, QChar::Nbsp) + square + QString(2, QChar::Nbsp) + QLatin1String("one") + QChar(QChar::LineSeparator) + QString(6, QChar::Nbsp) + square + QString(2, QChar::Nbsp) + QLatin1String("two") + QChar(QChar::LineSeparator) << FormatList() << false; - QTest::newRow("unordered list bad") << "<ul type=\"bad\"><li>one</li><li>two</li></ul>" << QChar(QChar::LineSeparator) + QString(6, QChar::Nbsp) + bullet + QString(2, QChar::Nbsp) + QLatin1String("one") + QChar(QChar::LineSeparator) + QString(6, QChar::Nbsp) + bullet + QString(2, QChar::Nbsp) + QLatin1String("two") + QChar(QChar::LineSeparator) << FormatList() << false; - QTest::newRow("header close") << "<h1>head</h1>more" << QChar(QChar::LineSeparator) + QLatin1String("head") + QChar(QChar::LineSeparator) + QLatin1String("more") << (FormatList() << Format(Format::Bold, 0, 5)) << true; + QTest::newRow("ordered list") << "<ol><li>one<li>two" << QString(6, QChar::Nbsp) + QLatin1String("1.") + QString(2, QChar::Nbsp) + QLatin1String("one") + QChar(QChar::LineSeparator) + QString(6, QChar::Nbsp) + QLatin1String("2.") + QString(2, QChar::Nbsp) + QLatin1String("two") << FormatList() << false; + QTest::newRow("ordered list closed") << "<ol><li>one</li><li>two</li></ol>" << QString(6, QChar::Nbsp) + QLatin1String("1.") + QString(2, QChar::Nbsp) + QLatin1String("one") + QChar(QChar::LineSeparator) + QString(6, QChar::Nbsp) + QLatin1String("2.") + QString(2, QChar::Nbsp) + QLatin1String("two") + QChar(QChar::LineSeparator) << FormatList() << false; + QTest::newRow("ordered list alpha") << "<ol type=\"a\"><li>one</li><li>two</li></ol>" << QString(6, QChar::Nbsp) + QLatin1String("a.") + QString(2, QChar::Nbsp) + QLatin1String("one") + QChar(QChar::LineSeparator) + QString(6, QChar::Nbsp) + QLatin1String("b.") + QString(2, QChar::Nbsp) + QLatin1String("two") + QChar(QChar::LineSeparator) << FormatList() << false; + QTest::newRow("ordered list upper alpha") << "<ol type=\"A\"><li>one</li><li>two</li></ol>" << QString(6, QChar::Nbsp) + QLatin1String("A.") + QString(2, QChar::Nbsp) + QLatin1String("one") + QChar(QChar::LineSeparator) + QString(6, QChar::Nbsp) + QLatin1String("B.") + QString(2, QChar::Nbsp) + QLatin1String("two") + QChar(QChar::LineSeparator) << FormatList() << false; + QTest::newRow("ordered list roman") << "<ol type=\"i\"><li>one</li><li>two</li></ol>" << QString(6, QChar::Nbsp) + QLatin1String("i.") + QString(2, QChar::Nbsp) + QLatin1String("one") + QChar(QChar::LineSeparator) + QString(6, QChar::Nbsp) + QLatin1String("ii.") + QString(2, QChar::Nbsp) + QLatin1String("two") + QChar(QChar::LineSeparator) << FormatList() << false; + QTest::newRow("ordered list upper roman") << "<ol type=\"I\"><li>one</li><li>two</li></ol>" << QString(6, QChar::Nbsp) + QLatin1String("I.") + QString(2, QChar::Nbsp) + QLatin1String("one") + QChar(QChar::LineSeparator) + QString(6, QChar::Nbsp) + QLatin1String("II.") + QString(2, QChar::Nbsp) + QLatin1String("two") + QChar(QChar::LineSeparator) << FormatList() << false; + QTest::newRow("ordered list bad") << "<ol type=\"z\"><li>one</li><li>two</li></ol>" << QString(6, QChar::Nbsp) + QLatin1String("1.") + QString(2, QChar::Nbsp) + QLatin1String("one") + QChar(QChar::LineSeparator) + QString(6, QChar::Nbsp) + QLatin1String("2.") + QString(2, QChar::Nbsp) + QLatin1String("two") + QChar(QChar::LineSeparator) << FormatList() << false; + QTest::newRow("unordered list") << "<ul><li>one<li>two" << QString(6, QChar::Nbsp) + bullet + QString(2, QChar::Nbsp) + QLatin1String("one") + QChar(QChar::LineSeparator) + QString(6, QChar::Nbsp) + bullet + QString(2, QChar::Nbsp) + QLatin1String("two") << FormatList() << false; + QTest::newRow("unordered list closed") << "<ul><li>one</li><li>two</li></ul>" << QString(6, QChar::Nbsp) + bullet + QString(2, QChar::Nbsp) + QLatin1String("one") + QChar(QChar::LineSeparator) + QString(6, QChar::Nbsp) + bullet + QString(2, QChar::Nbsp) + QLatin1String("two") + QChar(QChar::LineSeparator) << FormatList() << false; + QTest::newRow("unordered list disc") << "<ul type=\"disc\"><li>one</li><li>two</li></ul>" << QString(6, QChar::Nbsp) + disc + QString(2, QChar::Nbsp) + QLatin1String("one") + QChar(QChar::LineSeparator) + QString(6, QChar::Nbsp) + disc + QString(2, QChar::Nbsp) + QLatin1String("two") + QChar(QChar::LineSeparator) << FormatList() << false; + QTest::newRow("unordered list square") << "<ul type=\"square\"><li>one</li><li>two</li></ul>" << QString(6, QChar::Nbsp) + square + QString(2, QChar::Nbsp) + QLatin1String("one") + QChar(QChar::LineSeparator) + QString(6, QChar::Nbsp) + square + QString(2, QChar::Nbsp) + QLatin1String("two") + QChar(QChar::LineSeparator) << FormatList() << false; + QTest::newRow("unordered list bad") << "<ul type=\"bad\"><li>one</li><li>two</li></ul>" << QString(6, QChar::Nbsp) + bullet + QString(2, QChar::Nbsp) + QLatin1String("one") + QChar(QChar::LineSeparator) + QString(6, QChar::Nbsp) + bullet + QString(2, QChar::Nbsp) + QLatin1String("two") + QChar(QChar::LineSeparator) << FormatList() << false; + QTest::newRow("header close") << "<h1>head</h1>more" << QLatin1String("head") + QChar(QChar::LineSeparator) + QLatin1String("more") << (FormatList() << Format(Format::Bold, 0, 4)) << true; QTest::newRow("h0") << "<h0>head" << "head" << FormatList() << false; - QTest::newRow("h1") << "<h1>head" << QChar(QChar::LineSeparator) + QLatin1String("head") << (FormatList() << Format(Format::Bold, 0, 5)) << true; - QTest::newRow("h2") << "<h2>head" << QChar(QChar::LineSeparator) + QLatin1String("head") << (FormatList() << Format(Format::Bold, 0, 5)) << true; - QTest::newRow("h3") << "<h3>head" << QChar(QChar::LineSeparator) + QLatin1String("head") << (FormatList() << Format(Format::Bold, 0, 5)) << true; - QTest::newRow("h4") << "<h4>head" << QChar(QChar::LineSeparator) + QLatin1String("head") << (FormatList() << Format(Format::Bold, 0, 5)) << true; - QTest::newRow("h5") << "<h5>head" << QChar(QChar::LineSeparator) + QLatin1String("head") << (FormatList() << Format(Format::Bold, 0, 5)) << true; - QTest::newRow("h6") << "<h6>head" << QChar(QChar::LineSeparator) + QLatin1String("head") << (FormatList() << Format(Format::Bold, 0, 5)) << true; + QTest::newRow("h1") << "<h1>head" << "head" << (FormatList() << Format(Format::Bold, 0, 4)) << true; + QTest::newRow("h2") << "<h2>head" << "head" << (FormatList() << Format(Format::Bold, 0, 4)) << true; + QTest::newRow("h3") << "<h3>head" << "head" << (FormatList() << Format(Format::Bold, 0, 4)) << true; + QTest::newRow("h4") << "<h4>head" << "head" << (FormatList() << Format(Format::Bold, 0, 4)) << true; + QTest::newRow("h5") << "<h5>head" << "head" << (FormatList() << Format(Format::Bold, 0, 4)) << true; + QTest::newRow("h6") << "<h6>head" << "head" << (FormatList() << Format(Format::Bold, 0, 4)) << true; QTest::newRow("h7") << "<h7>head" << "head" << FormatList() << false; QTest::newRow("pre") << "normal<pre>pre text</pre>normal" << QLatin1String("normal") + QChar(QChar::LineSeparator) + QLatin1String("pre") + QChar(QChar::Nbsp) + QLatin1String("text") + QChar(QChar::LineSeparator) + QLatin1String("normal") << (FormatList() << Format(0, 6, 9)) << false; QTest::newRow("pre lb") << "normal<pre>pre\n text</pre>normal" << QLatin1String("normal") + QChar(QChar::LineSeparator) + QLatin1String("pre") + QChar(QChar::LineSeparator) + QChar(QChar::Nbsp) + QLatin1String("text") + QChar(QChar::LineSeparator) + QLatin1String("normal") << (FormatList() << Format(0, 6, 10)) << false; @@ -155,7 +155,7 @@ void tst_qquickstyledtext::textOutput_data() QTest::newRow("consecutive whitespace") << " consecutive \t \n whitespace" << "consecutive whitespace" << FormatList() << false; QTest::newRow("space after newline") << "text<br/> more text" << QLatin1String("text") + QChar(QChar::LineSeparator) + QLatin1String("more text") << FormatList() << false; QTest::newRow("space after paragraph") << "text<p> more text</p> more text" << QLatin1String("text") + QChar(QChar::LineSeparator) + QLatin1String("more text") + QChar(QChar::LineSeparator) + QLatin1String("more text") << FormatList() << false; - QTest::newRow("space in header") << "<h1> head</h1> " << QChar(QChar::LineSeparator) + QLatin1String("head") + QChar(QChar::LineSeparator) << (FormatList() << Format(Format::Bold, 0, 5)) << true; + QTest::newRow("space in header") << "<h1> head</h1> " << QLatin1String("head") + QChar(QChar::LineSeparator) << (FormatList() << Format(Format::Bold, 0, 4)) << true; QTest::newRow("space before bold") << "this is <b>bold</b>" << "this is bold" << (FormatList() << Format(Format::Bold, 8, 4)) << false; QTest::newRow("space leading bold") << "this is<b> bold</b>" << "this is bold" << (FormatList() << Format(Format::Bold, 7, 5)) << false; QTest::newRow("space trailing bold") << "this is <b>bold </b>" << "this is bold " << (FormatList() << Format(Format::Bold, 8, 5)) << false; diff --git a/tests/auto/quick/qquicktextedit/tst_qquicktextedit.cpp b/tests/auto/quick/qquicktextedit/tst_qquicktextedit.cpp index 3bf872569f..88b9c2d792 100644 --- a/tests/auto/quick/qquicktextedit/tst_qquicktextedit.cpp +++ b/tests/auto/quick/qquicktextedit/tst_qquicktextedit.cpp @@ -1296,7 +1296,7 @@ void tst_qquicktextedit::selectionOnFocusOut() QVERIFY(edit2->hasActiveFocus()); edit2->setFocus(false, Qt::PopupFocusReason); - QVERIFY(!edit2->hasActiveFocus()); + QVERIFY(edit2->hasActiveFocus()); QCOMPARE(edit2->selectedText(), QLatin1String("text 2")); } diff --git a/tests/auto/quick/qquicktextinput/qquicktextinput.pro b/tests/auto/quick/qquicktextinput/qquicktextinput.pro index c14b09c545..521f41df43 100644 --- a/tests/auto/quick/qquicktextinput/qquicktextinput.pro +++ b/tests/auto/quick/qquicktextinput/qquicktextinput.pro @@ -14,3 +14,5 @@ TESTDATA = data/* QT += core-private gui-private qml-private quick-private testlib DEFINES += QT_DISABLE_DEPRECATED_BEFORE=0 + +macx: CONFIG+=insignificant_test # QTBUG-38363 diff --git a/tests/auto/quick/qquicktextinput/tst_qquicktextinput.cpp b/tests/auto/quick/qquicktextinput/tst_qquicktextinput.cpp index 05cf0b9a5b..684229aa07 100644 --- a/tests/auto/quick/qquicktextinput/tst_qquicktextinput.cpp +++ b/tests/auto/quick/qquicktextinput/tst_qquicktextinput.cpp @@ -3606,7 +3606,8 @@ void tst_qquicktextinput::focusOutNotClearSelection() input.setFocus(false, Qt::PopupFocusReason); QGuiApplication::processEvents(); QTRY_COMPARE(input.selectedText(), QLatin1String("llo")); - QTRY_COMPARE(input.hasActiveFocus(), false); + // QTBUG-36332 and 36292: a popup window does not take focus + QTRY_COMPARE(input.hasActiveFocus(), true); input.setFocus(true); QTRY_COMPARE(input.hasActiveFocus(), true); diff --git a/tests/auto/quick/qquicktimeline/tst_qquicktimeline.cpp b/tests/auto/quick/qquicktimeline/tst_qquicktimeline.cpp index e9fbb5448c..9b62eb311c 100644 --- a/tests/auto/quick/qquicktimeline/tst_qquicktimeline.cpp +++ b/tests/auto/quick/qquicktimeline/tst_qquicktimeline.cpp @@ -53,6 +53,12 @@ private slots: void tst_QQuickTimeLine::overflow() { + // Test ensures that time value used in QQuickTimeLine::accel methods is always positive. + // On platforms where casting qreal value infinity to int yields a positive value this is + // always the case and the test would fail. Strictly speaking, the cast is undefined behavior. + if (static_cast<int>(qInf()) > 0) + QSKIP("Test is not applicable on this platform"); + QQuickTimeLine timeline; QQuickTimeLineValue value; diff --git a/tests/auto/quick/qquickwindow/data/active.qml b/tests/auto/quick/qquickwindow/data/active.qml index af0b7edeb2..4d47225b4e 100644 --- a/tests/auto/quick/qquickwindow/data/active.qml +++ b/tests/auto/quick/qquickwindow/data/active.qml @@ -14,7 +14,6 @@ Window { anchors.fill: parent; onPressed: window2.requestActivate(); } - Component.onCompleted: window2.show(); } Window { @@ -22,6 +21,7 @@ Window { objectName: "window2"; color: "#FF0000"; width: 100; height: 100; + visible: true Item { width: 100; height: 100; } diff --git a/tests/auto/quick/qquickwindow/data/windoworder.qml b/tests/auto/quick/qquickwindow/data/windoworder.qml new file mode 100644 index 0000000000..33aea95694 --- /dev/null +++ b/tests/auto/quick/qquickwindow/data/windoworder.qml @@ -0,0 +1,42 @@ +import QtQuick 2.1 +import QtQuick.Window 2.1 + +Window { + id: window1; + objectName: "window1"; + width: 100; height: 100; + visible: true + color: "blue" + property alias win2: window2 + property alias win3: window3 + property alias win4: window4 + property alias win5: window5 + Window { + id: window2; + objectName: "window2"; + width: 100; height: 100; + visible: true + color: "green" + Window { + id: window3; + objectName: "window3"; + width: 100; height: 100; + visible: true + } + + Window { //Is invisible by default + id: window4 + objectName: "window4"; + height: 200 + width: 200 + color: "black" + Window { + id: window5 + objectName: "window5"; + height: 200 + width: 200 + visible: true + } + } + } +} diff --git a/tests/auto/quick/qquickwindow/qquickwindow.pro b/tests/auto/quick/qquickwindow/qquickwindow.pro index 2d1d62c135..e95b7dbb10 100644 --- a/tests/auto/quick/qquickwindow/qquickwindow.pro +++ b/tests/auto/quick/qquickwindow/qquickwindow.pro @@ -15,6 +15,7 @@ OTHER_FILES += \ data/active.qml \ data/AnimationsWhileHidden.qml \ data/Headless.qml \ - data/showHideAnimate.qml + data/showHideAnimate.qml \ + data/windoworder.qml DEFINES += QT_DISABLE_DEPRECATED_BEFORE=0 diff --git a/tests/auto/quick/qquickwindow/tst_qquickwindow.cpp b/tests/auto/quick/qquickwindow/tst_qquickwindow.cpp index de4067b6e5..a2e2980223 100644 --- a/tests/auto/quick/qquickwindow/tst_qquickwindow.cpp +++ b/tests/auto/quick/qquickwindow/tst_qquickwindow.cpp @@ -343,6 +343,8 @@ private slots: void requestActivate(); + void testWindowVisibilityOrder(); + void blockClosing(); void crashWhenHoverItemDeleted(); @@ -1132,6 +1134,43 @@ void tst_qquickwindow::animationsWhileHidden() QTRY_VERIFY(window->isVisible()); } +// When running on native Nvidia graphics cards on linux, the +// distance field glyph pixels have a measurable, but not visible +// pixel error. Use a custom compare function to avoid +// +// This was GT-216 with the ubuntu "nvidia-319" driver package. +// llvmpipe does not show the same issue. +// +bool compareImages(const QImage &ia, const QImage &ib) +{ + if (ia.size() != ib.size()) + qDebug() << "images are of different size" << ia.size() << ib.size(); + Q_ASSERT(ia.size() == ib.size()); + Q_ASSERT(ia.format() == ib.format()); + + int w = ia.width(); + int h = ia.height(); + const int tolerance = 5; + for (int y=0; y<h; ++y) { + const uint *as= (const uint *) ia.constScanLine(y); + const uint *bs= (const uint *) ib.constScanLine(y); + for (int x=0; x<w; ++x) { + uint a = as[x]; + uint b = bs[x]; + + // No tolerance for error in the alpha. + if ((a & 0xff000000) != (b & 0xff000000)) + return false; + if (qAbs(qRed(a) - qRed(b)) > tolerance) + return false; + if (qAbs(qRed(a) - qRed(b)) > tolerance) + return false; + if (qAbs(qRed(a) - qRed(b)) > tolerance) + return false; + } + } + return true; +} void tst_qquickwindow::headless() { @@ -1179,8 +1218,7 @@ void tst_qquickwindow::headless() // Verify that the visual output is the same QImage newContent = window->grabWindow(); - - QCOMPARE(originalContent, newContent); + QVERIFY(compareImages(newContent, originalContent)); } void tst_qquickwindow::noUpdateWhenNothingChanges() @@ -1600,7 +1638,8 @@ void tst_qquickwindow::requestActivate() QVERIFY(windows.at(0)->objectName() == "window2"); window1->show(); - window1->requestActivate(); + QVERIFY(QTest::qWaitForWindowExposed(windows.at(0))); //We wait till window 2 comes up + window1->requestActivate(); // and then transfer the focus to window1 QTRY_VERIFY(QGuiApplication::focusWindow() == window1); QVERIFY(window1->isActive() == true); @@ -1626,6 +1665,54 @@ void tst_qquickwindow::requestActivate() QTRY_VERIFY(QGuiApplication::focusWindow() == windows.at(0)); QVERIFY(windows.at(0)->isActive()); + delete window1; +} + +void tst_qquickwindow::testWindowVisibilityOrder() +{ + QQmlEngine engine; + QQmlComponent component(&engine); + component.loadUrl(testFileUrl("windoworder.qml")); + QQuickWindow *window1 = qobject_cast<QQuickWindow *>(component.create()); + QQuickWindow *window2 = window1->property("win2").value<QQuickWindow*>(); + QQuickWindow *window3 = window1->property("win3").value<QQuickWindow*>(); + QQuickWindow *window4 = window1->property("win4").value<QQuickWindow*>(); + QQuickWindow *window5 = window1->property("win5").value<QQuickWindow*>(); + QVERIFY(window1); + QVERIFY(window2); + QVERIFY(window3); + + QTest::qWaitForWindowExposed(window3); + + QWindowList windows = QGuiApplication::topLevelWindows(); + QTRY_COMPARE(windows.size(), 5); + + QVERIFY(window3 == QGuiApplication::focusWindow()); + QVERIFY(window1->isActive()); + QVERIFY(window2->isActive()); + QVERIFY(window3->isActive()); + + //Test if window4 is shown 2 seconds after the application startup + //with window4 visible window5 (transient child) should also become visible + QVERIFY(!window4->isVisible()); + QVERIFY(!window5->isVisible()); + + window4->setVisible(true); + + QTest::qWaitForWindowExposed(window5); + QVERIFY(window4->isVisible()); + QVERIFY(window5->isVisible()); + window4->hide(); + window5->hide(); + + window3->hide(); +#if defined(Q_OS_OSX) + QEXPECT_FAIL("","Focus is not transferred to transient parent on window close (QTBUG-33423)", Continue); +#endif + QTRY_COMPARE(window2 == QGuiApplication::focusWindow(), true); + + window2->hide(); + QTRY_COMPARE(window1 == QGuiApplication::focusWindow(), true); } void tst_qquickwindow::blockClosing() diff --git a/tests/auto/quick/qquickxmllistmodel/data/proxyCrash.qml b/tests/auto/quick/qquickxmllistmodel/data/proxyCrash.qml new file mode 100644 index 0000000000..c0c5a25e3c --- /dev/null +++ b/tests/auto/quick/qquickxmllistmodel/data/proxyCrash.qml @@ -0,0 +1,9 @@ +import QtQuick 2.0 +import QtQuick.XmlListModel 2.0 +import SortFilterProxyModel 1.0 + +SortFilterProxyModel { + source: XmlListModel { + XmlRole { } + } +} diff --git a/tests/auto/quick/qquickxmllistmodel/tst_qquickxmllistmodel.cpp b/tests/auto/quick/qquickxmllistmodel/tst_qquickxmllistmodel.cpp index a3cfa0011a..1d5518047f 100644 --- a/tests/auto/quick/qquickxmllistmodel/tst_qquickxmllistmodel.cpp +++ b/tests/auto/quick/qquickxmllistmodel/tst_qquickxmllistmodel.cpp @@ -51,6 +51,7 @@ #include <QtCore/qtimer.h> #include <QtCore/qfile.h> #include <QtCore/qtemporaryfile.h> +#include <QtCore/qsortfilterproxymodel.h> #include "../../shared/util.h" #include <private/qqmlengine_p.h> @@ -106,6 +107,7 @@ private slots: void selectAncestor(); void roleCrash(); + void proxyCrash(); private: QString errorString(QAbstractItemModel *model) { @@ -988,6 +990,28 @@ void tst_qquickxmllistmodel::roleCrash() delete model; } +class SortFilterProxyModel : public QSortFilterProxyModel +{ + Q_OBJECT + Q_PROPERTY(QObject *source READ source WRITE setSource) + +public: + SortFilterProxyModel(QObject *parent = 0) : QSortFilterProxyModel(parent) { sort(0); } + QObject *source() const { return sourceModel(); } + void setSource(QObject *source) { setSourceModel(qobject_cast<QAbstractItemModel *>(source)); } +}; + +void tst_qquickxmllistmodel::proxyCrash() +{ + qmlRegisterType<SortFilterProxyModel>("SortFilterProxyModel", 1, 0, "SortFilterProxyModel"); + + // don't crash + QQmlComponent component(&engine, testFileUrl("proxyCrash.qml")); + QAbstractItemModel *model = qobject_cast<QAbstractItemModel *>(component.create()); + QVERIFY(model != 0); + delete model; +} + QTEST_MAIN(tst_qquickxmllistmodel) #include "tst_qquickxmllistmodel.moc" diff --git a/tests/auto/quick/scenegraph/data/render_bug37422.qml b/tests/auto/quick/scenegraph/data/render_bug37422.qml new file mode 100644 index 0000000000..38e2b64da7 --- /dev/null +++ b/tests/auto/quick/scenegraph/data/render_bug37422.qml @@ -0,0 +1,103 @@ +/**************************************************************************** +** +** Copyright (C) 2014 Jolla Ltd, author: <gunnar.sletta@jollamobile.com> +** Contact: http://www.qt-project.org/legal +** +** This file is part of the test suite of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** 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 Digia. For licensing terms and +** conditions see http://qt.digia.com/licensing. For further information +** use the contact form at http://qt.digia.com/contact-us. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 2.1 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 2.1 requirements +** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** In addition, as a special exception, Digia gives you certain additional +** rights. These rights are described in the Digia Qt LGPL Exception +** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 3.0 as published by the Free Software +** Foundation and appearing in the file LICENSE.GPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU General Public License version 3.0 requirements will be +** met: http://www.gnu.org/copyleft/gpl.html. +** +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +import QtQuick 2.2 + +/* + The test verifies that batching does not interfere with overlapping + regions. + + #samples: 8 + PixelPos R G B Error-tolerance + #base: 0 0 1.0 0.0 0.0 0.05 + #base: 1 1 0.0 0.0 1.0 0.05 + #base: 10 10 1.0 0.0 0.0 0.05 + #base: 1 11 0.0 0.0 1.0 0.05 + + #final: 0 0 1.0 0.0 0.0 0.05 + #final: 1 1 0.0 1.0 0.0 0.05 + #final: 10 10 1.0 0.0 0.0 0.05 + #final: 1 11 0.0 1.0 0.0 0.05 + +*/ + +RenderTestBase +{ + id: root + + opacity: 0.99 + + Rectangle { + width: 100 + height: 9 + color: Qt.rgba(1, 0, 0); + + Rectangle { + id: box + width: 5 + height: 5 + x: 1 + y: 1 + color: Qt.rgba(0, 0, 1); + } + } + + ShaderEffect { // Something which blends and is different than rectangle. Will get its own batch + width: 100 + height: 9 + y: 10 + fragmentShader: "varying highp vec2 qt_TexCoord0; void main() { gl_FragColor = vec4(1, 0, 0, 1); }" + + Rectangle { + width: 5 + height: 5 + x: 1 + y: 1 + color: box.color + } + } + + onEnterFinalStage: { + box.color = Qt.rgba(0, 1, 0); + root.finalStageComplete = true; + } + +} diff --git a/tests/auto/quick/scenegraph/tst_scenegraph.cpp b/tests/auto/quick/scenegraph/tst_scenegraph.cpp index 5d393fedb5..ac4938e8bc 100644 --- a/tests/auto/quick/scenegraph/tst_scenegraph.cpp +++ b/tests/auto/quick/scenegraph/tst_scenegraph.cpp @@ -119,7 +119,7 @@ bool compareImages(const QImage &ia, const QImage &ib) int w = ia.width(); int h = ia.height(); - const int tolerance = 1; + const int tolerance = 5; for (int y=0; y<h; ++y) { const uint *as= (const uint *) ia.constScanLine(y); const uint *bs= (const uint *) ib.constScanLine(y); @@ -328,6 +328,7 @@ void tst_SceneGraph::render_data() << "data/render_StackingOrder.qml" << "data/render_Mipmap.qml" << "data/render_ImageFiltering.qml" + << "data/render_bug37555.qml" ; QRegExp sampleCount("#samples: *(\\d+)"); diff --git a/tests/manual/highdpi/fillmodes.qml b/tests/manual/highdpi/fillmodes.qml new file mode 100644 index 0000000000..cff2bcc34c --- /dev/null +++ b/tests/manual/highdpi/fillmodes.qml @@ -0,0 +1,72 @@ +/**************************************************************************** +** +** Copyright (C) 2014 Digia Plc and/or its subsidiary(-ies). +** Contact: http://www.qt-project.org/legal +** +** This file is part of the QtQml module of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** 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 Digia. For licensing terms and +** conditions see http://qt.digia.com/licensing. For further information +** use the contact form at http://qt.digia.com/contact-us. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 2.1 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 2.1 requirements +** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** In addition, as a special exception, Digia gives you certain additional +** rights. These rights are described in the Digia Qt LGPL Exception +** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 3.0 as published by the Free Software +** Foundation and appearing in the file LICENSE.GPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU General Public License version 3.0 requirements will be +** met: http://www.gnu.org/copyleft/gpl.html. +** +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +import QtQuick 2.0 + +Rectangle { + width: 400 + height: 700 + + // the images should have the same display size and appearance on each row. + Column { + anchors.centerIn: parent.Center + Row { + Image { width: 130; height: 70; fillMode: Image.Stretch; source : "heart-lowdpi.png" } + Image { width: 130; height: 70; fillMode: Image.Stretch; source : "heart.png" } + Image { width: 130; height: 70; fillMode: Image.Stretch; source : "heart-highdpi@2x.png" } + } + Row { + Image { width: 130; height: 100; fillMode: Image.PreserveAspectFit; source : "heart-lowdpi.png" } + Image { width: 130; height: 100; fillMode: Image.PreserveAspectFit; source : "heart.png" } + Image { width: 130; height: 100; fillMode: Image.PreserveAspectFit; source : "heart-highdpi@2x.png" } + } + Row { + Image { width: 130; height: 100; fillMode: Image.PreserveAspectCrop; source : "heart-lowdpi.png" } + Image { width: 130; height: 100; fillMode: Image.PreserveAspectCrop; source : "heart.png" } + Image { width: 130; height: 100; fillMode: Image.PreserveAspectCrop; source : "heart-highdpi@2x.png" } + } + Row { + Image { width: 230; height: 200; fillMode: Image.Tile; source : "heart-lowdpi.png" } + Image { width: 230; height: 200; fillMode: Image.Tile; source : "heart.png" } + Image { width: 230; height: 200; fillMode: Image.Tile; source : "heart-highdpi@2x.png" } + } + } +} diff --git a/tests/manual/highdpi/heart-highdpi@2x.png b/tests/manual/highdpi/heart-highdpi@2x.png Binary files differnew file mode 100644 index 0000000000..a7a1ca89a4 --- /dev/null +++ b/tests/manual/highdpi/heart-highdpi@2x.png diff --git a/tests/manual/highdpi/heart-lowdpi.png b/tests/manual/highdpi/heart-lowdpi.png Binary files differnew file mode 100644 index 0000000000..deaec18274 --- /dev/null +++ b/tests/manual/highdpi/heart-lowdpi.png diff --git a/tests/manual/highdpi/heart.png b/tests/manual/highdpi/heart.png Binary files differnew file mode 100644 index 0000000000..deaec18274 --- /dev/null +++ b/tests/manual/highdpi/heart.png diff --git a/tests/manual/highdpi/heart@2x.png b/tests/manual/highdpi/heart@2x.png Binary files differnew file mode 100644 index 0000000000..a7a1ca89a4 --- /dev/null +++ b/tests/manual/highdpi/heart@2x.png diff --git a/tests/manual/highdpi/image.qml b/tests/manual/highdpi/image.qml new file mode 100644 index 0000000000..8deab5c734 --- /dev/null +++ b/tests/manual/highdpi/image.qml @@ -0,0 +1,52 @@ +/**************************************************************************** +** +** Copyright (C) 2014 Digia Plc and/or its subsidiary(-ies). +** Contact: http://www.qt-project.org/legal +** +** This file is part of the QtQml module of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** 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 Digia. For licensing terms and +** conditions see http://qt.digia.com/licensing. For further information +** use the contact form at http://qt.digia.com/contact-us. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 2.1 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 2.1 requirements +** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** In addition, as a special exception, Digia gives you certain additional +** rights. These rights are described in the Digia Qt LGPL Exception +** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 3.0 as published by the Free Software +** Foundation and appearing in the file LICENSE.GPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU General Public License version 3.0 requirements will be +** met: http://www.gnu.org/copyleft/gpl.html. +** +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +import QtQuick 2.0 + +Rectangle { + width: 400 + height: 400 + + Image { + source : "heart.png" + anchors.centerIn: parent + } +} diff --git a/tests/manual/highdpi/image2.qml b/tests/manual/highdpi/image2.qml new file mode 100644 index 0000000000..b83c8006d8 --- /dev/null +++ b/tests/manual/highdpi/image2.qml @@ -0,0 +1,64 @@ +/**************************************************************************** +** +** Copyright (C) 2014 Digia Plc and/or its subsidiary(-ies). +** Contact: http://www.qt-project.org/legal +** +** This file is part of the QtQml module of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** 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 Digia. For licensing terms and +** conditions see http://qt.digia.com/licensing. For further information +** use the contact form at http://qt.digia.com/contact-us. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 2.1 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 2.1 requirements +** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** In addition, as a special exception, Digia gives you certain additional +** rights. These rights are described in the Digia Qt LGPL Exception +** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 3.0 as published by the Free Software +** Foundation and appearing in the file LICENSE.GPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU General Public License version 3.0 requirements will be +** met: http://www.gnu.org/copyleft/gpl.html. +** +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +import QtQuick 2.0 + +Rectangle { + width: 400 + height: 400 + + // These images should all have the same visual size: + Row { + anchors.centerIn: parent + // 1X only + Image { + source : "heart-lowdpi.png" + } + // 1X and 2x, switches on screen change. + Image { + source : "heart.png" + } + // 2x only + Image { + source : "heart-highdpi@2x.png" + } + } +} diff --git a/tests/manual/highdpi/imagesize.qml b/tests/manual/highdpi/imagesize.qml new file mode 100644 index 0000000000..ee6719a6ee --- /dev/null +++ b/tests/manual/highdpi/imagesize.qml @@ -0,0 +1,76 @@ +/**************************************************************************** +** +** Copyright (C) 2014 Digia Plc and/or its subsidiary(-ies). +** Contact: http://www.qt-project.org/legal +** +** This file is part of the QtQml module of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** 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 Digia. For licensing terms and +** conditions see http://qt.digia.com/licensing. For further information +** use the contact form at http://qt.digia.com/contact-us. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 2.1 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 2.1 requirements +** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** In addition, as a special exception, Digia gives you certain additional +** rights. These rights are described in the Digia Qt LGPL Exception +** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 3.0 as published by the Free Software +** Foundation and appearing in the file LICENSE.GPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU General Public License version 3.0 requirements will be +** met: http://www.gnu.org/copyleft/gpl.html. +** +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +import QtQuick 2.0 + +Rectangle { + width: 400 + height: 400 + + Column { + anchors.centerIn: parent.Center + Row { + Image { width: 50; height: 50; fillMode: Image.Stretch; source : "heart-lowdpi.png" } + Image { width: 50; height: 50; fillMode: Image.Stretch; source : "heart.png" } + Image { width: 50; height: 50; fillMode: Image.Stretch; source : "heart-highdpi@2x.png" } + } + Row { + Image { width: 100; height: 100; fillMode: Image.Stretch; source : "heart-lowdpi.png" } + Image { width: 100; height: 100; fillMode: Image.Stretch; source : "heart.png" } + Image { width: 100; height: 100; fillMode: Image.Stretch; source : "heart-highdpi@2x.png" } + } + Row { + Image { width: 150; height: 150; fillMode: Image.Stretch; source : "heart-lowdpi.png" } + Image { width: 150; height: 150; fillMode: Image.Stretch; source : "heart.png" } + Image { width: 150; height: 150; fillMode: Image.Stretch; source : "heart-highdpi@2x.png" } + } + Row { + Image { width: 200; height: 200; fillMode: Image.Stretch; source : "heart-lowdpi.png" } + Image { width: 200; height: 200; fillMode: Image.Stretch; source : "heart.png" } + Image { width: 200; height: 200; fillMode: Image.Stretch; source : "heart-highdpi@2x.png" } + } + Row { + Image { width: 300; height: 300; fillMode: Image.Stretch; source : "heart-lowdpi.png" } + Image { width: 300; height: 300; fillMode: Image.Stretch; source : "heart.png" } + Image { width: 300; height: 300; fillMode: Image.Stretch; source : "heart-highdpi@2x.png" } + } + } +} diff --git a/tests/manual/highdpi/mirror.qml b/tests/manual/highdpi/mirror.qml new file mode 100644 index 0000000000..3a92a9abd4 --- /dev/null +++ b/tests/manual/highdpi/mirror.qml @@ -0,0 +1,57 @@ +/**************************************************************************** +** +** Copyright (C) 2014 Digia Plc and/or its subsidiary(-ies). +** Contact: http://www.qt-project.org/legal +** +** This file is part of the QtQml module of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** 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 Digia. For licensing terms and +** conditions see http://qt.digia.com/licensing. For further information +** use the contact form at http://qt.digia.com/contact-us. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 2.1 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 2.1 requirements +** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** In addition, as a special exception, Digia gives you certain additional +** rights. These rights are described in the Digia Qt LGPL Exception +** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 3.0 as published by the Free Software +** Foundation and appearing in the file LICENSE.GPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU General Public License version 3.0 requirements will be +** met: http://www.gnu.org/copyleft/gpl.html. +** +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +import QtQuick 2.0 + +Rectangle { + width: 400 + height: 700 + + // the images should have the same display size and appearance on each row. + Column { + anchors.centerIn: parent.Center + Row { + Image { mirror: true; source : "heart-lowdpi.png" } + Image { mirror: true; source : "heart.png" } + Image { mirror: true; source : "heart-highdpi@2x.png" } + } + } +} diff --git a/tests/manual/highdpi/sourcesize.qml b/tests/manual/highdpi/sourcesize.qml new file mode 100644 index 0000000000..64bf8ad86b --- /dev/null +++ b/tests/manual/highdpi/sourcesize.qml @@ -0,0 +1,76 @@ +/**************************************************************************** +** +** Copyright (C) 2014 Digia Plc and/or its subsidiary(-ies). +** Contact: http://www.qt-project.org/legal +** +** This file is part of the QtQml module of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** 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 Digia. For licensing terms and +** conditions see http://qt.digia.com/licensing. For further information +** use the contact form at http://qt.digia.com/contact-us. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 2.1 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 2.1 requirements +** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** In addition, as a special exception, Digia gives you certain additional +** rights. These rights are described in the Digia Qt LGPL Exception +** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 3.0 as published by the Free Software +** Foundation and appearing in the file LICENSE.GPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU General Public License version 3.0 requirements will be +** met: http://www.gnu.org/copyleft/gpl.html. +** +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +import QtQuick 2.0 + +Rectangle { + width: 400 + height: 400 + + // SourceSize is in device-independent pixels. These images + // should display at the same visual size. + Column { + anchors.centerIn: parent.Center + Row { + + // standard image with no @2x version + Image { + sourceSize.width: 75 + sourceSize.height: 75 + source : "heart-lowdpi.png" + } + + // image with "@2x" version on disk + Image { + sourceSize.width: 75 + sourceSize.height: 75 + source : "heart.png" + } + + // direct use of "@2x" image + Image { + sourceSize.width: 75 + sourceSize.height: 75 + source : "heart-highdpi@2x.png" + } + } + } +} diff --git a/tests/testapplications/text/text.qml b/tests/testapplications/text/text.qml index 56ca825d0a..b1e600a633 100644 --- a/tests/testapplications/text/text.qml +++ b/tests/testapplications/text/text.qml @@ -1,6 +1,6 @@ /**************************************************************************** ** -** Copyright (C) 2013 Digia Plc and/or its subsidiary(-ies). +** Copyright (C) 2014 Digia Plc and/or its subsidiary(-ies). ** Contact: http://www.qt-project.org/legal ** ** This file is part of the test suite of the Qt Toolkit. @@ -130,7 +130,7 @@ Rectangle { "value": "Qt Quick is a collection of technologies that are designed to help developers create the kind of intuitive, "+ "modern, fluid user interfaces that are increasingly used on mobile phones, media players, set-top boxes and other "+ "portable devices.\n"+ - "Qt Quick consists of a rich set of user interface elements, a declarative language for describing user interfaces "+ + "Qt Quick consists of a rich set of user interface elements, a language for describing user interfaces "+ "and a language runtime. "+ "A collection of C++ APIs is used to integrate these high level features with classic Qt applications."}); textmodel.append({ "name": "Short", @@ -143,7 +143,7 @@ Rectangle { "value": "<b>Qt Quick</b> is a collection of technologies that are designed to help developers create the kind of <i>intuitive, "+ "modern, fluid</i> user interfaces that are increasingly used on mobile phones, media players, set-top boxes and other "+ "portable devices.<br>"+ - "Qt Quick consists of a rich set of user interface elements, a declarative language for describing user interfaces "+ + "Qt Quick consists of a rich set of user interface elements, a language for describing user interfaces "+ "and a language runtime. "+ "A collection of C++ APIs is used to integrate these high level features with classic Qt applications."}); } diff --git a/tests/testapplications/text/textedit.qml b/tests/testapplications/text/textedit.qml index 6546abfe91..3baa307d8d 100644 --- a/tests/testapplications/text/textedit.qml +++ b/tests/testapplications/text/textedit.qml @@ -1,6 +1,6 @@ /**************************************************************************** ** -** Copyright (C) 2013 Digia Plc and/or its subsidiary(-ies). +** Copyright (C) 2014 Digia Plc and/or its subsidiary(-ies). ** Contact: http://www.qt-project.org/legal ** ** This file is part of the test suite of the Qt Toolkit. @@ -127,7 +127,7 @@ Rectangle { "value": "Qt Quick is a collection of technologies that are designed to help developers create the kind of intuitive, "+ "modern, fluid user interfaces that are increasingly used on mobile phones, media players, set-top boxes and other "+ "portable devices."+texteditelement.newline+ - "Qt Quick consists of a rich set of user interface elements, a declarative language for describing user interfaces "+ + "Qt Quick consists of a rich set of user interface elements, a language for describing user interfaces "+ "and a language runtime.\n"+ "A collection of C++ APIs is used to integrate these high level features with classic Qt applications."}); textmodel.append({ "name": "Short", @@ -140,7 +140,7 @@ Rectangle { "value": "<b>Qt Quick</b> is a collection of technologies that are designed to help developers create the kind of <i>intuitive, "+ "modern, fluid</i> user interfaces that are increasingly used on mobile phones, media players, set-top boxes and other "+ "portable devices.<br>"+ - "Qt Quick consists of a rich set of user interface elements, a declarative language for describing user interfaces "+ + "Qt Quick consists of a rich set of user interface elements, a language for describing user interfaces "+ "and a language runtime. "+ "A collection of C++ APIs is used to integrate these high level features with classic Qt applications."}); textmodel.append({ "name": "Links", diff --git a/tests/testapplications/text/textinput.qml b/tests/testapplications/text/textinput.qml index 556771bcb5..d15d02232a 100644 --- a/tests/testapplications/text/textinput.qml +++ b/tests/testapplications/text/textinput.qml @@ -1,6 +1,6 @@ /**************************************************************************** ** -** Copyright (C) 2013 Digia Plc and/or its subsidiary(-ies). +** Copyright (C) 2014 Digia Plc and/or its subsidiary(-ies). ** Contact: http://www.qt-project.org/legal ** ** This file is part of the test suite of the Qt Toolkit. @@ -175,7 +175,7 @@ Rectangle { "value": "Qt Quick is a collection of technologies that are designed to help developers create the kind of intuitive, "+ "modern, fluid user interfaces that are increasingly used on mobile phones, media players, set-top boxes and other "+ "portable devices. "+ - "Qt Quick consists of a rich set of user interface elements, a declarative language for describing user interfaces "+ + "Qt Quick consists of a rich set of user interface elements, a language for describing user interfaces "+ "and a language runtime. "+ "A collection of C++ APIs is used to integrate these high level features with classic Qt applications."}); } |