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