view qt/core/QMetaObject.d @ 296:5173835bb372 signals

iteration over QList with opApply
author eldar
date Sun, 22 Nov 2009 20:43:10 +0000
parents f9559a957be9
children 7c2cf27391c4
line wrap: on
line source

module qt.core.QMetaObject;

import qt.QGlobal;
import qt.core.QObject;
import qt.QtdObject;

import std.algorithm;

class Meta
{
    string name;
}

class MetaType : Meta
{
    this()
    {
    }
}

class MetaVariable : Meta
{
    MetaType type;
}

class MetaCallable : Meta { }

class MetaMethod : Meta { }

class QMetaArgument : MetaVariable { }

class QMetaMethod : MetaMethod
{
//    QMetaArgument[] arguments;
    string signature;
    int indexOfMethod;
    
    this(string signature_, int indexOfMethod_)
    {
        signature = signature_;
        indexOfMethod = indexOfMethod_;
    }
}

class QMetaSignal : QMetaMethod
{
    this(string signature_, int indexOfMethod_)
    {
        super(signature_, indexOfMethod_);
    }
}

class QMetaSlot : QMetaMethod
{
    this(string signature_, int indexOfMethod_)
    {
        super(signature_, indexOfMethod_);
    }
}

class MetaObject : MetaType
{
    MetaObject _base;
}

struct QMetaObjectNative
{
    QMetaObjectNative *superdata;
    immutable(char) *stringdata;
    const(uint) *data;
    void *extradata;
}

final class QMetaObject
{
    enum Call
    {
        InvokeMetaMethod,
        ReadProperty,
        WriteProperty,
        ResetProperty,
        QueryPropertyDesignable,
        QueryPropertyScriptable,
        QueryPropertyStored,
        QueryPropertyEditable,
        QueryPropertyUser,
        CreateInstance
    }
    
    private
    {
        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;
    }
    
    // NOTE: construction is split between this non-templated constructor and 'construct' function below.
    this(QMetaObjectNative* 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;        

        _createWrapper = function QObject(void* nativeId) {
                // COMPILER BUG: cast is should not be needed
                auto obj = new Concrete(nativeId, cast(QtdObjectFlags)(QtdObjectFlags.nativeOwnership | QtdObjectFlags.dynamicEntity));
                // TODO: Probably this should be a virtual call from T's constructor
                T.__createEntity(nativeId, cast(void*)obj);
                return obj;
            };
    }
    
    /++
    +/
    QMetaObject base()
    {
        return _base;
    }
    
    /++
    +/
    QMetaObjectNative* nativeId()
    {
        return _nativeId;
    }

    /++
    +/
    ClassInfo classInfo()
    {
        return _classInfo;
    }
    
    const (QMetaMethod[]) methods()
    {
        return _methods;
    }
    
    void addMethod(QMetaMethod method_)
    {
        _methods ~= method_;
    }
    
    int lookUpMethod(string slot)
    {
        foreach (method; _methods)
            if (method.signature == slot)
                return method.indexOfMethod;
        if (_base)
            return _base.lookUpMethod(slot);
        else
            return -1;
    }
    
    int lookUpSignal(string signal)
    {
//        auto signalBegin = signal[0..$-1];
        foreach (method; _methods)
            if (method.signature == signal && cast(QMetaSignal)method)
                return method.indexOfMethod;
        if (_base)
            return _base.lookUpSignal(signal);
        else
            return -1;
    }
    
    private QMetaObject lookupDerived(void*[] moIds)
    {
        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;
                else // look deeper
                    return mo.lookupDerived(moIds[1..$]);
            }
        }
        
        // no initialized wrapper that matches the native object.
        // use the base class wrapper
        return this;
    }
    
    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)._createWrapper(nativeObjId);
                }
            }
        }

        return result;
    }
    
    static void activate(QObject sender, QMetaObject m, int local_signal_index, void **argv)
    {
        qtd_QMetaObject_activate_3(sender.__nativeId, m.nativeId, local_signal_index, argv);
    }
    
    static void activate(QObject sender, QMetaObject m, int from_local_signal_index, int to_local_signal_index, void **argv)
    {
        qtd_QMetaObject_activate_4(sender.__nativeId, m.nativeId, from_local_signal_index, to_local_signal_index, argv);
    }

    static bool connect(const QObject sender, int signal_index,
                        const QObject receiver, int method_index,
                        int type = 0, int *types = null)
    {
        return qtd_QMetaObject_connect(sender.__nativeId, signal_index, receiver.__nativeId, method_index, type, types);
    }
    
    int indexOfMethod_Cpp(string method)
    {
        return qtd_QMetaObject_indexOfMethod(_nativeId, toStringz(method));
    }
    
    int methodCount()
    {
        return qtd_QMetaObject_methodCount(_nativeId);
    }

}

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);
extern(C) bool qtd_QMetaObject_connect(const void* sender, int signal_index,
                                       const void* receiver, int method_index,
                                       int type, int *types);
                                       
extern(C) int qtd_QMetaObject_indexOfMethod(void *nativeId, const(char) *method);
extern(C) int qtd_QMetaObject_methodCount(void *nativeId);

extern(C) void* qtd_QMetaObject_superClass(void* nativeId);