From e76ba402bfe309022a0be29c6bc8223f8f3f94b3 Mon Sep 17 00:00:00 2001 From: Martin Jones Date: Fri, 22 Jun 2012 16:56:27 +1000 Subject: [PATCH] qmlRegisterRevision clashes with qmlRegisterUncreatableType Add template qmlRegisterUncreatableType() in order to register an uncreatable type for a particular revision. Task-number: QTBUG-23278 Change-Id: Ic165e41c8176916929cf19eb9bf6eef4b5bee1eb Reviewed-by: Lincoln Ramsay Reviewed-by: Chris Adams --- .../doc/src/cppintegration/registercpptypes.qdoc | 3 ++ src/qml/qml/qqml.h | 31 ++++++++++++ tests/auto/qml/qqmllanguage/testtypes.cpp | 6 +++ tests/auto/qml/qqmllanguage/testtypes.h | 35 ++++++++++++++ tests/auto/qml/qqmllanguage/tst_qqmllanguage.cpp | 56 ++++++++++++++++++++++ 5 files changed, 131 insertions(+) diff --git a/src/qml/doc/src/cppintegration/registercpptypes.qdoc b/src/qml/doc/src/cppintegration/registercpptypes.qdoc index 9ccf428..0e11883 100644 --- a/src/qml/doc/src/cppintegration/registercpptypes.qdoc +++ b/src/qml/doc/src/cppintegration/registercpptypes.qdoc @@ -265,6 +265,9 @@ int qmlRegisterType(const char *uri, int versionMajor, int versionMinor, const c \code template int qmlRegisterRevision(const char *uri, int versionMajor, int versionMinor) + + template + 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 diff --git a/src/qml/qml/qqml.h b/src/qml/qml/qqml.h index c7092a6..528f8e6 100644 --- a/src/qml/qml/qqml.h +++ b/src/qml/qml/qqml.h @@ -167,6 +167,37 @@ int qmlRegisterUncreatableType(const char *uri, int versionMajor, int versionMin return QQmlPrivate::qmlregister(QQmlPrivate::TypeRegistration, &type); } +template +int qmlRegisterUncreatableType(const char *uri, int versionMajor, int versionMinor, const char *qmlName, const QString& reason) +{ + QML_GETTYPENAMES + + QQmlPrivate::RegisterType type = { + 1, + + qRegisterNormalizedMetaType(pointerName.constData()), + qRegisterNormalizedMetaType >(listName.constData()), + 0, 0, + reason, + + uri, versionMajor, versionMinor, qmlName, &T::staticMetaObject, + + QQmlPrivate::attachedPropertiesFunc(), + QQmlPrivate::attachedPropertiesMetaObject(), + + QQmlPrivate::StaticCastSelector::cast(), + QQmlPrivate::StaticCastSelector::cast(), + QQmlPrivate::StaticCastSelector::cast(), + + 0, 0, + + 0, + metaObjectRevision + }; + + return QQmlPrivate::qmlregister(QQmlPrivate::TypeRegistration, &type); +} + template int qmlRegisterType(const char *uri, int versionMajor, int versionMinor, const char *qmlName) { diff --git a/tests/auto/qml/qqmllanguage/testtypes.cpp b/tests/auto/qml/qqmllanguage/testtypes.cpp index beb0f59..561300d 100644 --- a/tests/auto/qml/qqmllanguage/testtypes.cpp +++ b/tests/auto/qml/qqmllanguage/testtypes.cpp @@ -83,6 +83,12 @@ void registerTypes() qmlRegisterType("Test",1,0,"MyEnumDerivedClass"); qmlRegisterType("Test",1,0,"MyReceiversTestObject"); + + qmlRegisterUncreatableType("Test", 1, 0, "MyUncreateableBaseClass", "Cannot create MyUncreateableBaseClass"); + qmlRegisterType("Test", 1, 0, "MyCreateableDerivedClass"); + + qmlRegisterUncreatableType("Test", 1, 1, "MyUncreateableBaseClass", "Cannot create MyUncreateableBaseClass"); + qmlRegisterType("Test", 1, 1, "MyCreateableDerivedClass"); } QVariant myCustomVariantTypeConverter(const QString &data) diff --git a/tests/auto/qml/qqmllanguage/testtypes.h b/tests/auto/qml/qqmllanguage/testtypes.h index f84e42f..50b6089 100644 --- a/tests/auto/qml/qqmllanguage/testtypes.h +++ b/tests/auto/qml/qqmllanguage/testtypes.h @@ -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 diff --git a/tests/auto/qml/qqmllanguage/tst_qqmllanguage.cpp b/tests/auto/qml/qqmllanguage/tst_qqmllanguage.cpp index 6349cd3..2f2f0a7 100644 --- a/tests/auto/qml/qqmllanguage/tst_qqmllanguage.cpp +++ b/tests/auto/qml/qqmllanguage/tst_qqmllanguage.cpp @@ -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("version"); + QTest::addColumn("prop"); + QTest::addColumn("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(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(0)); + return; + } + + QVERIFY(obj); + MyUncreateableBaseClass *base = qobject_cast(obj); + QVERIFY(base); + QCOMPARE(base->property(prop.toLatin1()).toBool(), true); + delete obj; +} + void tst_qqmllanguage::initTestCase() { QString testdataDir = QFileInfo(QFINDTESTDATA("data")).absolutePath(); -- 2.7.4