Mercurial > projects > qtd
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); |