changeset 368:185df9220ea7

Fixed startsWith. Implemented meta-object members as ranges. Freed QMetaObject from stuff that belongs to MetaClass
author Max Samukha <maxter@maxter.com>
date Mon, 28 Jun 2010 21:29:32 +0300
parents f69341b40588
children 6e1857c521af
files cmake/FindD.cmake d2/qt/core/QMetaObject.d d2/qtd/MOC.d d2/qtd/String.d d2/qtd/meta/Runtime.d examples/dialogs/classwizard/build.bat examples/layouts/dynamiclayouts/dialog.d examples/layouts/dynamiclayouts/main.d generator/dgenerator.cpp generator/typesystem_core-java.java mini/test1/build mini/test1/main.d
diffstat 12 files changed, 622 insertions(+), 418 deletions(-) [+]
line wrap: on
line diff
--- a/cmake/FindD.cmake	Thu Jun 24 13:47:30 2010 +0300
+++ b/cmake/FindD.cmake	Mon Jun 28 21:29:32 2010 +0300
@@ -87,7 +87,8 @@
     set(D_DEBUG_FLAG -debug)
 endif(D_IS_LLVM)
 if(CMAKE_HOST_WIN32)
-    set(D_RELEASE_FLAGS ${D_RELEASE_FLAGS} -L/subsystem:windows)
+    # Linking fails with this. Commenting out for now.
+    # set(D_RELEASE_FLAGS ${D_RELEASE_FLAGS} -L/subsystem:windows)
 endif(CMAKE_HOST_WIN32)
 set(D_DEBUG_FLAGS ${D_DEBUG_FLAGS} ${D_DEBUG_FLAG})
 
--- a/d2/qt/core/QMetaObject.d	Thu Jun 24 13:47:30 2010 +0300
+++ b/d2/qt/core/QMetaObject.d	Mon Jun 28 21:29:32 2010 +0300
@@ -14,23 +14,30 @@
     std.c.stdlib;
 
 import std.string : indexOf;
+import std.algorithm : filter;
 
-class QMetaArgument : Meta
+//TODO: remove
+import std.stdio;
+
+class QMetaArgument : MetaBase
 {
 }
 
-class QMetaMethod : Meta
+class QMetaMethod : MetaBase
 {
     alias typeof(this) This;
 
 //    QMetaArgument[]  arguments;
     string signature;
-    int indexOfMethod;
+    int index;
 
-    this(string signature_, int indexOfMethod_)
+    this(string signature, int index)
     {
-        signature = signature_;
-        indexOfMethod = indexOfMethod_;
+        this.signature = signature;
+        this.index = index;
+
+        int openBracket = indexOf(signature, '(');
+        name = signature[0..openBracket];
     }
 
     string args() const
@@ -42,27 +49,22 @@
             return "";
     }
 
-    string name() const
-    {
-        int openBracket = indexOf(signature, '(');
-        return signature[0..openBracket];
-    }
-
-    // mixin(Derived) or typeof(Derived) would help a lot here
-    static create(alias method, M : This)(uint index)
+    static M create(alias method, M : This)(uint index)
     {
         alias ParameterTypeTuple!method Args;
         return new M(.signature!(Args)(methodName!(method)), index);
     }
 }
 
+/**
+ */
 class QMetaSignal : QMetaMethod
 {
     alias typeof(this) This;
 
-    this(string signature_, int indexOfMethod_)
+    this(string signature, int indexOfMethod)
     {
-        super(signature_, indexOfMethod_);
+        super(signature, indexOfMethod);
     }
 
     static This create(alias method)(uint index)
@@ -75,9 +77,9 @@
 {
     alias typeof(this) This;
 
-    this(string signature_, int indexOfMethod_)
+    this(string signature, int indexOfMethod)
     {
-        super(signature_, indexOfMethod_);
+        super(signature, indexOfMethod);
     }
 
     static This create(alias method)(uint index)
@@ -86,9 +88,31 @@
     }
 }
 
-class MetaObject : MetaType
+/**
+    Base class for QtD meta-classes.
+ */
+abstract class QtdMetaClass : MetaClass
 {
-    MetaObject _base;
+private:
+    void* nativeId_;
+
+public:
+
+    this() {}
+
+    /**
+     */
+    @property
+    void* nativeId()
+    {
+        return nativeId_;
+    }
+
+    void construct(T)()
+    {
+        super.construct!T();
+        nativeId_ = T.qtd_nativeStaticMetaObject();
+    }
 }
 
 struct QMetaObjectNative
@@ -99,13 +123,16 @@
     void *extradata;
 }
 
-class QMetaException : Exception { this(string msg) { super(msg); } }
 
-final class QMetaObject
+/**
+ */
+final class QMetaObject : QtdMetaClass
 {
     alias typeof(this) This;
 
-    private this() {}
+    private QObject function(void* nativeId) _createWrapper;
+
+    this() {}
 
     enum Call
     {
@@ -121,42 +148,11 @@
         CreateInstance
     }
 
-    private
+    alias createImpl!This create;
+
+    void construct(T : QObject)()
     {
-        QMetaObjectNative* _nativeId;
-        QMetaObject _base; // super class
-        QMetaObject _firstDerived; // head of the linked list of derived classes
-        QMetaObject _next; // next sibling on this derivation level
-        QMetaMethod[] _methods;
-        ClassInfo _classInfo;
-
-        QObject function(void* nativeId) _createWrapper;
-    }
-
-    private void addDerived(QMetaObject mo)
-    {
-        mo._next = _firstDerived;
-        _firstDerived = mo;
-    }
-
-    // ctor
-    void construct(T : QObject)(void* nativeId)
-    {
-        alias BaseClassesTuple!(T)[0] Base;
-        This base;
-        static if (is(Base : QObject))
-            base = Base.staticMetaObject;
-
-        _nativeId = cast(QMetaObjectNative*)nativeId;
-        T.setStaticMetaObject(this);
-
-        if (base)
-        {
-            base.addDerived(this);
-            _base = base;
-        }
-        _classInfo = T.classinfo;
-
+        super.construct!T();
 
         static if (isQtType!T)
         {
@@ -171,12 +167,13 @@
                     return obj;
                 };
 
-            T._populateMetaInfo;
+            T._populateMetaInfo(this);
         }
         // create run time meta-objects for user-defined signals and slots
         else static if (is(typeof(T.methods)))
         {
-            int index = Base.staticMetaObject().methodCount();
+            alias BaseClassesTuple!(T)[0] Base;
+            int index = meta!(Base).methodCount;
 
             static if (T.signals.length)
             {
@@ -198,101 +195,83 @@
         }
     }
 
-    // new
-    static This create(T : QObject)(void* nativeId)
+    /**
+     */
+    @property
+    override This next()
     {
-        auto m = new This();
-        m.construct!T(nativeId);
-        return m;
+        return static_cast!This(super.next);
     }
 
-    /++
-    +/
-    QMetaObject base()
+    /**
+     */
+    @property
+    override This firstDerived()
     {
-        return _base;
+        return static_cast!This(super.firstDerived);
     }
 
-    /++
-    +/
+    void addMethod(QMetaMethod method)
+    {
+        members_ ~= method;
+    }
+
+    /**
+     */
+    @property
+    override This base()
+    {
+        return super.base;
+    }
+
+    /**
+     */
+    @property
     QMetaObjectNative* nativeId()
     {
-        return _nativeId;
+        return cast(QMetaObjectNative*)super.nativeId;
     }
 
-    /++
-    +/
-    ClassInfo classInfo()
+    M lookUpMethod(M : QMetaMethod = QMetaMethod)(string signature)
     {
-        return _classInfo;
+        foreach (method; allMembers)
+        {
+            if (auto m = cast(M)method)
+            {
+                if (m.signature == signature)
+                    return m;
+            }
+        }
+        return null;
     }
 
-    const (QMetaMethod[]) methods()
+    // TODO: probably make this return a filtering range.
+    auto lookUpMethodOverloads(M : QMetaMethod = QMetaMethod)(string name)
     {
-        return _methods;
+        M[] methods;
+        foreach (m; allMembers)
+        {
+            if (auto method = cast(M)m)
+            {
+                if (method.name == name)
+                    methods ~= method;
+            }
+        }
+        return methods;
     }
 
-    void addMethod(QMetaMethod method_)
-    {
-        _methods ~= method_;
-    }
-
-    QMetaMethod lookUpMethod(string slot)
-    {
-        foreach (method; _methods)
-            if (method.signature == slot)
-                return method;
-        if (_base)
-            return _base.lookUpMethod(slot);
-        else
-            return null;
-    }
-
-    QMetaSignal lookUpSignal(string signal)
-    {
-        foreach (method; _methods)
-            if (method.signature == signal && cast(QMetaSignal)method)
-                return cast(QMetaSignal)method;
-        if (_base)
-            return _base.lookUpSignal(signal);
-        else
-            return null;
-    }
-
-    QMetaMethod[] lookUpMethodOverloads(string methodName)
-    {
-        typeof(return) result;
-        foreach (method; _methods)
-            if (method.name == methodName)
-                result ~= method;
-        if (_base)
-            result ~= _base.lookUpMethodOverloads(methodName);
-        return result;
-    }
-
-    QMetaSignal[] lookUpSignalOverloads(string signalName)
-    {
-        typeof(return) result;
-        foreach (method; _methods)
-            if (method.name == signalName && cast(QMetaSignal)method)
-                result ~= cast(QMetaSignal)method;
-        if (_base)
-            result ~= _base.lookUpSignalOverloads(signalName);
-        return result;
-    }
-
-    private QMetaObject lookupDerived(void*[] moIds)
+    private QMetaObject lookUpDerived(void*[] moIds)
     {
         assert (moIds.length >= 1);
 
-        for (auto mo = _firstDerived; mo !is null; mo = mo._next)
+        for (auto mo = firstDerived; mo !is null; mo = mo.next)
         {
-            if (mo._nativeId == moIds[0])
+            if (mo.nativeId == moIds[0])
             {
                 if (moIds.length == 1) // exact match found
                     return mo;
                 else // look deeper
-                    return mo.lookupDerived(moIds[1..$]);
+                    return mo.lookUpDerived(moIds[1..$]);
             }
         }
 
@@ -311,7 +290,8 @@
             if (!result)
             {
                 auto moId = qtd_QObject_metaObject(nativeObjId);
-                if (_nativeId == moId)
+                auto nId = nativeId;
+                if (nId == moId)
                      result = _createWrapper(nativeObjId);
                 else
                 {
@@ -323,7 +303,7 @@
                     {
                         tmp = qtd_QMetaObject_superClass(tmp);
                         assert(tmp);
-                        if (tmp == _nativeId)
+                        if (tmp == nId)
                             break;
                         moCount++;
                     }
@@ -334,7 +314,7 @@
                     while (moCount > 0)
                         moIds[--moCount] = moId = qtd_QMetaObject_superClass(moId);
 
-                    result = lookupDerived(moIds)._createWrapper(nativeObjId);
+                    result = lookUpDerived(moIds)._createWrapper(nativeObjId);
                 }
             }
         }
@@ -361,12 +341,12 @@
 
     int indexOfMethod_Cpp(string method)
     {
-        return qtd_QMetaObject_indexOfMethod(_nativeId, toStringz(method));
+        return qtd_QMetaObject_indexOfMethod(nativeId, toStringz(method));
     }
 
     int methodCount()
     {
-        return qtd_QMetaObject_methodCount(_nativeId);
+        return qtd_QMetaObject_methodCount(nativeId);
     }
 
     static void connectImpl(QObject sender, string signalString, QObject receiver, string methodString, int type)
@@ -377,9 +357,9 @@
         QMetaMethod method;
 
         if(indexOf(signalString, '(') > 0)
-            signal = sender.metaObject.lookUpSignal(signalString);
+            signal = sender.metaObject.lookUpMethod!QMetaSignal(signalString);
         else
-            signals = sender.metaObject.lookUpSignalOverloads(signalString); // parameters not specified. Looking for a match
+            signals = sender.metaObject.lookUpMethodOverloads!QMetaSignal(signalString); // parameters not specified. Looking for a match
 
         if(indexOf(methodString, '(') > 0)
             method = receiver.metaObject.lookUpMethod(methodString);
@@ -390,13 +370,17 @@
         {
             Top:
             foreach(sig; signals)
+            {
                 foreach(meth; methods)
+                {
                     if(startsWith(sig.args, meth.args))
                     {
                         signal = sig;
                         method = meth;
                         break Top;
                     }
+                }
+            }
         }
         else if (!signal)
         {
@@ -425,14 +409,18 @@
         }
         else
         {
-            int signalIndex = signal.indexOfMethod;
-            int methodIndex = method.indexOfMethod;
+            int signalIndex = signal.index;
+            int methodIndex = method.index;
 
             success = QMetaObject.connect(sender, signalIndex, receiver, methodIndex, type);
         }
 
         if(!success)
-            throw new QMetaException("QMetaObject: Signal " ~ signalString ~ " cannot be connected to slot " ~ methodString);
+        {
+            throw new MetaException("QMetaObject: Failed to connect signal "
+                ~ sender.classinfo.name ~ "." ~ signalString ~ " to slot "
+                ~ receiver.classinfo.name ~ "." ~ methodString ~ ". Make sure the signal and slot exist and match.");
+        }
     }
 }
 
@@ -443,19 +431,50 @@
     mixin InnerAttribute!("Q_CLASSINFO", AttributeOptions.allowMultiple, name, value);
 }
 
+/**
+ */
+mixin template Q_PROPERTY(T, string params)
+{
+    static assert(false, "not implemented");
+}
+
 version (QtdUnittest)
 {
+    // COMPILER BUG: cannot put this inside the unittest block as static class.
+    class QMetaObject_A : QObject
+    {
+        mixin Q_CLASSINFO!("author", "Sabrina Schweinsteiger");
+        mixin Q_CLASSINFO!("url", "http://doc.moosesoft.co.uk/1.0/");
+
+        static int slot1Called;
+
+        final
+        {
+            void signal_signal1();
+            void signal_signal2(int);
+        }
+
+
+        void slot_slot1()
+        {
+            slot1Called++;
+        }
+
+        mixin Q_OBJECT;
+    }
+
     unittest
     {
-        static class Test : QObject
-        {
-            mixin Q_CLASSINFO!("author", "Sabrina Schweinsteiger");
-            mixin Q_CLASSINFO!("url", "http://doc.moosesoft.co.uk/1.0/");
+        scope a = new QMetaObject_A;
+        QObject.connect(a, "signal1", a, "slot1");
+        a.signal1();
+        assert(QMetaObject_A.slot1Called == 1);
 
-            mixin Q_OBJECT;
-        }
+        QObject.connect(a, "signal2", a, "slot1");
+        a.signal2(42);
+        assert(QMetaObject_A.slot1Called == 2);
     }
-}
+ }
 
 extern(C) void qtd_QMetaObject_activate_3(void* sender, void* m, int local_signal_index, void **argv);
 extern(C) void qtd_QMetaObject_activate_4(void *sender, void* m, int from_local_signal_index, int to_local_signal_index, void **argv);
--- a/d2/qtd/MOC.d	Thu Jun 24 13:47:30 2010 +0300
+++ b/d2/qtd/MOC.d	Mon Jun 28 21:29:32 2010 +0300
@@ -494,6 +494,7 @@
         std.typetuple,
         std.traits,
         qtd.Marshal,
+        qtd.meta.Runtime,
         qt.core.QString; // for QStringUtil.toNative
 
 public: // required to override the outside scope protection.
@@ -529,45 +530,32 @@
     }
 
     @property
-    override QMetaObject metaObject() const { return staticMetaObject(); }
-
-    private static
+    override QMetaObject metaObject() const
     {
-        __gshared QMetaObject staticMetaObject_;
-        __gshared QMetaObjectNative nativeStaticMetaObject_;
-        bool staticMoInited_;
+        return staticMetaObject;
     }
 
     @property
     static QMetaObject staticMetaObject()
     {
-        // using a thread-local flag to mitigate
-        // the performance hit caused by lazy initialization
-        if(!staticMoInited_)
+        return meta!This;
+    }
+
+    __gshared static QMetaObjectNative nativeStaticMetaObject_;
+
+    static void* qtd_nativeStaticMetaObject()
+    {
+        alias BaseClassesTuple!(This)[0] Base;
+
+        if (!nativeStaticMetaObject_.data)
         {
-            synchronized(qtdMoLock)
-            {
-                if (!staticMetaObject_)
-                {
-                    alias BaseClassesTuple!(This)[0] Base;
-
-                    nativeStaticMetaObject_ = QMetaObjectNative(
-                        Base.staticMetaObject.nativeId,
-                        qt_meta_stringdata.ptr,
-                        qt_meta_data.ptr, null);
-
-                    QMetaObject.create!This(&nativeStaticMetaObject_);
-                }
-            }
-            staticMoInited_ = true;
+            nativeStaticMetaObject_ = QMetaObjectNative(
+                meta!(Base).nativeId,
+                qt_meta_stringdata.ptr,
+                qt_meta_data.ptr, null);
         }
 
-        return staticMetaObject_;
-    }
-
-    /*internal*/ static void setStaticMetaObject(QMetaObject m)
-    {
-        staticMetaObject_ = m;
+        return &nativeStaticMetaObject_;
     }
 }
 
--- a/d2/qtd/String.d	Thu Jun 24 13:47:30 2010 +0300
+++ b/d2/qtd/String.d	Mon Jun 28 21:29:32 2010 +0300
@@ -74,13 +74,10 @@
         *str = toUTF8(arr[0..size]);
     }));
 
-
 // to work around the standard startsWith not being runnable at compile time.
-size_t startsWith(string s, string pattern)
+bool startsWith(string s, string pattern)
 {
-    if (pattern.length <= s.length && s[0..pattern.length] == pattern)
-        return pattern.length;
-    return 0;
+    return pattern.length <= s.length && s[0..pattern.length] == pattern;
 }
 
 
--- a/d2/qtd/meta/Runtime.d	Thu Jun 24 13:47:30 2010 +0300
+++ b/d2/qtd/meta/Runtime.d	Mon Jun 28 21:29:32 2010 +0300
@@ -4,21 +4,25 @@
     License: Boost Software License 1.0
 **************************************************************************/
 module qtd.meta.Runtime;
-//TODO: Probably replace switch dispatch with pointer dispatch
-//and leave switch dispatch only in C interface
 
 import
     qtd.meta.Compiletime,
 
     std.typetuple,
     std.conv,
-    std.variant,
-    core.sync.rwmutex;
+    std.stdio,
+    std.traits,
+    std.variant;
 
-private __gshared ReadWriteMutex lock;
+import std.range : isForwardRange, isRandomAccessRange;
+
+/**
+    Object to lock on when accessing thread-shared meta-objects.
+ */
+immutable Object metaLock;
 shared static this()
 {
-    lock = new ReadWriteMutex;
+    metaLock = cast(immutable)new Object;
 }
 
 /**
@@ -87,13 +91,14 @@
     }
 }
 
-abstract class Meta
+abstract class MetaBase
 {
     alias typeof(this) This;
 
     string name;
     MetaAttribute[] attributes;
-    Meta[] members;
+
+    protected MetaBase[] members_;
 
     template createImpl(M : This)
     {
@@ -125,35 +130,91 @@
 
     protected void construct(alias symbol)()
     {
+        name = symbol.stringof;
         createAttrs!symbol;
     }
+
+    static struct MembersRange
+    {
+        private MetaBase[] members_;
+
+        @property
+        MetaBase front()
+        {
+            return members_[0];
+        }
+
+        @property
+        bool empty()
+        {
+            return members_.length == 0;
+        }
+
+        @property
+        MembersRange save()
+        {
+            return this;
+        }
+
+        @property
+        MetaBase back()
+        {
+            return members_[$ - 1];
+        }
+
+        void popFront()
+        {
+            members_ = members_[1..$];
+        }
+
+        void popBack()
+        {
+            members_ = members_[0..$ - 1];
+        }
+
+        MetaBase opIndex(size_t i)
+        {
+            return members_[i];
+        }
+
+        @property
+        size_t length()
+        {
+            return members_.length;
+        }
+    }
+
+    /**
+        Returns a random access range of members of the class described by this meta-object.
+     */
+    @property
+    MembersRange members()
+    {
+        return MembersRange(members_);
+    }
 }
 
+version (QtdUnittest) unittest
+{
+    static assert(isRandomAccessRange!(MetaBase.MembersRange));
+}
+
 /**
-    Base class for run time attributes.
+    Base class for run-time attributes.
  */
 abstract class MetaAttribute
 {
-    alias typeof(this) This;
-
     string name;
     AttributeOptions options;
 
-    This create(string name, AttributeOptions opts, A...)()
-    {
-        auto ma = new This;
-        ma.construct!(name, opts, A)();
-        return ma;
-    }
-
-    void construct(string name, AttributeOptions opts)()
+    this(string name, AttributeOptions opts)
     {
         this.name = name;
         options = opts;
     }
 }
 
-abstract class MetaType : Meta
+abstract class MetaType : MetaBase
 {
 }
 
@@ -164,7 +225,148 @@
 class MetaClass : MetaAggregate
 {
     alias typeof(this) This;
+
+    private
+    {
+        This base_;
+        This firstDerived_;
+        This next_;
+        ClassInfo classInfo_;
+    }
+
     alias createImpl!This create;
+
+    static struct AllMembersRange
+    {
+        public //private
+        {
+            This metaClass_;
+            MetaBase[] members_;
+
+            void skipEmpty()
+            {
+                while (!metaClass_.members_.length)
+                {
+                    metaClass_ = metaClass_.base_;
+                    if (!metaClass_)
+                    {
+                        members_ = null;
+                        return;
+                    }
+                }
+
+                members_ = metaClass_.members_;
+            }
+        }
+
+        this(This metaClass)
+        {
+            metaClass_ = metaClass;
+            skipEmpty();
+        }
+
+        @property
+        MetaBase front()
+        {
+            return members_[0];
+        }
+
+        @property
+        bool empty()
+        {
+            return members_.length == 0;
+        }
+
+        @property
+        AllMembersRange save()
+        {
+            return this;
+        }
+
+        void popFront()
+        {
+            members_ = members_[1..$];
+            if (!members_.length)
+            {
+                metaClass_ = metaClass_.base_;
+                if (metaClass_)
+                    skipEmpty();
+            }
+        }
+    }
+
+    /**
+        Returns a forward range of members of the class described by this meta-object,
+        including base class members.
+     */
+    @property
+    AllMembersRange allMembers()
+    {
+        return AllMembersRange(this);
+    }
+
+    /**
+        Returns the meta-object of the base class.
+     */
+    @property
+    This base()
+    {
+        return base_;
+    }
+
+    /**
+        Returns the next meta-object on this level of the inheritance hierarchy.
+     */
+    @property
+    This next()
+    {
+        return next_;
+    }
+
+    /**
+        Returns the meta-object for the first derived class.
+     */
+    @property
+    This firstDerived()
+    {
+        return firstDerived_;
+    }
+
+    /**
+        D class info.
+     */
+    @property
+    ClassInfo classInfo()
+    {
+        return classInfo_;
+    }
+
+
+    /* internal */ void construct(T : Object)()
+    {
+        super.construct!T();
+        static if (!is(T == Object))
+        {
+            alias BaseClassesTuple!(T)[0] Base;
+            base_ = meta!Base;
+
+            next_ = base_.firstDerived_;
+            base_.firstDerived_ = this;
+        }
+        classInfo_ = T.classinfo;
+    }
+
+    /**
+     */
+    override string toString() const
+    {
+        return "MetaClass for " ~ classInfo_.name;
+    }
+}
+
+version (QtdUnittest) unittest
+{
+    static assert (isForwardRange!(MetaClass.AllMembersRange));
 }
 
 class MetaStruct : MetaAggregate
@@ -173,58 +375,72 @@
     alias createImpl!This create;
 }
 
+/**
+ */
 @property
-auto meta(alias symbol, M : Meta)()
+M meta(alias symbol, M : MetaBase)()
 {
-    __gshared static M m;
+    __gshared static M sharedM;
+    static M m;
 
+    if (!m)
     {
-        lock.reader.lock;
-        scope(exit)
-            lock.reader.unlock;
-        if (m)
-            return m;
+        synchronized(metaLock)
+        {
+            if (!sharedM)
+                sharedM = M.create!symbol;
+        }
+        m = sharedM;
     }
 
-    lock.writer.lock;
-    scope(exit)
-        lock.writer.unlock;
-
-    if (!m)
-        m = M.create!symbol;
+    assert (m is sharedM);
     return m;
 }
 
+version (QtdUnittest) unittest
+{
+    class A
+    {
+    }
+
+    auto m = meta!A;
+    assert(m is meta!A);
+}
+
+/**
+ */
 // only classes and structs for now
 @property
 auto meta(T)()
 {
-    static if (is(typeof(T.staticMetaObject)))
-        return T.staticMetaObject;
+    static if (is(T.Meta))
+        return meta!(T, T.Meta);
     else static if (is(T == class))
         return meta!(T, MetaClass);
     else static if (is(T == struct))
         return meta!(T, MetaStruct);
     else
-        static assert(false, "No meta object for symbol " ~ T.stringof);
+        static assert(false, "No meta-object for symbol " ~ T.stringof);
 }
 
 /**
-    A run time attribute implementation that stores the attribute data in an
+    A run-time attribute implementation that stores the attribute data in an
     array of variants.
  */
 class MetaVariantAttribute : MetaAttribute
 {
+    alias typeof(this) This;
+
     Variant[] values;
 
-    private this()
+    private this(string name, AttributeOptions opts)
     {
+        super(name, opts);
     }
 
-    static MetaVariantAttribute create(string category, AttributeOptions opts, A...)()
+    static MetaVariantAttribute create(string name, AttributeOptions opts, A...)()
     {
-        auto ret = new MetaVariantAttribute;
-        ret.construct!(category, opts)();
+        auto ret = new This(name, opts);
         foreach(i, _; A)
         {
             static if (__traits(compiles, { ret.values ~= Variant(A[i]); } ))
@@ -235,7 +451,7 @@
 }
 
 /**
-    A run time attribute implementation that stores the attribute data in an
+    A run-time attribute implementation that stores the attribute data in an
     assiciative array of variants.
  */
 class MetaVariantDictAttribute : MetaAttribute
@@ -243,14 +459,14 @@
     Variant[string] values;
     alias typeof(this) This;
 
-    private this()
+    private this(string name, AttributeOptions opts)
     {
+        super(name, opts);
     }
 
-    static This create(string category, AttributeOptions opts, A...)()
+    static This create(string name, AttributeOptions opts, A...)()
     {
-        auto ret = new This;
-        ret.construct!(category, opts)();
+        auto ret = new This(name, opts);
         foreach(i, _; A)
         {
             static if (i % 2 == 0 && __traits(compiles, { ret.values[A[i]] = Variant(A[i + 1]); } ))
@@ -260,33 +476,30 @@
     }
 }
 
-version (QtdUnittest)
+version(QtdUnittest) unittest
 {
-    unittest
+    static void foo() {}
+
+    static class C
     {
-        static void foo() {}
+        mixin InnerAttribute!("variantAttribute", MetaVariantAttribute, "22", foo, 33);
+        mixin InnerAttribute!("variantDictAttribute", MetaVariantDictAttribute,
+            //"a", "33", // PHOBOS BUG: variant is unusable with AAs
+            "b", foo
+            //"c", 44
+            );
+    }
 
-        static class C
-        {
-            mixin InnerAttribute!("variantAttribute", MetaVariantAttribute, "22", foo, 33);
-            mixin InnerAttribute!("variantDictAttribute", MetaVariantDictAttribute,
-                //"a", "33", // PHOBOS BUG: variant is unusable with AAs
-                "b", foo
-                //"c", 44
-                );
-        }
+    auto attrs = meta!(C).attributes;
+    assert(attrs.length == 2);
+    auto attr = cast(MetaVariantAttribute)attrs[0];
 
-        auto attrs = meta!(C).attributes;
-        assert(attrs.length == 2);
-        auto attr = cast(MetaVariantAttribute)attrs[0];
+    assert(attr.name == "variantAttribute");
+    assert(attr.values[0] == "22");
+    assert(attr.values[1] == 33);
 
-        assert(attr.name == "variantAttribute");
-        assert(attr.values[0] == "22");
-        assert(attr.values[1] == 33);
-
-        auto attr2 = cast(MetaVariantDictAttribute) attrs[1];
-        assert(attr2.name == "variantDictAttribute");
-        //assert(attr2.values["a"] == "33");
-        //assert(attr2.values["c"] == 44);
-    }
-}
\ No newline at end of file
+    auto attr2 = cast(MetaVariantDictAttribute) attrs[1];
+    assert(attr2.name == "variantDictAttribute");
+    //assert(attr2.values["a"] == "33");
+    //assert(attr2.values["c"] == 44);
+}
--- a/examples/dialogs/classwizard/build.bat	Thu Jun 24 13:47:30 2010 +0300
+++ b/examples/dialogs/classwizard/build.bat	Mon Jun 28 21:29:32 2010 +0300
@@ -1,2 +1,3 @@
 ../../../tools/drcc/drcc classwizard.qrc > qrc_classwizard.d
-dmd main.d classwizard.d qrc_classwizard.d libqtdcore.lib libqtdgui.lib -I../../../ -I../../../qt/d1 -ofclasswizard
\ No newline at end of file
+dmd -c -O -release -inline -unittest -version=QtdUnittest main.d qrc_classwizard.d classwizard.d ../../../output/build/lib/qtdcore.lib ../../../output/build/lib/qtdgui.lib -I../../../ -I../../../d2 -I../../../output/build/ -ofclasswizard.obj
+dmd -O -release -inline -unittest -version=QtdUnittest classwizard.obj ../../../output/build/lib/qtdcore.lib ../../../output/build/lib/qtdgui.lib -I../../../ -I../../../d2 -I../../../output/build/ -ofclasswizard.exe
--- a/examples/layouts/dynamiclayouts/dialog.d	Thu Jun 24 13:47:30 2010 +0300
+++ b/examples/layouts/dynamiclayouts/dialog.d	Mon Jun 28 21:29:32 2010 +0300
@@ -58,151 +58,153 @@
 {
 public:
 
-	this(QWidget parent = null)
-	{
-		super(parent);
-		createRotableGroupBox();
-		createOptionsGroupBox();
-		createButtonBox();
+    this(QWidget parent = null)
+    {
+        super(parent);
 
-		mainLayout = new QGridLayout;
-		mainLayout.addWidget(rotableGroupBox, 0, 0);
-		mainLayout.addWidget(optionsGroupBox, 1, 0);
-		mainLayout.addWidget(buttonBox, 2, 0);
-		setLayout(mainLayout);
+        createRotableGroupBox();
+        createOptionsGroupBox();
+        createButtonBox();
 
-		mainLayout.setSizeConstraint(QLayout.SetMinimumSize);
+        mainLayout = new QGridLayout;
+        mainLayout.addWidget(rotableGroupBox, 0, 0);
+        mainLayout.addWidget(optionsGroupBox, 1, 0);
+        mainLayout.addWidget(buttonBox, 2, 0);
+        setLayout(mainLayout);
 
-		setWindowTitle(tr("Dynamic Layouts"));
-	}
+        mainLayout.setSizeConstraint(QLayout.SetMinimumSize);
+
+        setWindowTitle(tr("Dynamic Layouts"));
+    }
 
 private: // slots
 
-	void slot_buttonsOrientationChanged(int index)
-	{
-		mainLayout.setSizeConstraint(QLayout.SetNoConstraint);
-		setMinimumSize(0, 0);
+    void slot_buttonsOrientationChanged(int index)
+    {
+        mainLayout.setSizeConstraint(QLayout.SetNoConstraint);
+        setMinimumSize(0, 0);
 
-		Qt.Orientation orientation = cast(Qt.Orientation) buttonsOrientationComboBox.itemData(index).toInt();
+        Qt.Orientation orientation = cast(Qt.Orientation) buttonsOrientationComboBox.itemData(index).toInt();
 
-		if (orientation == buttonBox.orientation())
-			return;
+        if (orientation == buttonBox.orientation())
+            return;
 
-		mainLayout.removeWidget(buttonBox);
+        mainLayout.removeWidget(buttonBox);
 
-		int spacing = mainLayout.spacing();
+        int spacing = mainLayout.spacing();
 
-		QSize oldSizeHint = buttonBox.sizeHint() + QSize(spacing, spacing);
-		buttonBox.setOrientation(orientation);
-		QSize newSizeHint = buttonBox.sizeHint() + QSize(spacing, spacing);
+        QSize oldSizeHint = buttonBox.sizeHint() + QSize(spacing, spacing);
+        buttonBox.setOrientation(orientation);
+        QSize newSizeHint = buttonBox.sizeHint() + QSize(spacing, spacing);
 
-		if (orientation == Qt.Orientation.Horizontal) {
-			mainLayout.addWidget(buttonBox, 2, 0);
-			resize(size() + QSize(-1 * oldSizeHint.width(), newSizeHint.height()));
-		} else {
-			mainLayout.addWidget(buttonBox, 0, 3, 2, 1);
-			resize(size() + QSize(newSizeHint.width(), -1 * oldSizeHint.height()));
-		}
+        if (orientation == Qt.Orientation.Horizontal) {
+            mainLayout.addWidget(buttonBox, 2, 0);
+            resize(size() + QSize(-1 * oldSizeHint.width(), newSizeHint.height()));
+        } else {
+            mainLayout.addWidget(buttonBox, 0, 3, 2, 1);
+            resize(size() + QSize(newSizeHint.width(), -1 * oldSizeHint.height()));
+        }
 
-		mainLayout.setSizeConstraint(QLayout.SetDefaultConstraint);
-	}
+        mainLayout.setSizeConstraint(QLayout.SetDefaultConstraint);
+    }
 
-	void slot_rotateWidgets()
-	{
-		assert(rotableWidgets.length % 2 == 0);
+    void slot_rotateWidgets()
+    {
+        assert(rotableWidgets.length % 2 == 0);
 
-		foreach (QWidget widget; rotableWidgets)
-			rotableLayout.removeWidget(widget);
+        foreach (QWidget widget; rotableWidgets)
+            rotableLayout.removeWidget(widget);
 
-		rotableWidgets = rotableWidgets[1..$] ~ rotableWidgets[0];
-		
-		int n = rotableWidgets.length;
-		for (int i = 0; i < n / 2; ++i) {
-			rotableLayout.addWidget(rotableWidgets[n - i - 1], 0, i);
-			rotableLayout.addWidget(rotableWidgets[i], 1, i);
-		}
-	}
+        rotableWidgets = rotableWidgets[1..$] ~ rotableWidgets[0];
 
-	void slot_help()
-	{
-		QMessageBox.information(this, tr("Dynamic Layouts Help"),
-			tr("This example shows how to change layouts dynamically."));
-	}
+        int n = rotableWidgets.length;
+        for (int i = 0; i < n / 2; ++i) {
+            rotableLayout.addWidget(rotableWidgets[n - i - 1], 0, i);
+            rotableLayout.addWidget(rotableWidgets[i], 1, i);
+        }
+    }
+
+    void slot_help()
+    {
+        QMessageBox.information(this, tr("Dynamic Layouts Help"),
+            tr("This example shows how to change layouts dynamically."));
+    }
 
 private:
-	
-	void createRotableGroupBox()
-	{
-		rotableGroupBox = new QGroupBox(tr("Rotable Widgets"));
 
-		auto a0 = new QSpinBox;
-		auto a1 = new QSlider;
-		auto a2 = new QDial;
-		auto a3 = new QProgressBar;
-		
-		rotableWidgets ~= a0;
-		rotableWidgets ~= a1;
-		rotableWidgets ~= a2;
-		rotableWidgets ~= a3;
+    void createRotableGroupBox()
+    {
+        rotableGroupBox = new QGroupBox(tr("Rotable Widgets"));
 
-		int n = rotableWidgets.length;
-		for (int i = 0; i < n; ++i)
-			connect(rotableWidgets[i], "valueChanged", rotableWidgets[(i + 1) % n], "setValue");
+        auto a0 = new QSpinBox;
+        auto a1 = new QSlider;
+        auto a2 = new QDial;
+        auto a3 = new QProgressBar;
 
-       
-		rotableLayout = new QGridLayout;
-		rotableGroupBox.setLayout(rotableLayout);
+        rotableWidgets ~= a0;
+        rotableWidgets ~= a1;
+        rotableWidgets ~= a2;
+        rotableWidgets ~= a3;
 
-		rotateWidgets();
-	}
+        int n = rotableWidgets.length;
 
-	void createOptionsGroupBox()
-	{
-		optionsGroupBox = new QGroupBox(tr("Options"));
+        for (int i = 0; i < n; ++i)
+            connect(rotableWidgets[i], "valueChanged", rotableWidgets[(i + 1) % n], "setValue");
 
-		buttonsOrientationLabel = new QLabel(tr("Orientation of buttons:"));
+        rotableLayout = new QGridLayout;
+        rotableGroupBox.setLayout(rotableLayout);
 
-		buttonsOrientationComboBox = new QComboBox;
-		buttonsOrientationComboBox.addItem(tr("Horizontal"), new QVariant(cast(ulong) Qt.Horizontal));
-		buttonsOrientationComboBox.addItem(tr("Vertical"), new QVariant(cast(ulong) Qt.Vertical));
+        rotateWidgets();
 
-		connect(buttonsOrientationComboBox, "currentIndexChanged", this, "buttonsOrientationChanged");
-      
-		optionsLayout = new QGridLayout;
-		optionsLayout.addWidget(buttonsOrientationLabel, 0, 0);
-		optionsLayout.addWidget(buttonsOrientationComboBox, 0, 1);
-		optionsLayout.setColumnStretch(2, 1);
-		optionsGroupBox.setLayout(optionsLayout);
-	}
+    }
 
-	void createButtonBox()
-	{
-		buttonBox = new QDialogButtonBox;
+    void createOptionsGroupBox()
+    {
+        optionsGroupBox = new QGroupBox(tr("Options"));
 
-		closeButton = buttonBox.addButton(QDialogButtonBox.Close);
-		helpButton = buttonBox.addButton(QDialogButtonBox.Help);
-		rotateWidgetsButton = buttonBox.addButton(tr("Rotate &Widgets"), QDialogButtonBox.ActionRole);
+        buttonsOrientationLabel = new QLabel(tr("Orientation of buttons:"));
 
-		connect(rotateWidgetsButton, "clicked", this, "rotateWidgets");
-		connect(closeButton, "clicked", this, "close");
-		connect(helpButton, "clicked", this, "help");
-	}
+        buttonsOrientationComboBox = new QComboBox;
+        buttonsOrientationComboBox.addItem(tr("Horizontal"), new QVariant(cast(ulong) Qt.Horizontal));
+        buttonsOrientationComboBox.addItem(tr("Vertical"), new QVariant(cast(ulong) Qt.Vertical));
 
-	QGroupBox rotableGroupBox;
-	QWidget[] rotableWidgets;
-    
-	QGroupBox optionsGroupBox;
-	QLabel buttonsOrientationLabel;
-	QComboBox buttonsOrientationComboBox;
+        connect(buttonsOrientationComboBox, "currentIndexChanged", this, "buttonsOrientationChanged");
 
-	QDialogButtonBox buttonBox;
-	QPushButton closeButton;
-	QPushButton helpButton;
-	QPushButton rotateWidgetsButton;
+        optionsLayout = new QGridLayout;
+        optionsLayout.addWidget(buttonsOrientationLabel, 0, 0);
+        optionsLayout.addWidget(buttonsOrientationComboBox, 0, 1);
+        optionsLayout.setColumnStretch(2, 1);
+        optionsGroupBox.setLayout(optionsLayout);
+    }
 
-	QGridLayout mainLayout;
-	QGridLayout rotableLayout;
-	QGridLayout optionsLayout;
+    void createButtonBox()
+    {
+        buttonBox = new QDialogButtonBox;
+
+        closeButton = buttonBox.addButton(QDialogButtonBox.Close);
+        helpButton = buttonBox.addButton(QDialogButtonBox.Help);
+        rotateWidgetsButton = buttonBox.addButton(tr("Rotate &Widgets"), QDialogButtonBox.ActionRole);
+
+        connect(rotateWidgetsButton, "clicked", this, "rotateWidgets");
+        connect(closeButton, "clicked", this, "close");
+        connect(helpButton, "clicked", this, "help");
+    }
+
+    QGroupBox rotableGroupBox;
+    QWidget[] rotableWidgets;
+
+    QGroupBox optionsGroupBox;
+    QLabel buttonsOrientationLabel;
+    QComboBox buttonsOrientationComboBox;
+
+    QDialogButtonBox buttonBox;
+    QPushButton closeButton;
+    QPushButton helpButton;
+    QPushButton rotateWidgetsButton;
+
+    QGridLayout mainLayout;
+    QGridLayout rotableLayout;
+    QGridLayout optionsLayout;
 
     mixin Q_OBJECT;
 }
--- a/examples/layouts/dynamiclayouts/main.d	Thu Jun 24 13:47:30 2010 +0300
+++ b/examples/layouts/dynamiclayouts/main.d	Mon Jun 28 21:29:32 2010 +0300
@@ -44,10 +44,12 @@
 import qt.gui.QApplication;
 import dialog;
 
+import std.stdio;
+
 
 int main(string[] args)
 {
-	scope app = new QApplication(args);
-	scope dialog = new Dialog;
-	return dialog.exec();
+    scope app = new QApplication(args);
+    scope dialog = new Dialog;
+    return dialog.exec();
 }
--- a/generator/dgenerator.cpp	Thu Jun 24 13:47:30 2010 +0300
+++ b/generator/dgenerator.cpp	Mon Jun 28 21:29:32 2010 +0300
@@ -1958,7 +1958,8 @@
         if (d_class->isQObject()) {
             s << "public import qtd.Signal;" << endl
               << "public import qtd.MOC;" << endl
-              << "public import qt.core.QMetaObject;" << endl;
+              << "public import qt.core.QMetaObject;" << endl
+              << "import qtd.meta.Runtime;";
 
             if (d_class->name() != "QObject")
                 s << "public import qt.core.QObject;" << endl;
@@ -2567,11 +2568,6 @@
         if (d_class->typeEntry()->isValue())
             s << INDENT << d_class->name() << ".QTypeInfo.init();" << endl;
 
-        if (d_class->isQObject()) {
-            // ensure meta-object is created at static construction
-            s << INDENT << d_class->name() << ".staticMetaObject();" << endl;
-        }
-
         if (cpp_shared && d_class->generateShellClass()) {
 
             AbstractMetaFunction::Options opts(AbstractMetaFunction::DeclaringClass | AbstractMetaFunction::NoExternNamespace);
@@ -2760,30 +2756,27 @@
           << "    }" << endl << endl;
     }
 
-    s << "    private static __gshared QMetaObject staticMetaObject_;" << endl
-      << "    protected static void setStaticMetaObject(QMetaObject m) {" << endl
-      << "        staticMetaObject_ = m;" << endl
+    s << "    @property QMetaObject metaObject() {" << endl
+      << "        return staticMetaObject;" << endl
       << "    }" << endl << endl
 
-      << "    @property QMetaObject metaObject() {" << endl
-      << "        return staticMetaObject_;" << endl
+      << "    @property static QMetaObject staticMetaObject() {" << endl
+      << "        return meta!(" << d_class->name() << ");" << endl
       << "    }" << endl << endl
 
-      << "    @property static QMetaObject staticMetaObject() {" << endl
-      << "        if (!staticMetaObject_)" << endl
-      << "            QMetaObject.create!(typeof(this))(qtd_" << d_class->name() << "_staticMetaObject());" << endl
-      << "        return staticMetaObject_;" << endl
+      << "    static " << d_class->name() << " __getObject(void* nativeId) {" << endl
+      << "        return static_cast!(" << d_class->name() << ")(staticMetaObject.getObject(nativeId));" << endl
       << "    }" << endl << endl
 
-      << "    static " << d_class->name() << " __getObject(void* nativeId) {" << endl
-      << "        return static_cast!(" << d_class->name() << ")(staticMetaObject_.getObject(nativeId));" << endl
-      << "    }" << endl << endl
-
-      << "    /* internal */ static void __createEntity(void* nativeId, void* dId) {" << endl
+      << "    static void __createEntity(void* nativeId, void* dId) {" << endl
       << "        return qtd_" << d_class->name() << "_createEntity(nativeId, dId);" << endl
       << "    }" << endl << endl
 
-      << "    /* internal */ static void _populateMetaInfo() {" << endl
+      << "    static void* qtd_nativeStaticMetaObject() {" << endl
+      << "        return qtd_" << d_class->name() << "_staticMetaObject();" << endl
+      << "    }" << endl
+
+      << "    static void _populateMetaInfo(QMetaObject mo) {" << endl
       << "        int index;" << endl << endl;
 
     AbstractMetaFunctionList signal_funcs = signalFunctions(d_class, false);
@@ -2796,8 +2789,8 @@
       do // need this to look for default arguments and generate extra signatures
       {
           AbstractMetaFunction *fn = signal_funcs.at(i);
-    s << "        index = staticMetaObject_.indexOfMethod_Cpp(__signalSignatures[" << staticId << "]);" << endl
-    << "        staticMetaObject_.addMethod(new QMetaSignal(signature!(";
+    s << "        index = mo.indexOfMethod_Cpp(__signalSignatures[" << staticId << "]);" << endl
+      << "        mo.addMethod(new QMetaSignal(signature!(";
           writeMetaMethodArguments(s, fn, j);
     s << ")(\"" << fn->name() << "\"), index));" << endl << endl;
           AbstractMetaArgumentList args = fn->arguments();
@@ -2818,8 +2811,8 @@
       do // need this to look for default arguments and generate extra signatures
       {
           AbstractMetaFunction *fn = slot_funcs.at(i);
-    s << "        index = staticMetaObject_.indexOfMethod_Cpp(__slotSignatures[" << staticId << "]);" << endl
-    << "        staticMetaObject_.addMethod(new QMetaSlot(signature!(";
+    s << "        index = mo.indexOfMethod_Cpp(__slotSignatures[" << staticId << "]);" << endl
+      << "        mo.addMethod(new QMetaSlot(signature!(";
           writeMetaMethodArguments(s, fn, j);
     s << ")(\"" << fn->name() << "\"), index));" << endl << endl;
           AbstractMetaArgumentList args = fn->arguments();
--- a/generator/typesystem_core-java.java	Thu Jun 24 13:47:30 2010 +0300
+++ b/generator/typesystem_core-java.java	Mon Jun 28 21:29:32 2010 +0300
@@ -46,6 +46,8 @@
 
 class QObject___ extends QObject {
     
+    alias QMetaObject Meta;
+    
     /* TODO: test whether the linked list is really a better solution
     public bool __stackAllocated = false;
     
--- a/mini/test1/build	Thu Jun 24 13:47:30 2010 +0300
+++ b/mini/test1/build	Mon Jun 28 21:29:32 2010 +0300
@@ -1,3 +1,4 @@
 #! /bin/bash
 
-dmd main.d -L-L../../lib -L-lqtdcore -I../../ -I../../qt/d2 -L-lQtCore
\ No newline at end of file
+dmd main.d -L-L/home/maxter/qtsdk-2010.02/qt/lib -L-L../../output-linux/build/lib -L-lqtdcore -I../../output-linux/build/ -I../../d2 -L-lQtCore
+
--- a/mini/test1/main.d	Thu Jun 24 13:47:30 2010 +0300
+++ b/mini/test1/main.d	Mon Jun 28 21:29:32 2010 +0300
@@ -3,28 +3,13 @@
 import std.stdio;
 import std.conv;
 import qtd.QtdObject;
-
-class A
-{
-    string name;
-
-    this(A copy)
-    {
-        writeln("Creating new from ", copy.name);
-        name = "Copy of " ~ copy.name;
-    }
-
-    this(string name)
-    {
-        this.name = name;
-    }
-
-    void dispose()
-    {
-        writeln("Disposing ", name);
-    }
-}
+//import qt.gui.QApplication;
 
 void main(string[] args)
 {
+    /+
+    writeln("Application");
+    scope app = new QApplication(args);
+    app.exec();
+    +/
 }