Add qmlRegisterType for Composite Types
authorAlan Alpert <aalpert@rim.com>
Thu, 24 Jan 2013 20:13:57 +0000 (12:13 -0800)
committerThe Qt Project <gerrit-noreply@qt-project.org>
Mon, 18 Feb 2013 18:46:02 +0000 (19:46 +0100)
This is equivalent functionality to registering a composite type in a
qmldir file, a type name in a versioned module is associated with a
given file. This function now allows that to be done easily from C++.

Change-Id: I1cf44b92c3ad7fee593f4f84773c35b56253e628
Reviewed-by: Shawn Rutledge <shawn.rutledge@digia.com>

src/qml/doc/src/qmlfunctions.qdoc
src/qml/qml/qqml.h
tests/auto/qml/qqmllanguage/data/badCompositeRegistration.1.errors.txt [new file with mode: 0644]
tests/auto/qml/qqmllanguage/data/badCompositeRegistration.1.qml [new file with mode: 0644]
tests/auto/qml/qqmllanguage/data/badCompositeRegistration.2.errors.txt [new file with mode: 0644]
tests/auto/qml/qqmllanguage/data/badCompositeRegistration.2.qml [new file with mode: 0644]
tests/auto/qml/qqmllanguage/data/registeredCompositeType.qml [new file with mode: 0644]
tests/auto/qml/qqmllanguage/tst_qqmllanguage.cpp
tests/auto/qml/qqmlmetatype/tst_qqmlmetatype.cpp

index da62dda..81b8fd5 100644 (file)
    \endcode
 
   */
+
+/*!
+  \fn int qmlRegisterType(const QUrl &url, const char *uri, int versionMajor, int versionMinor, const char *qmlName);
+  \relates QQmlEngine
+
+  This function registers a type in the QML system with the name \a qmlName, in the library imported from \a uri having the
+  version number composed from \a versionMajor and \a versionMinor. The type is defined by the QML file located at \a url. The
+  url must be an absolute URL, i.e. url.isRelative() == false.
+
+  Normally QML files can be loaded as types directly from other QML files, or using a qmldir file. This function allows
+  registration of files to types from a C++ module, such as when the type mapping needs to be procedurally determined at startup.
+
+  #include <QtQml> to use this function.
+
+  Returns non-zero if the registration was sucessful.
+*/
+
index 877e6c1..7e6e0d1 100644 (file)
@@ -49,6 +49,7 @@
 
 #include <QtCore/qbytearray.h>
 #include <QtCore/qmetaobject.h>
+#include <QtCore/qdebug.h>
 
 #define QML_VERSION     0x020000
 #define QML_VERSION_STR "2.0"
@@ -463,6 +464,26 @@ inline int qmlRegisterSingletonType(const char *uri, int versionMajor, int versi
     return QQmlPrivate::qmlregister(QQmlPrivate::SingletonRegistration, &api);
 }
 
+
+inline int qmlRegisterType(const QUrl &url, const char *uri, int versionMajor, int versionMinor, const char *qmlName)
+{
+    if (url.isRelative()) { 
+        // User input check must go here, because QQmlPrivate::qmlregister is also used internally for composite types
+        qWarning() << "qmlRegisterType requires absolute URLs.";
+        return 0;
+    }
+
+    QQmlPrivate::RegisterCompositeType type = {
+        url,
+        uri,
+        versionMajor,
+        versionMinor,
+        qmlName
+    };
+
+    return QQmlPrivate::qmlregister(QQmlPrivate::CompositeRegistration, &type);
+}
+
 QT_END_NAMESPACE
 
 QML_DECLARE_TYPE(QObject)
diff --git a/tests/auto/qml/qqmllanguage/data/badCompositeRegistration.1.errors.txt b/tests/auto/qml/qqmllanguage/data/badCompositeRegistration.1.errors.txt
new file mode 100644 (file)
index 0000000..7a75447
--- /dev/null
@@ -0,0 +1,2 @@
+3:1:Type RegisteredCompositeType2 unavailable
+-1:-1:File not found
diff --git a/tests/auto/qml/qqmllanguage/data/badCompositeRegistration.1.qml b/tests/auto/qml/qqmllanguage/data/badCompositeRegistration.1.qml
new file mode 100644 (file)
index 0000000..915a613
--- /dev/null
@@ -0,0 +1,3 @@
+import Test 1.0
+
+RegisteredCompositeType2 {}
diff --git a/tests/auto/qml/qqmllanguage/data/badCompositeRegistration.2.errors.txt b/tests/auto/qml/qqmllanguage/data/badCompositeRegistration.2.errors.txt
new file mode 100644 (file)
index 0000000..0272619
--- /dev/null
@@ -0,0 +1,2 @@
+3:1:Type RegisteredCompositeType3 unavailable
+1:1:Expected a qualified name id
diff --git a/tests/auto/qml/qqmllanguage/data/badCompositeRegistration.2.qml b/tests/auto/qml/qqmllanguage/data/badCompositeRegistration.2.qml
new file mode 100644 (file)
index 0000000..43d7f3e
--- /dev/null
@@ -0,0 +1,3 @@
+import Test 1.0
+
+RegisteredCompositeType3 {}
diff --git a/tests/auto/qml/qqmllanguage/data/registeredCompositeType.qml b/tests/auto/qml/qqmllanguage/data/registeredCompositeType.qml
new file mode 100644 (file)
index 0000000..f633a14
--- /dev/null
@@ -0,0 +1,3 @@
+import Test 1.0
+
+RegisteredCompositeType {}
index 222548d..3121d10 100644 (file)
@@ -139,6 +139,7 @@ private slots:
     void registrationOrder();
     void readonly();
     void receivers();
+    void registeredCompositeType();
 
     void basicRemote_data();
     void basicRemote();
@@ -467,6 +468,9 @@ void tst_qqmllanguage::errors_data()
     QTest::newRow("invalidTypeName.4") << "invalidTypeName.4.qml" << "invalidTypeName.4.errors.txt" << false;
 
     QTest::newRow("Major version isolation") << "majorVersionIsolation.qml" << "majorVersionIsolation.errors.txt" << false;
+
+    QTest::newRow("badCompositeRegistration.1") << "badCompositeRegistration.1.qml" << "badCompositeRegistration.1.errors.txt" << false;
+    QTest::newRow("badCompositeRegistration.2") << "badCompositeRegistration.2.qml" << "badCompositeRegistration.2.errors.txt" << false;
 }
 
 
@@ -2771,6 +2775,10 @@ void tst_qqmllanguage::initTestCase()
     QQmlMetaType::registerCustomStringConverter(qMetaTypeId<MyCustomVariantType>(), myCustomVariantTypeConverter);
 
     registerTypes();
+    // Registered here because it uses testFileUrl
+    qmlRegisterType(testFileUrl("CompositeType.qml"), "Test", 1, 0, "RegisteredCompositeType");
+    qmlRegisterType(testFileUrl("CompositeType.DoesNotExist.qml"), "Test", 1, 0, "RegisteredCompositeType2");
+    qmlRegisterType(testFileUrl("invalidRoot.1.qml"), "Test", 1, 0, "RegisteredCompositeType3");
 
     // Registering the TestType class in other modules should have no adverse effects
     qmlRegisterType<TestType>("org.qtproject.TestPre", 1, 0, "Test");
@@ -2915,6 +2923,17 @@ void tst_qqmllanguage::receivers()
     delete o;
 }
 
+void tst_qqmllanguage::registeredCompositeType()
+{
+    QQmlComponent component(&engine, testFileUrl("registeredCompositeType.qml"));
+
+    VERIFY_ERRORS(0);
+    QObject *o = component.create();
+    QVERIFY(o != 0);
+
+    delete o;
+}
+
 // QTBUG-18268
 void tst_qqmllanguage::remoteLoadCrash()
 {
index 03d2f0b..9002322 100644 (file)
@@ -129,11 +129,7 @@ void tst_qqmlmetatype::initTestCase()
     qmlRegisterType<ValueInterceptorTestType>("Test", 1, 0, "ValueInterceptorTestType");
 
     QUrl testTypeUrl(testFileUrl("CompositeType.qml"));
-    //TODO: Replace this with public API version when added
-    QQmlPrivate::RegisterCompositeType regStruct = {
-        testTypeUrl,"Test", 1, 0, "TestTypeComposite"
-    };
-    QQmlPrivate::qmlregister(QQmlPrivate::CompositeRegistration, &regStruct);
+    qmlRegisterType(testTypeUrl, "Test", 1, 0, "TestTypeComposite");
 }
 
 void tst_qqmlmetatype::qmlParserStatusCast()