qmetaobjectbuilder: Add support for revisioned methods and properties
authorKent Hansen <kent.hansen@nokia.com>
Sat, 4 Feb 2012 20:39:38 +0000 (21:39 +0100)
committerQt by Nokia <qt-info@nokia.com>
Wed, 15 Feb 2012 07:59:29 +0000 (08:59 +0100)
moc supports it, so qmetaobjectbuilder should too.

Change-Id: I01475794e928b5a1b659f0dab044933948186971
Reviewed-by: Bradley T. Hughes <bradley.hughes@nokia.com>
Reviewed-by: Jędrzej Nowacki <jedrzej.nowacki@nokia.com>
Reviewed-by: Kent Hansen <kent.hansen@nokia.com>
src/corelib/kernel/qmetaobjectbuilder.cpp
src/corelib/kernel/qmetaobjectbuilder_p.h
tests/auto/corelib/kernel/qmetaobjectbuilder/tst_qmetaobjectbuilder.cpp

index 064b8ed..c84c95c 100644 (file)
@@ -106,10 +106,12 @@ public:
             (QMetaMethod::MethodType _methodType,
              const QByteArray& _signature,
              const QByteArray& _returnType = QByteArray(),
-             QMetaMethod::Access _access = QMetaMethod::Public)
+             QMetaMethod::Access _access = QMetaMethod::Public,
+             int _revision = 0)
         : signature(QMetaObject::normalizedSignature(_signature.constData())),
           returnType(QMetaObject::normalizedType(_returnType)),
-          attributes(((int)_access) | (((int)_methodType) << 2))
+          attributes(((int)_access) | (((int)_methodType) << 2)),
+          revision(_revision)
     {
     }
 
@@ -118,6 +120,7 @@ public:
     QList<QByteArray> parameterNames;
     QByteArray tag;
     int attributes;
+    int revision;
 
     QMetaMethod::MethodType methodType() const
     {
@@ -139,10 +142,12 @@ class QMetaPropertyBuilderPrivate
 {
 public:
     QMetaPropertyBuilderPrivate
-            (const QByteArray& _name, const QByteArray& _type, int notifierIdx=-1)
+            (const QByteArray& _name, const QByteArray& _type, int notifierIdx=-1,
+             int _revision = 0)
         : name(_name),
           type(QMetaObject::normalizedType(_type.constData())),
-          flags(Readable | Writable | Scriptable), notifySignal(-1)
+          flags(Readable | Writable | Scriptable), notifySignal(-1),
+          revision(_revision)
     {
         if (notifierIdx >= 0) {
             flags |= Notify;
@@ -154,6 +159,7 @@ public:
     QByteArray type;
     int flags;
     int notifySignal;
+    int revision;
 
     bool flag(int f) const
     {
@@ -193,6 +199,9 @@ public:
         staticMetacallFunction = 0;
     }
 
+    bool hasRevisionedProperties() const;
+    bool hasRevisionedMethods() const;
+
     QByteArray className;
     const QMetaObject *superClass;
     QMetaObjectBuilder::StaticMetacallFunction staticMetacallFunction;
@@ -206,6 +215,24 @@ public:
     int flags;
 };
 
+bool QMetaObjectBuilderPrivate::hasRevisionedProperties() const
+{
+    for (int i = 0; i < properties.size(); ++i) {
+        if (properties.at(i).revision)
+            return true;
+    }
+    return false;
+}
+
+bool QMetaObjectBuilderPrivate::hasRevisionedMethods() const
+{
+    for (int i = 0; i < methods.size(); ++i) {
+        if (methods.at(i).revision)
+            return true;
+    }
+    return false;
+}
+
 /*!
     Constructs a new QMetaObjectBuilder.
 */
@@ -443,6 +470,7 @@ QMetaMethodBuilder QMetaObjectBuilder::addMethod(const QMetaMethod& prototype)
     method.setTag(prototype.tag());
     method.setAccess(prototype.access());
     method.setAttributes(prototype.attributes());
+    method.setRevision(prototype.revision());
     return method;
 }
 
@@ -556,6 +584,7 @@ QMetaPropertyBuilder QMetaObjectBuilder::addProperty(const QMetaProperty& protot
     property.setEnumOrFlag(prototype.isEnumType());
     property.setConstant(prototype.isConstant());
     property.setFinal(prototype.isFinal());
+    property.setRevision(prototype.revision());
     if (prototype.hasNotifySignal()) {
         // Find an existing method for the notify signal, or add a new one.
         QMetaMethod method = prototype.notifySignal();
@@ -1109,6 +1138,8 @@ static int buildMetaObject(QMetaObjectBuilderPrivate *d, char *buf,
     int dataIndex;
     int enumIndex;
     int index;
+    bool hasRevisionedMethods = d->hasRevisionedMethods();
+    bool hasRevisionedProperties = d->hasRevisionedProperties();
     bool hasNotifySignals = false;
 
     if (relocatable &&
@@ -1149,12 +1180,16 @@ static int buildMetaObject(QMetaObjectBuilderPrivate *d, char *buf,
         pmeta->methodCount = d->methods.size();
         pmeta->methodData = dataIndex;
         dataIndex += 5 * d->methods.size();
+        if (hasRevisionedMethods)
+            dataIndex += d->methods.size();
 
         pmeta->propertyCount = d->properties.size();
         pmeta->propertyData = dataIndex;
         dataIndex += 3 * d->properties.size();
         if (hasNotifySignals)
             dataIndex += d->properties.size();
+        if (hasRevisionedProperties)
+            dataIndex += d->properties.size();
 
         pmeta->enumeratorCount = d->enumerators.size();
         pmeta->enumeratorData = dataIndex;
@@ -1166,9 +1201,13 @@ static int buildMetaObject(QMetaObjectBuilderPrivate *d, char *buf,
     } else {
         dataIndex += 2 * d->classInfoNames.size();
         dataIndex += 5 * d->methods.size();
+        if (hasRevisionedMethods)
+            dataIndex += d->methods.size();
         dataIndex += 3 * d->properties.size();
         if (hasNotifySignals)
             dataIndex += d->properties.size();
+        if (hasRevisionedProperties)
+            dataIndex += d->properties.size();
         dataIndex += 4 * d->enumerators.size();
         dataIndex += 5 * d->constructors.size();
     }
@@ -1241,6 +1280,14 @@ static int buildMetaObject(QMetaObjectBuilderPrivate *d, char *buf,
         }
         dataIndex += 5;
     }
+    if (hasRevisionedMethods) {
+        for (index = 0; index < d->methods.size(); ++index) {
+            QMetaMethodBuilderPrivate *method = &(d->methods[index]);
+            if (buf)
+                data[dataIndex] = method->revision;
+            ++dataIndex;
+        }
+    }
 
     // Output the properties in the class.
     for (index = 0; index < d->properties.size(); ++index) {
@@ -1274,6 +1321,14 @@ static int buildMetaObject(QMetaObjectBuilderPrivate *d, char *buf,
             ++dataIndex;
         }
     }
+    if (hasRevisionedProperties) {
+        for (index = 0; index < d->properties.size(); ++index) {
+            QMetaPropertyBuilderPrivate *prop = &(d->properties[index]);
+            if (buf)
+                data[dataIndex] = prop->revision;
+            ++dataIndex;
+        }
+    }
 
     // Output the enumerators in the class.
     for (index = 0; index < d->enumerators.size(); ++index) {
@@ -1506,6 +1561,8 @@ void QMetaObjectBuilder::serialize(QDataStream& stream) const
         stream << method->parameterNames;
         stream << method->tag;
         stream << method->attributes;
+        if (method->revision)
+            stream << method->revision;
     }
 
     // Write the properties.
@@ -1515,6 +1572,8 @@ void QMetaObjectBuilder::serialize(QDataStream& stream) const
         stream << property->type;
         stream << property->flags;
         stream << property->notifySignal;
+        if (property->revision)
+            stream << property->revision;
     }
 
     // Write the enumerators.
@@ -1645,6 +1704,8 @@ void QMetaObjectBuilder::deserialize
         stream >> method->parameterNames;
         stream >> method->tag;
         stream >> method->attributes;
+        if (method->attributes & MethodRevisioned)
+            stream >> method->revision;
         if (method->methodType() == QMetaMethod::Constructor) {
             // Cannot add a constructor in this set of methods.
             stream.setStatus(QDataStream::ReadCorruptData);
@@ -1675,6 +1736,8 @@ void QMetaObjectBuilder::deserialize
             stream.setStatus(QDataStream::ReadCorruptData);
             return;
         }
+        if (property->flags & Revisioned)
+            stream >> property->revision;
     }
 
     // Read the enumerators.
@@ -1929,6 +1992,37 @@ void QMetaMethodBuilder::setAttributes(int value)
 }
 
 /*!
+    Returns the revision of this method.
+
+    \sa setRevision()
+*/
+int QMetaMethodBuilder::revision() const
+{
+    QMetaMethodBuilderPrivate *d = d_func();
+    if (d)
+        return d->revision;
+    return 0;
+
+}
+
+/*!
+    Sets the \a revision of this method.
+
+    \sa revision()
+*/
+void QMetaMethodBuilder::setRevision(int revision)
+{
+    QMetaMethodBuilderPrivate *d = d_func();
+    if (d) {
+        d->revision = revision;
+        if (revision)
+            d->attributes |= MethodRevisioned;
+        else
+            d->attributes &= ~MethodRevisioned;
+    }
+}
+
+/*!
     \class QMetaPropertyBuilder
     \internal
     \brief The QMetaPropertyBuilder class enables modifications to a property definition on a meta object builder.
@@ -2370,6 +2464,34 @@ void QMetaPropertyBuilder::setFinal(bool value)
         d->setFlag(Final, value);
 }
 
+/*!
+    Returns the revision of this property.
+
+    \sa setRevision()
+*/
+int QMetaPropertyBuilder::revision() const
+{
+    QMetaPropertyBuilderPrivate *d = d_func();
+    if (d)
+        return d->revision;
+    return 0;
+
+}
+
+/*!
+    Sets the \a revision of this property.
+
+    \sa revision()
+*/
+void QMetaPropertyBuilder::setRevision(int revision)
+{
+    QMetaPropertyBuilderPrivate *d = d_func();
+    if (d) {
+        d->revision = revision;
+        d->setFlag(Revisioned, revision != 0);
+    }
+}
+
 
 /*!
     \class QMetaEnumBuilder
index 17b7af0..86bc354 100644 (file)
@@ -215,6 +215,9 @@ public:
     int attributes() const;
     void setAttributes(int value);
 
+    int revision() const;
+    void setRevision(int revision);
+
 private:
     const QMetaObjectBuilder *_mobj;
     int _index;
@@ -269,6 +272,9 @@ public:
     void setConstant(bool value);
     void setFinal(bool value);
 
+    int revision() const;
+    void setRevision(int revision);
+
 private:
     const QMetaObjectBuilder *_mobj;
     int _index;
index 966ac02..02c69b9 100644 (file)
@@ -91,6 +91,7 @@ class SomethingOfEverything : public QObject
     Q_CLASSINFO("ci_bar", "DEF")
     Q_PROPERTY(QString prop READ prop WRITE setProp NOTIFY propChanged)
     Q_PROPERTY(QString prop2 READ prop WRITE setProp)
+    Q_PROPERTY(QString revisionProp READ prop WRITE setProp REVISION 42)
     Q_PROPERTY(SomethingEnum eprop READ eprop)
     Q_PROPERTY(SomethingFlagEnum fprop READ fprop)
     Q_PROPERTY(QLocale::Language language READ language)
@@ -124,6 +125,7 @@ public:
 public slots:
     void slot1(const QString&) {}
     void slot2(int, const QString&) {}
+    Q_REVISION(24) void revisionSlot() {}
 
 private slots:
     void slot3() {}
@@ -219,6 +221,7 @@ void tst_QMetaObjectBuilder::method()
     QVERIFY(nullMethod.tag().isEmpty());
     QVERIFY(nullMethod.access() == QMetaMethod::Public);
     QCOMPARE(nullMethod.attributes(), 0);
+    QCOMPARE(nullMethod.revision(), 0);
     QCOMPARE(nullMethod.index(), 0);
 
     // Add a method and check its attributes.
@@ -230,6 +233,7 @@ void tst_QMetaObjectBuilder::method()
     QVERIFY(method1.tag().isEmpty());
     QVERIFY(method1.access() == QMetaMethod::Public);
     QCOMPARE(method1.attributes(), 0);
+    QCOMPARE(method1.revision(), 0);
     QCOMPARE(method1.index(), 0);
     QCOMPARE(builder.methodCount(), 1);
 
@@ -242,6 +246,7 @@ void tst_QMetaObjectBuilder::method()
     QVERIFY(method2.tag().isEmpty());
     QVERIFY(method2.access() == QMetaMethod::Public);
     QCOMPARE(method2.attributes(), 0);
+    QCOMPARE(method2.revision(), 0);
     QCOMPARE(method2.index(), 1);
     QCOMPARE(builder.methodCount(), 2);
 
@@ -256,6 +261,7 @@ void tst_QMetaObjectBuilder::method()
     method1.setTag("tag");
     method1.setAccess(QMetaMethod::Private);
     method1.setAttributes(42);
+    method1.setRevision(123);
 
     // Check that method1 is changed, but method2 is not.
     QCOMPARE(method1.signature(), QByteArray("foo(QString,int)"));
@@ -265,6 +271,7 @@ void tst_QMetaObjectBuilder::method()
     QCOMPARE(method1.tag(), QByteArray("tag"));
     QVERIFY(method1.access() == QMetaMethod::Private);
     QCOMPARE(method1.attributes(), 42);
+    QCOMPARE(method1.revision(), 123);
     QCOMPARE(method1.index(), 0);
     QCOMPARE(method2.signature(), QByteArray("bar(QString)"));
     QVERIFY(method2.methodType() == QMetaMethod::Method);
@@ -273,6 +280,7 @@ void tst_QMetaObjectBuilder::method()
     QVERIFY(method2.tag().isEmpty());
     QVERIFY(method2.access() == QMetaMethod::Public);
     QCOMPARE(method2.attributes(), 0);
+    QCOMPARE(method2.revision(), 0);
     QCOMPARE(method2.index(), 1);
     QCOMPARE(builder.methodCount(), 2);
 
@@ -282,6 +290,7 @@ void tst_QMetaObjectBuilder::method()
     method2.setTag("Q_FOO");
     method2.setAccess(QMetaMethod::Protected);
     method2.setAttributes(24);
+    method2.setRevision(321);
 
     // This time check that only method2 changed.
     QCOMPARE(method1.signature(), QByteArray("foo(QString,int)"));
@@ -291,6 +300,7 @@ void tst_QMetaObjectBuilder::method()
     QCOMPARE(method1.tag(), QByteArray("tag"));
     QVERIFY(method1.access() == QMetaMethod::Private);
     QCOMPARE(method1.attributes(), 42);
+    QCOMPARE(method1.revision(), 123);
     QCOMPARE(method1.index(), 0);
     QCOMPARE(method2.signature(), QByteArray("bar(QString)"));
     QVERIFY(method2.methodType() == QMetaMethod::Method);
@@ -299,6 +309,7 @@ void tst_QMetaObjectBuilder::method()
     QCOMPARE(method2.tag(), QByteArray("Q_FOO"));
     QVERIFY(method2.access() == QMetaMethod::Protected);
     QCOMPARE(method2.attributes(), 24);
+    QCOMPARE(method2.revision(), 321);
     QCOMPARE(method2.index(), 1);
     QCOMPARE(builder.methodCount(), 2);
 
@@ -313,6 +324,7 @@ void tst_QMetaObjectBuilder::method()
     QCOMPARE(method2.tag(), QByteArray("Q_FOO"));
     QVERIFY(method2.access() == QMetaMethod::Protected);
     QCOMPARE(method2.attributes(), 24);
+    QCOMPARE(method2.revision(), 321);
     QCOMPARE(method2.index(), 0);
 
     // Perform index-based lookup again.
@@ -542,6 +554,7 @@ void tst_QMetaObjectBuilder::property()
     QVERIFY(!nullProp.isConstant());
     QVERIFY(!nullProp.isFinal());
     QCOMPARE(nullProp.index(), 0);
+    QCOMPARE(nullProp.revision(), 0);
 
     // Add a property and check its attributes.
     QMetaPropertyBuilder prop1 = builder.addProperty("foo", "const QString &");
@@ -560,6 +573,7 @@ void tst_QMetaObjectBuilder::property()
     QVERIFY(!prop1.isEnumOrFlag());
     QVERIFY(!prop1.isConstant());
     QVERIFY(!prop1.isFinal());
+    QCOMPARE(prop1.revision(), 0);
     QCOMPARE(prop1.index(), 0);
     QCOMPARE(builder.propertyCount(), 1);
 
@@ -580,6 +594,7 @@ void tst_QMetaObjectBuilder::property()
     QVERIFY(!prop2.isEnumOrFlag());
     QVERIFY(!prop2.isConstant());
     QVERIFY(!prop2.isFinal());
+    QCOMPARE(prop2.revision(), 0);
     QCOMPARE(prop2.index(), 1);
     QCOMPARE(builder.propertyCount(), 2);
 
@@ -603,6 +618,7 @@ void tst_QMetaObjectBuilder::property()
     prop1.setEnumOrFlag(true);
     prop1.setConstant(true);
     prop1.setFinal(true);
+    prop1.setRevision(123);
 
     // Check that prop1 is changed, but prop2 is not.
     QCOMPARE(prop1.name(), QByteArray("foo"));
@@ -619,6 +635,7 @@ void tst_QMetaObjectBuilder::property()
     QVERIFY(prop1.isEnumOrFlag());
     QVERIFY(prop1.isConstant());
     QVERIFY(prop1.isFinal());
+    QCOMPARE(prop1.revision(), 123);
     QVERIFY(prop2.isReadable());
     QVERIFY(prop2.isWritable());
     QCOMPARE(prop2.name(), QByteArray("bar"));
@@ -633,6 +650,7 @@ void tst_QMetaObjectBuilder::property()
     QVERIFY(!prop2.isEnumOrFlag());
     QVERIFY(!prop2.isConstant());
     QVERIFY(!prop2.isFinal());
+    QCOMPARE(prop2.revision(), 0);
 
     // Remove prop1 and check that prop2 becomes index 0.
     builder.removeProperty(0);
@@ -650,6 +668,7 @@ void tst_QMetaObjectBuilder::property()
     QVERIFY(!prop2.isEnumOrFlag());
     QVERIFY(!prop2.isConstant());
     QVERIFY(!prop2.isFinal());
+    QCOMPARE(prop2.revision(), 0);
     QCOMPARE(prop2.index(), 0);
 
     // Perform index-based lookup again.
@@ -1163,6 +1182,9 @@ static bool sameMethod(const QMetaMethod& method1, const QMetaMethod& method2)
     if (method1.attributes() != method2.attributes())
         return false;
 
+    if (method1.revision() != method2.revision())
+        return false;
+
     return true;
 }
 
@@ -1193,6 +1215,9 @@ static bool sameProperty(const QMetaProperty& prop1, const QMetaProperty& prop2)
             return false;
     }
 
+    if (prop1.revision() != prop2.revision())
+        return false;
+
     return true;
 }