From f858dd8083e59eb918058694956cd3546fb303b2 Mon Sep 17 00:00:00 2001 From: Aaron Kennedy Date: Thu, 30 Jul 2009 16:44:02 +1000 Subject: Dynamic meta object support This is an internal API used by declarative. Authored-by: mae Reviewed-by: Aaron Kennedy --- src/corelib/kernel/qmetaobject.cpp | 55 +++++++++++++++++++++++++++----------- src/corelib/kernel/qobject.cpp | 9 ++++--- src/corelib/kernel/qobject.h | 1 + src/corelib/kernel/qobject_p.h | 8 ++++++ src/corelib/kernel/qobjectdefs.h | 2 ++ src/tools/moc/generator.cpp | 9 ++++--- 6 files changed, 62 insertions(+), 22 deletions(-) diff --git a/src/corelib/kernel/qmetaobject.cpp b/src/corelib/kernel/qmetaobject.cpp index 611eff3..fc17e00 100644 --- a/src/corelib/kernel/qmetaobject.cpp +++ b/src/corelib/kernel/qmetaobject.cpp @@ -182,6 +182,10 @@ enum MethodFlags { MethodScriptable = 0x40 }; +enum MetaObjectFlags { + DynamicMetaObject = 0x01 +}; + struct QMetaObjectPrivate { int revision; @@ -191,6 +195,7 @@ struct QMetaObjectPrivate int propertyCount, propertyData; int enumeratorCount, enumeratorData; int constructorCount, constructorData; + int flags; }; static inline const QMetaObjectPrivate *priv(const uint* data) @@ -280,6 +285,17 @@ int QMetaObject::static_metacall(Call cl, int idx, void **argv) const } /*! + \internal +*/ +int QMetaObject::metacall(QObject *object, Call cl, int idx, void **argv) +{ + if (QMetaObject *mo = object->d_ptr->metaObject) + return static_cast(mo)->metaCall(cl, idx, argv); + else + return object->qt_metacall(cl, idx, argv); +} + +/*! \fn const char *QMetaObject::className() const Returns the class name. @@ -699,6 +715,14 @@ int QMetaObject::indexOfProperty(const char *name) const } m = m->d.superdata; } + + if (i == -1 && priv(this->d.data)->revision >= 3 && (priv(this->d.data)->flags & DynamicMetaObject)){ + QAbstractDynamicMetaObject *me = + const_cast(static_cast(this)); + + i = me->createProperty(name, 0); + } + return i; } @@ -1538,7 +1562,7 @@ bool QMetaMethod::invoke(QObject *object, // recompute the methodIndex by reversing the arithmetic in QMetaObject::property() int methodIndex = ((handle - priv(mobj->d.data)->methodData) / 5) + mobj->methodOffset(); if (connectionType == Qt::DirectConnection) { - return object->qt_metacall(QMetaObject::InvokeMetaMethod, methodIndex, param) < 0; + return QMetaObject::metacall(object, QMetaObject::InvokeMetaMethod, methodIndex, param) < 0; } else { if (returnValue.data()) { qWarning("QMetaMethod::invoke: Unable to invoke methods with return values in " @@ -2174,9 +2198,8 @@ QVariant QMetaProperty::read(const QObject *object) const value = QVariant(t, (void*)0); argv[0] = value.data(); } - const_cast(object)->qt_metacall(QMetaObject::ReadProperty, - idx + mobj->propertyOffset(), - argv); + QMetaObject::metacall(const_cast(object), QMetaObject::ReadProperty, + idx + mobj->propertyOffset(), argv); if (status != -1) return value; @@ -2247,7 +2270,7 @@ bool QMetaProperty::write(QObject *object, const QVariant &value) const argv[0] = &v; else argv[0] = v.data(); - object->qt_metacall(QMetaObject::WriteProperty, idx + mobj->propertyOffset(), argv); + QMetaObject::metacall(object, QMetaObject::WriteProperty, idx + mobj->propertyOffset(), argv); return status; } @@ -2264,7 +2287,7 @@ bool QMetaProperty::reset(QObject *object) const if (!object || !mobj || !isResettable()) return false; void *argv[] = { 0 }; - object->qt_metacall(QMetaObject::ResetProperty, idx + mobj->propertyOffset(), argv); + QMetaObject::metacall(object, QMetaObject::ResetProperty, idx + mobj->propertyOffset(), argv); return true; } @@ -2378,8 +2401,8 @@ bool QMetaProperty::isDesignable(const QObject *object) const bool b = flags & Designable; if (object) { void *argv[] = { &b }; - const_cast(object)->qt_metacall(QMetaObject::QueryPropertyDesignable, - idx + mobj->propertyOffset(), argv); + QMetaObject::metacall(const_cast(object), QMetaObject::QueryPropertyDesignable, + idx + mobj->propertyOffset(), argv); } return b; @@ -2404,8 +2427,8 @@ bool QMetaProperty::isScriptable(const QObject *object) const bool b = flags & Scriptable; if (object) { void *argv[] = { &b }; - const_cast(object)->qt_metacall(QMetaObject::QueryPropertyScriptable, - idx + mobj->propertyOffset(), argv); + QMetaObject::metacall(const_cast(object), QMetaObject::QueryPropertyScriptable, + idx + mobj->propertyOffset(), argv); } return b; } @@ -2428,8 +2451,8 @@ bool QMetaProperty::isStored(const QObject *object) const bool b = flags & Stored; if (object) { void *argv[] = { &b }; - const_cast(object)->qt_metacall(QMetaObject::QueryPropertyStored, - idx + mobj->propertyOffset(), argv); + QMetaObject::metacall(const_cast(object), QMetaObject::QueryPropertyStored, + idx + mobj->propertyOffset(), argv); } return b; } @@ -2455,8 +2478,8 @@ bool QMetaProperty::isUser(const QObject *object) const bool b = flags & User; if (object) { void *argv[] = { &b }; - const_cast(object)->qt_metacall(QMetaObject::QueryPropertyUser, - idx + mobj->propertyOffset(), argv); + QMetaObject::metacall(const_cast(object), QMetaObject::QueryPropertyUser, + idx + mobj->propertyOffset(), argv); } return b; } @@ -2520,8 +2543,8 @@ bool QMetaProperty::isEditable(const QObject *object) const bool b = flags & Editable; if (object) { void *argv[] = { &b }; - const_cast(object)->qt_metacall(QMetaObject::QueryPropertyEditable, - idx + mobj->propertyOffset(), argv); + QMetaObject::metacall(const_cast(object), QMetaObject::QueryPropertyEditable, + idx + mobj->propertyOffset(), argv); } return b; } diff --git a/src/corelib/kernel/qobject.cpp b/src/corelib/kernel/qobject.cpp index b0ddd81..ab91799 100644 --- a/src/corelib/kernel/qobject.cpp +++ b/src/corelib/kernel/qobject.cpp @@ -145,11 +145,13 @@ QObjectPrivate::QObjectPrivate(int version) inThreadChangeEvent = false; deleteWatch = 0; objectGuards = 0; + metaObject = 0; hasGuards = false; } QObjectPrivate::~QObjectPrivate() { + delete static_cast(metaObject); if (deleteWatch) *deleteWatch = 1; #ifndef QT_NO_USERDATA @@ -484,7 +486,7 @@ QMetaCallEvent::~QMetaCallEvent() */ int QMetaCallEvent::placeMetaCall(QObject *object) { - return object->qt_metacall(QMetaObject::InvokeMetaMethod, id_, args_); + return QMetaObject::metacall(object, QMetaObject::InvokeMetaMethod, id_, args_); } /*! @@ -3171,10 +3173,10 @@ void QMetaObject::activate(QObject *sender, int from_signal_index, int to_signal } #if defined(QT_NO_EXCEPTIONS) - receiver->qt_metacall(QMetaObject::InvokeMetaMethod, method, argv ? argv : empty_argv); + metacall(receiver, QMetaObject::InvokeMetaMethod, method, argv ? argv : empty_argv); #else try { - receiver->qt_metacall(QMetaObject::InvokeMetaMethod, method, argv ? argv : empty_argv); + metacall(receiver, QMetaObject::InvokeMetaMethod, method, argv ? argv : empty_argv); } catch (...) { locker.relock(); @@ -3917,6 +3919,7 @@ void qDeleteInEventHandler(QObject *o) delete o; } + QT_END_NAMESPACE #include "moc_qobject.cpp" diff --git a/src/corelib/kernel/qobject.h b/src/corelib/kernel/qobject.h index 4715626..9169a90 100644 --- a/src/corelib/kernel/qobject.h +++ b/src/corelib/kernel/qobject.h @@ -109,6 +109,7 @@ public: uint hasGuards : 1; //true iff there is one or more QPointer attached to this object uint unused : 22; int postedEvents; + QMetaObject *metaObject; // assert dynamic }; diff --git a/src/corelib/kernel/qobject_p.h b/src/corelib/kernel/qobject_p.h index 19df642..e908753 100644 --- a/src/corelib/kernel/qobject_p.h +++ b/src/corelib/kernel/qobject_p.h @@ -256,6 +256,14 @@ private: void Q_CORE_EXPORT qDeleteInEventHandler(QObject *o); + +struct Q_CORE_EXPORT QAbstractDynamicMetaObject : public QMetaObject +{ + virtual ~QAbstractDynamicMetaObject() {} + virtual int metaCall(QMetaObject::Call, int _id, void **) { return _id; } + virtual int createProperty(const char *, const char *) { return -1; } +}; + QT_END_NAMESPACE #endif // QOBJECT_P_H diff --git a/src/corelib/kernel/qobjectdefs.h b/src/corelib/kernel/qobjectdefs.h index 300e9fa..1ae46d5 100644 --- a/src/corelib/kernel/qobjectdefs.h +++ b/src/corelib/kernel/qobjectdefs.h @@ -431,6 +431,7 @@ struct Q_CORE_EXPORT QMetaObject }; int static_metacall(Call, int, void **) const; + static int metacall(QObject *, Call, int, void **); #ifdef QT3_SUPPORT QT3_SUPPORT const char *superClassName() const; @@ -442,6 +443,7 @@ struct Q_CORE_EXPORT QMetaObject const uint *data; const void *extradata; } d; + }; struct QMetaObjectExtraData diff --git a/src/tools/moc/generator.cpp b/src/tools/moc/generator.cpp index fbc434d..6df762d 100644 --- a/src/tools/moc/generator.cpp +++ b/src/tools/moc/generator.cpp @@ -205,10 +205,10 @@ void Generator::generateCode() QByteArray qualifiedClassNameIdentifier = cdef->qualified; qualifiedClassNameIdentifier.replace(':', '_'); - int index = 12; + int index = 13; fprintf(out, "static const uint qt_meta_data_%s[] = {\n", qualifiedClassNameIdentifier.constData()); fprintf(out, "\n // content:\n"); - fprintf(out, " %4d, // revision\n", 2); + fprintf(out, " %4d, // revision\n", 3); fprintf(out, " %4d, // classname\n", strreg(cdef->qualified)); fprintf(out, " %4d, %4d, // classinfo\n", cdef->classInfoList.count(), cdef->classInfoList.count() ? index : 0); index += cdef->classInfoList.count() * 2; @@ -228,6 +228,9 @@ void Generator::generateCode() fprintf(out, " %4d, %4d, // constructors\n", isConstructible ? cdef->constructorList.count() : 0, isConstructible ? index : 0); + fprintf(out, " %4d, // flags\n", 0); + + // // Build classinfo array // @@ -382,7 +385,7 @@ void Generator::generateCode() if (isQt || !cdef->hasQObject) return; - fprintf(out, "\nconst QMetaObject *%s::metaObject() const\n{\n return &staticMetaObject;\n}\n", + fprintf(out, "\nconst QMetaObject *%s::metaObject() const\n{\n return QObject::d_ptr->metaObject ? QObject::d_ptr->metaObject : &staticMetaObject;\n}\n", cdef->qualified.constData()); // // Generate smart cast function -- cgit v0.12