##// END OF EJS Templates
added automatic conversion to QColor,QPen,QCursor and QBrush from enums and colors...
florianlink -
r64:3ef1598f6c5e
parent child
Show More
@@ -1,822 +1,826
1 1 /*
2 2 *
3 3 * Copyright (C) 2006 MeVis Research GmbH All Rights Reserved.
4 4 *
5 5 * This library is free software; you can redistribute it and/or
6 6 * modify it under the terms of the GNU Lesser General Public
7 7 * License as published by the Free Software Foundation; either
8 8 * version 2.1 of the License, or (at your option) any later version.
9 9 *
10 10 * This library is distributed in the hope that it will be useful,
11 11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13 13 * Lesser General Public License for more details.
14 14 *
15 15 * Further, this software is distributed without any warranty that it is
16 16 * free of the rightful claim of any third person regarding infringement
17 17 * or the like. Any license provided herein, whether implied or
18 18 * otherwise, applies only to this software file. Patent licenses, if
19 19 * any, provided herein do not apply to combinations of this program with
20 20 * other software, or any other product whatsoever.
21 21 *
22 22 * You should have received a copy of the GNU Lesser General Public
23 23 * License along with this library; if not, write to the Free Software
24 24 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
25 25 *
26 26 * Contact information: MeVis Research GmbH, Universitaetsallee 29,
27 27 * 28359 Bremen, Germany or:
28 28 *
29 29 * http://www.mevis.de
30 30 *
31 31 */
32 32
33 33 //----------------------------------------------------------------------------------
34 34 /*!
35 35 // \file PythonQt.cpp
36 36 // \author Florian Link
37 37 // \author Last changed by $Author: florian $
38 38 // \date 2006-05
39 39 */
40 40 //----------------------------------------------------------------------------------
41 41
42 42 #include "PythonQtClassInfo.h"
43 43 #include "PythonQtMethodInfo.h"
44 44 #include "PythonQt.h"
45 45 #include <QMetaMethod>
46 46 #include <QMetaObject>
47 47 #include <QMetaEnum>
48 48
49 49 QHash<QByteArray, int> PythonQtMethodInfo::_parameterTypeDict;
50 50
51 51 PythonQtClassInfo::PythonQtClassInfo() {
52 52 _meta = NULL;
53 53 _constructors = NULL;
54 54 _destructor = NULL;
55 55 _decoratorProvider = NULL;
56 56 _decoratorProviderCB = NULL;
57 57 _pythonQtClassWrapper = NULL;
58 58 _shellSetInstanceWrapperCB = NULL;
59 59 _metaTypeId = -1;
60 60 _isQObject = false;
61 61 _enumsCreated = false;
62 62 }
63 63
64 64 PythonQtClassInfo::~PythonQtClassInfo()
65 65 {
66 66 clearCachedMembers();
67 67
68 68 if (_constructors) {
69 69 _constructors->deleteOverloadsAndThis();
70 70 }
71 71 if (_destructor) {
72 72 _destructor->deleteOverloadsAndThis();
73 73 }
74 74 foreach(PythonQtSlotInfo* info, _decoratorSlots) {
75 75 info->deleteOverloadsAndThis();
76 76 }
77 77 }
78 78
79 79 void PythonQtClassInfo::setupQObject(const QMetaObject* meta)
80 80 {
81 81 // _wrappedClassName is already set earlier in the class setup
82 82 _isQObject = true;
83 83 _meta = meta;
84 84 }
85 85
86 86 void PythonQtClassInfo::setupCPPObject(const QByteArray& classname)
87 87 {
88 88 _isQObject = false;
89 89 _wrappedClassName = classname;
90 90 _metaTypeId = QMetaType::type(classname);
91 91 }
92 92
93 93 void PythonQtClassInfo::clearCachedMembers()
94 94 {
95 95 QHashIterator<QByteArray, PythonQtMemberInfo> i(_cachedMembers);
96 96 while (i.hasNext()) {
97 97 PythonQtMemberInfo member = i.next().value();
98 98 if (member._type== PythonQtMemberInfo::Slot) {
99 99 PythonQtSlotInfo* info = member._slot;
100 100 while (info) {
101 101 PythonQtSlotInfo* next = info->nextInfo();
102 102 delete info;
103 103 info = next;
104 104 }
105 105 }
106 106 }
107 107 }
108 108
109 109 int PythonQtClassInfo::findCharOffset(const char* sigStart, char someChar)
110 110 {
111 111 const char* sigEnd = sigStart;
112 112 char c;
113 113 do {
114 114 c = *sigEnd++;
115 115 } while (c!=someChar && c!=0);
116 116 return sigEnd-sigStart-1;
117 117 }
118 118
119 119 bool PythonQtClassInfo::lookForPropertyAndCache(const char* memberName)
120 120 {
121 121 bool found = false;
122 122 bool nameMapped = false;
123 123 const char* attributeName = memberName;
124 124 // look for properties
125 125 int i = _meta->indexOfProperty(attributeName);
126 126 if (i==-1) {
127 127 // try to map name to objectName
128 128 if (qstrcmp(attributeName, "name")==0) {
129 129 attributeName = "objectName";
130 130 nameMapped = true;
131 131 i = _meta->indexOfProperty(attributeName);
132 132 }
133 133 }
134 134 if (i!=-1) {
135 135 PythonQtMemberInfo newInfo(_meta->property(i));
136 136 _cachedMembers.insert(attributeName, newInfo);
137 137 if (nameMapped) {
138 138 _cachedMembers.insert(memberName, newInfo);
139 139 }
140 140 #ifdef PYTHONQT_DEBUG
141 141 std::cout << "caching property " << memberName << " on " << _meta->className() << std::endl;
142 142 #endif
143 143 found = true;
144 144 }
145 145 return found;
146 146 }
147 147
148 148 PythonQtSlotInfo* PythonQtClassInfo::recursiveFindDecoratorSlotsFromDecoratorProvider(const char* memberName, PythonQtSlotInfo* inputInfo, bool &found, QHash<QByteArray, PythonQtMemberInfo>& memberCache, int upcastingOffset)
149 149 {
150 150 inputInfo = findDecoratorSlotsFromDecoratorProvider(memberName, inputInfo, found, memberCache, upcastingOffset);
151 151 foreach(const ParentClassInfo& info, _parentClasses) {
152 152 inputInfo = info._parent->recursiveFindDecoratorSlotsFromDecoratorProvider(memberName, inputInfo, found, memberCache, upcastingOffset+info._upcastingOffset);
153 153 }
154 154 return inputInfo;
155 155 }
156 156
157 157 PythonQtSlotInfo* PythonQtClassInfo::findDecoratorSlotsFromDecoratorProvider(const char* memberName, PythonQtSlotInfo* tail, bool &found, QHash<QByteArray, PythonQtMemberInfo>& memberCache, int upcastingOffset) {
158 158 QObject* decoratorProvider = decorator();
159 159 int memberNameLen = strlen(memberName);
160 160 if (decoratorProvider) {
161 161 //qDebug()<< "looking " << decoratorProvider->metaObject()->className() << " " << memberName << " " << upcastingOffset;
162 162 const QMetaObject* meta = decoratorProvider->metaObject();
163 163 int numMethods = meta->methodCount();
164 164 int startFrom = QObject::staticMetaObject.methodCount();
165 165 for (int i = startFrom; i < numMethods; i++) {
166 166 QMetaMethod m = meta->method(i);
167 167 if ((m.methodType() == QMetaMethod::Method ||
168 168 m.methodType() == QMetaMethod::Slot) && m.access() == QMetaMethod::Public) {
169 169
170 170 const char* sigStart = m.signature();
171 171 bool isClassDeco = false;
172 172 if (qstrncmp(sigStart, "static_", 7)==0) {
173 173 // skip the static_classname_ part of the string
174 174 sigStart += 7 + 1 + strlen(className());
175 175 isClassDeco = true;
176 176 } else if (qstrncmp(sigStart, "new_", 4)==0) {
177 177 isClassDeco = true;
178 178 } else if (qstrncmp(sigStart, "delete_", 7)==0) {
179 179 isClassDeco = true;
180 180 }
181 181 // find the first '('
182 182 int offset = findCharOffset(sigStart, '(');
183 183
184 184 // XXX no checking is currently done if the slots have correct first argument or not...
185 185
186 186 // check if same length and same name
187 187 if (memberNameLen == offset && qstrncmp(memberName, sigStart, offset)==0) {
188 188 found = true;
189 189 PythonQtSlotInfo* info = new PythonQtSlotInfo(this, m, i, decoratorProvider, isClassDeco?PythonQtSlotInfo::ClassDecorator:PythonQtSlotInfo::InstanceDecorator);
190 190 info->setUpcastingOffset(upcastingOffset);
191 191 //qDebug()<< "adding " << decoratorProvider->metaObject()->className() << " " << memberName << " " << upcastingOffset;
192 192 if (tail) {
193 193 tail->setNextInfo(info);
194 194 } else {
195 195 PythonQtMemberInfo newInfo(info);
196 196 memberCache.insert(memberName, newInfo);
197 197 }
198 198 tail = info;
199 199 }
200 200 }
201 201 }
202 202 }
203 203
204 204 tail = findDecoratorSlots(memberName, memberNameLen, tail, found, memberCache, upcastingOffset);
205 205
206 206 return tail;
207 207 }
208 208
209 209 bool PythonQtClassInfo::lookForMethodAndCache(const char* memberName)
210 210 {
211 211 bool found = false;
212 212 int memberNameLen = strlen(memberName);
213 213 PythonQtSlotInfo* tail = NULL;
214 214 if (_meta) {
215 215 int numMethods = _meta->methodCount();
216 216 for (int i = 0; i < numMethods; i++) {
217 217 QMetaMethod m = _meta->method(i);
218 218 if ((m.methodType() == QMetaMethod::Method ||
219 219 m.methodType() == QMetaMethod::Slot) && m.access() == QMetaMethod::Public) {
220 220
221 221 const char* sigStart = m.signature();
222 222 // find the first '('
223 223 int offset = findCharOffset(sigStart, '(');
224 224
225 225 // check if same length and same name
226 226 if (memberNameLen == offset && qstrncmp(memberName, sigStart, offset)==0) {
227 227 found = true;
228 228 PythonQtSlotInfo* info = new PythonQtSlotInfo(this, m, i);
229 229 if (tail) {
230 230 tail->setNextInfo(info);
231 231 } else {
232 232 PythonQtMemberInfo newInfo(info);
233 233 _cachedMembers.insert(memberName, newInfo);
234 234 }
235 235 tail = info;
236 236 }
237 237 }
238 238 }
239 239 }
240 240
241 241 // look for dynamic decorators in this class and in derived classes
242 242 tail = recursiveFindDecoratorSlotsFromDecoratorProvider(memberName, tail, found, _cachedMembers, 0);
243 243
244 244 return found;
245 245 }
246 246
247 247 bool PythonQtClassInfo::lookForEnumAndCache(const QMetaObject* meta, const char* memberName)
248 248 {
249 249 bool found = false;
250 250 // look for enum values
251 251 int enumCount = meta->enumeratorCount();
252 252 for (int i=0;i<enumCount; i++) {
253 253 QMetaEnum e = meta->enumerator(i);
254 254 // we do not want flags, they will cause our values to appear two times
255 255 if (e.isFlag()) continue;
256 256
257 257 for (int j=0; j < e.keyCount(); j++) {
258 258 if (qstrcmp(e.key(j), memberName)==0) {
259 259 PyObject* enumType = findEnumWrapper(e.name());
260 260 if (enumType) {
261 261 PythonQtObjectPtr enumValuePtr;
262 262 enumValuePtr.setNewRef(PythonQtPrivate::createEnumValueInstance(enumType, e.value(j)));
263 263 PythonQtMemberInfo newInfo(enumValuePtr);
264 264 _cachedMembers.insert(memberName, newInfo);
265 265 #ifdef PYTHONQT_DEBUG
266 266 std::cout << "caching enum " << memberName << " on " << meta->className() << std::endl;
267 267 #endif
268 268 found = true;
269 269 break;
270 270 } else {
271 271 std::cout << "enum " << e.name() << " not found on " << className() << std::endl;
272 272 }
273 273 }
274 274 }
275 275 }
276 276 return found;
277 277 }
278 278
279 279 PythonQtMemberInfo PythonQtClassInfo::member(const char* memberName)
280 280 {
281 281 PythonQtMemberInfo info = _cachedMembers.value(memberName);
282 282 if (info._type != PythonQtMemberInfo::Invalid) {
283 283 return info;
284 284 } else {
285 285 bool found = false;
286 286
287 287 found = lookForPropertyAndCache(memberName);
288 288 if (!found) {
289 289 found = lookForMethodAndCache(memberName);
290 290 }
291 291 if (!found) {
292 292 if (_meta) {
293 293 // check enums in our meta object directly
294 294 found = lookForEnumAndCache(_meta, memberName);
295 295 }
296 296 if (!found) {
297 297 // check enums in the class hierachy of CPP classes
298 298 // look for dynamic decorators in this class and in derived classes
299 299 QList<QObject*> decoObjects;
300 300 recursiveCollectDecoratorObjects(decoObjects);
301 301 foreach(QObject* deco, decoObjects) {
302 302 // call on ourself for caching, but with different metaObject():
303 303 found = lookForEnumAndCache(deco->metaObject(), memberName);
304 304 if (found) {
305 305 break;
306 306 }
307 307 }
308 308 }
309 309 }
310 310 if (!found) {
311 311 PyObject* p = findEnumWrapper(memberName);
312 312 if (p) {
313 313 info._type = PythonQtMemberInfo::EnumWrapper;
314 314 info._enumWrapper = p;
315 315 _cachedMembers.insert(memberName, info);
316 316 found = true;
317 317 }
318 318 }
319 319 if (!found) {
320 320 // we store a NotFound member, so that we get a quick result for non existing members (e.g. operator_equal lookup)
321 321 info._type = PythonQtMemberInfo::NotFound;
322 322 _cachedMembers.insert(memberName, info);
323 323 }
324 324 }
325 325
326 326 return _cachedMembers.value(memberName);
327 327 }
328 328
329 329 void PythonQtClassInfo::recursiveCollectDecoratorObjects(QList<QObject*>& decoratorObjects) {
330 330 QObject* deco = decorator();
331 331 if (deco) {
332 332 decoratorObjects.append(deco);
333 333 }
334 334 foreach(const ParentClassInfo& info, _parentClasses) {
335 335 info._parent->recursiveCollectDecoratorObjects(decoratorObjects);
336 336 }
337 337 }
338 338
339 339 void PythonQtClassInfo::recursiveCollectClassInfos(QList<PythonQtClassInfo*>& classInfoObjects) {
340 340 classInfoObjects.append(this);
341 341 foreach(const ParentClassInfo& info, _parentClasses) {
342 342 info._parent->recursiveCollectClassInfos(classInfoObjects);
343 343 }
344 344 }
345 345
346 346 PythonQtSlotInfo* PythonQtClassInfo::findDecoratorSlots(const char* memberName, int memberNameLen, PythonQtSlotInfo* tail, bool &found, QHash<QByteArray, PythonQtMemberInfo>& memberCache, int upcastingOffset)
347 347 {
348 348 QListIterator<PythonQtSlotInfo*> it(_decoratorSlots);
349 349 while (it.hasNext()) {
350 350
351 351 PythonQtSlotInfo* infoOrig = it.next();
352 352
353 353 const char* sigStart = infoOrig->metaMethod()->signature();
354 354 if (qstrncmp("static_", sigStart, 7)==0) {
355 355 sigStart += 7;
356 356 sigStart += findCharOffset(sigStart, '_')+1;
357 357 }
358 358 int offset = findCharOffset(sigStart, '(');
359 359 if (memberNameLen == offset && qstrncmp(memberName, sigStart, offset)==0) {
360 360 //make a copy, otherwise we will have trouble on overloads!
361 361 PythonQtSlotInfo* info = new PythonQtSlotInfo(*infoOrig);
362 362 info->setUpcastingOffset(upcastingOffset);
363 363 found = true;
364 364 if (tail) {
365 365 tail->setNextInfo(info);
366 366 } else {
367 367 PythonQtMemberInfo newInfo(info);
368 368 memberCache.insert(memberName, newInfo);
369 369 }
370 370 tail = info;
371 371 }
372 372 }
373 373 return tail;
374 374 }
375 375
376 376 void PythonQtClassInfo::listDecoratorSlotsFromDecoratorProvider(QStringList& list, bool metaOnly) {
377 377 QObject* decoratorProvider = decorator();
378 378 if (decoratorProvider) {
379 379 const QMetaObject* meta = decoratorProvider->metaObject();
380 380 int numMethods = meta->methodCount();
381 381 int startFrom = QObject::staticMetaObject.methodCount();
382 382 for (int i = startFrom; i < numMethods; i++) {
383 383 QMetaMethod m = meta->method(i);
384 384 if ((m.methodType() == QMetaMethod::Method ||
385 385 m.methodType() == QMetaMethod::Slot) && m.access() == QMetaMethod::Public) {
386 386
387 387 const char* sigStart = m.signature();
388 388 bool isClassDeco = false;
389 389 if (qstrncmp(sigStart, "static_", 7)==0) {
390 390 // skip the static_classname_ part of the string
391 391 sigStart += 7 + 1 + strlen(className());
392 392 isClassDeco = true;
393 393 } else if (qstrncmp(sigStart, "new_", 4)==0) {
394 394 continue;
395 395 } else if (qstrncmp(sigStart, "delete_", 7)==0) {
396 396 continue;
397 397 }
398 398 // find the first '('
399 399 int offset = findCharOffset(sigStart, '(');
400 400
401 401 // XXX no checking is currently done if the slots have correct first argument or not...
402 402 if (!metaOnly || isClassDeco) {
403 403 list << QString::fromLatin1(sigStart, offset);
404 404 }
405 405 }
406 406 }
407 407 }
408 408
409 409 // look for global decorator slots
410 410 QListIterator<PythonQtSlotInfo*> it(_decoratorSlots);
411 411 while (it.hasNext()) {
412 412 PythonQtSlotInfo* slot = it.next();
413 413 if (metaOnly) {
414 414 if (slot->isClassDecorator()) {
415 415 QByteArray first = slot->slotName();
416 416 if (first.startsWith("static_")) {
417 417 int idx = first.indexOf('_');
418 418 idx = first.indexOf('_', idx+1);
419 419 first = first.mid(idx+1);
420 420 }
421 421 list << first;
422 422 }
423 423 } else {
424 424 list << slot->slotName();
425 425 }
426 426 }
427 427 }
428 428
429 429 QStringList PythonQtClassInfo::propertyList()
430 430 {
431 431 QStringList l;
432 432 if (_isQObject && _meta) {
433 433 int i;
434 434 int numProperties = _meta->propertyCount();
435 435 for (i = 0; i < numProperties; i++) {
436 436 QMetaProperty p = _meta->property(i);
437 437 l << QString(p.name());
438 438 }
439 439 }
440 440 return l;
441 441 }
442 442
443 443 QStringList PythonQtClassInfo::memberList(bool metaOnly)
444 444 {
445 445 decorator();
446 446
447 447 QStringList l;
448 448 QString h;
449 449 if (_isQObject && _meta && !metaOnly) {
450 450 l = propertyList();
451 451 }
452 452
453 453 // normal slots of QObject (or wrapper QObject)
454 454 if (!metaOnly && _meta) {
455 455 int numMethods = _meta->methodCount();
456 456 bool skipQObj = !_isQObject;
457 457 for (int i = skipQObj?QObject::staticMetaObject.methodCount():0; i < numMethods; i++) {
458 458 QMetaMethod m = _meta->method(i);
459 459 if ((m.methodType() == QMetaMethod::Method ||
460 460 m.methodType() == QMetaMethod::Slot) && m.access() == QMetaMethod::Public) {
461 461 QByteArray signa(m.signature());
462 462 signa = signa.left(signa.indexOf('('));
463 463 l << signa;
464 464 }
465 465 }
466 466 }
467 467
468 468 {
469 469 // look for dynamic decorators in this class and in derived classes
470 470 QList<PythonQtClassInfo*> infos;
471 471 recursiveCollectClassInfos(infos);
472 472 foreach(PythonQtClassInfo* info, infos) {
473 473 info->listDecoratorSlotsFromDecoratorProvider(l, metaOnly);
474 474 }
475 475 }
476 476
477 477 // List enumerator keys...
478 478 QList<const QMetaObject*> enumMetaObjects;
479 479 if (_meta) {
480 480 enumMetaObjects << _meta;
481 481 }
482 482 // check enums in the class hierachy of CPP classes
483 483 QList<QObject*> decoObjects;
484 484 recursiveCollectDecoratorObjects(decoObjects);
485 485 foreach(QObject* deco, decoObjects) {
486 486 enumMetaObjects << deco->metaObject();
487 487 }
488 488
489 489 foreach(const QMetaObject* meta, enumMetaObjects) {
490 490 for (int i = 0; i<meta->enumeratorCount(); i++) {
491 491 QMetaEnum e = meta->enumerator(i);
492 492 l << e.name();
493 493 // we do not want flags, they will cause our values to appear two times
494 494 if (e.isFlag()) continue;
495 495
496 496 for (int j=0; j < e.keyCount(); j++) {
497 497 l << QString(e.key(j));
498 498 }
499 499 }
500 500 }
501 501
502 502 return QSet<QString>::fromList(l).toList();
503 503 }
504 504
505 505 const char* PythonQtClassInfo::className()
506 506 {
507 507 return _wrappedClassName.constData();
508 508 }
509 509
510 510 void* PythonQtClassInfo::castTo(void* ptr, const char* classname)
511 511 {
512 512 if (ptr==NULL) {
513 513 return NULL;
514 514 }
515 515 if (_wrappedClassName == classname) {
516 516 return ptr;
517 517 }
518 518 foreach(const ParentClassInfo& info, _parentClasses) {
519 519 void* result = info._parent->castTo((char*)ptr + info._upcastingOffset, classname);
520 520 if (result) {
521 521 return result;
522 522 }
523 523 }
524 524 return NULL;
525 525 }
526 526
527 527 bool PythonQtClassInfo::inherits(const char* name)
528 528 {
529 529 if (_wrappedClassName == name) {
530 530 return true;
531 531 }
532 532 foreach(const ParentClassInfo& info, _parentClasses) {
533 533 if (info._parent->inherits(name)) {
534 534 return true;
535 535 }
536 536 }
537 537 return false;
538 538 }
539 539
540 540 bool PythonQtClassInfo::inherits(PythonQtClassInfo* classInfo)
541 541 {
542 542 if (classInfo == this) {
543 543 return true;
544 544 }
545 545 foreach(const ParentClassInfo& info, _parentClasses) {
546 546 if (info._parent->inherits(classInfo)) {
547 547 return true;
548 548 }
549 549 }
550 550 return false;
551 551 }
552 552
553 553 QString PythonQtClassInfo::help()
554 554 {
555 555 decorator();
556 556 QString h;
557 557 h += QString("--- ") + QString(className()) + QString(" ---\n");
558 558
559 559 if (_isQObject) {
560 560 h += "Properties:\n";
561 561
562 562 int i;
563 563 int numProperties = _meta->propertyCount();
564 564 for (i = 0; i < numProperties; i++) {
565 565 QMetaProperty p = _meta->property(i);
566 566 h += QString(p.name()) + " (" + QString(p.typeName()) + " )\n";
567 567 }
568 568 }
569 569
570 570 if (constructors()) {
571 571 h += "Constructors:\n";
572 572 PythonQtSlotInfo* constr = constructors();
573 573 while (constr) {
574 574 h += constr->fullSignature() + "\n";
575 575 constr = constr->nextInfo();
576 576 }
577 577 }
578 578
579 579 h += "Slots:\n";
580 580 h += "QString help()\n";
581 581 h += "QString className()\n";
582 582
583 583 if (_meta) {
584 584 int numMethods = _meta->methodCount();
585 585 for (int i = 0; i < numMethods; i++) {
586 586 QMetaMethod m = _meta->method(i);
587 587 if ((m.methodType() == QMetaMethod::Method ||
588 588 m.methodType() == QMetaMethod::Slot) && m.access() == QMetaMethod::Public) {
589 589 PythonQtSlotInfo slot(this, m, i);
590 590 h += slot.fullSignature()+ "\n";
591 591 }
592 592 }
593 593 }
594 594
595 595 // TODO xxx : decorators and enums from decorator() are missing...
596 596 // maybe we can reuse memberlist()?
597 597
598 598 if (_meta && _meta->enumeratorCount()) {
599 599 h += "Enums:\n";
600 600 for (int i = 0; i<_meta->enumeratorCount(); i++) {
601 601 QMetaEnum e = _meta->enumerator(i);
602 602 h += QString(e.name()) + " {";
603 603 for (int j=0; j < e.keyCount(); j++) {
604 604 if (j) { h+= ", "; }
605 605 h += e.key(j);
606 606 }
607 607 h += " }\n";
608 608 }
609 609 }
610 610
611 611 if (_isQObject && _meta) {
612 612 int numMethods = _meta->methodCount();
613 613 if (numMethods>0) {
614 614 h += "Signals:\n";
615 615 for (int i = 0; i < numMethods; i++) {
616 616 QMetaMethod m = _meta->method(i);
617 617 if (m.methodType() == QMetaMethod::Signal) {
618 618 h += QString(m.signature()) + "\n";
619 619 }
620 620 }
621 621 }
622 622 }
623 623 return h;
624 624 }
625 625
626 626 PythonQtSlotInfo* PythonQtClassInfo::constructors()
627 627 {
628 628 if (!_constructors) {
629 629 // force creation of lazy decorator, which will register the decorators
630 630 decorator();
631 631 }
632 632 return _constructors;
633 633 }
634 634
635 635 PythonQtSlotInfo* PythonQtClassInfo::destructor()
636 636 {
637 637 if (!_destructor) {
638 638 // force creation of lazy decorator, which will register the decorators
639 639 decorator();
640 640 }
641 641 return _destructor;
642 642 }
643 643
644 644 void PythonQtClassInfo::addConstructor(PythonQtSlotInfo* info)
645 645 {
646 646 PythonQtSlotInfo* prev = constructors();
647 647 if (prev) {
648 648 info->setNextInfo(prev->nextInfo());
649 649 prev->setNextInfo(info);
650 650 } else {
651 651 _constructors = info;
652 652 }
653 653 }
654 654
655 655 void PythonQtClassInfo::addDecoratorSlot(PythonQtSlotInfo* info)
656 656 {
657 657 _decoratorSlots.append(info);
658 658 }
659 659
660 660 void PythonQtClassInfo::setDestructor(PythonQtSlotInfo* info)
661 661 {
662 662 if (_destructor) {
663 663 _destructor->deleteOverloadsAndThis();
664 664 }
665 665 _destructor = info;
666 666 }
667 667
668 668 void PythonQtClassInfo::setMetaObject(const QMetaObject* meta)
669 669 {
670 670 _meta = meta;
671 671 clearCachedMembers();
672 672 }
673 673
674 674 QObject* PythonQtClassInfo::decorator()
675 675 {
676 676 if (!_decoratorProvider && _decoratorProviderCB) {
677 677 _decoratorProvider = (*_decoratorProviderCB)();
678 678 if (_decoratorProvider) {
679 679 _decoratorProvider->setParent(PythonQt::priv());
680 680 // setup enums early, since they might be needed by the constructor decorators:
681 681 if (!_enumsCreated) {
682 682 createEnumWrappers();
683 683 }
684 684 PythonQt::priv()->addDecorators(_decoratorProvider, PythonQtPrivate::ConstructorDecorator | PythonQtPrivate::DestructorDecorator);
685 685 }
686 686 }
687 687 // check if enums need to be created and create them if they are not yet created
688 688 if (!_enumsCreated) {
689 689 createEnumWrappers();
690 690 }
691 691 return _decoratorProvider;
692 692 }
693 693
694 694 bool PythonQtClassInfo::hasOwnerMethodButNoOwner(void* object)
695 695 {
696 696 PythonQtMemberInfo info = member("hasOwner");
697 697 if (info._type == PythonQtMemberInfo::Slot) {
698 698 void* obj = object;
699 699 bool result = false;
700 700 void* args[2];
701 701 args[0] = &result;
702 702 args[1] = &obj;
703 703 info._slot->decorator()->qt_metacall(QMetaObject::InvokeMetaMethod, info._slot->slotIndex(), args);
704 704 return !result;
705 705 } else {
706 706 return false;
707 707 }
708 708 }
709 709
710 710 void* PythonQtClassInfo::recursiveCastDownIfPossible(void* ptr, char** resultClassName)
711 711 {
712 712 if (!_polymorphicHandlers.isEmpty()) {
713 713 foreach(PythonQtPolymorphicHandlerCB* cb, _polymorphicHandlers) {
714 714 void* resultPtr = (*cb)(ptr, resultClassName);
715 715 if (resultPtr) {
716 716 return resultPtr;
717 717 }
718 718 }
719 719 }
720 720 foreach(const ParentClassInfo& info, _parentClasses) {
721 721 if (!info._parent->isQObject()) {
722 722 void* resultPtr = info._parent->recursiveCastDownIfPossible((char*)ptr + info._upcastingOffset, resultClassName);
723 723 if (resultPtr) {
724 724 return resultPtr;
725 725 }
726 726 }
727 727 }
728 728 return NULL;
729 729 }
730 730
731 731 void* PythonQtClassInfo::castDownIfPossible(void* ptr, PythonQtClassInfo** resultClassInfo)
732 732 {
733 733 char* className;
734 734 // this would do downcasting recursively...
735 735 // void* resultPtr = recursiveCastDownIfPossible(ptr, &className);
736 736
737 737 // we only do downcasting on the base object, not on the whole inheritance tree...
738 738 void* resultPtr = NULL;
739 739 if (!_polymorphicHandlers.isEmpty()) {
740 740 foreach(PythonQtPolymorphicHandlerCB* cb, _polymorphicHandlers) {
741 741 resultPtr = (*cb)(ptr, &className);
742 742 if (resultPtr) {
743 743 break;
744 744 }
745 745 }
746 746 }
747 747 if (resultPtr) {
748 748 *resultClassInfo = PythonQt::priv()->getClassInfo(className);
749 749 } else {
750 750 *resultClassInfo = this;
751 751 resultPtr = ptr;
752 752 }
753 753 return resultPtr;
754 754 }
755 755
756 PyObject* PythonQtClassInfo::findEnumWrapper(const QByteArray& name, PythonQtClassInfo* localScope, bool& isLocalEnum)
756 PyObject* PythonQtClassInfo::findEnumWrapper(const QByteArray& name, PythonQtClassInfo* localScope, bool* isLocalEnum)
757 757 {
758 isLocalEnum = true;
758 if (isLocalEnum) {
759 *isLocalEnum = true;
760 }
759 761 int scopePos = name.lastIndexOf("::");
760 762 if (scopePos != -1) {
761 isLocalEnum = false;
762 // slit into scope and enum name
763 if (isLocalEnum) {
764 *isLocalEnum = false;
765 }
766 // split into scope and enum name
763 767 QByteArray enumScope = name.mid(0,scopePos);
764 768 QByteArray enumName = name.mid(scopePos+2);
765 769 PythonQtClassInfo* info = PythonQt::priv()->getClassInfo(enumScope);
766 770 if (info) {
767 771 return info->findEnumWrapper(enumName);
768 772 } else{
769 773 return NULL;
770 774 }
771 775 }
772 776 if (localScope) {
773 777 return localScope->findEnumWrapper(name);
774 778 } else {
775 779 return NULL;
776 780 }
777 781 }
778 782
779 783 void PythonQtClassInfo::createEnumWrappers(const QMetaObject* meta)
780 784 {
781 785 for (int i = meta->enumeratorOffset();i<meta->enumeratorCount();i++) {
782 786 QMetaEnum e = meta->enumerator(i);
783 787 PythonQtObjectPtr p;
784 788 p.setNewRef(PythonQtPrivate::createNewPythonQtEnumWrapper(e.name(), _pythonQtClassWrapper));
785 789 _enumWrappers.append(p);
786 790 }
787 791 }
788 792
789 793 void PythonQtClassInfo::createEnumWrappers()
790 794 {
791 795 if (!_enumsCreated) {
792 796 _enumsCreated = true;
793 797 if (_meta) {
794 798 createEnumWrappers(_meta);
795 799 }
796 800 if (decorator()) {
797 801 createEnumWrappers(decorator()->metaObject());
798 802 }
799 803 foreach(const ParentClassInfo& info, _parentClasses) {
800 804 info._parent->createEnumWrappers();
801 805 }
802 806 }
803 807 }
804 808
805 809 PyObject* PythonQtClassInfo::findEnumWrapper(const char* name) {
806 810 // force enum creation
807 811 if (!_enumsCreated) {
808 812 createEnumWrappers();
809 813 }
810 814 foreach(const PythonQtObjectPtr& p, _enumWrappers) {
811 815 const char* className = ((PyTypeObject*)p.object())->tp_name;
812 816 if (qstrcmp(className, name)==0) {
813 817 return p.object();
814 818 }
815 819 }
816 820 foreach(const ParentClassInfo& info, _parentClasses) {
817 821 PyObject* p = info._parent->findEnumWrapper(name);
818 822 if (p) return p;
819 823 }
820 824 return NULL;
821 825 }
822 826
@@ -1,256 +1,256
1 1 #ifndef _PYTHONQTCLASSINFO_H
2 2 #define _PYTHONQTCLASSINFO_H
3 3
4 4 /*
5 5 *
6 6 * Copyright (C) 2006 MeVis Research GmbH All Rights Reserved.
7 7 *
8 8 * This library is free software; you can redistribute it and/or
9 9 * modify it under the terms of the GNU Lesser General Public
10 10 * License as published by the Free Software Foundation; either
11 11 * version 2.1 of the License, or (at your option) any later version.
12 12 *
13 13 * This library is distributed in the hope that it will be useful,
14 14 * but WITHOUT ANY WARRANTY; without even the implied warranty of
15 15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
16 16 * Lesser General Public License for more details.
17 17 *
18 18 * Further, this software is distributed without any warranty that it is
19 19 * free of the rightful claim of any third person regarding infringement
20 20 * or the like. Any license provided herein, whether implied or
21 21 * otherwise, applies only to this software file. Patent licenses, if
22 22 * any, provided herein do not apply to combinations of this program with
23 23 * other software, or any other product whatsoever.
24 24 *
25 25 * You should have received a copy of the GNU Lesser General Public
26 26 * License along with this library; if not, write to the Free Software
27 27 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
28 28 *
29 29 * Contact information: MeVis Research GmbH, Universitaetsallee 29,
30 30 * 28359 Bremen, Germany or:
31 31 *
32 32 * http://www.mevis.de
33 33 *
34 34 */
35 35
36 36 #include <QMetaObject>
37 37 #include <QMetaMethod>
38 38 #include <QHash>
39 39 #include <QByteArray>
40 40 #include <QList>
41 41 #include "PythonQt.h"
42 42
43 43 class PythonQtSlotInfo;
44 44
45 45 struct PythonQtMemberInfo {
46 46 enum Type {
47 47 Invalid, Slot, EnumValue, EnumWrapper, Property, NotFound
48 48 };
49 49
50 50 PythonQtMemberInfo():_type(Invalid),_slot(NULL),_enumWrapper(NULL),_enumValue(0) { }
51 51
52 52 PythonQtMemberInfo(PythonQtSlotInfo* info) {
53 53 _type = Slot;
54 54 _slot = info;
55 55 _enumValue = NULL;
56 56 }
57 57
58 58 PythonQtMemberInfo(const PythonQtObjectPtr& enumValue) {
59 59 _type = EnumValue;
60 60 _slot = NULL;
61 61 _enumValue = enumValue;
62 62 _enumWrapper = NULL;
63 63 }
64 64
65 65 PythonQtMemberInfo(const QMetaProperty& prop) {
66 66 _type = Property;
67 67 _slot = NULL;
68 68 _enumValue = NULL;
69 69 _property = prop;
70 70 _enumWrapper = NULL;
71 71 }
72 72
73 73 Type _type;
74 74
75 75 // TODO: this could be a union...
76 76 PythonQtSlotInfo* _slot;
77 77 PyObject* _enumWrapper;
78 78 PythonQtObjectPtr _enumValue;
79 79 QMetaProperty _property;
80 80 };
81 81
82 82 //! a class that stores all required information about a Qt object (and an optional associated C++ class name)
83 83 /*! for fast lookup of slots when calling the object from Python
84 84 */
85 85 class PythonQtClassInfo {
86 86
87 87 public:
88 88 PythonQtClassInfo();
89 89 ~PythonQtClassInfo();
90 90
91 91 //! store information about parent classes
92 92 struct ParentClassInfo {
93 93 ParentClassInfo(PythonQtClassInfo* parent, int upcastingOffset=0):_parent(parent),_upcastingOffset(upcastingOffset)
94 94 {};
95 95
96 96 PythonQtClassInfo* _parent;
97 97 int _upcastingOffset;
98 98 };
99 99
100 100
101 101 //! setup as a QObject, taking the meta object as meta information about the QObject
102 102 void setupQObject(const QMetaObject* meta);
103 103
104 104 //! setup as a CPP (non-QObject), taking the classname
105 105 void setupCPPObject(const QByteArray& classname);
106 106
107 107 //! get the Python method definition for a given slot name (without return type and signature)
108 108 PythonQtMemberInfo member(const char* member);
109 109
110 110 //! get access to the constructor slot (which may be overloaded if there are multiple constructors)
111 111 PythonQtSlotInfo* constructors();
112 112
113 113 //! get access to the destructor slot
114 114 PythonQtSlotInfo* destructor();
115 115
116 116 //! add a constructor, ownership is passed to classinfo
117 117 void addConstructor(PythonQtSlotInfo* info);
118 118
119 119 //! set a destructor, ownership is passed to classinfo
120 120 void setDestructor(PythonQtSlotInfo* info);
121 121
122 122 //! add a decorator slot, ownership is passed to classinfo
123 123 void addDecoratorSlot(PythonQtSlotInfo* info);
124 124
125 125 //! get the classname (either of the QObject or of the wrapped CPP object)
126 126 const char* className();
127 127
128 128 //! returns if the QObject
129 129 bool isQObject() { return _isQObject; }
130 130
131 131 //! returns if the class is a CPP wrapper
132 132 bool isCPPWrapper() { return !_isQObject; }
133 133
134 134 //! get the meta object
135 135 const QMetaObject* metaObject() { return _meta; }
136 136
137 137 //! set the meta object, this will reset the caching
138 138 void setMetaObject(const QMetaObject* meta);
139 139
140 140 //! returns if this class inherits from the given classname
141 141 bool inherits(const char* classname);
142 142
143 143 //! returns if this class inherits from the given classinfo
144 144 bool inherits(PythonQtClassInfo* info);
145 145
146 146 //! casts the given \c ptr to an object of type \c classname, returns the new pointer
147 147 //! which might be different to \c ptr due to C++ multiple inheritance
148 148 //! (if the cast is not possible or if ptr is NULL, NULL is returned)
149 149 void* castTo(void* ptr, const char* classname);
150 150
151 151 //! get help string for the metaobject
152 152 QString help();
153 153
154 154 //! get list of all properties (on QObjects only, otherwise the list is empty)
155 155 QStringList propertyList();
156 156
157 157 //! get list of all members
158 158 QStringList memberList(bool metaOnly = false);
159 159
160 160 //! get the meta type id of this class (only valid for isCPPWrapper() == true)
161 161 int metaTypeId() { return _metaTypeId; }
162 162
163 163 //! set an additional decorator provider that offers additional decorator slots for this class
164 164 void setDecoratorProvider(PythonQtQObjectCreatorFunctionCB* cb) { _decoratorProviderCB = cb; _decoratorProvider = NULL; }
165 165
166 166 //! get the decorator qobject instance
167 167 QObject* decorator();
168 168
169 169 //! add the parent class info of a CPP object
170 170 void addParentClass(const ParentClassInfo& info) { _parentClasses.append(info); }
171 171
172 172 //! check if the special method "hasOwner" is implemented and if it returns false, which means that the object may be destroyed
173 173 bool hasOwnerMethodButNoOwner(void* object);
174 174
175 175 //! set the associated PythonQtClassWrapper (which handles instance creation of this type)
176 176 void setPythonQtClassWrapper(PyObject* obj) { _pythonQtClassWrapper = obj; }
177 177
178 178 //! get the associated PythonQtClassWrapper (which handles instance creation of this type)
179 179 PyObject* pythonQtClassWrapper() { return _pythonQtClassWrapper; }
180 180
181 181 //! set the shell set instance wrapper cb
182 182 void setShellSetInstanceWrapperCB(PythonQtShellSetInstanceWrapperCB* cb) {
183 183 _shellSetInstanceWrapperCB = cb;
184 184 }
185 185
186 186 //! get the shell set instance wrapper cb
187 187 PythonQtShellSetInstanceWrapperCB* shellSetInstanceWrapperCB() {
188 188 return _shellSetInstanceWrapperCB;
189 189 }
190 190
191 191 //! add a handler for polymorphic downcasting
192 192 void addPolymorphicHandler(PythonQtPolymorphicHandlerCB* cb) { _polymorphicHandlers.append(cb); }
193 193
194 194 //! cast the pointer down in the class hierarchy if a polymorphic handler allows to do that
195 195 void* castDownIfPossible(void* ptr, PythonQtClassInfo** resultClassInfo);
196 196
197 197 //! returns if the localScope has an enum of that type name or if the enum contains a :: scope, if that class contails the enum
198 static PyObject* findEnumWrapper(const QByteArray& name, PythonQtClassInfo* localScope, bool& isLocalEnum);
198 static PyObject* findEnumWrapper(const QByteArray& name, PythonQtClassInfo* localScope, bool* isLocalEnum = NULL);
199 199
200 200 private:
201 201 void createEnumWrappers();
202 202 void createEnumWrappers(const QMetaObject* meta);
203 203 PyObject* findEnumWrapper(const char* name);
204 204
205 205 //! clear all cached members
206 206 void clearCachedMembers();
207 207
208 208 void* recursiveCastDownIfPossible(void* ptr, char** resultClassName);
209 209
210 210 PythonQtSlotInfo* findDecoratorSlotsFromDecoratorProvider(const char* memberName, PythonQtSlotInfo* inputInfo, bool &found, QHash<QByteArray, PythonQtMemberInfo>& memberCache, int upcastingOffset);
211 211 void listDecoratorSlotsFromDecoratorProvider(QStringList& list, bool metaOnly);
212 212 PythonQtSlotInfo* recursiveFindDecoratorSlotsFromDecoratorProvider(const char* memberName, PythonQtSlotInfo* inputInfo, bool &found, QHash<QByteArray, PythonQtMemberInfo>& memberCache, int upcastingOffset);
213 213
214 214 void recursiveCollectClassInfos(QList<PythonQtClassInfo*>& classInfoObjects);
215 215 void recursiveCollectDecoratorObjects(QList<QObject*>& decoratorObjects);
216 216
217 217 bool lookForPropertyAndCache(const char* memberName);
218 218 bool lookForMethodAndCache(const char* memberName);
219 219 bool lookForEnumAndCache(const QMetaObject* m, const char* memberName);
220 220
221 221 PythonQtSlotInfo* findDecoratorSlots(const char* memberName, int memberNameLen, PythonQtSlotInfo* tail, bool &found, QHash<QByteArray, PythonQtMemberInfo>& memberCache, int upcastingOffset);
222 222 int findCharOffset(const char* sigStart, char someChar);
223 223
224 224 QHash<QByteArray, PythonQtMemberInfo> _cachedMembers;
225 225
226 226 PythonQtSlotInfo* _constructors;
227 227 PythonQtSlotInfo* _destructor;
228 228 QList<PythonQtSlotInfo*> _decoratorSlots;
229 229
230 230 QList<PythonQtObjectPtr> _enumWrappers;
231 231
232 232 const QMetaObject* _meta;
233 233
234 234 QByteArray _wrappedClassName;
235 235 QList<ParentClassInfo> _parentClasses;
236 236
237 237 QList<PythonQtPolymorphicHandlerCB*> _polymorphicHandlers;
238 238
239 239 QObject* _decoratorProvider;
240 240 PythonQtQObjectCreatorFunctionCB* _decoratorProviderCB;
241 241
242 242 PyObject* _pythonQtClassWrapper;
243 243
244 244 PythonQtShellSetInstanceWrapperCB* _shellSetInstanceWrapperCB;
245 245
246 246 int _metaTypeId;
247 247
248 248 bool _isQObject;
249 249 bool _enumsCreated;
250 250
251 251 };
252 252
253 253 //---------------------------------------------------------------
254 254
255 255
256 256 #endif
@@ -1,1131 +1,1213
1 1 /*
2 2 *
3 3 * Copyright (C) 2006 MeVis Research GmbH All Rights Reserved.
4 4 *
5 5 * This library is free software; you can redistribute it and/or
6 6 * modify it under the terms of the GNU Lesser General Public
7 7 * License as published by the Free Software Foundation; either
8 8 * version 2.1 of the License, or (at your option) any later version.
9 9 *
10 10 * This library is distributed in the hope that it will be useful,
11 11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13 13 * Lesser General Public License for more details.
14 14 *
15 15 * Further, this software is distributed without any warranty that it is
16 16 * free of the rightful claim of any third person regarding infringement
17 17 * or the like. Any license provided herein, whether implied or
18 18 * otherwise, applies only to this software file. Patent licenses, if
19 19 * any, provided herein do not apply to combinations of this program with
20 20 * other software, or any other product whatsoever.
21 21 *
22 22 * You should have received a copy of the GNU Lesser General Public
23 23 * License along with this library; if not, write to the Free Software
24 24 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
25 25 *
26 26 * Contact information: MeVis Research GmbH, Universitaetsallee 29,
27 27 * 28359 Bremen, Germany or:
28 28 *
29 29 * http://www.mevis.de
30 30 *
31 31 */
32 32
33 33 //----------------------------------------------------------------------------------
34 34 /*!
35 35 // \file PythonQtConversion.cpp
36 36 // \author Florian Link
37 37 // \author Last changed by $Author: florian $
38 38 // \date 2006-05
39 39 */
40 40 //----------------------------------------------------------------------------------
41 41
42 42 #include "PythonQtConversion.h"
43 43 #include "PythonQtVariants.h"
44 44 #include <QDateTime>
45 45 #include <QTime>
46 46 #include <QDate>
47 47
48 48 PythonQtValueStorage<qint64, 128> PythonQtConv::global_valueStorage;
49 49 PythonQtValueStorage<void*, 128> PythonQtConv::global_ptrStorage;
50 50 PythonQtValueStorage<QVariant, 32> PythonQtConv::global_variantStorage;
51 51
52 52 QHash<int, PythonQtConvertMetaTypeToPythonCB*> PythonQtConv::_metaTypeToPythonConverters;
53 53 QHash<int, PythonQtConvertPythonToMetaTypeCB*> PythonQtConv::_pythonToMetaTypeConverters;
54 54
55 55 PyObject* PythonQtConv::GetPyBool(bool val)
56 56 {
57 57 PyObject* r = val?Py_True:Py_False;
58 58 Py_INCREF(r);
59 59 return r;
60 60 }
61 61
62 62 PyObject* PythonQtConv::ConvertQtValueToPython(const PythonQtMethodInfo::ParameterInfo& info, const void* data) {
63 63 // is it an enum value?
64 64 if (info.enumWrapper) {
65 65 if (!info.isPointer) {
66 66 return PythonQtPrivate::createEnumValueInstance(info.enumWrapper, *((unsigned int*)data));
67 67 } else {
68 68 // we do not support pointers to enums (who needs them?)
69 69 Py_INCREF(Py_None);
70 70 return Py_None;
71 71 }
72 72 }
73 73
74 74 if (info.typeId == QMetaType::Void) {
75 75 Py_INCREF(Py_None);
76 76 return Py_None;
77 77 } else if (info.isPointer && (info.typeId == QMetaType::Char)) {
78 78 // a char ptr will probably be a null terminated string, so we support that:
79 79 return PyString_FromString(*((char**)data));
80 80 } else if ((info.typeId == PythonQtMethodInfo::Unknown || info.typeId >= QMetaType::User) &&
81 81 info.name.startsWith("QList<")) {
82 82 // it is a QList template:
83 83 // (TODO: check what happens if this is a pointer type?!)
84 84 QByteArray innerType = info.name.mid(6,info.name.length()-7);
85 85 if (innerType.endsWith("*")) {
86 86 innerType.truncate(innerType.length()-1);
87 87 return ConvertQListOfPointerTypeToPythonList((QList<void*>*)data, innerType);
88 88 }
89 89 }
90 90
91 91 if (info.typeId >= QMetaType::User) {
92 92 // if a converter is registered, we use is:
93 93 PythonQtConvertMetaTypeToPythonCB* converter = _metaTypeToPythonConverters.value(info.typeId);
94 94 if (converter) {
95 95 return (*converter)(data, info.typeId);
96 96 }
97 97 }
98 98
99 99 // special handling did not match, so we convert the usual way (either pointer or value version):
100 100 if (info.isPointer) {
101 101 // convert the pointer to a Python Object (we can handle ANY C++ object, in the worst case we just know the type and the pointer)
102 102 return PythonQt::priv()->wrapPtr(*((void**)data), info.name);
103 103 } else {
104 104 // handle values that are not yet handled and not pointers
105 105 return ConvertQtValueToPythonInternal(info.typeId, data);
106 106 }
107 107 }
108 108
109 109 PyObject* PythonQtConv::ConvertQtValueToPythonInternal(int type, const void* data) {
110 110 switch (type) {
111 111 case QMetaType::Void:
112 112 Py_INCREF(Py_None);
113 113 return Py_None;
114 114 case QMetaType::Char:
115 115 return PyInt_FromLong(*((char*)data));
116 116 case QMetaType::UChar:
117 117 return PyInt_FromLong(*((unsigned char*)data));
118 118 case QMetaType::Short:
119 119 return PyInt_FromLong(*((short*)data));
120 120 case QMetaType::UShort:
121 121 return PyInt_FromLong(*((unsigned short*)data));
122 122 case QMetaType::Long:
123 123 return PyInt_FromLong(*((long*)data));
124 124 case QMetaType::ULong:
125 125 // does not fit into simple int of python
126 126 return PyLong_FromUnsignedLong(*((unsigned long*)data));
127 127 case QMetaType::Bool:
128 128 return PythonQtConv::GetPyBool(*((bool*)data));
129 129 case QMetaType::Int:
130 130 return PyInt_FromLong(*((int*)data));
131 131 case QMetaType::UInt:
132 132 return PyInt_FromLong(*((unsigned int*)data));
133 133 case QMetaType::QChar:
134 134 return PyInt_FromLong(*((short*)data));
135 135 case QMetaType::Float:
136 136 return PyFloat_FromDouble(*((float*)data));
137 137 case QMetaType::Double:
138 138 return PyFloat_FromDouble(*((double*)data));
139 139 case QMetaType::LongLong:
140 140 return PyLong_FromLongLong(*((qint64*)data));
141 141 case QMetaType::ULongLong:
142 142 return PyLong_FromUnsignedLongLong(*((quint64*)data));
143 143 case QMetaType::QByteArray: {
144 144 QByteArray* v = (QByteArray*) data;
145 145 return PyString_FromStringAndSize(*v, v->size());
146 146 }
147 147 case QMetaType::QVariantMap:
148 148 return PythonQtConv::QVariantMapToPyObject(*((QVariantMap*)data));
149 149 case QMetaType::QVariantList:
150 150 return PythonQtConv::QVariantListToPyObject(*((QVariantList*)data));
151 151 case QMetaType::QString:
152 152 return PythonQtConv::QStringToPyObject(*((QString*)data));
153 153 case QMetaType::QStringList:
154 154 return PythonQtConv::QStringListToPyObject(*((QStringList*)data));
155 155
156 156 case PythonQtMethodInfo::Variant:
157 157 return PythonQtConv::QVariantToPyObject(*((QVariant*)data));
158 158 case QMetaType::QObjectStar:
159 159 case QMetaType::QWidgetStar:
160 160 return PythonQt::priv()->wrapQObject(*((QObject**)data));
161 161
162 162 default:
163 163 if (PythonQt::priv()->isPythonQtObjectPtrMetaId(type)) {
164 164 // special case, it is a PythonQtObjectPtr which contains a PyObject, take it directly:
165 165 PyObject* o = ((PythonQtObjectPtr*)data)->object();
166 166 Py_INCREF(o);
167 167 return o;
168 168 } else {
169 169 if (type > 0) {
170 170 // if the type is known, we can construct it via QMetaType::construct
171 171 void* newCPPObject = QMetaType::construct(type, data);
172 172 // XXX this could be optimized by using metatypeid directly
173 173 PythonQtInstanceWrapper* wrap = (PythonQtInstanceWrapper*)PythonQt::priv()->wrapPtr(newCPPObject, QMetaType::typeName(type));
174 174 wrap->_ownedByPythonQt = true;
175 175 wrap->_useQMetaTypeDestroy = true;
176 176 return (PyObject*)wrap;
177 177 }
178 178 std::cerr << "Unknown type that can not be converted to Python: " << type << ", in " << __FILE__ << ":" << __LINE__ << std::endl;
179 179 }
180 180 }
181 181 Py_INCREF(Py_None);
182 182 return Py_None;
183 183 }
184 184
185 185 void* PythonQtConv::CreateQtReturnValue(const PythonQtMethodInfo::ParameterInfo& info) {
186 186 void* ptr = NULL;
187 187 if (info.isPointer) {
188 188 PythonQtValueStorage_ADD_VALUE(global_ptrStorage, void*, NULL, ptr);
189 189 } else if (info.enumWrapper) {
190 190 // create enum return value
191 191 PythonQtValueStorage_ADD_VALUE(PythonQtConv::global_valueStorage, long, 0, ptr);
192 192 } else {
193 193 switch (info.typeId) {
194 194 case QMetaType::Char:
195 195 case QMetaType::UChar:
196 196 case QMetaType::Short:
197 197 case QMetaType::UShort:
198 198 case QMetaType::Long:
199 199 case QMetaType::ULong:
200 200 case QMetaType::Bool:
201 201 case QMetaType::Int:
202 202 case QMetaType::UInt:
203 203 case QMetaType::QChar:
204 204 case QMetaType::Float:
205 205 case QMetaType::Double:
206 206 PythonQtValueStorage_ADD_VALUE(global_valueStorage, long, 0, ptr);
207 207 break;
208 208 case PythonQtMethodInfo::Variant:
209 209 PythonQtValueStorage_ADD_VALUE(global_variantStorage, QVariant, 0, ptr);
210 210 // return the ptr to the variant
211 211 break;
212 212 default:
213 213 if (info.typeId == PythonQtMethodInfo::Unknown) {
214 214 // check if we have a QList of pointers, which we can circumvent with a QList<void*>
215 215 if (info.name.startsWith("QList<")) {
216 216 QByteArray innerType = info.name.mid(6,info.name.length()-7);
217 217 if (innerType.endsWith("*")) {
218 218 static int id = QMetaType::type("QList<void*>");
219 219 PythonQtValueStorage_ADD_VALUE(global_variantStorage, QVariant, QVariant::Type(id), ptr);
220 220 // return the constData pointer that will be filled with the result value later on
221 221 ptr = (void*)((QVariant*)ptr)->constData();
222 222 }
223 223 }
224 224 }
225 225
226 226 if (!ptr && info.typeId!=PythonQtMethodInfo::Unknown) {
227 227 // everything else is stored in a QVariant, if we know the meta type...
228 228 PythonQtValueStorage_ADD_VALUE(global_variantStorage, QVariant, QVariant::Type(info.typeId), ptr);
229 229 // return the constData pointer that will be filled with the result value later on
230 230 ptr = (void*)((QVariant*)ptr)->constData();
231 231 }
232 232 }
233 233 }
234 234 return ptr;
235 235 }
236 236
237 237 void* PythonQtConv::castWrapperTo(PythonQtInstanceWrapper* wrapper, const QByteArray& className, bool& ok)
238 238 {
239 239 void* object;
240 240 if (wrapper->classInfo()->isCPPWrapper()) {
241 241 object = wrapper->_wrappedPtr;
242 242 } else {
243 243 QObject* tmp = wrapper->_obj;
244 244 object = tmp;
245 245 }
246 246 if (object) {
247 247 // if we can be upcasted to the given name, we pass the casted pointer in:
248 248 object = wrapper->classInfo()->castTo(object, className);
249 249 ok = object!=NULL;
250 250 } else {
251 251 // if it is a NULL ptr, we need to check if it inherits, so that we might pass the NULL ptr
252 252 ok = wrapper->classInfo()->inherits(className);
253 253 }
254 254 return object;
255 255 }
256 256
257 void* PythonQtConv::ConvertPythonToQt(const PythonQtMethodInfo::ParameterInfo& info, PyObject* obj, bool strict, PythonQtClassInfo* /*classInfo*/, void* alreadyAllocatedCPPObject)
257 void* PythonQtConv::handlePythonToQtAutoConversion(int typeId, PyObject* obj, void* alreadyAllocatedCPPObject)
258 {
259 void* ptr = alreadyAllocatedCPPObject;
260
261 static int penId = QMetaType::type("QPen");
262 static int brushId = QMetaType::type("QBrush");
263 static int cursorId = QMetaType::type("QCursor");
264 static int colorId = QMetaType::type("QColor");
265 static PyObject* qtGlobalColorEnum = PythonQtClassInfo::findEnumWrapper("Qt::GlobalColor", NULL);
266 if (typeId == cursorId) {
267 static PyObject* qtCursorShapeEnum = PythonQtClassInfo::findEnumWrapper("Qt::CursorShape", NULL);
268 if ((PyObject*)obj->ob_type == qtCursorShapeEnum) {
269 Qt::CursorShape val = (Qt::CursorShape)PyInt_AS_LONG(obj);
270 if (!ptr) {
271 PythonQtValueStorage_ADD_VALUE(global_variantStorage, QVariant, QCursor(), ptr);
272 ptr = (void*)((QVariant*)ptr)->constData();
273 }
274 *((QCursor*)ptr) = QCursor(val);
275 return ptr;
276 }
277 } else if (typeId == penId) {
278 // brushes can be created from QColor and from Qt::GlobalColor (and from brushes, but that's the default)
279 static PyObject* qtColorClass = PythonQt::priv()->getClassInfo("QColor")->pythonQtClassWrapper();
280 if ((PyObject*)obj->ob_type == qtGlobalColorEnum) {
281 Qt::GlobalColor val = (Qt::GlobalColor)PyInt_AS_LONG(obj);
282 if (!ptr) {
283 PythonQtValueStorage_ADD_VALUE(global_variantStorage, QVariant, QPen(), ptr);
284 ptr = (void*)((QVariant*)ptr)->constData();
285 }
286 *((QPen*)ptr) = QPen(QColor(val));
287 return ptr;
288 } else if ((PyObject*)obj->ob_type == qtColorClass) {
289 if (!ptr) {
290 PythonQtValueStorage_ADD_VALUE(global_variantStorage, QVariant, QPen(), ptr);
291 ptr = (void*)((QVariant*)ptr)->constData();
292 }
293 *((QPen*)ptr) = QPen(*((QColor*)((PythonQtInstanceWrapper*)obj)->_wrappedPtr));
294 return ptr;
295 }
296 } else if (typeId == brushId) {
297 // brushes can be created from QColor and from Qt::GlobalColor (and from brushes, but that's the default)
298 static PyObject* qtColorClass = PythonQt::priv()->getClassInfo("QColor")->pythonQtClassWrapper();
299 if ((PyObject*)obj->ob_type == qtGlobalColorEnum) {
300 Qt::GlobalColor val = (Qt::GlobalColor)PyInt_AS_LONG(obj);
301 if (!ptr) {
302 PythonQtValueStorage_ADD_VALUE(global_variantStorage, QVariant, QBrush(), ptr);
303 ptr = (void*)((QVariant*)ptr)->constData();
304 }
305 *((QBrush*)ptr) = QBrush(QColor(val));
306 return ptr;
307 } else if ((PyObject*)obj->ob_type == qtColorClass) {
308 if (!ptr) {
309 PythonQtValueStorage_ADD_VALUE(global_variantStorage, QVariant, QBrush(), ptr);
310 ptr = (void*)((QVariant*)ptr)->constData();
311 }
312 *((QBrush*)ptr) = QBrush(*((QColor*)((PythonQtInstanceWrapper*)obj)->_wrappedPtr));
313 return ptr;
314 }
315 } else if (typeId == colorId) {
316 // colors can be created from Qt::GlobalColor (and from colors, but that's the default)
317 if ((PyObject*)obj->ob_type == qtGlobalColorEnum) {
318 Qt::GlobalColor val = (Qt::GlobalColor)PyInt_AS_LONG(obj);
319 if (!ptr) {
320 PythonQtValueStorage_ADD_VALUE(global_variantStorage, QVariant, QColor(), ptr);
321 ptr = (void*)((QVariant*)ptr)->constData();
322 }
323 *((QColor*)ptr) = QColor(val);
324 return ptr;
325 }
326 }
327 return NULL;
328 }
329
330 void* PythonQtConv::ConvertPythonToQt(const PythonQtMethodInfo::ParameterInfo& info, PyObject* obj, bool strict, PythonQtClassInfo* /*classInfo*/, void* alreadyAllocatedCPPObject)
258 331 {
259 332 bool ok = false;
260 333 void* ptr = NULL;
334
335 // autoconversion of QPen/QBrush/QCursor/QColor from different type
336 if (!info.isPointer && !strict) {
337 ptr = handlePythonToQtAutoConversion(info.typeId, obj, alreadyAllocatedCPPObject);
338 if (ptr) {
339 return ptr;
340 }
341 }
342
261 343 if (PyObject_TypeCheck(obj, &PythonQtInstanceWrapper_Type) && info.typeId != PythonQtMethodInfo::Variant) {
262 344 // if we have a Qt wrapper object and if we do not need a QVariant, we do the following:
263 345 // (the Variant case is handled below in a switch)
264 346
265 347 // a C++ wrapper (can be passed as pointer or reference)
266 348 PythonQtInstanceWrapper* wrap = (PythonQtInstanceWrapper*)obj;
267 349 void* object = castWrapperTo(wrap, info.name, ok);
268 350 if (ok) {
269 351 if (info.isPointer) {
270 352 // store the wrapped pointer in an extra pointer and let ptr point to the extra pointer
271 353 PythonQtValueStorage_ADD_VALUE_IF_NEEDED(alreadyAllocatedCPPObject,global_ptrStorage, void*, object, ptr);
272 354 } else {
273 355 // store the wrapped pointer directly, since we are a reference
274 356 ptr = object;
275 357 }
276 358 } else {
277 359 // not matching
278 360 }
279 361 } else if (info.isPointer) {
280 362 // a pointer
281 363 if (info.typeId == QMetaType::Char || info.typeId == QMetaType::UChar)
282 364 {
283 365 QString str = PyObjGetString(obj, strict, ok);
284 366 if (ok) {
285 367 void* ptr2 = NULL;
286 368 PythonQtValueStorage_ADD_VALUE_IF_NEEDED(alreadyAllocatedCPPObject,global_variantStorage, QVariant, QVariant(str.toUtf8()), ptr2);
287 369 PythonQtValueStorage_ADD_VALUE_IF_NEEDED(alreadyAllocatedCPPObject,global_ptrStorage, void*, (((QByteArray*)((QVariant*)ptr2)->constData())->data()), ptr);
288 370 }
289 371 } else if (info.name == "PyObject") {
290 372 // handle low level PyObject directly
291 373 PythonQtValueStorage_ADD_VALUE_IF_NEEDED(alreadyAllocatedCPPObject,global_ptrStorage, void*, obj, ptr);
292 374 } else if (obj == Py_None) {
293 375 // None is treated as a NULL ptr
294 376 PythonQtValueStorage_ADD_VALUE_IF_NEEDED(alreadyAllocatedCPPObject,global_ptrStorage, void*, NULL, ptr);
295 377 } else {
296 378 // if we are not strict, we try if we are passed a 0 integer
297 379 if (!strict) {
298 380 bool ok;
299 381 int value = PyObjGetInt(obj, true, ok);
300 382 if (ok && value==0) {
301 383 // TODOXXX is this wise? or should it be expected from the programmer to use None?
302 384 PythonQtValueStorage_ADD_VALUE_IF_NEEDED(alreadyAllocatedCPPObject,global_ptrStorage, void*, NULL, ptr);
303 385 }
304 386 }
305 387 }
306 388 } else {
307 389 // not a pointer
308 390 switch (info.typeId) {
309 391 case QMetaType::Char:
310 392 {
311 393 int val = PyObjGetInt(obj, strict, ok);
312 394 if (ok) {
313 395 PythonQtValueStorage_ADD_VALUE_IF_NEEDED(alreadyAllocatedCPPObject,global_valueStorage, char, val, ptr);
314 396 }
315 397 }
316 398 break;
317 399 case QMetaType::UChar:
318 400 {
319 401 int val = PyObjGetInt(obj, strict, ok);
320 402 if (ok) {
321 403 PythonQtValueStorage_ADD_VALUE_IF_NEEDED(alreadyAllocatedCPPObject,global_valueStorage, unsigned char, val, ptr);
322 404 }
323 405 }
324 406 break;
325 407 case QMetaType::Short:
326 408 {
327 409 int val = PyObjGetInt(obj, strict, ok);
328 410 if (ok) {
329 411 PythonQtValueStorage_ADD_VALUE_IF_NEEDED(alreadyAllocatedCPPObject,global_valueStorage, short, val, ptr);
330 412 }
331 413 }
332 414 break;
333 415 case QMetaType::UShort:
334 416 {
335 417 int val = PyObjGetInt(obj, strict, ok);
336 418 if (ok) {
337 419 PythonQtValueStorage_ADD_VALUE_IF_NEEDED(alreadyAllocatedCPPObject,global_valueStorage, unsigned short, val, ptr);
338 420 }
339 421 }
340 422 break;
341 423 case QMetaType::Long:
342 424 {
343 425 long val = (long)PyObjGetLongLong(obj, strict, ok);
344 426 if (ok) {
345 427 PythonQtValueStorage_ADD_VALUE_IF_NEEDED(alreadyAllocatedCPPObject,global_valueStorage, long, val, ptr);
346 428 }
347 429 }
348 430 break;
349 431 case QMetaType::ULong:
350 432 {
351 433 unsigned long val = (unsigned long)PyObjGetLongLong(obj, strict, ok);
352 434 if (ok) {
353 435 PythonQtValueStorage_ADD_VALUE_IF_NEEDED(alreadyAllocatedCPPObject,global_valueStorage, unsigned long, val, ptr);
354 436 }
355 437 }
356 438 break;
357 439 case QMetaType::Bool:
358 440 {
359 441 bool val = PyObjGetBool(obj, strict, ok);
360 442 if (ok) {
361 443 PythonQtValueStorage_ADD_VALUE_IF_NEEDED(alreadyAllocatedCPPObject,global_valueStorage, bool, val, ptr);
362 444 }
363 445 }
364 446 break;
365 447 case QMetaType::Int:
366 448 {
367 449 int val = PyObjGetInt(obj, strict, ok);
368 450 if (ok) {
369 451 PythonQtValueStorage_ADD_VALUE_IF_NEEDED(alreadyAllocatedCPPObject,global_valueStorage, int, val, ptr);
370 452 }
371 453 }
372 454 break;
373 455 case QMetaType::UInt:
374 456 {
375 457 unsigned int val = (unsigned int)PyObjGetLongLong(obj, strict, ok);
376 458 if (ok) {
377 459 PythonQtValueStorage_ADD_VALUE_IF_NEEDED(alreadyAllocatedCPPObject,global_valueStorage, unsigned int, val, ptr);
378 460 }
379 461 }
380 462 break;
381 463 case QMetaType::QChar:
382 464 {
383 465 int val = PyObjGetInt(obj, strict, ok);
384 466 if (ok) {
385 467 PythonQtValueStorage_ADD_VALUE_IF_NEEDED(alreadyAllocatedCPPObject,global_valueStorage, short, val, ptr);
386 468 }
387 469 }
388 470 break;
389 471 case QMetaType::Float:
390 472 {
391 473 float val = (float)PyObjGetDouble(obj, strict, ok);
392 474 if (ok) {
393 475 PythonQtValueStorage_ADD_VALUE_IF_NEEDED(alreadyAllocatedCPPObject,global_valueStorage, float, val, ptr);
394 476 }
395 477 }
396 478 break;
397 479 case QMetaType::Double:
398 480 {
399 481 double val = (double)PyObjGetDouble(obj, strict, ok);
400 482 if (ok) {
401 483 PythonQtValueStorage_ADD_VALUE_IF_NEEDED(alreadyAllocatedCPPObject,global_valueStorage, double, val, ptr);
402 484 }
403 485 }
404 486 break;
405 487 case QMetaType::LongLong:
406 488 {
407 489 qint64 val = PyObjGetLongLong(obj, strict, ok);
408 490 if (ok) {
409 491 PythonQtValueStorage_ADD_VALUE_IF_NEEDED(alreadyAllocatedCPPObject,global_valueStorage, qint64, val, ptr);
410 492 }
411 493 }
412 494 break;
413 495 case QMetaType::ULongLong:
414 496 {
415 497 quint64 val = PyObjGetULongLong(obj, strict, ok);
416 498 if (ok) {
417 499 PythonQtValueStorage_ADD_VALUE_IF_NEEDED(alreadyAllocatedCPPObject,global_valueStorage, quint64, val, ptr);
418 500 }
419 501 }
420 502 break;
421 503 case QMetaType::QByteArray:
422 504 {
423 505 QByteArray bytes = PyObjGetBytes(obj, strict, ok);
424 506 if (ok) {
425 507 PythonQtValueStorage_ADD_VALUE_IF_NEEDED(alreadyAllocatedCPPObject,global_variantStorage, QVariant, QVariant(bytes), ptr);
426 508 ptr = (void*)((QVariant*)ptr)->constData();
427 509 }
428 510 }
429 511 break;
430 512 case QMetaType::QString:
431 513 {
432 514 QString str = PyObjGetString(obj, strict, ok);
433 515 if (ok) {
434 516 PythonQtValueStorage_ADD_VALUE_IF_NEEDED(alreadyAllocatedCPPObject,global_variantStorage, QVariant, QVariant(str), ptr);
435 517 ptr = (void*)((QVariant*)ptr)->constData();
436 518 }
437 519 }
438 520 break;
439 521 case QMetaType::QStringList:
440 522 {
441 523 QStringList l = PyObjToStringList(obj, strict, ok);
442 524 if (ok) {
443 525 PythonQtValueStorage_ADD_VALUE_IF_NEEDED(alreadyAllocatedCPPObject,global_variantStorage, QVariant, QVariant(l), ptr);
444 526 ptr = (void*)((QVariant*)ptr)->constData();
445 527 }
446 528 }
447 529 break;
448 530
449 531 case PythonQtMethodInfo::Variant:
450 532 {
451 533 QVariant v = PyObjToQVariant(obj);
452 534 if (v.isValid()) {
453 535 PythonQtValueStorage_ADD_VALUE_IF_NEEDED(alreadyAllocatedCPPObject,global_variantStorage, QVariant, v, ptr);
454 536 }
455 537 }
456 538 break;
457 539 default:
458 540 {
459 541 // check for enum case
460 542 if (info.enumWrapper) {
461 543 unsigned int val;
462 544 ok = false;
463 545 if ((PyObject*)obj->ob_type == info.enumWrapper) {
464 546 // we have a exact enum type match:
465 547 val = PyInt_AS_LONG(obj);
466 548 ok = true;
467 549 } else if (!strict) {
468 550 // we try to get any integer, when not being strict. If we are strict, integers are not wanted because
469 551 // we want an integer overload to be taken first!
470 552 val = (unsigned int)PyObjGetLongLong(obj, false, ok);
471 553 }
472 554 if (ok) {
473 555 PythonQtValueStorage_ADD_VALUE_IF_NEEDED(alreadyAllocatedCPPObject,global_valueStorage, unsigned int, val, ptr);
474 556 return ptr;
475 557 } else {
476 558 return NULL;
477 559 }
478 560 }
479 561
480 562 if (info.typeId == PythonQtMethodInfo::Unknown || info.typeId >= QMetaType::User) {
481 563 // check for QList<AnyPtr*> case, where we will use a QList<void*> QVariant
482 564 if (info.name.startsWith("QList<")) {
483 565 QByteArray innerType = info.name.mid(6,info.name.length()-7);
484 566 if (innerType.endsWith("*")) {
485 567 innerType.truncate(innerType.length()-1);
486 568 static int id = QMetaType::type("QList<void*>");
487 569 if (!alreadyAllocatedCPPObject) {
488 570 PythonQtValueStorage_ADD_VALUE_IF_NEEDED(alreadyAllocatedCPPObject,global_variantStorage, QVariant, QVariant::Type(id), ptr);
489 571 ptr = (void*)((QVariant*)ptr)->constData();
490 572 } else {
491 573 ptr = alreadyAllocatedCPPObject;
492 574 }
493 575 ok = ConvertPythonListToQListOfPointerType(obj, (QList<void*>*)ptr, innerType, strict);
494 576 if (ok) {
495 577 return ptr;
496 578 } else {
497 579 return NULL;
498 580 }
499 581 }
500 582 }
501 583 }
502 584
503 585 // We only do this for registered type > QMetaType::User for performance reasons.
504 586 if (info.typeId >= QMetaType::User) {
505 587 // Maybe we have a special converter that is registered for that type:
506 588 PythonQtConvertPythonToMetaTypeCB* converter = _pythonToMetaTypeConverters.value(info.typeId);
507 589 if (converter) {
508 590 if (!alreadyAllocatedCPPObject) {
509 591 // create a new empty variant of concrete type:
510 592 PythonQtValueStorage_ADD_VALUE_IF_NEEDED(alreadyAllocatedCPPObject,global_variantStorage, QVariant, QVariant::Type(info.typeId), ptr);
511 593 ptr = (void*)((QVariant*)ptr)->constData();
512 594 } else {
513 595 ptr = alreadyAllocatedCPPObject;
514 596 }
515 597 // now call the converter, passing the internal object of the variant
516 598 ok = (*converter)(obj, ptr, info.typeId, strict);
517 599 if (ok) {
518 600 return ptr;
519 601 } else {
520 602 return NULL;
521 603 }
522 604 }
523 605 }
524 606 // if no type id is available, conversion to a QVariant makes no sense/is not possible
525 607 if (info.typeId != PythonQtMethodInfo::Unknown) {
526 608 // for all other types, we use the same qvariant conversion and pass out the constData of the variant:
527 609 QVariant v = PyObjToQVariant(obj, info.typeId);
528 610 if (v.isValid()) {
529 611 PythonQtValueStorage_ADD_VALUE_IF_NEEDED(alreadyAllocatedCPPObject,global_variantStorage, QVariant, v, ptr);
530 612 ptr = (void*)((QVariant*)ptr)->constData();
531 613 }
532 614 }
533 615 }
534 616 }
535 617 }
536 618 return ptr;
537 619 }
538 620
539 621
540 622 QStringList PythonQtConv::PyObjToStringList(PyObject* val, bool strict, bool& ok) {
541 623 QStringList v;
542 624 ok = false;
543 625 // if we are strict, we do not want to convert a string to a stringlist
544 626 // (strings in python are detected to be sequences)
545 627 if (strict &&
546 628 (val->ob_type == &PyString_Type ||
547 629 PyUnicode_Check(val))) {
548 630 ok = false;
549 631 return v;
550 632 }
551 633 if (PySequence_Check(val)) {
552 634 int count = PySequence_Size(val);
553 635 for (int i = 0;i<count;i++) {
554 636 PyObject* value = PySequence_GetItem(val,i);
555 637 v.append(PyObjGetString(value,false,ok));
556 638 }
557 639 ok = true;
558 640 }
559 641 return v;
560 642 }
561 643
562 644 QString PythonQtConv::PyObjGetRepresentation(PyObject* val)
563 645 {
564 646 QString r;
565 647 PyObject* str = PyObject_Repr(val);
566 648 if (str) {
567 649 r = QString(PyString_AS_STRING(str));
568 650 Py_DECREF(str);
569 651 }
570 652 return r;
571 653 }
572 654
573 655 QString PythonQtConv::PyObjGetString(PyObject* val, bool strict, bool& ok) {
574 656 QString r;
575 657 ok = true;
576 658 if (val->ob_type == &PyString_Type) {
577 659 r = QString(PyString_AS_STRING(val));
578 660 } else if (PyUnicode_Check(val)) {
579 661 #ifdef WIN32
580 662 r = QString::fromUtf16(PyUnicode_AS_UNICODE(val));
581 663 #else
582 664 PyObject *ptmp = PyUnicode_AsUTF8String(val);
583 665 if(ptmp) {
584 666 r = QString::fromUtf8(PyString_AS_STRING(ptmp));
585 667 Py_DECREF(ptmp);
586 668 }
587 669 #endif
588 670 } else if (!strict) {
589 671 // EXTRA: could also use _Unicode, but why should we?
590 672 PyObject* str = PyObject_Str(val);
591 673 if (str) {
592 674 r = QString(PyString_AS_STRING(str));
593 675 Py_DECREF(str);
594 676 } else {
595 677 ok = false;
596 678 }
597 679 } else {
598 680 ok = false;
599 681 }
600 682 return r;
601 683 }
602 684
603 685 QByteArray PythonQtConv::PyObjGetBytes(PyObject* val, bool /*strict*/, bool& ok) {
604 686 QByteArray r;
605 687 ok = true;
606 688 if (val->ob_type == &PyString_Type) {
607 689 long size = PyString_GET_SIZE(val);
608 690 r = QByteArray(PyString_AS_STRING(val), size);
609 691 } else {
610 692 ok = false;
611 693 }
612 694 return r;
613 695 }
614 696
615 697 bool PythonQtConv::PyObjGetBool(PyObject* val, bool strict, bool &ok) {
616 698 bool d = false;
617 699 ok = false;
618 700 if (val == Py_False) {
619 701 d = false;
620 702 ok = true;
621 703 } else if (val == Py_True) {
622 704 d = true;
623 705 ok = true;
624 706 } else if (!strict) {
625 707 d = PyObjGetInt(val, false, ok)!=0;
626 708 ok = true;
627 709 }
628 710 return d;
629 711 }
630 712
631 713 int PythonQtConv::PyObjGetInt(PyObject* val, bool strict, bool &ok) {
632 714 int d = 0;
633 715 ok = true;
634 716 if (val->ob_type == &PyInt_Type) {
635 717 d = PyInt_AS_LONG(val);
636 718 } else if (!strict) {
637 719 if (PyObject_TypeCheck(val, &PyInt_Type)) {
638 720 // support for derived int classes, e.g. for our enums
639 721 d = PyInt_AS_LONG(val);
640 722 } else if (val->ob_type == &PyFloat_Type) {
641 723 d = floor(PyFloat_AS_DOUBLE(val));
642 724 } else if (val->ob_type == &PyLong_Type) {
643 725 // handle error on overflow!
644 726 d = PyLong_AsLong(val);
645 727 } else if (val == Py_False) {
646 728 d = 0;
647 729 } else if (val == Py_True) {
648 730 d = 1;
649 731 } else {
650 732 ok = false;
651 733 }
652 734 } else {
653 735 ok = false;
654 736 }
655 737 return d;
656 738 }
657 739
658 740 qint64 PythonQtConv::PyObjGetLongLong(PyObject* val, bool strict, bool &ok) {
659 741 qint64 d = 0;
660 742 ok = true;
661 743 if (val->ob_type == &PyInt_Type) {
662 744 d = PyInt_AS_LONG(val);
663 745 } else if (val->ob_type == &PyLong_Type) {
664 746 d = PyLong_AsLongLong(val);
665 747 } else if (!strict) {
666 748 if (PyObject_TypeCheck(val, &PyInt_Type)) {
667 749 // support for derived int classes, e.g. for our enums
668 750 d = PyInt_AS_LONG(val);
669 751 } else if (val->ob_type == &PyFloat_Type) {
670 752 d = floor(PyFloat_AS_DOUBLE(val));
671 753 } else if (val == Py_False) {
672 754 d = 0;
673 755 } else if (val == Py_True) {
674 756 d = 1;
675 757 } else {
676 758 ok = false;
677 759 }
678 760 } else {
679 761 ok = false;
680 762 }
681 763 return d;
682 764 }
683 765
684 766 quint64 PythonQtConv::PyObjGetULongLong(PyObject* val, bool strict, bool &ok) {
685 767 quint64 d = 0;
686 768 ok = true;
687 769 if (PyObject_TypeCheck(val, &PyInt_Type)) {
688 770 d = PyInt_AS_LONG(val);
689 771 } else if (val->ob_type == &PyLong_Type) {
690 772 d = PyLong_AsLongLong(val);
691 773 } else if (!strict) {
692 774 if (PyObject_TypeCheck(val, &PyInt_Type)) {
693 775 // support for derived int classes, e.g. for our enums
694 776 d = PyInt_AS_LONG(val);
695 777 } else if (val->ob_type == &PyFloat_Type) {
696 778 d = floor(PyFloat_AS_DOUBLE(val));
697 779 } else if (val == Py_False) {
698 780 d = 0;
699 781 } else if (val == Py_True) {
700 782 d = 1;
701 783 } else {
702 784 ok = false;
703 785 }
704 786 } else {
705 787 ok = false;
706 788 }
707 789 return d;
708 790 }
709 791
710 792 double PythonQtConv::PyObjGetDouble(PyObject* val, bool strict, bool &ok) {
711 793 double d = 0;
712 794 ok = true;
713 795 if (val->ob_type == &PyFloat_Type) {
714 796 d = PyFloat_AS_DOUBLE(val);
715 797 } else if (!strict) {
716 798 if (PyObject_TypeCheck(val, &PyInt_Type)) {
717 799 d = PyInt_AS_LONG(val);
718 800 } else if (val->ob_type == &PyLong_Type) {
719 801 d = PyLong_AsLong(val);
720 802 } else if (val == Py_False) {
721 803 d = 0;
722 804 } else if (val == Py_True) {
723 805 d = 1;
724 806 } else {
725 807 ok = false;
726 808 }
727 809 } else {
728 810 ok = false;
729 811 }
730 812 return d;
731 813 }
732 814
733 815 QVariant PythonQtConv::PyObjToQVariant(PyObject* val, int type)
734 816 {
735 817 QVariant v;
736 818 bool ok = true;
737 819
738 820 if (type==-1) {
739 821 // no special type requested
740 822 if (val->ob_type==&PyString_Type || val->ob_type==&PyUnicode_Type) {
741 823 type = QVariant::String;
742 824 } else if (PyObject_TypeCheck(val, &PyInt_Type)) {
743 825 type = QVariant::Int;
744 826 } else if (val->ob_type==&PyLong_Type) {
745 827 type = QVariant::LongLong;
746 828 } else if (val->ob_type==&PyFloat_Type) {
747 829 type = QVariant::Double;
748 830 } else if (val == Py_False || val == Py_True) {
749 831 type = QVariant::Bool;
750 832 } else if (PyObject_TypeCheck(val, &PythonQtInstanceWrapper_Type)) {
751 833 PythonQtInstanceWrapper* wrap = (PythonQtInstanceWrapper*)val;
752 834 // c++ wrapper, check if the class names of the c++ objects match
753 835 if (wrap->classInfo()->isCPPWrapper()) {
754 836 if (wrap->classInfo()->metaTypeId()>0) {
755 837 // construct a new variant from the C++ object if it has a meta type (this will COPY the object!)
756 838 v = QVariant(wrap->classInfo()->metaTypeId(), wrap->_wrappedPtr);
757 839 } else {
758 840 // TODOXXX we could as well check if there is a registered meta type for "classname*", so that we may pass
759 841 // the pointer here...
760 842 // is this worth anything? we loose the knowledge of the cpp object type
761 843 v = qVariantFromValue(wrap->_wrappedPtr);
762 844 }
763 845 } else {
764 846 // this gives us a QObject pointer
765 847 QObject* myObject = wrap->_obj;
766 848 v = qVariantFromValue(myObject);
767 849 }
768 850 return v;
769 851 } else if (val->ob_type==&PyDict_Type) {
770 852 type = QVariant::Map;
771 853 } else if (val->ob_type==&PyList_Type || val->ob_type==&PyTuple_Type || PySequence_Check(val)) {
772 854 type = QVariant::List;
773 855 } else if (val == Py_None) {
774 856 // none is invalid
775 857 type = QVariant::Invalid;
776 858 } else {
777 859 // this used to be:
778 860 // type = QVariant::String;
779 861 // but now we want to transport the Python Objects directly:
780 862 PythonQtObjectPtr o(val);
781 863 v = qVariantFromValue(o);
782 864 return v;
783 865 }
784 866 }
785 867 // special type request:
786 868 switch (type) {
787 869 case QVariant::Invalid:
788 870 return v;
789 871 break;
790 872 case QVariant::Int:
791 873 {
792 874 int d = PyObjGetInt(val, false, ok);
793 875 if (ok) return QVariant(d);
794 876 }
795 877 break;
796 878 case QVariant::UInt:
797 879 {
798 880 int d = PyObjGetInt(val, false,ok);
799 881 if (ok) v = QVariant((unsigned int)d);
800 882 }
801 883 break;
802 884 case QVariant::Bool:
803 885 {
804 886 int d = PyObjGetBool(val,false,ok);
805 887 if (ok) v = QVariant((bool)(d!=0));
806 888 }
807 889 break;
808 890 case QVariant::Double:
809 891 {
810 892 double d = PyObjGetDouble(val,false,ok);
811 893 if (ok) v = QVariant(d);
812 894 break;
813 895 }
814 896 case QMetaType::Float:
815 897 {
816 898 float d = (float) PyObjGetDouble(val,false,ok);
817 899 if (ok) v = qVariantFromValue(d);
818 900 break;
819 901 }
820 902 case QMetaType::Long:
821 903 {
822 904 long d = (long) PyObjGetLongLong(val,false,ok);
823 905 if (ok) v = qVariantFromValue(d);
824 906 break;
825 907 }
826 908 case QMetaType::ULong:
827 909 {
828 910 unsigned long d = (unsigned long) PyObjGetLongLong(val,false,ok);
829 911 if (ok) v = qVariantFromValue(d);
830 912 break;
831 913 }
832 914 case QMetaType::Short:
833 915 {
834 916 short d = (short) PyObjGetInt(val,false,ok);
835 917 if (ok) v = qVariantFromValue(d);
836 918 break;
837 919 }
838 920 case QMetaType::UShort:
839 921 {
840 922 unsigned short d = (unsigned short) PyObjGetInt(val,false,ok);
841 923 if (ok) v = qVariantFromValue(d);
842 924 break;
843 925 }
844 926 case QMetaType::Char:
845 927 {
846 928 char d = (char) PyObjGetInt(val,false,ok);
847 929 if (ok) v = qVariantFromValue(d);
848 930 break;
849 931 }
850 932 case QMetaType::UChar:
851 933 {
852 934 unsigned char d = (unsigned char) PyObjGetInt(val,false,ok);
853 935 if (ok) v = qVariantFromValue(d);
854 936 break;
855 937 }
856 938
857 939 case QVariant::ByteArray:
858 940 case QVariant::String:
859 941 {
860 942 bool ok;
861 943 v = QVariant(PyObjGetString(val, false, ok));
862 944 }
863 945 break;
864 946
865 947 // these are important for MeVisLab
866 948 case QVariant::Map:
867 949 {
868 950 if (PyMapping_Check(val)) {
869 951 QMap<QString,QVariant> map;
870 952 PyObject* items = PyMapping_Items(val);
871 953 if (items) {
872 954 int count = PyList_Size(items);
873 955 PyObject* value;
874 956 PyObject* key;
875 957 PyObject* tuple;
876 958 for (int i = 0;i<count;i++) {
877 959 tuple = PyList_GetItem(items,i);
878 960 key = PyTuple_GetItem(tuple, 0);
879 961 value = PyTuple_GetItem(tuple, 1);
880 962 map.insert(PyObjGetString(key), PyObjToQVariant(value,-1));
881 963 }
882 964 Py_DECREF(items);
883 965 v = map;
884 966 }
885 967 }
886 968 }
887 969 break;
888 970 case QVariant::List:
889 971 if (PySequence_Check(val)) {
890 972 QVariantList list;
891 973 int count = PySequence_Size(val);
892 974 PyObject* value;
893 975 for (int i = 0;i<count;i++) {
894 976 value = PySequence_GetItem(val,i);
895 977 list.append(PyObjToQVariant(value, -1));
896 978 }
897 979 v = list;
898 980 }
899 981 break;
900 982 case QVariant::StringList:
901 983 {
902 984 bool ok;
903 985 QStringList l = PyObjToStringList(val, false, ok);
904 986 if (ok) {
905 987 v = l;
906 988 }
907 989 }
908 990 break;
909 991
910 992 default:
911 993 if (PyObject_TypeCheck(val, &PythonQtInstanceWrapper_Type)) {
912 994 PythonQtInstanceWrapper* wrap = (PythonQtInstanceWrapper*)val;
913 995 if (wrap->classInfo()->isCPPWrapper() && wrap->classInfo()->metaTypeId() == type) {
914 996 // construct a new variant from the C++ object if it has the same meta type
915 997 v = QVariant(type, wrap->_wrappedPtr);
916 998 } else {
917 999 v = QVariant();
918 1000 }
919 1001 } else {
920 1002 v = QVariant();
921 1003 }
922 1004 }
923 1005 return v;
924 1006 }
925 1007
926 1008 PyObject* PythonQtConv::QStringToPyObject(const QString& str)
927 1009 {
928 1010 if (str.isNull()) {
929 1011 return PyString_FromString("");
930 1012 } else {
931 1013 #ifdef WIN32
932 1014 // return PyString_FromString(str.toLatin1().data());
933 1015 return PyUnicode_FromUnicode(str.utf16(), str.length());
934 1016 #else
935 1017 return PyUnicode_DecodeUTF16((const char*)str.utf16(), str.length()*2, NULL, NULL);
936 1018 #endif
937 1019 }
938 1020 }
939 1021
940 1022 PyObject* PythonQtConv::QStringListToPyObject(const QStringList& list)
941 1023 {
942 1024 PyObject* result = PyTuple_New(list.count());
943 1025 int i = 0;
944 1026 QString str;
945 1027 foreach (str, list) {
946 1028 PyTuple_SET_ITEM(result, i, PythonQtConv::QStringToPyObject(str));
947 1029 i++;
948 1030 }
949 1031 // why is the error state bad after this?
950 1032 PyErr_Clear();
951 1033 return result;
952 1034 }
953 1035
954 1036 PyObject* PythonQtConv::QStringListToPyList(const QStringList& list)
955 1037 {
956 1038 PyObject* result = PyList_New(list.count());
957 1039 int i = 0;
958 1040 for (QStringList::ConstIterator it = list.begin(); it!=list.end(); ++it) {
959 1041 PyList_SET_ITEM(result, i, PythonQtConv::QStringToPyObject(*it));
960 1042 i++;
961 1043 }
962 1044 return result;
963 1045 }
964 1046
965 1047 PyObject* PythonQtConv::QVariantToPyObject(const QVariant& v)
966 1048 {
967 1049 return ConvertQtValueToPythonInternal(v.userType(), (void*)v.constData());
968 1050 }
969 1051
970 1052 PyObject* PythonQtConv::QVariantMapToPyObject(const QVariantMap& m) {
971 1053 PyObject* result = PyDict_New();
972 1054 QVariantMap::const_iterator t = m.constBegin();
973 1055 PyObject* key;
974 1056 PyObject* val;
975 1057 for (;t!=m.end();t++) {
976 1058 key = QStringToPyObject(t.key());
977 1059 val = QVariantToPyObject(t.value());
978 1060 PyDict_SetItem(result, key, val);
979 1061 Py_DECREF(key);
980 1062 Py_DECREF(val);
981 1063 }
982 1064 return result;
983 1065 }
984 1066
985 1067 PyObject* PythonQtConv::QVariantListToPyObject(const QVariantList& l) {
986 1068 PyObject* result = PyTuple_New(l.count());
987 1069 int i = 0;
988 1070 QVariant v;
989 1071 foreach (v, l) {
990 1072 PyTuple_SET_ITEM(result, i, PythonQtConv::QVariantToPyObject(v));
991 1073 i++;
992 1074 }
993 1075 // why is the error state bad after this?
994 1076 PyErr_Clear();
995 1077 return result;
996 1078 }
997 1079
998 1080 PyObject* PythonQtConv::ConvertQListOfPointerTypeToPythonList(QList<void*>* list, const QByteArray& typeName)
999 1081 {
1000 1082 PyObject* result = PyTuple_New(list->count());
1001 1083 int i = 0;
1002 1084 foreach (void* value, *list) {
1003 1085 PyTuple_SET_ITEM(result, i, PythonQt::priv()->wrapPtr(value, typeName));
1004 1086 i++;
1005 1087 }
1006 1088 return result;
1007 1089 }
1008 1090
1009 1091 bool PythonQtConv::ConvertPythonListToQListOfPointerType(PyObject* obj, QList<void*>* list, const QByteArray& type, bool /*strict*/)
1010 1092 {
1011 1093 bool result = false;
1012 1094 if (PySequence_Check(obj)) {
1013 1095 result = true;
1014 1096 int count = PySequence_Size(obj);
1015 1097 PyObject* value;
1016 1098 for (int i = 0;i<count;i++) {
1017 1099 value = PySequence_GetItem(obj,i);
1018 1100 if (PyObject_TypeCheck(value, &PythonQtInstanceWrapper_Type)) {
1019 1101 PythonQtInstanceWrapper* wrap = (PythonQtInstanceWrapper*)value;
1020 1102 bool ok;
1021 1103 void* object = castWrapperTo(wrap, type, ok);
1022 1104 if (ok) {
1023 1105 list->append(object);
1024 1106 } else {
1025 1107 result = false;
1026 1108 break;
1027 1109 }
1028 1110 }
1029 1111 }
1030 1112 }
1031 1113 return result;
1032 1114 }
1033 1115
1034 1116 int PythonQtConv::getInnerTemplateMetaType(const QByteArray& typeName)
1035 1117 {
1036 1118 int idx = typeName.indexOf("<");
1037 1119 if (idx>0) {
1038 1120 int idx2 = typeName.indexOf(">");
1039 1121 if (idx2>0) {
1040 1122 QByteArray innerType = typeName.mid(idx+1,idx2-idx-1);
1041 1123 return QMetaType::type(innerType.constData());
1042 1124 }
1043 1125 }
1044 1126 return QMetaType::Void;
1045 1127 }
1046 1128
1047 1129
1048 1130
1049 1131 QString PythonQtConv::qVariantToString(const QVariant& v) {
1050 1132 return CPPObjectToString(v.userType(), v.constData());
1051 1133 }
1052 1134
1053 1135 QString PythonQtConv::CPPObjectToString(int type, const void* data) {
1054 1136 QString r;
1055 1137 switch (type) {
1056 1138 case QVariant::Size: {
1057 1139 const QSize* s = static_cast<const QSize*>(data);
1058 1140 r = QString::number(s->width()) + ", " + QString::number(s->height());
1059 1141 }
1060 1142 break;
1061 1143 case QVariant::SizeF: {
1062 1144 const QSizeF* s = static_cast<const QSizeF*>(data);
1063 1145 r = QString::number(s->width()) + ", " + QString::number(s->height());
1064 1146 }
1065 1147 break;
1066 1148 case QVariant::Point: {
1067 1149 const QPoint* s = static_cast<const QPoint*>(data);
1068 1150 r = QString::number(s->x()) + ", " + QString::number(s->y());
1069 1151 }
1070 1152 break;
1071 1153 case QVariant::PointF: {
1072 1154 const QPointF* s = static_cast<const QPointF*>(data);
1073 1155 r = QString::number(s->x()) + ", " + QString::number(s->y());
1074 1156 }
1075 1157 break;
1076 1158 case QVariant::Rect: {
1077 1159 const QRect* s = static_cast<const QRect*>(data);
1078 1160 r = QString::number(s->x()) + ", " + QString::number(s->y());
1079 1161 r += ", " + QString::number(s->width()) + ", " + QString::number(s->height());
1080 1162 }
1081 1163 break;
1082 1164 case QVariant::RectF: {
1083 1165 const QRectF* s = static_cast<const QRectF*>(data);
1084 1166 r = QString::number(s->x()) + ", " + QString::number(s->y());
1085 1167 r += ", " + QString::number(s->width()) + ", " + QString::number(s->height());
1086 1168 }
1087 1169 break;
1088 1170 case QVariant::Date: {
1089 1171 const QDate* s = static_cast<const QDate*>(data);
1090 1172 r = s->toString(Qt::ISODate);
1091 1173 }
1092 1174 break;
1093 1175 case QVariant::DateTime: {
1094 1176 const QDateTime* s = static_cast<const QDateTime*>(data);
1095 1177 r = s->toString(Qt::ISODate);
1096 1178 }
1097 1179 break;
1098 1180 case QVariant::Time: {
1099 1181 const QTime* s = static_cast<const QTime*>(data);
1100 1182 r = s->toString(Qt::ISODate);
1101 1183 }
1102 1184 break;
1103 1185 case QVariant::Pixmap:
1104 1186 {
1105 1187 const QPixmap* s = static_cast<const QPixmap*>(data);
1106 1188 r = QString("Pixmap ") + QString::number(s->width()) + ", " + QString::number(s->height());
1107 1189 }
1108 1190 break;
1109 1191 case QVariant::Image:
1110 1192 {
1111 1193 const QImage* s = static_cast<const QImage*>(data);
1112 1194 r = QString("Image ") + QString::number(s->width()) + ", " + QString::number(s->height());
1113 1195 }
1114 1196 break;
1115 1197 case QVariant::Url:
1116 1198 {
1117 1199 const QUrl* s = static_cast<const QUrl*>(data);
1118 1200 r = s->toString();
1119 1201 }
1120 1202 break;
1121 1203 //TODO: add more printing for other variant types
1122 1204 default:
1123 1205 // this creates a copy, but that should not be expensive for typical simple variants
1124 1206 // (but we do not want to do this for our won user types!
1125 1207 if (type>0 && type < (int)QVariant::UserType) {
1126 1208 QVariant v(type, data);
1127 1209 r = v.toString();
1128 1210 }
1129 1211 }
1130 1212 return r;
1131 1213 }
@@ -1,204 +1,207
1 1 #ifndef _PYTHONQTCONVERSION_H
2 2 #define _PYTHONQTCONVERSION_H
3 3
4 4 /*
5 5 *
6 6 * Copyright (C) 2006 MeVis Research GmbH All Rights Reserved.
7 7 *
8 8 * This library is free software; you can redistribute it and/or
9 9 * modify it under the terms of the GNU Lesser General Public
10 10 * License as published by the Free Software Foundation; either
11 11 * version 2.1 of the License, or (at your option) any later version.
12 12 *
13 13 * This library is distributed in the hope that it will be useful,
14 14 * but WITHOUT ANY WARRANTY; without even the implied warranty of
15 15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
16 16 * Lesser General Public License for more details.
17 17 *
18 18 * Further, this software is distributed without any warranty that it is
19 19 * free of the rightful claim of any third person regarding infringement
20 20 * or the like. Any license provided herein, whether implied or
21 21 * otherwise, applies only to this software file. Patent licenses, if
22 22 * any, provided herein do not apply to combinations of this program with
23 23 * other software, or any other product whatsoever.
24 24 *
25 25 * You should have received a copy of the GNU Lesser General Public
26 26 * License along with this library; if not, write to the Free Software
27 27 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
28 28 *
29 29 * Contact information: MeVis Research GmbH, Universitaetsallee 29,
30 30 * 28359 Bremen, Germany or:
31 31 *
32 32 * http://www.mevis.de
33 33 *
34 34 */
35 35
36 36 //----------------------------------------------------------------------------------
37 37 /*!
38 38 // \file PythonQtConversion.h
39 39 // \author Florian Link
40 40 // \author Last changed by $Author: florian $
41 41 // \date 2006-05
42 42 */
43 43 //----------------------------------------------------------------------------------
44 44
45 45 #include "PythonQt.h"
46 46 #include "PythonQtMisc.h"
47 47 #include "PythonQtClassInfo.h"
48 48 #include "PythonQtMethodInfo.h"
49 49
50 50 #include <QWidget>
51 51 #include <QList>
52 52 #include <vector>
53 53
54 54 typedef PyObject* PythonQtConvertMetaTypeToPythonCB(const void* inObject, int metaTypeId);
55 55 typedef bool PythonQtConvertPythonToMetaTypeCB(PyObject* inObject, void* outObject, int metaTypeId, bool strict);
56 56
57 57 #define PythonQtRegisterListTemplateConverter(type, innertype) \
58 58 { int typeId = qRegisterMetaType<type<innertype> >(#type"<"#innertype">"); \
59 59 PythonQtConv::registerPythonToMetaTypeConverter(typeId, PythonQtConvertPythonListToListOfValueType<type<innertype>, innertype>); \
60 60 PythonQtConv::registerMetaTypeToPythonConverter(typeId, PythonQtConvertListOfValueTypeToPythonList<type<innertype>, innertype>); \
61 61 }
62 62
63 63 #define PythonQtRegisterToolClassesTemplateConverter(innertype) \
64 64 PythonQtRegisterListTemplateConverter(QList, innertype); \
65 65 PythonQtRegisterListTemplateConverter(QVector, innertype); \
66 66 PythonQtRegisterListTemplateConverter(std::vector, innertype);
67 67 // TODO: add QHash etc. here!
68 68
69 69 //! a static class that offers methods for type conversion
70 70 class PYTHONQT_EXPORT PythonQtConv {
71 71
72 72 public:
73 73
74 74 //! get a ref counted True or False Python object
75 75 static PyObject* GetPyBool(bool val);
76 76
77 77 //! converts the Qt parameter given in \c data, interpreting it as a \c info parameter, into a Python object,
78 78 static PyObject* ConvertQtValueToPython(const PythonQtMethodInfo::ParameterInfo& info, const void* data);
79 79
80 80 //! convert python object to Qt (according to the given parameter) and if the conversion should be strict (classInfo is currently not used anymore)
81 81 static void* ConvertPythonToQt(const PythonQtMethodInfo::ParameterInfo& info, PyObject* obj, bool strict, PythonQtClassInfo* classInfo, void* alreadyAllocatedCPPObject = NULL);
82 82
83 83 //! creates a data storage for the passed parameter type and returns a void pointer to be set as arg[0] of qt_metacall
84 84 static void* CreateQtReturnValue(const PythonQtMethodInfo::ParameterInfo& info);
85 85
86 86 //! converts QString to Python string (unicode!)
87 87 static PyObject* QStringToPyObject(const QString& str);
88 88
89 89 //! converts QStringList to Python tuple
90 90 static PyObject* QStringListToPyObject(const QStringList& list);
91 91
92 92 //! converts QStringList to Python list
93 93 static PyObject* QStringListToPyList(const QStringList& list);
94 94
95 95 //! get string representation of py object
96 96 static QString PyObjGetRepresentation(PyObject* val);
97 97
98 98 //! get string value from py object
99 99 static QString PyObjGetString(PyObject* val) { bool ok; QString s = PyObjGetString(val, false, ok); return s; }
100 100 //! get string value from py object
101 101 static QString PyObjGetString(PyObject* val, bool strict, bool &ok);
102 102 //! get bytes from py object
103 103 static QByteArray PyObjGetBytes(PyObject* val, bool strict, bool &ok);
104 104 //! get int from py object
105 105 static int PyObjGetInt(PyObject* val, bool strict, bool &ok);
106 106 //! get int64 from py object
107 107 static qint64 PyObjGetLongLong(PyObject* val, bool strict, bool &ok);
108 108 //! get int64 from py object
109 109 static quint64 PyObjGetULongLong(PyObject* val, bool strict, bool &ok);
110 110 //! get double from py object
111 111 static double PyObjGetDouble(PyObject* val, bool strict, bool &ok);
112 112 //! get bool from py object
113 113 static bool PyObjGetBool(PyObject* val, bool strict, bool &ok);
114 114
115 115 //! create a string list from python sequence
116 116 static QStringList PyObjToStringList(PyObject* val, bool strict, bool& ok);
117 117
118 118 //! convert python object to qvariant, if type is given it will try to create a qvariant of that type, otherwise
119 119 //! it will guess from the python type
120 120 static QVariant PyObjToQVariant(PyObject* val, int type = -1);
121 121
122 122 //! convert QVariant from PyObject
123 123 static PyObject* QVariantToPyObject(const QVariant& v);
124 124
125 125 static PyObject* QVariantMapToPyObject(const QVariantMap& m);
126 126 static PyObject* QVariantListToPyObject(const QVariantList& l);
127 127
128 128 //! get human readable string from qvariant
129 129 static QString qVariantToString(const QVariant& v);
130 130
131 131 //! get human readable string from CPP object (when the metatype is known)
132 132 static QString CPPObjectToString(int type, const void* data);
133 133
134 134 //! register a converter callback from python to cpp for given metatype
135 135 static void registerPythonToMetaTypeConverter(int metaTypeId, PythonQtConvertPythonToMetaTypeCB* cb) { _pythonToMetaTypeConverters.insert(metaTypeId, cb); }
136 136
137 137 //! register a converter callback from cpp to python for given metatype
138 138 static void registerMetaTypeToPythonConverter(int metaTypeId, PythonQtConvertMetaTypeToPythonCB* cb) { _metaTypeToPythonConverters.insert(metaTypeId, cb); }
139 139
140 140 //! returns the inner type id of a simple template of the form SomeObject<InnerType>
141 141 static int getInnerTemplateMetaType(const QByteArray& typeName);
142 142
143 143 //! converts the Qt parameter given in \c data, interpreting it as a \c type registered qvariant/meta type, into a Python object,
144 144 static PyObject* ConvertQtValueToPythonInternal(int type, const void* data);
145 145
146 146 public:
147 147
148 148 static PythonQtValueStorage<qint64, 128> global_valueStorage;
149 149 static PythonQtValueStorage<void*, 128> global_ptrStorage;
150 150 static PythonQtValueStorage<QVariant, 32> global_variantStorage;
151 151
152 152 protected:
153 153 static QHash<int, PythonQtConvertMetaTypeToPythonCB*> _metaTypeToPythonConverters;
154 154 static QHash<int, PythonQtConvertPythonToMetaTypeCB*> _pythonToMetaTypeConverters;
155
156 //! handle automatic conversion of some special types (QColor, QBrush, ...)
157 static void* handlePythonToQtAutoConversion(int typeId, PyObject* obj, void* alreadyAllocatedCPPObject);
155 158
156 159 //! converts the list of pointers of given type to Python
157 160 static PyObject* ConvertQListOfPointerTypeToPythonList(QList<void*>* list, const QByteArray& type);
158 161 //! tries to convert the python object to a QList of pointers to \c type objects, returns true on success
159 162 static bool ConvertPythonListToQListOfPointerType(PyObject* obj, QList<void*>* list, const QByteArray& type, bool strict);
160 163
161 164 //! cast wrapper to given className if possible
162 165 static void* castWrapperTo(PythonQtInstanceWrapper* wrapper, const QByteArray& className, bool& ok);
163 166 };
164 167
165 168 template<class ListType, class T>
166 169 PyObject* PythonQtConvertListOfValueTypeToPythonList(const void* /*QList<T>* */ inList, int metaTypeId)
167 170 {
168 171 ListType* list = (ListType*)inList;
169 172 static const int innerType = PythonQtConv::getInnerTemplateMetaType(QByteArray(QMetaType::typeName(metaTypeId)));
170 173 PyObject* result = PyTuple_New(list->size());
171 174 int i = 0;
172 175 foreach (const T& value, *list) {
173 176 PyTuple_SET_ITEM(result, i, PythonQtConv::ConvertQtValueToPythonInternal(innerType, &value));
174 177 i++;
175 178 }
176 179 return result;
177 180 }
178 181
179 182 template<class ListType, class T>
180 183 bool PythonQtConvertPythonListToListOfValueType(PyObject* obj, void* /*QList<T>* */ outList, int metaTypeId, bool /*strict*/)
181 184 {
182 185 ListType* list = (ListType*)outList;
183 186 static const int innerType = PythonQtConv::getInnerTemplateMetaType(QByteArray(QMetaType::typeName(metaTypeId)));
184 187 bool result = false;
185 188 if (PySequence_Check(obj)) {
186 189 result = true;
187 190 int count = PySequence_Size(obj);
188 191 PyObject* value;
189 192 for (int i = 0;i<count;i++) {
190 193 value = PySequence_GetItem(obj,i);
191 194 // this is quite some overhead, but it avoids having another large switch...
192 195 QVariant v = PythonQtConv::PyObjToQVariant(value, innerType);
193 196 if (v.isValid()) {
194 197 list->push_back(qVariantValue<T>(v));
195 198 } else {
196 199 result = false;
197 200 break;
198 201 }
199 202 }
200 203 }
201 204 return result;
202 205 }
203 206
204 207 #endif
@@ -1,328 +1,328
1 1 /*
2 2 *
3 3 * Copyright (C) 2006 MeVis Research GmbH All Rights Reserved.
4 4 *
5 5 * This library is free software; you can redistribute it and/or
6 6 * modify it under the terms of the GNU Lesser General Public
7 7 * License as published by the Free Software Foundation; either
8 8 * version 2.1 of the License, or (at your option) any later version.
9 9 *
10 10 * This library is distributed in the hope that it will be useful,
11 11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13 13 * Lesser General Public License for more details.
14 14 *
15 15 * Further, this software is distributed without any warranty that it is
16 16 * free of the rightful claim of any third person regarding infringement
17 17 * or the like. Any license provided herein, whether implied or
18 18 * otherwise, applies only to this software file. Patent licenses, if
19 19 * any, provided herein do not apply to combinations of this program with
20 20 * other software, or any other product whatsoever.
21 21 *
22 22 * You should have received a copy of the GNU Lesser General Public
23 23 * License along with this library; if not, write to the Free Software
24 24 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
25 25 *
26 26 * Contact information: MeVis Research GmbH, Universitaetsallee 29,
27 27 * 28359 Bremen, Germany or:
28 28 *
29 29 * http://www.mevis.de
30 30 *
31 31 */
32 32
33 33 //----------------------------------------------------------------------------------
34 34 /*!
35 35 // \file PythonQtMethodInfo.cpp
36 36 // \author Florian Link
37 37 // \author Last changed by $Author: florian $
38 38 // \date 2006-05
39 39 */
40 40 //----------------------------------------------------------------------------------
41 41
42 42 #include "PythonQtMethodInfo.h"
43 43 #include "PythonQtClassInfo.h"
44 44 #include <iostream>
45 45
46 46 QHash<QByteArray, PythonQtMethodInfo*> PythonQtMethodInfo::_cachedSignatures;
47 47 QHash<QByteArray, QByteArray> PythonQtMethodInfo::_parameterNameAliases;
48 48
49 49 PythonQtMethodInfo::PythonQtMethodInfo(const QMetaMethod& meta, PythonQtClassInfo* classInfo)
50 50 {
51 51 #ifdef PYTHONQT_DEBUG
52 52 QByteArray sig(meta.signature());
53 53 sig = sig.mid(sig.indexOf('('));
54 54 QByteArray fullSig = QByteArray(meta.typeName()) + " " + sig;
55 55 std::cout << "caching " << fullSig.data() << std::endl;
56 56 #endif
57 57
58 58 ParameterInfo type;
59 59 fillParameterInfo(type, QByteArray(meta.typeName()), classInfo);
60 60 _parameters.append(type);
61 61 QByteArray name;
62 62 QList<QByteArray> names = meta.parameterTypes();
63 63 foreach (name, names) {
64 64 fillParameterInfo(type, name, classInfo);
65 65 _parameters.append(type);
66 66 }
67 67 }
68 68
69 69 const PythonQtMethodInfo* PythonQtMethodInfo::getCachedMethodInfo(const QMetaMethod& signal, PythonQtClassInfo* classInfo)
70 70 {
71 71 QByteArray sig(signal.signature());
72 72 sig = sig.mid(sig.indexOf('('));
73 73 QByteArray fullSig = QByteArray(signal.typeName()) + " " + sig;
74 74 PythonQtMethodInfo* result = _cachedSignatures.value(fullSig);
75 75 if (!result) {
76 76 result = new PythonQtMethodInfo(signal, classInfo);
77 77 _cachedSignatures.insert(fullSig, result);
78 78 }
79 79 return result;
80 80 }
81 81
82 82 const PythonQtMethodInfo* PythonQtMethodInfo::getCachedMethodInfoFromMetaObjectAndSignature(const QMetaObject* metaObject, const char* signature)
83 83 {
84 84 QByteArray sig = QMetaObject::normalizedSignature(signature);
85 85 int idx = metaObject->indexOfMethod(sig);
86 86 QMetaMethod meta = metaObject->method(idx);
87 87 return PythonQtMethodInfo::getCachedMethodInfo(meta, NULL);
88 88 }
89 89
90 90 void PythonQtMethodInfo::fillParameterInfo(ParameterInfo& type, const QByteArray& orgName, PythonQtClassInfo* classInfo)
91 91 {
92 92 QByteArray name = orgName;
93 93
94 94 type.enumWrapper = NULL;
95 95
96 96 int len = name.length();
97 97 if (len>0) {
98 98 if (strncmp(name.constData(), "const ", 6)==0) {
99 99 name = name.mid(6);
100 100 len -= 6;
101 101 type.isConst = true;
102 102 } else {
103 103 type.isConst = false;
104 104 }
105 105 bool hadPointer = false;
106 106 bool hadReference = false;
107 107 // remove * and & from the end of the string, handle & and * the same way
108 108 while (name.at(len-1) == '*') {
109 109 len--;
110 110 hadPointer = true;
111 111 }
112 112 while (name.at(len-1) == '&') {
113 113 len--;
114 114 hadReference = true;
115 115 }
116 116 if (len!=name.length()) {
117 117 name = name.left(len);
118 118 }
119 119 type.isPointer = hadPointer;
120 120
121 121 QByteArray alias = _parameterNameAliases.value(name);
122 122 if (!alias.isEmpty()) {
123 123 name = alias;
124 124 }
125 125
126 126 type.typeId = nameToType(name);
127 127 if (!type.isPointer && type.typeId == Unknown) {
128 128 type.typeId = QMetaType::type(name.constData());
129 129 if (type.typeId == QMetaType::Void) {
130 130 type.typeId = Unknown;
131 131 }
132 132 }
133 133 type.name = name;
134 134
135 135 if (type.typeId == PythonQtMethodInfo::Unknown || type.typeId >= QMetaType::User) {
136 136 bool isLocalEnum;
137 137 // TODOXXX: make use of this flag!
138 type.enumWrapper = PythonQtClassInfo::findEnumWrapper(type.name, classInfo, isLocalEnum);
138 type.enumWrapper = PythonQtClassInfo::findEnumWrapper(type.name, classInfo, &isLocalEnum);
139 139 }
140 140 } else {
141 141 type.typeId = QMetaType::Void;
142 142 type.isPointer = false;
143 143 type.isConst = false;
144 144 }
145 145 }
146 146
147 147 int PythonQtMethodInfo::nameToType(const char* name)
148 148 {
149 149 if (_parameterTypeDict.isEmpty()) {
150 150 // we could also use QMetaType::nameToType, but that does a string compare search
151 151 // and does not support QVariant
152 152
153 153 // QMetaType names
154 154 _parameterTypeDict.insert("long", QMetaType::Long);
155 155 _parameterTypeDict.insert("int", QMetaType::Int);
156 156 _parameterTypeDict.insert("short", QMetaType::Short);
157 157 _parameterTypeDict.insert("char", QMetaType::Char);
158 158 _parameterTypeDict.insert("ulong", QMetaType::ULong);
159 159 _parameterTypeDict.insert("unsigned long", QMetaType::ULong);
160 160 _parameterTypeDict.insert("uint", QMetaType::UInt);
161 161 _parameterTypeDict.insert("unsigned int", QMetaType::UInt);
162 162 _parameterTypeDict.insert("ushort", QMetaType::UShort);
163 163 _parameterTypeDict.insert("unsigned short", QMetaType::UShort);
164 164 _parameterTypeDict.insert("uchar", QMetaType::UChar);
165 165 _parameterTypeDict.insert("unsigned char", QMetaType::UChar);
166 166 _parameterTypeDict.insert("bool", QMetaType::Bool);
167 167 _parameterTypeDict.insert("float", QMetaType::Float);
168 168 _parameterTypeDict.insert("double", QMetaType::Double);
169 169 _parameterTypeDict.insert("qreal", QMetaType::Double);
170 170 _parameterTypeDict.insert("QChar", QMetaType::QChar);
171 171 _parameterTypeDict.insert("QByteArray", QMetaType::QByteArray);
172 172 _parameterTypeDict.insert("Q3CString", QMetaType::QByteArray);
173 173 _parameterTypeDict.insert("QString", QMetaType::QString);
174 174 _parameterTypeDict.insert("", QMetaType::Void);
175 175 _parameterTypeDict.insert("void", QMetaType::Void);
176 176 // QVariant names
177 177 _parameterTypeDict.insert("Q_LLONG", QMetaType::LongLong);
178 178 _parameterTypeDict.insert("Q_ULLONG", QMetaType::ULongLong);
179 179 _parameterTypeDict.insert("qlonglong", QMetaType::LongLong);
180 180 _parameterTypeDict.insert("qulonglong", QMetaType::ULongLong);
181 181 _parameterTypeDict.insert("qint64", QMetaType::LongLong);
182 182 _parameterTypeDict.insert("quint64", QMetaType::ULongLong);
183 183 _parameterTypeDict.insert("QIconSet", QMetaType::QIcon);
184 184 _parameterTypeDict.insert("QVariantMap", QMetaType::QVariantMap);
185 185 _parameterTypeDict.insert("QVariantList", QMetaType::QVariantList);
186 186 _parameterTypeDict.insert("QMap<QString,QVariant>", QMetaType::QVariantMap);
187 187 _parameterTypeDict.insert("QList<QVariant>", QMetaType::QVariantList);
188 188 _parameterTypeDict.insert("QStringList", QMetaType::QStringList);
189 189 _parameterTypeDict.insert("QBitArray", QMetaType::QBitArray);
190 190 _parameterTypeDict.insert("QDate", QMetaType::QDate);
191 191 _parameterTypeDict.insert("QTime", QMetaType::QTime);
192 192 _parameterTypeDict.insert("QDateTime", QMetaType::QDateTime);
193 193 _parameterTypeDict.insert("QUrl", QMetaType::QUrl);
194 194 _parameterTypeDict.insert("QLocale", QMetaType::QLocale);
195 195 _parameterTypeDict.insert("QRect", QMetaType::QRect);
196 196 _parameterTypeDict.insert("QRectf", QMetaType::QRectF);
197 197 _parameterTypeDict.insert("QSize", QMetaType::QSize);
198 198 _parameterTypeDict.insert("QSizef", QMetaType::QSizeF);
199 199 _parameterTypeDict.insert("QLine", QMetaType::QLine);
200 200 _parameterTypeDict.insert("QLinef", QMetaType::QLineF);
201 201 _parameterTypeDict.insert("QPoint", QMetaType::QPoint);
202 202 _parameterTypeDict.insert("QPointf", QMetaType::QPointF);
203 203 _parameterTypeDict.insert("QRegExp", QMetaType::QRegExp);
204 204 // _parameterTypeDict.insert("QColorGroup", QMetaType::QColorGroup);
205 205 _parameterTypeDict.insert("QFont", QMetaType::QFont);
206 206 _parameterTypeDict.insert("QPixmap", QMetaType::QPixmap);
207 207 _parameterTypeDict.insert("QBrush", QMetaType::QBrush);
208 208 _parameterTypeDict.insert("QColor", QMetaType::QColor);
209 209 _parameterTypeDict.insert("QCursor", QMetaType::QCursor);
210 210 _parameterTypeDict.insert("QPalette", QMetaType::QPalette);
211 211 _parameterTypeDict.insert("QIcon", QMetaType::QIcon);
212 212 _parameterTypeDict.insert("QImage", QMetaType::QPolygon);
213 213 _parameterTypeDict.insert("QRegion", QMetaType::QRegion);
214 214 _parameterTypeDict.insert("QBitmap", QMetaType::QBitmap);
215 215 _parameterTypeDict.insert("QSizePolicy", QMetaType::QSizePolicy);
216 216 _parameterTypeDict.insert("QKeySequence", QMetaType::QKeySequence);
217 217 _parameterTypeDict.insert("QPen", QMetaType::QPen);
218 218 _parameterTypeDict.insert("QTextLength", QMetaType::QTextLength);
219 219 _parameterTypeDict.insert("QTextFormat", QMetaType::QTextFormat);
220 220 _parameterTypeDict.insert("QMatrix", QMetaType::QMatrix);
221 221 _parameterTypeDict.insert("QVariant", PythonQtMethodInfo::Variant);
222 222 // own special types... (none so far, could be e.g. ObjectList
223 223 }
224 224 QHash<QByteArray, int>::const_iterator it = _parameterTypeDict.find(name);
225 225 if (it!=_parameterTypeDict.end()) {
226 226 return it.value();
227 227 } else {
228 228 return PythonQtMethodInfo::Unknown;
229 229 }
230 230 }
231 231
232 232 void PythonQtMethodInfo::cleanupCachedMethodInfos()
233 233 {
234 234 QHashIterator<QByteArray, PythonQtMethodInfo *> i(_cachedSignatures);
235 235 while (i.hasNext()) {
236 236 delete i.next().value();
237 237 }
238 238 }
239 239
240 240 void PythonQtMethodInfo::addParameterTypeAlias(const QByteArray& alias, const QByteArray& name)
241 241 {
242 242 _parameterNameAliases.insert(alias, name);
243 243 }
244 244
245 245 //-------------------------------------------------------------------------------------------------
246 246
247 247 void PythonQtSlotInfo::deleteOverloadsAndThis()
248 248 {
249 249 PythonQtSlotInfo* cur = this;
250 250 while(cur->nextInfo()) {
251 251 PythonQtSlotInfo* next = cur->nextInfo();
252 252 delete cur;
253 253 cur = next;
254 254 }
255 255 }
256 256
257 257
258 258 QString PythonQtSlotInfo::fullSignature()
259 259 {
260 260 bool skipFirstArg = isInstanceDecorator();
261 261 QString result = _meta.typeName();
262 262 QByteArray sig = slotName();
263 263 QList<QByteArray> names = _meta.parameterNames();
264 264
265 265 bool isStatic = false;
266 266 bool isConstructor = false;
267 267 bool isDestructor = false;
268 268
269 269 if (_type == ClassDecorator) {
270 270 if (sig.startsWith("new_")) {
271 271 sig = sig.mid(strlen("new_"));
272 272 isConstructor = true;
273 273 } else if (sig.startsWith("delete_")) {
274 274 sig = sig.mid(strlen("delete_"));
275 275 isDestructor = true;
276 276 } else if(sig.startsWith("static_")) {
277 277 isStatic = true;
278 278 sig = sig.mid(strlen("static_"));
279 279 int idx = sig.indexOf("_");
280 280 if (idx>=0) {
281 281 sig = sig.mid(idx+1);
282 282 }
283 283 }
284 284 }
285 285
286 286 result += QByteArray(" ") + sig;
287 287 result += "(";
288 288
289 289 int lastEntry = _parameters.count()-1;
290 290 for (int i = skipFirstArg?2:1; i<_parameters.count(); i++) {
291 291 if (_parameters.at(i).isConst) {
292 292 result += "const ";
293 293 }
294 294 result += _parameters.at(i).name;
295 295 if (_parameters.at(i).isPointer) {
296 296 result += "*";
297 297 }
298 298 if (!names.at(i-1).isEmpty()) {
299 299 result += " ";
300 300 result += names.at(i-1);
301 301 }
302 302 if (i!=lastEntry) {
303 303 result += ", ";
304 304 }
305 305 }
306 306 result += ")";
307 307
308 308 if (isStatic) {
309 309 result = QString("static ") + result;
310 310 }
311 311 if (isConstructor) {
312 312 // result = QString("constructor ") + result;
313 313 }
314 314 if (isDestructor) {
315 315 result = QString("~") + result;
316 316 }
317 317 return result;
318 318 }
319 319
320 320
321 321 QByteArray PythonQtSlotInfo::slotName()
322 322 {
323 323 QByteArray sig(_meta.signature());
324 324 int idx = sig.indexOf('(');
325 325 sig = sig.left(idx);
326 326 return sig;
327 327 }
328 328
General Comments 0
You need to be logged in to leave comments. Login now