diff options
Diffstat (limited to 'tests')
114 files changed, 2830 insertions, 241 deletions
diff --git a/tests/auto/qml/debugger/qdebugmessageservice/tst_qdebugmessageservice.cpp b/tests/auto/qml/debugger/qdebugmessageservice/tst_qdebugmessageservice.cpp index 363efeabbc..e6cbd41b8e 100644 --- a/tests/auto/qml/debugger/qdebugmessageservice/tst_qdebugmessageservice.cpp +++ b/tests/auto/qml/debugger/qdebugmessageservice/tst_qdebugmessageservice.cpp @@ -48,7 +48,7 @@ #include <QtCore/QString> #include <QtTest/QtTest> -const char *NORMALMODE = "-qmljsdebugger=port:3777,block"; +const char *NORMALMODE = "-qmljsdebugger=port:3777,3787,block"; const char *QMLFILE = "test.qml"; class QQmlDebugMsgClient; @@ -186,7 +186,8 @@ void tst_QDebugMessageService::init() QVERIFY2(m_process->waitForSessionStart(), "Could not launch application, or did not get 'Waiting for connection'."); - m_connection->connectToHost("127.0.0.1", 3777); + const int port = m_process->debugPort(); + m_connection->connectToHost("127.0.0.1", port); QVERIFY(m_connection->waitForConnected()); if (m_client->state() != QQmlDebugClient::Enabled) diff --git a/tests/auto/qml/debugger/qqmldebugjs/qqmldebugjs.pro b/tests/auto/qml/debugger/qqmldebugjs/qqmldebugjs.pro index eb5f17a55d..d4ce36dc4a 100644 --- a/tests/auto/qml/debugger/qqmldebugjs/qqmldebugjs.pro +++ b/tests/auto/qml/debugger/qqmldebugjs/qqmldebugjs.pro @@ -22,3 +22,5 @@ OTHER_FILES += data/test.qml data/test.js \ data/breakpointRelocation.qml \ data/createComponent.qml DEFINES += QT_DISABLE_DEPRECATED_BEFORE=0 + +mac:CONFIG+=insignificant_test # QTBUG-28263 diff --git a/tests/auto/qml/debugger/qqmldebugjs/tst_qqmldebugjs.cpp b/tests/auto/qml/debugger/qqmldebugjs/tst_qqmldebugjs.cpp index 9c2ba5bcde..424a3b36ac 100644 --- a/tests/auto/qml/debugger/qqmldebugjs/tst_qqmldebugjs.cpp +++ b/tests/auto/qml/debugger/qqmldebugjs/tst_qqmldebugjs.cpp @@ -53,6 +53,11 @@ #include "qqmldebugclient.h" #include "../../../shared/util.h" +#if defined (Q_OS_WINCE) +#undef IN +#undef OUT +#endif + const char *V8REQUEST = "v8request"; const char *V8MESSAGE = "v8message"; const char *SEQ = "seq"; diff --git a/tests/auto/qml/debugger/qqmldebugservice/tst_qqmldebugservice.cpp b/tests/auto/qml/debugger/qqmldebugservice/tst_qqmldebugservice.cpp index dd4dd003ec..1c1d84f37b 100644 --- a/tests/auto/qml/debugger/qqmldebugservice/tst_qqmldebugservice.cpp +++ b/tests/auto/qml/debugger/qqmldebugservice/tst_qqmldebugservice.cpp @@ -104,7 +104,7 @@ void tst_QQmlDebugService::checkPortRange() QQmlDebugConnection *connection1 = new QQmlDebugConnection(); QQmlDebugProcess *process1 = new QQmlDebugProcess(QLibraryInfo::location(QLibraryInfo::BinariesPath) + "/qmlscene", this); - process1->start(QStringList() << QLatin1String("-qmljsdebugger=port:3772, 3774 ") << testFile("test.qml")); + process1->start(QStringList() << QLatin1String("-qmljsdebugger=port:3782,3792") << testFile("test.qml")); if (!process1->waitForSessionStart()) QFAIL("could not launch application, or did not get 'Waiting for connection'."); @@ -118,7 +118,7 @@ void tst_QQmlDebugService::checkPortRange() QQmlDebugConnection *connection2 = new QQmlDebugConnection(); QQmlDebugProcess *process2 = new QQmlDebugProcess(QLibraryInfo::location(QLibraryInfo::BinariesPath) + "/qmlscene", this); - process2->start(QStringList() << QLatin1String("-qmljsdebugger=port:3772,3774") << testFile("test.qml")); + process2->start(QStringList() << QLatin1String("-qmljsdebugger=port:3782,3792") << testFile("test.qml")); if (!process2->waitForSessionStart()) QFAIL("could not launch application, or did not get 'Waiting for connection'."); diff --git a/tests/auto/qml/debugger/qqmlenginedebuginspectorintegrationtest/tst_qqmlenginedebuginspectorintegration.cpp b/tests/auto/qml/debugger/qqmlenginedebuginspectorintegrationtest/tst_qqmlenginedebuginspectorintegration.cpp index 6f99afd917..5badcaa3ae 100644 --- a/tests/auto/qml/debugger/qqmlenginedebuginspectorintegrationtest/tst_qqmlenginedebuginspectorintegration.cpp +++ b/tests/auto/qml/debugger/qqmlenginedebuginspectorintegrationtest/tst_qqmlenginedebuginspectorintegration.cpp @@ -52,8 +52,8 @@ #include "qqmlinspectorclient.h" #include "qqmlenginedebugclient.h" -#define PORT 3776 -#define STR_PORT "3776" +#define STR_PORT_FROM "3776" +#define STR_PORT_TO "3786" class tst_QQmlEngineDebugInspectorIntegration : public QQmlDataTest { @@ -105,7 +105,7 @@ QmlDebugObjectReference tst_QQmlEngineDebugInspectorIntegration::findRootObject( void tst_QQmlEngineDebugInspectorIntegration::init() { - const QString argument = "-qmljsdebugger=port:" STR_PORT ",block"; + const QString argument = "-qmljsdebugger=port:" STR_PORT_FROM "," STR_PORT_TO ",block"; m_process = new QQmlDebugProcess(QLibraryInfo::location(QLibraryInfo::BinariesPath) + "/qmlscene", this); @@ -117,7 +117,8 @@ void tst_QQmlEngineDebugInspectorIntegration::init() m_inspectorClient = new QQmlInspectorClient(m_connection); m_engineDebugClient = new QQmlEngineDebugClient(m_connection); - m_connection->connectToHost(QLatin1String("127.0.0.1"), PORT); + const int port = m_process->debugPort(); + m_connection->connectToHost(QLatin1String("127.0.0.1"), port); bool ok = m_connection->waitForConnected(); QVERIFY(ok); } diff --git a/tests/auto/qml/debugger/qqmlinspector/tst_qqmlinspector.cpp b/tests/auto/qml/debugger/qqmlinspector/tst_qqmlinspector.cpp index f1fbdd20a9..e430875355 100644 --- a/tests/auto/qml/debugger/qqmlinspector/tst_qqmlinspector.cpp +++ b/tests/auto/qml/debugger/qqmlinspector/tst_qqmlinspector.cpp @@ -50,8 +50,8 @@ #include "../../../shared/util.h" #include "qqmlinspectorclient.h" -#define PORT 3772 -#define STR_PORT "3772" +#define STR_PORT_FROM "3772" +#define STR_PORT_TO "3782" @@ -87,7 +87,7 @@ private slots: void tst_QQmlInspector::startQmlsceneProcess(const char * /* qmlFile */) { - const QString argument = "-qmljsdebugger=port:" STR_PORT ",block"; + const QString argument = "-qmljsdebugger=port:" STR_PORT_FROM "," STR_PORT_TO ",block"; m_process = new QQmlDebugProcess(QLibraryInfo::location(QLibraryInfo::BinariesPath) + "/qmlscene", this); m_process->start(QStringList() << argument << testFile("qtquick2.qml")); @@ -97,7 +97,8 @@ void tst_QQmlInspector::startQmlsceneProcess(const char * /* qmlFile */) QQmlDebugConnection *m_connection = new QQmlDebugConnection(); m_client = new QQmlInspectorClient(m_connection); - m_connection->connectToHost(QLatin1String("127.0.0.1"), PORT); + const int port = m_process->debugPort(); + m_connection->connectToHost(QLatin1String("127.0.0.1"), port); } void tst_QQmlInspector::init() diff --git a/tests/auto/qml/debugger/qqmlprofilerservice/data/TestImage_2x2.png b/tests/auto/qml/debugger/qqmlprofilerservice/data/TestImage_2x2.png Binary files differnew file mode 100644 index 0000000000..30228cbbdc --- /dev/null +++ b/tests/auto/qml/debugger/qqmlprofilerservice/data/TestImage_2x2.png diff --git a/tests/auto/qml/debugger/qqmlprofilerservice/data/pixmapCacheTest.qml b/tests/auto/qml/debugger/qqmlprofilerservice/data/pixmapCacheTest.qml new file mode 100644 index 0000000000..d56786bfae --- /dev/null +++ b/tests/auto/qml/debugger/qqmlprofilerservice/data/pixmapCacheTest.qml @@ -0,0 +1,13 @@ +import QtQuick 2.0 + +Rectangle { + Image { + source: "TestImage_2x2.png" + onStatusChanged: switch (status) { + case 0: console.log("no image"); break; + case 1: console.log("image loaded"); break; + case 2: console.log("image loading"); break; + case 3: console.log("image error"); break; + } + } +} diff --git a/tests/auto/qml/debugger/qqmlprofilerservice/data/scenegraphTest.qml b/tests/auto/qml/debugger/qqmlprofilerservice/data/scenegraphTest.qml new file mode 100644 index 0000000000..dd9d053296 --- /dev/null +++ b/tests/auto/qml/debugger/qqmlprofilerservice/data/scenegraphTest.qml @@ -0,0 +1,18 @@ +import QtQuick 2.0 + +Rectangle { + Rectangle { + width: 10 + height: 10 + color: "blue" + } + + Component.onCompleted: timer.start(); + + Timer { + id: timer + interval: 100 // 100 ms, enough for at least one frame + running: false + onTriggered: console.log("tick") + } +} diff --git a/tests/auto/qml/debugger/qqmlprofilerservice/qqmlprofilerservice.pro b/tests/auto/qml/debugger/qqmlprofilerservice/qqmlprofilerservice.pro index 5bff33dd25..b2b325dc72 100644 --- a/tests/auto/qml/debugger/qqmlprofilerservice/qqmlprofilerservice.pro +++ b/tests/auto/qml/debugger/qqmlprofilerservice/qqmlprofilerservice.pro @@ -12,3 +12,6 @@ TESTDATA = data/* QT += core qml testlib gui-private DEFINES += QT_DISABLE_DEPRECATED_BEFORE=0 + +OTHER_FILES += \ + data/pixmapCacheTest.qml diff --git a/tests/auto/qml/debugger/qqmlprofilerservice/tst_qqmlprofilerservice.cpp b/tests/auto/qml/debugger/qqmlprofilerservice/tst_qqmlprofilerservice.cpp index 3a925e2905..e4f886f7ce 100644 --- a/tests/auto/qml/debugger/qqmlprofilerservice/tst_qqmlprofilerservice.cpp +++ b/tests/auto/qml/debugger/qqmlprofilerservice/tst_qqmlprofilerservice.cpp @@ -46,8 +46,8 @@ #include "qqmldebugclient.h" #include "../../../shared/util.h" -#define PORT 13773 -#define STR_PORT "13773" +#define STR_PORT_FROM "13773" +#define STR_PORT_TO "13783" struct QQmlProfilerData { @@ -77,6 +77,8 @@ public: RangeLocation, RangeEnd, Complete, // end of transmission + PixmapCacheEvent, + SceneGraphFrame, MaximumMessage }; @@ -102,6 +104,32 @@ public: MaximumRangeType }; + enum PixmapEventType { + PixmapSizeKnown, + PixmapReferenceCountChanged, + PixmapCacheCountChanged, + PixmapLoadingStarted, + PixmapLoadingFinished, + PixmapLoadingError, + + MaximumPixmapEventType + }; + + enum SceneGraphFrameType { + SceneGraphRendererFrame, + SceneGraphAdaptationLayerFrame, + SceneGraphContextFrame, + SceneGraphRenderLoopFrame, + SceneGraphTexturePrepare, + SceneGraphTextureDeletion, + SceneGraphPolishAndSync, + SceneGraphWindowsRenderShow, + SceneGraphWindowsAnimations, + SceneGraphWindowsPolishFrame, + + MaximumSceneGraphFrameType + }; + QQmlProfilerClient(QQmlDebugConnection *connection) : QQmlDebugClient(QLatin1String("CanvasFrameRate"), connection) { @@ -135,6 +163,7 @@ public: { } + private: QQmlDebugProcess *m_process; QQmlDebugConnection *m_connection; @@ -148,6 +177,8 @@ private slots: void blockingConnectWithTraceEnabled(); void blockingConnectWithTraceDisabled(); void nonBlockingConnect(); + void pixmapCacheData(); + void scenegraphData(); void profileOnExit(); }; @@ -219,6 +250,44 @@ void QQmlProfilerClient::messageReceived(const QByteArray &message) QVERIFY(data.line >= -2); break; } + case QQmlProfilerClient::PixmapCacheEvent: { + stream >> data.detailType >> data.detailData; + if (data.detailType == QQmlProfilerClient::PixmapSizeKnown) + stream >> data.line >> data.column; + if (data.detailType == QQmlProfilerClient::PixmapReferenceCountChanged) + stream >> data.animationcount; + if (data.detailType == QQmlProfilerClient::PixmapCacheCountChanged) + stream >> data.animationcount; + break; + } + case QQmlProfilerClient::SceneGraphFrame: { + stream >> data.detailType; + qint64 subtime_1, subtime_2, subtime_3, subtime_4, subtime_5; + int glyphCount; + switch (data.detailType) { + // RendererFrame: preprocessTime, updateTime, bindingTime, renderTime + case QQmlProfilerClient::SceneGraphRendererFrame: stream >> subtime_1 >> subtime_2 >> subtime_3 >> subtime_4; break; + // AdaptationLayerFrame: glyphCount, glyphRenderTime, glyphStoreTime + case QQmlProfilerClient::SceneGraphAdaptationLayerFrame: stream >> glyphCount >> subtime_2 >> subtime_3; break; + // ContextFrame: compiling material time + case QQmlProfilerClient::SceneGraphContextFrame: stream >> subtime_1; break; + // RenderLoop: syncTime, renderTime, swapTime + case QQmlProfilerClient::SceneGraphRenderLoopFrame: stream >> subtime_1 >> subtime_2 >> subtime_3; break; + // TexturePrepare: bind, convert, swizzle, upload, mipmap + case QQmlProfilerClient::SceneGraphTexturePrepare: stream >> subtime_1 >> subtime_2 >> subtime_3 >> subtime_4 >> subtime_5; break; + // TextureDeletion: deletionTime + case QQmlProfilerClient::SceneGraphTextureDeletion: stream >> subtime_1; break; + // PolishAndSync: polishTime, waitTime, syncTime, animationsTime, + case QQmlProfilerClient::SceneGraphPolishAndSync: stream >> subtime_1 >> subtime_2 >> subtime_3 >> subtime_4; break; + // WindowsRenderLoop: GL time, make current time, SceneGraph time + case QQmlProfilerClient::SceneGraphWindowsRenderShow: stream >> subtime_1 >> subtime_2 >> subtime_3; break; + // WindowsAnimations: update time + case QQmlProfilerClient::SceneGraphWindowsAnimations: stream >> subtime_1; break; + // WindowsRenderWindow: polish time + case QQmlProfilerClient::SceneGraphWindowsPolishFrame: stream >> subtime_1; break; + } + break; + } default: QString failMsg = QString("Unknown message type:") + data.messageType; QFAIL(qPrintable(failMsg)); @@ -234,9 +303,9 @@ void tst_QQmlProfilerService::connect(bool block, const QString &testFile) QStringList arguments; if (block) - arguments << QString("-qmljsdebugger=port:" STR_PORT ",block"); + arguments << QString("-qmljsdebugger=port:" STR_PORT_FROM "," STR_PORT_TO ",block"); else - arguments << QString("-qmljsdebugger=port:" STR_PORT); + arguments << QString("-qmljsdebugger=port:" STR_PORT_FROM "," STR_PORT_TO ); arguments << QQmlDataTest::instance()->testFile(testFile); @@ -247,7 +316,8 @@ void tst_QQmlProfilerService::connect(bool block, const QString &testFile) QQmlDebugConnection *m_connection = new QQmlDebugConnection(); m_client = new QQmlProfilerClient(m_connection); - m_connection->connectToHost(QLatin1String("127.0.0.1"), PORT); + const int port = m_process->debugPort(); + m_connection->connectToHost(QLatin1String("127.0.0.1"), port); } void tst_QQmlProfilerService::cleanup() @@ -319,6 +389,84 @@ void tst_QQmlProfilerService::nonBlockingConnect() QCOMPARE(m_client->traceMessages.last().detailType, (int)QQmlProfilerClient::EndTrace); } +void tst_QQmlProfilerService::pixmapCacheData() +{ + connect(true, "pixmapCacheTest.qml"); + QTRY_COMPARE(m_client->state(), QQmlDebugClient::Enabled); + + m_client->setTraceState(true); + QVERIFY(QQmlDebugTest::waitForSignal(m_process, SIGNAL(readyReadStandardOutput()))); + + QVERIFY(m_process->output().indexOf(QLatin1String("image loaded")) != -1 || + m_process->output().indexOf(QLatin1String("image error")) != -1 ); + + + m_client->setTraceState(false); + + QVERIFY2(QQmlDebugTest::waitForSignal(m_client, SIGNAL(complete())), "No trace received in time."); + QVERIFY(m_client->traceMessages.count()); + + // must start with "StartTrace" + QCOMPARE(m_client->traceMessages.first().messageType, (int)QQmlProfilerClient::Event); + QCOMPARE(m_client->traceMessages.first().detailType, (int)QQmlProfilerClient::StartTrace); + + // image starting to load + QCOMPARE(m_client->traceMessages[8].messageType, (int)QQmlProfilerClient::PixmapCacheEvent); + QCOMPARE(m_client->traceMessages[8].detailType, (int)QQmlProfilerClient::PixmapLoadingStarted); + + // image loaded + QCOMPARE(m_client->traceMessages[9].messageType, (int)QQmlProfilerClient::PixmapCacheEvent); + QCOMPARE(m_client->traceMessages[9].detailType, (int)QQmlProfilerClient::PixmapLoadingFinished); + + // image size + QCOMPARE(m_client->traceMessages[10].messageType, (int)QQmlProfilerClient::PixmapCacheEvent); + QCOMPARE(m_client->traceMessages[10].detailType, (int)QQmlProfilerClient::PixmapSizeKnown); + QCOMPARE(m_client->traceMessages[10].line, 2); // width + QCOMPARE(m_client->traceMessages[10].column, 2); // height + + // cache size + QCOMPARE(m_client->traceMessages[11].messageType, (int)QQmlProfilerClient::PixmapCacheEvent); + QCOMPARE(m_client->traceMessages[11].detailType, (int)QQmlProfilerClient::PixmapCacheCountChanged); + + // must end with "EndTrace" + QCOMPARE(m_client->traceMessages.last().messageType, (int)QQmlProfilerClient::Event); + QCOMPARE(m_client->traceMessages.last().detailType, (int)QQmlProfilerClient::EndTrace); + +} + +void tst_QQmlProfilerService::scenegraphData() +{ + connect(true, "scenegraphTest.qml"); + QTRY_COMPARE(m_client->state(), QQmlDebugClient::Enabled); + + m_client->setTraceState(true); + QVERIFY(QQmlDebugTest::waitForSignal(m_process, SIGNAL(readyReadStandardOutput()))); + QVERIFY(m_process->output().indexOf(QLatin1String("tick")) != -1); + m_client->setTraceState(false); + + QVERIFY2(QQmlDebugTest::waitForSignal(m_client, SIGNAL(complete())), "No trace received in time."); + QVERIFY(m_client->traceMessages.count()); + + // check that at least one frame was rendered + // there should be a SGPolishAndSync + SGRendererFrame + SGRenderLoopFrame sequence + // since the rendering happens in a different thread, there could be other unrelated events interleaved + int loopcheck = 0; + foreach (const QQmlProfilerData &msg, m_client->traceMessages) { + if (msg.messageType == QQmlProfilerClient::SceneGraphFrame) { + if (loopcheck == 0 && msg.detailType == QQmlProfilerClient::SceneGraphContextFrame) + loopcheck = 1; + else + if (loopcheck == 1 && msg.detailType == QQmlProfilerClient::SceneGraphRendererFrame) + loopcheck = 2; + else + if (loopcheck == 2 && msg.detailType == QQmlProfilerClient::SceneGraphRenderLoopFrame) + loopcheck = 3; + } + } + + QCOMPARE(loopcheck, 3); +} + void tst_QQmlProfilerService::profileOnExit() { connect(true, "exit.qml"); diff --git a/tests/auto/qml/debugger/shared/debugutil.cpp b/tests/auto/qml/debugger/shared/debugutil.cpp index 6585f7eca2..ff3140f520 100644 --- a/tests/auto/qml/debugger/shared/debugutil.cpp +++ b/tests/auto/qml/debugger/shared/debugutil.cpp @@ -182,6 +182,8 @@ void QQmlDebugProcess::processAppOutput() { m_mutex.lock(); + bool outputFromAppItself = false; + QString newOutput = m_process.readAll(); m_output.append(newOutput); m_outputBuffer.append(newOutput); @@ -208,7 +210,13 @@ void QQmlDebugProcess::processAppOutput() m_eventLoop.quit(); continue; } + } else { + // set to true if there is output not coming from the debugger + outputFromAppItself = true; } } m_mutex.unlock(); + + if (outputFromAppItself) + emit readyReadStandardOutput(); } diff --git a/tests/auto/qml/debugger/shared/debugutil_p.h b/tests/auto/qml/debugger/shared/debugutil_p.h index 2b9a94366a..11b16a1fb8 100644 --- a/tests/auto/qml/debugger/shared/debugutil_p.h +++ b/tests/auto/qml/debugger/shared/debugutil_p.h @@ -57,7 +57,7 @@ class QQmlDebugTest { public: - static bool waitForSignal(QObject *receiver, const char *member, int timeout = 10000); + static bool waitForSignal(QObject *receiver, const char *member, int timeout = 5000); }; class QQmlDebugTestClient : public QQmlDebugClient @@ -98,6 +98,9 @@ public: QString output() const; void stop(); +signals: + void readyReadStandardOutput(); + private slots: void timeout(); void processAppOutput(); diff --git a/tests/auto/qml/qjsengine/tst_qjsengine.cpp b/tests/auto/qml/qjsengine/tst_qjsengine.cpp index 5e3d78d39b..7c9f5b106c 100644 --- a/tests/auto/qml/qjsengine/tst_qjsengine.cpp +++ b/tests/auto/qml/qjsengine/tst_qjsengine.cpp @@ -2554,7 +2554,7 @@ void tst_QJSEngine::qRegExpInport() } // QScriptValue::toDateTime() returns a local time, whereas JS dates -// are always stored as UTC. QtScript must respect the current time +// are always stored as UTC. Qt Script must respect the current time // zone, and correctly adjust for daylight saving time that may be in // effect at a given date (QTBUG-9770). void tst_QJSEngine::dateRoundtripJSQtJS() diff --git a/tests/auto/qml/qml.pro b/tests/auto/qml/qml.pro index b080a824cf..371d47ba32 100644 --- a/tests/auto/qml/qml.pro +++ b/tests/auto/qml/qml.pro @@ -69,3 +69,7 @@ SUBDIRS += debugger contains(QT_CONFIG, private_tests) { SUBDIRS += $$PRIVATETESTS } + +qtNomakeTools( \ + qmlplugindump \ +) diff --git a/tests/auto/qml/qmlmin/tst_qmlmin.cpp b/tests/auto/qml/qmlmin/tst_qmlmin.cpp index a69dce7ec3..e513861bdf 100644 --- a/tests/auto/qml/qmlmin/tst_qmlmin.cpp +++ b/tests/auto/qml/qmlmin/tst_qmlmin.cpp @@ -169,7 +169,7 @@ bool tst_qmlmin::isInvalidFile(const QFileInfo &fileName) const } /* -This test runs all the examples in the QtQml UI source tree and ensures +This test runs all the examples in the Qt QML UI source tree and ensures that they start and exit cleanly. Examples are any .qml files under the examples/ directory that start diff --git a/tests/auto/qml/qmlplugindump/tst_qmlplugindump.cpp b/tests/auto/qml/qmlplugindump/tst_qmlplugindump.cpp index 6aca47656b..d9a370b200 100644 --- a/tests/auto/qml/qmlplugindump/tst_qmlplugindump.cpp +++ b/tests/auto/qml/qmlplugindump/tst_qmlplugindump.cpp @@ -68,9 +68,7 @@ void tst_qmlplugindump::initTestCase() { qmlplugindumpPath = QLibraryInfo::location(QLibraryInfo::BinariesPath); -#if defined(Q_OS_MAC) - qmlplugindumpPath += QLatin1String("/qmlplugindump.app/Contents/MacOS/qmlplugindump"); -#elif defined(Q_OS_WIN) +#if defined(Q_OS_WIN) qmlplugindumpPath += QLatin1String("/qmlplugindump.exe"); #else qmlplugindumpPath += QLatin1String("/qmlplugindump"); diff --git a/tests/auto/qml/qqmlapplicationengine/tst_qqmlapplicationengine.cpp b/tests/auto/qml/qqmlapplicationengine/tst_qqmlapplicationengine.cpp index 1c11fcbc73..4780ee0310 100644 --- a/tests/auto/qml/qqmlapplicationengine/tst_qqmlapplicationengine.cpp +++ b/tests/auto/qml/qqmlapplicationengine/tst_qqmlapplicationengine.cpp @@ -110,13 +110,11 @@ void tst_qqmlapplicationengine::application() */ QDir::setCurrent(buildDir); QProcess *testProcess = new QProcess(this); - QTest::ignoreMessage(QtWarningMsg, "Don't know how to handle 'QProcess::ExitStatus', use qRegisterMetaType to register it."); - QSignalSpy processFinished(testProcess, SIGNAL(finished(int,QProcess::ExitStatus))); QStringList args; args << QLatin1String("testData"); testProcess->start(QLatin1String("testapp/testapp"), args); - QTRY_VERIFY(processFinished.count());//Application should immediately exit - QCOMPARE(processFinished[0][0].toInt(), 0); + QVERIFY(testProcess->waitForFinished(5000)); + QCOMPARE(testProcess->exitCode(), 0); QByteArray test_stdout = testProcess->readAllStandardOutput(); QByteArray test_stderr = testProcess->readAllStandardError(); QByteArray test_stderr_target("Start: testData\nEnd\n"); diff --git a/tests/auto/qml/qqmlcomponent/data/createWindow.qml b/tests/auto/qml/qqmlcomponent/data/createWindow.qml new file mode 100644 index 0000000000..af0b7edeb2 --- /dev/null +++ b/tests/auto/qml/qqmlcomponent/data/createWindow.qml @@ -0,0 +1,29 @@ +import QtQuick 2.1 +import QtQuick.Window 2.1 + +Window { + id: window1; + objectName: "window1"; + color: "#00FF00"; + width: 100; height: 100; + Item { + objectName: "item1" + width: 100; height: 100; + MouseArea { + objectName: "mousearea" + anchors.fill: parent; + onPressed: window2.requestActivate(); + } + Component.onCompleted: window2.show(); + } + + Window { + id: window2; + objectName: "window2"; + color: "#FF0000"; + width: 100; height: 100; + Item { + width: 100; height: 100; + } + } +} diff --git a/tests/auto/qml/qqmlcomponent/tst_qqmlcomponent.cpp b/tests/auto/qml/qqmlcomponent/tst_qqmlcomponent.cpp index 697c8103b0..9eeff66e7a 100644 --- a/tests/auto/qml/qqmlcomponent/tst_qqmlcomponent.cpp +++ b/tests/auto/qml/qqmlcomponent/tst_qqmlcomponent.cpp @@ -105,6 +105,7 @@ public: private slots: void null(); void loadEmptyUrl(); + void qmlCreateWindow(); void qmlCreateObject(); void qmlCreateObjectWithProperties(); void qmlIncubateObject(); @@ -163,6 +164,15 @@ void tst_qqmlcomponent::qmlIncubateObject() delete object; } +void tst_qqmlcomponent::qmlCreateWindow() +{ + QQmlEngine engine; + QQmlComponent component(&engine); + component.loadUrl(testFileUrl("createWindow.qml")); + QQuickWindow* window = qobject_cast<QQuickWindow *>(component.create()); + QVERIFY(window); +} + void tst_qqmlcomponent::qmlCreateObject() { QQmlEngine engine; diff --git a/tests/auto/qml/qqmlecmascript/data/MyDeferredComponent.qml b/tests/auto/qml/qqmlecmascript/data/MyDeferredComponent.qml new file mode 100644 index 0000000000..1432e7da55 --- /dev/null +++ b/tests/auto/qml/qqmlecmascript/data/MyDeferredComponent.qml @@ -0,0 +1,10 @@ +import Qt.test 1.0 +import QtQml 2.0 + +MyDeferredObject { + id: root + property QtObject target: null + objectProperty: MyQmlObject { + value: target.value + } +} diff --git a/tests/auto/qml/qqmlecmascript/data/MyDeferredComponent2.qml b/tests/auto/qml/qqmlecmascript/data/MyDeferredComponent2.qml new file mode 100644 index 0000000000..de73629f7a --- /dev/null +++ b/tests/auto/qml/qqmlecmascript/data/MyDeferredComponent2.qml @@ -0,0 +1,3 @@ +import Qt.test 1.0 + +MyDeferredObject {} diff --git a/tests/auto/qml/qqmlecmascript/data/deferredPropertiesInComponents.qml b/tests/auto/qml/qqmlecmascript/data/deferredPropertiesInComponents.qml new file mode 100644 index 0000000000..868b7b1908 --- /dev/null +++ b/tests/auto/qml/qqmlecmascript/data/deferredPropertiesInComponents.qml @@ -0,0 +1,15 @@ +import Qt.test 1.0 +import QtQml 2.0 + +QtObject { + id: root + property int value: 10 + property QtObject deferredInside: MyDeferredComponent { + target: root + } + property QtObject deferredOutside: MyDeferredComponent2 { + objectProperty: MyQmlObject { + value: root.value + } + } +} diff --git a/tests/auto/qml/qqmlecmascript/tst_qqmlecmascript.cpp b/tests/auto/qml/qqmlecmascript/tst_qqmlecmascript.cpp index dcf72f9dc0..cb1b0b3212 100644 --- a/tests/auto/qml/qqmlecmascript/tst_qqmlecmascript.cpp +++ b/tests/auto/qml/qqmlecmascript/tst_qqmlecmascript.cpp @@ -89,6 +89,7 @@ private slots: void objectPropertiesTriggerReeval(); void deferredProperties(); void deferredPropertiesErrors(); + void deferredPropertiesInComponents(); void extensionObjects(); void overrideExtensionProperties(); void attachedProperties(); @@ -863,6 +864,37 @@ void tst_qqmlecmascript::deferredPropertiesErrors() delete object; } +void tst_qqmlecmascript::deferredPropertiesInComponents() +{ + // Test that it works when the property is set inside and outside component + QQmlComponent component(&engine, testFileUrl("deferredPropertiesInComponents.qml")); + QObject *object = component.create(); + if (!object) + qDebug() << component.errorString(); + QVERIFY(object != 0); + QCOMPARE(object->property("value").value<int>(), 10); + + MyDeferredObject *defObjectA = + qobject_cast<MyDeferredObject *>(object->property("deferredInside").value<QObject*>()); + QVERIFY(defObjectA != 0); + QVERIFY(defObjectA->objectProperty() == 0); + + qmlExecuteDeferred(defObjectA); + QVERIFY(defObjectA->objectProperty() != 0); + QCOMPARE(defObjectA->objectProperty()->property("value").value<int>(), 10); + + MyDeferredObject *defObjectB = + qobject_cast<MyDeferredObject *>(object->property("deferredOutside").value<QObject*>()); + QVERIFY(defObjectB != 0); + QVERIFY(defObjectB->objectProperty() == 0); + + qmlExecuteDeferred(defObjectB); + QVERIFY(defObjectB->objectProperty() != 0); + QCOMPARE(defObjectB->objectProperty()->property("value").value<int>(), 10); + + delete object; +} + void tst_qqmlecmascript::extensionObjects() { QQmlComponent component(&engine, testFileUrl("extensionObjects.qml")); diff --git a/tests/auto/qml/qqmlengine/data/interception/qmldir/Intercepted.qml b/tests/auto/qml/qqmlengine/data/interception/qmldir/Intercepted.qml new file mode 100644 index 0000000000..0331a01ad4 --- /dev/null +++ b/tests/auto/qml/qqmlengine/data/interception/qmldir/Intercepted.qml @@ -0,0 +1,5 @@ +import QtQml 2.0 + +QtObject { + property string myStr: "intercepted" +} diff --git a/tests/auto/qml/qqmlengine/data/interception/qmldir/intercepted.js b/tests/auto/qml/qqmlengine/data/interception/qmldir/intercepted.js new file mode 100644 index 0000000000..6f54ebcdc5 --- /dev/null +++ b/tests/auto/qml/qqmlengine/data/interception/qmldir/intercepted.js @@ -0,0 +1 @@ +var myStr = "base file" diff --git a/tests/auto/qml/qqmlengine/data/interception/qmldir/intercepted/Intercepted.qml b/tests/auto/qml/qqmlengine/data/interception/qmldir/intercepted/Intercepted.qml new file mode 100644 index 0000000000..ef5c28f87b --- /dev/null +++ b/tests/auto/qml/qqmlengine/data/interception/qmldir/intercepted/Intercepted.qml @@ -0,0 +1,6 @@ +import QtQml 2.0 + +QtObject { + property string myStr: "intercepted" + property Intercepted2 compilationIsTest: Intercepted2{} +} diff --git a/tests/auto/qml/qqmlengine/data/interception/qmldir/intercepted/Intercepted2.qml b/tests/auto/qml/qqmlengine/data/interception/qmldir/intercepted/Intercepted2.qml new file mode 100644 index 0000000000..0331a01ad4 --- /dev/null +++ b/tests/auto/qml/qqmlengine/data/interception/qmldir/intercepted/Intercepted2.qml @@ -0,0 +1,5 @@ +import QtQml 2.0 + +QtObject { + property string myStr: "intercepted" +} diff --git a/tests/auto/qml/qqmlengine/data/interception/qmldir/intercepted/intercepted.js b/tests/auto/qml/qqmlengine/data/interception/qmldir/intercepted/intercepted.js new file mode 100644 index 0000000000..6eeee6e72f --- /dev/null +++ b/tests/auto/qml/qqmlengine/data/interception/qmldir/intercepted/intercepted.js @@ -0,0 +1 @@ +var myStr = "intercepted" diff --git a/tests/auto/qml/qqmlengine/data/interception/qmldir/intercepted/urlInterceptor.qml b/tests/auto/qml/qqmlengine/data/interception/qmldir/intercepted/urlInterceptor.qml new file mode 100644 index 0000000000..bd4aee056a --- /dev/null +++ b/tests/auto/qml/qqmlengine/data/interception/qmldir/intercepted/urlInterceptor.qml @@ -0,0 +1,11 @@ +import QtQml 2.0 +import "intercepted.js" as Script + +QtObject { + property url filePath: "FailsTest" + property url resolvedUrl: Qt.resolvedUrl("FailsTest"); + property url absoluteUrl: Qt.resolvedUrl("file:///FailsTest"); + property string childString: child.myStr + property string scriptString: Script.myStr + property Intercepted child: Intercepted {} +} diff --git a/tests/auto/qml/qqmlengine/data/interception/qmldir/urlInterceptor.qml b/tests/auto/qml/qqmlengine/data/interception/qmldir/urlInterceptor.qml new file mode 100644 index 0000000000..22a09e5522 --- /dev/null +++ b/tests/auto/qml/qqmlengine/data/interception/qmldir/urlInterceptor.qml @@ -0,0 +1,12 @@ +import QtQml 2.0 +import "." +import "intercepted.js" as Script + +QtObject { + property url filePath: "doesNotExist.file" + property url resolvedUrl: Qt.resolvedUrl("doesNotExist.file"); + property url absoluteUrl: Qt.resolvedUrl("file:///doesNotExist.file"); + property string childString: child.myStr + property string scriptString: Script.myStr + property Intercepted child: Intercepted {} +} diff --git a/tests/auto/qml/qqmlengine/data/interception/strings/Intercepted.qml b/tests/auto/qml/qqmlengine/data/interception/strings/Intercepted.qml new file mode 100644 index 0000000000..449207e0e3 --- /dev/null +++ b/tests/auto/qml/qqmlengine/data/interception/strings/Intercepted.qml @@ -0,0 +1,5 @@ +import QtQml 2.0 + +QtObject { + property string myStr: "base file" +} diff --git a/tests/auto/qml/qqmlengine/data/interception/strings/intercepted.js b/tests/auto/qml/qqmlengine/data/interception/strings/intercepted.js new file mode 100644 index 0000000000..6f54ebcdc5 --- /dev/null +++ b/tests/auto/qml/qqmlengine/data/interception/strings/intercepted.js @@ -0,0 +1 @@ +var myStr = "base file" diff --git a/tests/auto/qml/qqmlengine/data/interception/strings/intercepted/Intercepted.qml b/tests/auto/qml/qqmlengine/data/interception/strings/intercepted/Intercepted.qml new file mode 100644 index 0000000000..0331a01ad4 --- /dev/null +++ b/tests/auto/qml/qqmlengine/data/interception/strings/intercepted/Intercepted.qml @@ -0,0 +1,5 @@ +import QtQml 2.0 + +QtObject { + property string myStr: "intercepted" +} diff --git a/tests/auto/qml/qqmlengine/data/interception/strings/intercepted/intercepted.js b/tests/auto/qml/qqmlengine/data/interception/strings/intercepted/intercepted.js new file mode 100644 index 0000000000..6eeee6e72f --- /dev/null +++ b/tests/auto/qml/qqmlengine/data/interception/strings/intercepted/intercepted.js @@ -0,0 +1 @@ +var myStr = "intercepted" diff --git a/tests/auto/qml/qqmlengine/data/interception/strings/intercepted/urlInterceptor.qml b/tests/auto/qml/qqmlengine/data/interception/strings/intercepted/urlInterceptor.qml new file mode 100644 index 0000000000..bd4aee056a --- /dev/null +++ b/tests/auto/qml/qqmlengine/data/interception/strings/intercepted/urlInterceptor.qml @@ -0,0 +1,11 @@ +import QtQml 2.0 +import "intercepted.js" as Script + +QtObject { + property url filePath: "FailsTest" + property url resolvedUrl: Qt.resolvedUrl("FailsTest"); + property url absoluteUrl: Qt.resolvedUrl("file:///FailsTest"); + property string childString: child.myStr + property string scriptString: Script.myStr + property Intercepted child: Intercepted {} +} diff --git a/tests/auto/qml/qqmlengine/data/interception/strings/urlInterceptor.qml b/tests/auto/qml/qqmlengine/data/interception/strings/urlInterceptor.qml new file mode 100644 index 0000000000..be86195bd8 --- /dev/null +++ b/tests/auto/qml/qqmlengine/data/interception/strings/urlInterceptor.qml @@ -0,0 +1,11 @@ +import QtQml 2.0 +import "intercepted.js" as Script + +QtObject { + property url filePath: "doesNotExist.file" + property url resolvedUrl: Qt.resolvedUrl("doesNotExist.file"); + property url absoluteUrl: Qt.resolvedUrl("file:///doesNotExist.file"); + property string childString: child.myStr + property string scriptString: Script.myStr + property Intercepted child: Intercepted {} +} diff --git a/tests/auto/qml/qqmlengine/data/interception/types/Intercepted.qml b/tests/auto/qml/qqmlengine/data/interception/types/Intercepted.qml new file mode 100644 index 0000000000..449207e0e3 --- /dev/null +++ b/tests/auto/qml/qqmlengine/data/interception/types/Intercepted.qml @@ -0,0 +1,5 @@ +import QtQml 2.0 + +QtObject { + property string myStr: "base file" +} diff --git a/tests/auto/qml/qqmlengine/data/interception/types/Intercepted2.qml b/tests/auto/qml/qqmlengine/data/interception/types/Intercepted2.qml new file mode 100644 index 0000000000..0331a01ad4 --- /dev/null +++ b/tests/auto/qml/qqmlengine/data/interception/types/Intercepted2.qml @@ -0,0 +1,5 @@ +import QtQml 2.0 + +QtObject { + property string myStr: "intercepted" +} diff --git a/tests/auto/qml/qqmlengine/data/interception/types/intercepted.js b/tests/auto/qml/qqmlengine/data/interception/types/intercepted.js new file mode 100644 index 0000000000..6f54ebcdc5 --- /dev/null +++ b/tests/auto/qml/qqmlengine/data/interception/types/intercepted.js @@ -0,0 +1 @@ +var myStr = "base file" diff --git a/tests/auto/qml/qqmlengine/data/interception/types/intercepted/Intercepted.qml b/tests/auto/qml/qqmlengine/data/interception/types/intercepted/Intercepted.qml new file mode 100644 index 0000000000..ef5c28f87b --- /dev/null +++ b/tests/auto/qml/qqmlengine/data/interception/types/intercepted/Intercepted.qml @@ -0,0 +1,6 @@ +import QtQml 2.0 + +QtObject { + property string myStr: "intercepted" + property Intercepted2 compilationIsTest: Intercepted2{} +} diff --git a/tests/auto/qml/qqmlengine/data/interception/types/intercepted/Intercepted2.qml b/tests/auto/qml/qqmlengine/data/interception/types/intercepted/Intercepted2.qml new file mode 100644 index 0000000000..0331a01ad4 --- /dev/null +++ b/tests/auto/qml/qqmlengine/data/interception/types/intercepted/Intercepted2.qml @@ -0,0 +1,5 @@ +import QtQml 2.0 + +QtObject { + property string myStr: "intercepted" +} diff --git a/tests/auto/qml/qqmlengine/data/interception/types/intercepted/intercepted.js b/tests/auto/qml/qqmlengine/data/interception/types/intercepted/intercepted.js new file mode 100644 index 0000000000..6eeee6e72f --- /dev/null +++ b/tests/auto/qml/qqmlengine/data/interception/types/intercepted/intercepted.js @@ -0,0 +1 @@ +var myStr = "intercepted" diff --git a/tests/auto/qml/qqmlengine/data/interception/types/intercepted/urlInterceptor.qml b/tests/auto/qml/qqmlengine/data/interception/types/intercepted/urlInterceptor.qml new file mode 100644 index 0000000000..be86195bd8 --- /dev/null +++ b/tests/auto/qml/qqmlengine/data/interception/types/intercepted/urlInterceptor.qml @@ -0,0 +1,11 @@ +import QtQml 2.0 +import "intercepted.js" as Script + +QtObject { + property url filePath: "doesNotExist.file" + property url resolvedUrl: Qt.resolvedUrl("doesNotExist.file"); + property url absoluteUrl: Qt.resolvedUrl("file:///doesNotExist.file"); + property string childString: child.myStr + property string scriptString: Script.myStr + property Intercepted child: Intercepted {} +} diff --git a/tests/auto/qml/qqmlengine/data/interception/types/urlInterceptor.qml b/tests/auto/qml/qqmlengine/data/interception/types/urlInterceptor.qml new file mode 100644 index 0000000000..bd4aee056a --- /dev/null +++ b/tests/auto/qml/qqmlengine/data/interception/types/urlInterceptor.qml @@ -0,0 +1,11 @@ +import QtQml 2.0 +import "intercepted.js" as Script + +QtObject { + property url filePath: "FailsTest" + property url resolvedUrl: Qt.resolvedUrl("FailsTest"); + property url absoluteUrl: Qt.resolvedUrl("file:///FailsTest"); + property string childString: child.myStr + property string scriptString: Script.myStr + property Intercepted child: Intercepted {} +} diff --git a/tests/auto/qml/qqmlengine/tst_qqmlengine.cpp b/tests/auto/qml/qqmlengine/tst_qqmlengine.cpp index 9177ff58f7..d604118b58 100644 --- a/tests/auto/qml/qqmlengine/tst_qqmlengine.cpp +++ b/tests/auto/qml/qqmlengine/tst_qqmlengine.cpp @@ -54,6 +54,7 @@ #include <QQmlExpression> #include <QQmlIncubationController> #include <private/qqmlengine_p.h> +#include <private/qqmlabstracturlinterceptor_p.h> class tst_qqmlengine : public QQmlDataTest { @@ -79,6 +80,8 @@ private slots: void multipleEngines(); void qtqmlModule_data(); void qtqmlModule(); + void urlInterceptor_data(); + void urlInterceptor(); public slots: QObject *createAQObjectForOwnershipTest () @@ -674,6 +677,99 @@ void tst_qqmlengine::qtqmlModule() } } +class CustomSelector : public QQmlAbstractUrlInterceptor +{ +public: + virtual QUrl intercept(const QUrl &url, QQmlAbstractUrlInterceptor::DataType d) + { + if (url.scheme() != QStringLiteral("file")) + return url; + if (!m_interceptionPoints.contains(d)) + return url; + + QString alteredPath = url.path(); + int a = alteredPath.lastIndexOf('/'); + if (a < 0) + a = 0; + alteredPath.insert(a, QStringLiteral("/intercepted")); + + QUrl ret = url; + ret.setPath(alteredPath); + return ret; + } + QList<QQmlAbstractUrlInterceptor::DataType> m_interceptionPoints; +}; + +Q_DECLARE_METATYPE(QList<QQmlAbstractUrlInterceptor::DataType>); +void tst_qqmlengine::urlInterceptor_data() +{ + QTest::addColumn<QUrl>("testFile"); + QTest::addColumn<QList<QQmlAbstractUrlInterceptor::DataType> >("interceptionPoint"); + QTest::addColumn<QString>("expectedFilePath"); + QTest::addColumn<QString>("expectedChildString"); + QTest::addColumn<QString>("expectedScriptString"); + QTest::addColumn<QString>("expectedResolvedUrl"); + QTest::addColumn<QString>("expectedAbsoluteUrl"); + + QTest::newRow("InterceptTypes") + << testFileUrl("interception/types/urlInterceptor.qml") + << (QList<QQmlAbstractUrlInterceptor::DataType>() << QQmlAbstractUrlInterceptor::QmlFile << QQmlAbstractUrlInterceptor::JavaScriptFile << QQmlAbstractUrlInterceptor::UrlString) + << testFileUrl("interception/types/intercepted/doesNotExist.file").toString() + << QStringLiteral("intercepted") + << QStringLiteral("intercepted") + << testFileUrl("interception/types/intercepted/doesNotExist.file").toString() + << QStringLiteral("file:///intercepted/doesNotExist.file"); + + QTest::newRow("InterceptQmlDir") + << testFileUrl("interception/qmldir/urlInterceptor.qml") + << (QList<QQmlAbstractUrlInterceptor::DataType>() << QQmlAbstractUrlInterceptor::QmldirFile << QQmlAbstractUrlInterceptor::UrlString) + << testFileUrl("interception/qmldir/intercepted/doesNotExist.file").toString() + << QStringLiteral("intercepted") + << QStringLiteral("base file") + << testFileUrl("interception/qmldir/intercepted/doesNotExist.file").toString() + << QStringLiteral("file:///intercepted/doesNotExist.file"); + + QTest::newRow("InterceptStrings") + << testFileUrl("interception/strings/urlInterceptor.qml") + << (QList<QQmlAbstractUrlInterceptor::DataType>() << QQmlAbstractUrlInterceptor::UrlString) + << testFileUrl("interception/strings/intercepted/doesNotExist.file").toString() + << QStringLiteral("base file") + << QStringLiteral("base file") + << testFileUrl("interception/strings/intercepted/doesNotExist.file").toString() + << QStringLiteral("file:///intercepted/doesNotExist.file"); +} + +void tst_qqmlengine::urlInterceptor() +{ + + QFETCH(QUrl, testFile); + QFETCH(QList<QQmlAbstractUrlInterceptor::DataType>, interceptionPoint); + QFETCH(QString, expectedFilePath); + QFETCH(QString, expectedChildString); + QFETCH(QString, expectedScriptString); + QFETCH(QString, expectedResolvedUrl); + QFETCH(QString, expectedAbsoluteUrl); + + QQmlEngine e; + CustomSelector cs; + cs.m_interceptionPoints = interceptionPoint; + e.setUrlInterceptor(&cs); + QQmlComponent c(&e, testFile); //Note that this can get intercepted too + QObject *o = c.create(); + if (!o) + qDebug() << c.errorString(); + QVERIFY(o); + //Test a URL as a property initialization + QCOMPARE(o->property("filePath").toString(), expectedFilePath); + //Test a URL as a Type location + QCOMPARE(o->property("childString").toString(), expectedChildString); + //Test a URL as a Script location + QCOMPARE(o->property("scriptString").toString(), expectedScriptString); + //Test a URL as a resolveUrl() call + QCOMPARE(o->property("resolvedUrl").toString(), expectedResolvedUrl); + QCOMPARE(o->property("absoluteUrl").toString(), expectedAbsoluteUrl); +} + QTEST_MAIN(tst_qqmlengine) #include "tst_qqmlengine.moc" diff --git a/tests/auto/qml/qqmllanguage/tst_qqmllanguage.cpp b/tests/auto/qml/qqmllanguage/tst_qqmllanguage.cpp index 1a82bacfb2..29c4463471 100644 --- a/tests/auto/qml/qqmllanguage/tst_qqmllanguage.cpp +++ b/tests/auto/qml/qqmllanguage/tst_qqmllanguage.cpp @@ -242,6 +242,7 @@ private: void tst_qqmllanguage::cleanupTestCase() { QVERIFY(QFile::remove(testFile(QString::fromUtf8("I18nType\303\201\303\242\303\243\303\244\303\245.qml")))); + qmlClearTypeRegistrations(); // Should not crash } void tst_qqmllanguage::insertedSemicolon_data() diff --git a/tests/auto/qml/qqmlpropertymap/tst_qqmlpropertymap.cpp b/tests/auto/qml/qqmlpropertymap/tst_qqmlpropertymap.cpp index 327716f1b5..ca212d333b 100644 --- a/tests/auto/qml/qqmlpropertymap/tst_qqmlpropertymap.cpp +++ b/tests/auto/qml/qqmlpropertymap/tst_qqmlpropertymap.cpp @@ -66,6 +66,8 @@ private slots: void crashBug(); void QTBUG_17868(); void metaObjectAccessibility(); + void QTBUG_31226(); + void QTBUG_29836(); }; void tst_QQmlPropertyMap::insert() @@ -286,13 +288,17 @@ class MyEnhancedPropertyMap : public QQmlPropertyMap { Q_OBJECT public: - MyEnhancedPropertyMap() : QQmlPropertyMap(this, 0) {} + MyEnhancedPropertyMap() : QQmlPropertyMap(this, 0), m_testSlotCalled(false) {} + bool testSlotCalled() const { return m_testSlotCalled; } signals: void testSignal(); public slots: - void testSlot() {} + void testSlot() { m_testSlotCalled = true; } + +private: + bool m_testSlotCalled; }; void tst_QQmlPropertyMap::metaObjectAccessibility() @@ -312,6 +318,57 @@ void tst_QQmlPropertyMap::metaObjectAccessibility() QVERIFY2(messageHandler.messages().isEmpty(), qPrintable(messageHandler.messageString())); } +void tst_QQmlPropertyMap::QTBUG_31226() +{ + /* Instantiate a property map from QML, and verify that property changes + * made from C++ are visible from QML */ + QQmlEngine engine; + QQmlContext context(&engine); + qmlRegisterType<QQmlPropertyMap>("QTBUG_31226", 1, 0, "PropertyMap"); + QQmlComponent c(&engine); + c.setData("import QtQuick 2.0\nimport QTBUG_31226 1.0\n" + "Item {\n" + " property string myProp\n" + " PropertyMap { id: qmlPropertyMap; objectName: \"qmlPropertyMap\" }\n" + " Timer { interval: 5; running: true; onTriggered: { myProp = qmlPropertyMap.greeting; } }\n" + "}", + QUrl()); + QObject *obj = c.create(&context); + QVERIFY(obj); + + QQmlPropertyMap *qmlPropertyMap = obj->findChild<QQmlPropertyMap*>(QString("qmlPropertyMap")); + QVERIFY(qmlPropertyMap); + + qmlPropertyMap->insert("greeting", QString("Hello world!")); + QTRY_COMPARE(obj->property("myProp").toString(), QString("Hello world!")); + + delete obj; + +} + +void tst_QQmlPropertyMap::QTBUG_29836() +{ + MyEnhancedPropertyMap map; + QCOMPARE(map.testSlotCalled(), false); + + QQmlEngine engine; + QQmlContext context(&engine); + context.setContextProperty("enhancedMap", &map); + QQmlComponent c(&engine); + c.setData("import QtQuick 2.0\n" + "Item {\n" + " Timer { interval: 5; running: true; onTriggered: enhancedMap.testSlot() }\n" + "}", + QUrl()); + QObject *obj = c.create(&context); + QVERIFY(obj); + + QTRY_COMPARE(map.testSlotCalled(), true); + + delete obj; + +} + QTEST_MAIN(tst_QQmlPropertyMap) #include "tst_qqmlpropertymap.moc" diff --git a/tests/auto/qml/qquickfolderlistmodel/data/showDotAndDotDot.qml b/tests/auto/qml/qquickfolderlistmodel/data/showDotAndDotDot.qml new file mode 100644 index 0000000000..b65ace2f78 --- /dev/null +++ b/tests/auto/qml/qquickfolderlistmodel/data/showDotAndDotDot.qml @@ -0,0 +1,5 @@ +import Qt.labs.folderlistmodel 1.0 + +FolderListModel { + showDotAndDotDot: false +} diff --git a/tests/auto/qml/qquickfolderlistmodel/tst_qquickfolderlistmodel.cpp b/tests/auto/qml/qquickfolderlistmodel/tst_qquickfolderlistmodel.cpp index a8bb887158..b845faca7d 100644 --- a/tests/auto/qml/qquickfolderlistmodel/tst_qquickfolderlistmodel.cpp +++ b/tests/auto/qml/qquickfolderlistmodel/tst_qquickfolderlistmodel.cpp @@ -73,9 +73,12 @@ private slots: void basicProperties(); void resetFiltering(); void refresh(); -#if defined (Q_OS_WIN) +#if defined (Q_OS_WIN) && !defined (Q_OS_WINCE) + // WinCE does not have drive concept, so lets execute this test only on desktop Windows. void changeDrive(); #endif + void showDotAndDotDot(); + void showDotAndDotDot_data(); private: void checkNoErrors(const QQmlComponent& component); @@ -112,7 +115,7 @@ void tst_qquickfolderlistmodel::basicProperties() QVERIFY(flm != 0); flm->setProperty("folder", dataDirectoryUrl()); - QTRY_COMPARE(flm->property("count").toInt(),4); // wait for refresh + QTRY_COMPARE(flm->property("count").toInt(),5); // wait for refresh QCOMPARE(flm->property("folder").toUrl(), dataDirectoryUrl()); QCOMPARE(flm->property("parentFolder").toUrl(), QUrl::fromLocalFile(QDir(directory()).canonicalPath())); QCOMPARE(flm->property("sortField").toInt(), int(Name)); @@ -168,7 +171,7 @@ void tst_qquickfolderlistmodel::refresh() QVERIFY(flm != 0); flm->setProperty("folder", dataDirectoryUrl()); - QTRY_COMPARE(flm->property("count").toInt(),4); // wait for refresh + QTRY_COMPARE(flm->property("count").toInt(),5); // wait for refresh int count = flm->rowCount(); @@ -181,7 +184,7 @@ void tst_qquickfolderlistmodel::refresh() QTRY_COMPARE(removeEnd, count-1); // wait for refresh } -#if defined (Q_OS_WIN) +#if defined (Q_OS_WIN) && !defined (Q_OS_WINCE) void tst_qquickfolderlistmodel::changeDrive() { QSKIP("QTBUG-26728"); @@ -227,6 +230,49 @@ void tst_qquickfolderlistmodel::changeDrive() } #endif +void tst_qquickfolderlistmodel::showDotAndDotDot() +{ + QFETCH(QUrl, folder); + QFETCH(QUrl, rootFolder); + QFETCH(bool, showDotAndDotDot); + QFETCH(bool, showDot); + QFETCH(bool, showDotDot); + + QQmlComponent component(&engine, testFileUrl("showDotAndDotDot.qml")); + checkNoErrors(component); + + QAbstractListModel *flm = qobject_cast<QAbstractListModel*>(component.create()); + QVERIFY(flm != 0); + + flm->setProperty("folder", folder); + flm->setProperty("rootFolder", rootFolder); + flm->setProperty("showDotAndDotDot", showDotAndDotDot); + + int count = 5; + if (showDot) count++; + if (showDotDot) count++; + QTRY_COMPARE(flm->property("count").toInt(), count); // wait for refresh + + if (showDot) + QCOMPARE(flm->data(flm->index(0),FileNameRole).toString(), QLatin1String(".")); + if (showDotDot) + QCOMPARE(flm->data(flm->index(1),FileNameRole).toString(), QLatin1String("..")); +} + +void tst_qquickfolderlistmodel::showDotAndDotDot_data() +{ + QTest::addColumn<QUrl>("folder"); + QTest::addColumn<QUrl>("rootFolder"); + QTest::addColumn<bool>("showDotAndDotDot"); + QTest::addColumn<bool>("showDot"); + QTest::addColumn<bool>("showDotDot"); + + QTest::newRow("false") << dataDirectoryUrl() << QUrl() << false << false << false; + QTest::newRow("true") << dataDirectoryUrl() << QUrl() << true << true << true; + QTest::newRow("true but root") << dataDirectoryUrl() << dataDirectoryUrl() << true << true << false; + +} + QTEST_MAIN(tst_qquickfolderlistmodel) #include "tst_qquickfolderlistmodel.moc" diff --git a/tests/auto/qml/qquickworkerscript/tst_qquickworkerscript.cpp b/tests/auto/qml/qquickworkerscript/tst_qquickworkerscript.cpp index 9d74e32383..1530ce83e2 100644 --- a/tests/auto/qml/qquickworkerscript/tst_qquickworkerscript.cpp +++ b/tests/auto/qml/qquickworkerscript/tst_qquickworkerscript.cpp @@ -138,7 +138,7 @@ void tst_QQuickWorkerScript::messaging_data() QTest::newRow("variant list") << qVariantFromValue((QVariantList() << "a" << "b" << "c")); QTest::newRow("date time") << qVariantFromValue(QDateTime::currentDateTime()); #ifndef QT_NO_REGEXP - // QtScript's QScriptValue -> QRegExp uses RegExp2 pattern syntax + // Qt Script's QScriptValue -> QRegExp uses RegExp2 pattern syntax QTest::newRow("regexp") << qVariantFromValue(QRegExp("^\\d\\d?$", Qt::CaseInsensitive, QRegExp::RegExp2)); #endif } diff --git a/tests/auto/qmldevtools/compile/compile.pro b/tests/auto/qmldevtools/compile/compile.pro index 1c65daf909..0ed113a031 100644 --- a/tests/auto/qmldevtools/compile/compile.pro +++ b/tests/auto/qmldevtools/compile/compile.pro @@ -1,9 +1,12 @@ option(host_build) TARGET = tst_compile -force_bootstrap: \ +force_bootstrap { QT = bootstrap-private -else: \ + !build_pass: CONFIG += release +} else { QT = core + !build_pass:contains(QT_CONFIG, build_all): CONFIG += release +} QT += qmldevtools-private macx:CONFIG -= app_bundle diff --git a/tests/auto/qmltest/fontloader/tst_fontloader.qml b/tests/auto/qmltest/fontloader/tst_fontloader.qml index 4d79a170f3..33307a3702 100644 --- a/tests/auto/qmltest/fontloader/tst_fontloader.qml +++ b/tests/auto/qmltest/fontloader/tst_fontloader.qml @@ -38,7 +38,7 @@ ** ****************************************************************************/ -import QtQuick 2.0 +import QtQuick 2.1 import QtTest 1.0 Item { @@ -63,34 +63,37 @@ Item { name: "FontLoader" function test_fontloading() { + if (Qt.platform.os === "mac") + skip("Skipped for QTBUG-25306") + compare(fontloader.status, FontLoader.Null) compare(testinput.font.family, "") fontloader.source = "tarzeau_ocr_a.ttf"; - tryCompare(fontloader.status, FontLoader.Loading) - tryCompare(fontloader.status, FontLoader.Ready) + tryCompare(fontloader, 'status', FontLoader.Ready) compare(testinput.font.family, "OCRA") fontloader.source = "dummy.ttf"; - tryCompare(fontloader.status, FontLoader.Error) + tryCompare(fontloader, 'status', FontLoader.Error) compare(testinput.font.family, "") fontloader.source = ""; fontloader.name = "Courier"; - tryCompare(fontloader.status, FontLoader.Ready) + tryCompare(fontloader, 'status', FontLoader.Ready) compare(testinput.font.family, "Courier") } function test_fontswitching() { + if (Qt.platform.os === "mac") + skip("Skipped for QTBUG-25306") + compare(fontswitch.status, FontLoader.Null) fontswitch.source = "tarzeau_ocr_a.ttf"; - tryCompare(fontswitch.status, FontLoader.Loading) - tryCompare(fontswitch.status, FontLoader.Ready) - tryCompare(fontswitch.name, "OCRA") + tryCompare(fontswitch, 'status', FontLoader.Ready) + compare(fontswitch.name, "OCRA") fontswitch.source = ""; fontswitch.name = "Courier"; - tryCompare(fontswitch.status, FontLoader.Ready) - tryCompare(fontswitch.name, "Courier") + tryCompare(fontswitch, 'status', FontLoader.Ready) + compare(fontswitch.name, "Courier") fontswitch.source = "tarzeau_ocr_a.ttf"; - tryCompare(fontswitch.status, FontLoader.Loading) - tryCompare(fontswitch.status, FontLoader.Ready) + tryCompare(fontswitch, 'status', FontLoader.Ready) compare(fontswitch.name, "OCRA") } } diff --git a/tests/auto/qmltest/listmodel/tst_listmodel.qml b/tests/auto/qmltest/listmodel/tst_listmodel.qml index a975691462..603993a092 100644 --- a/tests/auto/qmltest/listmodel/tst_listmodel.qml +++ b/tests/auto/qmltest/listmodel/tst_listmodel.qml @@ -95,28 +95,28 @@ Item { } function test_altermodeled() { - tryCompare(altermodel.count, 2) + tryCompare(altermodel, 'count', 2) compare(altermodel.get(0).name, "AlterModelElement0") compare(altermodel.get(1).name, "AlterModelElement1") altermodel.append({"name":"AlterModelElement2"}) - tryCompare(altermodel.count, 3) + tryCompare(altermodel, 'count', 3) compare(altermodel.get(0).name, "AlterModelElement0") compare(altermodel.get(1).name, "AlterModelElement1") compare(altermodel.get(2).name, "AlterModelElement2") altermodel.insert(2,{"name":"AlterModelElement1.5"}) - tryCompare(altermodel.count, 4) + tryCompare(altermodel, 'count', 4) compare(altermodel.get(0).name, "AlterModelElement0") compare(altermodel.get(1).name, "AlterModelElement1") compare(altermodel.get(2).name, "AlterModelElement1.5") compare(altermodel.get(3).name, "AlterModelElement2") - tryCompare(altermodel.count, 4) + tryCompare(altermodel, 'count', 4) altermodel.move(2,1,1); compare(altermodel.get(0).name, "AlterModelElement0") compare(altermodel.get(1).name, "AlterModelElement1.5") compare(altermodel.get(2).name, "AlterModelElement1") compare(altermodel.get(3).name, "AlterModelElement2") altermodel.remove(1,2) - tryCompare(altermodel.count, 2) + tryCompare(altermodel, 'count', 2) compare(altermodel.get(0).name, "AlterModelElement0") compare(altermodel.get(1).name, "AlterModelElement2") altermodel.set(1,{"name":"AlterModelElement1"}) @@ -125,7 +125,7 @@ Item { altermodel.setProperty(0, "name", "AlteredProperty") compare(altermodel.get(0).name, "AlteredProperty") altermodel.clear() - tryCompare(altermodel.count, 0) + tryCompare(altermodel, 'count', 0) compare(altermodel.get(0), undefined) } } diff --git a/tests/auto/qmltest/listview/data/asynclistviewloader.qml b/tests/auto/qmltest/listview/data/asynclistviewloader.qml new file mode 100644 index 0000000000..f7a55ff055 --- /dev/null +++ b/tests/auto/qmltest/listview/data/asynclistviewloader.qml @@ -0,0 +1,79 @@ +/**************************************************************************** +** +** Copyright (C) 2013 Digia Plc and/or its subsidiary(-ies). +** Contact: http://www.qt-project.org/legal +** +** This file is part of the test suite of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:BSD$ +** You may use this file under the terms of the BSD license as follows: +** +** "Redistribution and use in source and binary forms, with or without +** modification, are permitted provided that the following conditions are +** met: +** * Redistributions of source code must retain the above copyright +** notice, this list of conditions and the following disclaimer. +** * Redistributions in binary form must reproduce the above copyright +** notice, this list of conditions and the following disclaimer in +** the documentation and/or other materials provided with the +** distribution. +** * Neither the name of Digia Plc and its Subsidiary(-ies) nor the names +** of its contributors may be used to endorse or promote products derived +** from this software without specific prior written permission. +** +** +** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE." +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +import QtQuick 2.0 + +ListView { + id: root + width: 360 + height: 360 + cacheBuffer: 100000 + model: ListModel { + ListElement { component: "asyncloadercurrentindex.qml" } + ListElement { component: "asyncloadercurrentindex.qml" } + ListElement { component: "asyncloadercurrentindex.qml" } + ListElement { component: "asyncloadercurrentindex.qml" } + ListElement { component: "asyncloadercurrentindex.qml" } + ListElement { component: "asyncloadercurrentindex.qml" } + ListElement { component: "asyncloadercurrentindex.qml" } + ListElement { component: "asyncloadercurrentindex.qml" } + ListElement { component: "asyncloadercurrentindex.qml" } + ListElement { component: "asyncloadercurrentindex.qml" } + ListElement { component: "asyncloadercurrentindex.qml" } + ListElement { component: "asyncloadercurrentindex.qml" } + ListElement { component: "asyncloadercurrentindex.qml" } + ListElement { component: "asyncloadercurrentindex.qml" } + ListElement { component: "asyncloadercurrentindex.qml" } + ListElement { component: "asyncloadercurrentindex.qml" } + } + + interactive: false + orientation: ListView.Horizontal + + currentIndex: 0 + + delegate: Loader { + width: root.width + height: root.height + + source: component + asynchronous: true + } +} diff --git a/tests/auto/qmltest/listview/data/asyncloadercurrentindex.qml b/tests/auto/qmltest/listview/data/asyncloadercurrentindex.qml new file mode 100644 index 0000000000..a721f85eb9 --- /dev/null +++ b/tests/auto/qmltest/listview/data/asyncloadercurrentindex.qml @@ -0,0 +1,64 @@ +/**************************************************************************** +** +** Copyright (C) 2013 Digia Plc and/or its subsidiary(-ies). +** Contact: http://www.qt-project.org/legal +** +** This file is part of the test suite of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:BSD$ +** You may use this file under the terms of the BSD license as follows: +** +** "Redistribution and use in source and binary forms, with or without +** modification, are permitted provided that the following conditions are +** met: +** * Redistributions of source code must retain the above copyright +** notice, this list of conditions and the following disclaimer. +** * Redistributions in binary form must reproduce the above copyright +** notice, this list of conditions and the following disclaimer in +** the documentation and/or other materials provided with the +** distribution. +** * Neither the name of Digia Plc and its Subsidiary(-ies) nor the names +** of its contributors may be used to endorse or promote products derived +** from this software without specific prior written permission. +** +** +** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE." +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +import QtQuick 2.0 + +Rectangle { + color: "black" + + Rectangle { + color: "red" + + height: 150 + width: 150 + + anchors { + horizontalCenter: parent.horizontalCenter + verticalCenter: parent.verticalCenter + } + + NumberAnimation on rotation { + from: 0 + to: 360 + duration: 5000 + loops: Animation.Infinite + } + } +} diff --git a/tests/auto/qmltest/listview/tst_listview.qml b/tests/auto/qmltest/listview/tst_listview.qml index cbace624c3..0589e7c46b 100644 --- a/tests/auto/qmltest/listview/tst_listview.qml +++ b/tests/auto/qmltest/listview/tst_listview.qml @@ -38,7 +38,7 @@ ** ****************************************************************************/ -import QtQuick 2.0 +import QtQuick 2.1 import QtTest 1.0 Item { @@ -53,6 +53,7 @@ Item { ListView { id: viewmanyitems model: manyitems + delegate: Text { text: model.name } } ListView { @@ -67,14 +68,66 @@ Item { delegate: Text { text: model.name } } + ListView { + id: asyncLoaderCurrentIndexListView + width: 360 + height: 360 + model: asyncLoaderCurrentIndexListModel + + currentIndex: 0 + + delegate: Loader { + width: asyncLoaderCurrentIndexListView.width + height: asyncLoaderCurrentIndexListView.height + + source: component + asynchronous: true + } + } + + ListView { + id: asyncListViewLoaderView + width: 360 + height: 360 + model: asyncListViewLoaderModel + + currentIndex: 0 + + delegate: Loader { + width: asyncListViewLoaderView.width + height: asyncListViewLoaderView.height + + source: component + asynchronous: true + } + } + ListModel { id: emptymodel } ListModel { id: manyitems } ListModel { id: firstmodel; ListElement { name: "FirstModelElement0" } } ListModel { id: secondmodel; ListElement { name: "SecondModelElement0" } ListElement { name: "SecondModelElement1" } } ListModel { id: altermodel; ListElement { name: "AlterModelElement0" } ListElement { name: "AlterModelElement1" } } + ListModel { + id: asyncLoaderCurrentIndexListModel + ListElement { component: "data/asyncloadercurrentindex.qml" } + ListElement { component: "data/asyncloadercurrentindex.qml" } + ListElement { component: "data/asyncloadercurrentindex.qml" } + ListElement { component: "data/asyncloadercurrentindex.qml" } + ListElement { component: "data/asyncloadercurrentindex.qml" } + ListElement { component: "data/asyncloadercurrentindex.qml" } + } + ListModel { + id: asyncListViewLoaderModel + ListElement { component: "data/asynclistviewloader.qml" } + ListElement { component: "data/asynclistviewloader.qml" } + ListElement { component: "data/asynclistviewloader.qml" } + ListElement { component: "data/asynclistviewloader.qml" } + ListElement { component: "data/asynclistviewloader.qml" } + } TestCase { name: "ListView" + when: windowShown function test_empty() { compare(emptylist.count, 0) @@ -107,15 +160,16 @@ Item { manyitems.append({"name":"Item"+i}) } compare(manyitems.count, row.numitems) - tryCompare(viewmanyitems.count, row.numitems) + tryCompare(viewmanyitems, 'count', row.numitems) + } function test_modelchange() { - tryCompare(modelchange.count, 1) + tryCompare(modelchange, 'count', 1) modelchange.currentIndex = 0; compare(modelchange.currentItem.text, "FirstModelElement0") modelchange.model = secondmodel; - tryCompare(modelchange.count, 2) + tryCompare(modelchange, 'count', 2) modelchange.currentIndex = 0; compare(modelchange.currentItem.text, "SecondModelElement0") modelchange.currentIndex = 1; @@ -123,13 +177,13 @@ Item { } function test_modelaltered() { - tryCompare(modelalter.count, 2) + tryCompare(modelalter, 'count', 2) modelalter.currentIndex = 0; compare(modelalter.currentItem.text, "AlterModelElement0") modelalter.currentIndex = 1; compare(modelalter.currentItem.text, "AlterModelElement1") altermodel.append({"name":"AlterModelElement2"}) - tryCompare(modelalter.count, 3) + tryCompare(modelalter, 'count', 3) modelalter.currentIndex = 0; compare(modelalter.currentItem.text, "AlterModelElement0") modelalter.currentIndex = 1; @@ -137,7 +191,7 @@ Item { modelalter.currentIndex = 2; compare(modelalter.currentItem.text, "AlterModelElement2") altermodel.insert(2,{"name":"AlterModelElement1.5"}) - tryCompare(modelalter.count, 4) + tryCompare(modelalter, 'count', 4) modelalter.currentIndex = 0; compare(modelalter.currentItem.text, "AlterModelElement0") modelalter.currentIndex = 1; @@ -147,7 +201,7 @@ Item { modelalter.currentIndex = 3; compare(modelalter.currentItem.text, "AlterModelElement2") altermodel.move(2,1,1); - tryCompare(modelalter.count, 4) + tryCompare(modelalter, 'count', 4) modelalter.currentIndex = 0; compare(modelalter.currentItem.text, "AlterModelElement0") modelalter.currentIndex = 1; @@ -157,7 +211,7 @@ Item { modelalter.currentIndex = 3; compare(modelalter.currentItem.text, "AlterModelElement2") altermodel.remove(1,2) - tryCompare(modelalter.count, 2) + tryCompare(modelalter, 'count', 2) modelalter.currentIndex = 0; compare(modelalter.currentItem.text, "AlterModelElement0") modelalter.currentIndex = 1; @@ -168,8 +222,32 @@ Item { modelalter.currentIndex = 1; compare(modelalter.currentItem.text, "AlterModelElement1") altermodel.clear() - tryCompare(modelalter.count, 0) + modelalter.forceLayout() + tryCompare(modelalter, 'count', 0) compare(modelalter.currentItem, null) } + + function test_asyncLoaderCurrentIndexChange() { + for (var i = 0; i < 500; i++) { + asyncLoaderCurrentIndexListView.currentIndex = 0; + asyncLoaderCurrentIndexListView.currentIndex = 1; + asyncLoaderCurrentIndexListView.currentIndex = 2; + asyncLoaderCurrentIndexListView.currentIndex = 3; + asyncLoaderCurrentIndexListView.currentIndex = 4; + asyncLoaderCurrentIndexListView.currentIndex = 5; + } + wait(1000) + } + + function test_asyncListViewLoader() { + for (var i = 0; i < 50; i++) { + wait(10); + asyncListViewLoaderView.currentIndex = 0; + asyncListViewLoaderView.currentIndex = 1; + asyncListViewLoaderView.currentIndex = 2; + asyncListViewLoaderView.currentIndex = 3; + asyncListViewLoaderView.currentIndex = 4; + } + } } } diff --git a/tests/auto/qmltest/qmltest.pro b/tests/auto/qmltest/qmltest.pro index 0a7967654c..b1c29226e6 100644 --- a/tests/auto/qmltest/qmltest.pro +++ b/tests/auto/qmltest/qmltest.pro @@ -9,5 +9,4 @@ importFiles.files = borderimage buttonclick createbenchmark events qqmlbindi importFiles.path = . DEPLOYMENT += importFiles -mac:CONFIG+=insignificant_test # QTBUG-25306 DEFINES += QT_DISABLE_DEPRECATED_BEFORE=0 diff --git a/tests/auto/qmltest/selftests/tst_destroy.qml b/tests/auto/qmltest/selftests/tst_destroy.qml new file mode 100644 index 0000000000..b2a473dfca --- /dev/null +++ b/tests/auto/qmltest/selftests/tst_destroy.qml @@ -0,0 +1,62 @@ +/**************************************************************************** +** +** Copyright (C) 2013 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.1 +import QtTest 1.0 + +TestCase { + id: testCase + width: 100 + height: 100 + name: "SelfTests_Destroy" + + function test_a_QTBUG_30523() { + compare(testCase.children.length, 0) + var tmp = Qt.createQmlObject('import QtQuick 2.1; Rectangle {width: 20; height: 20;}', testCase, '') + compare(testCase.children.length, 1) + tmp.destroy() + } + + function test_b_QTBUG_30523() { + // The object created in test above should be deleted + compare(testCase.children.length, 0) + } +} diff --git a/tests/auto/qmltest/text/tst_text.qml b/tests/auto/qmltest/text/tst_text.qml index 87e9501ccd..b1d743f630 100644 --- a/tests/auto/qmltest/text/tst_text.qml +++ b/tests/auto/qmltest/text/tst_text.qml @@ -78,6 +78,13 @@ Item { font.pixelSize: 18 } + Text { + id: txtlines + property string styledtextvalue: "Line 1<br>Line 2<br>Line 3" + text: "Line 1\nLine 2\nLine 3" + textFormat: Text.PlainText + } + TestCase { name: "Text" @@ -116,6 +123,16 @@ Item { txtlinecount.width = 50; compare(txtlinecount.lineCount, 3) } + function test_linecounts() { + compare(txtlines.lineCount, 3) + txtlines.text = txtlines.styledtextvalue; + compare(txtlines.text, "Line 1<br>Line 2<br>Line 3") + tryCompare(txtlines, 'lineCount', 1) + txtlines.textFormat = Text.StyledText; + tryCompare(txtlines, 'lineCount', 3) + txtlines.textFormat = Text.RichText; + tryCompare(txtlines, 'lineCount', 3) + } } } diff --git a/tests/auto/qmltest/textedit/tst_textedit.qml b/tests/auto/qmltest/textedit/tst_textedit.qml index edfa127c59..eb53eaa604 100644 --- a/tests/auto/qmltest/textedit/tst_textedit.qml +++ b/tests/auto/qmltest/textedit/tst_textedit.qml @@ -91,7 +91,7 @@ Item { id: txtlines property string styledtextvalue: "Line 1<br>Line 2<br>Line 3" text: "Line 1\nLine 2\nLine 3" - textFormat: Text.PlainText + textFormat: TextEdit.PlainText } TestCase { @@ -179,11 +179,9 @@ Item { compare(txtlines.lineCount, 3) txtlines.text = txtlines.styledtextvalue; compare(txtlines.text, "Line 1<br>Line 2<br>Line 3") - tryCompare(txtlines.lineCount, 1) - txtlines.textFormat = Text.StyledText; - tryCompare(txtlines.lineCount, 3) - txtlines.textFormat = Text.RichText; - tryCompare(txtlines.lineCount, 3) + tryCompare(txtlines, 'lineCount', 1) + txtlines.textFormat = TextEdit.RichText; + tryCompare(txtlines, 'lineCount', 3) } } } diff --git a/tests/auto/quick/qquickanimatedimage/tst_qquickanimatedimage.cpp b/tests/auto/quick/qquickanimatedimage/tst_qquickanimatedimage.cpp index 201287b2a8..0377eaa71d 100644 --- a/tests/auto/quick/qquickanimatedimage/tst_qquickanimatedimage.cpp +++ b/tests/auto/quick/qquickanimatedimage/tst_qquickanimatedimage.cpp @@ -201,26 +201,28 @@ void tst_qquickanimatedimage::mirror_notRunning() QFETCH(QUrl, fileUrl); QQuickView window; + window.setSource(fileUrl); window.show(); + QTRY_VERIFY(window.isExposed()); - window.setSource(fileUrl); QQuickAnimatedImage *anim = qobject_cast<QQuickAnimatedImage *>(window.rootObject()); QVERIFY(anim); int width = anim->property("width").toInt(); - QPixmap screenshot = QPixmap::fromImage(window.grabWindow()); + QImage screenshot = window.grabWindow(); QTransform transform; transform.translate(width, 0).scale(-1, 1.0); - QPixmap expected = screenshot.transformed(transform); + QImage expected = screenshot.transformed(transform); int frame = anim->currentFrame(); bool playing = anim->isPlaying(); bool paused = anim->isPlaying(); anim->setProperty("mirror", true); - screenshot = QPixmap::fromImage(window.grabWindow()); + screenshot = window.grabWindow(); + screenshot.save("screen.png"); QCOMPARE(screenshot, expected); // mirroring should not change the current frame or playing status diff --git a/tests/auto/quick/qquickcanvasitem/data/tst_context.qml b/tests/auto/quick/qquickcanvasitem/data/tst_context.qml index b72e755ed9..ad44f6d28e 100644 --- a/tests/auto/quick/qquickcanvasitem/data/tst_context.qml +++ b/tests/auto/quick/qquickcanvasitem/data/tst_context.qml @@ -70,4 +70,20 @@ Canvas { compare(canvas.contextInPaint, canvas.getContext("2d")); } } + + TestCase { + name: "ContextFontValidation" + when: canvas.available + + function test_pixelSize() { + wait(100); + compare(contextSpy.count, 1); + + var ctx = canvas.getContext("2d"); + compare(ctx.font, "sans-serif,-1,10,5,50,0,0,0,0,0"); + + ctx.font = "80.1px sans-serif"; + compare(ctx.font, "sans-serif,-1,80,5,50,0,0,0,0,0"); + } + } } diff --git a/tests/auto/quick/qquickcanvasitem/data/tst_image.qml b/tests/auto/quick/qquickcanvasitem/data/tst_image.qml index 72b6dcdb00..ca95f2aec1 100644 --- a/tests/auto/quick/qquickcanvasitem/data/tst_image.qml +++ b/tests/auto/quick/qquickcanvasitem/data/tst_image.qml @@ -216,6 +216,17 @@ CanvasTestCase { } + property url green: 'green.png' + + function test_url(row) { + var canvas = createCanvasObject(row); + var ctx = canvas.getContext('2d'); + + canvas.loadImage(testCase.green); + ctx.drawImage(testCase.green, 0, 0); + comparePixel(ctx, 0,0, 0,255,0,255,2); + } + function test_composite(row) { var canvas = createCanvasObject(row); var ctx = canvas.getContext('2d'); diff --git a/tests/auto/quick/qquickgridview/tst_qquickgridview.cpp b/tests/auto/quick/qquickgridview/tst_qquickgridview.cpp index 0c9788ab8e..d0ffba9435 100644 --- a/tests/auto/quick/qquickgridview/tst_qquickgridview.cpp +++ b/tests/auto/quick/qquickgridview/tst_qquickgridview.cpp @@ -532,6 +532,7 @@ void tst_QQuickGridView::inserted_defaultLayout(QQuickGridView::Flow flow, for (int i=0; i<insertCount; i++) newData << qMakePair(QString("value %1").arg(i), QString::number(i)); model.insertItems(insertIndex, newData); + gridview->forceLayout(); QTRY_COMPARE(gridview->property("count").toInt(), model.count()); // check visibleItems.first() is in correct position @@ -728,6 +729,7 @@ void tst_QQuickGridView::insertBeforeVisible() for (int i=0; i<insertCount; i++) newData << qMakePair(QString("value %1").arg(i), QString::number(i)); model.insertItems(insertIndex, newData); + gridview->forceLayout(); QTRY_COMPARE(gridview->property("count").toInt(), model.count()); // now, moving to the top of the view should position the inserted items correctly @@ -958,6 +960,7 @@ void tst_QQuickGridView::removed_defaultLayout(QQuickGridView::Flow flow, QTRY_COMPARE(QQuickItemPrivate::get(gridview)->polishScheduled, false); model.removeItems(removeIndex, removeCount); + gridview->forceLayout(); QTRY_COMPARE(gridview->property("count").toInt(), model.count()); QString firstName; @@ -1245,6 +1248,7 @@ void tst_QQuickGridView::clear() QTRY_COMPARE(QQuickItemPrivate::get(gridview)->polishScheduled, false); model.clear(); + gridview->forceLayout(); QVERIFY(gridview->count() == 0); QVERIFY(gridview->currentItem() == 0); @@ -1254,6 +1258,7 @@ void tst_QQuickGridView::clear() // confirm sanity when adding an item to cleared list model.addItem("New", "1"); + gridview->forceLayout(); QTRY_COMPARE(gridview->count(), 1); QVERIFY(gridview->currentItem() != 0); QVERIFY(gridview->currentIndex() == 0); @@ -3483,6 +3488,7 @@ void tst_QQuickGridView::extents() QCOMPARE(gridview->originY(), origin_empty.y()); for (int i=0; i<30; i++) model.addItem("Item" + QString::number(i), ""); + gridview->forceLayout(); QTRY_COMPARE(gridview->count(), model.count()); QCOMPARE(gridview->originX(), origin_nonEmpty.x()); QCOMPARE(gridview->originY(), origin_nonEmpty.y()); @@ -3942,9 +3948,9 @@ void tst_QQuickGridView::onAdd() ctxt->setContextProperty("delegateHeight", delegateHeight); window->setSource(testFileUrl("attachedSignals.qml")); - QObject *object = window->rootObject(); - object->setProperty("width", window->width()); - object->setProperty("height", window->height()); + QQuickGridView *gridview = qobject_cast<QQuickGridView*>(window->rootObject()); + gridview->setProperty("width", window->width()); + gridview->setProperty("height", window->height()); qApp->processEvents(); QList<QPair<QString, QString> > items; @@ -3952,10 +3958,11 @@ void tst_QQuickGridView::onAdd() items << qMakePair(QString("value %1").arg(i), QString::number(i)); model.addItems(items); - QTRY_COMPARE(model.count(), qobject_cast<QQuickGridView*>(window->rootObject())->count()); + gridview->forceLayout(); + QTRY_COMPARE(model.count(), gridview->count()); qApp->processEvents(); - QVariantList result = object->property("addedDelegates").toList(); + QVariantList result = gridview->property("addedDelegates").toList(); QTRY_COMPARE(result.count(), items.count()); for (int i=0; i<items.count(); i++) QCOMPARE(result[i].toString(), items[i].first); @@ -3999,11 +4006,12 @@ void tst_QQuickGridView::onRemove() ctxt->setContextProperty("delegateWidth", delegateWidth); ctxt->setContextProperty("delegateHeight", delegateHeight); window->setSource(testFileUrl("attachedSignals.qml")); - QObject *object = window->rootObject(); + QQuickGridView *gridview = qobject_cast<QQuickGridView*>(window->rootObject()); model.removeItems(indexToRemove, removeCount); - QTRY_COMPARE(model.count(), qobject_cast<QQuickGridView*>(window->rootObject())->count()); - QCOMPARE(object->property("removedDelegateCount"), QVariant(removeCount)); + gridview->forceLayout(); + QTRY_COMPARE(model.count(), gridview->count()); + QCOMPARE(gridview->property("removedDelegateCount"), QVariant(removeCount)); releaseView(window); } @@ -4151,6 +4159,7 @@ void tst_QQuickGridView::margins() gridview->setContentX(-400); QTRY_COMPARE(QQuickItemPrivate::get(gridview)->polishScheduled, false); model.removeItems(0, 4); + gridview->forceLayout(); QTRY_COMPARE(model.count(), gridview->count()); gridview->setContentX(-240+50); gridview->returnToBounds(); @@ -4458,6 +4467,7 @@ void tst_QQuickGridView::unaligned() // removing model.removeItems(7, 10); + gridview->forceLayout(); QTRY_COMPARE(model.count(), gridview->count()); for (int i = 0; i < 18; ++i) { QQuickItem *item = 0; @@ -4663,6 +4673,7 @@ void tst_QQuickGridView::addTransitions() // start animation if (!newData.isEmpty()) { model.insertItems(insertionIndex, newData); + gridview->forceLayout(); QTRY_COMPARE(model.count(), gridview->count()); } @@ -4866,6 +4877,7 @@ void tst_QQuickGridView::moveTransitions() // start animation model.moveItems(moveFrom, moveTo, moveCount); + gridview->forceLayout(); QTRY_COMPARE(gridview->property("targetTransitionsDone").toInt(), expectedTargetData.count()); QTRY_COMPARE(gridview->property("displaceTransitionsDone").toInt(), @@ -5114,6 +5126,7 @@ void tst_QQuickGridView::removeTransitions() // start animation model.removeItems(removalIndex, removalCount); + gridview->forceLayout(); QTRY_COMPARE(model.count(), gridview->count()); if (shouldAnimateTargets || expectedDisplacedIndexes.isValid()) { @@ -5327,6 +5340,7 @@ void tst_QQuickGridView::displacedTransitions() case ListChange::Polish: break; } + gridview->forceLayout(); QVariantList resultTargetIndexes = gridview->property("displacedTargetIndexes").toList(); QVariantList resultTargetItems = gridview->property("displacedTargetItems").toList(); @@ -5534,6 +5548,7 @@ void tst_QQuickGridView::multipleTransitions() for (int j=changes[i].index; j<changes[i].index + changes[i].count; ++j) targetItems << qMakePair(QString("new item %1").arg(j), QString::number(j)); model.insertItems(changes[i].index, targetItems); + gridview->forceLayout(); QTRY_COMPARE(model.count(), gridview->count()); if (i == changes.count() - 1) { QTRY_VERIFY(!gridview->property("runningAddTargets").toBool()); @@ -5545,6 +5560,7 @@ void tst_QQuickGridView::multipleTransitions() } case ListChange::Removed: model.removeItems(changes[i].index, changes[i].count); + gridview->forceLayout(); QTRY_COMPARE(model.count(), gridview->count()); if (i == changes.count() - 1) { QTRY_VERIFY(!gridview->property("runningRemoveTargets").toBool()); @@ -5555,6 +5571,7 @@ void tst_QQuickGridView::multipleTransitions() break; case ListChange::Moved: model.moveItems(changes[i].index, changes[i].to, changes[i].count); + gridview->forceLayout(); QTRY_COMPARE(QQuickItemPrivate::get(gridview)->polishScheduled, false); if (i == changes.count() - 1) { QTRY_VERIFY(!gridview->property("runningMoveTargets").toBool()); @@ -5566,16 +5583,17 @@ void tst_QQuickGridView::multipleTransitions() case ListChange::SetCurrent: gridview->setCurrentIndex(changes[i].index); QTRY_COMPARE(QQuickItemPrivate::get(gridview)->polishScheduled, false); + gridview->forceLayout(); break; case ListChange::SetContentY: gridview->setContentY(changes[i].pos); QTRY_COMPARE(QQuickItemPrivate::get(gridview)->polishScheduled, false); + gridview->forceLayout(); break; case ListChange::Polish: break; } } - QCOMPARE(gridview->count(), model.count()); QList<QQuickItem*> items = findItems<QQuickItem>(contentItem, "wrapper"); int firstVisibleIndex = -1; @@ -5586,6 +5604,7 @@ void tst_QQuickGridView::multipleTransitions() break; } } + QTRY_COMPARE(gridview->count(), model.count()); QVERIFY2(firstVisibleIndex >= 0, QTest::toString(firstVisibleIndex)); // verify all items moved to the correct final positions diff --git a/tests/auto/quick/qquickimageprovider/tst_qquickimageprovider.cpp b/tests/auto/quick/qquickimageprovider/tst_qquickimageprovider.cpp index a790c7b9de..3eea3c955c 100644 --- a/tests/auto/quick/qquickimageprovider/tst_qquickimageprovider.cpp +++ b/tests/auto/quick/qquickimageprovider/tst_qquickimageprovider.cpp @@ -71,6 +71,9 @@ private slots: void removeProvider_data(); void removeProvider(); + void imageProviderId_data(); + void imageProviderId(); + void threadTest(); private: @@ -372,6 +375,31 @@ void tst_qquickimageprovider::removeProvider() delete obj; } +void tst_qquickimageprovider::imageProviderId_data() +{ + QTest::addColumn<QString>("providerId"); + + QTest::newRow("lowercase") << QStringLiteral("imageprovider"); + QTest::newRow("CamelCase") << QStringLiteral("ImageProvider"); + QTest::newRow("UPPERCASE") << QStringLiteral("IMAGEPROVIDER"); +} + +void tst_qquickimageprovider::imageProviderId() +{ + QFETCH(QString, providerId); + + QQmlEngine engine; + + bool deleteWatch = false; + TestQImageProvider *provider = new TestQImageProvider(&deleteWatch); + + engine.addImageProvider(providerId, provider); + QVERIFY(engine.imageProvider(providerId) != 0); + + engine.removeImageProvider(providerId); + QVERIFY(deleteWatch); +} + class TestThreadProvider : public QQuickImageProvider { public: diff --git a/tests/auto/quick/qquickitem2/data/activeFocusOnTab6.qml b/tests/auto/quick/qquickitem2/data/activeFocusOnTab6.qml new file mode 100644 index 0000000000..22b4d249f0 --- /dev/null +++ b/tests/auto/quick/qquickitem2/data/activeFocusOnTab6.qml @@ -0,0 +1,144 @@ +import QtQuick 2.1 + +Item { + id: main + objectName: "main" + width: 800 + height: 600 + focus: true + Component.onCompleted: button12.focus = true + Item { + id: sub1 + objectName: "sub1" + width: 230 + height: 600 + anchors.top: parent.top + anchors.left: parent.left + Item { + id: button11 + objectName: "button11" + width: 100 + height: 50 + activeFocusOnTab: true + Accessible.role: Accessible.Table + Rectangle { + anchors.fill: parent + color: parent.activeFocus ? "red" : "black" + } + + anchors.top: parent.top + anchors.topMargin: 100 + } + Item { + id: button12 + objectName: "button12" + activeFocusOnTab: true + Accessible.role: Accessible.List + Rectangle { + anchors.fill: parent + color: parent.activeFocus ? "red" : "black" + } + width: 100 + height: 50 + + anchors.top: button11.bottom + anchors.bottomMargin: 100 + } + Item { + id: button13 + objectName: "button13" + enabled: false + activeFocusOnTab: true + Accessible.role: Accessible.Table + Rectangle { + anchors.fill: parent + color: parent.activeFocus ? "red" : "black" + } + width: 100 + height: 50 + + anchors.top: button12.bottom + anchors.bottomMargin: 100 + } + Item { + id: button14 + objectName: "button14" + visible: false + activeFocusOnTab: true + Accessible.role: Accessible.List + Rectangle { + anchors.fill: parent + color: parent.activeFocus ? "red" : "black" + } + width: 100 + height: 50 + + anchors.top: button12.bottom + anchors.bottomMargin: 100 + } + } + Item { + id: sub2 + objectName: "sub2" + activeFocusOnTab: true + Accessible.role: Accessible.Row + width: 230 + height: 600 + anchors.top: parent.top + anchors.left: sub1.right + Item { + id: button21 + objectName: "button21" + width: 100 + height: 50 + activeFocusOnTab: true + Accessible.role: Accessible.PushButton + Rectangle { + anchors.fill: parent + color: parent.activeFocus ? "red" : "black" + } + + anchors.top: parent.top + anchors.topMargin: 100 + } + Item { + id: button22 + objectName: "button22" + width: 100 + height: 50 + activeFocusOnTab: true + Accessible.role: Accessible.RadioButton + Rectangle { + anchors.fill: parent + color: parent.activeFocus ? "red" : "black" + } + + anchors.top: button21.bottom + anchors.bottomMargin: 100 + } + } + Item { + id: sub3 + objectName: "sub3" + width: 230 + height: 600 + anchors.top: parent.top + anchors.left: sub2.right + TextEdit { + id: edit + objectName: "edit" + width: 230 + height: 400 + readOnly: false + activeFocusOnTab: true + Accessible.role: Accessible.EditableText + wrapMode: TextEdit.Wrap + textFormat: TextEdit.RichText + + text: "aaa\n" + +"bbb\n" + +"ccc\n" + +"ddd\n" + } + } +} diff --git a/tests/auto/quick/qquickitem2/data/activeFocusOnTab7.qml b/tests/auto/quick/qquickitem2/data/activeFocusOnTab7.qml new file mode 100644 index 0000000000..e81d9be950 --- /dev/null +++ b/tests/auto/quick/qquickitem2/data/activeFocusOnTab7.qml @@ -0,0 +1,36 @@ +import QtQuick 2.1 + +Item { + id: main + objectName: "main" + width: 300 + height: 300 + Item { + id: button1 + objectName: "button1" + width: 300 + height: 150 + activeFocusOnTab: true + Accessible.role: Accessible.Button + Rectangle { + anchors.fill: parent + color: parent.activeFocus ? "red" : "black" + } + anchors.top: parent.top + anchors.left: parent.left + } + Item { + id: button2 + objectName: "button2" + width: 300 + height: 150 + activeFocusOnTab: true + Accessible.role: Accessible.Button + Rectangle { + anchors.fill: parent + color: parent.activeFocus ? "red" : "black" + } + anchors.bottom: parent.bottom + anchors.left: parent.left + } +} diff --git a/tests/auto/quick/qquickitem2/data/activeFocusOnTab8.qml b/tests/auto/quick/qquickitem2/data/activeFocusOnTab8.qml new file mode 100644 index 0000000000..641a39c1fa --- /dev/null +++ b/tests/auto/quick/qquickitem2/data/activeFocusOnTab8.qml @@ -0,0 +1,36 @@ +import QtQuick 2.1 + +Item { + id: main + objectName: "main" + width: 300 + height: 300 + Item { + id: button1 + objectName: "button1" + width: 300 + height: 150 + activeFocusOnTab: true + Accessible.role: Accessible.Table + Rectangle { + anchors.fill: parent + color: parent.activeFocus ? "red" : "black" + } + anchors.top: parent.top + anchors.left: parent.left + } + Item { + id: button2 + objectName: "button2" + width: 300 + height: 150 + activeFocusOnTab: true + Accessible.role: Accessible.Table + Rectangle { + anchors.fill: parent + color: parent.activeFocus ? "red" : "black" + } + anchors.bottom: parent.bottom + anchors.left: parent.left + } +} diff --git a/tests/auto/quick/qquickitem2/data/resourcesProperty.qml b/tests/auto/quick/qquickitem2/data/resourcesProperty.qml index b8f18bb375..2c4c0aa5c1 100644 --- a/tests/auto/quick/qquickitem2/data/resourcesProperty.qml +++ b/tests/auto/quick/qquickitem2/data/resourcesProperty.qml @@ -8,14 +8,27 @@ Item { property bool test3 property bool test4 property bool test5 + property bool test6 Component.onCompleted: { - test1 = (root.resources.length >= 3) - test2 = root.resources[0] == item1 - test3 = root.resources[1] == item2 - test4 = root.resources[2] == item3 - test5 = root.resources[10] == null + test1 = (root.resources.length === 4) + test2 = root.resources[0] === item1 + test3 = root.resources[1] === item2 + test4 = root.resources[2] === item3 + test5 = root.resources[3] === otherObject + test6 = root.resources[10] == null } + //Resources can be used explicitly resources: [ Item { id: item1 }, Item { id: item2 }, Item { id: item3 } ] + + Item { + //Item in Data go the children property. + } + + QtObject { + //Objects in Data which are not items are put in resources. + id: otherObject + objectName: "subObject"; + } } diff --git a/tests/auto/quick/qquickitem2/tst_qquickitem.cpp b/tests/auto/quick/qquickitem2/tst_qquickitem.cpp index f2d25e81ed..992e81aa64 100644 --- a/tests/auto/quick/qquickitem2/tst_qquickitem.cpp +++ b/tests/auto/quick/qquickitem2/tst_qquickitem.cpp @@ -47,6 +47,7 @@ #include <QtGui/private/qinputmethod_p.h> #include <QtQuick/private/qquickrectangle_p.h> #include <QtQuick/private/qquicktextinput_p.h> +#include <QtGui/qpa/qplatformtheme.h> #include <private/qquickitem_p.h> #include "../../shared/util.h" #include "../shared/visualtestutil.h" @@ -69,6 +70,12 @@ private slots: void activeFocusOnTab3(); void activeFocusOnTab4(); void activeFocusOnTab5(); + void activeFocusOnTab6(); + void activeFocusOnTab7(); + void activeFocusOnTab8(); + + void nextItemInFocusChain(); + void nextItemInFocusChain2(); void keys(); void keysProcessingOrder(); @@ -108,6 +115,11 @@ private slots: private: QQmlEngine engine; + bool qt_tab_all_widgets() { + if (const QPlatformTheme *theme = QGuiApplicationPrivate::platformTheme()) + return theme->themeHint(QPlatformTheme::TabAllWidgets).toBool(); + return true; + } }; class KeysTestObject : public QObject @@ -281,6 +293,9 @@ void tst_QQuickItem::cleanup() void tst_QQuickItem::activeFocusOnTab() { + if (!qt_tab_all_widgets()) + QSKIP("This function doesn't support NOT iterating all."); + QQuickView *window = new QQuickView(0); window->setBaseSize(QSize(800,600)); @@ -390,6 +405,9 @@ void tst_QQuickItem::activeFocusOnTab() void tst_QQuickItem::activeFocusOnTab2() { + if (!qt_tab_all_widgets()) + QSKIP("This function doesn't support NOT iterating all."); + QQuickView *window = new QQuickView(0); window->setBaseSize(QSize(800,600)); @@ -427,6 +445,9 @@ void tst_QQuickItem::activeFocusOnTab2() void tst_QQuickItem::activeFocusOnTab3() { + if (!qt_tab_all_widgets()) + QSKIP("This function doesn't support NOT iterating all."); + QQuickView *window = new QQuickView(0); window->setBaseSize(QSize(800,600)); @@ -606,6 +627,9 @@ void tst_QQuickItem::activeFocusOnTab3() void tst_QQuickItem::activeFocusOnTab4() { + if (!qt_tab_all_widgets()) + QSKIP("This function doesn't support NOT iterating all."); + QQuickView *window = new QQuickView(0); window->setBaseSize(QSize(800,600)); @@ -635,6 +659,9 @@ void tst_QQuickItem::activeFocusOnTab4() void tst_QQuickItem::activeFocusOnTab5() { + if (!qt_tab_all_widgets()) + QSKIP("This function doesn't support NOT iterating all."); + QQuickView *window = new QQuickView(0); window->setBaseSize(QSize(800,600)); @@ -664,6 +691,273 @@ void tst_QQuickItem::activeFocusOnTab5() delete window; } +void tst_QQuickItem::activeFocusOnTab6() +{ + if (qt_tab_all_widgets()) + QSKIP("This function doesn't support iterating all."); + + QQuickView *window = new QQuickView(0); + window->setBaseSize(QSize(800,600)); + + window->setSource(testFileUrl("activeFocusOnTab6.qml")); + window->show(); + window->requestActivate(); + QVERIFY(QTest::qWaitForWindowActive(window)); + QVERIFY(QGuiApplication::focusWindow() == window); + + // original: button12 + QQuickItem *item = findItem<QQuickItem>(window->rootObject(), "button12"); + QVERIFY(item); + QVERIFY(item->hasActiveFocus()); + + // Tab: button12->edit + QKeyEvent key(QEvent::KeyPress, Qt::Key_Tab, Qt::NoModifier, "", false, 1); + QGuiApplication::sendEvent(window, &key); + QVERIFY(key.isAccepted()); + + item = findItem<QQuickItem>(window->rootObject(), "edit"); + QVERIFY(item); + QVERIFY(item->hasActiveFocus()); + + // BackTab: edit->button12 + key = QKeyEvent(QEvent::KeyPress, Qt::Key_Tab, Qt::ShiftModifier, "", false, 1); + QGuiApplication::sendEvent(window, &key); + QVERIFY(key.isAccepted()); + + item = findItem<QQuickItem>(window->rootObject(), "button12"); + QVERIFY(item); + QVERIFY(item->hasActiveFocus()); + + // BackTab: button12->button11 + key = QKeyEvent(QEvent::KeyPress, Qt::Key_Tab, Qt::ShiftModifier, "", false, 1); + QGuiApplication::sendEvent(window, &key); + QVERIFY(key.isAccepted()); + + item = findItem<QQuickItem>(window->rootObject(), "button11"); + QVERIFY(item); + QVERIFY(item->hasActiveFocus()); + + // BackTab: button11->edit + key = QKeyEvent(QEvent::KeyPress, Qt::Key_Tab, Qt::ShiftModifier, "", false, 1); + QGuiApplication::sendEvent(window, &key); + QVERIFY(key.isAccepted()); + + item = findItem<QQuickItem>(window->rootObject(), "edit"); + QVERIFY(item); + QVERIFY(item->hasActiveFocus()); + + delete window; +} + +void tst_QQuickItem::activeFocusOnTab7() +{ + if (qt_tab_all_widgets()) + QSKIP("This function doesn't support iterating all."); + + QQuickView *window = new QQuickView(0); + window->setBaseSize(QSize(300,300)); + + window->setSource(testFileUrl("activeFocusOnTab7.qml")); + window->show(); + window->requestActivate(); + QVERIFY(QTest::qWaitForWindowActive(window)); + QVERIFY(QGuiApplication::focusWindow() == window); + + QQuickItem *item = findItem<QQuickItem>(window->rootObject(), "button1"); + QVERIFY(item); + item->forceActiveFocus(); + QVERIFY(item->hasActiveFocus()); + + // Tab: button1->button1 + QKeyEvent key(QEvent::KeyPress, Qt::Key_Tab, Qt::NoModifier, "", false, 1); + QGuiApplication::sendEvent(window, &key); + QVERIFY(!key.isAccepted()); + + QVERIFY(item->hasActiveFocus()); + + // BackTab: button1->button1 + key = QKeyEvent(QEvent::KeyPress, Qt::Key_Tab, Qt::ShiftModifier, "", false, 1); + QGuiApplication::sendEvent(window, &key); + QVERIFY(!key.isAccepted()); + + QVERIFY(item->hasActiveFocus()); + + delete window; +} + +void tst_QQuickItem::activeFocusOnTab8() +{ + QQuickView *window = new QQuickView(0); + window->setBaseSize(QSize(300,300)); + + window->setSource(testFileUrl("activeFocusOnTab8.qml")); + window->show(); + window->requestActivate(); + QVERIFY(QTest::qWaitForWindowActive(window)); + QVERIFY(QGuiApplication::focusWindow() == window); + + QQuickItem *content = window->contentItem(); + QVERIFY(content); + QVERIFY(content->hasActiveFocus()); + + QQuickItem *button1 = findItem<QQuickItem>(window->rootObject(), "button1"); + QVERIFY(button1); + QVERIFY(!button1->hasActiveFocus()); + + QQuickItem *button2 = findItem<QQuickItem>(window->rootObject(), "button2"); + QVERIFY(button2); + QVERIFY(!button2->hasActiveFocus()); + + // Tab: contentItem->button1 + QKeyEvent key(QEvent::KeyPress, Qt::Key_Tab, Qt::NoModifier, "", false, 1); + QGuiApplication::sendEvent(window, &key); + QVERIFY(key.isAccepted()); + + QVERIFY(button1->hasActiveFocus()); + + // Tab: button1->button2 + key = QKeyEvent(QEvent::KeyPress, Qt::Key_Tab, Qt::NoModifier, "", false, 1); + QGuiApplication::sendEvent(window, &key); + QVERIFY(key.isAccepted()); + + QVERIFY(button2->hasActiveFocus()); + QVERIFY(!button1->hasActiveFocus()); + + // BackTab: button2->button1 + key = QKeyEvent(QEvent::KeyPress, Qt::Key_Tab, Qt::ShiftModifier, "", false, 1); + QGuiApplication::sendEvent(window, &key); + QVERIFY(key.isAccepted()); + + QVERIFY(button1->hasActiveFocus()); + QVERIFY(!button2->hasActiveFocus()); + + delete window; +} + +void tst_QQuickItem::nextItemInFocusChain() +{ + if (!qt_tab_all_widgets()) + QSKIP("This function doesn't support NOT iterating all."); + + QQuickView *window = new QQuickView(0); + window->setBaseSize(QSize(800,600)); + + window->setSource(testFileUrl("activeFocusOnTab.qml")); + window->show(); + window->requestActivate(); + QVERIFY(QTest::qWaitForWindowActive(window)); + QVERIFY(QGuiApplication::focusWindow() == window); + + QQuickItem *button11 = findItem<QQuickItem>(window->rootObject(), "button11"); + QVERIFY(button11); + QQuickItem *button12 = findItem<QQuickItem>(window->rootObject(), "button12"); + QVERIFY(button12); + + QQuickItem *sub2 = findItem<QQuickItem>(window->rootObject(), "sub2"); + QVERIFY(sub2); + QQuickItem *button21 = findItem<QQuickItem>(window->rootObject(), "button21"); + QVERIFY(button21); + QQuickItem *button22 = findItem<QQuickItem>(window->rootObject(), "button22"); + QVERIFY(button22); + + QQuickItem *edit = findItem<QQuickItem>(window->rootObject(), "edit"); + QVERIFY(edit); + + QQuickItem *next, *prev; + + next = button11->nextItemInFocusChain(true); + QVERIFY(next); + QCOMPARE(next, button12); + prev = button11->nextItemInFocusChain(false); + QVERIFY(prev); + QCOMPARE(prev, edit); + + next = button12->nextItemInFocusChain(); + QVERIFY(next); + QCOMPARE(next, sub2); + prev = button12->nextItemInFocusChain(false); + QVERIFY(prev); + QCOMPARE(prev, button11); + + next = sub2->nextItemInFocusChain(true); + QVERIFY(next); + QCOMPARE(next, button21); + prev = sub2->nextItemInFocusChain(false); + QVERIFY(prev); + QCOMPARE(prev, button12); + + next = button21->nextItemInFocusChain(); + QVERIFY(next); + QCOMPARE(next, button22); + prev = button21->nextItemInFocusChain(false); + QVERIFY(prev); + QCOMPARE(prev, sub2); + + next = button22->nextItemInFocusChain(true); + QVERIFY(next); + QCOMPARE(next, edit); + prev = button22->nextItemInFocusChain(false); + QVERIFY(prev); + QCOMPARE(prev, button21); + + next = edit->nextItemInFocusChain(); + QVERIFY(next); + QCOMPARE(next, button11); + prev = edit->nextItemInFocusChain(false); + QVERIFY(prev); + QCOMPARE(prev, button22); + + delete window; +} + +void tst_QQuickItem::nextItemInFocusChain2() +{ + if (qt_tab_all_widgets()) + QSKIP("This function doesn't support iterating all."); + + QQuickView *window = new QQuickView(0); + window->setBaseSize(QSize(800,600)); + + window->setSource(testFileUrl("activeFocusOnTab6.qml")); + window->show(); + window->requestActivate(); + QVERIFY(QTest::qWaitForWindowActive(window)); + QVERIFY(QGuiApplication::focusWindow() == window); + + QQuickItem *button11 = findItem<QQuickItem>(window->rootObject(), "button11"); + QVERIFY(button11); + QQuickItem *button12 = findItem<QQuickItem>(window->rootObject(), "button12"); + QVERIFY(button12); + + QQuickItem *edit = findItem<QQuickItem>(window->rootObject(), "edit"); + QVERIFY(edit); + + QQuickItem *next, *prev; + + next = button11->nextItemInFocusChain(true); + QVERIFY(next); + QCOMPARE(next, button12); + prev = button11->nextItemInFocusChain(false); + QVERIFY(prev); + QCOMPARE(prev, edit); + + next = button12->nextItemInFocusChain(); + QVERIFY(next); + QCOMPARE(next, edit); + prev = button12->nextItemInFocusChain(false); + QVERIFY(prev); + QCOMPARE(prev, button11); + + next = edit->nextItemInFocusChain(); + QVERIFY(next); + QCOMPARE(next, button11); + prev = edit->nextItemInFocusChain(false); + QVERIFY(prev); + QCOMPARE(prev, button12); + + delete window; +} + void tst_QQuickItem::keys() { QQuickView *window = new QQuickView(0); @@ -1633,15 +1927,35 @@ void tst_QQuickItem::resourcesProperty() { QQmlComponent component(&engine, testFileUrl("resourcesProperty.qml")); - QObject *o = component.create(); - QVERIFY(o != 0); + QObject *object = component.create(); + QVERIFY(object != 0); - QCOMPARE(o->property("test1").toBool(), true); - QCOMPARE(o->property("test2").toBool(), true); - QCOMPARE(o->property("test3").toBool(), true); - QCOMPARE(o->property("test4").toBool(), true); - QCOMPARE(o->property("test5").toBool(), true); - delete o; + QQmlProperty property(object, "resources", component.creationContext()); + + QVERIFY(property.isValid()); + QQmlListReference list = qvariant_cast<QQmlListReference>(property.read()); + QVERIFY(list.isValid()); + + QCOMPARE(list.count(), 4); + + QCOMPARE(object->property("test1").toBool(), true); + QCOMPARE(object->property("test2").toBool(), true); + QCOMPARE(object->property("test3").toBool(), true); + QCOMPARE(object->property("test4").toBool(), true); + QCOMPARE(object->property("test5").toBool(), true); + QCOMPARE(object->property("test6").toBool(), true); + + QObject *subObject = object->findChild<QObject *>("subObject"); + + QVERIFY(subObject); + + QCOMPARE(object, subObject->parent()); + + delete subObject; + + QCOMPARE(list.count(), 3); + + delete object; } void tst_QQuickItem::propertyChanges() diff --git a/tests/auto/quick/qquicklistview/data/delayedChanges.qml b/tests/auto/quick/qquicklistview/data/delayedChanges.qml new file mode 100644 index 0000000000..590af39c02 --- /dev/null +++ b/tests/auto/quick/qquicklistview/data/delayedChanges.qml @@ -0,0 +1,39 @@ +import QtQuick 2.1 + +Item { + width: 400 + height: 400 + function takeTwo() + { + listView.model.remove(0); + listView.model.remove(0); + } + function takeTwo_sync() + { + listView.model.remove(0); + listView.forceLayout(); + listView.model.remove(0); + listView.forceLayout(); + } + + ListView { + id: listView + height: parent.height + width: 400 + model: ListModel { + ListElement { name: "A" } + ListElement { name: "B" } + ListElement { name: "C" } + ListElement { name: "D" } + ListElement { name: "E" } + ListElement { name: "F" } + ListElement { name: "G" } + ListElement { name: "H" } + ListElement { name: "I" } + ListElement { name: "J" } + } + delegate: Text { + text: index + listView.count + } + } +} diff --git a/tests/auto/quick/qquicklistview/data/emptymodel.qml b/tests/auto/quick/qquicklistview/data/emptymodel.qml index 16bcd3f9ae..3feec691cf 100644 --- a/tests/auto/quick/qquicklistview/data/emptymodel.qml +++ b/tests/auto/quick/qquicklistview/data/emptymodel.qml @@ -1,4 +1,4 @@ -import QtQuick 2.0 +import QtQuick 2.1 Rectangle { ListModel { id: model @@ -12,11 +12,13 @@ Rectangle { } function remove() { model.remove(0) + list.forceLayout() isCurrentItemNull = list.currentItem === null //check no seg fault } function add() { model.append({name: "hello"}) + list.forceLayout() isCurrentItemNull = list.currentItem === null } property bool isCurrentItemNull diff --git a/tests/auto/quick/qquicklistview/tst_qquicklistview.cpp b/tests/auto/quick/qquicklistview/tst_qquicklistview.cpp index f8c7de6635..bec61eaccb 100644 --- a/tests/auto/quick/qquicklistview/tst_qquicklistview.cpp +++ b/tests/auto/quick/qquicklistview/tst_qquicklistview.cpp @@ -208,10 +208,11 @@ private slots: void parentBinding(); void defaultHighlightMoveDuration(); void accessEmptyCurrentItem_QTBUG_30227(); + void delayedChanges_QTBUG_30555(); private: - template <class T> void items(const QUrl &source, bool forceLayout); - template <class T> void changed(const QUrl &source, bool forceLayout); + template <class T> void items(const QUrl &source); + template <class T> void changed(const QUrl &source); template <class T> void inserted(const QUrl &source); template <class T> void inserted_more(QQuickItemView::VerticalLayoutDirection verticalLayoutDirection = QQuickItemView::TopToBottom); template <class T> void removed(const QUrl &source, bool animated); @@ -329,7 +330,7 @@ void tst_QQuickListView::cleanupTestCase() } template <class T> -void tst_QQuickListView::items(const QUrl &source, bool forceLayout) +void tst_QQuickListView::items(const QUrl &source) { QQuickView *window = createView(); @@ -349,6 +350,7 @@ void tst_QQuickListView::items(const QUrl &source, bool forceLayout) QQuickListView *listview = findItem<QQuickListView>(window->rootObject(), "list"); QTRY_VERIFY(listview != 0); + listview->forceLayout(); QQuickItem *contentItem = listview->contentItem(); QTRY_VERIFY(contentItem != 0); @@ -359,6 +361,7 @@ void tst_QQuickListView::items(const QUrl &source, bool forceLayout) QTRY_VERIFY(listview->highlightItem() != 0); QTRY_COMPARE(listview->count(), model.count()); QTRY_COMPARE(window->rootObject()->property("count").toInt(), model.count()); + listview->forceLayout(); QTRY_COMPARE(contentItem->childItems().count(), model.count()+1); // assumes all are visible, +1 for the (default) highlight item // current item should be first item @@ -398,8 +401,7 @@ void tst_QQuickListView::items(const QUrl &source, bool forceLayout) ctxt->setContextProperty("testModel", &model2); // Force a layout, necessary if ListView is completed before VisualDataModel. - if (forceLayout) - QCOMPARE(listview->property("count").toInt(), 0); + listview->forceLayout(); int itemCount = findItems<QQuickItem>(contentItem, "wrapper").count(); QTRY_VERIFY(itemCount == 0); @@ -413,7 +415,7 @@ void tst_QQuickListView::items(const QUrl &source, bool forceLayout) template <class T> -void tst_QQuickListView::changed(const QUrl &source, bool forceLayout) +void tst_QQuickListView::changed(const QUrl &source) { QQuickView *window = createView(); @@ -431,15 +433,15 @@ void tst_QQuickListView::changed(const QUrl &source, bool forceLayout) window->setSource(source); qApp->processEvents(); - QQuickFlickable *listview = findItem<QQuickFlickable>(window->rootObject(), "list"); + QQuickListView *listview = findItem<QQuickListView>(window->rootObject(), "list"); QTRY_VERIFY(listview != 0); + listview->forceLayout(); QQuickItem *contentItem = listview->contentItem(); QTRY_VERIFY(contentItem != 0); // Force a layout, necessary if ListView is completed before VisualDataModel. - if (forceLayout) - QCOMPARE(listview->property("count").toInt(), model.count()); + listview->forceLayout(); model.modifyItem(1, "Will", "9876"); QQuickText *name = findItem<QQuickText>(contentItem, "textName", 1); @@ -579,22 +581,24 @@ void tst_QQuickListView::inserted_more(QQuickItemView::VerticalLayoutDirection v QQuickItem *contentItem = listview->contentItem(); QTRY_VERIFY(contentItem != 0); - bool waitForPolish = (contentY != 0); if (verticalLayoutDirection == QQuickItemView::BottomToTop) { listview->setVerticalLayoutDirection(verticalLayoutDirection); QTRY_COMPARE(QQuickItemPrivate::get(listview)->polishScheduled, false); contentY = -listview->height() - contentY; } listview->setContentY(contentY); - if (waitForPolish) - QTRY_COMPARE(QQuickItemPrivate::get(listview)->polishScheduled, false); QList<QPair<QString, QString> > newData; for (int i=0; i<insertCount; i++) newData << qMakePair(QString("value %1").arg(i), QString::number(i)); model.insertItems(insertIndex, newData); + + //Wait for polish (updates list to the model changes) + QTRY_COMPARE(QQuickItemPrivate::get(listview)->polishScheduled, false); + QTRY_COMPARE(listview->property("count").toInt(), model.count()); + // check visibleItems.first() is in correct position QQuickItem *item0 = findItem<QQuickItem>(contentItem, "wrapper", 0); QVERIFY(item0); @@ -1019,17 +1023,17 @@ void tst_QQuickListView::removed_more(const QUrl &source, QQuickItemView::Vertic QQuickItem *contentItem = listview->contentItem(); QTRY_VERIFY(contentItem != 0); - bool waitForPolish = (contentY != 0); if (verticalLayoutDirection == QQuickItemView::BottomToTop) { listview->setVerticalLayoutDirection(verticalLayoutDirection); QTRY_COMPARE(QQuickItemPrivate::get(listview)->polishScheduled, false); contentY = -listview->height() - contentY; } listview->setContentY(contentY); - if (waitForPolish) - QTRY_COMPARE(QQuickItemPrivate::get(listview)->polishScheduled, false); model.removeItems(removeIndex, removeCount); + //Wait for polish (updates list to the model changes) + QTRY_COMPARE(QQuickItemPrivate::get(listview)->polishScheduled, false); + QTRY_COMPARE(listview->property("count").toInt(), model.count()); // check visibleItems.first() is in correct position @@ -1219,6 +1223,7 @@ void tst_QQuickListView::clear(const QUrl &source, QQuickItemView::VerticalLayou // confirm sanity when adding an item to cleared list model.addItem("New", "1"); + listview->forceLayout(); QTRY_VERIFY(listview->count() == 1); QVERIFY(listview->currentItem() != 0); QVERIFY(listview->currentIndex() == 0); @@ -1945,6 +1950,7 @@ void tst_QQuickListView::sections(const QUrl &source) // Remove section boundary model.removeItem(5); + listview->forceLayout(); QTRY_COMPARE(listview->count(), model.count()); // New section header created @@ -1953,6 +1959,7 @@ void tst_QQuickListView::sections(const QUrl &source) QTRY_COMPARE(item->height(), 40.0); model.insertItem(3, "New Item", "0"); + listview->forceLayout(); QTRY_COMPARE(listview->count(), model.count()); // Section header moved @@ -1966,6 +1973,7 @@ void tst_QQuickListView::sections(const QUrl &source) // insert item which will become a section header model.insertItem(6, "Replace header", "1"); + listview->forceLayout(); QTRY_COMPARE(listview->count(), model.count()); item = findItem<QQuickItem>(contentItem, "wrapper", 6); @@ -2061,6 +2069,7 @@ void tst_QQuickListView::sectionsDelegate() // remove section boundary model.removeItem(5); + listview->forceLayout(); QTRY_COMPARE(listview->count(), model.count()); for (int i = 0; i < 3; ++i) { QQuickItem *item = findItem<QQuickItem>(contentItem, @@ -2288,6 +2297,7 @@ void tst_QQuickListView::sectionsPositioning() listview->setContentY(120); QTRY_COMPARE(QQuickItemPrivate::get(listview)->polishScheduled, false); model.removeItem(5); + listview->forceLayout(); QTRY_COMPARE(listview->count(), model.count()); for (int i = 1; i < 3; ++i) { QQuickItem *item = findVisibleChild(contentItem, @@ -2485,7 +2495,8 @@ void tst_QQuickListView::currentIndex_delayedItemCreation() QTRY_VERIFY(contentItem != 0); QSignalSpy spy(listview, SIGNAL(currentItemChanged())); - QCOMPARE(listview->currentIndex(), 0); + //QCOMPARE(listview->currentIndex(), 0); + listview->forceLayout(); QTRY_COMPARE(spy.count(), 1); releaseView(window); @@ -2536,6 +2547,7 @@ void tst_QQuickListView::currentIndex() for (int i = 0; i < 30; i++) model.addItem("Item" + QString::number(i), QString::number(i)); ctxt->setContextProperty("testModel", &model); + listview->forceLayout(); QCOMPARE(listview->currentIndex(), 0); QCOMPARE(listview->currentItem(), findItem<QQuickItem>(contentItem, "wrapper", 0)); @@ -2679,6 +2691,7 @@ void tst_QQuickListView::keyNavigation() QTRY_COMPARE(listview->currentIndex(), i+1); } QTest::keyRelease(window, forwardsKey); + listview->forceLayout(); QTRY_COMPARE(listview->currentIndex(), model.count()-1); QTRY_COMPARE(listview->contentX(), contentPosAtLastItem.x()); QTRY_COMPARE(listview->contentY(), contentPosAtLastItem.y()); @@ -2689,6 +2702,7 @@ void tst_QQuickListView::keyNavigation() QTRY_COMPARE(listview->currentIndex(), i-1); } QTest::keyRelease(window, backwardsKey); + listview->forceLayout(); QTRY_COMPARE(listview->currentIndex(), 0); QTRY_COMPARE(listview->contentX(), contentPosAtFirstItem.x()); QTRY_COMPARE(listview->contentY(), contentPosAtFirstItem.y()); @@ -3123,6 +3137,7 @@ void tst_QQuickListView::resetModel() strings << "four" << "five" << "six" << "seven"; model.setStringList(strings); + listview->forceLayout(); QTRY_COMPARE(listview->count(), model.rowCount()); for (int i = 0; i < model.rowCount(); ++i) { @@ -3470,6 +3485,7 @@ void tst_QQuickListView::header() QCOMPARE(item->position(), firstDelegatePos); model.clear(); + listview->forceLayout(); QTRY_COMPARE(listview->count(), model.count()); QCOMPARE(header->position(), initialHeaderPos); // header should stay where it is if (orientation == QQuickListView::Vertical) @@ -3865,6 +3881,7 @@ void tst_QQuickListView::extents() QCOMPARE(listview->originY(), origin_empty.y()); for (int i=0; i<30; i++) model.addItem("Item" + QString::number(i), ""); + listview->forceLayout(); QTRY_COMPARE(listview->count(), model.count()); QCOMPARE(listview->originX(), origin_nonEmpty.x()); QCOMPARE(listview->originY(), origin_nonEmpty.y()); @@ -4262,6 +4279,7 @@ void tst_QQuickListView::resizeFirstDelegate() for (int i = 0; i < 10; i++) model.addItem("Item" + QString::number(i), ""); + listview->forceLayout(); QTRY_COMPARE(listview->count(), model.count()); item = findItem<QQuickItem>(contentItem, "wrapper", 1); @@ -4461,6 +4479,7 @@ void tst_QQuickListView::indexAt_itemAt() void tst_QQuickListView::incrementalModel() { QQuickView *window = createView(); + QSKIP("QTBUG-30716"); IncrementalModel model; QQmlContext *ctxt = window->rootContext(); @@ -4471,14 +4490,17 @@ void tst_QQuickListView::incrementalModel() QQuickListView *listview = findItem<QQuickListView>(window->rootObject(), "list"); QTRY_VERIFY(listview != 0); + listview->forceLayout(); QQuickItem *contentItem = listview->contentItem(); QTRY_VERIFY(contentItem != 0); + listview->forceLayout(); QTRY_COMPARE(listview->count(), 20); listview->positionViewAtIndex(10, QQuickListView::Beginning); + listview->forceLayout(); QTRY_COMPARE(listview->count(), 25); delete window; @@ -4503,18 +4525,19 @@ void tst_QQuickListView::onAdd() ctxt->setContextProperty("delegateHeight", delegateHeight); window->setSource(testFileUrl("attachedSignals.qml")); - QObject *object = window->rootObject(); - object->setProperty("width", window->width()); - object->setProperty("height", window->height()); + QQuickListView* listview = qobject_cast<QQuickListView*>(window->rootObject()); + listview->setProperty("width", window->width()); + listview->setProperty("height", window->height()); qApp->processEvents(); QList<QPair<QString, QString> > items; for (int i=0; i<itemsToAdd; i++) items << qMakePair(QString("value %1").arg(i), QString::number(i)); model.addItems(items); - QTRY_COMPARE(window->rootObject()->property("count").toInt(), model.count()); + listview->forceLayout(); + QTRY_COMPARE(listview->property("count").toInt(), model.count()); - QVariantList result = object->property("addedDelegates").toList(); + QVariantList result = listview->property("addedDelegates").toList(); QCOMPARE(result.count(), items.count()); for (int i=0; i<items.count(); i++) QCOMPARE(result[i].toString(), items[i].first); @@ -4557,12 +4580,13 @@ void tst_QQuickListView::onRemove() ctxt->setContextProperty("delegateHeight", delegateHeight); window->setSource(testFileUrl("attachedSignals.qml")); - QObject *object = window->rootObject(); + QQuickListView *listview = qobject_cast<QQuickListView *>(window->rootObject()); model.removeItems(indexToRemove, removeCount); - QTRY_COMPARE(window->rootObject()->property("count").toInt(), model.count()); + listview->forceLayout(); + QTRY_COMPARE(listview->property("count").toInt(), model.count()); - QCOMPARE(object->property("removedDelegateCount"), QVariant(removeCount)); + QCOMPARE(listview->property("removedDelegateCount"), QVariant(removeCount)); releaseView(window); } @@ -4741,6 +4765,7 @@ void tst_QQuickListView::margins() // and originY is updated listview->setContentY(100); model.removeItem(1); + listview->forceLayout(); QTRY_COMPARE(listview->count(), model.count()); listview->setContentY(-50); QTRY_COMPARE(QQuickItemPrivate::get(listview)->polishScheduled, false); @@ -4979,22 +5004,22 @@ void tst_QQuickListView::snapToItem() void tst_QQuickListView::qAbstractItemModel_package_items() { - items<QaimModel>(testFileUrl("listviewtest-package.qml"), true); + items<QaimModel>(testFileUrl("listviewtest-package.qml")); } void tst_QQuickListView::qAbstractItemModel_items() { - items<QaimModel>(testFileUrl("listviewtest.qml"), false); + items<QaimModel>(testFileUrl("listviewtest.qml")); } void tst_QQuickListView::qAbstractItemModel_package_changed() { - changed<QaimModel>(testFileUrl("listviewtest-package.qml"), true); + changed<QaimModel>(testFileUrl("listviewtest-package.qml")); } void tst_QQuickListView::qAbstractItemModel_changed() { - changed<QaimModel>(testFileUrl("listviewtest.qml"), false); + changed<QaimModel>(testFileUrl("listviewtest.qml")); } void tst_QQuickListView::qAbstractItemModel_package_inserted() @@ -5555,6 +5580,7 @@ void tst_QQuickListView::populateTransitions() // clear the model window->rootContext()->setContextProperty("testModel", QVariant()); + listview->forceLayout(); QTRY_COMPARE(listview->count(), 0); QTRY_COMPARE(findItems<QQuickItem>(contentItem, "wrapper").count(), 0); listview->setProperty("countPopulateTransitions", 0); @@ -5683,6 +5709,7 @@ void tst_QQuickListView::addTransitions() if (!newData.isEmpty()) { model.insertItems(insertionIndex, newData); QTRY_COMPARE(model.count(), listview->count()); + listview->forceLayout(); } QList<QQuickItem *> targetItems = findItems<QQuickItem>(contentItem, "wrapper", targetIndexes); @@ -6291,6 +6318,7 @@ void tst_QQuickListView::displacedTransitions() case ListChange::Polish: break; } + listview->forceLayout(); QVariantList resultTargetIndexes = listview->property("displacedTargetIndexes").toList(); QVariantList resultTargetItems = listview->property("displacedTargetItems").toList(); @@ -6539,6 +6567,7 @@ void tst_QQuickListView::multipleTransitions() break; } } + listview->forceLayout(); QCOMPARE(listview->count(), model.count()); // verify all items moved to the correct final positions @@ -6822,6 +6851,7 @@ void tst_QQuickListView::accessEmptyCurrentItem_QTBUG_30227() QQuickListView *listview = window->rootObject()->findChild<QQuickListView*>(); QTRY_VERIFY(listview != 0); + listview->forceLayout(); QMetaObject::invokeMethod(window->rootObject(), "remove"); QVERIFY(window->rootObject()->property("isCurrentItemNull").toBool()); @@ -6830,6 +6860,26 @@ void tst_QQuickListView::accessEmptyCurrentItem_QTBUG_30227() QVERIFY(!window->rootObject()->property("isCurrentItemNull").toBool()); } +void tst_QQuickListView::delayedChanges_QTBUG_30555() +{ + QQuickView *window = createView(); + window->setSource(testFileUrl("delayedChanges.qml")); + + QQuickListView *listview = window->rootObject()->findChild<QQuickListView*>(); + QTRY_VERIFY(listview != 0); + + QCOMPARE(listview->count(), 10); + + //Takes two just like in the bug report + QMetaObject::invokeMethod(window->rootObject(), "takeTwo"); + QTRY_COMPARE(listview->count(), 8); + + QMetaObject::invokeMethod(window->rootObject(), "takeTwo_sync"); + QCOMPARE(listview->count(), 6); + + delete window; +} + QTEST_MAIN(tst_QQuickListView) #include "tst_qquicklistview.moc" diff --git a/tests/auto/quick/qquickmousearea/data/hoverAfterPress.qml b/tests/auto/quick/qquickmousearea/data/hoverAfterPress.qml new file mode 100644 index 0000000000..69ec8fbd47 --- /dev/null +++ b/tests/auto/quick/qquickmousearea/data/hoverAfterPress.qml @@ -0,0 +1,29 @@ +import QtQuick 2.0 + +Item { + width: 500 + height: 500 + + Rectangle { + width: 300 + height: 300 + color: "grey" + x: 100 + y: 100 + + MouseArea { + id: mouseArea + objectName: "mouseArea" + anchors.fill: parent + hoverEnabled: true + onPressed: mouse.accepted = false + //onContainsMouseChanged: print("containsMouse changed =", containsMouse) + + Rectangle { + visible: parent.containsMouse + color: "red" + width: 10; height: 10 + } + } + } +} diff --git a/tests/auto/quick/qquickmousearea/tst_qquickmousearea.cpp b/tests/auto/quick/qquickmousearea/tst_qquickmousearea.cpp index fa33f3f626..a582c62701 100644 --- a/tests/auto/quick/qquickmousearea/tst_qquickmousearea.cpp +++ b/tests/auto/quick/qquickmousearea/tst_qquickmousearea.cpp @@ -78,6 +78,7 @@ private slots: void hoverPosition(); void hoverPropagation(); void hoverVisible(); + void hoverAfterPress(); void disableAfterPress(); void onWheel(); void transformedMouseArea_data(); @@ -585,7 +586,7 @@ void tst_QQuickMouseArea::pressedCanceledOnWindowDeactivate() QWindow *secondWindow = qvariant_cast<QWindow*>(window->rootObject()->property("secondWindow")); secondWindow->setProperty("visible", true); - QTest::qWaitForWindowActive(secondWindow); + QTest::qWaitForWindowExposed(secondWindow); QVERIFY(!window->rootObject()->property("pressed").toBool()); QVERIFY(window->rootObject()->property("canceled").toBool()); @@ -1007,6 +1008,33 @@ void tst_QQuickMouseArea::hoverVisible() delete window; } +void tst_QQuickMouseArea::hoverAfterPress() +{ + QQuickView *window = createView(); + window->setSource(testFileUrl("hoverAfterPress.qml")); + + QQuickItem *root = window->rootObject(); + QVERIFY(root != 0); + + QQuickMouseArea *mouseArea = window->rootObject()->findChild<QQuickMouseArea*>("mouseArea"); + QVERIFY(mouseArea != 0); + QTest::mouseMove(window, QPoint(22,33)); + QCOMPARE(mouseArea->hovered(), false); + QTest::mouseMove(window, QPoint(200,200)); + QCOMPARE(mouseArea->hovered(), true); + QTest::mouseMove(window, QPoint(22,33)); + QCOMPARE(mouseArea->hovered(), false); + QTest::mouseMove(window, QPoint(200,200)); + QCOMPARE(mouseArea->hovered(), true); + QTest::mousePress(window, Qt::LeftButton, Qt::NoModifier, QPoint(200,200)); + QCOMPARE(mouseArea->hovered(), true); + QTest::mouseRelease(window, Qt::LeftButton, Qt::NoModifier, QPoint(200,200)); + QCOMPARE(mouseArea->hovered(), true); + QTest::mouseMove(window, QPoint(22,33)); + QCOMPARE(mouseArea->hovered(), false); + delete window; +} + void tst_QQuickMouseArea::disableAfterPress() { QQuickView *window = createView(); diff --git a/tests/auto/quick/qquickrepeater/data/visualitemmodel.qml b/tests/auto/quick/qquickrepeater/data/visualitemmodel.qml new file mode 100644 index 0000000000..b1b7b97881 --- /dev/null +++ b/tests/auto/quick/qquickrepeater/data/visualitemmodel.qml @@ -0,0 +1,23 @@ +import QtQuick 2.0 + +Rectangle { + width: 360 + height: 360 + + VisualItemModel { + id: visItemModel + Rectangle { + width: 20 + height: 20 + color: "red" + } + } + + Column { + anchors.fill: parent + Repeater { + model: visItemModel + } + } +} + diff --git a/tests/auto/quick/qquickrepeater/tst_qquickrepeater.cpp b/tests/auto/quick/qquickrepeater/tst_qquickrepeater.cpp index 582503f938..9fb76f9584 100644 --- a/tests/auto/quick/qquickrepeater/tst_qquickrepeater.cpp +++ b/tests/auto/quick/qquickrepeater/tst_qquickrepeater.cpp @@ -78,6 +78,7 @@ private slots: void asynchronous(); void initParent(); void dynamicModelCrash(); + void visualItemModelCrash(); }; class TestObject : public QObject @@ -732,6 +733,17 @@ void tst_QQuickRepeater::dynamicModelCrash() QVERIFY(qvariant_cast<QObject *>(repeater->model()) == 0); } +void tst_QQuickRepeater::visualItemModelCrash() +{ + // This used to crash because the model would get + // deleted before the repeater, leading to double-deletion + // of the items. + QQuickView *window = createView(); + window->setSource(testFileUrl("visualitemmodel.qml")); + qApp->processEvents(); + delete window; +} + QTEST_MAIN(tst_QQuickRepeater) #include "tst_qquickrepeater.moc" diff --git a/tests/auto/quick/qquicktext/data/elideBeforeMaximumLineCount.qml b/tests/auto/quick/qquicktext/data/elideBeforeMaximumLineCount.qml new file mode 100644 index 0000000000..7f1ce705dd --- /dev/null +++ b/tests/auto/quick/qquicktext/data/elideBeforeMaximumLineCount.qml @@ -0,0 +1,10 @@ +import QtQuick 2.0 + +Text { + width: implicitWidth / 2 + height: implicitHeight / 2 + elide: Text.ElideRight + maximumLineCount: 4 + + text: "Line one\nLine two\nLine three\nLine four" +} diff --git a/tests/auto/quick/qquicktext/tst_qquicktext.cpp b/tests/auto/quick/qquicktext/tst_qquicktext.cpp index b95a646bd6..fdaa1d6617 100644 --- a/tests/auto/quick/qquicktext/tst_qquicktext.cpp +++ b/tests/auto/quick/qquicktext/tst_qquicktext.cpp @@ -110,8 +110,8 @@ private slots: void letterSpacing(); void wordSpacing(); - void clickLink_data(); - void clickLink(); + void linkInteraction_data(); + void linkInteraction(); void implicitSize_data(); void implicitSize(); @@ -149,6 +149,8 @@ private slots: void htmlLists(); void htmlLists_data(); + void elideBeforeMaximumLineCount(); + private: QStringList standard; QStringList richText; @@ -1480,15 +1482,30 @@ void tst_qquicktext::wordSpacing() class EventSender : public QQuickItem { public: - void sendEvent(QMouseEvent *event) { - if (event->type() == QEvent::MouseButtonPress) - mousePressEvent(event); - else if (event->type() == QEvent::MouseButtonRelease) - mouseReleaseEvent(event); - else if (event->type() == QEvent::MouseMove) - mouseMoveEvent(event); - else + void sendEvent(QEvent *event) { + switch (event->type()) { + case QEvent::MouseButtonPress: + mousePressEvent(static_cast<QMouseEvent *>(event)); + break; + case QEvent::MouseButtonRelease: + mouseReleaseEvent(static_cast<QMouseEvent *>(event)); + break; + case QEvent::MouseMove: + mouseMoveEvent(static_cast<QMouseEvent *>(event)); + break; + case QEvent::HoverEnter: + hoverEnterEvent(static_cast<QHoverEvent *>(event)); + break; + case QEvent::HoverLeave: + hoverLeaveEvent(static_cast<QHoverEvent *>(event)); + break; + case QEvent::HoverMove: + hoverMoveEvent(static_cast<QHoverEvent *>(event)); + break; + default: qWarning() << "Trying to send unsupported event type"; + break; + } } }; @@ -1498,10 +1515,12 @@ class LinkTest : public QObject public: LinkTest() {} - QString link; + QString clickedLink; + QString hoveredLink; public slots: - void linkClicked(QString l) { link = l; } + void linkClicked(QString l) { clickedLink = l; } + void linkHovered(QString l) { hoveredLink = l; } }; class TextMetrics @@ -1587,13 +1606,15 @@ public: typedef QVector<QPointF> PointVector; Q_DECLARE_METATYPE(PointVector); -void tst_qquicktext::clickLink_data() +void tst_qquicktext::linkInteraction_data() { QTest::addColumn<QString>("text"); QTest::addColumn<qreal>("width"); QTest::addColumn<QString>("bindings"); QTest::addColumn<PointVector>("mousePositions"); - QTest::addColumn<QString>("link"); + QTest::addColumn<QString>("clickedLink"); + QTest::addColumn<QString>("hoverEnterLink"); + QTest::addColumn<QString>("hoverMoveLink"); const QString singleLineText = "this text has a <a href=\\\"http://qt-project.org/single\\\">link</a> in it"; const QString singleLineLink = "http://qt-project.org/single"; @@ -1610,196 +1631,229 @@ void tst_qquicktext::clickLink_data() << singleLineText << 240. << "" << (PointVector() << metrics.characterRectangle(18).center()) - << singleLineLink; + << singleLineLink + << singleLineLink << singleLineLink; QTest::newRow("click on text") << singleLineText << 240. << "" << (PointVector() << metrics.characterRectangle(13).center()) - << QString(); + << QString() + << QString() << QString(); QTest::newRow("drag within link") << singleLineText << 240. << "" << (PointVector() << metrics.characterRectangle(17).center() << metrics.characterRectangle(19).center()) - << singleLineLink; + << singleLineLink + << singleLineLink << singleLineLink; QTest::newRow("drag away from link") << singleLineText << 240. << "" << (PointVector() << metrics.characterRectangle(18).center() << metrics.characterRectangle(13).center()) - << QString(); + << QString() + << singleLineLink << QString(); QTest::newRow("drag on to link") << singleLineText << 240. << "" << (PointVector() << metrics.characterRectangle(13).center() << metrics.characterRectangle(18).center()) - << QString(); + << QString() + << QString() << singleLineLink; QTest::newRow("click on bottom right aligned link") << singleLineText << 240. << "horizontalAlignment: Text.AlignRight; verticalAlignment: Text.AlignBottom" << (PointVector() << metrics.characterRectangle(18, Qt::AlignRight, Qt::AlignBottom).center()) - << singleLineLink; + << singleLineLink + << singleLineLink << singleLineLink; QTest::newRow("click on center aligned link") << singleLineText << 240. << "horizontalAlignment: Text.AlignHCenter; verticalAlignment: Text.AlignVCenter" << (PointVector() << metrics.characterRectangle(18, Qt::AlignHCenter, Qt::AlignVCenter).center()) - << singleLineLink; + << singleLineLink + << singleLineLink << singleLineLink; QTest::newRow("click on rich text link") << singleLineText << 240. << "textFormat: Text.RichText" << (PointVector() << metrics.characterRectangle(18).center()) - << singleLineLink; + << singleLineLink + << singleLineLink << singleLineLink; QTest::newRow("click on rich text") << singleLineText << 240. << "textFormat: Text.RichText" << (PointVector() << metrics.characterRectangle(13).center()) - << QString(); + << QString() + << QString() << QString(); QTest::newRow("click on bottom right aligned rich text link") << singleLineText << 240. << "textFormat: Text.RichText; horizontalAlignment: Text.AlignRight; verticalAlignment: Text.AlignBottom" << (PointVector() << metrics.characterRectangle(18, Qt::AlignRight, Qt::AlignBottom).center()) - << singleLineLink; + << singleLineLink + << singleLineLink << singleLineLink; QTest::newRow("click on center aligned rich text link") << singleLineText << 240. << "textFormat: Text.RichText; horizontalAlignment: Text.AlignHCenter; verticalAlignment: Text.AlignVCenter" << (PointVector() << metrics.characterRectangle(18, Qt::AlignHCenter, Qt::AlignVCenter).center()) - << singleLineLink; + << singleLineLink + << singleLineLink << singleLineLink; } { const TextMetrics metrics("this text has a li", Qt::ElideRight); QTest::newRow("click on right elided link") << singleLineText << metrics.width() + 2 << "elide: Text.ElideRight" << (PointVector() << metrics.characterRectangle(17).center()) - << singleLineLink; + << singleLineLink + << singleLineLink << singleLineLink; } { const TextMetrics metrics("ink in it", Qt::ElideLeft); QTest::newRow("click on left elided link") << singleLineText << metrics.width() + 2 << "elide: Text.ElideLeft" << (PointVector() << metrics.characterRectangle(2).center()) - << singleLineLink; + << singleLineLink + << singleLineLink << singleLineLink; } { const TextMetrics metrics("this text\nhas multiple\nlines in it"); QTest::newRow("click on second line") << multipleLineText << 240. << "" << (PointVector() << metrics.characterRectangle(18).center()) - << multipleLineLink; + << multipleLineLink + << multipleLineLink << multipleLineLink; QTest::newRow("click on third line") << multipleLineText << 240. << "" << (PointVector() << metrics.characterRectangle(25).center()) - << multipleLineLink; + << multipleLineLink + << multipleLineLink << multipleLineLink; QTest::newRow("drag from second line to third") << multipleLineText << 240. << "" << (PointVector() << metrics.characterRectangle(18).center() << metrics.characterRectangle(25).center()) - << multipleLineLink; + << multipleLineLink + << multipleLineLink << multipleLineLink; QTest::newRow("click on rich text second line") << multipleLineText << 240. << "textFormat: Text.RichText" << (PointVector() << metrics.characterRectangle(18).center()) - << multipleLineLink; + << multipleLineLink + << multipleLineLink << multipleLineLink; QTest::newRow("click on rich text third line") << multipleLineText << 240. << "textFormat: Text.RichText" << (PointVector() << metrics.characterRectangle(25).center()) - << multipleLineLink; + << multipleLineLink + << multipleLineLink << multipleLineLink; QTest::newRow("drag rich text from second line to third") << multipleLineText << 240. << "textFormat: Text.RichText" << (PointVector() << metrics.characterRectangle(18).center() << metrics.characterRectangle(25).center()) - << multipleLineLink; + << multipleLineLink + << multipleLineLink << multipleLineLink; } { const TextMetrics metrics("this text has a nested link in it"); QTest::newRow("click on left outer link") << nestedText << 240. << "" << (PointVector() << metrics.characterRectangle(22).center()) - << outerLink; + << outerLink + << outerLink << outerLink; QTest::newRow("click on right outer link") << nestedText << 240. << "" << (PointVector() << metrics.characterRectangle(27).center()) - << outerLink; + << outerLink + << outerLink << outerLink; QTest::newRow("click on inner link left") << nestedText << 240. << "" << (PointVector() << metrics.characterRectangle(23).center()) - << innerLink; + << innerLink + << innerLink << innerLink; QTest::newRow("click on inner link right") << nestedText << 240. << "" << (PointVector() << metrics.characterRectangle(26).center()) - << innerLink; + << innerLink + << innerLink << innerLink; QTest::newRow("drag from inner to outer link") << nestedText << 240. << "" << (PointVector() << metrics.characterRectangle(25).center() << metrics.characterRectangle(30).center()) - << QString(); + << QString() + << innerLink << outerLink; QTest::newRow("drag from outer to inner link") << nestedText << 240. << "" << (PointVector() << metrics.characterRectangle(30).center() << metrics.characterRectangle(25).center()) - << QString(); + << QString() + << outerLink << innerLink; QTest::newRow("click on left outer rich text link") << nestedText << 240. << "textFormat: Text.RichText" << (PointVector() << metrics.characterRectangle(22).center()) - << outerLink; + << outerLink + << outerLink << outerLink; QTest::newRow("click on right outer rich text link") << nestedText << 240. << "textFormat: Text.RichText" << (PointVector() << metrics.characterRectangle(27).center()) - << outerLink; + << outerLink + << outerLink << outerLink; QTest::newRow("click on inner rich text link left") << nestedText << 240. << "textFormat: Text.RichText" << (PointVector() << metrics.characterRectangle(23).center()) - << innerLink; + << innerLink + << innerLink << innerLink; QTest::newRow("click on inner rich text link right") << nestedText << 240. << "textFormat: Text.RichText" << (PointVector() << metrics.characterRectangle(26).center()) - << innerLink; + << innerLink + << innerLink << innerLink; QTest::newRow("drag from inner to outer rich text link") << nestedText << 240. << "textFormat: Text.RichText" << (PointVector() << metrics.characterRectangle(25).center() << metrics.characterRectangle(30).center()) - << QString(); + << QString() + << innerLink << outerLink; QTest::newRow("drag from outer to inner rich text link") << nestedText << 240. << "textFormat: Text.RichText" << (PointVector() << metrics.characterRectangle(30).center() << metrics.characterRectangle(25).center()) - << QString(); + << QString() + << outerLink << innerLink; } } -void tst_qquicktext::clickLink() +void tst_qquicktext::linkInteraction() { QFETCH(QString, text); QFETCH(qreal, width); QFETCH(QString, bindings); QFETCH(PointVector, mousePositions); - QFETCH(QString, link); + QFETCH(QString, clickedLink); + QFETCH(QString, hoverEnterLink); + QFETCH(QString, hoverMoveLink); QString componentStr = - "import QtQuick 2.0\nText {\n" + "import QtQuick 2.2\nText {\n" "width: " + QString::number(width) + "\n" "height: 320\n" "text: \"" + text + "\"\n" @@ -1813,28 +1867,46 @@ void tst_qquicktext::clickLink() LinkTest test; QObject::connect(textObject, SIGNAL(linkActivated(QString)), &test, SLOT(linkClicked(QString))); + QObject::connect(textObject, SIGNAL(linkHovered(QString)), &test, SLOT(linkHovered(QString))); QVERIFY(mousePositions.count() > 0); QPointF mousePosition = mousePositions.first(); { + QHoverEvent he(QEvent::HoverEnter, mousePosition, QPointF()); + static_cast<EventSender*>(static_cast<QQuickItem*>(textObject))->sendEvent(&he); + QMouseEvent me(QEvent::MouseButtonPress, mousePosition, Qt::LeftButton, Qt::NoButton, Qt::NoModifier); static_cast<EventSender*>(static_cast<QQuickItem*>(textObject))->sendEvent(&me); } + QCOMPARE(test.hoveredLink, hoverEnterLink); + QCOMPARE(textObject->hoveredLink(), hoverEnterLink); + for (int i = 1; i < mousePositions.count(); ++i) { mousePosition = mousePositions.at(i); + QHoverEvent he(QEvent::HoverMove, mousePosition, QPointF()); + static_cast<EventSender*>(static_cast<QQuickItem*>(textObject))->sendEvent(&he); + QMouseEvent me(QEvent::MouseMove, mousePosition, Qt::LeftButton, Qt::NoButton, Qt::NoModifier); static_cast<EventSender*>(static_cast<QQuickItem*>(textObject))->sendEvent(&me); } + QCOMPARE(test.hoveredLink, hoverMoveLink); + QCOMPARE(textObject->hoveredLink(), hoverMoveLink); + { + QHoverEvent he(QEvent::HoverLeave, mousePosition, QPointF()); + static_cast<EventSender*>(static_cast<QQuickItem*>(textObject))->sendEvent(&he); + QMouseEvent me(QEvent::MouseButtonRelease, mousePosition, Qt::LeftButton, Qt::NoButton, Qt::NoModifier); static_cast<EventSender*>(static_cast<QQuickItem*>(textObject))->sendEvent(&me); } - QCOMPARE(test.link, link); + QCOMPARE(test.clickedLink, clickedLink); + QCOMPARE(test.hoveredLink, QString()); + QCOMPARE(textObject->hoveredLink(), QString()); delete textObject; } @@ -3638,6 +3710,18 @@ void tst_qquicktext::htmlLists_data() QTest::newRow("unordered list bad") << "<ul type=\"bad\"><li>one</li><li>two</li></ul>" << 2; } +void tst_qquicktext::elideBeforeMaximumLineCount() +{ // QTBUG-31471 + QQmlComponent component(&engine, testFile("elideBeforeMaximumLineCount.qml")); + + QScopedPointer<QObject> object(component.create()); + + QQuickText *item = qobject_cast<QQuickText *>(object.data()); + QVERIFY(item); + + QCOMPARE(item->lineCount(), 2); +} + QTEST_MAIN(tst_qquicktext) #include "tst_qquicktext.moc" diff --git a/tests/auto/quick/qquicktextedit/data/linkActivated.qml b/tests/auto/quick/qquicktextedit/data/linkInteraction.qml index d3bba82b59..d3bba82b59 100644 --- a/tests/auto/quick/qquicktextedit/data/linkActivated.qml +++ b/tests/auto/quick/qquicktextedit/data/linkInteraction.qml diff --git a/tests/auto/quick/qquicktextedit/tst_qquicktextedit.cpp b/tests/auto/quick/qquicktextedit/tst_qquicktextedit.cpp index 2db79d7794..09ea35cd9e 100644 --- a/tests/auto/quick/qquicktextedit/tst_qquicktextedit.cpp +++ b/tests/auto/quick/qquicktextedit/tst_qquicktextedit.cpp @@ -144,7 +144,7 @@ private slots: void positionAt_data(); void positionAt(); - void linkActivated(); + void linkInteraction(); void cursorDelegate_data(); void cursorDelegate(); @@ -183,6 +183,8 @@ private slots: void getText(); void getFormattedText_data(); void getFormattedText(); + void append_data(); + void append(); void insert_data(); void insert(); void remove_data(); @@ -2342,9 +2344,9 @@ void tst_qquicktextedit::positionAt() QVERIFY(texteditObject->positionAt(x0 / 2, y1) > 0); } -void tst_qquicktextedit::linkActivated() +void tst_qquicktextedit::linkInteraction() { - QQuickView window(testFileUrl("linkActivated.qml")); + QQuickView window(testFileUrl("linkInteraction.qml")); QVERIFY(window.rootObject() != 0); window.show(); window.requestActivate(); @@ -2354,6 +2356,7 @@ void tst_qquicktextedit::linkActivated() QVERIFY(texteditObject != 0); QSignalSpy spy(texteditObject, SIGNAL(linkActivated(QString))); + QSignalSpy hover(texteditObject, SIGNAL(linkHovered(QString))); const QString link("http://example.com/"); @@ -2362,21 +2365,31 @@ void tst_qquicktextedit::linkActivated() QTest::mouseClick(&window, Qt::LeftButton, 0, linkPos.toPoint()); QTRY_COMPARE(spy.count(), 1); + QTRY_COMPARE(hover.count(), 1); QCOMPARE(spy.last()[0].toString(), link); + QCOMPARE(hover.last()[0].toString(), link); + QCOMPARE(texteditObject->hoveredLink(), link); QTest::mouseClick(&window, Qt::LeftButton, 0, textPos.toPoint()); - QTest::qWait(50); - QCOMPARE(spy.count(), 1); + QTRY_COMPARE(spy.count(), 1); + QTRY_COMPARE(hover.count(), 2); + QCOMPARE(hover.last()[0].toString(), QString()); + QCOMPARE(texteditObject->hoveredLink(), QString()); texteditObject->setReadOnly(true); QTest::mouseClick(&window, Qt::LeftButton, 0, linkPos.toPoint()); QTRY_COMPARE(spy.count(), 2); + QTRY_COMPARE(hover.count(), 3); QCOMPARE(spy.last()[0].toString(), link); + QCOMPARE(hover.last()[0].toString(), link); + QCOMPARE(texteditObject->hoveredLink(), link); QTest::mouseClick(&window, Qt::LeftButton, 0, textPos.toPoint()); - QTest::qWait(50); - QCOMPARE(spy.count(), 2); + QTRY_COMPARE(spy.count(), 2); + QTRY_COMPARE(hover.count(), 4); + QCOMPARE(hover.last()[0].toString(), QString()); + QCOMPARE(texteditObject->hoveredLink(), QString()); } void tst_qquicktextedit::cursorDelegate_data() @@ -3817,6 +3830,158 @@ void tst_qquicktextedit::getFormattedText() } } +void tst_qquicktextedit::append_data() +{ + QTest::addColumn<QString>("text"); + QTest::addColumn<QQuickTextEdit::TextFormat>("textFormat"); + QTest::addColumn<int>("selectionStart"); + QTest::addColumn<int>("selectionEnd"); + QTest::addColumn<QString>("appendText"); + QTest::addColumn<QString>("expectedText"); + QTest::addColumn<int>("expectedSelectionStart"); + QTest::addColumn<int>("expectedSelectionEnd"); + QTest::addColumn<int>("expectedCursorPosition"); + QTest::addColumn<bool>("selectionChanged"); + QTest::addColumn<bool>("cursorPositionChanged"); + + QTest::newRow("cursor kept intact (beginning)") + << standard.at(0) << QQuickTextEdit::PlainText + << 0 << 0 + << QString("Hello") + << standard.at(0) + QString("\nHello") + << 0 << 0 << 0 + << false << false; + + QTest::newRow("cursor kept intact (middle)") + << standard.at(0) << QQuickTextEdit::PlainText + << 18 << 18 + << QString("Hello") + << standard.at(0) + QString("\nHello") + << 18 << 18 << 18 + << false << false; + + QTest::newRow("cursor follows (end)") + << standard.at(0) << QQuickTextEdit::PlainText + << standard.at(0).length() << standard.at(0).length() + << QString("Hello") + << standard.at(0) + QString("\nHello") + << standard.at(0).length() + 6 << standard.at(0).length() + 6 << standard.at(0).length() + 6 + << false << true; + + QTest::newRow("selection kept intact (beginning)") + << standard.at(0) << QQuickTextEdit::PlainText + << 0 << 18 + << QString("Hello") + << standard.at(0) + QString("\nHello") + << 0 << 18 << 18 + << false << false; + + QTest::newRow("selection kept intact (middle)") + << standard.at(0) << QQuickTextEdit::PlainText + << 14 << 18 + << QString("Hello") + << standard.at(0) + QString("\nHello") + << 14 << 18 << 18 + << false << false; + + QTest::newRow("selection kept intact, cursor follows (end)") + << standard.at(0) << QQuickTextEdit::PlainText + << 18 << standard.at(0).length() + << QString("Hello") + << standard.at(0) + QString("\nHello") + << 18 << standard.at(0).length() + 6 << standard.at(0).length() + 6 + << false << true; + + QTest::newRow("reversed selection kept intact") + << standard.at(0) << QQuickTextEdit::PlainText + << 18 << 14 + << QString("Hello") + << standard.at(0) + QString("\nHello") + << 14 << 18 << 14 + << false << false; + + QTest::newRow("rich text into plain text") + << standard.at(0) << QQuickTextEdit::PlainText + << 0 << 0 + << QString("<b>Hello</b>") + << standard.at(0) + QString("\n<b>Hello</b>") + << 0 << 0 << 0 + << false << false; + + QTest::newRow("rich text into rich text") + << standard.at(0) << QQuickTextEdit::RichText + << 0 << 0 + << QString("<b>Hello</b>") + << standard.at(0) + QChar(QChar::ParagraphSeparator) + QString("Hello") + << 0 << 0 << 0 + << false << false; + + QTest::newRow("rich text into auto text") + << standard.at(0) << QQuickTextEdit::AutoText + << 0 << 0 + << QString("<b>Hello</b>") + << standard.at(0) + QString("\nHello") + << 0 << 0 << 0 + << false << false; +} + +void tst_qquicktextedit::append() +{ + QFETCH(QString, text); + QFETCH(QQuickTextEdit::TextFormat, textFormat); + QFETCH(int, selectionStart); + QFETCH(int, selectionEnd); + QFETCH(QString, appendText); + QFETCH(QString, expectedText); + QFETCH(int, expectedSelectionStart); + QFETCH(int, expectedSelectionEnd); + QFETCH(int, expectedCursorPosition); + QFETCH(bool, selectionChanged); + QFETCH(bool, cursorPositionChanged); + + QString componentStr = "import QtQuick 2.2\nTextEdit { text: \"" + text + "\" }"; + QQmlComponent textEditComponent(&engine); + textEditComponent.setData(componentStr.toLatin1(), QUrl()); + QQuickTextEdit *textEdit = qobject_cast<QQuickTextEdit*>(textEditComponent.create()); + QVERIFY(textEdit != 0); + + textEdit->setTextFormat(textFormat); + textEdit->select(selectionStart, selectionEnd); + + QSignalSpy selectionSpy(textEdit, SIGNAL(selectedTextChanged())); + QSignalSpy selectionStartSpy(textEdit, SIGNAL(selectionStartChanged())); + QSignalSpy selectionEndSpy(textEdit, SIGNAL(selectionEndChanged())); + QSignalSpy textSpy(textEdit, SIGNAL(textChanged())); + QSignalSpy cursorPositionSpy(textEdit, SIGNAL(cursorPositionChanged())); + + textEdit->append(appendText); + + if (textFormat == QQuickTextEdit::RichText || (textFormat == QQuickTextEdit::AutoText && ( + Qt::mightBeRichText(text) || Qt::mightBeRichText(appendText)))) { + QCOMPARE(textEdit->getText(0, expectedText.length()), expectedText); + } else { + QCOMPARE(textEdit->text(), expectedText); + + } + QCOMPARE(textEdit->length(), expectedText.length()); + + QCOMPARE(textEdit->selectionStart(), expectedSelectionStart); + QCOMPARE(textEdit->selectionEnd(), expectedSelectionEnd); + QCOMPARE(textEdit->cursorPosition(), expectedCursorPosition); + + if (selectionStart > selectionEnd) + qSwap(selectionStart, selectionEnd); + + QEXPECT_FAIL("into selection", "selectedTextChanged signal isn't emitted on edits within selection", Continue); + QEXPECT_FAIL("into reversed selection", "selectedTextChanged signal isn't emitted on edits within selection", Continue); + QCOMPARE(selectionSpy.count() > 0, selectionChanged); + QCOMPARE(selectionStartSpy.count() > 0, selectionStart != expectedSelectionStart); + QEXPECT_FAIL("into reversed selection", "selectionEndChanged signal not emitted", Continue); + QCOMPARE(selectionEndSpy.count() > 0, selectionEnd != expectedSelectionEnd); + QCOMPARE(textSpy.count() > 0, text != expectedText); + QCOMPARE(cursorPositionSpy.count() > 0, cursorPositionChanged); +} + void tst_qquicktextedit::insert_data() { QTest::addColumn<QString>("text"); diff --git a/tests/auto/quick/qquicktextinput/tst_qquicktextinput.cpp b/tests/auto/quick/qquicktextinput/tst_qquicktextinput.cpp index b1648cbed2..7a61ceb7fd 100644 --- a/tests/auto/quick/qquicktextinput/tst_qquicktextinput.cpp +++ b/tests/auto/quick/qquicktextinput/tst_qquicktextinput.cpp @@ -3149,6 +3149,7 @@ void tst_qquicktextinput::echoMode() QCOMPARE(initial, QLatin1String("ABCDefgh")); QCOMPARE(input->echoMode(), QQuickTextInput::Normal); QCOMPARE(input->displayText(), input->text()); + const QString passwordMaskCharacter = qApp->styleHints()->passwordMaskCharacter(); //Normal ref &= ~Qt::ImhHiddenText; ref &= ~(Qt::ImhNoAutoUppercase | Qt::ImhNoPredictiveText | Qt::ImhSensitiveData); @@ -3156,7 +3157,7 @@ void tst_qquicktextinput::echoMode() input->setEchoMode(QQuickTextInput::NoEcho); QCOMPARE(input->text(), initial); QCOMPARE(input->displayText(), QLatin1String("")); - QCOMPARE(input->passwordCharacter(), QLatin1String("*")); + QCOMPARE(input->passwordCharacter(), passwordMaskCharacter); //NoEcho ref |= Qt::ImhHiddenText; ref |= (Qt::ImhNoAutoUppercase | Qt::ImhNoPredictiveText | Qt::ImhSensitiveData); @@ -3166,7 +3167,7 @@ void tst_qquicktextinput::echoMode() ref |= Qt::ImhHiddenText; ref |= (Qt::ImhNoAutoUppercase | Qt::ImhNoPredictiveText | Qt::ImhSensitiveData); QCOMPARE(input->text(), initial); - QCOMPARE(input->displayText(), QLatin1String("********")); + QCOMPARE(input->displayText(), QString(8, passwordMaskCharacter.at(0))); QCOMPARE((Qt::InputMethodHints) input->inputMethodQuery(Qt::ImHints).toInt(), ref); // clearing input hints do not clear bits set by echo mode input->setInputMethodHints(Qt::ImhNone); @@ -3221,7 +3222,7 @@ void tst_qquicktextinput::passwordEchoDelay() QQuickItem *cursor = input->findChild<QQuickItem *>("cursor"); QVERIFY(cursor); - QChar fillChar = QLatin1Char('*'); + QChar fillChar = qApp->styleHints()->passwordMaskCharacter(); input->setEchoMode(QQuickTextInput::Password); QCOMPARE(input->displayText(), QString(8, fillChar)); @@ -6124,6 +6125,12 @@ void tst_qquicktextinput::keypress_inputMask_data() keys << Qt::Key_Home << "12ab"; QTest::newRow("uppercase") << QString("9999 >AA;_") << keys << QString("12 AB") << QString("12__ AB"); } + { + KeyList keys; + // inserting '12ab' + keys << Qt::Key_Right << Qt::Key_Right << "1"; + QTest::newRow("Move in mask") << QString("#0:00;*") << keys << QString(":1") << QString("**:1*"); + } } void tst_qquicktextinput::keypress_inputMask() diff --git a/tests/auto/quick/qquickvisualdatamodel/tst_qquickvisualdatamodel.cpp b/tests/auto/quick/qquickvisualdatamodel/tst_qquickvisualdatamodel.cpp index d16bf81d88..d374d71280 100644 --- a/tests/auto/quick/qquickvisualdatamodel/tst_qquickvisualdatamodel.cpp +++ b/tests/auto/quick/qquickvisualdatamodel/tst_qquickvisualdatamodel.cpp @@ -615,6 +615,7 @@ void tst_qquickvisualdatamodel::childChanged() vdm->setRootIndex(QVariant::fromValue(model.indexFromItem(model.item(1,0)))); QCOMPARE(listview->count(), 1); + listview->forceLayout(); QQuickText *name = findItem<QQuickText>(contentItem, "display", 0); QVERIFY(name); QCOMPARE(name->text(), QString("Row 2 Child Item")); @@ -628,6 +629,7 @@ void tst_qquickvisualdatamodel::childChanged() model.item(1,0)->appendRow(new QStandardItem(QLatin1String("Row 2 Child Item 2"))); QCOMPARE(listview->count(), 2); + listview->forceLayout(); name = findItem<QQuickText>(contentItem, "display", 1); QVERIFY(name != 0); QCOMPARE(name->text(), QString("Row 2 Child Item 2")); @@ -638,6 +640,8 @@ void tst_qquickvisualdatamodel::childChanged() vdm->setRootIndex(QVariant::fromValue(QModelIndex())); QCOMPARE(listview->count(), 3); + + listview->forceLayout(); name = findItem<QQuickText>(contentItem, "display", 0); QVERIFY(name); QCOMPARE(name->text(), QString("Row 1 Item")); @@ -989,6 +993,8 @@ void tst_qquickvisualdatamodel::packagesDestroyed() QQuickItem *rightContent = rightview->contentItem(); QTRY_VERIFY(rightContent != 0); + leftview->forceLayout(); + rightview->forceLayout(); QCOMPARE(leftview->currentIndex(), 0); QCOMPARE(rightview->currentIndex(), 0); @@ -3548,6 +3554,7 @@ void tst_qquickvisualdatamodel::resolve() evaluate<void>(visualModel, setupExpression); QCOMPARE(evaluate<int>(listView, "count"), unresolvedCount); + listView->forceLayout(); evaluate<void>(visualModel, resolveExpression); QCOMPARE(evaluate<int>(listView, "count"), inItems ? visualCount : modelCount); diff --git a/tests/auto/quick/qquickwindow/data/active.qml b/tests/auto/quick/qquickwindow/data/active.qml new file mode 100644 index 0000000000..af0b7edeb2 --- /dev/null +++ b/tests/auto/quick/qquickwindow/data/active.qml @@ -0,0 +1,29 @@ +import QtQuick 2.1 +import QtQuick.Window 2.1 + +Window { + id: window1; + objectName: "window1"; + color: "#00FF00"; + width: 100; height: 100; + Item { + objectName: "item1" + width: 100; height: 100; + MouseArea { + objectName: "mousearea" + anchors.fill: parent; + onPressed: window2.requestActivate(); + } + Component.onCompleted: window2.show(); + } + + Window { + id: window2; + objectName: "window2"; + color: "#FF0000"; + width: 100; height: 100; + Item { + width: 100; height: 100; + } + } +} diff --git a/tests/auto/quick/qquickwindow/data/ucantclosethis.qml b/tests/auto/quick/qquickwindow/data/ucantclosethis.qml new file mode 100644 index 0000000000..aa68cf5105 --- /dev/null +++ b/tests/auto/quick/qquickwindow/data/ucantclosethis.qml @@ -0,0 +1,32 @@ +import QtQuick 2.1 +import QtQuick.Window 2.1 + +Window { + width: 240 + height: 75 + title: "Hammer sez" + color: "#e0c31e" + property bool canCloseThis: false; + Rectangle { + color: "#14148c" + width: parent.width * 0.85 + height: parent.height * 0.7 + anchors.horizontalCenter: parent.horizontalCenter + Text { + id: text + anchors.centerIn: parent + color: "white" + textFormat: Text.StyledText + text: "whoa-oa-oa-oh<br/>U can't <font color='#b40000' size='+1'>close</font> this" + } + } + onClosing: { + if (canCloseThis) { + text.text = "uncle! I give up" + // the event is accepted by default + } else { + close.accepted = false + text.text = "...but you still can't close this" + } + } +} diff --git a/tests/auto/quick/qquickwindow/qquickwindow.pro b/tests/auto/quick/qquickwindow/qquickwindow.pro index 05b58fcb4c..46cf96423f 100644 --- a/tests/auto/quick/qquickwindow/qquickwindow.pro +++ b/tests/auto/quick/qquickwindow/qquickwindow.pro @@ -11,6 +11,7 @@ QT += core-private gui-private qml-private quick-private testlib TESTDATA = data/* OTHER_FILES += \ + data/active.qml \ data/AnimationsWhileHidden.qml \ data/Headless.qml \ data/showHideAnimate.qml diff --git a/tests/auto/quick/qquickwindow/tst_qquickwindow.cpp b/tests/auto/quick/qquickwindow/tst_qquickwindow.cpp index 2d3c8f7ca7..e2bb6b431c 100644 --- a/tests/auto/quick/qquickwindow/tst_qquickwindow.cpp +++ b/tests/auto/quick/qquickwindow/tst_qquickwindow.cpp @@ -48,6 +48,7 @@ #include <QtQml/QQmlComponent> #include <QtQuick/private/qquickrectangle_p.h> #include "../../shared/util.h" +#include "../shared/visualtestutil.h" #include <QSignalSpy> #include <qpa/qwindowsysteminterface.h> #include <private/qquickwindow_p.h> @@ -304,6 +305,7 @@ private slots: void qmlCreation(); void clearColor(); + void grab_data(); void grab(); void multipleWindows(); @@ -322,6 +324,10 @@ private slots: void testExpose(); + void requestActivate(); + + void blockClosing(); + #ifndef QT_NO_CURSOR void cursor(); #endif @@ -929,15 +935,28 @@ void tst_qquickwindow::clearColor() QCOMPARE(window->color(), QColor(Qt::blue)); } +void tst_qquickwindow::grab_data() +{ + QTest::addColumn<bool>("visible"); + QTest::newRow("visible") << true; + QTest::newRow("invisible") << false; +} + void tst_qquickwindow::grab() { + QFETCH(bool, visible); + QQuickWindow window; window.setColor(Qt::red); window.resize(250, 250); - window.show(); - QVERIFY(QTest::qWaitForWindowExposed(&window)); + if (visible) { + window.show(); + QVERIFY(QTest::qWaitForWindowExposed(&window)); + } else { + window.create(); + } QImage content = window.grabWindow(); QCOMPARE(content.width(), window.width()); @@ -1400,6 +1419,74 @@ void tst_qquickwindow::testExpose() QTRY_COMPARE(swapSpy.size(), 1); } +void tst_qquickwindow::requestActivate() +{ + QQmlEngine engine; + QQmlComponent component(&engine); + component.loadUrl(testFileUrl("active.qml")); + QQuickWindow* window1 = qobject_cast<QQuickWindow *>(component.create()); + QVERIFY(window1); + + QWindowList windows = QGuiApplication::topLevelWindows(); + QVERIFY(windows.size() == 2); + + for (int i = 0; i < windows.size(); ++i) { + if (windows.at(i)->objectName() == window1->objectName()) { + windows.removeAt(i); + break; + } + } + QVERIFY(windows.size() == 1); + QVERIFY(windows.at(0)->objectName() == "window2"); + + window1->show(); + window1->requestActivate(); + + QTRY_VERIFY(QGuiApplication::focusWindow() == window1); + QVERIFY(window1->isActive() == true); + + QQuickItem *item = QQuickVisualTestUtil::findItem<QQuickItem>(window1->contentItem(), "item1"); + QVERIFY(item); + + //copied from src/qmltest/quicktestevent.cpp + QPoint pos = item->mapToScene(QPointF(item->width()/2, item->height()/2)).toPoint(); + + QMouseEvent me(QEvent::MouseButtonPress, pos, window1->mapToGlobal(pos), Qt::LeftButton, Qt::LeftButton, Qt::NoModifier); + QSpontaneKeyEvent::setSpontaneous(&me); + if (!qApp->notify(window1, &me)) { + QString warning = QString::fromLatin1("Mouse event MousePress not accepted by receiving window"); + QWARN(warning.toLatin1().data()); + } + me = QMouseEvent(QEvent::MouseButtonPress, pos, window1->mapToGlobal(pos), Qt::LeftButton, 0, Qt::NoModifier); + QSpontaneKeyEvent::setSpontaneous(&me); + if (!qApp->notify(window1, &me)) { + QString warning = QString::fromLatin1("Mouse event MouseRelease not accepted by receiving window"); + QWARN(warning.toLatin1().data()); + } + + QTRY_VERIFY(QGuiApplication::focusWindow() == windows.at(0)); + QVERIFY(windows.at(0)->isActive()); +} + +void tst_qquickwindow::blockClosing() +{ + QQmlEngine engine; + QQmlComponent component(&engine); + component.loadUrl(testFileUrl("ucantclosethis.qml")); + QQuickWindow* window = qobject_cast<QQuickWindow *>(component.create()); + QVERIFY(window); + window->show(); + QTest::qWaitForWindowExposed(window); + QVERIFY(window->isVisible()); + QWindowSystemInterface::handleCloseEvent(window); + QVERIFY(window->isVisible()); + QWindowSystemInterface::handleCloseEvent(window); + QVERIFY(window->isVisible()); + window->setProperty("canCloseThis", true); + QWindowSystemInterface::handleCloseEvent(window); + QTRY_VERIFY(!window->isVisible()); +} + QTEST_MAIN(tst_qquickwindow) #include "tst_qquickwindow.moc" diff --git a/tests/auto/quick/touchmouse/tst_touchmouse.cpp b/tests/auto/quick/touchmouse/tst_touchmouse.cpp index 15a4f0cc27..4779942406 100644 --- a/tests/auto/quick/touchmouse/tst_touchmouse.cpp +++ b/tests/auto/quick/touchmouse/tst_touchmouse.cpp @@ -195,8 +195,9 @@ void tst_TouchMouse::simpleTouchEvent() window->setSource(testFileUrl("singleitem.qml")); window->show(); - window->requestActivate(); QVERIFY(QTest::qWaitForWindowExposed(window)); + window->requestActivate(); + QVERIFY(QTest::qWaitForWindowActive(window)); QVERIFY(window->rootObject() != 0); EventItem *eventItem1 = window->rootObject()->findChild<EventItem*>("eventItem1"); @@ -344,7 +345,9 @@ void tst_TouchMouse::mouse() window->setSource(testFileUrl("twoitems.qml")); window->show(); + QVERIFY(QTest::qWaitForWindowExposed(window)); window->requestActivate(); + QVERIFY(QTest::qWaitForWindowActive(window)); QVERIFY(window->rootObject() != 0); EventItem *eventItem1 = window->rootObject()->findChild<EventItem*>("eventItem1"); @@ -376,7 +379,9 @@ void tst_TouchMouse::touchOverMouse() window->setSource(testFileUrl("twoitems.qml")); window->show(); + QVERIFY(QTest::qWaitForWindowExposed(window)); window->requestActivate(); + QVERIFY(QTest::qWaitForWindowActive(window)); QVERIFY(window->rootObject() != 0); EventItem *eventItem1 = window->rootObject()->findChild<EventItem*>("eventItem1"); @@ -417,7 +422,9 @@ void tst_TouchMouse::mouseOverTouch() window->setSource(testFileUrl("twoitems.qml")); window->show(); + QVERIFY(QTest::qWaitForWindowExposed(window)); window->requestActivate(); + QVERIFY(QTest::qWaitForWindowActive(window)); QVERIFY(window->rootObject() != 0); EventItem *eventItem1 = window->rootObject()->findChild<EventItem*>("eventItem1"); @@ -461,7 +468,9 @@ void tst_TouchMouse::buttonOnFlickable() window->setSource(testFileUrl("buttononflickable.qml")); window->show(); + QVERIFY(QTest::qWaitForWindowExposed(window)); window->requestActivate(); + QVERIFY(QTest::qWaitForWindowActive(window)); QVERIFY(window->rootObject() != 0); QQuickFlickable *flickable = window->rootObject()->findChild<QQuickFlickable*>("flickable"); @@ -569,7 +578,9 @@ void tst_TouchMouse::buttonOnTouch() QQuickView *window = createView(); window->setSource(testFileUrl("buttonontouch.qml")); window->show(); + QVERIFY(QTest::qWaitForWindowExposed(window)); window->requestActivate(); + QVERIFY(QTest::qWaitForWindowActive(window)); QVERIFY(window->rootObject() != 0); QQuickPinchArea *pinchArea = window->rootObject()->findChild<QQuickPinchArea*>("pincharea"); @@ -691,7 +702,9 @@ void tst_TouchMouse::pinchOnFlickable() QQuickView *window = createView(); window->setSource(testFileUrl("pinchonflickable.qml")); window->show(); + QVERIFY(QTest::qWaitForWindowExposed(window)); window->requestActivate(); + QVERIFY(QTest::qWaitForWindowActive(window)); QVERIFY(window->rootObject() != 0); QQuickPinchArea *pinchArea = window->rootObject()->findChild<QQuickPinchArea*>("pincharea"); @@ -758,7 +771,9 @@ void tst_TouchMouse::flickableOnPinch() QQuickView *window = createView(); window->setSource(testFileUrl("flickableonpinch.qml")); window->show(); + QVERIFY(QTest::qWaitForWindowExposed(window)); window->requestActivate(); + QVERIFY(QTest::qWaitForWindowActive(window)); QVERIFY(window->rootObject() != 0); QQuickPinchArea *pinchArea = window->rootObject()->findChild<QQuickPinchArea*>("pincharea"); @@ -935,8 +950,9 @@ void tst_TouchMouse::tapOnDismissiveTopMouseAreaClicksBottomOne() window->setSource(testFileUrl("twoMouseAreas.qml")); window->show(); - window->requestActivate(); QVERIFY(QTest::qWaitForWindowExposed(window)); + window->requestActivate(); + QVERIFY(QTest::qWaitForWindowActive(window)); QVERIFY(window->rootObject() != 0); QQuickMouseArea *bottomMouseArea = diff --git a/tests/auto/shared/testhttpserver.cpp b/tests/auto/shared/testhttpserver.cpp index 205d5cec5d..fd681710de 100644 --- a/tests/auto/shared/testhttpserver.cpp +++ b/tests/auto/shared/testhttpserver.cpp @@ -137,7 +137,19 @@ bool TestHTTPServer::wait(const QUrl &expect, const QUrl &reply, const QUrl &bod bodyData = bodyFile.readAll(); } - waitData = expectFile.readAll(); + QByteArray line; + bool headers_done = false; + while (!(line = expectFile.readLine()).isEmpty()) { + line.replace('\r', ""); + if (line.at(0) == '\n') { + headers_done = true; + continue; + } + if (headers_done) + waitData.body.append(line); + else + waitData.headers.append(line); + } /* while (waitData.endsWith('\n')) waitData = waitData.left(waitData.count() - 1); @@ -199,39 +211,38 @@ void TestHTTPServer::readyRead() QTcpSocket *socket = qobject_cast<QTcpSocket *>(sender()); if (!socket || socket->state() == QTcpSocket::ClosingState) return; - QByteArray ba = socket->readAll(); - if (!dirs.isEmpty()) { - serveGET(socket, ba); + serveGET(socket, socket->readAll()); return; } - if (m_hasFailed || waitData.isEmpty()) { - qWarning() << "TestHTTPServer: Unexpected data" << ba; + if (m_hasFailed || (waitData.body.isEmpty() && waitData.headers.count() == 0)) { + qWarning() << "TestHTTPServer: Unexpected data" << socket->readAll(); return; } - for (int ii = 0; ii < ba.count(); ++ii) { - const char c = ba.at(ii); - if (c == '\r' && waitData.isEmpty()) - continue; - else if (!waitData.isEmpty() && c == waitData.at(0)) - waitData = waitData.mid(1); - else if (c == '\r') - continue; - else { - QByteArray data = ba.mid(ii); - qWarning() << "TestHTTPServer: Unexpected data" << data << "\nExpected: " << waitData; + QByteArray line; + while (!(line = socket->readLine()).isEmpty()) { + line.replace('\r', ""); + if (line.at(0) == '\n') { + QByteArray data = socket->readAll(); + if (waitData.body != data) { + qWarning() << "TestHTTPServer: Unexpected data" << data << "\nExpected: " << waitData.body; + m_hasFailed = true; + socket->disconnectFromHost(); + return; + } + } + else if (!waitData.headers.contains(line)) { + qWarning() << "TestHTTPServer: Unexpected header:" << line << "\nExpected headers: " << waitData.headers; m_hasFailed = true; socket->disconnectFromHost(); return; } } - if (waitData.isEmpty()) { - socket->write(replyData); - socket->disconnectFromHost(); - } + socket->write(replyData); + socket->disconnectFromHost(); } bool TestHTTPServer::reply(QTcpSocket *socket, const QByteArray &fileName) diff --git a/tests/auto/shared/testhttpserver.h b/tests/auto/shared/testhttpserver.h index 15e08afd0c..ce0501f170 100644 --- a/tests/auto/shared/testhttpserver.h +++ b/tests/auto/shared/testhttpserver.h @@ -81,7 +81,10 @@ private: QHash<QTcpSocket *, QByteArray> dataCache; QList<QPair<QTcpSocket *, QByteArray> > toSend; - QByteArray waitData; + struct WaitData { + QList <QByteArray>headers; + QByteArray body; + } waitData; QByteArray replyData; QByteArray bodyData; bool m_hasFailed; diff --git a/tests/benchmarks/qml/animation/animation.pro b/tests/benchmarks/qml/animation/animation.pro index 58933cf038..e089884a7e 100644 --- a/tests/benchmarks/qml/animation/animation.pro +++ b/tests/benchmarks/qml/animation/animation.pro @@ -1,11 +1,10 @@ +CONFIG += testcase TEMPLATE = app TARGET = tst_animation -QT += qml +QT += qml testlib core-private gui-private qml-private quick-private macx:CONFIG -= app_bundle SOURCES += tst_animation.cpp DEFINES += SRCDIR=\\\"$$PWD\\\" - -QT += testlib core-private gui-private qml-private quick-private DEFINES += QT_DISABLE_DEPRECATED_BEFORE=0 diff --git a/tests/benchmarks/qml/compilation/tst_compilation.cpp b/tests/benchmarks/qml/compilation/tst_compilation.cpp index 148396622b..eac3dcc2dd 100644 --- a/tests/benchmarks/qml/compilation/tst_compilation.cpp +++ b/tests/benchmarks/qml/compilation/tst_compilation.cpp @@ -120,7 +120,6 @@ void tst_compilation::jsparser() QBENCHMARK { QQmlJS::Engine engine; - QQmlJS::NodePool nodePool(file, &engine); QQmlJS::Lexer lexer(&engine); lexer.setCode(code, -1); @@ -146,11 +145,14 @@ void tst_compilation::scriptparser() QVERIFY(f.open(QIODevice::ReadOnly)); QByteArray data = f.readAll(); + //TODO(pvarga): check preparseData + QByteArray preparseData; QUrl url = QUrl::fromLocalFile(file); + QString urlString = url.toString(); QBENCHMARK { QQmlScript::Parser parser; - parser.parse(data, url); + parser.parse(data, preparseData, url, urlString); parser.tree(); } } diff --git a/tests/benchmarks/qml/creation/creation.pro b/tests/benchmarks/qml/creation/creation.pro index 8d26ef88df..0cfac64d5f 100644 --- a/tests/benchmarks/qml/creation/creation.pro +++ b/tests/benchmarks/qml/creation/creation.pro @@ -1,11 +1,10 @@ CONFIG += testcase TEMPLATE = app TARGET = tst_creation +QT += core-private gui-private qml-private quick-private widgets testlib macx:CONFIG -= app_bundle SOURCES += tst_creation.cpp DEFINES += SRCDIR=\\\"$$PWD\\\" - -QT += core-private gui-private qml-private qtquick1-private widgets testlib DEFINES += QT_DISABLE_DEPRECATED_BEFORE=0 diff --git a/tests/benchmarks/qml/creation/tst_creation.cpp b/tests/benchmarks/qml/creation/tst_creation.cpp index 4b5c1d1950..b6b402a6c0 100644 --- a/tests/benchmarks/qml/creation/tst_creation.cpp +++ b/tests/benchmarks/qml/creation/tst_creation.cpp @@ -48,7 +48,6 @@ #include <QGraphicsItem> #include <QQuickItem> #include <QQmlContext> -#include <QtQuick1/private/qdeclarativetextinput_p.h> #include <private/qobject_p.h> class tst_creation : public QObject @@ -96,7 +95,7 @@ public: : QObject(parent) {} QQmlListProperty<QObject> resources() { - return QQmlListProperty<QObject>(this, 0, resources_append); + return QQmlListProperty<QObject>(this, 0, resources_append, 0, 0, 0); } static void resources_append(QQmlListProperty<QObject> *p, QObject *o) { @@ -107,9 +106,6 @@ public: tst_creation::tst_creation() { qmlRegisterType<TestType>("Qt.test", 1, 0, "TestType"); - - //get rid of initialization effects - QDeclarative1TextInput te; } inline QUrl TEST_FILE(const QString &filename) @@ -321,9 +317,7 @@ void tst_creation::itemtree_qml() void tst_creation::itemtree_scene_cpp() { - QGraphicsScene scene; QQuickItem *root = new QQuickItem; - scene.addItem(root); QBENCHMARK { QQuickItem *item = new QQuickItem; for (int i = 0; i < 30; ++i) { diff --git a/tests/benchmarks/qml/holistic/testtypes.cpp b/tests/benchmarks/qml/holistic/testtypes.cpp index 0a9e36dc3a..9b1bb86850 100644 --- a/tests/benchmarks/qml/holistic/testtypes.cpp +++ b/tests/benchmarks/qml/holistic/testtypes.cpp @@ -82,13 +82,13 @@ void registerTypes() qmlRegisterType<ScarceResourceProvider>("Qt.test", 1,0, "MyScarceResourceProvider"); qmlRegisterType<ArbitraryVariantProvider>("Qt.test", 1,0, "MyArbitraryVariantProvider"); - qmlRegisterSingletonType("Qt.test",1,0,script_api); // register (script) singleton Type for an existing uri which contains elements - qmlRegisterSingletonType<testQObjectApi>("Qt.test",1,0,qobject_api); // register (qobject) for an existing uri for which another singleton Type was previously regd. Should replace! - qmlRegisterSingletonType("Qt.test.scriptApi",1,0,script_api); // register (script) singleton Type for a uri which doesn't contain elements - qmlRegisterSingletonType<testQObjectApi>("Qt.test.qobjectApi",1,0,qobject_api); // register (qobject) singleton Type for a uri which doesn't contain elements - qmlRegisterSingletonType<testQObjectApi>("Qt.test.qobjectApi",1,3,qobject_api); // register (qobject) singleton Type for a uri which doesn't contain elements, minor version set - qmlRegisterSingletonType<testQObjectApi>("Qt.test.qobjectApi",2,0,qobject_api); // register (qobject) singleton Type for a uri which doesn't contain elements, major version set - qmlRegisterSingletonType<testQObjectApi>("Qt.test.qobjectApiParented",1,0,qobject_api_engine_parent); // register (parented qobject) singleton Type for a uri which doesn't contain elements + qmlRegisterSingletonType("Qt.test",1,0,"Script",script_api); // register (script) singleton Type for an existing uri which contains elements + qmlRegisterSingletonType<testQObjectApi>("Qt.test",1,0,"QObject",qobject_api); // register (qobject) for an existing uri for which another singleton Type was previously regd. Should replace! + qmlRegisterSingletonType("Qt.test.scriptApi",1,0,"Script",script_api); // register (script) singleton Type for a uri which doesn't contain elements + qmlRegisterSingletonType<testQObjectApi>("Qt.test.qobjectApi",1,0,"QObject",qobject_api); // register (qobject) singleton Type for a uri which doesn't contain elements + qmlRegisterSingletonType<testQObjectApi>("Qt.test.qobjectApi",1,3,"QObject",qobject_api); // register (qobject) singleton Type for a uri which doesn't contain elements, minor version set + qmlRegisterSingletonType<testQObjectApi>("Qt.test.qobjectApi",2,0,"QObject",qobject_api); // register (qobject) singleton Type for a uri which doesn't contain elements, major version set + qmlRegisterSingletonType<testQObjectApi>("Qt.test.qobjectApiParented",1,0,"QObject",qobject_api_engine_parent); // register (parented qobject) singleton Type for a uri which doesn't contain elements } //#include "testtypes.moc" diff --git a/tests/benchmarks/qml/painting/paintbenchmark.cpp b/tests/benchmarks/qml/painting/paintbenchmark.cpp index b99161749d..1fc7813c04 100644 --- a/tests/benchmarks/qml/painting/paintbenchmark.cpp +++ b/tests/benchmarks/qml/painting/paintbenchmark.cpp @@ -180,6 +180,8 @@ void paint_RoundedRect(QPainter &p) } } +// Disable this test case since this cannot be compiled with Qt5. +#if 0 void paint_QPixmapCachedRoundedRect(QPainter &p) { static bool first = true; @@ -218,6 +220,7 @@ void paint_QPixmapCachedRoundedRect(QPainter &p) } } } +#endif void paint_pathCacheRoundedRect(QPainter &p) { @@ -312,7 +315,7 @@ struct { { "QStaticTextWithBackendOptimizations", &paint_QStaticText_optimizations }, { "CachedText", &paint_QPixmapCachedText }, { "RoundedRect", &paint_RoundedRect }, - { "CachedRoundedRect", &paint_QPixmapCachedRoundedRect }, + // { "CachedRoundedRect", &paint_QPixmapCachedRoundedRect }, { "PathCacheRoundedRect", &paint_pathCacheRoundedRect }, { "QPixmap63x63_opaque", &paint_QPixmap63x63_opaque }, { "QPixmap64x64_opaque", &paint_QPixmap64x64_opaque }, diff --git a/tests/benchmarks/qml/pointers/pointers.pro b/tests/benchmarks/qml/pointers/pointers.pro index 1db474428d..b9b44abb0f 100644 --- a/tests/benchmarks/qml/pointers/pointers.pro +++ b/tests/benchmarks/qml/pointers/pointers.pro @@ -1,5 +1,5 @@ CONFIG += testcase -QT += qml testlib +QT += core-private v8-private qml-private testlib TEMPLATE = app TARGET = tst_pointers macx:CONFIG -= app_bundle diff --git a/tests/benchmarks/qml/pointers/tst_pointers.cpp b/tests/benchmarks/qml/pointers/tst_pointers.cpp index 65dda28fe7..0c25030c7f 100644 --- a/tests/benchmarks/qml/pointers/tst_pointers.cpp +++ b/tests/benchmarks/qml/pointers/tst_pointers.cpp @@ -40,7 +40,7 @@ ****************************************************************************/ #include <qtest.h> -#include "private/qqmlguard_p.h" +#include <QtQml/private/qqmlguard_p.h> #include <QWeakPointer> class tst_pointers : public QObject diff --git a/tests/benchmarks/qml/qquickwindow/tst_qquickwindow.cpp b/tests/benchmarks/qml/qquickwindow/tst_qquickwindow.cpp index 01ddd70838..20e5fb6c64 100644 --- a/tests/benchmarks/qml/qquickwindow/tst_qquickwindow.cpp +++ b/tests/benchmarks/qml/qquickwindow/tst_qquickwindow.cpp @@ -63,9 +63,9 @@ tst_qquickwindow::tst_qquickwindow() { window = new QQuickWindow; window->resize(250, 250); - window->setPos(100, 100); + window->setPosition(100, 100); for ( int i=0; i<8000; i++ ) { - QQuickRectangle *r =new QQuickRectangle(window->rootItem()); + QQuickRectangle *r =new QQuickRectangle(window->contentItem()); for ( int j=0; j<10; ++j ) { new QQuickRectangle(r); } diff --git a/tests/benchmarks/qml/typeimports/tst_typeimports.cpp b/tests/benchmarks/qml/typeimports/tst_typeimports.cpp index c24e344a6b..5871565ace 100644 --- a/tests/benchmarks/qml/typeimports/tst_typeimports.cpp +++ b/tests/benchmarks/qml/typeimports/tst_typeimports.cpp @@ -67,7 +67,7 @@ public: TestType1(QObject *parent = 0) : QObject(parent) {} QQmlListProperty<QObject> resources() { - return QQmlListProperty<QObject>(this, 0, resources_append); + return QQmlListProperty<QObject>(this, 0, resources_append, 0, 0, 0); } static void resources_append(QQmlListProperty<QObject> *p, QObject *o) { diff --git a/tests/manual/qmltypememory/README b/tests/manual/qmltypememory/README new file mode 100644 index 0000000000..b1237a1fc7 --- /dev/null +++ b/tests/manual/qmltypememory/README @@ -0,0 +1,3 @@ +This test just continually builds up and tears down a QML scene. Watch over a long period to see if the memory usage goes up. + +This test specifically is targeting the QQmlType cache which is a global static. diff --git a/tests/manual/qmltypememory/TestPlugin/plugin.cpp b/tests/manual/qmltypememory/TestPlugin/plugin.cpp new file mode 100644 index 0000000000..40c2af20f5 --- /dev/null +++ b/tests/manual/qmltypememory/TestPlugin/plugin.cpp @@ -0,0 +1,63 @@ +/**************************************************************************** +** +** Copyright (C) 2013 Research In Motion. +** Contact: http://www.qt-project.org/legal +** +** This file is part of the tests 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$ +** +****************************************************************************/ + +#include <QtQml/QQmlExtensionPlugin> +#include <QtQml/qqml.h> +#include <qdebug.h> + +class TestType : public QObject +{ + Q_OBJECT +}; + +class TestPlugin : public QQmlExtensionPlugin +{ + Q_OBJECT + Q_PLUGIN_METADATA(IID "org.qt-project.Qt.QQmlExtensionInterface") + +public: + void registerTypes(const char *uri) + { + Q_ASSERT(uri == QLatin1String("TestPlugin")); + qmlRegisterType<TestType>(uri, 1, 0, "TestTypePlugin"); + } +}; + +#include "plugin.moc" diff --git a/tests/manual/qmltypememory/TestPlugin/plugin.pro b/tests/manual/qmltypememory/TestPlugin/plugin.pro new file mode 100644 index 0000000000..7575442800 --- /dev/null +++ b/tests/manual/qmltypememory/TestPlugin/plugin.pro @@ -0,0 +1,7 @@ +TEMPLATE = lib +CONFIG += plugin +QT += qml + +TARGET = testplugin + +SOURCES += plugin.cpp diff --git a/tests/manual/qmltypememory/TestPlugin/qmldir b/tests/manual/qmltypememory/TestPlugin/qmldir new file mode 100644 index 0000000000..f0624dfd82 --- /dev/null +++ b/tests/manual/qmltypememory/TestPlugin/qmldir @@ -0,0 +1,2 @@ +module TestPlugin +plugin testplugin diff --git a/tests/manual/qmltypememory/TestType.qml b/tests/manual/qmltypememory/TestType.qml new file mode 100644 index 0000000000..59e0bcf477 --- /dev/null +++ b/tests/manual/qmltypememory/TestType.qml @@ -0,0 +1,43 @@ +/**************************************************************************** +** +** Copyright (C) 2013 Research In Motion. +** Contact: http://www.qt-project.org/legal +** +** This file is part of the manual tests 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 2.0 +QtObject{property int notJustAStandardQtObject: 10 } diff --git a/tests/manual/qmltypememory/main.cpp b/tests/manual/qmltypememory/main.cpp new file mode 100644 index 0000000000..da086ec9f7 --- /dev/null +++ b/tests/manual/qmltypememory/main.cpp @@ -0,0 +1,56 @@ +/**************************************************************************** +** +** Copyright (C) 2013 Research In Motion. +** Contact: http://www.qt-project.org/legal +** +** This file is part of the manual tests 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 <QtQml> +#include <QGuiApplication> +#include "testdriver.h" + +int main (int argc, char* argv[]) +{ + QGuiApplication app(argc, argv); + int i = -1; + if (argc > 1) + i = atoi(argv[1]); + if (i < 1) + i = -1; + TestDriver td(QUrl::fromLocalFile("main.qml"), i); + return app.exec(); +} diff --git a/tests/manual/qmltypememory/main.qml b/tests/manual/qmltypememory/main.qml new file mode 100644 index 0000000000..7bc9006aec --- /dev/null +++ b/tests/manual/qmltypememory/main.qml @@ -0,0 +1,54 @@ +/**************************************************************************** +** +** Copyright (C) 2013 Research In Motion. +** Contact: http://www.qt-project.org/legal +** +** This file is part of the manual tests 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 2.0 +import QtQuick 2.0 +import QtQuick.Window 2.0 +import QtQuick.LocalStorage 2.0 +import Test 2.0 +import TestPlugin 1.0 +import "." + +QtObject { + property TestType tt //No object, although it should be properly parented if there were one + property TestTypeCpp tt2 //No object, although it should be properly parented if there were one + property TestTypePlugin tt3 +} diff --git a/tests/manual/qmltypememory/qmldir b/tests/manual/qmltypememory/qmldir new file mode 100644 index 0000000000..edb8c894c4 --- /dev/null +++ b/tests/manual/qmltypememory/qmldir @@ -0,0 +1,2 @@ +TestFromDir 2.0 TestType.qml +internal TestFromDirInt TestType.qml diff --git a/tests/manual/qmltypememory/qmltypememory.pro b/tests/manual/qmltypememory/qmltypememory.pro new file mode 100644 index 0000000000..2bd873d554 --- /dev/null +++ b/tests/manual/qmltypememory/qmltypememory.pro @@ -0,0 +1,8 @@ +TEMPLATE = app +TARGET = qmltypememory +INCLUDEPATH += . +QT += qml + +# Input +HEADERS += testdriver.h +SOURCES += main.cpp testdriver.cpp diff --git a/tests/manual/qmltypememory/testdriver.cpp b/tests/manual/qmltypememory/testdriver.cpp new file mode 100644 index 0000000000..42de18c4d4 --- /dev/null +++ b/tests/manual/qmltypememory/testdriver.cpp @@ -0,0 +1,105 @@ +/**************************************************************************** +** +** Copyright (C) 2013 Research In Motion. +** Contact: http://www.qt-project.org/legal +** +** This file is part of the manual tests 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 "testdriver.h" +#include <QCoreApplication> +const int interval = 0; + +QObject* singleFactory(QQmlEngine *, QJSEngine*) +{ + QObject* ret = new QObject; //NOTE: No parent - but also shouldn't need to be created + return ret; +} + +TestDriver::TestDriver(const QUrl &componentUrl, int maxIter) + : QObject(0), e(0), c(0), i(maxIter) +{ + testFile = componentUrl; + QTimer::singleShot(interval, this, SLOT(setUp())); +} + +void TestDriver::setUp() +{ + qmlRegisterType<TestType>("Test", 2, 0, "TestTypeCpp"); + for (int j=2; j<1000; j++) { + qmlRegisterType<TestType>("Test", j, 0, "TestType"); + qmlRegisterType<TestType>("Test", j, 1, "TestType"); + qmlRegisterType<TestType>("Test", j, 2, "TestType"); + qmlRegisterType<TestType>("Test", j, 3, "TestType"); + qmlRegisterType<TestType>("Test", j, 4, "TestType"); + qmlRegisterType<TestType>("Test", j, 5, "TestType"); + qmlRegisterType<TestType>("Test", j, 6, "TestType"); + qmlRegisterType<TestType>("Test", j, 7, "TestType"); + qmlRegisterType<TestType>("Test", j, 8, "TestType"); + qmlRegisterType<TestType>("Test", j, 9, "TestType"); + } + qmlRegisterType<TestType>("Test2", 1, 0, "TestType"); + qmlRegisterType<TestType>("Test2", 3, 0, "TestType"); + qmlRegisterType<TestType>("Test3", 9, 0, "TestType"); + qmlRegisterType(QUrl::fromLocalFile(QDir::currentPath() + QLatin1String("TestType.qml")), "Test", 2, 0, "TestType2"); + qmlRegisterUncreatableType<TestType2>("Test", 2, 0, "CannotDoThis", QLatin1String("Just don't")); + qmlRegisterType<TestType3>(); + qmlRegisterSingletonType<QObject>("Test", 2, 0, "Singlet", singleFactory); + + e = new QQmlEngine(this); + c = new QQmlComponent(e, testFile); + QObject* unused = c->create(); + if (!unused) { + qDebug() << "Creation failure" << c->errorString(); + exit(1); + } + unused->setParent(c); //Not testing leaky objects in the tree + QTimer::singleShot(interval, this, SLOT(tearDown())); +} + +void TestDriver::tearDown() +{ + delete c; + e->collectGarbage(); + delete e; + qmlClearTypeRegistrations(); + //Note that i < 0 will effectively never terminate. This is deliberate as a prime use is to run indefinitely and watch the memory *not* grow + i--; + if (!i) + qApp->quit(); + else + QTimer::singleShot(interval, this, SLOT(setUp())); +} diff --git a/tests/manual/qmltypememory/testdriver.h b/tests/manual/qmltypememory/testdriver.h new file mode 100644 index 0000000000..711a725aa1 --- /dev/null +++ b/tests/manual/qmltypememory/testdriver.h @@ -0,0 +1,65 @@ +/**************************************************************************** +** +** Copyright (C) 2013 Research In Motion. +** Contact: http://www.qt-project.org/legal +** +** This file is part of the manual tests 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$ +** +****************************************************************************/ + +#ifndef TESTDRIVER_H +#define TESTDRIVER_H +#include <QtCore> +#include <QtQml> + +class TestDriver : public QObject +{ + Q_OBJECT +public: + TestDriver(const QUrl &componentUrl, int maxIter = -1); +public slots: + void setUp(); + void tearDown(); +private: + QUrl testFile; + QQmlEngine* e; + QQmlComponent* c; + signed long int i; +}; + +class TestType : public QObject { Q_OBJECT }; +class TestType2 : public QObject { Q_OBJECT }; +class TestType3 : public QObject { Q_OBJECT }; +#endif diff --git a/tests/testapplications/elements/content/Help.qml b/tests/testapplications/elements/content/Help.qml index 1e1e26e26c..cb534108b1 100644 --- a/tests/testapplications/elements/content/Help.qml +++ b/tests/testapplications/elements/content/Help.qml @@ -45,7 +45,7 @@ Item { anchors.fill: parent Text { textFormat: Text.RichText; anchors.fill: parent; anchors.margins: 5; wrapMode: Text.WordWrap - text: "<b>QtQuick 2 System Testing</b><br><br>"+ + text: "<b>Qt Quick 2 System Testing</b><br><br>"+ "Each system test qml \"application\" provides a basic visual element affected by one or more non-visual (functional) elements.<br>"+ "Simply select the element you wish to test, and follow the instructions. Use the arrow to advance the test.<br>" } diff --git a/tests/testapplications/text/textedit.qml b/tests/testapplications/text/textedit.qml index e0d7dbdde4..6546abfe91 100644 --- a/tests/testapplications/text/textedit.qml +++ b/tests/testapplications/text/textedit.qml @@ -144,7 +144,7 @@ Rectangle { "and a language runtime. "+ "A collection of C++ APIs is used to integrate these high level features with classic Qt applications."}); textmodel.append({ "name": "Links", - "value": "This is a link - <a href=\"http://doc.qt.nokia.com\">Qt Docs</a>"}); + "value": "This is a link - <a href=\"http://qt-project.org/doc\">Qt Docs</a>"}); } } ControlView { |