diff options
author | Kent Hansen <kent.hansen@nokia.com> | 2012-03-23 14:31:47 +0100 |
---|---|---|
committer | Kent Hansen <kent.hansen@nokia.com> | 2012-03-23 14:31:47 +0100 |
commit | 0655209fdad022bd0f6eb20ce85522cb56506bf0 (patch) | |
tree | cdba0c1590655f5cb75a68cedff74f8a683db3a2 /tests | |
parent | c3babc03c99c6ca5fa210486e133eb456a405bab (diff) | |
parent | 3d8f103c2641f35e7681485102a1b59886db8934 (diff) |
Merge master into api_changes
Conflicts:
src/qml/qml/qqmlboundsignal.cpp
src/qml/qml/qqmlpropertycache.cpp
Change-Id: I5193a193fa301c0b518291645bf626a5fa07118f
Diffstat (limited to 'tests')
103 files changed, 6231 insertions, 2416 deletions
diff --git a/tests/auto/qml/debugger/debugger.pro b/tests/auto/qml/debugger/debugger.pro index 7669aaa83c..81ca29a2e0 100644 --- a/tests/auto/qml/debugger/debugger.pro +++ b/tests/auto/qml/debugger/debugger.pro @@ -1,9 +1,7 @@ TEMPLATE = subdirs -PRIVATETESTS += \ +PUBLICTESTS += \ qqmlenginedebugservice \ - qqmldebugclient \ - qqmldebugservice \ qqmldebugjs \ qqmlinspector \ qqmlprofilerservice \ @@ -11,6 +9,12 @@ PRIVATETESTS += \ qv8profilerservice \ qdebugmessageservice +PRIVATETESTS += \ + qqmldebugclient \ + qqmldebugservice + +SUBDIRS += $$PUBLICTESTS + contains(QT_CONFIG, private_tests) { SUBDIRS += $$PRIVATETESTS } diff --git a/tests/auto/qml/debugger/qdebugmessageservice/qdebugmessageservice.pro b/tests/auto/qml/debugger/qdebugmessageservice/qdebugmessageservice.pro index 4b5bf60ace..64f7274f6f 100644 --- a/tests/auto/qml/debugger/qdebugmessageservice/qdebugmessageservice.pro +++ b/tests/auto/qml/debugger/qdebugmessageservice/qdebugmessageservice.pro @@ -1,6 +1,6 @@ CONFIG += testcase TARGET = tst_qdebugmessageservice -QT += network qml-private testlib +QT += qml network testlib macx:CONFIG -= app_bundle SOURCES += tst_qdebugmessageservice.cpp diff --git a/tests/auto/qml/debugger/qpacketprotocol/qpacketprotocol.pro b/tests/auto/qml/debugger/qpacketprotocol/qpacketprotocol.pro index f631929427..e6869fe5cb 100644 --- a/tests/auto/qml/debugger/qpacketprotocol/qpacketprotocol.pro +++ b/tests/auto/qml/debugger/qpacketprotocol/qpacketprotocol.pro @@ -8,4 +8,4 @@ INCLUDEPATH += ../shared include(../shared/debugutil.pri) CONFIG += parallel_test -QT += qml-private network testlib +QT += qml network testlib diff --git a/tests/auto/qml/debugger/qpacketprotocol/tst_qpacketprotocol.cpp b/tests/auto/qml/debugger/qpacketprotocol/tst_qpacketprotocol.cpp index 4a6efb469d..8a8c0e5081 100644 --- a/tests/auto/qml/debugger/qpacketprotocol/tst_qpacketprotocol.cpp +++ b/tests/auto/qml/debugger/qpacketprotocol/tst_qpacketprotocol.cpp @@ -46,7 +46,7 @@ #include <QDebug> #include <QBuffer> -#include <private/qpacketprotocol_p.h> +#include "../../../../../src/plugins/qmltooling/shared/qpacketprotocol.h" #include "debugutil_p.h" diff --git a/tests/auto/qml/debugger/qqmldebugclient/qqmldebugclient.pro b/tests/auto/qml/debugger/qqmldebugclient/qqmldebugclient.pro index 22a4df7dc9..60355f1527 100644 --- a/tests/auto/qml/debugger/qqmldebugclient/qqmldebugclient.pro +++ b/tests/auto/qml/debugger/qqmldebugclient/qqmldebugclient.pro @@ -2,7 +2,10 @@ CONFIG += testcase TARGET = tst_qqmldebugclient macx:CONFIG -= app_bundle -SOURCES += tst_qqmldebugclient.cpp +HEADERS += ../shared/qqmldebugtestservice.h + +SOURCES += tst_qqmldebugclient.cpp \ + ../shared/qqmldebugtestservice.cpp INCLUDEPATH += ../shared include(../shared/debugutil.pri) diff --git a/tests/auto/qml/debugger/qqmldebugclient/tst_qqmldebugclient.cpp b/tests/auto/qml/debugger/qqmldebugclient/tst_qqmldebugclient.cpp index 1682913bc3..2d52ea9f50 100644 --- a/tests/auto/qml/debugger/qqmldebugclient/tst_qqmldebugclient.cpp +++ b/tests/auto/qml/debugger/qqmldebugclient/tst_qqmldebugclient.cpp @@ -48,6 +48,7 @@ #include <QtQml/qqmlengine.h> #include "debugutil_p.h" +#include "qqmldebugtestservice.h" #define PORT 13770 #define STR_PORT "13770" diff --git a/tests/auto/qml/debugger/qqmldebugjs/data/breakpointRelocation.qml b/tests/auto/qml/debugger/qqmldebugjs/data/breakpointRelocation.qml index 1f0f9e22c9..0a1a5eb610 100644 --- a/tests/auto/qml/debugger/qqmldebugjs/data/breakpointRelocation.qml +++ b/tests/auto/qml/debugger/qqmldebugjs/data/breakpointRelocation.qml @@ -47,7 +47,9 @@ Item { Component.onCompleted: { //Comment - var b = 6; + var x = 6; } + + width : height + 2 } diff --git a/tests/auto/qml/debugger/qqmldebugjs/qqmldebugjs.pro b/tests/auto/qml/debugger/qqmldebugjs/qqmldebugjs.pro index 7c3a2ea042..c06fd84e58 100644 --- a/tests/auto/qml/debugger/qqmldebugjs/qqmldebugjs.pro +++ b/tests/auto/qml/debugger/qqmldebugjs/qqmldebugjs.pro @@ -1,6 +1,6 @@ CONFIG += testcase TARGET = tst_qqmldebugjs -QT += qml-private testlib +QT += qml testlib macx:CONFIG -= app_bundle SOURCES += tst_qqmldebugjs.cpp diff --git a/tests/auto/qml/debugger/qqmldebugjs/tst_qqmldebugjs.cpp b/tests/auto/qml/debugger/qqmldebugjs/tst_qqmldebugjs.cpp index f4a9a4add7..8293ec6cda 100644 --- a/tests/auto/qml/debugger/qqmldebugjs/tst_qqmldebugjs.cpp +++ b/tests/auto/qml/debugger/qqmldebugjs/tst_qqmldebugjs.cpp @@ -191,6 +191,7 @@ private slots: void setBreakpointInScriptInDifferentFile(); void setBreakpointInScriptOnComment(); void setBreakpointInScriptOnEmptyLine(); + void setBreakpointInScriptOnOptimizedBinding(); void setBreakpointInScriptWithCondition(); //void setBreakpointInFunction(); //NOT SUPPORTED void setBreakpointOnEvent(); @@ -1019,9 +1020,6 @@ bool tst_QQmlDebugJS::init(const QString &qmlFile, bool blockMode) process = new QQmlDebugProcess(QLibraryInfo::location(QLibraryInfo::BinariesPath) + "/qmlscene"); client = new QJSDebugClient(connection); - QStringList systemEnvironment = QProcess::systemEnvironment(); - systemEnvironment << "QML_DISABLE_OPTIMIZER=1"; - process->setEnvironment(systemEnvironment); if (blockMode) process->start(QStringList() << QLatin1String(BLOCKMODE) << testFile(qmlFile)); else @@ -1295,6 +1293,26 @@ void tst_QQmlDebugJS::setBreakpointInScriptOnEmptyLine() QCOMPARE(QFileInfo(body.value("script").toMap().value("name").toString()).fileName(), QLatin1String(BREAKPOINTRELOCATION_QMLFILE)); } +void tst_QQmlDebugJS::setBreakpointInScriptOnOptimizedBinding() +{ + //void setBreakpoint(QString type, QString target, int line = -1, int column = -1, bool enabled = false, QString condition = QString(), int ignoreCount = -1) + + int sourceLine = 52; + QVERIFY(init(BREAKPOINTRELOCATION_QMLFILE)); + + client->setBreakpoint(QLatin1String(SCRIPTREGEXP), QLatin1String(BREAKPOINTRELOCATION_QMLFILE), sourceLine, -1, true); + client->connect(); + QVERIFY(QQmlDebugTest::waitForSignal(client, SIGNAL(stopped()))); + + QString jsonString(client->response); + QVariantMap value = client->parser.call(QJSValueList() << QJSValue(jsonString)).toVariant().toMap(); + + QVariantMap body = value.value("body").toMap(); + + QCOMPARE(body.value("sourceLine").toInt(), sourceLine); + QCOMPARE(QFileInfo(body.value("script").toMap().value("name").toString()).fileName(), QLatin1String(BREAKPOINTRELOCATION_QMLFILE)); +} + void tst_QQmlDebugJS::setBreakpointInScriptWithCondition() { //void setBreakpoint(QString type, QString target, int line = -1, int column = -1, bool enabled = false, QString condition = QString(), int ignoreCount = -1) diff --git a/tests/auto/qml/debugger/qqmldebugservice/qqmldebugservice.pro b/tests/auto/qml/debugger/qqmldebugservice/qqmldebugservice.pro index dc2039615a..bbf05b177c 100644 --- a/tests/auto/qml/debugger/qqmldebugservice/qqmldebugservice.pro +++ b/tests/auto/qml/debugger/qqmldebugservice/qqmldebugservice.pro @@ -2,7 +2,11 @@ CONFIG += testcase TARGET = tst_qqmldebugservice macx:CONFIG -= app_bundle -SOURCES += tst_qqmldebugservice.cpp +HEADERS += ../shared/qqmldebugtestservice.h + +SOURCES += tst_qqmldebugservice.cpp \ + ../shared/qqmldebugtestservice.cpp + INCLUDEPATH += ../shared include(../../../shared/util.pri) include(../shared/debugutil.pri) diff --git a/tests/auto/qml/debugger/qqmldebugservice/tst_qqmldebugservice.cpp b/tests/auto/qml/debugger/qqmldebugservice/tst_qqmldebugservice.cpp index 6e14c03a4c..8eb1523af9 100644 --- a/tests/auto/qml/debugger/qqmldebugservice/tst_qqmldebugservice.cpp +++ b/tests/auto/qml/debugger/qqmldebugservice/tst_qqmldebugservice.cpp @@ -47,11 +47,10 @@ #include <QtQml/qqmlengine.h> -#include <private/qqmldebugservice_p.h> - #include "../../../shared/util.h" #include "debugutil_p.h" #include "qqmldebugclient.h" +#include "qqmldebugtestservice.h" #define PORT 13769 #define STR_PORT "13769" @@ -204,7 +203,7 @@ int main(int argc, char *argv[]) char **_argv = new char*[_argc]; for (int i = 0; i < argc; ++i) _argv[i] = argv[i]; - char arg[] = "-qmljsdebugger=port:" STR_PORT; + char arg[] = "-qmljsdebugger=port:" STR_PORT ",host:127.0.0.1"; _argv[_argc - 1] = arg; QGuiApplication app(_argc, _argv); diff --git a/tests/auto/qml/debugger/qqmlenginedebugservice/qqmlenginedebugclient.cpp b/tests/auto/qml/debugger/qqmlenginedebugservice/qqmlenginedebugclient.cpp new file mode 100644 index 0000000000..9639a36065 --- /dev/null +++ b/tests/auto/qml/debugger/qqmlenginedebugservice/qqmlenginedebugclient.cpp @@ -0,0 +1,460 @@ +/**************************************************************************** +** +** Copyright (C) 2012 Nokia Corporation and/or its subsidiary(-ies). +** Contact: http://www.qt-project.org/ +** +** This file is part of the QtQml module of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** GNU Lesser General Public License Usage +** 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, Nokia gives you certain additional +** rights. These rights are described in the Nokia 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. +** +** Other Usage +** Alternatively, this file may be used in accordance with the terms and +** conditions contained in a signed written agreement between you and Nokia. +** +** +** +** +** +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#include "qqmlenginedebugclient.h" + +struct QmlObjectData { + QUrl url; + int lineNumber; + int columnNumber; + QString idString; + QString objectName; + QString objectType; + int objectId; + int contextId; +}; + +QDataStream &operator>>(QDataStream &ds, QmlObjectData &data) +{ + ds >> data.url >> data.lineNumber >> data.columnNumber >> data.idString + >> data.objectName >> data.objectType >> data.objectId >> data.contextId; + return ds; +} + +struct QmlObjectProperty { + enum Type { Unknown, Basic, Object, List, SignalProperty }; + Type type; + QString name; + QVariant value; + QString valueTypeName; + QString binding; + bool hasNotifySignal; +}; + +QDataStream &operator>>(QDataStream &ds, QmlObjectProperty &data) +{ + int type; + ds >> type >> data.name >> data.value >> data.valueTypeName + >> data.binding >> data.hasNotifySignal; + data.type = (QmlObjectProperty::Type)type; + return ds; +} + +QQmlEngineDebugClient::QQmlEngineDebugClient( + QQmlDebugConnection *connection) + : QQmlDebugClient(QLatin1String("QmlDebugger"), connection), + m_nextId(0), + m_valid(false) +{ +} + +quint32 QQmlEngineDebugClient::addWatch( + const QmlDebugPropertyReference &property, bool *success) +{ + quint32 id; + *success = false; + if (state() == QQmlDebugClient::Enabled) { + id = getId(); + QByteArray message; + QDataStream ds(&message, QIODevice::WriteOnly); + ds << QByteArray("WATCH_PROPERTY") << id << property.objectDebugId + << property.name.toUtf8(); + sendMessage(message); + *success = true; + } + return id; +} + +quint32 QQmlEngineDebugClient::addWatch( + const QmlDebugContextReference &, const QString &, bool *success) +{ + *success = false; + qWarning("QQmlEngineDebugClient::addWatch(): Not implemented"); + return 0; +} + +quint32 QQmlEngineDebugClient::addWatch( + const QmlDebugObjectReference &object, const QString &expr, + bool *success) +{ + quint32 id; + *success = false; + if (state() == QQmlDebugClient::Enabled) { + id = getId(); + QByteArray message; + QDataStream ds(&message, QIODevice::WriteOnly); + ds << QByteArray("WATCH_EXPR_OBJECT") << id << object.debugId << expr; + sendMessage(message); + *success = true; + } + return id; +} + +quint32 QQmlEngineDebugClient::addWatch( + const QmlDebugObjectReference &object, bool *success) +{ + quint32 id; + *success = false; + if (state() == QQmlDebugClient::Enabled) { + id = getId(); + QByteArray message; + QDataStream ds(&message, QIODevice::WriteOnly); + ds << QByteArray("WATCH_OBJECT") << id << object.debugId; + sendMessage(message); + *success = true; + } + return id; +} + +quint32 QQmlEngineDebugClient::addWatch( + const QmlDebugFileReference &, bool *success) +{ + *success = false; + qWarning("QQmlEngineDebugClient::addWatch(): Not implemented"); + return 0; +} + +void QQmlEngineDebugClient::removeWatch(quint32 id, bool *success) +{ + *success = false; + if (state() == QQmlDebugClient::Enabled) { + QByteArray message; + QDataStream ds(&message, QIODevice::WriteOnly); + ds << QByteArray("NO_WATCH") << id; + sendMessage(message); + *success = true; + } +} + +quint32 QQmlEngineDebugClient::queryAvailableEngines(bool *success) +{ + m_engines.clear(); + quint32 id; + *success = false; + if (state() == QQmlDebugClient::Enabled) { + id = getId(); + QByteArray message; + QDataStream ds(&message, QIODevice::WriteOnly); + ds << QByteArray("LIST_ENGINES") << id; + sendMessage(message); + *success = true; + } + return id; +} + +quint32 QQmlEngineDebugClient::queryRootContexts( + const QmlDebugEngineReference &engine, bool *success) +{ + m_rootContext = QmlDebugContextReference(); + quint32 id; + *success = false; + if (state() == QQmlDebugClient::Enabled && engine.debugId != -1) { + id = getId(); + QByteArray message; + QDataStream ds(&message, QIODevice::WriteOnly); + ds << QByteArray("LIST_OBJECTS") << id << engine.debugId; + sendMessage(message); + *success = true; + } + return id; +} + +quint32 QQmlEngineDebugClient::queryObject( + const QmlDebugObjectReference &object, bool *success) +{ + m_object = QmlDebugObjectReference(); + quint32 id; + *success = false; + if (state() == QQmlDebugClient::Enabled && object.debugId != -1) { + id = getId(); + QByteArray message; + QDataStream ds(&message, QIODevice::WriteOnly); + ds << QByteArray("FETCH_OBJECT") << id << object.debugId << false << + true; + sendMessage(message); + *success = true; + } + return id; +} + +quint32 QQmlEngineDebugClient::queryObjectRecursive( + const QmlDebugObjectReference &object, bool *success) +{ + m_object = QmlDebugObjectReference(); + quint32 id; + *success = false; + if (state() == QQmlDebugClient::Enabled && object.debugId != -1) { + id = getId(); + QByteArray message; + QDataStream ds(&message, QIODevice::WriteOnly); + ds << QByteArray("FETCH_OBJECT") << id << object.debugId << true << + true; + sendMessage(message); + *success = true; + } + return id; +} + +quint32 QQmlEngineDebugClient::queryExpressionResult( + int objectDebugId, const QString &expr, bool *success) +{ + m_exprResult = QVariant(); + quint32 id; + *success = false; + if (state() == QQmlDebugClient::Enabled && objectDebugId != -1) { + id = getId(); + QByteArray message; + QDataStream ds(&message, QIODevice::WriteOnly); + ds << QByteArray("EVAL_EXPRESSION") << id << objectDebugId << expr; + sendMessage(message); + *success = true; + } + return id; +} + +quint32 QQmlEngineDebugClient::setBindingForObject( + int objectDebugId, + const QString &propertyName, + const QVariant &bindingExpression, + bool isLiteralValue, + QString source, int line, + bool *success) +{ + quint32 id; + *success = false; + if (state() == QQmlDebugClient::Enabled && objectDebugId != -1) { + id = getId(); + QByteArray message; + QDataStream ds(&message, QIODevice::WriteOnly); + ds << QByteArray("SET_BINDING") << id << objectDebugId << propertyName + << bindingExpression << isLiteralValue << source << line; + sendMessage(message); + *success = true; + } + return id; +} + +quint32 QQmlEngineDebugClient::resetBindingForObject( + int objectDebugId, + const QString &propertyName, + bool *success) +{ + quint32 id; + *success = false; + if (state() == QQmlDebugClient::Enabled && objectDebugId != -1) { + id = getId(); + QByteArray message; + QDataStream ds(&message, QIODevice::WriteOnly); + ds << QByteArray("RESET_BINDING") << id << objectDebugId << propertyName; + sendMessage(message); + *success = true; + } + return id; +} + +quint32 QQmlEngineDebugClient::setMethodBody( + int objectDebugId, const QString &methodName, + const QString &methodBody, bool *success) +{ + quint32 id; + *success = false; + if (state() == QQmlDebugClient::Enabled && objectDebugId != -1) { + id = getId(); + QByteArray message; + QDataStream ds(&message, QIODevice::WriteOnly); + ds << QByteArray("SET_METHOD_BODY") << id << objectDebugId + << methodName << methodBody; + sendMessage(message); + *success = true; + } + return id; +} + +void QQmlEngineDebugClient::decode(QDataStream &ds, + QmlDebugObjectReference &o, + bool simple) +{ + QmlObjectData data; + ds >> data; + o.debugId = data.objectId; + o.className = data.objectType; + o.idString = data.idString; + o.name = data.objectName; + o.source.url = data.url; + o.source.lineNumber = data.lineNumber; + o.source.columnNumber = data.columnNumber; + o.contextDebugId = data.contextId; + + if (simple) + return; + + int childCount; + bool recur; + ds >> childCount >> recur; + + for (int ii = 0; ii < childCount; ++ii) { + o.children.append(QmlDebugObjectReference()); + decode(ds, o.children.last(), !recur); + } + + int propCount; + ds >> propCount; + + for (int ii = 0; ii < propCount; ++ii) { + QmlObjectProperty data; + ds >> data; + QmlDebugPropertyReference prop; + prop.objectDebugId = o.debugId; + prop.name = data.name; + prop.binding = data.binding; + prop.hasNotifySignal = data.hasNotifySignal; + prop.valueTypeName = data.valueTypeName; + switch (data.type) { + case QmlObjectProperty::Basic: + case QmlObjectProperty::List: + case QmlObjectProperty::SignalProperty: + { + prop.value = data.value; + break; + } + case QmlObjectProperty::Object: + { + QmlDebugObjectReference obj; + obj.debugId = prop.value.toInt(); + prop.value = qVariantFromValue(obj); + break; + } + case QmlObjectProperty::Unknown: + break; + } + o.properties << prop; + } +} + +void QQmlEngineDebugClient::decode(QDataStream &ds, + QmlDebugContextReference &c) +{ + ds >> c.name >> c.debugId; + + int contextCount; + ds >> contextCount; + + for (int ii = 0; ii < contextCount; ++ii) { + c.contexts.append(QmlDebugContextReference()); + decode(ds, c.contexts.last()); + } + + int objectCount; + ds >> objectCount; + + for (int ii = 0; ii < objectCount; ++ii) { + QmlDebugObjectReference obj; + decode(ds, obj, true); + + obj.contextDebugId = c.debugId; + c.objects << obj; + } +} + +void QQmlEngineDebugClient::messageReceived(const QByteArray &data) +{ + m_valid = false; + QDataStream ds(data); + int queryId; + QByteArray type; + ds >> type >> queryId; + + //qDebug() << "QQmlEngineDebugPrivate::message()" << type; + + if (type == "LIST_ENGINES_R") { + int count; + ds >> count; + + m_engines.clear(); + for (int ii = 0; ii < count; ++ii) { + QmlDebugEngineReference eng; + ds >> eng.name; + ds >> eng.debugId; + m_engines << eng; + } + } else if (type == "LIST_OBJECTS_R") { + if (!ds.atEnd()) + decode(ds, m_rootContext); + + } else if (type == "FETCH_OBJECT_R") { + if (!ds.atEnd()) + decode(ds, m_object, false); + + } else if (type == "EVAL_EXPRESSION_R") {; + ds >> m_exprResult; + + } else if (type == "WATCH_PROPERTY_R") { + ds >> m_valid; + + } else if (type == "WATCH_OBJECT_R") { + ds >> m_valid; + + } else if (type == "WATCH_EXPR_OBJECT_R") { + ds >> m_valid; + + } else if (type == "UPDATE_WATCH") { + int debugId; + QByteArray name; + QVariant value; + ds >> debugId >> name >> value; + emit valueChanged(name, value); + return; + + } else if (type == "OBJECT_CREATED") { + emit newObjects(); + return; + } else if (type == "SET_BINDING_R") { + ds >> m_valid; + } else if (type == "RESET_BINDING_R") { + ds >> m_valid; + } else if (type == "SET_METHOD_BODY_R") { + ds >> m_valid; + } else if (type == "NO_WATCH_R") { + ds >> m_valid; + } + emit result(); +} + diff --git a/tests/auto/qml/debugger/qqmlenginedebugservice/qqmlenginedebugclient.h b/tests/auto/qml/debugger/qqmlenginedebugservice/qqmlenginedebugclient.h new file mode 100644 index 0000000000..62f9b15824 --- /dev/null +++ b/tests/auto/qml/debugger/qqmlenginedebugservice/qqmlenginedebugclient.h @@ -0,0 +1,237 @@ +/**************************************************************************** +** +** Copyright (C) 2012 Nokia Corporation and/or its subsidiary(-ies). +** Contact: http://www.qt-project.org/ +** +** This file is part of the QtQml module of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** GNU Lesser General Public License Usage +** 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, Nokia gives you certain additional +** rights. These rights are described in the Nokia 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. +** +** Other Usage +** Alternatively, this file may be used in accordance with the terms and +** conditions contained in a signed written agreement between you and Nokia. +** +** +** +** +** +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#ifndef QQMLENGINEDEBUGCLIENT_H +#define QQMLENGINEDEBUGCLIENT_H + +#include "qqmldebugclient.h" + +#include <QtCore/qurl.h> +#include <QtCore/qvariant.h> + +class QQmlDebugConnection; + +struct QmlDebugPropertyReference +{ + QmlDebugPropertyReference() + : objectDebugId(-1), hasNotifySignal(false) + { + } + + QmlDebugPropertyReference &operator=( + const QmlDebugPropertyReference &o) + { + objectDebugId = o.objectDebugId; name = o.name; value = o.value; + valueTypeName = o.valueTypeName; binding = o.binding; + hasNotifySignal = o.hasNotifySignal; + return *this; + } + + int objectDebugId; + QString name; + QVariant value; + QString valueTypeName; + QString binding; + bool hasNotifySignal; +}; + +struct QmlDebugFileReference +{ + QmlDebugFileReference() + : lineNumber(-1), columnNumber(-1) + { + } + + QmlDebugFileReference &operator=( + const QmlDebugFileReference &o) + { + url = o.url; lineNumber = o.lineNumber; columnNumber = o.columnNumber; + return *this; + } + + QUrl url; + int lineNumber; + int columnNumber; +}; + +struct QmlDebugObjectReference +{ + QmlDebugObjectReference() + : debugId(-1), contextDebugId(-1) + { + } + + QmlDebugObjectReference(int id) + : debugId(id), contextDebugId(-1) + { + } + + QmlDebugObjectReference &operator=( + const QmlDebugObjectReference &o) + { + debugId = o.debugId; className = o.className; idString = o.idString; + name = o.name; source = o.source; contextDebugId = o.contextDebugId; + properties = o.properties; children = o.children; + return *this; + } + int debugId; + QString className; + QString idString; + QString name; + QmlDebugFileReference source; + int contextDebugId; + QList<QmlDebugPropertyReference> properties; + QList<QmlDebugObjectReference> children; +}; + +Q_DECLARE_METATYPE(QmlDebugObjectReference) + +struct QmlDebugContextReference +{ + QmlDebugContextReference() + : debugId(-1) + { + } + + QmlDebugContextReference &operator=( + const QmlDebugContextReference &o) + { + debugId = o.debugId; name = o.name; objects = o.objects; + contexts = o.contexts; + return *this; + } + + int debugId; + QString name; + QList<QmlDebugObjectReference> objects; + QList<QmlDebugContextReference> contexts; +}; + +struct QmlDebugEngineReference +{ + QmlDebugEngineReference() + : debugId(-1) + { + } + + QmlDebugEngineReference(int id) + : debugId(id) + { + } + + QmlDebugEngineReference &operator=( + const QmlDebugEngineReference &o) + { + debugId = o.debugId; name = o.name; + return *this; + } + + int debugId; + QString name; +}; + +class QQmlEngineDebugClient : public QQmlDebugClient +{ + Q_OBJECT +public: + explicit QQmlEngineDebugClient(QQmlDebugConnection *conn); + + quint32 addWatch(const QmlDebugPropertyReference &, + bool *success); + quint32 addWatch(const QmlDebugContextReference &, const QString &, + bool *success); + quint32 addWatch(const QmlDebugObjectReference &, const QString &, + bool *success); + quint32 addWatch(const QmlDebugObjectReference &, + bool *success); + quint32 addWatch(const QmlDebugFileReference &, + bool *success); + + void removeWatch(quint32 watch, bool *success); + + quint32 queryAvailableEngines(bool *success); + quint32 queryRootContexts(const QmlDebugEngineReference &, + bool *success); + quint32 queryObject(const QmlDebugObjectReference &, + bool *success); + quint32 queryObjectRecursive(const QmlDebugObjectReference &, + bool *success); + quint32 queryExpressionResult(int objectDebugId, + const QString &expr, + bool *success); + quint32 setBindingForObject(int objectDebugId, const QString &propertyName, + const QVariant &bindingExpression, + bool isLiteralValue, + QString source, int line, bool *success); + quint32 resetBindingForObject(int objectDebugId, + const QString &propertyName, bool *success); + quint32 setMethodBody(int objectDebugId, const QString &methodName, + const QString &methodBody, bool *success); + + quint32 getId() { return m_nextId++; } + + void decode(QDataStream &, QmlDebugContextReference &); + void decode(QDataStream &, QmlDebugObjectReference &, bool simple); + + QList<QmlDebugEngineReference> engines() { return m_engines; } + QmlDebugContextReference rootContext() { return m_rootContext; } + QmlDebugObjectReference object() { return m_object; } + QVariant resultExpr() { return m_exprResult; } + bool valid() { return m_valid; } + +signals: + void newObjects(); + void valueChanged(QByteArray,QVariant); + void result(); + +protected: + void messageReceived(const QByteArray &); + +private: + quint32 m_nextId; + bool m_valid; + QList<QmlDebugEngineReference> m_engines; + QmlDebugContextReference m_rootContext; + QmlDebugObjectReference m_object; + QVariant m_exprResult; +}; + +#endif // QQMLENGINEDEBUGCLIENT_H diff --git a/tests/auto/qml/debugger/qqmlenginedebugservice/qqmlenginedebugservice.pro b/tests/auto/qml/debugger/qqmlenginedebugservice/qqmlenginedebugservice.pro index 0b92a726b5..0212d11cd1 100644 --- a/tests/auto/qml/debugger/qqmlenginedebugservice/qqmlenginedebugservice.pro +++ b/tests/auto/qml/debugger/qqmlenginedebugservice/qqmlenginedebugservice.pro @@ -2,9 +2,15 @@ CONFIG += testcase TARGET = tst_qqmlenginedebugservice macx:CONFIG -= app_bundle -SOURCES += tst_qqmlenginedebugservice.cpp +HEADERS += \ + qqmlenginedebugclient.h + +SOURCES += \ + tst_qqmlenginedebugservice.cpp \ + qqmlenginedebugclient.cpp INCLUDEPATH += ../shared +include(../../../shared/util.pri) include(../shared/debugutil.pri) CONFIG += parallel_test declarative_debug diff --git a/tests/auto/qml/debugger/qqmlenginedebugservice/tst_qqmlenginedebugservice.cpp b/tests/auto/qml/debugger/qqmlenginedebugservice/tst_qqmlenginedebugservice.cpp index e409f3c8b6..e84e6623c1 100644 --- a/tests/auto/qml/debugger/qqmlenginedebugservice/tst_qqmlenginedebugservice.cpp +++ b/tests/auto/qml/debugger/qqmlenginedebugservice/tst_qqmlenginedebugservice.cpp @@ -59,27 +59,45 @@ #include <private/qqmlproperty_p.h> #include "debugutil_p.h" -#include "qqmlenginedebug_p.h" +#include "qqmlenginedebugclient.h" -Q_DECLARE_METATYPE(QQmlDebugWatch::State) +#include "../../../shared/util.h" + +#define QVERIFYOBJECT(statement) \ + do {\ + if (!QTest::qVerify((statement), #statement, "", __FILE__, __LINE__)) {\ + return QmlDebugObjectReference();\ + }\ + } while (0) + +class NonScriptProperty : public QObject { + Q_OBJECT + Q_PROPERTY(int nonScriptProp READ nonScriptProp WRITE setNonScriptProp NOTIFY nonScriptPropChanged SCRIPTABLE false) +public: + int nonScriptProp() const { return 0; } + void setNonScriptProp(int) {} +signals: + void nonScriptPropChanged(); +}; +QML_DECLARE_TYPE(NonScriptProperty) class tst_QQmlEngineDebugService : public QObject { Q_OBJECT private: - QQmlDebugObjectReference findRootObject(int context = 0, bool recursive = false); - QQmlDebugPropertyReference findProperty(const QList<QQmlDebugPropertyReference> &props, const QString &name) const; - void waitForQuery(QQmlDebugQuery *query); - - void recursiveObjectTest(QObject *o, const QQmlDebugObjectReference &oref, bool recursive) const; + QmlDebugObjectReference findRootObject(int context = 0, + bool recursive = false); + QmlDebugPropertyReference findProperty( + const QList<QmlDebugPropertyReference> &props, + const QString &name) const; - void recursiveCompareObjects(const QQmlDebugObjectReference &a, const QQmlDebugObjectReference &b) const; - void recursiveCompareContexts(const QQmlDebugContextReference &a, const QQmlDebugContextReference &b) const; - void compareProperties(const QQmlDebugPropertyReference &a, const QQmlDebugPropertyReference &b) const; + void recursiveObjectTest(QObject *o, + const QmlDebugObjectReference &oref, + bool recursive) const; QQmlDebugConnection *m_conn; - QQmlEngineDebug *m_dbg; + QQmlEngineDebugClient *m_dbg; QQmlEngine *m_engine; QQuickItem *m_rootItem; @@ -103,90 +121,62 @@ private slots: void queryExpressionResult(); void queryExpressionResult_data(); - void tst_QQmlDebugFileReference(); - void tst_QQmlDebugEngineReference(); - void tst_QQmlDebugObjectReference(); - void tst_QQmlDebugContextReference(); - void tst_QQmlDebugPropertyReference(); - void setBindingForObject(); void setMethodBody(); void queryObjectTree(); void setBindingInStates(); }; -class NonScriptProperty : public QObject { - Q_OBJECT - Q_PROPERTY(int nonScriptProp READ nonScriptProp WRITE setNonScriptProp NOTIFY nonScriptPropChanged SCRIPTABLE false) -public: - int nonScriptProp() const { return 0; } - void setNonScriptProp(int) {} -signals: - void nonScriptPropChanged(); -}; -QML_DECLARE_TYPE(NonScriptProperty) - - -QQmlDebugObjectReference tst_QQmlEngineDebugService::findRootObject(int context, bool recursive) -{ - QQmlDebugEnginesQuery *q_engines = m_dbg->queryAvailableEngines(this); - waitForQuery(q_engines); - - if (q_engines->engines().count() == 0) - return QQmlDebugObjectReference(); - QQmlDebugRootContextQuery *q_context = m_dbg->queryRootContexts(q_engines->engines()[0].debugId(), this); - waitForQuery(q_context); - - if (q_context->rootContext().contexts().count() == 0 || - q_context->rootContext().contexts().last().objects().count() == 0) - return QQmlDebugObjectReference(); - - //Contexts are in a stack - int count = q_context->rootContext().contexts().count(); - QQmlDebugObjectQuery *q_obj = recursive ? - m_dbg->queryObjectRecursive(q_context->rootContext().contexts()[count - context - 1].objects()[0], this) : - m_dbg->queryObject(q_context->rootContext().contexts()[count - context - 1].objects()[0], this); - waitForQuery(q_obj); - - QQmlDebugObjectReference result = q_obj->object(); - - delete q_engines; - delete q_context; - delete q_obj; - - return result; +QmlDebugObjectReference tst_QQmlEngineDebugService::findRootObject( + int context, bool recursive) +{ + bool success = false; + m_dbg->queryAvailableEngines(&success); + QVERIFYOBJECT(success); + QVERIFYOBJECT(QQmlDebugTest::waitForSignal(m_dbg, SIGNAL(result()))); + + QVERIFYOBJECT(m_dbg->engines().count()); + m_dbg->queryRootContexts(m_dbg->engines()[0].debugId, &success); + QVERIFYOBJECT(success); + QVERIFYOBJECT(QQmlDebugTest::waitForSignal(m_dbg, SIGNAL(result()))); + + QVERIFYOBJECT(m_dbg->rootContext().contexts.count()); + QVERIFYOBJECT(m_dbg->rootContext().contexts.last().objects.count()); + int count = m_dbg->rootContext().contexts.count(); + recursive ? m_dbg->queryObjectRecursive(m_dbg->rootContext().contexts[count - context - 1].objects[0], + &success) : + m_dbg->queryObject(m_dbg->rootContext().contexts[count - context - 1].objects[0], &success); + QVERIFYOBJECT(success); + QVERIFYOBJECT(QQmlDebugTest::waitForSignal(m_dbg, SIGNAL(result()))); + + return m_dbg->object(); } -QQmlDebugPropertyReference tst_QQmlEngineDebugService::findProperty(const QList<QQmlDebugPropertyReference> &props, const QString &name) const +QmlDebugPropertyReference tst_QQmlEngineDebugService::findProperty( + const QList<QmlDebugPropertyReference> &props, const QString &name) const { - foreach(const QQmlDebugPropertyReference &p, props) { - if (p.name() == name) + foreach (const QmlDebugPropertyReference &p, props) { + if (p.name == name) return p; } - return QQmlDebugPropertyReference(); -} - -void tst_QQmlEngineDebugService::waitForQuery(QQmlDebugQuery *query) -{ - QVERIFY(query); - QCOMPARE(query->parent(), qobject_cast<QObject*>(this)); - QVERIFY(query->state() == QQmlDebugQuery::Waiting); - if (!QQmlDebugTest::waitForSignal(query, SIGNAL(stateChanged(QQmlDebugQuery::State)))) - QFAIL("query timed out"); + return QmlDebugPropertyReference(); } -void tst_QQmlEngineDebugService::recursiveObjectTest(QObject *o, const QQmlDebugObjectReference &oref, bool recursive) const +void tst_QQmlEngineDebugService::recursiveObjectTest( + QObject *o, const QmlDebugObjectReference &oref, bool recursive) const { const QMetaObject *meta = o->metaObject(); QQmlType *type = QQmlMetaType::qmlType(meta); - QString className = type ? QString(type->qmlTypeName()) : QString(meta->className()); + QString className = type ? QString(type->qmlTypeName()) + : QString(meta->className()); className = className.mid(className.lastIndexOf(QLatin1Char('/'))+1); - QCOMPARE(oref.debugId(), QQmlDebugService::idForObject(o)); - QCOMPARE(oref.name(), o->objectName()); - QCOMPARE(oref.className(), className); - QCOMPARE(oref.contextDebugId(), QQmlDebugService::idForObject(qmlContext(o))); + QCOMPARE(oref.debugId, QQmlDebugService::idForObject(o)); + QCOMPARE(oref.name, o->objectName()); + QCOMPARE(oref.className, className); + QCOMPARE(oref.contextDebugId, QQmlDebugService::idForObject( + qmlContext(o))); const QObjectList &children = o->children(); for (int i=0; i<children.count(); i++) { @@ -196,26 +186,27 @@ void tst_QQmlEngineDebugService::recursiveObjectTest(QObject *o, const QQmlDebug int debugId = QQmlDebugService::idForObject(child); QVERIFY(debugId >= 0); - QQmlDebugObjectReference cref; - foreach (const QQmlDebugObjectReference &ref, oref.children()) { - if (ref.debugId() == debugId) { + QmlDebugObjectReference cref; + foreach (const QmlDebugObjectReference &ref, oref.children) { + if (ref.debugId == debugId) { cref = ref; break; } } - QVERIFY(cref.debugId() >= 0); + QVERIFY(cref.debugId >= 0); if (recursive) recursiveObjectTest(child, cref, true); } - foreach (const QQmlDebugPropertyReference &p, oref.properties()) { - QCOMPARE(p.objectDebugId(), QQmlDebugService::idForObject(o)); + foreach (const QmlDebugPropertyReference &p, oref.properties) { + QCOMPARE(p.objectDebugId, QQmlDebugService::idForObject(o)); // signal properties are fake - they are generated from QQmlBoundSignal children - if (p.name().startsWith("on") && p.name().length() > 2 && p.name()[2].isUpper()) { - QList<QQmlBoundSignal*> signalHandlers = o->findChildren<QQmlBoundSignal*>(); - QString signal = p.value().toString(); + if (p.name.startsWith("on") && p.name.length() > 2 && p.name[2].isUpper()) { + QList<QQmlBoundSignal*> signalHandlers = + o->findChildren<QQmlBoundSignal*>(); + QString signal = p.value.toString(); bool found = false; for (int i = 0; i < signalHandlers.count(); ++i) if (signalHandlers.at(i)->expression()->expression() == signal) { @@ -223,86 +214,40 @@ void tst_QQmlEngineDebugService::recursiveObjectTest(QObject *o, const QQmlDebug break; } QVERIFY(found); - QVERIFY(p.valueTypeName().isEmpty()); - QVERIFY(p.binding().isEmpty()); - QVERIFY(!p.hasNotifySignal()); + QVERIFY(p.valueTypeName.isEmpty()); + QVERIFY(p.binding.isEmpty()); + QVERIFY(!p.hasNotifySignal); continue; } - QMetaProperty pmeta = meta->property(meta->indexOfProperty(p.name().toUtf8().constData())); + QMetaProperty pmeta = meta->property(meta->indexOfProperty(p.name.toUtf8().constData())); - QCOMPARE(p.name(), QString::fromUtf8(pmeta.name())); + QCOMPARE(p.name, QString::fromUtf8(pmeta.name())); - if (pmeta.type() < QVariant::UserType && pmeta.userType() != QMetaType::QVariant) // TODO test complex types - QCOMPARE(p.value(), pmeta.read(o)); + if (pmeta.type() < QVariant::UserType && pmeta.userType() != + QMetaType::QVariant) // TODO test complex types + QCOMPARE(p.value , pmeta.read(o)); - if (p.name() == "parent") - QVERIFY(p.valueTypeName() == "QGraphicsObject*" || p.valueTypeName() == "QQuickItem*"); + if (p.name == "parent") + QVERIFY(p.valueTypeName == "QGraphicsObject*" || + p.valueTypeName == "QQuickItem*"); else - QCOMPARE(p.valueTypeName(), QString::fromUtf8(pmeta.typeName())); + QCOMPARE(p.valueTypeName, QString::fromUtf8(pmeta.typeName())); - QQmlAbstractBinding *binding = - QQmlPropertyPrivate::binding(QQmlProperty(o, p.name())); + QQmlAbstractBinding *binding = + QQmlPropertyPrivate::binding( + QQmlProperty(o, p.name)); if (binding) - QCOMPARE(binding->expression(), p.binding()); + QCOMPARE(binding->expression(), p.binding); - QCOMPARE(p.hasNotifySignal(), pmeta.hasNotifySignal()); + QCOMPARE(p.hasNotifySignal, pmeta.hasNotifySignal()); QVERIFY(pmeta.isValid()); } } -void tst_QQmlEngineDebugService::recursiveCompareObjects(const QQmlDebugObjectReference &a, const QQmlDebugObjectReference &b) const -{ - QCOMPARE(a.debugId(), b.debugId()); - QCOMPARE(a.className(), b.className()); - QCOMPARE(a.name(), b.name()); - QCOMPARE(a.contextDebugId(), b.contextDebugId()); - - QCOMPARE(a.source().url(), b.source().url()); - QCOMPARE(a.source().lineNumber(), b.source().lineNumber()); - QCOMPARE(a.source().columnNumber(), b.source().columnNumber()); - - QCOMPARE(a.properties().count(), b.properties().count()); - QCOMPARE(a.children().count(), b.children().count()); - - QList<QQmlDebugPropertyReference> aprops = a.properties(); - QList<QQmlDebugPropertyReference> bprops = b.properties(); - - for (int i=0; i<aprops.count(); i++) - compareProperties(aprops[i], bprops[i]); - - for (int i=0; i<a.children().count(); i++) - recursiveCompareObjects(a.children()[i], b.children()[i]); -} - -void tst_QQmlEngineDebugService::recursiveCompareContexts(const QQmlDebugContextReference &a, const QQmlDebugContextReference &b) const -{ - QCOMPARE(a.debugId(), b.debugId()); - QCOMPARE(a.name(), b.name()); - QCOMPARE(a.objects().count(), b.objects().count()); - QCOMPARE(a.contexts().count(), b.contexts().count()); - - for (int i=0; i<a.objects().count(); i++) - recursiveCompareObjects(a.objects()[i], b.objects()[i]); - - for (int i=0; i<a.contexts().count(); i++) - recursiveCompareContexts(a.contexts()[i], b.contexts()[i]); -} - -void tst_QQmlEngineDebugService::compareProperties(const QQmlDebugPropertyReference &a, const QQmlDebugPropertyReference &b) const -{ - QCOMPARE(a.objectDebugId(), b.objectDebugId()); - QCOMPARE(a.name(), b.name()); - QCOMPARE(a.value(), b.value()); - QCOMPARE(a.valueTypeName(), b.valueTypeName()); - QCOMPARE(a.binding(), b.binding()); - QCOMPARE(a.hasNotifySignal(), b.hasNotifySignal()); -} - void tst_QQmlEngineDebugService::initTestCase() { - qRegisterMetaType<QQmlDebugWatch::State>(); qmlRegisterType<NonScriptProperty>("Test", 1, 0, "NonScriptPropertyElement"); QTest::ignoreMessage(QtDebugMsg, "QML Debugger: Waiting for connection on port 3768..."); @@ -394,13 +339,12 @@ void tst_QQmlEngineDebugService::initTestCase() bool ok = m_conn->waitForConnected(); QVERIFY(ok); QTRY_VERIFY(QQmlDebugService::hasDebuggingClient()); - m_dbg = new QQmlEngineDebug(m_conn, this); - QTRY_VERIFY(m_dbg->state() == QQmlEngineDebug::Enabled); + m_dbg = new QQmlEngineDebugClient(m_conn); + QTRY_VERIFY(m_dbg->state() == QQmlEngineDebugClient::Enabled); } void tst_QQmlEngineDebugService::cleanupTestCase() { - delete m_dbg; delete m_conn; qDeleteAll(m_components); delete m_engine; @@ -408,7 +352,8 @@ void tst_QQmlEngineDebugService::cleanupTestCase() void tst_QQmlEngineDebugService::setMethodBody() { - QQmlDebugObjectReference obj = findRootObject(2); + bool success; + QmlDebugObjectReference obj = findRootObject(2); QObject *root = m_components.at(2); // Without args @@ -419,8 +364,10 @@ void tst_QQmlEngineDebugService::setMethodBody() QVERIFY(rv == QVariant(qreal(3))); - QVERIFY(m_dbg->setMethodBody(obj.debugId(), "myMethodNoArgs", "return 7")); - QTest::qWait(100); + QVERIFY(m_dbg->setMethodBody(obj.debugId, "myMethodNoArgs", "return 7", + &success)); + QVERIFY(success); + QVERIFY(QQmlDebugTest::waitForSignal(m_dbg, SIGNAL(result()))); QVERIFY(QMetaObject::invokeMethod(root, "myMethodNoArgs", Qt::DirectConnection, Q_RETURN_ARG(QVariant, rv))); @@ -434,8 +381,10 @@ void tst_QQmlEngineDebugService::setMethodBody() Q_RETURN_ARG(QVariant, rv), Q_ARG(QVariant, QVariant(19)))); QVERIFY(rv == QVariant(qreal(28))); - QVERIFY(m_dbg->setMethodBody(obj.debugId(), "myMethod", "return a + 7")); - QTest::qWait(100); + QVERIFY(m_dbg->setMethodBody(obj.debugId, "myMethod", "return a + 7", + &success)); + QVERIFY(success); + QVERIFY(QQmlDebugTest::waitForSignal(m_dbg, SIGNAL(result()))); QVERIFY(QMetaObject::invokeMethod(root, "myMethod", Qt::DirectConnection, Q_RETURN_ARG(QVariant, rv), Q_ARG(QVariant, QVariant(19)))); @@ -445,96 +394,78 @@ void tst_QQmlEngineDebugService::setMethodBody() void tst_QQmlEngineDebugService::watch_property() { - QQmlDebugObjectReference obj = findRootObject(); - QQmlDebugPropertyReference prop = findProperty(obj.properties(), "width"); + QmlDebugObjectReference obj = findRootObject(); + QmlDebugPropertyReference prop = findProperty(obj.properties, "width"); - QQmlDebugPropertyWatch *watch; + bool success; - QQmlEngineDebug *unconnected = new QQmlEngineDebug(0); - watch = unconnected->addWatch(prop, this); - QCOMPARE(watch->state(), QQmlDebugWatch::Dead); - delete watch; + QQmlEngineDebugClient *unconnected = new QQmlEngineDebugClient(0); + unconnected->addWatch(prop, &success); + QVERIFY(!success); delete unconnected; - watch = m_dbg->addWatch(QQmlDebugPropertyReference(), this); - QVERIFY(QQmlDebugTest::waitForSignal(watch, SIGNAL(stateChanged(QQmlDebugWatch::State)))); - QCOMPARE(watch->state(), QQmlDebugWatch::Inactive); - delete watch; + m_dbg->addWatch(QmlDebugPropertyReference(), &success); + QVERIFY(success); + QVERIFY(QQmlDebugTest::waitForSignal(m_dbg, SIGNAL(result()))); + QCOMPARE(m_dbg->valid(), false); - watch = m_dbg->addWatch(prop, this); - QCOMPARE(watch->state(), QQmlDebugWatch::Waiting); - QCOMPARE(watch->objectDebugId(), obj.debugId()); - QCOMPARE(watch->name(), prop.name()); + quint32 id = m_dbg->addWatch(prop, &success); + QVERIFY(success); + QVERIFY(QQmlDebugTest::waitForSignal(m_dbg, SIGNAL(result()))); + QCOMPARE(m_dbg->valid(), true); - QSignalSpy spy(watch, SIGNAL(valueChanged(QByteArray,QVariant))); + QSignalSpy spy(m_dbg, SIGNAL(valueChanged(QByteArray,QVariant))); int origWidth = m_rootItem->property("width").toInt(); m_rootItem->setProperty("width", origWidth*2); - // stateChanged() is received before valueChanged() - QVERIFY(QQmlDebugTest::waitForSignal(watch, SIGNAL(stateChanged(QQmlDebugWatch::State)))); - QCOMPARE(watch->state(), QQmlDebugWatch::Active); + QVERIFY(QQmlDebugTest::waitForSignal(m_dbg, SIGNAL(valueChanged(QByteArray,QVariant)))); QCOMPARE(spy.count(), 1); - m_dbg->removeWatch(watch); - delete watch; + m_dbg->removeWatch(id, &success); + QVERIFY(success); + QVERIFY(QQmlDebugTest::waitForSignal(m_dbg, SIGNAL(result()))); + QCOMPARE(m_dbg->valid(), true); // restore original value and verify spy doesn't get additional signal since watch has been removed m_rootItem->setProperty("width", origWidth); QTest::qWait(100); QCOMPARE(spy.count(), 1); - QCOMPARE(spy.at(0).at(0).value<QByteArray>(), prop.name().toUtf8()); + QCOMPARE(spy.at(0).at(0).value<QByteArray>(), prop.name.toUtf8()); QCOMPARE(spy.at(0).at(1).value<QVariant>(), qVariantFromValue(origWidth*2)); } void tst_QQmlEngineDebugService::watch_object() { - QQmlDebugEnginesQuery *q_engines = m_dbg->queryAvailableEngines(this); - waitForQuery(q_engines); - - QVERIFY(q_engines->engines().count() > 0); - QQmlDebugRootContextQuery *q_context = m_dbg->queryRootContexts(q_engines->engines()[0].debugId(), this); - waitForQuery(q_context); - - QVERIFY(q_context->rootContext().contexts().count()); - QVERIFY(q_context->rootContext().contexts().last().objects().count() > 0); - QQmlDebugObjectQuery *q_obj = m_dbg->queryObject(q_context->rootContext().contexts().last().objects()[0], this); - waitForQuery(q_obj); - - QQmlDebugObjectReference obj = q_obj->object(); + QmlDebugObjectReference obj = findRootObject(); - delete q_engines; - delete q_context; - delete q_obj; + bool success; - QQmlDebugWatch *watch; - - QQmlEngineDebug *unconnected = new QQmlEngineDebug(0); - watch = unconnected->addWatch(obj, this); - QCOMPARE(watch->state(), QQmlDebugWatch::Dead); - delete watch; + QQmlEngineDebugClient *unconnected = new QQmlEngineDebugClient(0); + unconnected->addWatch(obj, &success); + QVERIFY(!success); delete unconnected; - watch = m_dbg->addWatch(QQmlDebugObjectReference(), this); - QVERIFY(QQmlDebugTest::waitForSignal(watch, SIGNAL(stateChanged(QQmlDebugWatch::State)))); - QCOMPARE(watch->state(), QQmlDebugWatch::Inactive); - delete watch; + m_dbg->addWatch(QmlDebugObjectReference(), &success); + QVERIFY(success); + QVERIFY(QQmlDebugTest::waitForSignal(m_dbg, SIGNAL(result()))); + QCOMPARE(m_dbg->valid(), false); - watch = m_dbg->addWatch(obj, this); - QCOMPARE(watch->state(), QQmlDebugWatch::Waiting); - QCOMPARE(watch->objectDebugId(), obj.debugId()); + quint32 id = m_dbg->addWatch(obj, &success); + QVERIFY(success); + QVERIFY(QQmlDebugTest::waitForSignal(m_dbg, SIGNAL(result()))); + QCOMPARE(m_dbg->valid(), true); - QSignalSpy spy(watch, SIGNAL(valueChanged(QByteArray,QVariant))); + QSignalSpy spy(m_dbg, SIGNAL(valueChanged(QByteArray,QVariant))); int origWidth = m_rootItem->property("width").toInt(); int origHeight = m_rootItem->property("height").toInt(); m_rootItem->setProperty("width", origWidth*2); + QVERIFY(QQmlDebugTest::waitForSignal(m_dbg, SIGNAL(valueChanged(QByteArray,QVariant)))); m_rootItem->setProperty("height", origHeight*2); + QVERIFY(QQmlDebugTest::waitForSignal(m_dbg, SIGNAL(valueChanged(QByteArray,QVariant)))); - // stateChanged() is received before any valueChanged() signals - QVERIFY(QQmlDebugTest::waitForSignal(watch, SIGNAL(stateChanged(QQmlDebugWatch::State)))); - QCOMPARE(watch->state(), QQmlDebugWatch::Active); QVERIFY(spy.count() > 0); int newWidth = -1; @@ -548,8 +479,10 @@ void tst_QQmlEngineDebugService::watch_object() } - m_dbg->removeWatch(watch); - delete watch; + m_dbg->removeWatch(id, &success); + QVERIFY(success); + QVERIFY(QQmlDebugTest::waitForSignal(m_dbg, SIGNAL(result()))); + QCOMPARE(m_dbg->valid(), true); // since watch has been removed, restoring the original values should not trigger a valueChanged() spy.clear(); @@ -570,58 +503,50 @@ void tst_QQmlEngineDebugService::watch_expression() int origWidth = m_rootItem->property("width").toInt(); - QQmlDebugObjectReference obj = findRootObject(); + QmlDebugObjectReference obj = findRootObject(); - QQmlDebugObjectExpressionWatch *watch; + bool success; - QQmlEngineDebug *unconnected = new QQmlEngineDebug(0); - watch = unconnected->addWatch(obj, expr, this); - QCOMPARE(watch->state(), QQmlDebugWatch::Dead); - delete watch; + QQmlEngineDebugClient *unconnected = new QQmlEngineDebugClient(0); + unconnected->addWatch(obj, expr, &success); + QVERIFY(!success); delete unconnected; - watch = m_dbg->addWatch(QQmlDebugObjectReference(), expr, this); - QVERIFY(QQmlDebugTest::waitForSignal(watch, SIGNAL(stateChanged(QQmlDebugWatch::State)))); - QCOMPARE(watch->state(), QQmlDebugWatch::Inactive); - delete watch; - - watch = m_dbg->addWatch(obj, expr, this); - QCOMPARE(watch->state(), QQmlDebugWatch::Waiting); - QCOMPARE(watch->objectDebugId(), obj.debugId()); - QCOMPARE(watch->expression(), expr); + m_dbg->addWatch(QmlDebugObjectReference(), expr, &success); + QVERIFY(success); + QVERIFY(QQmlDebugTest::waitForSignal(m_dbg, SIGNAL(result()))); + QCOMPARE(m_dbg->valid(), false); - QSignalSpy spyState(watch, SIGNAL(stateChanged(QQmlDebugWatch::State))); + quint32 id = m_dbg->addWatch(obj, expr, &success); + QVERIFY(success); + QVERIFY(QQmlDebugTest::waitForSignal(m_dbg, SIGNAL(result()))); + QCOMPARE(m_dbg->valid(), true); - QSignalSpy spy(watch, SIGNAL(valueChanged(QByteArray,QVariant))); - int expectedSpyCount = incrementCount + 1; // should also get signal with expression's initial value + QSignalSpy spy(m_dbg, SIGNAL(valueChanged(QByteArray,QVariant))); int width = origWidth; for (int i=0; i<incrementCount+1; i++) { if (i > 0) { width += increment; m_rootItem->setProperty("width", width); + QVERIFY(QQmlDebugTest::waitForSignal(m_dbg, SIGNAL(valueChanged(QByteArray,QVariant)))); } - if (!QQmlDebugTest::waitForSignal(watch, SIGNAL(valueChanged(QByteArray,QVariant)))) - QFAIL("Did not receive valueChanged() for expression"); } - if (spyState.count() == 0) - QVERIFY(QQmlDebugTest::waitForSignal(watch, SIGNAL(stateChanged(QQmlDebugWatch::State)))); - QCOMPARE(spyState.count(), 1); - QCOMPARE(watch->state(), QQmlDebugWatch::Active); - - m_dbg->removeWatch(watch); - delete watch; + m_dbg->removeWatch(id, &success); + QVERIFY(success); + QVERIFY(QQmlDebugTest::waitForSignal(m_dbg, SIGNAL(result()))); + QCOMPARE(m_dbg->valid(), true); // restore original value and verify spy doesn't get a signal since watch has been removed m_rootItem->setProperty("width", origWidth); QTest::qWait(100); - QCOMPARE(spy.count(), expectedSpyCount); + QCOMPARE(spy.count(), incrementCount); width = origWidth + increment; for (int i=0; i<spy.count(); i++) { - QCOMPARE(spy.at(i).at(1).value<QVariant>().toInt(), width); width += increment; + QCOMPARE(spy.at(i).at(1).value<QVariant>().toInt(), width); } } @@ -637,165 +562,126 @@ void tst_QQmlEngineDebugService::watch_expression_data() void tst_QQmlEngineDebugService::watch_context() { - QQmlDebugContextReference c; - QTest::ignoreMessage(QtWarningMsg, "QQmlEngineDebug::addWatch(): Not implemented"); - QVERIFY(!m_dbg->addWatch(c, QString(), this)); + QmlDebugContextReference c; + QTest::ignoreMessage(QtWarningMsg, "QQmlEngineDebugClient::addWatch(): Not implemented"); + bool success; + m_dbg->addWatch(c, QString(), &success); + QVERIFY(!success); } void tst_QQmlEngineDebugService::watch_file() { - QQmlDebugFileReference f; - QTest::ignoreMessage(QtWarningMsg, "QQmlEngineDebug::addWatch(): Not implemented"); - QVERIFY(!m_dbg->addWatch(f, this)); + QmlDebugFileReference f; + QTest::ignoreMessage(QtWarningMsg, "QQmlEngineDebugClient::addWatch(): Not implemented"); + bool success; + m_dbg->addWatch(f, &success); + QVERIFY(!success); } void tst_QQmlEngineDebugService::queryAvailableEngines() { - QQmlDebugEnginesQuery *q_engines; + bool success; - QQmlEngineDebug *unconnected = new QQmlEngineDebug(0); - q_engines = unconnected->queryAvailableEngines(0); - QCOMPARE(q_engines->state(), QQmlDebugQuery::Error); - delete q_engines; + QQmlEngineDebugClient *unconnected = new QQmlEngineDebugClient(0); + unconnected->queryAvailableEngines(&success); + QVERIFY(!success); delete unconnected; - q_engines = m_dbg->queryAvailableEngines(this); - delete q_engines; - - q_engines = m_dbg->queryAvailableEngines(this); - QVERIFY(q_engines->engines().isEmpty()); - waitForQuery(q_engines); + m_dbg->queryAvailableEngines(&success); + QVERIFY(success); + QVERIFY(QQmlDebugTest::waitForSignal(m_dbg, SIGNAL(result()))); // TODO test multiple engines - QList<QQmlDebugEngineReference> engines = q_engines->engines(); + QList<QmlDebugEngineReference> engines = m_dbg->engines(); QCOMPARE(engines.count(), 1); - foreach(const QQmlDebugEngineReference &e, engines) { - QCOMPARE(e.debugId(), QQmlDebugService::idForObject(m_engine)); - QCOMPARE(e.name(), m_engine->objectName()); + foreach (const QmlDebugEngineReference &e, engines) { + QCOMPARE(e.debugId, QQmlDebugService::idForObject(m_engine)); + QCOMPARE(e.name, m_engine->objectName()); } - - // Make query invalid by deleting client - q_engines = m_dbg->queryAvailableEngines(this); - QCOMPARE(q_engines->state(), QQmlDebugQuery::Waiting); - delete m_dbg; - QCOMPARE(q_engines->state(), QQmlDebugQuery::Error); - delete q_engines; - m_dbg = new QQmlEngineDebug(m_conn, this); } void tst_QQmlEngineDebugService::queryRootContexts() { - QQmlDebugEnginesQuery *q_engines = m_dbg->queryAvailableEngines(this); - waitForQuery(q_engines); - int engineId = q_engines->engines()[0].debugId(); - delete q_engines; - - QQmlDebugRootContextQuery *q_context; + bool success; + m_dbg->queryAvailableEngines(&success); + QVERIFY(success); + QVERIFY(QQmlDebugTest::waitForSignal(m_dbg, SIGNAL(result()))); + QVERIFY(m_dbg->engines().count()); + int engineId = m_dbg->engines()[0].debugId; - QQmlEngineDebug *unconnected = new QQmlEngineDebug(0); - q_context = unconnected->queryRootContexts(engineId, this); - QCOMPARE(q_context->state(), QQmlDebugQuery::Error); - delete q_context; + QQmlEngineDebugClient *unconnected = new QQmlEngineDebugClient(0); + unconnected->queryRootContexts(engineId, &success); + QVERIFY(!success); delete unconnected; - q_context = m_dbg->queryRootContexts(engineId, this); - delete q_context; - - q_context = m_dbg->queryRootContexts(engineId, this); - waitForQuery(q_context); + m_dbg->queryRootContexts(engineId, &success); + QVERIFY(success); + QVERIFY(QQmlDebugTest::waitForSignal(m_dbg, SIGNAL(result()))); QQmlContext *actualContext = m_engine->rootContext(); - QQmlDebugContextReference context = q_context->rootContext(); - QCOMPARE(context.debugId(), QQmlDebugService::idForObject(actualContext)); - QCOMPARE(context.name(), actualContext->objectName()); + QmlDebugContextReference context = m_dbg->rootContext(); + QCOMPARE(context.debugId, QQmlDebugService::idForObject(actualContext)); + QCOMPARE(context.name, actualContext->objectName()); // root context query sends only root object data - it doesn't fill in // the children or property info - QCOMPARE(context.objects().count(), 0); - - QCOMPARE(context.contexts().count(), 5); - QVERIFY(context.contexts()[0].debugId() >= 0); - QCOMPARE(context.contexts()[0].name(), QString("tst_QQmlDebug_childContext")); - - // Make query invalid by deleting client - q_context = m_dbg->queryRootContexts(engineId, this); - QCOMPARE(q_context->state(), QQmlDebugQuery::Waiting); - delete m_dbg; - QCOMPARE(q_context->state(), QQmlDebugQuery::Error); - delete q_context; - m_dbg = new QQmlEngineDebug(m_conn, this); + QCOMPARE(context.objects.count(), 0); + QCOMPARE(context.contexts.count(), 5); + QVERIFY(context.contexts[0].debugId >= 0); + QCOMPARE(context.contexts[0].name, QString("tst_QQmlDebug_childContext")); } void tst_QQmlEngineDebugService::queryObject() { QFETCH(bool, recursive); - QQmlDebugEnginesQuery *q_engines = m_dbg->queryAvailableEngines(this); - waitForQuery(q_engines); + bool success; - QQmlDebugRootContextQuery *q_context = m_dbg->queryRootContexts(q_engines->engines()[0].debugId(), this); - waitForQuery(q_context); - QQmlDebugObjectReference rootObject = q_context->rootContext().contexts().last().objects()[0]; + QmlDebugObjectReference rootObject = findRootObject(); - QQmlDebugObjectQuery *q_obj = 0; - - QQmlEngineDebug *unconnected = new QQmlEngineDebug(0); - q_obj = recursive ? unconnected->queryObjectRecursive(rootObject, this) : unconnected->queryObject(rootObject, this); - QCOMPARE(q_obj->state(), QQmlDebugQuery::Error); - delete q_obj; + QQmlEngineDebugClient *unconnected = new QQmlEngineDebugClient(0); + recursive ? unconnected->queryObjectRecursive(rootObject, &success) : unconnected->queryObject(rootObject, &success); + QVERIFY(!success); delete unconnected; - q_obj = recursive ? m_dbg->queryObjectRecursive(rootObject, this) : m_dbg->queryObject(rootObject, this); - delete q_obj; - - q_obj = recursive ? m_dbg->queryObjectRecursive(rootObject, this) : m_dbg->queryObject(rootObject, this); - waitForQuery(q_obj); - - QQmlDebugObjectReference obj = q_obj->object(); + recursive ? m_dbg->queryObjectRecursive(rootObject, &success) : m_dbg->queryObject(rootObject, &success); + QVERIFY(success); + QVERIFY(QQmlDebugTest::waitForSignal(m_dbg, SIGNAL(result()))); - delete q_engines; - delete q_context; - - // Make query invalid by deleting client - q_obj = recursive ? m_dbg->queryObjectRecursive(rootObject, this) : m_dbg->queryObject(rootObject, this); - QCOMPARE(q_obj->state(), QQmlDebugQuery::Waiting); - delete m_dbg; - QCOMPARE(q_obj->state(), QQmlDebugQuery::Error); - delete q_obj; - m_dbg = new QQmlEngineDebug(m_conn, this); + QmlDebugObjectReference obj = m_dbg->object(); // check source as defined in main() - QQmlDebugFileReference source = obj.source(); - QCOMPARE(source.url(), QUrl::fromLocalFile("")); - QCOMPARE(source.lineNumber(), 3); - QCOMPARE(source.columnNumber(), 1); + QmlDebugFileReference source = obj.source; + QCOMPARE(source.url, QUrl::fromLocalFile("")); + QCOMPARE(source.lineNumber, 3); + QCOMPARE(source.columnNumber, 1); // generically test all properties, children and childrens' properties recursiveObjectTest(m_rootItem, obj, recursive); if (recursive) { - foreach(const QQmlDebugObjectReference &child, obj.children()) - QVERIFY(child.properties().count() > 0); + foreach (const QmlDebugObjectReference &child, obj.children) + QVERIFY(child.properties.count() > 0); - QQmlDebugObjectReference rect; - QQmlDebugObjectReference text; - foreach (const QQmlDebugObjectReference &child, obj.children()) { - if (child.className() == "Rectangle") + QmlDebugObjectReference rect; + QmlDebugObjectReference text; + foreach (const QmlDebugObjectReference &child, obj.children) { + if (child.className == "Rectangle") rect = child; - else if (child.className() == "Text") + else if (child.className == "Text") text = child; } // test specific property values - QCOMPARE(findProperty(rect.properties(), "width").value(), qVariantFromValue(500)); - QCOMPARE(findProperty(rect.properties(), "height").value(), qVariantFromValue(600)); - QCOMPARE(findProperty(rect.properties(), "color").value(), qVariantFromValue(QColor("blue"))); + QCOMPARE(findProperty(rect.properties, "width").value, qVariantFromValue(500)); + QCOMPARE(findProperty(rect.properties, "height").value, qVariantFromValue(600)); + QCOMPARE(findProperty(rect.properties, "color").value, qVariantFromValue(QColor("blue"))); - QCOMPARE(findProperty(text.properties(), "color").value(), qVariantFromValue(QColor("blue"))); + QCOMPARE(findProperty(text.properties, "color").value, qVariantFromValue(QColor("blue"))); } else { - foreach(const QQmlDebugObjectReference &child, obj.children()) - QCOMPARE(child.properties().count(), 0); + foreach (const QmlDebugObjectReference &child, obj.children) + QCOMPARE(child.properties.count(), 0); } } @@ -812,40 +698,20 @@ void tst_QQmlEngineDebugService::queryExpressionResult() QFETCH(QString, expr); QFETCH(QVariant, result); - QQmlDebugEnginesQuery *q_engines = m_dbg->queryAvailableEngines(this); - waitForQuery(q_engines); // check immediate deletion is ok - - QQmlDebugRootContextQuery *q_context = m_dbg->queryRootContexts(q_engines->engines()[0].debugId(), this); - waitForQuery(q_context); - int objectId = q_context->rootContext().contexts().last().objects()[0].debugId(); + int objectId = findRootObject().debugId; - QQmlDebugExpressionQuery *q_expr; + bool success; - QQmlEngineDebug *unconnected = new QQmlEngineDebug(0); - q_expr = unconnected->queryExpressionResult(objectId, expr, this); - QCOMPARE(q_expr->state(), QQmlDebugQuery::Error); - delete q_expr; + QQmlEngineDebugClient *unconnected = new QQmlEngineDebugClient(0); + unconnected->queryExpressionResult(objectId, expr, &success); + QVERIFY(!success); delete unconnected; - q_expr = m_dbg->queryExpressionResult(objectId, expr, this); - delete q_expr; - - q_expr = m_dbg->queryExpressionResult(objectId, expr, this); - QCOMPARE(q_expr->expression().toString(), expr); - waitForQuery(q_expr); + m_dbg->queryExpressionResult(objectId, expr, &success); + QVERIFY(success); + QVERIFY(QQmlDebugTest::waitForSignal(m_dbg, SIGNAL(result()))); - QCOMPARE(q_expr->result(), result); - - delete q_engines; - delete q_context; - - // Make query invalid by deleting client - q_expr = m_dbg->queryExpressionResult(objectId, expr, this); - QCOMPARE(q_expr->state(), QQmlDebugQuery::Waiting); - delete m_dbg; - QCOMPARE(q_expr->state(), QQmlDebugQuery::Error); - delete q_expr; - m_dbg = new QQmlEngineDebug(m_conn, this); + QCOMPARE(m_dbg->resultExpr(), result); } void tst_QQmlEngineDebugService::queryExpressionResult_data() @@ -863,204 +729,94 @@ void tst_QQmlEngineDebugService::queryExpressionResult_data() QTest::newRow("varObjMap") << "varObjMap" << qVariantFromValue(map); } -void tst_QQmlEngineDebugService::tst_QQmlDebugFileReference() -{ - QQmlDebugFileReference ref; - QVERIFY(ref.url().isEmpty()); - QCOMPARE(ref.lineNumber(), -1); - QCOMPARE(ref.columnNumber(), -1); - - ref.setUrl(QUrl("http://test")); - QCOMPARE(ref.url(), QUrl("http://test")); - ref.setLineNumber(1); - QCOMPARE(ref.lineNumber(), 1); - ref.setColumnNumber(1); - QCOMPARE(ref.columnNumber(), 1); - - QQmlDebugFileReference copy(ref); - QQmlDebugFileReference copyAssign; - copyAssign = ref; - foreach (const QQmlDebugFileReference &r, (QList<QQmlDebugFileReference>() << copy << copyAssign)) { - QCOMPARE(r.url(), ref.url()); - QCOMPARE(r.lineNumber(), ref.lineNumber()); - QCOMPARE(r.columnNumber(), ref.columnNumber()); - } -} - -void tst_QQmlEngineDebugService::tst_QQmlDebugEngineReference() -{ - QQmlDebugEngineReference ref; - QCOMPARE(ref.debugId(), -1); - QVERIFY(ref.name().isEmpty()); - - ref = QQmlDebugEngineReference(1); - QCOMPARE(ref.debugId(), 1); - QVERIFY(ref.name().isEmpty()); - - QQmlDebugEnginesQuery *q_engines = m_dbg->queryAvailableEngines(this); - waitForQuery(q_engines); - ref = q_engines->engines()[0]; - delete q_engines; - - QQmlDebugEngineReference copy(ref); - QQmlDebugEngineReference copyAssign; - copyAssign = ref; - foreach (const QQmlDebugEngineReference &r, (QList<QQmlDebugEngineReference>() << copy << copyAssign)) { - QCOMPARE(r.debugId(), ref.debugId()); - QCOMPARE(r.name(), ref.name()); - } -} - -void tst_QQmlEngineDebugService::tst_QQmlDebugObjectReference() -{ - QQmlDebugObjectReference ref; - QCOMPARE(ref.debugId(), -1); - QCOMPARE(ref.className(), QString()); - QCOMPARE(ref.name(), QString()); - QCOMPARE(ref.contextDebugId(), -1); - QVERIFY(ref.properties().isEmpty()); - QVERIFY(ref.children().isEmpty()); - - QQmlDebugFileReference source = ref.source(); - QVERIFY(source.url().isEmpty()); - QVERIFY(source.lineNumber() < 0); - QVERIFY(source.columnNumber() < 0); - - ref = QQmlDebugObjectReference(1); - QCOMPARE(ref.debugId(), 1); - - QQmlDebugObjectReference rootObject = findRootObject(); - QQmlDebugObjectQuery *query = m_dbg->queryObjectRecursive(rootObject, this); - waitForQuery(query); - ref = query->object(); - delete query; - - QVERIFY(ref.debugId() >= 0); - - QQmlDebugObjectReference copy(ref); - QQmlDebugObjectReference copyAssign; - copyAssign = ref; - foreach (const QQmlDebugObjectReference &r, (QList<QQmlDebugObjectReference>() << copy << copyAssign)) - recursiveCompareObjects(r, ref); -} - -void tst_QQmlEngineDebugService::tst_QQmlDebugContextReference() -{ - QQmlDebugContextReference ref; - QCOMPARE(ref.debugId(), -1); - QVERIFY(ref.name().isEmpty()); - QVERIFY(ref.objects().isEmpty()); - QVERIFY(ref.contexts().isEmpty()); - - QQmlDebugEnginesQuery *q_engines = m_dbg->queryAvailableEngines(this); - waitForQuery(q_engines); - QQmlDebugRootContextQuery *q_context = m_dbg->queryRootContexts(q_engines->engines()[0].debugId(), this); - waitForQuery(q_context); - - ref = q_context->rootContext(); - delete q_engines; - delete q_context; - QVERIFY(ref.debugId() >= 0); - - QQmlDebugContextReference copy(ref); - QQmlDebugContextReference copyAssign; - copyAssign = ref; - foreach (const QQmlDebugContextReference &r, (QList<QQmlDebugContextReference>() << copy << copyAssign)) - recursiveCompareContexts(r, ref); -} - -void tst_QQmlEngineDebugService::tst_QQmlDebugPropertyReference() -{ - QQmlDebugObjectReference rootObject = findRootObject(); - QQmlDebugObjectQuery *query = m_dbg->queryObject(rootObject, this); - waitForQuery(query); - QQmlDebugObjectReference obj = query->object(); - delete query; - - QQmlDebugPropertyReference ref = findProperty(obj.properties(), "scale"); - QVERIFY(ref.objectDebugId() > 0); - QVERIFY(!ref.name().isEmpty()); - QVERIFY(!ref.value().isNull()); - QVERIFY(!ref.valueTypeName().isEmpty()); - QVERIFY(!ref.binding().isEmpty()); - QVERIFY(ref.hasNotifySignal()); - - QQmlDebugPropertyReference copy(ref); - QQmlDebugPropertyReference copyAssign; - copyAssign = ref; - foreach (const QQmlDebugPropertyReference &r, (QList<QQmlDebugPropertyReference>() << copy << copyAssign)) - compareProperties(r, ref); -} - void tst_QQmlEngineDebugService::setBindingForObject() { - QQmlDebugObjectReference rootObject = findRootObject(); - QVERIFY(rootObject.debugId() != -1); - QQmlDebugPropertyReference widthPropertyRef = findProperty(rootObject.properties(), "width"); + QmlDebugObjectReference rootObject = findRootObject(); + QVERIFY(rootObject.debugId != -1); + QmlDebugPropertyReference widthPropertyRef = findProperty(rootObject.properties, "width"); - QCOMPARE(widthPropertyRef.value(), QVariant(10)); - QCOMPARE(widthPropertyRef.binding(), QString()); + QCOMPARE(widthPropertyRef.value, QVariant(10)); + QCOMPARE(widthPropertyRef.binding, QString()); + bool success; // // set literal // - m_dbg->setBindingForObject(rootObject.debugId(), "width", "15", true); + m_dbg->setBindingForObject(rootObject.debugId, "width", "15", true, + QString(), -1, &success); + QVERIFY(success); + QVERIFY(QQmlDebugTest::waitForSignal(m_dbg, SIGNAL(result()))); + QCOMPARE(m_dbg->valid(), true); rootObject = findRootObject(); - widthPropertyRef = findProperty(rootObject.properties(), "width"); + widthPropertyRef = findProperty(rootObject.properties, "width"); - QCOMPARE(widthPropertyRef.value(), QVariant(15)); - QCOMPARE(widthPropertyRef.binding(), QString()); + QCOMPARE(widthPropertyRef.value, QVariant(15)); + QCOMPARE(widthPropertyRef.binding, QString()); // // set expression // - m_dbg->setBindingForObject(rootObject.debugId(), "width", "height", false); + m_dbg->setBindingForObject(rootObject.debugId, "width", "height", false, + QString(), -1, &success); + QVERIFY(success); + QVERIFY(QQmlDebugTest::waitForSignal(m_dbg, SIGNAL(result()))); + QCOMPARE(m_dbg->valid(), true); rootObject = findRootObject(); - widthPropertyRef = findProperty(rootObject.properties(), "width"); + widthPropertyRef = findProperty(rootObject.properties, "width"); - QCOMPARE(widthPropertyRef.value(), QVariant(20)); - QCOMPARE(widthPropertyRef.binding(), QString("height")); + QCOMPARE(widthPropertyRef.value, QVariant(20)); + QCOMPARE(widthPropertyRef.binding, QString("height")); // // reset // - m_dbg->resetBindingForObject(rootObject.debugId(), "width"); + m_dbg->resetBindingForObject(rootObject.debugId, "width", &success); + QVERIFY(success); + QVERIFY(QQmlDebugTest::waitForSignal(m_dbg, SIGNAL(result()))); + QCOMPARE(m_dbg->valid(), true); rootObject = findRootObject(); - widthPropertyRef = findProperty(rootObject.properties(), "width"); + widthPropertyRef = findProperty(rootObject.properties, "width"); // QCOMPARE(widthPropertyRef.value(), QVariant(0)); // TODO: Shouldn't this work? - QCOMPARE(widthPropertyRef.binding(), QString()); + QCOMPARE(widthPropertyRef.binding, QString()); // // set handler // rootObject = findRootObject(); - QCOMPARE(rootObject.children().size(), 5); // Rectangle, Text, MouseArea, Component.onCompleted, NonScriptPropertyElement - QQmlDebugObjectReference mouseAreaObject = rootObject.children().at(2); - QQmlDebugObjectQuery *q_obj = m_dbg->queryObjectRecursive(mouseAreaObject, this); - waitForQuery(q_obj); - mouseAreaObject = q_obj->object(); + QCOMPARE(rootObject.children.size(), 5); // Rectangle, Text, MouseArea, Component.onCompleted, NonScriptPropertyElement + QmlDebugObjectReference mouseAreaObject = rootObject.children.at(2); + m_dbg->queryObjectRecursive(mouseAreaObject, &success); + QVERIFY(success); + QVERIFY(QQmlDebugTest::waitForSignal(m_dbg, SIGNAL(result()))); + mouseAreaObject = m_dbg->object(); - QCOMPARE(mouseAreaObject.className(), QString("MouseArea")); + QCOMPARE(mouseAreaObject.className, QString("MouseArea")); - QQmlDebugPropertyReference onEnteredRef = findProperty(mouseAreaObject.properties(), "onEntered"); + QmlDebugPropertyReference onEnteredRef = findProperty(mouseAreaObject.properties, "onEntered"); - QCOMPARE(onEnteredRef.name(), QString("onEntered")); - QCOMPARE(onEnteredRef.value(), QVariant("(function onEntered() { { console.log('hello') } })")); + QCOMPARE(onEnteredRef.name, QString("onEntered")); + QCOMPARE(onEnteredRef.value, QVariant("(function onEntered() { { console.log('hello') } })")); - m_dbg->setBindingForObject(mouseAreaObject.debugId(), "onEntered", "{console.log('hello, world') }", false) ; + m_dbg->setBindingForObject(mouseAreaObject.debugId, "onEntered", + "{console.log('hello, world') }", false, + QString(), -1, &success); + QVERIFY(success); + QVERIFY(QQmlDebugTest::waitForSignal(m_dbg, SIGNAL(result()))); + QCOMPARE(m_dbg->valid(), true); rootObject = findRootObject(); - mouseAreaObject = rootObject.children().at(2); - q_obj = m_dbg->queryObjectRecursive(mouseAreaObject, this); - waitForQuery(q_obj); - mouseAreaObject = q_obj->object(); - onEnteredRef = findProperty(mouseAreaObject.properties(), "onEntered"); - QCOMPARE(onEnteredRef.name(), QString("onEntered")); - QCOMPARE(onEnteredRef.value(), QVariant("{console.log('hello, world') }")); + mouseAreaObject = rootObject.children.at(2); + m_dbg->queryObjectRecursive(mouseAreaObject, &success); + QVERIFY(success); + QVERIFY(QQmlDebugTest::waitForSignal(m_dbg, SIGNAL(result()))); + mouseAreaObject = m_dbg->object(); + onEnteredRef = findProperty(mouseAreaObject.properties, "onEntered"); + QCOMPARE(onEnteredRef.name, QString("onEntered")); + QCOMPARE(onEnteredRef.value, QVariant("{console.log('hello, world') }")); } void tst_QQmlEngineDebugService::setBindingInStates() @@ -1069,155 +825,151 @@ void tst_QQmlEngineDebugService::setBindingInStates() const int sourceIndex = 3; - QQmlDebugObjectReference obj = findRootObject(sourceIndex); - - QVERIFY(obj.debugId() != -1); - QVERIFY(obj.children().count() >= 2); + QmlDebugObjectReference obj = findRootObject(sourceIndex); + QVERIFY(obj.debugId != -1); + QVERIFY(obj.children.count() >= 2); + bool success; // We are going to switch state a couple of times, we need to get rid of the transition before - QQmlDebugExpressionQuery *q_deleteTransition = m_dbg->queryExpressionResult(obj.debugId(),QString("transitions = []"),this); - waitForQuery(q_deleteTransition); - delete q_deleteTransition; + m_dbg->queryExpressionResult(obj.debugId,QString("transitions = []"), &success); + QVERIFY(success); + QVERIFY(QQmlDebugTest::waitForSignal(m_dbg, SIGNAL(result()))); // check initial value of the property that is changing - QQmlDebugExpressionQuery *q_setState; - q_setState = m_dbg->queryExpressionResult(obj.debugId(),QString("state=\"state1\""),this); - waitForQuery(q_setState); - delete q_setState; + m_dbg->queryExpressionResult(obj.debugId,QString("state=\"state1\""), &success); + QVERIFY(success); + QVERIFY(QQmlDebugTest::waitForSignal(m_dbg, SIGNAL(result()))); obj = findRootObject(sourceIndex); - QCOMPARE(findProperty(obj.properties(),"width").value().toInt(),200); + QCOMPARE(findProperty(obj.properties,"width").value.toInt(),200); - q_setState = m_dbg->queryExpressionResult(obj.debugId(),QString("state=\"\""),this); - waitForQuery(q_setState); - delete q_setState; + m_dbg->queryExpressionResult(obj.debugId,QString("state=\"\""), + &success); + QVERIFY(success); + QVERIFY(QQmlDebugTest::waitForSignal(m_dbg, SIGNAL(result()))); obj = findRootObject(sourceIndex, true); - QCOMPARE(findProperty(obj.properties(),"width").value().toInt(),100); + QCOMPARE(findProperty(obj.properties,"width").value.toInt(),100); // change the binding - QQmlDebugObjectReference state = obj.children()[1]; - QCOMPARE(state.className(), QString("State")); - QVERIFY(state.children().count() > 0); + QmlDebugObjectReference state = obj.children[1]; + QCOMPARE(state.className, QString("State")); + QVERIFY(state.children.count() > 0); - QQmlDebugObjectReference propertyChange = state.children()[0]; - QVERIFY(propertyChange.debugId() != -1); + QmlDebugObjectReference propertyChange = state.children[0]; + QVERIFY(propertyChange.debugId != -1); - QVERIFY( m_dbg->setBindingForObject(propertyChange.debugId(), "width",QVariant(300),true) ); + m_dbg->setBindingForObject(propertyChange.debugId, "width",QVariant(300),true, + QString(), -1, &success); + QVERIFY(success); + QVERIFY(QQmlDebugTest::waitForSignal(m_dbg, SIGNAL(result()))); // check properties changed in state obj = findRootObject(sourceIndex); - QCOMPARE(findProperty(obj.properties(),"width").value().toInt(),100); + QCOMPARE(findProperty(obj.properties,"width").value.toInt(),100); - q_setState = m_dbg->queryExpressionResult(obj.debugId(),QString("state=\"state1\""),this); - waitForQuery(q_setState); - delete q_setState; + m_dbg->queryExpressionResult(obj.debugId,QString("state=\"state1\""), &success); + QVERIFY(success); + QVERIFY(QQmlDebugTest::waitForSignal(m_dbg, SIGNAL(result()))); obj = findRootObject(sourceIndex); - QCOMPARE(findProperty(obj.properties(),"width").value().toInt(),300); + QCOMPARE(findProperty(obj.properties,"width").value.toInt(),300); // check changing properties of base state from within a state - QVERIFY(m_dbg->setBindingForObject(obj.debugId(),"width","height*2",false)); - QVERIFY(m_dbg->setBindingForObject(obj.debugId(),"height","200",true)); + m_dbg->setBindingForObject(obj.debugId,"width","height*2",false, + QString(), -1, &success); + QVERIFY(success); + QVERIFY(QQmlDebugTest::waitForSignal(m_dbg, SIGNAL(result()))); + m_dbg->setBindingForObject(obj.debugId,"height","200",true, + QString(), -1, &success); + QVERIFY(success); + QVERIFY(QQmlDebugTest::waitForSignal(m_dbg, SIGNAL(result()))); obj = findRootObject(sourceIndex); - QCOMPARE(findProperty(obj.properties(),"width").value().toInt(),300); + QCOMPARE(findProperty(obj.properties,"width").value.toInt(),300); - q_setState = m_dbg->queryExpressionResult(obj.debugId(),QString("state=\"\""),this); - waitForQuery(q_setState); - delete q_setState; + m_dbg->queryExpressionResult(obj.debugId,QString("state=\"\""), &success); + QVERIFY(success); + QVERIFY(QQmlDebugTest::waitForSignal(m_dbg, SIGNAL(result()))); obj = findRootObject(sourceIndex); - QCOMPARE(findProperty(obj.properties(),"width").value().toInt(), 400); + QCOMPARE(findProperty(obj.properties,"width").value.toInt(), 400); // reset binding while in a state - q_setState = m_dbg->queryExpressionResult(obj.debugId(),QString("state=\"state1\""),this); - waitForQuery(q_setState); - delete q_setState; + m_dbg->queryExpressionResult(obj.debugId,QString("state=\"state1\""), &success); + QVERIFY(success); + QVERIFY(QQmlDebugTest::waitForSignal(m_dbg, SIGNAL(result()))); obj = findRootObject(sourceIndex); - QCOMPARE(findProperty(obj.properties(),"width").value().toInt(), 300); + QCOMPARE(findProperty(obj.properties,"width").value.toInt(), 300); - m_dbg->resetBindingForObject(propertyChange.debugId(), "width"); + m_dbg->resetBindingForObject(propertyChange.debugId, "width", &success); + QVERIFY(success); + QVERIFY(QQmlDebugTest::waitForSignal(m_dbg, SIGNAL(result()))); + QCOMPARE(m_dbg->valid(), true); obj = findRootObject(sourceIndex); - QCOMPARE(findProperty(obj.properties(),"width").value().toInt(), 400); + QCOMPARE(findProperty(obj.properties,"width").value.toInt(), 400); // re-add binding - m_dbg->setBindingForObject(propertyChange.debugId(), "width", "300", true); + m_dbg->setBindingForObject(propertyChange.debugId, "width", "300", true, + QString(), -1, &success); + QVERIFY(success); + QVERIFY(QQmlDebugTest::waitForSignal(m_dbg, SIGNAL(result()))); + QCOMPARE(m_dbg->valid(), true); obj = findRootObject(sourceIndex); - QCOMPARE(findProperty(obj.properties(),"width").value().toInt(), 300); + QCOMPARE(findProperty(obj.properties,"width").value.toInt(), 300); } void tst_QQmlEngineDebugService::queryObjectTree() { const int sourceIndex = 3; - // Check if states/transitions are initialized when fetching root item - QQmlDebugEnginesQuery *q_engines = m_dbg->queryAvailableEngines(this); - waitForQuery(q_engines); - - QQmlDebugRootContextQuery *q_context = m_dbg->queryRootContexts(q_engines->engines()[0].debugId(), this); - waitForQuery(q_context); - - QVERIFY(q_context->rootContext().contexts().count() >= sourceIndex); - int count = q_context->rootContext().contexts().count(); - QQmlDebugObjectReference rootObject = q_context->rootContext().contexts()[count - sourceIndex - 1].objects()[0]; - - QQmlDebugObjectQuery *q_obj = m_dbg->queryObjectRecursive(rootObject, this); - waitForQuery(q_obj); - - QQmlDebugObjectReference obj = q_obj->object(); - - delete q_engines; - delete q_context; - delete q_obj; - - QVERIFY(obj.debugId() != -1); - QVERIFY(obj.children().count() >= 2); - + QmlDebugObjectReference obj = findRootObject(sourceIndex, true); + QVERIFY(obj.debugId != -1); + QVERIFY(obj.children.count() >= 2); // check state - QQmlDebugObjectReference state = obj.children()[1]; - QCOMPARE(state.className(), QString("State")); - QVERIFY(state.children().count() > 0); + QmlDebugObjectReference state = obj.children[1]; + QCOMPARE(state.className, QString("State")); + QVERIFY(state.children.count() > 0); - QQmlDebugObjectReference propertyChange = state.children()[0]; - QVERIFY(propertyChange.debugId() != -1); + QmlDebugObjectReference propertyChange = state.children[0]; + QVERIFY(propertyChange.debugId != -1); - QQmlDebugPropertyReference propertyChangeTarget = findProperty(propertyChange.properties(),"target"); - QCOMPARE(propertyChangeTarget.objectDebugId(), propertyChange.debugId()); + QmlDebugPropertyReference propertyChangeTarget = findProperty(propertyChange.properties,"target"); + QCOMPARE(propertyChangeTarget.objectDebugId, propertyChange.debugId); - QQmlDebugObjectReference targetReference = qvariant_cast<QQmlDebugObjectReference>(propertyChangeTarget.value()); - QVERIFY(targetReference.debugId() != -1); + QmlDebugObjectReference targetReference = qvariant_cast<QmlDebugObjectReference>(propertyChangeTarget.value); + QVERIFY(targetReference.debugId != -1); // check transition - QQmlDebugObjectReference transition = obj.children()[0]; - QCOMPARE(transition.className(), QString("Transition")); - QCOMPARE(findProperty(transition.properties(),"from").value().toString(), QString("*")); - QCOMPARE(findProperty(transition.properties(),"to").value(), findProperty(state.properties(),"name").value()); - QVERIFY(transition.children().count() > 0); + QmlDebugObjectReference transition = obj.children[0]; + QCOMPARE(transition.className, QString("Transition")); + QCOMPARE(findProperty(transition.properties,"from").value.toString(), QString("*")); + QCOMPARE(findProperty(transition.properties,"to").value, findProperty(state.properties,"name").value); + QVERIFY(transition.children.count() > 0); - QQmlDebugObjectReference animation = transition.children()[0]; - QVERIFY(animation.debugId() != -1); + QmlDebugObjectReference animation = transition.children[0]; + QVERIFY(animation.debugId != -1); - QQmlDebugPropertyReference animationTarget = findProperty(animation.properties(),"target"); - QCOMPARE(animationTarget.objectDebugId(), animation.debugId()); + QmlDebugPropertyReference animationTarget = findProperty(animation.properties,"target"); + QCOMPARE(animationTarget.objectDebugId, animation.debugId); - targetReference = qvariant_cast<QQmlDebugObjectReference>(animationTarget.value()); - QVERIFY(targetReference.debugId() != -1); + targetReference = qvariant_cast<QmlDebugObjectReference>(animationTarget.value); + QVERIFY(targetReference.debugId != -1); - QCOMPARE(findProperty(animation.properties(),"property").value().toString(), QString("width")); - QCOMPARE(findProperty(animation.properties(),"duration").value().toInt(), 100); + QCOMPARE(findProperty(animation.properties,"property").value.toString(), QString("width")); + QCOMPARE(findProperty(animation.properties,"duration").value.toInt(), 100); } int main(int argc, char *argv[]) diff --git a/tests/auto/qml/debugger/qqmlinspector/app/app.pro b/tests/auto/qml/debugger/qqmlinspector/app/app.pro index 9c7574a97e..ce8bfc645a 100644 --- a/tests/auto/qml/debugger/qqmlinspector/app/app.pro +++ b/tests/auto/qml/debugger/qqmlinspector/app/app.pro @@ -1,4 +1,5 @@ TARGET = app +DESTDIR = $$OUT_PWD QT += qml quick CONFIG += declarative_debug diff --git a/tests/auto/qml/debugger/qqmlinspector/tst_qqmlinspector.cpp b/tests/auto/qml/debugger/qqmlinspector/tst_qqmlinspector.cpp index e30b847139..39e0f0d3e5 100644 --- a/tests/auto/qml/debugger/qqmlinspector/tst_qqmlinspector.cpp +++ b/tests/auto/qml/debugger/qqmlinspector/tst_qqmlinspector.cpp @@ -141,7 +141,11 @@ void tst_QQmlInspector::cleanupTestCase() void tst_QQmlInspector::init() { +#if defined(Q_OS_WIN) + const QString executable = "app\\app.exe"; +#else const QString executable = "app/app"; +#endif const QString argument = "-qmljsdebugger=port:"STR_PORT",block"; m_process = new QQmlDebugProcess(executable); diff --git a/tests/auto/qml/debugger/qqmlinspector/tst_qqmlinspector.pro b/tests/auto/qml/debugger/qqmlinspector/tst_qqmlinspector.pro index b4ca60b547..6d4758182e 100644 --- a/tests/auto/qml/debugger/qqmlinspector/tst_qqmlinspector.pro +++ b/tests/auto/qml/debugger/qqmlinspector/tst_qqmlinspector.pro @@ -9,4 +9,4 @@ include(../shared/debugutil.pri) CONFIG += parallel_test declarative_debug -QT += qml-private testlib +QT += qml testlib diff --git a/tests/auto/qml/debugger/qqmlprofilerservice/qqmlprofilerservice.pro b/tests/auto/qml/debugger/qqmlprofilerservice/qqmlprofilerservice.pro index 2bf43c92a2..a83590cf63 100644 --- a/tests/auto/qml/debugger/qqmlprofilerservice/qqmlprofilerservice.pro +++ b/tests/auto/qml/debugger/qqmlprofilerservice/qqmlprofilerservice.pro @@ -12,4 +12,4 @@ OTHER_FILES += data/test.qml CONFIG += parallel_test declarative_debug -QT += core-private v8-private qml-private testlib +QT += core qml testlib diff --git a/tests/auto/qml/debugger/qqmlprofilerservice/tst_qqmlprofilerservice.cpp b/tests/auto/qml/debugger/qqmlprofilerservice/tst_qqmlprofilerservice.cpp index 2b33ab3944..972c3ac6f4 100644 --- a/tests/auto/qml/debugger/qqmlprofilerservice/tst_qqmlprofilerservice.cpp +++ b/tests/auto/qml/debugger/qqmlprofilerservice/tst_qqmlprofilerservice.cpp @@ -42,7 +42,6 @@ #include <qtest.h> #include <QLibraryInfo> -#include "QtQml/private/qqmlprofilerservice_p.h" #include "debugutil_p.h" #include "qqmldebugclient.h" #include "../../../shared/util.h" @@ -50,11 +49,59 @@ #define PORT 13773 #define STR_PORT "13773" +struct QQmlProfilerData +{ + qint64 time; + int messageType; + int detailType; + + //### + QString detailData; //used by RangeData and RangeLocation + int line; //used by RangeLocation + int column; //used by RangeLocation + int framerate; //used by animation events + int animationcount; //used by animation events + + QByteArray toByteArray() const; +}; + class QQmlProfilerClient : public QQmlDebugClient { Q_OBJECT public: + enum Message { + Event, + RangeStart, + RangeData, + RangeLocation, + RangeEnd, + Complete, // end of transmission + + MaximumMessage + }; + + enum EventType { + FramePaint, + Mouse, + Key, + AnimationFrame, + EndTrace, + StartTrace, + + MaximumEventType + }; + + enum RangeType { + Painting, + Compiling, + Creating, + Binding, //running a binding + HandlingSignal, //running a signal handler + + MaximumRangeType + }; + QQmlProfilerClient(QQmlDebugConnection *connection) : QQmlDebugClient(QLatin1String("CanvasFrameRate"), connection) { @@ -123,21 +170,21 @@ void QQmlProfilerClient::messageReceived(const QByteArray &message) QVERIFY(data.time >= -1); switch (data.messageType) { - case (QQmlProfilerService::Event): { + case (QQmlProfilerClient::Event): { stream >> data.detailType; switch (data.detailType) { - case QQmlProfilerService::AnimationFrame: { + case QQmlProfilerClient::AnimationFrame: { stream >> data.framerate >> data.animationcount; QVERIFY(data.framerate != -1); QVERIFY(data.animationcount != -1); break; } - case QQmlProfilerService::FramePaint: - case QQmlProfilerService::Mouse: - case QQmlProfilerService::Key: - case QQmlProfilerService::StartTrace: - case QQmlProfilerService::EndTrace: + case QQmlProfilerClient::FramePaint: + case QQmlProfilerClient::Mouse: + case QQmlProfilerClient::Key: + case QQmlProfilerClient::StartTrace: + case QQmlProfilerClient::EndTrace: break; default: { QString failMsg = QString("Unknown event type:") + data.detailType; @@ -147,28 +194,28 @@ void QQmlProfilerClient::messageReceived(const QByteArray &message) } break; } - case QQmlProfilerService::Complete: { + case QQmlProfilerClient::Complete: { emit complete(); return; } - case QQmlProfilerService::RangeStart: { + case QQmlProfilerClient::RangeStart: { stream >> data.detailType; - QVERIFY(data.detailType >= 0 && data.detailType < QQmlProfilerService::MaximumRangeType); + QVERIFY(data.detailType >= 0 && data.detailType < QQmlProfilerClient::MaximumRangeType); break; } - case QQmlProfilerService::RangeEnd: { + case QQmlProfilerClient::RangeEnd: { stream >> data.detailType; - QVERIFY(data.detailType >= 0 && data.detailType < QQmlProfilerService::MaximumRangeType); + QVERIFY(data.detailType >= 0 && data.detailType < QQmlProfilerClient::MaximumRangeType); break; } - case QQmlProfilerService::RangeData: { + case QQmlProfilerClient::RangeData: { stream >> data.detailType >> data.detailData; - QVERIFY(data.detailType >= 0 && data.detailType < QQmlProfilerService::MaximumRangeType); + QVERIFY(data.detailType >= 0 && data.detailType < QQmlProfilerClient::MaximumRangeType); break; } - case QQmlProfilerService::RangeLocation: { + case QQmlProfilerClient::RangeLocation: { stream >> data.detailType >> data.detailData >> data.line >> data.column; - QVERIFY(data.detailType >= 0 && data.detailType < QQmlProfilerService::MaximumRangeType); + QVERIFY(data.detailType >= 0 && data.detailType < QQmlProfilerClient::MaximumRangeType); QVERIFY(data.line >= -2); break; } @@ -229,12 +276,12 @@ void tst_QQmlProfilerService::blockingConnectWithTraceEnabled() QVERIFY(m_client->traceMessages.count()); // must start with "StartTrace" - QCOMPARE(m_client->traceMessages.first().messageType, (int)QQmlProfilerService::Event); - QCOMPARE(m_client->traceMessages.first().detailType, (int)QQmlProfilerService::StartTrace); + QCOMPARE(m_client->traceMessages.first().messageType, (int)QQmlProfilerClient::Event); + QCOMPARE(m_client->traceMessages.first().detailType, (int)QQmlProfilerClient::StartTrace); // must end with "EndTrace" - QCOMPARE(m_client->traceMessages.last().messageType, (int)QQmlProfilerService::Event); - QCOMPARE(m_client->traceMessages.last().detailType, (int)QQmlProfilerService::EndTrace); + QCOMPARE(m_client->traceMessages.last().messageType, (int)QQmlProfilerClient::Event); + QCOMPARE(m_client->traceMessages.last().detailType, (int)QQmlProfilerClient::EndTrace); } void tst_QQmlProfilerService::blockingConnectWithTraceDisabled() @@ -254,12 +301,12 @@ void tst_QQmlProfilerService::blockingConnectWithTraceDisabled() QVERIFY(m_client->traceMessages.count()); // must start with "StartTrace" - QCOMPARE(m_client->traceMessages.first().messageType, (int)QQmlProfilerService::Event); - QCOMPARE(m_client->traceMessages.first().detailType, (int)QQmlProfilerService::StartTrace); + QCOMPARE(m_client->traceMessages.first().messageType, (int)QQmlProfilerClient::Event); + QCOMPARE(m_client->traceMessages.first().detailType, (int)QQmlProfilerClient::StartTrace); // must end with "EndTrace" - QCOMPARE(m_client->traceMessages.last().messageType, (int)QQmlProfilerService::Event); - QCOMPARE(m_client->traceMessages.last().detailType, (int)QQmlProfilerService::EndTrace); + QCOMPARE(m_client->traceMessages.last().messageType, (int)QQmlProfilerClient::Event); + QCOMPARE(m_client->traceMessages.last().detailType, (int)QQmlProfilerClient::EndTrace); } void tst_QQmlProfilerService::nonBlockingConnect() @@ -276,12 +323,12 @@ void tst_QQmlProfilerService::nonBlockingConnect() } // must start with "StartTrace" - QCOMPARE(m_client->traceMessages.first().messageType, (int)QQmlProfilerService::Event); - QCOMPARE(m_client->traceMessages.first().detailType, (int)QQmlProfilerService::StartTrace); + QCOMPARE(m_client->traceMessages.first().messageType, (int)QQmlProfilerClient::Event); + QCOMPARE(m_client->traceMessages.first().detailType, (int)QQmlProfilerClient::StartTrace); // must end with "EndTrace" - QCOMPARE(m_client->traceMessages.last().messageType, (int)QQmlProfilerService::Event); - QCOMPARE(m_client->traceMessages.last().detailType, (int)QQmlProfilerService::EndTrace); + QCOMPARE(m_client->traceMessages.last().messageType, (int)QQmlProfilerClient::Event); + QCOMPARE(m_client->traceMessages.last().detailType, (int)QQmlProfilerClient::EndTrace); } void tst_QQmlProfilerService::profileOnExit() @@ -298,12 +345,12 @@ void tst_QQmlProfilerService::profileOnExit() } // must start with "StartTrace" - QCOMPARE(m_client->traceMessages.first().messageType, (int)QQmlProfilerService::Event); - QCOMPARE(m_client->traceMessages.first().detailType, (int)QQmlProfilerService::StartTrace); + QCOMPARE(m_client->traceMessages.first().messageType, (int)QQmlProfilerClient::Event); + QCOMPARE(m_client->traceMessages.first().detailType, (int)QQmlProfilerClient::StartTrace); // must end with "EndTrace" - QCOMPARE(m_client->traceMessages.last().messageType, (int)QQmlProfilerService::Event); - QCOMPARE(m_client->traceMessages.last().detailType, (int)QQmlProfilerService::EndTrace); + QCOMPARE(m_client->traceMessages.last().messageType, (int)QQmlProfilerClient::Event); + QCOMPARE(m_client->traceMessages.last().detailType, (int)QQmlProfilerClient::EndTrace); } QTEST_MAIN(tst_QQmlProfilerService) diff --git a/tests/auto/qml/debugger/qv8profilerservice/qv8profilerservice.pro b/tests/auto/qml/debugger/qv8profilerservice/qv8profilerservice.pro index a8dd634855..5088953c92 100644 --- a/tests/auto/qml/debugger/qv8profilerservice/qv8profilerservice.pro +++ b/tests/auto/qml/debugger/qv8profilerservice/qv8profilerservice.pro @@ -12,4 +12,4 @@ OTHER_FILES += data/test.qml CONFIG += parallel_test declarative_debug -QT += qml-private testlib +QT += qml testlib diff --git a/tests/auto/qml/debugger/qv8profilerservice/tst_qv8profilerservice.cpp b/tests/auto/qml/debugger/qv8profilerservice/tst_qv8profilerservice.cpp index 7b9cda937c..497d544390 100644 --- a/tests/auto/qml/debugger/qv8profilerservice/tst_qv8profilerservice.cpp +++ b/tests/auto/qml/debugger/qv8profilerservice/tst_qv8profilerservice.cpp @@ -42,7 +42,6 @@ #include <qtest.h> #include <QLibraryInfo> -#include "QtQml/private/qv8profilerservice_p.h" #include "debugutil_p.h" #include "qqmldebugclient.h" #include "../../../shared/util.h" @@ -50,11 +49,34 @@ #define PORT 13774 #define STR_PORT "13774" +struct QV8ProfilerData +{ + int messageType; + QString filename; + QString functionname; + int lineNumber; + double totalTime; + double selfTime; + int treeLevel; + + QByteArray toByteArray() const; +}; + class QV8ProfilerClient : public QQmlDebugClient { Q_OBJECT public: + enum MessageType { + V8Entry, + V8Complete, + V8SnapshotChunk, + V8SnapshotComplete, + V8Started, + + V8MaximumMessage + }; + QV8ProfilerClient(QQmlDebugConnection *connection) : QQmlDebugClient(QLatin1String("V8Profiler"), connection) { @@ -139,28 +161,28 @@ void QV8ProfilerClient::messageReceived(const QByteArray &message) stream >> messageType; QVERIFY(messageType >= 0); - QVERIFY(messageType < QV8ProfilerService::V8MaximumMessage); + QVERIFY(messageType < QV8ProfilerClient::V8MaximumMessage); switch (messageType) { - case QV8ProfilerService::V8Entry: { + case QV8ProfilerClient::V8Entry: { QV8ProfilerData entry; stream >> entry.filename >> entry.functionname >> entry.lineNumber >> entry.totalTime >> entry.selfTime >> entry.treeLevel; traceMessages.append(entry); break; } - case QV8ProfilerService::V8Complete: + case QV8ProfilerClient::V8Complete: emit complete(); break; - case QV8ProfilerService::V8SnapshotChunk: { + case QV8ProfilerClient::V8SnapshotChunk: { QByteArray json; stream >> json; snapshotMessages.append(json); break; } - case QV8ProfilerService::V8SnapshotComplete: + case QV8ProfilerClient::V8SnapshotComplete: emit snapshot(); break; - case QV8ProfilerService::V8Started: + case QV8ProfilerClient::V8Started: emit started(); break; default: diff --git a/tests/auto/qml/debugger/shared/debugutil.cpp b/tests/auto/qml/debugger/shared/debugutil.cpp index 3d2f460456..ac9fa5fae2 100644 --- a/tests/auto/qml/debugger/shared/debugutil.cpp +++ b/tests/auto/qml/debugger/shared/debugutil.cpp @@ -55,23 +55,6 @@ bool QQmlDebugTest::waitForSignal(QObject *receiver, const char *member, int tim return timer.isActive(); } -QQmlDebugTestService::QQmlDebugTestService(const QString &s, float version, QObject *parent) - : QQmlDebugService(s, version, parent) -{ - registerService(); -} - -void QQmlDebugTestService::messageReceived(const QByteArray &ba) -{ - sendMessage(ba); -} - -void QQmlDebugTestService::stateChanged(State) -{ - emit stateHasChanged(); -} - - QQmlDebugTestClient::QQmlDebugTestClient(const QString &s, QQmlDebugConnection *c) : QQmlDebugClient(s, c) { diff --git a/tests/auto/qml/debugger/shared/debugutil.pri b/tests/auto/qml/debugger/shared/debugutil.pri index b74f6b08b0..cb9c761395 100644 --- a/tests/auto/qml/debugger/shared/debugutil.pri +++ b/tests/auto/qml/debugger/shared/debugutil.pri @@ -1,9 +1,8 @@ -QT += core-private - HEADERS += $$PWD/debugutil_p.h \ $$PWD/qqmldebugclient.h \ - $$PWD/qqmlenginedebug_p.h + $$PWD/../../../../../src/plugins/qmltooling/shared/qpacketprotocol.h + SOURCES += $$PWD/debugutil.cpp \ $$PWD/qqmldebugclient.cpp \ - $$PWD/qqmlenginedebug.cpp + $$PWD/../../../../../src/plugins/qmltooling/shared/qpacketprotocol.cpp diff --git a/tests/auto/qml/debugger/shared/debugutil_p.h b/tests/auto/qml/debugger/shared/debugutil_p.h index 177c712833..2ea295b822 100644 --- a/tests/auto/qml/debugger/shared/debugutil_p.h +++ b/tests/auto/qml/debugger/shared/debugutil_p.h @@ -52,7 +52,6 @@ #include <QtQml/qqmlengine.h> #include "qqmldebugclient.h" -#include <private/qqmldebugservice_p.h> class QQmlDebugTest { @@ -60,20 +59,6 @@ public: static bool waitForSignal(QObject *receiver, const char *member, int timeout = 5000); }; -class QQmlDebugTestService : public QQmlDebugService -{ - Q_OBJECT -public: - QQmlDebugTestService(const QString &s, float version = 1, QObject *parent = 0); - -signals: - void stateHasChanged(); - -protected: - virtual void messageReceived(const QByteArray &ba); - virtual void stateChanged(State state); -}; - class QQmlDebugTestClient : public QQmlDebugClient { Q_OBJECT diff --git a/tests/auto/qml/debugger/shared/qqmldebugclient.cpp b/tests/auto/qml/debugger/shared/qqmldebugclient.cpp index 0453f88350..50feb950fb 100644 --- a/tests/auto/qml/debugger/shared/qqmldebugclient.cpp +++ b/tests/auto/qml/debugger/shared/qqmldebugclient.cpp @@ -40,8 +40,7 @@ ****************************************************************************/ #include "qqmldebugclient.h" - -#include <private/qpacketprotocol_p.h> +#include "../../../../../src/plugins/qmltooling/shared/qpacketprotocol.h" #include <QtCore/qdebug.h> #include <QtCore/qstringlist.h> diff --git a/tests/auto/qml/debugger/shared/qqmldebugclient.h b/tests/auto/qml/debugger/shared/qqmldebugclient.h index 1b05e86a64..0f140a1db1 100644 --- a/tests/auto/qml/debugger/shared/qqmldebugclient.h +++ b/tests/auto/qml/debugger/shared/qqmldebugclient.h @@ -44,8 +44,6 @@ #include <QtNetwork/qtcpsocket.h> -#include <private/qtqmlglobal_p.h> - class QQmlDebugConnectionPrivate; class QQmlDebugConnection : public QIODevice { @@ -84,7 +82,6 @@ class QQmlDebugClientPrivate; class QQmlDebugClient : public QObject { Q_OBJECT - Q_DECLARE_PRIVATE(QQmlDebugClient) Q_DISABLE_COPY(QQmlDebugClient) public: diff --git a/tests/auto/qml/debugger/shared/qqmldebugtestservice.cpp b/tests/auto/qml/debugger/shared/qqmldebugtestservice.cpp new file mode 100644 index 0000000000..1c8afd836b --- /dev/null +++ b/tests/auto/qml/debugger/shared/qqmldebugtestservice.cpp @@ -0,0 +1,58 @@ +/**************************************************************************** +** +** Copyright (C) 2012 Nokia Corporation and/or its subsidiary(-ies). +** Contact: http://www.qt-project.org/ +** +** This file is part of the test suite of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** GNU Lesser General Public License Usage +** 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, Nokia gives you certain additional +** rights. These rights are described in the Nokia 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. +** +** Other Usage +** Alternatively, this file may be used in accordance with the terms and +** conditions contained in a signed written agreement between you and Nokia. +** +** +** +** +** +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#include "qqmldebugtestservice.h" + +QQmlDebugTestService::QQmlDebugTestService(const QString &s, float version, QObject *parent) + : QQmlDebugService(s, version, parent) +{ + registerService(); +} + +void QQmlDebugTestService::messageReceived(const QByteArray &ba) +{ + sendMessage(ba); +} + +void QQmlDebugTestService::stateChanged(State) +{ + emit stateHasChanged(); +} diff --git a/tests/auto/qml/debugger/shared/qqmldebugtestservice.h b/tests/auto/qml/debugger/shared/qqmldebugtestservice.h new file mode 100644 index 0000000000..14fda551de --- /dev/null +++ b/tests/auto/qml/debugger/shared/qqmldebugtestservice.h @@ -0,0 +1,62 @@ + +/**************************************************************************** +** +** Copyright (C) 2012 Nokia Corporation and/or its subsidiary(-ies). +** Contact: http://www.qt-project.org/ +** +** This file is part of the test suite of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** GNU Lesser General Public License Usage +** 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, Nokia gives you certain additional +** rights. These rights are described in the Nokia 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. +** +** Other Usage +** Alternatively, this file may be used in accordance with the terms and +** conditions contained in a signed written agreement between you and Nokia. +** +** +** +** +** +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#ifndef QQMLDEBUGTESTSERVICE_H +#define QQMLDEBUGTESTSERVICE_H + +#include <private/qqmldebugservice_p.h> + +class QQmlDebugTestService : public QQmlDebugService +{ + Q_OBJECT +public: + QQmlDebugTestService(const QString &s, float version = 1, QObject *parent = 0); + +signals: + void stateHasChanged(); + +protected: + virtual void messageReceived(const QByteArray &ba); + virtual void stateChanged(State state); +}; + +#endif // QQMLDEBUGTESTSERVICE_H diff --git a/tests/auto/qml/debugger/shared/qqmlenginedebug.cpp b/tests/auto/qml/debugger/shared/qqmlenginedebug.cpp deleted file mode 100644 index 8a46c7617c..0000000000 --- a/tests/auto/qml/debugger/shared/qqmlenginedebug.cpp +++ /dev/null @@ -1,1068 +0,0 @@ -/**************************************************************************** -** -** Copyright (C) 2012 Nokia Corporation and/or its subsidiary(-ies). -** Contact: http://www.qt-project.org/ -** -** This file is part of the QtQml module of the Qt Toolkit. -** -** $QT_BEGIN_LICENSE:LGPL$ -** GNU Lesser General Public License Usage -** 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, Nokia gives you certain additional -** rights. These rights are described in the Nokia 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. -** -** Other Usage -** Alternatively, this file may be used in accordance with the terms and -** conditions contained in a signed written agreement between you and Nokia. -** -** -** -** -** -** -** $QT_END_LICENSE$ -** -****************************************************************************/ - -#include "qqmlenginedebug_p.h" - -#include "qqmldebugclient.h" - -#include <private/qqmlenginedebugservice_p.h> - -#include <QtCore/private/qobject_p.h> - -class QQmlEngineDebugClient : public QQmlDebugClient -{ -public: - QQmlEngineDebugClient(QQmlDebugConnection *client, QQmlEngineDebugPrivate *p); - -protected: - virtual void stateChanged(State state); - virtual void messageReceived(const QByteArray &); - -private: - QQmlEngineDebugPrivate *priv; - friend class QQmlEngineDebugPrivate; -}; - -class QQmlEngineDebugPrivate : public QObjectPrivate -{ - Q_DECLARE_PUBLIC(QQmlEngineDebug) -public: - QQmlEngineDebugPrivate(QQmlDebugConnection *); - ~QQmlEngineDebugPrivate(); - - void stateChanged(QQmlEngineDebug::State status); - void message(const QByteArray &); - - QQmlEngineDebugClient *client; - int nextId; - int getId(); - - void decode(QDataStream &, QQmlDebugContextReference &); - void decode(QDataStream &, QQmlDebugObjectReference &, bool simple); - - static void remove(QQmlEngineDebug *, QQmlDebugEnginesQuery *); - static void remove(QQmlEngineDebug *, QQmlDebugRootContextQuery *); - static void remove(QQmlEngineDebug *, QQmlDebugObjectQuery *); - static void remove(QQmlEngineDebug *, QQmlDebugExpressionQuery *); - static void remove(QQmlEngineDebug *, QQmlDebugWatch *); - - QHash<int, QQmlDebugEnginesQuery *> enginesQuery; - QHash<int, QQmlDebugRootContextQuery *> rootContextQuery; - QHash<int, QQmlDebugObjectQuery *> objectQuery; - QHash<int, QQmlDebugExpressionQuery *> expressionQuery; - - QHash<int, QQmlDebugWatch *> watched; -}; - -QQmlEngineDebugClient::QQmlEngineDebugClient(QQmlDebugConnection *client, - QQmlEngineDebugPrivate *p) - : QQmlDebugClient(QLatin1String("QDeclarativeEngine"), client), priv(p) -{ -} - -void QQmlEngineDebugClient::stateChanged(State status) -{ - if (priv) - priv->stateChanged(static_cast<QQmlEngineDebug::State>(status)); -} - -void QQmlEngineDebugClient::messageReceived(const QByteArray &data) -{ - if (priv) - priv->message(data); -} - -QQmlEngineDebugPrivate::QQmlEngineDebugPrivate(QQmlDebugConnection *c) - : client(new QQmlEngineDebugClient(c, this)), nextId(0) -{ -} - -QQmlEngineDebugPrivate::~QQmlEngineDebugPrivate() -{ - if (client) - client->priv = 0; - delete client; - - QHash<int, QQmlDebugEnginesQuery*>::iterator enginesIter = enginesQuery.begin(); - for (; enginesIter != enginesQuery.end(); ++enginesIter) { - enginesIter.value()->m_client = 0; - if (enginesIter.value()->state() == QQmlDebugQuery::Waiting) - enginesIter.value()->setState(QQmlDebugQuery::Error); - } - - QHash<int, QQmlDebugRootContextQuery*>::iterator rootContextIter = rootContextQuery.begin(); - for (; rootContextIter != rootContextQuery.end(); ++rootContextIter) { - rootContextIter.value()->m_client = 0; - if (rootContextIter.value()->state() == QQmlDebugQuery::Waiting) - rootContextIter.value()->setState(QQmlDebugQuery::Error); - } - - QHash<int, QQmlDebugObjectQuery*>::iterator objectIter = objectQuery.begin(); - for (; objectIter != objectQuery.end(); ++objectIter) { - objectIter.value()->m_client = 0; - if (objectIter.value()->state() == QQmlDebugQuery::Waiting) - objectIter.value()->setState(QQmlDebugQuery::Error); - } - - QHash<int, QQmlDebugExpressionQuery*>::iterator exprIter = expressionQuery.begin(); - for (; exprIter != expressionQuery.end(); ++exprIter) { - exprIter.value()->m_client = 0; - if (exprIter.value()->state() == QQmlDebugQuery::Waiting) - exprIter.value()->setState(QQmlDebugQuery::Error); - } - - QHash<int, QQmlDebugWatch*>::iterator watchIter = watched.begin(); - for (; watchIter != watched.end(); ++watchIter) { - watchIter.value()->m_client = 0; - watchIter.value()->setState(QQmlDebugWatch::Dead); - } -} - -int QQmlEngineDebugPrivate::getId() -{ - return nextId++; -} - -void QQmlEngineDebugPrivate::remove(QQmlEngineDebug *c, QQmlDebugEnginesQuery *q) -{ - if (c && q) { - QQmlEngineDebugPrivate *p = (QQmlEngineDebugPrivate *)QObjectPrivate::get(c); - p->enginesQuery.remove(q->m_queryId); - } -} - -void QQmlEngineDebugPrivate::remove(QQmlEngineDebug *c, - QQmlDebugRootContextQuery *q) -{ - if (c && q) { - QQmlEngineDebugPrivate *p = (QQmlEngineDebugPrivate *)QObjectPrivate::get(c); - p->rootContextQuery.remove(q->m_queryId); - } -} - -void QQmlEngineDebugPrivate::remove(QQmlEngineDebug *c, QQmlDebugObjectQuery *q) -{ - if (c && q) { - QQmlEngineDebugPrivate *p = (QQmlEngineDebugPrivate *)QObjectPrivate::get(c); - p->objectQuery.remove(q->m_queryId); - } -} - -void QQmlEngineDebugPrivate::remove(QQmlEngineDebug *c, QQmlDebugExpressionQuery *q) -{ - if (c && q) { - QQmlEngineDebugPrivate *p = (QQmlEngineDebugPrivate *)QObjectPrivate::get(c); - p->expressionQuery.remove(q->m_queryId); - } -} - -void QQmlEngineDebugPrivate::remove(QQmlEngineDebug *c, QQmlDebugWatch *w) -{ - if (c && w) { - QQmlEngineDebugPrivate *p = (QQmlEngineDebugPrivate *)QObjectPrivate::get(c); - p->watched.remove(w->m_queryId); - } -} - -void QQmlEngineDebugPrivate::decode(QDataStream &ds, QQmlDebugObjectReference &o, - bool simple) -{ - QQmlEngineDebugService::QQmlObjectData data; - ds >> data; - o.m_debugId = data.objectId; - o.m_class = data.objectType; - o.m_idString = data.idString; - o.m_name = data.objectName; - o.m_source.m_url = data.url; - o.m_source.m_lineNumber = data.lineNumber; - o.m_source.m_columnNumber = data.columnNumber; - o.m_contextDebugId = data.contextId; - - if (simple) - return; - - int childCount; - bool recur; - ds >> childCount >> recur; - - for (int ii = 0; ii < childCount; ++ii) { - o.m_children.append(QQmlDebugObjectReference()); - decode(ds, o.m_children.last(), !recur); - } - - int propCount; - ds >> propCount; - - for (int ii = 0; ii < propCount; ++ii) { - QQmlEngineDebugService::QQmlObjectProperty data; - ds >> data; - QQmlDebugPropertyReference prop; - prop.m_objectDebugId = o.m_debugId; - prop.m_name = data.name; - prop.m_binding = data.binding; - prop.m_hasNotifySignal = data.hasNotifySignal; - prop.m_valueTypeName = data.valueTypeName; - switch (data.type) { - case QQmlEngineDebugService::QQmlObjectProperty::Basic: - case QQmlEngineDebugService::QQmlObjectProperty::List: - case QQmlEngineDebugService::QQmlObjectProperty::SignalProperty: - { - prop.m_value = data.value; - break; - } - case QQmlEngineDebugService::QQmlObjectProperty::Object: - { - QQmlDebugObjectReference obj; - obj.m_debugId = prop.m_value.toInt(); - prop.m_value = QVariant::fromValue(obj); - break; - } - case QQmlEngineDebugService::QQmlObjectProperty::Unknown: - break; - } - o.m_properties << prop; - } -} - -void QQmlEngineDebugPrivate::decode(QDataStream &ds, QQmlDebugContextReference &c) -{ - ds >> c.m_name >> c.m_debugId; - - int contextCount; - ds >> contextCount; - - for (int ii = 0; ii < contextCount; ++ii) { - c.m_contexts.append(QQmlDebugContextReference()); - decode(ds, c.m_contexts.last()); - } - - int objectCount; - ds >> objectCount; - - for (int ii = 0; ii < objectCount; ++ii) { - QQmlDebugObjectReference obj; - decode(ds, obj, true); - - obj.m_contextDebugId = c.m_debugId; - c.m_objects << obj; - } -} - -void QQmlEngineDebugPrivate::stateChanged(QQmlEngineDebug::State status) -{ - emit q_func()->stateChanged(status); -} - -void QQmlEngineDebugPrivate::message(const QByteArray &data) -{ - QDataStream ds(data); - - QByteArray type; - ds >> type; - - //qDebug() << "QQmlEngineDebugPrivate::message()" << type; - - if (type == "LIST_ENGINES_R") { - int queryId; - ds >> queryId; - - QQmlDebugEnginesQuery *query = enginesQuery.value(queryId); - if (!query) - return; - enginesQuery.remove(queryId); - - int count; - ds >> count; - - for (int ii = 0; ii < count; ++ii) { - QQmlDebugEngineReference ref; - ds >> ref.m_name; - ds >> ref.m_debugId; - query->m_engines << ref; - } - - query->m_client = 0; - query->setState(QQmlDebugQuery::Completed); - } else if (type == "LIST_OBJECTS_R") { - int queryId; - ds >> queryId; - - QQmlDebugRootContextQuery *query = rootContextQuery.value(queryId); - if (!query) - return; - rootContextQuery.remove(queryId); - - if (!ds.atEnd()) - decode(ds, query->m_context); - - query->m_client = 0; - query->setState(QQmlDebugQuery::Completed); - } else if (type == "FETCH_OBJECT_R") { - int queryId; - ds >> queryId; - - QQmlDebugObjectQuery *query = objectQuery.value(queryId); - if (!query) - return; - objectQuery.remove(queryId); - - if (!ds.atEnd()) - decode(ds, query->m_object, false); - - query->m_client = 0; - query->setState(QQmlDebugQuery::Completed); - } else if (type == "EVAL_EXPRESSION_R") { - int queryId; - QVariant result; - ds >> queryId >> result; - - QQmlDebugExpressionQuery *query = expressionQuery.value(queryId); - if (!query) - return; - expressionQuery.remove(queryId); - - query->m_result = result; - query->m_client = 0; - query->setState(QQmlDebugQuery::Completed); - } else if (type == "WATCH_PROPERTY_R") { - int queryId; - bool ok; - ds >> queryId >> ok; - - QQmlDebugWatch *watch = watched.value(queryId); - if (!watch) - return; - - watch->setState(ok ? QQmlDebugWatch::Active : QQmlDebugWatch::Inactive); - } else if (type == "WATCH_OBJECT_R") { - int queryId; - bool ok; - ds >> queryId >> ok; - - QQmlDebugWatch *watch = watched.value(queryId); - if (!watch) - return; - - watch->setState(ok ? QQmlDebugWatch::Active : QQmlDebugWatch::Inactive); - } else if (type == "WATCH_EXPR_OBJECT_R") { - int queryId; - bool ok; - ds >> queryId >> ok; - - QQmlDebugWatch *watch = watched.value(queryId); - if (!watch) - return; - - watch->setState(ok ? QQmlDebugWatch::Active : QQmlDebugWatch::Inactive); - } else if (type == "UPDATE_WATCH") { - int queryId; - int debugId; - QByteArray name; - QVariant value; - ds >> queryId >> debugId >> name >> value; - - QQmlDebugWatch *watch = watched.value(queryId, 0); - if (!watch) - return; - emit watch->valueChanged(name, value); - } else if (type == "OBJECT_CREATED") { - emit q_func()->newObjects(); - } -} - -QQmlEngineDebug::QQmlEngineDebug(QQmlDebugConnection *client, QObject *parent) - : QObject(*(new QQmlEngineDebugPrivate(client)), parent) -{ -} - -QQmlEngineDebug::~QQmlEngineDebug() -{ -} - -QQmlEngineDebug::State QQmlEngineDebug::state() const -{ - Q_D(const QQmlEngineDebug); - - return static_cast<QQmlEngineDebug::State>(d->client->state()); -} - -QQmlDebugPropertyWatch *QQmlEngineDebug::addWatch(const QQmlDebugPropertyReference &property, QObject *parent) -{ - Q_D(QQmlEngineDebug); - - QQmlDebugPropertyWatch *watch = new QQmlDebugPropertyWatch(parent); - if (d->client->state() == QQmlDebugClient::Enabled) { - int queryId = d->getId(); - watch->m_queryId = queryId; - watch->m_client = this; - watch->m_objectDebugId = property.objectDebugId(); - watch->m_name = property.name(); - d->watched.insert(queryId, watch); - - QByteArray message; - QDataStream ds(&message, QIODevice::WriteOnly); - ds << QByteArray("WATCH_PROPERTY") << queryId << property.objectDebugId() << property.name().toUtf8(); - d->client->sendMessage(message); - } else { - watch->m_state = QQmlDebugWatch::Dead; - } - - return watch; -} - -QQmlDebugWatch *QQmlEngineDebug::addWatch(const QQmlDebugContextReference &, const QString &, QObject *) -{ - qWarning("QQmlEngineDebug::addWatch(): Not implemented"); - return 0; -} - -QQmlDebugObjectExpressionWatch *QQmlEngineDebug::addWatch(const QQmlDebugObjectReference &object, const QString &expr, QObject *parent) -{ - Q_D(QQmlEngineDebug); - QQmlDebugObjectExpressionWatch *watch = new QQmlDebugObjectExpressionWatch(parent); - if (d->client->state() == QQmlDebugClient::Enabled) { - int queryId = d->getId(); - watch->m_queryId = queryId; - watch->m_client = this; - watch->m_objectDebugId = object.debugId(); - watch->m_expr = expr; - d->watched.insert(queryId, watch); - - QByteArray message; - QDataStream ds(&message, QIODevice::WriteOnly); - ds << QByteArray("WATCH_EXPR_OBJECT") << queryId << object.debugId() << expr; - d->client->sendMessage(message); - } else { - watch->m_state = QQmlDebugWatch::Dead; - } - return watch; -} - -QQmlDebugWatch *QQmlEngineDebug::addWatch(const QQmlDebugObjectReference &object, QObject *parent) -{ - Q_D(QQmlEngineDebug); - - QQmlDebugWatch *watch = new QQmlDebugWatch(parent); - if (d->client->state() == QQmlDebugClient::Enabled) { - int queryId = d->getId(); - watch->m_queryId = queryId; - watch->m_client = this; - watch->m_objectDebugId = object.debugId(); - d->watched.insert(queryId, watch); - - QByteArray message; - QDataStream ds(&message, QIODevice::WriteOnly); - ds << QByteArray("WATCH_OBJECT") << queryId << object.debugId(); - d->client->sendMessage(message); - } else { - watch->m_state = QQmlDebugWatch::Dead; - } - - return watch; -} - -QQmlDebugWatch *QQmlEngineDebug::addWatch(const QQmlDebugFileReference &, QObject *) -{ - qWarning("QQmlEngineDebug::addWatch(): Not implemented"); - return 0; -} - -void QQmlEngineDebug::removeWatch(QQmlDebugWatch *watch) -{ - Q_D(QQmlEngineDebug); - - if (!watch || !watch->m_client) - return; - - watch->m_client = 0; - watch->setState(QQmlDebugWatch::Inactive); - - d->watched.remove(watch->queryId()); - - if (d->client && d->client->state() == QQmlDebugClient::Enabled) { - QByteArray message; - QDataStream ds(&message, QIODevice::WriteOnly); - ds << QByteArray("NO_WATCH") << watch->queryId(); - d->client->sendMessage(message); - } -} - -QQmlDebugEnginesQuery *QQmlEngineDebug::queryAvailableEngines(QObject *parent) -{ - Q_D(QQmlEngineDebug); - - QQmlDebugEnginesQuery *query = new QQmlDebugEnginesQuery(parent); - if (d->client->state() == QQmlDebugClient::Enabled) { - query->m_client = this; - int queryId = d->getId(); - query->m_queryId = queryId; - d->enginesQuery.insert(queryId, query); - - QByteArray message; - QDataStream ds(&message, QIODevice::WriteOnly); - ds << QByteArray("LIST_ENGINES") << queryId; - d->client->sendMessage(message); - } else { - query->m_state = QQmlDebugQuery::Error; - } - - return query; -} - -QQmlDebugRootContextQuery *QQmlEngineDebug::queryRootContexts(const QQmlDebugEngineReference &engine, QObject *parent) -{ - Q_D(QQmlEngineDebug); - - QQmlDebugRootContextQuery *query = new QQmlDebugRootContextQuery(parent); - if (d->client->state() == QQmlDebugClient::Enabled && engine.debugId() != -1) { - query->m_client = this; - int queryId = d->getId(); - query->m_queryId = queryId; - d->rootContextQuery.insert(queryId, query); - - QByteArray message; - QDataStream ds(&message, QIODevice::WriteOnly); - ds << QByteArray("LIST_OBJECTS") << queryId << engine.debugId(); - d->client->sendMessage(message); - } else { - query->m_state = QQmlDebugQuery::Error; - } - - return query; -} - -QQmlDebugObjectQuery *QQmlEngineDebug::queryObject(const QQmlDebugObjectReference &object, QObject *parent) -{ - Q_D(QQmlEngineDebug); - - QQmlDebugObjectQuery *query = new QQmlDebugObjectQuery(parent); - if (d->client->state() == QQmlDebugClient::Enabled && object.debugId() != -1) { - query->m_client = this; - int queryId = d->getId(); - query->m_queryId = queryId; - d->objectQuery.insert(queryId, query); - - QByteArray message; - QDataStream ds(&message, QIODevice::WriteOnly); - ds << QByteArray("FETCH_OBJECT") << queryId << object.debugId() - << false << true; - d->client->sendMessage(message); - } else { - query->m_state = QQmlDebugQuery::Error; - } - - return query; -} - -QQmlDebugObjectQuery *QQmlEngineDebug::queryObjectRecursive(const QQmlDebugObjectReference &object, QObject *parent) -{ - Q_D(QQmlEngineDebug); - - QQmlDebugObjectQuery *query = new QQmlDebugObjectQuery(parent); - if (d->client->state() == QQmlDebugClient::Enabled && object.debugId() != -1) { - query->m_client = this; - int queryId = d->getId(); - query->m_queryId = queryId; - d->objectQuery.insert(queryId, query); - - QByteArray message; - QDataStream ds(&message, QIODevice::WriteOnly); - ds << QByteArray("FETCH_OBJECT") << queryId << object.debugId() - << true << true; - d->client->sendMessage(message); - } else { - query->m_state = QQmlDebugQuery::Error; - } - - return query; -} - -QQmlDebugExpressionQuery *QQmlEngineDebug::queryExpressionResult(int objectDebugId, const QString &expr, QObject *parent) -{ - Q_D(QQmlEngineDebug); - - QQmlDebugExpressionQuery *query = new QQmlDebugExpressionQuery(parent); - if (d->client->state() == QQmlDebugClient::Enabled && objectDebugId != -1) { - query->m_client = this; - query->m_expr = expr; - int queryId = d->getId(); - query->m_queryId = queryId; - d->expressionQuery.insert(queryId, query); - - QByteArray message; - QDataStream ds(&message, QIODevice::WriteOnly); - ds << QByteArray("EVAL_EXPRESSION") << queryId << objectDebugId << expr; - d->client->sendMessage(message); - } else { - query->m_state = QQmlDebugQuery::Error; - } - - return query; -} - -bool QQmlEngineDebug::setBindingForObject(int objectDebugId, const QString &propertyName, - const QVariant &bindingExpression, - bool isLiteralValue, - QString source, int line) -{ - Q_D(QQmlEngineDebug); - - if (d->client->state() == QQmlDebugClient::Enabled && objectDebugId != -1) { - QByteArray message; - QDataStream ds(&message, QIODevice::WriteOnly); - ds << QByteArray("SET_BINDING") << objectDebugId << propertyName << bindingExpression << isLiteralValue << source << line; - d->client->sendMessage(message); - return true; - } else { - return false; - } -} - -bool QQmlEngineDebug::resetBindingForObject(int objectDebugId, const QString &propertyName) -{ - Q_D(QQmlEngineDebug); - - if (d->client->state() == QQmlDebugClient::Enabled && objectDebugId != -1) { - QByteArray message; - QDataStream ds(&message, QIODevice::WriteOnly); - ds << QByteArray("RESET_BINDING") << objectDebugId << propertyName; - d->client->sendMessage(message); - return true; - } else { - return false; - } -} - -bool QQmlEngineDebug::setMethodBody(int objectDebugId, const QString &methodName, - const QString &methodBody) -{ - Q_D(QQmlEngineDebug); - - if (d->client->state() == QQmlDebugClient::Enabled && objectDebugId != -1) { - QByteArray message; - QDataStream ds(&message, QIODevice::WriteOnly); - ds << QByteArray("SET_METHOD_BODY") << objectDebugId << methodName << methodBody; - d->client->sendMessage(message); - return true; - } else { - return false; - } -} - -QQmlDebugWatch::QQmlDebugWatch(QObject *parent) - : QObject(parent), m_state(Waiting), m_queryId(-1), m_client(0), m_objectDebugId(-1) -{ -} - -QQmlDebugWatch::~QQmlDebugWatch() -{ - if (m_client && m_queryId != -1) - QQmlEngineDebugPrivate::remove(m_client, this); -} - -int QQmlDebugWatch::queryId() const -{ - return m_queryId; -} - -int QQmlDebugWatch::objectDebugId() const -{ - return m_objectDebugId; -} - -QQmlDebugWatch::State QQmlDebugWatch::state() const -{ - return m_state; -} - -void QQmlDebugWatch::setState(State s) -{ - if (m_state == s) - return; - m_state = s; - emit stateChanged(m_state); -} - -QQmlDebugPropertyWatch::QQmlDebugPropertyWatch(QObject *parent) - : QQmlDebugWatch(parent) -{ -} - -QString QQmlDebugPropertyWatch::name() const -{ - return m_name; -} - - -QQmlDebugObjectExpressionWatch::QQmlDebugObjectExpressionWatch(QObject *parent) - : QQmlDebugWatch(parent) -{ -} - -QString QQmlDebugObjectExpressionWatch::expression() const -{ - return m_expr; -} - - -QQmlDebugQuery::QQmlDebugQuery(QObject *parent) - : QObject(parent), m_state(Waiting) -{ -} - -QQmlDebugQuery::State QQmlDebugQuery::state() const -{ - return m_state; -} - -bool QQmlDebugQuery::isWaiting() const -{ - return m_state == Waiting; -} - -void QQmlDebugQuery::setState(State s) -{ - if (m_state == s) - return; - m_state = s; - emit stateChanged(m_state); -} - -QQmlDebugEnginesQuery::QQmlDebugEnginesQuery(QObject *parent) - : QQmlDebugQuery(parent), m_client(0), m_queryId(-1) -{ -} - -QQmlDebugEnginesQuery::~QQmlDebugEnginesQuery() -{ - if (m_client && m_queryId != -1) - QQmlEngineDebugPrivate::remove(m_client, this); -} - -QList<QQmlDebugEngineReference> QQmlDebugEnginesQuery::engines() const -{ - return m_engines; -} - -QQmlDebugRootContextQuery::QQmlDebugRootContextQuery(QObject *parent) - : QQmlDebugQuery(parent), m_client(0), m_queryId(-1) -{ -} - -QQmlDebugRootContextQuery::~QQmlDebugRootContextQuery() -{ - if (m_client && m_queryId != -1) - QQmlEngineDebugPrivate::remove(m_client, this); -} - -QQmlDebugContextReference QQmlDebugRootContextQuery::rootContext() const -{ - return m_context; -} - -QQmlDebugObjectQuery::QQmlDebugObjectQuery(QObject *parent) - : QQmlDebugQuery(parent), m_client(0), m_queryId(-1) -{ -} - -QQmlDebugObjectQuery::~QQmlDebugObjectQuery() -{ - if (m_client && m_queryId != -1) - QQmlEngineDebugPrivate::remove(m_client, this); -} - -QQmlDebugObjectReference QQmlDebugObjectQuery::object() const -{ - return m_object; -} - -QQmlDebugExpressionQuery::QQmlDebugExpressionQuery(QObject *parent) - : QQmlDebugQuery(parent), m_client(0), m_queryId(-1) -{ -} - -QQmlDebugExpressionQuery::~QQmlDebugExpressionQuery() -{ - if (m_client && m_queryId != -1) - QQmlEngineDebugPrivate::remove(m_client, this); -} - -QVariant QQmlDebugExpressionQuery::expression() const -{ - return m_expr; -} - -QVariant QQmlDebugExpressionQuery::result() const -{ - return m_result; -} - -QQmlDebugEngineReference::QQmlDebugEngineReference() - : m_debugId(-1) -{ -} - -QQmlDebugEngineReference::QQmlDebugEngineReference(int debugId) - : m_debugId(debugId) -{ -} - -QQmlDebugEngineReference::QQmlDebugEngineReference(const QQmlDebugEngineReference &o) - : m_debugId(o.m_debugId), m_name(o.m_name) -{ -} - -QQmlDebugEngineReference & -QQmlDebugEngineReference::operator=(const QQmlDebugEngineReference &o) -{ - m_debugId = o.m_debugId; m_name = o.m_name; - return *this; -} - -int QQmlDebugEngineReference::debugId() const -{ - return m_debugId; -} - -QString QQmlDebugEngineReference::name() const -{ - return m_name; -} - -QQmlDebugObjectReference::QQmlDebugObjectReference() - : m_debugId(-1), m_contextDebugId(-1) -{ -} - -QQmlDebugObjectReference::QQmlDebugObjectReference(int debugId) - : m_debugId(debugId), m_contextDebugId(-1) -{ -} - -QQmlDebugObjectReference::QQmlDebugObjectReference(const QQmlDebugObjectReference &o) - : m_debugId(o.m_debugId), m_class(o.m_class), m_idString(o.m_idString), - m_name(o.m_name), m_source(o.m_source), m_contextDebugId(o.m_contextDebugId), - m_properties(o.m_properties), m_children(o.m_children) -{ -} - -QQmlDebugObjectReference & -QQmlDebugObjectReference::operator=(const QQmlDebugObjectReference &o) -{ - m_debugId = o.m_debugId; m_class = o.m_class; m_idString = o.m_idString; - m_name = o.m_name; m_source = o.m_source; m_contextDebugId = o.m_contextDebugId; - m_properties = o.m_properties; m_children = o.m_children; - return *this; -} - -int QQmlDebugObjectReference::debugId() const -{ - return m_debugId; -} - -QString QQmlDebugObjectReference::className() const -{ - return m_class; -} - -QString QQmlDebugObjectReference::idString() const -{ - return m_idString; -} - -QString QQmlDebugObjectReference::name() const -{ - return m_name; -} - -QQmlDebugFileReference QQmlDebugObjectReference::source() const -{ - return m_source; -} - -int QQmlDebugObjectReference::contextDebugId() const -{ - return m_contextDebugId; -} - -QList<QQmlDebugPropertyReference> QQmlDebugObjectReference::properties() const -{ - return m_properties; -} - -QList<QQmlDebugObjectReference> QQmlDebugObjectReference::children() const -{ - return m_children; -} - -QQmlDebugContextReference::QQmlDebugContextReference() - : m_debugId(-1) -{ -} - -QQmlDebugContextReference::QQmlDebugContextReference(const QQmlDebugContextReference &o) - : m_debugId(o.m_debugId), m_name(o.m_name), m_objects(o.m_objects), m_contexts(o.m_contexts) -{ -} - -QQmlDebugContextReference &QQmlDebugContextReference::operator=(const QQmlDebugContextReference &o) -{ - m_debugId = o.m_debugId; m_name = o.m_name; m_objects = o.m_objects; - m_contexts = o.m_contexts; - return *this; -} - -int QQmlDebugContextReference::debugId() const -{ - return m_debugId; -} - -QString QQmlDebugContextReference::name() const -{ - return m_name; -} - -QList<QQmlDebugObjectReference> QQmlDebugContextReference::objects() const -{ - return m_objects; -} - -QList<QQmlDebugContextReference> QQmlDebugContextReference::contexts() const -{ - return m_contexts; -} - -QQmlDebugFileReference::QQmlDebugFileReference() - : m_lineNumber(-1), m_columnNumber(-1) -{ -} - -QQmlDebugFileReference::QQmlDebugFileReference(const QQmlDebugFileReference &o) - : m_url(o.m_url), m_lineNumber(o.m_lineNumber), m_columnNumber(o.m_columnNumber) -{ -} - -QQmlDebugFileReference &QQmlDebugFileReference::operator=(const QQmlDebugFileReference &o) -{ - m_url = o.m_url; m_lineNumber = o.m_lineNumber; m_columnNumber = o.m_columnNumber; - return *this; -} - -QUrl QQmlDebugFileReference::url() const -{ - return m_url; -} - -void QQmlDebugFileReference::setUrl(const QUrl &u) -{ - m_url = u; -} - -int QQmlDebugFileReference::lineNumber() const -{ - return m_lineNumber; -} - -void QQmlDebugFileReference::setLineNumber(int l) -{ - m_lineNumber = l; -} - -int QQmlDebugFileReference::columnNumber() const -{ - return m_columnNumber; -} - -void QQmlDebugFileReference::setColumnNumber(int c) -{ - m_columnNumber = c; -} - -QQmlDebugPropertyReference::QQmlDebugPropertyReference() - : m_objectDebugId(-1), m_hasNotifySignal(false) -{ -} - -QQmlDebugPropertyReference::QQmlDebugPropertyReference(const QQmlDebugPropertyReference &o) - : m_objectDebugId(o.m_objectDebugId), m_name(o.m_name), m_value(o.m_value), - m_valueTypeName(o.m_valueTypeName), m_binding(o.m_binding), - m_hasNotifySignal(o.m_hasNotifySignal) -{ -} - -QQmlDebugPropertyReference &QQmlDebugPropertyReference::operator=(const QQmlDebugPropertyReference &o) -{ - m_objectDebugId = o.m_objectDebugId; m_name = o.m_name; m_value = o.m_value; - m_valueTypeName = o.m_valueTypeName; m_binding = o.m_binding; - m_hasNotifySignal = o.m_hasNotifySignal; - return *this; -} - -int QQmlDebugPropertyReference::objectDebugId() const -{ - return m_objectDebugId; -} - -QString QQmlDebugPropertyReference::name() const -{ - return m_name; -} - -QString QQmlDebugPropertyReference::valueTypeName() const -{ - return m_valueTypeName; -} - -QVariant QQmlDebugPropertyReference::value() const -{ - return m_value; -} - -QString QQmlDebugPropertyReference::binding() const -{ - return m_binding; -} - -bool QQmlDebugPropertyReference::hasNotifySignal() const -{ - return m_hasNotifySignal; -} - diff --git a/tests/auto/qml/debugger/shared/qqmlenginedebug_p.h b/tests/auto/qml/debugger/shared/qqmlenginedebug_p.h deleted file mode 100644 index 2ebdebca53..0000000000 --- a/tests/auto/qml/debugger/shared/qqmlenginedebug_p.h +++ /dev/null @@ -1,388 +0,0 @@ -/**************************************************************************** -** -** Copyright (C) 2012 Nokia Corporation and/or its subsidiary(-ies). -** Contact: http://www.qt-project.org/ -** -** This file is part of the QtQml module of the Qt Toolkit. -** -** $QT_BEGIN_LICENSE:LGPL$ -** GNU Lesser General Public License Usage -** 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, Nokia gives you certain additional -** rights. These rights are described in the Nokia 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. -** -** Other Usage -** Alternatively, this file may be used in accordance with the terms and -** conditions contained in a signed written agreement between you and Nokia. -** -** -** -** -** -** -** $QT_END_LICENSE$ -** -****************************************************************************/ - -#ifndef QQMLENGINEDEBUG_H -#define QQMLENGINEDEBUG_H - -// -// W A R N I N G -// ------------- -// -// This file is not part of the Qt API. It exists purely as an -// implementation detail. This header file may change from version to -// version without notice, or even be removed. -// -// We mean it. -// - -#include <QtCore/qobject.h> -#include <QtCore/qurl.h> -#include <QtCore/qvariant.h> - -#include <private/qtqmlglobal_p.h> - -class QQmlDebugConnection; -class QQmlDebugWatch; -class QQmlDebugPropertyWatch; -class QQmlDebugObjectExpressionWatch; -class QQmlDebugEnginesQuery; -class QQmlDebugRootContextQuery; -class QQmlDebugObjectQuery; -class QQmlDebugExpressionQuery; -class QQmlDebugPropertyReference; -class QQmlDebugContextReference; -class QQmlDebugObjectReference; -class QQmlDebugFileReference; -class QQmlDebugEngineReference; -class QQmlEngineDebugPrivate; -class QQmlEngineDebug : public QObject -{ - Q_OBJECT -public: - enum State { NotConnected, Unavailable, Enabled }; - - explicit QQmlEngineDebug(QQmlDebugConnection *, QObject * = 0); - ~QQmlEngineDebug(); - - State state() const; - - QQmlDebugPropertyWatch *addWatch(const QQmlDebugPropertyReference &, - QObject *parent = 0); - QQmlDebugWatch *addWatch(const QQmlDebugContextReference &, const QString &, - QObject *parent = 0); - QQmlDebugObjectExpressionWatch *addWatch(const QQmlDebugObjectReference &, const QString &, - QObject *parent = 0); - QQmlDebugWatch *addWatch(const QQmlDebugObjectReference &, - QObject *parent = 0); - QQmlDebugWatch *addWatch(const QQmlDebugFileReference &, - QObject *parent = 0); - - void removeWatch(QQmlDebugWatch *watch); - - QQmlDebugEnginesQuery *queryAvailableEngines(QObject *parent = 0); - QQmlDebugRootContextQuery *queryRootContexts(const QQmlDebugEngineReference &, - QObject *parent = 0); - QQmlDebugObjectQuery *queryObject(const QQmlDebugObjectReference &, - QObject *parent = 0); - QQmlDebugObjectQuery *queryObjectRecursive(const QQmlDebugObjectReference &, - QObject *parent = 0); - QQmlDebugExpressionQuery *queryExpressionResult(int objectDebugId, - const QString &expr, - QObject *parent = 0); - bool setBindingForObject(int objectDebugId, const QString &propertyName, - const QVariant &bindingExpression, bool isLiteralValue, - QString source = QString(), int line = -1); - bool resetBindingForObject(int objectDebugId, const QString &propertyName); - bool setMethodBody(int objectDebugId, const QString &methodName, const QString &methodBody); - -Q_SIGNALS: - void newObjects(); - void stateChanged(State state); - -private: - Q_DECLARE_PRIVATE(QQmlEngineDebug) -}; - -class QQmlDebugWatch : public QObject -{ - Q_OBJECT -public: - enum State { Waiting, Active, Inactive, Dead }; - - QQmlDebugWatch(QObject *); - ~QQmlDebugWatch(); - - int queryId() const; - int objectDebugId() const; - State state() const; - -Q_SIGNALS: - void stateChanged(QQmlDebugWatch::State); - //void objectChanged(int, const QQmlDebugObjectReference &); - //void valueChanged(int, const QVariant &); - - // Server sends value as string if it is a user-type variant - void valueChanged(const QByteArray &name, const QVariant &value); - -private: - friend class QQmlEngineDebug; - friend class QQmlEngineDebugPrivate; - void setState(State); - State m_state; - int m_queryId; - QQmlEngineDebug *m_client; - int m_objectDebugId; -}; - -class QQmlDebugPropertyWatch : public QQmlDebugWatch -{ - Q_OBJECT -public: - QQmlDebugPropertyWatch(QObject *parent); - - QString name() const; - -private: - friend class QQmlEngineDebug; - QString m_name; -}; - -class QQmlDebugObjectExpressionWatch : public QQmlDebugWatch -{ - Q_OBJECT -public: - QQmlDebugObjectExpressionWatch(QObject *parent); - - QString expression() const; - -private: - friend class QQmlEngineDebug; - QString m_expr; - int m_debugId; -}; - - -class QQmlDebugQuery : public QObject -{ - Q_OBJECT -public: - enum State { Waiting, Error, Completed }; - - State state() const; - bool isWaiting() const; - -Q_SIGNALS: - void stateChanged(QQmlDebugQuery::State); - -protected: - QQmlDebugQuery(QObject *); - -private: - friend class QQmlEngineDebug; - friend class QQmlEngineDebugPrivate; - void setState(State); - State m_state; -}; - -class QQmlDebugFileReference -{ -public: - QQmlDebugFileReference(); - QQmlDebugFileReference(const QQmlDebugFileReference &); - QQmlDebugFileReference &operator=(const QQmlDebugFileReference &); - - QUrl url() const; - void setUrl(const QUrl &); - int lineNumber() const; - void setLineNumber(int); - int columnNumber() const; - void setColumnNumber(int); - -private: - friend class QQmlEngineDebugPrivate; - QUrl m_url; - int m_lineNumber; - int m_columnNumber; -}; - -class QQmlDebugEngineReference -{ -public: - QQmlDebugEngineReference(); - QQmlDebugEngineReference(int); - QQmlDebugEngineReference(const QQmlDebugEngineReference &); - QQmlDebugEngineReference &operator=(const QQmlDebugEngineReference &); - - int debugId() const; - QString name() const; - -private: - friend class QQmlEngineDebugPrivate; - int m_debugId; - QString m_name; -}; - -class QQmlDebugObjectReference -{ -public: - QQmlDebugObjectReference(); - QQmlDebugObjectReference(int); - QQmlDebugObjectReference(const QQmlDebugObjectReference &); - QQmlDebugObjectReference &operator=(const QQmlDebugObjectReference &); - - int debugId() const; - QString className() const; - QString idString() const; - QString name() const; - - QQmlDebugFileReference source() const; - int contextDebugId() const; - - QList<QQmlDebugPropertyReference> properties() const; - QList<QQmlDebugObjectReference> children() const; - -private: - friend class QQmlEngineDebugPrivate; - int m_debugId; - QString m_class; - QString m_idString; - QString m_name; - QQmlDebugFileReference m_source; - int m_contextDebugId; - QList<QQmlDebugPropertyReference> m_properties; - QList<QQmlDebugObjectReference> m_children; -}; - -class QQmlDebugContextReference -{ -public: - QQmlDebugContextReference(); - QQmlDebugContextReference(const QQmlDebugContextReference &); - QQmlDebugContextReference &operator=(const QQmlDebugContextReference &); - - int debugId() const; - QString name() const; - - QList<QQmlDebugObjectReference> objects() const; - QList<QQmlDebugContextReference> contexts() const; - -private: - friend class QQmlEngineDebugPrivate; - int m_debugId; - QString m_name; - QList<QQmlDebugObjectReference> m_objects; - QList<QQmlDebugContextReference> m_contexts; -}; - -class QQmlDebugPropertyReference -{ -public: - QQmlDebugPropertyReference(); - QQmlDebugPropertyReference(const QQmlDebugPropertyReference &); - QQmlDebugPropertyReference &operator=(const QQmlDebugPropertyReference &); - - int objectDebugId() const; - QString name() const; - QVariant value() const; - QString valueTypeName() const; - QString binding() const; - bool hasNotifySignal() const; - -private: - friend class QQmlEngineDebugPrivate; - int m_objectDebugId; - QString m_name; - QVariant m_value; - QString m_valueTypeName; - QString m_binding; - bool m_hasNotifySignal; -}; - - -class QQmlDebugEnginesQuery : public QQmlDebugQuery -{ - Q_OBJECT -public: - virtual ~QQmlDebugEnginesQuery(); - QList<QQmlDebugEngineReference> engines() const; -private: - friend class QQmlEngineDebug; - friend class QQmlEngineDebugPrivate; - QQmlDebugEnginesQuery(QObject *); - QQmlEngineDebug *m_client; - int m_queryId; - QList<QQmlDebugEngineReference> m_engines; -}; - -class QQmlDebugRootContextQuery : public QQmlDebugQuery -{ - Q_OBJECT -public: - virtual ~QQmlDebugRootContextQuery(); - QQmlDebugContextReference rootContext() const; -private: - friend class QQmlEngineDebug; - friend class QQmlEngineDebugPrivate; - QQmlDebugRootContextQuery(QObject *); - QQmlEngineDebug *m_client; - int m_queryId; - QQmlDebugContextReference m_context; -}; - -class QQmlDebugObjectQuery : public QQmlDebugQuery -{ - Q_OBJECT -public: - virtual ~QQmlDebugObjectQuery(); - QQmlDebugObjectReference object() const; -private: - friend class QQmlEngineDebug; - friend class QQmlEngineDebugPrivate; - QQmlDebugObjectQuery(QObject *); - QQmlEngineDebug *m_client; - int m_queryId; - QQmlDebugObjectReference m_object; - -}; - -class QQmlDebugExpressionQuery : public QQmlDebugQuery -{ - Q_OBJECT -public: - virtual ~QQmlDebugExpressionQuery(); - QVariant expression() const; - QVariant result() const; -private: - friend class QQmlEngineDebug; - friend class QQmlEngineDebugPrivate; - QQmlDebugExpressionQuery(QObject *); - QQmlEngineDebug *m_client; - int m_queryId; - QVariant m_expr; - QVariant m_result; -}; - -Q_DECLARE_METATYPE(QQmlDebugEngineReference) -Q_DECLARE_METATYPE(QQmlDebugObjectReference) -Q_DECLARE_METATYPE(QQmlDebugContextReference) -Q_DECLARE_METATYPE(QQmlDebugPropertyReference) - -#endif // QQMLENGINEDEBUG_H diff --git a/tests/auto/qml/qjsengine/tst_qjsengine.cpp b/tests/auto/qml/qjsengine/tst_qjsengine.cpp index 6f9cc93757..e34304b258 100644 --- a/tests/auto/qml/qjsengine/tst_qjsengine.cpp +++ b/tests/auto/qml/qjsengine/tst_qjsengine.cpp @@ -2369,6 +2369,8 @@ void tst_QJSEngine::valueConversion_basic() QCOMPARE(eng.fromScriptValue<QChar>(code), c); QCOMPARE(eng.fromScriptValue<QChar>(eng.toScriptValue(c)), c); } + + QVERIFY(eng.toScriptValue(static_cast<void *>(0)).isNull()); } #if 0 // FIXME: No API for custom types @@ -2588,6 +2590,8 @@ void tst_QJSEngine::valueConversion_QVariant() } QCOMPARE(qjsvalue_cast<QVariant>(QJSValue(123)), QVariant(123)); + + QVERIFY(eng.toScriptValue(QVariant(QMetaType::VoidStar, 0)).isNull()); } #if 0 // FIXME: No support for custom types diff --git a/tests/auto/qml/qjsvalue/tst_qjsvalue.cpp b/tests/auto/qml/qjsvalue/tst_qjsvalue.cpp index ad655217ad..3522f22ca2 100644 --- a/tests/auto/qml/qjsvalue/tst_qjsvalue.cpp +++ b/tests/auto/qml/qjsvalue/tst_qjsvalue.cpp @@ -993,8 +993,8 @@ void tst_QJSValue::toVariant() QCOMPARE(qjsvalue_cast<QVariant>(undefined), QVariant()); QJSValue null = eng.evaluate("null"); - QCOMPARE(null.toVariant(), QVariant()); - QCOMPARE(qjsvalue_cast<QVariant>(null), QVariant()); + QCOMPARE(null.toVariant(), QVariant(QMetaType::VoidStar, 0)); + QCOMPARE(qjsvalue_cast<QVariant>(null), QVariant(QMetaType::VoidStar, 0)); { QJSValue number = eng.toScriptValue(123.0); @@ -1064,6 +1064,14 @@ void tst_QJSValue::toVariant() QJSValue str = QJSValue(QString("ciao")); QCOMPARE(str.toVariant(), QVariant(QString("ciao"))); QCOMPARE(qjsvalue_cast<QVariant>(str), QVariant(QString("ciao"))); + + QJSValue undef = QJSValue(QJSValue::UndefinedValue); + QCOMPARE(undef.toVariant(), QVariant()); + QCOMPARE(qjsvalue_cast<QVariant>(undef), QVariant()); + + QJSValue nil = QJSValue(QJSValue::NullValue); + QCOMPARE(nil.toVariant(), QVariant(QMetaType::VoidStar, 0)); + QCOMPARE(qjsvalue_cast<QVariant>(nil), QVariant(QMetaType::VoidStar, 0)); } #if 0 // FIXME: No automatic sequence conversion diff --git a/tests/auto/qml/qqmlecmascript/data/assignDate.2.qml b/tests/auto/qml/qqmlecmascript/data/assignDate.2.qml new file mode 100644 index 0000000000..578701844c --- /dev/null +++ b/tests/auto/qml/qqmlecmascript/data/assignDate.2.qml @@ -0,0 +1,6 @@ +import Qt.test 1.0 + +MyTypeObject { + dateProperty: if(1) new Date("1982-11-25") + dateTimeProperty: if(1) new Date("2009-05-12T13:22:01") +} diff --git a/tests/auto/qml/qqmlecmascript/data/assignDate.3.qml b/tests/auto/qml/qqmlecmascript/data/assignDate.3.qml new file mode 100644 index 0000000000..32b88d0183 --- /dev/null +++ b/tests/auto/qml/qqmlecmascript/data/assignDate.3.qml @@ -0,0 +1,6 @@ +import Qt.test 1.0 + +MyTypeObject { + dateProperty: if(1) "1982-11-25Z" + dateTimeProperty: if(1) "2009-05-12T13:22:01Z" +} diff --git a/tests/auto/qml/qqmlecmascript/data/assignDate.4.qml b/tests/auto/qml/qqmlecmascript/data/assignDate.4.qml new file mode 100644 index 0000000000..16213c691f --- /dev/null +++ b/tests/auto/qml/qqmlecmascript/data/assignDate.4.qml @@ -0,0 +1,6 @@ +import Qt.test 1.0 + +MyTypeObject { + dateProperty: if(1) new Date("1982-11-25Z") + dateTimeProperty: if(1) new Date("2009-05-12T13:22:01Z") +} diff --git a/tests/auto/qml/qqmlecmascript/data/assignDate.5.qml b/tests/auto/qml/qqmlecmascript/data/assignDate.5.qml new file mode 100644 index 0000000000..ff1d85fbef --- /dev/null +++ b/tests/auto/qml/qqmlecmascript/data/assignDate.5.qml @@ -0,0 +1,6 @@ +import Qt.test 1.0 + +MyTypeObject { + dateProperty: if(1) "1982-11-25Z" + dateTimeProperty: if(1) "2009-05-12T15:22:01+02:00" +} diff --git a/tests/auto/qml/qqmlecmascript/data/assignDate.6.qml b/tests/auto/qml/qqmlecmascript/data/assignDate.6.qml new file mode 100644 index 0000000000..859c02f79c --- /dev/null +++ b/tests/auto/qml/qqmlecmascript/data/assignDate.6.qml @@ -0,0 +1,6 @@ +import Qt.test 1.0 + +MyTypeObject { + dateProperty: if(1) new Date("1982-11-25") + dateTimeProperty: if(1) new Date("2009-05-12T15:22:01+02:00") +} diff --git a/tests/auto/qml/qqmlecmascript/data/assignDate.qml b/tests/auto/qml/qqmlecmascript/data/assignDate.qml new file mode 100644 index 0000000000..07a638d50f --- /dev/null +++ b/tests/auto/qml/qqmlecmascript/data/assignDate.qml @@ -0,0 +1,9 @@ +import Qt.test 1.0 +import QtQuick 2.0 + +MyTypeObject { + Component.onCompleted: { + dateProperty = new Date("1982-11-25") + dateTimeProperty = new Date("2009-05-12T13:22:01") + } +} diff --git a/tests/auto/qml/qqmlecmascript/data/componentCreation.qml b/tests/auto/qml/qqmlecmascript/data/componentCreation.qml new file mode 100644 index 0000000000..d21301ea13 --- /dev/null +++ b/tests/auto/qml/qqmlecmascript/data/componentCreation.qml @@ -0,0 +1,52 @@ +import Qt.test 1.0 +import QtQuick 2.0 + +MyTypeObject{ + id: obj + objectName: "obj" + + function url() + { + obj.componentProperty = Qt.createComponent('dynamicCreation.helper.qml'); + } + + function urlMode() + { + obj.componentProperty = Qt.createComponent('dynamicCreation.helper.qml', Component.PreferSynchronous); + } + + function urlParent() + { + obj.componentProperty = Qt.createComponent('dynamicCreation.helper.qml', obj); + } + + function urlNullParent() + { + obj.componentProperty = Qt.createComponent('dynamicCreation.helper.qml', null); + } + + function urlModeParent() + { + obj.componentProperty = Qt.createComponent('dynamicCreation.helper.qml', Component.PreferSynchronous, obj); + } + + function urlModeNullParent() + { + obj.componentProperty = Qt.createComponent('dynamicCreation.helper.qml', Component.PreferSynchronous, null); + } + + function invalidSecondArg() + { + obj.componentProperty = Qt.createComponent('dynamicCreation.helper.qml', 'Bad argument'); + } + + function invalidThirdArg() + { + obj.componentProperty = Qt.createComponent('dynamicCreation.helper.qml', Component.PreferSynchronous, 'Bad argument'); + } + + function invalidMode() + { + obj.componentProperty = Qt.createComponent('dynamicCreation.helper.qml', -666); + } +} diff --git a/tests/auto/qml/qqmlecmascript/data/enums.3.qml b/tests/auto/qml/qqmlecmascript/data/enums.3.qml new file mode 100644 index 0000000000..c77d635a1e --- /dev/null +++ b/tests/auto/qml/qqmlecmascript/data/enums.3.qml @@ -0,0 +1,41 @@ +import QtQuick 2.0 +import Qt.test 1.0 +import Qt.test 1.0 as Namespace + +Item { + // Enums from type + property int a: Item.Center + property int b: Item.Right + + // Enums from Qt + property int c: Qt.blue + property int d: Qt.darkRed + + // Enums from other type + property int e: MyQmlObject.EnumValue3 + property int f: MyQmlObject.EnumValue4 + + // Enums from namespaced other type + property int h: Namespace.MyQmlObject.EnumValue3 + property int i: Namespace.MyQmlObject.EnumValue4 + + // Count the onChanged signals to see whether + // they're assigned as literals or via bindings + property int ac: 0 + property int bc: 0 + property int cc: 0 + property int dc: 0 + property int ec: 0 + property int fc: 0 + property int hc: 0 + property int ic: 0 + + onAChanged: ac++ + onBChanged: bc++ + onCChanged: cc++ + onDChanged: dc++ + onEChanged: ec++ + onFChanged: fc++ + onHChanged: hc++ + onIChanged: ic++ +} diff --git a/tests/auto/qml/qqmlecmascript/data/jsimport/testJsImport.qml b/tests/auto/qml/qqmlecmascript/data/jsimport/testJsImport.qml new file mode 100644 index 0000000000..ae43e90210 --- /dev/null +++ b/tests/auto/qml/qqmlecmascript/data/jsimport/testJsImport.qml @@ -0,0 +1,13 @@ +import QtQuick 2.0 + +import com.nokia.JsModule 1.0 +import com.nokia.JsModule 1.0 as RenamedModule +import "testJsModuleImport.js" as TestJsModuleImport + +QtObject { + id: testQtObject + + property string importedScriptStringValue: ScriptAPI.greeting(); + property string renamedScriptStringValue: RenamedModule.ScriptAPI.greeting(); + property string reimportedScriptStringValue: TestJsModuleImport.importedValue(); +} diff --git a/tests/auto/qml/qqmlecmascript/data/jsimport/testJsModuleImport.js b/tests/auto/qml/qqmlecmascript/data/jsimport/testJsModuleImport.js new file mode 100644 index 0000000000..2d21953d2c --- /dev/null +++ b/tests/auto/qml/qqmlecmascript/data/jsimport/testJsModuleImport.js @@ -0,0 +1,5 @@ +.import com.nokia.JsModule 1.0 as JsModule + +function importedValue() { + return JsModule.ScriptAPI.greeting(); +} diff --git a/tests/auto/qml/qqmlecmascript/data/lib/com/nokia/JsModule/ScriptAPI.js b/tests/auto/qml/qqmlecmascript/data/lib/com/nokia/JsModule/ScriptAPI.js new file mode 100644 index 0000000000..b90033eeb4 --- /dev/null +++ b/tests/auto/qml/qqmlecmascript/data/lib/com/nokia/JsModule/ScriptAPI.js @@ -0,0 +1,5 @@ +var major = 1 +var minor = 0 + +function greeting() { return "Hello" } + diff --git a/tests/auto/qml/qqmlecmascript/data/lib/com/nokia/JsModule/qmldir b/tests/auto/qml/qqmlecmascript/data/lib/com/nokia/JsModule/qmldir new file mode 100644 index 0000000000..c33d1e7a0d --- /dev/null +++ b/tests/auto/qml/qqmlecmascript/data/lib/com/nokia/JsModule/qmldir @@ -0,0 +1 @@ +ScriptAPI 1.0 ScriptAPI.js diff --git a/tests/auto/qml/qqmlecmascript/data/ownershipConsistency.qml b/tests/auto/qml/qqmlecmascript/data/ownershipConsistency.qml new file mode 100644 index 0000000000..7ae099e32e --- /dev/null +++ b/tests/auto/qml/qqmlecmascript/data/ownershipConsistency.qml @@ -0,0 +1,21 @@ +import QtQuick 2.0 + +Item { + Loader { + source: "PropertyVarBaseItem.qml" + onLoaded: item.destroy() + } + Loader { + Component.onCompleted: setSource("PropertyVarBaseItem.qml", { random: "" }) + onLoaded: item.destroy() + } + + Repeater { + model: 1 + Item { Component.onCompleted: destroy() } + } + Repeater { + model: 1 + Item { id: me; Component.onCompleted: { setObject(me); getObject().destroy() } } + } +} diff --git a/tests/auto/qml/qqmlecmascript/data/ownershipRootObject.qml b/tests/auto/qml/qqmlecmascript/data/ownershipRootObject.qml new file mode 100644 index 0000000000..b1b0b72a87 --- /dev/null +++ b/tests/auto/qml/qqmlecmascript/data/ownershipRootObject.qml @@ -0,0 +1,6 @@ +import QtQuick 2.0 + +QtObject { + id: root + Component.onCompleted: { setObject(root); getObject() } +} diff --git a/tests/auto/qml/qqmlecmascript/testtypes.cpp b/tests/auto/qml/qqmlecmascript/testtypes.cpp index 64e91fbc95..a79207a1c8 100644 --- a/tests/auto/qml/qqmlecmascript/testtypes.cpp +++ b/tests/auto/qml/qqmlecmascript/testtypes.cpp @@ -196,7 +196,7 @@ void registerTypes() qmlRegisterModuleApi("Qt.test.qobjectApi",2,0,qobject_api); // register (qobject) module API for a uri which doesn't contain elements, major version set qmlRegisterModuleApi("Qt.test.qobjectApiParented",1,0,qobject_api_engine_parent); // register (parented qobject) module API for a uri which doesn't contain elements - qRegisterMetaType<MyQmlObject::MyType>("MyEnum2"); + qRegisterMetaType<MyQmlObject::MyEnum2>("MyEnum2"); qRegisterMetaType<Qt::MouseButtons>("Qt::MouseButtons"); qmlRegisterType<CircularReferenceObject>("Qt.test", 1, 0, "CircularReferenceObject"); diff --git a/tests/auto/qml/qqmlecmascript/tst_qqmlecmascript.cpp b/tests/auto/qml/qqmlecmascript/tst_qqmlecmascript.cpp index 861ff2e641..d932bc6d09 100644 --- a/tests/auto/qml/qqmlecmascript/tst_qqmlecmascript.cpp +++ b/tests/auto/qml/qqmlecmascript/tst_qqmlecmascript.cpp @@ -71,6 +71,8 @@ public: private slots: void initTestCase(); void assignBasicTypes(); + void assignDate_data(); + void assignDate(); void idShortcutInvalidates(); void boolPropertiesEvaluateAsBool(); void methods(); @@ -97,6 +99,8 @@ private slots: void importScope(); void signalParameterTypes(); void objectsCompareAsEqual(); + void componentCreation_data(); + void componentCreation(); void dynamicCreation_data(); void dynamicCreation(); void dynamicDestruction(); @@ -129,6 +133,8 @@ private slots: void ownership(); void cppOwnershipReturnValue(); void ownershipCustomReturnValue(); + void ownershipRootObject(); + void ownershipConsistency(); void qlistqobjectMethods(); void strictlyEquals(); void compiled(); @@ -255,6 +261,9 @@ void tst_qqmlecmascript::initTestCase() { QQmlDataTest::initTestCase(); registerTypes(); + + QString dataDir(dataDirectory() + QLatin1Char('/') + QLatin1String("lib")); + engine.addImportPath(dataDir); } void tst_qqmlecmascript::assignBasicTypes() @@ -274,7 +283,7 @@ void tst_qqmlecmascript::assignBasicTypes() QCOMPARE(object->colorProperty(), QColor("red")); QCOMPARE(object->dateProperty(), QDate(1982, 11, 25)); QCOMPARE(object->timeProperty(), QTime(11, 11, 32)); - QCOMPARE(object->dateTimeProperty(), QDateTime(QDate(2009, 5, 12), QTime(13, 22, 1))); + QCOMPARE(object->dateTimeProperty(), QDateTime(QDate(2009, 5, 12), QTime(13, 22, 1), Qt::UTC)); QCOMPARE(object->pointProperty(), QPoint(99,13)); QCOMPARE(object->pointFProperty(), QPointF(-10.1, 12.3)); QCOMPARE(object->sizeProperty(), QSize(99, 13)); @@ -302,7 +311,7 @@ void tst_qqmlecmascript::assignBasicTypes() QCOMPARE(object->colorProperty(), QColor("red")); QCOMPARE(object->dateProperty(), QDate(1982, 11, 25)); QCOMPARE(object->timeProperty(), QTime(11, 11, 32)); - QCOMPARE(object->dateTimeProperty(), QDateTime(QDate(2009, 5, 12), QTime(13, 22, 1))); + QCOMPARE(object->dateTimeProperty(), QDateTime(QDate(2009, 5, 12), QTime(13, 22, 1), Qt::UTC)); QCOMPARE(object->pointProperty(), QPoint(99,13)); QCOMPARE(object->pointFProperty(), QPointF(-10.1, 12.3)); QCOMPARE(object->sizeProperty(), QSize(99, 13)); @@ -317,6 +326,28 @@ void tst_qqmlecmascript::assignBasicTypes() } } +void tst_qqmlecmascript::assignDate_data() +{ + QTest::addColumn<QUrl>("source"); + QTest::newRow("Component.onComplete JS") << testFileUrl("assignDate.qml"); + QTest::newRow("Binding JS") << testFileUrl("assignDate.2.qml"); + QTest::newRow("Binding UTC") << testFileUrl("assignDate.3.qml"); + QTest::newRow("Binding JS UTC") << testFileUrl("assignDate.4.qml"); + QTest::newRow("Binding UTC+2") << testFileUrl("assignDate.5.qml"); + QTest::newRow("Binding JS UTC+2 ") << testFileUrl("assignDate.6.qml"); +} + +void tst_qqmlecmascript::assignDate() +{ + QFETCH(QUrl, source); + QQmlComponent component(&engine, source); + QScopedPointer<QObject> obj(component.create()); + MyTypeObject *object = qobject_cast<MyTypeObject *>(obj.data()); + QVERIFY(object != 0); + QCOMPARE(object->dateProperty(), QDate(1982, 11, 25)); + QCOMPARE(object->dateTimeProperty(), QDateTime(QDate(2009, 5, 12), QTime(13, 22, 1), Qt::UTC)); +} + void tst_qqmlecmascript::idShortcutInvalidates() { { @@ -820,6 +851,34 @@ void tst_qqmlecmascript::enums() delete object; } + // Enums as literals + { + QQmlComponent component(&engine, testFileUrl("enums.3.qml")); + QObject *object = component.create(); + QVERIFY(object != 0); + + // check the values are what we expect + QCOMPARE(object->property("a").toInt(), 4); + QCOMPARE(object->property("b").toInt(), 5); + QCOMPARE(object->property("c").toInt(), 9); + QCOMPARE(object->property("d").toInt(), 13); + QCOMPARE(object->property("e").toInt(), 2); + QCOMPARE(object->property("f").toInt(), 3); + QCOMPARE(object->property("h").toInt(), 2); + QCOMPARE(object->property("i").toInt(), 3); + + // count of change signals + QCOMPARE(object->property("ac").toInt(), 0); + QCOMPARE(object->property("bc").toInt(), 0); + QCOMPARE(object->property("cc").toInt(), 0); + QCOMPARE(object->property("dc").toInt(), 0); + QCOMPARE(object->property("ec").toInt(), 0); + QCOMPARE(object->property("fc").toInt(), 0); + QCOMPARE(object->property("hc").toInt(), 1); // namespace -> binding + QCOMPARE(object->property("ic").toInt(), 1); // namespace -> binding + + delete object; + } } void tst_qqmlecmascript::valueTypeFunctions() @@ -1199,6 +1258,89 @@ void tst_qqmlecmascript::aliasPropertyReset() delete object; } +void tst_qqmlecmascript::componentCreation_data() +{ + QTest::addColumn<QString>("method"); + QTest::addColumn<QString>("creationError"); + QTest::addColumn<QString>("createdParent"); + + QTest::newRow("url") + << "url" + << "" + << ""; + QTest::newRow("urlMode") + << "urlMode" + << "" + << ""; + QTest::newRow("urlParent") + << "urlParent" + << "" + << "obj"; + QTest::newRow("urlNullParent") + << "urlNullParent" + << "" + << "null"; + QTest::newRow("urlModeParent") + << "urlModeParent" + << "" + << "obj"; + QTest::newRow("urlModeNullParent") + << "urlModeNullParent" + << "" + << "null"; + QTest::newRow("invalidSecondArg") + << "invalidSecondArg" + << ":40: Error: Qt.createComponent(): Invalid arguments" + << ""; + QTest::newRow("invalidThirdArg") + << "invalidThirdArg" + << ":45: Error: Qt.createComponent(): Invalid parent object" + << ""; + QTest::newRow("invalidMode") + << "invalidMode" + << ":50: Error: Qt.createComponent(): Invalid arguments" + << ""; +} + +/* +Test using createComponent to dynamically generate a component. +*/ +void tst_qqmlecmascript::componentCreation() +{ + QFETCH(QString, method); + QFETCH(QString, creationError); + QFETCH(QString, createdParent); + + QUrl testUrl(testFileUrl("componentCreation.qml")); + + if (!creationError.isEmpty()) { + QString warning = testUrl.toString() + creationError; + QTest::ignoreMessage(QtWarningMsg, warning.toLatin1().constData()); + } + + QQmlComponent component(&engine, testUrl); + MyTypeObject *object = qobject_cast<MyTypeObject*>(component.create()); + QVERIFY(object != 0); + + QMetaObject::invokeMethod(object, method.toUtf8()); + QQmlComponent *created = object->componentProperty(); + + if (creationError.isEmpty()) { + QVERIFY(created); + + QObject *expectedParent; + if (createdParent.isEmpty()) { + // For now, the parent should be the engine; this will change for QTBUG-24841 + expectedParent = &engine; + } else if (createdParent == QLatin1String("obj")) { + expectedParent = object; + } else if (createdParent == QLatin1String("null")) { + expectedParent = 0; + } + QCOMPARE(created->parent(), expectedParent); + } +} + void tst_qqmlecmascript::dynamicCreation_data() { QTest::addColumn<QString>("method"); @@ -2800,6 +2942,72 @@ void tst_qqmlecmascript::ownershipCustomReturnValue() QVERIFY(source.value == 0); } +//the return value from getObject will be JS ownership, +//unless strong Cpp ownership has been set +class OwnershipChangingObject : public QObject +{ + Q_OBJECT +public: + OwnershipChangingObject(): object(0) { } + + QPointer<QObject> object; + +public slots: + QObject *getObject() { return object; } + void setObject(QObject *obj) { object = obj; } +}; + +void tst_qqmlecmascript::ownershipRootObject() +{ + OwnershipChangingObject own; + QQmlContext *context = new QQmlContext(engine.rootContext()); + context->setContextObject(&own); + + QQmlComponent component(&engine, testFileUrl("ownershipRootObject.qml")); + QQmlGuard<QObject> object = component.create(context); + QVERIFY(object); + + engine.collectGarbage(); + + QCoreApplication::sendPostedEvents(0, QEvent::DeferredDelete); + QCoreApplication::processEvents(); + + QVERIFY(own.object != 0); + + delete context; + delete object; +} + +void tst_qqmlecmascript::ownershipConsistency() +{ + OwnershipChangingObject own; + QQmlContext *context = new QQmlContext(engine.rootContext()); + context->setContextObject(&own); + + QString expectedWarning = testFileUrl("ownershipConsistency.qml").toString() + QLatin1String(":19: Error: Invalid attempt to destroy() an indestructible object"); + QTest::ignoreMessage(QtWarningMsg, qPrintable(expectedWarning)); // we expect a meaningful warning to be printed. + expectedWarning = testFileUrl("ownershipConsistency.qml").toString() + QLatin1String(":15: Error: Invalid attempt to destroy() an indestructible object"); + QTest::ignoreMessage(QtWarningMsg, qPrintable(expectedWarning)); // we expect a meaningful warning to be printed. + expectedWarning = testFileUrl("ownershipConsistency.qml").toString() + QLatin1String(":6: Error: Invalid attempt to destroy() an indestructible object"); + QTest::ignoreMessage(QtWarningMsg, qPrintable(expectedWarning)); // we expect a meaningful warning to be printed. + expectedWarning = testFileUrl("ownershipConsistency.qml").toString() + QLatin1String(":10: Error: Invalid attempt to destroy() an indestructible object"); + QTest::ignoreMessage(QtWarningMsg, qPrintable(expectedWarning)); // we expect a meaningful warning to be printed. + + QQmlComponent component(&engine, testFileUrl("ownershipConsistency.qml")); + QQmlGuard<QObject> object = component.create(context); + QVERIFY(object); + + engine.collectGarbage(); + + QCoreApplication::sendPostedEvents(0, QEvent::DeferredDelete); + QCoreApplication::processEvents(); + + QVERIFY(own.object != 0); + + delete context; + delete object; +} + class QListQObjectMethodsObject : public QObject { Q_OBJECT @@ -3299,6 +3507,17 @@ void tst_qqmlecmascript::importScripts_data() << QStringList() << (QStringList() << QLatin1String("testValue")) << (QVariantList() << QVariant(20)); + + QTest::newRow("import module which exports a script") + << testFileUrl("jsimport/testJsImport.qml") + << QString() + << QStringList() + << (QStringList() << QLatin1String("importedScriptStringValue") + << QLatin1String("renamedScriptStringValue") + << QLatin1String("reimportedScriptStringValue")) + << (QVariantList() << QVariant(QString("Hello")) + << QVariant(QString("Hello")) + << QVariant(QString("Hello"))); } void tst_qqmlecmascript::importScripts() diff --git a/tests/auto/qml/qqmlerror/.gitattributes b/tests/auto/qml/qqmlerror/.gitattributes new file mode 100644 index 0000000000..f50af65222 --- /dev/null +++ b/tests/auto/qml/qqmlerror/.gitattributes @@ -0,0 +1 @@ +data/test.txt eol=lf diff --git a/tests/auto/qml/qqmllanguage/data/globalEnums.qml b/tests/auto/qml/qqmllanguage/data/globalEnums.qml new file mode 100644 index 0000000000..fa248d544d --- /dev/null +++ b/tests/auto/qml/qqmllanguage/data/globalEnums.qml @@ -0,0 +1,55 @@ +import QtQuick 2.0 +import Test 1.0 + +Item { + MyEnum1Class { + id: enum1Class + objectName: "enum1Class" + } + + MyEnumDerivedClass { + id: enumDerivedClass + objectName: "enumDerivedClass" + + onValueAChanged: { + aValue = newValue; + } + + onValueBChanged: { + bValue = newValue; + } + + onValueCChanged: { + cValue = newValue; + } + + onValueDChanged: { + dValue = newValue; + } + + onValueEChanged: { + eValue = newValue; + } + + onValueE2Changed: { + e2Value = newValue; + } + + property int aValue: 0 + property int bValue: 0 + property int cValue: 0 + property int dValue: 0 + property int eValue: 0 + property int e2Value: 0 + } + + function setEnumValues() { + enum1Class.setValue(MyEnum1Class.A_13); + enumDerivedClass.setValueA(MyEnum1Class.A_11); + enumDerivedClass.setValueB(MyEnum2Class.B_37); + enumDerivedClass.setValueC(Qt.RichText); + enumDerivedClass.setValueD(Qt.ElideMiddle); + enumDerivedClass.setValueE(MyEnum2Class.E_14); + enumDerivedClass.setValueE2(MyEnum2Class.E_76); + } +} diff --git a/tests/auto/qml/qqmllanguage/testtypes.cpp b/tests/auto/qml/qqmllanguage/testtypes.cpp index 3c7a7c2058..5e9423761c 100644 --- a/tests/auto/qml/qqmllanguage/testtypes.cpp +++ b/tests/auto/qml/qqmllanguage/testtypes.cpp @@ -77,6 +77,10 @@ void registerTypes() qmlRegisterType<MyVersion2Class>("Test.VersionOrder", 2,0, "MyQmlObject"); qmlRegisterType<MyQmlObject>("Test.VersionOrder", 1,0, "MyQmlObject"); + + qmlRegisterType<MyEnum1Class>("Test",1,0,"MyEnum1Class"); + qmlRegisterType<MyEnum2Class>("Test",1,0,"MyEnum2Class"); + qmlRegisterType<MyEnumDerivedClass>("Test",1,0,"MyEnumDerivedClass"); } QVariant myCustomVariantTypeConverter(const QString &data) @@ -85,4 +89,3 @@ QVariant myCustomVariantTypeConverter(const QString &data) rv.a = data.toInt(); return QVariant::fromValue(rv); } - diff --git a/tests/auto/qml/qqmllanguage/testtypes.h b/tests/auto/qml/qqmllanguage/testtypes.h index e7294f090c..7b3265efb4 100644 --- a/tests/auto/qml/qqmllanguage/testtypes.h +++ b/tests/auto/qml/qqmllanguage/testtypes.h @@ -811,14 +811,103 @@ class MyVersion2Class : public QObject Q_OBJECT }; +class MyEnum1Class : public QObject +{ + Q_OBJECT + Q_ENUMS(EnumA) + +public: + MyEnum1Class() : value(A_Invalid) {} + + enum EnumA + { + A_Invalid = -1, + + A_11 = 11, + A_13 = 13 + }; + + Q_INVOKABLE void setValue(EnumA v) { value = v; } + + EnumA getValue() { return value; } + +private: + EnumA value; +}; + +class MyEnum2Class : public QObject +{ + Q_OBJECT + Q_ENUMS(EnumB) + Q_ENUMS(EnumE) + +public: + MyEnum2Class() : valueA(MyEnum1Class::A_Invalid), valueB(B_Invalid), valueC(Qt::PlainText), + valueD(Qt::ElideLeft), valueE(E_Invalid), valueE2(E_Invalid) {} + + enum EnumB + { + B_Invalid = -1, + + B_29 = 29, + B_31 = 31, + B_37 = 37 + }; + + enum EnumE + { + E_Invalid = -1, + + E_14 = 14, + E_76 = 76 + }; + + MyEnum1Class::EnumA getValueA() { return valueA; } + EnumB getValueB() { return valueB; } + Qt::TextFormat getValueC() { return valueC; } + Qt::TextElideMode getValueD() { return valueD; } + EnumE getValueE() { return valueE; } + EnumE getValueE2() { return valueE2; } + + Q_INVOKABLE void setValueA(MyEnum1Class::EnumA v) { valueA = v; emit valueAChanged(v); } + Q_INVOKABLE void setValueB(EnumB v) { valueB = v; emit valueBChanged(v); } + Q_INVOKABLE void setValueC(Qt::TextFormat v) { valueC = v; emit valueCChanged(v); } //registered + Q_INVOKABLE void setValueD(Qt::TextElideMode v) { valueD = v; emit valueDChanged(v); } //unregistered + Q_INVOKABLE void setValueE(EnumE v) { valueE = v; emit valueEChanged(v); } + Q_INVOKABLE void setValueE2(MyEnum2Class::EnumE v) { valueE2 = v; emit valueE2Changed(v); } + +signals: + void valueAChanged(MyEnum1Class::EnumA newValue); + void valueBChanged(MyEnum2Class::EnumB newValue); + void valueCChanged(Qt::TextFormat newValue); + void valueDChanged(Qt::TextElideMode newValue); + void valueEChanged(EnumE newValue); + void valueE2Changed(MyEnum2Class::EnumE newValue); + +private: + MyEnum1Class::EnumA valueA; + EnumB valueB; + Qt::TextFormat valueC; + Qt::TextElideMode valueD; + EnumE valueE; + EnumE valueE2; +}; + +class MyEnumDerivedClass : public MyEnum2Class +{ + Q_OBJECT +}; + +Q_DECLARE_METATYPE(MyEnum2Class::EnumB) +Q_DECLARE_METATYPE(MyEnum1Class::EnumA) +Q_DECLARE_METATYPE(Qt::TextFormat) + QML_DECLARE_TYPE(MyRevisionedBaseClassRegistered) QML_DECLARE_TYPE(MyRevisionedBaseClassUnregistered) QML_DECLARE_TYPE(MyRevisionedClass) QML_DECLARE_TYPE(MyRevisionedSubclass) QML_DECLARE_TYPE(MySubclass) - - void registerTypes(); #endif // TESTTYPES_H diff --git a/tests/auto/qml/qqmllanguage/tst_qqmllanguage.cpp b/tests/auto/qml/qqmllanguage/tst_qqmllanguage.cpp index 266cd2a52d..837a9d2604 100644 --- a/tests/auto/qml/qqmllanguage/tst_qqmllanguage.cpp +++ b/tests/auto/qml/qqmllanguage/tst_qqmllanguage.cpp @@ -46,6 +46,7 @@ #include <QtCore/qdebug.h> #include <QtCore/qfileinfo.h> #include <QtCore/qdir.h> +#include <QSignalSpy> #include <private/qqmlproperty_p.h> #include <private/qqmlmetatype_p.h> @@ -176,6 +177,8 @@ private slots: void crash1(); void crash2(); + void globalEnums(); + private: QQmlEngine engine; void testType(const QString& qml, const QString& type, const QString& error); @@ -2285,6 +2288,64 @@ void tst_qqmllanguage::remoteLoadCrash() delete o; } +// QTBUG-20639 +void tst_qqmllanguage::globalEnums() +{ + qRegisterMetaType<MyEnum1Class::EnumA>(); + qRegisterMetaType<MyEnum2Class::EnumB>(); + qRegisterMetaType<Qt::TextFormat>(); + + QQmlComponent component(&engine, TEST_FILE("globalEnums.qml")); + + QObject *o = component.create(); + QVERIFY(o != 0); + + MyEnum1Class *enum1Class = o->findChild<MyEnum1Class *>(QString::fromLatin1("enum1Class")); + QVERIFY(enum1Class != 0); + QVERIFY(enum1Class->getValue() == -1); + + MyEnumDerivedClass *enum2Class = o->findChild<MyEnumDerivedClass *>(QString::fromLatin1("enumDerivedClass")); + QVERIFY(enum2Class != 0); + QVERIFY(enum2Class->getValueA() == -1); + QVERIFY(enum2Class->getValueB() == -1); + QVERIFY(enum2Class->getValueC() == 0); + QVERIFY(enum2Class->getValueD() == 0); + QVERIFY(enum2Class->getValueE() == -1); + QVERIFY(enum2Class->getValueE2() == -1); + + QVERIFY(enum2Class->property("aValue") == 0); + QVERIFY(enum2Class->property("bValue") == 0); + QVERIFY(enum2Class->property("cValue") == 0); + QVERIFY(enum2Class->property("dValue") == 0); + QVERIFY(enum2Class->property("eValue") == 0); + QVERIFY(enum2Class->property("e2Value") == 0); + + QSignalSpy signalA(enum2Class, SIGNAL(valueAChanged(MyEnum1Class::EnumA))); + QSignalSpy signalB(enum2Class, SIGNAL(valueBChanged(MyEnum2Class::EnumB))); + + QMetaObject::invokeMethod(o, "setEnumValues"); + + QVERIFY(enum1Class->getValue() == MyEnum1Class::A_13); + QVERIFY(enum2Class->getValueA() == MyEnum1Class::A_11); + QVERIFY(enum2Class->getValueB() == MyEnum2Class::B_37); + QVERIFY(enum2Class->getValueC() == Qt::RichText); + QVERIFY(enum2Class->getValueD() == Qt::ElideMiddle); + QVERIFY(enum2Class->getValueE() == MyEnum2Class::E_14); + QVERIFY(enum2Class->getValueE2() == MyEnum2Class::E_76); + + QVERIFY(signalA.count() == 1); + QVERIFY(signalB.count() == 1); + + QVERIFY(enum2Class->property("aValue") == MyEnum1Class::A_11); + QVERIFY(enum2Class->property("bValue") == 37); + QVERIFY(enum2Class->property("cValue") == 1); + QVERIFY(enum2Class->property("dValue") == 2); + QVERIFY(enum2Class->property("eValue") == 14); + QVERIFY(enum2Class->property("e2Value") == 76); + + delete o; +} + QTEST_MAIN(tst_qqmllanguage) #include "tst_qqmllanguage.moc" diff --git a/tests/auto/qml/qqmlxmlhttprequest/.gitattributes b/tests/auto/qml/qqmlxmlhttprequest/.gitattributes new file mode 100644 index 0000000000..7805eb6951 --- /dev/null +++ b/tests/auto/qml/qqmlxmlhttprequest/.gitattributes @@ -0,0 +1,3 @@ +data/testdocument.html eol=lf +data/redirecttarget.html eol=lf +data/utf16.html eol=lf diff --git a/tests/auto/qml/qquickfolderlistmodel/qquickfolderlistmodel.pro b/tests/auto/qml/qquickfolderlistmodel/qquickfolderlistmodel.pro index 68c0d79f92..2726e20577 100644 --- a/tests/auto/qml/qquickfolderlistmodel/qquickfolderlistmodel.pro +++ b/tests/auto/qml/qquickfolderlistmodel/qquickfolderlistmodel.pro @@ -10,5 +10,3 @@ TESTDATA = data/* CONFIG += parallel_test QT += core-private gui-private qml-private testlib - -win32:CONFIG += insignificant_test # QTBUG-24777 diff --git a/tests/auto/qml/qquickfolderlistmodel/tst_qquickfolderlistmodel.cpp b/tests/auto/qml/qquickfolderlistmodel/tst_qquickfolderlistmodel.cpp index 3761929362..804bd1a813 100644 --- a/tests/auto/qml/qquickfolderlistmodel/tst_qquickfolderlistmodel.cpp +++ b/tests/auto/qml/qquickfolderlistmodel/tst_qquickfolderlistmodel.cpp @@ -38,7 +38,7 @@ ** $QT_END_LICENSE$ ** ****************************************************************************/ -#include <qtest.h> +#include <QtTest/QtTest> #include <QtTest/QSignalSpy> #include <QtQml/qqmlengine.h> #include <QtQml/qqmlcomponent.h> diff --git a/tests/auto/qml/v4/data/objectToBool.qml b/tests/auto/qml/v4/data/objectToBool.qml new file mode 100644 index 0000000000..8c8a67bee0 --- /dev/null +++ b/tests/auto/qml/v4/data/objectToBool.qml @@ -0,0 +1,16 @@ +import QtQuick 2.0 + +QtObject { + property QtObject prop1: null + property QtObject prop2: QtObject {} + + property bool test1: prop1 ? true : false + property bool test2: prop2 ? true : false + + property bool test3: prop1 == false + property bool test4: prop1 === false + + property bool test5: prop2 == false + property bool test6: prop2 === false +} + diff --git a/tests/auto/qml/v4/tst_v4.cpp b/tests/auto/qml/v4/tst_v4.cpp index 1c89617157..8c811f230e 100644 --- a/tests/auto/qml/v4/tst_v4.cpp +++ b/tests/auto/qml/v4/tst_v4.cpp @@ -133,6 +133,7 @@ void tst_v4::qtscript_data() QTest::newRow("double bool jump") << "doubleBoolJump.qml"; QTest::newRow("unary minus") << "unaryMinus.qml"; QTest::newRow("null qobject") << "nullQObject.qml"; + QTest::newRow("qobject -> bool") << "objectToBool.qml"; } void tst_v4::unnecessaryReeval() diff --git a/tests/auto/qmltest/animatedimage/stickman.gif b/tests/auto/qmltest/animatedimage/stickman.gif Binary files differnew file mode 100644 index 0000000000..7c4cd18687 --- /dev/null +++ b/tests/auto/qmltest/animatedimage/stickman.gif diff --git a/tests/auto/qmltest/animatedimage/tst_animatedimage.qml b/tests/auto/qmltest/animatedimage/tst_animatedimage.qml new file mode 100644 index 0000000000..bc2bbea1cb --- /dev/null +++ b/tests/auto/qmltest/animatedimage/tst_animatedimage.qml @@ -0,0 +1,220 @@ +/**************************************************************************** +** +** Copyright (C) 2012 Nokia Corporation and/or its subsidiary(-ies). +** Contact: http://www.qt-project.org/ +** +** 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 Nokia Corporation and its Subsidiary(-ies) nor +** the names of its contributors may be used to endorse or promote +** products derived from this software without specific prior written +** permission. +** +** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE." +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +import QtQuick 2.0 +import QtTest 1.0 + +Item { + id: top + property string srcImage: "stickman.gif" + property bool canconnect + property bool checkfinished: false + + Component.onCompleted: { + var check = new XMLHttpRequest; + check.open("GET", "http://127.0.0.1:14445/stickman.gif"); + check.onreadystatechange = function() { + + console.log("Status: ", check.status) + console.log("Readystate", check.readyState) + if (check.readyState == XMLHttpRequest.DONE) { + if (check.status == 404) { + top.canconnect = false; + }else{ + top.canconnect = true; + } + top.checkfinished = true; + } + } + check.send(); + } + + AnimatedImage { + id: noSource + source: "" + } + + AnimatedImage { + id: clearSource + source: srcImage + } + + AnimatedImage { + id: resized + source: srcImage + width: 300 + height: 300 + } + + AnimatedImage { + id: smooth + source: srcImage + smooth: true + width: 300 + height: 300 + } + + AnimatedImage { + id: tileModes1 + source: srcImage + width: 100 + height: 300 + fillMode: AnimatedImage.Tile + } + + AnimatedImage { + id: tileModes2 + source: srcImage + width: 300 + height: 150 + fillMode: AnimatedImage.TileVertically + } + AnimatedImage { + id: tileModes3 + source: srcImage + width: 300 + height: 150 + fillMode: AnimatedImage.TileHorizontally + } + + TestCase { + name: "AnimatedImage" + + function test_noSource() { + compare(noSource.source, "") + compare(noSource.width, 0) + compare(noSource.height, 0) + compare(noSource.fillMode, AnimatedImage.Stretch) + } + + function test_imageSource_data() { + return [ + { + tag: "local", + source: "stickman.gif", + remote: false, + error: "" + }, + { + tag: "local not found", + source: "no-such-file.png", + remote: false, + error: "SUBinline:1:21: QML AnimatedImage: Error Reading Animated Image File SUBno-such-file.png" + }, + { + tag: "remote", + source: "http://127.0.0.1:14445/stickman.gif", + remote: true, + error: "" + } + ] + } + + function test_imageSource(row) { + var expectError = (row.error.length != 0) + var canconnect = false; + + if (expectError) { + var parentUrl = Qt.resolvedUrl(".") + ignoreWarning(row.error.replace(/SUB/g, parentUrl)) + } + + var img = Qt.createQmlObject('import QtQuick 2.0; AnimatedImage { source: "'+row.source+'" }', top) + + if (row.remote) { + skip("Remote solution not yet complete") + tryCompare(img, "status", AnimatedImage.Loading) + tryCompare(top, "checkfinished", true, 10000) + if (top.canconnect == false) + skip("Cannot access remote") + } + + if (!expectError) { + tryCompare(img, "status", AnimatedImage.Ready, 10000) + compare(img.width, 160) + compare(img.height, 120) + compare(img.fillMode, AnimatedImage.Stretch) + } else { + tryCompare(img, "status", AnimatedImage.Error) + } + + img.destroy() + } + + function test_clearSource() { + compare(clearSource.source, Qt.resolvedUrl(srcImage)) + compare(clearSource.width, 160) + compare(clearSource.height, 120) + + srcImage = "" + compare(clearSource.source, "") + compare(clearSource.width, 0) + compare(clearSource.height, 0) + } + + function test_resized() { + compare(resized.width, 300) + compare(resized.height, 300) + compare(resized.fillMode, AnimatedImage.Stretch) + } + + function test_smooth() { + compare(smooth.smooth, true) + compare(smooth.width, 300) + compare(smooth.height, 300) + compare(smooth.fillMode, AnimatedImage.Stretch) + } + + function test_tileModes() { + compare(tileModes1.width, 100) + compare(tileModes1.height, 300) + compare(tileModes1.fillMode, AnimatedImage.Tile) + + compare(tileModes2.width, 300) + compare(tileModes2.height, 150) + compare(tileModes2.fillMode, AnimatedImage.TileVertically) + + compare(tileModes3.width, 300) + compare(tileModes3.height, 150) + compare(tileModes3.fillMode, AnimatedImage.TileHorizontally) + } + + } +} diff --git a/tests/auto/qmltest/borderimage/remote.sci b/tests/auto/qmltest/borderimage/remote.sci new file mode 100644 index 0000000000..70d5213453 --- /dev/null +++ b/tests/auto/qmltest/borderimage/remote.sci @@ -0,0 +1,7 @@ +border.left:10 +border.top:20 +border.right:30 +border.bottom:40 +horizontalTileRule:Round +verticalTileRule:Repeat +source:http://127.0.0.1:14445/colors.png diff --git a/tests/auto/qmltest/borderimage/tst_borderimage.qml b/tests/auto/qmltest/borderimage/tst_borderimage.qml index 98a71711ed..113c0de77d 100644 --- a/tests/auto/qmltest/borderimage/tst_borderimage.qml +++ b/tests/auto/qmltest/borderimage/tst_borderimage.qml @@ -44,6 +44,24 @@ import QtTest 1.0 Item { id: top + property bool canconnect + property bool checkfinished: false + + Component.onCompleted: { + var check = new XMLHttpRequest; + check.open("GET", "http://127.0.0.1:14445/colors.png"); + check.onreadystatechange = function() { + if (check.readyState == XMLHttpRequest.DONE) { + if (check.status == 404) { + top.canconnect = false; + }else{ + top.canconnect = true; + } + top.checkfinished = true; + } + } + check.send(); + } BorderImage { id: noSource @@ -59,14 +77,14 @@ Item { BorderImage { id: resized - source: "colors.png" + source: srcImage width: 300 height: 300 } BorderImage { id: smooth - source: "colors.png" + source: srcImage smooth: true width: 300 height: 300 @@ -74,7 +92,7 @@ Item { BorderImage { id: tileModes1 - source: "colors.png" + source: srcImage width: 100 height: 300 horizontalTileMode: BorderImage.Repeat @@ -83,7 +101,7 @@ Item { BorderImage { id: tileModes2 - source: "colors.png" + source: srcImage width: 300 height: 150 horizontalTileMode: BorderImage.Round @@ -114,8 +132,13 @@ Item { source: "no-such-file.png", remote: false, error: "SUBinline:1:21: QML BorderImage: Cannot open: SUBno-such-file.png" + }, + { + tag: "remote", + source: "http://127.0.0.1:14445/colors.png", + remote: true, + error: "" } - // TODO: remote tests that need to use http ] } @@ -130,11 +153,16 @@ Item { ('import QtQuick 2.0; BorderImage { source: "' + row.source + '" }', top) - if (row.remote) + if (row.remote) { + skip("Remote solution not yet complete") tryCompare(img, "status", BorderImage.Loading) + tryCompare(top, "checkfinished", true, 10000) + if (top.canconnect == false) + skip("Cannot access remote") + } if (!expectError) { - tryCompare(img, "status", BorderImage.Ready) + tryCompare(img, "status", BorderImage.Ready, 10000) compare(img.width, 120) compare(img.height, 120) compare(img.horizontalTileMode, BorderImage.Stretch) @@ -197,25 +225,35 @@ Item { source: "no-such-file.sci", remote: false, valid: false + }, + { + tag: "remote", + source: "remote.sci", + remote: true, + valid: true } - // TODO: remote tests that need to use http ] } function test_sciSource(row) { - var img = Qt.createQmlObject - ('import QtQuick 2.0; BorderImage { source: "' + - row.source + '"; width: 300; height: 300 }', top) - - if (row.remote) - tryCompare(img, "status", BorderImage.Loading) + var img = Qt.createQmlObject('import QtQuick 2.0; BorderImage { height: 300; width: 300 }', top) + + if (row.remote) { + skip("Remote solution not yet complete") + img.source = row.source; + tryCompare(top, "checkfinished", true, 10000) + if (top.canconnect == false) + skip("Cannot access remote") + }else{ + img.source = row.source; + } compare(img.source, Qt.resolvedUrl(row.source)) compare(img.width, 300) compare(img.height, 300) if (row.valid) { - tryCompare(img, "status", BorderImage.Ready) + tryCompare(img, "status", BorderImage.Ready, 10000) compare(img.border.left, 10) compare(img.border.top, 20) compare(img.border.right, 30) diff --git a/tests/auto/qmltest/fontloader/dummy.ttf b/tests/auto/qmltest/fontloader/dummy.ttf new file mode 100644 index 0000000000..e69de29bb2 --- /dev/null +++ b/tests/auto/qmltest/fontloader/dummy.ttf diff --git a/tests/auto/qmltest/fontloader/tarzeau_ocr_a.ttf b/tests/auto/qmltest/fontloader/tarzeau_ocr_a.ttf Binary files differnew file mode 100644 index 0000000000..cf93f9651f --- /dev/null +++ b/tests/auto/qmltest/fontloader/tarzeau_ocr_a.ttf diff --git a/tests/auto/qmltest/fontloader/tst_fontloader.qml b/tests/auto/qmltest/fontloader/tst_fontloader.qml new file mode 100644 index 0000000000..d389283e49 --- /dev/null +++ b/tests/auto/qmltest/fontloader/tst_fontloader.qml @@ -0,0 +1,97 @@ +/**************************************************************************** +** +** Copyright (C) 2012 Nokia Corporation and/or its subsidiary(-ies). +** Contact: http://www.qt-project.org/ +** +** 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 Nokia Corporation and its Subsidiary(-ies) nor +** the names of its contributors may be used to endorse or promote +** products derived from this software without specific prior written +** permission. +** +** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE." +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +import QtQuick 2.0 +import QtTest 1.0 + +Item { + id: top + + FontLoader { + id: fontloader + } + + FontLoader { + id: fontswitch + } + + TextInput { + id: testinput + font.family: fontloader.name + } + + + + TestCase { + name: "FontLoader" + + function test_fontloading() { + 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) + compare(testinput.font.family, "OCRA") + fontloader.source = "dummy.ttf"; + tryCompare(fontloader.status, FontLoader.Error) + compare(testinput.font.family, "") + fontloader.source = ""; + fontloader.name = "Courier"; + tryCompare(fontloader.status, FontLoader.Ready) + compare(testinput.font.family, "Courier") + } + + function test_fontswitching() { + 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") + fontswitch.source = ""; + fontswitch.name = "Courier"; + tryCompare(fontswitch.status, FontLoader.Ready) + tryCompare(fontswitch.name, "Courier") + fontswitch.source = "tarzeau_ocr_a.ttf"; + tryCompare(fontswitch.status, FontLoader.Loading) + tryCompare(fontswitch.status, FontLoader.Ready) + compare(fontswitch.name, "OCRA") + } + } +} diff --git a/tests/auto/qmltest/gradient/tst_gradient.qml b/tests/auto/qmltest/gradient/tst_gradient.qml new file mode 100644 index 0000000000..ed587502b6 --- /dev/null +++ b/tests/auto/qmltest/gradient/tst_gradient.qml @@ -0,0 +1,119 @@ +/**************************************************************************** +** +** Copyright (C) 2012 Nokia Corporation and/or its subsidiary(-ies). +** Contact: http://www.qt-project.org/ +** +** 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 Nokia Corporation and its Subsidiary(-ies) nor +** the names of its contributors may be used to endorse or promote +** products derived from this software without specific prior written +** permission. +** +** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE." +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +import QtQuick 2.0 +import QtTest 1.0 + +Item { + id: top + + Gradient { + id: emptygradient + } + + Gradient { + id: twogradients + GradientStop { position: 0.0; color: "red" } + GradientStop { position: 1.0; color: "green" } + } + + Gradient { + id: elevengradients + GradientStop { position: 0.0; color: "red" } + GradientStop { position: 0.1; color: "orange" } + GradientStop { position: 0.2; color: "yellow" } + GradientStop { position: 0.3; color: "green" } + GradientStop { position: 0.4; color: "blue" } + GradientStop { position: 0.5; color: "violet" } + GradientStop { position: 0.6; color: "indigo" } + GradientStop { position: 0.7; color: "brown" } + GradientStop { position: 0.8; color: "lightgray" } + GradientStop { position: 0.9; color: "gray" } + GradientStop { position: 1.0; color: "black" } + } + + Gradient { + id: movedgradients + property real stopposition: 0.5 + GradientStop { position: 0.0; color: "red" } + GradientStop { position: movedgradients.stopposition; color: "blue" } + GradientStop { position: 1.0; color: "green" } + } + + Gradient { + id: defaultgradient + GradientStop { } + GradientStop { position: 1.0; color: "red" } + } + + TestCase { + name: "Gradient" + + function test_empty() { + compare(emptygradient.stops.length, 0) + } + + function test_lengthtwo() { + compare(twogradients.stops.length, 2) + compare(twogradients.stops[0].color.toString(), "#ff0000") + compare(twogradients.stops[1].color.toString(), "#008000") + } + + function test_multiplestops() { + compare(elevengradients.stops.length, 11) + compare(elevengradients.stops[0].color.toString(), "#ff0000") + compare(elevengradients.stops[4].color.toString(), "#0000ff") + compare(elevengradients.stops[4].position, 0.4) + compare(elevengradients.stops[9].position, 0.9) + } + + function test_moved() { + compare(movedgradients.stops.length, 3) + compare(movedgradients.stops[1].position, 0.5) + movedgradients.stopposition = 0.3; + compare(movedgradients.stops[1].position, 0.3) + } + + function test_default() { + compare(defaultgradient.stops.length, 2) + compare(defaultgradient.stops[0].color.toString(), "#000000") + } + } +} diff --git a/tests/auto/qmltest/image/logo.png b/tests/auto/qmltest/image/logo.png Binary files differnew file mode 100644 index 0000000000..d75936b007 --- /dev/null +++ b/tests/auto/qmltest/image/logo.png diff --git a/tests/auto/qmltest/image/tst_image.qml b/tests/auto/qmltest/image/tst_image.qml new file mode 100644 index 0000000000..f6ad01014a --- /dev/null +++ b/tests/auto/qmltest/image/tst_image.qml @@ -0,0 +1,216 @@ +/**************************************************************************** +** +** Copyright (C) 2012 Nokia Corporation and/or its subsidiary(-ies). +** Contact: http://www.qt-project.org/ +** +** 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 Nokia Corporation and its Subsidiary(-ies) nor +** the names of its contributors may be used to endorse or promote +** products derived from this software without specific prior written +** permission. +** +** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE." +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +import QtQuick 2.0 +import QtTest 1.0 + +Item { + id: top + + property string srcImage: "logo.png" + property bool canconnect + property bool checkfinished: false + + Component.onCompleted: { + var check = new XMLHttpRequest; + check.open("GET", "http://127.0.0.1:14445/logo.png"); + check.onreadystatechange = function() { + if (check.readyState == XMLHttpRequest.DONE) { + if (check.status == 404) { + top.canconnect = false; + } else { + top.canconnect = true; + } + top.checkfinished = true; + } + } + check.send(); + } + + Image { + id: noSource + source: "" + } + + Image { + id: clearSource + source: srcImage + } + + Image { + id: resized + source: srcImage + width: 300 + height: 300 + } + + Image { + id: smooth + source: srcImage + smooth: true + width: 300 + height: 300 + } + + Image { + id: tileModes1 + source: srcImage + width: 100 + height: 300 + fillMode: Image.Tile + } + + Image { + id: tileModes2 + source: srcImage + width: 300 + height: 150 + fillMode: Image.TileVertically + } + Image { + id: tileModes3 + source: srcImage + width: 300 + height: 150 + fillMode: Image.TileHorizontally + } + + TestCase { + name: "Image" + + function test_noSource() { + compare(noSource.source, "") + compare(noSource.width, 0) + compare(noSource.height, 0) + compare(noSource.fillMode, Image.Stretch) + } + + function test_imageSource_data() { + return [ + { + tag: "local", + source: "logo.png", + remote: false, + error: "" + }, + { + tag: "local not found", + source: "no-such-file.png", + remote: false, + error: "SUBinline:1:21: QML Image: Cannot open: SUBno-such-file.png" + }, + { + tag: "remote", + source: "http://127.0.0.1:14445/logo.png", + remote: true, + error: "" + } + ] + } + + function test_imageSource(row) { + var expectError = (row.error.length != 0) + if (expectError) { + var parentUrl = Qt.resolvedUrl(".") + ignoreWarning(row.error.replace(/SUB/g, parentUrl)) + } + + var img = Qt.createQmlObject('import QtQuick 2.0; Image { source: "'+row.source+'" }', top) + + if (row.remote) { + skip("Remote solution not yet complete") + tryCompare(img, "status", Image.Loading) + tryCompare(top, "checkfinished", true, 10000) + if (top.canconnect == false) + skip("Cannot access remote") + } + + if (!expectError) { + tryCompare(img, "status", Image.Ready, 10000) + compare(img.width, 59) + compare(img.height, 71) + compare(img.fillMode, Image.Stretch) + } else { + tryCompare(img, "status", Image.Error) + } + + img.destroy() + } + + function test_clearSource() { + compare(clearSource.source, Qt.resolvedUrl(srcImage)) + compare(clearSource.width, 59) + compare(clearSource.height, 71) + + srcImage = "" + compare(clearSource.source, "") + compare(clearSource.width, 0) + compare(clearSource.height, 0) + } + + function test_resized() { + compare(resized.width, 300) + compare(resized.height, 300) + compare(resized.fillMode, Image.Stretch) + } + + function test_smooth() { + compare(smooth.smooth, true) + compare(smooth.width, 300) + compare(smooth.height, 300) + compare(smooth.fillMode, Image.Stretch) + } + + function test_tileModes() { + compare(tileModes1.width, 100) + compare(tileModes1.height, 300) + compare(tileModes1.fillMode, Image.Tile) + + compare(tileModes2.width, 300) + compare(tileModes2.height, 150) + compare(tileModes2.fillMode, Image.TileVertically) + + compare(tileModes3.width, 300) + compare(tileModes3.height, 150) + compare(tileModes3.fillMode, Image.TileHorizontally) + } + + } +} diff --git a/tests/auto/qmltest/listmodel/tst_listmodel.qml b/tests/auto/qmltest/listmodel/tst_listmodel.qml new file mode 100644 index 0000000000..7c393a1899 --- /dev/null +++ b/tests/auto/qmltest/listmodel/tst_listmodel.qml @@ -0,0 +1,132 @@ +/**************************************************************************** +** +** Copyright (C) 2012 Nokia Corporation and/or its subsidiary(-ies). +** Contact: http://www.qt-project.org/ +** +** 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 Nokia Corporation and its Subsidiary(-ies) nor +** the names of its contributors may be used to endorse or promote +** products derived from this software without specific prior written +** permission. +** +** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE." +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +import QtQuick 2.0 +import QtTest 1.0 + +Item { + id: top + ListModel { id: emptymodel } + ListModel { id: manyitems } + ListModel { id: insertmodel } + ListModel { id: move; ListElement { name: "Element0" } ListElement { name: "Element1" } } + ListModel { id: firstmodel; ListElement { name: "FirstModelElement0" } } + ListModel { id: secondmodel; ListElement { name: "SecondModelElement0" } ListElement { name: "SecondModelElement1" } } + ListModel { id: altermodel; ListElement { name: "AlterModelElement0" } ListElement { name: "AlterModelElement1" } } + + TestCase { + name: "ListModel" + + function test_empty() { + compare(emptymodel.count, 0) + emptymodel.clear(); + compare(emptymodel.count, 0) + } + + function test_multipleitems_data() { + return [ + { + tag: "10items", + numitems: 10 + }, + { + tag: "100items", + numitems: 100 + }, + { + tag: "10000items", + numitems: 10000 + } + ] + } + + function test_multipleitems(row) { + var i; + manyitems.clear(); + compare(manyitems.count, 0) + for (i = 0; i < row.numitems; ++i) { + manyitems.append({"name":"Item"+i}) + } + compare(manyitems.count, row.numitems) + } + + function test_insert() { + insertmodel.insert(0, {"name": "Element0"}) + compare(insertmodel.get(0).name, "Element0") + insertmodel.insert(1, {"name": "Element1"}) + compare(insertmodel.get(1).name, "Element1") + } + + function test_altermodeled() { + tryCompare(altermodel.count, 2) + compare(altermodel.get(0).name, "AlterModelElement0") + compare(altermodel.get(1).name, "AlterModelElement1") + altermodel.append({"name":"AlterModelElement2"}) + 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) + 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) + 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) + compare(altermodel.get(0).name, "AlterModelElement0") + compare(altermodel.get(1).name, "AlterModelElement2") + altermodel.set(1,{"name":"AlterModelElement1"}) + compare(altermodel.get(0).name, "AlterModelElement0") + compare(altermodel.get(1).name, "AlterModelElement1") + altermodel.setProperty(0, "name", "AlteredProperty") + compare(altermodel.get(0).name, "AlteredProperty") + altermodel.clear() + tryCompare(altermodel.count, 0) + compare(altermodel.get(0), undefined) + } + } +} diff --git a/tests/auto/qmltest/listview/tst_listview.qml b/tests/auto/qmltest/listview/tst_listview.qml new file mode 100644 index 0000000000..535c551ede --- /dev/null +++ b/tests/auto/qmltest/listview/tst_listview.qml @@ -0,0 +1,175 @@ +/**************************************************************************** +** +** Copyright (C) 2012 Nokia Corporation and/or its subsidiary(-ies). +** Contact: http://www.qt-project.org/ +** +** 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 Nokia Corporation and its Subsidiary(-ies) nor +** the names of its contributors may be used to endorse or promote +** products derived from this software without specific prior written +** permission. +** +** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE." +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +import QtQuick 2.0 +import QtTest 1.0 + +Item { + id: top + + ListView { + id: emptylist + height: 20 + width: 50 + } + + ListView { + id: viewmanyitems + model: manyitems + } + + ListView { + id: modelchange + model: firstmodel + delegate: Text { text: model.name } + } + + ListView { + id: modelalter + model: altermodel + delegate: Text { text: model.name } + } + + 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" } } + + TestCase { + name: "ListView" + + function test_empty() { + compare(emptylist.count, 0) + emptylist.model = emptymodel; + compare(emptylist.count, 0) + } + + function test_multipleitems_data() { + return [ + { + tag: "10items", + numitems: 10 + }, + { + tag: "100items", + numitems: 100 + }, + { + tag: "10000items", + numitems: 10000 + } + ] + } + + function test_multipleitems(row) { + var i; + manyitems.clear(); + compare(manyitems.count, 0) + for (i = 0; i < row.numitems; ++i) { + manyitems.append({"name":"Item"+i}) + } + compare(manyitems.count, row.numitems) + tryCompare(viewmanyitems.count, row.numitems) + } + + function test_modelchange() { + tryCompare(modelchange.count, 1) + modelchange.currentIndex = 0; + compare(modelchange.currentItem.text, "FirstModelElement0") + modelchange.model = secondmodel; + tryCompare(modelchange.count, 2) + modelchange.currentIndex = 0; + compare(modelchange.currentItem.text, "SecondModelElement0") + modelchange.currentIndex = 1; + compare(modelchange.currentItem.text, "SecondModelElement1") + } + + function test_modelaltered() { + 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) + modelalter.currentIndex = 0; + compare(modelalter.currentItem.text, "AlterModelElement0") + modelalter.currentIndex = 1; + compare(modelalter.currentItem.text, "AlterModelElement1") + modelalter.currentIndex = 2; + compare(modelalter.currentItem.text, "AlterModelElement2") + altermodel.insert(2,{"name":"AlterModelElement1.5"}) + tryCompare(modelalter.count, 4) + modelalter.currentIndex = 0; + compare(modelalter.currentItem.text, "AlterModelElement0") + modelalter.currentIndex = 1; + compare(modelalter.currentItem.text, "AlterModelElement1") + modelalter.currentIndex = 2; + compare(modelalter.currentItem.text, "AlterModelElement1.5") + modelalter.currentIndex = 3; + compare(modelalter.currentItem.text, "AlterModelElement2") + altermodel.move(2,1,1); + tryCompare(modelalter.count, 4) + modelalter.currentIndex = 0; + compare(modelalter.currentItem.text, "AlterModelElement0") + modelalter.currentIndex = 1; + compare(modelalter.currentItem.text, "AlterModelElement1.5") + modelalter.currentIndex = 2; + compare(modelalter.currentItem.text, "AlterModelElement1") + modelalter.currentIndex = 3; + compare(modelalter.currentItem.text, "AlterModelElement2") + altermodel.remove(1,2) + tryCompare(modelalter.count, 2) + modelalter.currentIndex = 0; + compare(modelalter.currentItem.text, "AlterModelElement0") + modelalter.currentIndex = 1; + compare(modelalter.currentItem.text, "AlterModelElement2") + altermodel.set(1,{"name":"AlterModelElement1"}) + modelalter.currentIndex = 0; + compare(modelalter.currentItem.text, "AlterModelElement0") + modelalter.currentIndex = 1; + compare(modelalter.currentItem.text, "AlterModelElement1") + altermodel.clear() + tryCompare(modelalter.count, 0) + compare(modelalter.currentItem, null) + } + } +} diff --git a/tests/auto/qmltest/rectangle/tst_rectangle.qml b/tests/auto/qmltest/rectangle/tst_rectangle.qml new file mode 100644 index 0000000000..038bb96c0f --- /dev/null +++ b/tests/auto/qmltest/rectangle/tst_rectangle.qml @@ -0,0 +1,137 @@ +/**************************************************************************** +** +** Copyright (C) 2012 Nokia Corporation and/or its subsidiary(-ies). +** Contact: http://www.qt-project.org/ +** +** 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 Nokia Corporation and its Subsidiary(-ies) nor +** the names of its contributors may be used to endorse or promote +** products derived from this software without specific prior written +** permission. +** +** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE." +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +import QtQuick 2.0 +import QtTest 1.0 + +Item { + id: top + + Rectangle { id: empty } + + Rectangle { id: radius } + + Rectangle { + id: resized + width: 300 + height: 300 + } + + Rectangle { + id: smooth + smooth: true + width: 300 + height: 300 + } + + Rectangle { + id: gradient + width: 100 + height: 300 + gradient: Gradient { + GradientStop { position: 0.0; color: "red" } + GradientStop { position: 0.5; color: "yellow" } + GradientStop { position: 1.0; color: "green" } + } + } + + Rectangle { + id: rectangleborder + width: 300 + height: 150 + border.width: 1 + border.color: "gray" + } + + TestCase { + name: "Rectangle" + + function test_empty() { + compare(empty.width, 0) + compare(empty.height, 0) + } + + function test_radius() { + compare(radius.width, 0) + compare(radius.height, 0) + compare(radius.radius, 0) + radius.height = 100; + radius.width = 100; + radius.radius = 10; + compare(radius.width, 100) + compare(radius.height, 100) + compare(radius.radius, 10) + } + + function test_resized() { + compare(resized.width, 300) + compare(resized.height, 300) + resized.height = 500; + resized.width = 500; + compare(resized.width, 500) + compare(resized.height, 500) + } + + function test_smooth() { + compare(smooth.smooth, true) + compare(smooth.width, 300) + compare(smooth.height, 300) + + } + + function test_gradient() { + var grad = gradient.gradient; + var gstops = grad.stops; + compare(gstops[0].color.toString(), "#ff0000") + compare(gstops[1].color.toString(), "#ffff00") + compare(gstops[2].color.toString(), "#008000") + } + + function test_borders() { + compare(rectangleborder.border.width, 1) + compare(rectangleborder.border.color.toString(), "#808080") + rectangleborder.border.width = 10; + rectangleborder.border.color = "brown"; + compare(rectangleborder.border.width, 10) + compare(rectangleborder.border.color.toString(), "#a52a2a") + } + + } +} diff --git a/tests/auto/qmltest/text/tst_text.qml b/tests/auto/qmltest/text/tst_text.qml new file mode 100644 index 0000000000..599fabcc8b --- /dev/null +++ b/tests/auto/qmltest/text/tst_text.qml @@ -0,0 +1,120 @@ +/**************************************************************************** +** +** Copyright (C) 2012 Nokia Corporation and/or its subsidiary(-ies). +** Contact: http://www.qt-project.org/ +** +** 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 Nokia Corporation and its Subsidiary(-ies) nor +** the names of its contributors may be used to endorse or promote +** products derived from this software without specific prior written +** permission. +** +** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE." +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +import QtQuick 2.0 +import QtTest 1.0 + +Item { + id: top + + Text { + id: emptyText + } + + Text { + id: txtfamily + text: "Hello world!" + font.family: "Courier" + } + + Text { + id: txtcolor + text: "Hello world!" + color: "red" + } + + Text { + id: txtelide + text: "Hello world!" + elide: Text.ElideRight + } + + Text { + property string first: "Hello world!" + property string second: "Hello\nworld!" + property string third: "Hello\nworld\n!" + + id: txtlinecount + text: first + width: 100 + wrapMode: Text.WrapAnywhere + } + + TestCase { + name: "Text" + + function test_empty() { + compare(emptyText.text, "") + } + + function test_family() { + compare(txtfamily.font.family, "Courier") + txtfamily.font.family = "Helvetica"; + compare(txtfamily.font.family, "Helvetica") + } + + function test_color() { + compare(txtcolor.color, "#ff0000") + txtcolor.color = "blue"; + compare(txtcolor.color, "#0000ff") + } + + function test_elide() { + compare(txtelide.elide, Text.ElideRight) + txtelide.elide = Text.ElideLeft; + compare(txtelide.elide, Text.ElideLeft) + txtelide.elide = Text.ElideMiddle; + compare(txtelide.elide, Text.ElideMiddle) + } + + function test_linecount() { + compare(txtlinecount.lineCount, 1) + txtlinecount.text = txtlinecount.second; + compare(txtlinecount.lineCount, 2) + txtlinecount.text = txtlinecount.third; + compare(txtlinecount.lineCount, 3) + txtlinecount.text = txtlinecount.first; + compare(txtlinecount.lineCount, 1) + txtlinecount.width = 50; + compare(txtlinecount.lineCount, 3) + } + + } +} diff --git a/tests/auto/qmltest/textedit/tst_textedit.qml b/tests/auto/qmltest/textedit/tst_textedit.qml new file mode 100644 index 0000000000..a0f0a8c8d7 --- /dev/null +++ b/tests/auto/qmltest/textedit/tst_textedit.qml @@ -0,0 +1,165 @@ +/**************************************************************************** +** +** Copyright (C) 2012 Nokia Corporation and/or its subsidiary(-ies). +** Contact: http://www.qt-project.org/ +** +** 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 Nokia Corporation and its Subsidiary(-ies) nor +** the names of its contributors may be used to endorse or promote +** products derived from this software without specific prior written +** permission. +** +** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE." +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +import QtQuick 2.0 +import QtTest 1.0 + +Item { + id: top + + TextEdit { + id: emptyText + height: 20 + width: 50 + } + + TextEdit { + id: txtfamily + text: "Hello world!" + font.family: "Courier" + height: 20 + width: 50 + } + + TextEdit { + id: txtcolor + text: "Hello world!" + color: "red" + height: 20 + width: 50 + } + + TextEdit { + id: txtentry + text: "" + height: 20 + width: 50 + } + + TextEdit { + id: txtfunctions + text: "The quick brown fox jumped over the lazy dog" + height: 20 + width: 50 + } + + TextEdit { + 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: "TextEdit" + when: windowShown + + function test_empty() { + compare(emptyText.text, "") + } + + function test_family() { + compare(txtfamily.font.family, "Courier") + txtfamily.font.family = "Helvetica"; + compare(txtfamily.font.family, "Helvetica") + } + + function test_color() { + compare(txtcolor.color, "#ff0000") + txtcolor.color = "blue"; + compare(txtcolor.color, "#0000ff") + } + + function test_textentry() { + txtentry.focus = true; + compare(txtentry.text, "") + keyClick(Qt.Key_H) + keyClick(Qt.Key_E) + keyClick(Qt.Key_L) + keyClick(Qt.Key_L) + keyClick(Qt.Key_O) + keyClick(Qt.Key_Space) + keyClick(Qt.Key_W) + keyClick(Qt.Key_O) + keyClick(Qt.Key_R) + keyClick(Qt.Key_L) + keyClick(Qt.Key_D) + compare(txtentry.text, "hello world") + } + + function test_functions() { + compare(txtfunctions.getText(4,9), "quick") + txtfunctions.select(4,9); + compare(txtfunctions.selectedText, "quick") + txtfunctions.deselect(); + compare(txtfunctions.selectedText, "") + txtfunctions.select(4,9); + txtfunctions.cut(); + compare(txtfunctions.text, "The brown fox jumped over the lazy dog") + txtfunctions.text = "Qt"; + txtfunctions.insert(txtfunctions.text.length, " ") + compare(txtfunctions.text, "Qt "); + txtfunctions.cursorPosition = txtfunctions.text.length; + txtfunctions.paste(); + compare(txtfunctions.text, "Qt quick"); + txtfunctions.cursorPosition = txtfunctions.text.length; + txtfunctions.selectWord(); + compare(txtfunctions.selectedText, "quick") + txtfunctions.copy(); + txtfunctions.selectAll(); + compare(txtfunctions.selectedText, "Qt quick") + txtfunctions.deselect(); + compare(txtfunctions.selectedText, "") + txtfunctions.paste(); + compare(txtfunctions.text, "Qt quickquick"); + } + + 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/textinput/tst_textinput.qml b/tests/auto/qmltest/textinput/tst_textinput.qml new file mode 100644 index 0000000000..2399456730 --- /dev/null +++ b/tests/auto/qmltest/textinput/tst_textinput.qml @@ -0,0 +1,286 @@ +/**************************************************************************** +** +** Copyright (C) 2012 Nokia Corporation and/or its subsidiary(-ies). +** Contact: http://www.qt-project.org/ +** +** 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 Nokia Corporation and its Subsidiary(-ies) nor +** the names of its contributors may be used to endorse or promote +** products derived from this software without specific prior written +** permission. +** +** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE." +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +import QtQuick 2.0 +import QtTest 1.0 + +Item { + id: top + + TextInput { + id: emptyText + height: 20 + width: 50 + } + + TextInput { + id: txtfamily + text: "Hello world!" + font.family: "Courier" + height: 20 + width: 50 + } + + TextInput { + id: txtcolor + text: "Hello world!" + color: "red" + height: 20 + width: 50 + } + + TextInput { + id: txtentry + text: "" + height: 20 + width: 50 + } + + TextInput { + id: txtfunctions + text: "The quick brown fox jumped over the lazy dog" + height: 20 + width: 50 + } + + TextInput { + id: txtintvalidator + text: "" + height: 20 + width: 50 + validator: IntValidator { id: iv; top: 20; bottom: 10; } + } + + TextInput { + id: txtdoublevalidator + text: "" + height: 20 + width: 50 + validator: DoubleValidator { id: dv; top: 2.0; bottom: 1.0; } + } + + TextInput { + id: txtregexpvalidator + text: "" + height: 20 + width: 50 + validator: RegExpValidator { id: rv; regExp: /[a-z]{3}/ } + } + + + + TestCase { + name: "TextInput" + when: windowShown + + function test_empty() { + compare(emptyText.text, "") + } + + function test_family() { + compare(txtfamily.font.family, "Courier") + txtfamily.font.family = "Helvetica"; + compare(txtfamily.font.family, "Helvetica") + } + + function test_color() { + compare(txtcolor.color, "#ff0000") + txtcolor.color = "blue"; + compare(txtcolor.color, "#0000ff") + } + + function test_textentry() { + txtentry.focus = true; + compare(txtentry.text, "") + keyClick(Qt.Key_H) + keyClick(Qt.Key_E) + keyClick(Qt.Key_L) + keyClick(Qt.Key_L) + keyClick(Qt.Key_O) + keyClick(Qt.Key_Space) + keyClick(Qt.Key_W) + keyClick(Qt.Key_O) + keyClick(Qt.Key_R) + keyClick(Qt.Key_L) + keyClick(Qt.Key_D) + compare(txtentry.text, "hello world") + } + + function test_functions() { + compare(txtfunctions.getText(4,9), "quick") + txtfunctions.select(4,9); + compare(txtfunctions.selectedText, "quick") + txtfunctions.deselect(); + compare(txtfunctions.selectedText, "") + txtfunctions.select(4,9); + txtfunctions.cut(); + compare(txtfunctions.text, "The brown fox jumped over the lazy dog") + txtfunctions.text = "Qt"; + txtfunctions.insert(txtfunctions.text.length, " ") + compare(txtfunctions.text, "Qt "); + txtfunctions.cursorPosition = txtfunctions.text.length; + txtfunctions.paste(); + compare(txtfunctions.text, "Qt quick"); + txtfunctions.cursorPosition = txtfunctions.text.length; + txtfunctions.selectWord(); + compare(txtfunctions.selectedText, "quick") + txtfunctions.copy(); + txtfunctions.selectAll(); + compare(txtfunctions.selectedText, "Qt quick") + txtfunctions.deselect(); + compare(txtfunctions.selectedText, "") + txtfunctions.paste(); + compare(txtfunctions.text, "Qt quickquick"); + } + + function test_intvalidators_data() { + return [ + { + tag: "toolow", + testnumber: "5", + acceptable: false + }, + { + tag: "toohigh", + testnumber: "50", + acceptable: false + }, + { + tag: "onlowerbounds", + testnumber: "10", + acceptable: true + }, + { + tag: "onupperbounds", + testnumber: "20", + acceptable: true + }, + { + tag: "middle", + testnumber: "15", + acceptable: true + }, + { + tag: "negativemiddle", + testnumber: "-15", + acceptable: false + } + ] + + } + + function test_intvalidators(row) { + compare(txtintvalidator.validator.top, 20) + compare(txtintvalidator.validator.bottom, 10) + txtintvalidator.text = row.testnumber; + compare(txtintvalidator.acceptableInput, row.acceptable) + } + + function test_doublevalidators_data() { + return [ + { + tag: "toolow", + testnumber: "0.5", + acceptable: false + }, + { + tag: "toohigh", + testnumber: "2.5", + acceptable: false + }, + { + tag: "onlowerbounds", + testnumber: "1.0", + acceptable: true + }, + { + tag: "onupperbounds", + testnumber: "2.0", + acceptable: true + }, + { + tag: "middle", + testnumber: "1.5", + acceptable: true + }, + { + tag: "negativemiddle", + testnumber: "-1.5", + acceptable: false + } + ] + + } + + function test_doublevalidators(row) { + compare(txtdoublevalidator.validator.top, 2.0) + compare(txtdoublevalidator.validator.bottom, 1.0) + txtdoublevalidator.text = row.testnumber; + compare(txtdoublevalidator.acceptableInput, row.acceptable) + } + + function test_regexpvalidators_data() { + return [ + { + tag: "toolow", + testtext: "ab", + acceptable: false + }, + { + tag: "toohigh", + testtext: "abcd", + acceptable: false + }, + { + tag: "acceptable", + testtext: "abc", + acceptable: true + } + ] + + } + + function test_regexpvalidators(row) { + compare(txtregexpvalidator.validator.regExp, /[a-z]{3}/) + txtregexpvalidator.text = row.testtext; + compare(txtregexpvalidator.acceptableInput, row.acceptable) + } + } +} diff --git a/tests/auto/quick/qquickanimations/data/pathAnimationInOutBackCrash.qml b/tests/auto/quick/qquickanimations/data/pathAnimationInOutBackCrash.qml new file mode 100644 index 0000000000..1ee76f6906 --- /dev/null +++ b/tests/auto/quick/qquickanimations/data/pathAnimationInOutBackCrash.qml @@ -0,0 +1,26 @@ +import QtQuick 2.0 +Item { + id: root + width: 450; height: 600 + + Rectangle { + objectName:"rect" + id: rect + x:200 + y:500 + width: 225; height: 40 + color: "lightsteelblue" + } + PathAnimation { + id:anim + running:true + duration: 200 + + easing.type: Easing.InOutBack + + target:rect + path: Path { + PathLine { x: 0; y: 0 } + } + } +}
\ No newline at end of file diff --git a/tests/auto/quick/qquickanimations/tst_qquickanimations.cpp b/tests/auto/quick/qquickanimations/tst_qquickanimations.cpp index d71100d120..166f4b8276 100644 --- a/tests/auto/quick/qquickanimations/tst_qquickanimations.cpp +++ b/tests/auto/quick/qquickanimations/tst_qquickanimations.cpp @@ -107,6 +107,7 @@ private slots: void pauseBug(); void loopingBug(); void anchorBug(); + void pathAnimationInOutBackBug(); }; #define QTIMED_COMPARE(lhs, rhs) do { \ @@ -455,6 +456,13 @@ void tst_qquickanimations::pathInterpolator() QCOMPARE(interpolator->x(), qreal(300)); QCOMPARE(interpolator->y(), qreal(300)); QCOMPARE(interpolator->angle(), qreal(0)); + + //for path interpulator the progress value must be [0,1] range. + interpolator->setProgress(1.1); + QCOMPARE(interpolator->progress(), qreal(1)); + + interpolator->setProgress(-0.000123); + QCOMPARE(interpolator->progress(), qreal(0)); } void tst_qquickanimations::pathInterpolatorBackwardJump() @@ -1171,6 +1179,22 @@ void tst_qquickanimations::runningTrueBug() QVERIFY(cloud->x() > qreal(0)); } +//QTBUG-24308 +void tst_qquickanimations::pathAnimationInOutBackBug() +{ + //ensure we don't pass bad progress value (out of [0,1]) to QQuickPath::backwardsPointAt() + QQmlEngine engine; + QQmlComponent c(&engine, testFileUrl("pathAnimationInOutBackCrash.qml")); + QQuickItem *item = qobject_cast<QQuickItem*>(c.create()); + QVERIFY(item); + + QQuickRectangle *rect = item->findChild<QQuickRectangle *>("rect"); + QVERIFY(rect); + QTest::qWait(1000); + QCOMPARE(rect->x(), qreal(0)); + QCOMPARE(rect->y(), qreal(0)); +} + //QTBUG-12805 void tst_qquickanimations::nonTransitionBug() { diff --git a/tests/auto/quick/qquickcanvasitem/data/tst_arc.qml b/tests/auto/quick/qquickcanvasitem/data/tst_arc.qml index ffe6583d2e..c33901d294 100644 --- a/tests/auto/quick/qquickcanvasitem/data/tst_arc.qml +++ b/tests/auto/quick/qquickcanvasitem/data/tst_arc.qml @@ -4,6 +4,7 @@ import "testhelper.js" as Helper Canvas { id:canvas; width:100;height:50; renderTarget: Canvas.Image; renderStrategy:Canvas.Threaded + smooth: false TestCase { name: "arc"; when: windowShown function test_angle_1() { diff --git a/tests/auto/quick/qquickcanvasitem/data/tst_arcto.qml b/tests/auto/quick/qquickcanvasitem/data/tst_arcto.qml index 8609ad0332..84bfc1a8db 100644 --- a/tests/auto/quick/qquickcanvasitem/data/tst_arcto.qml +++ b/tests/auto/quick/qquickcanvasitem/data/tst_arcto.qml @@ -4,6 +4,7 @@ import "testhelper.js" as Helper Canvas { id:canvas; width:100;height:50; renderTarget: Canvas.Image; renderStrategy:Canvas.Threaded + smooth: false TestCase { name: "arcTo"; when: windowShown function test_coincide() { diff --git a/tests/auto/quick/qquickcanvasitem/data/tst_path.qml b/tests/auto/quick/qquickcanvasitem/data/tst_path.qml index 6aaecbdfa5..f72e5b9eaa 100644 --- a/tests/auto/quick/qquickcanvasitem/data/tst_path.qml +++ b/tests/auto/quick/qquickcanvasitem/data/tst_path.qml @@ -4,6 +4,7 @@ import "testhelper.js" as Helper Canvas { id:canvas; width:100;height:50; renderTarget: Canvas.Image; renderStrategy:Canvas.Threaded + smooth: false TestCase { name: "path"; when: windowShown diff --git a/tests/auto/quick/qquickcanvasitem/data/tst_strokeStyle.qml b/tests/auto/quick/qquickcanvasitem/data/tst_strokeStyle.qml index 2521643837..c81ef73b90 100644 --- a/tests/auto/quick/qquickcanvasitem/data/tst_strokeStyle.qml +++ b/tests/auto/quick/qquickcanvasitem/data/tst_strokeStyle.qml @@ -4,6 +4,7 @@ import "testhelper.js" as Helper Canvas { id:canvas; width:100;height:50; renderTarget:Canvas.Image; renderStrategy:Canvas.Threaded + smooth: false TestCase { name: "strokeStyle"; when: windowShown function test_default() { diff --git a/tests/auto/quick/qquickflickable/data/cancel.qml b/tests/auto/quick/qquickflickable/data/cancel.qml new file mode 100644 index 0000000000..d1c3fddbf2 --- /dev/null +++ b/tests/auto/quick/qquickflickable/data/cancel.qml @@ -0,0 +1,15 @@ +import QtQuick 2.0 + +Flickable { + width: 200; height: 200 + contentWidth: row.width; contentHeight: row.height + + Row { + id: row + objectName: "row" + Repeater { + model: 4 + Rectangle { width: 400; height: 600; color: "yellow"; border.width: 1 } + } + } +} diff --git a/tests/auto/quick/qquickflickable/tst_qquickflickable.cpp b/tests/auto/quick/qquickflickable/tst_qquickflickable.cpp index 4b157a434b..2ed42e7f0f 100644 --- a/tests/auto/quick/qquickflickable/tst_qquickflickable.cpp +++ b/tests/auto/quick/qquickflickable/tst_qquickflickable.cpp @@ -77,6 +77,7 @@ private slots: void disabled(); void flickVelocity(); void margins(); + void cancel(); private: QQmlEngine engine; @@ -440,6 +441,19 @@ void tst_qquickflickable::movingAndDragging() // wait for any motion to end QTRY_VERIFY(flickable->isMoving() == false); + // Vertical with a quick press-move-release: should cause a flick in release. + QSignalSpy vFlickSpy(flickable, SIGNAL(flickingVerticallyChanged())); + + QTest::mousePress(canvas, Qt::LeftButton, 0, QPoint(50, 90)); + QTest::qWait(10); + QTest::mouseMove(canvas, QPoint(50, 40)); + QTest::mouseRelease(canvas, Qt::LeftButton, 0, QPoint(50, 40)); + + QCOMPARE(vFlickSpy.count(), 1); + + // wait for any motion to end + QTRY_VERIFY(flickable->isMoving() == false); + //Horizontal vDragSpy.clear(); hDragSpy.clear(); @@ -492,7 +506,7 @@ void tst_qquickflickable::movingAndDragging() vMoveSpy.clear(); hMoveSpy.clear(); moveSpy.clear(); - QSignalSpy vFlickSpy(flickable, SIGNAL(flickingVerticallyChanged())); + vFlickSpy.clear(); QSignalSpy hFlickSpy(flickable, SIGNAL(flickingHorizontallyChanged())); QSignalSpy flickSpy(flickable, SIGNAL(flickingChanged())); @@ -657,6 +671,41 @@ void tst_qquickflickable::margins() delete root; } +void tst_qquickflickable::cancel() +{ + QQuickView *canvas = new QQuickView; + canvas->setSource(testFileUrl("cancel.qml")); + canvas->show(); + canvas->requestActivateWindow(); + QVERIFY(canvas->rootObject() != 0); + + QQuickFlickable *flickable = qobject_cast<QQuickFlickable*>(canvas->rootObject()); + QVERIFY(flickable != 0); + + QTest::mousePress(canvas, Qt::LeftButton, 0, QPoint(10, 10)); + // drag out of bounds + QTest::mouseMove(canvas, QPoint(50, 50)); + QTest::mouseMove(canvas, QPoint(100, 100)); + QTest::mouseMove(canvas, QPoint(150, 150)); + + QVERIFY(flickable->contentX() != 0); + QVERIFY(flickable->contentY() != 0); + QVERIFY(flickable->isMoving()); + QVERIFY(flickable->isDragging()); + + // grabbing mouse will cancel flickable interaction. + QQuickItem *item = canvas->rootObject()->findChild<QQuickItem*>("row"); + item->grabMouse(); + + QTRY_COMPARE(flickable->contentX(), 0.); + QTRY_COMPARE(flickable->contentY(), 0.); + QTRY_VERIFY(!flickable->isMoving()); + QTRY_VERIFY(!flickable->isDragging()); + + QTest::mouseRelease(canvas, Qt::LeftButton, 0, QPoint(50, 10)); +} + + QTEST_MAIN(tst_qquickflickable) #include "tst_qquickflickable.moc" diff --git a/tests/auto/quick/qquickfontloader/tst_qquickfontloader.cpp b/tests/auto/quick/qquickfontloader/tst_qquickfontloader.cpp index f99c26803d..10f81accbf 100644 --- a/tests/auto/quick/qquickfontloader/tst_qquickfontloader.cpp +++ b/tests/auto/quick/qquickfontloader/tst_qquickfontloader.cpp @@ -116,6 +116,9 @@ void tst_qquickfontloader::namedFont() void tst_qquickfontloader::localFont() { +#if defined(Q_OS_WIN) + QSKIP("Windows doesn't support font loading."); +#endif QString componentStr = "import QtQuick 2.0\nFontLoader { source: \"" + testFileUrl("tarzeau_ocr_a.ttf").toString() + "\" }"; QQmlComponent component(&engine); component.setData(componentStr.toLatin1(), QUrl::fromLocalFile("")); @@ -129,6 +132,9 @@ void tst_qquickfontloader::localFont() void tst_qquickfontloader::failLocalFont() { +#if defined(Q_OS_WIN) + QSKIP("Windows doesn't support font loading."); +#endif QString componentStr = "import QtQuick 2.0\nFontLoader { source: \"" + testFileUrl("dummy.ttf").toString() + "\" }"; QTest::ignoreMessage(QtWarningMsg, QString("file::2:1: QML FontLoader: Cannot load font: \"" + testFileUrl("dummy.ttf").toString() + "\"").toUtf8().constData()); QQmlComponent component(&engine); @@ -143,6 +149,9 @@ void tst_qquickfontloader::failLocalFont() void tst_qquickfontloader::webFont() { +#if defined(Q_OS_WIN) + QSKIP("Windows doesn't support font loading."); +#endif QString componentStr = "import QtQuick 2.0\nFontLoader { source: \"http://localhost:14448/tarzeau_ocr_a.ttf\" }"; QQmlComponent component(&engine); @@ -157,6 +166,9 @@ void tst_qquickfontloader::webFont() void tst_qquickfontloader::redirWebFont() { +#if defined(Q_OS_WIN) + QSKIP("Windows doesn't support font loading."); +#endif server.addRedirect("olddir/oldname.ttf","../tarzeau_ocr_a.ttf"); QString componentStr = "import QtQuick 2.0\nFontLoader { source: \"http://localhost:14448/olddir/oldname.ttf\" }"; @@ -173,6 +185,9 @@ void tst_qquickfontloader::redirWebFont() void tst_qquickfontloader::failWebFont() { +#if defined(Q_OS_WIN) + QSKIP("Windows doesn't support font loading."); +#endif QString componentStr = "import QtQuick 2.0\nFontLoader { source: \"http://localhost:14448/nonexist.ttf\" }"; QTest::ignoreMessage(QtWarningMsg, "file::2:1: QML FontLoader: Cannot load font: \"http://localhost:14448/nonexist.ttf\""); QQmlComponent component(&engine); @@ -187,6 +202,9 @@ void tst_qquickfontloader::failWebFont() void tst_qquickfontloader::changeFont() { +#if defined(Q_OS_WIN) + QSKIP("Windows doesn't support font loading."); +#endif QString componentStr = "import QtQuick 2.0\nFontLoader { source: font }"; QQmlContext *ctxt = engine.rootContext(); ctxt->setContextProperty("font", testFileUrl("tarzeau_ocr_a.ttf")); @@ -226,6 +244,9 @@ void tst_qquickfontloader::changeFont() void tst_qquickfontloader::changeFontSourceViaState() { +#if defined(Q_OS_WIN) + QSKIP("Windows doesn't support font loading."); +#endif QQuickView canvas(testFileUrl("qtbug-20268.qml")); canvas.show(); canvas.requestActivateWindow(); diff --git a/tests/auto/quick/qquickgridview/tst_qquickgridview.cpp b/tests/auto/quick/qquickgridview/tst_qquickgridview.cpp index 88ed94d8bc..c7b5ca6b40 100644 --- a/tests/auto/quick/qquickgridview/tst_qquickgridview.cpp +++ b/tests/auto/quick/qquickgridview/tst_qquickgridview.cpp @@ -3691,31 +3691,32 @@ void tst_QQuickGridView::margins() QQuickItem *contentItem = gridview->contentItem(); QTRY_VERIFY(contentItem != 0); - QCOMPARE(gridview->contentX(), -240+30.); - QCOMPARE(gridview->xOrigin(), 0.); + QTRY_COMPARE(gridview->contentX(), -240+50.); + QTRY_COMPARE(gridview->xOrigin(), 0.); // check end bound gridview->positionViewAtEnd(); qreal pos = gridview->contentX(); gridview->setContentX(pos - 80); gridview->returnToBounds(); - QTRY_COMPARE(gridview->contentX(), pos - 50); + QTRY_COMPARE(gridview->contentX(), pos - 30); // remove item before visible and check that left margin is maintained // and xOrigin is updated gridview->setContentX(-400); + QTRY_COMPARE(QQuickItemPrivate::get(gridview)->polishScheduled, false); model.removeItems(0, 4); - QTest::qWait(100); + QTRY_COMPARE(model.count(), gridview->count()); gridview->setContentX(-240+50); gridview->returnToBounds(); QCOMPARE(gridview->xOrigin(), -100.); - QTRY_COMPARE(gridview->contentX(), -240-70.); + QTRY_COMPARE(gridview->contentX(), -240-50.); - // reduce left margin (i.e. right side due to RTL) + // reduce right margin pos = gridview->contentX(); - gridview->setLeftMargin(20); + gridview->setRightMargin(40); QCOMPARE(gridview->xOrigin(), -100.); - QTRY_COMPARE(gridview->contentX(), -240-80.); + QTRY_COMPARE(gridview->contentX(), -240-100 + 40.); // check end bound gridview->positionViewAtEnd(); @@ -3723,11 +3724,11 @@ void tst_QQuickGridView::margins() pos = gridview->contentX(); gridview->setContentX(pos - 80); gridview->returnToBounds(); - QTRY_COMPARE(gridview->contentX(), pos - 50); + QTRY_COMPARE(gridview->contentX(), pos - 30); - // reduce right margin (i.e. left side due to RTL) + // reduce left margin pos = gridview->contentX(); - gridview->setRightMargin(40); + gridview->setLeftMargin(20); QCOMPARE(gridview->xOrigin(), 0.); QTRY_COMPARE(gridview->contentX(), pos+10); diff --git a/tests/auto/quick/qquickitem/tst_qquickitem.cpp b/tests/auto/quick/qquickitem/tst_qquickitem.cpp index 9fdfa78559..abd0da8ac1 100644 --- a/tests/auto/quick/qquickitem/tst_qquickitem.cpp +++ b/tests/auto/quick/qquickitem/tst_qquickitem.cpp @@ -181,7 +181,7 @@ void tst_qquickitem::initTestCase() qmlRegisterType<TestPolishItem>("Qt.test", 1, 0, "TestPolishItem"); } -// Focus has no effect when outside a canvas +// Focus still updates when outside a canvas void tst_qquickitem::noCanvas() { QQuickItem *root = new TestItem; @@ -201,7 +201,7 @@ void tst_qquickitem::noCanvas() scopedChild2->setFocus(true); QCOMPARE(root->hasFocus(), true); QCOMPARE(child->hasFocus(), false); - QCOMPARE(scope->hasFocus(), true); + QCOMPARE(scope->hasFocus(), false); QCOMPARE(scopedChild->hasFocus(), false); QCOMPARE(scopedChild2->hasFocus(), true); @@ -210,10 +210,10 @@ void tst_qquickitem::noCanvas() scopedChild->setFocus(true); scope->setFocus(false); QCOMPARE(root->hasFocus(), false); - QCOMPARE(child->hasFocus(), true); + QCOMPARE(child->hasFocus(), false); QCOMPARE(scope->hasFocus(), false); QCOMPARE(scopedChild->hasFocus(), true); - QCOMPARE(scopedChild2->hasFocus(), true); + QCOMPARE(scopedChild2->hasFocus(), false); delete root; } @@ -434,7 +434,7 @@ void tst_qquickitem::addedToCanvas() c1->setFocus(true); c2->setFocus(true); focusState[item].set(true, true); - focusState[c1].set(true, false); + focusState[c1].set(false, false); focusState[c2].set(true, false); focusState.active(item); FVERIFY(); @@ -458,14 +458,14 @@ void tst_qquickitem::addedToCanvas() focusState << tree << c1 << c2; c1->setFocus(true); c2->setFocus(true); - focusState[c1].set(true, false); + focusState[c1].set(false, false); focusState[c2].set(true, false); FVERIFY(); tree->setParentItem(canvas.rootItem()); - focusState[c1].set(true, true); - focusState[c2].set(false, false); - focusState.active(c1); + focusState[c1].set(false, false); + focusState[c2].set(true, true); + focusState.active(c2); FVERIFY(); } @@ -481,19 +481,19 @@ void tst_qquickitem::addedToCanvas() focusState << tree << c1 << c2; c1->setFocus(true); c2->setFocus(true); - focusState[c1].set(true, false); + focusState[c1].set(false, false); focusState[c2].set(true, false); FVERIFY(); tree->setParentItem(canvas.rootItem()); - focusState[c1].set(true, false); - focusState[c2].set(false, false); + focusState[c1].set(false, false); + focusState[c2].set(true, false); FVERIFY(); tree->setFocus(true); focusState[tree].set(true, true); - focusState[c1].set(true, true); - focusState.active(c1); + focusState[c2].set(true, true); + focusState.active(c2); FVERIFY(); } @@ -511,15 +511,15 @@ void tst_qquickitem::addedToCanvas() c1->setFocus(true); c2->setFocus(true); focusState[tree].set(true, false); - focusState[c1].set(true, false); + focusState[c1].set(false, false); focusState[c2].set(true, false); FVERIFY(); tree->setParentItem(canvas.rootItem()); focusState[tree].set(true, true); - focusState[c1].set(true, true); - focusState[c2].set(false, false); - focusState.active(c1); + focusState[c1].set(false, false); + focusState[c2].set(true, true); + focusState.active(c2); FVERIFY(); } @@ -540,22 +540,22 @@ void tst_qquickitem::addedToCanvas() c2->setFocus(true); focusState[child].set(true, true); focusState[tree].set(true, false); - focusState[c1].set(true, false); + focusState[c1].set(false, false); focusState[c2].set(true, false); focusState.active(child); FVERIFY(); tree->setParentItem(canvas.rootItem()); focusState[tree].set(false, false); - focusState[c1].set(true, false); - focusState[c2].set(false, false); + focusState[c1].set(false, false); + focusState[c2].set(true, false); FVERIFY(); tree->setFocus(true); focusState[child].set(false, false); focusState[tree].set(true, true); - focusState[c1].set(true, true); - focusState.active(c1); + focusState[c2].set(true, true); + focusState.active(c2); FVERIFY(); } } @@ -674,6 +674,40 @@ void tst_qquickitem::changeParent() FVERIFY(); } + // child has active focus, then its fs parent changes parent to 0, then + // child is deleted, then its parent changes again to a valid parent + { + QQuickCanvas canvas; + ensureFocus(&canvas); + QTRY_VERIFY(QGuiApplication::focusWindow() == &canvas); + QQuickItem *item = new TestFocusScope(canvas.rootItem()); + QQuickItem *child = new TestItem(item); + QQuickItem *child2 = new TestItem; + + FocusState focusState; + focusState << item << child; + FVERIFY(); + + item->setFocus(true); + child->setFocus(true); + focusState[child].set(true, true); + focusState[item].set(true, true); + focusState.active(child); + FVERIFY(); + + item->setParentItem(0); + focusState[child].set(true, false); + focusState[item].set(true, false); + focusState.active(0); + FVERIFY(); + + focusState.remove(child); + delete child; + item->setParentItem(canvas.rootItem()); + focusState[item].set(true, true); + focusState.active(item); + FVERIFY(); + } } void tst_qquickitem::multipleFocusClears() diff --git a/tests/auto/quick/qquickitemlayer/data/Effect.qml b/tests/auto/quick/qquickitemlayer/data/Effect.qml index 630c8f90ed..678f86538d 100644 --- a/tests/auto/quick/qquickitemlayer/data/Effect.qml +++ b/tests/auto/quick/qquickitemlayer/data/Effect.qml @@ -2,19 +2,19 @@ import QtQuick 2.0 Item { - width: 100 + width: 200 height: 100 Rectangle { id: box - width: 100 + width: 200 height: 100 color: "#0000ff" Rectangle { - x: 50 - width: 50 + x: 100 + width: 100 height: 100 color: "#00ff00" } diff --git a/tests/auto/quick/qquickitemlayer/data/SourceRect.qml b/tests/auto/quick/qquickitemlayer/data/SourceRect.qml index 7cc7e8b21e..a161760028 100644 --- a/tests/auto/quick/qquickitemlayer/data/SourceRect.qml +++ b/tests/auto/quick/qquickitemlayer/data/SourceRect.qml @@ -2,12 +2,12 @@ import QtQuick 2.0 Item { - width: 100 + width: 200 height: 100 Rectangle { id: box - width: 100 + width: 200 height: 100 color: "#ff0000" diff --git a/tests/auto/quick/qquickitemlayer/data/TextureProvider.qml b/tests/auto/quick/qquickitemlayer/data/TextureProvider.qml index ccd515652a..427bd41310 100644 --- a/tests/auto/quick/qquickitemlayer/data/TextureProvider.qml +++ b/tests/auto/quick/qquickitemlayer/data/TextureProvider.qml @@ -2,19 +2,19 @@ import QtQuick 2.0 Item { - width: 100 + width: 200 height: 100 Rectangle { id: box - width: 100 + width: 200 height: 100 color: "#0000ff" Rectangle { - x: 50 - width: 50 + x: 100 + width: 100 height: 100 color: "#00ff00" } diff --git a/tests/auto/quick/qquicklistview/data/margins2.qml b/tests/auto/quick/qquicklistview/data/margins2.qml index e11c803c4b..4b1f2546bf 100644 --- a/tests/auto/quick/qquicklistview/data/margins2.qml +++ b/tests/auto/quick/qquicklistview/data/margins2.qml @@ -9,9 +9,9 @@ Item { } ListView { objectName: "listview" - topMargin: 20 + topMargin: 40 bottomMargin: 20 - leftMargin: 20 + leftMargin: 40 rightMargin: 20 anchors.fill: parent diff --git a/tests/auto/quick/qquicklistview/tst_qquicklistview.cpp b/tests/auto/quick/qquicklistview/tst_qquicklistview.cpp index 202f5164af..461a6b6750 100644 --- a/tests/auto/quick/qquicklistview/tst_qquicklistview.cpp +++ b/tests/auto/quick/qquicklistview/tst_qquicklistview.cpp @@ -4290,6 +4290,13 @@ void tst_QQuickListView::marginsResize() QFETCH(qreal, start); QFETCH(qreal, end); + QPoint flickStart(20, 20); + QPoint flickEnd(20, 20); + if (orientation == QQuickListView::Vertical) + flickStart.ry() += 180; + else + flickStart.rx() += (layoutDirection == Qt::LeftToRight) ? 180 : -180; + QQuickView *canvas = getView(); canvas->setSource(testFileUrl("margins2.qml")); @@ -4316,6 +4323,14 @@ void tst_QQuickListView::marginsResize() else QTRY_COMPARE(listview->contentX(), end); + // flick past the end and check content pos still settles on correct extents + flick(canvas, flickStart, flickEnd, 180); + QTRY_VERIFY(listview->isMoving() == false); + if (orientation == QQuickListView::Vertical) + QTRY_COMPARE(listview->contentY(), end); + else + QTRY_COMPARE(listview->contentX(), end); + // back to top - top margin should be visible. listview->setCurrentIndex(0); if (orientation == QQuickListView::Vertical) @@ -4323,6 +4338,14 @@ void tst_QQuickListView::marginsResize() else QTRY_COMPARE(listview->contentX(), start); + // flick past the beginning and check content pos still settles on correct extents + flick(canvas, flickEnd, flickStart, 180); + QTRY_VERIFY(listview->isMoving() == false); + if (orientation == QQuickListView::Vertical) + QTRY_COMPARE(listview->contentY(), start); + else + QTRY_COMPARE(listview->contentX(), start); + releaseView(canvas); } @@ -4333,9 +4356,11 @@ void tst_QQuickListView::marginsResize_data() QTest::addColumn<qreal>("start"); QTest::addColumn<qreal>("end"); - QTest::newRow("vertical") << QQuickListView::Vertical << Qt::LeftToRight << -20.0 << 1020.0; - QTest::newRow("horizontal") << QQuickListView::Horizontal << Qt::LeftToRight << -20.0 << 1020.0; - QTest::newRow("horizontal, rtl") << QQuickListView::Horizontal << Qt::RightToLeft << -180.0 << -1220.0; + // in Right to Left mode, leftMargin still means leftMargin - it doesn't reverse to mean rightMargin + + QTest::newRow("vertical") << QQuickListView::Vertical << Qt::LeftToRight << -40.0 << 1020.0; + QTest::newRow("horizontal") << QQuickListView::Horizontal << Qt::LeftToRight << -40.0 << 1020.0; + QTest::newRow("horizontal, rtl") << QQuickListView::Horizontal << Qt::RightToLeft << -180.0 << -1240.0; } void tst_QQuickListView::snapToItem_data() diff --git a/tests/auto/quick/qquickloader/tst_qquickloader.cpp b/tests/auto/quick/qquickloader/tst_qquickloader.cpp index bdf47fa9e9..01781f7b54 100644 --- a/tests/auto/quick/qquickloader/tst_qquickloader.cpp +++ b/tests/auto/quick/qquickloader/tst_qquickloader.cpp @@ -929,7 +929,7 @@ void tst_QQuickLoader::asynchronous_clear() QVERIFY(!loader->item()); QCOMPARE(loader->status(), QQuickLoader::Loading); - QCOMPARE(engine.incubationController()->incubatingObjectCount(), 1); + QTRY_COMPARE(engine.incubationController()->incubatingObjectCount(), 1); // clear before component created root->setProperty("comp", ""); @@ -942,7 +942,7 @@ void tst_QQuickLoader::asynchronous_clear() QCOMPARE(static_cast<QQuickItem*>(loader)->childItems().count(), 0); // check loading component - root->setProperty("comp", "Rect120x60.qml"); + root->setProperty("comp", "BigComponent.qml"); QMetaObject::invokeMethod(root, "loadComponent"); QVERIFY(!loader->item()); @@ -953,6 +953,8 @@ void tst_QQuickLoader::asynchronous_clear() QCOMPARE(loader->progress(), 1.0); QCOMPARE(loader->status(), QQuickLoader::Ready); QCOMPARE(static_cast<QQuickItem*>(loader)->childItems().count(), 1); + + delete root; } void tst_QQuickLoader::simultaneousSyncAsync() diff --git a/tests/auto/quick/qquickpathview/data/dragpath.qml b/tests/auto/quick/qquickpathview/data/dragpath.qml index f9c6615b04..6ba778bb80 100644 --- a/tests/auto/quick/qquickpathview/data/dragpath.qml +++ b/tests/auto/quick/qquickpathview/data/dragpath.qml @@ -14,6 +14,7 @@ PathView { preferredHighlightBegin: 0.5 preferredHighlightEnd: 0.5 Text { + objectName: "text" text: "current index: " + parent.currentIndex } } diff --git a/tests/auto/quick/qquickpathview/tst_qquickpathview.cpp b/tests/auto/quick/qquickpathview/tst_qquickpathview.cpp index 8866cafd80..613156b2f5 100644 --- a/tests/auto/quick/qquickpathview/tst_qquickpathview.cpp +++ b/tests/auto/quick/qquickpathview/tst_qquickpathview.cpp @@ -123,6 +123,7 @@ private slots: void creationContext(); void currentOffsetOnInsertion(); void asynchronous(); + void cancelDrag(); }; class TestObject : public QObject @@ -1453,6 +1454,41 @@ void tst_QQuickPathView::missingPercent() delete obj; } +void tst_QQuickPathView::cancelDrag() +{ + QQuickView *canvas = createView(); + canvas->setSource(testFileUrl("dragpath.qml")); + canvas->show(); + canvas->requestActivateWindow(); + QTest::qWaitForWindowShown(canvas); + QTRY_COMPARE(canvas, qGuiApp->focusWindow()); + + QQuickPathView *pathview = qobject_cast<QQuickPathView*>(canvas->rootObject()); + QVERIFY(pathview != 0); + + // drag between snap points + QTest::mousePress(canvas, Qt::LeftButton, 0, QPoint(10,100)); + QTest::qWait(100); + QTest::mouseMove(canvas, QPoint(30, 100)); + QTest::mouseMove(canvas, QPoint(85, 100)); + + QTRY_VERIFY(pathview->offset() != qFloor(pathview->offset())); + QTRY_VERIFY(pathview->isMoving()); + + // steal mouse grab - cancels PathView dragging + QQuickItem *item = canvas->rootObject()->findChild<QQuickItem*>("text"); + item->grabMouse(); + + // returns to a snap point. + QTRY_VERIFY(pathview->offset() == qFloor(pathview->offset())); + QTRY_VERIFY(!pathview->isMoving()); + + QTest::mouseRelease(canvas, Qt::LeftButton, 0, QPoint(40,100)); + + delete canvas; +} + + QTEST_MAIN(tst_QQuickPathView) #include "tst_qquickpathview.moc" diff --git a/tests/auto/quick/qquicktext/tst_qquicktext.cpp b/tests/auto/quick/qquicktext/tst_qquicktext.cpp index 77f0ec190d..affb355837 100644 --- a/tests/auto/quick/qquicktext/tst_qquicktext.cpp +++ b/tests/auto/quick/qquicktext/tst_qquicktext.cpp @@ -107,6 +107,8 @@ private slots: void implicitSize_data(); void implicitSize(); void contentSize(); + void implicitSizeBinding_data(); + void implicitSizeBinding(); void lineLaidOut(); @@ -1069,11 +1071,11 @@ void tst_qquicktext::smooth() for (int i = 0; i < standard.size(); i++) { { - QString componentStr = "import QtQuick 2.0\nText { smooth: true; text: \"" + standard.at(i) + "\" }"; + QString componentStr = "import QtQuick 2.0\nText { smooth: false; text: \"" + standard.at(i) + "\" }"; QQmlComponent textComponent(&engine); textComponent.setData(componentStr.toLatin1(), QUrl::fromLocalFile("")); QQuickText *textObject = qobject_cast<QQuickText*>(textComponent.create()); - QCOMPARE(textObject->smooth(), true); + QCOMPARE(textObject->smooth(), false); delete textObject; } @@ -1082,7 +1084,7 @@ void tst_qquicktext::smooth() QQmlComponent textComponent(&engine); textComponent.setData(componentStr.toLatin1(), QUrl::fromLocalFile("")); QQuickText *textObject = qobject_cast<QQuickText*>(textComponent.create()); - QCOMPARE(textObject->smooth(), false); + QCOMPARE(textObject->smooth(), true); delete textObject; } @@ -1090,11 +1092,11 @@ void tst_qquicktext::smooth() for (int i = 0; i < richText.size(); i++) { { - QString componentStr = "import QtQuick 2.0\nText { smooth: true; text: \"" + richText.at(i) + "\" }"; + QString componentStr = "import QtQuick 2.0\nText { smooth: false; text: \"" + richText.at(i) + "\" }"; QQmlComponent textComponent(&engine); textComponent.setData(componentStr.toLatin1(), QUrl::fromLocalFile("")); QQuickText *textObject = qobject_cast<QQuickText*>(textComponent.create()); - QCOMPARE(textObject->smooth(), true); + QCOMPARE(textObject->smooth(), false); delete textObject; } @@ -1103,7 +1105,7 @@ void tst_qquicktext::smooth() QQmlComponent textComponent(&engine); textComponent.setData(componentStr.toLatin1(), QUrl::fromLocalFile("")); QQuickText *textObject = qobject_cast<QQuickText*>(textComponent.create()); - QCOMPARE(textObject->smooth(), false); + QCOMPARE(textObject->smooth(), true); delete textObject; } @@ -1548,29 +1550,36 @@ void tst_qquicktext::implicitSize_data() QTest::addColumn<QString>("width"); QTest::addColumn<QString>("wrap"); QTest::addColumn<QString>("elide"); - QTest::newRow("plain") << "The quick red fox jumped over the lazy brown dog" << "50" << "Text.NoWrap" << "Text.ElideNone"; - QTest::newRow("richtext") << "<b>The quick red fox jumped over the lazy brown dog</b>" <<" 50" << "Text.NoWrap" << "Text.ElideNone"; - QTest::newRow("plain, 0 width") << "The quick red fox jumped over the lazy brown dog" << "0" << "Text.NoWrap" << "Text.ElideNone"; - QTest::newRow("plain, elide") << "The quick red fox jumped over the lazy brown dog" << "50" << "Text.NoWrap" << "Text.ElideRight"; - QTest::newRow("plain, 0 width, elide") << "The quick red fox jumped over the lazy brown dog" << "0" << "Text.NoWrap" << "Text.ElideRight"; - QTest::newRow("richtext, 0 width") << "<b>The quick red fox jumped over the lazy brown dog</b>" <<" 0" << "Text.NoWrap" << "Text.ElideNone"; - QTest::newRow("plain_wrap") << "The quick red fox jumped over the lazy brown dog" << "50" << "Text.Wrap" << "Text.ElideNone"; - QTest::newRow("richtext_wrap") << "<b>The quick red fox jumped over the lazy brown dog</b>" << "50" << "Text.Wrap" << "Text.ElideNone"; - QTest::newRow("plain_wrap, 0 width") << "The quick red fox jumped over the lazy brown dog" << "0" << "Text.Wrap" << "Text.ElideNone"; - QTest::newRow("plain_wrap, elide") << "The quick red fox jumped over the lazy brown dog" << "50" << "Text.Wrap" << "Text.ElideRight"; - QTest::newRow("plain_wrap, 0 width, elide") << "The quick red fox jumped over the lazy brown dog" << "0" << "Text.Wrap" << "Text.ElideRight"; - QTest::newRow("richtext_wrap, 0 width") << "<b>The quick red fox jumped over the lazy brown dog</b>" << "0" << "Text.Wrap" << "Text.ElideNone"; + QTest::addColumn<QString>("format"); + QTest::newRow("plain") << "The quick red fox jumped over the lazy brown dog" << "50" << "Text.NoWrap" << "Text.ElideNone" << "Text.PlainText"; + QTest::newRow("richtext") << "<b>The quick red fox jumped over the lazy brown dog</b>" <<" 50" << "Text.NoWrap" << "Text.ElideNone" << "Text.RichText"; + QTest::newRow("styledtext") << "<b>The quick red fox jumped over the lazy brown dog</b>" <<" 50" << "Text.NoWrap" << "Text.ElideNone" << "Text.StyledText"; + QTest::newRow("plain, 0 width") << "The quick red fox jumped over the lazy brown dog" << "0" << "Text.NoWrap" << "Text.ElideNone" << "Text.PlainText"; + QTest::newRow("plain, elide") << "The quick red fox jumped over the lazy brown dog" << "50" << "Text.NoWrap" << "Text.ElideRight" << "Text.PlainText"; + QTest::newRow("plain, 0 width, elide") << "The quick red fox jumped over the lazy brown dog" << "0" << "Text.NoWrap" << "Text.ElideRight" << "Text.PlainText"; + QTest::newRow("richtext, 0 width") << "<b>The quick red fox jumped over the lazy brown dog</b>" <<" 0" << "Text.NoWrap" << "Text.ElideNone" << "Text.RichText"; + QTest::newRow("styledtext, 0 width") << "<b>The quick red fox jumped over the lazy brown dog</b>" <<" 0" << "Text.NoWrap" << "Text.ElideNone" << "Text.StyledText"; + QTest::newRow("plain_wrap") << "The quick red fox jumped over the lazy brown dog" << "50" << "Text.Wrap" << "Text.ElideNone" << "Text.PlainText"; + QTest::newRow("richtext_wrap") << "<b>The quick red fox jumped over the lazy brown dog</b>" << "50" << "Text.Wrap" << "Text.ElideNone" << "Text.RichText"; + QTest::newRow("styledtext_wrap") << "<b>The quick red fox jumped over the lazy brown dog</b>" << "50" << "Text.Wrap" << "Text.ElideNone" << "Text.StyledText"; + QTest::newRow("plain_wrap, 0 width") << "The quick red fox jumped over the lazy brown dog" << "0" << "Text.Wrap" << "Text.ElideNone" << "Text.PlainText"; + QTest::newRow("plain_wrap, elide") << "The quick red fox jumped over the lazy brown dog" << "50" << "Text.Wrap" << "Text.ElideRight" << "Text.PlainText"; + QTest::newRow("plain_wrap, 0 width, elide") << "The quick red fox jumped over the lazy brown dog" << "0" << "Text.Wrap" << "Text.ElideRight" << "Text.PlainText"; + QTest::newRow("richtext_wrap, 0 width") << "<b>The quick red fox jumped over the lazy brown dog</b>" << "0" << "Text.Wrap" << "Text.ElideNone" << "Text.RichText"; + QTest::newRow("styledtext_wrap, 0 width") << "<b>The quick red fox jumped over the lazy brown dog</b>" << "0" << "Text.Wrap" << "Text.ElideNone" << "Text.StyledText"; } void tst_qquicktext::implicitSize() { QFETCH(QString, text); QFETCH(QString, width); + QFETCH(QString, format); QFETCH(QString, wrap); QFETCH(QString, elide); QString componentStr = "import QtQuick 2.0\nText { " "text: \"" + text + "\"; " "width: " + width + "; " + "textFormat: " + format + "; " "wrapMode: " + wrap + "; " "elide: " + elide + "; " "maximumLineCount: 1 }"; @@ -1631,6 +1640,35 @@ void tst_qquicktext::contentSize() QCOMPARE(spy.count(), ++spyCount); } +void tst_qquicktext::implicitSizeBinding_data() +{ + implicitSize_data(); +} + +void tst_qquicktext::implicitSizeBinding() +{ + QFETCH(QString, text); + QFETCH(QString, wrap); + QFETCH(QString, format); + QString componentStr = "import QtQuick 2.0\nText { text: \"" + text + "\"; width: implicitWidth; height: implicitHeight; wrapMode: " + wrap + "; textFormat: " + format + " }"; + + QDeclarativeComponent textComponent(&engine); + textComponent.setData(componentStr.toLatin1(), QUrl::fromLocalFile("")); + QScopedPointer<QObject> object(textComponent.create()); + QQuickText *textObject = qobject_cast<QQuickText *>(object.data()); + + QCOMPARE(textObject->width(), textObject->implicitWidth()); + QCOMPARE(textObject->height(), textObject->implicitHeight()); + + textObject->resetWidth(); + QCOMPARE(textObject->width(), textObject->implicitWidth()); + QCOMPARE(textObject->height(), textObject->implicitHeight()); + + textObject->resetHeight(); + QCOMPARE(textObject->width(), textObject->implicitWidth()); + QCOMPARE(textObject->height(), textObject->implicitHeight()); +} + void tst_qquicktext::lineLaidOut() { QQuickView *canvas = createView(testFile("lineLayout.qml")); diff --git a/tests/auto/quick/qquicktextedit/data/mouseselection_true.qml b/tests/auto/quick/qquicktextedit/data/mouseselection_true.qml index 7c7cb0b6fc..b7a15962f4 100644 --- a/tests/auto/quick/qquicktextedit/data/mouseselection_true.qml +++ b/tests/auto/quick/qquicktextedit/data/mouseselection_true.qml @@ -2,6 +2,6 @@ import QtQuick 2.0 TextEdit { focus: true - text: "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ" + text: "0123456789 ABCDEFGHIJKLMNOPQRSTUVWXYZ" selectByMouse: true } diff --git a/tests/auto/quick/qquicktextedit/tst_qquicktextedit.cpp b/tests/auto/quick/qquicktextedit/tst_qquicktextedit.cpp index a90b23dfd7..83e7e78866 100644 --- a/tests/auto/quick/qquicktextedit/tst_qquicktextedit.cpp +++ b/tests/auto/quick/qquicktextedit/tst_qquicktextedit.cpp @@ -69,6 +69,7 @@ Q_DECLARE_METATYPE(QQuickTextEdit::SelectionMode) +Q_DECLARE_METATYPE(Qt::Key) DEFINE_BOOL_CONFIG_OPTION(qmlDisableDistanceField, QML_DISABLE_DISTANCEFIELD) QString createExpectedFileIfNotFound(const QString& filebasename, const QImage& actual) @@ -151,6 +152,8 @@ private slots: void implicitSize_data(); void implicitSize(); void contentSize(); + void implicitSizeBinding_data(); + void implicitSizeBinding(); void preeditCursorRectangle(); void inputMethodComposing(); @@ -185,7 +188,7 @@ private: void simulateKeys(QWindow *window, const QList<Key> &keys); void simulateKeys(QWindow *window, const QKeySequence &sequence); - void simulateKey(QQuickView *, int key, Qt::KeyboardModifiers modifiers = 0); + void simulateKey(QWindow *, int key, Qt::KeyboardModifiers modifiers = 0); QStringList standard; QStringList richText; @@ -1012,23 +1015,88 @@ void tst_qquicktextedit::persistentSelection() void tst_qquicktextedit::focusOnPress() { - { - QString componentStr = "import QtQuick 2.0\nTextEdit { activeFocusOnPress: true; text: \"Hello World\" }"; - QQmlComponent texteditComponent(&engine); - texteditComponent.setData(componentStr.toLatin1(), QUrl()); - QQuickTextEdit *textEditObject = qobject_cast<QQuickTextEdit*>(texteditComponent.create()); - QVERIFY(textEditObject != 0); - QCOMPARE(textEditObject->focusOnPress(), true); - } + QString componentStr = + "import QtQuick 2.0\n" + "TextEdit {\n" + "property bool selectOnFocus: false\n" + "width: 100; height: 50\n" + "activeFocusOnPress: true\n" + "text: \"Hello World\"\n" + "onFocusChanged: { if (focus && selectOnFocus) selectAll() }" + " }"; + QQmlComponent texteditComponent(&engine); + texteditComponent.setData(componentStr.toLatin1(), QUrl()); + QQuickTextEdit *textEditObject = qobject_cast<QQuickTextEdit*>(texteditComponent.create()); + QVERIFY(textEditObject != 0); + QCOMPARE(textEditObject->focusOnPress(), true); + QCOMPARE(textEditObject->hasFocus(), false); - { - QString componentStr = "import QtQuick 2.0\nTextEdit { activeFocusOnPress: false; text: \"Hello World\" }"; - QQmlComponent texteditComponent(&engine); - texteditComponent.setData(componentStr.toLatin1(), QUrl()); - QQuickTextEdit *textEditObject = qobject_cast<QQuickTextEdit*>(texteditComponent.create()); - QVERIFY(textEditObject != 0); - QCOMPARE(textEditObject->focusOnPress(), false); - } + QSignalSpy focusSpy(textEditObject, SIGNAL(focusChanged(bool))); + QSignalSpy activeFocusSpy(textEditObject, SIGNAL(focusChanged(bool))); + QSignalSpy activeFocusOnPressSpy(textEditObject, SIGNAL(activeFocusOnPressChanged(bool))); + + textEditObject->setFocusOnPress(true); + QCOMPARE(textEditObject->focusOnPress(), true); + QCOMPARE(activeFocusOnPressSpy.count(), 0); + + QQuickCanvas canvas; + canvas.resize(100, 50); + textEditObject->setParentItem(canvas.rootItem()); + canvas.show(); + canvas.requestActivateWindow(); + QTest::qWaitForWindowShown(&canvas); + QTRY_COMPARE(QGuiApplication::activeWindow(), &canvas); + + QCOMPARE(textEditObject->hasFocus(), false); + QCOMPARE(textEditObject->hasActiveFocus(), false); + + QPoint centerPoint(canvas.width()/2, canvas.height()/2); + Qt::KeyboardModifiers noModifiers = 0; + QTest::mousePress(&canvas, Qt::LeftButton, noModifiers, centerPoint); + QGuiApplication::processEvents(); + QCOMPARE(textEditObject->hasFocus(), true); + QCOMPARE(textEditObject->hasActiveFocus(), true); + QCOMPARE(focusSpy.count(), 1); + QCOMPARE(activeFocusSpy.count(), 1); + QCOMPARE(textEditObject->selectedText(), QString()); + QTest::mouseRelease(&canvas, Qt::LeftButton, noModifiers, centerPoint); + + textEditObject->setFocusOnPress(false); + QCOMPARE(textEditObject->focusOnPress(), false); + QCOMPARE(activeFocusOnPressSpy.count(), 1); + + textEditObject->setFocus(false); + QCOMPARE(textEditObject->hasFocus(), false); + QCOMPARE(textEditObject->hasActiveFocus(), false); + QCOMPARE(focusSpy.count(), 2); + QCOMPARE(activeFocusSpy.count(), 2); + + // Wait for double click timeout to expire before clicking again. + QTest::qWait(400); + QTest::mousePress(&canvas, Qt::LeftButton, noModifiers, centerPoint); + QGuiApplication::processEvents(); + QCOMPARE(textEditObject->hasFocus(), false); + QCOMPARE(textEditObject->hasActiveFocus(), false); + QCOMPARE(focusSpy.count(), 2); + QCOMPARE(activeFocusSpy.count(), 2); + QTest::mouseRelease(&canvas, Qt::LeftButton, noModifiers, centerPoint); + + textEditObject->setFocusOnPress(true); + QCOMPARE(textEditObject->focusOnPress(), true); + QCOMPARE(activeFocusOnPressSpy.count(), 2); + + // Test a selection made in the on(Active)FocusChanged handler isn't overwritten. + textEditObject->setProperty("selectOnFocus", true); + + QTest::qWait(400); + QTest::mousePress(&canvas, Qt::LeftButton, noModifiers, centerPoint); + QGuiApplication::processEvents(); + QCOMPARE(textEditObject->hasFocus(), true); + QCOMPARE(textEditObject->hasActiveFocus(), true); + QCOMPARE(focusSpy.count(), 3); + QCOMPARE(activeFocusSpy.count(), 3); + QCOMPARE(textEditObject->selectedText(), textEditObject->text()); + QTest::mouseRelease(&canvas, Qt::LeftButton, noModifiers, centerPoint); } void tst_qquicktextedit::selection() @@ -1562,21 +1630,41 @@ void tst_qquicktextedit::mouseSelection_data() QTest::addColumn<int>("from"); QTest::addColumn<int>("to"); QTest::addColumn<QString>("selectedText"); + QTest::addColumn<bool>("focus"); + QTest::addColumn<bool>("focusOnPress"); + QTest::addColumn<bool>("doubleClick"); // import installed - QTest::newRow("on") << testFile("mouseselection_true.qml") << 4 << 9 << "45678"; - QTest::newRow("off") << testFile("mouseselection_false.qml") << 4 << 9 << QString(); - QTest::newRow("default") << testFile("mouseselection_default.qml") << 4 << 9 << QString(); - QTest::newRow("off word selection") << testFile("mouseselection_false_words.qml") << 4 << 9 << QString(); - QTest::newRow("on word selection (4,9)") << testFile("mouseselection_true_words.qml") << 4 << 9 << "0123456789"; - QTest::newRow("on word selection (2,13)") << testFile("mouseselection_true_words.qml") << 2 << 13 << "0123456789 ABCDEFGHIJKLMNOPQRSTUVWXYZ"; - QTest::newRow("on word selection (2,30)") << testFile("mouseselection_true_words.qml") << 2 << 30 << "0123456789 ABCDEFGHIJKLMNOPQRSTUVWXYZ"; - QTest::newRow("on word selection (9,13)") << testFile("mouseselection_true_words.qml") << 9 << 13 << "0123456789 ABCDEFGHIJKLMNOPQRSTUVWXYZ"; - QTest::newRow("on word selection (9,30)") << testFile("mouseselection_true_words.qml") << 9 << 30 << "0123456789 ABCDEFGHIJKLMNOPQRSTUVWXYZ"; - QTest::newRow("on word selection (13,2)") << testFile("mouseselection_true_words.qml") << 13 << 2 << "0123456789 ABCDEFGHIJKLMNOPQRSTUVWXYZ"; - QTest::newRow("on word selection (20,2)") << testFile("mouseselection_true_words.qml") << 20 << 2 << "0123456789 ABCDEFGHIJKLMNOPQRSTUVWXYZ"; - QTest::newRow("on word selection (12,9)") << testFile("mouseselection_true_words.qml") << 12 << 9 << "0123456789 ABCDEFGHIJKLMNOPQRSTUVWXYZ"; - QTest::newRow("on word selection (30,9)") << testFile("mouseselection_true_words.qml") << 30 << 9 << "0123456789 ABCDEFGHIJKLMNOPQRSTUVWXYZ"; + QTest::newRow("on") << testFile("mouseselection_true.qml") << 4 << 9 << "45678" << true << true << false; + QTest::newRow("off") << testFile("mouseselection_false.qml") << 4 << 9 << QString() << true << true << false; + QTest::newRow("default") << testFile("mouseselection_default.qml") << 4 << 9 << QString() << true << true << false; + QTest::newRow("off word selection") << testFile("mouseselection_false_words.qml") << 4 << 9 << QString() << true << true << false; + QTest::newRow("on word selection (4,9)") << testFile("mouseselection_true_words.qml") << 4 << 9 << "0123456789" << true << true << false; + + QTest::newRow("on unfocused") << testFile("mouseselection_true.qml") << 4 << 9 << "45678" << false << false << false; + QTest::newRow("on word selection (4,9) unfocused") << testFile("mouseselection_true_words.qml") << 4 << 9 << "0123456789" << false << false << false; + + QTest::newRow("on focus on press") << testFile("mouseselection_true.qml") << 4 << 9 << "45678" << false << true << false; + QTest::newRow("on word selection (4,9) focus on press") << testFile("mouseselection_true_words.qml") << 4 << 9 << "0123456789" << false << true << false; + + QTest::newRow("on word selection (2,13)") << testFile("mouseselection_true_words.qml") << 2 << 13 << "0123456789 ABCDEFGHIJKLMNOPQRSTUVWXYZ" << true << true << false; + QTest::newRow("on word selection (2,30)") << testFile("mouseselection_true_words.qml") << 2 << 30 << "0123456789 ABCDEFGHIJKLMNOPQRSTUVWXYZ" << true << true << false; + QTest::newRow("on word selection (9,13)") << testFile("mouseselection_true_words.qml") << 9 << 13 << "0123456789 ABCDEFGHIJKLMNOPQRSTUVWXYZ" << true << true << false; + QTest::newRow("on word selection (9,30)") << testFile("mouseselection_true_words.qml") << 9 << 30 << "0123456789 ABCDEFGHIJKLMNOPQRSTUVWXYZ" << true << true << false; + QTest::newRow("on word selection (13,2)") << testFile("mouseselection_true_words.qml") << 13 << 2 << "0123456789 ABCDEFGHIJKLMNOPQRSTUVWXYZ" << true << true << false; + QTest::newRow("on word selection (20,2)") << testFile("mouseselection_true_words.qml") << 20 << 2 << "0123456789 ABCDEFGHIJKLMNOPQRSTUVWXYZ" << true << true << false; + QTest::newRow("on word selection (12,9)") << testFile("mouseselection_true_words.qml") << 12 << 9 << "0123456789 ABCDEFGHIJKLMNOPQRSTUVWXYZ" << true << true << false; + QTest::newRow("on word selection (30,9)") << testFile("mouseselection_true_words.qml") << 30 << 9 << "0123456789 ABCDEFGHIJKLMNOPQRSTUVWXYZ" << true << true << false; + + QTest::newRow("off double click (4,9)") << testFile("mouseselection_true.qml") << 4 << 9 << "0123456789" << true << true << true; + QTest::newRow("off double click (2,13)") << testFile("mouseselection_true.qml") << 2 << 13 << "0123456789 ABCDEFGHIJKLMNOPQRSTUVWXYZ" << true << true << true; + QTest::newRow("off double click (2,30)") << testFile("mouseselection_true.qml") << 2 << 30 << "0123456789 ABCDEFGHIJKLMNOPQRSTUVWXYZ" << true << true << true; + QTest::newRow("off double click (9,13)") << testFile("mouseselection_true.qml") << 9 << 13 << "0123456789 ABCDEFGHIJKLMNOPQRSTUVWXYZ" << true << true << true; + QTest::newRow("off double click (9,30)") << testFile("mouseselection_true.qml") << 9 << 30 << "0123456789 ABCDEFGHIJKLMNOPQRSTUVWXYZ" << true << true << true; + QTest::newRow("off double click (13,2)") << testFile("mouseselection_true.qml") << 13 << 2 << "0123456789 ABCDEFGHIJKLMNOPQRSTUVWXYZ" << true << true << true; + QTest::newRow("off double click (20,2)") << testFile("mouseselection_true.qml") << 20 << 2 << "0123456789 ABCDEFGHIJKLMNOPQRSTUVWXYZ" << true << true << true; + QTest::newRow("off double click (12,9)") << testFile("mouseselection_true.qml") << 12 << 9 << "0123456789 ABCDEFGHIJKLMNOPQRSTUVWXYZ" << true << true << true; + QTest::newRow("off double click (30,9)") << testFile("mouseselection_true.qml") << 30 << 9 << "0123456789 ABCDEFGHIJKLMNOPQRSTUVWXYZ" << true << true << true; } void tst_qquicktextedit::mouseSelection() @@ -1585,6 +1673,9 @@ void tst_qquicktextedit::mouseSelection() QFETCH(int, from); QFETCH(int, to); QFETCH(QString, selectedText); + QFETCH(bool, focus); + QFETCH(bool, focusOnPress); + QFETCH(bool, doubleClick); QQuickView canvas(QUrl::fromLocalFile(qmlfile)); @@ -1597,9 +1688,14 @@ void tst_qquicktextedit::mouseSelection() QQuickTextEdit *textEditObject = qobject_cast<QQuickTextEdit *>(canvas.rootObject()); QVERIFY(textEditObject != 0); + textEditObject->setFocus(focus); + textEditObject->setFocusOnPress(focusOnPress); + // press-and-drag-and-release from x1 to x2 QPoint p1 = textEditObject->positionToRectangle(from).center().toPoint(); QPoint p2 = textEditObject->positionToRectangle(to).center().toPoint(); + if (doubleClick) + QTest::mouseClick(&canvas, Qt::LeftButton, 0, p1); QTest::mousePress(&canvas, Qt::LeftButton, 0, p1); QTest::mouseMove(&canvas, p2); QTest::mouseRelease(&canvas, Qt::LeftButton, 0, p2); @@ -1608,7 +1704,10 @@ void tst_qquicktextedit::mouseSelection() // Clicking and shift to clicking between the same points should select the same text. textEditObject->setCursorPosition(0); - QTest::mouseClick(&canvas, Qt::LeftButton, Qt::NoModifier, p1); + if (doubleClick) + QTest::mouseDClick(&canvas, Qt::LeftButton, 0, p1); + else + QTest::mouseClick(&canvas, Qt::LeftButton, Qt::NoModifier, p1); QTest::mouseClick(&canvas, Qt::LeftButton, Qt::ShiftModifier, p2); QTest::qWait(50); QTRY_COMPARE(textEditObject->selectedText(), selectedText); @@ -2155,7 +2254,7 @@ void tst_qquicktextedit::readOnly() QCOMPARE(edit->cursorPosition(), edit->text().length()); } -void tst_qquicktextedit::simulateKey(QQuickView *view, int key, Qt::KeyboardModifiers modifiers) +void tst_qquicktextedit::simulateKey(QWindow *view, int key, Qt::KeyboardModifiers modifiers) { QKeyEvent press(QKeyEvent::KeyPress, key, modifiers); QKeyEvent release(QKeyEvent::KeyRelease, key, modifiers); @@ -2415,17 +2514,19 @@ void tst_qquicktextedit::implicitSize_data() { QTest::addColumn<QString>("text"); QTest::addColumn<QString>("wrap"); - QTest::newRow("plain") << "The quick red fox jumped over the lazy brown dog" << "TextEdit.NoWrap"; - QTest::newRow("richtext") << "<b>The quick red fox jumped over the lazy brown dog</b>" << "TextEdit.NoWrap"; - QTest::newRow("plain_wrap") << "The quick red fox jumped over the lazy brown dog" << "TextEdit.Wrap"; - QTest::newRow("richtext_wrap") << "<b>The quick red fox jumped over the lazy brown dog</b>" << "TextEdit.Wrap"; + QTest::addColumn<QString>("format"); + QTest::newRow("plain") << "The quick red fox jumped over the lazy brown dog" << "TextEdit.NoWrap" << "TextEdit.PlainText"; + QTest::newRow("richtext") << "<b>The quick red fox jumped over the lazy brown dog</b>" << "TextEdit.NoWrap" << "TextEdit.RichText"; + QTest::newRow("plain_wrap") << "The quick red fox jumped over the lazy brown dog" << "TextEdit.Wrap" << "TextEdit.PlainText"; + QTest::newRow("richtext_wrap") << "<b>The quick red fox jumped over the lazy brown dog</b>" << "TextEdit.Wrap" << "TextEdit.RichText"; } void tst_qquicktextedit::implicitSize() { QFETCH(QString, text); QFETCH(QString, wrap); - QString componentStr = "import QtQuick 2.0\nTextEdit { text: \"" + text + "\"; width: 50; wrapMode: " + wrap + " }"; + QFETCH(QString, format); + QString componentStr = "import QtQuick 2.0\nTextEdit { text: \"" + text + "\"; width: 50; wrapMode: " + wrap + "; textFormat: " + format + " }"; QQmlComponent textComponent(&engine); textComponent.setData(componentStr.toLatin1(), QUrl::fromLocalFile("")); QQuickTextEdit *textObject = qobject_cast<QQuickTextEdit*>(textComponent.create()); @@ -2466,6 +2567,34 @@ void tst_qquicktextedit::contentSize() QCOMPARE(spy.count(), 3); } +void tst_qquicktextedit::implicitSizeBinding_data() +{ + implicitSize_data(); +} + +void tst_qquicktextedit::implicitSizeBinding() +{ + QFETCH(QString, text); + QFETCH(QString, wrap); + QFETCH(QString, format); + QString componentStr = "import QtQuick 2.0\nTextEdit { text: \"" + text + "\"; width: implicitWidth; height: implicitHeight; wrapMode: " + wrap + "; textFormat: " + format + " }"; + QDeclarativeComponent textComponent(&engine); + textComponent.setData(componentStr.toLatin1(), QUrl::fromLocalFile("")); + QScopedPointer<QObject> object(textComponent.create()); + QQuickTextEdit *textObject = qobject_cast<QQuickTextEdit *>(object.data()); + + QCOMPARE(textObject->width(), textObject->implicitWidth()); + QCOMPARE(textObject->height(), textObject->implicitHeight()); + + textObject->resetWidth(); + QCOMPARE(textObject->width(), textObject->implicitWidth()); + QCOMPARE(textObject->height(), textObject->implicitHeight()); + + textObject->resetHeight(); + QCOMPARE(textObject->width(), textObject->implicitWidth()); + QCOMPARE(textObject->height(), textObject->implicitHeight()); +} + void tst_qquicktextedit::preeditCursorRectangle() { QString preeditText = "super"; @@ -3255,63 +3384,118 @@ void tst_qquicktextedit::keySequence_data() QTest::addColumn<int>("cursorPosition"); QTest::addColumn<QString>("expectedText"); QTest::addColumn<QString>("selectedText"); + QTest::addColumn<Qt::Key>("layoutDirection"); // standard[0] == "the [4]quick [10]brown [16]fox [20]jumped [27]over [32]the [36]lazy [41]dog" QTest::newRow("select all") << standard.at(0) << QKeySequence(QKeySequence::SelectAll) << 0 << 0 - << 44 << standard.at(0) << standard.at(0); + << 44 << standard.at(0) << standard.at(0) + << Qt::Key_Direction_L; + QTest::newRow("select start of line") + << standard.at(0) << QKeySequence(QKeySequence::SelectStartOfLine) << 5 << 5 + << 0 << standard.at(0) << standard.at(0).mid(0, 5) + << Qt::Key_Direction_L; + QTest::newRow("select start of block") + << standard.at(0) << QKeySequence(QKeySequence::SelectStartOfBlock) << 5 << 5 + << 0 << standard.at(0) << standard.at(0).mid(0, 5) + << Qt::Key_Direction_L; QTest::newRow("select end of line") << standard.at(0) << QKeySequence(QKeySequence::SelectEndOfLine) << 5 << 5 - << 44 << standard.at(0) << standard.at(0).mid(5); + << 44 << standard.at(0) << standard.at(0).mid(5) + << Qt::Key_Direction_L; QTest::newRow("select end of document") << standard.at(0) << QKeySequence(QKeySequence::SelectEndOfDocument) << 3 << 3 - << 44 << standard.at(0) << standard.at(0).mid(3); + << 44 << standard.at(0) << standard.at(0).mid(3) + << Qt::Key_Direction_L; QTest::newRow("select end of block") << standard.at(0) << QKeySequence(QKeySequence::SelectEndOfBlock) << 18 << 18 - << 44 << standard.at(0) << standard.at(0).mid(18); + << 44 << standard.at(0) << standard.at(0).mid(18) + << Qt::Key_Direction_L; QTest::newRow("delete end of line") << standard.at(0) << QKeySequence(QKeySequence::DeleteEndOfLine) << 24 << 24 - << 24 << standard.at(0).mid(0, 24) << QString(); + << 24 << standard.at(0).mid(0, 24) << QString() + << Qt::Key_Direction_L; QTest::newRow("move to start of line") << standard.at(0) << QKeySequence(QKeySequence::MoveToStartOfLine) << 31 << 31 - << 0 << standard.at(0) << QString(); + << 0 << standard.at(0) << QString() + << Qt::Key_Direction_L; QTest::newRow("move to start of block") << standard.at(0) << QKeySequence(QKeySequence::MoveToStartOfBlock) << 25 << 25 - << 0 << standard.at(0) << QString(); + << 0 << standard.at(0) << QString() + << Qt::Key_Direction_L; QTest::newRow("move to next char") << standard.at(0) << QKeySequence(QKeySequence::MoveToNextChar) << 12 << 12 - << 13 << standard.at(0) << QString(); - QTest::newRow("move to previous char") + << 13 << standard.at(0) << QString() + << Qt::Key_Direction_L; + QTest::newRow("move to previous char (ltr)") << standard.at(0) << QKeySequence(QKeySequence::MoveToPreviousChar) << 3 << 3 - << 2 << standard.at(0) << QString(); - QTest::newRow("select next char") + << 2 << standard.at(0) << QString() + << Qt::Key_Direction_L; + QTest::newRow("move to previous char (rtl)") + << standard.at(0) << QKeySequence(QKeySequence::MoveToPreviousChar) << 3 << 3 + << 4 << standard.at(0) << QString() + << Qt::Key_Direction_R; + QTest::newRow("move to previous char with selection") + << standard.at(0) << QKeySequence(QKeySequence::MoveToPreviousChar) << 3 << 7 + << 3 << standard.at(0) << QString() + << Qt::Key_Direction_L; + QTest::newRow("select next char (ltr)") + << standard.at(0) << QKeySequence(QKeySequence::SelectNextChar) << 23 << 23 + << 24 << standard.at(0) << standard.at(0).mid(23, 1) + << Qt::Key_Direction_L; + QTest::newRow("select next char (rtl)") << standard.at(0) << QKeySequence(QKeySequence::SelectNextChar) << 23 << 23 - << 24 << standard.at(0) << standard.at(0).mid(23, 1); - QTest::newRow("select previous char") + << 22 << standard.at(0) << standard.at(0).mid(22, 1) + << Qt::Key_Direction_R; + QTest::newRow("select previous char (ltr)") + << standard.at(0) << QKeySequence(QKeySequence::SelectPreviousChar) << 19 << 19 + << 18 << standard.at(0) << standard.at(0).mid(18, 1) + << Qt::Key_Direction_L; + QTest::newRow("select previous char (rtl)") << standard.at(0) << QKeySequence(QKeySequence::SelectPreviousChar) << 19 << 19 - << 18 << standard.at(0) << standard.at(0).mid(18, 1); - QTest::newRow("move to next word") + << 20 << standard.at(0) << standard.at(0).mid(19, 1) + << Qt::Key_Direction_R; + QTest::newRow("move to next word (ltr)") << standard.at(0) << QKeySequence(QKeySequence::MoveToNextWord) << 7 << 7 - << 10 << standard.at(0) << QString(); - QTest::newRow("move to previous word") + << 10 << standard.at(0) << QString() + << Qt::Key_Direction_L; + QTest::newRow("move to next word (rtl)") + << standard.at(0) << QKeySequence(QKeySequence::MoveToNextWord) << 7 << 7 + << 4 << standard.at(0) << QString() + << Qt::Key_Direction_R; + QTest::newRow("move to previous word (ltr)") + << standard.at(0) << QKeySequence(QKeySequence::MoveToPreviousWord) << 7 << 7 + << 4 << standard.at(0) << QString() + << Qt::Key_Direction_L; + QTest::newRow("move to previous word (rlt)") << standard.at(0) << QKeySequence(QKeySequence::MoveToPreviousWord) << 7 << 7 - << 4 << standard.at(0) << QString(); + << 10 << standard.at(0) << QString() + << Qt::Key_Direction_R; + QTest::newRow("select next word") + << standard.at(0) << QKeySequence(QKeySequence::SelectNextWord) << 11 << 11 + << 16 << standard.at(0) << standard.at(0).mid(11, 5) + << Qt::Key_Direction_L; QTest::newRow("select previous word") << standard.at(0) << QKeySequence(QKeySequence::SelectPreviousWord) << 11 << 11 - << 10 << standard.at(0) << standard.at(0).mid(10, 1); + << 10 << standard.at(0) << standard.at(0).mid(10, 1) + << Qt::Key_Direction_L; QTest::newRow("delete (selection)") << standard.at(0) << QKeySequence(QKeySequence::Delete) << 12 << 15 - << 12 << (standard.at(0).mid(0, 12) + standard.at(0).mid(15)) << QString(); + << 12 << (standard.at(0).mid(0, 12) + standard.at(0).mid(15)) << QString() + << Qt::Key_Direction_L; QTest::newRow("delete (no selection)") << standard.at(0) << QKeySequence(QKeySequence::Delete) << 15 << 15 - << 15 << (standard.at(0).mid(0, 15) + standard.at(0).mid(16)) << QString(); + << 15 << (standard.at(0).mid(0, 15) + standard.at(0).mid(16)) << QString() + << Qt::Key_Direction_L; QTest::newRow("delete end of word") << standard.at(0) << QKeySequence(QKeySequence::DeleteEndOfWord) << 24 << 24 - << 24 << (standard.at(0).mid(0, 24) + standard.at(0).mid(27)) << QString(); + << 24 << (standard.at(0).mid(0, 24) + standard.at(0).mid(27)) << QString() + << Qt::Key_Direction_L; QTest::newRow("delete start of word") << standard.at(0) << QKeySequence(QKeySequence::DeleteStartOfWord) << 7 << 7 - << 4 << (standard.at(0).mid(0, 4) + standard.at(0).mid(7)) << QString(); + << 4 << (standard.at(0).mid(0, 4) + standard.at(0).mid(7)) << QString() + << Qt::Key_Direction_L; } void tst_qquicktextedit::keySequence() @@ -3323,6 +3507,7 @@ void tst_qquicktextedit::keySequence() QFETCH(int, cursorPosition); QFETCH(QString, expectedText); QFETCH(QString, selectedText); + QFETCH(Qt::Key, layoutDirection); if (sequence.isEmpty()) { QSKIP("Key sequence is undefined"); @@ -3341,6 +3526,8 @@ void tst_qquicktextedit::keySequence() QTest::qWaitForWindowShown(&canvas); QTRY_COMPARE(QGuiApplication::activeWindow(), &canvas); + simulateKey(&canvas, layoutDirection); + textEdit->select(selectionStart, selectionEnd); simulateKeys(&canvas, sequence); @@ -3466,7 +3653,7 @@ void tst_qquicktextedit::undo_data() insertString << " unique instance."; expectedString << "Ensuring a unique instance."; - expectedString << "Ensuring a "; // ### Not present in TextInput. + expectedString << "Ensuring a "; // ### Not present in TextEdit. expectedString << "Ensuring an instan"; expectedString << "Ensuring instan"; expectedString << ""; @@ -3754,7 +3941,7 @@ void tst_qquicktextedit::undo_keypressevents_data() << "ABC"; expectedString << "ABC"; - // ### One operation in TextInput. + // ### One operation in TextEdit. expectedString << "A"; expectedString << "123"; diff --git a/tests/auto/quick/qquicktextinput/tst_qquicktextinput.cpp b/tests/auto/quick/qquicktextinput/tst_qquicktextinput.cpp index c5db92af45..afe102aa4c 100644 --- a/tests/auto/quick/qquicktextinput/tst_qquicktextinput.cpp +++ b/tests/auto/quick/qquicktextinput/tst_qquicktextinput.cpp @@ -63,6 +63,9 @@ #include "../../shared/platforminputcontext.h" Q_DECLARE_METATYPE(QQuickTextInput::SelectionMode) +Q_DECLARE_METATYPE(QQuickTextInput::EchoMode) +Q_DECLARE_METATYPE(Qt::Key) + DEFINE_BOOL_CONFIG_OPTION(qmlDisableDistanceField, QML_DISABLE_DISTANCEFIELD) QString createExpectedFileIfNotFound(const QString& filebasename, const QImage& actual) @@ -90,6 +93,8 @@ template <typename T> static T evaluate(QObject *scope, const QString &expressio return result; } +template<typename T, int N> int lengthOf(const T (&)[N]) { return N; } + typedef QPair<int, QChar> Key; class tst_qquicktextinput : public QQmlDataTest @@ -137,6 +142,7 @@ private slots: void cursorDelegate_data(); void cursorDelegate(); void cursorVisible(); + void cursorRectangle_data(); void cursorRectangle(); void navigation(); void navigation_RTL(); @@ -145,6 +151,7 @@ private slots: void canPasteEmpty(); void canPaste(); void readOnly(); + void focusOnPress(); void openInputPanel(); void setHAlignClearCache(); @@ -185,10 +192,28 @@ private slots: void QTBUG_19956_data(); void QTBUG_19956_regexp(); + void implicitSize_data(); + void implicitSize(); + void implicitSizeBinding_data(); + void implicitSizeBinding(); + void negativeDimensions(); + + void setInputMask_data(); + void setInputMask(); + void inputMask_data(); + void inputMask(); + void clearInputMask(); + void keypress_inputMask_data(); + void keypress_inputMask(); + void hasAcceptableInputMask_data(); + void hasAcceptableInputMask(); + void maskCharacter_data(); + void maskCharacter(); + private: - void simulateKey(QQuickView *, int key); + void simulateKey(QWindow *, int key); void simulateKeys(QWindow *window, const QList<Key> &keys); void simulateKeys(QWindow *window, const QKeySequence &sequence); @@ -1184,17 +1209,27 @@ void tst_qquicktextinput::mouseSelectionMode_data() { QTest::addColumn<QString>("qmlfile"); QTest::addColumn<bool>("selectWords"); + QTest::addColumn<bool>("focus"); + QTest::addColumn<bool>("focusOnPress"); // import installed - QTest::newRow("SelectWords") << testFile("mouseselectionmode_words.qml") << true; - QTest::newRow("SelectCharacters") << testFile("mouseselectionmode_characters.qml") << false; - QTest::newRow("default") << testFile("mouseselectionmode_default.qml") << false; + QTest::newRow("SelectWords focused") << testFile("mouseselectionmode_words.qml") << true << true << true; + QTest::newRow("SelectCharacters focused") << testFile("mouseselectionmode_characters.qml") << false << true << true; + QTest::newRow("default focused") << testFile("mouseselectionmode_default.qml") << false << true << true; + QTest::newRow("SelectWords unfocused") << testFile("mouseselectionmode_words.qml") << true << false << false; + QTest::newRow("SelectCharacters unfocused") << testFile("mouseselectionmode_characters.qml") << false << false << false; + QTest::newRow("default unfocused") << testFile("mouseselectionmode_default.qml") << false << true << false; + QTest::newRow("SelectWords focuss on press") << testFile("mouseselectionmode_words.qml") << true << false << true; + QTest::newRow("SelectCharacters focus on press") << testFile("mouseselectionmode_characters.qml") << false << false << true; + QTest::newRow("default focus on press") << testFile("mouseselectionmode_default.qml") << false << false << true; } void tst_qquicktextinput::mouseSelectionMode() { QFETCH(QString, qmlfile); QFETCH(bool, selectWords); + QFETCH(bool, focus); + QFETCH(bool, focusOnPress); QString text = "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ"; @@ -1209,6 +1244,9 @@ void tst_qquicktextinput::mouseSelectionMode() QQuickTextInput *textInputObject = qobject_cast<QQuickTextInput *>(canvas.rootObject()); QVERIFY(textInputObject != 0); + textInputObject->setFocus(focus); + textInputObject->setFocusOnPress(focusOnPress); + // press-and-drag-and-release from x1 to x2 int x1 = 10; int x2 = 70; @@ -2126,7 +2164,7 @@ void tst_qquicktextinput::copyAndPaste() { // copy and paste QCOMPARE(textInput->text().length(), 12); - textInput->select(0, textInput->text().length());; + textInput->select(0, textInput->text().length()); textInput->copy(); QCOMPARE(textInput->selectedText(), QString("Hello world!")); QCOMPARE(textInput->selectedText().length(), 12); @@ -2169,7 +2207,7 @@ void tst_qquicktextinput::copyAndPaste() { QQuickTextInput::EchoMode echoMode = QQuickTextInput::EchoMode(index); textInput->setEchoMode(echoMode); textInput->setText("My password"); - textInput->select(0, textInput->text().length());; + textInput->select(0, textInput->text().length()); textInput->copy(); if (echoMode == QQuickTextInput::Normal) { QVERIFY(!clipboard->text().isEmpty()); @@ -2246,7 +2284,7 @@ void tst_qquicktextinput::copyAndPasteKeySequence() { QQuickTextInput::EchoMode echoMode = QQuickTextInput::EchoMode(index); textInput->setEchoMode(echoMode); textInput->setText("My password"); - textInput->select(0, textInput->text().length());; + textInput->select(0, textInput->text().length()); simulateKeys(&canvas, QKeySequence::Copy); if (echoMode == QQuickTextInput::Normal) { QVERIFY(!clipboard->text().isEmpty()); @@ -2402,10 +2440,34 @@ void tst_qquicktextinput::cursorVisible() QCOMPARE(spy.count(), 7); } +void tst_qquicktextinput::cursorRectangle_data() +{ + const quint16 arabic_str[] = { 0x0638, 0x0643, 0x00646, 0x0647, 0x0633, 0x0020, 0x0020, 0x0020, 0x0020, 0x0020, 0x0020, 0x0638, 0x0643, 0x00646, 0x0647, 0x0633, 0x0647}; + + QTest::addColumn<QString>("text"); + QTest::addColumn<int>("positionAtWidth"); + QTest::addColumn<int>("wrapPosition"); + QTest::addColumn<QString>("shortText"); + QTest::addColumn<bool>("leftToRight"); + + QTest::newRow("left to right") + << "Hello World!" << 5 << 11 + << "Hi" + << true; + QTest::newRow("right to left") + << QString::fromUtf16(arabic_str, lengthOf(arabic_str)) << 5 << 11 + << QString::fromUtf16(arabic_str, 3) + << false; +} + void tst_qquicktextinput::cursorRectangle() { - QString text = "Hello World!"; + QFETCH(QString, text); + QFETCH(int, positionAtWidth); + QFETCH(int, wrapPosition); + QFETCH(QString, shortText); + QFETCH(bool, leftToRight); QQuickTextInput input; input.setText(text); @@ -2422,33 +2484,30 @@ void tst_qquicktextinput::cursorRectangle() QTextLine line = layout.createLine(); layout.endLayout(); - input.setWidth(line.cursorToX(5, QTextLine::Leading)); + qreal offset = 0; + if (leftToRight) { + input.setWidth(line.cursorToX(positionAtWidth, QTextLine::Leading)); + } else { + input.setWidth(line.horizontalAdvance() - line.cursorToX(positionAtWidth, QTextLine::Leading)); + offset = line.horizontalAdvance() - input.width(); + } input.setHeight(qCeil(line.height() * 3 / 2)); QRectF r; - // some tolerance for different fonts. -#ifdef Q_OS_LINUX - const int error = 2; -#else - const int error = 5; -#endif - - for (int i = 0; i <= 5; ++i) { + for (int i = 0; i <= positionAtWidth; ++i) { input.setCursorPosition(i); r = input.cursorRectangle(); - QVERIFY(r.left() < qCeil(line.cursorToX(i, QTextLine::Trailing))); - QVERIFY(r.right() >= qFloor(line.cursorToX(i , QTextLine::Leading))); + QCOMPARE(r.left(), line.cursorToX(i, QTextLine::Leading) - offset); QCOMPARE(input.inputMethodQuery(Qt::ImCursorRectangle).toRectF(), r); QCOMPARE(input.positionToRectangle(i), r); } // Check the cursor rectangle remains within the input bounding rect when auto scrolling. - QVERIFY(r.left() < input.width() + error); - QVERIFY(r.right() >= input.width() - error); + QCOMPARE(r.left(), leftToRight ? input.width() : 0); - for (int i = 6; i < text.length(); ++i) { + for (int i = positionAtWidth + 1; i < text.length(); ++i) { input.setCursorPosition(i); QCOMPARE(r, input.cursorRectangle()); QCOMPARE(input.inputMethodQuery(Qt::ImCursorRectangle).toRectF(), r); @@ -2459,7 +2518,11 @@ void tst_qquicktextinput::cursorRectangle() input.setCursorPosition(i); r = input.cursorRectangle(); QCOMPARE(r.top(), 0.); - QVERIFY(r.right() >= 0); + if (leftToRight) { + QVERIFY(r.right() >= 0); + } else { + QVERIFY(r.left() <= input.width()); + } QCOMPARE(input.inputMethodQuery(Qt::ImCursorRectangle).toRectF(), r); QCOMPARE(input.positionToRectangle(i), r); } @@ -2467,69 +2530,102 @@ void tst_qquicktextinput::cursorRectangle() // Check position with word wrap. input.setWrapMode(QQuickTextInput::WordWrap); input.setAutoScroll(false); - for (int i = 0; i <= 5; ++i) { + for (int i = 0; i < wrapPosition; ++i) { input.setCursorPosition(i); r = input.cursorRectangle(); - QVERIFY(r.left() < qCeil(line.cursorToX(i, QTextLine::Trailing))); - QVERIFY(r.right() >= qFloor(line.cursorToX(i , QTextLine::Leading))); + if (i > positionAtWidth) + QEXPECT_FAIL("right to left", "QTBUG-24801", Continue); + QCOMPARE(r.left(), line.cursorToX(i, QTextLine::Leading) - offset); QCOMPARE(r.top(), 0.); QCOMPARE(input.inputMethodQuery(Qt::ImCursorRectangle).toRectF(), r); QCOMPARE(input.positionToRectangle(i), r); } - input.setCursorPosition(6); + input.setCursorPosition(wrapPosition); r = input.cursorRectangle(); - QCOMPARE(r.left(), 0.); - QVERIFY(r.top() > line.height() - error); + if (leftToRight) { + QCOMPARE(r.left(), 0.); + } else { + QCOMPARE(r.left(), input.width()); + } + QVERIFY(r.top() >= line.height() - 1); QCOMPARE(input.inputMethodQuery(Qt::ImCursorRectangle).toRectF(), r); - QCOMPARE(input.positionToRectangle(6), r); + QCOMPARE(input.positionToRectangle(11), r); - for (int i = 7; i < text.length(); ++i) { + for (int i = wrapPosition + 1; i < text.length(); ++i) { input.setCursorPosition(i); r = input.cursorRectangle(); - QVERIFY(r.top() > line.height() - error); + QVERIFY(r.top() >= line.height() - 1); QCOMPARE(input.inputMethodQuery(Qt::ImCursorRectangle).toRectF(), r); QCOMPARE(input.positionToRectangle(i), r); } // Check vertical scrolling with word wrap. input.setAutoScroll(true); - for (int i = 0; i <= 5; ++i) { + for (int i = 0; i <= positionAtWidth; ++i) { input.setCursorPosition(i); r = input.cursorRectangle(); - QVERIFY(r.left() < qCeil(line.cursorToX(i, QTextLine::Trailing))); - QVERIFY(r.right() >= qFloor(line.cursorToX(i , QTextLine::Leading))); + QCOMPARE(r.left(), line.cursorToX(i, QTextLine::Leading) - offset); QCOMPARE(r.top(), 0.); QCOMPARE(input.inputMethodQuery(Qt::ImCursorRectangle).toRectF(), r); QCOMPARE(input.positionToRectangle(i), r); } - input.setCursorPosition(6); + // Whitespace doesn't wrap, so scroll horizontally until the until the cursor + // reaches the next non-whitespace character. + QCOMPARE(r.left(), leftToRight ? input.width() : 0); + for (int i = positionAtWidth + 1; i < wrapPosition && leftToRight; ++i) { + input.setCursorPosition(i); + QCOMPARE(r, input.cursorRectangle()); + QCOMPARE(input.inputMethodQuery(Qt::ImCursorRectangle).toRectF(), r); + QCOMPARE(input.positionToRectangle(i), r); + } + + input.setCursorPosition(wrapPosition); r = input.cursorRectangle(); - QCOMPARE(r.left(), 0.); - QVERIFY(r.bottom() >= input.height() - error); + if (leftToRight) { + QCOMPARE(r.left(), 0.); + } else { + QCOMPARE(r.left(), input.width()); + } + QVERIFY(r.bottom() >= input.height()); QCOMPARE(input.inputMethodQuery(Qt::ImCursorRectangle).toRectF(), r); - QCOMPARE(input.positionToRectangle(6), r); + QCOMPARE(input.positionToRectangle(11), r); - for (int i = 7; i < text.length(); ++i) { + for (int i = wrapPosition + 1; i < text.length(); ++i) { input.setCursorPosition(i); r = input.cursorRectangle(); - QVERIFY(r.bottom() >= input.height() - error); + QVERIFY(r.bottom() >= input.height()); QCOMPARE(input.inputMethodQuery(Qt::ImCursorRectangle).toRectF(), r); QCOMPARE(input.positionToRectangle(i), r); } - for (int i = text.length() - 2; i >= 6; --i) { + for (int i = text.length() - 2; i >= wrapPosition; --i) { input.setCursorPosition(i); r = input.cursorRectangle(); - QVERIFY(r.bottom() >= input.height() - error); + QVERIFY(r.bottom() >= input.height()); + QCOMPARE(input.inputMethodQuery(Qt::ImCursorRectangle).toRectF(), r); + QCOMPARE(input.positionToRectangle(i), r); + } + + input.setCursorPosition(wrapPosition - 1); + r = input.cursorRectangle(); + QCOMPARE(r.top(), 0.); + QEXPECT_FAIL("right to left", "QTBUG-24801", Continue); + QCOMPARE(r.left(), leftToRight ? input.width() : 0); + QCOMPARE(input.inputMethodQuery(Qt::ImCursorRectangle).toRectF(), r); + QCOMPARE(input.positionToRectangle(10), r); + + for (int i = wrapPosition - 2; i >= positionAtWidth + 1; --i) { + input.setCursorPosition(i); + QCOMPARE(r, input.cursorRectangle()); QCOMPARE(input.inputMethodQuery(Qt::ImCursorRectangle).toRectF(), r); QCOMPARE(input.positionToRectangle(i), r); } - for (int i = 5; i >= 0; --i) { + for (int i = positionAtWidth; i >= 0; --i) { input.setCursorPosition(i); r = input.cursorRectangle(); QCOMPARE(r.top(), 0.); @@ -2537,11 +2633,10 @@ void tst_qquicktextinput::cursorRectangle() QCOMPARE(input.positionToRectangle(i), r); } - input.setText("Hi!"); - input.setHAlign(QQuickTextInput::AlignRight); + input.setText(shortText); + input.setHAlign(leftToRight ? QQuickTextInput::AlignRight : QQuickTextInput::AlignLeft); r = input.cursorRectangle(); - QVERIFY(r.left() < input.width() + error); - QVERIFY(r.right() >= input.width() - error); + QCOMPARE(r.left(), leftToRight ? input.width() : 0); } void tst_qquicktextinput::readOnly() @@ -2702,7 +2797,7 @@ void tst_qquicktextinput::passwordEchoDelay() #endif -void tst_qquicktextinput::simulateKey(QQuickView *view, int key) +void tst_qquicktextinput::simulateKey(QWindow *view, int key) { QKeyEvent press(QKeyEvent::KeyPress, key, 0); QKeyEvent release(QKeyEvent::KeyRelease, key, 0); @@ -2712,6 +2807,92 @@ void tst_qquicktextinput::simulateKey(QQuickView *view, int key) } +void tst_qquicktextinput::focusOnPress() +{ + QString componentStr = + "import QtQuick 2.0\n" + "TextInput {\n" + "property bool selectOnFocus: false\n" + "width: 100; height: 50\n" + "activeFocusOnPress: true\n" + "text: \"Hello World\"\n" + "onFocusChanged: { if (focus && selectOnFocus) selectAll() }" + " }"; + QQmlComponent texteditComponent(&engine); + texteditComponent.setData(componentStr.toLatin1(), QUrl()); + QQuickTextInput *textInputObject = qobject_cast<QQuickTextInput*>(texteditComponent.create()); + QVERIFY(textInputObject != 0); + QCOMPARE(textInputObject->focusOnPress(), true); + QCOMPARE(textInputObject->hasFocus(), false); + + QSignalSpy focusSpy(textInputObject, SIGNAL(focusChanged(bool))); + QSignalSpy activeFocusSpy(textInputObject, SIGNAL(focusChanged(bool))); + QSignalSpy activeFocusOnPressSpy(textInputObject, SIGNAL(activeFocusOnPressChanged(bool))); + + textInputObject->setFocusOnPress(true); + QCOMPARE(textInputObject->focusOnPress(), true); + QCOMPARE(activeFocusOnPressSpy.count(), 0); + + QQuickCanvas canvas; + canvas.resize(100, 50); + textInputObject->setParentItem(canvas.rootItem()); + canvas.show(); + canvas.requestActivateWindow(); + QTest::qWaitForWindowShown(&canvas); + QTRY_COMPARE(QGuiApplication::activeWindow(), &canvas); + + QCOMPARE(textInputObject->hasFocus(), false); + QCOMPARE(textInputObject->hasActiveFocus(), false); + + QPoint centerPoint(canvas.width()/2, canvas.height()/2); + Qt::KeyboardModifiers noModifiers = 0; + QTest::mousePress(&canvas, Qt::LeftButton, noModifiers, centerPoint); + QGuiApplication::processEvents(); + QCOMPARE(textInputObject->hasFocus(), true); + QCOMPARE(textInputObject->hasActiveFocus(), true); + QCOMPARE(focusSpy.count(), 1); + QCOMPARE(activeFocusSpy.count(), 1); + QCOMPARE(textInputObject->selectedText(), QString()); + QTest::mouseRelease(&canvas, Qt::LeftButton, noModifiers, centerPoint); + + textInputObject->setFocusOnPress(false); + QCOMPARE(textInputObject->focusOnPress(), false); + QCOMPARE(activeFocusOnPressSpy.count(), 1); + + textInputObject->setFocus(false); + QCOMPARE(textInputObject->hasFocus(), false); + QCOMPARE(textInputObject->hasActiveFocus(), false); + QCOMPARE(focusSpy.count(), 2); + QCOMPARE(activeFocusSpy.count(), 2); + + // Wait for double click timeout to expire before clicking again. + QTest::qWait(400); + QTest::mousePress(&canvas, Qt::LeftButton, noModifiers, centerPoint); + QGuiApplication::processEvents(); + QCOMPARE(textInputObject->hasFocus(), false); + QCOMPARE(textInputObject->hasActiveFocus(), false); + QCOMPARE(focusSpy.count(), 2); + QCOMPARE(activeFocusSpy.count(), 2); + QTest::mouseRelease(&canvas, Qt::LeftButton, noModifiers, centerPoint); + + textInputObject->setFocusOnPress(true); + QCOMPARE(textInputObject->focusOnPress(), true); + QCOMPARE(activeFocusOnPressSpy.count(), 2); + + // Test a selection made in the on(Active)FocusChanged handler isn't overwritten. + textInputObject->setProperty("selectOnFocus", true); + + QTest::qWait(400); + QTest::mousePress(&canvas, Qt::LeftButton, noModifiers, centerPoint); + QGuiApplication::processEvents(); + QCOMPARE(textInputObject->hasFocus(), true); + QCOMPARE(textInputObject->hasActiveFocus(), true); + QCOMPARE(focusSpy.count(), 3); + QCOMPARE(activeFocusSpy.count(), 3); + QCOMPARE(textInputObject->selectedText(), textInputObject->text()); + QTest::mouseRelease(&canvas, Qt::LeftButton, noModifiers, centerPoint); +} + void tst_qquicktextinput::openInputPanel() { PlatformInputContext platformInputContext; @@ -2888,6 +3069,13 @@ void tst_qquicktextinput::contentSize() QVERIFY(textObject->contentWidth() > textObject->width()); QVERIFY(textObject->contentHeight() > textObject->height()); QCOMPARE(spy.count(), 3); + + textObject->setText("The quick red fox jumped over the lazy brown dog"); + for (int w = 60; w < 120; ++w) { + textObject->setWidth(w); + QVERIFY(textObject->contentWidth() <= textObject->width()); + QVERIFY(textObject->contentHeight() > textObject->height()); + } } static void sendPreeditText(const QString &text, int cursor) @@ -4084,63 +4272,135 @@ void tst_qquicktextinput::keySequence_data() QTest::addColumn<int>("cursorPosition"); QTest::addColumn<QString>("expectedText"); QTest::addColumn<QString>("selectedText"); + QTest::addColumn<QQuickTextInput::EchoMode>("echoMode"); + QTest::addColumn<Qt::Key>("layoutDirection"); // standard[0] == "the [4]quick [10]brown [16]fox [20]jumped [27]over [32]the [36]lazy [41]dog" QTest::newRow("select all") << standard.at(0) << QKeySequence(QKeySequence::SelectAll) << 0 << 0 - << 44 << standard.at(0) << standard.at(0); + << 44 << standard.at(0) << standard.at(0) + << QQuickTextInput::Normal << Qt::Key_Direction_L; + QTest::newRow("select start of line") + << standard.at(0) << QKeySequence(QKeySequence::SelectStartOfLine) << 5 << 5 + << 0 << standard.at(0) << standard.at(0).mid(0, 5) + << QQuickTextInput::Normal << Qt::Key_Direction_L; + QTest::newRow("select start of block") + << standard.at(0) << QKeySequence(QKeySequence::SelectStartOfBlock) << 5 << 5 + << 0 << standard.at(0) << standard.at(0).mid(0, 5) + << QQuickTextInput::Normal << Qt::Key_Direction_L; QTest::newRow("select end of line") << standard.at(0) << QKeySequence(QKeySequence::SelectEndOfLine) << 5 << 5 - << 44 << standard.at(0) << standard.at(0).mid(5); + << 44 << standard.at(0) << standard.at(0).mid(5) + << QQuickTextInput::Normal << Qt::Key_Direction_L; QTest::newRow("select end of document") // ### Not handled. << standard.at(0) << QKeySequence(QKeySequence::SelectEndOfDocument) << 3 << 3 - << 3 << standard.at(0) << QString(); + << 3 << standard.at(0) << QString() + << QQuickTextInput::Normal << Qt::Key_Direction_L; QTest::newRow("select end of block") << standard.at(0) << QKeySequence(QKeySequence::SelectEndOfBlock) << 18 << 18 - << 44 << standard.at(0) << standard.at(0).mid(18); + << 44 << standard.at(0) << standard.at(0).mid(18) + << QQuickTextInput::Normal << Qt::Key_Direction_L; QTest::newRow("delete end of line") << standard.at(0) << QKeySequence(QKeySequence::DeleteEndOfLine) << 24 << 24 - << 24 << standard.at(0).mid(0, 24) << QString(); + << 24 << standard.at(0).mid(0, 24) << QString() + << QQuickTextInput::Normal << Qt::Key_Direction_L; QTest::newRow("move to start of line") << standard.at(0) << QKeySequence(QKeySequence::MoveToStartOfLine) << 31 << 31 - << 0 << standard.at(0) << QString(); + << 0 << standard.at(0) << QString() + << QQuickTextInput::Normal << Qt::Key_Direction_L; QTest::newRow("move to start of block") << standard.at(0) << QKeySequence(QKeySequence::MoveToStartOfBlock) << 25 << 25 - << 0 << standard.at(0) << QString(); + << 0 << standard.at(0) << QString() + << QQuickTextInput::Normal << Qt::Key_Direction_L; QTest::newRow("move to next char") << standard.at(0) << QKeySequence(QKeySequence::MoveToNextChar) << 12 << 12 - << 13 << standard.at(0) << QString(); - QTest::newRow("move to previous char") + << 13 << standard.at(0) << QString() + << QQuickTextInput::Normal << Qt::Key_Direction_L; + QTest::newRow("move to previous char (ltr)") + << standard.at(0) << QKeySequence(QKeySequence::MoveToPreviousChar) << 3 << 3 + << 2 << standard.at(0) << QString() + << QQuickTextInput::Normal << Qt::Key_Direction_L; + QTest::newRow("move to previous char (rtl)") << standard.at(0) << QKeySequence(QKeySequence::MoveToPreviousChar) << 3 << 3 - << 2 << standard.at(0) << QString(); - QTest::newRow("select next char") + << 4 << standard.at(0) << QString() + << QQuickTextInput::Normal << Qt::Key_Direction_R; + QTest::newRow("move to previous char with selection") + << standard.at(0) << QKeySequence(QKeySequence::MoveToPreviousChar) << 3 << 7 + << 3 << standard.at(0) << QString() + << QQuickTextInput::Normal << Qt::Key_Direction_L; + QTest::newRow("select next char (ltr)") << standard.at(0) << QKeySequence(QKeySequence::SelectNextChar) << 23 << 23 - << 24 << standard.at(0) << standard.at(0).mid(23, 1); - QTest::newRow("select previous char") + << 24 << standard.at(0) << standard.at(0).mid(23, 1) + << QQuickTextInput::Normal << Qt::Key_Direction_L; + QTest::newRow("select next char (rtl)") + << standard.at(0) << QKeySequence(QKeySequence::SelectNextChar) << 23 << 23 + << 22 << standard.at(0) << standard.at(0).mid(22, 1) + << QQuickTextInput::Normal << Qt::Key_Direction_R; + QTest::newRow("select previous char (ltr)") + << standard.at(0) << QKeySequence(QKeySequence::SelectPreviousChar) << 19 << 19 + << 18 << standard.at(0) << standard.at(0).mid(18, 1) + << QQuickTextInput::Normal << Qt::Key_Direction_L; + QTest::newRow("select previous char (rtl)") << standard.at(0) << QKeySequence(QKeySequence::SelectPreviousChar) << 19 << 19 - << 18 << standard.at(0) << standard.at(0).mid(18, 1); - QTest::newRow("move to next word") + << 20 << standard.at(0) << standard.at(0).mid(19, 1) + << QQuickTextInput::Normal << Qt::Key_Direction_R; + QTest::newRow("move to next word (ltr)") << standard.at(0) << QKeySequence(QKeySequence::MoveToNextWord) << 7 << 7 - << 10 << standard.at(0) << QString(); - QTest::newRow("move to previous word") + << 10 << standard.at(0) << QString() + << QQuickTextInput::Normal << Qt::Key_Direction_L; + QTest::newRow("move to next word (rtl)") + << standard.at(0) << QKeySequence(QKeySequence::MoveToNextWord) << 7 << 7 + << 4 << standard.at(0) << QString() + << QQuickTextInput::Normal << Qt::Key_Direction_R; + QTest::newRow("move to next word (password,ltr)") + << standard.at(0) << QKeySequence(QKeySequence::MoveToNextWord) << 7 << 7 + << 44 << standard.at(0) << QString() + << QQuickTextInput::Password << Qt::Key_Direction_L; + QTest::newRow("move to next word (password,rtl)") + << standard.at(0) << QKeySequence(QKeySequence::MoveToNextWord) << 7 << 7 + << 0 << standard.at(0) << QString() + << QQuickTextInput::Password << Qt::Key_Direction_R; + QTest::newRow("move to previous word (ltr)") + << standard.at(0) << QKeySequence(QKeySequence::MoveToPreviousWord) << 7 << 7 + << 4 << standard.at(0) << QString() + << QQuickTextInput::Normal << Qt::Key_Direction_L; + QTest::newRow("move to previous word (rlt)") << standard.at(0) << QKeySequence(QKeySequence::MoveToPreviousWord) << 7 << 7 - << 4 << standard.at(0) << QString(); + << 10 << standard.at(0) << QString() + << QQuickTextInput::Normal << Qt::Key_Direction_R; + QTest::newRow("move to previous word (password,ltr)") + << standard.at(0) << QKeySequence(QKeySequence::MoveToPreviousWord) << 7 << 7 + << 0 << standard.at(0) << QString() + << QQuickTextInput::Password << Qt::Key_Direction_L; + QTest::newRow("move to previous word (password,rtl)") + << standard.at(0) << QKeySequence(QKeySequence::MoveToPreviousWord) << 7 << 7 + << 44 << standard.at(0) << QString() + << QQuickTextInput::Password << Qt::Key_Direction_R; + QTest::newRow("select next word") + << standard.at(0) << QKeySequence(QKeySequence::SelectNextWord) << 11 << 11 + << 16 << standard.at(0) << standard.at(0).mid(11, 5) + << QQuickTextInput::Normal << Qt::Key_Direction_L; QTest::newRow("select previous word") << standard.at(0) << QKeySequence(QKeySequence::SelectPreviousWord) << 11 << 11 - << 10 << standard.at(0) << standard.at(0).mid(10, 1); + << 10 << standard.at(0) << standard.at(0).mid(10, 1) + << QQuickTextInput::Normal << Qt::Key_Direction_L; QTest::newRow("delete (selection)") << standard.at(0) << QKeySequence(QKeySequence::Delete) << 12 << 15 - << 12 << (standard.at(0).mid(0, 12) + standard.at(0).mid(15)) << QString(); + << 12 << (standard.at(0).mid(0, 12) + standard.at(0).mid(15)) << QString() + << QQuickTextInput::Normal << Qt::Key_Direction_L; QTest::newRow("delete (no selection)") << standard.at(0) << QKeySequence(QKeySequence::Delete) << 15 << 15 - << 15 << (standard.at(0).mid(0, 15) + standard.at(0).mid(16)) << QString(); + << 15 << (standard.at(0).mid(0, 15) + standard.at(0).mid(16)) << QString() + << QQuickTextInput::Normal << Qt::Key_Direction_L; QTest::newRow("delete end of word") << standard.at(0) << QKeySequence(QKeySequence::DeleteEndOfWord) << 24 << 24 - << 24 << (standard.at(0).mid(0, 24) + standard.at(0).mid(27)) << QString(); + << 24 << (standard.at(0).mid(0, 24) + standard.at(0).mid(27)) << QString() + << QQuickTextInput::Normal << Qt::Key_Direction_L; QTest::newRow("delete start of word") << standard.at(0) << QKeySequence(QKeySequence::DeleteStartOfWord) << 7 << 7 - << 4 << (standard.at(0).mid(0, 4) + standard.at(0).mid(7)) << QString(); + << 4 << (standard.at(0).mid(0, 4) + standard.at(0).mid(7)) << QString() + << QQuickTextInput::Normal << Qt::Key_Direction_L; } void tst_qquicktextinput::keySequence() @@ -4152,6 +4412,8 @@ void tst_qquicktextinput::keySequence() QFETCH(int, cursorPosition); QFETCH(QString, expectedText); QFETCH(QString, selectedText); + QFETCH(QQuickTextInput::EchoMode, echoMode); + QFETCH(Qt::Key, layoutDirection); if (sequence.isEmpty()) { QSKIP("Key sequence is undefined"); @@ -4162,6 +4424,7 @@ void tst_qquicktextinput::keySequence() textInputComponent.setData(componentStr.toLatin1(), QUrl()); QQuickTextInput *textInput = qobject_cast<QQuickTextInput*>(textInputComponent.create()); QVERIFY(textInput != 0); + textInput->setEchoMode(echoMode); QQuickCanvas canvas; textInput->setParentItem(canvas.rootItem()); @@ -4170,6 +4433,8 @@ void tst_qquicktextinput::keySequence() QTest::qWaitForWindowShown(&canvas); QTRY_COMPARE(QGuiApplication::activeWindow(), &canvas); + simulateKey(&canvas, layoutDirection); + textInput->select(selectionStart, selectionEnd); simulateKeys(&canvas, sequence); @@ -4507,9 +4772,6 @@ void tst_qquicktextinput::undo_keypressevents_data() << Qt::Key_Delete << QKeySequence::Undo << Qt::Key_Right -#ifdef Q_OS_WIN //Mac(?) has a specialcase to handle jumping to the end of a selection - << Qt::Key_Left -#endif << (Qt::Key_Right | Qt::ShiftModifier) << (Qt::Key_Right | Qt::ShiftModifier) << Qt::Key_Delete; @@ -4586,6 +4848,19 @@ void tst_qquicktextinput::undo_keypressevents_data() expectedString << "123"; QTest::newRow("Inserts,moving,selection and overwriting") << keys << expectedString; + } { + KeyList keys; + QStringList expectedString; + + // inserting '123' + keys << "123" + << QKeySequence::Undo + << QKeySequence::Redo; + + expectedString << "123"; + expectedString << QString(); + + QTest::newRow("Insert,undo,redo") << keys << expectedString; } } @@ -4683,6 +4958,58 @@ void tst_qquicktextinput::QTBUG_19956_regexp() QVERIFY(canvas.rootObject()->property("acceptableInput").toBool()); } +void tst_qquicktextinput::implicitSize_data() +{ + QTest::addColumn<QString>("text"); + QTest::addColumn<QString>("wrap"); + QTest::newRow("plain") << "The quick red fox jumped over the lazy brown dog" << "TextInput.NoWrap"; + QTest::newRow("plain_wrap") << "The quick red fox jumped over the lazy brown dog" << "TextInput.Wrap"; +} + +void tst_qquicktextinput::implicitSize() +{ + QFETCH(QString, text); + QFETCH(QString, wrap); + QString componentStr = "import QtQuick 2.0\nTextInput { text: \"" + text + "\"; width: 50; wrapMode: " + wrap + " }"; + QDeclarativeComponent textComponent(&engine); + textComponent.setData(componentStr.toLatin1(), QUrl::fromLocalFile("")); + QQuickTextInput *textObject = qobject_cast<QQuickTextInput*>(textComponent.create()); + + QVERIFY(textObject->width() < textObject->implicitWidth()); + QVERIFY(textObject->height() == textObject->implicitHeight()); + + textObject->resetWidth(); + QVERIFY(textObject->width() == textObject->implicitWidth()); + QVERIFY(textObject->height() == textObject->implicitHeight()); +} + +void tst_qquicktextinput::implicitSizeBinding_data() +{ + implicitSize_data(); +} + +void tst_qquicktextinput::implicitSizeBinding() +{ + QFETCH(QString, text); + QFETCH(QString, wrap); + QString componentStr = "import QtQuick 2.0\nTextInput { text: \"" + text + "\"; width: implicitWidth; height: implicitHeight; wrapMode: " + wrap + " }"; + QDeclarativeComponent textComponent(&engine); + textComponent.setData(componentStr.toLatin1(), QUrl::fromLocalFile("")); + QScopedPointer<QObject> object(textComponent.create()); + QQuickTextInput *textObject = qobject_cast<QQuickTextInput *>(object.data()); + + QCOMPARE(textObject->width(), textObject->implicitWidth()); + QCOMPARE(textObject->height(), textObject->implicitHeight()); + + textObject->resetWidth(); + QCOMPARE(textObject->width(), textObject->implicitWidth()); + QCOMPARE(textObject->height(), textObject->implicitHeight()); + + textObject->resetHeight(); + QCOMPARE(textObject->width(), textObject->implicitWidth()); + QCOMPARE(textObject->height(), textObject->implicitHeight()); +} + void tst_qquicktextinput::negativeDimensions() { @@ -4696,6 +5023,482 @@ void tst_qquicktextinput::negativeDimensions() QCOMPARE(input->height(), qreal(-1)); } + +void tst_qquicktextinput::setInputMask_data() +{ + QTest::addColumn<QString>("mask"); + QTest::addColumn<QString>("input"); + QTest::addColumn<QString>("expectedText"); + QTest::addColumn<QString>("expectedDisplay"); + QTest::addColumn<bool>("insert_text"); + + // both keyboard and insert() + for (int i=0; i<2; i++) { + bool insert_text = i==0 ? false : true; + QString insert_mode = "keys "; + if (insert_text) + insert_mode = "insert "; + + QTest::newRow(QString(insert_mode + "ip_localhost").toLatin1()) + << QString("000.000.000.000") + << QString("127.0.0.1") + << QString("127.0.0.1") + << QString("127.0 .0 .1 ") + << bool(insert_text); + QTest::newRow(QString(insert_mode + "mac").toLatin1()) + << QString("HH:HH:HH:HH:HH:HH;#") + << QString("00:E0:81:21:9E:8E") + << QString("00:E0:81:21:9E:8E") + << QString("00:E0:81:21:9E:8E") + << bool(insert_text); + QTest::newRow(QString(insert_mode + "mac2").toLatin1()) + << QString("<HH:>HH:!HH:HH:HH:HH;#") + << QString("AAe081219E8E") + << QString("aa:E0:81:21:9E:8E") + << QString("aa:E0:81:21:9E:8E") + << bool(insert_text); + QTest::newRow(QString(insert_mode + "byte").toLatin1()) + << QString("BBBBBBBB;0") + << QString("11011001") + << QString("11111") + << QString("11011001") + << bool(insert_text); + QTest::newRow(QString(insert_mode + "halfbytes").toLatin1()) + << QString("bbbb.bbbb;-") + << QString("110. 0001") + << QString("110.0001") + << QString("110-.0001") + << bool(insert_text); + QTest::newRow(QString(insert_mode + "blank char same type as content").toLatin1()) + << QString("000.000.000.000;0") + << QString("127.0.0.1") + << QString("127...1") + << QString("127.000.000.100") + << bool(insert_text); + QTest::newRow(QString(insert_mode + "parts of ip_localhost").toLatin1()) + << QString("000.000.000.000") + << QString(".0.0.1") + << QString(".0.0.1") + << QString(" .0 .0 .1 ") + << bool(insert_text); + QTest::newRow(QString(insert_mode + "ip_null").toLatin1()) + << QString("000.000.000.000") + << QString() + << QString("...") + << QString(" . . . ") + << bool(insert_text); + QTest::newRow(QString(insert_mode + "ip_null_hash").toLatin1()) + << QString("000.000.000.000;#") + << QString() + << QString("...") + << QString("###.###.###.###") + << bool(insert_text); + QTest::newRow(QString(insert_mode + "ip_overflow").toLatin1()) + << QString("000.000.000.000") + << QString("1234123412341234") + << QString("123.412.341.234") + << QString("123.412.341.234") + << bool(insert_text); + QTest::newRow(QString(insert_mode + "uppercase").toLatin1()) + << QString(">AAAA") + << QString("AbCd") + << QString("ABCD") + << QString("ABCD") + << bool(insert_text); + QTest::newRow(QString(insert_mode + "lowercase").toLatin1()) + << QString("<AAAA") + << QString("AbCd") + << QString("abcd") + << QString("abcd") + << bool(insert_text); + + QTest::newRow(QString(insert_mode + "nocase").toLatin1()) + << QString("!AAAA") + << QString("AbCd") + << QString("AbCd") + << QString("AbCd") + << bool(insert_text); + QTest::newRow(QString(insert_mode + "nocase1").toLatin1()) + << QString("!A!A!A!A") + << QString("AbCd") + << QString("AbCd") + << QString("AbCd") + << bool(insert_text); + QTest::newRow(QString(insert_mode + "nocase2").toLatin1()) + << QString("AAAA") + << QString("AbCd") + << QString("AbCd") + << QString("AbCd") + << bool(insert_text); + + QTest::newRow(QString(insert_mode + "reserved").toLatin1()) + << QString("{n}[0]") + << QString("A9") + << QString("A9") + << QString("A9") + << bool(insert_text); + QTest::newRow(QString(insert_mode + "escape01").toLatin1()) + << QString("\\\\N\\\\n00") + << QString("9") + << QString("Nn9") + << QString("Nn9 ") + << bool(insert_text); + QTest::newRow(QString(insert_mode + "escape02").toLatin1()) + << QString("\\\\\\\\00") + << QString("0") + << QString("\\0") + << QString("\\0 ") + << bool(insert_text); + QTest::newRow(QString(insert_mode + "escape03").toLatin1()) + << QString("\\\\(00\\\\)") + << QString("0") + << QString("(0)") + << QString("(0 )") + << bool(insert_text); + + QTest::newRow(QString(insert_mode + "upper_lower_nocase1").toLatin1()) + << QString(">AAAA<AAAA!AAAA") + << QString("AbCdEfGhIjKl") + << QString("ABCDefghIjKl") + << QString("ABCDefghIjKl") + << bool(insert_text); + QTest::newRow(QString(insert_mode + "upper_lower_nocase2").toLatin1()) + << QString(">aaaa<aaaa!aaaa") + << QString("AbCdEfGhIjKl") + << QString("ABCDefghIjKl") + << QString("ABCDefghIjKl") + << bool(insert_text); + + QTest::newRow(QString(insert_mode + "exact_case1").toLatin1()) + << QString(">A<A<A>A>A<A!A!A") + << QString("AbCdEFGH") + << QString("AbcDEfGH") + << QString("AbcDEfGH") + << bool(insert_text); + QTest::newRow(QString(insert_mode + "exact_case2").toLatin1()) + << QString(">A<A<A>A>A<A!A!A") + << QString("aBcDefgh") + << QString("AbcDEfgh") + << QString("AbcDEfgh") + << bool(insert_text); + QTest::newRow(QString(insert_mode + "exact_case3").toLatin1()) + << QString(">a<a<a>a>a<a!a!a") + << QString("AbCdEFGH") + << QString("AbcDEfGH") + << QString("AbcDEfGH") + << bool(insert_text); + QTest::newRow(QString(insert_mode + "exact_case4").toLatin1()) + << QString(">a<a<a>a>a<a!a!a") + << QString("aBcDefgh") + << QString("AbcDEfgh") + << QString("AbcDEfgh") + << bool(insert_text); + QTest::newRow(QString(insert_mode + "exact_case5").toLatin1()) + << QString(">H<H<H>H>H<H!H!H") + << QString("aBcDef01") + << QString("AbcDEf01") + << QString("AbcDEf01") + << bool(insert_text); + QTest::newRow(QString(insert_mode + "exact_case6").toLatin1()) + << QString(">h<h<h>h>h<h!h!h") + << QString("aBcDef92") + << QString("AbcDEf92") + << QString("AbcDEf92") + << bool(insert_text); + + QTest::newRow(QString(insert_mode + "illegal_keys1").toLatin1()) + << QString("AAAAAAAA") + << QString("A2#a;.0!") + << QString("Aa") + << QString("Aa ") + << bool(insert_text); + QTest::newRow(QString(insert_mode + "illegal_keys2").toLatin1()) + << QString("AAAA") + << QString("f4f4f4f4") + << QString("ffff") + << QString("ffff") + << bool(insert_text); + QTest::newRow(QString(insert_mode + "blank=input").toLatin1()) + << QString("9999;0") + << QString("2004") + << QString("2004") + << QString("2004") + << bool(insert_text); + } +} + +void tst_qquicktextinput::setInputMask() +{ + QFETCH(QString, mask); + QFETCH(QString, input); + QFETCH(QString, expectedText); + QFETCH(QString, expectedDisplay); + QFETCH(bool, insert_text); + + QString componentStr = "import QtQuick 2.0\nTextInput { focus: true; inputMask: \"" + mask + "\" }"; + QQmlComponent textInputComponent(&engine); + textInputComponent.setData(componentStr.toLatin1(), QUrl()); + QQuickTextInput *textInput = qobject_cast<QQuickTextInput*>(textInputComponent.create()); + QVERIFY(textInput != 0); + + // then either insert using insert() or keyboard + if (insert_text) { + textInput->insert(0, input); + } else { + QQuickCanvas canvas; + textInput->setParentItem(canvas.rootItem()); + canvas.show(); + canvas.requestActivateWindow(); + QTest::qWaitForWindowShown(&canvas); + QTRY_COMPARE(QGuiApplication::activeWindow(), &canvas); + + simulateKey(&canvas, Qt::Key_Home); + for (int i = 0; i < input.length(); i++) + QTest::keyClick(&canvas, input.at(i).toLatin1()); + } + + QEXPECT_FAIL( "keys blank=input", "To eat blanks or not? Known issue. Task 43172", Abort); + QEXPECT_FAIL( "insert blank=input", "To eat blanks or not? Known issue. Task 43172", Abort); + + QCOMPARE(textInput->text(), expectedText); + QCOMPARE(textInput->displayText(), expectedDisplay); +} + +void tst_qquicktextinput::inputMask_data() +{ + QTest::addColumn<QString>("mask"); + QTest::addColumn<QString>("expectedMask"); + + // if no mask is set a nul string should be returned + QTest::newRow("nul 1") << QString("") << QString(); + QTest::newRow("nul 2") << QString() << QString(); + + // try different masks + QTest::newRow("mask 1") << QString("000.000.000.000") << QString("000.000.000.000; "); + QTest::newRow("mask 2") << QString("000.000.000.000;#") << QString("000.000.000.000;#"); + QTest::newRow("mask 3") << QString("AAA.aa.999.###;") << QString("AAA.aa.999.###; "); + QTest::newRow("mask 4") << QString(">abcdef<GHIJK") << QString(">abcdef<GHIJK; "); + + // set an invalid input mask... + // the current behaviour is that this exact (faulty) string is returned. + QTest::newRow("invalid") << QString("ABCDEFGHIKLMNOP;") << QString("ABCDEFGHIKLMNOP; "); + + // verify that we can unset the mask again + QTest::newRow("unset") << QString("") << QString(); +} + +void tst_qquicktextinput::inputMask() +{ + QFETCH(QString, mask); + QFETCH(QString, expectedMask); + + QString componentStr = "import QtQuick 2.0\nTextInput { focus: true; inputMask: \"" + mask + "\" }"; + QQmlComponent textInputComponent(&engine); + textInputComponent.setData(componentStr.toLatin1(), QUrl()); + QQuickTextInput *textInput = qobject_cast<QQuickTextInput*>(textInputComponent.create()); + QVERIFY(textInput != 0); + + QCOMPARE(textInput->inputMask(), expectedMask); +} + +void tst_qquicktextinput::clearInputMask() +{ + QString componentStr = "import QtQuick 2.0\nTextInput { focus: true; inputMask: \"000.000.000.000\" }"; + QQmlComponent textInputComponent(&engine); + textInputComponent.setData(componentStr.toLatin1(), QUrl()); + QQuickTextInput *textInput = qobject_cast<QQuickTextInput*>(textInputComponent.create()); + QVERIFY(textInput != 0); + + QVERIFY(textInput->inputMask() != QString()); + textInput->setInputMask(QString()); + QCOMPARE(textInput->inputMask(), QString()); +} + +void tst_qquicktextinput::keypress_inputMask_data() +{ + QTest::addColumn<QString>("mask"); + QTest::addColumn<KeyList>("keys"); + QTest::addColumn<QString>("expectedText"); + QTest::addColumn<QString>("expectedDisplayText"); + + { + KeyList keys; + // inserting 'A1.2B' + keys << Qt::Key_Home << "A1.2B"; + QTest::newRow("jumping on period(separator)") << QString("000.000;_") << keys << QString("1.2") << QString("1__.2__"); + } + { + KeyList keys; + // inserting '0!P3' + keys << Qt::Key_Home << "0!P3"; + QTest::newRow("jumping on input") << QString("D0.AA.XX.AA.00;_") << keys << QString("0..!P..3") << QString("_0.__.!P.__.3_"); + } + { + KeyList keys; + // pressing delete + keys << Qt::Key_Home + << Qt::Key_Delete; + QTest::newRow("delete") << QString("000.000;_") << keys << QString(".") << QString("___.___"); + } + { + KeyList keys; + // selecting all and delete + keys << Qt::Key_Home + << Key(Qt::ShiftModifier, Qt::Key_End) + << Qt::Key_Delete; + QTest::newRow("deleting all") << QString("000.000;_") << keys << QString(".") << QString("___.___"); + } + { + KeyList keys; + // inserting '12.12' then two backspaces + keys << Qt::Key_Home << "12.12" << Qt::Key_Backspace << Qt::Key_Backspace; + QTest::newRow("backspace") << QString("000.000;_") << keys << QString("12.") << QString("12_.___"); + } + { + KeyList keys; + // inserting '12ab' + keys << Qt::Key_Home << "12ab"; + QTest::newRow("uppercase") << QString("9999 >AA;_") << keys << QString("12 AB") << QString("12__ AB"); + } +} + +void tst_qquicktextinput::keypress_inputMask() +{ + QFETCH(QString, mask); + QFETCH(KeyList, keys); + QFETCH(QString, expectedText); + QFETCH(QString, expectedDisplayText); + + QString componentStr = "import QtQuick 2.0\nTextInput { focus: true; inputMask: \"" + mask + "\" }"; + QQmlComponent textInputComponent(&engine); + textInputComponent.setData(componentStr.toLatin1(), QUrl()); + QQuickTextInput *textInput = qobject_cast<QQuickTextInput*>(textInputComponent.create()); + QVERIFY(textInput != 0); + + QQuickCanvas canvas; + textInput->setParentItem(canvas.rootItem()); + canvas.show(); + canvas.requestActivateWindow(); + QTest::qWaitForWindowShown(&canvas); + QTRY_COMPARE(QGuiApplication::activeWindow(), &canvas); + + simulateKeys(&canvas, keys); + + QCOMPARE(textInput->text(), expectedText); + QCOMPARE(textInput->displayText(), expectedDisplayText); +} + + +void tst_qquicktextinput::hasAcceptableInputMask_data() +{ + QTest::addColumn<QString>("optionalMask"); + QTest::addColumn<QString>("requiredMask"); + QTest::addColumn<QString>("invalid"); + QTest::addColumn<QString>("valid"); + + QTest::newRow("Alphabetic optional and required") + << QString("aaaa") << QString("AAAA") << QString("ab") << QString("abcd"); + QTest::newRow("Alphanumeric optional and require") + << QString("nnnn") << QString("NNNN") << QString("R2") << QString("R2D2"); + QTest::newRow("Any optional and required") + << QString("xxxx") << QString("XXXX") << QString("+-") << QString("+-*/"); + QTest::newRow("Numeric (0-9) required") + << QString("0000") << QString("9999") << QString("11") << QString("1138"); + QTest::newRow("Numeric (1-9) optional and required") + << QString("dddd") << QString("DDDD") << QString("12") << QString("1234"); +} + +void tst_qquicktextinput::hasAcceptableInputMask() +{ + QFETCH(QString, optionalMask); + QFETCH(QString, requiredMask); + QFETCH(QString, invalid); + QFETCH(QString, valid); + + QString componentStr = "import QtQuick 2.0\nTextInput { focus: true; inputMask: \"" + optionalMask + "\" }"; + QQmlComponent textInputComponent(&engine); + textInputComponent.setData(componentStr.toLatin1(), QUrl()); + QQuickTextInput *textInput = qobject_cast<QQuickTextInput*>(textInputComponent.create()); + QVERIFY(textInput != 0); + + QQuickCanvas canvas; + textInput->setParentItem(canvas.rootItem()); + canvas.show(); + canvas.requestActivateWindow(); + QTest::qWaitForWindowShown(&canvas); + QTRY_COMPARE(QGuiApplication::activeWindow(), &canvas); + + // test that invalid input (for required) work for optionalMask + textInput->setText(invalid); + QVERIFY(textInput->hasAcceptableInput()); + + // at the moment we don't strip the blank character if it is valid input, this makes the test between x vs X useless + QEXPECT_FAIL( "Any optional and required", "To eat blanks or not? Known issue. Task 43172", Abort); + + // test requiredMask + textInput->setInputMask(requiredMask); + textInput->setText(invalid); + QVERIFY(!textInput->hasAcceptableInput()); + + textInput->setText(valid); + QVERIFY(textInput->hasAcceptableInput()); +} + +void tst_qquicktextinput::maskCharacter_data() +{ + QTest::addColumn<QString>("mask"); + QTest::addColumn<QString>("input"); + QTest::addColumn<bool>("expectedValid"); + + QTest::newRow("Hex") << QString("H") + << QString("0123456789abcdefABCDEF") << true; + QTest::newRow("hex") << QString("h") + << QString("0123456789abcdefABCDEF") << true; + QTest::newRow("HexInvalid") << QString("H") + << QString("ghijklmnopqrstuvwxyzGHIJKLMNOPQRSTUVWXYZ") + << false; + QTest::newRow("hexInvalid") << QString("h") + << QString("ghijklmnopqrstuvwxyzGHIJKLMNOPQRSTUVWXYZ") + << false; + QTest::newRow("Bin") << QString("B") + << QString("01") << true; + QTest::newRow("bin") << QString("b") + << QString("01") << true; + QTest::newRow("BinInvalid") << QString("B") + << QString("23456789qwertyuiopasdfghjklzxcvbnm") + << false; + QTest::newRow("binInvalid") << QString("b") + << QString("23456789qwertyuiopasdfghjklzxcvbnm") + << false; +} + +void tst_qquicktextinput::maskCharacter() +{ + QFETCH(QString, mask); + QFETCH(QString, input); + QFETCH(bool, expectedValid); + + QString componentStr = "import QtQuick 2.0\nTextInput { focus: true; inputMask: \"" + mask + "\" }"; + QQmlComponent textInputComponent(&engine); + textInputComponent.setData(componentStr.toLatin1(), QUrl()); + QQuickTextInput *textInput = qobject_cast<QQuickTextInput*>(textInputComponent.create()); + QVERIFY(textInput != 0); + + QQuickCanvas canvas; + textInput->setParentItem(canvas.rootItem()); + canvas.show(); + canvas.requestActivateWindow(); + QTest::qWaitForWindowShown(&canvas); + QTRY_COMPARE(QGuiApplication::activeWindow(), &canvas); + + for (int i = 0; i < input.size(); ++i) { + QString in = QString(input.at(i)); + QString expected = expectedValid ? in : QString(); + textInput->setText(QString(input.at(i))); + QCOMPARE(textInput->text(), expected); + } +} + QTEST_MAIN(tst_qquicktextinput) #include "tst_qquicktextinput.moc" diff --git a/tests/system/sys_listview.qtt b/tests/system/sys_listview.qtt new file mode 100644 index 0000000000..efd116fa92 --- /dev/null +++ b/tests/system/sys_listview.qtt @@ -0,0 +1,221 @@ +/**************************************************************************** +** +** Copyright (C) 2012 Nokia Corporation and/or its subsidiary(-ies). +** Contact: http://www.qt-project.org/ +** +** This file is part of the test suite of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** GNU Lesser General Public License Usage +** 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, Nokia gives you certain additional +** rights. These rights are described in the Nokia 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. +** +** Other Usage +** Alternatively, this file may be used in accordance with the terms and +** conditions contained in a signed written agreement between you and Nokia. +** +** +** +** +** +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +//TESTED_COMPONENT=qtdeclarative + +testcase = { + + altering_listview_primary_properties: function() + { + // Test Meta-data + testTitle = "Altering ListView primary properties"; + testBinary = "alteredViews.qml"; + testSource: "$QTDIR/qtdeclarative/tests/system/listview"; + testGoal = "Verify that the model and delegate for a ListView can be changed"; + testPreconditions = "None"; + testGroups = "BAT,QtQuick 2.0"; + + // Test Steps + prompt(twiki('---+++ ' + testTitle + '<br><br> + *Goal:* ' + testGoal + '<br> + *Pre-Requisites:* ' + testPreconditions + '<br> + *Tested Binary:* ' + testBinary + '<br> + | *Step* | *Verification* | + | Run '+testBinary+' | Application has started, showing a ListView | + | | The view shows items named Model1_1 - 5, and the delegates are white with a black border | + | Press the Mod button | The view now shows items named Model2_1 - 5 | + | Press Del | The delegates are now golden with a black border | + | Press Mod, then Del | The view again shows items named Model1_1 - 5, and are white |')); + }, + + altering_listview_orientation: function() + { + // Test Meta-data + testTitle = "Altering ListView orientation"; + testBinary = "alteredViews.qml"; + testSource: "$QTDIR/qtdeclarative/tests/system/listview"; + testGoal = "Verify that the orientation of a listview can be changed at runtime"; + testPreconditions = "None"; + testGroups = "BAT,QtQuick 2.0"; + + // Test Steps + prompt(twiki('---+++ ' + testTitle + '<br><br> + *Goal:* ' + testGoal + '<br> + *Pre-Requisites:* ' + testPreconditions + '<br> + *Tested Binary:* ' + testBinary + '<br> + | *Step* | *Verification* | + | Run '+testBinary+' | Application has started, showing a ListView | + | | The view shows items named Model1_1 - 5, and the delegates are white with a black border | + | Press the Ori button | The view is now displayed in a horizontal orientation | + | | The delegates should have resized quickly and smoothly, and the text rotated anticlockwise (both animated) | + | Press Del | The delegates are now golden with a black border, still in horizontal orientation | + | Press Ori | The view again shows in a vertical orientation, with the golden delegates |')); + }, + + basic_view_transition: function() + { + // Test Meta-data + testTitle = "Basic View Transitions"; + testBinary = "viewTransitions.qml"; + testSource: "$QTDIR/qtdeclarative/tests/system/listview"; + testGoal = "Verify a basic transition can be applied to a ListView action"; + testPreconditions = "None"; + testGroups = "BAT,QtQuick 2.0"; + testRequirements = "QTBUG-21504: Enable transitions for add/move/remove operations on views"; + + // Test Steps + prompt(twiki('---+++ ' + testTitle + '<br><br> + *Goal:* ' + testGoal + '<br> + *Pre-Requisites:* ' + testPreconditions + '<br> + *Tested Binary:* ' + testBinary + '<br> + | *Step* | *Verification* | + | Run '+testBinary+' | Application has started, showing a ListView | + | Press the Set A button | The Set A button shows green | + | Press Add | A new yellow item fades in after the currently selected item | + | | The other items slide down, with a slight delay for each item, giving it a flowing effect | + | Select the new item | | + | Press To Top | The item changes to light blue and moves to the top, curving out to the right of the ListView | + | Select an item near the top and press Remove | The selected item fades out | + | | The other items slide up, with a slight delay for each item, giving it a flowing effect |')); + }, + + switching_view_transition: function() { + // Test Meta-data + testTitle = "Switching View Transitions"; + testBinary = "viewTransitions.qml"; + testSource: "$QTDIR/qtdeclarative/tests/system/listview"; + testGoal = "Verify a basic ListView transition can be changed to another"; + testPreconditions = "None"; + testGroups = "BAT,QtQuick 2.0"; + testRequirements = "QTBUG-21504: Enable transitions for add/move/remove operations on views"; + + // Test Steps + prompt(twiki('---+++ ' + testTitle + '<br><br> + *Goal:* ' + testGoal + '<br> + *Pre-Requisites:* ' + testPreconditions + '<br> + *Tested Binary:* ' + testBinary + '<br> + | *Step* | *Verification* | + | Run '+testBinary+' | Application has started, showing a ListView | + | Press the Set A button | The Set A button shows green | + | Press Add | A new yellow item fades in after the currently selected item | + | | The other items slide down, with a slight delay for each item, giving it a flowing effect | + | Select the new item | | + | Press To Top | The item changes to light blue and moves to the top, curving out to the right of the ListView | + | Select an item near the top and press Remove | The selected item fades out | + | | The other items slide up, with a slight delay for each item, giving it a flowing effect | + | Press the Set B button | The Set B button shows green | + | Press Add | A new yellow item pops in after the currently selected item | + | | The other items tumble down in a disorderly manner | + | Select the new item | | + | Press To Top | The item changes from red to light blue and curves out to the right of the ListView, bouncing in at the top | + | Select an item near the top and press Remove | The selected item pops out | + | | The other items slide up, with a slight delay for each item, giving it a flowing effect |')); + }, + + different_transitions_for_every_operation: function() { + // Test Meta-data + testTitle = "Different Transitions for all Operations"; + testBinary = "viewTransitions.qml"; + testSource: "$QTDIR/qtdeclarative/tests/system/listview"; + testGoal = "Verify a different Transition can be applied to displacement from adding, moving and removing."; + testPreconditions = "None"; + testGroups = "BAT,QtQuick 2.0"; + testRequirements = "QTBUG-21504: Enable transitions for add/move/remove operations on views"; + + // Test Steps + prompt(twiki('---+++ ' + testTitle + '<br><br> + *Goal:* ' + testGoal + '<br> + *Pre-Requisites:* ' + testPreconditions + '<br> + *Tested Binary:* ' + testBinary + '<br> + | *Step* | *Verification* | + | Run '+testBinary+' | Application has started, showing a ListView | + | Press the Set C button | The Set C button shows green | + | Press Add | A new yellow item swoops in from the side | + | | The other items jitter down, with a slight delay for each item | + | Select the new item | | + | Press To Top | The item changes from red to light blue and moves to the top, curving out to the right of the ListView | + | | The other items bounce down in a solid block | + | Select an item near the top and press Remove | The selected item fades out in a flashing manner | + | | The other items snap up, with a slight delay for each item | + | Press the Append button a few times | Each added item swoops in from alternating sides | ')); + }, + + delegates_and_effects: function() { + testTitle = "Delegates and effects"; + testBinary = "viewTransitions.qml"; + testSource: "$QTDIR/qtdeclarative/tests/system/listview"; + testGoal = "Verify a delegate in transition can show effects."; + testPreconditions = "None"; + testGroups = "BAT,QtQuick 2.0"; + testRequirements = "QTBUG-21504: Enable transitions for add/move/remove operations on views"; + + // Test Steps + prompt(twiki('---+++ ' + testTitle + '<br><br> + *Goal:* ' + testGoal + '<br> + *Pre-Requisites:* ' + testPreconditions + '<br> + *Tested Binary:* ' + testBinary + '<br> + | *Step* | *Verification* | + | Run '+testBinary+' | Application has started, showing a ListView | + | Press the Set D button | The Set D button shows green | + | Select a lower item | The item is highlighted | + | Press To Top | The item fades to red particles, shifts to the top, and fades back to a normal delegate | + | | The other items shuffle down |')); + }, + + attached_onremove_property: function() { + testTitle = "Using the attached onRemove property"; + testBinary = "onRemove.qml"; + testSource: "$QTDIR/qtdeclarative/tests/system/listview"; + testGoal = "Verify the onRemove attached property can be assigned."; + testPreconditions = "None"; + testGroups = "BAT,QtQuick 2.0"; + testRequirements = "QTBUG-21504: Enable transitions for add/move/remove operations on views"; + + // Test Steps + prompt(twiki('---+++ ' + testTitle + '<br><br> + *Goal:* ' + testGoal + '<br> + *Pre-Requisites:* ' + testPreconditions + '<br> + *Tested Binary:* ' + testBinary + '<br> + | *Step* | *Verification* | + | Run '+testBinary+' | Application has started, showing a ListView | + | Press the <b>-</b> button | The selected item disappears in a shower of sparks |')); + } +} diff --git a/tests/testapplications/listview/alteredViews.qml b/tests/testapplications/listview/alteredViews.qml new file mode 100644 index 0000000000..26aa678db2 --- /dev/null +++ b/tests/testapplications/listview/alteredViews.qml @@ -0,0 +1,153 @@ +/**************************************************************************** +** +** Copyright (C) 2012 Nokia Corporation and/or its subsidiary(-ies). +** Contact: http://www.qt-project.org/ +** +** 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 Nokia Corporation 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 { + width: 300 + height: 400 + + ListView { + id: listview + model: model1 + delegate: delegate1 + anchors.fill: parent + anchors.margins: 20 + } + + Component { + id: delegate1 + Rectangle { + height: listview.orientation == ListView.Horizontal ? 260 : 50 + Behavior on height { NumberAnimation { duration: 500 } } + width: listview.orientation == ListView.Horizontal ? 50 : 260 + Behavior on width { NumberAnimation { duration: 500 } } + border.color: "black" + Text { + anchors.centerIn: parent; color: "black"; text: model.name + rotation: listview.orientation == ListView.Horizontal ? -90 : 0 + Behavior on rotation { NumberAnimation { duration: 500 } } + + } + } + } + + Component { + id: delegate2 + Rectangle { + height: listview.orientation == ListView.Horizontal ? 260 : 50 + Behavior on height { NumberAnimation { duration: 500 } } + width: listview.orientation == ListView.Horizontal ? 50 : 260 + Behavior on width { NumberAnimation { duration: 500 } } + color: "goldenrod"; border.color: "black" + Text { + anchors.centerIn: parent; color: "royalblue"; text: model.name + rotation: listview.orientation == ListView.Horizontal ? -90 : 0 + Behavior on rotation { NumberAnimation { duration: 1500 } } + } + } + + } + + Column { + Rectangle { + height: 50 + width: 50 + color: "blue" + border.color: "orange" + Text { + anchors.centerIn: parent + text: "Mod" + } + MouseArea { + anchors.fill: parent + onClicked: listview.model = listview.model == model2 ? model1 : model2 + } + } + + Rectangle { + height: 50 + width: 50 + color: "blue" + border.color: "orange" + Text { + anchors.centerIn: parent + text: "Del" + } + MouseArea { + anchors.fill: parent + onClicked: listview.delegate = listview.delegate == delegate2 ? delegate1 : delegate2 + } + } + + Rectangle { + height: 50 + width: 50 + color: "blue" + border.color: "orange" + Text { + anchors.centerIn: parent + text: "Ori" + } + MouseArea { + anchors.fill: parent + onClicked: listview.orientation = listview.orientation == ListView.Horizontal ? ListView.Vertical : ListView.Horizontal + } + } + } + + ListModel { + id: model1 + ListElement { name: "model1_1" } + ListElement { name: "model1_2" } + ListElement { name: "model1_3" } + ListElement { name: "model1_4" } + ListElement { name: "model1_5" } + } + + ListModel { + id: model2 + ListElement { name: "model2_1" } + ListElement { name: "model2_2" } + ListElement { name: "model2_3" } + ListElement { name: "model2_4" } + ListElement { name: "model2_5" } + } +} diff --git a/tests/testapplications/listview/onRemove.qml b/tests/testapplications/listview/onRemove.qml new file mode 100644 index 0000000000..2c1d52a40e --- /dev/null +++ b/tests/testapplications/listview/onRemove.qml @@ -0,0 +1,156 @@ +/**************************************************************************** +** +** Copyright (C) 2012 Nokia Corporation and/or its subsidiary(-ies). +** Contact: http://www.qt-project.org/ +** +** 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 Nokia Corporation and its Subsidiary(-ies) nor +** the names of its contributors may be used to endorse or promote +** products derived from this software without specific prior written +** permission. +** +** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE." +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +import QtQuick 2.0 +import QtQuick.Particles 2.0 +Item { + id: root + width: 450; height: 600 + + Component { + id: viewDelegate + + Rectangle { + id: item + signal boom + Connections { + target: item + onBoom: emitter.burst(1000) + } + + width: 225; height: 40 + border.width: ListView.isCurrentItem ? 3 : 1 + z: ListView.isCurrentItem ? 100 : 1 + color: original ? "lightsteelblue" : "yellow" + objectName: name + Text { x: 10; text: name; font.pixelSize: 20 } + MouseArea { anchors.fill: parent; onClicked: listview.currentIndex = index } + + Emitter { + id: emitter + system: ps + anchors.fill: parent + enabled: false + speed: AngleDirection { + angle: 0 + angleVariation: 360 + magnitude: 50 + magnitudeVariation: 50 + } + lifeSpan: 2000 + } + + ListView.onRemove: SequentialAnimation { + PropertyAction { target: item; property: "ListView.delayRemove"; value: true } + PropertyAction { target: item; property: "opacity"; value: 0 } + ScriptAction { script: item.boom() } + PauseAnimation { duration: 1000 } + PropertyAction { target: item; property: "ListView.delayRemove"; value: false } + } + } + } + + + ListView { + id: listview + width: 225; height: 500 + anchors.centerIn: parent + delegate: viewDelegate + header: Rectangle { + height: 50; width: 225 + color: "blue" + Text { anchors.centerIn: parent; text: "Transitions!"; color: "goldenrod" } + } + model: ListModel { + id: a_model + ListElement { name: "Item A"; original: true } + ListElement { name: "Item B"; original: true } + ListElement { name: "Item C"; original: true } + ListElement { name: "Item D"; original: true } + ListElement { name: "Item E"; original: true } + ListElement { name: "Item F"; original: true } + } + Rectangle { + anchors.fill: parent + color: "transparent" + border.color: "black" + } + + } + + ParticleSystem { + id: ps + ImageParticle { + id: imageparticle + source: "star.png" + color: "blue" + } + } + Column { + spacing: 2 + Rectangle { + gradient: Gradient { + GradientStop { position: 0.0; color: "darkgray" } + GradientStop { position: 0.5; color: "lightgray" } + GradientStop { position: 1.0; color: "darkgray" } + } + radius: 6 + border.color: "black" + height: 50; width: 80 + Text { anchors.centerIn: parent; text: "+"; font.pixelSize: 25; font.bold: true } + MouseArea { anchors.fill: parent; onClicked: listview.model.insert(listview.currentIndex+1, {"name": "New item", "original": false } ) } + } + Rectangle { + gradient: Gradient { + GradientStop { position: 0.0; color: "darkgray" } + GradientStop { position: 0.5; color: "lightgray" } + GradientStop { position: 1.0; color: "darkgray" } + } + radius: 6 + border.color: "black" + height: 50; width: 80 + Text { anchors.centerIn: parent; text: "-"; font.pixelSize: 25; font.bold: true } + MouseArea { anchors.fill: parent; onClicked: listview.model.remove(listview.currentIndex) } + } + } +} + + + diff --git a/tests/testapplications/listview/star.png b/tests/testapplications/listview/star.png Binary files differnew file mode 100644 index 0000000000..0d592cfa87 --- /dev/null +++ b/tests/testapplications/listview/star.png diff --git a/tests/testapplications/listview/viewTransitions.qml b/tests/testapplications/listview/viewTransitions.qml new file mode 100644 index 0000000000..6ed7cc1619 --- /dev/null +++ b/tests/testapplications/listview/viewTransitions.qml @@ -0,0 +1,479 @@ +/**************************************************************************** +** +** Copyright (C) 2012 Nokia Corporation and/or its subsidiary(-ies). +** Contact: http://www.qt-project.org/ +** +** 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 Nokia Corporation and its Subsidiary(-ies) nor +** the names of its contributors may be used to endorse or promote +** products derived from this software without specific prior written +** permission. +** +** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE." +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +import QtQuick 2.0 +import QtQuick.Particles 2.0 +Item { + id: root + width: 450; height: 600 + + property int currentSet: 0 + property bool useStock: false + + Component { + id: viewDelegate + + Rectangle { + id: item + property bool movn: false + property int parts: 0 + + width: 225; height: 40 + border.width: ListView.isCurrentItem ? 3 : 1 + z: ListView.isCurrentItem ? 100 : 1 + color: original ? "lightsteelblue" : "yellow" + objectName: name + Text { x: 10; text: name; font.pixelSize: 20 } + MouseArea { anchors.fill: parent; onClicked: listview.currentIndex = index } + + Emitter { + id: emitter + system: ps + anchors.fill: parent + enabled: false + speed: AngleDirection { + angle: 0 + angleVariation: 360 + magnitude: 50 + magnitudeVariation: 50 + } + } + Emitter { + id: emitter2 + system: ps + anchors.fill: parent + enabled: item.movn + emitRate: parts + speed: AngleDirection { + angle: 0 + angleVariation: 360 + magnitude: 2 + magnitudeVariation: 5 + } + } + } + } + + ListView { + id: listview + width: 225; height: 500 + anchors.centerIn: parent + delegate: viewDelegate + header: Rectangle { + height: 50; width: 225 + color: "blue" + Text { anchors.centerIn: parent; text: "Transitions!"; color: "goldenrod" } + } + model: ListModel { + id: a_model + ListElement { name: "Item A"; original: true } + ListElement { name: "Item B"; original: true } + ListElement { name: "Item C"; original: true } + ListElement { name: "Item D"; original: true } + ListElement { name: "Item E"; original: true } + ListElement { name: "Item F"; original: true } + } + Rectangle { + anchors.fill: parent + color: "transparent" + border.color: "black" + } + + } + + ParticleSystem { + id: ps + ImageParticle { + id: imageparticle + source: "star.png" + color: "red" + } + } + + + /* States (Selected operation Transitions) */ + states: [ + State { + name: "setA" + when: currentSet == 0 + PropertyChanges { + target: listview + add: a_add + move: a_move + remove: a_remove + displaced: a_displaced + } + }, + State { + name: "setB" + when: currentSet == 1 + PropertyChanges { + target: listview + add: b_add + move: b_move + remove: b_remove + displaced: b_displaced + } + }, + State { + name: "setC" + when: currentSet == 2 + PropertyChanges { + target: listview + add: c_add + move: c_move + remove: c_remove + addDisplaced: c_addDisplaced + moveDisplaced: c_moveDisplaced + removeDisplaced: c_removeDisplaced + } + }, + State { + name: "setD" + when: currentSet == 3 + PropertyChanges { + target: listview + move: d_move + moveDisplaced: d_moveDisplaced + } + PropertyChanges { + target: root + useStock: true + } + } + ] + + /* Transitions */ + Transition { + id: a_add + ParallelAnimation { + NumberAnimation { target: a_add.ViewTransition.item; properties: "opacity"; from: 0; to: 1; duration: 1000 } + } + } + Transition { + id: a_remove + SequentialAnimation { + NumberAnimation { target: a_remove.ViewTransition.item; properties: "opacity"; from: 1; to: 0; duration: 1000 } + } + } + Transition { + id: a_move + ColorAnimation { target: a_move.ViewTransition.item; properties: "color"; to: "lightsteelblue"; duration: 1000 } + PathAnimation { + duration: 1000 + target: a_move.ViewTransition.item + path: Path { + PathCurve { x: a_move.ViewTransition.destination.x + 150; y: a_move.ViewTransition.destination.y + 100 } + PathCurve { x: a_move.ViewTransition.destination.x + 150; y: a_move.ViewTransition.destination.y } + PathCurve { x: a_move.ViewTransition.destination.x; y: a_move.ViewTransition.destination.y } + } + } + } + Transition { + id: a_displaced + PropertyAction { target: a_displaced.ViewTransition.item; property: "color"; value: "lightsteelblue" } + ParallelAnimation { + NumberAnimation { target: a_displaced.ViewTransition.item; property: "opacity"; to: 1; duration: 250 } + SequentialAnimation { + PauseAnimation { duration: a_displaced.ViewTransition.index * 200 } + NumberAnimation { properties: "x,y"; duration: 1000; easing.type: Easing.OutQuad } + } + } + } + + + Transition { + id: b_add + SequentialAnimation { + NumberAnimation { target: b_add.ViewTransition.item; properties: "scale"; from: 1; to: 1.3; duration: 100 } + NumberAnimation { target: b_add.ViewTransition.item; properties: "scale"; from: 1.3; to: 1; duration: 500; easing.type: Easing.OutBounce } + } + } + Transition { + id: b_move + SequentialAnimation { + PauseAnimation { duration: b_move.ViewTransition.index * 100 } + ParallelAnimation { + ColorAnimation { target: b_move.ViewTransition.item; properties: "color"; from: "red"; to: "lightsteelblue"; duration: 2000 } + SequentialAnimation { + PathAnimation { + duration: 1000 + target: b_move.ViewTransition.item + path: Path { + PathCurve { x: b_move.ViewTransition.destination.x + 150; y: b_move.ViewTransition.destination.y + 100 } + PathCurve { relativeX: 30; relativeY: -100 } + } + } + NumberAnimation { properties: "x,y"; duration: 1000; easing.type: Easing.OutBounce } + } + } + } + } + Transition { + id: b_remove + SequentialAnimation { + NumberAnimation { target: b_remove.ViewTransition.item; properties: "opacity"; from: 1; to: 0; duration: 1000 } + } + } + Transition { + id: b_displaced + PropertyAction { target: b_displaced.ViewTransition.item; property: "color"; value: "lightsteelblue" } + SequentialAnimation { + PauseAnimation { duration: b_displaced.ViewTransition.item.x == 0 ? b_displaced.ViewTransition.index * 200 : 0 } + NumberAnimation { properties: "x,y"; duration: 1000; easing.type: Easing.OutBounce } + } + } + + + Transition { + id: c_add + NumberAnimation { property: "opacity"; from: 0; to: 1.0; duration: 400 } + NumberAnimation { property: "scale"; from: 0; to: 1.0; duration: 400 } + property int xoff + xoff: c_add.ViewTransition.index % 2 == 0 ? 200 : -200 + PathAnimation { + duration: 1000 + path: Path { + startX: c_add.ViewTransition.destination.x + c_add.xoff + startY: c_add.ViewTransition.destination.y + 200 + PathCurve { relativeX: -100; relativeY: -50 } + PathCurve { relativeX: 50; relativeY: -150 } + PathCurve { + x: c_add.ViewTransition.destination.x + y: c_add.ViewTransition.destination.y + } + } + } + } + Transition { + id: c_move + ColorAnimation { target: c_move.ViewTransition.item; properties: "color"; from: "red"; to: "lightsteelblue"; duration: 1000 } + PathAnimation { + duration: 1000 + target: c_move.ViewTransition.item + path: Path { + PathCurve { x: c_move.ViewTransition.destination.x + 150; y: c_move.ViewTransition.destination.y + 100 } + PathCurve { x: c_move.ViewTransition.destination.x + 150; y: c_move.ViewTransition.destination.y } + PathCurve { x: c_move.ViewTransition.destination.x; y: c_move.ViewTransition.destination.y } + } + } + } + Transition { + id: c_remove + PropertyAnimation { target: c_remove.ViewTransition.item; properties: "opacity"; to: 0; duration: 3000; easing.type: Easing.OutInBounce } + } + Transition { + id: c_addDisplaced + + PropertyAction { property: "color"; value: "lightsteelblue" } + PropertyAction { property: "opacity"; value: 1.0 } + PropertyAction { property: "scale"; value: 1.0 } + SequentialAnimation { + PauseAnimation { duration: c_addDisplaced.ViewTransition.index * 200 } + NumberAnimation { properties: "x,y"; duration: 1000; easing.type: Easing.OutElastic } + } + + } + Transition { + id: c_moveDisplaced + + PropertyAction { property: "color"; value: "lightsteelblue" } + PropertyAction { property: "opacity"; value: 1.0 } + PropertyAction { property: "scale"; value: 1.0 } + SequentialAnimation { + NumberAnimation { properties: "x,y"; duration: 1000; easing.type: Easing.OutBounce } + } + + } + Transition { + id: c_removeDisplaced + + PropertyAction { property: "color"; value: "lightsteelblue" } + PropertyAction { property: "opacity"; value: 1.0 } + PropertyAction { property: "scale"; value: 1.0 } + SequentialAnimation { + PauseAnimation { duration: (c_removeDisplaced.ViewTransition.index * 200) + 3000 } + NumberAnimation { properties: "x,y"; duration: 1000; easing.type: Easing.OutElastic } + } + + } + Transition { + id: d_move + SequentialAnimation { + PropertyAction { target: d_move.ViewTransition.item; property: "movn"; value: true } + ParallelAnimation { + NumberAnimation { target: d_move.ViewTransition.item; properties: "opacity"; to: 0; duration: 2000 } + NumberAnimation { target: d_move.ViewTransition.item; properties: "parts"; to: 500; duration: 2000 } + } + NumberAnimation { properties: "x,y"; duration: 1000*(d_move.ViewTransition.index+1) } + ParallelAnimation { + NumberAnimation { target: d_move.ViewTransition.item; properties: "opacity"; to: 1; duration: 2000 } + NumberAnimation { target: d_move.ViewTransition.item; properties: "parts"; to: 0; duration: 2000 } + } + PropertyAction { target: d_move.ViewTransition.item; property: "movn"; value: false } + } + } + + Transition { + id: d_moveDisplaced + PropertyAction { target: d_moveDisplaced.ViewTransition.item; property: "color"; value: "lightsteelblue" } + SequentialAnimation { + PauseAnimation { duration: 500*(d_moveDisplaced.ViewTransition.index+1) } + NumberAnimation { properties: "x,y"; duration: 1000; easing.type: Easing.OutQuad } + } + } + + /* Buttons */ + Column { + spacing: 2 + Rectangle { + gradient: Gradient { + GradientStop { position: 0.0; color: "darkgray" } + GradientStop { position: 0.5; color: "lightgray" } + GradientStop { position: 1.0; color: "darkgray" } + } + radius: 6 + border.color: "black" + height: 50; width: 80 + Text { anchors.centerIn: parent; text: "To Top" } + MouseArea { anchors.fill: parent; onClicked: listview.model.move(listview.currentIndex, 0, 1) } + } + Rectangle { + gradient: Gradient { + GradientStop { position: 0.0; color: "darkgray" } + GradientStop { position: 0.5; color: "lightgray" } + GradientStop { position: 1.0; color: "darkgray" } + } + radius: 6 + border.color: "black" + height: 50; width: 80 + Text { anchors.centerIn: parent; text: "Add" } + MouseArea { + anchors.fill: parent + onClicked: listview.model.insert(listview.currentIndex+1, {"name": "New item", "original": false } ) + } + } + Rectangle { + gradient: Gradient { + GradientStop { position: 0.0; color: "darkgray" } + GradientStop { position: 0.5; color: "lightgray" } + GradientStop { position: 1.0; color: "darkgray" } + } + radius: 6 + border.color: "black" + height: 50; width: 80 + Text { anchors.centerIn: parent; text: "Remove" } + MouseArea { + anchors.fill: parent + onClicked: listview.model.remove(listview.currentIndex) + } + } + Rectangle { + gradient: Gradient { + GradientStop { position: 0.0; color: "darkgray" } + GradientStop { position: 0.5; color: "lightgray" } + GradientStop { position: 1.0; color: "darkgray" } + } + radius: 6 + border.color: "black" + height: 50; width: 80 + Text { anchors.centerIn: parent; text: "Append" } + MouseArea { + anchors.fill: parent + onClicked: listview.model.append({"name": "New item", "original": false }) + } + } + } + Column { + spacing: 2 + anchors.right: parent.right + anchors.rightMargin: 2 + Rectangle { + gradient: Gradient { + GradientStop { position: 0.0; color: "darkgray" } + GradientStop { position: 0.5; color: currentSet == 0 ? "green" : "lightgray" + ColorAnimation on color { duration: 1000 } + } + GradientStop { position: 1.0; color: "darkgray" } + } + radius: 6 + border.color: "black" + height: 50; width: 80 + Text { anchors.centerIn: parent; text: "Set A" } + MouseArea { anchors.fill: parent; onClicked: { currentSet = 0 } } + } + Rectangle { + gradient: Gradient { + GradientStop { position: 0.0; color: "darkgray" } + GradientStop { position: 0.5; color: currentSet == 1 ? "green" : "lightgray" } + GradientStop { position: 1.0; color: "darkgray" } + } + radius: 6 + border.color: "black" + height: 50; width: 80 + Text { anchors.centerIn: parent; text: "Set B" } + MouseArea { anchors.fill: parent; onClicked: { currentSet = 1 } } + } + Rectangle { + gradient: Gradient { + GradientStop { position: 0.0; color: "darkgray" } + GradientStop { position: 0.5; color: currentSet == 2 ? "green" : "lightgray" } + GradientStop { position: 1.0; color: "darkgray" } + } + radius: 6 + border.color: "black" + height: 50; width: 80 + Text { anchors.centerIn: parent; text: "Set C" } + MouseArea { anchors.fill: parent; onClicked: { currentSet = 2 } } + } + Rectangle { + gradient: Gradient { + GradientStop { position: 0.0; color: "darkgray" } + GradientStop { position: 0.5; color: currentSet == 3 ? "green" : "lightgray" } + GradientStop { position: 1.0; color: "darkgray" } + } + radius: 6 + border.color: "black" + height: 50; width: 80 + Text { anchors.centerIn: parent; text: "Set D" } + MouseArea { anchors.fill: parent; onClicked: { currentSet = 3 } } + } + } +} |