summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--src/declarative/qml/qmlcompiler.cpp4
-rw-r--r--src/declarative/qml/qmlcomponent.h3
-rw-r--r--src/declarative/qml/qmlengine.cpp75
-rw-r--r--tests/auto/declarative/qmlengine/tst_qmlengine.cpp53
-rw-r--r--tests/auto/declarative/qmlqt/data/createComponent.qml23
-rw-r--r--tests/auto/declarative/qmlqt/data/createComponentData.qml5
-rw-r--r--tests/auto/declarative/qmlqt/data/createQmlObject.qml31
-rw-r--r--tests/auto/declarative/qmlqt/tst_qmlqt.cpp53
8 files changed, 211 insertions, 36 deletions
diff --git a/src/declarative/qml/qmlcompiler.cpp b/src/declarative/qml/qmlcompiler.cpp
index 2cb44a3..9000339 100644
--- a/src/declarative/qml/qmlcompiler.cpp
+++ b/src/declarative/qml/qmlcompiler.cpp
@@ -2044,12 +2044,12 @@ bool QmlCompiler::checkDynamicMeta(QmlParser::Object *obj)
if (prop.isDefaultProperty) {
if (seenDefaultProperty)
- COMPILE_EXCEPTION(obj, qApp->translate("QmlCompiler","Duplicate default property"));
+ COMPILE_EXCEPTION(&prop, qApp->translate("QmlCompiler","Duplicate default property"));
seenDefaultProperty = true;
}
if (propNames.contains(prop.name))
- COMPILE_EXCEPTION(obj, qApp->translate("QmlCompiler","Duplicate property name"));
+ COMPILE_EXCEPTION(&prop, qApp->translate("QmlCompiler","Duplicate property name"));
propNames.insert(prop.name);
}
diff --git a/src/declarative/qml/qmlcomponent.h b/src/declarative/qml/qmlcomponent.h
index 835bdc5..0abb58f 100644
--- a/src/declarative/qml/qmlcomponent.h
+++ b/src/declarative/qml/qmlcomponent.h
@@ -67,6 +67,9 @@ class Q_DECLARATIVE_EXPORT QmlComponent : public QObject
Q_PROPERTY(bool isReady READ isReady NOTIFY statusChanged)
Q_PROPERTY(bool isError READ isError NOTIFY statusChanged)
Q_PROPERTY(bool isLoading READ isLoading NOTIFY statusChanged)
+ Q_PROPERTY(qreal progress READ progress NOTIFY progressChanged)
+ Q_PROPERTY(Status status READ status NOTIFY statusChanged)
+ Q_PROPERTY(QUrl url READ url CONSTANT)
public:
QmlComponent(QObject *parent = 0);
diff --git a/src/declarative/qml/qmlengine.cpp b/src/declarative/qml/qmlengine.cpp
index 1483c8c..9abd216 100644
--- a/src/declarative/qml/qmlengine.cpp
+++ b/src/declarative/qml/qmlengine.cpp
@@ -572,23 +572,23 @@ QmlContext *QmlEnginePrivate::getContext(QScriptContext *ctxt)
QScriptValue QmlEnginePrivate::createComponent(QScriptContext *ctxt,
QScriptEngine *engine)
{
- QmlComponent* c;
-
QmlEnginePrivate *activeEnginePriv =
static_cast<QmlScriptEngine*>(engine)->p;
QmlEngine* activeEngine = activeEnginePriv->q_func();
QmlContext* context = activeEnginePriv->getContext(ctxt);
+ Q_ASSERT(context);
if(ctxt->argumentCount() != 1) {
- c = new QmlComponent(activeEngine);
+ return engine->nullValue();
}else{
- QUrl url = QUrl(context->resolvedUrl(ctxt->argument(0).toString()));
- if(!url.isValid())
- url = QUrl(ctxt->argument(0).toString());
- c = new QmlComponent(activeEngine, url, activeEngine);
+ QString arg = ctxt->argument(0).toString();
+ if (arg.isEmpty())
+ return engine->nullValue();
+ QUrl url = QUrl(context->resolvedUrl(arg));
+ QmlComponent *c = new QmlComponent(activeEngine, url, activeEngine);
+ c->setCreationContext(context);
+ return activeEnginePriv->objectClass->newQObject(c, qMetaTypeId<QmlComponent*>());
}
- c->setCreationContext(context);
- return engine->newQObject(c);
}
QScriptValue QmlEnginePrivate::createQmlObject(QScriptContext *ctxt, QScriptEngine *engine)
@@ -597,57 +597,64 @@ QScriptValue QmlEnginePrivate::createQmlObject(QScriptContext *ctxt, QScriptEngi
static_cast<QmlScriptEngine*>(engine)->p;
QmlEngine* activeEngine = activeEnginePriv->q_func();
- if(ctxt->argumentCount() < 2)
+ if(ctxt->argumentCount() < 2 || ctxt->argumentCount() > 3)
return engine->nullValue();
+ QmlContext* context = activeEnginePriv->getContext(ctxt);
+ Q_ASSERT(context);
+
QString qml = ctxt->argument(0).toString();
+ if (qml.isEmpty())
+ return engine->nullValue();
+
QUrl url;
if(ctxt->argumentCount() > 2)
url = QUrl(ctxt->argument(2).toString());
+
+ if (url.isValid() && url.isRelative())
+ url = context->resolvedUrl(url);
+
QObject *parentArg = activeEnginePriv->objectClass->toQObject(ctxt->argument(1));
- QmlContext *qmlCtxt = qmlContext(parentArg);
- if(!parentArg || !qmlCtxt){
- //TODO: Could use a qmlInfo() like function for script functions
- qWarning() << "createQmlObject called with invalid parent object";
+ if(!parentArg)
return engine->nullValue();
- }
- if (url.isEmpty()) {
- url = qmlCtxt->resolvedUrl(QUrl(QLatin1String("<Unknown File>")));
- } else {
- url = qmlCtxt->resolvedUrl(url);
- }
QmlComponent component(activeEngine, qml.toUtf8(), url);
if(component.isError()) {
QList<QmlError> errors = component.errors();
- qWarning() <<"QmlEngine::createQmlObject():";
+ qWarning().nospace() << "QmlEngine::createQmlObject():";
foreach (const QmlError &error, errors)
- qWarning() << " " << error;
+ qWarning().nospace() << " " << error;
+
+ return engine->nullValue();
+ }
+
+ if (!component.isReady()) {
+ qWarning().nospace() << "QmlEngine::createQmlObject(): Component is not ready";
return engine->nullValue();
}
- QObject *obj = component.create(qmlCtxt);
+ QObject *obj = component.create(context);
if(component.isError()) {
QList<QmlError> errors = component.errors();
- qWarning() <<"QmlEngine::createQmlObject():";
+ qWarning().nospace() << "QmlEngine::createQmlObject():";
foreach (const QmlError &error, errors)
- qWarning() << " " << error;
+ qWarning().nospace() << " " << error;
return engine->nullValue();
}
- if(obj) {
- obj->setParent(parentArg);
- QGraphicsObject* gobj = qobject_cast<QGraphicsObject*>(obj);
- QGraphicsObject* gparent = qobject_cast<QGraphicsObject*>(parentArg);
- if(gobj && gparent)
- gobj->setParentItem(gparent);
- return qmlScriptObject(obj, activeEngine);
- }
- return engine->nullValue();
+ Q_ASSERT(obj);
+
+ obj->setParent(parentArg);
+ QGraphicsObject* gobj = qobject_cast<QGraphicsObject*>(obj);
+ QGraphicsObject* gparent = qobject_cast<QGraphicsObject*>(parentArg);
+ if(gobj && gparent)
+ gobj->setParentItem(gparent);
+
+ return qmlScriptObject(obj, activeEngine);
}
QScriptValue QmlEnginePrivate::vector(QScriptContext *ctxt, QScriptEngine *engine)
diff --git a/tests/auto/declarative/qmlengine/tst_qmlengine.cpp b/tests/auto/declarative/qmlengine/tst_qmlengine.cpp
index ef1eee5..54f916f 100644
--- a/tests/auto/declarative/qmlengine/tst_qmlengine.cpp
+++ b/tests/auto/declarative/qmlengine/tst_qmlengine.cpp
@@ -47,6 +47,7 @@
#include <QDir>
#include <QDesktopServices>
#include <QDebug>
+#include <QmlComponent>
class tst_qmlengine : public QObject
{
@@ -60,6 +61,7 @@ private slots:
void baseUrl();
void contextForObject();
void offlineStoragePath();
+ void clearComponentCache();
};
void tst_qmlengine::rootContext()
@@ -171,6 +173,57 @@ void tst_qmlengine::offlineStoragePath()
QCOMPARE(engine.offlineStoragePath(), QDir::homePath());
}
+void tst_qmlengine::clearComponentCache()
+{
+ QmlEngine engine;
+
+ // Create original qml file
+ {
+ QFile file("temp.qml");
+ QVERIFY(file.open(QIODevice::WriteOnly));
+ file.write("import Qt 4.6\nObject {\nproperty int test: 10\n}\n");
+ file.close();
+ }
+
+ // Test "test" property
+ {
+ QmlComponent component(&engine, "temp.qml");
+ QObject *obj = component.create();
+ QVERIFY(obj != 0);
+ QCOMPARE(obj->property("test").toInt(), 10);
+ delete obj;
+ }
+
+ // Modify qml file
+ {
+ QFile file("temp.qml");
+ QVERIFY(file.open(QIODevice::WriteOnly));
+ file.write("import Qt 4.6\nObject {\nproperty int test: 11\n}\n");
+ file.close();
+ }
+
+ // Test cache hit
+ {
+ QmlComponent component(&engine, "temp.qml");
+ QObject *obj = component.create();
+ QVERIFY(obj != 0);
+ QCOMPARE(obj->property("test").toInt(), 10);
+ delete obj;
+ }
+
+ // Clear cache
+ engine.clearComponentCache();
+
+ // Test cache refresh
+ {
+ QmlComponent component(&engine, "temp.qml");
+ QObject *obj = component.create();
+ QVERIFY(obj != 0);
+ QCOMPARE(obj->property("test").toInt(), 11);
+ delete obj;
+ }
+}
+
QTEST_MAIN(tst_qmlengine)
#include "tst_qmlengine.moc"
diff --git a/tests/auto/declarative/qmlqt/data/createComponent.qml b/tests/auto/declarative/qmlqt/data/createComponent.qml
new file mode 100644
index 0000000..57f50d8
--- /dev/null
+++ b/tests/auto/declarative/qmlqt/data/createComponent.qml
@@ -0,0 +1,23 @@
+import Qt 4.6
+
+Object {
+ property bool incorrectArgCount1: false
+ property bool incorrectArgCount2: false
+ property bool emptyArg: false
+
+ property string relativeUrl
+ property string absoluteUrl
+
+ Component.onCompleted: {
+ // Test that using incorrect argument count returns a null object
+ incorrectArgCount1 = (createComponent() == null);
+ incorrectArgCount2 = (createComponent("main.qml", 10) == null);
+ emptyArg = (createComponent("") == null);
+
+ var r = createComponent("createComponentData.qml");
+ relativeUrl = r.url;
+
+ var a = createComponent("http://www.example.com/test.qml");
+ absoluteUrl = a.url;
+ }
+}
diff --git a/tests/auto/declarative/qmlqt/data/createComponentData.qml b/tests/auto/declarative/qmlqt/data/createComponentData.qml
new file mode 100644
index 0000000..145fe78
--- /dev/null
+++ b/tests/auto/declarative/qmlqt/data/createComponentData.qml
@@ -0,0 +1,5 @@
+import Qt 4.6
+
+Object {
+ property int test: 1913
+}
diff --git a/tests/auto/declarative/qmlqt/data/createQmlObject.qml b/tests/auto/declarative/qmlqt/data/createQmlObject.qml
new file mode 100644
index 0000000..8e8919a
--- /dev/null
+++ b/tests/auto/declarative/qmlqt/data/createQmlObject.qml
@@ -0,0 +1,31 @@
+import Qt 4.6
+
+Item {
+ id: root
+
+ property bool incorrectArgCount1: false
+ property bool incorrectArgCount2: false
+ property bool emptyArg: false
+ property bool noParent: false
+ property bool notReady: false
+ property bool runtimeError: false
+ property bool errors: false
+
+ property bool success: false
+
+ Component.onCompleted: {
+ // errors
+ incorrectArgCount1 = (createQmlObject() == null);
+ incorrectArgCount2 = (createQmlObject("import Qt 4.6\nObject{}", root, "main.qml", 10) == null);
+ emptyArg = (createQmlObject("", root) == null);
+ errors = (createQmlObject("import Qt 4.6\nObject{\nproperty int test: 13\nproperty int test: 13\n}", root, "main.qml") == null);
+ noParent = (createQmlObject("import Qt 4.6\nObject{\nproperty int test: 13}", 0) == null);
+ notReady = (createQmlObject("import Qt 4.6\nObject{\nBlah{}\n}", root, "http://www.example.com/main.qml") == null);
+ runtimeError = (createQmlObject("import Qt 4.6\nObject{property int test\nonTestChanged: Object{}\n}", root) == null);
+
+ var o = createQmlObject("import Qt 4.6\nObject{\nproperty int test: 13\n}", root);
+ success = (o.test == 13);
+
+ createQmlObject("import Qt 4.6\nItem {}\n", root);
+ }
+}
diff --git a/tests/auto/declarative/qmlqt/tst_qmlqt.cpp b/tests/auto/declarative/qmlqt/tst_qmlqt.cpp
index 4d09aee..292102a 100644
--- a/tests/auto/declarative/qmlqt/tst_qmlqt.cpp
+++ b/tests/auto/declarative/qmlqt/tst_qmlqt.cpp
@@ -47,6 +47,7 @@
#include <QDir>
#include <QVector3D>
#include <QCryptographicHash>
+#include <QmlGraphicsItem>
class tst_qmlqt : public QObject
{
@@ -69,6 +70,8 @@ private slots:
void playSound();
void openUrlExternally();
void md5();
+ void createComponent();
+ void createQmlObject();
private:
QmlEngine engine;
@@ -299,6 +302,56 @@ void tst_qmlqt::md5()
delete object;
}
+void tst_qmlqt::createComponent()
+{
+ QmlComponent component(&engine, TEST_FILE("createComponent.qml"));
+ QObject *object = component.create();
+ QVERIFY(object != 0);
+
+ QCOMPARE(object->property("incorrectArgCount1").toBool(), true);
+ QCOMPARE(object->property("incorrectArgCount2").toBool(), true);
+ QCOMPARE(object->property("emptyArg").toBool(), true);
+
+ QCOMPARE(object->property("absoluteUrl").toString(), QString("http://www.example.com/test.qml"));
+ QCOMPARE(object->property("relativeUrl").toString(), TEST_FILE("createComponentData.qml").toString());
+
+ delete object;
+}
+
+void tst_qmlqt::createQmlObject()
+{
+ QmlComponent component(&engine, TEST_FILE("createQmlObject.qml"));
+
+ QString warning1 = "QmlEngine::createQmlObject():";
+ QString warning2 = " " + TEST_FILE("main.qml").toString() + ":4:1: Duplicate property name";
+ QString warning3 = "QmlEngine::createQmlObject(): Component is not ready";
+ QString warning4 = "QmlEngine::createQmlObject():";
+ QString warning5 = " :3: Cannot assign object type QObject with no default method";
+
+ QTest::ignoreMessage(QtWarningMsg, qPrintable(warning1));
+ QTest::ignoreMessage(QtWarningMsg, qPrintable(warning2));
+ QTest::ignoreMessage(QtWarningMsg, qPrintable(warning3));
+ QTest::ignoreMessage(QtWarningMsg, qPrintable(warning4));
+ QTest::ignoreMessage(QtWarningMsg, qPrintable(warning5));
+
+ QObject *object = component.create();
+ QVERIFY(object != 0);
+
+ QCOMPARE(object->property("incorrectArgCount1").toBool(), true);
+ QCOMPARE(object->property("incorrectArgCount2").toBool(), true);
+ QCOMPARE(object->property("emptyArg").toBool(), true);
+ QCOMPARE(object->property("errors").toBool(), true);
+ QCOMPARE(object->property("noParent").toBool(), true);
+ QCOMPARE(object->property("notReady").toBool(), true);
+ QCOMPARE(object->property("runtimeError").toBool(), true);
+ QCOMPARE(object->property("success").toBool(), true);
+
+ QmlGraphicsItem *item = qobject_cast<QmlGraphicsItem *>(object);
+ QVERIFY(item != 0);
+ QVERIFY(item->childItems().count() == 1);
+
+ delete object;
+}
QTEST_MAIN(tst_qmlqt)