Mercurial > projects > qtd
view d2/qt/core/QMetaObject.d @ 369:6e1857c521af
removed unnecessary std.stdio
author | Max Samukha <maxter@maxter.com> |
---|---|
date | Mon, 28 Jun 2010 22:02:08 +0300 |
parents | 185df9220ea7 |
children | a032df77b6ab |
line wrap: on
line source
module qt.core.QMetaObject; import qt.QGlobal, qt.core.QObject, qtd.QtdObject, qtd.meta.Runtime, qtd.meta.Compiletime, qtd.Marshal, qtd.MOC, qtd.String, std.typetuple, std.traits, std.c.stdlib; import std.string : indexOf; import std.algorithm : filter; class QMetaArgument : MetaBase { } class QMetaMethod : MetaBase { alias typeof(this) This; // QMetaArgument[] arguments; string signature; int index; this(string signature, int index) { this.signature = signature; this.index = index; int openBracket = indexOf(signature, '('); name = signature[0..openBracket]; } string args() const { int openBracket = indexOf(signature, '('); if(signature.length - openBracket - 2 > 0) return signature[openBracket + 1 .. $-1]; else return ""; } 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) { super(signature, indexOfMethod); } static This create(alias method)(uint index) { return typeof(super).create!(method, This)(index); } } class QMetaSlot : QMetaMethod { alias typeof(this) This; this(string signature, int indexOfMethod) { super(signature, indexOfMethod); } static This create(alias method)(uint index) { return typeof(super).create!(method, This)(index); } } /** Base class for QtD meta-classes. */ abstract class QtdMetaClass : MetaClass { private: void* nativeId_; public: this() {} /** */ @property void* nativeId() { return nativeId_; } void construct(T)() { super.construct!T(); nativeId_ = T.qtd_nativeStaticMetaObject(); } } struct QMetaObjectNative { QMetaObjectNative *superdata; immutable(char) *stringdata; const(uint) *data; void *extradata; } /** */ final class QMetaObject : QtdMetaClass { alias typeof(this) This; private QObject function(void* nativeId) _createWrapper; this() {} enum Call { InvokeMetaMethod, ReadProperty, WriteProperty, ResetProperty, QueryPropertyDesignable, QueryPropertyScriptable, QueryPropertyStored, QueryPropertyEditable, QueryPropertyUser, CreateInstance } alias createImpl!This create; void construct(T : QObject)() { super.construct!T(); static if (isQtType!T) { static if (is(T.ConcreteType)) alias T.ConcreteType Concrete; else alias T Concrete; _createWrapper = function QObject(void* nativeId) { auto obj = new Concrete(nativeId, cast(QtdObjectFlags)(QtdObjectFlags.nativeOwnership | QtdObjectFlags.dynamicEntity)); T.__createEntity(nativeId, cast(void*)obj); return obj; }; T._populateMetaInfo(this); } // create run time meta-objects for user-defined signals and slots else static if (is(typeof(T.methods))) { alias BaseClassesTuple!(T)[0] Base; int index = meta!(Base).methodCount; static if (T.signals.length) { foreach (signal; T.signals) { addMethod(QMetaSignal.create!signal(index)); index++; } } static if (T.slots.length) { foreach (slot; T.slots) { addMethod(QMetaSlot.create!slot(index)); index++; } } } } /** */ @property override This next() { return static_cast!This(super.next); } /** */ @property override This firstDerived() { return static_cast!This(super.firstDerived); } void addMethod(QMetaMethod method) { members_ ~= method; } /** */ @property override This base() { return super.base; } /** */ @property QMetaObjectNative* nativeId() { return cast(QMetaObjectNative*)super.nativeId; } M lookUpMethod(M : QMetaMethod = QMetaMethod)(string signature) { foreach (method; allMembers) { if (auto m = cast(M)method) { if (m.signature == signature) return m; } } return null; } // TODO: probably make this return a filtering range. auto lookUpMethodOverloads(M : QMetaMethod = QMetaMethod)(string name) { M[] methods; foreach (m; allMembers) { if (auto method = cast(M)m) { if (method.name == name) methods ~= method; } } return methods; } 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); auto nId = nativeId; if (nId == 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 == nId) 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); } static void connectImpl(QObject sender, string signalString, QObject receiver, string methodString, int type) { QMetaSignal[] signals; QMetaMethod[] methods; QMetaSignal signal; QMetaMethod method; if(indexOf(signalString, '(') > 0) signal = sender.metaObject.lookUpMethod!QMetaSignal(signalString); else signals = sender.metaObject.lookUpMethodOverloads!QMetaSignal(signalString); // parameters not specified. Looking for a match if(indexOf(methodString, '(') > 0) method = receiver.metaObject.lookUpMethod(methodString); else methods = receiver.metaObject.lookUpMethodOverloads(methodString); // parameters not specified. Looking for a match if(!signal && !method) { Top: foreach(sig; signals) { foreach(meth; methods) { if(startsWith(sig.args, meth.args)) { signal = sig; method = meth; break Top; } } } } else if (!signal) { foreach(sig; signals) if(startsWith(sig.args, method.args)) { signal = sig; break; } } else if (!method) { foreach(meth; methods) if(startsWith(signal.args, meth.args)) { method = meth; break; } } bool success = false; if(!signal && !method) { success = false; } else { int signalIndex = signal.index; int methodIndex = method.index; success = QMetaObject.connect(sender, signalIndex, receiver, methodIndex, type); } if(!success) { 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."); } } } /** */ mixin template Q_CLASSINFO(string name, string value) { 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 { scope a = new QMetaObject_A; QObject.connect(a, "signal1", a, "slot1"); a.signal1(); assert(QMetaObject_A.slot1Called == 1); 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); 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);