qtbindings 4.8.6.1 → 4.8.6.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
- data/bin/rbqtapi +0 -0
- data/bin/rbrcc +0 -0
- data/bin/rbuic4 +0 -0
- data/bin/smokeapi +0 -0
- data/bin/smokedeptool +0 -0
- data/ext/ruby/qtruby/src/Qt.cpp +1327 -1310
- data/ext/ruby/qtruby/src/qtruby.cpp +9 -2
- data/ext/smoke/qtgui/smokeconfig.xml +0 -0
- data/lib/Qt/qtruby4.rb +21 -11
- data/lib/qtbindings_version.rb +2 -2
- metadata +47 -47
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 874c746da6fcf13bcc0fb15ad796433b0b15096e
|
4
|
+
data.tar.gz: 1de49eb84b084043466eb169b6f1f08693ac872d
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 0e707b3a1425145c4a03d1102d315c4765301d0f35fd26a26fffe276028065907388e38f1aae4826921b6ad8468a9fe7e681f3a74f65d91ea1f9c489c5c50244
|
7
|
+
data.tar.gz: 9a7cd631a80d509a3b23fa5a5e1d1ab63d318c9b7d4070e9f4f6a2f833da4fe3aa35d7f564b75989ea7736c86f4ba17bd8d64c89a53b027b0aab85891a4bbe6f
|
data/bin/rbqtapi
CHANGED
File without changes
|
data/bin/rbrcc
CHANGED
File without changes
|
data/bin/rbuic4
CHANGED
File without changes
|
data/bin/smokeapi
CHANGED
File without changes
|
data/bin/smokedeptool
CHANGED
File without changes
|
data/ext/ruby/qtruby/src/Qt.cpp
CHANGED
@@ -1,1310 +1,1327 @@
|
|
1
|
-
/***************************************************************************
|
2
|
-
Qt.cpp - description
|
3
|
-
-------------------
|
4
|
-
begin : Fri Jul 4 2003
|
5
|
-
copyright : (C) 2003-2006 by Richard Dale
|
6
|
-
email : Richard_Dale@tipitina.demon.co.uk
|
7
|
-
***************************************************************************/
|
8
|
-
|
9
|
-
/***************************************************************************
|
10
|
-
* *
|
11
|
-
* This program is free software; you can redistribute it and/or modify *
|
12
|
-
* it under the terms of the GNU Lesser General Public License as *
|
13
|
-
* published by the Free Software Foundation; either version 2 of the *
|
14
|
-
* License, or (at your option) any later version. *
|
15
|
-
* *
|
16
|
-
***************************************************************************/
|
17
|
-
|
18
|
-
#ifndef _GNU_SOURCE
|
19
|
-
#define _GNU_SOURCE
|
20
|
-
#endif
|
21
|
-
#include <stdio.h>
|
22
|
-
#include <stdarg.h>
|
23
|
-
|
24
|
-
#include <QtCore/qabstractitemmodel.h>
|
25
|
-
#include <QtCore/qglobal.h>
|
26
|
-
#include <QtCore/qhash.h>
|
27
|
-
#include <QtCore/qline.h>
|
28
|
-
#include <QtCore/qmetaobject.h>
|
29
|
-
#include <QtCore/qobject.h>
|
30
|
-
#include <QtCore/qrect.h>
|
31
|
-
#include <QtCore/qregexp.h>
|
32
|
-
#include <QtCore/qstring.h>
|
33
|
-
#include <QtCore/qvariant.h>
|
34
|
-
#include <QtCore/qmutex.h>
|
35
|
-
#include <QtGui/qapplication.h>
|
36
|
-
#include <QtGui/qbitmap.h>
|
37
|
-
#include <QtGui/qcolor.h>
|
38
|
-
#include <QtGui/qcursor.h>
|
39
|
-
#include <QtGui/qfont.h>
|
40
|
-
#include <QtGui/qicon.h>
|
41
|
-
#include <QtGui/qitemselectionmodel.h>
|
42
|
-
#include <QtGui/qpalette.h>
|
43
|
-
#include <QtGui/qpen.h>
|
44
|
-
#include <QtGui/qpixmap.h>
|
45
|
-
#include <QtGui/qpolygon.h>
|
46
|
-
#include <QtGui/qtextformat.h>
|
47
|
-
#include <QtGui/qwidget.h>
|
48
|
-
|
49
|
-
#ifdef QT_QTDBUS
|
50
|
-
#include <QtDBus/qdbusargument.h>
|
51
|
-
#endif
|
52
|
-
|
53
|
-
#undef DEBUG
|
54
|
-
#ifndef __USE_POSIX
|
55
|
-
#define __USE_POSIX
|
56
|
-
#endif
|
57
|
-
#ifndef __USE_XOPEN
|
58
|
-
#define __USE_XOPEN
|
59
|
-
#endif
|
60
|
-
#ifdef _BOOL
|
61
|
-
#define HAS_BOOL
|
62
|
-
#endif
|
63
|
-
|
64
|
-
#include <ruby.h>
|
65
|
-
|
66
|
-
#include <smoke/smoke.h>
|
67
|
-
#include <smoke/qtcore_smoke.h>
|
68
|
-
|
69
|
-
#undef free
|
70
|
-
#undef malloc
|
71
|
-
|
72
|
-
#include "marshall.h"
|
73
|
-
#include "qtruby.h"
|
74
|
-
#include "smokeruby.h"
|
75
|
-
#include "smoke.h"
|
76
|
-
#include "marshall_types.h"
|
77
|
-
// #define DEBUG
|
78
|
-
|
79
|
-
extern "C" {
|
80
|
-
VALUE qt_internal_module = Qnil;
|
81
|
-
VALUE qt_module = Qnil;
|
82
|
-
|
83
|
-
VALUE qlistmodel_class = Qnil;
|
84
|
-
VALUE qmetaobject_class = Qnil;
|
85
|
-
VALUE qtablemodel_class = Qnil;
|
86
|
-
VALUE qt_base_class = Qnil;
|
87
|
-
VALUE qvariant_class = Qnil;
|
88
|
-
|
89
|
-
VALUE moduleindex_class = Qnil;
|
90
|
-
|
91
|
-
bool application_terminated = false;
|
92
|
-
}
|
93
|
-
|
94
|
-
QList<Smoke*> smokeList;
|
95
|
-
QHash<Smoke*, QtRubyModule> qtruby_modules;
|
96
|
-
|
97
|
-
#ifdef DEBUG
|
98
|
-
int do_debug = qtdb_gc;
|
99
|
-
#else
|
100
|
-
int do_debug = qtdb_none;
|
101
|
-
#endif
|
102
|
-
|
103
|
-
typedef QHash<void *, SmokeValue> PointerMap;
|
104
|
-
static QMutex pointer_map_mutex;
|
105
|
-
Q_GLOBAL_STATIC(PointerMap, pointer_map)
|
106
|
-
int object_count = 0;
|
107
|
-
|
108
|
-
// FIXME:
|
109
|
-
// Don't the two following hashs create memory leaks by using pointers to Smoke::(Module)Index ?
|
110
|
-
QHash<QByteArray, Smoke::ModuleIndex *> methcache;
|
111
|
-
QHash<QByteArray, Smoke::ModuleIndex *> classcache;
|
112
|
-
|
113
|
-
QHash<Smoke::ModuleIndex, QByteArray*> IdToClassNameMap;
|
114
|
-
|
115
|
-
#define logger logger_backend
|
116
|
-
|
117
|
-
Smoke::ModuleIndex _current_method;
|
118
|
-
|
119
|
-
smokeruby_object *
|
120
|
-
alloc_smokeruby_object(bool allocated, Smoke * smoke, int classId, void * ptr)
|
121
|
-
{
|
122
|
-
smokeruby_object * o = ALLOC(smokeruby_object);
|
123
|
-
o->classId = classId;
|
124
|
-
o->smoke = smoke;
|
125
|
-
o->ptr = ptr;
|
126
|
-
o->allocated = allocated;
|
127
|
-
return o;
|
128
|
-
}
|
129
|
-
|
130
|
-
void
|
131
|
-
free_smokeruby_object(smokeruby_object * o)
|
132
|
-
{
|
133
|
-
o->ptr = 0;
|
134
|
-
xfree(o);
|
135
|
-
return;
|
136
|
-
}
|
137
|
-
|
138
|
-
smokeruby_object *value_obj_info(VALUE ruby_value) { // ptr on success, null on fail
|
139
|
-
if (TYPE(ruby_value) != T_DATA) {
|
140
|
-
return 0;
|
141
|
-
}
|
142
|
-
|
143
|
-
smokeruby_object * o = 0;
|
144
|
-
Data_Get_Struct(ruby_value, smokeruby_object, o);
|
145
|
-
return o;
|
146
|
-
}
|
147
|
-
|
148
|
-
void *value_to_ptr(VALUE ruby_value) { // ptr on success, null on fail
|
149
|
-
smokeruby_object *o = value_obj_info(ruby_value);
|
150
|
-
return o;
|
151
|
-
}
|
152
|
-
|
153
|
-
VALUE getPointerObject(void *ptr) {
|
154
|
-
return getSmokeValue(ptr).value;
|
155
|
-
}
|
156
|
-
|
157
|
-
SmokeValue getSmokeValue(void *ptr) {
|
158
|
-
pointer_map_mutex.lock();
|
159
|
-
|
160
|
-
if (!pointer_map() || !pointer_map()->contains(ptr)) {
|
161
|
-
if (do_debug & qtdb_gc) {
|
162
|
-
qWarning("getPointerObject %p -> nil", ptr);
|
163
|
-
if (!pointer_map()) {
|
164
|
-
qWarning("getPointerObject pointer_map deleted");
|
165
|
-
}
|
166
|
-
}
|
167
|
-
pointer_map_mutex.unlock();
|
168
|
-
return SmokeValue();
|
169
|
-
} else {
|
170
|
-
if (do_debug & qtdb_gc) {
|
171
|
-
qWarning("getPointerObject %p -> %p", ptr, (void *) pointer_map()->operator[](ptr).value);
|
172
|
-
}
|
173
|
-
pointer_map_mutex.unlock();
|
174
|
-
return pointer_map()->operator[](ptr);
|
175
|
-
}
|
176
|
-
}
|
177
|
-
|
178
|
-
void unmapPointer(void *ptr, Smoke *smoke, Smoke::Index fromClassId, Smoke::Index toClassId, void *lastptr) {
|
179
|
-
pointer_map_mutex.lock();
|
180
|
-
ptr = smoke->cast(ptr, fromClassId, toClassId);
|
181
|
-
|
182
|
-
if (ptr != lastptr) {
|
183
|
-
lastptr = ptr;
|
184
|
-
if (pointer_map() && pointer_map()->contains(ptr)) {
|
185
|
-
VALUE obj_ptr = pointer_map()->operator[](ptr).value;
|
186
|
-
|
187
|
-
if (do_debug & qtdb_gc) {
|
188
|
-
const char *className = smoke->classes[fromClassId].className;
|
189
|
-
qWarning("unmapPointer (%s*)%p -> %p size: %d", className, ptr, (void*)(&obj_ptr), pointer_map()->size() - 1);
|
190
|
-
}
|
191
|
-
|
192
|
-
pointer_map()->remove(ptr);
|
193
|
-
}
|
194
|
-
}
|
195
|
-
|
196
|
-
if (smoke->classes[toClassId].external) {
|
197
|
-
// encountered external class
|
198
|
-
Smoke::ModuleIndex mi = Smoke::findClass(smoke->classes[toClassId].className);
|
199
|
-
if (!mi.index || !mi.smoke) return;
|
200
|
-
|
201
|
-
smoke = mi.smoke;
|
202
|
-
toClassId = mi.index;
|
203
|
-
}
|
204
|
-
|
205
|
-
pointer_map_mutex.unlock();
|
206
|
-
for (Smoke::Index *i = smoke->inheritanceList + smoke->classes[toClassId].parents; *i; i++) {
|
207
|
-
unmapPointer(ptr, smoke, toClassId, *i, lastptr);
|
208
|
-
}
|
209
|
-
|
210
|
-
}
|
211
|
-
|
212
|
-
void unmapPointer(smokeruby_object *o, Smoke::Index classId, void *lastptr) {
|
213
|
-
unmapPointer(o->ptr, o->smoke, o->classId, classId, lastptr);
|
214
|
-
}
|
215
|
-
|
216
|
-
// Store pointer in pointer_map hash : "pointer_to_Qt_object" => weak ref to associated Ruby object
|
217
|
-
// Recurse to store it also as casted to its parent classes.
|
218
|
-
|
219
|
-
void mapPointer(VALUE obj, smokeruby_object* o, void *ptr, Smoke *smoke, Smoke::Index fromClassId, Smoke::Index toClassId, void *lastptr) {
|
220
|
-
pointer_map_mutex.unlock();
|
221
|
-
|
222
|
-
ptr = smoke->cast(ptr, fromClassId, toClassId);
|
223
|
-
|
224
|
-
if (ptr != lastptr) {
|
225
|
-
lastptr = ptr;
|
226
|
-
|
227
|
-
if (do_debug & qtdb_gc) {
|
228
|
-
const char *className = smoke->classes[fromClassId].className;
|
229
|
-
qWarning("mapPointer (%s*)%p -> %p size: %d", className, ptr, (void*)obj, pointer_map()->size() + 1);
|
230
|
-
}
|
231
|
-
|
232
|
-
SmokeValue value(obj, o);
|
233
|
-
pointer_map()->insert(ptr, value);
|
234
|
-
}
|
235
|
-
|
236
|
-
if (smoke->classes[toClassId].external) {
|
237
|
-
// encountered external class
|
238
|
-
Smoke::ModuleIndex mi = Smoke::findClass(smoke->classes[toClassId].className);
|
239
|
-
if (!mi.index || !mi.smoke) return;
|
240
|
-
|
241
|
-
smoke = mi.smoke;
|
242
|
-
toClassId = mi.index;
|
243
|
-
}
|
244
|
-
|
245
|
-
pointer_map_mutex.unlock();
|
246
|
-
for (Smoke::Index *i = smoke->inheritanceList + smoke->classes[toClassId].parents; *i; i++) {
|
247
|
-
mapPointer(obj, o, ptr, smoke, toClassId, *i, lastptr);
|
248
|
-
}
|
249
|
-
|
250
|
-
return;
|
251
|
-
}
|
252
|
-
|
253
|
-
void mapPointer(VALUE obj, smokeruby_object *o, Smoke::Index classId, void *lastptr) {
|
254
|
-
mapPointer(obj, o, o->ptr, o->smoke, o->classId, classId, lastptr);
|
255
|
-
}
|
256
|
-
|
257
|
-
namespace QtRuby {
|
258
|
-
|
259
|
-
Binding::Binding() : SmokeBinding(0) {}
|
260
|
-
Binding::Binding(Smoke *s) : SmokeBinding(s) {}
|
261
|
-
|
262
|
-
void
|
263
|
-
Binding::deleted(Smoke::Index classId, void *ptr) {
|
264
|
-
if (!pointer_map()) {
|
265
|
-
return;
|
266
|
-
}
|
267
|
-
|
268
|
-
smokeruby_object *o = getSmokeValue(ptr).o;
|
269
|
-
if (do_debug & qtdb_gc) {
|
270
|
-
qWarning("unmapping: o = %p, ptr = %p\n", o, ptr);
|
271
|
-
qWarning("%p->~%s()", ptr, smoke->className(classId));
|
272
|
-
}
|
273
|
-
if (!o || !o->ptr) {
|
274
|
-
return;
|
275
|
-
}
|
276
|
-
unmapPointer(o, o->classId, 0);
|
277
|
-
o->ptr = 0;
|
278
|
-
}
|
279
|
-
|
280
|
-
bool
|
281
|
-
Binding::callMethod(Smoke::Index method, void *ptr, Smoke::Stack args, bool /*isAbstract*/) {
|
282
|
-
VALUE obj = getPointerObject(ptr);
|
283
|
-
smokeruby_object *o = value_obj_info(obj);
|
284
|
-
|
285
|
-
if (do_debug & qtdb_virtual) {
|
286
|
-
const Smoke::Method & meth = smoke->methods[method];
|
287
|
-
QByteArray signature(smoke->methodNames[meth.name]);
|
288
|
-
signature += "(";
|
289
|
-
for (int i = 0; i < meth.numArgs; i++) {
|
290
|
-
if (i != 0) signature += ", ";
|
291
|
-
signature += smoke->types[smoke->argumentList[meth.args + i]].name;
|
292
|
-
}
|
293
|
-
signature += ")";
|
294
|
-
if (meth.flags & Smoke::mf_const) {
|
295
|
-
signature += " const";
|
296
|
-
}
|
297
|
-
qWarning( "module: %s virtual %p->%s::%s called",
|
298
|
-
smoke->moduleName(),
|
299
|
-
ptr,
|
300
|
-
smoke->classes[smoke->methods[method].classId].className,
|
301
|
-
(const char *) signature );
|
302
|
-
}
|
303
|
-
|
304
|
-
if (o == 0) {
|
305
|
-
if( do_debug & qtdb_virtual ) // if not in global destruction
|
306
|
-
qWarning("Cannot find object for virtual method %p -> %p", ptr, &obj);
|
307
|
-
return false;
|
308
|
-
}
|
309
|
-
const char *methodName = smoke->methodNames[smoke->methods[method].name];
|
310
|
-
if (qstrncmp(methodName, "operator", sizeof("operator") - 1) == 0) {
|
311
|
-
methodName += (sizeof("operator") - 1);
|
312
|
-
}
|
313
|
-
|
314
|
-
// If not in a ruby thread, just call the C++ version
|
315
|
-
// During GC, avoid checking for override and just call the C++ version
|
316
|
-
// If the virtual method hasn't been overriden, just call the C++ one.
|
317
|
-
#ifdef HAVE_RUBY_RUBY_H
|
318
|
-
int ruby_thread = ruby_native_thread_p();
|
319
|
-
if ((ruby_thread == 0) || rb_during_gc() || rb_respond_to(obj, rb_intern(methodName)) == 0) {
|
320
|
-
return false;
|
321
|
-
}
|
322
|
-
#else
|
323
|
-
if (rb_during_gc() || ruby_stack_check() || rb_respond_to(obj, rb_intern(methodName)) == 0) {
|
324
|
-
return false;
|
325
|
-
}
|
326
|
-
#endif
|
327
|
-
|
328
|
-
QtRuby::VirtualMethodCall c(smoke, method, args, obj, ALLOCA_N(VALUE, smoke->methods[method].numArgs));
|
329
|
-
c.next();
|
330
|
-
return true;
|
331
|
-
}
|
332
|
-
|
333
|
-
char*
|
334
|
-
Binding::className(Smoke::Index classId) {
|
335
|
-
Smoke::ModuleIndex mi(smoke, classId);
|
336
|
-
return (char *) (const char *) *(IdToClassNameMap.value(mi));
|
337
|
-
}
|
338
|
-
|
339
|
-
/*
|
340
|
-
Converts a C++ value returned by a signal invocation to a Ruby
|
341
|
-
reply type
|
342
|
-
*/
|
343
|
-
class SignalReturnValue : public Marshall {
|
344
|
-
QList<MocArgument*> _replyType;
|
345
|
-
Smoke::Stack _stack;
|
346
|
-
VALUE * _result;
|
347
|
-
public:
|
348
|
-
SignalReturnValue(void ** o, VALUE * result, QList<MocArgument*> replyType)
|
349
|
-
{
|
350
|
-
_result = result;
|
351
|
-
_replyType = replyType;
|
352
|
-
_stack = new Smoke::StackItem[1];
|
353
|
-
smokeStackFromQtStack(_stack, o, 0, 1, _replyType);
|
354
|
-
Marshall::HandlerFn fn = getMarshallFn(type());
|
355
|
-
(*fn)(this);
|
356
|
-
}
|
357
|
-
|
358
|
-
SmokeType type() {
|
359
|
-
return _replyType[0]->st;
|
360
|
-
}
|
361
|
-
Marshall::Action action() { return Marshall::ToVALUE; }
|
362
|
-
Smoke::StackItem &item() { return _stack[0]; }
|
363
|
-
VALUE * var() {
|
364
|
-
return _result;
|
365
|
-
}
|
366
|
-
|
367
|
-
void unsupported()
|
368
|
-
{
|
369
|
-
rb_raise(rb_eArgError, "Cannot handle '%s' as signal reply-type", type().name());
|
370
|
-
}
|
371
|
-
Smoke *smoke() { return type().smoke(); }
|
372
|
-
|
373
|
-
void next() {}
|
374
|
-
|
375
|
-
bool cleanup() { return false; }
|
376
|
-
|
377
|
-
~SignalReturnValue() {
|
378
|
-
delete[] _stack;
|
379
|
-
}
|
380
|
-
};
|
381
|
-
|
382
|
-
/* Note that the SignalReturnValue and EmitSignal classes really belong in
|
383
|
-
marshall_types.cpp. However, for unknown reasons they don't link with certain
|
384
|
-
versions of gcc. So they were moved here in to work round that bug.
|
385
|
-
*/
|
386
|
-
EmitSignal::EmitSignal(QObject *obj, int id, int /*items*/, QList<MocArgument*> args, VALUE *sp, VALUE * result) : SigSlotBase(args),
|
387
|
-
_obj(obj), _id(id)
|
388
|
-
{
|
389
|
-
_sp = sp;
|
390
|
-
_result = result;
|
391
|
-
}
|
392
|
-
|
393
|
-
Marshall::Action
|
394
|
-
EmitSignal::action()
|
395
|
-
{
|
396
|
-
return Marshall::FromVALUE;
|
397
|
-
}
|
398
|
-
|
399
|
-
Smoke::StackItem &
|
400
|
-
EmitSignal::item()
|
401
|
-
{
|
402
|
-
return _stack[_cur];
|
403
|
-
}
|
404
|
-
|
405
|
-
const char *
|
406
|
-
EmitSignal::mytype()
|
407
|
-
{
|
408
|
-
return "signal";
|
409
|
-
}
|
410
|
-
|
411
|
-
void
|
412
|
-
EmitSignal::emitSignal()
|
413
|
-
{
|
414
|
-
if (_called) return;
|
415
|
-
_called = true;
|
416
|
-
void ** o = new void*[_items];
|
417
|
-
smokeStackToQtStack(_stack, o + 1, 1, _items, _args);
|
418
|
-
void * ptr;
|
419
|
-
o[0] = &ptr;
|
420
|
-
prepareReturnValue(o);
|
421
|
-
|
422
|
-
_obj->metaObject()->activate(_obj, _id, o);
|
423
|
-
|
424
|
-
if (_args[0]->argType != xmoc_void) {
|
425
|
-
SignalReturnValue r(o, _result, _args);
|
426
|
-
}
|
427
|
-
delete[] o;
|
428
|
-
}
|
429
|
-
|
430
|
-
void
|
431
|
-
EmitSignal::mainfunction()
|
432
|
-
{
|
433
|
-
emitSignal();
|
434
|
-
}
|
435
|
-
|
436
|
-
bool
|
437
|
-
EmitSignal::cleanup()
|
438
|
-
{
|
439
|
-
return true;
|
440
|
-
}
|
441
|
-
|
442
|
-
InvokeNativeSlot::InvokeNativeSlot(QObject *obj, int id, int /*items*/, QList<MocArgument*> args, VALUE *sp, VALUE * result) : SigSlotBase(args),
|
443
|
-
_obj(obj), _id(id)
|
444
|
-
{
|
445
|
-
_sp = sp;
|
446
|
-
_result = result;
|
447
|
-
}
|
448
|
-
|
449
|
-
Marshall::Action
|
450
|
-
InvokeNativeSlot::action()
|
451
|
-
{
|
452
|
-
return Marshall::FromVALUE;
|
453
|
-
}
|
454
|
-
|
455
|
-
Smoke::StackItem &
|
456
|
-
InvokeNativeSlot::item()
|
457
|
-
{
|
458
|
-
return _stack[_cur];
|
459
|
-
}
|
460
|
-
|
461
|
-
const char *
|
462
|
-
InvokeNativeSlot::mytype()
|
463
|
-
{
|
464
|
-
return "slot";
|
465
|
-
}
|
466
|
-
|
467
|
-
void
|
468
|
-
InvokeNativeSlot::invokeSlot()
|
469
|
-
{
|
470
|
-
if (_called) return;
|
471
|
-
_called = true;
|
472
|
-
void ** o = new void*[_items];
|
473
|
-
smokeStackToQtStack(_stack, o + 1, 1, _items, _args);
|
474
|
-
void * ptr;
|
475
|
-
o[0] = &ptr;
|
476
|
-
prepareReturnValue(o);
|
477
|
-
|
478
|
-
_obj->qt_metacall(QMetaObject::InvokeMetaMethod, _id, o);
|
479
|
-
|
480
|
-
if (_args[0]->argType != xmoc_void) {
|
481
|
-
SignalReturnValue r(o, _result, _args);
|
482
|
-
}
|
483
|
-
delete[] o;
|
484
|
-
}
|
485
|
-
|
486
|
-
void
|
487
|
-
InvokeNativeSlot::mainfunction()
|
488
|
-
{
|
489
|
-
invokeSlot();
|
490
|
-
}
|
491
|
-
|
492
|
-
bool
|
493
|
-
InvokeNativeSlot::cleanup()
|
494
|
-
{
|
495
|
-
return true;
|
496
|
-
}
|
497
|
-
|
498
|
-
}
|
499
|
-
|
500
|
-
VALUE rb_str_catf(VALUE self, const char *format, ...)
|
501
|
-
{
|
502
|
-
#define CAT_BUFFER_SIZE 2048
|
503
|
-
static char p[CAT_BUFFER_SIZE];
|
504
|
-
va_list ap;
|
505
|
-
va_start(ap, format);
|
506
|
-
qvsnprintf(p, CAT_BUFFER_SIZE, format, ap);
|
507
|
-
p[CAT_BUFFER_SIZE - 1] = '\0';
|
508
|
-
rb_str_cat2(self, p);
|
509
|
-
va_end(ap);
|
510
|
-
return self;
|
511
|
-
}
|
512
|
-
|
513
|
-
const char *
|
514
|
-
resolve_classname(smokeruby_object * o)
|
515
|
-
{
|
516
|
-
if (Smoke::isDerivedFrom(o->smoke->classes[o->classId].className, "QObject")) {
|
517
|
-
QObject * qobject = (QObject *) o->smoke->cast(o->ptr, o->classId, o->smoke->idClass("QObject").index);
|
518
|
-
const QMetaObject * meta = qobject->metaObject();
|
519
|
-
|
520
|
-
while (meta != 0) {
|
521
|
-
Smoke::ModuleIndex mi = o->smoke->findClass(meta->className());
|
522
|
-
o->smoke = mi.smoke;
|
523
|
-
o->classId = mi.index;
|
524
|
-
if (o->smoke != 0) {
|
525
|
-
if (o->classId != 0) {
|
526
|
-
return qtruby_modules[o->smoke].binding->className(o->classId);
|
527
|
-
}
|
528
|
-
}
|
529
|
-
|
530
|
-
meta = meta->superClass();
|
531
|
-
}
|
532
|
-
}
|
533
|
-
|
534
|
-
if (o->smoke->classes[o->classId].external) {
|
535
|
-
Smoke::ModuleIndex mi = o->smoke->findClass(o->smoke->className(o->classId));
|
536
|
-
o->smoke = mi.smoke;
|
537
|
-
o->classId = mi.index;
|
538
|
-
return qtruby_modules.value(mi.smoke).resolve_classname(o);
|
539
|
-
}
|
540
|
-
return qtruby_modules.value(o->smoke).resolve_classname(o);
|
541
|
-
}
|
542
|
-
|
543
|
-
VALUE
|
544
|
-
findMethod(VALUE /*self*/, VALUE c_value, VALUE name_value)
|
545
|
-
{
|
546
|
-
char *c = StringValuePtr(c_value);
|
547
|
-
char *name = StringValuePtr(name_value);
|
548
|
-
VALUE result = rb_ary_new();
|
549
|
-
Smoke::ModuleIndex classId = Smoke::findClass(c);
|
550
|
-
Smoke::ModuleIndex meth = Smoke::NullModuleIndex;
|
551
|
-
QList<Smoke::ModuleIndex> milist;
|
552
|
-
if (classId.smoke != 0) {
|
553
|
-
meth = classId.smoke->findMethod(c, name);
|
554
|
-
}
|
555
|
-
#ifdef DEBUG
|
556
|
-
if (do_debug & qtdb_calls) qWarning("Found method %s::%s => %d", c, name, meth.index);
|
557
|
-
#endif
|
558
|
-
if(!meth.index) {
|
559
|
-
// since every smoke module defines a class 'QGlobalSpace' we can't rely on the classMap,
|
560
|
-
// so we search for methods by hand
|
561
|
-
foreach (Smoke* s, smokeList) {
|
562
|
-
Smoke::ModuleIndex cid = s->idClass("QGlobalSpace");
|
563
|
-
Smoke::ModuleIndex mnid = s->idMethodName(name);
|
564
|
-
if (!cid.index || !mnid.index) continue;
|
565
|
-
meth = s->idMethod(cid.index, mnid.index);
|
566
|
-
if (meth.index) milist.append(meth);
|
567
|
-
}
|
568
|
-
#ifdef DEBUG
|
569
|
-
if (do_debug & qtdb_calls) qWarning("Found method QGlobalSpace::%s => %d", name, meth.index);
|
570
|
-
#endif
|
571
|
-
}
|
572
|
-
else
|
573
|
-
{
|
574
|
-
milist.append(meth);
|
575
|
-
}
|
576
|
-
|
577
|
-
if (milist.count() == 0) {
|
578
|
-
return result;
|
579
|
-
// empty list
|
580
|
-
} else {
|
581
|
-
foreach (Smoke::ModuleIndex meth, milist) {
|
582
|
-
if (meth.index > 0) {
|
583
|
-
Smoke::Index i = meth.smoke->methodMaps[meth.index].method;
|
584
|
-
if (i == 0) { // shouldn't happen
|
585
|
-
rb_raise(rb_eArgError, "Corrupt method %s::%s", c, name);
|
586
|
-
} else if(i > 0) { // single match
|
587
|
-
const Smoke::Method &methodRef = meth.smoke->methods[i];
|
588
|
-
if ((methodRef.flags & Smoke::mf_internal) == 0) {
|
589
|
-
rb_ary_push(result, rb_funcall(moduleindex_class, rb_intern("new"), 2, INT2NUM(smokeList.indexOf(meth.smoke)), INT2NUM(i)));
|
590
|
-
}
|
591
|
-
} else { // multiple match
|
592
|
-
i = -i; // turn into ambiguousMethodList index
|
593
|
-
while (meth.smoke->ambiguousMethodList[i]) {
|
594
|
-
const Smoke::Method &methodRef = meth.smoke->methods[meth.smoke->ambiguousMethodList[i]];
|
595
|
-
if ((methodRef.flags & Smoke::mf_internal) == 0) {
|
596
|
-
rb_ary_push(result, rb_funcall(moduleindex_class, rb_intern("new"), 2, INT2NUM(smokeList.indexOf(meth.smoke)), INT2NUM(meth.smoke->ambiguousMethodList[i])));
|
597
|
-
//#ifdef DEBUG
|
598
|
-
if (do_debug & qtdb_calls) qWarning("Ambiguous Method %s::%s => %d", c, name, meth.smoke->ambiguousMethodList[i]);
|
599
|
-
//#endif
|
600
|
-
|
601
|
-
}
|
602
|
-
i++;
|
603
|
-
}
|
604
|
-
}
|
605
|
-
}
|
606
|
-
}
|
607
|
-
}
|
608
|
-
return result;
|
609
|
-
}
|
610
|
-
|
611
|
-
// findAllMethods(ModuleIndex [, startingWith]) : returns { "mungedName" => [index in methods, ...], ... }
|
612
|
-
|
613
|
-
VALUE
|
614
|
-
findAllMethods(int argc, VALUE * argv, VALUE /*self*/)
|
615
|
-
{
|
616
|
-
VALUE rb_mi = argv[0];
|
617
|
-
VALUE result = rb_hash_new();
|
618
|
-
if (rb_mi != Qnil) {
|
619
|
-
Smoke::Index c = (Smoke::Index) NUM2INT(rb_funcall(rb_mi, rb_intern("index"), 0));
|
620
|
-
Smoke *smoke = smokeList[NUM2INT(rb_funcall(rb_mi, rb_intern("smoke"), 0))];
|
621
|
-
if (c > smoke->numClasses) {
|
622
|
-
return Qnil;
|
623
|
-
}
|
624
|
-
char * pat = 0L;
|
625
|
-
if(argc > 1 && TYPE(argv[1]) == T_STRING)
|
626
|
-
pat = StringValuePtr(argv[1]);
|
627
|
-
#ifdef DEBUG
|
628
|
-
if (do_debug & qtdb_calls) qWarning("findAllMethods called with classid = %d, pat == %s", c, pat);
|
629
|
-
#endif
|
630
|
-
Smoke::Index imax = smoke->numMethodMaps;
|
631
|
-
Smoke::Index imin = 0, icur = -1, methmin, methmax;
|
632
|
-
methmin = -1; methmax = -1; // kill warnings
|
633
|
-
int icmp = -1;
|
634
|
-
while(imax >= imin) {
|
635
|
-
icur = (imin + imax) / 2;
|
636
|
-
icmp = smoke->leg(smoke->methodMaps[icur].classId, c);
|
637
|
-
if (icmp == 0) {
|
638
|
-
Smoke::Index pos = icur;
|
639
|
-
while (icur && smoke->methodMaps[icur-1].classId == c)
|
640
|
-
icur --;
|
641
|
-
methmin = icur;
|
642
|
-
icur = pos;
|
643
|
-
while(icur < imax && smoke->methodMaps[icur+1].classId == c)
|
644
|
-
icur ++;
|
645
|
-
methmax = icur;
|
646
|
-
break;
|
647
|
-
}
|
648
|
-
if (icmp > 0)
|
649
|
-
imax = icur - 1;
|
650
|
-
else
|
651
|
-
imin = icur + 1;
|
652
|
-
}
|
653
|
-
if (icmp == 0) {
|
654
|
-
for (Smoke::Index i = methmin; i <= methmax; i++) {
|
655
|
-
Smoke::Index m = smoke->methodMaps[i].name;
|
656
|
-
if (pat == 0L || strncmp(smoke->methodNames[m], pat, strlen(pat)) == 0) {
|
657
|
-
Smoke::Index ix = smoke->methodMaps[i].method;
|
658
|
-
VALUE meths = rb_ary_new();
|
659
|
-
if (ix >= 0) { // single match
|
660
|
-
const Smoke::Method &methodRef = smoke->methods[ix];
|
661
|
-
if ((methodRef.flags & Smoke::mf_internal) == 0) {
|
662
|
-
rb_ary_push(meths, rb_funcall(moduleindex_class, rb_intern("new"), 2, INT2NUM(smokeList.indexOf(smoke)), INT2NUM((int) ix)));
|
663
|
-
}
|
664
|
-
} else { // multiple match
|
665
|
-
ix = -ix; // turn into ambiguousMethodList index
|
666
|
-
while (smoke->ambiguousMethodList[ix]) {
|
667
|
-
const Smoke::Method &methodRef = smoke->methods[smoke->ambiguousMethodList[ix]];
|
668
|
-
if ((methodRef.flags & Smoke::mf_internal) == 0) {
|
669
|
-
rb_ary_push(meths, rb_funcall(moduleindex_class, rb_intern("new"), 2, INT2NUM(smokeList.indexOf(smoke)), INT2NUM((int)smoke->ambiguousMethodList[ix])));
|
670
|
-
}
|
671
|
-
ix++;
|
672
|
-
}
|
673
|
-
}
|
674
|
-
rb_hash_aset(result, rb_str_new2(smoke->methodNames[m]), meths);
|
675
|
-
}
|
676
|
-
}
|
677
|
-
}
|
678
|
-
}
|
679
|
-
return result;
|
680
|
-
}
|
681
|
-
|
682
|
-
/*
|
683
|
-
Flags values
|
684
|
-
0 All methods, except enum values and protected non-static methods
|
685
|
-
mf_static Static methods only
|
686
|
-
mf_enum Enums only
|
687
|
-
mf_protected Protected non-static methods only
|
688
|
-
*/
|
689
|
-
|
690
|
-
#define PUSH_QTRUBY_METHOD \
|
691
|
-
if ( (methodRef.flags & (Smoke::mf_internal|Smoke::mf_ctor|Smoke::mf_dtor)) == 0 \
|
692
|
-
&& strcmp(s->methodNames[methodRef.name], "operator=") != 0 \
|
693
|
-
&& strcmp(s->methodNames[methodRef.name], "operator!=") != 0 \
|
694
|
-
&& strcmp(s->methodNames[methodRef.name], "operator--") != 0 \
|
695
|
-
&& strcmp(s->methodNames[methodRef.name], "operator++") != 0 \
|
696
|
-
&& strncmp(s->methodNames[methodRef.name], "operator ", strlen("operator ")) != 0 \
|
697
|
-
&& ( (flags == 0 && (methodRef.flags & (Smoke::mf_static|Smoke::mf_enum|Smoke::mf_protected)) == 0) \
|
698
|
-
|| ( flags == Smoke::mf_static \
|
699
|
-
&& (methodRef.flags & Smoke::mf_enum) == 0 \
|
700
|
-
&& (methodRef.flags & Smoke::mf_static) == Smoke::mf_static ) \
|
701
|
-
|| (flags == Smoke::mf_enum && (methodRef.flags & Smoke::mf_enum) == Smoke::mf_enum) \
|
702
|
-
|| ( flags == Smoke::mf_protected \
|
703
|
-
&& (methodRef.flags & Smoke::mf_static) == 0 \
|
704
|
-
&& (methodRef.flags & Smoke::mf_protected) == Smoke::mf_protected ) ) ) { \
|
705
|
-
if (strncmp(s->methodNames[methodRef.name], "operator", strlen("operator")) == 0) { \
|
706
|
-
if (op_re.indexIn(s->methodNames[methodRef.name]) != -1) { \
|
707
|
-
rb_ary_push(result, rb_str_new2((op_re.cap(1) + op_re.cap(2)).toLatin1())); \
|
708
|
-
} else { \
|
709
|
-
rb_ary_push(result, rb_str_new2(s->methodNames[methodRef.name] + strlen("operator"))); \
|
710
|
-
} \
|
711
|
-
} else if (predicate_re.indexIn(s->methodNames[methodRef.name]) != -1 && methodRef.numArgs == 0) { \
|
712
|
-
rb_ary_push(result, rb_str_new2((predicate_re.cap(2).toLower() + predicate_re.cap(3) + "?").toLatin1())); \
|
713
|
-
} else if (set_re.indexIn(s->methodNames[methodRef.name]) != -1 && methodRef.numArgs == 1) { \
|
714
|
-
rb_ary_push(result, rb_str_new2((set_re.cap(2).toLower() + set_re.cap(3) + "=").toLatin1())); \
|
715
|
-
} else { \
|
716
|
-
rb_ary_push(result, rb_str_new2(s->methodNames[methodRef.name])); \
|
717
|
-
} \
|
718
|
-
}
|
719
|
-
|
720
|
-
VALUE
|
721
|
-
findAllMethodNames(VALUE /*self*/, VALUE result, VALUE classid, VALUE flags_value)
|
722
|
-
{
|
723
|
-
QRegExp predicate_re("^(is|has)(.)(.*)");
|
724
|
-
QRegExp set_re("^(set)([A-Z])(.*)");
|
725
|
-
QRegExp op_re("operator(.*)(([-%~/+|&*])|(>>)|(<<)|(&&)|(\\|\\|)|(\\*\\*))=$");
|
726
|
-
|
727
|
-
unsigned short flags = (unsigned short) NUM2UINT(flags_value);
|
728
|
-
if (classid != Qnil) {
|
729
|
-
Smoke::Index c = (Smoke::Index) NUM2INT(rb_funcall(classid, rb_intern("index"), 0));
|
730
|
-
Smoke* s = smokeList[NUM2INT(rb_funcall(classid, rb_intern("smoke"), 0))];
|
731
|
-
if (c > s->numClasses) {
|
732
|
-
return Qnil;
|
733
|
-
}
|
734
|
-
#ifdef DEBUG
|
735
|
-
if (do_debug & qtdb_calls) qWarning("findAllMethodNames called with classid = %d in module %s", c, s->moduleName());
|
736
|
-
#endif
|
737
|
-
Smoke::Index imax = s->numMethodMaps;
|
738
|
-
Smoke::Index imin = 0, icur = -1, methmin, methmax;
|
739
|
-
methmin = -1; methmax = -1; // kill warnings
|
740
|
-
int icmp = -1;
|
741
|
-
|
742
|
-
while (imax >= imin) {
|
743
|
-
icur = (imin + imax) / 2;
|
744
|
-
icmp = s->leg(s->methodMaps[icur].classId, c);
|
745
|
-
if (icmp == 0) {
|
746
|
-
Smoke::Index pos = icur;
|
747
|
-
while(icur && s->methodMaps[icur-1].classId == c)
|
748
|
-
icur --;
|
749
|
-
methmin = icur;
|
750
|
-
icur = pos;
|
751
|
-
while(icur < imax && s->methodMaps[icur+1].classId == c)
|
752
|
-
icur ++;
|
753
|
-
methmax = icur;
|
754
|
-
break;
|
755
|
-
}
|
756
|
-
if (icmp > 0)
|
757
|
-
imax = icur - 1;
|
758
|
-
else
|
759
|
-
imin = icur + 1;
|
760
|
-
}
|
761
|
-
|
762
|
-
if (icmp == 0) {
|
763
|
-
for (Smoke::Index i=methmin ; i <= methmax ; i++) {
|
764
|
-
Smoke::Index ix= s->methodMaps[i].method;
|
765
|
-
if (ix > 0) { // single match
|
766
|
-
const Smoke::Method &methodRef = s->methods[ix];
|
767
|
-
PUSH_QTRUBY_METHOD
|
768
|
-
} else { // multiple match
|
769
|
-
ix = -ix; // turn into ambiguousMethodList index
|
770
|
-
while (s->ambiguousMethodList[ix]) {
|
771
|
-
const Smoke::Method &methodRef = s->methods[s->ambiguousMethodList[ix]];
|
772
|
-
PUSH_QTRUBY_METHOD
|
773
|
-
ix++;
|
774
|
-
}
|
775
|
-
}
|
776
|
-
}
|
777
|
-
}
|
778
|
-
}
|
779
|
-
return result;
|
780
|
-
}
|
781
|
-
|
782
|
-
QByteArray *
|
783
|
-
find_cached_selector(int argc, VALUE * argv, VALUE klass, const char * methodName)
|
784
|
-
{
|
785
|
-
// Look in the cache
|
786
|
-
static QByteArray * mcid = 0;
|
787
|
-
if (mcid == 0) {
|
788
|
-
mcid = new QByteArray();
|
789
|
-
}
|
790
|
-
|
791
|
-
*mcid = rb_class2name(klass);
|
792
|
-
*mcid += ';';
|
793
|
-
*mcid += methodName;
|
794
|
-
for(int i=4; i<argc ; i++)
|
795
|
-
{
|
796
|
-
*mcid += ';';
|
797
|
-
*mcid += value_to_type_flag(argv[i]);
|
798
|
-
}
|
799
|
-
Smoke::ModuleIndex *rcid = methcache.value(*mcid);
|
800
|
-
#ifdef DEBUG
|
801
|
-
if (do_debug & qtdb_calls) qWarning("method_missing mcid: %s", (const char *) *mcid);
|
802
|
-
#endif
|
803
|
-
|
804
|
-
if (rcid) {
|
805
|
-
// Got a hit
|
806
|
-
#ifdef DEBUG
|
807
|
-
if (do_debug & qtdb_calls) qWarning("method_missing cache hit, mcid: %s", (const char *) *mcid);
|
808
|
-
#endif
|
809
|
-
_current_method.smoke = rcid->smoke;
|
810
|
-
_current_method.index = rcid->index;
|
811
|
-
} else {
|
812
|
-
_current_method.smoke = 0;
|
813
|
-
_current_method.index = -1;
|
814
|
-
}
|
815
|
-
|
816
|
-
return mcid;
|
817
|
-
}
|
818
|
-
|
819
|
-
VALUE
|
820
|
-
method_missing(int argc, VALUE * argv, VALUE self)
|
821
|
-
{
|
822
|
-
const char * methodName = rb_id2name(SYM2ID(argv[0]));
|
823
|
-
VALUE klass = rb_funcall(self, rb_intern("class"), 0);
|
824
|
-
|
825
|
-
VALUE retval = Qnil;
|
826
|
-
|
827
|
-
// Look for 'thing?' methods, and try to match isThing() or hasThing() in the Smoke runtime
|
828
|
-
static QByteArray * pred = 0;
|
829
|
-
|
830
|
-
|
831
|
-
|
832
|
-
|
833
|
-
|
834
|
-
|
835
|
-
|
836
|
-
|
837
|
-
|
838
|
-
|
839
|
-
|
840
|
-
|
841
|
-
|
842
|
-
|
843
|
-
|
844
|
-
|
845
|
-
|
846
|
-
|
847
|
-
|
848
|
-
|
849
|
-
|
850
|
-
|
851
|
-
|
852
|
-
|
853
|
-
|
854
|
-
|
855
|
-
|
856
|
-
|
857
|
-
|
858
|
-
|
859
|
-
|
860
|
-
|
861
|
-
|
862
|
-
|
863
|
-
|
864
|
-
|
865
|
-
|
866
|
-
|
867
|
-
|
868
|
-
|
869
|
-
|
870
|
-
|
871
|
-
|
872
|
-
|
873
|
-
|
874
|
-
|
875
|
-
|
876
|
-
|
877
|
-
|
878
|
-
|
879
|
-
|
880
|
-
|
881
|
-
|
882
|
-
|
883
|
-
|
884
|
-
|
885
|
-
|
886
|
-
|
887
|
-
|
888
|
-
|
889
|
-
|
890
|
-
|
891
|
-
|
892
|
-
|
893
|
-
|
894
|
-
|
895
|
-
|
896
|
-
|
897
|
-
|
898
|
-
|
899
|
-
|
900
|
-
|
901
|
-
|
902
|
-
|
903
|
-
|
904
|
-
|
905
|
-
|
906
|
-
|
907
|
-
|
908
|
-
|
909
|
-
|
910
|
-
|
911
|
-
|
912
|
-
|
913
|
-
|
914
|
-
|
915
|
-
|
916
|
-
if (
|
917
|
-
|
918
|
-
|
919
|
-
|
920
|
-
|
921
|
-
|
922
|
-
|
923
|
-
|
924
|
-
if (meta->indexOfProperty(*name) != -1) {
|
925
|
-
VALUE qvariant = rb_funcall(self, rb_intern("
|
926
|
-
return rb_funcall(
|
927
|
-
}
|
928
|
-
}
|
929
|
-
|
930
|
-
|
931
|
-
|
932
|
-
|
933
|
-
|
934
|
-
|
935
|
-
|
936
|
-
|
937
|
-
|
938
|
-
|
939
|
-
|
940
|
-
|
941
|
-
|
942
|
-
|
943
|
-
|
944
|
-
|
945
|
-
|
946
|
-
|
947
|
-
|
948
|
-
|
949
|
-
|
950
|
-
|
951
|
-
|
952
|
-
|
953
|
-
|
954
|
-
|
955
|
-
|
956
|
-
|
957
|
-
|
958
|
-
|
959
|
-
|
960
|
-
|
961
|
-
|
962
|
-
|
963
|
-
|
964
|
-
|
965
|
-
|
966
|
-
|
967
|
-
|
968
|
-
|
969
|
-
|
970
|
-
|
971
|
-
|
972
|
-
|
973
|
-
|
974
|
-
|
975
|
-
|
976
|
-
|
977
|
-
|
978
|
-
|
979
|
-
|
980
|
-
|
981
|
-
|
982
|
-
|
983
|
-
|
984
|
-
|
985
|
-
|
986
|
-
|
987
|
-
|
988
|
-
|
989
|
-
|
990
|
-
|
991
|
-
|
992
|
-
|
993
|
-
|
994
|
-
|
995
|
-
|
996
|
-
|
997
|
-
|
998
|
-
|
999
|
-
|
1000
|
-
|
1001
|
-
|
1002
|
-
|
1003
|
-
|
1004
|
-
|
1005
|
-
|
1006
|
-
|
1007
|
-
|
1008
|
-
|
1009
|
-
|
1010
|
-
|
1011
|
-
|
1012
|
-
|
1013
|
-
|
1014
|
-
|
1015
|
-
|
1016
|
-
|
1017
|
-
|
1018
|
-
|
1019
|
-
|
1020
|
-
|
1021
|
-
|
1022
|
-
|
1023
|
-
|
1024
|
-
|
1025
|
-
|
1026
|
-
|
1027
|
-
|
1028
|
-
|
1029
|
-
|
1030
|
-
|
1031
|
-
{
|
1032
|
-
|
1033
|
-
|
1034
|
-
|
1035
|
-
|
1036
|
-
|
1037
|
-
|
1038
|
-
|
1039
|
-
|
1040
|
-
|
1041
|
-
|
1042
|
-
|
1043
|
-
|
1044
|
-
|
1045
|
-
|
1046
|
-
|
1047
|
-
|
1048
|
-
|
1049
|
-
|
1050
|
-
|
1051
|
-
|
1052
|
-
|
1053
|
-
|
1054
|
-
|
1055
|
-
|
1056
|
-
|
1057
|
-
|
1058
|
-
|
1059
|
-
|
1060
|
-
|
1061
|
-
|
1062
|
-
|
1063
|
-
|
1064
|
-
|
1065
|
-
|
1066
|
-
|
1067
|
-
|
1068
|
-
|
1069
|
-
|
1070
|
-
|
1071
|
-
|
1072
|
-
|
1073
|
-
|
1074
|
-
|
1075
|
-
|
1076
|
-
|
1077
|
-
|
1078
|
-
|
1079
|
-
|
1080
|
-
|
1081
|
-
|
1082
|
-
|
1083
|
-
|
1084
|
-
|
1085
|
-
|
1086
|
-
|
1087
|
-
|
1088
|
-
|
1089
|
-
|
1090
|
-
|
1091
|
-
|
1092
|
-
|
1093
|
-
|
1094
|
-
|
1095
|
-
|
1096
|
-
|
1097
|
-
|
1098
|
-
|
1099
|
-
|
1100
|
-
|
1101
|
-
|
1102
|
-
|
1103
|
-
|
1104
|
-
|
1105
|
-
|
1106
|
-
|
1107
|
-
|
1108
|
-
|
1109
|
-
|
1110
|
-
|
1111
|
-
|
1112
|
-
|
1113
|
-
|
1114
|
-
|
1115
|
-
|
1116
|
-
|
1117
|
-
smoke = qtcore_Smoke;
|
1118
|
-
typeId = smoke->idType(name.constData());
|
1119
|
-
}
|
1120
|
-
|
1121
|
-
|
1122
|
-
|
1123
|
-
|
1124
|
-
|
1125
|
-
|
1126
|
-
|
1127
|
-
|
1128
|
-
|
1129
|
-
|
1130
|
-
|
1131
|
-
|
1132
|
-
|
1133
|
-
|
1134
|
-
|
1135
|
-
|
1136
|
-
|
1137
|
-
|
1138
|
-
|
1139
|
-
|
1140
|
-
|
1141
|
-
|
1142
|
-
|
1143
|
-
|
1144
|
-
|
1145
|
-
|
1146
|
-
|
1147
|
-
|
1148
|
-
|
1149
|
-
|
1150
|
-
|
1151
|
-
|
1152
|
-
|
1153
|
-
|
1154
|
-
|
1155
|
-
|
1156
|
-
|
1157
|
-
|
1158
|
-
|
1159
|
-
|
1160
|
-
|
1161
|
-
|
1162
|
-
|
1163
|
-
|
1164
|
-
|
1165
|
-
|
1166
|
-
|
1167
|
-
|
1168
|
-
|
1169
|
-
|
1170
|
-
|
1171
|
-
|
1172
|
-
|
1173
|
-
|
1174
|
-
|
1175
|
-
|
1176
|
-
|
1177
|
-
|
1178
|
-
|
1179
|
-
|
1180
|
-
|
1181
|
-
|
1182
|
-
|
1183
|
-
|
1184
|
-
|
1185
|
-
|
1186
|
-
|
1187
|
-
|
1188
|
-
|
1189
|
-
|
1190
|
-
|
1191
|
-
|
1192
|
-
|
1193
|
-
|
1194
|
-
|
1195
|
-
|
1196
|
-
|
1197
|
-
|
1198
|
-
|
1199
|
-
|
1200
|
-
|
1201
|
-
|
1202
|
-
|
1203
|
-
|
1204
|
-
|
1205
|
-
|
1206
|
-
|
1207
|
-
|
1208
|
-
|
1209
|
-
|
1210
|
-
|
1211
|
-
|
1212
|
-
|
1213
|
-
|
1214
|
-
|
1215
|
-
|
1216
|
-
|
1217
|
-
|
1218
|
-
|
1219
|
-
|
1220
|
-
|
1221
|
-
|
1222
|
-
|
1223
|
-
|
1224
|
-
|
1225
|
-
|
1226
|
-
|
1227
|
-
|
1228
|
-
|
1229
|
-
|
1230
|
-
|
1231
|
-
|
1232
|
-
|
1233
|
-
|
1234
|
-
|
1235
|
-
|
1236
|
-
|
1237
|
-
|
1238
|
-
|
1239
|
-
|
1240
|
-
|
1241
|
-
|
1242
|
-
|
1243
|
-
|
1244
|
-
|
1245
|
-
|
1246
|
-
|
1247
|
-
|
1248
|
-
|
1249
|
-
|
1250
|
-
|
1251
|
-
|
1252
|
-
|
1253
|
-
|
1254
|
-
|
1255
|
-
|
1256
|
-
|
1257
|
-
|
1258
|
-
|
1259
|
-
|
1260
|
-
|
1261
|
-
|
1262
|
-
|
1263
|
-
|
1264
|
-
|
1265
|
-
|
1266
|
-
|
1267
|
-
|
1268
|
-
|
1269
|
-
|
1270
|
-
|
1271
|
-
|
1272
|
-
|
1273
|
-
|
1274
|
-
|
1275
|
-
|
1276
|
-
|
1277
|
-
|
1278
|
-
|
1279
|
-
|
1280
|
-
|
1281
|
-
|
1282
|
-
|
1283
|
-
|
1284
|
-
|
1285
|
-
|
1286
|
-
|
1287
|
-
|
1288
|
-
|
1289
|
-
|
1290
|
-
|
1291
|
-
|
1292
|
-
|
1293
|
-
|
1294
|
-
|
1295
|
-
|
1296
|
-
|
1297
|
-
|
1298
|
-
|
1299
|
-
|
1300
|
-
|
1301
|
-
|
1302
|
-
|
1303
|
-
|
1304
|
-
|
1305
|
-
|
1306
|
-
|
1307
|
-
|
1308
|
-
|
1309
|
-
|
1310
|
-
|
1
|
+
/***************************************************************************
|
2
|
+
Qt.cpp - description
|
3
|
+
-------------------
|
4
|
+
begin : Fri Jul 4 2003
|
5
|
+
copyright : (C) 2003-2006 by Richard Dale
|
6
|
+
email : Richard_Dale@tipitina.demon.co.uk
|
7
|
+
***************************************************************************/
|
8
|
+
|
9
|
+
/***************************************************************************
|
10
|
+
* *
|
11
|
+
* This program is free software; you can redistribute it and/or modify *
|
12
|
+
* it under the terms of the GNU Lesser General Public License as *
|
13
|
+
* published by the Free Software Foundation; either version 2 of the *
|
14
|
+
* License, or (at your option) any later version. *
|
15
|
+
* *
|
16
|
+
***************************************************************************/
|
17
|
+
|
18
|
+
#ifndef _GNU_SOURCE
|
19
|
+
#define _GNU_SOURCE
|
20
|
+
#endif
|
21
|
+
#include <stdio.h>
|
22
|
+
#include <stdarg.h>
|
23
|
+
|
24
|
+
#include <QtCore/qabstractitemmodel.h>
|
25
|
+
#include <QtCore/qglobal.h>
|
26
|
+
#include <QtCore/qhash.h>
|
27
|
+
#include <QtCore/qline.h>
|
28
|
+
#include <QtCore/qmetaobject.h>
|
29
|
+
#include <QtCore/qobject.h>
|
30
|
+
#include <QtCore/qrect.h>
|
31
|
+
#include <QtCore/qregexp.h>
|
32
|
+
#include <QtCore/qstring.h>
|
33
|
+
#include <QtCore/qvariant.h>
|
34
|
+
#include <QtCore/qmutex.h>
|
35
|
+
#include <QtGui/qapplication.h>
|
36
|
+
#include <QtGui/qbitmap.h>
|
37
|
+
#include <QtGui/qcolor.h>
|
38
|
+
#include <QtGui/qcursor.h>
|
39
|
+
#include <QtGui/qfont.h>
|
40
|
+
#include <QtGui/qicon.h>
|
41
|
+
#include <QtGui/qitemselectionmodel.h>
|
42
|
+
#include <QtGui/qpalette.h>
|
43
|
+
#include <QtGui/qpen.h>
|
44
|
+
#include <QtGui/qpixmap.h>
|
45
|
+
#include <QtGui/qpolygon.h>
|
46
|
+
#include <QtGui/qtextformat.h>
|
47
|
+
#include <QtGui/qwidget.h>
|
48
|
+
|
49
|
+
#ifdef QT_QTDBUS
|
50
|
+
#include <QtDBus/qdbusargument.h>
|
51
|
+
#endif
|
52
|
+
|
53
|
+
#undef DEBUG
|
54
|
+
#ifndef __USE_POSIX
|
55
|
+
#define __USE_POSIX
|
56
|
+
#endif
|
57
|
+
#ifndef __USE_XOPEN
|
58
|
+
#define __USE_XOPEN
|
59
|
+
#endif
|
60
|
+
#ifdef _BOOL
|
61
|
+
#define HAS_BOOL
|
62
|
+
#endif
|
63
|
+
|
64
|
+
#include <ruby.h>
|
65
|
+
|
66
|
+
#include <smoke/smoke.h>
|
67
|
+
#include <smoke/qtcore_smoke.h>
|
68
|
+
|
69
|
+
#undef free
|
70
|
+
#undef malloc
|
71
|
+
|
72
|
+
#include "marshall.h"
|
73
|
+
#include "qtruby.h"
|
74
|
+
#include "smokeruby.h"
|
75
|
+
#include "smoke.h"
|
76
|
+
#include "marshall_types.h"
|
77
|
+
// #define DEBUG
|
78
|
+
|
79
|
+
extern "C" {
|
80
|
+
VALUE qt_internal_module = Qnil;
|
81
|
+
VALUE qt_module = Qnil;
|
82
|
+
|
83
|
+
VALUE qlistmodel_class = Qnil;
|
84
|
+
VALUE qmetaobject_class = Qnil;
|
85
|
+
VALUE qtablemodel_class = Qnil;
|
86
|
+
VALUE qt_base_class = Qnil;
|
87
|
+
VALUE qvariant_class = Qnil;
|
88
|
+
|
89
|
+
VALUE moduleindex_class = Qnil;
|
90
|
+
|
91
|
+
bool application_terminated = false;
|
92
|
+
}
|
93
|
+
|
94
|
+
QList<Smoke*> smokeList;
|
95
|
+
QHash<Smoke*, QtRubyModule> qtruby_modules;
|
96
|
+
|
97
|
+
#ifdef DEBUG
|
98
|
+
int do_debug = qtdb_gc;
|
99
|
+
#else
|
100
|
+
int do_debug = qtdb_none;
|
101
|
+
#endif
|
102
|
+
|
103
|
+
typedef QHash<void *, SmokeValue> PointerMap;
|
104
|
+
static QMutex pointer_map_mutex;
|
105
|
+
Q_GLOBAL_STATIC(PointerMap, pointer_map)
|
106
|
+
int object_count = 0;
|
107
|
+
|
108
|
+
// FIXME:
|
109
|
+
// Don't the two following hashs create memory leaks by using pointers to Smoke::(Module)Index ?
|
110
|
+
QHash<QByteArray, Smoke::ModuleIndex *> methcache;
|
111
|
+
QHash<QByteArray, Smoke::ModuleIndex *> classcache;
|
112
|
+
|
113
|
+
QHash<Smoke::ModuleIndex, QByteArray*> IdToClassNameMap;
|
114
|
+
|
115
|
+
#define logger logger_backend
|
116
|
+
|
117
|
+
Smoke::ModuleIndex _current_method;
|
118
|
+
|
119
|
+
smokeruby_object *
|
120
|
+
alloc_smokeruby_object(bool allocated, Smoke * smoke, int classId, void * ptr)
|
121
|
+
{
|
122
|
+
smokeruby_object * o = ALLOC(smokeruby_object);
|
123
|
+
o->classId = classId;
|
124
|
+
o->smoke = smoke;
|
125
|
+
o->ptr = ptr;
|
126
|
+
o->allocated = allocated;
|
127
|
+
return o;
|
128
|
+
}
|
129
|
+
|
130
|
+
void
|
131
|
+
free_smokeruby_object(smokeruby_object * o)
|
132
|
+
{
|
133
|
+
o->ptr = 0;
|
134
|
+
xfree(o);
|
135
|
+
return;
|
136
|
+
}
|
137
|
+
|
138
|
+
smokeruby_object *value_obj_info(VALUE ruby_value) { // ptr on success, null on fail
|
139
|
+
if (TYPE(ruby_value) != T_DATA) {
|
140
|
+
return 0;
|
141
|
+
}
|
142
|
+
|
143
|
+
smokeruby_object * o = 0;
|
144
|
+
Data_Get_Struct(ruby_value, smokeruby_object, o);
|
145
|
+
return o;
|
146
|
+
}
|
147
|
+
|
148
|
+
void *value_to_ptr(VALUE ruby_value) { // ptr on success, null on fail
|
149
|
+
smokeruby_object *o = value_obj_info(ruby_value);
|
150
|
+
return o;
|
151
|
+
}
|
152
|
+
|
153
|
+
VALUE getPointerObject(void *ptr) {
|
154
|
+
return getSmokeValue(ptr).value;
|
155
|
+
}
|
156
|
+
|
157
|
+
SmokeValue getSmokeValue(void *ptr) {
|
158
|
+
pointer_map_mutex.lock();
|
159
|
+
|
160
|
+
if (!pointer_map() || !pointer_map()->contains(ptr)) {
|
161
|
+
if (do_debug & qtdb_gc) {
|
162
|
+
qWarning("getPointerObject %p -> nil", ptr);
|
163
|
+
if (!pointer_map()) {
|
164
|
+
qWarning("getPointerObject pointer_map deleted");
|
165
|
+
}
|
166
|
+
}
|
167
|
+
pointer_map_mutex.unlock();
|
168
|
+
return SmokeValue();
|
169
|
+
} else {
|
170
|
+
if (do_debug & qtdb_gc) {
|
171
|
+
qWarning("getPointerObject %p -> %p", ptr, (void *) pointer_map()->operator[](ptr).value);
|
172
|
+
}
|
173
|
+
pointer_map_mutex.unlock();
|
174
|
+
return pointer_map()->operator[](ptr);
|
175
|
+
}
|
176
|
+
}
|
177
|
+
|
178
|
+
void unmapPointer(void *ptr, Smoke *smoke, Smoke::Index fromClassId, Smoke::Index toClassId, void *lastptr) {
|
179
|
+
pointer_map_mutex.lock();
|
180
|
+
ptr = smoke->cast(ptr, fromClassId, toClassId);
|
181
|
+
|
182
|
+
if (ptr != lastptr) {
|
183
|
+
lastptr = ptr;
|
184
|
+
if (pointer_map() && pointer_map()->contains(ptr)) {
|
185
|
+
VALUE obj_ptr = pointer_map()->operator[](ptr).value;
|
186
|
+
|
187
|
+
if (do_debug & qtdb_gc) {
|
188
|
+
const char *className = smoke->classes[fromClassId].className;
|
189
|
+
qWarning("unmapPointer (%s*)%p -> %p size: %d", className, ptr, (void*)(&obj_ptr), pointer_map()->size() - 1);
|
190
|
+
}
|
191
|
+
|
192
|
+
pointer_map()->remove(ptr);
|
193
|
+
}
|
194
|
+
}
|
195
|
+
|
196
|
+
if (smoke->classes[toClassId].external) {
|
197
|
+
// encountered external class
|
198
|
+
Smoke::ModuleIndex mi = Smoke::findClass(smoke->classes[toClassId].className);
|
199
|
+
if (!mi.index || !mi.smoke) return;
|
200
|
+
|
201
|
+
smoke = mi.smoke;
|
202
|
+
toClassId = mi.index;
|
203
|
+
}
|
204
|
+
|
205
|
+
pointer_map_mutex.unlock();
|
206
|
+
for (Smoke::Index *i = smoke->inheritanceList + smoke->classes[toClassId].parents; *i; i++) {
|
207
|
+
unmapPointer(ptr, smoke, toClassId, *i, lastptr);
|
208
|
+
}
|
209
|
+
|
210
|
+
}
|
211
|
+
|
212
|
+
void unmapPointer(smokeruby_object *o, Smoke::Index classId, void *lastptr) {
|
213
|
+
unmapPointer(o->ptr, o->smoke, o->classId, classId, lastptr);
|
214
|
+
}
|
215
|
+
|
216
|
+
// Store pointer in pointer_map hash : "pointer_to_Qt_object" => weak ref to associated Ruby object
|
217
|
+
// Recurse to store it also as casted to its parent classes.
|
218
|
+
|
219
|
+
void mapPointer(VALUE obj, smokeruby_object* o, void *ptr, Smoke *smoke, Smoke::Index fromClassId, Smoke::Index toClassId, void *lastptr) {
|
220
|
+
pointer_map_mutex.unlock();
|
221
|
+
|
222
|
+
ptr = smoke->cast(ptr, fromClassId, toClassId);
|
223
|
+
|
224
|
+
if (ptr != lastptr) {
|
225
|
+
lastptr = ptr;
|
226
|
+
|
227
|
+
if (do_debug & qtdb_gc) {
|
228
|
+
const char *className = smoke->classes[fromClassId].className;
|
229
|
+
qWarning("mapPointer (%s*)%p -> %p size: %d", className, ptr, (void*)obj, pointer_map()->size() + 1);
|
230
|
+
}
|
231
|
+
|
232
|
+
SmokeValue value(obj, o);
|
233
|
+
pointer_map()->insert(ptr, value);
|
234
|
+
}
|
235
|
+
|
236
|
+
if (smoke->classes[toClassId].external) {
|
237
|
+
// encountered external class
|
238
|
+
Smoke::ModuleIndex mi = Smoke::findClass(smoke->classes[toClassId].className);
|
239
|
+
if (!mi.index || !mi.smoke) return;
|
240
|
+
|
241
|
+
smoke = mi.smoke;
|
242
|
+
toClassId = mi.index;
|
243
|
+
}
|
244
|
+
|
245
|
+
pointer_map_mutex.unlock();
|
246
|
+
for (Smoke::Index *i = smoke->inheritanceList + smoke->classes[toClassId].parents; *i; i++) {
|
247
|
+
mapPointer(obj, o, ptr, smoke, toClassId, *i, lastptr);
|
248
|
+
}
|
249
|
+
|
250
|
+
return;
|
251
|
+
}
|
252
|
+
|
253
|
+
void mapPointer(VALUE obj, smokeruby_object *o, Smoke::Index classId, void *lastptr) {
|
254
|
+
mapPointer(obj, o, o->ptr, o->smoke, o->classId, classId, lastptr);
|
255
|
+
}
|
256
|
+
|
257
|
+
namespace QtRuby {
|
258
|
+
|
259
|
+
Binding::Binding() : SmokeBinding(0) {}
|
260
|
+
Binding::Binding(Smoke *s) : SmokeBinding(s) {}
|
261
|
+
|
262
|
+
void
|
263
|
+
Binding::deleted(Smoke::Index classId, void *ptr) {
|
264
|
+
if (!pointer_map()) {
|
265
|
+
return;
|
266
|
+
}
|
267
|
+
|
268
|
+
smokeruby_object *o = getSmokeValue(ptr).o;
|
269
|
+
if (do_debug & qtdb_gc) {
|
270
|
+
qWarning("unmapping: o = %p, ptr = %p\n", o, ptr);
|
271
|
+
qWarning("%p->~%s()", ptr, smoke->className(classId));
|
272
|
+
}
|
273
|
+
if (!o || !o->ptr) {
|
274
|
+
return;
|
275
|
+
}
|
276
|
+
unmapPointer(o, o->classId, 0);
|
277
|
+
o->ptr = 0;
|
278
|
+
}
|
279
|
+
|
280
|
+
bool
|
281
|
+
Binding::callMethod(Smoke::Index method, void *ptr, Smoke::Stack args, bool /*isAbstract*/) {
|
282
|
+
VALUE obj = getPointerObject(ptr);
|
283
|
+
smokeruby_object *o = value_obj_info(obj);
|
284
|
+
|
285
|
+
if (do_debug & qtdb_virtual) {
|
286
|
+
const Smoke::Method & meth = smoke->methods[method];
|
287
|
+
QByteArray signature(smoke->methodNames[meth.name]);
|
288
|
+
signature += "(";
|
289
|
+
for (int i = 0; i < meth.numArgs; i++) {
|
290
|
+
if (i != 0) signature += ", ";
|
291
|
+
signature += smoke->types[smoke->argumentList[meth.args + i]].name;
|
292
|
+
}
|
293
|
+
signature += ")";
|
294
|
+
if (meth.flags & Smoke::mf_const) {
|
295
|
+
signature += " const";
|
296
|
+
}
|
297
|
+
qWarning( "module: %s virtual %p->%s::%s called",
|
298
|
+
smoke->moduleName(),
|
299
|
+
ptr,
|
300
|
+
smoke->classes[smoke->methods[method].classId].className,
|
301
|
+
(const char *) signature );
|
302
|
+
}
|
303
|
+
|
304
|
+
if (o == 0) {
|
305
|
+
if( do_debug & qtdb_virtual ) // if not in global destruction
|
306
|
+
qWarning("Cannot find object for virtual method %p -> %p", ptr, &obj);
|
307
|
+
return false;
|
308
|
+
}
|
309
|
+
const char *methodName = smoke->methodNames[smoke->methods[method].name];
|
310
|
+
if (qstrncmp(methodName, "operator", sizeof("operator") - 1) == 0) {
|
311
|
+
methodName += (sizeof("operator") - 1);
|
312
|
+
}
|
313
|
+
|
314
|
+
// If not in a ruby thread, just call the C++ version
|
315
|
+
// During GC, avoid checking for override and just call the C++ version
|
316
|
+
// If the virtual method hasn't been overriden, just call the C++ one.
|
317
|
+
#ifdef HAVE_RUBY_RUBY_H
|
318
|
+
int ruby_thread = ruby_native_thread_p();
|
319
|
+
if ((ruby_thread == 0) || rb_during_gc() || rb_respond_to(obj, rb_intern(methodName)) == 0) {
|
320
|
+
return false;
|
321
|
+
}
|
322
|
+
#else
|
323
|
+
if (rb_during_gc() || ruby_stack_check() || rb_respond_to(obj, rb_intern(methodName)) == 0) {
|
324
|
+
return false;
|
325
|
+
}
|
326
|
+
#endif
|
327
|
+
|
328
|
+
QtRuby::VirtualMethodCall c(smoke, method, args, obj, ALLOCA_N(VALUE, smoke->methods[method].numArgs));
|
329
|
+
c.next();
|
330
|
+
return true;
|
331
|
+
}
|
332
|
+
|
333
|
+
char*
|
334
|
+
Binding::className(Smoke::Index classId) {
|
335
|
+
Smoke::ModuleIndex mi(smoke, classId);
|
336
|
+
return (char *) (const char *) *(IdToClassNameMap.value(mi));
|
337
|
+
}
|
338
|
+
|
339
|
+
/*
|
340
|
+
Converts a C++ value returned by a signal invocation to a Ruby
|
341
|
+
reply type
|
342
|
+
*/
|
343
|
+
class SignalReturnValue : public Marshall {
|
344
|
+
QList<MocArgument*> _replyType;
|
345
|
+
Smoke::Stack _stack;
|
346
|
+
VALUE * _result;
|
347
|
+
public:
|
348
|
+
SignalReturnValue(void ** o, VALUE * result, QList<MocArgument*> replyType)
|
349
|
+
{
|
350
|
+
_result = result;
|
351
|
+
_replyType = replyType;
|
352
|
+
_stack = new Smoke::StackItem[1];
|
353
|
+
smokeStackFromQtStack(_stack, o, 0, 1, _replyType);
|
354
|
+
Marshall::HandlerFn fn = getMarshallFn(type());
|
355
|
+
(*fn)(this);
|
356
|
+
}
|
357
|
+
|
358
|
+
SmokeType type() {
|
359
|
+
return _replyType[0]->st;
|
360
|
+
}
|
361
|
+
Marshall::Action action() { return Marshall::ToVALUE; }
|
362
|
+
Smoke::StackItem &item() { return _stack[0]; }
|
363
|
+
VALUE * var() {
|
364
|
+
return _result;
|
365
|
+
}
|
366
|
+
|
367
|
+
void unsupported()
|
368
|
+
{
|
369
|
+
rb_raise(rb_eArgError, "Cannot handle '%s' as signal reply-type", type().name());
|
370
|
+
}
|
371
|
+
Smoke *smoke() { return type().smoke(); }
|
372
|
+
|
373
|
+
void next() {}
|
374
|
+
|
375
|
+
bool cleanup() { return false; }
|
376
|
+
|
377
|
+
~SignalReturnValue() {
|
378
|
+
delete[] _stack;
|
379
|
+
}
|
380
|
+
};
|
381
|
+
|
382
|
+
/* Note that the SignalReturnValue and EmitSignal classes really belong in
|
383
|
+
marshall_types.cpp. However, for unknown reasons they don't link with certain
|
384
|
+
versions of gcc. So they were moved here in to work round that bug.
|
385
|
+
*/
|
386
|
+
EmitSignal::EmitSignal(QObject *obj, int id, int /*items*/, QList<MocArgument*> args, VALUE *sp, VALUE * result) : SigSlotBase(args),
|
387
|
+
_obj(obj), _id(id)
|
388
|
+
{
|
389
|
+
_sp = sp;
|
390
|
+
_result = result;
|
391
|
+
}
|
392
|
+
|
393
|
+
Marshall::Action
|
394
|
+
EmitSignal::action()
|
395
|
+
{
|
396
|
+
return Marshall::FromVALUE;
|
397
|
+
}
|
398
|
+
|
399
|
+
Smoke::StackItem &
|
400
|
+
EmitSignal::item()
|
401
|
+
{
|
402
|
+
return _stack[_cur];
|
403
|
+
}
|
404
|
+
|
405
|
+
const char *
|
406
|
+
EmitSignal::mytype()
|
407
|
+
{
|
408
|
+
return "signal";
|
409
|
+
}
|
410
|
+
|
411
|
+
void
|
412
|
+
EmitSignal::emitSignal()
|
413
|
+
{
|
414
|
+
if (_called) return;
|
415
|
+
_called = true;
|
416
|
+
void ** o = new void*[_items];
|
417
|
+
smokeStackToQtStack(_stack, o + 1, 1, _items, _args);
|
418
|
+
void * ptr;
|
419
|
+
o[0] = &ptr;
|
420
|
+
prepareReturnValue(o);
|
421
|
+
|
422
|
+
_obj->metaObject()->activate(_obj, _id, o);
|
423
|
+
|
424
|
+
if (_args[0]->argType != xmoc_void) {
|
425
|
+
SignalReturnValue r(o, _result, _args);
|
426
|
+
}
|
427
|
+
delete[] o;
|
428
|
+
}
|
429
|
+
|
430
|
+
void
|
431
|
+
EmitSignal::mainfunction()
|
432
|
+
{
|
433
|
+
emitSignal();
|
434
|
+
}
|
435
|
+
|
436
|
+
bool
|
437
|
+
EmitSignal::cleanup()
|
438
|
+
{
|
439
|
+
return true;
|
440
|
+
}
|
441
|
+
|
442
|
+
InvokeNativeSlot::InvokeNativeSlot(QObject *obj, int id, int /*items*/, QList<MocArgument*> args, VALUE *sp, VALUE * result) : SigSlotBase(args),
|
443
|
+
_obj(obj), _id(id)
|
444
|
+
{
|
445
|
+
_sp = sp;
|
446
|
+
_result = result;
|
447
|
+
}
|
448
|
+
|
449
|
+
Marshall::Action
|
450
|
+
InvokeNativeSlot::action()
|
451
|
+
{
|
452
|
+
return Marshall::FromVALUE;
|
453
|
+
}
|
454
|
+
|
455
|
+
Smoke::StackItem &
|
456
|
+
InvokeNativeSlot::item()
|
457
|
+
{
|
458
|
+
return _stack[_cur];
|
459
|
+
}
|
460
|
+
|
461
|
+
const char *
|
462
|
+
InvokeNativeSlot::mytype()
|
463
|
+
{
|
464
|
+
return "slot";
|
465
|
+
}
|
466
|
+
|
467
|
+
void
|
468
|
+
InvokeNativeSlot::invokeSlot()
|
469
|
+
{
|
470
|
+
if (_called) return;
|
471
|
+
_called = true;
|
472
|
+
void ** o = new void*[_items];
|
473
|
+
smokeStackToQtStack(_stack, o + 1, 1, _items, _args);
|
474
|
+
void * ptr;
|
475
|
+
o[0] = &ptr;
|
476
|
+
prepareReturnValue(o);
|
477
|
+
|
478
|
+
_obj->qt_metacall(QMetaObject::InvokeMetaMethod, _id, o);
|
479
|
+
|
480
|
+
if (_args[0]->argType != xmoc_void) {
|
481
|
+
SignalReturnValue r(o, _result, _args);
|
482
|
+
}
|
483
|
+
delete[] o;
|
484
|
+
}
|
485
|
+
|
486
|
+
void
|
487
|
+
InvokeNativeSlot::mainfunction()
|
488
|
+
{
|
489
|
+
invokeSlot();
|
490
|
+
}
|
491
|
+
|
492
|
+
bool
|
493
|
+
InvokeNativeSlot::cleanup()
|
494
|
+
{
|
495
|
+
return true;
|
496
|
+
}
|
497
|
+
|
498
|
+
}
|
499
|
+
|
500
|
+
VALUE rb_str_catf(VALUE self, const char *format, ...)
|
501
|
+
{
|
502
|
+
#define CAT_BUFFER_SIZE 2048
|
503
|
+
static char p[CAT_BUFFER_SIZE];
|
504
|
+
va_list ap;
|
505
|
+
va_start(ap, format);
|
506
|
+
qvsnprintf(p, CAT_BUFFER_SIZE, format, ap);
|
507
|
+
p[CAT_BUFFER_SIZE - 1] = '\0';
|
508
|
+
rb_str_cat2(self, p);
|
509
|
+
va_end(ap);
|
510
|
+
return self;
|
511
|
+
}
|
512
|
+
|
513
|
+
const char *
|
514
|
+
resolve_classname(smokeruby_object * o)
|
515
|
+
{
|
516
|
+
if (Smoke::isDerivedFrom(o->smoke->classes[o->classId].className, "QObject")) {
|
517
|
+
QObject * qobject = (QObject *) o->smoke->cast(o->ptr, o->classId, o->smoke->idClass("QObject").index);
|
518
|
+
const QMetaObject * meta = qobject->metaObject();
|
519
|
+
|
520
|
+
while (meta != 0) {
|
521
|
+
Smoke::ModuleIndex mi = o->smoke->findClass(meta->className());
|
522
|
+
o->smoke = mi.smoke;
|
523
|
+
o->classId = mi.index;
|
524
|
+
if (o->smoke != 0) {
|
525
|
+
if (o->classId != 0) {
|
526
|
+
return qtruby_modules[o->smoke].binding->className(o->classId);
|
527
|
+
}
|
528
|
+
}
|
529
|
+
|
530
|
+
meta = meta->superClass();
|
531
|
+
}
|
532
|
+
}
|
533
|
+
|
534
|
+
if (o->smoke->classes[o->classId].external) {
|
535
|
+
Smoke::ModuleIndex mi = o->smoke->findClass(o->smoke->className(o->classId));
|
536
|
+
o->smoke = mi.smoke;
|
537
|
+
o->classId = mi.index;
|
538
|
+
return qtruby_modules.value(mi.smoke).resolve_classname(o);
|
539
|
+
}
|
540
|
+
return qtruby_modules.value(o->smoke).resolve_classname(o);
|
541
|
+
}
|
542
|
+
|
543
|
+
VALUE
|
544
|
+
findMethod(VALUE /*self*/, VALUE c_value, VALUE name_value)
|
545
|
+
{
|
546
|
+
char *c = StringValuePtr(c_value);
|
547
|
+
char *name = StringValuePtr(name_value);
|
548
|
+
VALUE result = rb_ary_new();
|
549
|
+
Smoke::ModuleIndex classId = Smoke::findClass(c);
|
550
|
+
Smoke::ModuleIndex meth = Smoke::NullModuleIndex;
|
551
|
+
QList<Smoke::ModuleIndex> milist;
|
552
|
+
if (classId.smoke != 0) {
|
553
|
+
meth = classId.smoke->findMethod(c, name);
|
554
|
+
}
|
555
|
+
#ifdef DEBUG
|
556
|
+
if (do_debug & qtdb_calls) qWarning("Found method %s::%s => %d", c, name, meth.index);
|
557
|
+
#endif
|
558
|
+
if(!meth.index) {
|
559
|
+
// since every smoke module defines a class 'QGlobalSpace' we can't rely on the classMap,
|
560
|
+
// so we search for methods by hand
|
561
|
+
foreach (Smoke* s, smokeList) {
|
562
|
+
Smoke::ModuleIndex cid = s->idClass("QGlobalSpace");
|
563
|
+
Smoke::ModuleIndex mnid = s->idMethodName(name);
|
564
|
+
if (!cid.index || !mnid.index) continue;
|
565
|
+
meth = s->idMethod(cid.index, mnid.index);
|
566
|
+
if (meth.index) milist.append(meth);
|
567
|
+
}
|
568
|
+
#ifdef DEBUG
|
569
|
+
if (do_debug & qtdb_calls) qWarning("Found method QGlobalSpace::%s => %d", name, meth.index);
|
570
|
+
#endif
|
571
|
+
}
|
572
|
+
else
|
573
|
+
{
|
574
|
+
milist.append(meth);
|
575
|
+
}
|
576
|
+
|
577
|
+
if (milist.count() == 0) {
|
578
|
+
return result;
|
579
|
+
// empty list
|
580
|
+
} else {
|
581
|
+
foreach (Smoke::ModuleIndex meth, milist) {
|
582
|
+
if (meth.index > 0) {
|
583
|
+
Smoke::Index i = meth.smoke->methodMaps[meth.index].method;
|
584
|
+
if (i == 0) { // shouldn't happen
|
585
|
+
rb_raise(rb_eArgError, "Corrupt method %s::%s", c, name);
|
586
|
+
} else if(i > 0) { // single match
|
587
|
+
const Smoke::Method &methodRef = meth.smoke->methods[i];
|
588
|
+
if ((methodRef.flags & Smoke::mf_internal) == 0) {
|
589
|
+
rb_ary_push(result, rb_funcall(moduleindex_class, rb_intern("new"), 2, INT2NUM(smokeList.indexOf(meth.smoke)), INT2NUM(i)));
|
590
|
+
}
|
591
|
+
} else { // multiple match
|
592
|
+
i = -i; // turn into ambiguousMethodList index
|
593
|
+
while (meth.smoke->ambiguousMethodList[i]) {
|
594
|
+
const Smoke::Method &methodRef = meth.smoke->methods[meth.smoke->ambiguousMethodList[i]];
|
595
|
+
if ((methodRef.flags & Smoke::mf_internal) == 0) {
|
596
|
+
rb_ary_push(result, rb_funcall(moduleindex_class, rb_intern("new"), 2, INT2NUM(smokeList.indexOf(meth.smoke)), INT2NUM(meth.smoke->ambiguousMethodList[i])));
|
597
|
+
//#ifdef DEBUG
|
598
|
+
if (do_debug & qtdb_calls) qWarning("Ambiguous Method %s::%s => %d", c, name, meth.smoke->ambiguousMethodList[i]);
|
599
|
+
//#endif
|
600
|
+
|
601
|
+
}
|
602
|
+
i++;
|
603
|
+
}
|
604
|
+
}
|
605
|
+
}
|
606
|
+
}
|
607
|
+
}
|
608
|
+
return result;
|
609
|
+
}
|
610
|
+
|
611
|
+
// findAllMethods(ModuleIndex [, startingWith]) : returns { "mungedName" => [index in methods, ...], ... }
|
612
|
+
|
613
|
+
VALUE
|
614
|
+
findAllMethods(int argc, VALUE * argv, VALUE /*self*/)
|
615
|
+
{
|
616
|
+
VALUE rb_mi = argv[0];
|
617
|
+
VALUE result = rb_hash_new();
|
618
|
+
if (rb_mi != Qnil) {
|
619
|
+
Smoke::Index c = (Smoke::Index) NUM2INT(rb_funcall(rb_mi, rb_intern("index"), 0));
|
620
|
+
Smoke *smoke = smokeList[NUM2INT(rb_funcall(rb_mi, rb_intern("smoke"), 0))];
|
621
|
+
if (c > smoke->numClasses) {
|
622
|
+
return Qnil;
|
623
|
+
}
|
624
|
+
char * pat = 0L;
|
625
|
+
if(argc > 1 && TYPE(argv[1]) == T_STRING)
|
626
|
+
pat = StringValuePtr(argv[1]);
|
627
|
+
#ifdef DEBUG
|
628
|
+
if (do_debug & qtdb_calls) qWarning("findAllMethods called with classid = %d, pat == %s", c, pat);
|
629
|
+
#endif
|
630
|
+
Smoke::Index imax = smoke->numMethodMaps;
|
631
|
+
Smoke::Index imin = 0, icur = -1, methmin, methmax;
|
632
|
+
methmin = -1; methmax = -1; // kill warnings
|
633
|
+
int icmp = -1;
|
634
|
+
while(imax >= imin) {
|
635
|
+
icur = (imin + imax) / 2;
|
636
|
+
icmp = smoke->leg(smoke->methodMaps[icur].classId, c);
|
637
|
+
if (icmp == 0) {
|
638
|
+
Smoke::Index pos = icur;
|
639
|
+
while (icur && smoke->methodMaps[icur-1].classId == c)
|
640
|
+
icur --;
|
641
|
+
methmin = icur;
|
642
|
+
icur = pos;
|
643
|
+
while(icur < imax && smoke->methodMaps[icur+1].classId == c)
|
644
|
+
icur ++;
|
645
|
+
methmax = icur;
|
646
|
+
break;
|
647
|
+
}
|
648
|
+
if (icmp > 0)
|
649
|
+
imax = icur - 1;
|
650
|
+
else
|
651
|
+
imin = icur + 1;
|
652
|
+
}
|
653
|
+
if (icmp == 0) {
|
654
|
+
for (Smoke::Index i = methmin; i <= methmax; i++) {
|
655
|
+
Smoke::Index m = smoke->methodMaps[i].name;
|
656
|
+
if (pat == 0L || strncmp(smoke->methodNames[m], pat, strlen(pat)) == 0) {
|
657
|
+
Smoke::Index ix = smoke->methodMaps[i].method;
|
658
|
+
VALUE meths = rb_ary_new();
|
659
|
+
if (ix >= 0) { // single match
|
660
|
+
const Smoke::Method &methodRef = smoke->methods[ix];
|
661
|
+
if ((methodRef.flags & Smoke::mf_internal) == 0) {
|
662
|
+
rb_ary_push(meths, rb_funcall(moduleindex_class, rb_intern("new"), 2, INT2NUM(smokeList.indexOf(smoke)), INT2NUM((int) ix)));
|
663
|
+
}
|
664
|
+
} else { // multiple match
|
665
|
+
ix = -ix; // turn into ambiguousMethodList index
|
666
|
+
while (smoke->ambiguousMethodList[ix]) {
|
667
|
+
const Smoke::Method &methodRef = smoke->methods[smoke->ambiguousMethodList[ix]];
|
668
|
+
if ((methodRef.flags & Smoke::mf_internal) == 0) {
|
669
|
+
rb_ary_push(meths, rb_funcall(moduleindex_class, rb_intern("new"), 2, INT2NUM(smokeList.indexOf(smoke)), INT2NUM((int)smoke->ambiguousMethodList[ix])));
|
670
|
+
}
|
671
|
+
ix++;
|
672
|
+
}
|
673
|
+
}
|
674
|
+
rb_hash_aset(result, rb_str_new2(smoke->methodNames[m]), meths);
|
675
|
+
}
|
676
|
+
}
|
677
|
+
}
|
678
|
+
}
|
679
|
+
return result;
|
680
|
+
}
|
681
|
+
|
682
|
+
/*
|
683
|
+
Flags values
|
684
|
+
0 All methods, except enum values and protected non-static methods
|
685
|
+
mf_static Static methods only
|
686
|
+
mf_enum Enums only
|
687
|
+
mf_protected Protected non-static methods only
|
688
|
+
*/
|
689
|
+
|
690
|
+
#define PUSH_QTRUBY_METHOD \
|
691
|
+
if ( (methodRef.flags & (Smoke::mf_internal|Smoke::mf_ctor|Smoke::mf_dtor)) == 0 \
|
692
|
+
&& strcmp(s->methodNames[methodRef.name], "operator=") != 0 \
|
693
|
+
&& strcmp(s->methodNames[methodRef.name], "operator!=") != 0 \
|
694
|
+
&& strcmp(s->methodNames[methodRef.name], "operator--") != 0 \
|
695
|
+
&& strcmp(s->methodNames[methodRef.name], "operator++") != 0 \
|
696
|
+
&& strncmp(s->methodNames[methodRef.name], "operator ", strlen("operator ")) != 0 \
|
697
|
+
&& ( (flags == 0 && (methodRef.flags & (Smoke::mf_static|Smoke::mf_enum|Smoke::mf_protected)) == 0) \
|
698
|
+
|| ( flags == Smoke::mf_static \
|
699
|
+
&& (methodRef.flags & Smoke::mf_enum) == 0 \
|
700
|
+
&& (methodRef.flags & Smoke::mf_static) == Smoke::mf_static ) \
|
701
|
+
|| (flags == Smoke::mf_enum && (methodRef.flags & Smoke::mf_enum) == Smoke::mf_enum) \
|
702
|
+
|| ( flags == Smoke::mf_protected \
|
703
|
+
&& (methodRef.flags & Smoke::mf_static) == 0 \
|
704
|
+
&& (methodRef.flags & Smoke::mf_protected) == Smoke::mf_protected ) ) ) { \
|
705
|
+
if (strncmp(s->methodNames[methodRef.name], "operator", strlen("operator")) == 0) { \
|
706
|
+
if (op_re.indexIn(s->methodNames[methodRef.name]) != -1) { \
|
707
|
+
rb_ary_push(result, rb_str_new2((op_re.cap(1) + op_re.cap(2)).toLatin1())); \
|
708
|
+
} else { \
|
709
|
+
rb_ary_push(result, rb_str_new2(s->methodNames[methodRef.name] + strlen("operator"))); \
|
710
|
+
} \
|
711
|
+
} else if (predicate_re.indexIn(s->methodNames[methodRef.name]) != -1 && methodRef.numArgs == 0) { \
|
712
|
+
rb_ary_push(result, rb_str_new2((predicate_re.cap(2).toLower() + predicate_re.cap(3) + "?").toLatin1())); \
|
713
|
+
} else if (set_re.indexIn(s->methodNames[methodRef.name]) != -1 && methodRef.numArgs == 1) { \
|
714
|
+
rb_ary_push(result, rb_str_new2((set_re.cap(2).toLower() + set_re.cap(3) + "=").toLatin1())); \
|
715
|
+
} else { \
|
716
|
+
rb_ary_push(result, rb_str_new2(s->methodNames[methodRef.name])); \
|
717
|
+
} \
|
718
|
+
}
|
719
|
+
|
720
|
+
VALUE
|
721
|
+
findAllMethodNames(VALUE /*self*/, VALUE result, VALUE classid, VALUE flags_value)
|
722
|
+
{
|
723
|
+
QRegExp predicate_re("^(is|has)(.)(.*)");
|
724
|
+
QRegExp set_re("^(set)([A-Z])(.*)");
|
725
|
+
QRegExp op_re("operator(.*)(([-%~/+|&*])|(>>)|(<<)|(&&)|(\\|\\|)|(\\*\\*))=$");
|
726
|
+
|
727
|
+
unsigned short flags = (unsigned short) NUM2UINT(flags_value);
|
728
|
+
if (classid != Qnil) {
|
729
|
+
Smoke::Index c = (Smoke::Index) NUM2INT(rb_funcall(classid, rb_intern("index"), 0));
|
730
|
+
Smoke* s = smokeList[NUM2INT(rb_funcall(classid, rb_intern("smoke"), 0))];
|
731
|
+
if (c > s->numClasses) {
|
732
|
+
return Qnil;
|
733
|
+
}
|
734
|
+
#ifdef DEBUG
|
735
|
+
if (do_debug & qtdb_calls) qWarning("findAllMethodNames called with classid = %d in module %s", c, s->moduleName());
|
736
|
+
#endif
|
737
|
+
Smoke::Index imax = s->numMethodMaps;
|
738
|
+
Smoke::Index imin = 0, icur = -1, methmin, methmax;
|
739
|
+
methmin = -1; methmax = -1; // kill warnings
|
740
|
+
int icmp = -1;
|
741
|
+
|
742
|
+
while (imax >= imin) {
|
743
|
+
icur = (imin + imax) / 2;
|
744
|
+
icmp = s->leg(s->methodMaps[icur].classId, c);
|
745
|
+
if (icmp == 0) {
|
746
|
+
Smoke::Index pos = icur;
|
747
|
+
while(icur && s->methodMaps[icur-1].classId == c)
|
748
|
+
icur --;
|
749
|
+
methmin = icur;
|
750
|
+
icur = pos;
|
751
|
+
while(icur < imax && s->methodMaps[icur+1].classId == c)
|
752
|
+
icur ++;
|
753
|
+
methmax = icur;
|
754
|
+
break;
|
755
|
+
}
|
756
|
+
if (icmp > 0)
|
757
|
+
imax = icur - 1;
|
758
|
+
else
|
759
|
+
imin = icur + 1;
|
760
|
+
}
|
761
|
+
|
762
|
+
if (icmp == 0) {
|
763
|
+
for (Smoke::Index i=methmin ; i <= methmax ; i++) {
|
764
|
+
Smoke::Index ix= s->methodMaps[i].method;
|
765
|
+
if (ix > 0) { // single match
|
766
|
+
const Smoke::Method &methodRef = s->methods[ix];
|
767
|
+
PUSH_QTRUBY_METHOD
|
768
|
+
} else { // multiple match
|
769
|
+
ix = -ix; // turn into ambiguousMethodList index
|
770
|
+
while (s->ambiguousMethodList[ix]) {
|
771
|
+
const Smoke::Method &methodRef = s->methods[s->ambiguousMethodList[ix]];
|
772
|
+
PUSH_QTRUBY_METHOD
|
773
|
+
ix++;
|
774
|
+
}
|
775
|
+
}
|
776
|
+
}
|
777
|
+
}
|
778
|
+
}
|
779
|
+
return result;
|
780
|
+
}
|
781
|
+
|
782
|
+
QByteArray *
|
783
|
+
find_cached_selector(int argc, VALUE * argv, VALUE klass, const char * methodName)
|
784
|
+
{
|
785
|
+
// Look in the cache
|
786
|
+
static QByteArray * mcid = 0;
|
787
|
+
if (mcid == 0) {
|
788
|
+
mcid = new QByteArray();
|
789
|
+
}
|
790
|
+
|
791
|
+
*mcid = rb_class2name(klass);
|
792
|
+
*mcid += ';';
|
793
|
+
*mcid += methodName;
|
794
|
+
for(int i=4; i<argc ; i++)
|
795
|
+
{
|
796
|
+
*mcid += ';';
|
797
|
+
*mcid += value_to_type_flag(argv[i]);
|
798
|
+
}
|
799
|
+
Smoke::ModuleIndex *rcid = methcache.value(*mcid);
|
800
|
+
#ifdef DEBUG
|
801
|
+
if (do_debug & qtdb_calls) qWarning("method_missing mcid: %s", (const char *) *mcid);
|
802
|
+
#endif
|
803
|
+
|
804
|
+
if (rcid) {
|
805
|
+
// Got a hit
|
806
|
+
#ifdef DEBUG
|
807
|
+
if (do_debug & qtdb_calls) qWarning("method_missing cache hit, mcid: %s", (const char *) *mcid);
|
808
|
+
#endif
|
809
|
+
_current_method.smoke = rcid->smoke;
|
810
|
+
_current_method.index = rcid->index;
|
811
|
+
} else {
|
812
|
+
_current_method.smoke = 0;
|
813
|
+
_current_method.index = -1;
|
814
|
+
}
|
815
|
+
|
816
|
+
return mcid;
|
817
|
+
}
|
818
|
+
|
819
|
+
VALUE
|
820
|
+
method_missing(int argc, VALUE * argv, VALUE self)
|
821
|
+
{
|
822
|
+
const char * methodName = rb_id2name(SYM2ID(argv[0]));
|
823
|
+
VALUE klass = rb_funcall(self, rb_intern("class"), 0);
|
824
|
+
|
825
|
+
VALUE retval = Qnil;
|
826
|
+
|
827
|
+
// Look for 'thing?' methods, and try to match isThing() or hasThing() in the Smoke runtime
|
828
|
+
static QByteArray * pred = 0;
|
829
|
+
static VALUE mainThread = Qnil;
|
830
|
+
if (pred == 0) {
|
831
|
+
pred = new QByteArray();
|
832
|
+
}
|
833
|
+
if (mainThread == Qnil) {
|
834
|
+
mainThread = rb_thread_main();
|
835
|
+
}
|
836
|
+
|
837
|
+
if (rb_thread_current() != mainThread) {
|
838
|
+
rb_raise(rb_eRuntimeError, "Qt methods cannot be called from outside of the main thread");
|
839
|
+
}
|
840
|
+
|
841
|
+
*pred = methodName;
|
842
|
+
if (pred->endsWith("?")) {
|
843
|
+
smokeruby_object *o = value_obj_info(self);
|
844
|
+
if(!o || !o->ptr) {
|
845
|
+
return rb_call_super(argc, argv);
|
846
|
+
}
|
847
|
+
|
848
|
+
// Drop the trailing '?'
|
849
|
+
pred->replace(pred->length() - 1, 1, "");
|
850
|
+
|
851
|
+
pred->replace(0, 1, pred->mid(0, 1).toUpper());
|
852
|
+
pred->replace(0, 0, "is");
|
853
|
+
Smoke::ModuleIndex meth = o->smoke->findMethod(o->smoke->classes[o->classId].className, (const char *) *pred);
|
854
|
+
|
855
|
+
if (meth.index == 0) {
|
856
|
+
pred->replace(0, 2, "has");
|
857
|
+
meth = o->smoke->findMethod(o->smoke->classes[o->classId].className, *pred);
|
858
|
+
}
|
859
|
+
|
860
|
+
if (meth.index > 0) {
|
861
|
+
methodName = (char *) (const char *) *pred;
|
862
|
+
}
|
863
|
+
}
|
864
|
+
|
865
|
+
VALUE * temp_stack = ALLOCA_N(VALUE, argc+3);
|
866
|
+
temp_stack[0] = rb_str_new2("Qt");
|
867
|
+
temp_stack[1] = rb_str_new2(methodName);
|
868
|
+
temp_stack[2] = klass;
|
869
|
+
temp_stack[3] = self;
|
870
|
+
for (int count = 1; count < argc; count++) {
|
871
|
+
temp_stack[count+3] = argv[count];
|
872
|
+
}
|
873
|
+
|
874
|
+
{
|
875
|
+
QByteArray * mcid = find_cached_selector(argc+3, temp_stack, klass, methodName);
|
876
|
+
|
877
|
+
if (_current_method.index == -1) {
|
878
|
+
// Find the C++ method to call. Do that from Ruby for now
|
879
|
+
|
880
|
+
retval = rb_funcall2(qt_internal_module, rb_intern("do_method_missing"), argc+3, temp_stack);
|
881
|
+
if (_current_method.index == -1) {
|
882
|
+
const char * op = rb_id2name(SYM2ID(argv[0]));
|
883
|
+
if ( qstrcmp(op, "-") == 0
|
884
|
+
|| qstrcmp(op, "+") == 0
|
885
|
+
|| qstrcmp(op, "/") == 0
|
886
|
+
|| qstrcmp(op, "%") == 0
|
887
|
+
|| qstrcmp(op, "|") == 0 )
|
888
|
+
{
|
889
|
+
// Look for operator methods of the form 'operator+=', 'operator-=' and so on..
|
890
|
+
char op1[3];
|
891
|
+
op1[0] = op[0];
|
892
|
+
op1[1] = '=';
|
893
|
+
op1[2] = '\0';
|
894
|
+
temp_stack[1] = rb_str_new2(op1);
|
895
|
+
retval = rb_funcall2(qt_internal_module, rb_intern("do_method_missing"), argc+3, temp_stack);
|
896
|
+
}
|
897
|
+
|
898
|
+
if (_current_method.index == -1) {
|
899
|
+
// Check for property getter/setter calls, and for slots in QObject classes
|
900
|
+
// not in the smoke library
|
901
|
+
smokeruby_object *o = value_obj_info(self);
|
902
|
+
if ( o != 0
|
903
|
+
&& o->ptr != 0
|
904
|
+
&& Smoke::isDerivedFrom(Smoke::ModuleIndex(o->smoke, o->classId), Smoke::findClass("QObject")) )
|
905
|
+
{
|
906
|
+
QObject * qobject = (QObject *) o->smoke->cast(o->ptr, o->classId, o->smoke->idClass("QObject").index);
|
907
|
+
static QByteArray * name = 0;
|
908
|
+
if (name == 0) {
|
909
|
+
name = new QByteArray();
|
910
|
+
}
|
911
|
+
|
912
|
+
*name = rb_id2name(SYM2ID(argv[0]));
|
913
|
+
const QMetaObject * meta = qobject->metaObject();
|
914
|
+
|
915
|
+
if (argc == 1) {
|
916
|
+
if (name->endsWith("?")) {
|
917
|
+
name->replace(0, 1, pred->mid(0, 1).toUpper());
|
918
|
+
name->replace(0, 0, "is");
|
919
|
+
if (meta->indexOfProperty(*name) == -1) {
|
920
|
+
name->replace(0, 2, "has");
|
921
|
+
}
|
922
|
+
}
|
923
|
+
|
924
|
+
if (meta->indexOfProperty(*name) != -1) {
|
925
|
+
VALUE qvariant = rb_funcall(self, rb_intern("property"), 1, rb_str_new2(*name));
|
926
|
+
return rb_funcall(qvariant, rb_intern("value"), 0);
|
927
|
+
}
|
928
|
+
}
|
929
|
+
|
930
|
+
if (argc == 2 && name->endsWith("=")) {
|
931
|
+
name->replace("=", "");
|
932
|
+
if (meta->indexOfProperty(*name) != -1) {
|
933
|
+
VALUE qvariant = rb_funcall(self, rb_intern("qVariantFromValue"), 1, argv[1]);
|
934
|
+
return rb_funcall(self, rb_intern("setProperty"), 2, rb_str_new2(*name), qvariant);
|
935
|
+
}
|
936
|
+
}
|
937
|
+
|
938
|
+
int classId = o->smoke->idClass(meta->className()).index;
|
939
|
+
|
940
|
+
// The class isn't in the Smoke lib. But if it is called 'local::Merged'
|
941
|
+
// it is from a QDBusInterface and the slots are remote, so don't try to
|
942
|
+
// those.
|
943
|
+
while ( classId == 0
|
944
|
+
&& qstrcmp(meta->className(), "local::Merged") != 0
|
945
|
+
&& qstrcmp(meta->superClass()->className(), "QDBusAbstractInterface") != 0 )
|
946
|
+
{
|
947
|
+
// Assume the QObject has slots which aren't in the Smoke library, so try
|
948
|
+
// and call the slot directly
|
949
|
+
for (int id = meta->methodOffset(); id < meta->methodCount(); id++) {
|
950
|
+
if (meta->method(id).methodType() == QMetaMethod::Slot) {
|
951
|
+
QByteArray signature(meta->method(id).signature());
|
952
|
+
QByteArray methodName = signature.mid(0, signature.indexOf('('));
|
953
|
+
|
954
|
+
// Don't check that the types of the ruby args match the c++ ones for now,
|
955
|
+
// only that the name and arg count is the same.
|
956
|
+
if (*name == methodName && meta->method(id).parameterTypes().count() == (argc - 1)) {
|
957
|
+
QList<MocArgument*> args = get_moc_arguments( o->smoke, meta->method(id).typeName(),
|
958
|
+
meta->method(id).parameterTypes() );
|
959
|
+
VALUE result = Qnil;
|
960
|
+
QtRuby::InvokeNativeSlot slot(qobject, id, argc - 1, args, argv + 1, &result);
|
961
|
+
slot.next();
|
962
|
+
return result;
|
963
|
+
}
|
964
|
+
}
|
965
|
+
}
|
966
|
+
meta = meta->superClass();
|
967
|
+
classId = o->smoke->idClass(meta->className()).index;
|
968
|
+
}
|
969
|
+
}
|
970
|
+
|
971
|
+
return rb_call_super(argc, argv);
|
972
|
+
}
|
973
|
+
}
|
974
|
+
// Success. Cache result.
|
975
|
+
methcache.insert(*mcid, new Smoke::ModuleIndex(_current_method));
|
976
|
+
}
|
977
|
+
}
|
978
|
+
QtRuby::MethodCall c(_current_method.smoke, _current_method.index, self, temp_stack+4, argc-1);
|
979
|
+
c.next();
|
980
|
+
VALUE result = *(c.var());
|
981
|
+
return result;
|
982
|
+
}
|
983
|
+
|
984
|
+
VALUE
|
985
|
+
class_method_missing(int argc, VALUE * argv, VALUE klass)
|
986
|
+
{
|
987
|
+
VALUE result = Qnil;
|
988
|
+
VALUE retval = Qnil;
|
989
|
+
const char * methodName = rb_id2name(SYM2ID(argv[0]));
|
990
|
+
VALUE * temp_stack = ALLOCA_N(VALUE, argc+3);
|
991
|
+
static VALUE mainThread = Qnil;
|
992
|
+
if (mainThread == Qnil) {
|
993
|
+
mainThread = rb_thread_main();
|
994
|
+
}
|
995
|
+
temp_stack[0] = rb_str_new2("Qt");
|
996
|
+
temp_stack[1] = rb_str_new2(methodName);
|
997
|
+
temp_stack[2] = klass;
|
998
|
+
temp_stack[3] = Qnil;
|
999
|
+
|
1000
|
+
if (rb_thread_current() != mainThread) {
|
1001
|
+
rb_raise(rb_eRuntimeError, "Qt methods cannot be called from outside of the main thread");
|
1002
|
+
}
|
1003
|
+
|
1004
|
+
for (int count = 1; count < argc; count++) {
|
1005
|
+
temp_stack[count+3] = argv[count];
|
1006
|
+
}
|
1007
|
+
|
1008
|
+
{
|
1009
|
+
QByteArray * mcid = find_cached_selector(argc+3, temp_stack, klass, methodName);
|
1010
|
+
|
1011
|
+
if (_current_method.index == -1) {
|
1012
|
+
retval = rb_funcall2(qt_internal_module, rb_intern("do_method_missing"), argc+3, temp_stack);
|
1013
|
+
if (_current_method.index != -1) {
|
1014
|
+
// Success. Cache result.
|
1015
|
+
methcache.insert(*mcid, new Smoke::ModuleIndex(_current_method));
|
1016
|
+
}
|
1017
|
+
}
|
1018
|
+
}
|
1019
|
+
|
1020
|
+
if (_current_method.index == -1) {
|
1021
|
+
static QRegExp * rx = 0;
|
1022
|
+
if (rx == 0) {
|
1023
|
+
rx = new QRegExp("[a-zA-Z]+");
|
1024
|
+
}
|
1025
|
+
|
1026
|
+
if (rx->indexIn(methodName) == -1) {
|
1027
|
+
// If an operator method hasn't been found as an instance method,
|
1028
|
+
// then look for a class method - after 'op(self,a)' try 'self.op(a)'
|
1029
|
+
VALUE * method_stack = ALLOCA_N(VALUE, argc - 1);
|
1030
|
+
method_stack[0] = argv[0];
|
1031
|
+
for (int count = 1; count < argc - 1; count++) {
|
1032
|
+
method_stack[count] = argv[count+1];
|
1033
|
+
}
|
1034
|
+
result = method_missing(argc-1, method_stack, argv[1]);
|
1035
|
+
return result;
|
1036
|
+
} else {
|
1037
|
+
return rb_call_super(argc, argv);
|
1038
|
+
}
|
1039
|
+
}
|
1040
|
+
QtRuby::MethodCall c(_current_method.smoke, _current_method.index, Qnil, temp_stack+4, argc-1);
|
1041
|
+
c.next();
|
1042
|
+
result = *(c.var());
|
1043
|
+
return result;
|
1044
|
+
}
|
1045
|
+
|
1046
|
+
QList<MocArgument*>
|
1047
|
+
get_moc_arguments(Smoke* smoke, const char * typeName, QList<QByteArray> methodTypes)
|
1048
|
+
{
|
1049
|
+
static QRegExp * rx = 0;
|
1050
|
+
if (rx == 0) {
|
1051
|
+
rx = new QRegExp("^(bool|int|uint|long|ulong|double|char\\*|QString)&?$");
|
1052
|
+
}
|
1053
|
+
methodTypes.prepend(QByteArray(typeName));
|
1054
|
+
QList<MocArgument*> result;
|
1055
|
+
|
1056
|
+
foreach (QByteArray name, methodTypes) {
|
1057
|
+
MocArgument *arg = new MocArgument;
|
1058
|
+
Smoke::Index typeId = 0;
|
1059
|
+
|
1060
|
+
if (name.isEmpty()) {
|
1061
|
+
arg->argType = xmoc_void;
|
1062
|
+
result.append(arg);
|
1063
|
+
} else {
|
1064
|
+
name.replace("const ", "");
|
1065
|
+
QString staticType = (rx->indexIn(name) != -1 ? rx->cap(1) : "ptr");
|
1066
|
+
if (staticType == "ptr") {
|
1067
|
+
arg->argType = xmoc_ptr;
|
1068
|
+
QByteArray targetType = name;
|
1069
|
+
typeId = smoke->idType(targetType.constData());
|
1070
|
+
if (typeId == 0 && !name.contains('*')) {
|
1071
|
+
if (!name.contains("&")) {
|
1072
|
+
targetType += "&";
|
1073
|
+
}
|
1074
|
+
typeId = smoke->idType(targetType.constData());
|
1075
|
+
}
|
1076
|
+
|
1077
|
+
// This shouldn't be necessary because the type of the slot arg should always be in the
|
1078
|
+
// smoke module of the slot being invoked. However, that isn't true for a dataUpdated()
|
1079
|
+
// slot in a PlasmaScripting::Applet
|
1080
|
+
if (typeId == 0) {
|
1081
|
+
QHash<Smoke*, QtRubyModule>::const_iterator it;
|
1082
|
+
for (it = qtruby_modules.constBegin(); it != qtruby_modules.constEnd(); ++it) {
|
1083
|
+
smoke = it.key();
|
1084
|
+
targetType = name;
|
1085
|
+
typeId = smoke->idType(targetType.constData());
|
1086
|
+
if (typeId != 0) {
|
1087
|
+
break;
|
1088
|
+
}
|
1089
|
+
|
1090
|
+
if (typeId == 0 && !name.contains('*')) {
|
1091
|
+
if (!name.contains("&")) {
|
1092
|
+
targetType += "&";
|
1093
|
+
}
|
1094
|
+
|
1095
|
+
typeId = smoke->idType(targetType.constData());
|
1096
|
+
|
1097
|
+
if (typeId != 0) {
|
1098
|
+
break;
|
1099
|
+
}
|
1100
|
+
}
|
1101
|
+
}
|
1102
|
+
}
|
1103
|
+
} else if (staticType == "bool") {
|
1104
|
+
arg->argType = xmoc_bool;
|
1105
|
+
smoke = qtcore_Smoke;
|
1106
|
+
typeId = smoke->idType(name.constData());
|
1107
|
+
} else if (staticType == "int") {
|
1108
|
+
arg->argType = xmoc_int;
|
1109
|
+
smoke = qtcore_Smoke;
|
1110
|
+
typeId = smoke->idType(name.constData());
|
1111
|
+
} else if (staticType == "uint") {
|
1112
|
+
arg->argType = xmoc_uint;
|
1113
|
+
smoke = qtcore_Smoke;
|
1114
|
+
typeId = smoke->idType("unsigned int");
|
1115
|
+
} else if (staticType == "long") {
|
1116
|
+
arg->argType = xmoc_long;
|
1117
|
+
smoke = qtcore_Smoke;
|
1118
|
+
typeId = smoke->idType(name.constData());
|
1119
|
+
} else if (staticType == "ulong") {
|
1120
|
+
arg->argType = xmoc_ulong;
|
1121
|
+
smoke = qtcore_Smoke;
|
1122
|
+
typeId = smoke->idType("unsigned long");
|
1123
|
+
} else if (staticType == "double") {
|
1124
|
+
arg->argType = xmoc_double;
|
1125
|
+
smoke = qtcore_Smoke;
|
1126
|
+
typeId = smoke->idType(name.constData());
|
1127
|
+
} else if (staticType == "char*") {
|
1128
|
+
arg->argType = xmoc_charstar;
|
1129
|
+
smoke = qtcore_Smoke;
|
1130
|
+
typeId = smoke->idType(name.constData());
|
1131
|
+
} else if (staticType == "QString") {
|
1132
|
+
arg->argType = xmoc_QString;
|
1133
|
+
name += "*";
|
1134
|
+
smoke = qtcore_Smoke;
|
1135
|
+
typeId = smoke->idType(name.constData());
|
1136
|
+
}
|
1137
|
+
|
1138
|
+
if (typeId == 0) {
|
1139
|
+
rb_raise(rb_eArgError, "Cannot handle '%s' as slot argument\n", name.constData());
|
1140
|
+
return result;
|
1141
|
+
}
|
1142
|
+
|
1143
|
+
arg->st.set(smoke, typeId);
|
1144
|
+
result.append(arg);
|
1145
|
+
}
|
1146
|
+
}
|
1147
|
+
|
1148
|
+
return result;
|
1149
|
+
}
|
1150
|
+
|
1151
|
+
extern "C"
|
1152
|
+
{
|
1153
|
+
// ---------------- Helpers -------------------
|
1154
|
+
|
1155
|
+
//---------- All functions except fully qualified statics & enums ---------
|
1156
|
+
|
1157
|
+
VALUE
|
1158
|
+
mapObject(VALUE self, VALUE obj)
|
1159
|
+
{
|
1160
|
+
smokeruby_object *o = value_obj_info(obj);
|
1161
|
+
if(!o)
|
1162
|
+
return Qnil;
|
1163
|
+
mapPointer(obj, o, o->classId, 0);
|
1164
|
+
return self;
|
1165
|
+
}
|
1166
|
+
|
1167
|
+
VALUE set_obj_info(const char * className, smokeruby_object * o);
|
1168
|
+
|
1169
|
+
VALUE
|
1170
|
+
qobject_metaobject(VALUE self)
|
1171
|
+
{
|
1172
|
+
smokeruby_object * o = value_obj_info(self);
|
1173
|
+
QObject * qobject = (QObject *) o->smoke->cast(o->ptr, o->classId, o->smoke->idClass("QObject").index);
|
1174
|
+
QMetaObject * meta = (QMetaObject *) qobject->metaObject();
|
1175
|
+
VALUE obj = getPointerObject(meta);
|
1176
|
+
if (obj != Qnil) {
|
1177
|
+
return obj;
|
1178
|
+
}
|
1179
|
+
|
1180
|
+
smokeruby_object * m = alloc_smokeruby_object( false,
|
1181
|
+
o->smoke,
|
1182
|
+
o->smoke->idClass("QMetaObject").index,
|
1183
|
+
meta );
|
1184
|
+
|
1185
|
+
obj = set_obj_info("Qt::MetaObject", m);
|
1186
|
+
return obj;
|
1187
|
+
}
|
1188
|
+
|
1189
|
+
VALUE
|
1190
|
+
set_obj_info(const char * className, smokeruby_object * o)
|
1191
|
+
{
|
1192
|
+
VALUE klass = rb_funcall(qt_internal_module,
|
1193
|
+
rb_intern("find_class"),
|
1194
|
+
1,
|
1195
|
+
rb_str_new2(className) );
|
1196
|
+
if (klass == Qnil) {
|
1197
|
+
rb_raise(rb_eRuntimeError, "Class '%s' not found", className);
|
1198
|
+
}
|
1199
|
+
|
1200
|
+
Smoke::ModuleIndex *r = classcache.value(className);
|
1201
|
+
if (r != 0) {
|
1202
|
+
o->classId = (int) r->index;
|
1203
|
+
}
|
1204
|
+
// If the instance is a subclass of QObject, then check to see if the
|
1205
|
+
// className from its QMetaObject is in the Smoke library. If not then
|
1206
|
+
// create a Ruby class for it dynamically. Remove the first letter from
|
1207
|
+
// any class names beginning with 'Q' or 'K' and put them under the Qt::
|
1208
|
+
// or KDE:: modules respectively.
|
1209
|
+
if (o->smoke->isDerivedFrom(o->smoke, o->classId, o->smoke->idClass("QObject").smoke, o->smoke->idClass("QObject").index)) {
|
1210
|
+
QObject * qobject = (QObject *) o->smoke->cast(o->ptr, o->classId, o->smoke->idClass("QObject").index);
|
1211
|
+
const QMetaObject * meta = qobject->metaObject();
|
1212
|
+
int classId = o->smoke->idClass(meta->className()).index;
|
1213
|
+
// The class isn't in the Smoke lib..
|
1214
|
+
if (classId == 0) {
|
1215
|
+
VALUE new_klass = Qnil;
|
1216
|
+
QByteArray className(meta->className());
|
1217
|
+
|
1218
|
+
if (className == "QTableModel") {
|
1219
|
+
new_klass = qtablemodel_class;
|
1220
|
+
} else if (className == "QListModel") {
|
1221
|
+
new_klass = qlistmodel_class;
|
1222
|
+
} else if (className.startsWith("Q")) {
|
1223
|
+
className.replace("Q", "");
|
1224
|
+
className = className.mid(0, 1).toUpper() + className.mid(1);
|
1225
|
+
new_klass = rb_define_class_under(qt_module, className, klass);
|
1226
|
+
} else {
|
1227
|
+
new_klass = rb_define_class(className, klass);
|
1228
|
+
}
|
1229
|
+
|
1230
|
+
if (new_klass != Qnil) {
|
1231
|
+
klass = new_klass;
|
1232
|
+
|
1233
|
+
for (int id = meta->enumeratorOffset(); id < meta->enumeratorCount(); id++) {
|
1234
|
+
// If there are any enum keys with the same scope as the new class then
|
1235
|
+
// add them
|
1236
|
+
if (qstrcmp(meta->className(), meta->enumerator(id).scope()) == 0) {
|
1237
|
+
for (int i = 0; i < meta->enumerator(id).keyCount(); i++) {
|
1238
|
+
rb_define_const( klass,
|
1239
|
+
meta->enumerator(id).key(i),
|
1240
|
+
INT2NUM(meta->enumerator(id).value(i)) );
|
1241
|
+
}
|
1242
|
+
}
|
1243
|
+
}
|
1244
|
+
}
|
1245
|
+
|
1246
|
+
// Add a Qt::Object.metaObject method which will do dynamic despatch on the
|
1247
|
+
// metaObject() virtual method so that the true QMetaObject of the class
|
1248
|
+
// is returned, rather than for the one for the parent class that is in
|
1249
|
+
// the Smoke library.
|
1250
|
+
rb_define_method(klass, "metaObject", (VALUE (*) (...)) qobject_metaobject, 0);
|
1251
|
+
}
|
1252
|
+
}
|
1253
|
+
|
1254
|
+
VALUE obj = Data_Wrap_Struct(klass, smokeruby_mark, smokeruby_free, (void *) o);
|
1255
|
+
return obj;
|
1256
|
+
}
|
1257
|
+
|
1258
|
+
VALUE
|
1259
|
+
kross2smoke(VALUE /*self*/, VALUE krobject, VALUE new_klass)
|
1260
|
+
{
|
1261
|
+
VALUE new_klassname = rb_funcall(new_klass, rb_intern("name"), 0);
|
1262
|
+
|
1263
|
+
Smoke::ModuleIndex * cast_to_id = classcache.value(StringValuePtr(new_klassname));
|
1264
|
+
if (cast_to_id == 0) {
|
1265
|
+
rb_raise(rb_eArgError, "unable to find class \"%s\" to cast to\n", StringValuePtr(new_klassname));
|
1266
|
+
}
|
1267
|
+
|
1268
|
+
void* o;
|
1269
|
+
Data_Get_Struct(krobject, void, o);
|
1270
|
+
|
1271
|
+
smokeruby_object * o_cast = alloc_smokeruby_object(false, cast_to_id->smoke, (int) cast_to_id->index, o);
|
1272
|
+
|
1273
|
+
VALUE obj = Data_Wrap_Struct(new_klass, smokeruby_mark, smokeruby_free, (void *) o_cast);
|
1274
|
+
mapPointer(obj, o_cast, o_cast->classId, 0);
|
1275
|
+
return obj;
|
1276
|
+
}
|
1277
|
+
|
1278
|
+
const char *
|
1279
|
+
value_to_type_flag(VALUE ruby_value)
|
1280
|
+
{
|
1281
|
+
const char * classname = rb_obj_classname(ruby_value);
|
1282
|
+
const char *r = "";
|
1283
|
+
if (ruby_value == Qnil)
|
1284
|
+
r = "u";
|
1285
|
+
else if (TYPE(ruby_value) == T_FIXNUM || TYPE(ruby_value) == T_BIGNUM || qstrcmp(classname, "Qt::Integer") == 0)
|
1286
|
+
r = "i";
|
1287
|
+
else if (TYPE(ruby_value) == T_FLOAT)
|
1288
|
+
r = "n";
|
1289
|
+
else if (TYPE(ruby_value) == T_STRING)
|
1290
|
+
r = "s";
|
1291
|
+
else if(ruby_value == Qtrue || ruby_value == Qfalse || qstrcmp(classname, "Qt::Boolean") == 0)
|
1292
|
+
r = "B";
|
1293
|
+
else if (qstrcmp(classname, "Qt::Enum") == 0) {
|
1294
|
+
VALUE temp = rb_funcall(qt_internal_module, rb_intern("get_qenum_type"), 1, ruby_value);
|
1295
|
+
r = StringValuePtr(temp);
|
1296
|
+
} else if (TYPE(ruby_value) == T_DATA) {
|
1297
|
+
smokeruby_object *o = value_obj_info(ruby_value);
|
1298
|
+
if (o == 0 || o->smoke == 0) {
|
1299
|
+
r = "a";
|
1300
|
+
} else {
|
1301
|
+
r = o->smoke->classes[o->classId].className;
|
1302
|
+
}
|
1303
|
+
} else {
|
1304
|
+
r = "U";
|
1305
|
+
}
|
1306
|
+
|
1307
|
+
return r;
|
1308
|
+
}
|
1309
|
+
|
1310
|
+
VALUE prettyPrintMethod(Smoke::Index id)
|
1311
|
+
{
|
1312
|
+
VALUE r = rb_str_new2("");
|
1313
|
+
const Smoke::Method &meth = qtcore_Smoke->methods[id];
|
1314
|
+
const char *tname = qtcore_Smoke->types[meth.ret].name;
|
1315
|
+
if(meth.flags & Smoke::mf_static) rb_str_catf(r, "static ");
|
1316
|
+
rb_str_catf(r, "%s ", (tname ? tname:"void"));
|
1317
|
+
rb_str_catf(r, "%s::%s(", qtcore_Smoke->classes[meth.classId].className, qtcore_Smoke->methodNames[meth.name]);
|
1318
|
+
for(int i = 0; i < meth.numArgs; i++) {
|
1319
|
+
if(i) rb_str_catf(r, ", ");
|
1320
|
+
tname = qtcore_Smoke->types[qtcore_Smoke->argumentList[meth.args+i]].name;
|
1321
|
+
rb_str_catf(r, "%s", (tname ? tname:"void"));
|
1322
|
+
}
|
1323
|
+
rb_str_catf(r, ")");
|
1324
|
+
if(meth.flags & Smoke::mf_const) rb_str_catf(r, " const");
|
1325
|
+
return r;
|
1326
|
+
}
|
1327
|
+
}
|