aboutsummaryrefslogtreecommitdiffstats
path: root/tests
diff options
context:
space:
mode:
Diffstat (limited to 'tests')
-rw-r--r--tests/auto/auto.pro2
-rw-r--r--tests/auto/qml/debugger/qqmldebugjs/tst_qqmldebugjs.cpp36
-rw-r--r--tests/auto/qml/debugger/qqmlprofilerservice/tst_qqmlprofilerservice.cpp74
-rw-r--r--tests/auto/qml/debugger/shared/qqmlenginedebugclient.cpp6
-rw-r--r--tests/auto/qml/debugger/shared/qqmlenginedebugclient.h2
-rw-r--r--tests/auto/qml/qjsengine/idtranslatable-unicode.js5
-rw-r--r--tests/auto/qml/qjsengine/idtranslatable.js5
-rw-r--r--tests/auto/qml/qjsengine/qjsengine.pro1
-rw-r--r--tests/auto/qml/qjsengine/qjsengine.qrc8
-rw-r--r--tests/auto/qml/qjsengine/translatable-unicode.js9
-rw-r--r--tests/auto/qml/qjsengine/translatable.js12
-rw-r--r--tests/auto/qml/qjsengine/translatable2.js9
-rw-r--r--tests/auto/qml/qjsengine/translations/idtranslatable-unicode.qmbin0 -> 209 bytes
-rw-r--r--tests/auto/qml/qjsengine/translations/idtranslatable-unicode.ts26
-rw-r--r--tests/auto/qml/qjsengine/translations/idtranslatable_la.qmbin0 -> 342 bytes
-rw-r--r--tests/auto/qml/qjsengine/translations/idtranslatable_la.ts30
-rw-r--r--tests/auto/qml/qjsengine/translations/translatable-unicode.qmbin0 -> 322 bytes
-rw-r--r--tests/auto/qml/qjsengine/translations/translatable-unicode.ts37
-rw-r--r--tests/auto/qml/qjsengine/translations/translatable_la.qmbin0 -> 975 bytes
-rw-r--r--tests/auto/qml/qjsengine/translations/translatable_la.ts88
-rw-r--r--tests/auto/qml/qjsengine/tst_qjsengine.cpp486
-rw-r--r--tests/auto/qml/qqmlapplicationengine/tst_qqmlapplicationengine.cpp3
-rw-r--r--tests/auto/qml/qqmlchangeset/tst_qqmlchangeset.cpp36
-rw-r--r--tests/auto/qml/qqmlcomponent/tst_qqmlcomponent.cpp8
-rw-r--r--tests/auto/qml/qqmlcontext/tst_qqmlcontext.cpp2
-rw-r--r--tests/auto/qml/qqmlecmascript/data/assignSequenceTypes.1.qml2
-rw-r--r--tests/auto/qml/qqmlecmascript/data/assignSequenceTypes.3.qml2
-rw-r--r--tests/auto/qml/qqmlecmascript/data/assignSequenceTypes.4.qml2
-rw-r--r--tests/auto/qml/qqmlecmascript/data/assignSequenceTypes.6.qml2
-rw-r--r--tests/auto/qml/qqmlecmascript/data/extendedObjectPropertyLookup3.qml13
-rw-r--r--tests/auto/qml/qqmlecmascript/data/uncreatableExtendedObjectFailureCheck.qml8
-rw-r--r--tests/auto/qml/qqmlecmascript/testtypes.cpp41
-rw-r--r--tests/auto/qml/qqmlecmascript/testtypes.h2
-rw-r--r--tests/auto/qml/qqmlecmascript/tst_qqmlecmascript.cpp81
-rw-r--r--tests/auto/qml/qqmlengine/tst_qqmlengine.cpp2
-rw-r--r--tests/auto/qml/qqmllanguage/data/customExtendedParserProperties.qml12
-rw-r--r--tests/auto/qml/qqmllanguage/testtypes.cpp83
-rw-r--r--tests/auto/qml/qqmllanguage/testtypes.h39
-rw-r--r--tests/auto/qml/qqmllanguage/tst_qqmllanguage.cpp37
-rw-r--r--tests/auto/qml/qqmllistmodel/tst_qqmllistmodel.cpp4
-rw-r--r--tests/auto/qml/qqmlmoduleplugin/tst_qqmlmoduleplugin.cpp8
-rw-r--r--tests/auto/qml/qqmlproperty/tst_qqmlproperty.cpp1
-rw-r--r--tests/auto/qml/qqmlpropertymap/tst_qqmlpropertymap.cpp2
-rw-r--r--tests/auto/qml/qqmlxmlhttprequest/tst_qqmlxmlhttprequest.cpp83
-rw-r--r--tests/auto/qml/qv4debugger/tst_qv4debugger.cpp28
-rw-r--r--tests/auto/qml/v4misc/tst_v4misc.cpp2
-rw-r--r--tests/auto/qmltest/item/tst_layerInPositioner.qml207
-rw-r--r--tests/auto/qmltest/itemgrabber/tst_itemgrabber.qml160
-rw-r--r--tests/auto/qmltest/selftests/tst_findChild.qml112
-rw-r--r--tests/auto/qmltest/shadersource/tst_DynamicallyCreated.qml84
-rw-r--r--tests/auto/qmltest/shadersource/tst_SourceInOtherWindow.qml81
-rw-r--r--tests/auto/qmltest/shadersource/tst_SourcedFromOtherWindow.qml81
-rw-r--r--tests/auto/qmltest/statemachine/tst_anonymousstate.qml52
-rw-r--r--tests/auto/qmltest/statemachine/tst_historystate.qml102
-rw-r--r--tests/auto/qmltest/statemachine/tst_initialstate.qml65
-rw-r--r--tests/auto/qmltest/statemachine/tst_nestedinitialstates.qml74
-rw-r--r--tests/auto/qmltest/statemachine/tst_parallelmachine.qml90
-rw-r--r--tests/auto/qmltest/statemachine/tst_trafficlight.qml157
-rw-r--r--tests/auto/quick/nodes/tst_nodestest.cpp30
-rw-r--r--tests/auto/quick/qquickaccessible/tst_qquickaccessible.cpp2
-rw-r--r--tests/auto/quick/qquickanchors/tst_qquickanchors.cpp22
-rw-r--r--tests/auto/quick/qquickanimatedimage/tst_qquickanimatedimage.cpp20
-rw-r--r--tests/auto/quick/qquickapplication/tst_qquickapplication.cpp19
-rw-r--r--tests/auto/quick/qquickborderimage/tst_qquickborderimage.cpp39
-rw-r--r--tests/auto/quick/qquickcanvasitem/data/tst_canvas.qml343
-rw-r--r--tests/auto/quick/qquickdrag/tst_qquickdrag.cpp27
-rw-r--r--tests/auto/quick/qquickdroparea/tst_qquickdroparea.cpp114
-rw-r--r--tests/auto/quick/qquickflickable/data/nestedClickThenFlick.qml39
-rw-r--r--tests/auto/quick/qquickflickable/tst_qquickflickable.cpp66
-rw-r--r--tests/auto/quick/qquickfontloader/tst_qquickfontloader.cpp9
-rw-r--r--tests/auto/quick/qquickfontmetrics/qquickfontmetrics.pro10
-rw-r--r--tests/auto/quick/qquickfontmetrics/tst_quickfontmetrics.cpp150
-rw-r--r--tests/auto/quick/qquickframebufferobject/tst_qquickframebufferobject.cpp4
-rw-r--r--tests/auto/quick/qquickimage/tst_qquickimage.cpp61
-rw-r--r--tests/auto/quick/qquickimageprovider/tst_qquickimageprovider.cpp6
-rw-r--r--tests/auto/quick/qquickitem/qquickitem.pro1
-rw-r--r--tests/auto/quick/qquickitem/tst_qquickitem.cpp38
-rw-r--r--tests/auto/quick/qquickitem2/data/grabToImage.qml60
-rw-r--r--tests/auto/quick/qquickitem2/tst_qquickitem.cpp115
-rw-r--r--tests/auto/quick/qquickitemlayer/tst_qquickitemlayer.cpp40
-rw-r--r--tests/auto/quick/qquicklistview/data/sizeTransitions.qml101
-rw-r--r--tests/auto/quick/qquicklistview/data/stickyPositioning-both.qml77
-rw-r--r--tests/auto/quick/qquicklistview/data/stickyPositioning-footer.qml70
-rw-r--r--tests/auto/quick/qquicklistview/data/stickyPositioning-header.qml70
-rw-r--r--tests/auto/quick/qquicklistview/tst_qquicklistview.cpp462
-rw-r--r--tests/auto/quick/qquickloader/tst_qquickloader.cpp16
-rw-r--r--tests/auto/quick/qquickmousearea/data/containsPress.qml20
-rw-r--r--tests/auto/quick/qquickmousearea/tst_qquickmousearea.cpp110
-rw-r--r--tests/auto/quick/qquickmultipointtoucharea/qquickmultipointtoucharea.pro1
-rw-r--r--tests/auto/quick/qquickmultipointtoucharea/tst_qquickmultipointtoucharea.cpp91
-rw-r--r--tests/auto/quick/qquickopenglinfo/data/basic.qml8
-rw-r--r--tests/auto/quick/qquickopenglinfo/qquickopenglinfo.pro15
-rw-r--r--tests/auto/quick/qquickopenglinfo/tst_qquickopenglinfo.cpp85
-rw-r--r--tests/auto/quick/qquickpincharea/qquickpincharea.pro1
-rw-r--r--tests/auto/quick/qquickpincharea/tst_qquickpincharea.cpp25
-rw-r--r--tests/auto/quick/qquickpixmapcache/tst_qquickpixmapcache.cpp10
-rw-r--r--tests/auto/quick/qquickpositioners/tst_qquickpositioners.cpp16
-rw-r--r--tests/auto/quick/qquickrepeater/data/invalidContextCrash.qml7
-rw-r--r--tests/auto/quick/qquickrepeater/tst_qquickrepeater.cpp43
-rw-r--r--tests/auto/quick/qquickspritesequence/tst_qquickspritesequence.cpp3
-rw-r--r--tests/auto/quick/qquicktext/tst_qquicktext.cpp17
-rw-r--r--tests/auto/quick/qquicktextedit/tst_qquicktextedit.cpp9
-rw-r--r--tests/auto/quick/qquicktextinput/tst_qquicktextinput.cpp72
-rw-r--r--tests/auto/quick/qquicktextmetrics/qquicktextmetrics.pro10
-rw-r--r--tests/auto/quick/qquicktextmetrics/tst_qquicktextmetrics.cpp161
-rw-r--r--tests/auto/quick/qquickwindow/data/windowattached.qml25
-rw-r--r--tests/auto/quick/qquickwindow/qquickwindow.pro1
-rw-r--r--tests/auto/quick/qquickwindow/tst_qquickwindow.cpp207
-rw-r--r--tests/auto/quick/quick.pro2
-rw-r--r--tests/auto/quick/rendernode/data/matrix.qml87
-rw-r--r--tests/auto/quick/rendernode/rendernode.pro2
-rw-r--r--tests/auto/quick/rendernode/tst_rendernode.cpp98
-rw-r--r--tests/auto/quick/scenegraph/data/render_DrawSets.qml33
-rw-r--r--tests/auto/quick/scenegraph/tst_scenegraph.cpp52
-rw-r--r--tests/auto/quick/shared/viewtestutil.cpp23
-rw-r--r--tests/auto/quick/shared/viewtestutil.h4
-rw-r--r--tests/auto/quick/touchmouse/touchmouse.pro1
-rw-r--r--tests/auto/quick/touchmouse/tst_touchmouse.cpp124
-rw-r--r--tests/auto/quickwidgets/qquickwidget/data/animating.qml11
-rw-r--r--tests/auto/quickwidgets/qquickwidget/data/error1.qml5
-rw-r--r--tests/auto/quickwidgets/qquickwidget/data/rectangle.qml8
-rw-r--r--tests/auto/quickwidgets/qquickwidget/data/resizemodeitem.qml7
-rw-r--r--tests/auto/quickwidgets/qquickwidget/qquickwidget.pro19
-rw-r--r--tests/auto/quickwidgets/qquickwidget/tst_qquickwidget.cpp276
-rw-r--r--tests/auto/quickwidgets/quickwidgets.pro2
-rw-r--r--tests/auto/shared/testhttpserver.cpp15
-rw-r--r--tests/auto/shared/testhttpserver.h5
-rw-r--r--tests/manual/httpserver/main.cpp6
-rw-r--r--tests/manual/v4/Sha1.js146
-rw-r--r--tests/testapplications/listview/sticky.qml250
130 files changed, 6269 insertions, 459 deletions
diff --git a/tests/auto/auto.pro b/tests/auto/auto.pro
index 715f3e01ad..d37e4a57ed 100644
--- a/tests/auto/auto.pro
+++ b/tests/auto/auto.pro
@@ -9,6 +9,8 @@ SUBDIRS=\
cmake \
installed_cmake
+qtHaveModule(widgets): SUBDIRS += quickwidgets
+
qmldevtools.CONFIG = host_build
installed_cmake.depends = cmake
diff --git a/tests/auto/qml/debugger/qqmldebugjs/tst_qqmldebugjs.cpp b/tests/auto/qml/debugger/qqmldebugjs/tst_qqmldebugjs.cpp
index fef020704f..8763c4fa55 100644
--- a/tests/auto/qml/debugger/qqmldebugjs/tst_qqmldebugjs.cpp
+++ b/tests/auto/qml/debugger/qqmldebugjs/tst_qqmldebugjs.cpp
@@ -187,7 +187,7 @@ private slots:
void setBreakpointInScriptOnComment();
void setBreakpointInScriptOnEmptyLine();
void setBreakpointInScriptOnOptimizedBinding();
-// void setBreakpointInScriptWithCondition(); // Not supported yet.
+ void setBreakpointInScriptWithCondition();
void setBreakpointInScriptThatQuits();
//void setBreakpointInFunction(); //NOT SUPPORTED
// void setBreakpointOnEvent();
@@ -1082,13 +1082,8 @@ void tst_QQmlDebugJS::setBreakpointInScriptOnOptimizedBinding()
QCOMPARE(QFileInfo(body.value("script").toMap().value("name").toString()).fileName(), QLatin1String(BREAKPOINTRELOCATION_QMLFILE));
}
-#if 0
void tst_QQmlDebugJS::setBreakpointInScriptWithCondition()
{
- QFAIL("conditional breakpoints are not yet supported");
-
- //void setBreakpoint(QString type, QString target, int line = -1, int column = -1, bool enabled = false, QString condition = QString(), int ignoreCount = -1)
-
int out = 10;
int sourceLine = 50;
QVERIFY(init(CONDITION_QMLFILE));
@@ -1102,23 +1097,26 @@ void tst_QQmlDebugJS::setBreakpointInScriptWithCondition()
QString jsonString = client->response;
QVariantMap value = client->parser.call(QJSValueList() << QJSValue(jsonString)).toVariant().toMap();
- QVariantMap body = value.value("body").toMap();
-
- int frameIndex = body.value("index").toInt();
-
- //Verify the value of 'result'
- client->evaluate(QLatin1String("a"),frameIndex);
+ {
+ QVariantMap body = value.value("body").toMap();
+ int frameIndex = body.value("index").toInt();
- QVERIFY(QQmlDebugTest::waitForSignal(client, SIGNAL(result())));
+ //Verify the value of 'result'
+ client->evaluate(QLatin1String("a"),frameIndex);
+ QVERIFY(QQmlDebugTest::waitForSignal(client, SIGNAL(result())));
+ }
jsonString = client->response;
- value = client->parser.call(QJSValueList() << QJSValue(jsonString)).toVariant().toMap();
-
- body = value.value("body").toMap();
-
- QVERIFY(body.value("value").toInt() > out);
+ QJSValue val = client->parser.call(QJSValueList() << QJSValue(jsonString));
+ QVERIFY(val.isObject());
+ QJSValue body = val.property(QStringLiteral("body"));
+ QVERIFY(body.isObject());
+ val = body.property("value");
+ QVERIFY(val.isNumber());
+
+ const int a = val.toInt();
+ QVERIFY(a > out);
}
-#endif
void tst_QQmlDebugJS::setBreakpointInScriptThatQuits()
{
diff --git a/tests/auto/qml/debugger/qqmlprofilerservice/tst_qqmlprofilerservice.cpp b/tests/auto/qml/debugger/qqmlprofilerservice/tst_qqmlprofilerservice.cpp
index b544427c08..935b9d4120 100644
--- a/tests/auto/qml/debugger/qqmlprofilerservice/tst_qqmlprofilerservice.cpp
+++ b/tests/auto/qml/debugger/qqmlprofilerservice/tst_qqmlprofilerservice.cpp
@@ -61,6 +61,7 @@ struct QQmlProfilerData
int column; //used by RangeLocation
int framerate; //used by animation events
int animationcount; //used by animation events
+ qint64 amount; //used by heap events
QByteArray toByteArray() const;
};
@@ -79,6 +80,7 @@ public:
Complete, // end of transmission
PixmapCacheEvent,
SceneGraphFrame,
+ MemoryAllocation,
MaximumMessage
};
@@ -131,6 +133,12 @@ public:
MaximumSceneGraphFrameType
};
+ enum MemoryType {
+ HeapPage,
+ LargeItem,
+ SmallItem
+ };
+
QQmlProfilerClient(QQmlDebugConnection *connection)
: QQmlDebugClient(QLatin1String("CanvasFrameRate"), connection)
{
@@ -138,6 +146,7 @@ public:
QList<QQmlProfilerData> qmlMessages;
QList<QQmlProfilerData> javascriptMessages;
+ QList<QQmlProfilerData> jsHeapMessages;
QList<QQmlProfilerData> asynchronousMessages;
QList<QQmlProfilerData> pixmapMessages;
@@ -175,6 +184,7 @@ private:
void connect(bool block, const QString &testFile);
void checkTraceReceived();
+ void checkJsHeap();
private slots:
void cleanup();
@@ -303,6 +313,11 @@ void QQmlProfilerClient::messageReceived(const QByteArray &message)
}
break;
}
+ case QQmlProfilerClient::MemoryAllocation: {
+ stream >> data.detailType;
+ stream >> data.amount;
+ break;
+ }
default:
QString failMsg = QString("Unknown message type:") + data.messageType;
QFAIL(qPrintable(failMsg));
@@ -314,6 +329,8 @@ void QQmlProfilerClient::messageReceived(const QByteArray &message)
else if (data.messageType == QQmlProfilerClient::SceneGraphFrame ||
data.messageType == QQmlProfilerClient::Event)
asynchronousMessages.append(data);
+ else if (data.messageType == QQmlProfilerClient::MemoryAllocation)
+ jsHeapMessages.append(data);
else if (data.detailType == QQmlProfilerClient::Javascript)
javascriptMessages.append(data);
else
@@ -357,6 +374,48 @@ void tst_QQmlProfilerService::checkTraceReceived()
QCOMPARE(m_client->asynchronousMessages.last().detailType, (int)QQmlProfilerClient::EndTrace);
}
+void tst_QQmlProfilerService::checkJsHeap()
+{
+ QVERIFY2(m_client->jsHeapMessages.count() > 0, "no JavaScript heap messages received");
+
+ bool seen_alloc = false;
+ bool seen_small = false;
+ bool seen_large = false;
+ qint64 allocated = 0;
+ qint64 used = 0;
+ foreach (const QQmlProfilerData &message, m_client->jsHeapMessages) {
+ switch (message.detailType) {
+ case QQmlProfilerClient::HeapPage:
+ allocated += message.amount;
+ seen_alloc = true;
+ break;
+ case QQmlProfilerClient::SmallItem:
+ used += message.amount;
+ seen_small = true;
+ break;
+ case QQmlProfilerClient::LargeItem:
+ allocated += message.amount;
+ used += message.amount;
+ seen_large = true;
+ break;
+ }
+
+ QVERIFY2(used >= 0, QString::fromLatin1("Negative memory usage seen: %1")
+ .arg(used).toUtf8().constData());
+
+ QVERIFY2(allocated >= 0, QString::fromLatin1("Negative memory allocation seen: %1")
+ .arg(allocated).toUtf8().constData());
+
+ QVERIFY2(used <= allocated,
+ QString::fromLatin1("More memory usage than allocation seen: %1 > %2")
+ .arg(used).arg(allocated).toUtf8().constData());
+ }
+
+ QVERIFY2(seen_alloc, "No heap allocation seen");
+ QVERIFY2(seen_small, "No small item seen");
+ QVERIFY2(seen_large, "No large item seen");
+}
+
void tst_QQmlProfilerService::cleanup()
{
if (QTest::currentTestFailed()) {
@@ -388,6 +447,12 @@ void tst_QQmlProfilerService::cleanup()
<< data.line << data.column;
}
qDebug() << " ";
+ qDebug() << "Javascript Heap Messages:" << m_client->jsHeapMessages.count();
+ i = 0;
+ foreach (const QQmlProfilerData &data, m_client->jsHeapMessages) {
+ qDebug() << i++ << data.time << data.messageType << data.detailType;
+ }
+ qDebug() << " ";
qDebug() << "Process State:" << (m_process ? m_process->state() : QLatin1String("null"));
qDebug() << "Application Output:" << (m_process ? m_process->output() : QLatin1String("null"));
qDebug() << "Connection State:" << (m_connection ? m_connection->stateString() : QLatin1String("null"));
@@ -410,6 +475,7 @@ void tst_QQmlProfilerService::blockingConnectWithTraceEnabled()
m_client->setTraceState(true);
m_client->setTraceState(false);
checkTraceReceived();
+ checkJsHeap();
}
void tst_QQmlProfilerService::blockingConnectWithTraceDisabled()
@@ -422,6 +488,7 @@ void tst_QQmlProfilerService::blockingConnectWithTraceDisabled()
m_client->setTraceState(true);
m_client->setTraceState(false);
checkTraceReceived();
+ checkJsHeap();
}
void tst_QQmlProfilerService::nonBlockingConnect()
@@ -433,6 +500,7 @@ void tst_QQmlProfilerService::nonBlockingConnect()
m_client->setTraceState(true);
m_client->setTraceState(false);
checkTraceReceived();
+ checkJsHeap();
}
void tst_QQmlProfilerService::pixmapCacheData()
@@ -451,6 +519,7 @@ void tst_QQmlProfilerService::pixmapCacheData()
m_client->setTraceState(false);
checkTraceReceived();
+ checkJsHeap();
QVERIFY2(m_client->pixmapMessages.count() >= 4,
QString::number(m_client->pixmapMessages.count()).toUtf8().constData());
@@ -487,6 +556,7 @@ void tst_QQmlProfilerService::scenegraphData()
m_client->setTraceState(false);
checkTraceReceived();
+ checkJsHeap();
// check that at least one frame was rendered
// there should be a SGPolishAndSync + SGRendererFrame + SGRenderLoopFrame sequence
@@ -516,6 +586,7 @@ void tst_QQmlProfilerService::profileOnExit()
m_client->setTraceState(true);
checkTraceReceived();
+ checkJsHeap();
}
void tst_QQmlProfilerService::controlFromJS()
@@ -526,6 +597,7 @@ void tst_QQmlProfilerService::controlFromJS()
m_client->setTraceState(false);
checkTraceReceived();
+ checkJsHeap();
}
void tst_QQmlProfilerService::signalSourceLocation()
@@ -539,6 +611,7 @@ void tst_QQmlProfilerService::signalSourceLocation()
QVERIFY(QQmlDebugTest::waitForSignal(m_process, SIGNAL(readyReadStandardOutput())));
m_client->setTraceState(false);
checkTraceReceived();
+ checkJsHeap();
QVERIFY2(m_client->qmlMessages.count() >= 16,
QString::number(m_client->qmlMessages.count()).toUtf8().constData());
@@ -569,6 +642,7 @@ void tst_QQmlProfilerService::javascript()
QVERIFY(QQmlDebugTest::waitForSignal(m_process, SIGNAL(readyReadStandardOutput())));
m_client->setTraceState(false);
checkTraceReceived();
+ checkJsHeap();
QVERIFY2(m_client->javascriptMessages.count() >= 22,
QString::number(m_client->javascriptMessages.count()).toUtf8().constData());
diff --git a/tests/auto/qml/debugger/shared/qqmlenginedebugclient.cpp b/tests/auto/qml/debugger/shared/qqmlenginedebugclient.cpp
index 610d80d559..022ba8c440 100644
--- a/tests/auto/qml/debugger/shared/qqmlenginedebugclient.cpp
+++ b/tests/auto/qml/debugger/shared/qqmlenginedebugclient.cpp
@@ -84,7 +84,8 @@ QQmlEngineDebugClient::QQmlEngineDebugClient(
QQmlDebugConnection *connection)
: QQmlDebugClient(QLatin1String("QmlDebugger"), connection),
m_nextId(0),
- m_valid(false)
+ m_valid(false),
+ m_connection(connection)
{
}
@@ -467,6 +468,9 @@ void QQmlEngineDebugClient::messageReceived(const QByteArray &data)
{
m_valid = false;
QDataStream ds(data);
+ ds.setVersion(m_connection->dataStreamVersion());
+
+
int queryId;
QByteArray type;
ds >> type >> queryId;
diff --git a/tests/auto/qml/debugger/shared/qqmlenginedebugclient.h b/tests/auto/qml/debugger/shared/qqmlenginedebugclient.h
index 1d4b95a9e3..2712692389 100644
--- a/tests/auto/qml/debugger/shared/qqmlenginedebugclient.h
+++ b/tests/auto/qml/debugger/shared/qqmlenginedebugclient.h
@@ -242,6 +242,8 @@ private:
QmlDebugObjectReference m_object;
QList<QmlDebugObjectReference> m_objects;
QVariant m_exprResult;
+
+ QQmlDebugConnection *m_connection;
};
#endif // QQMLENGINEDEBUGCLIENT_H
diff --git a/tests/auto/qml/qjsengine/idtranslatable-unicode.js b/tests/auto/qml/qjsengine/idtranslatable-unicode.js
new file mode 100644
index 0000000000..e17d6172bc
--- /dev/null
+++ b/tests/auto/qml/qjsengine/idtranslatable-unicode.js
@@ -0,0 +1,5 @@
+qsTrId('\u01F8\u01D2\u0199\u01D0\u01E1');
+
+QT_TRID_NOOP("\u0191\u01CE\u0211\u0229\u019C\u018E\u019A\u01D0");
+
+qsTrId("\u0181\u01A1\u0213\u018F\u018C", 10);
diff --git a/tests/auto/qml/qjsengine/idtranslatable.js b/tests/auto/qml/qjsengine/idtranslatable.js
new file mode 100644
index 0000000000..554ca88d41
--- /dev/null
+++ b/tests/auto/qml/qjsengine/idtranslatable.js
@@ -0,0 +1,5 @@
+qsTrId("qtn_foo_bar");
+
+var more_greeting_strings = [ QT_TRID_NOOP("qtn_needle"), QT_TRID_NOOP("qtn_haystack") ];
+
+qsTrId("qtn_bar_baz", 10);
diff --git a/tests/auto/qml/qjsengine/qjsengine.pro b/tests/auto/qml/qjsengine/qjsengine.pro
index a62eb75c21..fc2452c2bc 100644
--- a/tests/auto/qml/qjsengine/qjsengine.pro
+++ b/tests/auto/qml/qjsengine/qjsengine.pro
@@ -4,6 +4,7 @@ TARGET = tst_qjsengine
QT += qml qml-private widgets testlib gui-private
macx:CONFIG -= app_bundle
SOURCES += tst_qjsengine.cpp
+RESOURCES += qjsengine.qrc
TESTDATA = script/*
DEFINES += QT_DISABLE_DEPRECATED_BEFORE=0
diff --git a/tests/auto/qml/qjsengine/qjsengine.qrc b/tests/auto/qml/qjsengine/qjsengine.qrc
new file mode 100644
index 0000000000..d05d115966
--- /dev/null
+++ b/tests/auto/qml/qjsengine/qjsengine.qrc
@@ -0,0 +1,8 @@
+<!DOCTYPE RCC><RCC version="1.0">
+<qresource>
+ <file>translations/translatable_la.qm</file>
+ <file>translations/idtranslatable_la.qm</file>
+ <file>translations/translatable-unicode.qm</file>
+ <file>translations/idtranslatable-unicode.qm</file>
+</qresource>
+</RCC>
diff --git a/tests/auto/qml/qjsengine/translatable-unicode.js b/tests/auto/qml/qjsengine/translatable-unicode.js
new file mode 100644
index 0000000000..afe2aff21c
--- /dev/null
+++ b/tests/auto/qml/qjsengine/translatable-unicode.js
@@ -0,0 +1,9 @@
+qsTr("H\u2082O");
+qsTranslate("\u010C\u0101\u011F\u0115", "CO\u2082");
+
+var unicode_strings = [
+ QT_TR_NOOP("\u0391\u0392\u0393"),
+ QT_TRANSLATE_NOOP("\u010C\u0101\u011F\u0115", "\u0414\u0415\u0416")
+];
+
+qsTr("H\u2082O", "not the same H\u2082O");
diff --git a/tests/auto/qml/qjsengine/translatable.js b/tests/auto/qml/qjsengine/translatable.js
new file mode 100644
index 0000000000..5d6ad9b3b6
--- /dev/null
+++ b/tests/auto/qml/qjsengine/translatable.js
@@ -0,0 +1,12 @@
+qsTr("One");
+qsTranslate("FooContext", "Two");
+
+var greeting_strings = [
+ QT_TR_NOOP("Hello"),
+ QT_TRANSLATE_NOOP("FooContext", "Goodbye")
+];
+
+qsTr("One", "not the same one");
+
+qsTr("%n message(s) saved", "", 10);
+qsTranslate("FooContext", "%n fooish bar(s) found", "", 10);
diff --git a/tests/auto/qml/qjsengine/translatable2.js b/tests/auto/qml/qjsengine/translatable2.js
new file mode 100644
index 0000000000..eee66f17c1
--- /dev/null
+++ b/tests/auto/qml/qjsengine/translatable2.js
@@ -0,0 +1,9 @@
+qsTr("Three");
+qsTranslate("BarContext", "Four");
+
+var celebration_strings = [
+ QT_TR_NOOP("Happy birthday!"),
+ QT_TRANSLATE_NOOP("BarContext", "Congratulations!")
+];
+
+qsTr("Three", "not the same three");
diff --git a/tests/auto/qml/qjsengine/translations/idtranslatable-unicode.qm b/tests/auto/qml/qjsengine/translations/idtranslatable-unicode.qm
new file mode 100644
index 0000000000..8c5fb91b1d
--- /dev/null
+++ b/tests/auto/qml/qjsengine/translations/idtranslatable-unicode.qm
Binary files differ
diff --git a/tests/auto/qml/qjsengine/translations/idtranslatable-unicode.ts b/tests/auto/qml/qjsengine/translations/idtranslatable-unicode.ts
new file mode 100644
index 0000000000..74ebf43c47
--- /dev/null
+++ b/tests/auto/qml/qjsengine/translations/idtranslatable-unicode.ts
@@ -0,0 +1,26 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!DOCTYPE TS>
+<TS version="2.0" language="nb_NO">
+<defaultcodec>UTF-8</defaultcodec>
+<context>
+ <name></name>
+ <message id="Ǹǒƙǐǡ">
+ <location filename="idtranslatable-unicode.js" line="1"/>
+ <source></source>
+ <translation>Ƨưƈȼȝȿș</translation>
+ </message>
+ <message id="ƑǎȑȩƜƎƚǐ">
+ <location filename="idtranslatable-unicode.js" line="3"/>
+ <source></source>
+ <translation>Ǡȡȋȅȕ</translation>
+ </message>
+ <message id="ƁơȓƏƌ" numerus="yes">
+ <location filename="idtranslatable-unicode.js" line="5"/>
+ <source></source>
+ <translation>
+ <numerusform>Ƒưǹ</numerusform>
+ <numerusform>%n ƒơǒ(ș)</numerusform>
+ </translation>
+ </message>
+</context>
+</TS>
diff --git a/tests/auto/qml/qjsengine/translations/idtranslatable_la.qm b/tests/auto/qml/qjsengine/translations/idtranslatable_la.qm
new file mode 100644
index 0000000000..c8c0b72acb
--- /dev/null
+++ b/tests/auto/qml/qjsengine/translations/idtranslatable_la.qm
Binary files differ
diff --git a/tests/auto/qml/qjsengine/translations/idtranslatable_la.ts b/tests/auto/qml/qjsengine/translations/idtranslatable_la.ts
new file mode 100644
index 0000000000..b6d7053024
--- /dev/null
+++ b/tests/auto/qml/qjsengine/translations/idtranslatable_la.ts
@@ -0,0 +1,30 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!DOCTYPE TS>
+<TS version="2.0" language="nb_NO">
+<context>
+ <name></name>
+ <message id="qtn_foo_bar">
+ <location filename="idtranslatable.js" line="1"/>
+ <source></source>
+ <translation>First string</translation>
+ </message>
+ <message id="qtn_needle">
+ <location filename="idtranslatable.js" line="3"/>
+ <source></source>
+ <translation>Second string</translation>
+ </message>
+ <message id="qtn_haystack">
+ <location filename="idtranslatable.js" line="3"/>
+ <source></source>
+ <translation>Third string</translation>
+ </message>
+ <message id="qtn_bar_baz" numerus="yes">
+ <location filename="idtranslatable.js" line="5"/>
+ <source></source>
+ <translation>
+ <numerusform>Fourth string</numerusform>
+ <numerusform>%n fooish bar(s) found</numerusform>
+ </translation>
+ </message>
+</context>
+</TS>
diff --git a/tests/auto/qml/qjsengine/translations/translatable-unicode.qm b/tests/auto/qml/qjsengine/translations/translatable-unicode.qm
new file mode 100644
index 0000000000..aa75ce61df
--- /dev/null
+++ b/tests/auto/qml/qjsengine/translations/translatable-unicode.qm
Binary files differ
diff --git a/tests/auto/qml/qjsengine/translations/translatable-unicode.ts b/tests/auto/qml/qjsengine/translations/translatable-unicode.ts
new file mode 100644
index 0000000000..1b8b4d2309
--- /dev/null
+++ b/tests/auto/qml/qjsengine/translations/translatable-unicode.ts
@@ -0,0 +1,37 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!DOCTYPE TS>
+<TS version="2.0">
+<defaultcodec>UTF-8</defaultcodec>
+<context>
+ <name>translatable-unicode</name>
+ <message>
+ <location filename="translatable-unicode.js" line="1"/>
+ <source>H₂O</source>
+ <translation>ͻͼͽ</translation>
+ </message>
+ <message>
+ <location filename="translatable-unicode.js" line="5"/>
+ <source>ΑΒΓ</source>
+ <translation>ӜҴѼ</translation>
+ </message>
+ <message>
+ <location filename="translatable-unicode.js" line="9"/>
+ <source>H₂O</source>
+ <comment>not the same H₂O</comment>
+ <translation>ԶՊՒ</translation>
+ </message>
+</context>
+<context>
+ <name>Čāğĕ</name>
+ <message>
+ <location filename="translatable-unicode.js" line="2"/>
+ <source>CO₂</source>
+ <translation>בךע</translation>
+ </message>
+ <message>
+ <location filename="translatable-unicode.js" line="6"/>
+ <source>ДЕЖ</source>
+ <translation>خسس</translation>
+ </message>
+</context>
+</TS>
diff --git a/tests/auto/qml/qjsengine/translations/translatable_la.qm b/tests/auto/qml/qjsengine/translations/translatable_la.qm
new file mode 100644
index 0000000000..d76b1cad5f
--- /dev/null
+++ b/tests/auto/qml/qjsengine/translations/translatable_la.qm
Binary files differ
diff --git a/tests/auto/qml/qjsengine/translations/translatable_la.ts b/tests/auto/qml/qjsengine/translations/translatable_la.ts
new file mode 100644
index 0000000000..36271c9cbe
--- /dev/null
+++ b/tests/auto/qml/qjsengine/translations/translatable_la.ts
@@ -0,0 +1,88 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!DOCTYPE TS>
+<TS version="2.0" language="nb_NO">
+<context>
+ <name>BarContext</name>
+ <message>
+ <location filename="translatable2.js" line="2"/>
+ <source>Four</source>
+ <translation>Fire</translation>
+ </message>
+ <message>
+ <location filename="translatable2.js" line="6"/>
+ <source>Congratulations!</source>
+ <translation>Gratulerer!</translation>
+ </message>
+</context>
+<context>
+ <name>FooContext</name>
+ <message>
+ <location filename="translatable.js" line="2"/>
+ <source>Two</source>
+ <translation>To</translation>
+ </message>
+ <message>
+ <location filename="translatable.js" line="6"/>
+ <source>Goodbye</source>
+ <translation>Farvel</translation>
+ </message>
+ <message numerus="yes">
+ <location filename="translatable.js" line="12"/>
+ <source>%n fooish bar(s) found</source>
+ <translation>
+ <numerusform>%n fooaktig bar funnet</numerusform>
+ <numerusform>%n fooaktige barer funnet</numerusform>
+ </translation>
+ </message>
+</context>
+<context>
+ <name>translatable</name>
+ <message>
+ <location filename="translatable.js" line="1"/>
+ <source>One</source>
+ <translation>En</translation>
+ </message>
+ <message>
+ <location filename="translatable.js" line="5"/>
+ <source>Hello</source>
+ <translation>Hallo</translation>
+ </message>
+ <message>
+ <location filename="translatable.js" line="9"/>
+ <source>One</source>
+ <comment>not the same one</comment>
+ <translation>Enda en</translation>
+ </message>
+ <message numerus="yes">
+ <location filename="translatable.js" line="11"/>
+ <source>%n message(s) saved</source>
+ <translation>
+ <numerusform>%n melding lagret</numerusform>
+ <numerusform>%n meldinger lagret</numerusform>
+ </translation>
+ </message>
+ <message>
+ <source>Goodbye</source>
+ <translation type="obsolete">Farvel</translation>
+ </message>
+</context>
+<context>
+ <name>translatable2</name>
+ <message>
+ <location filename="translatable2.js" line="1"/>
+ <source>Three</source>
+ <translation>Tre</translation>
+ </message>
+ <message>
+ <location filename="translatable2.js" line="5"/>
+ <source>Happy birthday!</source>
+ <translation>Gratulerer med dagen!</translation>
+ </message>
+ <message>
+ <location filename="translatable2.js" line="9"/>
+ <source>Three</source>
+ <comment>not the same three</comment>
+ <translation>Tre andre</translation>
+ </message>
+</context>
+</TS>
diff --git a/tests/auto/qml/qjsengine/tst_qjsengine.cpp b/tests/auto/qml/qjsengine/tst_qjsengine.cpp
index 51cd69998a..8a1bedb600 100644
--- a/tests/auto/qml/qjsengine/tst_qjsengine.cpp
+++ b/tests/auto/qml/qjsengine/tst_qjsengine.cpp
@@ -159,6 +159,27 @@ private slots:
void scopeOfEvaluate();
+ void callConstants();
+
+ void installTranslatorFunctions();
+ void translateScript_data();
+ void translateScript();
+ void translateScript_crossScript();
+ void translateScript_trNoOp();
+ void translateScript_callQsTrFromCpp();
+ void translateWithInvalidArgs_data();
+ void translateWithInvalidArgs();
+ void translationContext_data();
+ void translationContext();
+ void translateScriptIdBased();
+ void translateScriptUnicode_data();
+ void translateScriptUnicode();
+ void translateScriptUnicodeIdBased_data();
+ void translateScriptUnicodeIdBased();
+ void translateFromBuiltinCallback();
+
+ void privateMethods();
+
signals:
void testSignal();
};
@@ -3099,6 +3120,471 @@ void tst_QJSEngine::scopeOfEvaluate()
QCOMPARE(result.toInt(), 42);
}
+void tst_QJSEngine::callConstants()
+{
+ QJSEngine engine;
+ engine.evaluate("function f() {\n"
+ " var one; one();\n"
+ " var two = null; two();\n"
+ "}\n");
+}
+
+void tst_QJSEngine::installTranslatorFunctions()
+{
+ QJSEngine eng;
+ QJSValue global = eng.globalObject();
+ QVERIFY(global.property("qsTranslate").isUndefined());
+ QVERIFY(global.property("QT_TRANSLATE_NOOP").isUndefined());
+ QVERIFY(global.property("qsTr").isUndefined());
+ QVERIFY(global.property("QT_TR_NOOP").isUndefined());
+ QVERIFY(global.property("qsTrId").isUndefined());
+ QVERIFY(global.property("QT_TRID_NOOP").isUndefined());
+
+ eng.installTranslatorFunctions();
+ QVERIFY(global.property("qsTranslate").isCallable());
+ QVERIFY(global.property("QT_TRANSLATE_NOOP").isCallable());
+ QVERIFY(global.property("qsTr").isCallable());
+ QVERIFY(global.property("QT_TR_NOOP").isCallable());
+ QVERIFY(global.property("qsTrId").isCallable());
+ QVERIFY(global.property("QT_TRID_NOOP").isCallable());
+
+ {
+ QJSValue ret = eng.evaluate("qsTr('foo')");
+ QVERIFY(ret.isString());
+ QCOMPARE(ret.toString(), QString::fromLatin1("foo"));
+ }
+ {
+ QJSValue ret = eng.evaluate("qsTranslate('foo', 'bar')");
+ QVERIFY(ret.isString());
+ QCOMPARE(ret.toString(), QString::fromLatin1("bar"));
+ }
+ {
+ QJSValue ret = eng.evaluate("QT_TR_NOOP('foo')");
+ QVERIFY(ret.isString());
+ QCOMPARE(ret.toString(), QString::fromLatin1("foo"));
+ }
+ {
+ QJSValue ret = eng.evaluate("QT_TRANSLATE_NOOP('foo', 'bar')");
+ QVERIFY(ret.isString());
+ QCOMPARE(ret.toString(), QString::fromLatin1("bar"));
+ }
+
+ {
+ QJSValue ret = eng.evaluate("qsTrId('foo')");
+ QVERIFY(ret.isString());
+ QCOMPARE(ret.toString(), QString::fromLatin1("foo"));
+ }
+ {
+ QJSValue ret = eng.evaluate("QT_TRID_NOOP('foo')");
+ QVERIFY(ret.isString());
+ QCOMPARE(ret.toString(), QString::fromLatin1("foo"));
+ }
+ QVERIFY(eng.evaluate("QT_TRID_NOOP()").isUndefined());
+}
+
+class TranslationScope
+{
+public:
+ TranslationScope(const QString &fileName)
+ {
+ translator.load(fileName);
+ QCoreApplication::instance()->installTranslator(&translator);
+ }
+ ~TranslationScope()
+ {
+ QCoreApplication::instance()->removeTranslator(&translator);
+ }
+
+private:
+ QTranslator translator;
+};
+
+void tst_QJSEngine::translateScript_data()
+{
+ QTest::addColumn<QString>("expression");
+ QTest::addColumn<QString>("fileName");
+ QTest::addColumn<QString>("expectedTranslation");
+
+ QString fileName = QString::fromLatin1("translatable.js");
+ // Top-level
+ QTest::newRow("qsTr('One')@translatable.js")
+ << QString::fromLatin1("qsTr('One')") << fileName << QString::fromLatin1("En");
+ QTest::newRow("qsTr('Hello')@translatable.js")
+ << QString::fromLatin1("qsTr('Hello')") << fileName << QString::fromLatin1("Hallo");
+ // From function
+ QTest::newRow("(function() { return qsTr('One'); })()@translatable.js")
+ << QString::fromLatin1("(function() { return qsTr('One'); })()") << fileName << QString::fromLatin1("En");
+ QTest::newRow("(function() { return qsTr('Hello'); })()@translatable.js")
+ << QString::fromLatin1("(function() { return qsTr('Hello'); })()") << fileName << QString::fromLatin1("Hallo");
+ // Plural
+ QTest::newRow("qsTr('%n message(s) saved', '', 1)@translatable.js")
+ << QString::fromLatin1("qsTr('%n message(s) saved', '', 1)") << fileName << QString::fromLatin1("1 melding lagret");
+ QTest::newRow("qsTr('%n message(s) saved', '', 3).arg@translatable.js")
+ << QString::fromLatin1("qsTr('%n message(s) saved', '', 3)") << fileName << QString::fromLatin1("3 meldinger lagret");
+
+ // Top-level
+ QTest::newRow("qsTranslate('FooContext', 'Two')@translatable.js")
+ << QString::fromLatin1("qsTranslate('FooContext', 'Two')") << fileName << QString::fromLatin1("To");
+ QTest::newRow("qsTranslate('FooContext', 'Goodbye')@translatable.js")
+ << QString::fromLatin1("qsTranslate('FooContext', 'Goodbye')") << fileName << QString::fromLatin1("Farvel");
+ // From eval
+ QTest::newRow("eval('qsTranslate(\\'FooContext\\', \\'Two\\')')@translatable.js")
+ << QString::fromLatin1("eval('qsTranslate(\\'FooContext\\', \\'Two\\')')") << fileName << QString::fromLatin1("To");
+ QTest::newRow("eval('qsTranslate(\\'FooContext\\', \\'Goodbye\\')')@translatable.js")
+ << QString::fromLatin1("eval('qsTranslate(\\'FooContext\\', \\'Goodbye\\')')") << fileName << QString::fromLatin1("Farvel");
+
+ QTest::newRow("qsTranslate('FooContext', 'Goodbye', '')@translatable.js")
+ << QString::fromLatin1("qsTranslate('FooContext', 'Goodbye', '')") << fileName << QString::fromLatin1("Farvel");
+
+ QTest::newRow("qsTranslate('FooContext', 'Goodbye', '', 42)@translatable.js")
+ << QString::fromLatin1("qsTranslate('FooContext', 'Goodbye', '', 42)") << fileName << QString::fromLatin1("Goodbye");
+
+ QTest::newRow("qsTr('One', 'not the same one')@translatable.js")
+ << QString::fromLatin1("qsTr('One', 'not the same one')") << fileName << QString::fromLatin1("Enda en");
+
+ QTest::newRow("qsTr('One', 'not the same one', 42)@translatable.js")
+ << QString::fromLatin1("qsTr('One', 'not the same one', 42)") << fileName << QString::fromLatin1("One");
+
+ // Plural
+ QTest::newRow("qsTranslate('FooContext', '%n fooish bar(s) found', '', 1)@translatable.js")
+ << QString::fromLatin1("qsTranslate('FooContext', '%n fooish bar(s) found', '', 1)") << fileName << QString::fromLatin1("1 fooaktig bar funnet");
+ QTest::newRow("qsTranslate('FooContext', '%n fooish bar(s) found', '', 2)@translatable.js")
+ << QString::fromLatin1("qsTranslate('FooContext', '%n fooish bar(s) found', '', 2)") << fileName << QString::fromLatin1("2 fooaktige barer funnet");
+
+ // Don't exist in translation
+ QTest::newRow("qsTr('Three')@translatable.js")
+ << QString::fromLatin1("qsTr('Three')") << fileName << QString::fromLatin1("Three");
+ QTest::newRow("qsTranslate('FooContext', 'So long')@translatable.js")
+ << QString::fromLatin1("qsTranslate('FooContext', 'So long')") << fileName << QString::fromLatin1("So long");
+ QTest::newRow("qsTranslate('BarContext', 'Goodbye')@translatable.js")
+ << QString::fromLatin1("qsTranslate('BarContext', 'Goodbye')") << fileName << QString::fromLatin1("Goodbye");
+
+ // Translate strings from the second script (translatable2.js)
+
+ QString fileName2 = QString::fromLatin1("translatable2.js");
+ QTest::newRow("qsTr('Three')@translatable2.js")
+ << QString::fromLatin1("qsTr('Three')") << fileName2 << QString::fromLatin1("Tre");
+ QTest::newRow("qsTr('Happy birthday!')@translatable2.js")
+ << QString::fromLatin1("qsTr('Happy birthday!')") << fileName2 << QString::fromLatin1("Gratulerer med dagen!");
+
+ // Not translated because translation is only in translatable.js
+ QTest::newRow("qsTr('One')@translatable2.js")
+ << QString::fromLatin1("qsTr('One')") << fileName2 << QString::fromLatin1("One");
+ QTest::newRow("(function() { return qsTr('One'); })()@translatable2.js")
+ << QString::fromLatin1("(function() { return qsTr('One'); })()") << fileName2 << QString::fromLatin1("One");
+
+ // For qsTranslate() the filename shouldn't matter
+ QTest::newRow("qsTranslate('FooContext', 'Two')@translatable2.js")
+ << QString::fromLatin1("qsTranslate('FooContext', 'Two')") << fileName2 << QString::fromLatin1("To");
+ QTest::newRow("qsTranslate('BarContext', 'Congratulations!')@translatable.js")
+ << QString::fromLatin1("qsTranslate('BarContext', 'Congratulations!')") << fileName << QString::fromLatin1("Gratulerer!");
+}
+
+void tst_QJSEngine::translateScript()
+{
+ QFETCH(QString, expression);
+ QFETCH(QString, fileName);
+ QFETCH(QString, expectedTranslation);
+
+ QJSEngine engine;
+
+ TranslationScope tranScope(":/translations/translatable_la");
+ engine.installTranslatorFunctions();
+
+ QCOMPARE(engine.evaluate(expression, fileName).toString(), expectedTranslation);
+}
+
+void tst_QJSEngine::translateScript_crossScript()
+{
+ QJSEngine engine;
+ TranslationScope tranScope(":/translations/translatable_la");
+ engine.installTranslatorFunctions();
+
+ QString fileName = QString::fromLatin1("translatable.js");
+ QString fileName2 = QString::fromLatin1("translatable2.js");
+ // qsTr() should use the innermost filename as context
+ engine.evaluate("function foo(s) { return bar(s); }", fileName);
+ engine.evaluate("function bar(s) { return qsTr(s); }", fileName2);
+ QCOMPARE(engine.evaluate("bar('Three')", fileName2).toString(), QString::fromLatin1("Tre"));
+ QCOMPARE(engine.evaluate("bar('Three')", fileName).toString(), QString::fromLatin1("Tre"));
+ QCOMPARE(engine.evaluate("bar('One')", fileName2).toString(), QString::fromLatin1("One"));
+
+ engine.evaluate("function foo(s) { return bar(s); }", fileName2);
+ engine.evaluate("function bar(s) { return qsTr(s); }", fileName);
+ QCOMPARE(engine.evaluate("bar('Three')", fileName2).toString(), QString::fromLatin1("Three"));
+ QCOMPARE(engine.evaluate("bar('One')", fileName).toString(), QString::fromLatin1("En"));
+ QCOMPARE(engine.evaluate("bar('One')", fileName2).toString(), QString::fromLatin1("En"));
+}
+
+void tst_QJSEngine::translateScript_trNoOp()
+{
+ QJSEngine engine;
+ TranslationScope tranScope(":/translations/translatable_la");
+ engine.installTranslatorFunctions();
+
+ QVERIFY(engine.evaluate("QT_TR_NOOP()").isUndefined());
+ QCOMPARE(engine.evaluate("QT_TR_NOOP('One')").toString(), QString::fromLatin1("One"));
+
+ QVERIFY(engine.evaluate("QT_TRANSLATE_NOOP()").isUndefined());
+ QVERIFY(engine.evaluate("QT_TRANSLATE_NOOP('FooContext')").isUndefined());
+ QCOMPARE(engine.evaluate("QT_TRANSLATE_NOOP('FooContext', 'Two')").toString(), QString::fromLatin1("Two"));
+}
+
+void tst_QJSEngine::translateScript_callQsTrFromCpp()
+{
+ QJSEngine engine;
+ TranslationScope tranScope(":/translations/translatable_la");
+ engine.installTranslatorFunctions();
+
+ // There is no context, but it shouldn't crash
+ QCOMPARE(engine.globalObject().property("qsTr").call(QJSValueList() << "One").toString(), QString::fromLatin1("One"));
+}
+
+void tst_QJSEngine::translateWithInvalidArgs_data()
+{
+ QTest::addColumn<QString>("expression");
+ QTest::addColumn<QString>("expectedError");
+
+ QTest::newRow("qsTr()") << "qsTr()" << "Error: qsTr() requires at least one argument";
+ QTest::newRow("qsTr(123)") << "qsTr(123)" << "Error: qsTr(): first argument (sourceText) must be a string";
+ QTest::newRow("qsTr('foo', 123)") << "qsTr('foo', 123)" << "Error: qsTr(): second argument (disambiguation) must be a string";
+ QTest::newRow("qsTr('foo', 'bar', 'baz')") << "qsTr('foo', 'bar', 'baz')" << "Error: qsTr(): third argument (n) must be a number";
+ QTest::newRow("qsTr('foo', 'bar', true)") << "qsTr('foo', 'bar', true)" << "Error: qsTr(): third argument (n) must be a number";
+
+ QTest::newRow("qsTranslate()") << "qsTranslate()" << "Error: qsTranslate() requires at least two arguments";
+ QTest::newRow("qsTranslate('foo')") << "qsTranslate('foo')" << "Error: qsTranslate() requires at least two arguments";
+ QTest::newRow("qsTranslate(123, 'foo')") << "qsTranslate(123, 'foo')" << "Error: qsTranslate(): first argument (context) must be a string";
+ QTest::newRow("qsTranslate('foo', 123)") << "qsTranslate('foo', 123)" << "Error: qsTranslate(): second argument (sourceText) must be a string";
+ QTest::newRow("qsTranslate('foo', 'bar', 123)") << "qsTranslate('foo', 'bar', 123)" << "Error: qsTranslate(): third argument (disambiguation) must be a string";
+
+ QTest::newRow("qsTrId()") << "qsTrId()" << "Error: qsTrId() requires at least one argument";
+ QTest::newRow("qsTrId(123)") << "qsTrId(123)" << "TypeError: qsTrId(): first argument (id) must be a string";
+ QTest::newRow("qsTrId('foo', 'bar')") << "qsTrId('foo', 'bar')" << "TypeError: qsTrId(): second argument (n) must be a number";
+}
+
+void tst_QJSEngine::translateWithInvalidArgs()
+{
+ QFETCH(QString, expression);
+ QFETCH(QString, expectedError);
+ QJSEngine engine;
+ engine.installTranslatorFunctions();
+ QJSValue result = engine.evaluate(expression);
+ QVERIFY(result.isError());
+ QCOMPARE(result.toString(), expectedError);
+}
+
+void tst_QJSEngine::translationContext_data()
+{
+ QTest::addColumn<QString>("path");
+ QTest::addColumn<QString>("text");
+ QTest::addColumn<QString>("expectedTranslation");
+
+ QTest::newRow("translatable.js") << "translatable.js" << "One" << "En";
+ QTest::newRow("/translatable.js") << "/translatable.js" << "One" << "En";
+ QTest::newRow("/foo/translatable.js") << "/foo/translatable.js" << "One" << "En";
+ QTest::newRow("/foo/bar/translatable.js") << "/foo/bar/translatable.js" << "One" << "En";
+ QTest::newRow("./translatable.js") << "./translatable.js" << "One" << "En";
+ QTest::newRow("../translatable.js") << "../translatable.js" << "One" << "En";
+ QTest::newRow("foo/translatable.js") << "foo/translatable.js" << "One" << "En";
+ QTest::newRow("file:///home/qt/translatable.js") << "file:///home/qt/translatable.js" << "One" << "En";
+ QTest::newRow(":/resources/translatable.js") << ":/resources/translatable.js" << "One" << "En";
+ QTest::newRow("/translatable.js.foo") << "/translatable.js.foo" << "One" << "En";
+ QTest::newRow("/translatable.txt") << "/translatable.txt" << "One" << "En";
+ QTest::newRow("translatable") << "translatable" << "One" << "En";
+ QTest::newRow("foo/translatable") << "foo/translatable" << "One" << "En";
+
+ QTest::newRow("translatable.js/") << "translatable.js/" << "One" << "One";
+ QTest::newRow("nosuchscript.js") << "" << "One" << "One";
+ QTest::newRow("(empty)") << "" << "One" << "One";
+}
+
+void tst_QJSEngine::translationContext()
+{
+ TranslationScope tranScope(":/translations/translatable_la");
+
+ QJSEngine engine;
+ engine.installTranslatorFunctions();
+
+ QFETCH(QString, path);
+ QFETCH(QString, text);
+ QFETCH(QString, expectedTranslation);
+ QJSValue ret = engine.evaluate(QString::fromLatin1("qsTr('%0')").arg(text), path);
+ QVERIFY(ret.isString());
+ QCOMPARE(ret.toString(), expectedTranslation);
+}
+
+void tst_QJSEngine::translateScriptIdBased()
+{
+ QJSEngine engine;
+
+ TranslationScope tranScope(":/translations/idtranslatable_la");
+ engine.installTranslatorFunctions();
+
+ QString fileName = QString::fromLatin1("idtranslatable.js");
+
+ QHash<QString, QString> expectedTranslations;
+ expectedTranslations["qtn_foo_bar"] = "First string";
+ expectedTranslations["qtn_needle"] = "Second string";
+ expectedTranslations["qtn_haystack"] = "Third string";
+ expectedTranslations["qtn_bar_baz"] = "Fourth string";
+
+ QHash<QString, QString>::const_iterator it;
+ for (it = expectedTranslations.constBegin(); it != expectedTranslations.constEnd(); ++it) {
+ for (int x = 0; x < 2; ++x) {
+ QString fn;
+ if (x)
+ fn = fileName;
+ // Top-level
+ QCOMPARE(engine.evaluate(QString::fromLatin1("qsTrId('%0')")
+ .arg(it.key()), fn).toString(),
+ it.value());
+ QCOMPARE(engine.evaluate(QString::fromLatin1("QT_TRID_NOOP('%0')")
+ .arg(it.key()), fn).toString(),
+ it.key());
+ // From function
+ QCOMPARE(engine.evaluate(QString::fromLatin1("(function() { return qsTrId('%0'); })()")
+ .arg(it.key()), fn).toString(),
+ it.value());
+ QCOMPARE(engine.evaluate(QString::fromLatin1("(function() { return QT_TRID_NOOP('%0'); })()")
+ .arg(it.key()), fn).toString(),
+ it.key());
+ }
+ }
+
+ // Plural form
+ QCOMPARE(engine.evaluate("qsTrId('qtn_bar_baz', 10)").toString(),
+ QString::fromLatin1("10 fooish bar(s) found"));
+ QCOMPARE(engine.evaluate("qsTrId('qtn_foo_bar', 10)").toString(),
+ QString::fromLatin1("qtn_foo_bar")); // Doesn't have plural
+}
+
+// How to add a new test row:
+// - Find a nice list of Unicode characters to choose from
+// - Write source string/context/comment in .js using Unicode escape sequences (\uABCD)
+// - Update corresponding .ts file (e.g. lupdate foo.js -ts foo.ts -codecfortr UTF-8)
+// - Enter translation in Linguist
+// - Update corresponding .qm file (e.g. lrelease foo.ts)
+// - Evaluate script that performs translation; make sure the correct result is returned
+// (e.g. by setting the resulting string as the text of a QLabel and visually verifying
+// that it looks the same as what you entered in Linguist :-) )
+// - Generate the expectedTranslation column data using toUtf8().toHex()
+void tst_QJSEngine::translateScriptUnicode_data()
+{
+ QTest::addColumn<QString>("expression");
+ QTest::addColumn<QString>("fileName");
+ QTest::addColumn<QString>("expectedTranslation");
+
+ QString fileName = QString::fromLatin1("translatable-unicode.js");
+ QTest::newRow("qsTr('H\\u2082O')@translatable-unicode.js")
+ << QString::fromLatin1("qsTr('H\\u2082O')") << fileName << QString::fromUtf8("\xcd\xbb\xcd\xbc\xcd\xbd");
+ QTest::newRow("qsTranslate('\\u010C\\u0101\\u011F\\u0115', 'CO\\u2082')@translatable-unicode.js")
+ << QString::fromLatin1("qsTranslate('\\u010C\\u0101\\u011F\\u0115', 'CO\\u2082')") << fileName << QString::fromUtf8("\xd7\x91\xd7\x9a\xd7\xa2");
+ QTest::newRow("qsTr('\\u0391\\u0392\\u0393')@translatable-unicode.js")
+ << QString::fromLatin1("qsTr('\\u0391\\u0392\\u0393')") << fileName << QString::fromUtf8("\xd3\x9c\xd2\xb4\xd1\xbc");
+ QTest::newRow("qsTranslate('\\u010C\\u0101\\u011F\\u0115', '\\u0414\\u0415\\u0416')@translatable-unicode.js")
+ << QString::fromLatin1("qsTranslate('\\u010C\\u0101\\u011F\\u0115', '\\u0414\\u0415\\u0416')") << fileName << QString::fromUtf8("\xd8\xae\xd8\xb3\xd8\xb3");
+ QTest::newRow("qsTr('H\\u2082O', 'not the same H\\u2082O')@translatable-unicode.js")
+ << QString::fromLatin1("qsTr('H\\u2082O', 'not the same H\\u2082O')") << fileName << QString::fromUtf8("\xd4\xb6\xd5\x8a\xd5\x92");
+ QTest::newRow("qsTr('H\\u2082O')")
+ << QString::fromLatin1("qsTr('H\\u2082O')") << QString() << QString::fromUtf8("\x48\xe2\x82\x82\x4f");
+ QTest::newRow("qsTranslate('\\u010C\\u0101\\u011F\\u0115', 'CO\\u2082')")
+ << QString::fromLatin1("qsTranslate('\\u010C\\u0101\\u011F\\u0115', 'CO\\u2082')") << QString() << QString::fromUtf8("\xd7\x91\xd7\x9a\xd7\xa2");
+}
+
+void tst_QJSEngine::translateScriptUnicode()
+{
+ QFETCH(QString, expression);
+ QFETCH(QString, fileName);
+ QFETCH(QString, expectedTranslation);
+
+ QJSEngine engine;
+
+ TranslationScope tranScope(":/translations/translatable-unicode");
+ engine.installTranslatorFunctions();
+
+ QCOMPARE(engine.evaluate(expression, fileName).toString(), expectedTranslation);
+}
+
+void tst_QJSEngine::translateScriptUnicodeIdBased_data()
+{
+ QTest::addColumn<QString>("expression");
+ QTest::addColumn<QString>("expectedTranslation");
+
+ QTest::newRow("qsTrId('\\u01F8\\u01D2\\u0199\\u01D0\\u01E1'')")
+ << QString::fromLatin1("qsTrId('\\u01F8\\u01D2\\u0199\\u01D0\\u01E1')") << QString::fromUtf8("\xc6\xa7\xc6\xb0\xc6\x88\xc8\xbc\xc8\x9d\xc8\xbf\xc8\x99");
+ QTest::newRow("qsTrId('\\u0191\\u01CE\\u0211\\u0229\\u019C\\u018E\\u019A\\u01D0')")
+ << QString::fromLatin1("qsTrId('\\u0191\\u01CE\\u0211\\u0229\\u019C\\u018E\\u019A\\u01D0')") << QString::fromUtf8("\xc7\xa0\xc8\xa1\xc8\x8b\xc8\x85\xc8\x95");
+ QTest::newRow("qsTrId('\\u0181\\u01A1\\u0213\\u018F\\u018C', 10)")
+ << QString::fromLatin1("qsTrId('\\u0181\\u01A1\\u0213\\u018F\\u018C', 10)") << QString::fromUtf8("\x31\x30\x20\xc6\x92\xc6\xa1\xc7\x92\x28\xc8\x99\x29");
+ QTest::newRow("qsTrId('\\u0181\\u01A1\\u0213\\u018F\\u018C')")
+ << QString::fromLatin1("qsTrId('\\u0181\\u01A1\\u0213\\u018F\\u018C')") << QString::fromUtf8("\xc6\x91\xc6\xb0\xc7\xb9");
+ QTest::newRow("qsTrId('\\u01CD\\u0180\\u01A8\\u0190\\u019E\\u01AB')")
+ << QString::fromLatin1("qsTrId('\\u01CD\\u0180\\u01A8\\u0190\\u019E\\u01AB')") << QString::fromUtf8("\xc7\x8d\xc6\x80\xc6\xa8\xc6\x90\xc6\x9e\xc6\xab");
+}
+
+void tst_QJSEngine::translateScriptUnicodeIdBased()
+{
+ QFETCH(QString, expression);
+ QFETCH(QString, expectedTranslation);
+
+ QJSEngine engine;
+
+ TranslationScope tranScope(":/translations/idtranslatable-unicode");
+ engine.installTranslatorFunctions();
+
+ QCOMPARE(engine.evaluate(expression).toString(), expectedTranslation);
+}
+
+void tst_QJSEngine::translateFromBuiltinCallback()
+{
+ QJSEngine eng;
+ eng.installTranslatorFunctions();
+
+ // Callback has no translation context.
+ eng.evaluate("function foo() { qsTr('foo'); }");
+
+ // Stack at translation time will be:
+ // qsTr, foo, forEach, global
+ // qsTr() needs to walk to the outer-most (global) frame before it finds
+ // a translation context, and this should not crash.
+ eng.evaluate("[10,20].forEach(foo)", "script.js");
+}
+
+class ObjectWithPrivateMethods : public QObject
+{
+ Q_OBJECT
+private slots:
+ void myPrivateMethod() {}
+};
+
+void tst_QJSEngine::privateMethods()
+{
+ ObjectWithPrivateMethods object;
+ QJSEngine engine;
+ QJSValue jsWrapper = engine.newQObject(&object);
+ QQmlEngine::setObjectOwnership(&object, QQmlEngine::CppOwnership);
+
+ QSet<QString> privateMethods;
+ {
+ const QMetaObject *mo = object.metaObject();
+ for (int i = 0; i < mo->methodCount(); ++i) {
+ const QMetaMethod method = mo->method(i);
+ if (method.access() == QMetaMethod::Private)
+ privateMethods << QString::fromUtf8(method.name());
+ }
+ }
+
+ QVERIFY(privateMethods.contains("myPrivateMethod"));
+ QVERIFY(privateMethods.contains("_q_reregisterTimers"));
+ privateMethods << QStringLiteral("deleteLater") << QStringLiteral("destroyed");
+
+ QJSValueIterator it(jsWrapper);
+ while (it.hasNext()) {
+ it.next();
+ QVERIFY(!privateMethods.contains(it.name()));
+ }
+}
+
QTEST_MAIN(tst_QJSEngine)
#include "tst_qjsengine.moc"
diff --git a/tests/auto/qml/qqmlapplicationengine/tst_qqmlapplicationengine.cpp b/tests/auto/qml/qqmlapplicationengine/tst_qqmlapplicationengine.cpp
index b261bb5191..9dcf68f50c 100644
--- a/tests/auto/qml/qqmlapplicationengine/tst_qqmlapplicationengine.cpp
+++ b/tests/auto/qml/qqmlapplicationengine/tst_qqmlapplicationengine.cpp
@@ -64,6 +64,7 @@ private:
void tst_qqmlapplicationengine::initTestCase()
{
+ qputenv("QT_MESSAGE_PATTERN", ""); // don't let it modify the debug output from testapp
buildDir = QDir::currentPath();
QQmlDataTest::initTestCase(); //Changes current path to src dir
srcDir = QDir::currentPath();
@@ -123,7 +124,7 @@ void tst_qqmlapplicationengine::application()
test_stderr_target.replace('\n', QByteArray("\r\n"));
#endif
QCOMPARE(test_stdout, QByteArray(""));
- QCOMPARE(test_stderr, test_stderr_target);
+ QCOMPARE(QString(test_stderr), QString(test_stderr_target));
delete testProcess;
QDir::setCurrent(srcDir);
#else // !QT_NO_PROCESS
diff --git a/tests/auto/qml/qqmlchangeset/tst_qqmlchangeset.cpp b/tests/auto/qml/qqmlchangeset/tst_qqmlchangeset.cpp
index 0f09de26d3..cfc850a9c6 100644
--- a/tests/auto/qml/qqmlchangeset/tst_qqmlchangeset.cpp
+++ b/tests/auto/qml/qqmlchangeset/tst_qqmlchangeset.cpp
@@ -148,7 +148,7 @@ public:
return false;
}
if (signal.moveId != -1) {
- QQmlChangeSet::Insert insert(signal.index, signal.count, signal.moveId, signal.offset);
+ QQmlChangeSet::Change insert(signal.index, signal.count, signal.moveId, signal.offset);
for (int i = insert.start(); i < insert.end(); ++i)
list.insert(i, removedValues.take(insert.moveKey(i)));
} else {
@@ -160,7 +160,7 @@ public:
return false;
}
if (signal.moveId != -1) {
- QQmlChangeSet::Remove remove(signal.index, signal.count, signal.moveId, signal.offset);
+ QQmlChangeSet::Change remove(signal.index, signal.count, signal.moveId, signal.offset);
for (int i = remove.start(); i < remove.end(); ++i)
removedValues.insert(remove.moveKey(i), list.at(i));
}
@@ -1182,9 +1182,9 @@ void tst_qqmlchangeset::sequence()
}
SignalList changes;
- foreach (const QQmlChangeSet::Remove &remove, set.removes())
+ foreach (const QQmlChangeSet::Change &remove, set.removes())
changes << Remove(remove.index, remove.count, remove.moveId, remove.offset);
- foreach (const QQmlChangeSet::Insert &insert, set.inserts())
+ foreach (const QQmlChangeSet::Change &insert, set.inserts())
changes << Insert(insert.index, insert.count, insert.moveId, insert.offset);
foreach (const QQmlChangeSet::Change &change, set.changes())
changes << Change(change.index, change.count);
@@ -1322,15 +1322,15 @@ void tst_qqmlchangeset::apply()
}
SignalList changes;
- foreach (const QQmlChangeSet::Remove &remove, set.removes())
+ foreach (const QQmlChangeSet::Change &remove, set.removes())
changes << Remove(remove.index, remove.count, remove.moveId, remove.offset);
- foreach (const QQmlChangeSet::Insert &insert, set.inserts())
+ foreach (const QQmlChangeSet::Change &insert, set.inserts())
changes << Insert(insert.index, insert.count, insert.moveId, insert.offset);
SignalList linearChanges;
- foreach (const QQmlChangeSet::Remove &remove, linearSet.removes())
+ foreach (const QQmlChangeSet::Change &remove, linearSet.removes())
linearChanges << Remove(remove.index, remove.count, remove.moveId, remove.offset);
- foreach (const QQmlChangeSet::Insert &insert, linearSet.inserts())
+ foreach (const QQmlChangeSet::Change &insert, linearSet.inserts())
linearChanges << Insert(insert.index, insert.count, insert.moveId, insert.offset);
// The output in the failing tests isn't incorrect, merely sub-optimal.
@@ -1364,17 +1364,17 @@ void tst_qqmlchangeset::removeConsecutive()
QFETCH(SignalList, input);
QFETCH(SignalList, output);
- QVector<QQmlChangeSet::Remove> removes;
+ QVector<QQmlChangeSet::Change> removes;
foreach (const Signal &signal, input) {
QVERIFY(signal.isRemove());
- removes.append(QQmlChangeSet::Remove(signal.index, signal.count, signal.moveId, signal.offset));
+ removes.append(QQmlChangeSet::Change(signal.index, signal.count, signal.moveId, signal.offset));
}
QQmlChangeSet set;
set.remove(removes);
SignalList changes;
- foreach (const QQmlChangeSet::Remove &remove, set.removes())
+ foreach (const QQmlChangeSet::Change &remove, set.removes())
changes << Remove(remove.index, remove.count, remove.moveId, remove.offset);
QVERIFY(set.inserts().isEmpty());
QVERIFY(set.changes().isEmpty());
@@ -1404,17 +1404,17 @@ void tst_qqmlchangeset::insertConsecutive()
QFETCH(SignalList, input);
QFETCH(SignalList, output);
- QVector<QQmlChangeSet::Insert> inserts;
+ QVector<QQmlChangeSet::Change> inserts;
foreach (const Signal &signal, input) {
QVERIFY(signal.isInsert());
- inserts.append(QQmlChangeSet::Insert(signal.index, signal.count, signal.moveId, signal.offset));
+ inserts.append(QQmlChangeSet::Change(signal.index, signal.count, signal.moveId, signal.offset));
}
QQmlChangeSet set;
set.insert(inserts);
SignalList changes;
- foreach (const QQmlChangeSet::Insert &insert, set.inserts())
+ foreach (const QQmlChangeSet::Change &insert, set.inserts())
changes << Insert(insert.index, insert.count, insert.moveId, insert.offset);
QVERIFY(set.removes().isEmpty());
QVERIFY(set.changes().isEmpty());
@@ -1462,12 +1462,12 @@ void tst_qqmlchangeset::debug()
changeSet.insert(15, 2);
changeSet.change(24, 8);
- QTest::ignoreMessage(QtDebugMsg, "QQmlChangeSet(Remove(0,12) Remove(5,4) Insert(3,9) Insert(15,2) Change(24,8) )");
+ QTest::ignoreMessage(QtDebugMsg, "QQmlChangeSet(Change(0,12) Change(5,4) Change(3,9) Change(15,2) Change(24,8) )");
qDebug() << changeSet;
changeSet.clear();
- QTest::ignoreMessage(QtDebugMsg, "QQmlChangeSet(Remove(12,4,0,0) Insert(5,4,0,0) )");
+ QTest::ignoreMessage(QtDebugMsg, "QQmlChangeSet(Change(12,4) Change(5,4) )");
changeSet.move(12, 5, 4, 0);
qDebug() << changeSet;
@@ -1537,9 +1537,9 @@ void tst_qqmlchangeset::random()
}
SignalList output;
- foreach (const QQmlChangeSet::Remove &remove, accumulatedSet.removes())
+ foreach (const QQmlChangeSet::Change &remove, accumulatedSet.removes())
output << Remove(remove.index, remove.count, remove.moveId, remove.offset);
- foreach (const QQmlChangeSet::Insert &insert, accumulatedSet.inserts())
+ foreach (const QQmlChangeSet::Change &insert, accumulatedSet.inserts())
output << Insert(insert.index, insert.count, insert.moveId, insert.offset);
QVector<int> inputList;
diff --git a/tests/auto/qml/qqmlcomponent/tst_qqmlcomponent.cpp b/tests/auto/qml/qqmlcomponent/tst_qqmlcomponent.cpp
index dbf28a5471..d5a5f10634 100644
--- a/tests/auto/qml/qqmlcomponent/tst_qqmlcomponent.cpp
+++ b/tests/auto/qml/qqmlcomponent/tst_qqmlcomponent.cpp
@@ -267,8 +267,8 @@ void tst_qqmlcomponent::qmlCreateParentReference()
void tst_qqmlcomponent::async()
{
- TestHTTPServer server(SERVER_PORT);
- QVERIFY(server.isValid());
+ TestHTTPServer server;
+ QVERIFY2(server.listen(SERVER_PORT), qPrintable(server.errorString()));
server.serveDirectory(dataDirectory());
QQmlComponent component(&engine);
@@ -287,8 +287,8 @@ void tst_qqmlcomponent::async()
void tst_qqmlcomponent::asyncHierarchy()
{
- TestHTTPServer server(SERVER_PORT);
- QVERIFY(server.isValid());
+ TestHTTPServer server;
+ QVERIFY2(server.listen(SERVER_PORT), qPrintable(server.errorString()));
server.serveDirectory(dataDirectory());
// ensure that the item hierarchy is compiled correctly.
diff --git a/tests/auto/qml/qqmlcontext/tst_qqmlcontext.cpp b/tests/auto/qml/qqmlcontext/tst_qqmlcontext.cpp
index 553663ac22..147887109f 100644
--- a/tests/auto/qml/qqmlcontext/tst_qqmlcontext.cpp
+++ b/tests/auto/qml/qqmlcontext/tst_qqmlcontext.cpp
@@ -348,7 +348,7 @@ void tst_qqmlcontext::setContextProperty()
QQmlContext ctxt(engine.rootContext());
ctxt.setContextProperty("ctxtProp", QVariant());
- QTest::ignoreMessage(QtWarningMsg, "<Unknown File>: TypeError: Cannot read property 'a' of undefined");
+ QTest::ignoreMessage(QtWarningMsg, "<Unknown File>:1: TypeError: Cannot read property 'a' of undefined");
QObject *obj = component.create(&ctxt);
QVariant v = obj->property("obj");
diff --git a/tests/auto/qml/qqmlecmascript/data/assignSequenceTypes.1.qml b/tests/auto/qml/qqmlecmascript/data/assignSequenceTypes.1.qml
index be283fdda1..027fdbdfcb 100644
--- a/tests/auto/qml/qqmlecmascript/data/assignSequenceTypes.1.qml
+++ b/tests/auto/qml/qqmlecmascript/data/assignSequenceTypes.1.qml
@@ -3,7 +3,7 @@ import Qt.test 1.0
MySequenceConversionObject {
intListProperty: [1, 2]
- qrealListProperty: [1.1, 2.2]
+ qrealListProperty: [1.1, 2.2, 3]
boolListProperty: [false, true]
urlListProperty: [ "http://www.example1.com", "http://www.example2.com" ]
stringListProperty: [ "one", "two" ]
diff --git a/tests/auto/qml/qqmlecmascript/data/assignSequenceTypes.3.qml b/tests/auto/qml/qqmlecmascript/data/assignSequenceTypes.3.qml
index ad8a92e317..e486feb96c 100644
--- a/tests/auto/qml/qqmlecmascript/data/assignSequenceTypes.3.qml
+++ b/tests/auto/qml/qqmlecmascript/data/assignSequenceTypes.3.qml
@@ -3,7 +3,7 @@ import Qt.test 1.0
MySequenceConversionObject {
intListProperty: 1
- qrealListProperty: 1.1
+ qrealListProperty: 1
boolListProperty: false
urlListProperty: Qt.resolvedUrl("example.html")
}
diff --git a/tests/auto/qml/qqmlecmascript/data/assignSequenceTypes.4.qml b/tests/auto/qml/qqmlecmascript/data/assignSequenceTypes.4.qml
index a9f2e642d1..10e49af8e0 100644
--- a/tests/auto/qml/qqmlecmascript/data/assignSequenceTypes.4.qml
+++ b/tests/auto/qml/qqmlecmascript/data/assignSequenceTypes.4.qml
@@ -4,7 +4,7 @@ import Qt.test 1.0
MySequenceConversionObject {
Component.onCompleted: {
intListProperty = [1, 2]
- qrealListProperty = [1.1, 2.2]
+ qrealListProperty = [1.1, 2.2, 3]
boolListProperty = [false, true]
urlListProperty = [ "http://www.example1.com", "http://www.example2.com" ]
stringListProperty = [ "one", "two" ]
diff --git a/tests/auto/qml/qqmlecmascript/data/assignSequenceTypes.6.qml b/tests/auto/qml/qqmlecmascript/data/assignSequenceTypes.6.qml
index 7a794eb694..bc72b78af7 100644
--- a/tests/auto/qml/qqmlecmascript/data/assignSequenceTypes.6.qml
+++ b/tests/auto/qml/qqmlecmascript/data/assignSequenceTypes.6.qml
@@ -4,7 +4,7 @@ import Qt.test 1.0
MySequenceConversionObject {
Component.onCompleted: {
intListProperty = 1;
- qrealListProperty = 1.1;
+ qrealListProperty = 1;
boolListProperty = false;
urlListProperty = Qt.resolvedUrl("example.html");
}
diff --git a/tests/auto/qml/qqmlecmascript/data/extendedObjectPropertyLookup3.qml b/tests/auto/qml/qqmlecmascript/data/extendedObjectPropertyLookup3.qml
new file mode 100644
index 0000000000..ef574f9361
--- /dev/null
+++ b/tests/auto/qml/qqmlecmascript/data/extendedObjectPropertyLookup3.qml
@@ -0,0 +1,13 @@
+import Qt.test 1.0
+import QtQuick 2.0
+
+QtObject {
+ property ImplementedExtensionObject a : ImplementedExtensionObject { id: root; extendedProperty : 42 }
+ property int b: root.abstractProperty
+ property int c: root.implementedProperty
+ property int d: root.extendedProperty
+
+ function getAbstractProperty() { return b; }
+ function getImplementedProperty() { return c; }
+ function getExtendedProperty() { return d; }
+}
diff --git a/tests/auto/qml/qqmlecmascript/data/uncreatableExtendedObjectFailureCheck.qml b/tests/auto/qml/qqmlecmascript/data/uncreatableExtendedObjectFailureCheck.qml
new file mode 100644
index 0000000000..3619d8588c
--- /dev/null
+++ b/tests/auto/qml/qqmlecmascript/data/uncreatableExtendedObjectFailureCheck.qml
@@ -0,0 +1,8 @@
+import Qt.test 1.0
+import QtQuick 2.0
+
+QtObject {
+ property AbstractExtensionObject a;
+ a: AbstractExtensionObject { id: root }
+ property int b: Math.max(root.abstractProperty, 0)
+}
diff --git a/tests/auto/qml/qqmlecmascript/testtypes.cpp b/tests/auto/qml/qqmlecmascript/testtypes.cpp
index 560d86005c..c4e6709958 100644
--- a/tests/auto/qml/qqmlecmascript/testtypes.cpp
+++ b/tests/auto/qml/qqmlecmascript/testtypes.cpp
@@ -63,6 +63,44 @@ private:
int m_value;
};
+class AbstractExtensionObject : public QObject
+{
+ Q_OBJECT
+ Q_PROPERTY(int abstractProperty READ abstractProperty WRITE setAbstractProperty NOTIFY abstractPropertyChanged)
+public:
+
+ AbstractExtensionObject(QObject *parent = 0) : QObject(parent), m_abstractProperty(-1) {}
+
+ void setAbstractProperty(int abstractProperty) { m_abstractProperty = abstractProperty; emit abstractPropertyChanged(); }
+ int abstractProperty() const { return m_abstractProperty; }
+
+ virtual void shouldBeImplemented() = 0;
+
+signals:
+ void abstractPropertyChanged();
+
+private:
+ int m_abstractProperty;
+};
+
+class ImplementedExtensionObject : public AbstractExtensionObject
+{
+ Q_OBJECT
+ Q_PROPERTY(int implementedProperty READ implementedProperty WRITE setImplementedProperty NOTIFY implementedPropertyChanged)
+public:
+ ImplementedExtensionObject(QObject *parent = 0) : AbstractExtensionObject(parent), m_implementedProperty(883) {}
+ void shouldBeImplemented() {}
+
+ void setImplementedProperty(int implementedProperty) { m_implementedProperty = implementedProperty; emit implementedPropertyChanged(); }
+ int implementedProperty() const { return m_implementedProperty; }
+
+signals:
+ void implementedPropertyChanged();
+
+private:
+ int m_implementedProperty;
+};
+
class ExtensionObject : public QObject
{
Q_OBJECT
@@ -376,6 +414,9 @@ void registerTypes()
qmlRegisterType<MyRevisionedClass,1>("Qt.test",1,1,"MyRevisionedClass");
qmlRegisterType<MyWorkerObject>("Qt.test", 1,0, "MyWorkerObject");
+ qmlRegisterExtendedUncreatableType<AbstractExtensionObject, ExtensionObject>("Qt.test", 1,0, "AbstractExtensionObject", QStringLiteral("Abstracts are uncreatable"));
+ qmlRegisterType<ImplementedExtensionObject>("Qt.test", 1,0, "ImplementedExtensionObject");
+
// test scarce resource property binding post-evaluation optimization
// and for testing memory usage in property var circular reference test
qmlRegisterType<ScarceResourceObject>("Qt.test", 1,0, "MyScarceResourceObject");
diff --git a/tests/auto/qml/qqmlecmascript/testtypes.h b/tests/auto/qml/qqmlecmascript/testtypes.h
index d5a1220f23..8f9dae4d17 100644
--- a/tests/auto/qml/qqmlecmascript/testtypes.h
+++ b/tests/auto/qml/qqmlecmascript/testtypes.h
@@ -1135,7 +1135,7 @@ class testQObjectApi : public QObject
{
Q_OBJECT
Q_ENUMS(MyEnum)
- Q_PROPERTY (int qobjectTestProperty READ qobjectTestProperty NOTIFY qobjectTestPropertyChanged)
+ Q_PROPERTY (int qobjectTestProperty READ qobjectTestProperty NOTIFY qobjectTestPropertyChanged FINAL)
Q_PROPERTY (int qobjectTestWritableProperty READ qobjectTestWritableProperty WRITE setQObjectTestWritableProperty NOTIFY qobjectTestWritablePropertyChanged)
Q_PROPERTY (int qobjectTestWritableFinalProperty READ qobjectTestWritableFinalProperty WRITE setQObjectTestWritableFinalProperty NOTIFY qobjectTestWritableFinalPropertyChanged FINAL)
diff --git a/tests/auto/qml/qqmlecmascript/tst_qqmlecmascript.cpp b/tests/auto/qml/qqmlecmascript/tst_qqmlecmascript.cpp
index 34413b23de..2550dd5473 100644
--- a/tests/auto/qml/qqmlecmascript/tst_qqmlecmascript.cpp
+++ b/tests/auto/qml/qqmlecmascript/tst_qqmlecmascript.cpp
@@ -122,6 +122,8 @@ private slots:
void selfDeletingBinding();
void extendedObjectPropertyLookup();
void extendedObjectPropertyLookup2();
+ void uncreatableExtendedObjectFailureCheck();
+ void extendedObjectPropertyLookup3();
void scriptErrors();
void functionErrors();
void propertyAssignmentErrors();
@@ -323,6 +325,7 @@ private slots:
void importedScriptsAccessOnObjectWithInvalidContext();
void contextObjectOnLazyBindings();
void garbageCollectionDuringCreation();
+ void qtbug_39520();
private:
// static void propertyVarWeakRefCallback(v8::Persistent<v8::Value> object, void* parameter);
@@ -1834,6 +1837,38 @@ void tst_qqmlecmascript::extendedObjectPropertyLookup2()
delete object;
}
+
+/*
+Test failure when trying to create and uncreatable extended type object.
+ */
+void tst_qqmlecmascript::uncreatableExtendedObjectFailureCheck()
+{
+ QQmlComponent component(&engine, testFileUrl("uncreatableExtendedObjectFailureCheck.qml"));
+
+ QObject *object = component.create();
+ QVERIFY(object == 0);
+}
+
+/*
+Test that an subclass of an uncreatable extended object contains all the required properties.
+ */
+void tst_qqmlecmascript::extendedObjectPropertyLookup3()
+{
+ QQmlComponent component(&engine, testFileUrl("extendedObjectPropertyLookup3.qml"));
+
+ QObject *object = component.create();
+ QVERIFY(object != 0);
+
+ QVariant returnValue;
+ QVERIFY(QMetaObject::invokeMethod(object, "getAbstractProperty", Q_RETURN_ARG(QVariant, returnValue)));
+ QCOMPARE(returnValue.toInt(), -1);
+ QVERIFY(QMetaObject::invokeMethod(object, "getImplementedProperty", Q_RETURN_ARG(QVariant, returnValue)));
+ QCOMPARE(returnValue.toInt(), 883);
+ QVERIFY(QMetaObject::invokeMethod(object, "getExtendedProperty", Q_RETURN_ARG(QVariant, returnValue)));
+ QCOMPARE(returnValue.toInt(), 42);
+
+ delete object;
+}
/*
Test file/lineNumbers for binding/Script errors.
*/
@@ -3925,7 +3960,7 @@ void tst_qqmlecmascript::verifyContextLifetime(QQmlContextData *ctxt) {
Q_UNUSED(temporaryScope)
}
- engine->gc();
+ ctxt->engine->collectGarbage();
qml = scripts->getIndexed(i);
newContext = QV4::QmlContextWrapper::getContext(qml);
QVERIFY(scriptContext == newContext);
@@ -4172,8 +4207,8 @@ void tst_qqmlecmascript::importScripts()
QFETCH(QStringList, propertyNames);
QFETCH(QVariantList, propertyValues);
- TestHTTPServer server(8111);
- QVERIFY(server.isValid());
+ TestHTTPServer server;
+ QVERIFY2(server.listen(8111), qPrintable(server.errorString()));
server.serveDirectory(dataDirectory() + "/remote");
QStringList importPathList = engine.importPathList();
@@ -5549,7 +5584,7 @@ void tst_qqmlecmascript::assignSequenceTypes()
MySequenceConversionObject *object = qobject_cast<MySequenceConversionObject *>(component.create());
QVERIFY(object != 0);
QCOMPARE(object->intListProperty(), (QList<int>() << 1 << 2));
- QCOMPARE(object->qrealListProperty(), (QList<qreal>() << 1.1 << 2.2));
+ QCOMPARE(object->qrealListProperty(), (QList<qreal>() << 1.1 << 2.2 << 3));
QCOMPARE(object->boolListProperty(), (QList<bool>() << false << true));
QCOMPARE(object->urlListProperty(), (QList<QUrl>() << QUrl("http://www.example1.com") << QUrl("http://www.example2.com")));
QCOMPARE(object->stringListProperty(), (QList<QString>() << QLatin1String("one") << QLatin1String("two")));
@@ -5577,7 +5612,7 @@ void tst_qqmlecmascript::assignSequenceTypes()
MySequenceConversionObject *object = qobject_cast<MySequenceConversionObject *>(component.create());
QVERIFY(object != 0);
QCOMPARE(object->intListProperty(), (QList<int>() << 1));
- QCOMPARE(object->qrealListProperty(), (QList<qreal>() << 1.1));
+ QCOMPARE(object->qrealListProperty(), (QList<qreal>() << 1));
QCOMPARE(object->boolListProperty(), (QList<bool>() << false));
QCOMPARE(object->urlListProperty(), (QList<QUrl>() << QUrl(testFileUrl("example.html"))));
delete object;
@@ -5589,7 +5624,7 @@ void tst_qqmlecmascript::assignSequenceTypes()
MySequenceConversionObject *object = qobject_cast<MySequenceConversionObject *>(component.create());
QVERIFY(object != 0);
QCOMPARE(object->intListProperty(), (QList<int>() << 1 << 2));
- QCOMPARE(object->qrealListProperty(), (QList<qreal>() << 1.1 << 2.2));
+ QCOMPARE(object->qrealListProperty(), (QList<qreal>() << 1.1 << 2.2 << 3));
QCOMPARE(object->boolListProperty(), (QList<bool>() << false << true));
QCOMPARE(object->urlListProperty(), (QList<QUrl>() << QUrl("http://www.example1.com") << QUrl("http://www.example2.com")));
QCOMPARE(object->stringListProperty(), (QList<QString>() << QLatin1String("one") << QLatin1String("two")));
@@ -5617,7 +5652,7 @@ void tst_qqmlecmascript::assignSequenceTypes()
MySequenceConversionObject *object = qobject_cast<MySequenceConversionObject *>(component.create());
QVERIFY(object != 0);
QCOMPARE(object->intListProperty(), (QList<int>() << 1));
- QCOMPARE(object->qrealListProperty(), (QList<qreal>() << 1.1));
+ QCOMPARE(object->qrealListProperty(), (QList<qreal>() << 1));
QCOMPARE(object->boolListProperty(), (QList<bool>() << false));
QCOMPARE(object->urlListProperty(), (QList<QUrl>() << QUrl(testFileUrl("example.html"))));
delete object;
@@ -6000,8 +6035,8 @@ void tst_qqmlecmascript::include()
// Remote - error
{
- TestHTTPServer server(8111);
- QVERIFY(server.isValid());
+ TestHTTPServer server;
+ QVERIFY2(server.listen(8111), qPrintable(server.errorString()));
server.serveDirectory(dataDirectory());
QQmlComponent component(&engine, testFileUrl("include_remote_missing.qml"));
@@ -6042,8 +6077,8 @@ void tst_qqmlecmascript::includeRemoteSuccess()
#endif
// Remote - success
- TestHTTPServer server(8111);
- QVERIFY(server.isValid());
+ TestHTTPServer server;
+ QVERIFY2(server.listen(8111), qPrintable(server.errorString()));
server.serveDirectory(dataDirectory());
QQmlComponent component(&engine, testFileUrl("include_remote.qml"));
@@ -7648,6 +7683,30 @@ void tst_qqmlecmascript::garbageCollectionDuringCreation()
QCOMPARE(container->dataChildren.count(), 0);
}
+void tst_qqmlecmascript::qtbug_39520()
+{
+ QQmlComponent component(&engine);
+ component.setData("import QtQuick 2.0\n"
+ "Item {\n"
+ " property string s\n"
+ " Component.onCompleted: test()\n"
+ " function test() {\n"
+ " var count = 1 * 1000 * 1000\n"
+ " var t = ''\n"
+ " for (var i = 0; i < count; ++i)\n"
+ " t += 'testtest ' + i + '\n'\n"
+ " s = t\n"
+ " }\n"
+ "}\n",
+ QUrl());
+
+ QScopedPointer<QObject> object(component.create());
+ QVERIFY(!object.isNull());
+
+ QString s = object->property("s").toString();
+ QCOMPARE(s.count('\n'), 1 * 1000 * 1000);
+}
+
QTEST_MAIN(tst_qqmlecmascript)
#include "tst_qqmlecmascript.moc"
diff --git a/tests/auto/qml/qqmlengine/tst_qqmlengine.cpp b/tests/auto/qml/qqmlengine/tst_qqmlengine.cpp
index 004514d39c..23c50f940b 100644
--- a/tests/auto/qml/qqmlengine/tst_qqmlengine.cpp
+++ b/tests/auto/qml/qqmlengine/tst_qqmlengine.cpp
@@ -488,7 +488,7 @@ void tst_qqmlengine::outputWarningsToStandardError()
delete o;
QCOMPARE(messageHandler.messages().count(), 1);
- QCOMPARE(messageHandler.messages().at(0), QLatin1String("<Unknown File>: Unable to assign [undefined] to int"));
+ QCOMPARE(messageHandler.messages().at(0), QLatin1String("<Unknown File>:1:48: Unable to assign [undefined] to int"));
messageHandler.clear();
engine.setOutputWarningsToStandardError(false);
diff --git a/tests/auto/qml/qqmllanguage/data/customExtendedParserProperties.qml b/tests/auto/qml/qqmllanguage/data/customExtendedParserProperties.qml
new file mode 100644
index 0000000000..e53a7c6bd5
--- /dev/null
+++ b/tests/auto/qml/qqmllanguage/data/customExtendedParserProperties.qml
@@ -0,0 +1,12 @@
+import Test 1.0
+import QtQml 2.0
+SimpleExtendedObjectWithCustomParser {
+ id : obj
+ intProperty: 42
+ property string qmlString: "Hello"
+ property var someObject: QtObject {}
+
+ property int c : obj.extendedProperty
+
+ function getExtendedProperty() { return c; }
+}
diff --git a/tests/auto/qml/qqmllanguage/testtypes.cpp b/tests/auto/qml/qqmllanguage/testtypes.cpp
index 8ffa327cf2..b37c6836eb 100644
--- a/tests/auto/qml/qqmllanguage/testtypes.cpp
+++ b/tests/auto/qml/qqmllanguage/testtypes.cpp
@@ -40,6 +40,8 @@
****************************************************************************/
#include "testtypes.h"
+#include <private/qqmlcompiler_p.h>
+
void registerTypes()
{
qmlRegisterInterface<MyInterface>("MyInterface");
@@ -94,6 +96,8 @@ void registerTypes()
qmlRegisterCustomType<CustomBinding>("Test", 1, 0, "CustomBinding", new CustomBindingParser);
qmlRegisterCustomType<SimpleObjectWithCustomParser>("Test", 1, 0, "SimpleObjectWithCustomParser", new SimpleObjectCustomParser);
+ qmlRegisterCustomExtendedType<SimpleObjectWithCustomParser, SimpleObjectExtension>("Test", 1, 0, "SimpleExtendedObjectWithCustomParser", new SimpleObjectCustomParser);
+
qmlRegisterType<RootObjectInCreationTester>("Test", 1, 0, "RootObjectInCreationTester");
}
@@ -105,105 +109,70 @@ QVariant myCustomVariantTypeConverter(const QString &data)
}
-QByteArray CustomBindingParser::compile(const QV4::CompiledData::QmlUnit *qmlUnit, const QList<const QV4::CompiledData::Binding *> &bindings)
-{
- QByteArray result;
- QDataStream ds(&result, QIODevice::WriteOnly);
-
- ds << bindings.count();
- for (int i = 0; i < bindings.count(); ++i) {
- const QV4::CompiledData::Binding *binding = bindings.at(i);
- ds << qmlUnit->header.stringAt(binding->propertyNameIndex);
-
- Q_ASSERT(binding->type == QV4::CompiledData::Binding::Type_Script);
- int bindingId = bindingIdentifier(binding);
- ds << bindingId;
-
- ds << binding->location.line;
- }
-
- return result;
-}
-
-void CustomBindingParser::setCustomData(QObject *object, const QByteArray &data, QQmlCompiledData*)
+void CustomBindingParser::applyBindings(QObject *object, QQmlCompiledData *cdata, const QList<const QV4::CompiledData::Binding *> &bindings)
{
CustomBinding *customBinding = qobject_cast<CustomBinding*>(object);
Q_ASSERT(customBinding);
- customBinding->m_bindingData = data;
+ customBinding->cdata = cdata;
+ customBinding->bindings = bindings;
}
void CustomBinding::componentComplete()
{
Q_ASSERT(m_target);
- QDataStream ds(m_bindingData);
- int count;
- ds >> count;
- for (int i = 0; i < count; ++i) {
- QString name;
- ds >> name;
+ foreach (const QV4::CompiledData::Binding *binding, bindings) {
+ QString name = cdata->compilationUnit->data->stringAt(binding->propertyNameIndex);
- int bindingId;
- ds >> bindingId;
+ int bindingId = binding->value.compiledScriptIndex;
- int line;
- ds >> line;
+ QQmlContextData *context = QQmlContextData::get(qmlContext(this));
- QQmlBinding *binding = QQmlBinding::createBinding(QQmlBinding::Identifier(bindingId), m_target, qmlContext(this));
+ QV4::Scope scope(QQmlEnginePrivate::getV4Engine(qmlEngine(this)));
+ QV4::ScopedValue function(scope, QV4::QmlBindingWrapper::createQmlCallableForFunction(context, m_target, cdata->compilationUnit->runtimeFunctions[bindingId]));
+ QQmlBinding *qmlBinding = new QQmlBinding(function, m_target, context);
QQmlProperty property(m_target, name, qmlContext(this));
- binding->setTarget(property);
- QQmlPropertyPrivate::setBinding(property, binding);
+ qmlBinding->setTarget(property);
+ QQmlPropertyPrivate::setBinding(property, qmlBinding);
}
}
-QByteArray EnumSupportingCustomParser::compile(const QV4::CompiledData::QmlUnit *qmlUnit, const QList<const QV4::CompiledData::Binding *> &bindings)
+void EnumSupportingCustomParser::verifyBindings(const QV4::CompiledData::QmlUnit *qmlUnit, const QList<const QV4::CompiledData::Binding *> &bindings)
{
- Q_UNUSED(qmlUnit)
-
if (bindings.count() != 1) {
error(bindings.first(), QStringLiteral("Custom parser invoked incorrectly for unit test"));
- return QByteArray();
+ return;
}
const QV4::CompiledData::Binding *binding = bindings.first();
if (qmlUnit->header.stringAt(binding->propertyNameIndex) != QStringLiteral("foo")) {
error(binding, QStringLiteral("Custom parser invoked with the wrong property name"));
- return QByteArray();
+ return;
}
if (binding->type != QV4::CompiledData::Binding::Type_Script) {
error(binding, QStringLiteral("Custom parser invoked with the wrong property value. Expected script that evaluates to enum"));
- return QByteArray();
+ return;
}
QByteArray script = qmlUnit->header.stringAt(binding->stringIndex).toUtf8();
bool ok;
int v = evaluateEnum(script, &ok);
if (!ok) {
error(binding, QStringLiteral("Custom parser invoked with the wrong property value. Script did not evaluate to enum"));
- return QByteArray();
+ return;
}
if (v != MyEnum1Class::A_13) {
error(binding, QStringLiteral("Custom parser invoked with the wrong property value. Enum value is not the expected value."));
- return QByteArray();
+ return;
}
-
- 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*)
+void SimpleObjectCustomParser::applyBindings(QObject *object, QQmlCompiledData *, const QList<const QV4::CompiledData::Binding *> &bindings)
{
- SimpleObjectWithCustomParser *o = qobject_cast<SimpleObjectWithCustomParser*>(object);
- Q_ASSERT(o);
- bool ok = false;
- o->setCustomBindingsCount(data.toInt(&ok));
- Q_ASSERT(ok);
+ SimpleObjectWithCustomParser *o = qobject_cast<SimpleObjectWithCustomParser*>(object);
+ Q_ASSERT(o);
+ o->setCustomBindingsCount(bindings.count());
}
diff --git a/tests/auto/qml/qqmllanguage/testtypes.h b/tests/auto/qml/qqmllanguage/testtypes.h
index 1c13a2e21c..bb1e9c158d 100644
--- a/tests/auto/qml/qqmllanguage/testtypes.h
+++ b/tests/auto/qml/qqmllanguage/testtypes.h
@@ -54,7 +54,7 @@
#include <QtQml/qqmlpropertyvaluesource.h>
#include <QtQml/qqmlscriptstring.h>
#include <QtQml/qqmlproperty.h>
-
+#include <private/qqmlcompiler_p.h>
#include <private/qqmlcustomparser_p.h>
QVariant myCustomVariantTypeConverter(const QString &data);
@@ -739,15 +739,15 @@ class MyCustomParserType : public QObject
class MyCustomParserTypeParser : public QQmlCustomParser
{
public:
- QByteArray compile(const QV4::CompiledData::QmlUnit *, const QList<const QV4::CompiledData::Binding *> &) { return QByteArray(); }
- void setCustomData(QObject *, const QByteArray &, QQmlCompiledData*) {}
+ virtual void verifyBindings(const QV4::CompiledData::QmlUnit *, const QList<const QV4::CompiledData::Binding *> &) {}
+ virtual void applyBindings(QObject *, QQmlCompiledData *, const QList<const QV4::CompiledData::Binding *> &) {}
};
class EnumSupportingCustomParser : public QQmlCustomParser
{
public:
- QByteArray compile(const QV4::CompiledData::QmlUnit *qmlUnit, const QList<const QV4::CompiledData::Binding *> &bindings);
- void setCustomData(QObject *, const QByteArray &, QQmlCompiledData*) {}
+ virtual void verifyBindings(const QV4::CompiledData::QmlUnit *, const QList<const QV4::CompiledData::Binding *> &);
+ virtual void applyBindings(QObject *, QQmlCompiledData *, const QList<const QV4::CompiledData::Binding *> &) {}
};
class MyParserStatus : public QObject, public QQmlParserStatus
@@ -1112,13 +1112,15 @@ public:
void setTarget(QObject *newTarget) { m_target = newTarget; }
QPointer<QObject> m_target;
+ QQmlRefPointer<QQmlCompiledData> cdata;
+ QList<const QV4::CompiledData::Binding*> bindings;
QByteArray m_bindingData;
};
class CustomBindingParser : public QQmlCustomParser
{
- virtual QByteArray compile(const QV4::CompiledData::QmlUnit *qmlUnit, const QList<const QV4::CompiledData::Binding *> &bindings);
- virtual void setCustomData(QObject *object, const QByteArray &data, QQmlCompiledData *);
+ virtual void verifyBindings(const QV4::CompiledData::QmlUnit *, const QList<const QV4::CompiledData::Binding *> &) {}
+ virtual void applyBindings(QObject *, QQmlCompiledData *, const QList<const QV4::CompiledData::Binding *> &);
};
class SimpleObjectWithCustomParser : public QObject
@@ -1142,10 +1144,29 @@ private:
int m_customBindingsCount;
};
+class SimpleObjectExtension : public QObject
+{
+ Q_OBJECT
+ Q_PROPERTY(int extendedProperty READ extendedProperty WRITE setExtendedProperty NOTIFY extendedPropertyChanged)
+public:
+ SimpleObjectExtension(QObject *parent = 0)
+ : QObject(parent)
+ , m_extendedProperty(1584)
+ {}
+
+ void setExtendedProperty(int extendedProperty) { m_extendedProperty = extendedProperty; emit extendedPropertyChanged(); }
+ int extendedProperty() const { return m_extendedProperty; }
+
+signals:
+ void extendedPropertyChanged();
+private:
+ int m_extendedProperty;
+};
+
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 *);
+ virtual void verifyBindings(const QV4::CompiledData::QmlUnit *, const QList<const QV4::CompiledData::Binding *> &) {}
+ virtual void applyBindings(QObject *, QQmlCompiledData *, const QList<const QV4::CompiledData::Binding *> &);
};
class RootObjectInCreationTester : public QObject
diff --git a/tests/auto/qml/qqmllanguage/tst_qqmllanguage.cpp b/tests/auto/qml/qqmllanguage/tst_qqmllanguage.cpp
index 7976987b58..8bc937d2bc 100644
--- a/tests/auto/qml/qqmllanguage/tst_qqmllanguage.cpp
+++ b/tests/auto/qml/qqmllanguage/tst_qqmllanguage.cpp
@@ -232,6 +232,7 @@ private slots:
void customParserBindingScopes();
void customParserEvaluateEnum();
void customParserProperties();
+ void customParserWithExtendedObject();
void preservePropertyCacheOnGroupObjects();
void propertyCacheInSync();
@@ -2359,7 +2360,8 @@ void tst_qqmllanguage::basicRemote()
QFETCH(QString, type);
QFETCH(QString, error);
- TestHTTPServer server(14447);
+ TestHTTPServer server;
+ QVERIFY2(server.listen(14447), qPrintable(server.errorString()));
server.serveDirectory(dataDirectory());
QQmlComponent component(&engine, url);
@@ -2403,7 +2405,8 @@ void tst_qqmllanguage::importsRemote()
QFETCH(QString, type);
QFETCH(QString, error);
- TestHTTPServer server(14447);
+ TestHTTPServer server;
+ QVERIFY2(server.listen(14447), qPrintable(server.errorString()));
server.serveDirectory(dataDirectory());
testType(qml,type,error);
@@ -2495,7 +2498,8 @@ void tst_qqmllanguage::importsInstalledRemote()
QFETCH(QString, type);
QFETCH(QString, error);
- TestHTTPServer server(14447);
+ TestHTTPServer server;
+ QVERIFY2(server.listen(14447), qPrintable(server.errorString()));
server.serveDirectory(dataDirectory());
QString serverdir = "http://127.0.0.1:14447/lib/";
@@ -2561,7 +2565,8 @@ void tst_qqmllanguage::importsPath()
QFETCH(QString, qml);
QFETCH(QString, value);
- TestHTTPServer server(14447);
+ TestHTTPServer server;
+ QVERIFY2(server.listen(14447), qPrintable(server.errorString()));
server.serveDirectory(dataDirectory());
engine.setImportPathList(QStringList(defaultImportPathList) << importPath);
@@ -3137,7 +3142,8 @@ void tst_qqmllanguage::registeredCompositeType()
// QTBUG-18268
void tst_qqmllanguage::remoteLoadCrash()
{
- TestHTTPServer server(14448);
+ TestHTTPServer server;
+ QVERIFY2(server.listen(14448), qPrintable(server.errorString()));
server.serveDirectory(dataDirectory());
QQmlComponent component(&engine);
@@ -3627,7 +3633,8 @@ void tst_qqmllanguage::compositeSingletonQmlDirError()
// Load a remote composite singleton type via qmldir that defines the type as a singleton
void tst_qqmllanguage::compositeSingletonRemote()
{
- TestHTTPServer server(14447);
+ TestHTTPServer server;
+ QVERIFY2(server.listen(14447), qPrintable(server.errorString()));
server.serveDirectory(dataDirectory());
QQmlComponent component(&engine, testFile("singletonTest15.qml"));
@@ -3718,6 +3725,24 @@ void tst_qqmllanguage::customParserProperties()
QVERIFY(!testObject->property("someObject").isNull());
}
+void tst_qqmllanguage::customParserWithExtendedObject()
+{
+ QQmlComponent component(&engine, testFile("customExtendedParserProperties.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());
+
+ QVariant returnValue;
+ QVERIFY(QMetaObject::invokeMethod(o.data(), "getExtendedProperty", Q_RETURN_ARG(QVariant, returnValue)));
+ QCOMPARE(returnValue.toInt(), 1584);
+}
+
void tst_qqmllanguage::preservePropertyCacheOnGroupObjects()
{
QQmlComponent component(&engine, testFile("preservePropertyCacheOnGroupObjects.qml"));
diff --git a/tests/auto/qml/qqmllistmodel/tst_qqmllistmodel.cpp b/tests/auto/qml/qqmllistmodel/tst_qqmllistmodel.cpp
index b37f0e3d26..ede80b355a 100644
--- a/tests/auto/qml/qqmllistmodel/tst_qqmllistmodel.cpp
+++ b/tests/auto/qml/qqmllistmodel/tst_qqmllistmodel.cpp
@@ -353,12 +353,12 @@ void tst_qqmllistmodel::dynamic_i18n_data()
QTest::newRow("qsTr")
<< QString::fromUtf8("ListElement { foo: qsTr(\"test\") }")
<< QVariant(QString::fromUtf8("test"))
- << QString("ListElement: cannot use script for property value");
+ << QString();
QTest::newRow("qsTrId")
<< "ListElement { foo: qsTrId(\"qtn_test\") }"
<< QVariant(QString("qtn_test"))
- << QString("ListElement: cannot use script for property value");
+ << QString();
}
void tst_qqmllistmodel::dynamic_i18n()
diff --git a/tests/auto/qml/qqmlmoduleplugin/tst_qqmlmoduleplugin.cpp b/tests/auto/qml/qqmlmoduleplugin/tst_qqmlmoduleplugin.cpp
index 15be1fdbc0..1861b37bea 100644
--- a/tests/auto/qml/qqmlmoduleplugin/tst_qqmlmoduleplugin.cpp
+++ b/tests/auto/qml/qqmlmoduleplugin/tst_qqmlmoduleplugin.cpp
@@ -247,8 +247,8 @@ void tst_qqmlmoduleplugin::importPluginWithQmlFile()
void tst_qqmlmoduleplugin::remoteImportWithQuotedUrl()
{
- TestHTTPServer server(SERVER_PORT);
- QVERIFY(server.isValid());
+ TestHTTPServer server;
+ QVERIFY2(server.listen(SERVER_PORT), qPrintable(server.errorString()));
server.serveDirectory(m_dataImportsDirectory);
QQmlEngine engine;
@@ -268,8 +268,8 @@ void tst_qqmlmoduleplugin::remoteImportWithQuotedUrl()
void tst_qqmlmoduleplugin::remoteImportWithUnquotedUri()
{
- TestHTTPServer server(SERVER_PORT);
- QVERIFY(server.isValid());
+ TestHTTPServer server;
+ QVERIFY2(server.listen(SERVER_PORT), qPrintable(server.errorString()));
server.serveDirectory(m_dataImportsDirectory);
QQmlEngine engine;
diff --git a/tests/auto/qml/qqmlproperty/tst_qqmlproperty.cpp b/tests/auto/qml/qqmlproperty/tst_qqmlproperty.cpp
index 27c3fd985e..fc4f7edcb8 100644
--- a/tests/auto/qml/qqmlproperty/tst_qqmlproperty.cpp
+++ b/tests/auto/qml/qqmlproperty/tst_qqmlproperty.cpp
@@ -46,7 +46,6 @@
#include <QtQml/private/qqmlproperty_p.h>
#include <private/qqmlbinding_p.h>
#include <private/qqmlboundsignal_p.h>
-#include <QtWidgets/QLineEdit>
#include <QtCore/qfileinfo.h>
#include <QtCore/qdir.h>
#include <QtCore/private/qobject_p.h>
diff --git a/tests/auto/qml/qqmlpropertymap/tst_qqmlpropertymap.cpp b/tests/auto/qml/qqmlpropertymap/tst_qqmlpropertymap.cpp
index b8c2ce4460..c0d66785bb 100644
--- a/tests/auto/qml/qqmlpropertymap/tst_qqmlpropertymap.cpp
+++ b/tests/auto/qml/qqmlpropertymap/tst_qqmlpropertymap.cpp
@@ -451,7 +451,7 @@ void tst_QQmlPropertyMap::disallowExtending()
obj.reset(component.create());
QVERIFY(obj.isNull());
QCOMPARE(component.errors().count(), 1);
- QCOMPARE(component.errors().at(0).toString(), QStringLiteral("<Unknown File>: Fully dynamic types cannot declare new properties."));
+ QCOMPARE(component.errors().at(0).toString(), QStringLiteral("<Unknown File>:3:1: Fully dynamic types cannot declare new properties."));
}
void tst_QQmlPropertyMap::QTBUG_35906()
diff --git a/tests/auto/qml/qqmlxmlhttprequest/tst_qqmlxmlhttprequest.cpp b/tests/auto/qml/qqmlxmlhttprequest/tst_qqmlxmlhttprequest.cpp
index 17becb3714..e1ccde2c42 100644
--- a/tests/auto/qml/qqmlxmlhttprequest/tst_qqmlxmlhttprequest.cpp
+++ b/tests/auto/qml/qqmlxmlhttprequest/tst_qqmlxmlhttprequest.cpp
@@ -240,13 +240,12 @@ void tst_qqmlxmlhttprequest::open()
QFETCH(QString, url);
QFETCH(bool, remote);
- QScopedPointer<TestHTTPServer> server; // ensure deletion in case test fails
+ TestHTTPServer server;
if (remote) {
- server.reset(new TestHTTPServer(SERVER_PORT));
- QVERIFY(server->isValid());
- QVERIFY(server->wait(testFileUrl("open_network.expect"),
- testFileUrl("open_network.reply"),
- testFileUrl("testdocument.html")));
+ QVERIFY2(server.listen(SERVER_PORT), qPrintable(server.errorString()));
+ QVERIFY(server.wait(testFileUrl("open_network.expect"),
+ testFileUrl("open_network.reply"),
+ testFileUrl("testdocument.html")));
}
QQmlComponent component(&engine, qmlFile);
@@ -322,8 +321,8 @@ void tst_qqmlxmlhttprequest::open_arg_count()
// Test valid setRequestHeader() calls
void tst_qqmlxmlhttprequest::setRequestHeader()
{
- TestHTTPServer server(SERVER_PORT);
- QVERIFY(server.isValid());
+ TestHTTPServer server;
+ QVERIFY2(server.listen(SERVER_PORT), qPrintable(server.errorString()));
QVERIFY(server.wait(testFileUrl("setRequestHeader.expect"),
testFileUrl("setRequestHeader.reply"),
testFileUrl("testdocument.html")));
@@ -340,8 +339,8 @@ void tst_qqmlxmlhttprequest::setRequestHeader()
// Test valid setRequestHeader() calls with different header cases
void tst_qqmlxmlhttprequest::setRequestHeader_caseInsensitive()
{
- TestHTTPServer server(SERVER_PORT);
- QVERIFY(server.isValid());
+ TestHTTPServer server;
+ QVERIFY2(server.listen(SERVER_PORT), qPrintable(server.errorString()));
QVERIFY(server.wait(testFileUrl("setRequestHeader.expect"),
testFileUrl("setRequestHeader.reply"),
testFileUrl("testdocument.html")));
@@ -397,8 +396,8 @@ void tst_qqmlxmlhttprequest::setRequestHeader_illegalName()
{
QFETCH(QString, name);
- TestHTTPServer server(SERVER_PORT);
- QVERIFY(server.isValid());
+ TestHTTPServer server;
+ QVERIFY2(server.listen(SERVER_PORT), qPrintable(server.errorString()));
QVERIFY(server.wait(testFileUrl("open_network.expect"),
testFileUrl("open_network.reply"),
testFileUrl("testdocument.html")));
@@ -423,8 +422,8 @@ void tst_qqmlxmlhttprequest::setRequestHeader_illegalName()
// Test that attempting to set a header after a request is sent throws an exception
void tst_qqmlxmlhttprequest::setRequestHeader_sent()
{
- TestHTTPServer server(SERVER_PORT);
- QVERIFY(server.isValid());
+ TestHTTPServer server;
+ QVERIFY2(server.listen(SERVER_PORT), qPrintable(server.errorString()));
QVERIFY(server.wait(testFileUrl("open_network.expect"),
testFileUrl("open_network.reply"),
testFileUrl("testdocument.html")));
@@ -475,8 +474,8 @@ void tst_qqmlxmlhttprequest::send_alreadySent()
void tst_qqmlxmlhttprequest::send_ignoreData()
{
{
- TestHTTPServer server(SERVER_PORT);
- QVERIFY(server.isValid());
+ TestHTTPServer server;
+ QVERIFY2(server.listen(SERVER_PORT), qPrintable(server.errorString()));
QVERIFY(server.wait(testFileUrl("send_ignoreData_GET.expect"),
testFileUrl("send_ignoreData.reply"),
testFileUrl("testdocument.html")));
@@ -492,8 +491,8 @@ void tst_qqmlxmlhttprequest::send_ignoreData()
}
{
- TestHTTPServer server(SERVER_PORT);
- QVERIFY(server.isValid());
+ TestHTTPServer server;
+ QVERIFY2(server.listen(SERVER_PORT), qPrintable(server.errorString()));
QVERIFY(server.wait(testFileUrl("send_ignoreData_HEAD.expect"),
testFileUrl("send_ignoreData.reply"),
QUrl()));
@@ -509,8 +508,8 @@ void tst_qqmlxmlhttprequest::send_ignoreData()
}
{
- TestHTTPServer server(SERVER_PORT);
- QVERIFY(server.isValid());
+ TestHTTPServer server;
+ QVERIFY2(server.listen(SERVER_PORT), qPrintable(server.errorString()));
QVERIFY(server.wait(testFileUrl("send_ignoreData_DELETE.expect"),
testFileUrl("send_ignoreData.reply"),
QUrl()));
@@ -532,8 +531,8 @@ void tst_qqmlxmlhttprequest::send_withdata()
QFETCH(QString, file_expected);
QFETCH(QString, file_qml);
- TestHTTPServer server(SERVER_PORT);
- QVERIFY(server.isValid());
+ TestHTTPServer server;
+ QVERIFY2(server.listen(SERVER_PORT), qPrintable(server.errorString()));
QVERIFY(server.wait(testFileUrl(file_expected),
testFileUrl("send_data.reply"),
testFileUrl("testdocument.html")));
@@ -602,8 +601,8 @@ void tst_qqmlxmlhttprequest::abort_opened()
// Test abort() aborts in progress send
void tst_qqmlxmlhttprequest::abort()
{
- TestHTTPServer server(SERVER_PORT);
- QVERIFY(server.isValid());
+ TestHTTPServer server;
+ QVERIFY2(server.listen(SERVER_PORT), qPrintable(server.errorString()));
QVERIFY(server.wait(testFileUrl("abort.expect"),
testFileUrl("abort.reply"),
testFileUrl("testdocument.html")));
@@ -626,8 +625,8 @@ void tst_qqmlxmlhttprequest::getResponseHeader()
{
QQmlEngine engine; // Avoid cookie contamination
- TestHTTPServer server(SERVER_PORT);
- QVERIFY(server.isValid());
+ TestHTTPServer server;
+ QVERIFY2(server.listen(SERVER_PORT), qPrintable(server.errorString()));
QVERIFY(server.wait(testFileUrl("getResponseHeader.expect"),
testFileUrl("getResponseHeader.reply"),
testFileUrl("testdocument.html")));
@@ -693,8 +692,8 @@ void tst_qqmlxmlhttprequest::getAllResponseHeaders()
{
QQmlEngine engine; // Avoid cookie contamination
- TestHTTPServer server(SERVER_PORT);
- QVERIFY(server.isValid());
+ TestHTTPServer server;
+ QVERIFY2(server.listen(SERVER_PORT), qPrintable(server.errorString()));
QVERIFY(server.wait(testFileUrl("getResponseHeader.expect"),
testFileUrl("getResponseHeader.reply"),
testFileUrl("testdocument.html")));
@@ -754,8 +753,8 @@ void tst_qqmlxmlhttprequest::status()
QFETCH(QUrl, replyUrl);
QFETCH(int, status);
- TestHTTPServer server(SERVER_PORT);
- QVERIFY(server.isValid());
+ TestHTTPServer server;
+ QVERIFY2(server.listen(SERVER_PORT), qPrintable(server.errorString()));
QVERIFY(server.wait(testFileUrl("status.expect"),
replyUrl,
testFileUrl("testdocument.html")));
@@ -793,8 +792,8 @@ void tst_qqmlxmlhttprequest::statusText()
QFETCH(QUrl, replyUrl);
QFETCH(QString, statusText);
- TestHTTPServer server(SERVER_PORT);
- QVERIFY(server.isValid());
+ TestHTTPServer server;
+ QVERIFY2(server.listen(SERVER_PORT), qPrintable(server.errorString()));
QVERIFY(server.wait(testFileUrl("status.expect"),
replyUrl,
testFileUrl("testdocument.html")));
@@ -833,8 +832,8 @@ void tst_qqmlxmlhttprequest::responseText()
QFETCH(QUrl, bodyUrl);
QFETCH(QString, responseText);
- TestHTTPServer server(SERVER_PORT);
- QVERIFY(server.isValid());
+ TestHTTPServer server;
+ QVERIFY2(server.listen(SERVER_PORT), qPrintable(server.errorString()));
QVERIFY(server.wait(testFileUrl("status.expect"),
replyUrl,
bodyUrl));
@@ -934,8 +933,8 @@ void tst_qqmlxmlhttprequest::invalidMethodUsage()
void tst_qqmlxmlhttprequest::redirects()
{
{
- TestHTTPServer server(SERVER_PORT);
- QVERIFY(server.isValid());
+ TestHTTPServer server;
+ QVERIFY2(server.listen(SERVER_PORT), qPrintable(server.errorString()));
server.addRedirect("redirect.html", "http://127.0.0.1:14445/redirecttarget.html");
server.serveDirectory(dataDirectory());
@@ -951,8 +950,8 @@ void tst_qqmlxmlhttprequest::redirects()
}
{
- TestHTTPServer server(SERVER_PORT);
- QVERIFY(server.isValid());
+ TestHTTPServer server;
+ QVERIFY2(server.listen(SERVER_PORT), qPrintable(server.errorString()));
server.addRedirect("redirect.html", "http://127.0.0.1:14445/redirectmissing.html");
server.serveDirectory(dataDirectory());
@@ -968,8 +967,8 @@ void tst_qqmlxmlhttprequest::redirects()
}
{
- TestHTTPServer server(SERVER_PORT);
- QVERIFY(server.isValid());
+ TestHTTPServer server;
+ QVERIFY2(server.listen(SERVER_PORT), qPrintable(server.errorString()));
server.addRedirect("redirect.html", "http://127.0.0.1:14445/redirect.html");
server.serveDirectory(dataDirectory());
@@ -1070,8 +1069,8 @@ void tst_qqmlxmlhttprequest::stateChangeCallingContext()
// ensure that we don't crash by attempting to evaluate
// without a valid calling context.
- TestHTTPServer server(SERVER_PORT);
- QVERIFY(server.isValid());
+ TestHTTPServer server;
+ QVERIFY2(server.listen(SERVER_PORT), qPrintable(server.errorString()));
server.serveDirectory(dataDirectory(), TestHTTPServer::Delay);
QQmlComponent component(&engine, testFileUrl("stateChangeCallingContext.qml"));
diff --git a/tests/auto/qml/qv4debugger/tst_qv4debugger.cpp b/tests/auto/qml/qv4debugger/tst_qv4debugger.cpp
index b7e5cf48e0..45652d7191 100644
--- a/tests/auto/qml/qv4debugger/tst_qv4debugger.cpp
+++ b/tests/auto/qml/qv4debugger/tst_qv4debugger.cpp
@@ -89,7 +89,7 @@ public:
QV4::Scope scope(v4);
QV4::Scoped<QV4::String> name(scope, v4->newString(functionName));
- QV4::ScopedValue function(scope, v4->newBuiltinFunction(v4->rootContext, name, injectedFunction));
+ QV4::ScopedValue function(scope, BuiltinFunction::create(v4->rootContext, name, injectedFunction));
v4->globalObject->put(name, function);
}
@@ -266,6 +266,7 @@ private slots:
void removePendingBreakPoint();
void addBreakPointWhilePaused();
void removeBreakPointForNextInstruction();
+ void conditionalBreakPoint();
// context access:
void readArguments();
@@ -393,7 +394,7 @@ void tst_qv4debugger::addBreakPointWhilePaused()
static QV4::ReturnedValue someCall(QV4::CallContext *ctx)
{
- ctx->engine->debugger->removeBreakPoint("removeBreakPointForNextInstruction", 2);
+ ctx->d()->engine->debugger->removeBreakPoint("removeBreakPointForNextInstruction", 2);
return QV4::Encode::undefined();
}
@@ -412,6 +413,29 @@ void tst_qv4debugger::removeBreakPointForNextInstruction()
QVERIFY(!m_debuggerAgent->m_wasPaused);
}
+void tst_qv4debugger::conditionalBreakPoint()
+{
+ m_debuggerAgent->m_captureContextInfo = true;
+ QString script =
+ "function test() {\n"
+ " for (var i = 0; i < 15; ++i) {\n"
+ " var x = i;\n"
+ " }\n"
+ "}\n"
+ "test()\n";
+
+ m_debuggerAgent->addBreakPoint("conditionalBreakPoint", 3, /*enabled*/true, QStringLiteral("i > 10"));
+ evaluateJavaScript(script, "conditionalBreakPoint");
+ QVERIFY(m_debuggerAgent->m_wasPaused);
+ QCOMPARE(m_debuggerAgent->m_statesWhenPaused.count(), 4);
+ QV4::Debugging::Debugger::ExecutionState state = m_debuggerAgent->m_statesWhenPaused.first();
+ QCOMPARE(state.fileName, QString("conditionalBreakPoint"));
+ QCOMPARE(state.lineNumber, 3);
+ QCOMPARE(m_debuggerAgent->m_capturedLocals[0].size(), 2);
+ QVERIFY(m_debuggerAgent->m_capturedLocals[0].contains(QStringLiteral("i")));
+ QCOMPARE(m_debuggerAgent->m_capturedLocals[0]["i"].toInt(), 11);
+}
+
void tst_qv4debugger::readArguments()
{
m_debuggerAgent->m_captureContextInfo = true;
diff --git a/tests/auto/qml/v4misc/tst_v4misc.cpp b/tests/auto/qml/v4misc/tst_v4misc.cpp
index 79ccdc9a4b..17f2fed3f9 100644
--- a/tests/auto/qml/v4misc/tst_v4misc.cpp
+++ b/tests/auto/qml/v4misc/tst_v4misc.cpp
@@ -139,7 +139,7 @@ void tst_v4misc::rangeSplitting_3()
interval.validate();
QCOMPARE(interval.end(), 71);
- LifeTimeInterval newInterval = interval.split(64, LifeTimeInterval::Invalid);
+ LifeTimeInterval newInterval = interval.split(64, LifeTimeInterval::InvalidPosition);
interval.validate();
newInterval.validate();
QVERIFY(!newInterval.isValid());
diff --git a/tests/auto/qmltest/item/tst_layerInPositioner.qml b/tests/auto/qmltest/item/tst_layerInPositioner.qml
new file mode 100644
index 0000000000..9144fe1d8f
--- /dev/null
+++ b/tests/auto/qmltest/item/tst_layerInPositioner.qml
@@ -0,0 +1,207 @@
+/****************************************************************************
+**
+** 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.4
+import QtTest 1.0
+
+Item {
+ id: root;
+ width: 400
+ height: 400
+
+ TestCase {
+ id: testCase
+ name: "transparentForPositioner"
+ when: windowShown
+ function test_endresult() {
+ var image = grabImage(root);
+
+ // Row of red, green, blue and white box inside blue
+ // At 10,10, spanning 10x10 pixels each
+ verify(image.pixel(10, 10) == Qt.rgba(1, 0, 0, 1));
+ verify(image.pixel(20, 10) == Qt.rgba(0, 1, 0, 1));
+ verify(image.pixel(30, 10) == Qt.rgba(0, 0, 1, 1));
+
+ // Column of red, green, blue and white box inside blue
+ // At 10,30, spanning 10x10 pixels each
+ verify(image.pixel(10, 30) == Qt.rgba(1, 0, 0, 1));
+ verify(image.pixel(10, 40) == Qt.rgba(0, 1, 0, 1));
+ verify(image.pixel(10, 50) == Qt.rgba(0, 0, 1, 1));
+
+ // Flow of red, green, blue and white box inside blue
+ // At 30,30, spanning 10x10 pixels each, wrapping after two boxes
+ verify(image.pixel(30, 30) == Qt.rgba(1, 0, 0, 1));
+ verify(image.pixel(40, 30) == Qt.rgba(0, 1, 0, 1));
+ verify(image.pixel(30, 40) == Qt.rgba(0, 0, 1, 1));
+
+ // Flow of red, green, blue and white box inside blue
+ // At 100,10, spanning 10x10 pixels each, wrapping after two boxes
+ verify(image.pixel(60, 10) == Qt.rgba(1, 0, 0, 1));
+ verify(image.pixel(70, 10) == Qt.rgba(0, 1, 0, 1));
+ verify(image.pixel(60, 20) == Qt.rgba(0, 0, 1, 1));
+ }
+ }
+
+ Component {
+ id: greenPassThrough
+ ShaderEffect {
+ fragmentShader:
+ "
+ uniform lowp sampler2D source;
+ varying highp vec2 qt_TexCoord0;
+ void main() {
+ gl_FragColor = texture2D(source, qt_TexCoord0) * vec4(0, 1, 0, 1);
+ }
+ "
+ }
+ }
+
+ Row {
+ id: theRow
+ x: 10
+ y: 10
+ Rectangle {
+ width: 10
+ height: 10
+ color: "#ff0000"
+ layer.enabled: true
+ }
+
+ Rectangle {
+ width: 10
+ height: 10
+ color: "#ffffff"
+ layer.enabled: true
+ layer.effect: greenPassThrough
+ }
+
+ Rectangle {
+ id: blueInRow
+ width: 10
+ height: 10
+ color: "#0000ff"
+ }
+ }
+
+ Column {
+ id: theColumn
+ x: 10
+ y: 30
+ Rectangle {
+ width: 10
+ height: 10
+ color: "#ff0000"
+ layer.enabled: true
+ }
+
+ Rectangle {
+ width: 10
+ height: 10
+ color: "#ffffff"
+ layer.enabled: true
+ layer.effect: greenPassThrough
+ }
+
+ Rectangle {
+ id: blueInColumn
+ width: 10
+ height: 10
+ color: "#0000ff"
+ }
+ }
+
+ Flow {
+ id: theFlow
+ x: 30
+ y: 30
+ width: 20
+ Rectangle {
+ width: 10
+ height: 10
+ color: "#ff0000"
+ layer.enabled: true
+ }
+
+ Rectangle {
+ width: 10
+ height: 10
+ color: "#ffffff"
+ layer.enabled: true
+ layer.effect: greenPassThrough
+ }
+
+ Rectangle {
+ id: blueInFlow
+ width: 10
+ height: 10
+ color: "#0000ff"
+ }
+ }
+
+ Grid {
+ id: theGrid
+ x: 60
+ y: 10
+ columns: 2
+ Rectangle {
+ width: 10
+ height: 10
+ color: "#ff0000"
+ layer.enabled: true
+ }
+
+ Rectangle {
+ width: 10
+ height: 10
+ color: "#ffffff"
+ layer.enabled: true
+ layer.effect: greenPassThrough
+ }
+
+ Rectangle {
+ id: blueInGrid
+ width: 10
+ height: 10
+ color: "#0000ff"
+ }
+ }
+
+}
diff --git a/tests/auto/qmltest/itemgrabber/tst_itemgrabber.qml b/tests/auto/qmltest/itemgrabber/tst_itemgrabber.qml
new file mode 100644
index 0000000000..4f827bbf33
--- /dev/null
+++ b/tests/auto/qmltest/itemgrabber/tst_itemgrabber.qml
@@ -0,0 +1,160 @@
+/****************************************************************************
+**
+** 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.4
+import QtTest 1.0
+
+Item {
+ id: root;
+ width: 400
+ height: 400
+
+ TestCase {
+ id: testCase
+ name: "item-grabber"
+ when: imageOnDisk.ready && imageOnDiskSmall.ready && imageInCache.ready && imageInCacheSmall.ready
+ function test_endresult() {
+ var image = grabImage(root);
+
+ // imageOnDisk at (0, 0) - (100x100)
+ compare(imageOnDisk.width, 100);
+ compare(imageOnDisk.height, 100);
+ verify(image.pixel(0, 0) === Qt.rgba(1, 0, 0, 1)); // Use verify because compare doesn't support colors (QTBUG-34878)
+ verify(image.pixel(99, 99) === Qt.rgba(0, 0, 1, 1));
+
+ // imageOnDiskSmall at (100, 0) - 50x50
+ compare(imageOnDiskSmall.width, 50);
+ compare(imageOnDiskSmall.height, 50);
+ verify(image.pixel(100, 0) === Qt.rgba(1, 0, 0, 1));
+ verify(image.pixel(149, 49) === Qt.rgba(0, 0, 1, 1));
+
+ // imageInCache at (0, 100) - 100x100
+ compare(imageInCache.width, 100);
+ compare(imageInCache.height, 100);
+ verify(image.pixel(0, 100) === Qt.rgba(1, 0, 0, 1));
+ verify(image.pixel(99, 199) === Qt.rgba(0, 0, 1, 1));
+
+ // imageInCacheSmall at (100, 100) - 50x50
+ compare(imageInCacheSmall.width, 50);
+ compare(imageInCacheSmall.height, 50);
+ verify(image.pixel(100, 100) === Qt.rgba(1, 0, 0, 1));
+ verify(image.pixel(149, 149) === Qt.rgba(0, 0, 1, 1));
+
+ // After all that has been going on, it should only have been called that one time..
+ compare(imageOnDisk.callCount, 1);
+ }
+
+ onWindowShownChanged: {
+ box.grabToImage(imageOnDisk.handleGrab);
+ box.grabToImage(imageOnDiskSmall.handleGrab, Qt.size(50, 50));
+ box.grabToImage(imageInCache.handleGrab);
+ box.grabToImage(imageInCacheSmall.handleGrab, Qt.size(50, 50));
+ }
+
+ }
+
+ Rectangle {
+ id: box
+ width: 100
+ height: 100
+ color: "red";
+
+ visible: false
+
+ Rectangle {
+ anchors.bottom: parent.bottom;
+ anchors.right: parent.right;
+ width: 10
+ height: 10
+ color: "blue";
+ }
+ }
+
+ Image {
+ id: imageOnDisk
+ x: 0
+ y: 0
+ property int callCount: 0;
+ property bool ready: false;
+ function handleGrab(result) {
+ if (!result.saveToFile("image.png"))
+ print("Error: Failed to save image to disk...");
+ source = "image.png";
+ ready = true;
+ ++callCount;
+ }
+ }
+
+ Image {
+ id: imageOnDiskSmall
+ x: 100
+ y: 0
+ property bool ready: false;
+ function handleGrab(result) {
+ if (!result.saveToFile("image_small.png"))
+ print("Error: Failed to save image to disk...");
+ source = "image_small.png";
+ ready = true;
+ }
+ }
+
+ Image {
+ id: imageInCache
+ x: 0
+ y: 100
+ property bool ready: false;
+ function handleGrab(result) {
+ source = result.url;
+ ready = true;
+ }
+ }
+
+ Image {
+ id: imageInCacheSmall
+ x: 100
+ y: 100
+ property bool ready: false;
+ function handleGrab(result) {
+ source = result.url;
+ ready = true;
+ }
+ }
+}
diff --git a/tests/auto/qmltest/selftests/tst_findChild.qml b/tests/auto/qmltest/selftests/tst_findChild.qml
new file mode 100644
index 0000000000..cb41cbf061
--- /dev/null
+++ b/tests/auto/qmltest/selftests/tst_findChild.qml
@@ -0,0 +1,112 @@
+/****************************************************************************
+**
+** 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
+import QtTest 1.0
+
+TestCase {
+ name: "tst_findChild"
+
+ QtObject {
+ id: singleObject
+ }
+
+ Item {
+ id: oneObjectChildItem
+
+ QtObject {
+ id: childObject
+ objectName: "childObject"
+ }
+ }
+
+ Item {
+ id: oneItemChildItem
+
+ Item {
+ id: childItem
+ objectName: "childItem"
+ }
+ }
+
+ Item {
+ id: nestedChildrenItem
+
+ Item {
+ id: nestedChildItem0
+ objectName: "nestedChildItem0"
+
+ Item {
+ id: nestedChildItem1
+ objectName: "nestedChildItem1"
+
+ Item {
+ id: nestedChildItem2
+ objectName: "nestedChildItem2"
+ }
+ }
+ }
+ }
+
+ property Component duplicateNestedChildItem2Component: Item {
+ objectName: "nestedChildItem2"
+ }
+
+ function test_findChild() {
+ compare(findChild(null, ""), null);
+ compare(findChild(undefined, ""), null);
+ compare(findChild(singleObject, "doesNotExist"), null);
+ compare(findChild(oneObjectChildItem, "childObject"), childObject);
+ compare(findChild(oneItemChildItem, "childItem"), childItem);
+ compare(findChild(nestedChildrenItem, "nestedChildItem0"), nestedChildItem0);
+ compare(findChild(nestedChildrenItem, "nestedChildItem1"), nestedChildItem1);
+ compare(findChild(nestedChildrenItem, "nestedChildItem2"), nestedChildItem2);
+
+ // Shouldn't be found, since it's not the first in the list.
+ duplicateNestedChildItem2Component.createObject(nestedChildItem1);
+ compare(nestedChildItem1.children.length, 2);
+ compare(findChild(nestedChildrenItem, "nestedChildItem2"), nestedChildItem2);
+
+ var mostDirectChild = duplicateNestedChildItem2Component.createObject(nestedChildItem0);
+ compare(nestedChildItem0.children.length, 2);
+ compare(findChild(nestedChildrenItem, "nestedChildItem2"), mostDirectChild);
+ }
+}
diff --git a/tests/auto/qmltest/shadersource/tst_DynamicallyCreated.qml b/tests/auto/qmltest/shadersource/tst_DynamicallyCreated.qml
new file mode 100644
index 0000000000..ba0289fadc
--- /dev/null
+++ b/tests/auto/qmltest/shadersource/tst_DynamicallyCreated.qml
@@ -0,0 +1,84 @@
+/****************************************************************************
+**
+** 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 QtQuick.Window 2.0
+import QtTest 1.0
+
+Item {
+ width: 100
+ height: 100
+
+ Window {
+ id: win
+
+ width: 100
+ height: 100
+
+ property bool rendered: false;
+ visible: true
+
+ title: "QML window"
+
+ onFrameSwapped: {
+ if (shaderSource.sourceItem) {
+ rendered = true;
+ } else {
+ var com = Qt.createQmlObject('import QtQuick 2.2; Rectangle { color: "red"; width: 100; height: 100 }', win);
+ shaderSource.sourceItem = com;
+ }
+ }
+
+ ShaderEffectSource {
+ id: shaderSource
+ }
+
+ }
+
+ TestCase {
+ when: win.rendered;
+ name: "shadersource-dynamic-sourceobject"
+ function test_endresult() {
+ var image = grabImage(shaderSource);
+ compare(image.pixel(0, 0), Qt.rgba(1, 0, 0, 1));
+ }
+ }
+}
diff --git a/tests/auto/qmltest/shadersource/tst_SourceInOtherWindow.qml b/tests/auto/qmltest/shadersource/tst_SourceInOtherWindow.qml
new file mode 100644
index 0000000000..d9959d7fad
--- /dev/null
+++ b/tests/auto/qmltest/shadersource/tst_SourceInOtherWindow.qml
@@ -0,0 +1,81 @@
+/****************************************************************************
+**
+** 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.0
+import QtQuick.Window 2.0
+
+import QtTest 1.0
+
+Item {
+ Rectangle {
+ id: box
+ color: "red"
+ }
+
+ Window {
+ id: childWindow
+
+ width: 100
+ height: 100
+
+ property bool rendered: false;
+ visible: true
+ onFrameSwapped: rendered = true;
+
+ ShaderEffectSource {
+ id: theSource
+ sourceItem: box
+ }
+
+ ShaderEffect {
+ property variant source: theSource;
+ anchors.fill: parent
+ }
+ }
+
+ TestCase {
+ name: "shadersource-from-other-window"
+ when: childWindow.isRendered
+ function test_endresult() {
+ verify(true); // that we got here without problems...
+ }
+ }
+}
diff --git a/tests/auto/qmltest/shadersource/tst_SourcedFromOtherWindow.qml b/tests/auto/qmltest/shadersource/tst_SourcedFromOtherWindow.qml
new file mode 100644
index 0000000000..436705befc
--- /dev/null
+++ b/tests/auto/qmltest/shadersource/tst_SourcedFromOtherWindow.qml
@@ -0,0 +1,81 @@
+/****************************************************************************
+**
+** 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.0
+import QtQuick.Window 2.0
+
+import QtTest 1.0
+
+Item {
+ Rectangle {
+ id: box
+ color: "red"
+ }
+
+ ShaderEffectSource {
+ id: theSource
+ sourceItem: box
+ }
+
+ Window {
+ id: childWindow
+
+ width: 100
+ height: 100
+
+ property bool rendered: false;
+ visible: true
+ onFrameSwapped: rendered = true;
+
+ ShaderEffect {
+ property variant source: theSource;
+ anchors.fill: parent
+ }
+ }
+
+ TestCase {
+ name: "shadersource-from-other-window"
+ when: childWindow.isRendered
+ function test_endresult() {
+ verify(true); // that we got here without problems...
+ }
+ }
+}
diff --git a/tests/auto/qmltest/statemachine/tst_anonymousstate.qml b/tests/auto/qmltest/statemachine/tst_anonymousstate.qml
new file mode 100644
index 0000000000..cd20f67c20
--- /dev/null
+++ b/tests/auto/qmltest/statemachine/tst_anonymousstate.qml
@@ -0,0 +1,52 @@
+/****************************************************************************
+**
+** Copyright (C) 2014 Ford Motor Company
+** Contact: http://www.qt-project.org/legal
+**
+** This file is part of the test suite 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 QtQml.StateMachine 1.0
+import QtTest 1.0
+
+TestCase {
+ StateMachine {
+ StateBase {
+ }
+ }
+ name: "anonymousState"
+ // no real tests, just make sure it runs
+}
diff --git a/tests/auto/qmltest/statemachine/tst_historystate.qml b/tests/auto/qmltest/statemachine/tst_historystate.qml
new file mode 100644
index 0000000000..86e63af5b0
--- /dev/null
+++ b/tests/auto/qmltest/statemachine/tst_historystate.qml
@@ -0,0 +1,102 @@
+/****************************************************************************
+**
+** Copyright (C) 2014 Ford Motor Company
+** Contact: http://www.qt-project.org/legal
+**
+** This file is part of the test suite 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 QtQml.StateMachine 1.0
+import QtTest 1.0
+
+TestCase {
+
+ StateMachine {
+ id: stateMachine
+ initialState: historyState1
+
+ StateBase {
+ id: state1
+ SignalTransition {
+ id: st1
+ targetState: state2
+ }
+ }
+
+ StateBase {
+ id: state2
+ initialState: historyState2
+ HistoryState {
+ id: historyState2
+ defaultState: state21
+ }
+ StateBase {
+ id: state21
+ }
+ }
+
+ HistoryState {
+ id: historyState1
+ defaultState: state1
+ }
+ }
+
+ SignalSpy {
+ id: state1SpyActive
+ target: state1
+ signalName: "activeChanged"
+ }
+
+ SignalSpy {
+ id: state2SpyActive
+ target: state2
+ signalName: "activeChanged"
+ }
+
+
+ function test_historyStateAsInitialState()
+ {
+ stateMachine.start();
+ tryCompare(stateMachine, "running", true);
+ tryCompare(state1SpyActive, "count" , 1);
+ tryCompare(state2SpyActive, "count" , 0);
+ st1.invoke();
+ tryCompare(state1SpyActive, "count" , 2);
+ tryCompare(state2SpyActive, "count" , 1);
+ tryCompare(state21, "active", true);
+ tryCompare(state1, "active", false);
+ }
+}
diff --git a/tests/auto/qmltest/statemachine/tst_initialstate.qml b/tests/auto/qmltest/statemachine/tst_initialstate.qml
new file mode 100644
index 0000000000..660bfcb327
--- /dev/null
+++ b/tests/auto/qmltest/statemachine/tst_initialstate.qml
@@ -0,0 +1,65 @@
+/****************************************************************************
+**
+** Copyright (C) 2014 Ford Motor Company
+** Contact: http://www.qt-project.org/legal
+**
+** This file is part of the test suite 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 QtQml.StateMachine 1.0
+import QtTest 1.0
+
+TestCase {
+ StateMachine {
+ id: myStateMachine
+ initialState: myState;
+ running: true
+ StateBase {
+ id: myState
+ }
+ }
+
+ name: "initialStateTest"
+ function test_initialState() {
+ tryCompare(myStateMachine, "running", true);
+ compare(myState.active, true);
+ myStateMachine.running = false;
+ tryCompare(myStateMachine, "running", false);
+ myStateMachine.running = true;
+ tryCompare(myStateMachine, "running", true);
+ tryCompare(myState, "active", true);
+ }
+}
diff --git a/tests/auto/qmltest/statemachine/tst_nestedinitialstates.qml b/tests/auto/qmltest/statemachine/tst_nestedinitialstates.qml
new file mode 100644
index 0000000000..60230f1e86
--- /dev/null
+++ b/tests/auto/qmltest/statemachine/tst_nestedinitialstates.qml
@@ -0,0 +1,74 @@
+/****************************************************************************
+**
+** Copyright (C) 2014 Ford Motor Company
+** Contact: http://www.qt-project.org/legal
+**
+** This file is part of the test suite 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 QtQml.StateMachine 1.0
+import QtTest 1.0
+
+TestCase {
+ StateMachine {
+ id: myStateMachine
+ initialState: parentState
+ StateBase {
+ id: parentState
+ initialState: childState1
+ StateBase {
+ id: childState1
+ }
+ StateBase {
+ id: childState2
+ }
+ }
+ }
+ name: "nestedInitalStates"
+
+ function test_nestedInitalStates() {
+ // uncomment me after vm problems are fixed.
+ // compare(myStateMachine.running, false);
+ compare(parentState.active, false);
+ compare(childState1.active, false);
+ compare(childState2.active, false);
+ myStateMachine.start();
+ tryCompare(myStateMachine, "running", true);
+ tryCompare(parentState, "active", true);
+ tryCompare(childState1, "active", true);
+ compare(childState2.active, false);
+ }
+}
diff --git a/tests/auto/qmltest/statemachine/tst_parallelmachine.qml b/tests/auto/qmltest/statemachine/tst_parallelmachine.qml
new file mode 100644
index 0000000000..99ef49860c
--- /dev/null
+++ b/tests/auto/qmltest/statemachine/tst_parallelmachine.qml
@@ -0,0 +1,90 @@
+/****************************************************************************
+**
+** Copyright (C) 2014 Ford Motor Company
+** Contact: http://www.qt-project.org/legal
+**
+** This file is part of the test suite 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 QtQml.StateMachine 1.0
+import QtTest 1.0
+
+TestCase {
+ StateMachine {
+ id: myStateMachine
+ childMode: StateBase.ParallelStates
+ StateBase {
+ id: childState1
+ childMode: StateBase.ParallelStates
+ StateBase {
+ id: childState11
+ }
+ StateBase {
+ id: childState12
+ }
+ }
+ StateBase {
+ id: childState2
+ initialState: childState21
+ StateBase {
+ id: childState21
+ }
+ StateBase {
+ id: childState22
+ }
+ }
+ }
+ name: "nestedParallelMachineStates"
+
+ function test_nestedInitalStates() {
+ // uncomment me after vm problems are fixed.
+ // compare(myStateMachine.running, false);
+ compare(childState1.active, false);
+ compare(childState11.active, false);
+ compare(childState12.active, false);
+ compare(childState2.active, false);
+ compare(childState21.active, false);
+ compare(childState22.active, false);
+ myStateMachine.start();
+ tryCompare(myStateMachine, "running", true);
+ tryCompare(childState1, "active", true);
+ tryCompare(childState11, "active", true);
+ tryCompare(childState12, "active", true);
+ tryCompare(childState2, "active", true);
+ tryCompare(childState21, "active", true);
+ tryCompare(childState22, "active", false);
+ }
+}
diff --git a/tests/auto/qmltest/statemachine/tst_trafficlight.qml b/tests/auto/qmltest/statemachine/tst_trafficlight.qml
new file mode 100644
index 0000000000..7b02cd0597
--- /dev/null
+++ b/tests/auto/qmltest/statemachine/tst_trafficlight.qml
@@ -0,0 +1,157 @@
+/****************************************************************************
+**
+** Copyright (C) 2014 Ford Motor Company
+** Contact: http://www.qt-project.org/legal
+**
+** This file is part of the test suite 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 QtQml.StateMachine 1.0
+import QtTest 1.0
+
+TestCase {
+ StateMachine {
+ id: machine
+ initialState: red
+ FinalState {
+ id: finalState
+ }
+
+ StateBase {
+ id: red
+ initialState: justRed
+ StateBase {
+ id: justRed
+ SignalTransition {
+ id: e1
+ targetState: waitingForGreen
+ }
+ SignalTransition {
+ id: finalSignal
+ targetState: finalState
+ }
+ }
+ StateBase {
+ id: waitingForGreen
+ TimeoutTransition {
+ id: e2
+ targetState: yellowred
+ timeout: 30
+ }
+ }
+ }
+ StateBase {
+ id: yellowred
+ TimeoutTransition {
+ id: e3
+ targetState: green
+ timeout: 10
+ }
+ }
+ StateBase {
+ id: green
+ TimeoutTransition {
+ id: e4
+ targetState: yellow
+ timeout: 50
+ }
+ }
+ StateBase {
+ id: yellow
+ TimeoutTransition {
+ id: e5
+ targetState: red
+ timeout: 10
+ }
+ }
+ }
+
+ SignalSpy {
+ id: machineSpyRunning
+ target: machine
+ signalName: "runningChanged"
+ }
+
+ SignalSpy {
+ id: redSpyActive
+ target: red
+ signalName: "activeChanged"
+ }
+
+ SignalSpy {
+ id: yellowredSpyActive
+ target: yellowred
+ signalName: "activeChanged"
+ }
+
+ SignalSpy {
+ id: greenSpyActive
+ target: green
+ signalName: "activeChanged"
+ }
+
+ SignalSpy {
+ id: yellowSpyActive
+ target: yellow
+ signalName: "activeChanged"
+ }
+
+
+ name: "testTrafficLight"
+ function test_trafficLight()
+ {
+ var i = 1;
+ machine.start();
+ tryCompare(machine, "running", true);
+ tryCompare(machineSpyRunning, "count", 1);
+ tryCompare(redSpyActive, "count", 1);
+ for (; i <= 5; ++i) {
+ e1.invoke();
+ tryCompare(yellowredSpyActive, "count", i * 2);
+ tryCompare(greenSpyActive, "count", i * 2);
+ tryCompare(redSpyActive, "count", i * 2 + 1);
+ tryCompare(yellowSpyActive, "count", i * 2);
+ }
+ finalSignal.guard = false;
+ finalSignal.invoke();
+ wait(100);
+ tryCompare(machine, "running", true);
+ finalSignal.guard = true;
+ finalSignal.invoke();
+ tryCompare(machine, "running", false);
+ tryCompare(redSpyActive, "count", i * 2);
+ }
+}
diff --git a/tests/auto/quick/nodes/tst_nodestest.cpp b/tests/auto/quick/nodes/tst_nodestest.cpp
index 662e78ef6c..212337957e 100644
--- a/tests/auto/quick/nodes/tst_nodestest.cpp
+++ b/tests/auto/quick/nodes/tst_nodestest.cpp
@@ -52,6 +52,8 @@
#include <QtQuick/private/qsgcontext_p.h>
#include <QtQuick/qsgsimplerectnode.h>
+#include <QtQuick/qsgsimpletexturenode.h>
+#include <QtQuick/private/qsgtexture_p.h>
class NodesTest : public QObject
{
@@ -74,6 +76,8 @@ private Q_SLOTS:
void isBlockedCheck();
+ void textureNodeTextureOwnership();
+
private:
QOffscreenSurface *surface;
QOpenGLContext *context;
@@ -259,6 +263,32 @@ void NodesTest::isBlockedCheck()
QVERIFY(!updater.isNodeBlocked(node, &root));
}
+void NodesTest::textureNodeTextureOwnership()
+{
+ { // Check that it is not deleted by default
+ QPointer<QSGTexture> texture(new QSGPlainTexture());
+
+ QSGSimpleTextureNode *tn = new QSGSimpleTextureNode();
+ QVERIFY(!tn->ownsTexture());
+
+ tn->setTexture(texture);
+ delete tn;
+ QVERIFY(!texture.isNull());
+ }
+
+ { // Check that it is deleted when we so desire
+ QPointer<QSGTexture> texture(new QSGPlainTexture());
+
+ QSGSimpleTextureNode *tn = new QSGSimpleTextureNode();
+ tn->setOwnsTexture(true);
+ QVERIFY(tn->ownsTexture());
+
+ tn->setTexture(texture);
+ delete tn;
+ QVERIFY(texture.isNull());
+ }
+}
+
QTEST_MAIN(NodesTest);
#include "tst_nodestest.moc"
diff --git a/tests/auto/quick/qquickaccessible/tst_qquickaccessible.cpp b/tests/auto/quick/qquickaccessible/tst_qquickaccessible.cpp
index 760cdd7b49..cb801f5539 100644
--- a/tests/auto/quick/qquickaccessible/tst_qquickaccessible.cpp
+++ b/tests/auto/quick/qquickaccessible/tst_qquickaccessible.cpp
@@ -41,7 +41,7 @@
#include <QtTest/QtTest>
-#include "QtTest/qtestaccessible.h"
+#include <QtTest/qtestaccessible.h>
#include <QtGui/qaccessible.h>
#include <QtGui/private/qguiapplication_p.h>
diff --git a/tests/auto/quick/qquickanchors/tst_qquickanchors.cpp b/tests/auto/quick/qquickanchors/tst_qquickanchors.cpp
index ee277ecd9b..02c30b652a 100644
--- a/tests/auto/quick/qquickanchors/tst_qquickanchors.cpp
+++ b/tests/auto/quick/qquickanchors/tst_qquickanchors.cpp
@@ -310,55 +310,55 @@ void tst_qquickanchors::illegalSets_data()
QTest::newRow("H - too many anchors")
<< "Rectangle { id: rect; Rectangle { anchors.left: rect.left; anchors.right: rect.right; anchors.horizontalCenter: rect.horizontalCenter } }"
- << "file::2:23: QML Rectangle: Cannot specify left, right, and horizontalCenter anchors at the same time.";
+ << "<Unknown File>:2:23: QML Rectangle: Cannot specify left, right, and horizontalCenter anchors at the same time.";
foreach (const QString &side, QStringList() << "left" << "right") {
QTest::newRow("H - anchor to V")
<< QString("Rectangle { Rectangle { anchors.%1: parent.top } }").arg(side)
- << "file::2:13: QML Rectangle: Cannot anchor a horizontal edge to a vertical edge.";
+ << "<Unknown File>:2:13: QML Rectangle: Cannot anchor a horizontal edge to a vertical edge.";
QTest::newRow("H - anchor to non parent/sibling")
<< QString("Rectangle { Item { Rectangle { id: rect } } Rectangle { anchors.%1: rect.%1 } }").arg(side)
- << "file::2:45: QML Rectangle: Cannot anchor to an item that isn't a parent or sibling.";
+ << "<Unknown File>:2:45: QML Rectangle: Cannot anchor to an item that isn't a parent or sibling.";
QTest::newRow("H - anchor to self")
<< QString("Rectangle { id: rect; anchors.%1: rect.%1 }").arg(side)
- << "file::2:1: QML Rectangle: Cannot anchor item to self.";
+ << "<Unknown File>:2:1: QML Rectangle: Cannot anchor item to self.";
}
QTest::newRow("V - too many anchors")
<< "Rectangle { id: rect; Rectangle { anchors.top: rect.top; anchors.bottom: rect.bottom; anchors.verticalCenter: rect.verticalCenter } }"
- << "file::2:23: QML Rectangle: Cannot specify top, bottom, and verticalCenter anchors at the same time.";
+ << "<Unknown File>:2:23: QML Rectangle: Cannot specify top, bottom, and verticalCenter anchors at the same time.";
QTest::newRow("V - too many anchors with baseline")
<< "Rectangle { Text { id: text1; text: \"Hello\" } Text { anchors.baseline: text1.baseline; anchors.top: text1.top; } }"
- << "file::2:47: QML Text: Baseline anchor cannot be used in conjunction with top, bottom, or verticalCenter anchors.";
+ << "<Unknown File>:2:47: QML Text: Baseline anchor cannot be used in conjunction with top, bottom, or verticalCenter anchors.";
foreach (const QString &side, QStringList() << "top" << "bottom" << "baseline") {
QTest::newRow("V - anchor to H")
<< QString("Rectangle { Rectangle { anchors.%1: parent.left } }").arg(side)
- << "file::2:13: QML Rectangle: Cannot anchor a vertical edge to a horizontal edge.";
+ << "<Unknown File>:2:13: QML Rectangle: Cannot anchor a vertical edge to a horizontal edge.";
QTest::newRow("V - anchor to non parent/sibling")
<< QString("Rectangle { Item { Rectangle { id: rect } } Rectangle { anchors.%1: rect.%1 } }").arg(side)
- << "file::2:45: QML Rectangle: Cannot anchor to an item that isn't a parent or sibling.";
+ << "<Unknown File>:2:45: QML Rectangle: Cannot anchor to an item that isn't a parent or sibling.";
QTest::newRow("V - anchor to self")
<< QString("Rectangle { id: rect; anchors.%1: rect.%1 }").arg(side)
- << "file::2:1: QML Rectangle: Cannot anchor item to self.";
+ << "<Unknown File>:2:1: QML Rectangle: Cannot anchor item to self.";
}
QTest::newRow("centerIn - anchor to non parent/sibling")
<< "Rectangle { Item { Rectangle { id: rect } } Rectangle { anchors.centerIn: rect} }"
- << "file::2:45: QML Rectangle: Cannot anchor to an item that isn't a parent or sibling.";
+ << "<Unknown File>:2:45: QML Rectangle: Cannot anchor to an item that isn't a parent or sibling.";
QTest::newRow("fill - anchor to non parent/sibling")
<< "Rectangle { Item { Rectangle { id: rect } } Rectangle { anchors.fill: rect} }"
- << "file::2:45: QML Rectangle: Cannot anchor to an item that isn't a parent or sibling.";
+ << "<Unknown File>:2:45: QML Rectangle: Cannot anchor to an item that isn't a parent or sibling.";
}
void tst_qquickanchors::reset()
diff --git a/tests/auto/quick/qquickanimatedimage/tst_qquickanimatedimage.cpp b/tests/auto/quick/qquickanimatedimage/tst_qquickanimatedimage.cpp
index d10963b579..eb0ea7c8f5 100644
--- a/tests/auto/quick/qquickanimatedimage/tst_qquickanimatedimage.cpp
+++ b/tests/auto/quick/qquickanimatedimage/tst_qquickanimatedimage.cpp
@@ -259,8 +259,8 @@ void tst_qquickanimatedimage::remote()
QFETCH(QString, fileName);
QFETCH(bool, paused);
- TestHTTPServer server(14449);
- QVERIFY(server.isValid());
+ TestHTTPServer server;
+ QVERIFY2(server.listen(14449), qPrintable(server.errorString()));
server.serveDirectory(dataDirectory());
QQmlEngine engine;
@@ -305,10 +305,10 @@ void tst_qquickanimatedimage::invalidSource()
{
QQmlEngine engine;
QQmlComponent component(&engine);
- component.setData("import QtQuick 2.0\n AnimatedImage { source: \"no-such-file.gif\" }", QUrl::fromLocalFile(""));
+ component.setData("import QtQuick 2.0\n AnimatedImage { source: \"no-such-file.gif\" }", QUrl::fromLocalFile("relative"));
QVERIFY(component.isReady());
- QTest::ignoreMessage(QtWarningMsg, "file::2:2: QML AnimatedImage: Error Reading Animated Image File file:no-such-file.gif");
+ QTest::ignoreMessage(QtWarningMsg, "file:relative:2:2: QML AnimatedImage: Error Reading Animated Image File file:no-such-file.gif");
QQuickAnimatedImage *anim = qobject_cast<QQuickAnimatedImage *>(component.create());
QVERIFY(anim);
@@ -324,8 +324,8 @@ void tst_qquickanimatedimage::invalidSource()
void tst_qquickanimatedimage::sourceSizeChanges()
{
- TestHTTPServer server(14449);
- QVERIFY(server.isValid());
+ TestHTTPServer server;
+ QVERIFY2(server.listen(14449), qPrintable(server.errorString()));
server.serveDirectory(dataDirectory());
QQmlEngine engine;
@@ -390,8 +390,8 @@ void tst_qquickanimatedimage::sourceSizeChanges()
void tst_qquickanimatedimage::qtbug_16520()
{
- TestHTTPServer server(14449);
- QVERIFY(server.isValid());
+ TestHTTPServer server;
+ QVERIFY2(server.listen(14449), qPrintable(server.errorString()));
server.serveDirectory(dataDirectory());
QQmlEngine engine;
@@ -413,8 +413,8 @@ void tst_qquickanimatedimage::qtbug_16520()
void tst_qquickanimatedimage::progressAndStatusChanges()
{
- TestHTTPServer server(14449);
- QVERIFY(server.isValid());
+ TestHTTPServer server;
+ QVERIFY2(server.listen(14449), qPrintable(server.errorString()));
server.serveDirectory(dataDirectory());
QQmlEngine engine;
diff --git a/tests/auto/quick/qquickapplication/tst_qquickapplication.cpp b/tests/auto/quick/qquickapplication/tst_qquickapplication.cpp
index dfcef43a7e..0993d03ee4 100644
--- a/tests/auto/quick/qquickapplication/tst_qquickapplication.cpp
+++ b/tests/auto/quick/qquickapplication/tst_qquickapplication.cpp
@@ -60,6 +60,7 @@ private slots:
void state();
void layoutDirection();
void inputMethod();
+ void cleanup();
private:
QQmlEngine engine;
@@ -69,6 +70,14 @@ tst_qquickapplication::tst_qquickapplication()
{
}
+void tst_qquickapplication::cleanup()
+{
+ if (QGuiApplicationPrivate::platformIntegration()->hasCapability(QPlatformIntegration::ApplicationState)) {
+ QWindowSystemInterface::handleApplicationStateChanged(Qt::ApplicationInactive);
+ QTest::waitForEvents();
+ }
+}
+
void tst_qquickapplication::active()
{
QQmlComponent component(&engine);
@@ -98,12 +107,19 @@ void tst_qquickapplication::active()
QVERIFY(item->property("active").toBool());
QVERIFY(item->property("active2").toBool());
- // not active again
QWindowSystemInterface::handleWindowActivated(0);
+#ifdef Q_OS_OSX
+ // OS X has the concept of "reactivation"
+ QTRY_VERIFY(QGuiApplication::focusWindow() != &window);
+ QVERIFY(item->property("active").toBool());
+ QVERIFY(item->property("active2").toBool());
+#else
+ // not active again
QTRY_VERIFY(QGuiApplication::focusWindow() != &window);
QVERIFY(!item->property("active").toBool());
QVERIFY(!item->property("active2").toBool());
+#endif
}
void tst_qquickapplication::state()
@@ -117,6 +133,7 @@ void tst_qquickapplication::state()
" target: Qt.application; "
" onStateChanged: state2 = Qt.application.state; "
" } "
+ " Component.onCompleted: state2 = Qt.application.state; "
"}", QUrl::fromLocalFile(""));
QQuickItem *item = qobject_cast<QQuickItem *>(component.create());
QVERIFY(item);
diff --git a/tests/auto/quick/qquickborderimage/tst_qquickborderimage.cpp b/tests/auto/quick/qquickborderimage/tst_qquickborderimage.cpp
index 4e7b6522dd..ce4394cf6f 100644
--- a/tests/auto/quick/qquickborderimage/tst_qquickborderimage.cpp
+++ b/tests/auto/quick/qquickborderimage/tst_qquickborderimage.cpp
@@ -131,10 +131,10 @@ void tst_qquickborderimage::imageSource_data()
QTest::newRow("local") << testFileUrl("colors.png").toString() << false << "";
QTest::newRow("local not found") << testFileUrl("no-such-file.png").toString() << false
- << "file::2:1: QML BorderImage: Cannot open: " + testFileUrl("no-such-file.png").toString();
+ << "<Unknown File>:2:1: QML BorderImage: Cannot open: " + testFileUrl("no-such-file.png").toString();
QTest::newRow("remote") << SERVER_ADDR "/colors.png" << true << "";
QTest::newRow("remote not found") << SERVER_ADDR "/no-such-file.png" << true
- << "file::2:1: QML BorderImage: Error downloading " SERVER_ADDR "/no-such-file.png - server replied: Not found";
+ << "<Unknown File>:2:1: QML BorderImage: Error downloading " SERVER_ADDR "/no-such-file.png - server replied: Not found";
}
void tst_qquickborderimage::imageSource()
@@ -143,11 +143,10 @@ void tst_qquickborderimage::imageSource()
QFETCH(bool, remote);
QFETCH(QString, error);
- TestHTTPServer *server = 0;
+ TestHTTPServer server;
if (remote) {
- server = new TestHTTPServer(SERVER_PORT);
- QVERIFY(server->isValid());
- server->serveDirectory(dataDirectory());
+ QVERIFY2(server.listen(SERVER_PORT), qPrintable(server.errorString()));
+ server.serveDirectory(dataDirectory());
}
if (!error.isEmpty())
@@ -177,7 +176,6 @@ void tst_qquickborderimage::imageSource()
}
delete obj;
- delete server;
}
void tst_qquickborderimage::clearSource()
@@ -292,11 +290,11 @@ void tst_qquickborderimage::sciSource()
QFETCH(bool, valid);
bool remote = source.startsWith("http");
- TestHTTPServer *server = 0;
+
+ TestHTTPServer server;
if (remote) {
- server = new TestHTTPServer(SERVER_PORT);
- QVERIFY(server->isValid());
- server->serveDirectory(dataDirectory());
+ QVERIFY2(server.listen(SERVER_PORT), qPrintable(server.errorString()));
+ server.serveDirectory(dataDirectory());
}
QString componentStr = "import QtQuick 2.0\nBorderImage { source: \"" + source + "\"; width: 300; height: 300 }";
@@ -325,7 +323,6 @@ void tst_qquickborderimage::sciSource()
}
delete obj;
- delete server;
}
void tst_qquickborderimage::sciSource_data()
@@ -435,11 +432,10 @@ void tst_qquickborderimage::statusChanges()
QFETCH(bool, remote);
QFETCH(QQuickImageBase::Status, finalStatus);
- TestHTTPServer *server = 0;
+ TestHTTPServer server;
if (remote) {
- server = new TestHTTPServer(SERVER_PORT);
- QVERIFY(server->isValid());
- server->serveDirectory(dataDirectory(), TestHTTPServer::Delay);
+ QVERIFY2(server.listen(SERVER_PORT), qPrintable(server.errorString()));
+ server.serveDirectory(dataDirectory());
}
QString componentStr = "import QtQuick 2.0\nBorderImage { width: 300; height: 300 }";
@@ -452,18 +448,17 @@ void tst_qquickborderimage::statusChanges()
QVERIFY(obj != 0);
obj->setSource(source);
if (remote)
- server->sendDelayedItem();
+ server.sendDelayedItem();
QTRY_VERIFY(obj->status() == finalStatus);
QCOMPARE(spy.count(), emissions);
delete obj;
- delete server;
}
void tst_qquickborderimage::sourceSizeChanges()
{
- TestHTTPServer server(14449);
- QVERIFY(server.isValid());
+ TestHTTPServer server;
+ QVERIFY2(server.listen(14449), qPrintable(server.errorString()));
server.serveDirectory(dataDirectory());
QQmlEngine engine;
@@ -528,8 +523,8 @@ void tst_qquickborderimage::sourceSizeChanges()
void tst_qquickborderimage::progressAndStatusChanges()
{
- TestHTTPServer server(14449);
- QVERIFY(server.isValid());
+ TestHTTPServer server;
+ QVERIFY2(server.listen(14449), qPrintable(server.errorString()));
server.serveDirectory(dataDirectory());
QQmlEngine engine;
diff --git a/tests/auto/quick/qquickcanvasitem/data/tst_canvas.qml b/tests/auto/quick/qquickcanvasitem/data/tst_canvas.qml
index d90eb3971e..23fd5192f3 100644
--- a/tests/auto/quick/qquickcanvasitem/data/tst_canvas.qml
+++ b/tests/auto/quick/qquickcanvasitem/data/tst_canvas.qml
@@ -247,5 +247,348 @@ CanvasTestCase {
c.destroy();
}
+
+ Image {
+ id: image
+ source: "anim-gr.png"
+ }
+
+ /*
+ Ensures that extra arguments to functions are ignored,
+ by checking that drawing, clearing, etc. still occurs.
+ */
+ function test_extraArgumentsIgnored_data() {
+ var extra = 0;
+ return [
+ {
+ tag: "arc",
+ test: function(ctx) {
+ ctx.arc(10, 10, 5, 0, Math.PI * 2, true, extra);
+ ctx.fill();
+ comparePixel(ctx, 10, 10, 255, 0, 0, 255);
+ }
+ },
+ {
+ tag: "arcTo",
+ test: function(ctx) {
+ ctx.translate(-50, -25);
+ ctx.moveTo(20,20);
+ ctx.arcTo(150, 20, 100, 70, 50, extra);
+ ctx.fill();
+ comparePixel(ctx, 0, 0, 255, 0, 0, 255);
+ }
+ },
+ {
+ tag: "bezierCurveTo",
+ test: function(ctx) {
+ ctx.beginPath();
+ ctx.moveTo(-20, -20);
+ ctx.bezierCurveTo(20, 100, 100, 100, 100, 20, extra);
+ ctx.fill();
+ comparePixel(ctx, 0, 0, 255, 0, 0, 255);
+ }
+ },
+ {
+ tag: "clearRect",
+ test: function(ctx) {
+ ctx.fillRect(0, 0, ctx.canvas.width, ctx.canvas.height);
+ ctx.clearRect(0, 0, 10, 10, extra);
+ comparePixel(ctx, 0, 0, 0, 0, 0, 0);
+ }
+ },
+ {
+ tag: "createConicalGradient",
+ test: function(ctx) {
+ verify(ctx.createConicalGradient(0, 0, 0, extra) !== ctx);
+ }
+ },
+ {
+ tag: "createLinearGradient",
+ test: function(ctx) {
+ verify(ctx.createLinearGradient(0, 0, 10, 10, extra) !== ctx);
+ }
+ },
+ {
+ tag: "createRadialGradient",
+ test: function(ctx) {
+ verify(ctx.createRadialGradient(0, 0, 10, 20, 20, 10, extra) !== ctx);
+ }
+ },
+ {
+ tag: "createPattern-image",
+ test: function(ctx) {
+ verify(ctx.createPattern(image, "repeat", extra) !== undefined);
+ }
+ },
+ {
+ tag: "createPattern-color",
+ test: function(ctx) {
+ verify(ctx.createPattern("red", Qt.SolidPattern, extra) !== undefined);
+ }
+ },
+ {
+ tag: "drawImage-9-args",
+ test: function(ctx) {
+ ctx.drawImage(image, 0, 0, image.sourceSize.width, image.sourceSize.height,
+ 0, 0, image.sourceSize.width, image.sourceSize.height, extra);
+ comparePixel(ctx, 10, 10, 0, 255, 0, 255);
+ }
+ },
+ {
+ tag: "drawImage-5-args",
+ test: function(ctx) {
+ ctx.drawImage(image, 0, 0, image.sourceSize.width, image.sourceSize.height, extra);
+ comparePixel(ctx, 10, 10, 0, 255, 0, 255);
+ }
+ },
+ {
+ tag: "drawImage-3-args",
+ test: function(ctx) {
+ ctx.drawImage(image, 0, 0, extra);
+ comparePixel(ctx, 10, 10, 0, 255, 0, 255);
+ }
+ },
+ {
+ tag: "ellipse",
+ test: function(ctx) {
+ ctx.ellipse(0, 0, 10, 10);
+ ctx.fill();
+ comparePixel(ctx, 5, 5, 255, 0, 0, 255);
+ }
+ },
+ {
+ tag: "fillRect",
+ test: function(ctx) {
+ ctx.fillRect(0, 0, 10, 10, extra);
+ comparePixel(ctx, 0, 0, 255, 0, 0, 255, 200);
+ }
+ },
+ {
+ tag: "fillText",
+ test: function(ctx) {
+ ctx.font = "100px sans-serif";
+ ctx.fillText("Hello", -10, 10, extra);
+ comparePixel(ctx, 0, 0, 255, 0, 0, 255);
+ }
+ },
+ {
+ tag: "getImageData",
+ test: function(ctx) {
+ verify(ctx.getImageData(0, 0, 1, 1, extra) !== null);
+ }
+ },
+ {
+ tag: "isPointInPath",
+ test: function(ctx) {
+ ctx.moveTo(0, 0);
+ ctx.lineTo(10, 10);
+ verify(ctx.isPointInPath(0, 0, extra));
+ }
+ },
+ {
+ tag: "lineTo",
+ test: function(ctx) {
+ ctx.lineWidth = 5;
+ ctx.moveTo(0, 0);
+ ctx.lineTo(10, 10, extra);
+ ctx.stroke();
+ comparePixel(ctx, 0, 0, 255, 0, 0, 255);
+ }
+ },
+ {
+ tag: "measureText",
+ test: function(ctx) {
+ var textMetrics = ctx.measureText("Hello", extra);
+ verify(textMetrics !== undefined);
+ verify(textMetrics.width > 0);
+ }
+ },
+ {
+ tag: "moveTo",
+ test: function(ctx) {
+ ctx.lineWidth = 5;
+ ctx.moveTo(10, 10, extra);
+ ctx.lineTo(20, 20, extra);
+ ctx.stroke();
+ comparePixel(ctx, 0, 0, 0, 0, 0, 0);
+ comparePixel(ctx, 10, 10, 255, 0, 0, 255);
+ }
+ },
+ {
+ tag: "putImageData",
+ test: function(ctx) {
+ ctx.drawImage(image, 0, 0);
+ comparePixel(ctx, 0, 0, 0, 255, 0, 255);
+ var imageData = ctx.getImageData(0, 0, 1, 1);
+ // Swap green with red.
+ imageData.data[0] = 255;
+ imageData.data[1] = 0;
+ ctx.putImageData(imageData, 0, 0, 0, 0, ctx.canvas.width, ctx.canvas.height, extra);
+ comparePixel(ctx, 0, 0, 255, 0, 0, 255);
+ }
+ },
+ {
+ tag: "quadraticCurveTo",
+ test: function(ctx) {
+ ctx.lineWidth = 5;
+ ctx.moveTo(0, 0);
+ ctx.quadraticCurveTo(20, 100, 100, 20, extra);
+ ctx.stroke();
+ comparePixel(ctx, 0, 0, 255, 0, 0, 255);
+ }
+ },
+ {
+ tag: "rect",
+ test: function(ctx) {
+ ctx.rect(0, 0, 1, 1, extra);
+ ctx.fill();
+ comparePixel(ctx, 0, 0, 255, 0, 0, 255);
+ }
+ },
+ {
+ tag: "rotate",
+ test: function(ctx) {
+ // If we don't rotate, it should be red in the middle.
+ comparePixel(ctx, 50, 50, 0, 0, 0, 0);
+ ctx.fillRect(50, 50, 1, 1);
+ comparePixel(ctx, 50, 50, 255, 0, 0, 255);
+
+ ctx.reset();
+ comparePixel(ctx, 50, 50, 0, 0, 0, 0);
+
+ // If we do rotate, it shouldn't be there.
+ ctx.rotate(Math.PI / 4, extra);
+ ctx.fillRect(50, 50, 1, 1);
+ comparePixel(ctx, 50, 50, 0, 0, 0, 0);
+ }
+ },
+ {
+ tag: "roundedRect",
+ test: function(ctx) {
+ ctx.roundedRect(0, 0, 50, 50, 5, 5, extra);
+ ctx.fill();
+ comparePixel(ctx, 25, 25, 255, 0, 0, 255);
+ }
+ },
+ {
+ tag: "scale",
+ test: function(ctx) {
+ // If we don't scale, it should be red in the middle.
+ comparePixel(ctx, 50, 50, 0, 0, 0, 0);
+ ctx.fillRect(50, 50, 1, 1);
+ comparePixel(ctx, 50, 50, 255, 0, 0, 255);
+
+ ctx.reset();
+ comparePixel(ctx, 50, 50, 0, 0, 0, 0);
+
+ // If we do scale, it shouldn't be there.
+ ctx.scale(1.25, 1.25, extra);
+ ctx.fillRect(50, 50, 1, 1);
+ comparePixel(ctx, 50, 50, 0, 0, 0, 0);
+ }
+ },
+ {
+ tag: "setTransform",
+ test: function(ctx) {
+ // The same as the scale test, except with setTransform.
+ comparePixel(ctx, 50, 50, 0, 0, 0, 0);
+ ctx.fillRect(50, 50, 1, 1);
+ comparePixel(ctx, 50, 50, 255, 0, 0, 255);
+
+ ctx.reset();
+ comparePixel(ctx, 50, 50, 0, 0, 0, 0);
+
+ ctx.setTransform(1.25, 0, 0, 1.25, 0, 0, extra);
+ ctx.fillRect(50, 50, 1, 1);
+ comparePixel(ctx, 50, 50, 0, 0, 0, 0);
+ }
+ },
+ {
+ tag: "shear",
+ test: function(ctx) {
+ comparePixel(ctx, 50, 50, 0, 0, 0, 0);
+ ctx.fillRect(50, 50, 1, 1);
+ comparePixel(ctx, 50, 50, 255, 0, 0, 255);
+
+ ctx.reset();
+ comparePixel(ctx, 50, 50, 0, 0, 0, 0);
+
+ ctx.shear(0.5, 0, extra);
+ ctx.fillRect(50, 50, 1, 1);
+ comparePixel(ctx, 50, 50, 0, 0, 0, 0);
+ }
+ },
+ {
+ tag: "strokeRect",
+ test: function(ctx) {
+ ctx.strokeRect(0, 0, 10, 10, extra);
+ comparePixel(ctx, 0, 0, 255, 0, 0, 255, 200);
+ }
+ },
+ {
+ tag: "strokeText",
+ test: function(ctx) {
+ ctx.font = "10px sans-serif";
+ ctx.strokeText("Hello", -1, 5, extra);
+ comparePixel(ctx, 0, 5, 255, 0, 0, 255, 200);
+ }
+ },
+ {
+ tag: "text",
+ test: function(ctx) {
+ ctx.font = "100px sans-serif";
+ ctx.text(".", -15, 8, extra);
+ ctx.fill();
+ comparePixel(ctx, 0, 0, 255, 0, 0, 255, 200);
+ }
+ },
+ {
+ tag: "transform",
+ test: function(ctx) {
+ comparePixel(ctx, 50, 50, 0, 0, 0, 0);
+ ctx.fillRect(50, 50, 1, 1);
+ comparePixel(ctx, 50, 50, 255, 0, 0, 255);
+
+ ctx.reset();
+ comparePixel(ctx, 50, 50, 0, 0, 0, 0);
+
+ ctx.transform(1.25, 0, 0, 1.25, 0, 0, extra);
+ ctx.fillRect(50, 50, 1, 1);
+ comparePixel(ctx, 50, 50, 0, 0, 0, 0);
+ }
+ },
+ {
+ tag: "translate",
+ test: function(ctx) {
+ comparePixel(ctx, 50, 50, 0, 0, 0, 0);
+ ctx.fillRect(50, 50, 1, 1);
+ comparePixel(ctx, 50, 50, 255, 0, 0, 255);
+
+ ctx.reset();
+ comparePixel(ctx, 50, 50, 0, 0, 0, 0);
+
+ ctx.translate(1, 1, extra);
+ ctx.fillRect(50, 50, 1, 1);
+ comparePixel(ctx, 50, 50, 0, 0, 0, 0);
+ }
+ }
+ ];
+ }
+
+ function test_extraArgumentsIgnored(data) {
+ var canvas = Qt.createQmlObject("import QtQuick 2.3; Canvas { onPaint: {} }", testCase);
+ verify(canvas);
+ canvas.width = 100;
+ canvas.height = 100;
+
+ var ctx = canvas.getContext("2d");
+
+ ctx.beginPath();
+ ctx.fillStyle = "red";
+ ctx.strokeStyle = "red";
+ data.test(ctx);
+
+ canvas.destroy();
+ }
}
diff --git a/tests/auto/quick/qquickdrag/tst_qquickdrag.cpp b/tests/auto/quick/qquickdrag/tst_qquickdrag.cpp
index 15282d4b02..410220899a 100644
--- a/tests/auto/quick/qquickdrag/tst_qquickdrag.cpp
+++ b/tests/auto/quick/qquickdrag/tst_qquickdrag.cpp
@@ -416,7 +416,7 @@ void tst_QQuickDrag::drop()
QCOMPARE(evaluate<bool>(item, "dragActive"), true);
QCOMPARE(evaluate<QObject *>(item, "Drag.target"), static_cast<QObject *>(&innerTarget));
QCOMPARE(evaluate<QObject *>(item, "dragTarget"), static_cast<QObject *>(&innerTarget));
- QCOMPARE(outerTarget.enterEvents, 1); QCOMPARE(outerTarget.leaveEvents, 0); QCOMPARE(outerTarget.dropEvents, 0);
+ QCOMPARE(outerTarget.enterEvents, 0); QCOMPARE(outerTarget.leaveEvents, 0); QCOMPARE(outerTarget.dropEvents, 0);
QCOMPARE(innerTarget.enterEvents, 1); QCOMPARE(innerTarget.leaveEvents, 0); QCOMPARE(innerTarget.dropEvents, 0);
innerTarget.reset(); outerTarget.reset();
@@ -425,7 +425,7 @@ void tst_QQuickDrag::drop()
QCOMPARE(evaluate<bool>(item, "dragActive"), false);
QCOMPARE(evaluate<QObject *>(item, "Drag.target"), static_cast<QObject *>(&innerTarget));
QCOMPARE(evaluate<QObject *>(item, "dragTarget"), static_cast<QObject *>(&innerTarget));
- QCOMPARE(outerTarget.enterEvents, 0); QCOMPARE(outerTarget.leaveEvents, 1); QCOMPARE(outerTarget.dropEvents, 0);
+ QCOMPARE(outerTarget.enterEvents, 0); QCOMPARE(outerTarget.leaveEvents, 0); QCOMPARE(outerTarget.dropEvents, 0);
QCOMPARE(innerTarget.enterEvents, 0); QCOMPARE(innerTarget.leaveEvents, 0); QCOMPARE(innerTarget.dropEvents, 1);
innerTarget.reset(); outerTarget.reset();
@@ -434,24 +434,13 @@ void tst_QQuickDrag::drop()
QCOMPARE(evaluate<bool>(item, "dragActive"), true);
QCOMPARE(evaluate<QObject *>(item, "Drag.target"), static_cast<QObject *>(&innerTarget));
QCOMPARE(evaluate<QObject *>(item, "dragTarget"), static_cast<QObject *>(&innerTarget));
- QCOMPARE(outerTarget.enterEvents, 1); QCOMPARE(outerTarget.leaveEvents, 0); QCOMPARE(outerTarget.dropEvents, 0);
+ QCOMPARE(outerTarget.enterEvents, 0); QCOMPARE(outerTarget.leaveEvents, 0); QCOMPARE(outerTarget.dropEvents, 0);
QCOMPARE(innerTarget.enterEvents, 1); QCOMPARE(innerTarget.leaveEvents, 0); QCOMPARE(innerTarget.dropEvents, 0);
- // Inner target declines the drop so it is propagated to the outer target.
- innerTarget.accept = false;
-
- innerTarget.reset(); outerTarget.reset();
- QCOMPARE(evaluate<bool>(item, "Drag.drop() == Qt.CopyAction"), true);
- QCOMPARE(evaluate<bool>(item, "Drag.active"), false);
- QCOMPARE(evaluate<bool>(item, "dragActive"), false);
- QCOMPARE(evaluate<QObject *>(item, "Drag.target"), static_cast<QObject *>(&outerTarget));
- QCOMPARE(evaluate<QObject *>(item, "dragTarget"), static_cast<QObject *>(&outerTarget));
- QCOMPARE(outerTarget.enterEvents, 0); QCOMPARE(outerTarget.leaveEvents, 0); QCOMPARE(outerTarget.dropEvents, 1);
- QCOMPARE(innerTarget.enterEvents, 0); QCOMPARE(innerTarget.leaveEvents, 0); QCOMPARE(innerTarget.dropEvents, 1);
-
+ evaluate<void>(item, "Drag.active = false");
// Inner target doesn't accept enter so drop goes directly to outer.
- innerTarget.accept = true;
+ innerTarget.accept = false;
innerTarget.setFlags(QQuickItem::Flags());
innerTarget.reset(); outerTarget.reset();
@@ -584,10 +573,9 @@ void tst_QQuickDrag::move()
QCoreApplication::processEvents();
QCOMPARE(evaluate<QObject *>(item, "Drag.target"), static_cast<QObject *>(&rightTarget));
QCOMPARE(evaluate<QObject *>(item, "dragTarget"), static_cast<QObject *>(&rightTarget));
- QCOMPARE(outerTarget.enterEvents, 0); QCOMPARE(outerTarget.leaveEvents, 0); QCOMPARE(outerTarget.moveEvents, 1);
+ QCOMPARE(outerTarget.enterEvents, 0); QCOMPARE(outerTarget.leaveEvents, 0); QCOMPARE(outerTarget.moveEvents, 0);
QCOMPARE(leftTarget .enterEvents, 0); QCOMPARE(leftTarget .leaveEvents, 0); QCOMPARE(leftTarget .moveEvents, 0);
QCOMPARE(rightTarget.enterEvents, 1); QCOMPARE(rightTarget.leaveEvents, 0); QCOMPARE(rightTarget.moveEvents, 0);
- QCOMPARE(outerTarget.position.x(), qreal(75)); QCOMPARE(outerTarget.position.y(), qreal(50));
QCOMPARE(rightTarget.position.x(), qreal(5)); QCOMPARE(rightTarget.position.y(), qreal(15));
// Move into the left target.
@@ -596,10 +584,9 @@ void tst_QQuickDrag::move()
QCoreApplication::processEvents();
QCOMPARE(evaluate<QObject *>(item, "Drag.target"), static_cast<QObject *>(&leftTarget));
QCOMPARE(evaluate<QObject *>(item, "dragTarget"), static_cast<QObject *>(&leftTarget));
- QCOMPARE(outerTarget.enterEvents, 0); QCOMPARE(outerTarget.leaveEvents, 0); QCOMPARE(outerTarget.moveEvents, 1);
+ QCOMPARE(outerTarget.enterEvents, 0); QCOMPARE(outerTarget.leaveEvents, 0); QCOMPARE(outerTarget.moveEvents, 0);
QCOMPARE(leftTarget .enterEvents, 1); QCOMPARE(leftTarget .leaveEvents, 0); QCOMPARE(leftTarget .moveEvents, 0);
QCOMPARE(rightTarget.enterEvents, 0); QCOMPARE(rightTarget.leaveEvents, 1); QCOMPARE(rightTarget.moveEvents, 0);
- QCOMPARE(outerTarget.position.x(), qreal(25)); QCOMPARE(outerTarget.position.y(), qreal(50));
QCOMPARE(leftTarget.position.x(), qreal(25)); QCOMPARE(leftTarget.position.y(), qreal(15));
// Move within the left target.
diff --git a/tests/auto/quick/qquickdroparea/tst_qquickdroparea.cpp b/tests/auto/quick/qquickdroparea/tst_qquickdroparea.cpp
index b65e766190..375613e3c7 100644
--- a/tests/auto/quick/qquickdroparea/tst_qquickdroparea.cpp
+++ b/tests/auto/quick/qquickdroparea/tst_qquickdroparea.cpp
@@ -84,6 +84,7 @@ private slots:
void position_external();
void drop_internal();
// void drop_external();
+ void competingDrags();
void simultaneousDrags();
private:
@@ -767,6 +768,50 @@ void tst_QQuickDropArea::drop_internal()
//{
//}
+void tst_QQuickDropArea::competingDrags()
+{
+ QQuickWindow window;
+ QQmlComponent component(&engine);
+ component.setData(
+ "import QtQuick 2.0\n"
+ "DropArea {\n"
+ "width: 100; height: 100\n"
+ "objectName: \"dropArea1\"\n"
+ "property string statuslol\n"
+ "onEntered: { statuslol = 'parent' }\n"
+ "DropArea {\n"
+ "objectName: \"dropArea2\"\n"
+ "width: 100; height: 100\n"
+ "property bool acceptsEnters: true\n"
+ "onEntered: { parent.statuslol = 'son'; drag.accepted = acceptsEnters; }\n"
+ "}\n"
+ "Item {\n"
+ "objectName: \"dragItem\"\n"
+ "x: 50; y: 50\n"
+ "width: 10; height: 10\n"
+ "}\n"
+ "}\n", QUrl());
+
+ QScopedPointer<QObject> object(component.create());
+ QQuickItem *dropArea1 = qobject_cast<QQuickItem *>(object.data());
+ QVERIFY(dropArea1);
+ dropArea1->setParentItem(window.contentItem());
+
+ QQuickItem *dropArea2 = dropArea1->findChild<QQuickItem *>("dropArea2");
+ QVERIFY(dropArea2);
+
+ QQuickItem *dragItem = dropArea1->findChild<QQuickItem *>("dragItem");
+ QVERIFY(dragItem);
+
+ QCOMPARE(evaluate<QString>(dropArea1, "statuslol"), QStringLiteral(""));
+ evaluate<void>(dragItem, "Drag.active = true");
+ QCOMPARE(evaluate<QString>(dropArea1, "statuslol"), QStringLiteral("son"));
+ evaluate<void>(dragItem, "Drag.active = false");
+ evaluate<void>(dropArea2, "acceptsEnters = false");
+ evaluate<void>(dragItem, "Drag.active = true");
+ QCOMPARE(evaluate<QString>(dropArea1, "statuslol"), QStringLiteral("parent"));
+}
+
void tst_QQuickDropArea::simultaneousDrags()
{
QQuickWindow window;
@@ -777,6 +822,7 @@ void tst_QQuickDropArea::simultaneousDrags()
"property int enterEvents: 0\n"
"property int exitEvents: 0\n"
"width: 100; height: 100\n"
+ "objectName: \"dropArea1\"\n"
"keys: [\"red\", \"text/x-red\"]\n"
"onEntered: {++enterEvents}\n"
"onExited: {++exitEvents}\n"
@@ -827,8 +873,8 @@ void tst_QQuickDropArea::simultaneousDrags()
evaluate<void>(dropArea1, "{ enterEvents = 0; exitEvents = 0 }");
evaluate<void>(dropArea2, "{ enterEvents = 0; exitEvents = 0 }");
evaluate<void>(dragItem1, "Drag.active = true");
- QCOMPARE(evaluate<bool>(dropArea1, "containsDrag"), true);
- QCOMPARE(evaluate<int>(dropArea1, "enterEvents"), 1);
+ QCOMPARE(evaluate<bool>(dropArea1, "containsDrag"), false);
+ QCOMPARE(evaluate<int>(dropArea1, "enterEvents"), 0);
QCOMPARE(evaluate<int>(dropArea1, "exitEvents"), 0);
QCOMPARE(evaluate<bool>(dropArea2, "containsDrag"), true);
QCOMPARE(evaluate<int>(dropArea2, "enterEvents"), 1);
@@ -837,32 +883,33 @@ void tst_QQuickDropArea::simultaneousDrags()
evaluate<void>(dropArea1, "{ enterEvents = 0; exitEvents = 0 }");
evaluate<void>(dropArea2, "{ enterEvents = 0; exitEvents = 0 }");
evaluate<void>(dragItem2, "Drag.active = true");
+ //DropArea discards events if already contains something being dragged in
QCOMPARE(evaluate<bool>(dropArea1, "containsDrag"), true);
- QCOMPARE(evaluate<int>(dropArea1, "enterEvents"), 0);
+ QCOMPARE(evaluate<int>(dropArea1, "enterEvents"), 1);
QCOMPARE(evaluate<int>(dropArea1, "exitEvents"), 0);
QCOMPARE(evaluate<bool>(dropArea2, "containsDrag"), true);
QCOMPARE(evaluate<int>(dropArea2, "enterEvents"), 0);
QCOMPARE(evaluate<int>(dropArea2, "exitEvents"), 0);
evaluate<void>(dragItem2, "Drag.active = false");
- QCOMPARE(evaluate<bool>(dropArea1, "containsDrag"), true);
- QCOMPARE(evaluate<int>(dropArea1, "enterEvents"), 0);
- QCOMPARE(evaluate<int>(dropArea1, "exitEvents"), 0);
+ QCOMPARE(evaluate<bool>(dropArea1, "containsDrag"), false);
+ QCOMPARE(evaluate<int>(dropArea1, "enterEvents"), 1);
+ QCOMPARE(evaluate<int>(dropArea1, "exitEvents"), 1);
QCOMPARE(evaluate<bool>(dropArea2, "containsDrag"), true);
QCOMPARE(evaluate<int>(dropArea2, "enterEvents"), 0);
QCOMPARE(evaluate<int>(dropArea2, "exitEvents"), 0);
evaluate<void>(dragItem2, "Drag.active = true");
QCOMPARE(evaluate<bool>(dropArea1, "containsDrag"), true);
- QCOMPARE(evaluate<int>(dropArea1, "enterEvents"), 0);
- QCOMPARE(evaluate<int>(dropArea1, "exitEvents"), 0);
+ QCOMPARE(evaluate<int>(dropArea1, "enterEvents"), 2);
+ QCOMPARE(evaluate<int>(dropArea1, "exitEvents"), 1);
QCOMPARE(evaluate<bool>(dropArea2, "containsDrag"), true);
QCOMPARE(evaluate<int>(dropArea2, "enterEvents"), 0);
QCOMPARE(evaluate<int>(dropArea2, "exitEvents"), 0);
evaluate<void>(dragItem1, "Drag.active = false");
- QCOMPARE(evaluate<bool>(dropArea1, "containsDrag"), false);
- QCOMPARE(evaluate<int>(dropArea1, "enterEvents"), 0);
+ QCOMPARE(evaluate<bool>(dropArea1, "containsDrag"), true);
+ QCOMPARE(evaluate<int>(dropArea1, "enterEvents"), 2);
QCOMPARE(evaluate<int>(dropArea1, "exitEvents"), 1);
QCOMPARE(evaluate<bool>(dropArea2, "containsDrag"), false);
QCOMPARE(evaluate<int>(dropArea2, "enterEvents"), 0);
@@ -873,7 +920,7 @@ void tst_QQuickDropArea::simultaneousDrags()
evaluate<void>(dragItem2, "Drag.active = false");
QCOMPARE(evaluate<bool>(dropArea1, "containsDrag"), false);
QCOMPARE(evaluate<int>(dropArea1, "enterEvents"), 0);
- QCOMPARE(evaluate<int>(dropArea1, "exitEvents"), 0);
+ QCOMPARE(evaluate<int>(dropArea1, "exitEvents"), 1);
QCOMPARE(evaluate<bool>(dropArea2, "containsDrag"), false);
QCOMPARE(evaluate<int>(dropArea2, "enterEvents"), 0);
QCOMPARE(evaluate<int>(dropArea2, "exitEvents"), 0);
@@ -882,8 +929,8 @@ void tst_QQuickDropArea::simultaneousDrags()
evaluate<void>(dropArea1, "{ enterEvents = 0; exitEvents = 0 }");
evaluate<void>(dropArea2, "{ enterEvents = 0; exitEvents = 0 }");
evaluate<void>(dragItem1, "Drag.active = true");
- QCOMPARE(evaluate<bool>(dropArea1, "containsDrag"), true);
- QCOMPARE(evaluate<int>(dropArea1, "enterEvents"), 1);
+ QCOMPARE(evaluate<bool>(dropArea1, "containsDrag"), false);
+ QCOMPARE(evaluate<int>(dropArea1, "enterEvents"), 0);
QCOMPARE(evaluate<int>(dropArea1, "exitEvents"), 0);
QCOMPARE(evaluate<bool>(dropArea2, "containsDrag"), true);
QCOMPARE(evaluate<int>(dropArea2, "enterEvents"), 1);
@@ -892,32 +939,33 @@ void tst_QQuickDropArea::simultaneousDrags()
evaluate<void>(dropArea1, "{ enterEvents = 0; exitEvents = 0 }");
evaluate<void>(dropArea2, "{ enterEvents = 0; exitEvents = 0 }");
QWindowSystemInterface::handleDrag(&window, &data, QPoint(50, 50), Qt::CopyAction);
+ //Same as in the first case, dropArea2 already contains a drag, dropArea1 will get the event
QCOMPARE(evaluate<bool>(dropArea1, "containsDrag"), true);
- QCOMPARE(evaluate<int>(dropArea1, "enterEvents"), 0);
+ QCOMPARE(evaluate<int>(dropArea1, "enterEvents"), 1);
QCOMPARE(evaluate<int>(dropArea1, "exitEvents"), 0);
QCOMPARE(evaluate<bool>(dropArea2, "containsDrag"), true);
QCOMPARE(evaluate<int>(dropArea2, "enterEvents"), 0);
QCOMPARE(evaluate<int>(dropArea2, "exitEvents"), 0);
QWindowSystemInterface::handleDrag(&alternateWindow, &data, QPoint(50, 50), Qt::CopyAction);
- QCOMPARE(evaluate<bool>(dropArea1, "containsDrag"), true);
- QCOMPARE(evaluate<int>(dropArea1, "enterEvents"), 0);
- QCOMPARE(evaluate<int>(dropArea1, "exitEvents"), 0);
+ QCOMPARE(evaluate<bool>(dropArea1, "containsDrag"), false);
+ QCOMPARE(evaluate<int>(dropArea1, "enterEvents"), 1);
+ QCOMPARE(evaluate<int>(dropArea1, "exitEvents"), 1);
QCOMPARE(evaluate<bool>(dropArea2, "containsDrag"), true);
QCOMPARE(evaluate<int>(dropArea2, "enterEvents"), 0);
QCOMPARE(evaluate<int>(dropArea2, "exitEvents"), 0);
QWindowSystemInterface::handleDrag(&window, &data, QPoint(50, 50), Qt::CopyAction);
QCOMPARE(evaluate<bool>(dropArea1, "containsDrag"), true);
- QCOMPARE(evaluate<int>(dropArea1, "enterEvents"), 0);
- QCOMPARE(evaluate<int>(dropArea1, "exitEvents"), 0);
+ QCOMPARE(evaluate<int>(dropArea1, "enterEvents"), 2);
+ QCOMPARE(evaluate<int>(dropArea1, "exitEvents"), 1);
QCOMPARE(evaluate<bool>(dropArea2, "containsDrag"), true);
QCOMPARE(evaluate<int>(dropArea2, "enterEvents"), 0);
QCOMPARE(evaluate<int>(dropArea2, "exitEvents"), 0);
evaluate<void>(dragItem1, "Drag.active = false");
- QCOMPARE(evaluate<bool>(dropArea1, "containsDrag"), false);
- QCOMPARE(evaluate<int>(dropArea1, "enterEvents"), 0);
+ QCOMPARE(evaluate<bool>(dropArea1, "containsDrag"), true);
+ QCOMPARE(evaluate<int>(dropArea1, "enterEvents"), 2);
QCOMPARE(evaluate<int>(dropArea1, "exitEvents"), 1);
QCOMPARE(evaluate<bool>(dropArea2, "containsDrag"), false);
QCOMPARE(evaluate<int>(dropArea2, "enterEvents"), 0);
@@ -928,7 +976,7 @@ void tst_QQuickDropArea::simultaneousDrags()
QWindowSystemInterface::handleDrag(&alternateWindow, &data, QPoint(50, 50), Qt::CopyAction);
QCOMPARE(evaluate<bool>(dropArea1, "containsDrag"), false);
QCOMPARE(evaluate<int>(dropArea1, "enterEvents"), 0);
- QCOMPARE(evaluate<int>(dropArea1, "exitEvents"), 0);
+ QCOMPARE(evaluate<int>(dropArea1, "exitEvents"), 1);
QCOMPARE(evaluate<bool>(dropArea2, "containsDrag"), false);
QCOMPARE(evaluate<int>(dropArea2, "enterEvents"), 0);
QCOMPARE(evaluate<int>(dropArea2, "exitEvents"), 0);
@@ -937,8 +985,8 @@ void tst_QQuickDropArea::simultaneousDrags()
evaluate<void>(dropArea1, "{ enterEvents = 0; exitEvents = 0 }");
evaluate<void>(dropArea2, "{ enterEvents = 0; exitEvents = 0 }");
QWindowSystemInterface::handleDrag(&window, &data, QPoint(50, 50), Qt::CopyAction);
- QCOMPARE(evaluate<bool>(dropArea1, "containsDrag"), true);
- QCOMPARE(evaluate<int>(dropArea1, "enterEvents"), 1);
+ QCOMPARE(evaluate<bool>(dropArea1, "containsDrag"), false);
+ QCOMPARE(evaluate<int>(dropArea1, "enterEvents"), 0);
QCOMPARE(evaluate<int>(dropArea1, "exitEvents"), 0);
QCOMPARE(evaluate<bool>(dropArea2, "containsDrag"), true);
QCOMPARE(evaluate<int>(dropArea2, "enterEvents"), 1);
@@ -948,31 +996,31 @@ void tst_QQuickDropArea::simultaneousDrags()
evaluate<void>(dropArea2, "{ enterEvents = 0; exitEvents = 0 }");
evaluate<void>(dragItem2, "Drag.active = true");
QCOMPARE(evaluate<bool>(dropArea1, "containsDrag"), true);
- QCOMPARE(evaluate<int>(dropArea1, "enterEvents"), 0);
+ QCOMPARE(evaluate<int>(dropArea1, "enterEvents"), 1);
QCOMPARE(evaluate<int>(dropArea1, "exitEvents"), 0);
QCOMPARE(evaluate<bool>(dropArea2, "containsDrag"), true);
QCOMPARE(evaluate<int>(dropArea2, "enterEvents"), 0);
QCOMPARE(evaluate<int>(dropArea2, "exitEvents"), 0);
evaluate<void>(dragItem2, "Drag.active = false");
- QCOMPARE(evaluate<bool>(dropArea1, "containsDrag"), true);
- QCOMPARE(evaluate<int>(dropArea1, "enterEvents"), 0);
- QCOMPARE(evaluate<int>(dropArea1, "exitEvents"), 0);
+ QCOMPARE(evaluate<bool>(dropArea1, "containsDrag"), false);
+ QCOMPARE(evaluate<int>(dropArea1, "enterEvents"), 1);
+ QCOMPARE(evaluate<int>(dropArea1, "exitEvents"), 1);
QCOMPARE(evaluate<bool>(dropArea2, "containsDrag"), true);
QCOMPARE(evaluate<int>(dropArea2, "enterEvents"), 0);
QCOMPARE(evaluate<int>(dropArea2, "exitEvents"), 0);
evaluate<void>(dragItem2, "Drag.active = true");
QCOMPARE(evaluate<bool>(dropArea1, "containsDrag"), true);
- QCOMPARE(evaluate<int>(dropArea1, "enterEvents"), 0);
- QCOMPARE(evaluate<int>(dropArea1, "exitEvents"), 0);
+ QCOMPARE(evaluate<int>(dropArea1, "enterEvents"), 2);
+ QCOMPARE(evaluate<int>(dropArea1, "exitEvents"), 1);
QCOMPARE(evaluate<bool>(dropArea2, "containsDrag"), true);
QCOMPARE(evaluate<int>(dropArea2, "enterEvents"), 0);
QCOMPARE(evaluate<int>(dropArea2, "exitEvents"), 0);
QWindowSystemInterface::handleDrag(&alternateWindow, &data, QPoint(50, 50), Qt::CopyAction);
- QCOMPARE(evaluate<bool>(dropArea1, "containsDrag"), false);
- QCOMPARE(evaluate<int>(dropArea1, "enterEvents"), 0);
+ QCOMPARE(evaluate<bool>(dropArea1, "containsDrag"), true);
+ QCOMPARE(evaluate<int>(dropArea1, "enterEvents"), 2);
QCOMPARE(evaluate<int>(dropArea1, "exitEvents"), 1);
QCOMPARE(evaluate<bool>(dropArea2, "containsDrag"), false);
QCOMPARE(evaluate<int>(dropArea2, "enterEvents"), 0);
@@ -983,7 +1031,7 @@ void tst_QQuickDropArea::simultaneousDrags()
evaluate<void>(dragItem2, "Drag.active = false");
QCOMPARE(evaluate<bool>(dropArea1, "containsDrag"), false);
QCOMPARE(evaluate<int>(dropArea1, "enterEvents"), 0);
- QCOMPARE(evaluate<int>(dropArea1, "exitEvents"), 0);
+ QCOMPARE(evaluate<int>(dropArea1, "exitEvents"), 1);
QCOMPARE(evaluate<bool>(dropArea2, "containsDrag"), false);
QCOMPARE(evaluate<int>(dropArea2, "enterEvents"), 0);
QCOMPARE(evaluate<int>(dropArea2, "exitEvents"), 0);
diff --git a/tests/auto/quick/qquickflickable/data/nestedClickThenFlick.qml b/tests/auto/quick/qquickflickable/data/nestedClickThenFlick.qml
new file mode 100644
index 0000000000..619ab6d1dc
--- /dev/null
+++ b/tests/auto/quick/qquickflickable/data/nestedClickThenFlick.qml
@@ -0,0 +1,39 @@
+import QtQuick 2.0
+
+Flickable {
+ property bool pressed: ma.pressed
+ width: 240
+ height: 320
+ contentWidth: 480
+ contentHeight: 320
+ flickableDirection: Flickable.HorizontalFlick
+ pressDelay: 50
+ Rectangle {
+ anchors.fill: parent
+ anchors.margins: 50
+ color: "yellow"
+
+ }
+
+ onMovingChanged: console.log("outer moving", moving)
+
+ Flickable {
+ objectName: "innerFlickable"
+ anchors.fill: parent
+ flickableDirection: Flickable.VerticalFlick
+ contentWidth: 480
+ contentHeight: 1480
+ pressDelay: 50
+ Rectangle {
+ anchors.fill: parent
+ anchors.margins: 100
+ color: ma.pressed ? 'blue' : 'green'
+ }
+ MouseArea {
+ id: ma
+ objectName: "mouseArea"
+ anchors.fill: parent
+ }
+ }
+}
+
diff --git a/tests/auto/quick/qquickflickable/tst_qquickflickable.cpp b/tests/auto/quick/qquickflickable/tst_qquickflickable.cpp
index 8ab86bf2d3..80aaf5895f 100644
--- a/tests/auto/quick/qquickflickable/tst_qquickflickable.cpp
+++ b/tests/auto/quick/qquickflickable/tst_qquickflickable.cpp
@@ -75,6 +75,7 @@ private slots:
void flickDeceleration();
void pressDelay();
void nestedPressDelay();
+ void nestedClickThenFlick();
void flickableDirection();
void resizeContent();
void returnToBounds();
@@ -100,7 +101,7 @@ private slots:
void pressDelayWithLoader();
private:
- void flickWithTouch(QWindow *window, QTouchDevice *touchDevice, const QPoint &from, const QPoint &to);
+ void flickWithTouch(QQuickWindow *window, QTouchDevice *touchDevice, const QPoint &from, const QPoint &to);
QQmlEngine engine;
};
@@ -513,6 +514,51 @@ void tst_qquickflickable::nestedPressDelay()
QTest::mouseRelease(window.data(), Qt::LeftButton, 0, QPoint(90, 150));
}
+// QTBUG-37316
+void tst_qquickflickable::nestedClickThenFlick()
+{
+ QScopedPointer<QQuickView> window(new QQuickView);
+ window->setSource(testFileUrl("nestedClickThenFlick.qml"));
+ QTRY_COMPARE(window->status(), QQuickView::Ready);
+ QQuickViewTestUtil::centerOnScreen(window.data());
+ QQuickViewTestUtil::moveMouseAway(window.data());
+ window->show();
+ QVERIFY(QTest::qWaitForWindowExposed(window.data()));
+ QVERIFY(window->rootObject() != 0);
+
+ QQuickFlickable *outer = qobject_cast<QQuickFlickable*>(window->rootObject());
+ QVERIFY(outer != 0);
+
+ QQuickFlickable *inner = window->rootObject()->findChild<QQuickFlickable*>("innerFlickable");
+ QVERIFY(inner != 0);
+
+ QTest::mousePress(window.data(), Qt::LeftButton, 0, QPoint(150, 150));
+
+ // the MouseArea is not pressed immediately
+ QVERIFY(outer->property("pressed").toBool() == false);
+ QTRY_VERIFY(outer->property("pressed").toBool() == true);
+
+ QTest::mouseRelease(window.data(), Qt::LeftButton, 0, QPoint(150, 150));
+
+ QVERIFY(outer->property("pressed").toBool() == false);
+
+ // Dragging inner Flickable should work
+ QTest::mousePress(window.data(), Qt::LeftButton, 0, QPoint(80, 150));
+ // the MouseArea is not pressed immediately
+
+ QVERIFY(outer->property("pressed").toBool() == false);
+
+ QTest::mouseMove(window.data(), QPoint(80, 148));
+ QTest::mouseMove(window.data(), QPoint(80, 140));
+ QTest::mouseMove(window.data(), QPoint(80, 120));
+ QTest::mouseMove(window.data(), QPoint(80, 100));
+
+ QVERIFY(outer->property("moving").toBool() == false);
+ QVERIFY(inner->property("moving").toBool() == true);
+
+ QTest::mouseRelease(window.data(), Qt::LeftButton, 0, QPoint(80, 100));
+}
+
void tst_qquickflickable::flickableDirection()
{
QQmlComponent component(&engine);
@@ -1349,20 +1395,18 @@ void tst_qquickflickable::flickTwiceUsingTouches()
QTRY_VERIFY(contentYAfterSecondFlick > (contentYAfterFirstFlick + 80.0f));
}
-void tst_qquickflickable::flickWithTouch(QWindow *window, QTouchDevice *touchDevice, const QPoint &from, const QPoint &to)
+void tst_qquickflickable::flickWithTouch(QQuickWindow *window, QTouchDevice *touchDevice, const QPoint &from, const QPoint &to)
{
- QTest::touchEvent(window, touchDevice)
- .press(0, from, window);
- QTest::qWait(1);
+ QTest::touchEvent(window, touchDevice).press(0, from, window);
+ QQuickTouchUtils::flush(window);
+
QPoint diff = to - from;
for (int i = 1; i <= 8; ++i) {
- QTest::touchEvent(window, touchDevice)
- .move(0, from + i*diff/8, window);
- QTest::qWait(1);
+ QTest::touchEvent(window, touchDevice).move(0, from + i*diff/8, window);
+ QQuickTouchUtils::flush(window);
}
- QTest::touchEvent(window, touchDevice)
- .release(0, to, window);
- QTest::qWait(1);
+ QTest::touchEvent(window, touchDevice).release(0, to, window);
+ QQuickTouchUtils::flush(window);
}
void tst_qquickflickable::nestedStopAtBounds_data()
diff --git a/tests/auto/quick/qquickfontloader/tst_qquickfontloader.cpp b/tests/auto/quick/qquickfontloader/tst_qquickfontloader.cpp
index bcb496eab7..225cdb5389 100644
--- a/tests/auto/quick/qquickfontloader/tst_qquickfontloader.cpp
+++ b/tests/auto/quick/qquickfontloader/tst_qquickfontloader.cpp
@@ -75,8 +75,7 @@ private:
TestHTTPServer server;
};
-tst_qquickfontloader::tst_qquickfontloader() :
- server(SERVER_PORT)
+tst_qquickfontloader::tst_qquickfontloader()
{
}
@@ -84,7 +83,7 @@ void tst_qquickfontloader::initTestCase()
{
QQmlDataTest::initTestCase();
server.serveDirectory(dataDirectory());
- QVERIFY(server.isValid());
+ QVERIFY2(server.listen(SERVER_PORT), qPrintable(server.errorString()));
}
void tst_qquickfontloader::noFont()
@@ -131,7 +130,7 @@ void tst_qquickfontloader::localFont()
void tst_qquickfontloader::failLocalFont()
{
QString componentStr = "import QtQuick 2.0\nFontLoader { source: \"" + testFileUrl("dummy.ttf").toString() + "\" }";
- QTest::ignoreMessage(QtWarningMsg, QString("file::2:1: QML FontLoader: Cannot load font: \"" + testFileUrl("dummy.ttf").toString() + "\"").toUtf8().constData());
+ QTest::ignoreMessage(QtWarningMsg, QString("<Unknown File>:2:1: QML FontLoader: Cannot load font: \"" + testFileUrl("dummy.ttf").toString() + "\"").toUtf8().constData());
QQmlComponent component(&engine);
component.setData(componentStr.toLatin1(), QUrl::fromLocalFile(""));
QQuickFontLoader *fontObject = qobject_cast<QQuickFontLoader*>(component.create());
@@ -175,7 +174,7 @@ void tst_qquickfontloader::redirWebFont()
void tst_qquickfontloader::failWebFont()
{
QString componentStr = "import QtQuick 2.0\nFontLoader { source: \"" SERVER_ADDR "/nonexist.ttf\" }";
- QTest::ignoreMessage(QtWarningMsg, "file::2:1: QML FontLoader: Cannot load font: \"" SERVER_ADDR "/nonexist.ttf\"");
+ QTest::ignoreMessage(QtWarningMsg, "<Unknown File>:2:1: QML FontLoader: Cannot load font: \"" SERVER_ADDR "/nonexist.ttf\"");
QQmlComponent component(&engine);
component.setData(componentStr.toLatin1(), QUrl::fromLocalFile(""));
QQuickFontLoader *fontObject = qobject_cast<QQuickFontLoader*>(component.create());
diff --git a/tests/auto/quick/qquickfontmetrics/qquickfontmetrics.pro b/tests/auto/quick/qquickfontmetrics/qquickfontmetrics.pro
new file mode 100644
index 0000000000..452dd70bd3
--- /dev/null
+++ b/tests/auto/quick/qquickfontmetrics/qquickfontmetrics.pro
@@ -0,0 +1,10 @@
+CONFIG += testcase
+TARGET = tst_quickfontmetrics
+osx:CONFIG -= app_bundle
+
+SOURCES += tst_quickfontmetrics.cpp
+
+CONFIG += parallel_test
+
+QT += core gui qml quick-private testlib
+DEFINES += QT_DISABLE_DEPRECATED_BEFORE=0
diff --git a/tests/auto/quick/qquickfontmetrics/tst_quickfontmetrics.cpp b/tests/auto/quick/qquickfontmetrics/tst_quickfontmetrics.cpp
new file mode 100644
index 0000000000..5e64858955
--- /dev/null
+++ b/tests/auto/quick/qquickfontmetrics/tst_quickfontmetrics.cpp
@@ -0,0 +1,150 @@
+/****************************************************************************
+**
+** 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$
+**
+****************************************************************************/
+
+#include <QFont>
+#include <QFontDatabase>
+#include <QString>
+#include <QtTest>
+#include <QCoreApplication>
+
+#include <QtQuick/private/qquickfontmetrics_p.h>
+
+#include <QFontMetricsF>
+
+class tst_QuickFontMetrics : public QObject
+{
+ Q_OBJECT
+
+public:
+ tst_QuickFontMetrics();
+
+private Q_SLOTS:
+ void properties();
+ void functions_data();
+ void functions();
+};
+
+tst_QuickFontMetrics::tst_QuickFontMetrics()
+{
+}
+
+void tst_QuickFontMetrics::properties()
+{
+ QStringList families = QFontDatabase().families().mid(0, 10);
+ QQuickFontMetrics metrics;
+
+ foreach (const QString &family, families) {
+ QFont font(family);
+ QFontMetricsF expected(font);
+
+ QSignalSpy spy(&metrics, SIGNAL(fontChanged(QFont)));
+ metrics.setFont(font);
+ QCOMPARE(spy.count(), 1);
+
+ QCOMPARE(metrics.ascent(), expected.ascent());
+ QCOMPARE(metrics.descent(), expected.descent());
+ QCOMPARE(metrics.height(), expected.height());
+ QCOMPARE(metrics.leading(), expected.leading());
+ QCOMPARE(metrics.lineSpacing(), expected.lineSpacing());
+ QCOMPARE(metrics.minimumLeftBearing(), expected.minLeftBearing());
+ QCOMPARE(metrics.minimumRightBearing(), expected.minRightBearing());
+ QCOMPARE(metrics.maximumCharacterWidth(), expected.maxWidth());
+ QCOMPARE(metrics.xHeight(), expected.xHeight());
+ QCOMPARE(metrics.averageCharacterWidth(), expected.averageCharWidth());
+ QCOMPARE(metrics.underlinePosition(), expected.underlinePos());
+ QCOMPARE(metrics.overlinePosition(), expected.overlinePos());
+ QCOMPARE(metrics.strikeOutPosition(), expected.strikeOutPos());
+ QCOMPARE(metrics.lineWidth(), expected.lineWidth());
+ }
+}
+
+Q_DECLARE_METATYPE(Qt::TextElideMode)
+
+void tst_QuickFontMetrics::functions_data()
+{
+ QTest::addColumn<QString>("text");
+ QTest::addColumn<Qt::TextElideMode>("mode");
+ QTest::addColumn<qreal>("width");
+ QTest::addColumn<int>("flags");
+
+ QStringList strings;
+ strings << QString()
+ << QString::fromLatin1("")
+ << QString::fromLatin1("0")
+ << QString::fromLatin1("@@@@@@@")
+ << QString::fromLatin1("Hello");
+
+ QVector<Qt::TextElideMode> elideModes;
+ elideModes << Qt::ElideLeft << Qt::ElideMiddle << Qt::ElideRight << Qt::ElideNone;
+
+ for (int stringIndex = 0; stringIndex < strings.size(); ++stringIndex) {
+ const QString string = strings.at(stringIndex);
+
+ for (int elideModeIndex = 0; elideModeIndex < elideModes.size(); ++elideModeIndex) {
+ Qt::TextElideMode elideMode = static_cast<Qt::TextElideMode>(elideModes.at(elideModeIndex));
+
+ for (qreal width = 0; width < 100; width += 20) {
+ const QString tag = QString::fromLatin1("string=%1, mode=%2, width=%3").arg(string).arg(elideMode).arg(width);
+ QTest::newRow(qPrintable(tag)) << QString() << elideMode << width << 0;
+ }
+ }
+ }
+}
+
+void tst_QuickFontMetrics::functions()
+{
+ QFETCH(QString, text);
+ QFETCH(Qt::TextElideMode, mode);
+ QFETCH(qreal, width);
+ QFETCH(int, flags);
+
+ QQuickFontMetrics metrics;
+ QFontMetricsF expected = QFontMetricsF(QFont());
+
+ QCOMPARE(metrics.elidedText(text, mode, width, flags), expected.elidedText(text, mode, width, flags));
+ QCOMPARE(metrics.advanceWidth(text), expected.width(text));
+ QCOMPARE(metrics.boundingRect(text), expected.boundingRect(text));
+ QCOMPARE(metrics.tightBoundingRect(text), expected.tightBoundingRect(text));
+}
+
+QTEST_MAIN(tst_QuickFontMetrics)
+
+#include "tst_quickfontmetrics.moc"
diff --git a/tests/auto/quick/qquickframebufferobject/tst_qquickframebufferobject.cpp b/tests/auto/quick/qquickframebufferobject/tst_qquickframebufferobject.cpp
index b7b58c6d3d..35a01b33ba 100644
--- a/tests/auto/quick/qquickframebufferobject/tst_qquickframebufferobject.cpp
+++ b/tests/auto/quick/qquickframebufferobject/tst_qquickframebufferobject.cpp
@@ -45,6 +45,7 @@
#include <QtQuick/qquickview.h>
#include <QtGui/qopenglcontext.h>
#include <QtGui/qopenglframebufferobject.h>
+#include <QtGui/qopenglfunctions.h>
#include <QtQuick/QQuickFramebufferObject>
@@ -62,7 +63,7 @@ struct FrameInfo {
QSize fboSize;
} frameInfo;
-class ColorRenderer : public QQuickFramebufferObject::Renderer
+class ColorRenderer : public QQuickFramebufferObject::Renderer, protected QOpenGLFunctions
{
public:
void render();
@@ -142,6 +143,7 @@ void ColorRenderer::synchronize(QQuickFramebufferObject *item)
QOpenGLFramebufferObject *ColorRenderer::createFramebufferObject(const QSize &size)
{
+ initializeOpenGLFunctions();
frameInfo.createFBOCount++;
QOpenGLFramebufferObjectFormat format;
if (msaa)
diff --git a/tests/auto/quick/qquickimage/tst_qquickimage.cpp b/tests/auto/quick/qquickimage/tst_qquickimage.cpp
index 0e012c5c6a..a68a763887 100644
--- a/tests/auto/quick/qquickimage/tst_qquickimage.cpp
+++ b/tests/auto/quick/qquickimage/tst_qquickimage.cpp
@@ -153,9 +153,9 @@ void tst_qquickimage::imageSource_data()
QTest::newRow("local no cache") << testFileUrl("colors.png").toString() << 120.0 << 120.0 << false << false << false << "";
QTest::newRow("local async") << testFileUrl("colors1.png").toString() << 120.0 << 120.0 << false << true << true << "";
QTest::newRow("local not found") << testFileUrl("no-such-file.png").toString() << 0.0 << 0.0 << false
- << false << true << "file::2:1: QML Image: Cannot open: " + testFileUrl("no-such-file.png").toString();
+ << false << true << "<Unknown File>:2:1: QML Image: Cannot open: " + testFileUrl("no-such-file.png").toString();
QTest::newRow("local async not found") << testFileUrl("no-such-file-1.png").toString() << 0.0 << 0.0 << false
- << true << true << "file::2:1: QML Image: Cannot open: " + testFileUrl("no-such-file-1.png").toString();
+ << true << true << "<Unknown File>:2:1: QML Image: Cannot open: " + testFileUrl("no-such-file-1.png").toString();
QTest::newRow("remote") << SERVER_ADDR "/colors.png" << 120.0 << 120.0 << true << false << true << "";
QTest::newRow("remote redirected") << SERVER_ADDR "/oldcolors.png" << 120.0 << 120.0 << true << false << false << "";
if (QImageReader::supportedImageFormats().contains("svg"))
@@ -163,7 +163,7 @@ void tst_qquickimage::imageSource_data()
if (QImageReader::supportedImageFormats().contains("svgz"))
QTest::newRow("remote svgz") << SERVER_ADDR "/heart.svgz" << 550.0 << 500.0 << true << false << false << "";
QTest::newRow("remote not found") << SERVER_ADDR "/no-such-file.png" << 0.0 << 0.0 << true
- << false << true << "file::2:1: QML Image: Error downloading " SERVER_ADDR "/no-such-file.png - server replied: Not found";
+ << false << true << "<Unknown File>:2:1: QML Image: Error downloading " SERVER_ADDR "/no-such-file.png - server replied: Not found";
}
@@ -177,9 +177,9 @@ void tst_qquickimage::imageSource()
QFETCH(bool, cache);
QFETCH(QString, error);
- TestHTTPServer server(SERVER_PORT);
+ TestHTTPServer server;
if (remote) {
- QVERIFY(server.isValid());
+ QVERIFY2(server.listen(SERVER_PORT), qPrintable(server.errorString()));
server.serveDirectory(dataDirectory());
server.addRedirect("oldcolors.png", SERVER_ADDR "/colors.png");
}
@@ -263,8 +263,9 @@ void tst_qquickimage::resized()
void tst_qquickimage::preserveAspectRatio()
{
- QQuickView *window = new QQuickView(0);
+ QScopedPointer<QQuickView> window(new QQuickView(0));
window->show();
+ QVERIFY(QTest::qWaitForWindowExposed(window.data()));
window->setSource(testFileUrl("aspectratio.qml"));
QQuickImage *image = qobject_cast<QQuickImage*>(window->rootObject());
@@ -279,7 +280,6 @@ void tst_qquickimage::preserveAspectRatio()
QVERIFY(image != 0);
QCOMPARE(image->height(), 60.);
QCOMPARE(image->width(), 60.);
- delete window;
}
void tst_qquickimage::smooth()
@@ -312,7 +312,7 @@ void tst_qquickimage::mirror()
QWindow dummy; // On BlackBerry first window is always full screen,
dummy.showFullScreen(); // so make test window a second window.
#endif
- QQuickView *window = new QQuickView;
+ QScopedPointer<QQuickView> window(new QQuickView);
window->setSource(testFileUrl("mirror.qml"));
QQuickImage *obj = window->rootObject()->findChild<QQuickImage*>("image");
@@ -321,11 +321,10 @@ void tst_qquickimage::mirror()
obj->setFillMode(fillMode);
obj->setProperty("mirror", true);
window->showNormal();
- QVERIFY(QTest::qWaitForWindowExposed(window));
+ QVERIFY(QTest::qWaitForWindowExposed(window.data()));
QImage screenshot = window->grabWindow();
screenshots[fillMode] = screenshot;
- delete window;
}
foreach (QQuickImage::FillMode fillMode, fillModes) {
@@ -529,8 +528,8 @@ void tst_qquickimage::noLoading()
{
qRegisterMetaType<QQuickImageBase::Status>();
- TestHTTPServer server(SERVER_PORT);
- QVERIFY(server.isValid());
+ TestHTTPServer server;
+ QVERIFY2(server.listen(SERVER_PORT), qPrintable(server.errorString()));
server.serveDirectory(dataDirectory());
server.addRedirect("oldcolors.png", SERVER_ADDR "/colors.png");
@@ -644,10 +643,10 @@ void tst_qquickimage::sourceSize_QTBUG_14303()
void tst_qquickimage::sourceSize_QTBUG_16389()
{
- QQuickView *window = new QQuickView(0);
+ QScopedPointer<QQuickView> window(new QQuickView(0));
window->setSource(testFileUrl("qtbug_16389.qml"));
window->show();
- qApp->processEvents();
+ QVERIFY(QTest::qWaitForWindowExposed(window.data()));
QQuickImage *image = findItem<QQuickImage>(window->rootObject(), "iconImage");
QQuickItem *handle = findItem<QQuickItem>(window->rootObject(), "blueHandle");
@@ -663,16 +662,15 @@ void tst_qquickimage::sourceSize_QTBUG_16389()
QCOMPARE(image->sourceSize().height(), 200);
QCOMPARE(image->paintedWidth(), 20.0);
QCOMPARE(image->paintedHeight(), 20.0);
-
- delete window;
}
// QTBUG-15690
void tst_qquickimage::nullPixmapPaint()
{
- QQuickView *window = new QQuickView(0);
+ QScopedPointer<QQuickView> window(new QQuickView(0));
window->setSource(testFileUrl("nullpixmap.qml"));
window->show();
+ QVERIFY(QTest::qWaitForWindowExposed(window.data()));
QQuickImage *image = qobject_cast<QQuickImage*>(window->rootObject());
QTRY_VERIFY(image != 0);
@@ -681,23 +679,20 @@ void tst_qquickimage::nullPixmapPaint()
QQmlTestMessageHandler messageHandler;
// used to print "QTransform::translate with NaN called"
QPixmap pm = QPixmap::fromImage(window->grabWindow());
- const QStringList glErrors = messageHandler.messages().filter(QLatin1String("QGLContext::makeCurrent(): Failed."), Qt::CaseInsensitive);
- QVERIFY2(glErrors.size() == messageHandler.messages().size(), qPrintable(messageHandler.messageString()));
+ QVERIFY2(messageHandler.messages().size() == 0, qPrintable(messageHandler.messageString()));
delete image;
-
- delete window;
}
void tst_qquickimage::imageCrash_QTBUG_22125()
{
- TestHTTPServer server(SERVER_PORT);
- QVERIFY(server.isValid());
+ TestHTTPServer server;
+ QVERIFY2(server.listen(SERVER_PORT), qPrintable(server.errorString()));
server.serveDirectory(dataDirectory(), TestHTTPServer::Delay);
{
QQuickView view(testFileUrl("qtbug_22125.qml"));
view.show();
- qApp->processEvents();
+ QVERIFY(QTest::qWaitForWindowExposed(&view));
qApp->processEvents();
// shouldn't crash when the view drops out of scope due to
// QQuickPixmapData attempting to dereference a pointer to
@@ -739,14 +734,14 @@ void tst_qquickimage::sourceSize()
QFETCH(qreal, implicitWidth);
QFETCH(qreal, implicitHeight);
- QQuickView *window = new QQuickView(0);
+ QScopedPointer<QQuickView> window(new QQuickView(0));
QQmlContext *ctxt = window->rootContext();
ctxt->setContextProperty("srcWidth", sourceWidth);
ctxt->setContextProperty("srcHeight", sourceHeight);
window->setSource(testFileUrl("sourceSize.qml"));
window->show();
- qApp->processEvents();
+ QVERIFY(QTest::qWaitForWindowExposed(window.data()));
QQuickImage *image = qobject_cast<QQuickImage*>(window->rootObject());
QVERIFY(image);
@@ -755,14 +750,12 @@ void tst_qquickimage::sourceSize()
QCOMPARE(image->sourceSize().height(), sourceHeight);
QCOMPARE(image->implicitWidth(), implicitWidth);
QCOMPARE(image->implicitHeight(), implicitHeight);
-
- delete window;
}
void tst_qquickimage::sourceSizeChanges()
{
- TestHTTPServer server(14449);
- QVERIFY(server.isValid());
+ TestHTTPServer server;
+ QVERIFY2(server.listen(14449), qPrintable(server.errorString()));
server.serveDirectory(dataDirectory());
QQmlEngine engine;
@@ -827,8 +820,8 @@ void tst_qquickimage::sourceSizeChanges()
void tst_qquickimage::progressAndStatusChanges()
{
- TestHTTPServer server(14449);
- QVERIFY(server.isValid());
+ TestHTTPServer server;
+ QVERIFY2(server.listen(14449), qPrintable(server.errorString()));
server.serveDirectory(dataDirectory());
QQmlEngine engine;
@@ -935,8 +928,8 @@ void tst_qquickimage::correctStatus()
void tst_qquickimage::highdpi()
{
- TestHTTPServer server(14449);
- QVERIFY(server.isValid());
+ TestHTTPServer server;
+ QVERIFY2(server.listen(SERVER_PORT), qPrintable(server.errorString()));
server.serveDirectory(dataDirectory());
QString componentStr = "import QtQuick 2.0\nImage { source: srcImage ; }";
diff --git a/tests/auto/quick/qquickimageprovider/tst_qquickimageprovider.cpp b/tests/auto/quick/qquickimageprovider/tst_qquickimageprovider.cpp
index 48af48b17b..be302241da 100644
--- a/tests/auto/quick/qquickimageprovider/tst_qquickimageprovider.cpp
+++ b/tests/auto/quick/qquickimageprovider/tst_qquickimageprovider.cpp
@@ -206,11 +206,11 @@ void tst_qquickimageprovider::fillRequestTestsData(const QString &id)
QTest::newRow(QTest::toString(id + " missing"))
<< "image://test/no-such-file.png" << "no-such-file.png" << "" << QSize(100,100)
- << "file::2:1: QML Image: Failed to get image from provider: image://test/no-such-file.png";
+ << "<Unknown File>:2:1: QML Image: Failed to get image from provider: image://test/no-such-file.png";
QTest::newRow(QTest::toString(id + " unknown provider"))
<< "image://bogus/exists.png" << "" << "" << QSize()
- << "file::2:1: QML Image: Invalid image provider: image://bogus/exists.png";
+ << "<Unknown File>:2:1: QML Image: Invalid image provider: image://bogus/exists.png";
}
void tst_qquickimageprovider::runTest(bool async, QQuickImageProvider *provider)
@@ -364,7 +364,7 @@ void tst_qquickimageprovider::removeProvider()
// remove the provider and confirm
QString fileName = newImageFileName();
- QString error("file::2:1: QML Image: Invalid image provider: " + fileName);
+ QString error("<Unknown File>:2:1: QML Image: Invalid image provider: " + fileName);
QTest::ignoreMessage(QtWarningMsg, error.toUtf8());
engine.removeImageProvider("test");
diff --git a/tests/auto/quick/qquickitem/qquickitem.pro b/tests/auto/quick/qquickitem/qquickitem.pro
index d4bd0874d8..1d8ae0148b 100644
--- a/tests/auto/quick/qquickitem/qquickitem.pro
+++ b/tests/auto/quick/qquickitem/qquickitem.pro
@@ -3,6 +3,7 @@ TARGET = tst_qquickitem
SOURCES += tst_qquickitem.cpp
include (../../shared/util.pri)
+include (../shared/util.pri)
macx:CONFIG -= app_bundle
diff --git a/tests/auto/quick/qquickitem/tst_qquickitem.cpp b/tests/auto/quick/qquickitem/tst_qquickitem.cpp
index 2db510a69e..5993008c4a 100644
--- a/tests/auto/quick/qquickitem/tst_qquickitem.cpp
+++ b/tests/auto/quick/qquickitem/tst_qquickitem.cpp
@@ -51,6 +51,8 @@
#include <QTimer>
#include <QQmlEngine>
#include "../../shared/util.h"
+#include "../shared/viewtestutil.h"
+#include <QSignalSpy>
class TestItem : public QQuickItem
{
@@ -171,6 +173,8 @@ private slots:
void visualParentOwnership();
void visualParentOwnershipWindow();
+ void testSGInitializeAndInvalidate();
+
private:
enum PaintOrderOp {
@@ -1313,6 +1317,7 @@ void tst_qquickitem::touchEventAcceptIgnore()
item->touchEventReached = false;
bool accepted = window.event(&event);
+ QQuickTouchUtils::flush(&window);
QVERIFY(item->touchEventReached);
@@ -1336,6 +1341,7 @@ void tst_qquickitem::touchEventAcceptIgnore()
item->touchEventReached = false;
bool accepted = window.event(&event);
+ QQuickTouchUtils::flush(&window);
QCOMPARE(item->touchEventReached, itemSupportsTouch);
@@ -1359,6 +1365,7 @@ void tst_qquickitem::touchEventAcceptIgnore()
item->touchEventReached = false;
bool accepted = window.event(&event);
+ QQuickTouchUtils::flush(&window);
QCOMPARE(item->touchEventReached, itemSupportsTouch);
@@ -1879,6 +1886,37 @@ void tst_qquickitem::visualParentOwnershipWindow()
}
}
+void tst_qquickitem::testSGInitializeAndInvalidate()
+{
+ for (int i=0; i<2; ++i) {
+ QScopedPointer<QQuickView> view(new QQuickView());
+
+ QQuickItem *item = new QQuickItem();
+
+ int expected;
+ if (i == 0) {
+ // First iteration, item has contents and should get signals
+ expected = 1;
+ item->setFlag(QQuickItem::ItemHasContents, true);
+ } else {
+ // Second iteration, item does not have content and will not get signals
+ expected = 0;
+ }
+
+ QSignalSpy initializeSpy(item, SIGNAL(sceneGraphInitialized()));
+ QSignalSpy invalidateSpy(item, SIGNAL(sceneGraphInvalidated()));
+ item->setParentItem(view->contentItem());
+ view->show();
+
+ QVERIFY(QTest::qWaitForWindowExposed(view.data()));
+ QCOMPARE(initializeSpy.size(), expected);
+
+ delete view.take();
+ QCOMPARE(invalidateSpy.size(), expected);
+ }
+
+}
+
QTEST_MAIN(tst_qquickitem)
#include "tst_qquickitem.moc"
diff --git a/tests/auto/quick/qquickitem2/data/grabToImage.qml b/tests/auto/quick/qquickitem2/data/grabToImage.qml
new file mode 100644
index 0000000000..9f25210ee2
--- /dev/null
+++ b/tests/auto/quick/qquickitem2/data/grabToImage.qml
@@ -0,0 +1,60 @@
+/****************************************************************************
+**
+** 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.0
+
+Item {
+ width: 320
+ height: 480
+ Rectangle {
+ objectName: "myItem";
+ width: 100
+ height: 100
+ color: "red"
+ Rectangle {
+ anchors.right: parent.right
+ anchors.bottom: parent.bottom
+ width: 10
+ height: 10
+ color: "blue"
+ }
+ }
+}
diff --git a/tests/auto/quick/qquickitem2/tst_qquickitem.cpp b/tests/auto/quick/qquickitem2/tst_qquickitem.cpp
index bcfafac93b..1eb9bb0cf2 100644
--- a/tests/auto/quick/qquickitem2/tst_qquickitem.cpp
+++ b/tests/auto/quick/qquickitem2/tst_qquickitem.cpp
@@ -43,6 +43,7 @@
#include <QtQml/qqmlengine.h>
#include <QtQml/qqmlcomponent.h>
#include <QtQml/qqmlcontext.h>
+#include <QtQuick/qquickitemgrabresult.h>
#include <QtQuick/qquickview.h>
#include <QtGui/private/qinputmethod_p.h>
#include <QtQuick/private/qquickrectangle_p.h>
@@ -91,6 +92,7 @@ private slots:
void keyNavigation_RightToLeft();
void keyNavigation_skipNotVisible();
void keyNavigation_implicitSetting();
+ void keyNavigation_focusReason();
void layoutMirroring();
void layoutMirroringIllegalParent();
void smooth();
@@ -120,6 +122,8 @@ private slots:
void contains();
void childAt();
+ void grab();
+
private:
QQmlEngine engine;
bool qt_tab_all_widgets() {
@@ -215,6 +219,21 @@ public:
int mKey;
};
+class FocusEventFilter : public QObject
+{
+protected:
+ bool eventFilter(QObject *watched, QEvent *event) {
+ if ((event->type() == QEvent::FocusIn) || (event->type() == QEvent::FocusOut)) {
+ QFocusEvent *focusEvent = static_cast<QFocusEvent *>(event);
+ lastFocusReason = focusEvent->reason();
+ return false;
+ } else
+ return QObject::eventFilter(watched, event);
+ }
+public:
+ Qt::FocusReason lastFocusReason;
+};
+
QML_DECLARE_TYPE(KeyTestItem);
class HollowTestItem : public QQuickItem
@@ -1613,7 +1632,7 @@ void tst_QQuickItem::layoutMirroringIllegalParent()
{
QQmlComponent component(&engine);
component.setData("import QtQuick 2.0; QtObject { LayoutMirroring.enabled: true; LayoutMirroring.childrenInherit: true }", QUrl::fromLocalFile(""));
- QTest::ignoreMessage(QtWarningMsg, "file::1:21: QML QtObject: LayoutDirection attached property only works with Items");
+ QTest::ignoreMessage(QtWarningMsg, "<Unknown File>:1:21: QML QtObject: LayoutDirection attached property only works with Items");
QObject *object = component.create();
QVERIFY(object != 0);
}
@@ -1961,6 +1980,62 @@ void tst_QQuickItem::keyNavigation_implicitSetting()
delete window;
}
+void tst_QQuickItem::keyNavigation_focusReason()
+{
+ QQuickView *window = new QQuickView(0);
+ window->setBaseSize(QSize(240,320));
+
+ FocusEventFilter focusEventFilter;
+
+ window->setSource(testFileUrl("keynavigationtest.qml"));
+ window->show();
+ window->requestActivate();
+
+ QVERIFY(QTest::qWaitForWindowActive(window));
+ QVERIFY(QGuiApplication::focusWindow() == window);
+
+ // install event filter on first item
+ QQuickItem *item = findItem<QQuickItem>(window->rootObject(), "item1");
+ QVERIFY(item);
+ QVERIFY(item->hasActiveFocus());
+ item->installEventFilter(&focusEventFilter);
+
+ //install event filter on second item
+ item = findItem<QQuickItem>(window->rootObject(), "item2");
+ QVERIFY(item);
+ item->installEventFilter(&focusEventFilter);
+
+ //install event filter on third item
+ item = findItem<QQuickItem>(window->rootObject(), "item3");
+ QVERIFY(item);
+ item->installEventFilter(&focusEventFilter);
+
+ //install event filter on last item
+ item = findItem<QQuickItem>(window->rootObject(), "item4");
+ QVERIFY(item);
+ item->installEventFilter(&focusEventFilter);
+
+ // tab
+ QKeyEvent key = QKeyEvent(QEvent::KeyPress, Qt::Key_Tab, Qt::NoModifier, "", false, 1);
+ QGuiApplication::sendEvent(window, &key);
+ QVERIFY(key.isAccepted());
+ QCOMPARE(focusEventFilter.lastFocusReason, Qt::TabFocusReason);
+
+ // backtab
+ key = QKeyEvent(QEvent::KeyPress, Qt::Key_Backtab, Qt::NoModifier, "", false, 1);
+ QGuiApplication::sendEvent(window, &key);
+ QVERIFY(key.isAccepted());
+ QCOMPARE(focusEventFilter.lastFocusReason, Qt::BacktabFocusReason);
+
+ // some arbitrary cursor key
+ key = QKeyEvent(QEvent::KeyPress, Qt::Key_Right, Qt::NoModifier, "", false, 1);
+ QGuiApplication::sendEvent(window, &key);
+ QVERIFY(key.isAccepted());
+ QCOMPARE(focusEventFilter.lastFocusReason, Qt::OtherFocusReason);
+
+ delete window;
+}
+
void tst_QQuickItem::smooth()
{
QQmlComponent component(&engine);
@@ -2737,6 +2812,44 @@ void tst_QQuickItem::childAt()
QCOMPARE(parent.childAt(300, 300), static_cast<QQuickItem *>(0));
}
+void tst_QQuickItem::grab()
+{
+#if defined(Q_OS_WIN32) && defined(QT_OPENGL_ES_2_ANGLE)
+ QSKIP("QTBUG-40649");
+#endif
+ QQuickView view;
+ view.setSource(testFileUrl("grabToImage.qml"));
+ view.show();
+ QTest::qWaitForWindowExposed(&view);
+
+ QQuickItem *root = qobject_cast<QQuickItem *>(view.rootObject());
+ QVERIFY(root);
+ QQuickItem *item = root->findChild<QQuickItem *>("myItem");
+ QVERIFY(item);
+
+ { // Default size (item is 100x100)
+ QSharedPointer<QQuickItemGrabResult> result = item->grabToImage();
+ QSignalSpy spy(result.data(), SIGNAL(ready()));
+ QTRY_VERIFY(spy.size() > 0);
+ QVERIFY(!result->url().isEmpty());
+ QImage image = result->image();
+ QCOMPARE(image.pixel(0, 0), qRgb(255, 0, 0));
+ QCOMPARE(image.pixel(99, 99), qRgb(0, 0, 255));
+ }
+
+ { // Smaller size
+ QSharedPointer<QQuickItemGrabResult> result = item->grabToImage(QSize(50, 50));
+ QVERIFY(!result.isNull());
+ QSignalSpy spy(result.data(), SIGNAL(ready()));
+ QTRY_VERIFY(spy.size() > 0);
+ QVERIFY(!result->url().isEmpty());
+ QImage image = result->image();
+ QCOMPARE(image.pixel(0, 0), qRgb(255, 0, 0));
+ QCOMPARE(image.pixel(49, 49), qRgb(0, 0, 255));
+ }
+
+}
+
QTEST_MAIN(tst_QQuickItem)
diff --git a/tests/auto/quick/qquickitemlayer/tst_qquickitemlayer.cpp b/tests/auto/quick/qquickitemlayer/tst_qquickitemlayer.cpp
index b5980929a6..2bef45056f 100644
--- a/tests/auto/quick/qquickitemlayer/tst_qquickitemlayer.cpp
+++ b/tests/auto/quick/qquickitemlayer/tst_qquickitemlayer.cpp
@@ -44,6 +44,7 @@
#include <QtQuick/qquickitem.h>
#include <QtQuick/qquickview.h>
#include <QtGui/qopenglcontext.h>
+#include <QtGui/qopenglfunctions.h>
#include "../../shared/util.h"
@@ -107,13 +108,13 @@ tst_QQuickItemLayer::tst_QQuickItemLayer()
window.create();
context.create();
context.makeCurrent(&window);
- const char *vendor = (const char *)glGetString(GL_VENDOR);
- const char *renderer = (const char *)glGetString(GL_RENDERER);
+ const char *vendor = (const char *)context.functions()->glGetString(GL_VENDOR);
+ const char *renderer = (const char *)context.functions()->glGetString(GL_RENDERER);
m_isMesaSoftwareRasterizer = strcmp(vendor, "Mesa Project") == 0
&& strcmp(renderer, "Software Rasterizer") == 0;
if (m_isMesaSoftwareRasterizer) {
// Expects format: <OpenGL version> Mesa <Mesa version>[-devel] [...]
- const char *version = (const char *)glGetString(GL_VERSION);
+ const char *version = (const char *)context.functions()->glGetString(GL_VERSION);
QList<QByteArray> list = QByteArray(version).split(' ');
if (list.size() >= 3) {
list = list.at(2).split('-').at(0).split('.');
@@ -137,6 +138,9 @@ tst_QQuickItemLayer::tst_QQuickItemLayer()
void tst_QQuickItemLayer::layerSmooth()
{
+#if defined(Q_OS_WIN32) && defined(QT_OPENGL_ES_2_ANGLE)
+ QSKIP("QTBUG-40649");
+#endif
if (m_isMesaSoftwareRasterizer && m_mesaVersion < QT_VERSION_CHECK(7, 11, 0))
QSKIP("Mesa Software Rasterizer below version 7.11 does not render this test correctly.");
QImage fb = runTest("Smooth.qml");
@@ -156,6 +160,9 @@ void tst_QQuickItemLayer::layerSmooth()
void tst_QQuickItemLayer::layerEnabled()
{
+#if defined(Q_OS_WIN32) && defined(QT_OPENGL_ES_2_ANGLE)
+ QSKIP("QTBUG-40649");
+#endif
if (m_isMesaSoftwareRasterizer && m_mesaVersion < QT_VERSION_CHECK(7, 11, 0))
QSKIP("Mesa Software Rasterizer below version 7.11 does not render this test correctly.");
QImage fb = runTest("Enabled.qml");
@@ -172,6 +179,9 @@ void tst_QQuickItemLayer::layerEnabled()
void tst_QQuickItemLayer::layerMipmap()
{
+#if defined(Q_OS_WIN32) && defined(QT_OPENGL_ES_2_ANGLE)
+ QSKIP("QTBUG-40649");
+#endif
if (m_isMesaSoftwareRasterizer)
QSKIP("Mipmapping does not work with the Mesa Software Rasterizer.");
QImage fb = runTest("Mipmap.qml");
@@ -186,6 +196,9 @@ void tst_QQuickItemLayer::layerMipmap()
void tst_QQuickItemLayer::layerEffect()
{
+#if defined(Q_OS_WIN32) && defined(QT_OPENGL_ES_2_ANGLE)
+ QSKIP("QTBUG-40649");
+#endif
if (m_isMesaSoftwareRasterizer && m_mesaVersion < QT_VERSION_CHECK(7, 11, 0))
QSKIP("Mesa Software Rasterizer below version 7.11 does not render this test correctly.");
QImage fb = runTest("Effect.qml");
@@ -200,6 +213,9 @@ void tst_QQuickItemLayer::layerEffect()
// a shader that pads transparent to blue. Everything else is red.
void tst_QQuickItemLayer::layerSourceRect()
{
+#if defined(Q_OS_WIN32) && defined(QT_OPENGL_ES_2_ANGLE)
+ QSKIP("QTBUG-40649");
+#endif
if (m_isMesaSoftwareRasterizer && m_mesaVersion < QT_VERSION_CHECK(7, 11, 0))
QSKIP("Mesa Software Rasterizer below version 7.11 does not render this test correctly.");
@@ -221,6 +237,9 @@ void tst_QQuickItemLayer::layerSourceRect()
// directly in a stand alone ShaderEffect
void tst_QQuickItemLayer::layerIsTextureProvider()
{
+#if defined(Q_OS_WIN32) && defined(QT_OPENGL_ES_2_ANGLE)
+ QSKIP("QTBUG-40649");
+#endif
if (m_isMesaSoftwareRasterizer && m_mesaVersion < QT_VERSION_CHECK(7, 11, 0))
QSKIP("Mesa Software Rasterizer below version 7.11 does not render this test correctly.");
QImage fb = runTest("TextureProvider.qml");
@@ -253,6 +272,9 @@ void tst_QQuickItemLayer::layerVisibility_data()
void tst_QQuickItemLayer::layerVisibility()
{
+#if defined(Q_OS_WIN32) && defined(QT_OPENGL_ES_2_ANGLE)
+ QSKIP("QTBUG-40649");
+#endif
if (m_isMesaSoftwareRasterizer && m_mesaVersion < QT_VERSION_CHECK(7, 11, 0))
QSKIP("Mesa Software Rasterizer below version 7.11 does not render this test correctly.");
@@ -301,6 +323,9 @@ void tst_QQuickItemLayer::layerZOrder_data()
void tst_QQuickItemLayer::layerZOrder()
{
+#if defined(Q_OS_WIN32) && defined(QT_OPENGL_ES_2_ANGLE)
+ QSKIP("QTBUG-40649");
+#endif
if (m_isMesaSoftwareRasterizer && m_mesaVersion < QT_VERSION_CHECK(7, 11, 0))
QSKIP("Mesa Software Rasterizer below version 7.11 does not render this test correctly.");
@@ -335,6 +360,9 @@ void tst_QQuickItemLayer::changeZOrder_data()
void tst_QQuickItemLayer::changeZOrder()
{
+#if defined(Q_OS_WIN32) && defined(QT_OPENGL_ES_2_ANGLE)
+ QSKIP("QTBUG-40649");
+#endif
if (m_isMesaSoftwareRasterizer && m_mesaVersion < QT_VERSION_CHECK(7, 11, 0))
QSKIP("Mesa Software Rasterizer below version 7.11 does not render this test correctly.");
@@ -403,6 +431,9 @@ void tst_QQuickItemLayer::disableLayer()
void tst_QQuickItemLayer::changeSamplerName()
{
+#if defined(Q_OS_WIN32) && defined(QT_OPENGL_ES_2_ANGLE)
+ QSKIP("QTBUG-40649");
+#endif
if (m_isMesaSoftwareRasterizer && m_mesaVersion < QT_VERSION_CHECK(7, 11, 0))
QSKIP("Mesa Software Rasterizer below version 7.11 does not render this test correctly.");
QImage fb = runTest("SamplerNameChange.qml");
@@ -411,6 +442,9 @@ void tst_QQuickItemLayer::changeSamplerName()
void tst_QQuickItemLayer::itemEffect()
{
+#if defined(Q_OS_WIN32) && defined(QT_OPENGL_ES_2_ANGLE)
+ QSKIP("QTBUG-40649");
+#endif
if (m_isMesaSoftwareRasterizer && m_mesaVersion < QT_VERSION_CHECK(7, 11, 0))
QSKIP("Mesa Software Rasterizer below version 7.11 does not render this test correctly.");
QImage fb = runTest("ItemEffect.qml");
diff --git a/tests/auto/quick/qquicklistview/data/sizeTransitions.qml b/tests/auto/quick/qquicklistview/data/sizeTransitions.qml
new file mode 100644
index 0000000000..6dfc5ee70a
--- /dev/null
+++ b/tests/auto/quick/qquicklistview/data/sizeTransitions.qml
@@ -0,0 +1,101 @@
+/****************************************************************************
+**
+** 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.2
+import QtQuick.Window 2.1
+
+Rectangle {
+ id: root
+ width: 500
+ height: 600
+ property int animationDuration: 10
+ property int itemHeight: 40
+
+ Rectangle {
+ id: sightingsListPanel
+ border.width: 2
+ border.color: "lightgray"
+ y: 200
+ anchors.fill: parent
+ anchors.topMargin: 200
+ anchors.leftMargin: 200
+ ListView {
+ id: list
+ objectName: "list"
+ orientation: topToBottom ? ListView.Vertical : ListView.Horizontal
+ property bool transitionFinished: false
+ property bool scriptActionExecuted : false
+ anchors { fill: parent; margins: parent.border.width; }
+ model: testModel
+ delegate: listDelegate
+ // clip when we have no animation running
+ clip: false
+ add: Transition {
+ id: trans
+ onRunningChanged: {
+ if (!running)
+ list.transitionFinished = true;
+ }
+ SequentialAnimation {
+ ParallelAnimation {
+ NumberAnimation { properties: "x"; from: -100; duration: root.animationDuration }
+ NumberAnimation { properties: "y"; from: -100; duration: root.animationDuration }
+ NumberAnimation { properties: "width"; from: 1; to: list.width; duration: root.animationDuration;}
+ // Commenting out the height animation and it works
+ NumberAnimation { properties: "height"; from: 1; to: root.itemHeight; duration: root.animationDuration }
+ }
+ ScriptAction { script: list.scriptActionExecuted = true;}
+ }
+
+ }
+ }
+ // Delegate for defining a template for an item in the list
+ Component {
+ id: listDelegate
+ Rectangle {
+ id: background
+ width: list.width
+ height: root.itemHeight
+ border.width: 2
+ radius: 3
+ }
+ }
+ }
+}
diff --git a/tests/auto/quick/qquicklistview/data/stickyPositioning-both.qml b/tests/auto/quick/qquicklistview/data/stickyPositioning-both.qml
new file mode 100644
index 0000000000..4bbe7a0053
--- /dev/null
+++ b/tests/auto/quick/qquicklistview/data/stickyPositioning-both.qml
@@ -0,0 +1,77 @@
+/****************************************************************************
+**
+** 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.4
+
+Rectangle {
+ width: 240
+ height: 320
+ ListView {
+ id: list
+ objectName: "list"
+ width: 100
+ height: 100
+ cacheBuffer: 0
+ anchors.centerIn: parent
+ model: testModel
+ orientation: testOrientation
+ layoutDirection: testLayoutDirection
+ verticalLayoutDirection: testVerticalLayoutDirection
+ delegate: Rectangle {
+ width: 10
+ height: 10
+ border.width: 1
+ border.color: "gray"
+ }
+ headerPositioning: ListView.PullBackHeader
+ header: Rectangle {
+ width: 10
+ height: 10
+ color: "red"
+ objectName: "header"
+ }
+ footerPositioning: ListView.PullBackFooter
+ footer: Rectangle {
+ width: 10
+ height: 10
+ color: "blue"
+ objectName: "footer"
+ }
+ }
+}
diff --git a/tests/auto/quick/qquicklistview/data/stickyPositioning-footer.qml b/tests/auto/quick/qquicklistview/data/stickyPositioning-footer.qml
new file mode 100644
index 0000000000..57773df37e
--- /dev/null
+++ b/tests/auto/quick/qquicklistview/data/stickyPositioning-footer.qml
@@ -0,0 +1,70 @@
+/****************************************************************************
+**
+** 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.4
+
+Rectangle {
+ width: 240
+ height: 320
+ ListView {
+ id: list
+ objectName: "list"
+ width: 100
+ height: 100
+ cacheBuffer: 0
+ anchors.centerIn: parent
+ model: testModel
+ orientation: testOrientation
+ layoutDirection: testLayoutDirection
+ verticalLayoutDirection: testVerticalLayoutDirection
+ delegate: Rectangle {
+ width: 10
+ height: 10
+ border.width: 1
+ border.color: "gray"
+ }
+ footerPositioning: ListView.PullBackFooter
+ footer: Rectangle {
+ width: 10
+ height: 10
+ color: "blue"
+ objectName: "footer"
+ }
+ }
+}
diff --git a/tests/auto/quick/qquicklistview/data/stickyPositioning-header.qml b/tests/auto/quick/qquicklistview/data/stickyPositioning-header.qml
new file mode 100644
index 0000000000..1ca9813baa
--- /dev/null
+++ b/tests/auto/quick/qquicklistview/data/stickyPositioning-header.qml
@@ -0,0 +1,70 @@
+/****************************************************************************
+**
+** 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.4
+
+Rectangle {
+ width: 240
+ height: 320
+ ListView {
+ id: list
+ objectName: "list"
+ width: 100
+ height: 100
+ cacheBuffer: 0
+ anchors.centerIn: parent
+ model: testModel
+ orientation: testOrientation
+ layoutDirection: testLayoutDirection
+ verticalLayoutDirection: testVerticalLayoutDirection
+ delegate: Rectangle {
+ width: 10
+ height: 10
+ border.width: 1
+ border.color: "gray"
+ }
+ headerPositioning: ListView.PullBackHeader
+ header: Rectangle {
+ width: 10
+ height: 10
+ color: "red"
+ objectName: "header"
+ }
+ }
+}
diff --git a/tests/auto/quick/qquicklistview/tst_qquicklistview.cpp b/tests/auto/quick/qquicklistview/tst_qquicklistview.cpp
index d22f3487da..50bf1e03f1 100644
--- a/tests/auto/quick/qquicklistview/tst_qquicklistview.cpp
+++ b/tests/auto/quick/qquicklistview/tst_qquicklistview.cpp
@@ -199,6 +199,9 @@ private slots:
void populateTransitions();
void populateTransitions_data();
+ void sizeTransitions();
+ void sizeTransitions_data();
+
void addTransitions();
void addTransitions_data();
void moveTransitions();
@@ -230,6 +233,9 @@ private slots:
void QTBUG_36481();
void QTBUG_35920();
+ void stickyPositioning();
+ void stickyPositioning_data();
+
void roundingErrors();
void roundingErrors_data();
@@ -5814,6 +5820,56 @@ void tst_QQuickListView::populateTransitions_data()
QTest::newRow("empty to start with, no populate") << false << false << false;
}
+
+/*
+ * Tests if the first visible item is not repositioned if the same item
+ * resized + changes position during a transition. The test does not test the
+ * actual position while it is transitioning (since its timing sensitive), but
+ * rather tests if the transition has reached its target state properly.
+ **/
+void tst_QQuickListView::sizeTransitions()
+{
+ QFETCH(bool, topToBottom);
+ QQuickView *window = getView();
+ QQmlContext *ctxt = window->rootContext();
+ QaimModel model;
+ ctxt->setContextProperty("testModel", &model);
+ ctxt->setContextProperty("topToBottom", topToBottom);
+ TestObject *testObject = new TestObject;
+ ctxt->setContextProperty("testObject", &model);
+ window->setSource(testFileUrl("sizeTransitions.qml"));
+ window->show();
+ QVERIFY(QTest::qWaitForWindowExposed(window));
+
+ QQuickListView *listview = findItem<QQuickListView>(window->rootObject(), "list");
+ QTRY_VERIFY(listview != 0);
+ QTRY_COMPARE(QQuickItemPrivate::get(listview)->polishScheduled, false);
+
+ // the following will start the transition
+ model.addItem(QLatin1String("Test"), "");
+
+ // This ensures early failure in case of failure (in which case
+ // transitionFinished == true and scriptActionExecuted == false)
+ QTRY_COMPARE(listview->property("scriptActionExecuted").toBool() ||
+ listview->property("transitionFinished").toBool(), true);
+ QCOMPARE(listview->property("scriptActionExecuted").toBool(), true);
+ QCOMPARE(listview->property("transitionFinished").toBool(), true);
+
+ releaseView(window);
+ delete testObject;
+}
+
+void tst_QQuickListView::sizeTransitions_data()
+{
+ QTest::addColumn<bool>("topToBottom");
+
+ QTest::newRow("TopToBottom")
+ << true;
+
+ QTest::newRow("LeftToRight")
+ << false;
+}
+
void tst_QQuickListView::addTransitions()
{
QFETCH(int, initialItemCount);
@@ -7266,6 +7322,412 @@ void tst_QQuickListView::QTBUG_35920()
QTest::mouseRelease(window.data(), Qt::LeftButton, 0, QPoint(10,100));
}
+Q_DECLARE_METATYPE(Qt::Orientation)
+
+void tst_QQuickListView::stickyPositioning()
+{
+ QFETCH(QString, fileName);
+
+ QFETCH(Qt::Orientation, orientation);
+ QFETCH(Qt::LayoutDirection, layoutDirection);
+ QFETCH(QQuickItemView::VerticalLayoutDirection, verticalLayoutDirection);
+
+ QFETCH(int, positionIndex);
+ QFETCH(QQuickItemView::PositionMode, positionMode);
+ QFETCH(QList<QPointF>, movement);
+
+ QFETCH(QPointF, headerPos);
+ QFETCH(QPointF, footerPos);
+
+ QQuickView *window = createView();
+
+ QaimModel model;
+ for (int i = 0; i < 20; i++)
+ model.addItem(QString::number(i), QString::number(i/10));
+
+ QQmlContext *ctxt = window->rootContext();
+ ctxt->setContextProperty("testModel", &model);
+ ctxt->setContextProperty("testOrientation", orientation);
+ ctxt->setContextProperty("testLayoutDirection", layoutDirection);
+ ctxt->setContextProperty("testVerticalLayoutDirection", verticalLayoutDirection);
+
+ window->setSource(testFileUrl(fileName));
+ window->show();
+ QVERIFY(QTest::qWaitForWindowExposed(window));
+
+ QQuickListView *listview = findItem<QQuickListView>(window->rootObject(), "list");
+ QVERIFY(listview);
+
+ QQuickItem *contentItem = listview->contentItem();
+ QVERIFY(contentItem);
+
+ listview->positionViewAtIndex(positionIndex, positionMode);
+
+ foreach (const QPointF &offset, movement) {
+ listview->setContentX(listview->contentX() + offset.x());
+ listview->setContentY(listview->contentY() + offset.y());
+ }
+
+ if (listview->header()) {
+ QQuickItem *headerItem = listview->headerItem();
+ QVERIFY(headerItem);
+ QPointF actualPos = listview->mapFromItem(contentItem, headerItem->position());
+ QCOMPARE(actualPos, headerPos);
+ }
+
+ if (listview->footer()) {
+ QQuickItem *footerItem = listview->footerItem();
+ QVERIFY(footerItem);
+ QPointF actualPos = listview->mapFromItem(contentItem, footerItem->position());
+ QCOMPARE(actualPos, footerPos);
+ }
+
+ delete window;
+}
+
+void tst_QQuickListView::stickyPositioning_data()
+{
+ qRegisterMetaType<Qt::Orientation>();
+ qRegisterMetaType<Qt::LayoutDirection>();
+ qRegisterMetaType<QQuickItemView::VerticalLayoutDirection>();
+ qRegisterMetaType<QQuickItemView::PositionMode>();
+
+ QTest::addColumn<QString>("fileName");
+
+ QTest::addColumn<Qt::Orientation>("orientation");
+ QTest::addColumn<Qt::LayoutDirection>("layoutDirection");
+ QTest::addColumn<QQuickItemView::VerticalLayoutDirection>("verticalLayoutDirection");
+
+ QTest::addColumn<int>("positionIndex");
+ QTest::addColumn<QQuickItemView::PositionMode>("positionMode");
+ QTest::addColumn<QList<QPointF> >("movement");
+
+ QTest::addColumn<QPointF>("headerPos");
+ QTest::addColumn<QPointF>("footerPos");
+
+ // header at the top
+ QTest::newRow("top header") << "stickyPositioning-header.qml"
+ << Qt::Vertical << Qt::LeftToRight << QQuickListView::TopToBottom
+ << 0 << QQuickItemView::Beginning << QList<QPointF>()
+ << QPointF(0,-10) << QPointF();
+
+ QTest::newRow("top header: 1/2 up") << "stickyPositioning-header.qml"
+ << Qt::Vertical << Qt::LeftToRight << QQuickListView::TopToBottom
+ << 1 << QQuickItemView::Beginning << (QList<QPointF>() << QPointF(0,-5))
+ << QPointF(0,-5) << QPointF();
+
+ QTest::newRow("top header: up") << "stickyPositioning-header.qml"
+ << Qt::Vertical << Qt::LeftToRight << QQuickListView::TopToBottom
+ << 2 << QQuickItemView::Beginning << (QList<QPointF>() << QPointF(0,-15))
+ << QPointF(0,0) << QPointF();
+
+ QTest::newRow("top header: 1/2 down") << "stickyPositioning-header.qml"
+ << Qt::Vertical << Qt::LeftToRight << QQuickListView::TopToBottom
+ << 3 << QQuickItemView::Beginning << (QList<QPointF>() << QPointF(0,-15) << QPointF(0,5))
+ << QPointF(0,-5) << QPointF();
+
+ QTest::newRow("top header: down") << "stickyPositioning-header.qml"
+ << Qt::Vertical << Qt::LeftToRight << QQuickListView::TopToBottom
+ << 4 << QQuickItemView::Beginning << (QList<QPointF>() << QPointF(0,-15) << QPointF(0,10))
+ << QPointF(0,-10) << QPointF();
+
+
+ // footer at the top
+ QTest::newRow("top footer") << "stickyPositioning-footer.qml"
+ << Qt::Vertical << Qt::LeftToRight << QQuickListView::BottomToTop
+ << 19 << QQuickItemView::End << QList<QPointF>()
+ << QPointF() << QPointF(0,-10);
+
+ QTest::newRow("top footer: 1/2 up") << "stickyPositioning-footer.qml"
+ << Qt::Vertical << Qt::LeftToRight << QQuickListView::BottomToTop
+ << 18 << QQuickItemView::End << (QList<QPointF>() << QPointF(0,-5))
+ << QPointF() << QPointF(0,-5);
+
+ QTest::newRow("top footer: up") << "stickyPositioning-footer.qml"
+ << Qt::Vertical << Qt::LeftToRight << QQuickListView::BottomToTop
+ << 17 << QQuickItemView::End << (QList<QPointF>() << QPointF(0,-15))
+ << QPointF() << QPointF(0,0);
+
+ QTest::newRow("top footer: 1/2 down") << "stickyPositioning-footer.qml"
+ << Qt::Vertical << Qt::LeftToRight << QQuickListView::BottomToTop
+ << 16 << QQuickItemView::End << (QList<QPointF>() << QPointF(0,-15) << QPointF(0,5))
+ << QPointF() << QPointF(0,-5);
+
+ QTest::newRow("top footer: down") << "stickyPositioning-footer.qml"
+ << Qt::Vertical << Qt::LeftToRight << QQuickListView::BottomToTop
+ << 15 << QQuickItemView::End << (QList<QPointF>() << QPointF(0,-15) << QPointF(0,10))
+ << QPointF() << QPointF(0,-10);
+
+
+ // header at the bottom
+ QTest::newRow("bottom header") << "stickyPositioning-header.qml"
+ << Qt::Vertical << Qt::LeftToRight << QQuickListView::BottomToTop
+ << 0 << QQuickItemView::Beginning << QList<QPointF>()
+ << QPointF(0,100) << QPointF();
+
+ QTest::newRow("bottom header: 1/2 down") << "stickyPositioning-header.qml"
+ << Qt::Vertical << Qt::LeftToRight << QQuickListView::BottomToTop
+ << 1 << QQuickItemView::Beginning << (QList<QPointF>() << QPointF(0,5))
+ << QPointF(0,95) << QPointF();
+
+ QTest::newRow("bottom header: down") << "stickyPositioning-header.qml"
+ << Qt::Vertical << Qt::LeftToRight << QQuickListView::BottomToTop
+ << 2 << QQuickItemView::Beginning << (QList<QPointF>() << QPointF(0,15))
+ << QPointF(0,90) << QPointF();
+
+ QTest::newRow("bottom header: 1/2 up") << "stickyPositioning-header.qml"
+ << Qt::Vertical << Qt::LeftToRight << QQuickListView::BottomToTop
+ << 3 << QQuickItemView::Beginning << (QList<QPointF>() << QPointF(0,15) << QPointF(0,-5))
+ << QPointF(0,95) << QPointF();
+
+ QTest::newRow("bottom header: up") << "stickyPositioning-header.qml"
+ << Qt::Vertical << Qt::LeftToRight << QQuickListView::BottomToTop
+ << 4 << QQuickItemView::Beginning << (QList<QPointF>() << QPointF(0,15) << QPointF(0,-10))
+ << QPointF(0,100) << QPointF();
+
+
+ // footer at the bottom
+ QTest::newRow("bottom footer") << "stickyPositioning-footer.qml"
+ << Qt::Vertical << Qt::LeftToRight << QQuickListView::TopToBottom
+ << 19 << QQuickItemView::End << QList<QPointF>()
+ << QPointF() << QPointF(0,100);
+
+ QTest::newRow("bottom footer: 1/2 down") << "stickyPositioning-footer.qml"
+ << Qt::Vertical << Qt::LeftToRight << QQuickListView::TopToBottom
+ << 18 << QQuickItemView::End << (QList<QPointF>() << QPointF(0,5))
+ << QPointF() << QPointF(0,95);
+
+ QTest::newRow("bottom footer: down") << "stickyPositioning-footer.qml"
+ << Qt::Vertical << Qt::LeftToRight << QQuickListView::TopToBottom
+ << 17 << QQuickItemView::End << (QList<QPointF>() << QPointF(0,15))
+ << QPointF() << QPointF(0,90);
+
+ QTest::newRow("bottom footer: 1/2 up") << "stickyPositioning-footer.qml"
+ << Qt::Vertical << Qt::LeftToRight << QQuickListView::TopToBottom
+ << 16 << QQuickItemView::End << (QList<QPointF>() << QPointF(0,15) << QPointF(0,-5))
+ << QPointF() << QPointF(0,95);
+
+ QTest::newRow("bottom footer: up") << "stickyPositioning-footer.qml"
+ << Qt::Vertical << Qt::LeftToRight << QQuickListView::TopToBottom
+ << 15 << QQuickItemView::End << (QList<QPointF>() << QPointF(0,15) << QPointF(0,-10))
+ << QPointF() << QPointF(0,100);
+
+
+ // header at the top (& footer at the bottom)
+ QTest::newRow("top header & bottom footer") << "stickyPositioning-both.qml"
+ << Qt::Vertical << Qt::LeftToRight << QQuickListView::TopToBottom
+ << 0 << QQuickItemView::Beginning << QList<QPointF>()
+ << QPointF(0,-10) << QPointF(0,90);
+
+ QTest::newRow("top header & bottom footer: 1/2 up") << "stickyPositioning-both.qml"
+ << Qt::Vertical << Qt::LeftToRight << QQuickListView::TopToBottom
+ << 1 << QQuickItemView::Beginning << (QList<QPointF>() << QPointF(0,-5))
+ << QPointF(0,-5) << QPointF(0,95);
+
+ QTest::newRow("top header & bottom footer: up") << "stickyPositioning-both.qml"
+ << Qt::Vertical << Qt::LeftToRight << QQuickListView::TopToBottom
+ << 2 << QQuickItemView::Beginning << (QList<QPointF>() << QPointF(0,-15))
+ << QPointF(0,0) << QPointF(0,100);
+
+ QTest::newRow("top header & bottom footer: 1/2 down") << "stickyPositioning-both.qml"
+ << Qt::Vertical << Qt::LeftToRight << QQuickListView::TopToBottom
+ << 3 << QQuickItemView::Beginning << (QList<QPointF>() << QPointF(0,-15) << QPointF(0,5))
+ << QPointF(0,-5) << QPointF(0,95);
+
+ QTest::newRow("top header & bottom footer: down") << "stickyPositioning-both.qml"
+ << Qt::Vertical << Qt::LeftToRight << QQuickListView::TopToBottom
+ << 4 << QQuickItemView::Beginning << (QList<QPointF>() << QPointF(0,-15) << QPointF(0,10))
+ << QPointF(0,-10) << QPointF(0,90);
+
+
+ // footer at the bottom (& header at the top)
+ QTest::newRow("bottom footer & top header") << "stickyPositioning-both.qml"
+ << Qt::Vertical << Qt::LeftToRight << QQuickListView::TopToBottom
+ << 1 << QQuickItemView::Beginning << QList<QPointF>()
+ << QPointF(0,-10) << QPointF(0,90);
+
+ QTest::newRow("bottom footer & top header: 1/2 down") << "stickyPositioning-both.qml"
+ << Qt::Vertical << Qt::LeftToRight << QQuickListView::TopToBottom
+ << 1 << QQuickItemView::Beginning << (QList<QPointF>() << QPointF(0,5))
+ << QPointF(0,-10) << QPointF(0,90);
+
+ QTest::newRow("bottom footer & top header: down") << "stickyPositioning-both.qml"
+ << Qt::Vertical << Qt::LeftToRight << QQuickListView::TopToBottom
+ << 2 << QQuickItemView::Beginning << (QList<QPointF>() << QPointF(0,15))
+ << QPointF(0,-10) << QPointF(0,90);
+
+ QTest::newRow("bottom footer & top header: 1/2 up") << "stickyPositioning-both.qml"
+ << Qt::Vertical << Qt::LeftToRight << QQuickListView::TopToBottom
+ << 3 << QQuickItemView::Beginning << (QList<QPointF>() << QPointF(0,15) << QPointF(0,-5))
+ << QPointF(0,-5) << QPointF(0,95);
+
+ QTest::newRow("bottom footer & top header: up") << "stickyPositioning-both.qml"
+ << Qt::Vertical << Qt::LeftToRight << QQuickListView::TopToBottom
+ << 4 << QQuickItemView::Beginning << (QList<QPointF>() << QPointF(0,15) << QPointF(0,-10))
+ << QPointF(0,0) << QPointF(0,100);
+
+ // header on the left
+ QTest::newRow("left header") << "stickyPositioning-header.qml"
+ << Qt::Horizontal << Qt::LeftToRight << QQuickListView::TopToBottom
+ << 0 << QQuickItemView::Beginning << QList<QPointF>()
+ << QPointF(-10,0) << QPointF();
+
+ QTest::newRow("left header: 1/2 left") << "stickyPositioning-header.qml"
+ << Qt::Horizontal << Qt::LeftToRight << QQuickListView::TopToBottom
+ << 1 << QQuickItemView::Beginning << (QList<QPointF>() << QPointF(-5,0))
+ << QPointF(-5,0) << QPointF();
+
+ QTest::newRow("left header: left") << "stickyPositioning-header.qml"
+ << Qt::Horizontal << Qt::LeftToRight << QQuickListView::TopToBottom
+ << 2 << QQuickItemView::Beginning << (QList<QPointF>() << QPointF(-15,0))
+ << QPointF(0,0) << QPointF();
+
+ QTest::newRow("left header: 1/2 right") << "stickyPositioning-header.qml"
+ << Qt::Horizontal << Qt::LeftToRight << QQuickListView::TopToBottom
+ << 3 << QQuickItemView::Beginning << (QList<QPointF>() << QPointF(-15,0) << QPointF(5,0))
+ << QPointF(-5,0) << QPointF();
+
+ QTest::newRow("left header: right") << "stickyPositioning-header.qml"
+ << Qt::Horizontal << Qt::LeftToRight << QQuickListView::TopToBottom
+ << 4 << QQuickItemView::Beginning << (QList<QPointF>() << QPointF(-15,0) << QPointF(10,0))
+ << QPointF(-10,0) << QPointF();
+
+
+ // footer on the left
+ QTest::newRow("left footer") << "stickyPositioning-footer.qml"
+ << Qt::Horizontal << Qt::RightToLeft << QQuickListView::TopToBottom
+ << 19 << QQuickItemView::End << QList<QPointF>()
+ << QPointF() << QPointF(-10,0);
+
+ QTest::newRow("left footer: 1/2 left") << "stickyPositioning-footer.qml"
+ << Qt::Horizontal << Qt::RightToLeft << QQuickListView::TopToBottom
+ << 18 << QQuickItemView::End << (QList<QPointF>() << QPointF(-5,0))
+ << QPointF() << QPointF(-5,0);
+
+ QTest::newRow("left footer: left") << "stickyPositioning-footer.qml"
+ << Qt::Horizontal << Qt::RightToLeft << QQuickListView::TopToBottom
+ << 17 << QQuickItemView::End << (QList<QPointF>() << QPointF(-15,0))
+ << QPointF() << QPointF(0,0);
+
+ QTest::newRow("left footer: 1/2 right") << "stickyPositioning-footer.qml"
+ << Qt::Horizontal << Qt::RightToLeft << QQuickListView::TopToBottom
+ << 16 << QQuickItemView::End << (QList<QPointF>() << QPointF(-15,0) << QPointF(5,0))
+ << QPointF() << QPointF(-5,0);
+
+ QTest::newRow("left footer: right") << "stickyPositioning-footer.qml"
+ << Qt::Horizontal << Qt::RightToLeft << QQuickListView::TopToBottom
+ << 15 << QQuickItemView::End << (QList<QPointF>() << QPointF(-15,0) << QPointF(10,0))
+ << QPointF() << QPointF(-10,0);
+
+
+ // header on the right
+ QTest::newRow("right header") << "stickyPositioning-header.qml"
+ << Qt::Horizontal << Qt::RightToLeft << QQuickListView::TopToBottom
+ << 0 << QQuickItemView::Beginning << QList<QPointF>()
+ << QPointF(100,0) << QPointF();
+
+ QTest::newRow("right header: 1/2 right") << "stickyPositioning-header.qml"
+ << Qt::Horizontal << Qt::RightToLeft << QQuickListView::TopToBottom
+ << 1 << QQuickItemView::Beginning << (QList<QPointF>() << QPointF(5,0))
+ << QPointF(95,0) << QPointF();
+
+ QTest::newRow("right header: right") << "stickyPositioning-header.qml"
+ << Qt::Horizontal << Qt::RightToLeft << QQuickListView::TopToBottom
+ << 2 << QQuickItemView::Beginning << (QList<QPointF>() << QPointF(15,0))
+ << QPointF(90,0) << QPointF();
+
+ QTest::newRow("right header: 1/2 left") << "stickyPositioning-header.qml"
+ << Qt::Horizontal << Qt::RightToLeft << QQuickListView::TopToBottom
+ << 3 << QQuickItemView::Beginning << (QList<QPointF>() << QPointF(15,0) << QPointF(-5,0))
+ << QPointF(95,0) << QPointF();
+
+ QTest::newRow("right header: left") << "stickyPositioning-header.qml"
+ << Qt::Horizontal << Qt::RightToLeft << QQuickListView::TopToBottom
+ << 4 << QQuickItemView::Beginning << (QList<QPointF>() << QPointF(15,0) << QPointF(-10,0))
+ << QPointF(100,0) << QPointF();
+
+
+ // footer on the right
+ QTest::newRow("right footer") << "stickyPositioning-footer.qml"
+ << Qt::Horizontal << Qt::LeftToRight << QQuickListView::TopToBottom
+ << 19 << QQuickItemView::End << QList<QPointF>()
+ << QPointF() << QPointF(100,0);
+
+ QTest::newRow("right footer: 1/2 right") << "stickyPositioning-footer.qml"
+ << Qt::Horizontal << Qt::LeftToRight << QQuickListView::TopToBottom
+ << 18 << QQuickItemView::End << (QList<QPointF>() << QPointF(5,0))
+ << QPointF() << QPointF(95,0);
+
+ QTest::newRow("right footer: right") << "stickyPositioning-footer.qml"
+ << Qt::Horizontal << Qt::LeftToRight << QQuickListView::TopToBottom
+ << 17 << QQuickItemView::End << (QList<QPointF>() << QPointF(15,0))
+ << QPointF() << QPointF(90,0);
+
+ QTest::newRow("right footer: 1/2 left") << "stickyPositioning-footer.qml"
+ << Qt::Horizontal << Qt::LeftToRight << QQuickListView::TopToBottom
+ << 16 << QQuickItemView::End << (QList<QPointF>() << QPointF(15,0) << QPointF(-5,0))
+ << QPointF() << QPointF(95,0);
+
+ QTest::newRow("right footer: left") << "stickyPositioning-footer.qml"
+ << Qt::Horizontal << Qt::LeftToRight << QQuickListView::TopToBottom
+ << 15 << QQuickItemView::End << (QList<QPointF>() << QPointF(15,0) << QPointF(-10,0))
+ << QPointF() << QPointF(100,0);
+
+
+ // header on the left (& footer on the right)
+ QTest::newRow("left header & right footer") << "stickyPositioning-both.qml"
+ << Qt::Horizontal << Qt::LeftToRight << QQuickListView::TopToBottom
+ << 0 << QQuickItemView::Beginning << QList<QPointF>()
+ << QPointF(-10,0) << QPointF(90,0);
+
+ QTest::newRow("left header & right footer: 1/2 left") << "stickyPositioning-both.qml"
+ << Qt::Horizontal << Qt::LeftToRight << QQuickListView::TopToBottom
+ << 1 << QQuickItemView::Beginning << (QList<QPointF>() << QPointF(-5,0))
+ << QPointF(-5,0) << QPointF(95,0);
+
+ QTest::newRow("left header & right footer: left") << "stickyPositioning-both.qml"
+ << Qt::Horizontal << Qt::LeftToRight << QQuickListView::TopToBottom
+ << 2 << QQuickItemView::Beginning << (QList<QPointF>() << QPointF(-15,0))
+ << QPointF(0,0) << QPointF(100,0);
+
+ QTest::newRow("left header & right footer: 1/2 right") << "stickyPositioning-both.qml"
+ << Qt::Horizontal << Qt::LeftToRight << QQuickListView::TopToBottom
+ << 3 << QQuickItemView::Beginning << (QList<QPointF>() << QPointF(-15,0) << QPointF(5,0))
+ << QPointF(-5,0) << QPointF(95,0);
+
+ QTest::newRow("left header & right footer: right") << "stickyPositioning-both.qml"
+ << Qt::Horizontal << Qt::LeftToRight << QQuickListView::TopToBottom
+ << 4 << QQuickItemView::Beginning << (QList<QPointF>() << QPointF(-15,0) << QPointF(10,0))
+ << QPointF(-10,0) << QPointF(90,0);
+
+
+ // footer on the right (& header on the left)
+ QTest::newRow("right footer & left header") << "stickyPositioning-both.qml"
+ << Qt::Horizontal << Qt::LeftToRight << QQuickListView::TopToBottom
+ << 1 << QQuickItemView::Beginning << QList<QPointF>()
+ << QPointF(-10,0) << QPointF(90,0);
+
+ QTest::newRow("right footer & left header: 1/2 right") << "stickyPositioning-both.qml"
+ << Qt::Horizontal << Qt::LeftToRight << QQuickListView::TopToBottom
+ << 1 << QQuickItemView::Beginning << (QList<QPointF>() << QPointF(5,0))
+ << QPointF(-10,0) << QPointF(90,0);
+
+ QTest::newRow("right footer & left header: right") << "stickyPositioning-both.qml"
+ << Qt::Horizontal << Qt::LeftToRight << QQuickListView::TopToBottom
+ << 2 << QQuickItemView::Beginning << (QList<QPointF>() << QPointF(15,0))
+ << QPointF(-10,0) << QPointF(90,0);
+
+ QTest::newRow("right footer & left header: 1/2 left") << "stickyPositioning-both.qml"
+ << Qt::Horizontal << Qt::LeftToRight << QQuickListView::TopToBottom
+ << 3 << QQuickItemView::Beginning << (QList<QPointF>() << QPointF(15,0) << QPointF(-5,0))
+ << QPointF(-5,0) << QPointF(95,0);
+
+ QTest::newRow("right footer & left header: left") << "stickyPositioning-both.qml"
+ << Qt::Horizontal << Qt::LeftToRight << QQuickListView::TopToBottom
+ << 4 << QQuickItemView::Beginning << (QList<QPointF>() << QPointF(15,0) << QPointF(-10,0))
+ << QPointF(0,0) << QPointF(100,0);
+}
+
void tst_QQuickListView::roundingErrors()
{
QFETCH(bool, pixelAligned);
diff --git a/tests/auto/quick/qquickloader/tst_qquickloader.cpp b/tests/auto/quick/qquickloader/tst_qquickloader.cpp
index 877bb59613..9ac2663f24 100644
--- a/tests/auto/quick/qquickloader/tst_qquickloader.cpp
+++ b/tests/auto/quick/qquickloader/tst_qquickloader.cpp
@@ -446,8 +446,8 @@ void tst_QQuickLoader::noResize()
void tst_QQuickLoader::networkRequestUrl()
{
- TestHTTPServer server(SERVER_PORT);
- QVERIFY(server.isValid());
+ TestHTTPServer server;
+ QVERIFY2(server.listen(SERVER_PORT), qPrintable(server.errorString()));
server.serveDirectory(dataDirectory());
QQmlComponent component(&engine);
@@ -470,8 +470,8 @@ void tst_QQuickLoader::networkRequestUrl()
/* XXX Component waits until all dependencies are loaded. Is this actually possible? */
void tst_QQuickLoader::networkComponent()
{
- TestHTTPServer server(SERVER_PORT);
- QVERIFY(server.isValid());
+ TestHTTPServer server;
+ QVERIFY2(server.listen(SERVER_PORT), qPrintable(server.errorString()));
server.serveDirectory(dataDirectory(), TestHTTPServer::Delay);
QQmlComponent component(&engine);
@@ -503,8 +503,8 @@ void tst_QQuickLoader::networkComponent()
void tst_QQuickLoader::failNetworkRequest()
{
- TestHTTPServer server(SERVER_PORT);
- QVERIFY(server.isValid());
+ TestHTTPServer server;
+ QVERIFY2(server.listen(SERVER_PORT), qPrintable(server.errorString()));
server.serveDirectory(dataDirectory());
QTest::ignoreMessage(QtWarningMsg, SERVER_ADDR "/IDontExist.qml: File not found");
@@ -718,8 +718,8 @@ void tst_QQuickLoader::initialPropertyValues()
QFETCH(QStringList, propertyNames);
QFETCH(QVariantList, propertyValues);
- TestHTTPServer server(SERVER_PORT);
- QVERIFY(server.isValid());
+ TestHTTPServer server;
+ QVERIFY2(server.listen(SERVER_PORT), qPrintable(server.errorString()));
server.serveDirectory(dataDirectory());
foreach (const QString &warning, expectedWarnings)
diff --git a/tests/auto/quick/qquickmousearea/data/containsPress.qml b/tests/auto/quick/qquickmousearea/data/containsPress.qml
new file mode 100644
index 0000000000..367c73c175
--- /dev/null
+++ b/tests/auto/quick/qquickmousearea/data/containsPress.qml
@@ -0,0 +1,20 @@
+import QtQuick 2.4
+
+Item {
+ width: 500
+ height: 500
+
+ Rectangle {
+ width: 300
+ height: 300
+ color: mouseArea.containsPress ? "red" : "grey"
+ x: 100
+ y: 100
+
+ MouseArea {
+ id: mouseArea
+ objectName: "mouseArea"
+ anchors.fill: parent
+ }
+ }
+}
diff --git a/tests/auto/quick/qquickmousearea/tst_qquickmousearea.cpp b/tests/auto/quick/qquickmousearea/tst_qquickmousearea.cpp
index d0a1c18885..75497a4b5f 100644
--- a/tests/auto/quick/qquickmousearea/tst_qquickmousearea.cpp
+++ b/tests/auto/quick/qquickmousearea/tst_qquickmousearea.cpp
@@ -86,6 +86,7 @@ private slots:
void resetDrag();
void dragging_data() { acceptedButton_data(); }
void dragging();
+ void dragSmoothed();
void dragThreshold();
void invalidDrag_data() { rejectedButton_data(); }
void invalidDrag();
@@ -122,6 +123,8 @@ private slots:
void moveAndReleaseWithoutPress();
void nestedStopAtBounds();
void nestedStopAtBounds_data();
+ void containsPress_data();
+ void containsPress();
private:
void acceptedButton_data();
@@ -334,6 +337,50 @@ void tst_QQuickMouseArea::dragging()
QCOMPARE(blackRect->y(), 61.0);
}
+void tst_QQuickMouseArea::dragSmoothed()
+{
+ QQuickView window;
+ QByteArray errorMessage;
+ QVERIFY2(initView(window, testFileUrl("dragging.qml"), true, &errorMessage), errorMessage.constData());
+
+ window.show();
+ QVERIFY(QTest::qWaitForWindowExposed(&window));
+ QVERIFY(window.rootObject() != 0);
+
+ QQuickMouseArea *mouseRegion = window.rootObject()->findChild<QQuickMouseArea*>("mouseregion");
+ QQuickDrag *drag = mouseRegion->drag();
+ drag->setThreshold(5);
+
+ mouseRegion->setAcceptedButtons(Qt::LeftButton);
+ QQuickItem *blackRect = window.rootObject()->findChild<QQuickItem*>("blackrect");
+ QVERIFY(blackRect != 0);
+ QVERIFY(blackRect == drag->target());
+ QVERIFY(!drag->active());
+ QTest::mousePress(&window, Qt::LeftButton, 0, QPoint(100,100));
+ QVERIFY(!drag->active());
+ QTest::mouseMove(&window, QPoint(100, 102), 50);
+ QTest::mouseMove(&window, QPoint(100, 106), 50);
+ QTest::mouseMove(&window, QPoint(100, 122), 50);
+ QTRY_COMPARE(blackRect->x(), 50.0);
+ QTRY_COMPARE(blackRect->y(), 66.0);
+ QTest::mouseRelease(&window, Qt::LeftButton, 0, QPoint(100,122));
+
+ // reset rect position
+ blackRect->setX(50.0);
+ blackRect->setY(50.0);
+
+ // now try with smoothed disabled
+ drag->setSmoothed(false);
+ QVERIFY(!drag->active());
+ QTest::mousePress(&window, Qt::LeftButton, 0, QPoint(100,100));
+ QVERIFY(!drag->active());
+ QTest::mouseMove(&window, QPoint(100, 102), 50);
+ QTest::mouseMove(&window, QPoint(100, 106), 50);
+ QTest::mouseMove(&window, QPoint(100, 122), 50);
+ QTRY_COMPARE(blackRect->x(), 50.0);
+ QTRY_COMPARE(blackRect->y(), 72.0);
+ QTest::mouseRelease(&window, Qt::LeftButton, 0, QPoint(100, 122));
+}
void tst_QQuickMouseArea::dragThreshold()
{
@@ -1639,6 +1686,69 @@ void tst_QQuickMouseArea::nestedStopAtBounds()
QTest::mouseRelease(&view, Qt::LeftButton, 0, position);
}
+void tst_QQuickMouseArea::containsPress_data()
+{
+ QTest::addColumn<bool>("hoverEnabled");
+
+ QTest::newRow("hover enabled") << true;
+ QTest::newRow("hover disaabled") << false;
+}
+
+void tst_QQuickMouseArea::containsPress()
+{
+ QFETCH(bool, hoverEnabled);
+
+ QQuickView window;
+ QByteArray errorMessage;
+ QVERIFY2(initView(window, testFileUrl("containsPress.qml"), true, &errorMessage), errorMessage.constData());
+ window.show();
+ window.requestActivate();
+ QVERIFY(QTest::qWaitForWindowExposed(&window));
+ QQuickItem *root = window.rootObject();
+ QVERIFY(root != 0);
+
+ QQuickMouseArea *mouseArea = window.rootObject()->findChild<QQuickMouseArea*>("mouseArea");
+ QVERIFY(mouseArea != 0);
+
+ QSignalSpy containsPressSpy(mouseArea, SIGNAL(containsPressChanged()));
+
+ mouseArea->setHoverEnabled(hoverEnabled);
+
+ QTest::mouseMove(&window, QPoint(22,33));
+ QCOMPARE(mouseArea->hovered(), false);
+ QCOMPARE(mouseArea->pressed(), false);
+ QCOMPARE(mouseArea->containsPress(), false);
+
+ QTest::mouseMove(&window, QPoint(200,200));
+ QCOMPARE(mouseArea->hovered(), hoverEnabled);
+ QCOMPARE(mouseArea->pressed(), false);
+ QCOMPARE(mouseArea->containsPress(), false);
+
+ QTest::mousePress(&window, Qt::LeftButton, Qt::NoModifier, QPoint(200,200));
+ QCOMPARE(mouseArea->hovered(), true);
+ QTRY_COMPARE(mouseArea->pressed(), true);
+ QCOMPARE(mouseArea->containsPress(), true);
+ QCOMPARE(containsPressSpy.count(), 1);
+
+ QTest::mouseMove(&window, QPoint(22,33));
+ QCOMPARE(mouseArea->hovered(), false);
+ QCOMPARE(mouseArea->pressed(), true);
+ QCOMPARE(mouseArea->containsPress(), false);
+ QCOMPARE(containsPressSpy.count(), 2);
+
+ QTest::mouseMove(&window, QPoint(200,200));
+ QCOMPARE(mouseArea->hovered(), true);
+ QCOMPARE(mouseArea->pressed(), true);
+ QCOMPARE(mouseArea->containsPress(), true);
+ QCOMPARE(containsPressSpy.count(), 3);
+
+ QTest::mouseRelease(&window, Qt::LeftButton, Qt::NoModifier, QPoint(200,200));
+ QCOMPARE(mouseArea->hovered(), hoverEnabled);
+ QCOMPARE(mouseArea->pressed(), false);
+ QCOMPARE(mouseArea->containsPress(), false);
+ QCOMPARE(containsPressSpy.count(), 4);
+}
+
QTEST_MAIN(tst_QQuickMouseArea)
#include "tst_qquickmousearea.moc"
diff --git a/tests/auto/quick/qquickmultipointtoucharea/qquickmultipointtoucharea.pro b/tests/auto/quick/qquickmultipointtoucharea/qquickmultipointtoucharea.pro
index d3abc198d9..5724a7179e 100644
--- a/tests/auto/quick/qquickmultipointtoucharea/qquickmultipointtoucharea.pro
+++ b/tests/auto/quick/qquickmultipointtoucharea/qquickmultipointtoucharea.pro
@@ -8,6 +8,7 @@ SOURCES += tst_qquickmultipointtoucharea.cpp
TESTDATA = data/*
include(../../shared/util.pri)
+include(../shared/util.pri)
QT += core-private gui-private qml-private quick-private testlib
DEFINES += QT_DISABLE_DEPRECATED_BEFORE=0
diff --git a/tests/auto/quick/qquickmultipointtoucharea/tst_qquickmultipointtoucharea.cpp b/tests/auto/quick/qquickmultipointtoucharea/tst_qquickmultipointtoucharea.cpp
index 1d4932c432..842babddd9 100644
--- a/tests/auto/quick/qquickmultipointtoucharea/tst_qquickmultipointtoucharea.cpp
+++ b/tests/auto/quick/qquickmultipointtoucharea/tst_qquickmultipointtoucharea.cpp
@@ -48,12 +48,14 @@
#include <QtQuick/qquickview.h>
#include <QtGui/QScreen>
#include "../../shared/util.h"
+#include "../shared/viewtestutil.h"
class tst_QQuickMultiPointTouchArea : public QQmlDataTest
{
Q_OBJECT
public:
tst_QQuickMultiPointTouchArea() : device(0) { }
+
private slots:
void initTestCase() {
QQmlDataTest::initTestCase();
@@ -118,6 +120,7 @@ void tst_QQuickMultiPointTouchArea::signalTest()
QTest::QTouchEventSequence sequence = QTest::touchEvent(window.data(), device);
sequence.press(0, p1).press(1, p2).commit();
+ QQuickTouchUtils::flush(window.data());
QCOMPARE(area->property("touchPointPressCount").toInt(), 2);
QCOMPARE(area->property("touchPointUpdateCount").toInt(), 0);
@@ -126,6 +129,7 @@ void tst_QQuickMultiPointTouchArea::signalTest()
QMetaObject::invokeMethod(area, "clearCounts");
sequence.stationary(0).stationary(1).press(2, p3).commit();
+ QQuickTouchUtils::flush(window.data());
QCOMPARE(area->property("touchPointPressCount").toInt(), 1);
QCOMPARE(area->property("touchPointUpdateCount").toInt(), 0);
@@ -136,6 +140,7 @@ void tst_QQuickMultiPointTouchArea::signalTest()
p1 -= QPoint(10,10);
p2 += QPoint(10,10);
sequence.move(0, p1).move(1, p2).stationary(2).commit();
+ QQuickTouchUtils::flush(window.data());
QCOMPARE(area->property("touchPointPressCount").toInt(), 0);
QCOMPARE(area->property("touchPointUpdateCount").toInt(), 2);
@@ -146,6 +151,7 @@ void tst_QQuickMultiPointTouchArea::signalTest()
p3 += QPoint(10,10);
sequence.release(0, p1).release(1, p2)
.move(2, p3).press(3, p4).press(4, p5).commit();
+ QQuickTouchUtils::flush(window.data());
QCOMPARE(area->property("touchPointPressCount").toInt(), 2);
QCOMPARE(area->property("touchPointUpdateCount").toInt(), 1);
@@ -154,6 +160,7 @@ void tst_QQuickMultiPointTouchArea::signalTest()
QMetaObject::invokeMethod(area, "clearCounts");
sequence.release(2, p3).release(3, p4).release(4, p5).commit();
+ QQuickTouchUtils::flush(window.data());
QCOMPARE(area->property("touchPointPressCount").toInt(), 0);
QCOMPARE(area->property("touchPointUpdateCount").toInt(), 0);
@@ -177,12 +184,14 @@ void tst_QQuickMultiPointTouchArea::release()
QTest::QTouchEventSequence sequence = QTest::touchEvent(window.data(), device);
sequence.press(0, p1).commit();
+ QQuickTouchUtils::flush(window.data());
QCOMPARE(point1->pressed(), true);
p1 += QPoint(0,10);
sequence.move(0, p1).commit();
+ QQuickTouchUtils::flush(window.data());
QCOMPARE(point1->pressed(), true);
QCOMPARE(point1->x(), qreal(20)); QCOMPARE(point1->y(), qreal(110));
@@ -190,6 +199,7 @@ void tst_QQuickMultiPointTouchArea::release()
p1 += QPoint(4,10);
sequence.release(0, p1).commit();
+ QQuickTouchUtils::flush(window.data());
//test that a release without a prior move to the release position successfully updates the point's position
QCOMPARE(point1->pressed(), false);
@@ -216,12 +226,14 @@ void tst_QQuickMultiPointTouchArea::reuse()
QTest::QTouchEventSequence sequence = QTest::touchEvent(window.data(), device);
sequence.press(0, p1).press(1, p2).commit();
+ QQuickTouchUtils::flush(window.data());
QCOMPARE(point1->pressed(), true);
QCOMPARE(point2->pressed(), true);
QCOMPARE(point3->pressed(), false);
sequence.release(0, p1).stationary(1).press(2, p3).commit();
+ QQuickTouchUtils::flush(window.data());
//we shouldn't reuse point 1 yet
QCOMPARE(point1->pressed(), false);
@@ -230,24 +242,28 @@ void tst_QQuickMultiPointTouchArea::reuse()
//back to base state (no touches)
sequence.release(1, p2).release(2, p3).commit();
+ QQuickTouchUtils::flush(window.data());
QCOMPARE(point1->pressed(), false);
QCOMPARE(point2->pressed(), false);
QCOMPARE(point3->pressed(), false);
sequence.press(0, p1).press(1, p2).commit();
+ QQuickTouchUtils::flush(window.data());
QCOMPARE(point1->pressed(), true);
QCOMPARE(point2->pressed(), true);
QCOMPARE(point3->pressed(), false);
sequence.release(0, p1).stationary(1).commit();
+ QQuickTouchUtils::flush(window.data());
QCOMPARE(point1->pressed(), false);
QCOMPARE(point2->pressed(), true);
QCOMPARE(point3->pressed(), false);
sequence.press(4, p4).stationary(1).commit();
+ QQuickTouchUtils::flush(window.data());
//the new touch point should reuse point 1
QCOMPARE(point1->pressed(), true);
@@ -283,6 +299,7 @@ void tst_QQuickMultiPointTouchArea::nonOverlapping()
QTest::QTouchEventSequence sequence = QTest::touchEvent(window.data(), device);
sequence.press(0, p1).commit();
+ QQuickTouchUtils::flush(window.data());
QCOMPARE(point11->pressed(), false);
QCOMPARE(point12->pressed(), false);
@@ -291,6 +308,7 @@ void tst_QQuickMultiPointTouchArea::nonOverlapping()
QCOMPARE(point23->pressed(), false);
sequence.stationary(0).press(1, p2).commit();
+ QQuickTouchUtils::flush(window.data());
QCOMPARE(point11->pressed(), true);
QCOMPARE(point12->pressed(), true);
@@ -304,6 +322,7 @@ void tst_QQuickMultiPointTouchArea::nonOverlapping()
p1 += QPoint(0,10);
p2 += QPoint(5,0);
sequence.move(0, p1).move(1, p2).commit();
+ QQuickTouchUtils::flush(window.data());
QCOMPARE(point11->pressed(), true);
QCOMPARE(point12->pressed(), true);
@@ -315,6 +334,7 @@ void tst_QQuickMultiPointTouchArea::nonOverlapping()
QCOMPARE(point12->x(), qreal(45)); QCOMPARE(point12->y(), qreal(100));
sequence.stationary(0).stationary(1).press(2, p3).commit();
+ QQuickTouchUtils::flush(window.data());
QCOMPARE(point11->pressed(), true);
QCOMPARE(point12->pressed(), true);
@@ -323,6 +343,7 @@ void tst_QQuickMultiPointTouchArea::nonOverlapping()
QCOMPARE(point23->pressed(), false);
sequence.stationary(0).stationary(1).stationary(2).press(3, p4).press(4, p5).commit();
+ QQuickTouchUtils::flush(window.data());
QCOMPARE(point11->pressed(), true);
QCOMPARE(point12->pressed(), true);
@@ -342,6 +363,7 @@ void tst_QQuickMultiPointTouchArea::nonOverlapping()
p4 += QPoint(1,-1);
p5 += QPoint(-7,10);
sequence.move(0, p1).move(1, p2).move(2, p3).move(3, p4).move(4, p5).commit();
+ QQuickTouchUtils::flush(window.data());
QCOMPARE(point11->pressed(), true);
QCOMPARE(point12->pressed(), true);
@@ -356,6 +378,7 @@ void tst_QQuickMultiPointTouchArea::nonOverlapping()
QCOMPARE(point23->x(), qreal(93)); QCOMPARE(point23->y(), qreal(30));
sequence.release(0, p1).release(1, p2).release(2, p3).release(3, p4).release(4, p5).commit();
+ QQuickTouchUtils::flush(window.data());
QCOMPARE(point11->pressed(), false);
QCOMPARE(point12->pressed(), false);
@@ -388,6 +411,7 @@ void tst_QQuickMultiPointTouchArea::nested()
QTest::QTouchEventSequence sequence = QTest::touchEvent(window.data(), device);
sequence.press(0, p1).commit();
+ QQuickTouchUtils::flush(window.data());
QCOMPARE(point11->pressed(), false);
QCOMPARE(point12->pressed(), false);
@@ -396,6 +420,7 @@ void tst_QQuickMultiPointTouchArea::nested()
QCOMPARE(point23->pressed(), false);
sequence.stationary(0).press(1, p2).commit();
+ QQuickTouchUtils::flush(window.data());
QCOMPARE(point11->pressed(), true);
QCOMPARE(point12->pressed(), true);
@@ -409,6 +434,7 @@ void tst_QQuickMultiPointTouchArea::nested()
p1 += QPoint(0,10);
p2 += QPoint(5,0);
sequence.move(0, p1).move(1, p2).commit();
+ QQuickTouchUtils::flush(window.data());
QCOMPARE(point11->pressed(), true);
QCOMPARE(point12->pressed(), true);
@@ -420,6 +446,7 @@ void tst_QQuickMultiPointTouchArea::nested()
QCOMPARE(point12->x(), qreal(45)); QCOMPARE(point12->y(), qreal(100));
sequence.stationary(0).stationary(1).press(2, p3).commit();
+ QQuickTouchUtils::flush(window.data());
QCOMPARE(point11->pressed(), true);
QCOMPARE(point12->pressed(), true);
@@ -435,6 +462,7 @@ void tst_QQuickMultiPointTouchArea::nested()
QCOMPARE(point23->x(), qreal(60)); QCOMPARE(point23->y(), qreal(180));
sequence.stationary(0).stationary(1).stationary(2).press(3, QPoint(80,180)).press(4, QPoint(100,180)).commit();
+ QQuickTouchUtils::flush(window.data());
QCOMPARE(point11->pressed(), true);
QCOMPARE(point12->pressed(), true);
@@ -455,6 +483,7 @@ void tst_QQuickMultiPointTouchArea::nested()
p2 += QPoint(17,17);
p3 += QPoint(3,0);
sequence.move(0, p1).move(1, p2).move(2, p3).commit();
+ QQuickTouchUtils::flush(window.data());
QCOMPARE(point11->pressed(), true);
QCOMPARE(point12->pressed(), true);
@@ -472,6 +501,7 @@ void tst_QQuickMultiPointTouchArea::nested()
p2 += QPoint(17,17);
p3 += QPoint(3,0);
sequence.move(0, p1).move(1, p2).move(2, p3).commit();
+ QQuickTouchUtils::flush(window.data());
QCOMPARE(point11->pressed(), false);
QCOMPARE(point12->pressed(), false);
@@ -489,6 +519,7 @@ void tst_QQuickMultiPointTouchArea::nested()
sequence.release(0, p1).release(1, p2).release(2, p3).commit();
sequence.press(0, p1).commit();
+ QQuickTouchUtils::flush(window.data());
QCOMPARE(point11->pressed(), false);
QCOMPARE(point12->pressed(), false);
@@ -497,11 +528,13 @@ void tst_QQuickMultiPointTouchArea::nested()
QCOMPARE(point23->pressed(), false);
sequence.release(0, p1).commit();
+ QQuickTouchUtils::flush(window.data());
//test with grabbing turned off
window->rootObject()->setProperty("grabInnerArea", false);
sequence.press(0, p1).press(1, p2).press(2, p3).commit();
+ QQuickTouchUtils::flush(window.data());
QCOMPARE(point11->pressed(), true);
QCOMPARE(point12->pressed(), true);
@@ -513,6 +546,7 @@ void tst_QQuickMultiPointTouchArea::nested()
p2 -= QPoint(17,17);
p3 -= QPoint(3,0);
sequence.move(0, p1).move(1, p2).move(2, p3).commit();
+ QQuickTouchUtils::flush(window.data());
QCOMPARE(point11->pressed(), true);
QCOMPARE(point12->pressed(), true);
@@ -530,6 +564,7 @@ void tst_QQuickMultiPointTouchArea::nested()
p2 -= QPoint(17,17);
p3 -= QPoint(3,0);
sequence.move(0, p1).move(1, p2).move(2, p3).commit();
+ QQuickTouchUtils::flush(window.data());
QCOMPARE(point11->pressed(), true);
QCOMPARE(point12->pressed(), true);
@@ -545,6 +580,7 @@ void tst_QQuickMultiPointTouchArea::nested()
QCOMPARE(point23->x(), qreal(60)); QCOMPARE(point23->y(), qreal(180));
sequence.release(0, p1).release(1, p2).release(2, p3).commit();
+ QQuickTouchUtils::flush(window.data());
}
void tst_QQuickMultiPointTouchArea::inFlickable()
@@ -569,25 +605,30 @@ void tst_QQuickMultiPointTouchArea::inFlickable()
//moving one point vertically
QTest::touchEvent(window.data(), device).press(0, p1);
+ QQuickTouchUtils::flush(window.data());
p1 += QPoint(0,15);
QTest::touchEvent(window.data(), device).move(0, p1);
+ QQuickTouchUtils::flush(window.data());
p1 += QPoint(0,15);
QTest::touchEvent(window.data(), device).move(0, p1);
+ QQuickTouchUtils::flush(window.data());
p1 += QPoint(0,15);
QTest::touchEvent(window.data(), device).move(0, p1);
+ QQuickTouchUtils::flush(window.data());
p1 += QPoint(0,15);
QTest::touchEvent(window.data(), device).move(0, p1);
+ QQuickTouchUtils::flush(window.data());
QVERIFY(flickable->contentY() < 0);
QCOMPARE(point11->pressed(), false);
QCOMPARE(point12->pressed(), false);
QTest::touchEvent(window.data(), device).release(0, p1);
- QTest::qWait(50);
+ QQuickTouchUtils::flush(window.data());
QTRY_VERIFY(!flickable->isMoving());
@@ -595,6 +636,7 @@ void tst_QQuickMultiPointTouchArea::inFlickable()
p1 = QPoint(20,100);
QTest::touchEvent(window.data(), device).press(0, p1).press(1, p2);
QTest::mousePress(window.data(), Qt::LeftButton, 0, p1);
+ QQuickTouchUtils::flush(window.data());
QCOMPARE(point11->pressed(), true);
QCOMPARE(point12->pressed(), true);
@@ -604,18 +646,22 @@ void tst_QQuickMultiPointTouchArea::inFlickable()
p1 += QPoint(0,15); p2 += QPoint(0,15);
QTest::touchEvent(window.data(), device).move(0, p1).move(1, p2);
QTest::mouseMove(window.data(), p1);
+ QQuickTouchUtils::flush(window.data());
p1 += QPoint(0,15); p2 += QPoint(0,15);
QTest::touchEvent(window.data(), device).move(0, p1).move(1, p2);
QTest::mouseMove(window.data(), p1);
+ QQuickTouchUtils::flush(window.data());
p1 += QPoint(0,15); p2 += QPoint(0,15);
QTest::touchEvent(window.data(), device).move(0, p1).move(1, p2);
QTest::mouseMove(window.data(), p1);
+ QQuickTouchUtils::flush(window.data());
p1 += QPoint(0,15); p2 += QPoint(0,15);
QTest::touchEvent(window.data(), device).move(0, p1).move(1, p2);
QTest::mouseMove(window.data(), p1);
+ QQuickTouchUtils::flush(window.data());
QVERIFY(flickable->contentY() < 0);
QCOMPARE(point11->pressed(), false);
@@ -625,7 +671,7 @@ void tst_QQuickMultiPointTouchArea::inFlickable()
QTest::touchEvent(window.data(), device).release(0, p1).release(1, p2);
QTest::mouseRelease(window.data(), Qt::LeftButton, 0, p1);
- QTest::qWait(50);
+ QQuickTouchUtils::flush(window.data());
QTRY_VERIFY(!flickable->isMoving());
@@ -633,6 +679,7 @@ void tst_QQuickMultiPointTouchArea::inFlickable()
p1 = QPoint(20,100);
p2 = QPoint(40,100);
QTest::touchEvent(window.data(), device).press(0, p1).press(1, p2);
+ QQuickTouchUtils::flush(window.data());
// ensure that mouse events do not fall through to the Flickable
mpta->setMaximumTouchPoints(3);
QTest::mousePress(window.data(), Qt::LeftButton, 0, p1);
@@ -643,34 +690,42 @@ void tst_QQuickMultiPointTouchArea::inFlickable()
p1 += QPoint(15,0); p2 += QPoint(15,0);
QTest::touchEvent(window.data(), device).move(0, p1).move(1, p2);
QTest::mouseMove(window.data(), p1);
+ QQuickTouchUtils::flush(window.data());
p1 += QPoint(15,0); p2 += QPoint(15,0);
QTest::touchEvent(window.data(), device).move(0, p1).move(1, p2);
QTest::mouseMove(window.data(), p1);
+ QQuickTouchUtils::flush(window.data());
p1 += QPoint(15,0); p2 += QPoint(15,0);
QTest::touchEvent(window.data(), device).move(0, p1).move(1, p2);
QTest::mouseMove(window.data(), p1);
+ QQuickTouchUtils::flush(window.data());
p1 += QPoint(15,0); p2 += QPoint(15,0);
QTest::touchEvent(window.data(), device).move(0, p1).move(1, p2);
QTest::mouseMove(window.data(), p1);
+ QQuickTouchUtils::flush(window.data());
p1 += QPoint(0,15); p2 += QPoint(0,15);
QTest::touchEvent(window.data(), device).move(0, p1).move(1, p2);
QTest::mouseMove(window.data(), p1);
+ QQuickTouchUtils::flush(window.data());
p1 += QPoint(0,15); p2 += QPoint(0,15);
QTest::touchEvent(window.data(), device).move(0, p1).move(1, p2);
QTest::mouseMove(window.data(), p1);
+ QQuickTouchUtils::flush(window.data());
p1 += QPoint(0,15); p2 += QPoint(0,15);
QTest::touchEvent(window.data(), device).move(0, p1).move(1, p2);
QTest::mouseMove(window.data(), p1);
+ QQuickTouchUtils::flush(window.data());
p1 += QPoint(0,15); p2 += QPoint(0,15);
QTest::touchEvent(window.data(), device).move(0, p1).move(1, p2);
QTest::mouseMove(window.data(), p1);
+ QQuickTouchUtils::flush(window.data());
QVERIFY(flickable->contentY() == 0);
QCOMPARE(point11->pressed(), true);
@@ -678,7 +733,7 @@ void tst_QQuickMultiPointTouchArea::inFlickable()
QTest::touchEvent(window.data(), device).release(0, p1).release(1, p2);
QTest::mouseRelease(window.data(), Qt::LeftButton, 0, p1);
- QTest::qWait(50);
+ QQuickTouchUtils::flush(window.data());
}
// test that dragging out of a Flickable containing a MPTA doesn't harm Flickable's state.
@@ -699,28 +754,34 @@ void tst_QQuickMultiPointTouchArea::inFlickable2()
// move point horizontally, out of Flickable area
QTest::touchEvent(window.data(), device).press(0, p1);
+ QQuickTouchUtils::flush(window.data());
QTest::mousePress(window.data(), Qt::LeftButton, 0, p1);
p1 += QPoint(15,0);
QTest::touchEvent(window.data(), device).move(0, p1);
+ QQuickTouchUtils::flush(window.data());
QTest::mouseMove(window.data(), p1);
p1 += QPoint(15,0);
QTest::touchEvent(window.data(), device).move(0, p1);
+ QQuickTouchUtils::flush(window.data());
QTest::mouseMove(window.data(), p1);
p1 += QPoint(15,0);
QTest::touchEvent(window.data(), device).move(0, p1);
+ QQuickTouchUtils::flush(window.data());
QTest::mouseMove(window.data(), p1);
p1 += QPoint(15,0);
QTest::touchEvent(window.data(), device).move(0, p1);
+ QQuickTouchUtils::flush(window.data());
QTest::mouseMove(window.data(), p1);
QVERIFY(!flickable->isMoving());
QVERIFY(point11->pressed());
QTest::touchEvent(window.data(), device).release(0, p1);
+ QQuickTouchUtils::flush(window.data());
QTest::mouseRelease(window.data(), Qt::LeftButton, 0, p1);
QTest::qWait(50);
@@ -729,26 +790,32 @@ void tst_QQuickMultiPointTouchArea::inFlickable2()
// Check that we can still move the Flickable
p1 = QPoint(50,100);
QTest::touchEvent(window.data(), device).press(0, p1);
+ QQuickTouchUtils::flush(window.data());
QCOMPARE(point11->pressed(), true);
p1 += QPoint(0,15);
QTest::touchEvent(window.data(), device).move(0, p1);
+ QQuickTouchUtils::flush(window.data());
p1 += QPoint(0,15);
QTest::touchEvent(window.data(), device).move(0, p1);
+ QQuickTouchUtils::flush(window.data());
p1 += QPoint(0,15);
QTest::touchEvent(window.data(), device).move(0, p1);
+ QQuickTouchUtils::flush(window.data());
p1 += QPoint(0,15);
QTest::touchEvent(window.data(), device).move(0, p1);
+ QQuickTouchUtils::flush(window.data());
QVERIFY(flickable->contentY() < 0);
QVERIFY(flickable->isMoving());
QCOMPARE(point11->pressed(), true);
QTest::touchEvent(window.data(), device).release(0, p1);
+ QQuickTouchUtils::flush(window.data());
QTest::qWait(50);
QTRY_VERIFY(!flickable->isMoving());
@@ -859,7 +926,9 @@ void tst_QQuickMultiPointTouchArea::mouseAsTouchpoint()
// Touch both, release one, manipulate other touchpoint with mouse
QTest::touchEvent(window.data(), device).press(1, touch1);
+ QQuickTouchUtils::flush(window.data());
QTest::touchEvent(window.data(), device).press(2, touch2);
+ QQuickTouchUtils::flush(window.data());
QCOMPARE(touch1rect->property("x").toInt(), touch1.x());
QCOMPARE(touch1rect->property("y").toInt(), touch1.y());
QCOMPARE(touch2rect->property("x").toInt(), touch2.x());
@@ -867,12 +936,14 @@ void tst_QQuickMultiPointTouchArea::mouseAsTouchpoint()
QTest::touchEvent(window.data(), device).release(1, touch1);
touch1.setY(20);
QTest::mousePress(window.data(), Qt::LeftButton, 0, touch1);
+ QQuickTouchUtils::flush(window.data());
QCOMPARE(touch1rect->property("x").toInt(), touch1.x());
QCOMPARE(touch1rect->property("y").toInt(), touch1.y());
QCOMPARE(touch2rect->property("x").toInt(), touch2.x());
QCOMPARE(touch2rect->property("y").toInt(), touch2.y());
QTest::touchEvent(window.data(), device).release(2, touch2);
QTest::mouseRelease(window.data(), Qt::LeftButton, 0, touch1);
+ QQuickTouchUtils::flush(window.data());
// Start with mouse, move it, touch second point, move it
QTest::mousePress(window.data(), Qt::LeftButton, 0, touch1);
@@ -882,12 +953,14 @@ void tst_QQuickMultiPointTouchArea::mouseAsTouchpoint()
QCOMPARE(touch1rect->property("y").toInt(), touch1.y());
touch2.setX(60);
QTest::touchEvent(window.data(), device).press(3, touch2);
+ QQuickTouchUtils::flush(window.data());
QCOMPARE(touch1rect->property("x").toInt(), touch1.x());
QCOMPARE(touch1rect->property("y").toInt(), touch1.y());
QCOMPARE(touch2rect->property("x").toInt(), touch2.x());
QCOMPARE(touch2rect->property("y").toInt(), touch2.y());
touch2.setY(150);
QTest::touchEvent(window.data(), device).move(3, touch2);
+ QQuickTouchUtils::flush(window.data());
QCOMPARE(touch1rect->property("x").toInt(), touch1.x());
QCOMPARE(touch1rect->property("y").toInt(), touch1.y());
QCOMPARE(touch2rect->property("x").toInt(), touch2.x());
@@ -895,6 +968,7 @@ void tst_QQuickMultiPointTouchArea::mouseAsTouchpoint()
// Touch third point - nothing happens
QTest::touchEvent(window.data(), device).press(4, touch3);
+ QQuickTouchUtils::flush(window.data());
QCOMPARE(touch1rect->property("x").toInt(), touch1.x());
QCOMPARE(touch1rect->property("y").toInt(), touch1.y());
QCOMPARE(touch2rect->property("x").toInt(), touch2.x());
@@ -903,7 +977,9 @@ void tst_QQuickMultiPointTouchArea::mouseAsTouchpoint()
// Release all
QTest::mouseRelease(window.data(), Qt::LeftButton, 0, touch1);
QTest::touchEvent(window.data(), device).release(3, touch2);
+ QQuickTouchUtils::flush(window.data());
QTest::touchEvent(window.data(), device).release(4, touch3);
+ QQuickTouchUtils::flush(window.data());
QCOMPARE(touch1rect->property("x").toInt(), touch1.x());
QCOMPARE(touch1rect->property("y").toInt(), touch1.y());
QCOMPARE(touch2rect->property("x").toInt(), touch2.x());
@@ -922,12 +998,14 @@ void tst_QQuickMultiPointTouchArea::mouseAsTouchpoint()
QCOMPARE(touch1rect->property("x").toInt(), mouse1.x());
QCOMPARE(touch1rect->property("y").toInt(), mouse1.y());
QTest::touchEvent(window.data(), device).press(1, touch1);
+ QQuickTouchUtils::flush(window.data());
QCOMPARE(touch1rect->property("x").toInt(), mouse1.x());
QCOMPARE(touch1rect->property("y").toInt(), mouse1.y());
QCOMPARE(touch2rect->property("x").toInt(), touch1.x());
QCOMPARE(touch2rect->property("y").toInt(), touch1.y());
QTest::touchEvent(window.data(), device).press(2, touch2).press(3, touch3).press(4, touch4);
+ QQuickTouchUtils::flush(window.data());
QCOMPARE(touch1rect->property("x").toInt(), mouse1.x());
QCOMPARE(touch1rect->property("y").toInt(), mouse1.y());
QCOMPARE(touch2rect->property("x").toInt(), touch1.x());
@@ -942,6 +1020,7 @@ void tst_QQuickMultiPointTouchArea::mouseAsTouchpoint()
// Release all
QTest::mouseRelease(window.data(), Qt::LeftButton, 0, mouse1);
QTest::touchEvent(window.data(), device).release(1, touch1).release(2, touch2).release(3, touch3).release(4, touch4);
+ QQuickTouchUtils::flush(window.data());
}
dualmpta->setProperty("mouseEnabled", false);
@@ -964,13 +1043,16 @@ void tst_QQuickMultiPointTouchArea::mouseAsTouchpoint()
QCOMPARE(touch1rect->property("y").toInt(), 10);
QTest::touchEvent(window.data(), device).press(1, touch1);
+ QQuickTouchUtils::flush(window.data());
QCOMPARE(touch1rect->property("x").toInt(), touch1.x());
QCOMPARE(touch1rect->property("y").toInt(), touch1.y());
touch1.setY(150);
QTest::touchEvent(window.data(), device).move(1, touch1);
+ QQuickTouchUtils::flush(window.data());
QCOMPARE(touch1rect->property("x").toInt(), touch1.x());
QCOMPARE(touch1rect->property("y").toInt(), touch1.y());
QTest::touchEvent(window.data(), device).press(2, touch2);
+ QQuickTouchUtils::flush(window.data());
QCOMPARE(touch1rect->property("x").toInt(), touch1.x());
QCOMPARE(touch1rect->property("y").toInt(), touch1.y());
QCOMPARE(touch2rect->property("x").toInt(), touch2.x());
@@ -979,7 +1061,9 @@ void tst_QQuickMultiPointTouchArea::mouseAsTouchpoint()
// Release all
QTest::mouseRelease(window.data(), Qt::LeftButton, 0, mouse1);
QTest::touchEvent(window.data(), device).release(1, touch1);
+ QQuickTouchUtils::flush(window.data());
QTest::touchEvent(window.data(), device).release(2, touch2);
+ QQuickTouchUtils::flush(window.data());
QCOMPARE(touch1rect->property("x").toInt(), touch1.x());
QCOMPARE(touch1rect->property("y").toInt(), touch1.y());
QCOMPARE(touch2rect->property("x").toInt(), touch2.x());
@@ -1028,7 +1112,6 @@ void tst_QQuickMultiPointTouchArea::transformedTouchArea_data()
QTest::newRow("3rd point inside")
<< QPoint(140, 260) << QPoint(260, 140) << QPoint(200, 140) << 0 << 0 << 1;
-
QTest::newRow("all points inside")
<< QPoint(200, 140) << QPoint(200, 260) << QPoint(140, 200) << 1 << 2 << 3;
diff --git a/tests/auto/quick/qquickopenglinfo/data/basic.qml b/tests/auto/quick/qquickopenglinfo/data/basic.qml
new file mode 100644
index 0000000000..b48447941b
--- /dev/null
+++ b/tests/auto/quick/qquickopenglinfo/data/basic.qml
@@ -0,0 +1,8 @@
+import QtQuick 2.4
+
+Item {
+ property int majorVersion: OpenGLInfo.majorVersion
+ property int minorVersion: OpenGLInfo.minorVersion
+ property int profile: OpenGLInfo.profile
+ property int renderableType: OpenGLInfo.renderableType
+}
diff --git a/tests/auto/quick/qquickopenglinfo/qquickopenglinfo.pro b/tests/auto/quick/qquickopenglinfo/qquickopenglinfo.pro
new file mode 100644
index 0000000000..8489dfffd2
--- /dev/null
+++ b/tests/auto/quick/qquickopenglinfo/qquickopenglinfo.pro
@@ -0,0 +1,15 @@
+CONFIG += testcase
+TARGET = tst_qquickopenglinfo
+SOURCES += tst_qquickopenglinfo.cpp
+
+TESTDATA = data/*
+include(../../shared/util.pri)
+
+osx:CONFIG -= app_bundle
+
+CONFIG += parallel_test
+QT += quick testlib
+
+OTHER_FILES += \
+ data/basic.qml
+
diff --git a/tests/auto/quick/qquickopenglinfo/tst_qquickopenglinfo.cpp b/tests/auto/quick/qquickopenglinfo/tst_qquickopenglinfo.cpp
new file mode 100644
index 0000000000..de28769e36
--- /dev/null
+++ b/tests/auto/quick/qquickopenglinfo/tst_qquickopenglinfo.cpp
@@ -0,0 +1,85 @@
+/****************************************************************************
+**
+** Copyright (C) 2014 BlackBerry Ltd.
+** 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$
+**
+****************************************************************************/
+
+#include <QtTest/qtest.h>
+#include <QtTest/qsignalspy.h>
+
+#include <QtQuick/qquickitem.h>
+#include <QtQuick/qquickview.h>
+
+#include <QtGui/qopenglcontext.h>
+#include <QtGui/qsurfaceformat.h>
+
+#include "../../shared/util.h"
+
+class tst_QQuickOpenGLInfo : public QQmlDataTest
+{
+ Q_OBJECT
+
+private slots:
+ void testProperties();
+};
+
+void tst_QQuickOpenGLInfo::testProperties()
+{
+ QQuickView view;
+ view.setSource(QUrl::fromLocalFile("data/basic.qml"));
+
+ view.show();
+ QVERIFY(QTest::qWaitForWindowExposed(&view));
+
+ QSignalSpy spy(&view, SIGNAL(sceneGraphInitialized()));
+ spy.wait();
+
+ QVERIFY(view.openglContext());
+ QSurfaceFormat format = view.openglContext()->format();
+
+ QObject* obj = view.rootObject();
+ QVERIFY(obj);
+ QCOMPARE(obj->property("majorVersion").toInt(), format.majorVersion());
+ QCOMPARE(obj->property("minorVersion").toInt(), format.minorVersion());
+ QCOMPARE(obj->property("profile").toInt(), static_cast<int>(format.profile()));
+ QCOMPARE(obj->property("renderableType").toInt(), static_cast<int>(format.renderableType()));
+}
+
+QTEST_MAIN(tst_QQuickOpenGLInfo)
+
+#include "tst_qquickopenglinfo.moc"
diff --git a/tests/auto/quick/qquickpincharea/qquickpincharea.pro b/tests/auto/quick/qquickpincharea/qquickpincharea.pro
index 970ce48851..fa14afa261 100644
--- a/tests/auto/quick/qquickpincharea/qquickpincharea.pro
+++ b/tests/auto/quick/qquickpincharea/qquickpincharea.pro
@@ -6,6 +6,7 @@ macx:CONFIG -= app_bundle
SOURCES += tst_qquickpincharea.cpp
include (../../shared/util.pri)
+include (../shared/util.pri)
TESTDATA = data/*
diff --git a/tests/auto/quick/qquickpincharea/tst_qquickpincharea.cpp b/tests/auto/quick/qquickpincharea/tst_qquickpincharea.cpp
index b9d314b63e..1dbce1b730 100644
--- a/tests/auto/quick/qquickpincharea/tst_qquickpincharea.cpp
+++ b/tests/auto/quick/qquickpincharea/tst_qquickpincharea.cpp
@@ -48,6 +48,7 @@
#include <QtQuick/qquickview.h>
#include <QtQml/qqmlcontext.h>
#include "../../shared/util.h"
+#include "../shared/viewtestutil.h"
class tst_QQuickPinchArea: public QQmlDataTest
{
@@ -232,15 +233,18 @@ void tst_QQuickPinchArea::scale()
{
QTest::QTouchEventSequence pinchSequence = QTest::touchEvent(window, device);
pinchSequence.press(0, p1, window).commit();
+ QQuickTouchUtils::flush(window);
// In order for the stationary point to remember its previous position,
// we have to reuse the same pinchSequence object. Otherwise if we let it
// be destroyed and then start a new sequence, point 0 will default to being
// stationary at 0, 0, and PinchArea will filter out that touchpoint because
// it is outside its bounds.
pinchSequence.stationary(0).press(1, p2, window).commit();
+ QQuickTouchUtils::flush(window);
p1 -= QPoint(10,10);
p2 += QPoint(10,10);
pinchSequence.move(0, p1,window).move(1, p2,window).commit();
+ QQuickTouchUtils::flush(window);
QCOMPARE(root->property("scale").toReal(), 1.0);
QVERIFY(root->property("pinchActive").toBool());
@@ -248,6 +252,7 @@ void tst_QQuickPinchArea::scale()
p1 -= QPoint(10,10);
p2 += QPoint(10,10);
pinchSequence.move(0, p1,window).move(1, p2,window).commit();
+ QQuickTouchUtils::flush(window);
QCOMPARE(root->property("scale").toReal(), 1.5);
QCOMPARE(root->property("center").toPointF(), QPointF(40, 40)); // blackrect is at 50,50
@@ -260,8 +265,10 @@ void tst_QQuickPinchArea::scale()
{
QTest::QTouchEventSequence pinchSequence = QTest::touchEvent(window, device);
pinchSequence.move(0, p1, window).move(1, p2, window).commit();
+ QQuickTouchUtils::flush(window);
QCOMPARE(blackRect->scale(), 2.0);
pinchSequence.release(0, p1, window).release(1, p2, window).commit();
+ QQuickTouchUtils::flush(window);
}
QVERIFY(!root->property("pinchActive").toBool());
}
@@ -293,12 +300,15 @@ void tst_QQuickPinchArea::pan()
{
QTest::QTouchEventSequence pinchSequence = QTest::touchEvent(window, device);
pinchSequence.press(0, p1, window).commit();
+ QQuickTouchUtils::flush(window);
// In order for the stationary point to remember its previous position,
// we have to reuse the same pinchSequence object.
pinchSequence.stationary(0).press(1, p2, window).commit();
+ QQuickTouchUtils::flush(window);
p1 += QPoint(10,10);
p2 += QPoint(10,10);
pinchSequence.move(0, p1,window).move(1, p2,window).commit();
+ QQuickTouchUtils::flush(window);
QCOMPARE(root->property("scale").toReal(), 1.0);
QVERIFY(root->property("pinchActive").toBool());
@@ -306,6 +316,7 @@ void tst_QQuickPinchArea::pan()
p1 += QPoint(10,10);
p2 += QPoint(10,10);
pinchSequence.move(0, p1,window).move(1, p2,window).commit();
+ QQuickTouchUtils::flush(window);
}
QCOMPARE(root->property("center").toPointF(), QPointF(60, 60)); // blackrect is at 50,50
@@ -316,11 +327,13 @@ void tst_QQuickPinchArea::pan()
p1 += QPoint(100,100);
p2 += QPoint(100,100);
QTest::touchEvent(window, device).move(0, p1, window).move(1, p2, window);
+ QQuickTouchUtils::flush(window);
QCOMPARE(blackRect->x(), 140.0);
QCOMPARE(blackRect->y(), 160.0);
QTest::touchEvent(window, device).release(0, p1, window).release(1, p2, window);
+ QQuickTouchUtils::flush(window);
QVERIFY(!root->property("pinchActive").toBool());
}
@@ -355,12 +368,15 @@ void tst_QQuickPinchArea::retouch()
{
QTest::QTouchEventSequence pinchSequence = QTest::touchEvent(window, device);
pinchSequence.press(0, p1, window).commit();
+ QQuickTouchUtils::flush(window);
// In order for the stationary point to remember its previous position,
// we have to reuse the same pinchSequence object.
pinchSequence.stationary(0).press(1, p2, window).commit();
+ QQuickTouchUtils::flush(window);
p1 -= QPoint(10,10);
p2 += QPoint(10,10);
pinchSequence.move(0, p1,window).move(1, p2,window).commit();
+ QQuickTouchUtils::flush(window);
QCOMPARE(root->property("scale").toReal(), 1.0);
QVERIFY(root->property("pinchActive").toBool());
@@ -368,6 +384,7 @@ void tst_QQuickPinchArea::retouch()
p1 -= QPoint(10,10);
p2 += QPoint(10,10);
pinchSequence.move(0, p1,window).move(1, p2,window).commit();
+ QQuickTouchUtils::flush(window);
QCOMPARE(startedSpy.count(), 1);
@@ -382,6 +399,7 @@ void tst_QQuickPinchArea::retouch()
// Hold down the first finger but release the second one
pinchSequence.stationary(0).release(1, p2, window).commit();
+ QQuickTouchUtils::flush(window);
QCOMPARE(startedSpy.count(), 1);
QCOMPARE(finishedSpy.count(), 0);
@@ -390,9 +408,11 @@ void tst_QQuickPinchArea::retouch()
// Keep holding down the first finger and re-touch the second one, then move them both
pinchSequence.stationary(0).press(1, p2, window).commit();
+ QQuickTouchUtils::flush(window);
p1 -= QPoint(10,10);
p2 += QPoint(10,10);
pinchSequence.move(0, p1, window).move(1, p2, window).commit();
+ QQuickTouchUtils::flush(window);
// Lifting and retouching results in onPinchStarted being called again
QCOMPARE(startedSpy.count(), 2);
@@ -401,6 +421,7 @@ void tst_QQuickPinchArea::retouch()
QCOMPARE(window->rootObject()->property("pointCount").toInt(), 2);
pinchSequence.release(0, p1, window).release(1, p2, window).commit();
+ QQuickTouchUtils::flush(window);
QVERIFY(!root->property("pinchActive").toBool());
QCOMPARE(startedSpy.count(), 2);
@@ -456,14 +477,18 @@ void tst_QQuickPinchArea::transformedPinchArea()
QTest::QTouchEventSequence pinchSequence = QTest::touchEvent(view, device);
// start pinch
pinchSequence.press(0, p1, view).commit();
+ QQuickTouchUtils::flush(view);
// In order for the stationary point to remember its previous position,
// we have to reuse the same pinchSequence object.
pinchSequence.stationary(0).press(1, p2, view).commit();
+ QQuickTouchUtils::flush(view);
pinchSequence.stationary(0).move(1, p2 + QPoint(threshold * 2, 0), view).commit();
+ QQuickTouchUtils::flush(view);
QCOMPARE(pinchArea->property("pinching").toBool(), shouldPinch);
// release pinch
pinchSequence.release(0, p1, view).release(1, p2, view).commit();
+ QQuickTouchUtils::flush(view);
QCOMPARE(pinchArea->property("pinching").toBool(), false);
}
}
diff --git a/tests/auto/quick/qquickpixmapcache/tst_qquickpixmapcache.cpp b/tests/auto/quick/qquickpixmapcache/tst_qquickpixmapcache.cpp
index 75bd468aef..f104154205 100644
--- a/tests/auto/quick/qquickpixmapcache/tst_qquickpixmapcache.cpp
+++ b/tests/auto/quick/qquickpixmapcache/tst_qquickpixmapcache.cpp
@@ -59,7 +59,7 @@ class tst_qquickpixmapcache : public QQmlDataTest
{
Q_OBJECT
public:
- tst_qquickpixmapcache() : server(14452) {}
+ tst_qquickpixmapcache() {}
private slots:
void initTestCase();
@@ -116,6 +116,8 @@ void tst_qquickpixmapcache::initTestCase()
{
QQmlDataTest::initTestCase();
+ QVERIFY2(server.listen(14452), qPrintable(server.errorString()));
+
// This avoids a race condition/deadlock bug in network config
// manager when it is accessed by the HTTP server thread before
// anything else. Bug report can be found at:
@@ -379,7 +381,8 @@ void tst_qquickpixmapcache::shrinkcache()
void createNetworkServer()
{
QEventLoop eventLoop;
- TestHTTPServer server(14453);
+ TestHTTPServer server;
+ QVERIFY2(server.listen(14453), qPrintable(server.errorString()));
server.serveDirectory(QQmlDataTest::instance()->testFile("http"));
QTimer::singleShot(100, &eventLoop, SLOT(quit()));
eventLoop.exec();
@@ -407,7 +410,8 @@ void tst_qquickpixmapcache::networkCrash()
// QTBUG-22125
void tst_qquickpixmapcache::lockingCrash()
{
- TestHTTPServer server(14453);
+ TestHTTPServer server;
+ QVERIFY2(server.listen(14453), qPrintable(server.errorString()));
server.serveDirectory(testFile("http"), TestHTTPServer::Delay);
{
diff --git a/tests/auto/quick/qquickpositioners/tst_qquickpositioners.cpp b/tests/auto/quick/qquickpositioners/tst_qquickpositioners.cpp
index e63ff6639e..035735914a 100644
--- a/tests/auto/quick/qquickpositioners/tst_qquickpositioners.cpp
+++ b/tests/auto/quick/qquickpositioners/tst_qquickpositioners.cpp
@@ -1857,7 +1857,7 @@ void tst_qquickpositioners::test_conflictinganchors()
item = qobject_cast<QQuickItem*>(component.create());
QVERIFY(item);
QCOMPARE(messageHandler.messages().size(), 1);
- QCOMPARE(messageHandler.messages().back(), QString("file::2:1: QML Column: Cannot specify top, bottom, verticalCenter, fill or centerIn anchors for items inside Column. Column will not function."));
+ QCOMPARE(messageHandler.messages().back(), QString("<Unknown File>:2:1: QML Column: Cannot specify top, bottom, verticalCenter, fill or centerIn anchors for items inside Column. Column will not function."));
messageHandler.clear();
delete item;
@@ -1865,7 +1865,7 @@ void tst_qquickpositioners::test_conflictinganchors()
item = qobject_cast<QQuickItem*>(component.create());
QVERIFY(item);
QCOMPARE(messageHandler.messages().size(), 1);
- QCOMPARE(messageHandler.messages().back(), QString("file::2:1: QML Column: Cannot specify top, bottom, verticalCenter, fill or centerIn anchors for items inside Column. Column will not function."));
+ QCOMPARE(messageHandler.messages().back(), QString("<Unknown File>:2:1: QML Column: Cannot specify top, bottom, verticalCenter, fill or centerIn anchors for items inside Column. Column will not function."));
messageHandler.clear();
delete item;
@@ -1879,7 +1879,7 @@ void tst_qquickpositioners::test_conflictinganchors()
item = qobject_cast<QQuickItem*>(component.create());
QVERIFY(item);
QCOMPARE(messageHandler.messages().size(), 1);
- QCOMPARE(messageHandler.messages().back(), QString("file::2:1: QML Row: Cannot specify left, right, horizontalCenter, fill or centerIn anchors for items inside Row. Row will not function."));
+ QCOMPARE(messageHandler.messages().back(), QString("<Unknown File>:2:1: QML Row: Cannot specify left, right, horizontalCenter, fill or centerIn anchors for items inside Row. Row will not function."));
messageHandler.clear();
delete item;
@@ -1887,7 +1887,7 @@ void tst_qquickpositioners::test_conflictinganchors()
item = qobject_cast<QQuickItem*>(component.create());
QVERIFY(item);
QCOMPARE(messageHandler.messages().size(), 1);
- QCOMPARE(messageHandler.messages().back(), QString("file::2:1: QML Row: Cannot specify left, right, horizontalCenter, fill or centerIn anchors for items inside Row. Row will not function."));
+ QCOMPARE(messageHandler.messages().back(), QString("<Unknown File>:2:1: QML Row: Cannot specify left, right, horizontalCenter, fill or centerIn anchors for items inside Row. Row will not function."));
messageHandler.clear();
delete item;
@@ -1901,7 +1901,7 @@ void tst_qquickpositioners::test_conflictinganchors()
item = qobject_cast<QQuickItem*>(component.create());
QVERIFY(item);
QCOMPARE(messageHandler.messages().size(), 1);
- QCOMPARE(messageHandler.messages().back(), QString("file::2:1: QML Grid: Cannot specify anchors for items inside Grid. Grid will not function."));
+ QCOMPARE(messageHandler.messages().back(), QString("<Unknown File>:2:1: QML Grid: Cannot specify anchors for items inside Grid. Grid will not function."));
messageHandler.clear();
delete item;
@@ -1909,7 +1909,7 @@ void tst_qquickpositioners::test_conflictinganchors()
item = qobject_cast<QQuickItem*>(component.create());
QVERIFY(item);
QCOMPARE(messageHandler.messages().size(), 1);
- QCOMPARE(messageHandler.messages().back(), QString("file::2:1: QML Grid: Cannot specify anchors for items inside Grid. Grid will not function."));
+ QCOMPARE(messageHandler.messages().back(), QString("<Unknown File>:2:1: QML Grid: Cannot specify anchors for items inside Grid. Grid will not function."));
messageHandler.clear();
delete item;
@@ -1917,7 +1917,7 @@ void tst_qquickpositioners::test_conflictinganchors()
item = qobject_cast<QQuickItem*>(component.create());
QVERIFY(item);
QCOMPARE(messageHandler.messages().size(), 1);
- QCOMPARE(messageHandler.messages().back(), QString("file::2:1: QML Flow: Cannot specify anchors for items inside Flow. Flow will not function."));
+ QCOMPARE(messageHandler.messages().back(), QString("<Unknown File>:2:1: QML Flow: Cannot specify anchors for items inside Flow. Flow will not function."));
messageHandler.clear();
delete item;
@@ -1925,7 +1925,7 @@ void tst_qquickpositioners::test_conflictinganchors()
item = qobject_cast<QQuickItem*>(component.create());
QVERIFY(item);
QCOMPARE(messageHandler.messages().size(), 1);
- QCOMPARE(messageHandler.messages().back(), QString("file::2:1: QML Flow: Cannot specify anchors for items inside Flow. Flow will not function."));
+ QCOMPARE(messageHandler.messages().back(), QString("<Unknown File>:2:1: QML Flow: Cannot specify anchors for items inside Flow. Flow will not function."));
delete item;
}
diff --git a/tests/auto/quick/qquickrepeater/data/invalidContextCrash.qml b/tests/auto/quick/qquickrepeater/data/invalidContextCrash.qml
new file mode 100644
index 0000000000..4a822cf25a
--- /dev/null
+++ b/tests/auto/quick/qquickrepeater/data/invalidContextCrash.qml
@@ -0,0 +1,7 @@
+import QtQuick 2.0
+Item {
+ Repeater {
+ model: badModel
+ delegate: Item {}
+ }
+}
diff --git a/tests/auto/quick/qquickrepeater/tst_qquickrepeater.cpp b/tests/auto/quick/qquickrepeater/tst_qquickrepeater.cpp
index 9fb76f9584..2dc5a65d7d 100644
--- a/tests/auto/quick/qquickrepeater/tst_qquickrepeater.cpp
+++ b/tests/auto/quick/qquickrepeater/tst_qquickrepeater.cpp
@@ -79,6 +79,7 @@ private slots:
void initParent();
void dynamicModelCrash();
void visualItemModelCrash();
+ void invalidContextCrash();
};
class TestObject : public QObject
@@ -744,6 +745,48 @@ void tst_QQuickRepeater::visualItemModelCrash()
delete window;
}
+class BadModel : public QAbstractListModel
+{
+public:
+ ~BadModel()
+ {
+ beginResetModel();
+ endResetModel();
+ }
+
+ QVariant data(const QModelIndex &, int) const { return QVariant(); }
+ int rowCount(const QModelIndex &) const { return 0; }
+};
+
+
+void tst_QQuickRepeater::invalidContextCrash()
+{
+ QQmlEngine engine;
+ QQmlComponent component(&engine, testFileUrl("invalidContextCrash.qml"));
+
+ BadModel* model = new BadModel;
+ engine.rootContext()->setContextProperty("badModel", model);
+
+ QScopedPointer<QObject> root(component.create());
+ QCOMPARE(root->children().count(), 1);
+ QObject *repeater = root->children().first();
+
+ // Make sure the model comes first in the child list, so it will be
+ // deleted first and then the repeater. During deletion the QML context
+ // has been deleted already and is invalid.
+ model->setParent(root.data());
+ repeater->setParent(0);
+ repeater->setParent(root.data());
+
+ QCOMPARE(root->children().count(), 2);
+ QVERIFY(root->children().at(0) == model);
+ QVERIFY(root->children().at(1) == repeater);
+
+ // Delete the root object, which will invalidate/delete the QML context
+ // and then delete the child QObjects, which may try to access the context.
+ root.reset(0);
+}
+
QTEST_MAIN(tst_QQuickRepeater)
#include "tst_qquickrepeater.moc"
diff --git a/tests/auto/quick/qquickspritesequence/tst_qquickspritesequence.cpp b/tests/auto/quick/qquickspritesequence/tst_qquickspritesequence.cpp
index 79b80c5cfe..2676abb9eb 100644
--- a/tests/auto/quick/qquickspritesequence/tst_qquickspritesequence.cpp
+++ b/tests/auto/quick/qquickspritesequence/tst_qquickspritesequence.cpp
@@ -117,6 +117,9 @@ void tst_qquickspritesequence::test_framerateAdvance()
void tst_qquickspritesequence::test_jumpToCrash()
{
+#if defined(QT_OPENGL_ES_2_ANGLE) && _MSC_VER==1600
+ QSKIP("QTBUG-40658");
+#endif
QQuickView *window = new QQuickView(0);
window->setSource(testFileUrl("crashonstart.qml"));
diff --git a/tests/auto/quick/qquicktext/tst_qquicktext.cpp b/tests/auto/quick/qquicktext/tst_qquicktext.cpp
index 0a7c8c9f92..7897f6d36a 100644
--- a/tests/auto/quick/qquicktext/tst_qquicktext.cpp
+++ b/tests/auto/quick/qquicktext/tst_qquicktext.cpp
@@ -876,6 +876,9 @@ static inline QByteArray msgNotLessThan(int n1, int n2)
void tst_qquicktext::hAlignImplicitWidth()
{
+#if defined(QT_OPENGL_ES_2_ANGLE) && _MSC_VER==1600
+ QSKIP("QTBUG-40658");
+#endif
QQuickView view(testFileUrl("hAlignImplicitWidth.qml"));
view.setFlags(view.flags() | Qt::WindowStaysOnTopHint); // Prevent being obscured by other windows.
view.show();
@@ -2034,7 +2037,8 @@ void tst_qquicktext::embeddedImages()
QFETCH(QUrl, qmlfile);
QFETCH(QString, error);
- TestHTTPServer server(SERVER_PORT);
+ TestHTTPServer server;
+ QVERIFY2(server.listen(SERVER_PORT), qPrintable(server.errorString()));
server.serveDirectory(testFile("http"));
if (!error.isEmpty())
@@ -2772,7 +2776,8 @@ void tst_qquicktext::imgTagsBaseUrl()
QFETCH(QUrl, contextUrl);
QFETCH(qreal, imgHeight);
- TestHTTPServer server(SERVER_PORT);
+ TestHTTPServer server;
+ QVERIFY2(server.listen(SERVER_PORT), qPrintable(server.errorString()));
server.serveDirectory(testFile(""));
QByteArray baseUrlFragment;
@@ -2811,7 +2816,7 @@ void tst_qquicktext::imgTagsAlign()
QFETCH(QString, align);
QString componentStr = "import QtQuick 2.0\nText { text: \"This is a test <img src=\\\"" + src + "\\\" align=\\\"" + align + "\\\"> of image.\" }";
QQmlComponent textComponent(&engine);
- textComponent.setData(componentStr.toLatin1(), QUrl::fromLocalFile(""));
+ textComponent.setData(componentStr.toLatin1(), QUrl::fromLocalFile("."));
QQuickText *textObject = qobject_cast<QQuickText*>(textComponent.create());
QVERIFY(textObject != 0);
@@ -2836,7 +2841,7 @@ void tst_qquicktext::imgTagsMultipleImages()
QString componentStr = "import QtQuick 2.0\nText { text: \"This is a starfish<img src=\\\"data/images/starfish_2.png\\\" width=\\\"60\\\" height=\\\"60\\\" > and another one<img src=\\\"data/images/heart200.png\\\" width=\\\"85\\\" height=\\\"85\\\">.\" }";
QQmlComponent textComponent(&engine);
- textComponent.setData(componentStr.toLatin1(), QUrl::fromLocalFile(""));
+ textComponent.setData(componentStr.toLatin1(), QUrl::fromLocalFile("."));
QQuickText *textObject = qobject_cast<QQuickText*>(textComponent.create());
QVERIFY(textObject != 0);
@@ -2897,8 +2902,8 @@ void tst_qquicktext::imgTagsError()
QString componentStr = "import QtQuick 2.0\nText { text: \"This is a starfish<img src=\\\"data/images/starfish_2.pn\\\" width=\\\"60\\\" height=\\\"60\\\">.\" }";
QQmlComponent textComponent(&engine);
- QTest::ignoreMessage(QtWarningMsg, "file::2:1: QML Text: Cannot open: file:data/images/starfish_2.pn");
- textComponent.setData(componentStr.toLatin1(), QUrl::fromLocalFile(""));
+ QTest::ignoreMessage(QtWarningMsg, "<Unknown File>:2:1: QML Text: Cannot open: file:data/images/starfish_2.pn");
+ textComponent.setData(componentStr.toLatin1(), QUrl("file:"));
QQuickText *textObject = qobject_cast<QQuickText*>(textComponent.create());
QVERIFY(textObject != 0);
diff --git a/tests/auto/quick/qquicktextedit/tst_qquicktextedit.cpp b/tests/auto/quick/qquicktextedit/tst_qquicktextedit.cpp
index 741a724632..00aa1dbe10 100644
--- a/tests/auto/quick/qquicktextedit/tst_qquicktextedit.cpp
+++ b/tests/auto/quick/qquicktextedit/tst_qquicktextedit.cpp
@@ -2603,7 +2603,8 @@ void tst_qquicktextedit::cursorDelegate()
void tst_qquicktextedit::remoteCursorDelegate()
{
- TestHTTPServer server(SERVER_PORT);
+ TestHTTPServer server;
+ QVERIFY2(server.listen(SERVER_PORT), qPrintable(server.errorString()));
server.serveDirectory(dataDirectory(), TestHTTPServer::Delay);
QQuickView view;
@@ -2740,7 +2741,8 @@ void tst_qquicktextedit::delegateLoading()
QFETCH(QString, qmlfile);
QFETCH(QString, error);
- TestHTTPServer server(SERVER_PORT);
+ TestHTTPServer server;
+ QVERIFY2(server.listen(SERVER_PORT), qPrintable(server.errorString()));
server.serveDirectory(testFile("httpfail"), TestHTTPServer::Disconnect);
server.serveDirectory(testFile("httpslow"), TestHTTPServer::Delay);
server.serveDirectory(testFile("http"));
@@ -5214,7 +5216,8 @@ void tst_qquicktextedit::embeddedImages()
QFETCH(QUrl, qmlfile);
QFETCH(QString, error);
- TestHTTPServer server(SERVER_PORT);
+ TestHTTPServer server;
+ QVERIFY2(server.listen(SERVER_PORT), qPrintable(server.errorString()));
server.serveDirectory(testFile("http"));
if (!error.isEmpty())
diff --git a/tests/auto/quick/qquicktextinput/tst_qquicktextinput.cpp b/tests/auto/quick/qquicktextinput/tst_qquicktextinput.cpp
index e125c33a56..c50923b32f 100644
--- a/tests/auto/quick/qquicktextinput/tst_qquicktextinput.cpp
+++ b/tests/auto/quick/qquicktextinput/tst_qquicktextinput.cpp
@@ -232,6 +232,8 @@ private slots:
void baselineOffset_data();
void baselineOffset();
+ void ensureVisible();
+
private:
void simulateKey(QWindow *, int key);
@@ -2232,25 +2234,34 @@ void tst_qquicktextinput::inputMethods()
QTRY_COMPARE(qGuiApp->focusObject(), input);
QGuiApplication::sendEvent(input, &event);
QCOMPARE(input->text(), QString("My Hello world!"));
+ QCOMPARE(input->displayText(), QString("My Hello world!"));
input->setCursorPosition(2);
event.setCommitString("Your", -2, 2);
QGuiApplication::sendEvent(input, &event);
QCOMPARE(input->text(), QString("Your Hello world!"));
+ QCOMPARE(input->displayText(), QString("Your Hello world!"));
QCOMPARE(input->cursorPosition(), 4);
input->setCursorPosition(7);
event.setCommitString("Goodbye", -2, 5);
QGuiApplication::sendEvent(input, &event);
QCOMPARE(input->text(), QString("Your Goodbye world!"));
+ QCOMPARE(input->displayText(), QString("Your Goodbye world!"));
QCOMPARE(input->cursorPosition(), 12);
input->setCursorPosition(8);
event.setCommitString("Our", -8, 4);
QGuiApplication::sendEvent(input, &event);
QCOMPARE(input->text(), QString("Our Goodbye world!"));
+ QCOMPARE(input->displayText(), QString("Our Goodbye world!"));
QCOMPARE(input->cursorPosition(), 7);
+ QInputMethodEvent preeditEvent("PREEDIT", QList<QInputMethodEvent::Attribute>());
+ QGuiApplication::sendEvent(input, &preeditEvent);
+ QCOMPARE(input->text(), QString("Our Goodbye world!"));
+ QCOMPARE(input->displayText(), QString("Our GooPREEDITdbye world!"));
+
// input should reset selection even if replacement parameters are out of bounds
input->setText("text");
input->setCursorPosition(0);
@@ -2258,6 +2269,8 @@ void tst_qquicktextinput::inputMethods()
event.setCommitString("replacement", -input->text().length(), input->text().length());
QGuiApplication::sendEvent(input, &event);
QCOMPARE(input->selectionStart(), input->selectionEnd());
+ QCOMPARE(input->text(), QString("replacement"));
+ QCOMPARE(input->displayText(), QString("replacement"));
QInputMethodQueryEvent enabledQueryEvent(Qt::ImEnabled);
QGuiApplication::sendEvent(input, &enabledQueryEvent);
@@ -2490,7 +2503,7 @@ void tst_qquicktextinput::copyAndPaste()
QCOMPARE(textInput->selectedText(), QString("Hello world!"));
QCOMPARE(textInput->selectedText().length(), 12);
textInput->setCursorPosition(0);
- QVERIFY(textInput->canPaste());
+ QTRY_VERIFY(textInput->canPaste());
textInput->paste();
QCOMPARE(textInput->text(), QString("Hello world!Hello world!"));
QCOMPARE(textInput->text().length(), 24);
@@ -2544,7 +2557,7 @@ void tst_qquicktextinput::copyAndPaste()
QClipboard *clipboard = QGuiApplication::clipboard();
QVERIFY(clipboard);
clipboard->clear();
- QVERIFY(!textInput->canPaste());
+ QTRY_VERIFY(!textInput->canPaste());
// test that copy functionality is disabled
// when echo mode is set to hide text/password mode
@@ -2612,7 +2625,7 @@ void tst_qquicktextinput::copyAndPasteKeySequence()
QClipboard *clipboard = QGuiApplication::clipboard();
QVERIFY(clipboard);
clipboard->clear();
- QVERIFY(!textInput->canPaste());
+ QTRY_VERIFY(!textInput->canPaste());
// test that copy functionality is disabled
// when echo mode is set to hide text/password mode
@@ -2853,7 +2866,8 @@ void tst_qquicktextinput::cursorDelegate()
void tst_qquicktextinput::remoteCursorDelegate()
{
- TestHTTPServer server(SERVER_PORT);
+ TestHTTPServer server;
+ QVERIFY2(server.listen(SERVER_PORT), qPrintable(server.errorString()));
server.serveDirectory(dataDirectory(), TestHTTPServer::Delay);
QQuickView view;
@@ -6269,13 +6283,11 @@ void tst_qquicktextinput::hasAcceptableInputMask()
textInput->setText(invalid);
QVERIFY(textInput->hasAcceptableInput());
- // at the moment we don't strip the blank character if it is valid input, this makes the test between x vs X useless
- QEXPECT_FAIL( "Any optional and required", "To eat blanks or not? Known issue. Task 43172", Abort);
-
// test requiredMask
textInput->setInputMask(requiredMask);
textInput->setText(invalid);
- QVERIFY(!textInput->hasAcceptableInput());
+ // invalid text gets the input mask applied when setting, text becomes acceptable.
+ QVERIFY(textInput->hasAcceptableInput());
textInput->setText(valid);
QVERIFY(textInput->hasAcceptableInput());
@@ -6463,6 +6475,50 @@ void tst_qquicktextinput::baselineOffset()
}
}
+void tst_qquicktextinput::ensureVisible()
+{
+ QQmlComponent component(&engine);
+ component.setData("import QtQuick 2.0\n TextInput {}", QUrl());
+ QScopedPointer<QObject> object(component.create());
+ QQuickTextInput *input = qobject_cast<QQuickTextInput *>(object.data());
+ QVERIFY(input);
+
+ input->setWidth(QFontMetrics(input->font()).averageCharWidth() * 3);
+ input->setText("Hello World");
+
+ QTextLayout layout;
+ layout.setText(input->text());
+ layout.setFont(input->font());
+
+ if (!qmlDisableDistanceField()) {
+ QTextOption option;
+ option.setUseDesignMetrics(true);
+ layout.setTextOption(option);
+ }
+ layout.beginLayout();
+ QTextLine line = layout.createLine();
+ layout.endLayout();
+
+ input->ensureVisible(0);
+
+ QCOMPARE(input->boundingRect().x(), qreal(0));
+ QCOMPARE(input->boundingRect().y(), qreal(0));
+ QCOMPARE(input->boundingRect().width(), line.naturalTextWidth() + input->cursorRectangle().width());
+ QCOMPARE(input->boundingRect().height(), line.height());
+
+ QSignalSpy cursorSpy(input, SIGNAL(cursorRectangleChanged()));
+ QVERIFY(cursorSpy.isValid());
+
+ input->ensureVisible(input->length());
+
+ QCOMPARE(cursorSpy.count(), 1);
+
+ QCOMPARE(input->boundingRect().x(), input->width() - line.naturalTextWidth());
+ QCOMPARE(input->boundingRect().y(), qreal(0));
+ QCOMPARE(input->boundingRect().width(), line.naturalTextWidth() + input->cursorRectangle().width());
+ QCOMPARE(input->boundingRect().height(), line.height());
+}
+
QTEST_MAIN(tst_qquicktextinput)
#include "tst_qquicktextinput.moc"
diff --git a/tests/auto/quick/qquicktextmetrics/qquicktextmetrics.pro b/tests/auto/quick/qquicktextmetrics/qquicktextmetrics.pro
new file mode 100644
index 0000000000..6ef68db8e2
--- /dev/null
+++ b/tests/auto/quick/qquicktextmetrics/qquicktextmetrics.pro
@@ -0,0 +1,10 @@
+CONFIG += testcase
+TARGET = tst_qquicktextmetrics
+osx:CONFIG -= app_bundle
+
+SOURCES += tst_qquicktextmetrics.cpp
+
+CONFIG += parallel_test
+
+QT += core gui qml quick-private testlib
+DEFINES += QT_DISABLE_DEPRECATED_BEFORE=0
diff --git a/tests/auto/quick/qquicktextmetrics/tst_qquicktextmetrics.cpp b/tests/auto/quick/qquicktextmetrics/tst_qquicktextmetrics.cpp
new file mode 100644
index 0000000000..733b3d06b3
--- /dev/null
+++ b/tests/auto/quick/qquicktextmetrics/tst_qquicktextmetrics.cpp
@@ -0,0 +1,161 @@
+/****************************************************************************
+**
+** 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$
+**
+****************************************************************************/
+
+#include <QFont>
+#include <QString>
+#include <QtTest>
+#include <QCoreApplication>
+#include <QQmlComponent>
+#include <QQmlEngine>
+#include <QQuickItem>
+
+#include <QtQuick/private/qquicktextmetrics_p.h>
+
+#include <QFontMetricsF>
+
+class tst_QQuickTextMetrics : public QObject
+{
+ Q_OBJECT
+
+public:
+ tst_QQuickTextMetrics();
+
+private Q_SLOTS:
+ void font();
+ void functionsWithArguments_data();
+ void functionsWithArguments();
+};
+
+tst_QQuickTextMetrics::tst_QQuickTextMetrics()
+{
+}
+
+void tst_QQuickTextMetrics::font()
+{
+ QQuickTextMetrics metrics;
+
+ QSignalSpy fontSpy(&metrics, SIGNAL(fontChanged()));
+ QSignalSpy metricsSpy(&metrics, SIGNAL(metricsChanged()));
+ QFont font;
+ font.setPointSize(font.pointSize() + 1);
+ metrics.setFont(font);
+ QCOMPARE(fontSpy.count(), 1);
+ QCOMPARE(metricsSpy.count(), 1);
+}
+
+Q_DECLARE_METATYPE(Qt::TextElideMode)
+
+void tst_QQuickTextMetrics::functionsWithArguments_data()
+{
+ QTest::addColumn<QString>("text");
+ QTest::addColumn<Qt::TextElideMode>("mode");
+ QTest::addColumn<qreal>("width");
+
+ QStringList strings;
+ strings << QString()
+ << QString::fromLatin1("")
+ << QString::fromLatin1("0")
+ << QString::fromLatin1("@@@@@@@")
+ << QString::fromLatin1("Hello");
+
+ QVector<Qt::TextElideMode> elideModes;
+ elideModes << Qt::ElideLeft << Qt::ElideMiddle << Qt::ElideRight << Qt::ElideNone;
+
+ for (int stringIndex = 0; stringIndex < strings.size(); ++stringIndex) {
+ const QString string = strings.at(stringIndex);
+
+ for (int elideModeIndex = 0; elideModeIndex < elideModes.size(); ++elideModeIndex) {
+ Qt::TextElideMode elideMode = static_cast<Qt::TextElideMode>(elideModes.at(elideModeIndex));
+
+ for (qreal width = 0; width < 100; width += 20) {
+ const QString tag = QString::fromLatin1("string=%1, mode=%2, width=%3").arg(string).arg(elideMode).arg(width);
+ QTest::newRow(qPrintable(tag)) << QString() << elideMode << width;
+ }
+ }
+ }
+}
+
+void tst_QQuickTextMetrics::functionsWithArguments()
+{
+ QFETCH(QString, text);
+ QFETCH(Qt::TextElideMode, mode);
+ QFETCH(qreal, width);
+
+ QQuickTextMetrics metrics;
+ // Ensures that the values actually change.
+ metrics.setText(text + "extra");
+ metrics.setElideWidth(width + 1);
+ switch (mode) {
+ case Qt::ElideNone: metrics.setElide(Qt::ElideMiddle); break;
+ case Qt::ElideLeft: metrics.setElide(Qt::ElideRight); break;
+ case Qt::ElideMiddle: metrics.setElide(Qt::ElideNone); break;
+ case Qt::ElideRight: metrics.setElide(Qt::ElideLeft); break;
+ }
+
+ QSignalSpy textSpy(&metrics, SIGNAL(textChanged()));
+ QSignalSpy metricsSpy(&metrics, SIGNAL(metricsChanged()));
+ metrics.setText(text);
+ QCOMPARE(textSpy.count(), 1);
+ QCOMPARE(metricsSpy.count(), 1);
+
+ QSignalSpy elideSpy(&metrics, SIGNAL(elideChanged()));
+ metrics.setElide(mode);
+ QCOMPARE(elideSpy.count(), 1);
+ QCOMPARE(metricsSpy.count(), 2);
+
+ QSignalSpy elideWidthSpy(&metrics, SIGNAL(elideWidthChanged()));
+ metrics.setElideWidth(width);
+ QCOMPARE(elideWidthSpy.count(), 1);
+ QCOMPARE(metricsSpy.count(), 3);
+
+ QFontMetricsF expected = QFontMetricsF(QFont());
+
+ QCOMPARE(metrics.elidedText(), expected.elidedText(text, mode, width, 0));
+ QCOMPARE(metrics.advanceWidth(), expected.width(text));
+ QCOMPARE(metrics.boundingRect(), expected.boundingRect(text));
+ QCOMPARE(metrics.width(), expected.boundingRect(text).width());
+ QCOMPARE(metrics.height(), expected.boundingRect(text).height());
+ QCOMPARE(metrics.tightBoundingRect(), expected.tightBoundingRect(text));
+}
+
+QTEST_MAIN(tst_QQuickTextMetrics)
+
+#include "tst_qquicktextmetrics.moc"
diff --git a/tests/auto/quick/qquickwindow/data/windowattached.qml b/tests/auto/quick/qquickwindow/data/windowattached.qml
new file mode 100644
index 0000000000..e000d5c6fd
--- /dev/null
+++ b/tests/auto/quick/qquickwindow/data/windowattached.qml
@@ -0,0 +1,25 @@
+import QtQuick 2.4
+import QtQuick.Window 2.2
+
+Rectangle {
+ id: root
+ width: 100
+ height: 100
+ property bool windowActive: root.Window.active
+ Text {
+ objectName: "rectangleWindowText"
+ anchors.centerIn: parent
+ text: (windowActive ? "active" : "inactive") + "\nvisibility: " + root.Window.visibility
+ }
+
+ property Window extraWindow: Window {
+ objectName: "extraWindow"
+ title: "extra window"
+ visible: true
+ Text {
+ objectName: "extraWindowText"
+ anchors.centerIn: parent
+ text: (extraWindow.active ? "active" : "inactive") + "\nvisibility: " + Window.visibility
+ }
+ }
+}
diff --git a/tests/auto/quick/qquickwindow/qquickwindow.pro b/tests/auto/quick/qquickwindow/qquickwindow.pro
index 6bce209df9..e95b7dbb10 100644
--- a/tests/auto/quick/qquickwindow/qquickwindow.pro
+++ b/tests/auto/quick/qquickwindow/qquickwindow.pro
@@ -3,6 +3,7 @@ TARGET = tst_qquickwindow
SOURCES += tst_qquickwindow.cpp
include (../../shared/util.pri)
+include(../shared/util.pri)
macx:CONFIG -= app_bundle
diff --git a/tests/auto/quick/qquickwindow/tst_qquickwindow.cpp b/tests/auto/quick/qquickwindow/tst_qquickwindow.cpp
index b8f9102775..52dd3f1a8d 100644
--- a/tests/auto/quick/qquickwindow/tst_qquickwindow.cpp
+++ b/tests/auto/quick/qquickwindow/tst_qquickwindow.cpp
@@ -43,6 +43,7 @@
#include <QDebug>
#include <QTouchEvent>
#include <QtQuick/QQuickItem>
+#include <QtQuick/QQuickView>
#include <QtQuick/QQuickWindow>
#include <QtQml/QQmlEngine>
#include <QtQml/QQmlComponent>
@@ -50,10 +51,12 @@
#include <QtQuick/private/qquickloader_p.h>
#include "../../shared/util.h"
#include "../shared/visualtestutil.h"
+#include "../shared/viewtestutil.h"
#include <QSignalSpy>
#include <qpa/qwindowsysteminterface.h>
#include <private/qquickwindow_p.h>
#include <private/qguiapplication_p.h>
+#include <QRunnable>
struct TouchEventData {
QEvent::Type type;
@@ -328,6 +331,7 @@ private slots:
void animationsWhileHidden();
void focusObject();
+ void focusReason();
void ignoreUnhandledMouseEvents();
@@ -362,6 +366,12 @@ private slots:
void contentItemSize();
+ void defaultSurfaceFormat();
+
+ void attachedProperty();
+
+ void testRenderJob();
+
private:
QTouchDevice *touchDevice;
QTouchDevice *touchDeviceWithVelocity;
@@ -395,7 +405,7 @@ void tst_qquickwindow::aboutToStopSignal()
window.hide();
- QVERIFY(spy.count() > 0);
+ QTRY_VERIFY(spy.count() > 0);
}
//If the item calls update inside updatePaintNode, it should schedule another sync pass
@@ -522,7 +532,7 @@ void tst_qquickwindow::touchEvent_basic()
// press multiple points
QTest::touchEvent(window, touchDevice).press(0, topItem->mapToScene(pos).toPoint(),window)
.press(1, bottomItem->mapToScene(pos).toPoint(), window);
- QTest::qWait(50);
+ QQuickTouchUtils::flush(window);
QCOMPARE(topItem->lastEvent.touchPoints.count(), 1);
QVERIFY(middleItem->lastEvent.touchPoints.isEmpty());
QCOMPARE(bottomItem->lastEvent.touchPoints.count(), 1);
@@ -533,9 +543,9 @@ void tst_qquickwindow::touchEvent_basic()
// touch point on top item moves to bottom item, but top item should still receive the event
QTest::touchEvent(window, touchDevice).press(0, topItem->mapToScene(pos).toPoint(), window);
- QTest::qWait(50);
+ QQuickTouchUtils::flush(window);
QTest::touchEvent(window, touchDevice).move(0, bottomItem->mapToScene(pos).toPoint(), window);
- QTest::qWait(50);
+ QQuickTouchUtils::flush(window);
QCOMPARE(topItem->lastEvent.touchPoints.count(), 1);
COMPARE_TOUCH_DATA(topItem->lastEvent, makeTouchData(QEvent::TouchUpdate, window, Qt::TouchPointMoved,
makeTouchPoint(topItem, topItem->mapFromItem(bottomItem, pos), pos)));
@@ -543,9 +553,9 @@ void tst_qquickwindow::touchEvent_basic()
// touch point on bottom item moves to top item, but bottom item should still receive the event
QTest::touchEvent(window, touchDevice).press(0, bottomItem->mapToScene(pos).toPoint(), window);
- QTest::qWait(50);
+ QQuickTouchUtils::flush(window);
QTest::touchEvent(window, touchDevice).move(0, topItem->mapToScene(pos).toPoint(), window);
- QTest::qWait(50);
+ QQuickTouchUtils::flush(window);
QCOMPARE(bottomItem->lastEvent.touchPoints.count(), 1);
COMPARE_TOUCH_DATA(bottomItem->lastEvent, makeTouchData(QEvent::TouchUpdate, window, Qt::TouchPointMoved,
makeTouchPoint(bottomItem, bottomItem->mapFromItem(topItem, pos), pos)));
@@ -553,10 +563,10 @@ void tst_qquickwindow::touchEvent_basic()
// a single stationary press on an item shouldn't cause an event
QTest::touchEvent(window, touchDevice).press(0, topItem->mapToScene(pos).toPoint(), window);
- QTest::qWait(50);
+ QQuickTouchUtils::flush(window);
QTest::touchEvent(window, touchDevice).stationary(0)
.press(1, bottomItem->mapToScene(pos).toPoint(), window);
- QTest::qWait(50);
+ QQuickTouchUtils::flush(window);
QCOMPARE(topItem->lastEvent.touchPoints.count(), 1); // received press only, not stationary
QVERIFY(middleItem->lastEvent.touchPoints.isEmpty());
QCOMPARE(bottomItem->lastEvent.touchPoints.count(), 1);
@@ -568,12 +578,13 @@ void tst_qquickwindow::touchEvent_basic()
// Otherwise you will get an assertion failure:
// ASSERT: "itemForTouchPointId.isEmpty()" in file items/qquickwindow.cpp
QTest::touchEvent(window, touchDevice).release(0, pos.toPoint(), window).release(1, pos.toPoint(), window);
+ QQuickTouchUtils::flush(window);
// move touch point from top item to bottom, and release
QTest::touchEvent(window, touchDevice).press(0, topItem->mapToScene(pos).toPoint(),window);
- QTest::qWait(50);
+ QQuickTouchUtils::flush(window);
QTest::touchEvent(window, touchDevice).release(0, bottomItem->mapToScene(pos).toPoint(),window);
- QTest::qWait(50);
+ QQuickTouchUtils::flush(window);
QCOMPARE(topItem->lastEvent.touchPoints.count(), 1);
COMPARE_TOUCH_DATA(topItem->lastEvent, makeTouchData(QEvent::TouchEnd, window, Qt::TouchPointReleased,
makeTouchPoint(topItem, topItem->mapFromItem(bottomItem, pos), pos)));
@@ -582,12 +593,12 @@ void tst_qquickwindow::touchEvent_basic()
// release while another point is pressed
QTest::touchEvent(window, touchDevice).press(0, topItem->mapToScene(pos).toPoint(),window)
.press(1, bottomItem->mapToScene(pos).toPoint(), window);
- QTest::qWait(50);
+ QQuickTouchUtils::flush(window);
QTest::touchEvent(window, touchDevice).move(0, bottomItem->mapToScene(pos).toPoint(), window);
- QTest::qWait(50);
+ QQuickTouchUtils::flush(window);
QTest::touchEvent(window, touchDevice).release(0, bottomItem->mapToScene(pos).toPoint(), window)
.stationary(1);
- QTest::qWait(50);
+ QQuickTouchUtils::flush(window);
QCOMPARE(topItem->lastEvent.touchPoints.count(), 1);
QVERIFY(middleItem->lastEvent.touchPoints.isEmpty());
QCOMPARE(bottomItem->lastEvent.touchPoints.count(), 1);
@@ -835,12 +846,15 @@ void tst_qquickwindow::touchEvent_velocity()
tp.area = QRectF(pos, QSizeF(4, 4));
points << tp;
QWindowSystemInterface::handleTouchEvent(window, touchDeviceWithVelocity, points);
+ QGuiApplication::processEvents();
+ QQuickTouchUtils::flush(window);
points[0].state = Qt::TouchPointMoved;
points[0].area.adjust(5, 5, 5, 5);
QVector2D velocity(1.5, 2.5);
points[0].velocity = velocity;
QWindowSystemInterface::handleTouchEvent(window, touchDeviceWithVelocity, points);
- QCoreApplication::processEvents();
+ QGuiApplication::processEvents();
+ QQuickTouchUtils::flush(window);
QCOMPARE(item->touchEventCount, 2);
QCOMPARE(item->lastEvent.touchPoints.count(), 1);
QCOMPARE(item->lastVelocity, velocity);
@@ -852,7 +866,8 @@ void tst_qquickwindow::touchEvent_velocity()
QVector2D transformedVelocity = transformMatrix.mapVector(velocity).toVector2D();
points[0].area.adjust(5, 5, 5, 5);
QWindowSystemInterface::handleTouchEvent(window, touchDeviceWithVelocity, points);
- QCoreApplication::processEvents();
+ QGuiApplication::processEvents();
+ QQuickTouchUtils::flush(window);
QCOMPARE(item->lastVelocity, transformedVelocity);
QPoint itemLocalPos = item->mapFromScene(window->mapFromGlobal(points[0].area.center().toPoint())).toPoint();
QPoint itemLocalPosFromEvent = item->lastEvent.touchPoints[0].pos().toPoint();
@@ -860,7 +875,8 @@ void tst_qquickwindow::touchEvent_velocity()
points[0].state = Qt::TouchPointReleased;
QWindowSystemInterface::handleTouchEvent(window, touchDeviceWithVelocity, points);
- QCoreApplication::processEvents();
+ QGuiApplication::processEvents();
+ QQuickTouchUtils::flush(window);
delete item;
}
@@ -892,14 +908,19 @@ void tst_qquickwindow::mouseFromTouch_basic()
tp.area = QRectF(pos, QSizeF(4, 4));
points << tp;
QWindowSystemInterface::handleTouchEvent(window, touchDeviceWithVelocity, points);
+ QGuiApplication::processEvents();
+ QQuickTouchUtils::flush(window);
points[0].state = Qt::TouchPointMoved;
points[0].area.adjust(5, 5, 5, 5);
QVector2D velocity(1.5, 2.5);
points[0].velocity = velocity;
QWindowSystemInterface::handleTouchEvent(window, touchDeviceWithVelocity, points);
+ QGuiApplication::processEvents();
+ QQuickTouchUtils::flush(window);
points[0].state = Qt::TouchPointReleased;
QWindowSystemInterface::handleTouchEvent(window, touchDeviceWithVelocity, points);
- QCoreApplication::processEvents();
+ QGuiApplication::processEvents();
+ QQuickTouchUtils::flush(window);
// The item should have received a mouse press, move, and release.
QCOMPARE(item->mousePressNum, 1);
@@ -918,16 +939,20 @@ void tst_qquickwindow::mouseFromTouch_basic()
points[0].velocity = velocity;
points[0].area = QRectF(pos, QSizeF(4, 4));
QWindowSystemInterface::handleTouchEvent(window, touchDeviceWithVelocity, points);
+ QGuiApplication::processEvents();
+ QQuickTouchUtils::flush(window);
points[0].state = Qt::TouchPointMoved;
points[0].area.adjust(5, 5, 5, 5);
QWindowSystemInterface::handleTouchEvent(window, touchDeviceWithVelocity, points);
- QCoreApplication::processEvents();
+ QGuiApplication::processEvents();
+ QQuickTouchUtils::flush(window);
QCOMPARE(item->lastMousePos.toPoint(), item->mapFromScene(window->mapFromGlobal(points[0].area.center().toPoint())).toPoint());
QCOMPARE(item->lastVelocityFromMouseMove, transformedVelocity);
points[0].state = Qt::TouchPointReleased;
QWindowSystemInterface::handleTouchEvent(window, touchDeviceWithVelocity, points);
QCoreApplication::processEvents();
+ QQuickTouchUtils::flush(window);
delete item;
}
@@ -1275,6 +1300,33 @@ void tst_qquickwindow::focusObject()
QCOMPARE(focusObjectSpy.count(), 3);
}
+void tst_qquickwindow::focusReason()
+{
+ QQuickWindow *window = new QQuickWindow;
+ QScopedPointer<QQuickWindow> cleanup(window);
+ window->resize(200, 200);
+ window->show();
+ QVERIFY(QTest::qWaitForWindowExposed(window));
+
+ QQuickItem *firstItem = new QQuickItem;
+ firstItem->setSize(QSizeF(100, 100));
+ firstItem->setParentItem(window->contentItem());
+
+ QQuickItem *secondItem = new QQuickItem;
+ secondItem->setSize(QSizeF(100, 100));
+ secondItem->setParentItem(window->contentItem());
+
+ firstItem->forceActiveFocus(Qt::OtherFocusReason);
+ QCOMPARE(QQuickWindowPrivate::get(window)->lastFocusReason, Qt::OtherFocusReason);
+
+ secondItem->forceActiveFocus(Qt::TabFocusReason);
+ QCOMPARE(QQuickWindowPrivate::get(window)->lastFocusReason, Qt::TabFocusReason);
+
+ firstItem->forceActiveFocus(Qt::BacktabFocusReason);
+ QCOMPARE(QQuickWindowPrivate::get(window)->lastFocusReason, Qt::BacktabFocusReason);
+
+}
+
void tst_qquickwindow::ignoreUnhandledMouseEvents()
{
QQuickWindow *window = new QQuickWindow;
@@ -1718,14 +1770,14 @@ void tst_qquickwindow::unloadSubWindow()
QVERIFY(window);
window->show();
QTest::qWaitForWindowExposed(window);
- QQuickWindow *transient = Q_NULLPTR;
+ QPointer<QQuickWindow> transient;
QTRY_VERIFY(transient = window->property("transientWindow").value<QQuickWindow*>());
QTest::qWaitForWindowExposed(transient);
// Unload the inner window (in nested Loaders) and make sure it doesn't crash
QQuickLoader *loader = window->property("loader1").value<QQuickLoader*>();
loader->setActive(false);
- QTRY_VERIFY(!transient->isVisible());
+ QTRY_VERIFY(transient.isNull() || !transient->isVisible());
}
// QTBUG-32004
@@ -1851,6 +1903,121 @@ void tst_qquickwindow::contentItemSize()
QCOMPARE(QSizeF(rect->width(), rect->height()), size);
}
+void tst_qquickwindow::defaultSurfaceFormat()
+{
+ // It is quite difficult to verify anything for real since the resulting format after
+ // surface/context creation can be anything, depending on the platform and drivers,
+ // and many options and settings may fail in various configurations, but test at
+ // least using some harmless settings to check that the global, static format is
+ // taken into account in the requested format.
+
+ QSurfaceFormat savedDefaultFormat = QSurfaceFormat::defaultFormat();
+
+ // Verify that depth and stencil are set, as they should be, unless they are disabled
+ // via environment variables.
+
+ QSurfaceFormat format = savedDefaultFormat;
+ format.setSwapInterval(0);
+ format.setRedBufferSize(8);
+ format.setGreenBufferSize(8);
+ format.setBlueBufferSize(8);
+ format.setProfile(QSurfaceFormat::CompatibilityProfile);
+ format.setOption(QSurfaceFormat::DebugContext);
+ // Will not set depth and stencil. That should be added automatically,
+ // unless the are disabled (but they aren't).
+ QSurfaceFormat::setDefaultFormat(format);
+
+ QQuickWindow window;
+ window.show();
+ QVERIFY(QTest::qWaitForWindowExposed(&window));
+
+ const QSurfaceFormat reqFmt = window.requestedFormat();
+ QCOMPARE(format.swapInterval(), reqFmt.swapInterval());
+ QCOMPARE(format.redBufferSize(), reqFmt.redBufferSize());
+ QCOMPARE(format.greenBufferSize(), reqFmt.greenBufferSize());
+ QCOMPARE(format.blueBufferSize(), reqFmt.blueBufferSize());
+ QCOMPARE(format.profile(), reqFmt.profile());
+ QCOMPARE(int(format.options()), int(reqFmt.options()));
+
+ // Depth and stencil should be >= what has been requested. For real. But use
+ // the context since the window's surface format is only partially updated
+ // on most platforms.
+ QVERIFY(window.openglContext()->format().depthBufferSize() >= 16);
+ QVERIFY(window.openglContext()->format().stencilBufferSize() >= 8);
+
+ QSurfaceFormat::setDefaultFormat(savedDefaultFormat);
+}
+
+void tst_qquickwindow::attachedProperty()
+{
+ QQuickView view(testFileUrl("windowattached.qml"));
+ view.show();
+ view.requestActivate();
+ QVERIFY(QTest::qWaitForWindowActive(&view));
+ QVERIFY(view.rootObject()->property("windowActive").toBool());
+
+ QQuickWindow *innerWindow = view.rootObject()->findChild<QQuickWindow*>("extraWindow");
+ QVERIFY(innerWindow);
+ innerWindow->requestActivate();
+ QVERIFY(QTest::qWaitForWindowActive(innerWindow));
+
+ QQuickText *text = view.rootObject()->findChild<QQuickText*>("extraWindowText");
+ QVERIFY(text);
+ QCOMPARE(text->text(), QLatin1String("active\nvisibility: 2"));
+}
+
+class RenderJob : public QRunnable
+{
+public:
+ RenderJob(QQuickWindow::RenderStage s, QList<QQuickWindow::RenderStage> *l) : stage(s), list(l) { }
+ ~RenderJob() { ++deleted; }
+ QQuickWindow::RenderStage stage;
+ QList<QQuickWindow::RenderStage> *list;
+ void run() {
+ list->append(stage);
+ }
+ static int deleted;
+};
+
+int RenderJob::deleted = 0;
+
+void tst_qquickwindow::testRenderJob()
+{
+ QList<QQuickWindow::RenderStage> completedJobs;
+
+ QQuickWindow window;
+
+ QQuickWindow::RenderStage stages[] = {
+ QQuickWindow::BeforeSynchronizingStage,
+ QQuickWindow::AfterSynchronizingStage,
+ QQuickWindow::BeforeRenderingStage,
+ QQuickWindow::AfterRenderingStage,
+ QQuickWindow::AfterSwapStage
+ };
+ // Schedule the jobs
+ for (int i=0; i<5; ++i)
+ window.scheduleRenderJob(new RenderJob(stages[i], &completedJobs), stages[i]);
+ window.show();
+
+ QTRY_COMPARE(completedJobs.size(), 5);
+
+ for (int i=0; i<5; ++i) {
+ QCOMPARE(completedJobs.at(i), stages[i]);
+ }
+
+ // Verify that jobs are deleted when window has not been rendered at all...
+ completedJobs.clear();
+ RenderJob::deleted = 0;
+ {
+ QQuickWindow window2;
+ for (int i=0; i<5; ++i) {
+ window2.scheduleRenderJob(new RenderJob(stages[i], &completedJobs), stages[i]);
+ }
+ }
+ QCOMPARE(completedJobs.size(), 0);
+ QCOMPARE(RenderJob::deleted, 5);
+}
+
QTEST_MAIN(tst_qquickwindow)
#include "tst_qquickwindow.moc"
diff --git a/tests/auto/quick/quick.pro b/tests/auto/quick/quick.pro
index 6c163d9619..0a887534bd 100644
--- a/tests/auto/quick/quick.pro
+++ b/tests/auto/quick/quick.pro
@@ -18,6 +18,7 @@ PRIVATETESTS += \
qquickapplication \
qquickbehaviors \
qquickfontloader \
+ qquickfontmetrics \
qquickimageprovider \
qquickpath \
qquicksmoothedanimation \
@@ -55,6 +56,7 @@ QUICKTESTS = \
qquickloader \
qquickmousearea \
qquickmultipointtoucharea \
+ qquickopenglinfo \
qquickpainteditem \
qquickpathview \
qquickpincharea \
diff --git a/tests/auto/quick/rendernode/data/matrix.qml b/tests/auto/quick/rendernode/data/matrix.qml
new file mode 100644
index 0000000000..8b721e5075
--- /dev/null
+++ b/tests/auto/quick/rendernode/data/matrix.qml
@@ -0,0 +1,87 @@
+/****************************************************************************
+**
+** 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.0
+import RenderNode 1.0
+
+Item {
+ width: 320
+ height: 480
+
+ Item { x: 10; y: 10; width: 10; height: 10;
+ StateRecorder { x: 10; y: 10; objectName: "no-clip; no-rotation"; }
+ }
+
+ Item { x: 10; y: 10; width: 10; height: 10; clip: true
+ StateRecorder { x: 10; y: 10; objectName: "parent-clip; no-rotation"; }
+ }
+
+ Item { x: 10; y: 10; width: 10; height: 10;
+ StateRecorder { x: 10; y: 10; objectName: "self-clip; no-rotation"; clip: true }
+ }
+
+
+ Item { x: 10; y: 10; width: 10; height: 10; rotation: 90
+ StateRecorder { x: 10; y: 10; objectName: "no-clip; parent-rotation"; }
+ }
+
+ Item { x: 10; y: 10; width: 10; height: 10; clip: true; rotation: 90
+ StateRecorder { x: 10; y: 10; objectName: "parent-clip; parent-rotation"; }
+ }
+
+ Item { x: 10; y: 10; width: 10; height: 10; rotation: 90
+ StateRecorder { x: 10; y: 10; objectName: "self-clip; parent-rotation"; clip: true }
+ }
+
+
+ Item { x: 10; y: 10; width: 10; height: 10;
+ StateRecorder { x: 10; y: 10; objectName: "no-clip; self-rotation"; rotation: 90 }
+ }
+
+ Item { x: 10; y: 10; width: 10; height: 10; clip: true;
+ StateRecorder { x: 10; y: 10; objectName: "parent-clip; self-rotation"; rotation: 90}
+ }
+
+ Item { x: 10; y: 10; width: 10; height: 10;
+ StateRecorder { x: 10; y: 10; objectName: "self-clip; self-rotation"; clip: true; rotation: 90 }
+ }
+
+}
diff --git a/tests/auto/quick/rendernode/rendernode.pro b/tests/auto/quick/rendernode/rendernode.pro
index b55b7b0bec..bedcefde86 100644
--- a/tests/auto/quick/rendernode/rendernode.pro
+++ b/tests/auto/quick/rendernode/rendernode.pro
@@ -14,4 +14,6 @@ QT += core-private gui-private qml-private quick-private testlib
OTHER_FILES += \
data/RenderOrder.qml \
data/MessUpState.qml \
+ data/matrix.qml
+
DEFINES += QT_DISABLE_DEPRECATED_BEFORE=0
diff --git a/tests/auto/quick/rendernode/tst_rendernode.cpp b/tests/auto/quick/rendernode/tst_rendernode.cpp
index 06338e09e2..2397392419 100644
--- a/tests/auto/quick/rendernode/tst_rendernode.cpp
+++ b/tests/auto/quick/rendernode/tst_rendernode.cpp
@@ -44,6 +44,7 @@
#include <QtQuick/qquickitem.h>
#include <QtQuick/qquickview.h>
#include <QtGui/qopenglcontext.h>
+#include <QtGui/qopenglfunctions.h>
#include <QtGui/qscreen.h>
#include <private/qsgrendernode_p.h>
@@ -72,6 +73,7 @@ public:
private slots:
void renderOrder();
void messUpState();
+ void matrix();
};
class ClearNode : public QSGRenderNode
@@ -85,8 +87,8 @@ public:
virtual void render(const RenderState &)
{
// If clip has been set, scissoring will make sure the right area is cleared.
- glClearColor(color.redF(), color.greenF(), color.blueF(), 1.0f);
- glClear(GL_COLOR_BUFFER_BIT);
+ QOpenGLContext::currentContext()->functions()->glClearColor(color.redF(), color.greenF(), color.blueF(), 1.0f);
+ QOpenGLContext::currentContext()->functions()->glClear(GL_COLOR_BUFFER_BIT);
}
QColor color;
@@ -128,9 +130,11 @@ private:
QColor m_color;
};
-class MessUpNode : public QSGRenderNode
+class MessUpNode : public QSGRenderNode, protected QOpenGLFunctions
{
public:
+ MessUpNode() : initialized(false) { }
+
virtual StateFlags changedStates()
{
return StateFlags(DepthState) | StencilState | ScissorState | ColorState | BlendState
@@ -139,17 +143,17 @@ public:
virtual void render(const RenderState &)
{
+ if (!initialized) {
+ initializeOpenGLFunctions();
+ initialized = true;
+ }
// Don't draw anything, just mess up the state
glViewport(10, 10, 10, 10);
glDisable(GL_SCISSOR_TEST);
glDepthMask(true);
glEnable(GL_DEPTH_TEST);
glDepthFunc(GL_EQUAL);
-#if defined(QT_OPENGL_ES)
glClearDepthf(1);
-#else
- glClearDepth(1);
-#endif
glClearStencil(42);
glClearColor(1.0f, 0.5f, 1.0f, 0.0f);
glClear(GL_DEPTH_BUFFER_BIT | GL_STENCIL_BUFFER_BIT);
@@ -162,6 +166,8 @@ public:
glFrontFace(frontFace == GL_CW ? GL_CCW : GL_CW);
glEnable(GL_CULL_FACE);
}
+
+ bool initialized;
};
class MessUpItem : public QQuickItem
@@ -261,6 +267,84 @@ void tst_rendernode::messUpState()
QCOMPARE(fb.pixel(x2, y5), qRgb(0x00, 0x00, 0x00));
}
+class StateRecordingRenderNode : public QSGRenderNode
+{
+public:
+ StateFlags changedStates() { return StateFlags(-1); }
+ void render(const RenderState &) {
+ matrices[name] = *matrix();
+
+ }
+
+ QString name;
+ static QHash<QString, QMatrix4x4> matrices;
+};
+
+QHash<QString, QMatrix4x4> StateRecordingRenderNode::matrices;
+
+class StateRecordingRenderNodeItem : public QQuickItem
+{
+ Q_OBJECT
+public:
+ StateRecordingRenderNodeItem() { setFlag(ItemHasContents, true); }
+ QSGNode *updatePaintNode(QSGNode *r, UpdatePaintNodeData *) {
+ if (r)
+ return r;
+ StateRecordingRenderNode *rn = new StateRecordingRenderNode();
+ rn->name = objectName();
+ return rn;
+ }
+};
+
+void tst_rendernode::matrix()
+{
+ qmlRegisterType<StateRecordingRenderNodeItem>("RenderNode", 1, 0, "StateRecorder");
+ StateRecordingRenderNode::matrices.clear();
+ runTest("matrix.qml");
+
+ QMatrix4x4 noRotateOffset;
+ noRotateOffset.translate(20, 20);
+ { QMatrix4x4 result = StateRecordingRenderNode::matrices.value(QStringLiteral("no-clip; no-rotation"));
+ QCOMPARE(result, noRotateOffset);
+ }
+ { QMatrix4x4 result = StateRecordingRenderNode::matrices.value(QStringLiteral("parent-clip; no-rotation"));
+ QCOMPARE(result, noRotateOffset);
+ }
+ { QMatrix4x4 result = StateRecordingRenderNode::matrices.value(QStringLiteral("self-clip; no-rotation"));
+ QCOMPARE(result, noRotateOffset);
+ }
+
+ QMatrix4x4 parentRotation;
+ parentRotation.translate(10, 10); // parent at x/y: 10
+ parentRotation.translate(5, 5); // rotate 90 around center (width/height: 10)
+ parentRotation.rotate(90, 0, 0, 1);
+ parentRotation.translate(-5, -5);
+ parentRotation.translate(10, 10); // StateRecorder at: x/y: 10
+ { QMatrix4x4 result = StateRecordingRenderNode::matrices.value(QStringLiteral("no-clip; parent-rotation"));
+ QCOMPARE(result, parentRotation);
+ }
+ { QMatrix4x4 result = StateRecordingRenderNode::matrices.value(QStringLiteral("parent-clip; parent-rotation"));
+ QCOMPARE(result, parentRotation);
+ }
+ { QMatrix4x4 result = StateRecordingRenderNode::matrices.value(QStringLiteral("self-clip; parent-rotation"));
+ QCOMPARE(result, parentRotation);
+ }
+
+ QMatrix4x4 selfRotation;
+ selfRotation.translate(10, 10); // parent at x/y: 10
+ selfRotation.translate(10, 10); // StateRecorder at: x/y: 10
+ selfRotation.rotate(90, 0, 0, 1); // rotate 90, width/height: 0
+ { QMatrix4x4 result = StateRecordingRenderNode::matrices.value(QStringLiteral("no-clip; self-rotation"));
+ QCOMPARE(result, selfRotation);
+ }
+ { QMatrix4x4 result = StateRecordingRenderNode::matrices.value(QStringLiteral("parent-clip; self-rotation"));
+ QCOMPARE(result, selfRotation);
+ }
+ { QMatrix4x4 result = StateRecordingRenderNode::matrices.value(QStringLiteral("self-clip; self-rotation"));
+ QCOMPARE(result, selfRotation);
+ }
+}
+
QTEST_MAIN(tst_rendernode)
diff --git a/tests/auto/quick/scenegraph/data/render_DrawSets.qml b/tests/auto/quick/scenegraph/data/render_DrawSets.qml
index 7515bcf95a..35a8e2860c 100644
--- a/tests/auto/quick/scenegraph/data/render_DrawSets.qml
+++ b/tests/auto/quick/scenegraph/data/render_DrawSets.qml
@@ -40,6 +40,7 @@
****************************************************************************/
import QtQuick 2.2
+import SceneGraphTest 1.0
/*
The purpose of the test is to verify that a batch of more than 64K
@@ -64,39 +65,20 @@ RenderTestBase
{
id: root
- Grid {
+ Column {
id: clipped
width: 100
- height: 500
clip: true
- columns: 100
- Repeater {
- id: clippedRepeater
- model: clipped.width * clipped.height
- Rectangle {
- width: 1
- height: 1
- color: index < clippedRepeater.model / 2 ? "red" : "blue";
- }
- }
+ PerPixelRect { width: 100; height: 250; color: "red" }
+ PerPixelRect { width: 100; height: 250; color: "blue" }
}
- Grid {
+ Column {
id: unclipped
x: 100
width: 100
- height: 500
- clip: true
- columns: 100
- Repeater {
- id: unclippedRepeater
- model: unclipped.width * unclipped.height
- Rectangle {
- width: 1
- height: 1
- color: index < unclippedRepeater.model / 2 ? "black" : "#00ff00";
- }
- }
+ PerPixelRect { width: 100; height: 250; color: "black" }
+ PerPixelRect { width: 100; height: 250; color: "#00ff00" }
}
SequentialAnimation {
@@ -108,6 +90,5 @@ RenderTestBase
onEnterFinalStage: {
animation.running = true;
-
}
}
diff --git a/tests/auto/quick/scenegraph/tst_scenegraph.cpp b/tests/auto/quick/scenegraph/tst_scenegraph.cpp
index d510fdcda8..301174656c 100644
--- a/tests/auto/quick/scenegraph/tst_scenegraph.cpp
+++ b/tests/auto/quick/scenegraph/tst_scenegraph.cpp
@@ -45,14 +45,59 @@
#include <private/qopenglcontext_p.h>
-
#include <QtQml>
+class PerPixelRect : public QQuickItem
+{
+ Q_PROPERTY(QColor color READ color WRITE setColor NOTIFY colorChanged)
+ Q_OBJECT
+public:
+ PerPixelRect() {
+ setFlag(ItemHasContents);
+ }
+
+ void setColor(const QColor &c) {
+ if (c == m_color)
+ return;
+ m_color = c;
+ emit colorChanged(c);
+ }
+
+ QColor color() const { return m_color; }
+
+ QSGNode *updatePaintNode(QSGNode *old, UpdatePaintNodeData *)
+ {
+ if (old)
+ delete old;
+
+ QSGNode *node = new QSGNode();
+
+ for (int y=0; y<height(); ++y) {
+ for (int x=0; x<width(); ++x) {
+ QSGSimpleRectNode *rn = new QSGSimpleRectNode();
+ rn->setRect(x, y, 1, 1);
+ rn->setColor(m_color);
+ node->appendChildNode(rn);
+ }
+ }
+
+ return node;
+ }
+
+Q_SIGNALS:
+ void colorChanged(const QColor &c );
+
+private:
+ QColor m_color;
+};
+
class tst_SceneGraph : public QObject
{
Q_OBJECT
private slots:
+ void initTestCase();
+
void manyWindows_data();
void manyWindows();
@@ -67,6 +112,11 @@ public:
~ScopedList() { qDeleteAll(*this); }
};
+void tst_SceneGraph::initTestCase()
+{
+ qmlRegisterType<PerPixelRect>("SceneGraphTest", 1, 0, "PerPixelRect");
+}
+
QQuickView *createView(const QString &file, QWindow *parent = 0, int x = -1, int y = -1, int w = -1, int h = -1)
{
QQuickView *view = new QQuickView(parent);
diff --git a/tests/auto/quick/shared/viewtestutil.cpp b/tests/auto/quick/shared/viewtestutil.cpp
index 0e3964d52d..aa6d7c4a93 100644
--- a/tests/auto/quick/shared/viewtestutil.cpp
+++ b/tests/auto/quick/shared/viewtestutil.cpp
@@ -47,6 +47,9 @@
#include <QtTest/QTest>
+#include <private/qquickwindow_p.h>
+
+
QQuickView *QQuickViewTestUtil::createView()
{
QQuickView *window = new QQuickView(0);
@@ -341,3 +344,23 @@ QList<QPair<QString,QString> > QQuickViewTestUtil::ListRange::getModelDataValues
return data;
}
+namespace QQuickTouchUtils {
+
+ /* QQuickWindow does event compression and only delivers events just
+ * before it is about to render the next frame. Since some tests
+ * rely on events being delivered immediately AND that no other
+ * event processing has occurred in the meanwhile, we flush the
+ * event manually and immediately.
+ */
+ void flush(QQuickWindow *window) {
+ if (!window)
+ return;
+ QQuickWindowPrivate *wd = QQuickWindowPrivate::get(window);
+ if (!wd || !wd->delayedTouch)
+ return;
+ wd->reallyDeliverTouchEvent(wd->delayedTouch);
+ delete wd->delayedTouch;
+ wd->delayedTouch = 0;
+ }
+
+}
diff --git a/tests/auto/quick/shared/viewtestutil.h b/tests/auto/quick/shared/viewtestutil.h
index 5b0b10b69c..e10966ddba 100644
--- a/tests/auto/quick/shared/viewtestutil.h
+++ b/tests/auto/quick/shared/viewtestutil.h
@@ -166,6 +166,10 @@ namespace QQuickViewTestUtil
}
}
+namespace QQuickTouchUtils {
+ void flush(QQuickWindow *window);
+}
+
Q_DECLARE_METATYPE(QQuickViewTestUtil::QaimModel*)
Q_DECLARE_METATYPE(QQuickViewTestUtil::ListChange)
Q_DECLARE_METATYPE(QList<QQuickViewTestUtil::ListChange>)
diff --git a/tests/auto/quick/touchmouse/touchmouse.pro b/tests/auto/quick/touchmouse/touchmouse.pro
index 445bee08ae..7d23dfc0ae 100644
--- a/tests/auto/quick/touchmouse/touchmouse.pro
+++ b/tests/auto/quick/touchmouse/touchmouse.pro
@@ -8,6 +8,7 @@ macx:CONFIG -= app_bundle
SOURCES += tst_touchmouse.cpp
include (../../shared/util.pri)
+include (../shared/util.pri)
TESTDATA = data/*
diff --git a/tests/auto/quick/touchmouse/tst_touchmouse.cpp b/tests/auto/quick/touchmouse/tst_touchmouse.cpp
index 5b4ad0ffa3..f39a22e131 100644
--- a/tests/auto/quick/touchmouse/tst_touchmouse.cpp
+++ b/tests/auto/quick/touchmouse/tst_touchmouse.cpp
@@ -58,6 +58,7 @@
#include <QtQml/qqmlproperty.h>
#include "../../shared/util.h"
+#include "../shared/viewtestutil.h"
struct Event
{
@@ -221,12 +222,15 @@ void tst_TouchMouse::simpleTouchEvent()
QPoint p1;
p1 = QPoint(20, 20);
QTest::touchEvent(window, device).press(0, p1, window);
+ QQuickTouchUtils::flush(window);
QCOMPARE(eventItem1->eventList.size(), 1);
QCOMPARE(eventItem1->eventList.at(0).type, QEvent::TouchBegin);
p1 += QPoint(10, 0);
QTest::touchEvent(window, device).move(0, p1, window);
+ QQuickTouchUtils::flush(window);
QCOMPARE(eventItem1->eventList.size(), 1);
QTest::touchEvent(window, device).release(0, p1, window);
+ QQuickTouchUtils::flush(window);
QCOMPARE(eventItem1->eventList.size(), 1);
eventItem1->eventList.clear();
@@ -234,11 +238,14 @@ void tst_TouchMouse::simpleTouchEvent()
eventItem1->acceptTouch = true;
p1 = QPoint(20, 20);
QTest::touchEvent(window, device).press(0, p1, window);
+ QQuickTouchUtils::flush(window);
QCOMPARE(eventItem1->eventList.size(), 1);
p1 += QPoint(10, 0);
QTest::touchEvent(window, device).move(0, p1, window);
+ QQuickTouchUtils::flush(window);
QCOMPARE(eventItem1->eventList.size(), 2);
QTest::touchEvent(window, device).release(0, p1, window);
+ QQuickTouchUtils::flush(window);
QCOMPARE(eventItem1->eventList.size(), 3);
eventItem1->eventList.clear();
@@ -251,6 +258,7 @@ void tst_TouchMouse::simpleTouchEvent()
eventItem1->setAcceptedMouseButtons(Qt::LeftButton);
p1 = QPoint(20, 20);
QTest::touchEvent(window, device).press(0, p1, window);
+ QQuickTouchUtils::flush(window);
QCOMPARE(eventItem1->eventList.size(), 2);
QCOMPARE(eventItem1->eventList.at(0).type, QEvent::TouchBegin);
QCOMPARE(eventItem1->eventList.at(1).type, QEvent::MouseButtonPress);
@@ -268,10 +276,12 @@ void tst_TouchMouse::simpleTouchEvent()
p1 += QPoint(10, 0);
QTest::touchEvent(window, device).move(0, p1, window);
+ QQuickTouchUtils::flush(window);
QCOMPARE(eventItem1->eventList.size(), 4);
QCOMPARE(eventItem1->eventList.at(2).type, QEvent::TouchUpdate);
QCOMPARE(eventItem1->eventList.at(3).type, QEvent::MouseMove);
QTest::touchEvent(window, device).release(0, p1, window);
+ QQuickTouchUtils::flush(window);
QCOMPARE(eventItem1->eventList.size(), 6);
QCOMPARE(eventItem1->eventList.at(4).type, QEvent::TouchEnd);
QCOMPARE(eventItem1->eventList.at(5).type, QEvent::MouseButtonRelease);
@@ -286,13 +296,16 @@ void tst_TouchMouse::simpleTouchEvent()
eventItem1->setAcceptedMouseButtons(Qt::LeftButton);
p1 = QPoint(20, 20);
QTest::touchEvent(window, device).press(0, p1, window);
+ QQuickTouchUtils::flush(window);
QCOMPARE(eventItem1->eventList.size(), 2);
QCOMPARE(eventItem1->eventList.at(0).type, QEvent::TouchBegin);
QCOMPARE(eventItem1->eventList.at(1).type, QEvent::MouseButtonPress);
p1 += QPoint(10, 0);
QTest::touchEvent(window, device).move(0, p1, window);
+ QQuickTouchUtils::flush(window);
QCOMPARE(eventItem1->eventList.size(), 2);
QTest::touchEvent(window, device).release(0, p1, window);
+ QQuickTouchUtils::flush(window);
QCOMPARE(eventItem1->eventList.size(), 2);
eventItem1->eventList.clear();
@@ -304,13 +317,16 @@ void tst_TouchMouse::simpleTouchEvent()
eventItem1->setAcceptedMouseButtons(Qt::LeftButton);
p1 = QPoint(20, 20);
QTest::touchEvent(window, device).press(0, p1, window);
+ QQuickTouchUtils::flush(window);
QCOMPARE(eventItem1->eventList.size(), 1);
QCOMPARE(eventItem1->eventList.at(0).type, QEvent::TouchBegin);
p1 += QPoint(10, 0);
QTest::touchEvent(window, device).move(0, p1, window);
+ QQuickTouchUtils::flush(window);
QCOMPARE(eventItem1->eventList.size(), 2);
QCOMPARE(eventItem1->eventList.at(1).type, QEvent::TouchUpdate);
QTest::touchEvent(window, device).release(0, p1, window);
+ QQuickTouchUtils::flush(window);
QCOMPARE(eventItem1->eventList.size(), 3);
QCOMPARE(eventItem1->eventList.at(2).type, QEvent::TouchEnd);
eventItem1->eventList.clear();
@@ -376,6 +392,7 @@ void tst_TouchMouse::mouse()
// item 2 doesn't accept anything, thus it sees a touch pass by
QPoint p1 = QPoint(30, 30);
QTest::touchEvent(window, device).press(0, p1, window);
+ QQuickTouchUtils::flush(window);
QCOMPARE(eventItem1->eventList.size(), 2);
QCOMPARE(eventItem1->eventList.at(0).type, QEvent::TouchBegin);
@@ -412,14 +429,17 @@ void tst_TouchMouse::touchOverMouse()
QCOMPARE(eventItem1->eventList.size(), 0);
QPoint p1 = QPoint(20, 20);
QTest::touchEvent(window, device).press(0, p1, window);
+ QQuickTouchUtils::flush(window);
QCOMPARE(eventItem1->eventList.size(), 0);
QCOMPARE(eventItem2->eventList.size(), 1);
QCOMPARE(eventItem2->eventList.at(0).type, QEvent::TouchBegin);
p1 += QPoint(10, 0);
QTest::touchEvent(window, device).move(0, p1, window);
+ QQuickTouchUtils::flush(window);
QCOMPARE(eventItem2->eventList.size(), 2);
QCOMPARE(eventItem2->eventList.at(1).type, QEvent::TouchUpdate);
QTest::touchEvent(window, device).release(0, p1, window);
+ QQuickTouchUtils::flush(window);
QCOMPARE(eventItem2->eventList.size(), 3);
QCOMPARE(eventItem2->eventList.at(2).type, QEvent::TouchEnd);
eventItem2->eventList.clear();
@@ -456,6 +476,7 @@ void tst_TouchMouse::mouseOverTouch()
QPoint p1 = QPoint(20, 20);
QTest::qWait(qApp->styleHints()->mouseDoubleClickInterval() + 10);
QTest::touchEvent(window, device).press(0, p1, window);
+ QQuickTouchUtils::flush(window);
QCOMPARE(eventItem1->eventList.size(), 0);
QCOMPARE(eventItem2->eventList.size(), 2);
QCOMPARE(eventItem2->eventList.at(0).type, QEvent::TouchBegin);
@@ -510,10 +531,12 @@ void tst_TouchMouse::buttonOnFlickable()
QCOMPARE(eventItem1->eventList.size(), 0);
QPoint p1 = QPoint(20, 130);
QTest::touchEvent(window, device).press(0, p1, window);
+ QQuickTouchUtils::flush(window);
QTRY_COMPARE(eventItem1->eventList.size(), 2);
QCOMPARE(eventItem1->eventList.at(0).type, QEvent::TouchBegin);
QCOMPARE(eventItem1->eventList.at(1).type, QEvent::MouseButtonPress);
QTest::touchEvent(window, device).release(0, p1, window);
+ QQuickTouchUtils::flush(window);
QCOMPARE(eventItem1->eventList.size(), 4);
QCOMPARE(eventItem1->eventList.at(2).type, QEvent::TouchEnd);
QCOMPARE(eventItem1->eventList.at(3).type, QEvent::MouseButtonRelease);
@@ -522,9 +545,11 @@ void tst_TouchMouse::buttonOnFlickable()
// touch button
p1 = QPoint(10, 310);
QTest::touchEvent(window, device).press(0, p1, window);
+ QQuickTouchUtils::flush(window);
QCOMPARE(eventItem2->eventList.size(), 1);
QCOMPARE(eventItem2->eventList.at(0).type, QEvent::TouchBegin);
QTest::touchEvent(window, device).release(0, p1, window);
+ QQuickTouchUtils::flush(window);
QCOMPARE(eventItem2->eventList.size(), 2);
QCOMPARE(eventItem2->eventList.at(1).type, QEvent::TouchEnd);
QCOMPARE(eventItem1->eventList.size(), 0);
@@ -536,8 +561,10 @@ void tst_TouchMouse::buttonOnFlickable()
// click above button, no events please
p1 = QPoint(10, 90);
QTest::touchEvent(window, device).press(0, p1, window);
+ QQuickTouchUtils::flush(window);
QCOMPARE(eventItem1->eventList.size(), 0);
QTest::touchEvent(window, device).release(0, p1, window);
+ QQuickTouchUtils::flush(window);
QCOMPARE(eventItem1->eventList.size(), 0);
eventItem1->eventList.clear();
@@ -548,6 +575,7 @@ void tst_TouchMouse::buttonOnFlickable()
QCOMPARE(eventItem1->eventList.size(), 0);
p1 = QPoint(10, 110);
QTest::touchEvent(window, device).press(0, p1, window);
+ QQuickTouchUtils::flush(window);
QCOMPARE(eventItem1->eventList.size(), 2);
QCOMPARE(eventItem1->eventList.at(0).type, QEvent::TouchBegin);
QCOMPARE(eventItem1->eventList.at(1).type, QEvent::MouseButtonPress);
@@ -560,12 +588,13 @@ void tst_TouchMouse::buttonOnFlickable()
p1 += QPoint(0, -10);
QPoint p2 = p1 + QPoint(0, -10);
QPoint p3 = p2 + QPoint(0, -10);
- QTest::qWait(10);
+ QQuickTouchUtils::flush(window);
QTest::touchEvent(window, device).move(0, p1, window);
- QTest::qWait(10);
+ QQuickTouchUtils::flush(window);
QTest::touchEvent(window, device).move(0, p2, window);
- QTest::qWait(10);
+ QQuickTouchUtils::flush(window);
QTest::touchEvent(window, device).move(0, p3, window);
+ QQuickTouchUtils::flush(window);
// we cannot really know when the events get grabbed away
QVERIFY(eventItem1->eventList.size() >= 4);
@@ -578,6 +607,7 @@ void tst_TouchMouse::buttonOnFlickable()
QVERIFY(flickable->isMovingVertically());
QTest::touchEvent(window, device).release(0, p3, window);
+ QQuickTouchUtils::flush(window);
delete window;
}
@@ -625,11 +655,13 @@ void tst_TouchMouse::buttonOnDelayedPressFlickable()
QCOMPARE(eventItem1->eventList.size(), 0);
QPoint p1 = QPoint(10, 110);
QTest::touchEvent(window, device).press(0, p1, window);
+ QQuickTouchUtils::flush(window);
// Flickable initially steals events
QCOMPARE(eventItem1->eventList.size(), 0);
// but we'll get the delayed mouse press after a delay
QTRY_COMPARE(eventItem1->eventList.size(), 1);
QCOMPARE(eventItem1->eventList.at(0).type, QEvent::MouseButtonPress);
+ QCOMPARE(filteredEventList.count(), 1);
// eventItem1 should have the mouse grab, and have moved the itemForTouchPointId
// for the touchMouseId to the new grabber.
@@ -641,12 +673,13 @@ void tst_TouchMouse::buttonOnDelayedPressFlickable()
p1 += QPoint(0, -10);
QPoint p2 = p1 + QPoint(0, -10);
QPoint p3 = p2 + QPoint(0, -10);
- QTest::qWait(10);
+ QQuickTouchUtils::flush(window);
QTest::touchEvent(window, device).move(0, p1, window);
- QTest::qWait(10);
+ QQuickTouchUtils::flush(window);
QTest::touchEvent(window, device).move(0, p2, window);
- QTest::qWait(10);
+ QQuickTouchUtils::flush(window);
QTest::touchEvent(window, device).move(0, p3, window);
+ QQuickTouchUtils::flush(window);
QVERIFY(flickable->isMovingVertically());
// flickable should have the mouse grab, and have moved the itemForTouchPointId
@@ -656,9 +689,11 @@ void tst_TouchMouse::buttonOnDelayedPressFlickable()
QCOMPARE(windowPriv->itemForTouchPointId[0], flickable);
QTest::touchEvent(window, device).release(0, p3, window);
+ QQuickTouchUtils::flush(window);
- // We should not have received any synthesised mouse events from Qt gui.
- QCOMPARE(filteredEventList.count(), 0);
+ // We should not have received any synthesised mouse events from Qt gui,
+ // just the delayed press.
+ QCOMPARE(filteredEventList.count(), 1);
delete window;
}
@@ -709,7 +744,9 @@ void tst_TouchMouse::buttonOnTouch()
// Normal touch click
QPoint p1 = QPoint(10, 110);
QTest::touchEvent(window, device).press(0, p1, window);
+ QQuickTouchUtils::flush(window);
QTest::touchEvent(window, device).release(0, p1, window);
+ QQuickTouchUtils::flush(window);
QCOMPARE(eventItem1->eventList.size(), 4);
QCOMPARE(eventItem1->eventList.at(0).type, QEvent::TouchBegin);
QCOMPARE(eventItem1->eventList.at(1).type, QEvent::MouseButtonPress);
@@ -730,7 +767,9 @@ void tst_TouchMouse::buttonOnTouch()
// Start the events after each other
QTest::touchEvent(window, device).press(0, p1, window);
+ QQuickTouchUtils::flush(window);
QTest::touchEvent(window, device).stationary(0).press(1, p2, window);
+ QQuickTouchUtils::flush(window);
QCOMPARE(button1->scale(), 1.0);
@@ -738,20 +777,24 @@ void tst_TouchMouse::buttonOnTouch()
p1 -= QPoint(10, 0);
p2 += QPoint(10, 0);
QTest::touchEvent(window, device).move(0, p1, window).move(1, p2, window);
+ QQuickTouchUtils::flush(window);
p1 -= QPoint(10, 0);
p2 += QPoint(10, 0);
QTest::touchEvent(window, device).move(0, p1, window).move(1, p2, window);
+ QQuickTouchUtils::flush(window);
// QCOMPARE(button1->scale(), 1.5);
qDebug() << "Button scale: " << button1->scale();
p1 -= QPoint(10, 0);
p2 += QPoint(10, 0);
QTest::touchEvent(window, device).move(0, p1, window).move(1, p2, window);
+ QQuickTouchUtils::flush(window);
// QCOMPARE(button1->scale(), 2.0);
qDebug() << "Button scale: " << button1->scale();
QTest::touchEvent(window, device).release(0, p1, window).release(1, p2, window);
+ QQuickTouchUtils::flush(window);
// QVERIFY(eventItem1->eventList.isEmpty());
// QCOMPARE(button1->scale(), 2.0);
qDebug() << "Button scale: " << button1->scale();
@@ -765,6 +808,7 @@ void tst_TouchMouse::buttonOnTouch()
p1 = QPoint(40, 110);
p2 = QPoint(60, 110);
QTest::touchEvent(window, device).press(0, p1, window).press(1, p2, window);
+ QQuickTouchUtils::flush(window);
QCOMPARE(button1->scale(), 1.0);
QCOMPARE(eventItem1->eventList.count(), 2);
QCOMPARE(eventItem1->eventList.at(0).type, QEvent::TouchBegin);
@@ -774,20 +818,24 @@ void tst_TouchMouse::buttonOnTouch()
p1 -= QPoint(10, 0);
p2 += QPoint(10, 0);
QTest::touchEvent(window, device).move(0, p1, window).move(1, p2, window);
+ QQuickTouchUtils::flush(window);
p1 -= QPoint(10, 0);
p2 += QPoint(10, 0);
QTest::touchEvent(window, device).move(0, p1, window).move(1, p2, window);
+ QQuickTouchUtils::flush(window);
//QCOMPARE(button1->scale(), 1.5);
qDebug() << button1->scale();
p1 -= QPoint(10, 0);
p2 += QPoint(10, 0);
QTest::touchEvent(window, device).move(0, p1, window).move(1, p2, window);
+ QQuickTouchUtils::flush(window);
qDebug() << button1->scale();
//QCOMPARE(button1->scale(), 2.0);
QTest::touchEvent(window, device).release(0, p1, window).release(1, p2, window);
+ QQuickTouchUtils::flush(window);
// QCOMPARE(eventItem1->eventList.size(), 99);
qDebug() << button1->scale();
//QCOMPARE(button1->scale(), 2.0);
@@ -816,18 +864,22 @@ void tst_TouchMouse::pinchOnFlickable()
QVERIFY(flickable->contentX() == 0.0);
QPoint p = QPoint(100, 100);
QTest::touchEvent(window, device).press(0, p, window);
+ QQuickTouchUtils::flush(window);
QCOMPARE(rect->position(), QPointF(200.0, 200.0));
p -= QPoint(10, 0);
QTest::touchEvent(window, device).move(0, p, window);
+ QQuickTouchUtils::flush(window);
p -= QPoint(10, 0);
QTest::touchEvent(window, device).move(0, p, window);
- QTest::qWait(10);
+ QQuickTouchUtils::flush(window);
p -= QPoint(10, 0);
QTest::touchEvent(window, device).move(0, p, window);
- QTest::qWait(10);
+ QQuickTouchUtils::flush(window);
p -= QPoint(10, 0);
QTest::touchEvent(window, device).move(0, p, window);
+ QQuickTouchUtils::flush(window);
QTest::touchEvent(window, device).release(0, p, window);
+ QQuickTouchUtils::flush(window);
QGuiApplication::processEvents();
QTest::qWait(10);
@@ -840,27 +892,36 @@ void tst_TouchMouse::pinchOnFlickable()
QPoint p2 = QPoint(60, 20);
QTest::QTouchEventSequence pinchSequence = QTest::touchEvent(window, device);
+ QQuickTouchUtils::flush(window);
pinchSequence.press(0, p1, window).commit();
+ QQuickTouchUtils::flush(window);
// In order for the stationary point to remember its previous position,
// we have to reuse the same pinchSequence object. Otherwise if we let it
// be destroyed and then start a new sequence, point 0 will default to being
// stationary at 0, 0, and PinchArea will filter out that touchpoint because
// it is outside its bounds.
pinchSequence.stationary(0).press(1, p2, window).commit();
+ QQuickTouchUtils::flush(window);
p1 -= QPoint(10,10);
p2 += QPoint(10,10);
pinchSequence.move(0, p1, window).move(1, p2, window).commit();
+ QQuickTouchUtils::flush(window);
QCOMPARE(rect->scale(), 1.0);
p1 -= QPoint(10, 0);
p2 += QPoint(10, 0);
pinchSequence.move(0, p1, window).move(1, p2, window).commit();
+ QQuickTouchUtils::flush(window);
p1 -= QPoint(10, 0);
p2 += QPoint(10, 0);
pinchSequence.move(0, p1, window).move(1, p2, window).commit();
+ QQuickTouchUtils::flush(window);
p1 -= QPoint(10, 0);
p2 += QPoint(10, 0);
pinchSequence.move(0, p1, window).move(1, p2, window).commit();
+ QVERIFY(!flickable->isDragging());
+ QQuickTouchUtils::flush(window);
pinchSequence.release(0, p1, window).release(1, p2, window).commit();
+ QQuickTouchUtils::flush(window);
QVERIFY(rect->scale() > 1.0);
}
@@ -885,17 +946,22 @@ void tst_TouchMouse::flickableOnPinch()
QVERIFY(flickable->contentX() == 0.0);
QPoint p = QPoint(100, 100);
QTest::touchEvent(window, device).press(0, p, window);
+ QQuickTouchUtils::flush(window);
QCOMPARE(rect->position(), QPointF(200.0, 200.0));
p -= QPoint(10, 0);
QTest::touchEvent(window, device).move(0, p, window);
+ QQuickTouchUtils::flush(window);
p -= QPoint(10, 0);
QTest::touchEvent(window, device).move(0, p, window);
+ QQuickTouchUtils::flush(window);
QTest::qWait(1000);
p -= QPoint(10, 0);
QTest::touchEvent(window, device).move(0, p, window);
+ QQuickTouchUtils::flush(window);
QTest::touchEvent(window, device).release(0, p, window);
+ QQuickTouchUtils::flush(window);
QTest::qWait(1000);
@@ -909,26 +975,33 @@ void tst_TouchMouse::flickableOnPinch()
QPoint p2 = QPoint(60, 20);
QTest::QTouchEventSequence pinchSequence = QTest::touchEvent(window, device);
pinchSequence.press(0, p1, window).commit();
+ QQuickTouchUtils::flush(window);
// In order for the stationary point to remember its previous position,
// we have to reuse the same pinchSequence object. Otherwise if we let it
// be destroyed and then start a new sequence, point 0 will default to being
// stationary at 0, 0, and PinchArea will filter out that touchpoint because
// it is outside its bounds.
pinchSequence.stationary(0).press(1, p2, window).commit();
+ QQuickTouchUtils::flush(window);
p1 -= QPoint(10,10);
p2 += QPoint(10,10);
pinchSequence.move(0, p1, window).move(1, p2, window).commit();
+ QQuickTouchUtils::flush(window);
QCOMPARE(rect->scale(), 1.0);
p1 -= QPoint(10, 0);
p2 += QPoint(10, 0);
pinchSequence.move(0, p1, window).move(1, p2, window).commit();
+ QQuickTouchUtils::flush(window);
p1 -= QPoint(10, 0);
p2 += QPoint(10, 0);
pinchSequence.move(0, p1, window).move(1, p2, window).commit();
+ QQuickTouchUtils::flush(window);
p1 -= QPoint(10, 0);
p2 += QPoint(10, 0);
pinchSequence.move(0, p1, window).move(1, p2, window).commit();
+ QQuickTouchUtils::flush(window);
pinchSequence.release(0, p1, window).release(1, p2, window).commit();
+ QQuickTouchUtils::flush(window);
QVERIFY(rect->scale() > 1.0);
}
@@ -953,16 +1026,19 @@ void tst_TouchMouse::mouseOnFlickableOnPinch()
QVERIFY(flickable->contentX() == 0.0);
QPoint p = QPoint(100, 100);
QTest::touchEvent(window, device).press(0, p, window);
+ QQuickTouchUtils::flush(window);
QCOMPARE(rect->position(), QPointF(200.0, 200.0));
p -= QPoint(10, 0);
QTest::touchEvent(window, device).move(0, p, window);
+ QQuickTouchUtils::flush(window);
p -= QPoint(10, 0);
QTest::touchEvent(window, device).move(0, p, window);
- QGuiApplication::processEvents();
+ QQuickTouchUtils::flush(window);
p -= QPoint(10, 0);
QTest::touchEvent(window, device).move(0, p, window);
+ QQuickTouchUtils::flush(window);
QTest::touchEvent(window, device).release(0, p, window);
- QGuiApplication::processEvents();
+ QQuickTouchUtils::flush(window);
//QVERIFY(flickable->isMovingHorizontally());
@@ -975,26 +1051,33 @@ void tst_TouchMouse::mouseOnFlickableOnPinch()
QPoint p2 = QPoint(60, 20);
QTest::QTouchEventSequence pinchSequence = QTest::touchEvent(window, device);
pinchSequence.press(0, p1, window).commit();
+ QQuickTouchUtils::flush(window);
// In order for the stationary point to remember its previous position,
// we have to reuse the same pinchSequence object. Otherwise if we let it
// be destroyed and then start a new sequence, point 0 will default to being
// stationary at 0, 0, and PinchArea will filter out that touchpoint because
// it is outside its bounds.
pinchSequence.stationary(0).press(1, p2, window).commit();
+ QQuickTouchUtils::flush(window);
p1 -= QPoint(10,10);
p2 += QPoint(10,10);
pinchSequence.move(0, p1, window).move(1, p2, window).commit();
+ QQuickTouchUtils::flush(window);
QCOMPARE(rect->scale(), 1.0);
p1 -= QPoint(10, 0);
p2 += QPoint(10, 0);
pinchSequence.move(0, p1, window).move(1, p2, window).commit();
+ QQuickTouchUtils::flush(window);
p1 -= QPoint(10, 0);
p2 += QPoint(10, 0);
pinchSequence.move(0, p1, window).move(1, p2, window).commit();
+ QQuickTouchUtils::flush(window);
p1 -= QPoint(10, 0);
p2 += QPoint(10, 0);
pinchSequence.move(0, p1, window).move(1, p2, window).commit();
+ QQuickTouchUtils::flush(window);
pinchSequence.release(0, p1, window).release(1, p2, window).commit();
+ QQuickTouchUtils::flush(window);
QVERIFY(rect->scale() > 1.0);
// PinchArea should steal the event after flicking started
@@ -1002,14 +1085,18 @@ void tst_TouchMouse::mouseOnFlickableOnPinch()
flickable->setContentX(0.0);
p = QPoint(100, 100);
pinchSequence.press(0, p, window).commit();
+ QQuickTouchUtils::flush(window);
QCOMPARE(rect->position(), QPointF(200.0, 200.0));
p -= QPoint(10, 0);
pinchSequence.move(0, p, window).commit();
+ QQuickTouchUtils::flush(window);
p -= QPoint(10, 0);
pinchSequence.move(0, p, window).commit();
+ QQuickTouchUtils::flush(window);
QGuiApplication::processEvents();
p -= QPoint(10, 0);
pinchSequence.move(0, p, window).commit();
+ QQuickTouchUtils::flush(window);
QQuickWindowPrivate *windowPriv = QQuickWindowPrivate::get(window);
qDebug() << "Mouse Grabber: " << windowPriv->mouseGrabberItem << " itemForTouchPointId: " << windowPriv->itemForTouchPointId;
@@ -1019,20 +1106,26 @@ void tst_TouchMouse::mouseOnFlickableOnPinch()
p1 = QPoint(40, 100);
p2 = QPoint(60, 100);
pinchSequence.stationary(0).press(1, p2, window).commit();
+ QQuickTouchUtils::flush(window);
QCOMPARE(rect->scale(), 1.0);
p1 -= QPoint(5, 0);
p2 += QPoint(5, 0);
pinchSequence.move(0, p1, window).move(1, p2, window).commit();
+ QQuickTouchUtils::flush(window);
p1 -= QPoint(5, 0);
p2 += QPoint(5, 0);
pinchSequence.move(0, p1, window).move(1, p2, window).commit();
+ QQuickTouchUtils::flush(window);
p1 -= QPoint(5, 0);
p2 += QPoint(5, 0);
pinchSequence.move(0, p1, window).move(1, p2, window).commit();
+ QQuickTouchUtils::flush(window);
pinchSequence.release(0, p1, window).release(1, p2, window).commit();
+ QQuickTouchUtils::flush(window);
QVERIFY(rect->scale() > 1.0);
pinchSequence.release(0, p, window).commit();
+ QQuickTouchUtils::flush(window);
}
/*
@@ -1066,16 +1159,17 @@ void tst_TouchMouse::tapOnDismissiveTopMouseAreaClicksBottomOne()
// tap the front mouse area (see qml file)
QPoint p1(20, 20);
QTest::touchEvent(window, device).press(0, p1, window);
- QTest::qWait(1);
+ QQuickTouchUtils::flush(window);
QTest::touchEvent(window, device).release(0, p1, window);
+ QQuickTouchUtils::flush(window);
QCOMPARE(bottomClickedSpy.count(), 1);
QCOMPARE(bottomDoubleClickedSpy.count(), 0);
- QTest::qWait(15);
QTest::touchEvent(window, device).press(0, p1, window);
- QTest::qWait(1);
+ QQuickTouchUtils::flush(window);
QTest::touchEvent(window, device).release(0, p1, window);
+ QQuickTouchUtils::flush(window);
QCOMPARE(bottomClickedSpy.count(), 1);
QCOMPARE(bottomDoubleClickedSpy.count(), 1);
diff --git a/tests/auto/quickwidgets/qquickwidget/data/animating.qml b/tests/auto/quickwidgets/qquickwidget/data/animating.qml
new file mode 100644
index 0000000000..1f6467aabe
--- /dev/null
+++ b/tests/auto/quickwidgets/qquickwidget/data/animating.qml
@@ -0,0 +1,11 @@
+import QtQuick 2.0
+
+Rectangle {
+ Rectangle {
+ width: 100
+ height: 100
+ anchors.centerIn: parent
+ color: "red"
+ NumberAnimation on rotation { from: 0; to: 360; duration: 2000; loops: Animation.Infinite; }
+ }
+}
diff --git a/tests/auto/quickwidgets/qquickwidget/data/error1.qml b/tests/auto/quickwidgets/qquickwidget/data/error1.qml
new file mode 100644
index 0000000000..09df679555
--- /dev/null
+++ b/tests/auto/quickwidgets/qquickwidget/data/error1.qml
@@ -0,0 +1,5 @@
+import QtQuick 2.0
+
+Rectangle {
+ nonExistentProperty: 5
+}
diff --git a/tests/auto/quickwidgets/qquickwidget/data/rectangle.qml b/tests/auto/quickwidgets/qquickwidget/data/rectangle.qml
new file mode 100644
index 0000000000..3b18ba35c1
--- /dev/null
+++ b/tests/auto/quickwidgets/qquickwidget/data/rectangle.qml
@@ -0,0 +1,8 @@
+import QtQuick 2.0
+Rectangle {
+ width: 200
+ height: 200
+
+ color: "red"
+}
+
diff --git a/tests/auto/quickwidgets/qquickwidget/data/resizemodeitem.qml b/tests/auto/quickwidgets/qquickwidget/data/resizemodeitem.qml
new file mode 100644
index 0000000000..225c5711a9
--- /dev/null
+++ b/tests/auto/quickwidgets/qquickwidget/data/resizemodeitem.qml
@@ -0,0 +1,7 @@
+import QtQuick 2.0
+Item {
+ width: 200
+ height: 200
+
+}
+
diff --git a/tests/auto/quickwidgets/qquickwidget/qquickwidget.pro b/tests/auto/quickwidgets/qquickwidget/qquickwidget.pro
new file mode 100644
index 0000000000..069270da3c
--- /dev/null
+++ b/tests/auto/quickwidgets/qquickwidget/qquickwidget.pro
@@ -0,0 +1,19 @@
+CONFIG += testcase
+TARGET = tst_qquickwidget
+SOURCES += tst_qquickwidget.cpp
+
+include (../../shared/util.pri)
+
+osx:CONFIG -= app_bundle
+
+QT += core-private gui-private qml-private quick-private quickwidgets quickwidgets-private widgets-private testlib
+
+TESTDATA = data/*
+
+OTHER_FILES += \
+ animating.qml \
+ error1.qml \
+ rectangle.qml \
+ resizemodeitem.qml
+
+DEFINES += QT_DISABLE_DEPRECATED_BEFORE=0
diff --git a/tests/auto/quickwidgets/qquickwidget/tst_qquickwidget.cpp b/tests/auto/quickwidgets/qquickwidget/tst_qquickwidget.cpp
new file mode 100644
index 0000000000..db2d0e14e4
--- /dev/null
+++ b/tests/auto/quickwidgets/qquickwidget/tst_qquickwidget.cpp
@@ -0,0 +1,276 @@
+/****************************************************************************
+**
+** 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$
+**
+****************************************************************************/
+
+#include <qtest.h>
+#include <QtTest/QSignalSpy>
+#include <QtQml/qqmlcomponent.h>
+#include <QtQml/qqmlcontext.h>
+#include <QtQuick/qquickview.h>
+#include <QtQuick/qquickitem.h>
+#include "../../shared/util.h"
+#include <QtGui/QWindow>
+#include <QtCore/QDebug>
+#include <QtQml/qqmlengine.h>
+
+#include <QtQuickWidgets/QQuickWidget>
+
+class tst_qquickwidget : public QQmlDataTest
+{
+ Q_OBJECT
+public:
+ tst_qquickwidget();
+
+private slots:
+ void showHide();
+ void reparentAfterShow();
+ void changeGeometry();
+ void resizemodeitem();
+ void errors();
+ void engine();
+ void readback();
+};
+
+
+tst_qquickwidget::tst_qquickwidget()
+{
+}
+
+void tst_qquickwidget::showHide()
+{
+ QWidget window;
+
+ QQuickWidget *childView = new QQuickWidget(&window);
+ childView->setSource(testFileUrl("rectangle.qml"));
+
+ window.show();
+ QVERIFY(QTest::qWaitForWindowExposed(&window, 5000));
+
+ childView->hide();
+}
+
+void tst_qquickwidget::reparentAfterShow()
+{
+ QWidget window;
+
+ QQuickWidget *childView = new QQuickWidget(&window);
+ childView->setSource(testFileUrl("rectangle.qml"));
+ window.show();
+ QVERIFY(QTest::qWaitForWindowExposed(&window, 5000));
+
+ QScopedPointer<QQuickWidget> toplevelView(new QQuickWidget);
+ toplevelView->setParent(&window);
+ toplevelView->setSource(testFileUrl("rectangle.qml"));
+ toplevelView->show();
+ QVERIFY(QTest::qWaitForWindowExposed(&window, 5000));
+}
+
+void tst_qquickwidget::changeGeometry()
+{
+ QWidget window;
+
+ QQuickWidget *childView = new QQuickWidget(&window);
+ childView->setSource(testFileUrl("rectangle.qml"));
+
+ window.show();
+ QVERIFY(QTest::qWaitForWindowExposed(&window, 5000));
+
+ childView->setGeometry(100,100,100,100);
+}
+
+void tst_qquickwidget::resizemodeitem()
+{
+ QWidget window;
+ window.setGeometry(0, 0, 400, 400);
+
+ QScopedPointer<QQuickWidget> view(new QQuickWidget);
+ view->setParent(&window);
+ view->setResizeMode(QQuickWidget::SizeRootObjectToView);
+ QCOMPARE(QSize(0,0), view->initialSize());
+ view->setSource(testFileUrl("resizemodeitem.qml"));
+ QQuickItem* item = qobject_cast<QQuickItem*>(view->rootObject());
+ QVERIFY(item);
+ window.show();
+
+ view->showNormal();
+ // initial size from root object
+ QCOMPARE(item->width(), 200.0);
+ QCOMPARE(item->height(), 200.0);
+ QCOMPARE(view->size(), QSize(200, 200));
+ QCOMPARE(view->size(), view->sizeHint());
+ QCOMPARE(view->size(), view->initialSize());
+
+ // size update from view
+ view->resize(QSize(80,100));
+
+ QTRY_COMPARE(item->width(), 80.0);
+ QCOMPARE(item->height(), 100.0);
+ QCOMPARE(view->size(), QSize(80, 100));
+ QCOMPARE(view->size(), view->sizeHint());
+
+ view->setResizeMode(QQuickWidget::SizeViewToRootObject);
+
+ // size update from view disabled
+ view->resize(QSize(60,80));
+ QCOMPARE(item->width(), 80.0);
+ QCOMPARE(item->height(), 100.0);
+ QTRY_COMPARE(view->size(), QSize(60, 80));
+
+ // size update from root object
+ item->setWidth(250);
+ item->setHeight(350);
+ QCOMPARE(item->width(), 250.0);
+ QCOMPARE(item->height(), 350.0);
+ QTRY_COMPARE(view->size(), QSize(250, 350));
+ QCOMPARE(view->size(), QSize(250, 350));
+ QCOMPARE(view->size(), view->sizeHint());
+
+ // reset window
+ window.hide();
+ view.reset(new QQuickWidget(&window));
+ view->setResizeMode(QQuickWidget::SizeViewToRootObject);
+ view->setSource(testFileUrl("resizemodeitem.qml"));
+ item = qobject_cast<QQuickItem*>(view->rootObject());
+ QVERIFY(item);
+ window.show();
+
+ view->showNormal();
+
+ // initial size for root object
+ QCOMPARE(item->width(), 200.0);
+ QCOMPARE(item->height(), 200.0);
+ QCOMPARE(view->size(), view->sizeHint());
+ QCOMPARE(view->size(), view->initialSize());
+
+ // size update from root object
+ item->setWidth(80);
+ item->setHeight(100);
+ QCOMPARE(item->width(), 80.0);
+ QCOMPARE(item->height(), 100.0);
+ QTRY_COMPARE(view->size(), QSize(80, 100));
+ QCOMPARE(view->size(), view->sizeHint());
+
+ // size update from root object disabled
+ view->setResizeMode(QQuickWidget::SizeRootObjectToView);
+ item->setWidth(60);
+ item->setHeight(80);
+ QCOMPARE(view->width(), 80);
+ QCOMPARE(view->height(), 100);
+ QCOMPARE(QSize(item->width(), item->height()), view->sizeHint());
+
+ // size update from view
+ view->resize(QSize(200,300));
+ QTRY_COMPARE(item->width(), 200.0);
+ QCOMPARE(item->height(), 300.0);
+ QCOMPARE(view->size(), QSize(200, 300));
+ QCOMPARE(view->size(), view->sizeHint());
+
+ window.hide();
+
+ // if we set a specific size for the view then it should keep that size
+ // for SizeRootObjectToView mode.
+ view.reset(new QQuickWidget(&window));
+ view->resize(300, 300);
+ view->setResizeMode(QQuickWidget::SizeRootObjectToView);
+ QCOMPARE(QSize(0,0), view->initialSize());
+ view->setSource(testFileUrl("resizemodeitem.qml"));
+ view->resize(300, 300);
+ item = qobject_cast<QQuickItem*>(view->rootObject());
+ QVERIFY(item);
+ window.show();
+
+ view->showNormal();
+
+ // initial size from root object
+ QCOMPARE(item->width(), 300.0);
+ QCOMPARE(item->height(), 300.0);
+ QTRY_COMPARE(view->size(), QSize(300, 300));
+ QCOMPARE(view->size(), view->sizeHint());
+ QCOMPARE(view->initialSize(), QSize(200, 200)); // initial object size
+}
+
+void tst_qquickwidget::errors()
+{
+ QQuickWidget *view = new QQuickWidget;
+ QScopedPointer<QQuickWidget> cleanupView(view);
+
+ QQmlTestMessageHandler messageHandler;
+ view->setSource(testFileUrl("error1.qml"));
+ QVERIFY(view->status() == QQuickWidget::Error);
+ QVERIFY(view->errors().count() == 1);
+}
+
+void tst_qquickwidget::engine()
+{
+ QScopedPointer<QQmlEngine> engine(new QQmlEngine);
+ QScopedPointer<QQuickWidget> view(new QQuickWidget(engine.data(), 0));
+ QScopedPointer<QQuickWidget> view2(new QQuickWidget(view->engine(), 0));
+
+ QVERIFY(view->engine());
+ QVERIFY(view2->engine());
+ QCOMPARE(view->engine(), view2->engine());
+}
+
+void tst_qquickwidget::readback()
+{
+#ifdef Q_OS_MAC
+ QSKIP("Skipping due to issues on OS X: QTBUG-39919");
+#endif
+
+ QWidget window;
+
+ QScopedPointer<QQuickWidget> view(new QQuickWidget);
+ view->setSource(testFileUrl("rectangle.qml"));
+
+ view->show();
+ QVERIFY(QTest::qWaitForWindowExposed(view.data(), 5000));
+
+ QImage img = view->grabFramebuffer();
+ QVERIFY(!img.isNull());
+ QCOMPARE(img.width(), view->width());
+ QCOMPARE(img.height(), view->height());
+
+ QRgb pix = img.pixel(5, 5);
+ QCOMPARE(pix, qRgb(255, 0, 0));
+}
+
+QTEST_MAIN(tst_qquickwidget)
+
+#include "tst_qquickwidget.moc"
diff --git a/tests/auto/quickwidgets/quickwidgets.pro b/tests/auto/quickwidgets/quickwidgets.pro
new file mode 100644
index 0000000000..ee8d6077e6
--- /dev/null
+++ b/tests/auto/quickwidgets/quickwidgets.pro
@@ -0,0 +1,2 @@
+TEMPLATE = subdirs
+SUBDIRS += qquickwidget
diff --git a/tests/auto/shared/testhttpserver.cpp b/tests/auto/shared/testhttpserver.cpp
index d3de584084..231f22b35b 100644
--- a/tests/auto/shared/testhttpserver.cpp
+++ b/tests/auto/shared/testhttpserver.cpp
@@ -71,7 +71,8 @@ slowFiles/slowMain.qml
\endcode
it can be added like this:
\code
-TestHTTPServer server(14445);
+TestHTTPServer server;
+QVERIFY2(server.listen(14445), qPrintable(server.errorString()));
server.serveDirectory("disconnect", TestHTTPServer::Disconnect);
server.serveDirectory("files");
server.serveDirectory("slowFiles", TestHTTPServer::Delay);
@@ -87,17 +88,21 @@ The following request urls will then result in the appropriate action:
\row \li http://localhost:14445/slowMain.qml \li slowMain.qml returned after 500ms
\endtable
*/
-TestHTTPServer::TestHTTPServer(quint16 port)
+TestHTTPServer::TestHTTPServer()
: m_state(AwaitingHeader)
{
QObject::connect(&server, SIGNAL(newConnection()), this, SLOT(newConnection()));
- server.listen(QHostAddress::LocalHost, port);
}
-bool TestHTTPServer::isValid() const
+bool TestHTTPServer::listen(quint16 port)
{
- return server.isListening();
+ return server.listen(QHostAddress::LocalHost, port);
+}
+
+QString TestHTTPServer::errorString() const
+{
+ return server.errorString();
}
bool TestHTTPServer::serveDirectory(const QString &dir, Mode mode)
diff --git a/tests/auto/shared/testhttpserver.h b/tests/auto/shared/testhttpserver.h
index ae7d137143..a71386ddec 100644
--- a/tests/auto/shared/testhttpserver.h
+++ b/tests/auto/shared/testhttpserver.h
@@ -51,9 +51,10 @@ class TestHTTPServer : public QObject
{
Q_OBJECT
public:
- TestHTTPServer(quint16 port);
+ TestHTTPServer();
- bool isValid() const;
+ bool listen(quint16 port);
+ QString errorString() const;
enum Mode { Normal, Delay, Disconnect };
bool serveDirectory(const QString &, Mode = Normal);
diff --git a/tests/manual/httpserver/main.cpp b/tests/manual/httpserver/main.cpp
index ea729547ce..4ad44508b0 100644
--- a/tests/manual/httpserver/main.cpp
+++ b/tests/manual/httpserver/main.cpp
@@ -112,7 +112,11 @@ int main(int argc, char *argv[])
<< "\":\n\n" << QDir(directory).entryList(QDir::Files).join(QLatin1Char('\n'))
<< "\n\non http://localhost:" << port << '\n';
- TestHTTPServer server(port);
+ TestHTTPServer server;
+ if (!server.listen(port)) {
+ std::wcout << "Couldn't listen on port " << port << server.errorString().toLocal8Bit();
+ exit(-1);
+ }
server.serveDirectory(directory);
return a.exec();
diff --git a/tests/manual/v4/Sha1.js b/tests/manual/v4/Sha1.js
new file mode 100644
index 0000000000..406849ca58
--- /dev/null
+++ b/tests/manual/v4/Sha1.js
@@ -0,0 +1,146 @@
+/*
+ * A JavaScript implementation of the Secure Hash Algorithm, SHA-1, as defined
+ * in FIPS PUB 180-1
+ * Version 2.1a Copyright Paul Johnston 2000 - 2002.
+ * Other contributors: Greg Holt, Andrew Kepert, Ydnar, Lostinet
+ * Distributed under the BSD License
+ * See http://pajhome.org.uk/crypt/md5 for details.
+ */
+
+/*
+ * Configurable variables. You may need to tweak these to be compatible with
+ * the server-side, but the defaults work in most cases.
+ */
+var hexcase = 0; /* hex output format. 0 - lowercase; 1 - uppercase */
+var chrsz = 8; /* bits per input character. 8 - ASCII; 16 - Unicode */
+
+/*
+ * These are the functions you'll usually want to call
+ * They take string arguments and return either hex or base-64 encoded strings
+ */
+function hex_sha1(s){return binb2hex(core_sha1(str2binb(s),s.length * chrsz));}
+
+/*
+ * Perform a simple self-test to see if the VM is working
+ */
+function sha1_vm_test()
+{
+ return hex_sha1("abc") == "a9993e364706816aba3e25717850c26c9cd0d89d";
+}
+
+/*
+ * Calculate the SHA-1 of an array of big-endian words, and a bit length
+ */
+function core_sha1(x, len)
+{
+ /* append padding */
+ x[len >> 5] |= 0x80 << (24 - len % 32);
+ x[((len + 64 >> 9) << 4) + 15] = len;
+
+ var w = Array(80);
+ var a = 1732584193;
+ var b = -271733879;
+ var c = -1732584194;
+ var d = 271733878;
+ var e = -1009589776;
+
+ for(var i = 0; i < x.length; i += 16)
+ {
+ var olda = a;
+ var oldb = b;
+ var oldc = c;
+ var oldd = d;
+ var olde = e;
+
+ for(var j = 0; j < 80; j++)
+ {
+ if(j < 16) w[j] = x[i + j];
+ else w[j] = rol(w[j-3] ^ w[j-8] ^ w[j-14] ^ w[j-16], 1);
+ var t = safe_add(safe_add(rol(a, 5), sha1_ft(j, b, c, d)),
+ safe_add(safe_add(e, w[j]), sha1_kt(j)));
+ e = d;
+ d = c;
+ c = rol(b, 30);
+ b = a;
+ a = t;
+ }
+
+ a = safe_add(a, olda);
+ b = safe_add(b, oldb);
+ c = safe_add(c, oldc);
+ d = safe_add(d, oldd);
+ e = safe_add(e, olde);
+ }
+ return Array(a, b, c, d, e);
+
+}
+
+/*
+ * Perform the appropriate triplet combination function for the current
+ * iteration
+ */
+function sha1_ft(t, b, c, d)
+{
+ if(t < 20) return (b & c) | ((~b) & d);
+ if(t < 40) return b ^ c ^ d;
+ if(t < 60) return (b & c) | (b & d) | (c & d);
+ return b ^ c ^ d;
+}
+
+/*
+ * Determine the appropriate additive constant for the current iteration
+ */
+function sha1_kt(t)
+{
+ return (t < 20) ? 1518500249 : (t < 40) ? 1859775393 :
+ (t < 60) ? -1894007588 : -899497514;
+}
+
+/*
+ * Add integers, wrapping at 2^32. This uses 16-bit operations internally
+ * to work around bugs in some JS interpreters.
+ */
+function safe_add(x, y)
+{
+ var lsw = (x & 0xFFFF) + (y & 0xFFFF);
+ var msw = (x >> 16) + (y >> 16) + (lsw >> 16);
+ return (msw << 16) | (lsw & 0xFFFF);
+}
+
+/*
+ * Bitwise rotate a 32-bit number to the left.
+ */
+function rol(num, cnt)
+{
+ return (num << cnt) | (num >>> (32 - cnt));
+}
+
+/*
+ * Convert an 8-bit or 16-bit string to an array of big-endian words
+ * In 8-bit function, characters >255 have their hi-byte silently ignored.
+ */
+function str2binb(str)
+{
+ var bin = Array();
+ var mask = (1 << chrsz) - 1;
+ for(var i = 0; i < str.length * chrsz; i += chrsz)
+ bin[i>>5] |= (str.charCodeAt(i / chrsz) & mask) << (32 - chrsz - i%32);
+ return bin;
+}
+
+/*
+ * Convert an array of big-endian words to a hex string.
+ */
+function binb2hex(binarray)
+{
+ var hex_tab = hexcase ? "0123456789ABCDEF" : "0123456789abcdef";
+ var str = "";
+ for(var i = 0; i < binarray.length * 4; i++)
+ {
+ str += hex_tab.charAt((binarray[i>>2] >> ((3 - i%4)*8+4)) & 0xF) +
+ hex_tab.charAt((binarray[i>>2] >> ((3 - i%4)*8 )) & 0xF);
+ }
+ return str;
+}
+
+print ("Self check:", sha1_vm_test())
diff --git a/tests/testapplications/listview/sticky.qml b/tests/testapplications/listview/sticky.qml
new file mode 100644
index 0000000000..6dcdf6b57e
--- /dev/null
+++ b/tests/testapplications/listview/sticky.qml
@@ -0,0 +1,250 @@
+/****************************************************************************
+**
+** 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.4
+import QtQuick.Window 2.1
+import QtQuick.Layouts 1.1
+import QtQuick.Controls 1.1
+import QtQuick.Controls.Styles 1.1
+import Qt.labs.settings 1.0
+
+ApplicationWindow {
+ id: window
+
+ width: 640
+ height: 480
+ visible: true
+
+ property int hspacing: 10
+ property int vspacing: 35
+
+ Settings {
+ property alias windowX: window.x
+ property alias windowY: window.y
+ property alias windowWidth: window.width
+ property alias windowHeight: window.height
+ property alias orientation: oriItem.currentIndex
+ property alias layoutDirection: ldItem.currentIndex
+ property alias verticalLayoutDirection: vldItem.currentIndex
+ property alias hasHeader: hItem.checked
+ property alias headerPositioning: shItem.currentIndex
+ property alias hasFooter: fItem.checked
+ property alias footerPositioning: sfItem.currentIndex
+ property alias clipEnabled: clipItem.checked
+ property alias filterEnabled: filterItem.checked
+ property alias opacityEnabled: opacityItem.checked
+ property alias inlineSections: isItem.checked
+ property alias stickyCurrentSection: scsItem.checked
+ property alias stickyNextSection: snsItem.checked
+ }
+
+ toolBar: GridLayout {
+ rows: 3
+ flow: GridLayout.TopToBottom
+
+ anchors.margins: hspacing
+ anchors.left: parent.left
+ anchors.right: parent.right
+
+ ComboBox { id: oriItem; currentIndex: 1; model: ["Horizontal", "Vertical"] }
+ ComboBox { id: ldItem; model: ["LeftToRight", "RightToLeft"] }
+ ComboBox { id: vldItem; model: ["TopToBottom", "BottomToTop"] }
+
+ CheckBox { id: clipItem; text: "Clip"; checked: true }
+ CheckBox { id: opacityItem; text: "Opaque"; checked: true }
+ CheckBox { id: filterItem; text: "Filter" }
+
+ CheckBox { id: hItem; text: "Header:" }
+ CheckBox { id: fItem; text: "Footer:" }
+ Item { width: 1; height: 1 }
+
+ ComboBox { id: shItem; model: shModel; textRole: "name"; enabled: hItem.checked }
+ ComboBox { id: sfItem; model: sfModel; textRole: "name"; enabled: fItem.checked }
+ Item { width: 1; height: 1 }
+
+ CheckBox { id: scsItem; text: "Sticky current section" }
+ CheckBox { id: snsItem; text: "Sticky next section" }
+ CheckBox { id: isItem; text: "Inline sections" }
+
+ Button { text: "Beginning"; onClicked: listview.positionViewAtBeginning() }
+ Button { text: "Middle"; onClicked: listview.positionViewAtIndex(50, ListView.Center) }
+ Button { text: "End"; onClicked: listview.positionViewAtEnd() }
+ }
+
+ ListModel {
+ id: shModel
+ ListElement { name: "Inline"; value: ListView.InlineHeader }
+ ListElement { name: "Overlay"; value: ListView.OverlayHeader }
+ ListElement { name: "PullBack"; value: ListView.PullBackHeader }
+ }
+
+ ListModel {
+ id: sfModel
+ ListElement { name: "Inline"; value: ListView.InlineFooter }
+ ListElement { name: "Overlay"; value: ListView.OverlayFooter }
+ ListElement { name: "PullBack"; value: ListView.PullBackFooter }
+ }
+
+ statusBar: RowLayout {
+ anchors.margins: window.hspacing
+ anchors.left: parent.left
+ anchors.right: parent.right
+ Text {
+ anchors.left: parent.left
+ text: listview.currentSection ? "#" + listview.currentSection : ""
+ visible: scsItem.checked || snsItem.checked || isItem.checked
+ }
+ Text {
+ anchors.right: parent.right
+ property string pos: listview.isVertical ? listview.contentY.toFixed(2) : listview.contentX.toFixed(2)
+ property string size: listview.isVertical ? listview.contentHeight.toFixed(2) : listview.contentWidth.toFixed(2)
+ function padded(str) {
+ return String(" " + str).slice(-8)
+ }
+ text: padded(pos) + " /" + padded(size)
+ }
+ }
+
+ ListView {
+ id: listview
+
+ property bool isVertical: orientation == ListView.Vertical
+
+ anchors.fill: parent
+ anchors.leftMargin: window.hspacing
+ anchors.rightMargin: window.hspacing
+ anchors.topMargin: window.vspacing
+ anchors.bottomMargin: window.vspacing
+
+ clip: clipItem.checked
+
+ orientation: oriItem.currentIndex === 0 ? ListView.Horizontal : ListView.Vertical
+ layoutDirection: ldItem.currentIndex === 0 ? ListView.LeftToRight : ListView.RightToLeft
+ verticalLayoutDirection: vldItem.currentIndex === 0 ? ListView.TopToBottom : ListView.BottomToTop
+
+ model: ListModel {
+ Component.onCompleted: {
+ for (var i = 0; i < 100; ++i)
+ append({section: Math.floor(i / 10)})
+ }
+ }
+
+ delegate: Rectangle {
+ clip: true
+ property bool filterOut: filterItem.checked && index % 5
+ visible: !filterOut
+ width: filterOut ? 0 : parent && listview.isVertical ? parent.width : label.implicitHeight
+ height: filterOut ? 0 : !parent || listview.isVertical ? label.implicitHeight : parent.height
+ color: index % 2 ? "#ffffff" : "#f3f3f3"
+ Text {
+ id: label
+ anchors.centerIn: parent
+ rotation: listview.isVertical ? 0 : -90
+ text: index
+ }
+ }
+
+ section.property: "section"
+ section.delegate: Rectangle {
+ width: parent && listview.orientation == ListView.Vertical ? parent.width : sectionLabel.implicitHeight
+ height: !parent || listview.orientation == ListView.Vertical ? sectionLabel.implicitHeight : parent.height
+ color: "darkgray"
+ opacity: opacityItem.checked ? 1.0 : 0.8
+ Text {
+ id: sectionLabel
+ anchors.centerIn: parent
+ rotation: listview.isVertical ? 0 : -90
+ text: "#" + section
+ }
+ }
+ section.labelPositioning: (isItem.checked ? ViewSection.InlineLabels : 0) |
+ (scsItem.checked ? ViewSection.CurrentLabelAtStart : 0) |
+ (snsItem.checked ? ViewSection.NextLabelAtEnd : 0)
+
+ headerPositioning: shModel.get(shItem.currentIndex).value
+ header: hItem.checked ? headerComponent : null
+
+ footerPositioning: sfModel.get(sfItem.currentIndex).value
+ footer: fItem.checked ? footerComponent : null
+
+ Rectangle {
+ border.width: 1
+ anchors.fill: parent
+ color: "transparent"
+ border.color: "darkgray"
+ }
+
+ Component {
+ id: headerComponent
+ Rectangle {
+ z: 3
+ width: parent && listview.orientation == ListView.Vertical ? parent.width : headerLabel.implicitHeight * 2
+ height: !parent || listview.orientation == ListView.Vertical ? headerLabel.implicitHeight * 2 : parent.height
+ color: "steelblue"
+ opacity: opacityItem.checked ? 1.0 : 0.8
+ Text {
+ id: headerLabel
+ text: "Header"
+ font.pointSize: 12
+ anchors.centerIn: parent
+ rotation: listview.isVertical ? 0 : -90
+ }
+ }
+ }
+
+ Component {
+ id: footerComponent
+ Rectangle {
+ z: 3
+ width: parent && listview.orientation == ListView.Vertical ? parent.width : footerLabel.implicitHeight * 2
+ height: !parent || listview.orientation == ListView.Vertical ? footerLabel.implicitHeight * 2 : parent.height
+ color: "steelblue"
+ opacity: opacityItem.checked ? 1.0 : 0.8
+ Text {
+ id: footerLabel
+ text: "Footer"
+ font.pointSize: 10
+ anchors.centerIn: parent
+ rotation: listview.isVertical ? 0 : -90
+ }
+ }
+ }
+ }
+}