qmlRegisterRevision clashes with qmlRegisterUncreatableType
authorMartin Jones <martin.jones@nokia.com>
Fri, 22 Jun 2012 06:56:27 +0000 (16:56 +1000)
committerQt by Nokia <qt-info@nokia.com>
Mon, 25 Jun 2012 02:50:01 +0000 (04:50 +0200)
Add template<typename T, int metaObjectRevision>
qmlRegisterUncreatableType() in order to register an uncreatable type
for a particular revision.

Task-number: QTBUG-23278
Change-Id: Ic165e41c8176916929cf19eb9bf6eef4b5bee1eb
Reviewed-by: Lincoln Ramsay <lincoln.ramsay@nokia.com>
Reviewed-by: Chris Adams <christopher.adams@nokia.com>
src/qml/doc/src/cppintegration/registercpptypes.qdoc
src/qml/qml/qqml.h
tests/auto/qml/qqmllanguage/testtypes.cpp
tests/auto/qml/qqmllanguage/testtypes.h
tests/auto/qml/qqmllanguage/tst_qqmllanguage.cpp

index 9ccf428..0e11883 100644 (file)
@@ -265,6 +265,9 @@ int qmlRegisterType(const char *uri, int versionMajor, int versionMinor, const c
     \code
     template<typename T, int metaObjectRevision>
     int qmlRegisterRevision(const char *uri, int versionMajor, int versionMinor)
+
+    template<typename T, int metaObjectRevision>
+    int qmlRegisterUncreatableType(const char *uri, int versionMajor, int versionMinor, const char *qmlName, const QString& reason)
     \endcode
 
     For example, if \c BaseObject is changed and now has a revision 1, you can specify that
index c7092a6..528f8e6 100644 (file)
@@ -167,6 +167,37 @@ int qmlRegisterUncreatableType(const char *uri, int versionMajor, int versionMin
     return QQmlPrivate::qmlregister(QQmlPrivate::TypeRegistration, &type);
 }
 
+template<typename T, int metaObjectRevision>
+int qmlRegisterUncreatableType(const char *uri, int versionMajor, int versionMinor, const char *qmlName, const QString& reason)
+{
+    QML_GETTYPENAMES
+
+    QQmlPrivate::RegisterType type = {
+        1,
+
+        qRegisterNormalizedMetaType<T *>(pointerName.constData()),
+        qRegisterNormalizedMetaType<QQmlListProperty<T> >(listName.constData()),
+        0, 0,
+        reason,
+
+        uri, versionMajor, versionMinor, qmlName, &T::staticMetaObject,
+
+        QQmlPrivate::attachedPropertiesFunc<T>(),
+        QQmlPrivate::attachedPropertiesMetaObject<T>(),
+
+        QQmlPrivate::StaticCastSelector<T,QQmlParserStatus>::cast(),
+        QQmlPrivate::StaticCastSelector<T,QQmlPropertyValueSource>::cast(),
+        QQmlPrivate::StaticCastSelector<T,QQmlPropertyValueInterceptor>::cast(),
+
+        0, 0,
+
+        0,
+        metaObjectRevision
+    };
+
+    return QQmlPrivate::qmlregister(QQmlPrivate::TypeRegistration, &type);
+}
+
 template<typename T>
 int qmlRegisterType(const char *uri, int versionMajor, int versionMinor, const char *qmlName)
 {
index beb0f59..561300d 100644 (file)
@@ -83,6 +83,12 @@ void registerTypes()
     qmlRegisterType<MyEnumDerivedClass>("Test",1,0,"MyEnumDerivedClass");
 
     qmlRegisterType<MyReceiversTestObject>("Test",1,0,"MyReceiversTestObject");
+
+    qmlRegisterUncreatableType<MyUncreateableBaseClass>("Test", 1, 0, "MyUncreateableBaseClass", "Cannot create MyUncreateableBaseClass");
+    qmlRegisterType<MyCreateableDerivedClass>("Test", 1, 0, "MyCreateableDerivedClass");
+
+    qmlRegisterUncreatableType<MyUncreateableBaseClass,1>("Test", 1, 1, "MyUncreateableBaseClass", "Cannot create MyUncreateableBaseClass");
+    qmlRegisterType<MyCreateableDerivedClass,1>("Test", 1, 1, "MyCreateableDerivedClass");
 }
 
 QVariant myCustomVariantTypeConverter(const QString &data)
index f84e42f..50b6089 100644 (file)
@@ -910,6 +910,41 @@ protected:
     qreal m_p5;
 };
 
+class MyUncreateableBaseClass : public QObject
+{
+    Q_OBJECT
+    Q_PROPERTY(bool prop1 READ prop1 WRITE setprop1)
+    Q_PROPERTY(bool prop2 READ prop2 WRITE setprop2 REVISION 1)
+    Q_PROPERTY(bool prop3 READ prop3 WRITE setprop3 REVISION 1)
+public:
+    explicit MyUncreateableBaseClass(bool arg, QObject *parent = 0)
+        : QObject(parent), _prop1(false), _prop2(false), _prop3(false)
+    {
+    }
+
+    bool _prop1;
+    bool prop1() const { return _prop1; }
+    void setprop1(bool p) { _prop1 = p; }
+    bool _prop2;
+    bool prop2() const { return _prop2; }
+    void setprop2(bool p) { _prop2 = p; }
+    bool _prop3;
+    bool prop3() const { return _prop3; }
+    void setprop3(bool p) { _prop3 = p; }
+};
+
+class MyCreateableDerivedClass : public MyUncreateableBaseClass
+{
+    Q_OBJECT
+    Q_PROPERTY(bool prop2 READ prop2 WRITE setprop2 REVISION 1)
+
+public:
+    MyCreateableDerivedClass(QObject *parent = 0)
+        : MyUncreateableBaseClass(true, parent)
+    {
+    }
+};
+
 class MyVersion2Class : public QObject
 {
     Q_OBJECT
index 6349cd3..2f2f0a7 100644 (file)
@@ -176,6 +176,9 @@ private slots:
     void revisions();
     void revisionOverloads();
 
+    void subclassedUncreateableRevision_data();
+    void subclassedUncreateableRevision();
+
     void propertyInit();
     void remoteLoadCrash();
     void signalWithDefaultArg();
@@ -2540,6 +2543,59 @@ void tst_qqmllanguage::revisionOverloads()
     }
 }
 
+void tst_qqmllanguage::subclassedUncreateableRevision_data()
+{
+    QTest::addColumn<QString>("version");
+    QTest::addColumn<QString>("prop");
+    QTest::addColumn<bool>("shouldWork");
+
+    QTest::newRow("prop1 exists in 1.0") << "1.0" << "prop1" << true;
+    QTest::newRow("prop2 does not exist in 1.0") << "1.0" << "prop2" << false;
+    QTest::newRow("prop3 does not exist in 1.0") << "1.0" << "prop3" << false;
+
+    QTest::newRow("prop1 exists in 1.1") << "1.1" << "prop1" << true;
+    QTest::newRow("prop2 works because it's re-declared in Derived") << "1.1" << "prop2" << true;
+    QTest::newRow("prop3 only works if the Base REVISION 1 is picked up") << "1.1" << "prop3" << true;
+
+}
+
+void tst_qqmllanguage::subclassedUncreateableRevision()
+{
+    QFETCH(QString, version);
+    QFETCH(QString, prop);
+    QFETCH(bool, shouldWork);
+
+    {
+        QQmlEngine engine;
+        QString qml = QString("import QtQuick 2.0\nimport Test %1\nMyUncreateableBaseClass {}").arg(version);
+        QQmlComponent c(&engine);
+        QTest::ignoreMessage(QtWarningMsg, "QQmlComponent: Component is not ready");
+        c.setData(qml.toUtf8(), QUrl::fromLocalFile(QDir::currentPath()));
+        QObject *obj = c.create();
+        QCOMPARE(obj, static_cast<QObject*>(0));
+        QCOMPARE(c.errors().count(), 1);
+        QCOMPARE(c.errors().first().description(), QString("Cannot create MyUncreateableBaseClass"));
+    }
+
+    QQmlEngine engine;
+    QString qml = QString("import QtQuick 2.0\nimport Test %1\nMyCreateableDerivedClass {\n%3: true\n}").arg(version).arg(prop);
+    QQmlComponent c(&engine);
+    if (!shouldWork)
+        QTest::ignoreMessage(QtWarningMsg, "QQmlComponent: Component is not ready");
+    c.setData(qml.toUtf8(), QUrl::fromLocalFile(QDir::currentPath()));
+    QObject *obj = c.create();
+    if (!shouldWork) {
+        QCOMPARE(obj, static_cast<QObject*>(0));
+        return;
+    }
+
+    QVERIFY(obj);
+    MyUncreateableBaseClass *base = qobject_cast<MyUncreateableBaseClass*>(obj);
+    QVERIFY(base);
+    QCOMPARE(base->property(prop.toLatin1()).toBool(), true);
+    delete obj;
+}
+
 void tst_qqmllanguage::initTestCase()
 {
     QString testdataDir = QFileInfo(QFINDTESTDATA("data")).absolutePath();