Mercurial > projects > qtd
diff qt/core/QMetaObject.d @ 248:7664de4a55e5
Fixed #23.
QtD_QObjectEntity is not created dynamically for shell classes any more.
Class initialization is now performed by static constructors.
When wrapping QObjects returned from functions, their run-time types are now taken into account.
QObjects are allocated on GC heap, a doubly-linked list is used to prevent them from been collected (arguably a better solution than allocating on C heap and adding GC ranges)
Minor changes (including unnecessary).
author | maxter |
---|---|
date | Thu, 20 Aug 2009 14:47:17 +0000 |
parents | |
children |
line wrap: on
line diff
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/qt/core/QMetaObject.d Thu Aug 20 14:47:17 2009 +0000 @@ -0,0 +1,136 @@ +module qt.core.QMetaObject; + +import qt.QGlobal; +import qt.core.QObject; +import qt.QtdObject; + +final class QMetaObject +{ + private + { + void* _nativeId; + QMetaObject _base; // super class + QMetaObject _firstDerived; // head of the linked list of derived classes + QMetaObject _next; // next sibling on this derivation level + ClassInfo _classInfo; + + QObject function(void* nativeId) _createWrapper; + } + + private void addDerived(QMetaObject mo) + { + mo._next = _firstDerived; + _firstDerived = mo; + } + + // NOTE: construction is split between this non-templated constructor and 'construct' function below. + this(void* nativeId, QMetaObject base) + { + _nativeId = nativeId; + if (base) + { + base.addDerived(this); + _base = base; + } + } + + // TODO: remove when D acquires templated constructors + void construct(T : QObject, Concrete = T)() + { + _classInfo = T.classinfo; + + static QObject createWrapper(void* nativeId) + { + T obj = new Concrete(nativeId, QtdObjectFlags.nativeOwnership); + // TODO: this probably should be moved to QObject constructor + qtd_create_qobject_entity(nativeId, cast(void*)obj); + return obj; + } + + _createWrapper = &createWrapper; + } + + /++ + +/ + QMetaObject base() + { + return _base; + } + + /++ + +/ + void* nativeId() + { + return _nativeId; + } + + /++ + +/ + ClassInfo classInfo() + { + return _classInfo; + } + + private QObject lookupDerived(void*[] moIds, void* nativeObjId) + { + assert (moIds.length >= 1); + + for (auto mo = _firstDerived; mo !is null; mo = mo._next) + { + if (mo._nativeId == moIds[0]) + { + if (moIds.length == 1) // exact match found + return mo._createWrapper(nativeObjId); + else // look deeper + return mo.lookupDerived(moIds[1..$], nativeObjId); + } + } + + // no initialized wrapper that matches the native object. + // use the base class wrapper + return _createWrapper(nativeObjId); + } + + QObject getObject(void* nativeObjId) + { + QObject result; + + if (nativeObjId) + { + result = cast(QObject)qtd_get_d_qobject(nativeObjId); + if (!result) + { + auto moId = qtd_QObject_metaObject(nativeObjId); + if (_nativeId == moId) + result = _createWrapper(nativeObjId); + else + { + // get native metaobjects for the entire derivation lattice + // up to, but not including, the current metaobject. + size_t moCount = 1; + + for (void* tmp = moId;;) + { + tmp = qtd_QMetaObject_superClass(tmp); + assert(tmp); + if (tmp == _nativeId) + break; + moCount++; + } + + void*[] moIds = (cast(void**)alloca(moCount * (void*).sizeof))[0..moCount]; + + moIds[--moCount] = moId; + while (moCount > 0) + moIds[--moCount] = moId = qtd_QMetaObject_superClass(moId); + + result = lookupDerived(moIds, nativeObjId); + } + } + } + + return result; + } +} + +extern(C) void* qtd_QMetaObject_superClass(void* nativeId); \ No newline at end of file