##// END OF EJS Templates
added support for dynamic properties...
florianlink -
r85:90c5da76b56c
parent child
Show More
@@ -1,843 +1,845
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 if (!_meta) return false;
122
121 123 bool found = false;
122 124 bool nameMapped = false;
123 125 const char* attributeName = memberName;
124 126 // look for properties
125 127 int i = _meta->indexOfProperty(attributeName);
126 128 if (i==-1) {
127 129 // try to map name to objectName
128 130 if (qstrcmp(attributeName, "name")==0) {
129 131 attributeName = "objectName";
130 132 nameMapped = true;
131 133 i = _meta->indexOfProperty(attributeName);
132 134 }
133 135 }
134 136 if (i!=-1) {
135 137 PythonQtMemberInfo newInfo(_meta->property(i));
136 138 _cachedMembers.insert(attributeName, newInfo);
137 139 if (nameMapped) {
138 140 _cachedMembers.insert(memberName, newInfo);
139 141 }
140 142 #ifdef PYTHONQT_DEBUG
141 143 std::cout << "caching property " << memberName << " on " << _meta->className() << std::endl;
142 144 #endif
143 145 found = true;
144 146 }
145 147 return found;
146 148 }
147 149
148 150 PythonQtSlotInfo* PythonQtClassInfo::recursiveFindDecoratorSlotsFromDecoratorProvider(const char* memberName, PythonQtSlotInfo* inputInfo, bool &found, QHash<QByteArray, PythonQtMemberInfo>& memberCache, int upcastingOffset)
149 151 {
150 152 inputInfo = findDecoratorSlotsFromDecoratorProvider(memberName, inputInfo, found, memberCache, upcastingOffset);
151 153 foreach(const ParentClassInfo& info, _parentClasses) {
152 154 inputInfo = info._parent->recursiveFindDecoratorSlotsFromDecoratorProvider(memberName, inputInfo, found, memberCache, upcastingOffset+info._upcastingOffset);
153 155 }
154 156 return inputInfo;
155 157 }
156 158
157 159 PythonQtSlotInfo* PythonQtClassInfo::findDecoratorSlotsFromDecoratorProvider(const char* memberName, PythonQtSlotInfo* tail, bool &found, QHash<QByteArray, PythonQtMemberInfo>& memberCache, int upcastingOffset) {
158 160 QObject* decoratorProvider = decorator();
159 161 int memberNameLen = strlen(memberName);
160 162 if (decoratorProvider) {
161 163 //qDebug()<< "looking " << decoratorProvider->metaObject()->className() << " " << memberName << " " << upcastingOffset;
162 164 const QMetaObject* meta = decoratorProvider->metaObject();
163 165 int numMethods = meta->methodCount();
164 166 int startFrom = QObject::staticMetaObject.methodCount();
165 167 for (int i = startFrom; i < numMethods; i++) {
166 168 QMetaMethod m = meta->method(i);
167 169 if ((m.methodType() == QMetaMethod::Method ||
168 170 m.methodType() == QMetaMethod::Slot) && m.access() == QMetaMethod::Public) {
169 171
170 172 const char* sigStart = m.signature();
171 173 bool isClassDeco = false;
172 174 if (qstrncmp(sigStart, "static_", 7)==0) {
173 175 // skip the static_classname_ part of the string
174 176 sigStart += 7 + 1 + strlen(className());
175 177 isClassDeco = true;
176 178 } else if (qstrncmp(sigStart, "new_", 4)==0) {
177 179 isClassDeco = true;
178 180 } else if (qstrncmp(sigStart, "delete_", 7)==0) {
179 181 isClassDeco = true;
180 182 }
181 183 // find the first '('
182 184 int offset = findCharOffset(sigStart, '(');
183 185
184 186 // XXX no checking is currently done if the slots have correct first argument or not...
185 187
186 188 // check if same length and same name
187 189 if (memberNameLen == offset && qstrncmp(memberName, sigStart, offset)==0) {
188 190 found = true;
189 191 PythonQtSlotInfo* info = new PythonQtSlotInfo(this, m, i, decoratorProvider, isClassDeco?PythonQtSlotInfo::ClassDecorator:PythonQtSlotInfo::InstanceDecorator);
190 192 info->setUpcastingOffset(upcastingOffset);
191 193 //qDebug()<< "adding " << decoratorProvider->metaObject()->className() << " " << memberName << " " << upcastingOffset;
192 194 if (tail) {
193 195 tail->setNextInfo(info);
194 196 } else {
195 197 PythonQtMemberInfo newInfo(info);
196 198 memberCache.insert(memberName, newInfo);
197 199 }
198 200 tail = info;
199 201 }
200 202 }
201 203 }
202 204 }
203 205
204 206 tail = findDecoratorSlots(memberName, memberNameLen, tail, found, memberCache, upcastingOffset);
205 207
206 208 return tail;
207 209 }
208 210
209 211 bool PythonQtClassInfo::lookForMethodAndCache(const char* memberName)
210 212 {
211 213 bool found = false;
212 214 int memberNameLen = strlen(memberName);
213 215 PythonQtSlotInfo* tail = NULL;
214 216 if (_meta) {
215 217 int numMethods = _meta->methodCount();
216 218 for (int i = 0; i < numMethods; i++) {
217 219 QMetaMethod m = _meta->method(i);
218 220 if (((m.methodType() == QMetaMethod::Method ||
219 221 m.methodType() == QMetaMethod::Slot) && m.access() == QMetaMethod::Public)
220 222 || m.methodType()==QMetaMethod::Signal) {
221 223
222 224 const char* sigStart = m.signature();
223 225 // find the first '('
224 226 int offset = findCharOffset(sigStart, '(');
225 227
226 228 // check if same length and same name
227 229 if (memberNameLen == offset && qstrncmp(memberName, sigStart, offset)==0) {
228 230 found = true;
229 231 PythonQtSlotInfo* info = new PythonQtSlotInfo(this, m, i);
230 232 if (tail) {
231 233 tail->setNextInfo(info);
232 234 } else {
233 235 PythonQtMemberInfo newInfo(info);
234 236 _cachedMembers.insert(memberName, newInfo);
235 237 }
236 238 tail = info;
237 239 }
238 240 }
239 241 }
240 242 }
241 243
242 244 // look for dynamic decorators in this class and in derived classes
243 245 tail = recursiveFindDecoratorSlotsFromDecoratorProvider(memberName, tail, found, _cachedMembers, 0);
244 246
245 247 return found;
246 248 }
247 249
248 250 bool PythonQtClassInfo::lookForEnumAndCache(const QMetaObject* meta, const char* memberName)
249 251 {
250 252 bool found = false;
251 253 // look for enum values
252 254 int enumCount = meta->enumeratorCount();
253 255 for (int i=0;i<enumCount; i++) {
254 256 QMetaEnum e = meta->enumerator(i);
255 257 // we do not want flags, they will cause our values to appear two times
256 258 if (e.isFlag()) continue;
257 259
258 260 for (int j=0; j < e.keyCount(); j++) {
259 261 if (qstrcmp(e.key(j), memberName)==0) {
260 262 PyObject* enumType = findEnumWrapper(e.name());
261 263 if (enumType) {
262 264 PythonQtObjectPtr enumValuePtr;
263 265 enumValuePtr.setNewRef(PythonQtPrivate::createEnumValueInstance(enumType, e.value(j)));
264 266 PythonQtMemberInfo newInfo(enumValuePtr);
265 267 _cachedMembers.insert(memberName, newInfo);
266 268 #ifdef PYTHONQT_DEBUG
267 269 std::cout << "caching enum " << memberName << " on " << meta->className() << std::endl;
268 270 #endif
269 271 found = true;
270 272 break;
271 273 } else {
272 274 std::cout << "enum " << e.name() << " not found on " << className() << std::endl;
273 275 }
274 276 }
275 277 }
276 278 }
277 279 return found;
278 280 }
279 281
280 282 PythonQtMemberInfo PythonQtClassInfo::member(const char* memberName)
281 283 {
282 284 PythonQtMemberInfo info = _cachedMembers.value(memberName);
283 285 if (info._type != PythonQtMemberInfo::Invalid) {
284 286 return info;
285 287 } else {
286 288 bool found = false;
287 289
288 290 found = lookForPropertyAndCache(memberName);
289 291 if (!found) {
290 292 found = lookForMethodAndCache(memberName);
291 293 }
292 294 if (!found) {
293 295 if (_meta) {
294 296 // check enums in our meta object directly
295 297 found = lookForEnumAndCache(_meta, memberName);
296 298 }
297 299 if (!found) {
298 300 // check enums in the class hierachy of CPP classes
299 301 // look for dynamic decorators in this class and in derived classes
300 302 QList<QObject*> decoObjects;
301 303 recursiveCollectDecoratorObjects(decoObjects);
302 304 foreach(QObject* deco, decoObjects) {
303 305 // call on ourself for caching, but with different metaObject():
304 306 found = lookForEnumAndCache(deco->metaObject(), memberName);
305 307 if (found) {
306 308 break;
307 309 }
308 310 }
309 311 }
310 312 }
311 313 if (!found) {
312 314 // maybe it is an enum wrapper?
313 315 PyObject* p = findEnumWrapper(memberName);
314 316 if (p) {
315 317 info._type = PythonQtMemberInfo::EnumWrapper;
316 318 info._enumWrapper = p;
317 319 _cachedMembers.insert(memberName, info);
318 320 found = true;
319 321 }
320 322 }
321 323 if (!found) {
322 324 // since python keywords can not be looked up, we check if the name contains a single trailing _
323 325 // and remove that and look again, so that we e.g. find exec on an exec_ lookup
324 326 QByteArray mbrName(memberName);
325 327 if ((mbrName.length()>2) &&
326 328 (mbrName.at(mbrName.length()-1) == '_') &&
327 329 (mbrName.at(mbrName.length()-2) != '_')) {
328 330 mbrName = mbrName.mid(0,mbrName.length()-1);
329 331 found = lookForMethodAndCache(mbrName.constData());
330 332 if (found) {
331 333 return _cachedMembers.value(mbrName);
332 334 }
333 335 }
334 336 }
335 337 if (!found) {
336 338 // we store a NotFound member, so that we get a quick result for non existing members (e.g. operator_equal lookup)
337 339 info._type = PythonQtMemberInfo::NotFound;
338 340 _cachedMembers.insert(memberName, info);
339 341 }
340 342 }
341 343
342 344 return _cachedMembers.value(memberName);
343 345 }
344 346
345 347 void PythonQtClassInfo::recursiveCollectDecoratorObjects(QList<QObject*>& decoratorObjects) {
346 348 QObject* deco = decorator();
347 349 if (deco) {
348 350 decoratorObjects.append(deco);
349 351 }
350 352 foreach(const ParentClassInfo& info, _parentClasses) {
351 353 info._parent->recursiveCollectDecoratorObjects(decoratorObjects);
352 354 }
353 355 }
354 356
355 357 void PythonQtClassInfo::recursiveCollectClassInfos(QList<PythonQtClassInfo*>& classInfoObjects) {
356 358 classInfoObjects.append(this);
357 359 foreach(const ParentClassInfo& info, _parentClasses) {
358 360 info._parent->recursiveCollectClassInfos(classInfoObjects);
359 361 }
360 362 }
361 363
362 364 PythonQtSlotInfo* PythonQtClassInfo::findDecoratorSlots(const char* memberName, int memberNameLen, PythonQtSlotInfo* tail, bool &found, QHash<QByteArray, PythonQtMemberInfo>& memberCache, int upcastingOffset)
363 365 {
364 366 QListIterator<PythonQtSlotInfo*> it(_decoratorSlots);
365 367 while (it.hasNext()) {
366 368
367 369 PythonQtSlotInfo* infoOrig = it.next();
368 370
369 371 const char* sigStart = infoOrig->metaMethod()->signature();
370 372 if (qstrncmp("static_", sigStart, 7)==0) {
371 373 sigStart += 7;
372 374 sigStart += findCharOffset(sigStart, '_')+1;
373 375 }
374 376 int offset = findCharOffset(sigStart, '(');
375 377 if (memberNameLen == offset && qstrncmp(memberName, sigStart, offset)==0) {
376 378 //make a copy, otherwise we will have trouble on overloads!
377 379 PythonQtSlotInfo* info = new PythonQtSlotInfo(*infoOrig);
378 380 info->setUpcastingOffset(upcastingOffset);
379 381 found = true;
380 382 if (tail) {
381 383 tail->setNextInfo(info);
382 384 } else {
383 385 PythonQtMemberInfo newInfo(info);
384 386 memberCache.insert(memberName, newInfo);
385 387 }
386 388 tail = info;
387 389 }
388 390 }
389 391 return tail;
390 392 }
391 393
392 394 void PythonQtClassInfo::listDecoratorSlotsFromDecoratorProvider(QStringList& list, bool metaOnly) {
393 395 QObject* decoratorProvider = decorator();
394 396 if (decoratorProvider) {
395 397 const QMetaObject* meta = decoratorProvider->metaObject();
396 398 int numMethods = meta->methodCount();
397 399 int startFrom = QObject::staticMetaObject.methodCount();
398 400 for (int i = startFrom; i < numMethods; i++) {
399 401 QMetaMethod m = meta->method(i);
400 402 if ((m.methodType() == QMetaMethod::Method ||
401 403 m.methodType() == QMetaMethod::Slot) && m.access() == QMetaMethod::Public) {
402 404
403 405 const char* sigStart = m.signature();
404 406 bool isClassDeco = false;
405 407 if (qstrncmp(sigStart, "static_", 7)==0) {
406 408 // skip the static_classname_ part of the string
407 409 sigStart += 7 + 1 + strlen(className());
408 410 isClassDeco = true;
409 411 } else if (qstrncmp(sigStart, "new_", 4)==0) {
410 412 continue;
411 413 } else if (qstrncmp(sigStart, "delete_", 7)==0) {
412 414 continue;
413 415 }
414 416 // find the first '('
415 417 int offset = findCharOffset(sigStart, '(');
416 418
417 419 // XXX no checking is currently done if the slots have correct first argument or not...
418 420 if (!metaOnly || isClassDeco) {
419 421 list << QString::fromLatin1(sigStart, offset);
420 422 }
421 423 }
422 424 }
423 425 }
424 426
425 427 // look for global decorator slots
426 428 QListIterator<PythonQtSlotInfo*> it(_decoratorSlots);
427 429 while (it.hasNext()) {
428 430 PythonQtSlotInfo* slot = it.next();
429 431 if (metaOnly) {
430 432 if (slot->isClassDecorator()) {
431 433 QByteArray first = slot->slotName();
432 434 if (first.startsWith("static_")) {
433 435 int idx = first.indexOf('_');
434 436 idx = first.indexOf('_', idx+1);
435 437 first = first.mid(idx+1);
436 438 }
437 439 list << first;
438 440 }
439 441 } else {
440 442 list << slot->slotName();
441 443 }
442 444 }
443 445 }
444 446
445 447 QStringList PythonQtClassInfo::propertyList()
446 448 {
447 449 QStringList l;
448 450 if (_isQObject && _meta) {
449 451 int i;
450 452 int numProperties = _meta->propertyCount();
451 453 for (i = 0; i < numProperties; i++) {
452 454 QMetaProperty p = _meta->property(i);
453 455 l << QString(p.name());
454 456 }
455 457 }
456 458 return l;
457 459 }
458 460
459 461 QStringList PythonQtClassInfo::memberList(bool metaOnly)
460 462 {
461 463 decorator();
462 464
463 465 QStringList l;
464 466 QString h;
465 467 if (_isQObject && _meta && !metaOnly) {
466 468 l = propertyList();
467 469 }
468 470
469 471 // normal slots of QObject (or wrapper QObject)
470 472 if (!metaOnly && _meta) {
471 473 int numMethods = _meta->methodCount();
472 474 bool skipQObj = !_isQObject;
473 475 for (int i = skipQObj?QObject::staticMetaObject.methodCount():0; i < numMethods; i++) {
474 476 QMetaMethod m = _meta->method(i);
475 477 if (((m.methodType() == QMetaMethod::Method ||
476 478 m.methodType() == QMetaMethod::Slot) && m.access() == QMetaMethod::Public)
477 479 || m.methodType()==QMetaMethod::Signal) {
478 480 QByteArray signa(m.signature());
479 481 signa = signa.left(signa.indexOf('('));
480 482 l << signa;
481 483 }
482 484 }
483 485 }
484 486
485 487 {
486 488 // look for dynamic decorators in this class and in derived classes
487 489 QList<PythonQtClassInfo*> infos;
488 490 recursiveCollectClassInfos(infos);
489 491 foreach(PythonQtClassInfo* info, infos) {
490 492 info->listDecoratorSlotsFromDecoratorProvider(l, metaOnly);
491 493 }
492 494 }
493 495
494 496 // List enumerator keys...
495 497 QList<const QMetaObject*> enumMetaObjects;
496 498 if (_meta) {
497 499 enumMetaObjects << _meta;
498 500 }
499 501 // check enums in the class hierachy of CPP classes
500 502 QList<QObject*> decoObjects;
501 503 recursiveCollectDecoratorObjects(decoObjects);
502 504 foreach(QObject* deco, decoObjects) {
503 505 enumMetaObjects << deco->metaObject();
504 506 }
505 507
506 508 foreach(const QMetaObject* meta, enumMetaObjects) {
507 509 for (int i = 0; i<meta->enumeratorCount(); i++) {
508 510 QMetaEnum e = meta->enumerator(i);
509 511 l << e.name();
510 512 // we do not want flags, they will cause our values to appear two times
511 513 if (e.isFlag()) continue;
512 514
513 515 for (int j=0; j < e.keyCount(); j++) {
514 516 l << QString(e.key(j));
515 517 }
516 518 }
517 519 }
518 520
519 521 return QSet<QString>::fromList(l).toList();
520 522 }
521 523
522 524 const char* PythonQtClassInfo::className()
523 525 {
524 526 return _wrappedClassName.constData();
525 527 }
526 528
527 529 void* PythonQtClassInfo::castTo(void* ptr, const char* classname)
528 530 {
529 531 if (ptr==NULL) {
530 532 return NULL;
531 533 }
532 534 if (_wrappedClassName == classname) {
533 535 return ptr;
534 536 }
535 537 foreach(const ParentClassInfo& info, _parentClasses) {
536 538 void* result = info._parent->castTo((char*)ptr + info._upcastingOffset, classname);
537 539 if (result) {
538 540 return result;
539 541 }
540 542 }
541 543 return NULL;
542 544 }
543 545
544 546 bool PythonQtClassInfo::inherits(const char* name)
545 547 {
546 548 if (_wrappedClassName == name) {
547 549 return true;
548 550 }
549 551 foreach(const ParentClassInfo& info, _parentClasses) {
550 552 if (info._parent->inherits(name)) {
551 553 return true;
552 554 }
553 555 }
554 556 return false;
555 557 }
556 558
557 559 bool PythonQtClassInfo::inherits(PythonQtClassInfo* classInfo)
558 560 {
559 561 if (classInfo == this) {
560 562 return true;
561 563 }
562 564 foreach(const ParentClassInfo& info, _parentClasses) {
563 565 if (info._parent->inherits(classInfo)) {
564 566 return true;
565 567 }
566 568 }
567 569 return false;
568 570 }
569 571
570 572 QString PythonQtClassInfo::help()
571 573 {
572 574 decorator();
573 575 QString h;
574 576 h += QString("--- ") + QString(className()) + QString(" ---\n");
575 577
576 578 if (_isQObject) {
577 579 h += "Properties:\n";
578 580
579 581 int i;
580 582 int numProperties = _meta->propertyCount();
581 583 for (i = 0; i < numProperties; i++) {
582 584 QMetaProperty p = _meta->property(i);
583 585 h += QString(p.name()) + " (" + QString(p.typeName()) + " )\n";
584 586 }
585 587 }
586 588
587 589 if (constructors()) {
588 590 h += "Constructors:\n";
589 591 PythonQtSlotInfo* constr = constructors();
590 592 while (constr) {
591 593 h += constr->fullSignature() + "\n";
592 594 constr = constr->nextInfo();
593 595 }
594 596 }
595 597
596 598 h += "Slots:\n";
597 599 h += "QString help()\n";
598 600 h += "QString className()\n";
599 601
600 602 if (_meta) {
601 603 int numMethods = _meta->methodCount();
602 604 for (int i = 0; i < numMethods; i++) {
603 605 QMetaMethod m = _meta->method(i);
604 606 if ((m.methodType() == QMetaMethod::Method ||
605 607 m.methodType() == QMetaMethod::Slot) && m.access() == QMetaMethod::Public) {
606 608 PythonQtSlotInfo slot(this, m, i);
607 609 h += slot.fullSignature()+ "\n";
608 610 }
609 611 }
610 612 }
611 613
612 614 // TODO xxx : decorators and enums from decorator() are missing...
613 615 // maybe we can reuse memberlist()?
614 616
615 617 if (_meta && _meta->enumeratorCount()) {
616 618 h += "Enums:\n";
617 619 for (int i = 0; i<_meta->enumeratorCount(); i++) {
618 620 QMetaEnum e = _meta->enumerator(i);
619 621 h += QString(e.name()) + " {";
620 622 for (int j=0; j < e.keyCount(); j++) {
621 623 if (j) { h+= ", "; }
622 624 h += e.key(j);
623 625 }
624 626 h += " }\n";
625 627 }
626 628 }
627 629
628 630 if (_isQObject && _meta) {
629 631 int numMethods = _meta->methodCount();
630 632 if (numMethods>0) {
631 633 h += "Signals:\n";
632 634 for (int i = 0; i < numMethods; i++) {
633 635 QMetaMethod m = _meta->method(i);
634 636 if (m.methodType() == QMetaMethod::Signal) {
635 637 h += QString(m.signature()) + "\n";
636 638 }
637 639 }
638 640 }
639 641 }
640 642 return h;
641 643 }
642 644
643 645 PythonQtSlotInfo* PythonQtClassInfo::constructors()
644 646 {
645 647 if (!_constructors) {
646 648 // force creation of lazy decorator, which will register the decorators
647 649 decorator();
648 650 }
649 651 return _constructors;
650 652 }
651 653
652 654 PythonQtSlotInfo* PythonQtClassInfo::destructor()
653 655 {
654 656 if (!_destructor) {
655 657 // force creation of lazy decorator, which will register the decorators
656 658 decorator();
657 659 }
658 660 return _destructor;
659 661 }
660 662
661 663 void PythonQtClassInfo::addConstructor(PythonQtSlotInfo* info)
662 664 {
663 665 PythonQtSlotInfo* prev = constructors();
664 666 if (prev) {
665 667 info->setNextInfo(prev->nextInfo());
666 668 prev->setNextInfo(info);
667 669 } else {
668 670 _constructors = info;
669 671 }
670 672 }
671 673
672 674 void PythonQtClassInfo::addDecoratorSlot(PythonQtSlotInfo* info)
673 675 {
674 676 _decoratorSlots.append(info);
675 677 }
676 678
677 679 void PythonQtClassInfo::setDestructor(PythonQtSlotInfo* info)
678 680 {
679 681 if (_destructor) {
680 682 _destructor->deleteOverloadsAndThis();
681 683 }
682 684 _destructor = info;
683 685 }
684 686
685 687 void PythonQtClassInfo::setMetaObject(const QMetaObject* meta)
686 688 {
687 689 _meta = meta;
688 690 clearCachedMembers();
689 691 }
690 692
691 693 QObject* PythonQtClassInfo::decorator()
692 694 {
693 695 if (!_decoratorProvider && _decoratorProviderCB) {
694 696 _decoratorProvider = (*_decoratorProviderCB)();
695 697 if (_decoratorProvider) {
696 698 _decoratorProvider->setParent(PythonQt::priv());
697 699 // setup enums early, since they might be needed by the constructor decorators:
698 700 if (!_enumsCreated) {
699 701 createEnumWrappers();
700 702 }
701 703 PythonQt::priv()->addDecorators(_decoratorProvider, PythonQtPrivate::ConstructorDecorator | PythonQtPrivate::DestructorDecorator);
702 704 }
703 705 }
704 706 // check if enums need to be created and create them if they are not yet created
705 707 if (!_enumsCreated) {
706 708 createEnumWrappers();
707 709 }
708 710 return _decoratorProvider;
709 711 }
710 712
711 713 bool PythonQtClassInfo::hasOwnerMethodButNoOwner(void* object)
712 714 {
713 715 PythonQtMemberInfo info = member("hasOwner");
714 716 if (info._type == PythonQtMemberInfo::Slot) {
715 717 void* obj = object;
716 718 bool result = false;
717 719 void* args[2];
718 720 args[0] = &result;
719 721 args[1] = &obj;
720 722 info._slot->decorator()->qt_metacall(QMetaObject::InvokeMetaMethod, info._slot->slotIndex(), args);
721 723 return !result;
722 724 } else {
723 725 return false;
724 726 }
725 727 }
726 728
727 729 void* PythonQtClassInfo::recursiveCastDownIfPossible(void* ptr, char** resultClassName)
728 730 {
729 731 if (!_polymorphicHandlers.isEmpty()) {
730 732 foreach(PythonQtPolymorphicHandlerCB* cb, _polymorphicHandlers) {
731 733 void* resultPtr = (*cb)(ptr, resultClassName);
732 734 if (resultPtr) {
733 735 return resultPtr;
734 736 }
735 737 }
736 738 }
737 739 foreach(const ParentClassInfo& info, _parentClasses) {
738 740 if (!info._parent->isQObject()) {
739 741 void* resultPtr = info._parent->recursiveCastDownIfPossible((char*)ptr + info._upcastingOffset, resultClassName);
740 742 if (resultPtr) {
741 743 return resultPtr;
742 744 }
743 745 }
744 746 }
745 747 return NULL;
746 748 }
747 749
748 750 void* PythonQtClassInfo::castDownIfPossible(void* ptr, PythonQtClassInfo** resultClassInfo)
749 751 {
750 752 char* className;
751 753 // this would do downcasting recursively...
752 754 // void* resultPtr = recursiveCastDownIfPossible(ptr, &className);
753 755
754 756 // we only do downcasting on the base object, not on the whole inheritance tree...
755 757 void* resultPtr = NULL;
756 758 if (!_polymorphicHandlers.isEmpty()) {
757 759 foreach(PythonQtPolymorphicHandlerCB* cb, _polymorphicHandlers) {
758 760 resultPtr = (*cb)(ptr, &className);
759 761 if (resultPtr) {
760 762 break;
761 763 }
762 764 }
763 765 }
764 766 if (resultPtr) {
765 767 *resultClassInfo = PythonQt::priv()->getClassInfo(className);
766 768 } else {
767 769 *resultClassInfo = this;
768 770 resultPtr = ptr;
769 771 }
770 772 return resultPtr;
771 773 }
772 774
773 775 PyObject* PythonQtClassInfo::findEnumWrapper(const QByteArray& name, PythonQtClassInfo* localScope, bool* isLocalEnum)
774 776 {
775 777 if (isLocalEnum) {
776 778 *isLocalEnum = true;
777 779 }
778 780 int scopePos = name.lastIndexOf("::");
779 781 if (scopePos != -1) {
780 782 if (isLocalEnum) {
781 783 *isLocalEnum = false;
782 784 }
783 785 // split into scope and enum name
784 786 QByteArray enumScope = name.mid(0,scopePos);
785 787 QByteArray enumName = name.mid(scopePos+2);
786 788 PythonQtClassInfo* info = PythonQt::priv()->getClassInfo(enumScope);
787 789 if (info) {
788 790 return info->findEnumWrapper(enumName);
789 791 } else{
790 792 return NULL;
791 793 }
792 794 }
793 795 if (localScope) {
794 796 return localScope->findEnumWrapper(name);
795 797 } else {
796 798 return NULL;
797 799 }
798 800 }
799 801
800 802 void PythonQtClassInfo::createEnumWrappers(const QMetaObject* meta)
801 803 {
802 804 for (int i = meta->enumeratorOffset();i<meta->enumeratorCount();i++) {
803 805 QMetaEnum e = meta->enumerator(i);
804 806 PythonQtObjectPtr p;
805 807 p.setNewRef(PythonQtPrivate::createNewPythonQtEnumWrapper(e.name(), _pythonQtClassWrapper));
806 808 _enumWrappers.append(p);
807 809 }
808 810 }
809 811
810 812 void PythonQtClassInfo::createEnumWrappers()
811 813 {
812 814 if (!_enumsCreated) {
813 815 _enumsCreated = true;
814 816 if (_meta) {
815 817 createEnumWrappers(_meta);
816 818 }
817 819 if (decorator()) {
818 820 createEnumWrappers(decorator()->metaObject());
819 821 }
820 822 foreach(const ParentClassInfo& info, _parentClasses) {
821 823 info._parent->createEnumWrappers();
822 824 }
823 825 }
824 826 }
825 827
826 828 PyObject* PythonQtClassInfo::findEnumWrapper(const char* name) {
827 829 // force enum creation
828 830 if (!_enumsCreated) {
829 831 createEnumWrappers();
830 832 }
831 833 foreach(const PythonQtObjectPtr& p, _enumWrappers) {
832 834 const char* className = ((PyTypeObject*)p.object())->tp_name;
833 835 if (qstrcmp(className, name)==0) {
834 836 return p.object();
835 837 }
836 838 }
837 839 foreach(const ParentClassInfo& info, _parentClasses) {
838 840 PyObject* p = info._parent->findEnumWrapper(name);
839 841 if (p) return p;
840 842 }
841 843 return NULL;
842 844 }
843 845
@@ -1,585 +1,620
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 PythonQtInstanceWrapper.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 "PythonQtInstanceWrapper.h"
43 43 #include <QObject>
44 44 #include "PythonQt.h"
45 45 #include "PythonQtSlot.h"
46 46 #include "PythonQtClassInfo.h"
47 47 #include "PythonQtConversion.h"
48 48 #include "PythonQtClassWrapper.h"
49 49
50 50 PythonQtClassInfo* PythonQtInstanceWrapperStruct::classInfo()
51 51 {
52 52 // take the class info from our type object
53 53 return ((PythonQtClassWrapper*)ob_type)->_classInfo;
54 54 }
55 55
56 56 static void PythonQtInstanceWrapper_deleteObject(PythonQtInstanceWrapper* self, bool force = false) {
57 57
58 58 // is this a C++ wrapper?
59 59 if (self->_wrappedPtr) {
60 60 //mlabDebugConst("Python","c++ wrapper removed " << self->_wrappedPtr << " " << self->_obj->className() << " " << self->classInfo()->wrappedClassName().latin1());
61 61
62 62 PythonQt::priv()->removeWrapperPointer(self->_wrappedPtr);
63 63 // we own our qobject, so we delete it now:
64 64 delete self->_obj;
65 65 self->_obj = NULL;
66 66 if (force || self->classInfo()->hasOwnerMethodButNoOwner(self->_wrappedPtr) || self->_ownedByPythonQt) {
67 67 int type = self->classInfo()->metaTypeId();
68 68 if (self->_useQMetaTypeDestroy && type>=0) {
69 69 // use QMetaType to destroy the object
70 70 QMetaType::destroy(type, self->_wrappedPtr);
71 71 } else {
72 72 PythonQtSlotInfo* slot = self->classInfo()->destructor();
73 73 if (slot) {
74 74 void* args[2];
75 75 args[0] = NULL;
76 76 args[1] = &self->_wrappedPtr;
77 77 slot->decorator()->qt_metacall(QMetaObject::InvokeMetaMethod, slot->slotIndex(), args);
78 78 self->_wrappedPtr = NULL;
79 79 } else {
80 80 if (type>=0) {
81 81 // use QMetaType to destroy the object
82 82 QMetaType::destroy(type, self->_wrappedPtr);
83 83 } else {
84 84 // TODO: warn about not being able to destroy the object?
85 85 }
86 86 }
87 87 }
88 88 }
89 89 } else {
90 90 //mlabDebugConst("Python","qobject wrapper removed " << self->_obj->className() << " " << self->classInfo()->wrappedClassName().latin1());
91 91 if (self->_objPointerCopy) {
92 92 PythonQt::priv()->removeWrapperPointer(self->_objPointerCopy);
93 93 }
94 94 if (self->_obj) {
95 95 if (force || self->_ownedByPythonQt) {
96 96 if (force || !self->_obj->parent()) {
97 97 delete self->_obj;
98 98 }
99 99 } else {
100 100 if (self->_obj->parent()==NULL) {
101 101 // tell someone who is interested that the qobject is no longer wrapped, if it has no parent
102 102 PythonQt::qObjectNoLongerWrappedCB(self->_obj);
103 103 }
104 104 }
105 105 }
106 106 }
107 107 self->_obj = NULL;
108 108 }
109 109
110 110 static void PythonQtInstanceWrapper_dealloc(PythonQtInstanceWrapper* self)
111 111 {
112 112 PythonQtInstanceWrapper_deleteObject(self);
113 113 self->_obj.~QPointer<QObject>();
114 114 self->ob_type->tp_free((PyObject*)self);
115 115 }
116 116
117 117 static PyObject* PythonQtInstanceWrapper_new(PyTypeObject *type, PyObject * /*args*/, PyObject * /*kwds*/)
118 118 {
119 119 //PythonQtClassWrapper *classType = (PythonQtClassWrapper*)type;
120 120 PythonQtInstanceWrapper *self;
121 121 static PyObject* emptyTuple = NULL;
122 122 if (emptyTuple==NULL) {
123 123 emptyTuple = PyTuple_New(0);
124 124 }
125 125
126 126 self = (PythonQtInstanceWrapper*)PyBaseObject_Type.tp_new(type, emptyTuple, NULL);
127 127
128 128 if (self != NULL) {
129 129 new (&self->_obj) QPointer<QObject>();
130 130 self->_wrappedPtr = NULL;
131 131 self->_ownedByPythonQt = false;
132 132 self->_useQMetaTypeDestroy = false;
133 133 self->_isShellInstance = false;
134 134 }
135 135 return (PyObject *)self;
136 136 }
137 137
138 138 int PythonQtInstanceWrapper_init(PythonQtInstanceWrapper * self, PyObject * args, PyObject * kwds)
139 139 {
140 140 if (args == PythonQtPrivate::dummyTuple()) {
141 141 // we are called from the internal PythonQt API, so our data will be filled later on...
142 142 return 0;
143 143 }
144 144
145 145 // we are called from python, try to construct our object
146 146 if (self->classInfo()->constructors()) {
147 147 void* directCPPPointer = NULL;
148 148 PythonQtSlotFunction_CallImpl(self->classInfo(), NULL, self->classInfo()->constructors(), args, kwds, NULL, &directCPPPointer);
149 149 if (PyErr_Occurred()) {
150 150 return -1;
151 151 }
152 152 if (directCPPPointer) {
153 153 // change ownershipflag to be owned by PythonQt
154 154 self->_ownedByPythonQt = true;
155 155 self->_useQMetaTypeDestroy = false;
156 156 if (self->classInfo()->isCPPWrapper()) {
157 157 self->_wrappedPtr = directCPPPointer;
158 158 // TODO xxx: if there is a wrapper factory, we might want to generate a wrapper for our class?!
159 159 } else {
160 160 self->setQObject((QObject*)directCPPPointer);
161 161 }
162 162 // register with PythonQt
163 163 PythonQt::priv()->addWrapperPointer(directCPPPointer, self);
164 164
165 165 PythonQtShellSetInstanceWrapperCB* cb = self->classInfo()->shellSetInstanceWrapperCB();
166 166 if (cb) {
167 167 // if we are a derived python class, we set the wrapper
168 168 // to activate the shell class, otherwise we just ignore that it is a shell...
169 169 // we detect it be checking if the type does not have PythonQtInstanceWrapper_Type as direct base class,
170 170 // which is the case for all non-python derived types
171 171 if (((PyObject*)self)->ob_type->tp_base != &PythonQtInstanceWrapper_Type) {
172 172 // set the wrapper and remember that we have a shell instance!
173 173 (*cb)(directCPPPointer, self);
174 174 self->_isShellInstance = true;
175 175 }
176 176 }
177 177 }
178 178 } else {
179 179 QString error = QString("No constructors available for ") + self->classInfo()->className();
180 180 PyErr_SetString(PyExc_ValueError, error.toLatin1().data());
181 181 return -1;
182 182 }
183 183 return 0;
184 184 }
185 185
186 186 static PyObject *PythonQtInstanceWrapper_classname(PythonQtInstanceWrapper* obj)
187 187 {
188 188 return PyString_FromString(obj->ob_type->tp_name);
189 189 }
190 190
191 191 static PyObject *PythonQtInstanceWrapper_help(PythonQtInstanceWrapper* obj)
192 192 {
193 193 return PythonQt::self()->helpCalled(obj->classInfo());
194 194 }
195 195
196 196 static PyObject *PythonQtInstanceWrapper_delete(PythonQtInstanceWrapper * self)
197 197 {
198 198 PythonQtInstanceWrapper_deleteObject(self, true);
199 199 Py_INCREF(Py_None);
200 200 return Py_None;
201 201 }
202 202
203 203
204 204 static PyMethodDef PythonQtInstanceWrapper_methods[] = {
205 205 {"className", (PyCFunction)PythonQtInstanceWrapper_classname, METH_NOARGS,
206 206 "Return the classname of the object"
207 207 },
208 208 {"help", (PyCFunction)PythonQtInstanceWrapper_help, METH_NOARGS,
209 209 "Shows the help of available methods for this class"
210 210 },
211 211 {"delete", (PyCFunction)PythonQtInstanceWrapper_delete, METH_NOARGS,
212 212 "Deletes the C++ object (at your own risk, my friend!)"
213 213 },
214 214 {NULL, NULL, 0, NULL} /* Sentinel */
215 215 };
216 216
217 217
218 218 static PyObject *PythonQtInstanceWrapper_getattro(PyObject *obj,PyObject *name)
219 219 {
220 220 const char *attributeName;
221 221 PythonQtInstanceWrapper *wrapper = (PythonQtInstanceWrapper *)obj;
222 222
223 223 if ((attributeName = PyString_AsString(name)) == NULL) {
224 224 return NULL;
225 225 }
226 226
227 227 if (qstrcmp(attributeName, "__dict__")==0) {
228 228 PyObject* dict = PyBaseObject_Type.tp_getattro(obj, name);
229 229 dict = PyDict_Copy(dict);
230 230
231 231 if (wrapper->_obj) {
232 232 // only the properties are missing, the rest is already available from
233 233 // PythonQtClassWrapper...
234 234 QStringList l = wrapper->classInfo()->propertyList();
235 235 foreach (QString name, l) {
236 236 PyObject* o = PyObject_GetAttrString(obj, name.toLatin1().data());
237 237 if (o) {
238 238 PyDict_SetItemString(dict, name.toLatin1().data(), o);
239 239 Py_DECREF(o);
240 240 } else {
241 241 std::cerr << "PythonQtInstanceWrapper: something is wrong, could not get attribute " << name.toLatin1().data();
242 242 }
243 243 }
244
245 QList<QByteArray> dynamicProps = wrapper->_obj->dynamicPropertyNames();
246 foreach (QByteArray name, dynamicProps) {
247 PyObject* o = PyObject_GetAttrString(obj, name.data());
248 if (o) {
249 PyDict_SetItemString(dict, name.data(), o);
250 Py_DECREF(o);
251 } else {
252 std::cerr << "PythonQtInstanceWrapper: dynamic property could not be read " << name.data();
253 }
254 }
244 255 }
245 256 // Note: we do not put children into the dict, is would look confusing?!
246 257 return dict;
247 258 }
248 259
249 260 // first look in super, to return derived methods from base object first
250 261 PyObject* superAttr = PyBaseObject_Type.tp_getattro(obj, name);
251 262 if (superAttr) {
252 263 return superAttr;
253 264 }
254 265 PyErr_Clear();
255 266
256 267 // mlabDebugConst("Python","get " << attributeName);
257 268
258 // TODO: dynamic properties are missing
259
260 269 PythonQtMemberInfo member = wrapper->classInfo()->member(attributeName);
261 270 switch (member._type) {
262 271 case PythonQtMemberInfo::Property:
263 272 if (wrapper->_obj) {
264 273 if (member._property.userType() != QVariant::Invalid) {
265 274 return PythonQtConv::QVariantToPyObject(member._property.read(wrapper->_obj));
266 275 } else {
267 276 Py_INCREF(Py_None);
268 277 return Py_None;
269 278 }
270 279 } else {
271 280 QString error = QString("Trying to read property '") + attributeName + "' from a destroyed " + wrapper->classInfo()->className() + " object";
272 281 PyErr_SetString(PyExc_ValueError, error.toLatin1().data());
273 282 return NULL;
274 283 }
275 284 break;
276 285 case PythonQtMemberInfo::Slot:
277 286 return PythonQtSlotFunction_New(member._slot, obj, NULL);
278 287 break;
279 288 case PythonQtMemberInfo::EnumValue:
280 289 {
281 290 PyObject* enumValue = member._enumValue;
282 291 Py_INCREF(enumValue);
283 292 return enumValue;
284 293 }
285 294 break;
286 295 case PythonQtMemberInfo::EnumWrapper:
287 296 {
288 297 PyObject* enumWrapper = member._enumWrapper;
289 298 Py_INCREF(enumWrapper);
290 299 return enumWrapper;
291 300 }
292 301 break;
302 case PythonQtMemberInfo::NotFound:
303 // handle dynamic properties
304 if (wrapper->_obj) {
305 QVariant v = wrapper->_obj->property(attributeName);
306 if (v.isValid()) {
307 return PythonQtConv::QVariantToPyObject(v);
308 }
309 }
310 break;
293 311 default:
294 312 // is an invalid type, go on
295 313 break;
296 314 }
297 315
298 316 // look for the internal methods (className(), help())
299 317 PyObject* internalMethod = Py_FindMethod( PythonQtInstanceWrapper_methods, obj, (char*)attributeName);
300 318 if (internalMethod) {
301 319 return internalMethod;
302 320 }
303 321 PyErr_Clear();
304 322
305 323 if (wrapper->_obj) {
306 324 // look for a child
307 325 QObjectList children = wrapper->_obj->children();
308 326 for (int i = 0; i < children.count(); i++) {
309 327 QObject *child = children.at(i);
310 328 if (child->objectName() == attributeName) {
311 329 return PythonQt::priv()->wrapQObject(child);
312 330 }
313 331 }
314 332 }
315 333
316 334 QString error = QString(wrapper->classInfo()->className()) + " has no attribute named '" + QString(attributeName) + "'";
317 335 PyErr_SetString(PyExc_AttributeError, error.toLatin1().data());
318 336 return NULL;
319 337 }
320 338
321 339 static int PythonQtInstanceWrapper_setattro(PyObject *obj,PyObject *name,PyObject *value)
322 340 {
323 341 QString error;
324 342 char *attributeName;
325 343 PythonQtInstanceWrapper *wrapper = (PythonQtInstanceWrapper *)obj;
326 344
327 345 if ((attributeName = PyString_AsString(name)) == NULL)
328 346 return -1;
329 347
330 348 PythonQtMemberInfo member = wrapper->classInfo()->member(attributeName);
331 349 if (member._type == PythonQtMemberInfo::Property) {
332 350
333 351 if (!wrapper->_obj) {
334 352 error = QString("Trying to set property '") + attributeName + "' on a destroyed " + wrapper->classInfo()->className() + " object";
335 353 PyErr_SetString(PyExc_AttributeError, error.toLatin1().data());
336 354 return -1;
337 355 }
338 356
339 357 QMetaProperty prop = member._property;
340 358 if (prop.isWritable()) {
341 359 QVariant v;
342 360 if (prop.isEnumType()) {
343 361 // this will give us either a string or an int, everything else will probably be an error
344 362 v = PythonQtConv::PyObjToQVariant(value);
345 363 } else {
346 364 int t = prop.userType();
347 365 v = PythonQtConv::PyObjToQVariant(value, t);
348 366 }
349 367 bool success = false;
350 368 if (v.isValid()) {
351 369 success = prop.write(wrapper->_obj, v);
352 370 }
353 371 if (success) {
354 372 return 0;
355 373 } else {
356 374 error = QString("Property '") + attributeName + "' of type '" +
357 375 prop.typeName() + "' does not accept an object of type "
358 376 + QString(value->ob_type->tp_name) + " (" + PythonQtConv::PyObjGetRepresentation(value) + ")";
359 377 }
360 378 } else {
361 379 error = QString("Property '") + attributeName + "' of " + obj->ob_type->tp_name + " object is not writable";
362 380 }
363 381 } else if (member._type == PythonQtMemberInfo::Slot) {
364 382 error = QString("Slot '") + attributeName + "' can not be overwritten on " + obj->ob_type->tp_name + " object";
365 383 } else if (member._type == PythonQtMemberInfo::EnumValue) {
366 384 error = QString("EnumValue '") + attributeName + "' can not be overwritten on " + obj->ob_type->tp_name + " object";
367 385 } else if (member._type == PythonQtMemberInfo::EnumWrapper) {
368 386 error = QString("Enum '") + attributeName + "' can not be overwritten on " + obj->ob_type->tp_name + " object";
369 387 } else if (member._type == PythonQtMemberInfo::NotFound) {
388 // handle dynamic properties
389 if (wrapper->_obj) {
390 QVariant prop = wrapper->_obj->property(attributeName);
391 if (prop.isValid()) {
392 QVariant v = PythonQtConv::PyObjToQVariant(value);
393 if (v.isValid()) {
394 wrapper->_obj->setProperty(attributeName, v);
395 return 0;
396 } else {
397 error = QString("Dynamic property '") + attributeName + "' does not accept an object of type "
398 + QString(value->ob_type->tp_name) + " (" + PythonQtConv::PyObjGetRepresentation(value) + ")";
399 PyErr_SetString(PyExc_AttributeError, error.toLatin1().data());
400 return -1;
401 }
402 }
403 }
404
370 405 // if we are a derived python class, we allow setting attributes.
371 406 // if we are a direct CPP wrapper, we do NOT allow it, since
372 407 // it would be confusing to allow it because a wrapper will go away when it is not seen by python anymore
373 408 // and when it is recreated from a CPP pointer the attributes are gone...
374 409 if (obj->ob_type->tp_base != &PythonQtInstanceWrapper_Type) {
375 410 return PyBaseObject_Type.tp_setattro(obj,name,value);
376 411 } else {
377 412 error = QString("'") + attributeName + "' does not exist on " + obj->ob_type->tp_name + " and creating new attributes on C++ objects is not allowed";
378 413 }
379 414 }
380 415
381 416 PyErr_SetString(PyExc_AttributeError, error.toLatin1().data());
382 417 return -1;
383 418 }
384 419
385 420 static PyObject * PythonQtInstanceWrapper_str(PyObject * obj)
386 421 {
387 422 PythonQtInstanceWrapper* wrapper = (PythonQtInstanceWrapper*)obj;
388 423 const char* typeName = obj->ob_type->tp_name;
389 424 QObject *qobj = wrapper->_obj;
390 425 if (wrapper->_wrappedPtr) {
391 426 QString str = PythonQtConv::CPPObjectToString(wrapper->classInfo()->metaTypeId(), wrapper->_wrappedPtr);
392 427 if (!str.isEmpty()) {
393 428 return PyString_FromFormat("%s", str.toLatin1().constData());
394 429 } else
395 430 if (wrapper->_obj) {
396 431 return PyString_FromFormat("%s (C++ Object %p wrapped by %s %p))", typeName, wrapper->_wrappedPtr, wrapper->_obj->metaObject()->className(), qobj);
397 432 } else {
398 433 return PyString_FromFormat("%s (C++ Object %p)", typeName, wrapper->_wrappedPtr);
399 434 }
400 435 } else {
401 436 return PyString_FromFormat("%s (QObject %p)", typeName, qobj);
402 437 }
403 438 }
404 439
405 440 static PyObject * PythonQtInstanceWrapper_repr(PyObject * obj)
406 441 {
407 442 PythonQtInstanceWrapper* wrapper = (PythonQtInstanceWrapper*)obj;
408 443 const char* typeName = obj->ob_type->tp_name;
409 444
410 445 QObject *qobj = wrapper->_obj;
411 446 if (wrapper->_wrappedPtr) {
412 447 QString str = PythonQtConv::CPPObjectToString(wrapper->classInfo()->metaTypeId(), wrapper->_wrappedPtr);
413 448 if (!str.isEmpty()) {
414 449 return PyString_FromFormat("%s(%s, %p)", typeName, str.toLatin1().constData(), wrapper->_wrappedPtr);
415 450 } else
416 451 if (wrapper->_obj) {
417 452 return PyString_FromFormat("%s (C++ Object %p wrapped by %s %p))", typeName, wrapper->_wrappedPtr, wrapper->_obj->metaObject()->className(), qobj);
418 453 } else {
419 454 return PyString_FromFormat("%s (C++ Object %p)", typeName, wrapper->_wrappedPtr);
420 455 }
421 456 } else {
422 457 return PyString_FromFormat("%s (%s %p)", typeName, wrapper->classInfo()->className(), qobj);
423 458 }
424 459 }
425 460
426 461 static int PythonQtInstanceWrapper_compare(PyObject * obj1, PyObject * obj2)
427 462 {
428 463 if (PyObject_TypeCheck(obj1, &PythonQtInstanceWrapper_Type) &&
429 464 PyObject_TypeCheck(obj2, &PythonQtInstanceWrapper_Type)) {
430 465
431 466 PythonQtInstanceWrapper* w1 = (PythonQtInstanceWrapper*)obj1;
432 467 PythonQtInstanceWrapper* w2 = (PythonQtInstanceWrapper*)obj2;
433 468 // check pointers directly first:
434 469 if (w1->_wrappedPtr != NULL) {
435 470 if (w1->_wrappedPtr == w2->_wrappedPtr) {
436 471 return 0;
437 472 }
438 473 } else if (w1->_obj == w2->_obj) {
439 474 return 0;
440 475 }
441 476 const char* class1 = w1->classInfo()->className();
442 477 const char* class2 = w2->classInfo()->className();
443 478 if (strcmp(class1, class2) == 0) {
444 479 // same class names, so we can try the operator_equal
445 480 PythonQtMemberInfo info = w1->classInfo()->member("operator_equal");
446 481 if (info._type == PythonQtMemberInfo::Slot) {
447 482 bool result = false;
448 483 void* obj1 = w1->_wrappedPtr;
449 484 if (!obj1) {
450 485 obj1 = w1->_obj;
451 486 }
452 487 if (!obj1) { return -1; }
453 488 void* obj2 = w2->_wrappedPtr;
454 489 if (!obj2) {
455 490 obj2 = w2->_obj;
456 491 }
457 492 if (!obj2) { return -1; }
458 493 if (info._slot->isInstanceDecorator()) {
459 494 // call on decorator QObject
460 495 void* args[3];
461 496 args[0] = &result;
462 497 args[1] = &obj1; // this is a pointer, so it needs a pointer to a pointer
463 498 args[2] = obj2; // this is a reference, so it needs the direct pointer
464 499 info._slot->decorator()->qt_metacall(QMetaObject::InvokeMetaMethod, info._slot->slotIndex(), args);
465 500 return result?0:-1;
466 501 } else {
467 502 // call directly on QObject
468 503 if (w1->_obj && w2->_obj) {
469 504 void* args[2];
470 505 args[0] = &result;
471 506 args[2] = obj2; // this is a reference, so it needs the direct pointer
472 507 w1->_obj->qt_metacall(QMetaObject::InvokeMetaMethod, info._slot->slotIndex(), args);
473 508 }
474 509 }
475 510 }
476 511 }
477 512 }
478 513 return -1;
479 514 }
480 515
481 516 static int PythonQtInstanceWrapper_nonzero(PyObject *obj)
482 517 {
483 518 PythonQtInstanceWrapper* wrapper = (PythonQtInstanceWrapper*)obj;
484 519 return (wrapper->_wrappedPtr == NULL && wrapper->_obj == NULL)?0:1;
485 520 }
486 521
487 522
488 523 static long PythonQtInstanceWrapper_hash(PythonQtInstanceWrapper *obj)
489 524 {
490 525 if (obj->_wrappedPtr != NULL) {
491 526 return reinterpret_cast<long>(obj->_wrappedPtr);
492 527 } else {
493 528 QObject* qobj = obj->_obj; // get pointer from QPointer wrapper
494 529 return reinterpret_cast<long>(qobj);
495 530 }
496 531 }
497 532
498 533
499 534
500 535 // we override nb_nonzero, so that one can do 'if' expressions to test for a NULL ptr
501 536 static PyNumberMethods PythonQtInstanceWrapper_as_number = {
502 537 0, /* nb_add */
503 538 0, /* nb_subtract */
504 539 0, /* nb_multiply */
505 540 0, /* nb_divide */
506 541 0, /* nb_remainder */
507 542 0, /* nb_divmod */
508 543 0, /* nb_power */
509 544 0, /* nb_negative */
510 545 0, /* nb_positive */
511 546 0, /* nb_absolute */
512 547 PythonQtInstanceWrapper_nonzero, /* nb_nonzero */
513 548 0, /* nb_invert */
514 549 0, /* nb_lshift */
515 550 0, /* nb_rshift */
516 551 0, /* nb_and */
517 552 0, /* nb_xor */
518 553 0, /* nb_or */
519 554 0, /* nb_coerce */
520 555 0, /* nb_int */
521 556 0, /* nb_long */
522 557 0, /* nb_float */
523 558 0, /* nb_oct */
524 559 0, /* nb_hex */
525 560 0, /* nb_inplace_add */
526 561 0, /* nb_inplace_subtract */
527 562 0, /* nb_inplace_multiply */
528 563 0, /* nb_inplace_divide */
529 564 0, /* nb_inplace_remainder */
530 565 0, /* nb_inplace_power */
531 566 0, /* nb_inplace_lshift */
532 567 0, /* nb_inplace_rshift */
533 568 0, /* nb_inplace_and */
534 569 0, /* nb_inplace_xor */
535 570 0, /* nb_inplace_or */
536 571 0, /* nb_floor_divide */
537 572 0, /* nb_true_divide */
538 573 0, /* nb_inplace_floor_divide */
539 574 0, /* nb_inplace_true_divide */
540 575 };
541 576
542 577 PyTypeObject PythonQtInstanceWrapper_Type = {
543 578 PyObject_HEAD_INIT(&PythonQtClassWrapper_Type)
544 579 0, /*ob_size*/
545 580 "PythonQt.PythonQtInstanceWrapper", /*tp_name*/
546 581 sizeof(PythonQtInstanceWrapper), /*tp_basicsize*/
547 582 0, /*tp_itemsize*/
548 583 (destructor)PythonQtInstanceWrapper_dealloc, /*tp_dealloc*/
549 584 0, /*tp_print*/
550 585 0, /*tp_getattr*/
551 586 0, /*tp_setattr*/
552 587 PythonQtInstanceWrapper_compare, /*tp_compare*/
553 588 PythonQtInstanceWrapper_repr, /*tp_repr*/
554 589 &PythonQtInstanceWrapper_as_number, /*tp_as_number*/
555 590 0, /*tp_as_sequence*/
556 591 0, /*tp_as_mapping*/
557 592 (hashfunc)PythonQtInstanceWrapper_hash, /*tp_hash */
558 593 0, /*tp_call*/
559 594 PythonQtInstanceWrapper_str, /*tp_str*/
560 595 PythonQtInstanceWrapper_getattro, /*tp_getattro*/
561 596 PythonQtInstanceWrapper_setattro, /*tp_setattro*/
562 597 0, /*tp_as_buffer*/
563 598 Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE, /*tp_flags*/
564 599 "PythonQtInstanceWrapper object", /* tp_doc */
565 600 0, /* tp_traverse */
566 601 0, /* tp_clear */
567 602 0, /* tp_richcompare */
568 603 0, /* tp_weaklistoffset */
569 604 0, /* tp_iter */
570 605 0, /* tp_iternext */
571 606 0, /* tp_methods */
572 607 0, /* tp_members */
573 608 0, /* tp_getset */
574 609 0, /* tp_base */
575 610 0, /* tp_dict */
576 611 0, /* tp_descr_get */
577 612 0, /* tp_descr_set */
578 613 0, /* tp_dictoffset */
579 614 (initproc)PythonQtInstanceWrapper_init, /* tp_init */
580 615 0, /* tp_alloc */
581 616 PythonQtInstanceWrapper_new, /* tp_new */
582 617 };
583 618
584 619 //-------------------------------------------------------
585 620
@@ -1,304 +1,314
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 PythonQtStdDecorators.cpp
36 36 // \author Florian Link
37 37 // \author Last changed by $Author: florian $
38 38 // \date 2007-04
39 39 */
40 40 //----------------------------------------------------------------------------------
41 41
42 42 #include "PythonQtStdDecorators.h"
43 43 #include "PythonQt.h"
44 44 #include "PythonQtClassInfo.h"
45 45 #include <QCoreApplication>
46 46
47 47 bool PythonQtStdDecorators::connect(QObject* sender, const QByteArray& signal, PyObject* callable)
48 48 {
49 49 QByteArray signalTmp;
50 50 char first = signal.at(0);
51 51 if (first>='0' && first<='9') {
52 52 signalTmp = signal;
53 53 } else {
54 54 signalTmp = "2" + signal;
55 55 }
56 56
57 57 if (sender) {
58 58 return PythonQt::self()->addSignalHandler(sender, signalTmp, callable);
59 59 } else {
60 60 return false;
61 61 }
62 62 }
63 63
64 64 bool PythonQtStdDecorators::connect(QObject* sender, const QByteArray& signal, QObject* receiver, const QByteArray& slot)
65 65 {
66 66 bool r = false;
67 67 if (sender && receiver) {
68 68 QByteArray signalTmp;
69 69 char first = signal.at(0);
70 70 if (first>='0' && first<='9') {
71 71 signalTmp = signal;
72 72 } else {
73 73 signalTmp = "2" + signal;
74 74 }
75 75
76 76 QByteArray slotTmp;
77 77 first = slot.at(0);
78 78 if (first>='0' && first<='9') {
79 79 slotTmp = slot;
80 80 } else {
81 81 slotTmp = "1" + slot;
82 82 }
83 83 r = QObject::connect(sender, signalTmp, receiver, slotTmp);
84 84 }
85 85 return r;
86 86 }
87 87
88 88 bool PythonQtStdDecorators::disconnect(QObject* sender, const QByteArray& signal, PyObject* callable)
89 89 {
90 90 QByteArray signalTmp;
91 91 char first = signal.at(0);
92 92 if (first>='0' && first<='9') {
93 93 signalTmp = signal;
94 94 } else {
95 95 signalTmp = "2" + signal;
96 96 }
97 97 if (sender) {
98 98 return PythonQt::self()->removeSignalHandler(sender, signalTmp, callable);
99 99 } else {
100 100 return false;
101 101 }
102 102 }
103 103
104 104 bool PythonQtStdDecorators::disconnect(QObject* sender, const QByteArray& signal, QObject* receiver, const QByteArray& slot)
105 105 {
106 106 bool r = false;
107 107 if (sender && receiver) {
108 108 QByteArray signalTmp;
109 109 char first = signal.at(0);
110 110 if (first>='0' && first<='9') {
111 111 signalTmp = signal;
112 112 } else {
113 113 signalTmp = "2" + signal;
114 114 }
115 115
116 116 QByteArray slotTmp;
117 117 first = slot.at(0);
118 118 if (first>='0' && first<='9') {
119 119 slotTmp = slot;
120 120 } else {
121 121 slotTmp = "1" + slot;
122 122 }
123 123
124 124 r = QObject::disconnect(sender, signalTmp, receiver, slotTmp);
125 125 }
126 126 return r;
127 127 }
128 128
129 129 #undef emit
130 130 void PythonQtStdDecorators::emit(QObject* sender, const QByteArray& signal, PyObject* arg1 ,PyObject* arg2 ,
131 131 PyObject* arg3 ,PyObject* arg4 ,PyObject* arg5 ,PyObject* arg6 ,PyObject* arg7 )
132 132 {
133 133 // TODO xxx
134 134 // use normal PythonQtSlot calling code, add "allowSignal" to member lookup?!
135 135 }
136 136 #define emit
137 137
138 138 QObject* PythonQtStdDecorators::parent(QObject* o) {
139 139 return o->parent();
140 140 }
141 141
142 142 void PythonQtStdDecorators::setParent(QObject* o, QObject* parent)
143 143 {
144 144 o->setParent(parent);
145 145 }
146 146
147 147 const QObjectList* PythonQtStdDecorators::children(QObject* o)
148 148 {
149 149 return &o->children();
150 150 }
151 151
152 bool PythonQtStdDecorators::setProperty(QObject* o, const char* name, const QVariant& value)
153 {
154 return o->setProperty(name, value);
155 }
156
157 QVariant PythonQtStdDecorators::property(QObject* o, const char* name)
158 {
159 return o->property(name);
160 }
161
152 162 QString PythonQtStdDecorators::tr(QObject* obj, const QByteArray& text, const QByteArray& ambig, int n)
153 163 {
154 164 return QCoreApplication::translate(obj->metaObject()->className(), text.constData(), ambig.constData(), QCoreApplication::CodecForTr, n);
155 165 }
156 166
157 167 QObject* PythonQtStdDecorators::findChild(QObject* parent, PyObject* type, const QString& name)
158 168 {
159 169 const QMetaObject* meta = NULL;
160 170 const char* typeName = NULL;
161 171
162 172 if (PyObject_TypeCheck(type, &PythonQtClassWrapper_Type)) {
163 173 meta = ((PythonQtClassWrapper*)type)->classInfo()->metaObject();
164 174 } else if (PyObject_TypeCheck(type, &PythonQtInstanceWrapper_Type)) {
165 175 meta = ((PythonQtInstanceWrapper*)type)->classInfo()->metaObject();
166 176 } else if (PyString_Check(type)) {
167 177 typeName = PyString_AsString(type);
168 178 }
169 179
170 180 if (!typeName && !meta)
171 181 return NULL;
172 182
173 183 return findChild(parent, typeName, meta, name);
174 184 }
175 185
176 186 QList<QObject*> PythonQtStdDecorators::findChildren(QObject* parent, PyObject* type, const QString& name)
177 187 {
178 188 const QMetaObject* meta = NULL;
179 189 const char* typeName = NULL;
180 190
181 191 if (PyObject_TypeCheck(type, &PythonQtClassWrapper_Type)) {
182 192 meta = ((PythonQtClassWrapper*)type)->classInfo()->metaObject();
183 193 } else if (PyObject_TypeCheck(type, &PythonQtInstanceWrapper_Type)) {
184 194 meta = ((PythonQtInstanceWrapper*)type)->classInfo()->metaObject();
185 195 } else if (PyString_Check(type)) {
186 196 typeName = PyString_AsString(type);
187 197 }
188 198
189 199 QList<QObject*> list;
190 200
191 201 if (!typeName && !meta)
192 202 return list;
193 203
194 204 findChildren(parent, typeName, meta, name, list);
195 205
196 206 return list;
197 207 }
198 208
199 209 QList<QObject*> PythonQtStdDecorators::findChildren(QObject* parent, PyObject* type, const QRegExp& regExp)
200 210 {
201 211 const QMetaObject* meta = NULL;
202 212 const char* typeName = NULL;
203 213
204 214 if (PyObject_TypeCheck(type, &PythonQtClassWrapper_Type)) {
205 215 meta = ((PythonQtClassWrapper*)type)->classInfo()->metaObject();
206 216 } else if (PyObject_TypeCheck(type, &PythonQtInstanceWrapper_Type)) {
207 217 meta = ((PythonQtInstanceWrapper*)type)->classInfo()->metaObject();
208 218 } else if (PyString_Check(type)) {
209 219 typeName = PyString_AsString(type);
210 220 }
211 221
212 222 QList<QObject*> list;
213 223
214 224 if (!typeName && !meta)
215 225 return list;
216 226
217 227 findChildren(parent, typeName, meta, regExp, list);
218 228
219 229 return list;
220 230 }
221 231
222 232 QObject* PythonQtStdDecorators::findChild(QObject* parent, const char* typeName, const QMetaObject* meta, const QString& name)
223 233 {
224 234 const QObjectList &children = parent->children();
225 235
226 236 int i;
227 237 for (i = 0; i < children.size(); ++i) {
228 238 QObject* obj = children.at(i);
229 239
230 240 if (!obj)
231 241 return NULL;
232 242
233 243 // Skip if the name doesn't match.
234 244 if (!name.isNull() && obj->objectName() != name)
235 245 continue;
236 246
237 247 if ((typeName && obj->inherits(typeName)) ||
238 248 (meta && meta->cast(obj)))
239 249 return obj;
240 250 }
241 251
242 252 for (i = 0; i < children.size(); ++i) {
243 253 QObject* obj = findChild(children.at(i), typeName, meta, name);
244 254
245 255 if (obj != NULL)
246 256 return obj;
247 257 }
248 258
249 259 return NULL;
250 260 }
251 261
252 262 int PythonQtStdDecorators::findChildren(QObject* parent, const char* typeName, const QMetaObject* meta, const QString& name, QList<QObject*>& list)
253 263 {
254 264 const QObjectList& children = parent->children();
255 265 int i;
256 266
257 267 for (i = 0; i < children.size(); ++i) {
258 268 QObject* obj = children.at(i);
259 269
260 270 if (!obj)
261 271 return -1;
262 272
263 273 // Skip if the name doesn't match.
264 274 if (!name.isNull() && obj->objectName() != name)
265 275 continue;
266 276
267 277 if ((typeName && obj->inherits(typeName)) ||
268 278 (meta && meta->cast(obj))) {
269 279 list += obj;
270 280 }
271 281
272 282 if (findChildren(obj, typeName, meta, name, list) < 0)
273 283 return -1;
274 284 }
275 285
276 286 return 0;
277 287 }
278 288
279 289 int PythonQtStdDecorators::findChildren(QObject* parent, const char* typeName, const QMetaObject* meta, const QRegExp& regExp, QList<QObject*>& list)
280 290 {
281 291 const QObjectList& children = parent->children();
282 292 int i;
283 293
284 294 for (i = 0; i < children.size(); ++i) {
285 295 QObject* obj = children.at(i);
286 296
287 297 if (!obj)
288 298 return -1;
289 299
290 300 // Skip if the name doesn't match.
291 301 if (regExp.indexIn(obj->objectName()) == -1)
292 302 continue;
293 303
294 304 if ((typeName && obj->inherits(typeName)) ||
295 305 (meta && meta->cast(obj))) {
296 306 list += obj;
297 307 }
298 308
299 309 if (findChildren(obj, typeName, meta, regExp, list) < 0)
300 310 return -1;
301 311 }
302 312
303 313 return 0;
304 314 }
@@ -1,109 +1,112
1 1 #ifndef _PYTHONQTSTDDECORATORS_H
2 2 #define _PYTHONQTSTDDECORATORS_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 PythonQtStdDecorators.h
39 39 // \author Florian Link
40 40 // \author Last changed by $Author: florian $
41 41 // \date 2007-04
42 42 */
43 43 //----------------------------------------------------------------------------------
44 44
45 45 #include "PythonQtSystem.h"
46 46 #include <Python.h>
47 47 #include <QObject>
48 48 #include <QVariantList>
49 49 #include <QTextDocument>
50 50 #include <QColor>
51 51 #include <QDateTime>
52 52 #include <QDate>
53 53 #include <QTime>
54 54
55 55 class PYTHONQT_EXPORT PythonQtStdDecorators : public QObject
56 56 {
57 57 Q_OBJECT
58 58
59 59 public slots:
60 60 bool connect(QObject* sender, const QByteArray& signal, PyObject* callable);
61 61 bool connect(QObject* sender, const QByteArray& signal, QObject* receiver, const QByteArray& slot);
62 62 bool disconnect(QObject* sender, const QByteArray& signal, PyObject* callable);
63 63 bool disconnect(QObject* sender, const QByteArray& signal, QObject* receiver, const QByteArray& slot);
64 64
65 65 #undef emit
66 66 void emit(QObject* sender, const QByteArray& signal, PyObject* arg1 = NULL,PyObject* arg2 = NULL,
67 67 PyObject* arg3 = NULL,PyObject* arg4 = NULL,PyObject* arg5 = NULL,PyObject* arg6 = NULL,PyObject* arg7 = NULL);
68 68 #define emit
69 69
70 70 QObject* parent(QObject* o);
71 71 void setParent(QObject* o, QObject* parent);
72 72
73 73 const QObjectList* children(QObject* o);
74 74 QObject* findChild(QObject* parent, PyObject* type, const QString& name = QString());
75 75 QList<QObject*> findChildren(QObject* parent, PyObject* type, const QString& name= QString());
76 76 QList<QObject*> findChildren(QObject* parent, PyObject* type, const QRegExp& regExp);
77 77
78 bool setProperty(QObject* o, const char* name, const QVariant& value);
79 QVariant property(QObject* o, const char* name);
80
78 81 double static_Qt_qAbs(double a) { return qAbs(a); }
79 82 double static_Qt_qBound(double a,double b,double c) { return qBound(a,b,c); }
80 83 void static_Qt_qDebug(const QByteArray& msg) { qDebug(msg.constData()); }
81 84 // TODO: multi arg qDebug...
82 85 void static_Qt_qWarning(const QByteArray& msg) { qWarning(msg.constData()); }
83 86 // TODO: multi arg qWarning...
84 87 void static_Qt_qCritical(const QByteArray& msg) { qCritical(msg.constData()); }
85 88 // TODO: multi arg qCritical...
86 89 void static_Qt_qFatal(const QByteArray& msg) { qFatal(msg.constData()); }
87 90 // TODO: multi arg qFatal...
88 91 bool static_Qt_qFuzzyCompare(double a, double b) { return qFuzzyCompare(a, b); }
89 92 double static_Qt_qMax(double a, double b) { return qMax(a, b); }
90 93 double static_Qt_qMin(double a, double b) { return qMin(a, b); }
91 94 int static_Qt_qRound(double a) { return qRound(a); }
92 95 qint64 static_Qt_qRound64(double a) { return qRound64(a); }
93 96 const char* static_Qt_qVersion() { return qVersion(); }
94 97 int static_Qt_qrand() { return qrand(); }
95 98 void static_Qt_qsrand(uint a) { qsrand(a); }
96 99
97 100 QString tr(QObject* obj, const QByteArray& text, const QByteArray& ambig = QByteArray(), int n = -1);
98 101
99 102 QByteArray static_Qt_SIGNAL(const QByteArray& s) { return QByteArray("2") + s; }
100 103 QByteArray static_Qt_SLOT(const QByteArray& s) { return QByteArray("1") + s; }
101 104
102 105 private:
103 106 QObject* findChild(QObject* parent, const char* typeName, const QMetaObject* meta, const QString& name);
104 107 int findChildren(QObject* parent, const char* typeName, const QMetaObject* meta, const QString& name, QList<QObject*>& list);
105 108 int findChildren(QObject* parent, const char* typeName, const QMetaObject* meta, const QRegExp& regExp, QList<QObject*>& list);
106 109 };
107 110
108 111
109 112 #endif
General Comments 0
You need to be logged in to leave comments. Login now