From 58d6c856ece204be11bc4f53a0967d317468d558 Mon Sep 17 00:00:00 2001 From: Kent Hansen Date: Sat, 4 Feb 2012 21:39:38 +0100 Subject: [PATCH] qmetaobjectbuilder: Add support for revisioned methods and properties MIME-Version: 1.0 Content-Type: text/plain; charset=utf8 Content-Transfer-Encoding: 8bit moc supports it, so qmetaobjectbuilder should too. Change-Id: I01475794e928b5a1b659f0dab044933948186971 Reviewed-by: Bradley T. Hughes Reviewed-by: Jędrzej Nowacki Reviewed-by: Kent Hansen --- src/corelib/kernel/qmetaobjectbuilder.cpp | 130 ++++++++++++++++++++- src/corelib/kernel/qmetaobjectbuilder_p.h | 6 + .../qmetaobjectbuilder/tst_qmetaobjectbuilder.cpp | 25 ++++ 3 files changed, 157 insertions(+), 4 deletions(-) diff --git a/src/corelib/kernel/qmetaobjectbuilder.cpp b/src/corelib/kernel/qmetaobjectbuilder.cpp index 064b8ed..c84c95c 100644 --- a/src/corelib/kernel/qmetaobjectbuilder.cpp +++ b/src/corelib/kernel/qmetaobjectbuilder.cpp @@ -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 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 diff --git a/src/corelib/kernel/qmetaobjectbuilder_p.h b/src/corelib/kernel/qmetaobjectbuilder_p.h index 17b7af0..86bc354 100644 --- a/src/corelib/kernel/qmetaobjectbuilder_p.h +++ b/src/corelib/kernel/qmetaobjectbuilder_p.h @@ -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; diff --git a/tests/auto/corelib/kernel/qmetaobjectbuilder/tst_qmetaobjectbuilder.cpp b/tests/auto/corelib/kernel/qmetaobjectbuilder/tst_qmetaobjectbuilder.cpp index 966ac02..02c69b9 100644 --- a/tests/auto/corelib/kernel/qmetaobjectbuilder/tst_qmetaobjectbuilder.cpp +++ b/tests/auto/corelib/kernel/qmetaobjectbuilder/tst_qmetaobjectbuilder.cpp @@ -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; } -- 2.7.4