comparison d2/qt/core/QMetaObject.d @ 344:96a75b1e5b26

project structure changes
author Max Samukha <maxter@spambox.com>
date Fri, 14 May 2010 12:14:37 +0300
parents qt/core/QMetaObject.d@5896535a03cd
children 31520b2c0b3c
comparison
equal deleted inserted replaced
343:552647ec0f82 344:96a75b1e5b26
1 module qt.core.QMetaObject;
2
3 import qt.QGlobal;
4 import qt.core.QObject;
5 import qtd.QtdObject;
6
7 import std.algorithm;
8 import std.string;
9 import std.stdio;
10
11 class Meta
12 {
13 string name;
14 }
15
16 class MetaType : Meta
17 {
18 this()
19 {
20 }
21 }
22
23 class MetaVariable : Meta
24 {
25 MetaType type;
26 }
27
28 class MetaCallable : Meta { }
29
30 class MetaMethod : Meta { }
31
32 class QMetaArgument : MetaVariable { }
33
34 class QMetaMethod : MetaMethod
35 {
36 // QMetaArgument[] arguments;
37 string signature;
38 int indexOfMethod;
39
40 this(string signature_, int indexOfMethod_)
41 {
42 signature = signature_;
43 indexOfMethod = indexOfMethod_;
44 }
45
46 string args() const
47 {
48 int openBracket = indexOf(signature, '(');
49 if(signature.length - openBracket - 2 > 0)
50 return signature[openBracket + 1 .. $-1];
51 else
52 return "";
53 }
54
55 string name() const
56 {
57 int openBracket = indexOf(signature, '(');
58 return signature[0..openBracket];
59 }
60 }
61
62 class QMetaSignal : QMetaMethod
63 {
64 this(string signature_, int indexOfMethod_)
65 {
66 super(signature_, indexOfMethod_);
67 }
68 }
69
70 class QMetaSlot : QMetaMethod
71 {
72 this(string signature_, int indexOfMethod_)
73 {
74 super(signature_, indexOfMethod_);
75 }
76 }
77
78 class MetaObject : MetaType
79 {
80 MetaObject _base;
81 }
82
83 struct QMetaObjectNative
84 {
85 QMetaObjectNative *superdata;
86 immutable(char) *stringdata;
87 const(uint) *data;
88 void *extradata;
89 }
90
91 class QMetaException : Exception { this(string msg) { super(msg); } }
92
93 final class QMetaObject
94 {
95 enum Call
96 {
97 InvokeMetaMethod,
98 ReadProperty,
99 WriteProperty,
100 ResetProperty,
101 QueryPropertyDesignable,
102 QueryPropertyScriptable,
103 QueryPropertyStored,
104 QueryPropertyEditable,
105 QueryPropertyUser,
106 CreateInstance
107 }
108
109 private
110 {
111 QMetaObjectNative* _nativeId;
112 QMetaObject _base; // super class
113 QMetaObject _firstDerived; // head of the linked list of derived classes
114 QMetaObject _next; // next sibling on this derivation level
115 QMetaMethod[] _methods;
116 ClassInfo _classInfo;
117
118 QObject function(void* nativeId) _createWrapper;
119 }
120
121 private void addDerived(QMetaObject mo)
122 {
123 mo._next = _firstDerived;
124 _firstDerived = mo;
125 }
126
127 // NOTE: construction is split between this non-templated constructor and 'construct' function below.
128 this(QMetaObjectNative* nativeId, QMetaObject base)
129 {
130 _nativeId = nativeId;
131 if (base)
132 {
133 base.addDerived(this);
134 _base = base;
135 }
136 }
137
138 // TODO: remove when D acquires templated constructors
139 void construct(T : QObject, Concrete = T)()
140 {
141 _classInfo = T.classinfo;
142
143 _createWrapper = function QObject(void* nativeId) {
144 // COMPILER BUG: cast is should not be needed
145 auto obj = new Concrete(nativeId, cast(QtdObjectFlags)(QtdObjectFlags.nativeOwnership | QtdObjectFlags.dynamicEntity));
146 // TODO: Probably this should be a virtual call from T's constructor
147 T.__createEntity(nativeId, cast(void*)obj);
148 return obj;
149 };
150 }
151
152 /++
153 +/
154 QMetaObject base()
155 {
156 return _base;
157 }
158
159 /++
160 +/
161 QMetaObjectNative* nativeId()
162 {
163 return _nativeId;
164 }
165
166 /++
167 +/
168 ClassInfo classInfo()
169 {
170 return _classInfo;
171 }
172
173 const (QMetaMethod[]) methods()
174 {
175 return _methods;
176 }
177
178 void addMethod(QMetaMethod method_)
179 {
180 _methods ~= method_;
181 }
182
183 QMetaMethod lookUpMethod(string slot)
184 {
185 foreach (method; _methods)
186 if (method.signature == slot)
187 return method;
188 if (_base)
189 return _base.lookUpMethod(slot);
190 else
191 return null;
192 }
193
194 QMetaSignal lookUpSignal(string signal)
195 {
196 foreach (method; _methods)
197 if (method.signature == signal && cast(QMetaSignal)method)
198 return cast(QMetaSignal)method;
199 if (_base)
200 return _base.lookUpSignal(signal);
201 else
202 return null;
203 }
204
205 QMetaMethod[] lookUpMethodOverloads(string methodName)
206 {
207 typeof(return) result;
208 foreach (method; _methods)
209 if (method.name == methodName)
210 result ~= method;
211 if (_base)
212 result ~= _base.lookUpMethodOverloads(methodName);
213 return result;
214 }
215
216 QMetaSignal[] lookUpSignalOverloads(string signalName)
217 {
218 typeof(return) result;
219 foreach (method; _methods)
220 if (method.name == signalName && cast(QMetaSignal)method)
221 result ~= cast(QMetaSignal)method;
222 if (_base)
223 result ~= _base.lookUpSignalOverloads(signalName);
224 return result;
225 }
226
227 private QMetaObject lookupDerived(void*[] moIds)
228 {
229 assert (moIds.length >= 1);
230
231 for (auto mo = _firstDerived; mo !is null; mo = mo._next)
232 {
233 if (mo._nativeId == moIds[0])
234 {
235 if (moIds.length == 1) // exact match found
236 return mo;
237 else // look deeper
238 return mo.lookupDerived(moIds[1..$]);
239 }
240 }
241
242 // no initialized wrapper that matches the native object.
243 // use the base class wrapper
244 return this;
245 }
246
247 QObject getObject(void* nativeObjId)
248 {
249 QObject result;
250
251 if (nativeObjId)
252 {
253 result = cast(QObject)qtd_get_d_qobject(nativeObjId);
254 if (!result)
255 {
256 auto moId = qtd_QObject_metaObject(nativeObjId);
257 if (_nativeId == moId)
258 result = _createWrapper(nativeObjId);
259 else
260 {
261 // get native metaobjects for the entire derivation lattice
262 // up to, but not including, the current metaobject.
263 size_t moCount = 1;
264
265 for (void* tmp = moId;;)
266 {
267 tmp = qtd_QMetaObject_superClass(tmp);
268 assert(tmp);
269 if (tmp == _nativeId)
270 break;
271 moCount++;
272 }
273
274 void*[] moIds = (cast(void**)alloca(moCount * (void*).sizeof))[0..moCount];
275
276 moIds[--moCount] = moId;
277 while (moCount > 0)
278 moIds[--moCount] = moId = qtd_QMetaObject_superClass(moId);
279
280 result = lookupDerived(moIds)._createWrapper(nativeObjId);
281 }
282 }
283 }
284
285 return result;
286 }
287
288 static void activate(QObject sender, QMetaObject m, int local_signal_index, void **argv)
289 {
290 qtd_QMetaObject_activate_3(sender.__nativeId, m.nativeId, local_signal_index, argv);
291 }
292
293 static void activate(QObject sender, QMetaObject m, int from_local_signal_index, int to_local_signal_index, void **argv)
294 {
295 qtd_QMetaObject_activate_4(sender.__nativeId, m.nativeId, from_local_signal_index, to_local_signal_index, argv);
296 }
297
298 static bool connect(const QObject sender, int signal_index,
299 const QObject receiver, int method_index,
300 int type = 0, int *types = null)
301 {
302 return qtd_QMetaObject_connect(sender.__nativeId, signal_index, receiver.__nativeId, method_index, type, types);
303 }
304
305 int indexOfMethod_Cpp(string method)
306 {
307 return qtd_QMetaObject_indexOfMethod(_nativeId, toStringz(method));
308 }
309
310 int methodCount()
311 {
312 return qtd_QMetaObject_methodCount(_nativeId);
313 }
314
315 static void connectImpl(QObject sender, string signalString, QObject receiver, string methodString, int type)
316 {
317 QMetaSignal[] signals;
318 QMetaMethod[] methods;
319 QMetaSignal signal;
320 QMetaMethod method;
321
322 if(indexOf(signalString, '(') > 0)
323 signal = sender.metaObject.lookUpSignal(signalString);
324 else
325 signals = sender.metaObject.lookUpSignalOverloads(signalString); // parameters not specified. Looking for a match
326
327 if(indexOf(methodString, '(') > 0)
328 method = receiver.metaObject.lookUpMethod(methodString);
329 else
330 methods = receiver.metaObject.lookUpMethodOverloads(methodString); // parameters not specified. Looking for a match
331
332 if(!signal && !method)
333 {
334 Top:
335 foreach(sig; signals)
336 foreach(meth; methods)
337 if(startsWith(sig.args, meth.args))
338 {
339 signal = sig;
340 method = meth;
341 break Top;
342 }
343 }
344 else if (!signal)
345 {
346 foreach(sig; signals)
347 if(startsWith(sig.args, method.args))
348 {
349 signal = sig;
350 break;
351 }
352 }
353 else if (!method)
354 {
355 foreach(meth; methods)
356 if(startsWith(signal.args, meth.args))
357 {
358 method = meth;
359 break;
360 }
361 }
362
363 bool success = false;
364
365 if(!signal && !method)
366 {
367 success = false;
368 }
369 else
370 {
371 int signalIndex = signal.indexOfMethod;
372 int methodIndex = method.indexOfMethod;
373 success = QMetaObject.connect(sender, signalIndex, receiver, methodIndex, type);
374 }
375
376 if(!success)
377 throw new QMetaException("QMetaObject: Signal " ~ signalString ~ " and slot " ~ methodString ~ " cannot be found");
378 }
379 }
380
381 extern(C) void qtd_QMetaObject_activate_3(void* sender, void* m, int local_signal_index, void **argv);
382 extern(C) void qtd_QMetaObject_activate_4(void *sender, void* m, int from_local_signal_index, int to_local_signal_index, void **argv);
383 extern(C) bool qtd_QMetaObject_connect(const void* sender, int signal_index,
384 const void* receiver, int method_index,
385 int type, int *types);
386
387 extern(C) int qtd_QMetaObject_indexOfMethod(void *nativeId, const(char) *method);
388 extern(C) int qtd_QMetaObject_methodCount(void *nativeId);
389
390 extern(C) void* qtd_QMetaObject_superClass(void* nativeId);