##// END OF EJS Templates
code cleanup and rename of PythonQtWrapper to PythonQtInstanceWrapper and PythonQtMetaObjectWrapper to PythonQtClassWrapper, since these names match much better what these classes wrap, regarding that we are wrapping CPP objects as well...
florianlink -
r16:c68e0aff542c
parent child
Show More
@@ -1,1081 +1,1081
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 "PythonQt.h"
43 43 #include "PythonQtImporter.h"
44 44 #include "PythonQtClassInfo.h"
45 45 #include "PythonQtMethodInfo.h"
46 46 #include "PythonQtSignalReceiver.h"
47 47 #include "PythonQtConversion.h"
48 48 #include "PythonQtStdOut.h"
49 49 #include "PythonQtCppWrapperFactory.h"
50 50 #include "PythonQtVariants.h"
51 51 #include "PythonQtStdDecorators.h"
52 52 #include "PythonQtQFileImporter.h"
53 53 #include <pydebug.h>
54 54 #include <vector>
55 55
56 56 PythonQt* PythonQt::_self = NULL;
57 57 int PythonQt::_uniqueModuleCount = 0;
58 58
59 59 void PythonQt::init(int flags)
60 60 {
61 61 if (!_self) {
62 62 _self = new PythonQt(flags);
63 63 }
64 64
65 65 PythonQtMethodInfo::addParameterTypeAlias("QObjectList", "QList<QObject*>");
66 66 qRegisterMetaType<QList<QObject*> >("QList<void*>");
67 67
68 68 PythonQtRegisterToolClassesTemplateConverter(int);
69 69 PythonQtRegisterToolClassesTemplateConverter(float);
70 70 PythonQtRegisterToolClassesTemplateConverter(double);
71 71 // TODO: which other POD types should be available for QList etc.
72 72
73 73 PythonQt::self()->addDecorators(new PythonQtStdDecorators());
74 74
75 75 PythonQt::self()->registerCPPClass("Qt", "", "QtCore", PythonQtCreateObject<PythonQtWrapper_Qt>);
76 76 PythonQt::self()->registerCPPClass("QBitArray", "", "QtCore", PythonQtCreateObject<PythonQtWrapper_QBitArray>);
77 77 PythonQt::self()->registerCPPClass("QDate", "", "QtCore", PythonQtCreateObject<PythonQtWrapper_QDate>);
78 78 PythonQt::self()->registerCPPClass("QTime", "", "QtCore", PythonQtCreateObject<PythonQtWrapper_QTime>);
79 79 PythonQt::self()->registerCPPClass("QDateTime", "", "QtCore", PythonQtCreateObject<PythonQtWrapper_QDateTime>);
80 80 PythonQt::self()->registerCPPClass("QUrl", "", "QtCore", PythonQtCreateObject<PythonQtWrapper_QUrl>);
81 81 PythonQt::self()->registerCPPClass("QLocale", "", "QtCore", PythonQtCreateObject<PythonQtWrapper_QLocale>);
82 82 PythonQt::self()->registerCPPClass("QRect", "", "QtCore", PythonQtCreateObject<PythonQtWrapper_QRect>);
83 83 PythonQt::self()->registerCPPClass("QRectF", "", "QtCore", PythonQtCreateObject<PythonQtWrapper_QRectF>);
84 84 PythonQt::self()->registerCPPClass("QSize", "", "QtCore", PythonQtCreateObject<PythonQtWrapper_QSize>);
85 85 PythonQt::self()->registerCPPClass("QSizeF", "", "QtCore", PythonQtCreateObject<PythonQtWrapper_QSizeF>);
86 86 PythonQt::self()->registerCPPClass("QLine", "", "QtCore", PythonQtCreateObject<PythonQtWrapper_QLine>);
87 87 PythonQt::self()->registerCPPClass("QLineF", "", "QtCore", PythonQtCreateObject<PythonQtWrapper_QLineF>);
88 88 PythonQt::self()->registerCPPClass("QPoint", "", "QtCore", PythonQtCreateObject<PythonQtWrapper_QPoint>);
89 89 PythonQt::self()->registerCPPClass("QPointF", "", "QtCore", PythonQtCreateObject<PythonQtWrapper_QPointF>);
90 90 PythonQt::self()->registerCPPClass("QRegExp", "", "QtCore", PythonQtCreateObject<PythonQtWrapper_QRegExp>);
91 91
92 92 PythonQtRegisterToolClassesTemplateConverter(QDate);
93 93 PythonQtRegisterToolClassesTemplateConverter(QTime);
94 94 PythonQtRegisterToolClassesTemplateConverter(QDateTime);
95 95 PythonQtRegisterToolClassesTemplateConverter(QUrl);
96 96 PythonQtRegisterToolClassesTemplateConverter(QLocale);
97 97 PythonQtRegisterToolClassesTemplateConverter(QRect);
98 98 PythonQtRegisterToolClassesTemplateConverter(QRectF);
99 99 PythonQtRegisterToolClassesTemplateConverter(QSize);
100 100 PythonQtRegisterToolClassesTemplateConverter(QSizeF);
101 101 PythonQtRegisterToolClassesTemplateConverter(QLine);
102 102 PythonQtRegisterToolClassesTemplateConverter(QLineF);
103 103 PythonQtRegisterToolClassesTemplateConverter(QPoint);
104 104 PythonQtRegisterToolClassesTemplateConverter(QPointF);
105 105 PythonQtRegisterToolClassesTemplateConverter(QRegExp);
106 106
107 107 PythonQt::self()->registerCPPClass("QFont", "", "QtGui", PythonQtCreateObject<PythonQtWrapper_QFont>);
108 108 PythonQt::self()->registerCPPClass("QPixmap", "", "QtGui", PythonQtCreateObject<PythonQtWrapper_QPixmap>);
109 109 PythonQt::self()->registerCPPClass("QBrush", "", "QtGui", PythonQtCreateObject<PythonQtWrapper_QBrush>);
110 110 PythonQt::self()->registerCPPClass("QColor", "", "QtGui", PythonQtCreateObject<PythonQtWrapper_QColor>);
111 111 PythonQt::self()->registerCPPClass("QPalette", "", "QtGui", PythonQtCreateObject<PythonQtWrapper_QPalette>);
112 112 PythonQt::self()->registerCPPClass("QIcon", "", "QtGui", PythonQtCreateObject<PythonQtWrapper_QIcon>);
113 113 PythonQt::self()->registerCPPClass("QImage", "", "QtGui", PythonQtCreateObject<PythonQtWrapper_QImage>);
114 114 PythonQt::self()->registerCPPClass("QPolygon", "", "QtGui", PythonQtCreateObject<PythonQtWrapper_QPolygon>);
115 115 PythonQt::self()->registerCPPClass("QRegion", "", "QtGui", PythonQtCreateObject<PythonQtWrapper_QRegion>);
116 116 PythonQt::self()->registerCPPClass("QBitmap", "", "QtGui", PythonQtCreateObject<PythonQtWrapper_QBitmap>);
117 117 PythonQt::self()->registerCPPClass("QCursor", "", "QtGui", PythonQtCreateObject<PythonQtWrapper_QCursor>);
118 118 PythonQt::self()->registerCPPClass("QSizePolicy", "", "QtGui", PythonQtCreateObject<PythonQtWrapper_QSizePolicy>);
119 119 PythonQt::self()->registerCPPClass("QKeySequence", "", "QtGui", PythonQtCreateObject<PythonQtWrapper_QKeySequence>);
120 120 PythonQt::self()->registerCPPClass("QPen", "", "QtGui", PythonQtCreateObject<PythonQtWrapper_QPen>);
121 121 PythonQt::self()->registerCPPClass("QTextLength", "", "QtGui", PythonQtCreateObject<PythonQtWrapper_QTextLength>);
122 122 PythonQt::self()->registerCPPClass("QTextFormat", "", "QtGui", PythonQtCreateObject<PythonQtWrapper_QTextFormat>);
123 123 PythonQt::self()->registerCPPClass("QMatrix", "", "QtGui", PythonQtCreateObject<PythonQtWrapper_QMatrix>);
124 124
125 125 PythonQtRegisterToolClassesTemplateConverter(QFont);
126 126 PythonQtRegisterToolClassesTemplateConverter(QPixmap);
127 127 PythonQtRegisterToolClassesTemplateConverter(QBrush);
128 128 PythonQtRegisterToolClassesTemplateConverter(QColor);
129 129 PythonQtRegisterToolClassesTemplateConverter(QPalette);
130 130 PythonQtRegisterToolClassesTemplateConverter(QIcon);
131 131 PythonQtRegisterToolClassesTemplateConverter(QImage);
132 132 PythonQtRegisterToolClassesTemplateConverter(QPolygon);
133 133 PythonQtRegisterToolClassesTemplateConverter(QRegion);
134 134 PythonQtRegisterToolClassesTemplateConverter(QBitmap);
135 135 PythonQtRegisterToolClassesTemplateConverter(QCursor);
136 136 PythonQtRegisterToolClassesTemplateConverter(QSizePolicy);
137 137 PythonQtRegisterToolClassesTemplateConverter(QKeySequence);
138 138 PythonQtRegisterToolClassesTemplateConverter(QPen);
139 139 PythonQtRegisterToolClassesTemplateConverter(QTextLength);
140 140 PythonQtRegisterToolClassesTemplateConverter(QTextFormat);
141 141 PythonQtRegisterToolClassesTemplateConverter(QMatrix);
142 142
143 143 }
144 144
145 145 void PythonQt::cleanup()
146 146 {
147 147 if (_self) {
148 148 delete _self;
149 149 _self = NULL;
150 150 }
151 151 }
152 152
153 153 PythonQt::PythonQt(int flags)
154 154 {
155 155 _p = new PythonQtPrivate;
156 156 _p->_initFlags = flags;
157 157
158 158 _p->_PythonQtObjectPtr_metaId = qRegisterMetaType<PythonQtObjectPtr>("PythonQtObjectPtr");
159 159
160 160 Py_SetProgramName("PythonQt");
161 161 if (flags & IgnoreSiteModule) {
162 162 // this prevents the automatic importing of Python site files
163 163 Py_NoSiteFlag = 1;
164 164 }
165 165 Py_Initialize();
166 166
167 167 // add our own python object types for qt object slots
168 168 if (PyType_Ready(&PythonQtSlotFunction_Type) < 0) {
169 169 std::cerr << "could not initialize PythonQtSlotFunction_Type" << ", in " << __FILE__ << ":" << __LINE__ << std::endl;
170 170 }
171 171 Py_INCREF(&PythonQtSlotFunction_Type);
172 172
173 173 // add our own python object types for qt objects
174 if (PyType_Ready(&PythonQtWrapper_Type) < 0) {
175 std::cerr << "could not initialize PythonQtWrapper_Type" << ", in " << __FILE__ << ":" << __LINE__ << std::endl;
174 if (PyType_Ready(&PythonQtInstanceWrapper_Type) < 0) {
175 std::cerr << "could not initialize PythonQtInstanceWrapper_Type" << ", in " << __FILE__ << ":" << __LINE__ << std::endl;
176 176 }
177 Py_INCREF(&PythonQtWrapper_Type);
177 Py_INCREF(&PythonQtInstanceWrapper_Type);
178 178
179 179 // add our own python object types for qt objects
180 if (PyType_Ready(&PythonQtMetaObjectWrapper_Type) < 0) {
181 std::cerr << "could not initialize PythonQtMetaObjectWrapper_Type" << ", in " << __FILE__ << ":" << __LINE__ << std::endl;
180 if (PyType_Ready(&PythonQtClassWrapper_Type) < 0) {
181 std::cerr << "could not initialize PythonQtClassWrapper_Type" << ", in " << __FILE__ << ":" << __LINE__ << std::endl;
182 182 }
183 Py_INCREF(&PythonQtMetaObjectWrapper_Type);
183 Py_INCREF(&PythonQtClassWrapper_Type);
184 184
185 185 // add our own python object types for redirection of stdout
186 186 if (PyType_Ready(&PythonQtStdOutRedirectType) < 0) {
187 187 std::cerr << "could not initialize PythonQtStdOutRedirectType" << ", in " << __FILE__ << ":" << __LINE__ << std::endl;
188 188 }
189 189 Py_INCREF(&PythonQtStdOutRedirectType);
190 190
191 191 initPythonQtModule(flags & RedirectStdOut);
192 192
193 193 }
194 194
195 195 PythonQt::~PythonQt() {
196 196 delete _p;
197 197 _p = NULL;
198 198 }
199 199
200 200 PythonQtPrivate::~PythonQtPrivate() {
201 201 delete _defaultImporter;
202 202 _defaultImporter = NULL;
203 203 {
204 204 QHashIterator<QByteArray, PythonQtSlotInfo *> i(_knownQtDecoratorSlots);
205 205 while (i.hasNext()) {
206 206 delete i.next().value();
207 207 }
208 208 }
209 209 {
210 210 QHashIterator<QByteArray, PythonQtClassInfo *> i(_knownQtClasses);
211 211 while (i.hasNext()) {
212 212 delete i.next().value();
213 213 }
214 214 }
215 215 {
216 216 QHashIterator<QByteArray, PythonQtClassInfo *> i(_knownQtWrapperClasses);
217 217 while (i.hasNext()) {
218 218 delete i.next().value();
219 219 }
220 220 }
221 221 {
222 222 QHashIterator<QByteArray, PythonQtSlotInfo *> i(_constructorSlots);
223 223 while (i.hasNext()) {
224 224 PythonQtSlotInfo* cur = i.next().value();
225 225 while(cur->nextInfo()) {
226 226 PythonQtSlotInfo* next = cur->nextInfo();
227 227 delete cur;
228 228 cur = next;
229 229 }
230 230 delete cur;
231 231 }
232 232 }
233 233 {
234 234 QHashIterator<QByteArray, PythonQtSlotInfo *> i(_destructorSlots);
235 235 while (i.hasNext()) {
236 236 PythonQtSlotInfo* cur = i.next().value();
237 237 while(cur->nextInfo()) {
238 238 PythonQtSlotInfo* next = cur->nextInfo();
239 239 delete cur;
240 240 cur = next;
241 241 }
242 242 delete cur;
243 243 }
244 244 }
245 245 PythonQtConv::global_valueStorage.clear();
246 246 PythonQtConv::global_ptrStorage.clear();
247 247 PythonQtConv::global_variantStorage.clear();
248 248
249 249 PythonQtMethodInfo::cleanupCachedMethodInfos();
250 250 }
251 251
252 252 PythonQtImportFileInterface* PythonQt::importInterface()
253 253 {
254 254 return _self->_p->_importInterface?_self->_p->_importInterface:_self->_p->_defaultImporter;
255 255 }
256 256
257 257 void PythonQt::qObjectNoLongerWrappedCB(QObject* o)
258 258 {
259 259 if (_self->_p->_noLongerWrappedCB) {
260 260 (*_self->_p->_noLongerWrappedCB)(o);
261 261 };
262 262 }
263 263
264 264 void PythonQt::registerClass(const QMetaObject* metaobject, const char* package, PythonQtQObjectCreatorFunctionCB* wrapperCreator)
265 265 {
266 266 _p->registerClass(metaobject, package, wrapperCreator);
267 267 }
268 268
269 269 void PythonQtPrivate::registerClass(const QMetaObject* metaobject, const char* package, PythonQtQObjectCreatorFunctionCB* wrapperCreator)
270 270 {
271 271 // we register all classes in the hierarchy
272 272 const QMetaObject* m = metaobject;
273 273 bool first = true;
274 274 while (m) {
275 275 PythonQtClassInfo* info = _knownQtClasses.value(m->className());
276 276 if (!info) {
277 277 info = new PythonQtClassInfo(m);
278 278 _knownQtClasses.insert(m->className(), info);
279 279 PythonQtObjectPtr pack = packageByName(package);
280 PyObject* pyobj = (PyObject*)createNewPythonQtMetaObjectWrapper(info);
280 PyObject* pyobj = (PyObject*)createNewPythonQtClassWrapper(info);
281 281 PyModule_AddObject(pack, m->className(), pyobj);
282 282 if (package && strncmp(package,"Qt",2)==0) {
283 283 // put all qt objects into Qt as well
284 284 PythonQtObjectPtr pack = packageByName("Qt");
285 285 PyModule_AddObject(pack, m->className(), pyobj);
286 286 }
287 287 }
288 288 if (first) {
289 289 first = false;
290 290 if (wrapperCreator) {
291 291 info->setDecoratorProvider(wrapperCreator);
292 292 }
293 293 }
294 294 m = m->superClass();
295 295 }
296 296 }
297 297
298 298 bool PythonQtPrivate::isEnumType(const QMetaObject* meta, const QByteArray& name) {
299 299 int i = meta?meta->indexOfEnumerator(name.constData()):-1;
300 300 if (i!=-1) {
301 301 return true;
302 302 } else {
303 303 // look for scope
304 304 int scopePos = name.indexOf("::");
305 305 if (scopePos != -1) {
306 306 // slit into scope and enum name
307 307 QByteArray enumScope = name.mid(0,scopePos);
308 308 QByteArray enumName = name.mid(scopePos+2);
309 309 if (enumScope == "Qt") {
310 310 // special qt namespace case
311 311 return isEnumType(&staticQtMetaObject, enumName);
312 312 } else {
313 313 // look for known classes as scope
314 314 // TODO: Q_GADGETS are not yet handled
315 315 PythonQtClassInfo* info = _knownQtClasses.value(enumScope);
316 316 if (info) {
317 317 return isEnumType(info->metaObject(), enumName);
318 318 }
319 319 }
320 320 }
321 321 }
322 322 return false;
323 323 }
324 324
325 325 PyObject* PythonQtPrivate::wrapQObject(QObject* obj)
326 326 {
327 327 if (!obj) {
328 328 Py_INCREF(Py_None);
329 329 return Py_None;
330 330 }
331 PythonQtWrapper* wrap = findWrapperAndRemoveUnused(obj);
331 PythonQtInstanceWrapper* wrap = findWrapperAndRemoveUnused(obj);
332 332 if (!wrap) {
333 333 // smuggling it in...
334 334 PythonQtClassInfo* classInfo = _knownQtClasses.value(obj->metaObject()->className());
335 335 if (!classInfo) {
336 336 registerClass(obj->metaObject());
337 337 classInfo = _knownQtClasses.value(obj->metaObject()->className());
338 338 }
339 wrap = createNewPythonQtWrapper(obj, classInfo);
339 wrap = createNewPythonQtInstanceWrapper(obj, classInfo);
340 340 // mlabDebugConst("MLABPython","new qobject wrapper added " << " " << wrap->_obj->className() << " " << wrap->_info->wrappedClassName().latin1());
341 341 } else {
342 342 Py_INCREF(wrap);
343 343 // mlabDebugConst("MLABPython","qobject wrapper reused " << wrap->_obj->className() << " " << wrap->_info->wrappedClassName().latin1());
344 344 }
345 345 return (PyObject*)wrap;
346 346 }
347 347
348 348 PyObject* PythonQtPrivate::wrapPtr(void* ptr, const QByteArray& name)
349 349 {
350 350 if (!ptr) {
351 351 Py_INCREF(Py_None);
352 352 return Py_None;
353 353 }
354 PythonQtWrapper* wrap = findWrapperAndRemoveUnused(ptr);
354 PythonQtInstanceWrapper* wrap = findWrapperAndRemoveUnused(ptr);
355 355 if (!wrap) {
356 356 PythonQtClassInfo* info = _knownQtClasses.value(name);
357 357 if (!info) {
358 358 // we do not know the metaobject yet, but we might know it by it's name:
359 359 if (_knownQObjectClassNames.find(name)!=_knownQObjectClassNames.end()) {
360 360 // yes, we know it, so we can convert to QObject
361 361 QObject* qptr = (QObject*)ptr;
362 362 registerClass(qptr->metaObject());
363 363 info = _knownQtClasses.value(qptr->metaObject()->className());
364 364 }
365 365 }
366 366 if (info) {
367 367 QObject* qptr = (QObject*)ptr;
368 368 // if the object is a derived object, we want to switch the class info to the one of the derived class:
369 369 if (name!=(qptr->metaObject()->className())) {
370 370 registerClass(qptr->metaObject());
371 371 info = _knownQtClasses.value(qptr->metaObject()->className());
372 372 }
373 wrap = createNewPythonQtWrapper(qptr, info);
373 wrap = createNewPythonQtInstanceWrapper(qptr, info);
374 374 // mlabDebugConst("MLABPython","new qobject wrapper added " << " " << wrap->_obj->className() << " " << wrap->_info->wrappedClassName().latin1());
375 375 } else {
376 376 // maybe it is a PyObject, which we can return directly
377 377 if (name == "PyObject") {
378 378 PyObject* p = (PyObject*)ptr;
379 379 Py_INCREF(p);
380 380 return p;
381 381 }
382 382 // not a known QObject, so try our wrapper factory:
383 383 QObject* wrapper = NULL;
384 384 for (int i=0; i<_cppWrapperFactories.size(); i++) {
385 385 wrapper = _cppWrapperFactories.at(i)->create(name, ptr);
386 386 if (wrapper) {
387 387 break;
388 388 }
389 389 }
390 390 PythonQtClassInfo* info = _knownQtWrapperClasses.value(name);
391 391 if (!info) {
392 392 info = new PythonQtClassInfo(wrapper?wrapper->metaObject():NULL, name);
393 393 _knownQtWrapperClasses.insert(name, info);
394 PyModule_AddObject(_pythonQtModule, name, (PyObject*)createNewPythonQtMetaObjectWrapper(info));
394 PyModule_AddObject(_pythonQtModule, name, (PyObject*)createNewPythonQtClassWrapper(info));
395 395 } else {
396 396 if (wrapper && (info->metaObject() != wrapper->metaObject())) {
397 397 info->setMetaObject(wrapper->metaObject());
398 398 }
399 399 }
400 wrap = createNewPythonQtWrapper(wrapper, info, ptr);
400 wrap = createNewPythonQtInstanceWrapper(wrapper, info, ptr);
401 401 // mlabDebugConst("MLABPython","new c++ wrapper added " << wrap->_wrappedPtr << " " << wrap->_obj->className() << " " << wrap->_info->wrappedClassName().latin1());
402 402 }
403 403 } else {
404 404 Py_INCREF(wrap);
405 405 //mlabDebugConst("MLABPython","c++ wrapper reused " << wrap->_wrappedPtr << " " << wrap->_obj->className() << " " << wrap->_info->wrappedClassName().latin1());
406 406 }
407 407 return (PyObject*)wrap;
408 408 }
409 409
410 410
411 PythonQtWrapper* PythonQtPrivate::createNewPythonQtWrapper(QObject* obj, PythonQtClassInfo* info, void* wrappedPtr) {
412 PythonQtWrapper* result;
413 result = (PythonQtWrapper *)PythonQtWrapper_Type.tp_new(&PythonQtWrapper_Type,
411 PythonQtInstanceWrapper* PythonQtPrivate::createNewPythonQtInstanceWrapper(QObject* obj, PythonQtClassInfo* info, void* wrappedPtr) {
412 PythonQtInstanceWrapper* result;
413 result = (PythonQtInstanceWrapper *)PythonQtInstanceWrapper_Type.tp_new(&PythonQtInstanceWrapper_Type,
414 414 NULL, NULL);
415 415
416 416 result->setQObject(obj);
417 417 result->_info = info;
418 418 result->_wrappedPtr = wrappedPtr;
419 419 result->_ownedByPythonQt = false;
420 420 result->_useQMetaTypeDestroy = false;
421 421
422 422 if (wrappedPtr) {
423 423 _wrappedObjects.insert(wrappedPtr, result);
424 424 } else {
425 425 _wrappedObjects.insert(obj, result);
426 426 if (obj->parent()== NULL && _wrappedCB) {
427 427 // tell someone who is interested that the qobject is wrapped the first time, if it has no parent
428 428 (*_wrappedCB)(obj);
429 429 }
430 430 }
431 431 return result;
432 432 }
433 433
434 PythonQtMetaObjectWrapper* PythonQtPrivate::createNewPythonQtMetaObjectWrapper(PythonQtClassInfo* info) {
435 PythonQtMetaObjectWrapper* result;
436 result = (PythonQtMetaObjectWrapper *)PythonQtMetaObjectWrapper_Type.tp_new(&PythonQtMetaObjectWrapper_Type,
434 PythonQtClassWrapper* PythonQtPrivate::createNewPythonQtClassWrapper(PythonQtClassInfo* info) {
435 PythonQtClassWrapper* result;
436 result = (PythonQtClassWrapper *)PythonQtClassWrapper_Type.tp_new(&PythonQtClassWrapper_Type,
437 437 NULL, NULL);
438 438 result->_info = info;
439 439 return result;
440 440 }
441 441
442 442
443 443 PythonQtSignalReceiver* PythonQt::getSignalReceiver(QObject* obj)
444 444 {
445 445 PythonQtSignalReceiver* r = _p->_signalReceivers[obj];
446 446 if (!r) {
447 447 r = new PythonQtSignalReceiver(obj);
448 448 _p->_signalReceivers.insert(obj, r);
449 449 }
450 450 return r;
451 451 }
452 452
453 453 bool PythonQt::addSignalHandler(QObject* obj, const char* signal, PyObject* module, const QString& objectname)
454 454 {
455 455 bool flag = false;
456 456 PythonQtObjectPtr callable = lookupCallable(module, objectname);
457 457 if (callable) {
458 458 PythonQtSignalReceiver* r = getSignalReceiver(obj);
459 459 flag = r->addSignalHandler(signal, callable);
460 460 if (!flag) {
461 461 // signal not found
462 462 }
463 463 } else {
464 464 // callable not found
465 465 }
466 466 return flag;
467 467 }
468 468
469 469 bool PythonQt::addSignalHandler(QObject* obj, const char* signal, PyObject* receiver)
470 470 {
471 471 bool flag = false;
472 472 PythonQtSignalReceiver* r = getSignalReceiver(obj);
473 473 if (r) {
474 474 flag = r->addSignalHandler(signal, receiver);
475 475 }
476 476 return flag;
477 477 }
478 478
479 479 bool PythonQt::removeSignalHandler(QObject* obj, const char* signal, PyObject* module, const QString& objectname)
480 480 {
481 481 bool flag = false;
482 482 PythonQtObjectPtr callable = lookupCallable(module, objectname);
483 483 if (callable) {
484 484 PythonQtSignalReceiver* r = _p->_signalReceivers[obj];
485 485 if (r) {
486 486 flag = r->removeSignalHandler(signal, callable);
487 487 }
488 488 } else {
489 489 // callable not found
490 490 }
491 491 return flag;
492 492 }
493 493
494 494 bool PythonQt::removeSignalHandler(QObject* obj, const char* signal, PyObject* receiver)
495 495 {
496 496 bool flag = false;
497 497 PythonQtSignalReceiver* r = _p->_signalReceivers[obj];
498 498 if (r) {
499 499 flag = r->removeSignalHandler(signal, receiver);
500 500 }
501 501 return flag;
502 502 }
503 503
504 504 PythonQtObjectPtr PythonQt::lookupCallable(PyObject* module, const QString& name)
505 505 {
506 506 PythonQtObjectPtr p = lookupObject(module, name);
507 507 if (p) {
508 508 if (PyCallable_Check(p)) {
509 509 return p;
510 510 }
511 511 }
512 512 PyErr_Clear();
513 513 return NULL;
514 514 }
515 515
516 516 PythonQtObjectPtr PythonQt::lookupObject(PyObject* module, const QString& name)
517 517 {
518 518 QStringList l = name.split('.');
519 519 PythonQtObjectPtr p = module;
520 520 PythonQtObjectPtr prev;
521 521 QString s;
522 522 QByteArray b;
523 523 for (QStringList::ConstIterator i = l.begin(); i!=l.end() && p; ++i) {
524 524 prev = p;
525 525 b = (*i).toLatin1();
526 526 p.setNewRef(PyObject_GetAttrString(p, b.data()));
527 527 }
528 528 PyErr_Clear();
529 529 return p;
530 530 }
531 531
532 532 PythonQtObjectPtr PythonQt::getMainModule() {
533 533 //both borrowed
534 534 PythonQtObjectPtr dict = PyImport_GetModuleDict();
535 535 return PyDict_GetItemString(dict, "__main__");
536 536 }
537 537
538 538 QVariant PythonQt::evalCode(PyObject* module, PyObject* pycode) {
539 539 QVariant result;
540 540 if (pycode) {
541 541 PyObject* r = PyEval_EvalCode((PyCodeObject*)pycode, PyModule_GetDict((PyObject*)module) , PyModule_GetDict((PyObject*)module));
542 542 if (r) {
543 543 result = PythonQtConv::PyObjToQVariant(r);
544 544 Py_DECREF(r);
545 545 } else {
546 546 handleError();
547 547 }
548 548 } else {
549 549 handleError();
550 550 }
551 551 return result;
552 552 }
553 553
554 554 QVariant PythonQt::evalScript(PyObject* module, const QString& script, int start)
555 555 {
556 556 QVariant result;
557 557 PythonQtObjectPtr p;
558 558 p.setNewRef(PyRun_String(script.toLatin1().data(), start, PyModule_GetDict(module), PyModule_GetDict(module)));
559 559 if (p) {
560 560 result = PythonQtConv::PyObjToQVariant(p);
561 561 } else {
562 562 handleError();
563 563 }
564 564 return result;
565 565 }
566 566
567 567 void PythonQt::evalFile(PyObject* module, const QString& filename)
568 568 {
569 569 PythonQtObjectPtr code = parseFile(filename);
570 570 if (code) {
571 571 evalCode(module, code);
572 572 } else {
573 573 handleError();
574 574 }
575 575 }
576 576
577 577 PythonQtObjectPtr PythonQt::parseFile(const QString& filename)
578 578 {
579 579 PythonQtObjectPtr p;
580 580 p.setNewRef(PythonQtImport::getCodeFromPyc(filename));
581 581 if (!p) {
582 582 handleError();
583 583 }
584 584 return p;
585 585 }
586 586
587 587 PythonQtObjectPtr PythonQt::createModuleFromFile(const QString& name, const QString& filename)
588 588 {
589 589 PythonQtObjectPtr code = parseFile(filename);
590 590 PythonQtObjectPtr module = _p->createModule(name, code);
591 591 return module;
592 592 }
593 593
594 594 PythonQtObjectPtr PythonQt::createModuleFromScript(const QString& name, const QString& script)
595 595 {
596 596 PyErr_Clear();
597 597 QString scriptCode = script;
598 598 if (scriptCode.isEmpty()) {
599 599 // we always need at least a linefeed
600 600 scriptCode = "\n";
601 601 }
602 602 PythonQtObjectPtr pycode;
603 603 pycode.setNewRef(Py_CompileString((char*)scriptCode.toLatin1().data(), "", Py_file_input));
604 604 PythonQtObjectPtr module = _p->createModule(name, pycode);
605 605 return module;
606 606 }
607 607
608 608 PythonQtObjectPtr PythonQt::createUniqueModule()
609 609 {
610 610 static QString pyQtStr("PythonQt_module");
611 611 QString moduleName = pyQtStr+QString::number(_uniqueModuleCount++);
612 612 return createModuleFromScript(moduleName);
613 613 }
614 614
615 615 void PythonQt::addObject(PyObject* module, const QString& name, QObject* object)
616 616 {
617 617 PyModule_AddObject(module, name.toLatin1().data(), _p->wrapQObject(object));
618 618 }
619 619
620 620 void PythonQt::addVariable(PyObject* module, const QString& name, const QVariant& v)
621 621 {
622 622 PyModule_AddObject(module, name.toLatin1().data(), PythonQtConv::QVariantToPyObject(v));
623 623 }
624 624
625 625 void PythonQt::removeVariable(PyObject* module, const QString& name)
626 626 {
627 627 PyObject_DelAttrString(module, name.toLatin1().data());
628 628 }
629 629
630 630 QVariant PythonQt::getVariable(PyObject* module, const QString& objectname)
631 631 {
632 632 QVariant result;
633 633 PythonQtObjectPtr obj = lookupObject(module, objectname);
634 634 if (obj) {
635 635 result = PythonQtConv::PyObjToQVariant(obj);
636 636 }
637 637 return result;
638 638 }
639 639
640 640 QStringList PythonQt::introspection(PyObject* module, const QString& objectname, PythonQt::ObjectType type)
641 641 {
642 642 QStringList results;
643 643
644 644 PythonQtObjectPtr object;
645 645 if (objectname.isEmpty()) {
646 646 object = module;
647 647 } else {
648 648 object = lookupObject(module, objectname);
649 649 if (!object && type == CallOverloads) {
650 650 PyObject* dict = lookupObject(module, "__builtins__");
651 651 if (dict) {
652 652 object = PyDict_GetItemString(dict, objectname.toLatin1().constData());
653 653 }
654 654 }
655 655 }
656 656
657 657 if (object) {
658 658 if (type == CallOverloads) {
659 659 if (PythonQtSlotFunction_Check(object)) {
660 660 PythonQtSlotFunctionObject* o = (PythonQtSlotFunctionObject*)object.object();
661 661 PythonQtSlotInfo* info = o->m_ml;
662 662
663 663 while (info) {
664 664 results << info->fullSignature(info->isInstanceDecorator());
665 665 info = info->nextInfo();
666 666 }
667 } else if (object->ob_type == &PythonQtMetaObjectWrapper_Type) {
668 PythonQtMetaObjectWrapper* o = (PythonQtMetaObjectWrapper*)object.object();
667 } else if (object->ob_type == &PythonQtClassWrapper_Type) {
668 PythonQtClassWrapper* o = (PythonQtClassWrapper*)object.object();
669 669 PythonQtSlotInfo* info = o->_info->constructors();
670 670
671 671 while (info) {
672 672 results << info->fullSignature(false);
673 673 info = info->nextInfo();
674 674 }
675 675 } else {
676 676 //TODO: use pydoc!
677 677 PyObject* doc = PyObject_GetAttrString(object, "__doc__");
678 678 if (doc) {
679 679 results << PyString_AsString(doc);
680 680 Py_DECREF(doc);
681 681 }
682 682 }
683 683 } else {
684 684 PyObject* keys = PyObject_Dir(object);
685 685 if (keys) {
686 686 int count = PyList_Size(keys);
687 687 PyObject* key;
688 688 PyObject* value;
689 689 QString keystr;
690 690 for (int i = 0;i<count;i++) {
691 691 key = PyList_GetItem(keys,i);
692 692 value = PyObject_GetAttr(object, key);
693 693 if (!value) continue;
694 694 keystr = PyString_AsString(key);
695 695 static const QString underscoreStr("__tmp");
696 696 if (!keystr.startsWith(underscoreStr)) {
697 697 switch (type) {
698 698 case Anything:
699 699 results << keystr;
700 700 break;
701 701 case Class:
702 702 if (value->ob_type == &PyClass_Type) {
703 703 results << keystr;
704 704 }
705 705 break;
706 706 case Variable:
707 707 if (value->ob_type != &PyClass_Type
708 708 && value->ob_type != &PyCFunction_Type
709 709 && value->ob_type != &PyFunction_Type
710 710 && value->ob_type != &PyModule_Type
711 711 ) {
712 712 results << keystr;
713 713 }
714 714 break;
715 715 case Function:
716 716 if (value->ob_type == &PyFunction_Type ||
717 717 value->ob_type == &PyMethod_Type
718 718 ) {
719 719 results << keystr;
720 720 }
721 721 break;
722 722 case Module:
723 723 if (value->ob_type == &PyModule_Type) {
724 724 results << keystr;
725 725 }
726 726 break;
727 727 default:
728 728 std::cerr << "PythonQt: introspection: unknown case" << ", in " << __FILE__ << ":" << __LINE__ << std::endl;
729 729 }
730 730 }
731 731 Py_DECREF(value);
732 732 }
733 733 Py_DECREF(keys);
734 734 }
735 735 }
736 736 }
737 737 return results;
738 738 }
739 739
740 740 QVariant PythonQt::call(PyObject* module, const QString& name, const QVariantList& args)
741 741 {
742 742 QVariant r;
743 743
744 744 PythonQtObjectPtr callable = lookupCallable(module, name);
745 745 if (callable) {
746 746 PythonQtObjectPtr pargs;
747 747 int count = args.size();
748 748 if (count>0) {
749 749 pargs.setNewRef(PyTuple_New(count));
750 750 }
751 751 bool err = false;
752 752 // transform QVariants to Python
753 753 for (int i = 0; i < count; i++) {
754 754 PyObject* arg = PythonQtConv::QVariantToPyObject(args.at(i));
755 755 if (arg) {
756 756 // steals reference, no unref
757 757 PyTuple_SetItem(pargs, i,arg);
758 758 } else {
759 759 err = true;
760 760 break;
761 761 }
762 762 }
763 763
764 764 if (!err) {
765 765 PyErr_Clear();
766 766 PythonQtObjectPtr result;
767 767 result.setNewRef(PyObject_CallObject(callable, pargs));
768 768 if (result) {
769 769 // ok
770 770 r = PythonQtConv::PyObjToQVariant(result);
771 771 } else {
772 772 PythonQt::self()->handleError();
773 773 }
774 774 }
775 775 }
776 776 return r;
777 777 }
778 778
779 779 void PythonQt::addInstanceDecorators(QObject* o)
780 780 {
781 781 _p->addDecorators(o, PythonQtPrivate::InstanceDecorator);
782 782 }
783 783
784 784 void PythonQt::addClassDecorators(QObject* o)
785 785 {
786 786 _p->addDecorators(o, PythonQtPrivate::StaticDecorator | PythonQtPrivate::ConstructorDecorator | PythonQtPrivate::DestructorDecorator);
787 787 }
788 788
789 789 void PythonQt::addDecorators(QObject* o)
790 790 {
791 791 _p->addDecorators(o, PythonQtPrivate::AllDecorators);
792 792 }
793 793
794 794 void PythonQt::registerQObjectClassNames(const QStringList& names)
795 795 {
796 796 _p->registerQObjectClassNames(names);
797 797 }
798 798
799 799 void PythonQt::setImporter(PythonQtImportFileInterface* importInterface)
800 800 {
801 801 PythonQtImport::init();
802 802 _p->_importInterface = importInterface;
803 803 }
804 804
805 805 void PythonQt::setImporterIgnorePaths(const QStringList& paths)
806 806 {
807 807 _p->_importIgnorePaths = paths;
808 808 }
809 809
810 810 const QStringList& PythonQt::getImporterIgnorePaths()
811 811 {
812 812 return _p->_importIgnorePaths;
813 813 }
814 814
815 815 void PythonQt::addWrapperFactory(PythonQtCppWrapperFactory* factory)
816 816 {
817 817 _p->_cppWrapperFactories.append(factory);
818 818 }
819 819
820 820 void PythonQt::addConstructorHandler(PythonQtConstructorHandler* factory)
821 821 {
822 822 _p->_constructorHandlers.append(factory);
823 823 }
824 824
825 825 const QList<PythonQtConstructorHandler*>& PythonQt::constructorHandlers()
826 826 {
827 827 return _p->_constructorHandlers;
828 828 };
829 829
830 830 //---------------------------------------------------------------------------------------------------
831 831 PythonQtPrivate::PythonQtPrivate()
832 832 {
833 833 _importInterface = NULL;
834 834 _defaultImporter = new PythonQtQFileImporter;
835 835 _noLongerWrappedCB = NULL;
836 836 _wrappedCB = NULL;
837 837 }
838 838
839 839 void PythonQtPrivate::addDecorators(QObject* o, int decoTypes)
840 840 {
841 841 o->setParent(this);
842 842 int numMethods = o->metaObject()->methodCount();
843 843 for (int i = 0; i < numMethods; i++) {
844 844 QMetaMethod m = o->metaObject()->method(i);
845 845 if ((m.methodType() == QMetaMethod::Method ||
846 846 m.methodType() == QMetaMethod::Slot) && m.access() == QMetaMethod::Public) {
847 847 const PythonQtMethodInfo* info = PythonQtMethodInfo::getCachedMethodInfo(m);
848 848 if (qstrncmp(m.signature(), "new_", 4)==0) {
849 849 if ((decoTypes & ConstructorDecorator) == 0) continue;
850 850 // either it returns a * or a QVariant and the name starts with "new_"
851 851 bool isVariantReturn = info->parameters().at(0).typeId == PythonQtMethodInfo::Variant;
852 852 if ((info->parameters().at(0).isPointer || isVariantReturn)) {
853 853 QByteArray signature = m.signature();
854 854 QByteArray nameOfClass = signature.mid(4, signature.indexOf('(')-4);
855 855 PythonQtSlotInfo* prev = _constructorSlots.value(nameOfClass);
856 856 PythonQtSlotInfo* newSlot = new PythonQtSlotInfo(m, i, o, PythonQtSlotInfo::ClassDecorator);
857 857 if (prev) {
858 858 newSlot->setNextInfo(prev->nextInfo());
859 859 prev->setNextInfo(newSlot);
860 860 } else {
861 861 _constructorSlots.insert(nameOfClass, newSlot);
862 862 }
863 863 }
864 864 } else if (qstrncmp(m.signature(), "delete_", 7)==0) {
865 865 if ((decoTypes & DestructorDecorator) == 0) continue;
866 866 QByteArray signature = m.signature();
867 867 QByteArray nameOfClass = signature.mid(7, signature.indexOf('(')-7);
868 868 PythonQtSlotInfo* newSlot = new PythonQtSlotInfo(m, i, o, PythonQtSlotInfo::ClassDecorator);
869 869 _destructorSlots.insert(nameOfClass, newSlot);
870 870 } else if (qstrncmp(m.signature(), "static_", 7)==0) {
871 871 if ((decoTypes & StaticDecorator) == 0) continue;
872 872 QByteArray signature = m.signature();
873 873 QByteArray nameOfClass = signature.mid(signature.indexOf('_')+1);
874 874 nameOfClass = nameOfClass.mid(0, nameOfClass.indexOf('_'));
875 875 PythonQtSlotInfo* slotCopy = new PythonQtSlotInfo(m, i, o, PythonQtSlotInfo::ClassDecorator);
876 876 _knownQtDecoratorSlots.insert(nameOfClass, slotCopy);
877 877 } else {
878 878 if ((decoTypes & InstanceDecorator) == 0) continue;
879 879 if (info->parameters().count()>1) {
880 880 PythonQtMethodInfo::ParameterInfo p = info->parameters().at(1);
881 881 if (p.isPointer) {
882 882 PythonQtSlotInfo* slotCopy = new PythonQtSlotInfo(m, i, o, PythonQtSlotInfo::InstanceDecorator);
883 883 _knownQtDecoratorSlots.insert(p.name, slotCopy);
884 884 }
885 885 }
886 886 }
887 887 }
888 888 }
889 889 }
890 890
891 891 void PythonQtPrivate::registerQObjectClassNames(const QStringList& names)
892 892 {
893 893 foreach(QString name, names) {
894 894 _knownQObjectClassNames.insert(name.toLatin1(), true);
895 895 }
896 896 }
897 897
898 898 QList<PythonQtSlotInfo*> PythonQtPrivate::getDecoratorSlots(const QByteArray& className)
899 899 {
900 900 return _knownQtDecoratorSlots.values(className);
901 901 }
902 902
903 903 void PythonQtPrivate::removeSignalEmitter(QObject* obj)
904 904 {
905 905 _signalReceivers.remove(obj);
906 906 }
907 907
908 908 bool PythonQt::handleError()
909 909 {
910 910 bool flag = false;
911 911 if (PyErr_Occurred()) {
912 912
913 913 // currently we just print the error and the stderr handler parses the errors
914 914 PyErr_Print();
915 915
916 916 /*
917 917 // EXTRA: the format of the ptype and ptraceback is not really documented, so I use PyErr_Print() above
918 918 PyObject *ptype;
919 919 PyObject *pvalue;
920 920 PyObject *ptraceback;
921 921 PyErr_Fetch( &ptype, &pvalue, &ptraceback);
922 922
923 923 Py_XDECREF(ptype);
924 924 Py_XDECREF(pvalue);
925 925 Py_XDECREF(ptraceback);
926 926 */
927 927 PyErr_Clear();
928 928 flag = true;
929 929 }
930 930 return flag;
931 931 }
932 932
933 933 void PythonQt::addSysPath(const QString& path)
934 934 {
935 935 PythonQtObjectPtr sys;
936 936 sys.setNewRef(PyImport_ImportModule("sys"));
937 937 PythonQtObjectPtr obj = lookupObject(sys, "path");
938 938 PyList_Insert(obj, 0, PythonQtConv::QStringToPyObject(path));
939 939 }
940 940
941 941 void PythonQt::overwriteSysPath(const QStringList& paths)
942 942 {
943 943 PythonQtObjectPtr sys;
944 944 sys.setNewRef(PyImport_ImportModule("sys"));
945 945 PyModule_AddObject(sys, "path", PythonQtConv::QStringListToPyList(paths));
946 946 }
947 947
948 948 void PythonQt::setModuleImportPath(PyObject* module, const QStringList& paths)
949 949 {
950 950 PyModule_AddObject(module, "__path__", PythonQtConv::QStringListToPyList(paths));
951 951 }
952 952
953 953 void PythonQt::stdOutRedirectCB(const QString& str)
954 954 {
955 955 emit PythonQt::self()->pythonStdOut(str);
956 956 }
957 957
958 958 void PythonQt::stdErrRedirectCB(const QString& str)
959 959 {
960 960 emit PythonQt::self()->pythonStdErr(str);
961 961 }
962 962
963 963 void PythonQt::setQObjectWrappedCallback(PythonQtQObjectWrappedCB* cb)
964 964 {
965 965 _p->_wrappedCB = cb;
966 966 }
967 967
968 968 void PythonQt::setQObjectNoLongerWrappedCallback(PythonQtQObjectNoLongerWrappedCB* cb)
969 969 {
970 970 _p->_noLongerWrappedCB = cb;
971 971 }
972 972
973 973
974 974
975 975 static PyMethodDef PythonQtMethods[] = {
976 976 {NULL, NULL, 0, NULL}
977 977 };
978 978
979 979 void PythonQt::initPythonQtModule(bool redirectStdOut)
980 980 {
981 981 _p->_pythonQtModule.setNewRef(Py_InitModule("PythonQt", PythonQtMethods));
982 982
983 983 if (redirectStdOut) {
984 984 PythonQtObjectPtr sys;
985 985 PythonQtObjectPtr out;
986 986 PythonQtObjectPtr err;
987 987 sys.setNewRef(PyImport_ImportModule("sys"));
988 988 // create a redirection object for stdout and stderr
989 989 out = PythonQtStdOutRedirectType.tp_new(&PythonQtStdOutRedirectType,NULL, NULL);
990 990 ((PythonQtStdOutRedirect*)out.object())->_cb = stdOutRedirectCB;
991 991 err = PythonQtStdOutRedirectType.tp_new(&PythonQtStdOutRedirectType,NULL, NULL);
992 992 ((PythonQtStdOutRedirect*)err.object())->_cb = stdErrRedirectCB;
993 993 // replace the built in file objects with our own objects
994 994 PyModule_AddObject(sys, "stdout", out);
995 995 PyModule_AddObject(sys, "stderr", err);
996 996 }
997 997 }
998 998
999 999 void PythonQt::registerCPPClass(const char* typeName, const char* parentTypeName, const char* package, PythonQtQObjectCreatorFunctionCB* wrapperCreator)
1000 1000 {
1001 1001 _p->registerCPPClass(typeName, parentTypeName, package, wrapperCreator);
1002 1002 }
1003 1003
1004 1004
1005 1005 void PythonQtPrivate::registerCPPClass(const char* typeName, const char* parentTypeName, const char* package, PythonQtQObjectCreatorFunctionCB* wrapperCreator)
1006 1006 {
1007 1007 PythonQtClassInfo* info = _knownQtWrapperClasses.value(typeName);
1008 1008 if (!info) {
1009 1009 info = new PythonQtClassInfo(NULL, typeName);
1010 1010 _knownQtWrapperClasses.insert(typeName, info);
1011 1011 PythonQtObjectPtr pack = packageByName(package);
1012 PyObject* pyobj = (PyObject*)createNewPythonQtMetaObjectWrapper(info);
1012 PyObject* pyobj = (PyObject*)createNewPythonQtClassWrapper(info);
1013 1013 PyModule_AddObject(pack, typeName, pyobj);
1014 1014 if (package && strncmp(package,"Qt",2)==0) {
1015 1015 // put all qt objects into Qt as well
1016 1016 PythonQtObjectPtr pack = packageByName("Qt");
1017 1017 PyModule_AddObject(pack, typeName, pyobj);
1018 1018 }
1019 1019 }
1020 1020 if (parentTypeName) {
1021 1021 info->setWrappedParentClassName(parentTypeName);
1022 1022 }
1023 1023 if (wrapperCreator) {
1024 1024 info->setDecoratorProvider(wrapperCreator);
1025 1025 }
1026 1026 }
1027 1027
1028 1028 PythonQtObjectPtr PythonQtPrivate::packageByName(const char* name)
1029 1029 {
1030 1030 if (name==NULL || name[0]==0) {
1031 1031 return _pythonQtModule;
1032 1032 }
1033 1033 PythonQtObjectPtr v = _packages.value(name);
1034 1034 if (!v) {
1035 1035 v.setNewRef(PyImport_AddModule((QByteArray("PythonQt.") + name).constData()));
1036 1036 _packages.insert(name, v);
1037 1037 PyModule_AddObject(_pythonQtModule, name, v);
1038 1038 }
1039 1039 return v;
1040 1040 }
1041 1041
1042 1042
1043 1043 PyObject* PythonQt::helpCalled(PythonQtClassInfo* info)
1044 1044 {
1045 1045 if (_p->_initFlags & ExternalHelp) {
1046 1046 emit pythonHelpRequest(QByteArray(info->className()));
1047 1047 return Py_BuildValue("");
1048 1048 } else {
1049 1049 return PyString_FromString(info->help().toLatin1().data());
1050 1050 }
1051 1051 }
1052 1052
1053 1053 void PythonQtPrivate::removeWrapperPointer(void* obj)
1054 1054 {
1055 1055 _wrappedObjects.remove(obj);
1056 1056 }
1057 1057
1058 PythonQtWrapper* PythonQtPrivate::findWrapperAndRemoveUnused(void* obj)
1058 PythonQtInstanceWrapper* PythonQtPrivate::findWrapperAndRemoveUnused(void* obj)
1059 1059 {
1060 PythonQtWrapper* wrap = _wrappedObjects.value(obj);
1060 PythonQtInstanceWrapper* wrap = _wrappedObjects.value(obj);
1061 1061 if (wrap && !wrap->_wrappedPtr && wrap->_obj == NULL) {
1062 1062 // this is a wrapper whose QObject was already removed due to destruction
1063 1063 // so the obj pointer has to be a new QObject with the same address...
1064 1064 // we remove the old one and set the copy to NULL
1065 1065 wrap->_objPointerCopy = NULL;
1066 1066 removeWrapperPointer(obj);
1067 1067 wrap = NULL;
1068 1068 }
1069 1069 return wrap;
1070 1070 }
1071 1071
1072 1072 PythonQtObjectPtr PythonQtPrivate::createModule(const QString& name, PyObject* pycode)
1073 1073 {
1074 1074 PythonQtObjectPtr result;
1075 1075 if (pycode) {
1076 1076 result.setNewRef(PyImport_ExecCodeModule((char*)name.toLatin1().data(), pycode));
1077 1077 } else {
1078 1078 PythonQt::self()->handleError();
1079 1079 }
1080 1080 return result;
1081 1081 }
@@ -1,504 +1,504
1 1 #ifndef _PYTHONQT_H
2 2 #define _PYTHONQT_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 PythonQt.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 "PythonQtSystem.h"
46 #include "PythonQtWrapper.h"
47 #include "PythonQtMetaObjectWrapper.h"
46 #include "PythonQtInstanceWrapper.h"
47 #include "PythonQtClassWrapper.h"
48 48 #include "PythonQtSlot.h"
49 49 #include "PythonQtObjectPtr.h"
50 50 #include <QObject>
51 51 #include <QVariant>
52 52 #include <QList>
53 53 #include <QHash>
54 54 #include <QByteArray>
55 55 #include <QStringList>
56 56 #include <QtDebug>
57 57 #include <iostream>
58 58
59 59
60 60 class PythonQtClassInfo;
61 61 class PythonQtPrivate;
62 62 class PythonQtMethodInfo;
63 63 class PythonQtSignalReceiver;
64 64 class PythonQtImportFileInterface;
65 65 class PythonQtCppWrapperFactory;
66 66 class PythonQtConstructorHandler;
67 67 class PythonQtQFileImporter;
68 68
69 69 typedef void PythonQtQObjectWrappedCB(QObject* object);
70 70 typedef void PythonQtQObjectNoLongerWrappedCB(QObject* object);
71 71
72 72 //! callback to create a QObject lazyly
73 73 typedef QObject* PythonQtQObjectCreatorFunctionCB();
74 74
75 75 //! helper template to create a derived QObject class
76 76 template<class T> QObject* PythonQtCreateObject() { return new T(); };
77 77
78 78 //! the main interface to the Python Qt binding, realized as a singleton
79 79 class PYTHONQT_EXPORT PythonQt : public QObject {
80 80
81 81 Q_OBJECT
82 82
83 83 public:
84 84 enum InitFlags {
85 85 RedirectStdOut = 1, //!<< sets if the std out/err is redirected to pythonStdOut() and pythonStdErr() signals
86 86 IgnoreSiteModule = 2, //!<< sets if Python should ignore the site module
87 87 ExternalHelp = 4 //!<< sets if help() calls on PythonQt modules are forwarded to the pythonHelpRequest() signal
88 88 };
89 89
90 90 //! initialize the python qt binding (flags are a or combination of InitFlags)
91 91 static void init(int flags = IgnoreSiteModule | RedirectStdOut);
92 92
93 93 //! cleanup
94 94 static void cleanup();
95 95
96 96 //! get the singleton instance
97 97 static PythonQt* self() { return _self; }
98 98
99 99 //-----------------------------------------------------------------------------
100 100 // Public API:
101 101
102 102 //! defines the object types for introspection
103 103 enum ObjectType {
104 104 Class,
105 105 Function,
106 106 Variable,
107 107 Module,
108 108 Anything,
109 109 CallOverloads
110 110 };
111 111
112 112 //! overwrite the python sys path (call this directly after PythonQt::init() if you want to change the std python sys path)
113 113 void overwriteSysPath(const QStringList& paths);
114 114
115 115 //! prepend a path to sys.path to allow importing from it
116 116 void addSysPath(const QString& path);
117 117
118 118 //! sets the __path__ list of a module to the given list (important for local imports)
119 119 void setModuleImportPath(PyObject* module, const QStringList& paths);
120 120
121 121 //! get the __main__ module of python
122 122 PythonQtObjectPtr getMainModule();
123 123
124 124 //! registers a QObject derived class to PythonQt (this is implicitly called by addObject as well)
125 125 /* Since Qt4 does not offer a way to detect if a given classname is derived from QObject and thus has a QMetaObject,
126 126 you MUST register all your QObject derived classes here when you want them to be detected in signal and slot calls */
127 127 void registerClass(const QMetaObject* metaobject, const char* package = NULL, PythonQtQObjectCreatorFunctionCB* wrapperCreator = NULL);
128 128
129 129 //! add a wrapper object for the given QMetaType typeName, also does an addClassDecorators() to add constructors for variants
130 130 //! (ownership of wrapper is passed to PythonQt)
131 131 /*! Make sure that you have done a qRegisterMetaType first, if typeName is a user type!
132 132
133 133 This will add a wrapper object that is used to make calls to the given classname \c typeName.
134 134 All slots that take a pointer to typeName as the first argument will be callable from Python on
135 135 a variant object that contains such a type.
136 136 */
137 137 void registerCPPClass(const char* typeName, const char* parentTypeName = NULL, const char* package = NULL, PythonQtQObjectCreatorFunctionCB* wrapperCreator = NULL);
138 138
139 139 //! as an alternative to registerClass, you can tell PythonQt the names of QObject derived classes
140 140 //! and it will register the classes when it first sees a pointer to such a derived class
141 141 void registerQObjectClassNames(const QStringList& names);
142 142
143 143 //! parses the given file and returns the python code object, this can then be used to call evalCode()
144 144 PythonQtObjectPtr parseFile(const QString& filename);
145 145
146 146 //! evaluates the given code and returns the result value (use Py_Compile etc. to create pycode from string)
147 147 //! If pycode is NULL, a python error is printed.
148 148 QVariant evalCode(PyObject* module, PyObject* pycode);
149 149
150 150 //! evaluates the given script code and returns the result value
151 151 QVariant evalScript(PyObject* module, const QString& script, int start = Py_file_input);
152 152
153 153 //! evaluates the given script code from file
154 154 void evalFile(PyObject* module, const QString& filename);
155 155
156 156 //! creates the new module \c name and evaluates the given file in the context of that module
157 157 //! If the \c script is empty, the module contains no initial code. You can use evalScript/evalCode to add code
158 158 //! to a module later on.
159 159 //! The user needs to make sure that the \c name is unique in the python module dictionary.
160 160 PythonQtObjectPtr createModuleFromFile(const QString& name, const QString& filename);
161 161
162 162 //! creates the new module \c name and evaluates the given script in the context of that module.
163 163 //! If the \c script is empty, the module contains no initial code. You can use evalScript/evalCode to add code
164 164 //! to a module later on.
165 165 //! The user needs to make sure that the \c name is unique in the python module dictionary.
166 166 PythonQtObjectPtr createModuleFromScript(const QString& name, const QString& script = QString());
167 167
168 168 //! create a uniquely named module, you can use evalFile or evalScript to populate the module with
169 169 //! script code
170 170 PythonQtObjectPtr createUniqueModule();
171 171
172 172 //@{ Signal handlers
173 173
174 174 //! add a signal handler to the given \c signal of \c obj and connect it to a callable \c objectname in module
175 175 bool addSignalHandler(QObject* obj, const char* signal, PyObject* module, const QString& objectname);
176 176
177 177 //! remove a signal handler from the given \c signal of \c obj
178 178 bool removeSignalHandler(QObject* obj, const char* signal, PyObject* module, const QString& objectname);
179 179
180 180 //! add a signal handler to the given \c signal of \c obj and connect it to a callable \c receiver
181 181 bool addSignalHandler(QObject* obj, const char* signal, PyObject* receiver);
182 182
183 183 //! remove a signal handler from the given \c signal of \c obj
184 184 bool removeSignalHandler(QObject* obj, const char* signal, PyObject* receiver);
185 185
186 186 //@}
187 187
188 188 //@{ Variable access
189 189
190 190 //! add the given \c object to the \c module as a variable with \c name (it can be removed via clearVariable)
191 191 void addObject(PyObject* module, const QString& name, QObject* object);
192 192
193 193 //! add the given variable to the module
194 194 void addVariable(PyObject* module, const QString& name, const QVariant& v);
195 195
196 196 //! remove the given variable
197 197 void removeVariable(PyObject* module, const QString& name);
198 198
199 199 //! get the variable with the \c name of the \c module, returns an invalid QVariant on error
200 200 QVariant getVariable(PyObject* module, const QString& name);
201 201
202 202 //! read vars etc. in scope of a module, optional looking inside of an object \c objectname
203 203 QStringList introspection(PyObject* module, const QString& objectname, ObjectType type);
204 204
205 205 //! returns the found callable object or NULL
206 206 //! @return new reference
207 207 PythonQtObjectPtr lookupCallable(PyObject* module, const QString& name);
208 208
209 209 //@}
210 210
211 211 //@{ Calling of python callables
212 212
213 213 //! call the given python method, returns the result converted to a QVariant
214 214 QVariant call(PyObject* module, const QString& callable, const QVariantList& args = QVariantList());
215 215
216 216 //@}
217 217
218 218 //@{ Decorations, constructors, wrappers...
219 219
220 220
221 221 //! add an object whose slots will be used as decorator slots for
222 222 //! other QObjects or CPP classes. The slots need to follow the
223 223 //! convention that the first argument is a pointer to the wrapped object.
224 224 //! (ownership is passed to PythonQt)
225 225 /*!
226 226 Example:
227 227
228 228 A slot with the signature
229 229
230 230 \code
231 231 bool doSomething(QWidget* w, int a)
232 232 \endcode
233 233
234 234 will extend QWidget instances (and derived classes) with a "bool doSomething(int a)" slot
235 235 that will be called with the concrete instance as first argument.
236 236 So in Python you can now e.g. call
237 237
238 238 \code
239 239 someWidget.doSomething(12)
240 240 \endcode
241 241
242 242 without QWidget really having this method. This allows to easily make normal methods
243 243 of Qt classes callable by forwarding them with such decorator slots
244 244 or to make CPP classes (which are not derived from QObject) callable from Python.
245 245 */
246 246 void addInstanceDecorators(QObject* o);
247 247
248 248 //! add an object whose slots will be used as decorator slots for
249 249 //! class objects (ownership is passed to PythonQt)
250 250 /*!
251 251 The slots need to follow the following convention:
252 252 - SomeClass* new_SomeClass(...)
253 253 - QVariant new_SomeClass(...)
254 254 - void delete_SomeClass(SomeClass*)
255 255 - ... static_SomeClass_someName(...)
256 256
257 257 This will add:
258 258 - a constructor
259 259 - a constructor which generates a QVariant
260 260 - a destructor (only useful for CPP objects)
261 261 - a static decorator slot which will be available on the MetaObject (visible in PythonQt module)
262 262
263 263 */
264 264 void addClassDecorators(QObject* o);
265 265
266 266 //! this will add the object both as class and instance decorator (ownership is passed to PythonQt)
267 267 void addDecorators(QObject* o);
268 268
269 269 //! add the given factory to PythonQt (ownership stays with caller)
270 270 void addWrapperFactory(PythonQtCppWrapperFactory* factory);
271 271
272 272 //! add the given constructor handler to PythonQt (ownership stays with caller)
273 273 void addConstructorHandler(PythonQtConstructorHandler* handler);
274 274
275 275 //! get list of constructor handlers
276 276 const QList<PythonQtConstructorHandler*>& constructorHandlers();
277 277
278 278 //@}
279 279
280 280 //@{ Custom importer (to replace internal import implementation of python)
281 281
282 282 //! replace the internal import implementation and use the supplied interface to load files (both py and pyc files)
283 283 //! (this method should be called directly after initialization of init() and before calling overwriteSysPath().
284 284 //! On the first call to this method, it will install a generic PythonQt importer in Pythons "path_hooks".
285 285 //! This is not reversible, so even setting setImporter(NULL) afterwards will
286 286 //! keep the custom PythonQt importer with a QFile default import interface.
287 287 //! Subsequent python import calls will make use of the passed importInterface
288 288 //! which forwards all import calls to the given \c importInterface.
289 289 //! Passing NULL will install a default QFile importer.
290 290 //! (\c importInterface ownership stays with caller)
291 291 void setImporter(PythonQtImportFileInterface* importInterface);
292 292
293 293 //! this installs the default QFile importer (which effectively does a setImporter(NULL))
294 294 //! (without calling setImporter or installDefaultImporter at least once, the default python import
295 295 //! mechanism is in place)
296 296 //! the default importer allows to import files from anywhere QFile can read from,
297 297 //! including the Qt resource system using ":". Keep in mind that you need to extend
298 298 //! "sys.path" with ":" to be able to import from the Qt resources.
299 299 void installDefaultImporter() { setImporter(NULL); }
300 300
301 301 //! set paths that the importer should ignore
302 302 void setImporterIgnorePaths(const QStringList& paths);
303 303
304 304 //! get paths that the importer should ignore
305 305 const QStringList& getImporterIgnorePaths();
306 306
307 307 //@}
308 308
309 309 //! get access to internal data (should not be used on the public API, but is used by some C functions)
310 310 static PythonQtPrivate* priv() { return _self->_p; }
311 311
312 312 //! get access to the file importer (if set)
313 313 static PythonQtImportFileInterface* importInterface();
314 314
315 315 //! handle a python error, call this when a python function fails. If no error occurred, it returns false.
316 316 //! The error is currently just output to the python stderr, future version might implement better trace printing
317 317 bool handleError();
318 318
319 319 //! set a callback that is called when a QObject with parent == NULL is wrapped by pythonqt
320 320 void setQObjectWrappedCallback(PythonQtQObjectWrappedCB* cb);
321 321 //! set a callback that is called when a QObject with parent == NULL is no longer wrapped by pythonqt
322 322 void setQObjectNoLongerWrappedCallback(PythonQtQObjectNoLongerWrappedCB* cb);
323 323
324 324 //! call the callback if it is set
325 325 static void qObjectNoLongerWrappedCB(QObject* o);
326 326
327 327 signals:
328 328 //! emitted when python outputs something to stdout (and redirection is turned on)
329 329 void pythonStdOut(const QString& str);
330 330 //! emitted when python outputs something to stderr (and redirection is turned on)
331 331 void pythonStdErr(const QString& str);
332 332
333 333 //! emitted when help() is called on a PythonQt object and \c ExternalHelp is enabled
334 334 void pythonHelpRequest(const QByteArray& cppClassName);
335 335
336 336
337 337 public:
338 338 //! called by internal help methods
339 339 PyObject* helpCalled(PythonQtClassInfo* info);
340 340
341 341 //! returns the found object or NULL
342 342 //! @return new reference
343 343 PythonQtObjectPtr lookupObject(PyObject* module, const QString& name);
344 344
345 345 private:
346 346 void initPythonQtModule(bool redirectStdOut);
347 347
348 348 //! callback for stdout redirection, emits pythonStdOut signal
349 349 static void stdOutRedirectCB(const QString& str);
350 350 //! callback for stderr redirection, emits pythonStdErr signal
351 351 static void stdErrRedirectCB(const QString& str);
352 352
353 353 //! get (and create if not available) the signal receiver of that QObject, signal receiver is made child of the passed \c obj
354 354 PythonQtSignalReceiver* getSignalReceiver(QObject* obj);
355 355
356 356 PythonQt(int flags);
357 357 ~PythonQt();
358 358
359 359 static PythonQt* _self;
360 360 static int _uniqueModuleCount;
361 361
362 362 PythonQtPrivate* _p;
363 363
364 364 };
365 365
366 366 //! internal PythonQt details
367 367 class PythonQtPrivate : public QObject {
368 368
369 369 Q_OBJECT
370 370
371 371 public:
372 372 PythonQtPrivate();
373 373 ~PythonQtPrivate();
374 374
375 375 enum DecoratorTypes {
376 376 StaticDecorator = 1,
377 377 ConstructorDecorator = 2,
378 378 DestructorDecorator = 4,
379 379 InstanceDecorator = 8,
380 380 AllDecorators = 0xffff
381 381 };
382 382
383 383 //! returns if the id is the id for PythonQtObjectPtr
384 384 bool isPythonQtObjectPtrMetaId(int id) { return _PythonQtObjectPtr_metaId == id; }
385 385
386 386 //! remove the wrapper ptr again
387 387 void removeWrapperPointer(void* obj);
388 388
389 389 //! called when a signal emitting QObject is destroyed to remove the signal handler from the hash map
390 390 void removeSignalEmitter(QObject* obj);
391 391
392 392 //! wrap the given QObject into a Python object (or return existing wrapper!)
393 393 PyObject* wrapQObject(QObject* obj);
394 394
395 395 //! wrap the given ptr into a Python object (or return existing wrapper!) if there is a known QObject of that name or a known wrapper in the factory
396 396 PyObject* wrapPtr(void* ptr, const QByteArray& name);
397 397
398 398 //! registers a QObject derived class to PythonQt (this is implicitly called by addObject as well)
399 399 /* Since Qt4 does not offer a way to detect if a given classname is derived from QObject and thus has a QMetaObject,
400 400 you MUST register all your QObject derived classes here when you want them to be detected in signal and slot calls */
401 401 void registerClass(const QMetaObject* metaobject, const char* package = NULL, PythonQtQObjectCreatorFunctionCB* wrapperCreator = NULL);
402 402
403 403 //! add a wrapper object for the given QMetaType typeName, also does an addClassDecorators() to add constructors for variants
404 404 //! (ownership of wrapper is passed to PythonQt)
405 405 /*! Make sure that you have done a qRegisterMetaType first, if typeName is a user type!
406 406
407 407 This will add a wrapper object that is used to make calls to the given classname \c typeName.
408 408 All slots that take a pointer to typeName as the first argument will be callable from Python on
409 409 a variant object that contains such a type.
410 410 */
411 411 void registerCPPClass(const char* typeName, const char* parentTypeName = NULL, const char* package = NULL, PythonQtQObjectCreatorFunctionCB* wrapperCreator = NULL);
412 412
413 413 //! as an alternative to registerClass, you can tell PythonQt the names of QObject derived classes
414 414 //! and it will register the classes when it first sees a pointer to such a derived class
415 415 void registerQObjectClassNames(const QStringList& names);
416 416
417 417 //! add a decorator object
418 418 void addDecorators(QObject* o, int decoTypes);
419 419
420 420 //! get list of all slots that are available as decorator slots
421 421 QList<PythonQtSlotInfo*> getDecoratorSlots(const QByteArray& className);
422 422
423 423 //! check if the enum is either part of the \c meta class or contains a scope and is
424 424 //! an enum of another known metaobject (and as last resort, of the Qt namespace)
425 425 bool isEnumType(const QMetaObject* meta, const QByteArray& name);
426 426
427 //! helper method that creates a PythonQtMetaObjectWrapper object
428 PythonQtMetaObjectWrapper* createNewPythonQtMetaObjectWrapper(PythonQtClassInfo* info);
427 //! helper method that creates a PythonQtClassWrapper object
428 PythonQtClassWrapper* createNewPythonQtClassWrapper(PythonQtClassInfo* info);
429 429
430 //! helper method that creates a PythonQtWrapper object and registers it in the object map
431 PythonQtWrapper* createNewPythonQtWrapper(QObject* obj, PythonQtClassInfo* info, void* wrappedPtr = NULL);
430 //! helper method that creates a PythonQtInstanceWrapper object and registers it in the object map
431 PythonQtInstanceWrapper* createNewPythonQtInstanceWrapper(QObject* obj, PythonQtClassInfo* info, void* wrappedPtr = NULL);
432 432
433 433 //! get the class info for a meta object (if available)
434 434 PythonQtClassInfo* getClassInfo(const QMetaObject* meta) { return _knownQtClasses.value(meta->className()); }
435 435
436 436 //! get the class info for a meta object (if available)
437 437 PythonQtClassInfo* getClassInfo(const QByteArray& className) { return _knownQtClasses.value(className); }
438 438
439 439 //! get the constructor slot for the given classname
440 440 PythonQtSlotInfo* getConstructorSlot(const QByteArray& className) { return _constructorSlots.value(className); }
441 441
442 442 //! get the destructor slot for the given classname
443 443 PythonQtSlotInfo* getDestructorSlot(const QByteArray& className) { return _destructorSlots.value(className); }
444 444
445 445 //! creates the new module from the given pycode
446 446 PythonQtObjectPtr createModule(const QString& name, PyObject* pycode);
447 447
448 448 private:
449 449 //! get/create new package module
450 450 PythonQtObjectPtr packageByName(const char* name);
451 451
452 452 //! get the wrapper for a given pointer (and remove a wrapper of an already destroyed qobject)
453 PythonQtWrapper* findWrapperAndRemoveUnused(void* obj);
453 PythonQtInstanceWrapper* findWrapperAndRemoveUnused(void* obj);
454 454
455 455 //! stores pointer to PyObject mapping of wrapped QObjects AND C++ objects
456 QHash<void* , PythonQtWrapper *> _wrappedObjects;
456 QHash<void* , PythonQtInstanceWrapper *> _wrappedObjects;
457 457
458 458 //! stores the meta info of known Qt classes
459 459 QHash<QByteArray, PythonQtClassInfo *> _knownQtClasses;
460 460
461 461 //! stores the meta info of known Qt classes
462 462 QHash<QByteArray, PythonQtClassInfo *> _knownQtWrapperClasses;
463 463
464 464 //! stores the meta info of known Qt C++ wrapper classes
465 465 QMultiHash<QByteArray, PythonQtSlotInfo *> _knownQtDecoratorSlots;
466 466
467 467 //! names of qobject derived classes that can be casted to qobject savely
468 468 QHash<QByteArray, bool> _knownQObjectClassNames;
469 469
470 470 //! stores signal receivers for QObjects
471 471 QHash<QObject* , PythonQtSignalReceiver *> _signalReceivers;
472 472
473 473 //! the PythonQt python module
474 474 PythonQtObjectPtr _pythonQtModule;
475 475
476 476 //! the importer interface (if set)
477 477 PythonQtImportFileInterface* _importInterface;
478 478
479 479 //! the default importer
480 480 PythonQtQFileImporter* _defaultImporter;
481 481
482 482 PythonQtQObjectNoLongerWrappedCB* _noLongerWrappedCB;
483 483 PythonQtQObjectWrappedCB* _wrappedCB;
484 484
485 485 QStringList _importIgnorePaths;
486 486
487 487 //! the cpp object wrapper factories
488 488 QList<PythonQtCppWrapperFactory*> _cppWrapperFactories;
489 489
490 490 //! the cpp object wrapper factories
491 491 QList<PythonQtConstructorHandler*> _constructorHandlers;
492 492
493 493 QHash<QByteArray , PythonQtSlotInfo *> _constructorSlots;
494 494 QHash<QByteArray , PythonQtSlotInfo *> _destructorSlots;
495 495
496 496 QHash<QByteArray, PythonQtObjectPtr> _packages;
497 497
498 498 int _initFlags;
499 499 int _PythonQtObjectPtr_metaId;
500 500
501 501 friend class PythonQt;
502 502 };
503 503
504 504 #endif
@@ -1,659 +1,657
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
47 47 QHash<QByteArray, int> PythonQtMethodInfo::_parameterTypeDict;
48 48
49 49 PythonQtClassInfo::PythonQtClassInfo(const QMetaObject* meta, const QByteArray& wrappedClassName) {
50 50 _meta = meta;
51 51 _wrappedClassName = wrappedClassName;
52 52 _constructors = NULL;
53 53 _parentClassInfo = NULL;
54 54 _parentClassInfoResolved = false;
55 55 _decoratorProvider = NULL;
56 56 _decoratorProviderCB = NULL;
57 57 if (wrappedClassName.isEmpty()) {
58 58 _metaTypeId = -1;
59 59 } else {
60 60 _metaTypeId = QMetaType::type(wrappedClassName);
61 61 }
62 62 }
63 63
64 64 PythonQtClassInfo::~PythonQtClassInfo()
65 65 {
66 66 clearCachedMembers();
67 67 }
68 68
69 69 void PythonQtClassInfo::clearCachedMembers()
70 70 {
71 71 QHashIterator<QByteArray, PythonQtMemberInfo> i(_cachedMembers);
72 72 while (i.hasNext()) {
73 73 PythonQtMemberInfo member = i.next().value();
74 74 if (member._type== PythonQtMemberInfo::Slot) {
75 75 PythonQtSlotInfo* info = member._slot;
76 76 while (info) {
77 77 PythonQtSlotInfo* next = info->nextInfo();
78 78 delete info;
79 79 info = next;
80 80 }
81 81 }
82 82 }
83 83 }
84 84
85 85 void PythonQtClassInfo::resolveParentClassInfo()
86 86 {
87 87 if (!_parentClassInfoResolved) {
88 88 _parentClassInfoResolved = true;
89 89 if (isCPPWrapper()) {
90 90 if (!_wrappedClassName.isEmpty()) {
91 91 _parentClassInfo = PythonQt::priv()->getClassInfo(_wrappedParentClassName);
92 92 }
93 93 } else {
94 94 if (_meta->superClass()) {
95 95 _parentClassInfo = PythonQt::priv()->getClassInfo(_meta->superClass());
96 96 }
97 97 }
98 98 }
99 99 }
100 100
101 101 int PythonQtClassInfo::findCharOffset(const char* sigStart, char someChar)
102 102 {
103 103 const char* sigEnd = sigStart;
104 104 char c;
105 105 do {
106 106 c = *sigEnd++;
107 107 } while (c!=someChar && c!=0);
108 108 return sigEnd-sigStart-1;
109 109 }
110 110
111 111 bool PythonQtClassInfo::lookForPropertyAndCache(const char* memberName)
112 112 {
113 113 bool found = false;
114 114 bool nameMapped = false;
115 115 const char* attributeName = memberName;
116 116 // look for properties
117 117 int i = _meta->indexOfProperty(attributeName);
118 118 if (i==-1) {
119 119 // try to map name to objectName
120 120 if (qstrcmp(attributeName, "name")==0) {
121 121 attributeName = "objectName";
122 122 nameMapped = true;
123 123 i = _meta->indexOfProperty(attributeName);
124 124 }
125 125 }
126 126 if (i!=-1) {
127 127 PythonQtMemberInfo newInfo(_meta->property(i));
128 128 _cachedMembers.insert(attributeName, newInfo);
129 129 if (nameMapped) {
130 130 _cachedMembers.insert(memberName, newInfo);
131 131 }
132 132 #ifdef PYTHONQT_DEBUG
133 133 std::cout << "caching property " << memberName << " on " << _meta->className() << std::endl;
134 134 #endif
135 135 found = true;
136 136 }
137 137 return found;
138 138 }
139 139
140 140 PythonQtSlotInfo* PythonQtClassInfo::findDecoratorSlotsFromDecoratorProvider(const char* memberName, PythonQtSlotInfo* tail, bool &found, QHash<QByteArray, PythonQtMemberInfo>& memberCache) {
141 141 QObject* decoratorProvider = decorator();
142 142 if (decoratorProvider) {
143 143 const QMetaObject* meta = decoratorProvider->metaObject();
144 144 int memberNameLen = strlen(memberName);
145 145 int numMethods = meta->methodCount();
146 146 int startFrom = QObject::staticMetaObject.methodCount();
147 147 for (int i = startFrom; i < numMethods; i++) {
148 148 QMetaMethod m = meta->method(i);
149 149 if ((m.methodType() == QMetaMethod::Method ||
150 150 m.methodType() == QMetaMethod::Slot) && m.access() == QMetaMethod::Public) {
151 151
152 152 const char* sigStart = m.signature();
153 153 bool isClassDeco = false;
154 154 if (qstrncmp(sigStart, "static_", 7)==0) {
155 155 // skip the static_classname_ part of the string
156 156 sigStart += 7 + 1 + strlen(className());
157 157 isClassDeco = true;
158 158 } else if (qstrncmp(sigStart, "new_", 4)==0) {
159 159 isClassDeco = true;
160 160 } else if (qstrncmp(sigStart, "delete_", 7)==0) {
161 161 isClassDeco = true;
162 162 }
163 163 // find the first '('
164 164 int offset = findCharOffset(sigStart, '(');
165 165
166 166 // XXX no checking is currently done if the slots have correct first argument or not...
167 167
168 168 // check if same length and same name
169 169 if (memberNameLen == offset && qstrncmp(memberName, sigStart, offset)==0) {
170 170 found = true;
171 171 PythonQtSlotInfo* info = new PythonQtSlotInfo(m, i, decoratorProvider, isClassDeco?PythonQtSlotInfo::ClassDecorator:PythonQtSlotInfo::InstanceDecorator);
172 172 if (tail) {
173 173 tail->setNextInfo(info);
174 174 } else {
175 175 PythonQtMemberInfo newInfo(info);
176 176 memberCache.insert(memberName, newInfo);
177 177 }
178 178 tail = info;
179 179 }
180 180 }
181 181 }
182 182 }
183 183 return tail;
184 184 }
185 185
186 186 bool PythonQtClassInfo::lookForMethodAndCache(const char* memberName)
187 187 {
188 188 bool found = false;
189 189 int memberNameLen = strlen(memberName);
190 190 PythonQtSlotInfo* tail = NULL;
191 191 if (_meta) {
192 192 int numMethods = _meta->methodCount();
193 193 for (int i = 0; i < numMethods; i++) {
194 194 QMetaMethod m = _meta->method(i);
195 195 if ((m.methodType() == QMetaMethod::Method ||
196 196 m.methodType() == QMetaMethod::Slot) && m.access() == QMetaMethod::Public) {
197 197
198 198 const char* sigStart = m.signature();
199 199 // find the first '('
200 200 int offset = findCharOffset(sigStart, '(');
201 201
202 202 // check if same length and same name
203 203 if (memberNameLen == offset && qstrncmp(memberName, sigStart, offset)==0) {
204 204 found = true;
205 205 PythonQtSlotInfo* info = new PythonQtSlotInfo(m, i);
206 206 if (tail) {
207 207 tail->setNextInfo(info);
208 208 } else {
209 209 PythonQtMemberInfo newInfo(info);
210 210 _cachedMembers.insert(memberName, newInfo);
211 211 }
212 212 tail = info;
213 213 }
214 214 }
215 215 }
216 216 }
217 217
218 218 // look for dynamic decorators in this class and in derived classes
219 219 PythonQtClassInfo* info = this;
220 220 while (info) {
221 221 tail = info->findDecoratorSlotsFromDecoratorProvider(memberName, tail, found, _cachedMembers);
222 222 if (!info->_parentClassInfoResolved) {
223 223 info->resolveParentClassInfo();
224 224 }
225 225 info = info->_parentClassInfo;
226 226 }
227 227
228 228 // look for decorators
229 229 if (!_wrappedClassName.isEmpty()) {
230 230 tail = findDecoratorSlots(_wrappedClassName.constData(), memberName, memberNameLen, tail, found);
231 231 }
232 232
233 233 const QMetaObject* meta = _meta;
234 234 while (meta) {
235 235 tail = findDecoratorSlots(meta->className(), memberName, memberNameLen, tail, found);
236 236 meta = meta->superClass();
237 237 }
238 238 return found;
239 239 }
240 240
241 241 bool PythonQtClassInfo::lookForEnumAndCache(const QMetaObject* meta, const char* memberName)
242 242 {
243 243 bool found = false;
244 244 // look for enum values
245 245 int enumCount = meta->enumeratorCount();
246 246 for (int i=0;i<enumCount; i++) {
247 247 QMetaEnum e = meta->enumerator(i);
248 248 for (int j=0; j < e.keyCount(); j++) {
249 249 if (qstrcmp(e.key(j), memberName)==0) {
250 250 PythonQtMemberInfo newInfo(e.value(j));
251 251 _cachedMembers.insert(memberName, newInfo);
252 252 #ifdef PYTHONQT_DEBUG
253 253 std::cout << "caching enum " << memberName << " on " << meta->className() << std::endl;
254 254 #endif
255 255 found = true;
256 256 }
257 257 }
258 258 }
259 259 return found;
260 260 }
261 261
262 262 PythonQtMemberInfo PythonQtClassInfo::member(const char* memberName)
263 263 {
264 264 PythonQtMemberInfo info = _cachedMembers.value(memberName);
265 265 if (info._type != PythonQtMemberInfo::Invalid) {
266 266 return info;
267 267 } else {
268 268 bool found = false;
269 269
270 270 found = lookForPropertyAndCache(memberName);
271 271 if (!found) {
272 272 found = lookForMethodAndCache(memberName);
273 273 }
274 274 if (!found) {
275 275 if (_meta) {
276 276 // check enums in our meta object directly
277 277 found = lookForEnumAndCache(_meta, memberName);
278 278 }
279 279 if (!found) {
280 280 // check enums in the class hierachy of CPP classes
281 281 // look for dynamic decorators in this class and in derived classes
282 282 PythonQtClassInfo* info = this;
283 283 while (info && !found) {
284 284 QObject* deco = info->decorator();
285 285 if (deco) {
286 286 // call on ourself for caching, but with different metaObject():
287 287 found = lookForEnumAndCache(deco->metaObject(), memberName);
288 288 }
289 289 if (!info->_parentClassInfoResolved) {
290 290 info->resolveParentClassInfo();
291 291 }
292 292 info = info->_parentClassInfo;
293 293 }
294 294 }
295 295 }
296 296 if (!found) {
297 297 // we store a NotFound member, so that we get a quick result for non existing members (e.g. operator_equal lookup)
298 298 info._type = PythonQtMemberInfo::NotFound;
299 299 _cachedMembers.insert(memberName, info);
300 300 }
301 301 }
302 302
303 303 return _cachedMembers.value(memberName);
304 304 }
305 305
306 306 PythonQtSlotInfo* PythonQtClassInfo::findDecoratorSlots(const char* classname, const char* memberName, int memberNameLen, PythonQtSlotInfo* tail, bool& found)
307 307 {
308 308 QListIterator<PythonQtSlotInfo*> it(PythonQt::priv()->getDecoratorSlots(classname));
309 309 while (it.hasNext()) {
310 310
311 311 PythonQtSlotInfo* infoOrig = it.next();
312 312
313 313 const char* sigStart = infoOrig->metaMethod()->signature();
314 314 if (qstrncmp("static_", sigStart, 7)==0) {
315 315 sigStart += 7;
316 316 sigStart += findCharOffset(sigStart, '_')+1;
317 317 }
318 318 int offset = findCharOffset(sigStart, '(');
319 319 if (memberNameLen == offset && qstrncmp(memberName, sigStart, offset)==0) {
320 320 //make a copy, otherwise we will have trouble on overloads!
321 321 PythonQtSlotInfo* info = new PythonQtSlotInfo(*infoOrig);
322 322 found = true;
323 323 if (tail) {
324 324 tail->setNextInfo(info);
325 325 } else {
326 326 PythonQtMemberInfo newInfo(info);
327 327 _cachedMembers.insert(memberName, newInfo);
328 328 }
329 329 tail = info;
330 330 }
331 331 }
332 332 return tail;
333 333 }
334 334
335 335 void PythonQtClassInfo::listDecoratorSlotsFromDecoratorProvider(QStringList& list, bool metaOnly) {
336 336 QObject* decoratorProvider = decorator();
337 337 if (decoratorProvider) {
338 338 const QMetaObject* meta = decoratorProvider->metaObject();
339 339 int numMethods = meta->methodCount();
340 340 int startFrom = QObject::staticMetaObject.methodCount();
341 341 for (int i = startFrom; i < numMethods; i++) {
342 342 QMetaMethod m = meta->method(i);
343 343 if ((m.methodType() == QMetaMethod::Method ||
344 344 m.methodType() == QMetaMethod::Slot) && m.access() == QMetaMethod::Public) {
345 345
346 346 const char* sigStart = m.signature();
347 347 bool isClassDeco = false;
348 348 if (qstrncmp(sigStart, "static_", 7)==0) {
349 349 // skip the static_classname_ part of the string
350 350 sigStart += 7 + 1 + strlen(className());
351 351 isClassDeco = true;
352 352 } else if (qstrncmp(sigStart, "new_", 4)==0) {
353 sigStart += 4 + 1 + strlen(className());
354 isClassDeco = true;
353 continue;
355 354 } else if (qstrncmp(sigStart, "delete_", 7)==0) {
356 sigStart += 7 + 1 + strlen(className());
357 isClassDeco = true;
355 continue;
358 356 }
359 357 // find the first '('
360 358 int offset = findCharOffset(sigStart, '(');
361 359
362 360 // XXX no checking is currently done if the slots have correct first argument or not...
363 361 if (!metaOnly || isClassDeco) {
364 362 list << QString::fromLatin1(sigStart, offset);
365 363 }
366 364 }
367 365 }
368 366 }
369 367 }
370 368
371 369 QStringList PythonQtClassInfo::memberList(bool metaOnly)
372 370 {
373 371 resolveParentClassInfo();
374 372 decorator();
375 373
376 374 QStringList l;
377 375 QString h;
378 if (_wrappedClassName.isEmpty() && _meta) {
376 if (_wrappedClassName.isEmpty() && _meta && !metaOnly) {
379 377 int i;
380 378 int numProperties = _meta->propertyCount();
381 379 for (i = 0; i < numProperties; i++) {
382 380 QMetaProperty p = _meta->property(i);
383 381 l << QString(p.name());
384 382 }
385 383 }
386 384
387 385 // normal slots of QObject (or wrapper QObject)
388 386 if (!metaOnly && _meta) {
389 387 int numMethods = _meta->methodCount();
390 388 bool skipQObj = !_wrappedClassName.isEmpty();
391 389 for (int i = skipQObj?QObject::staticMetaObject.methodCount():0; i < numMethods; i++) {
392 390 QMetaMethod m = _meta->method(i);
393 391 if ((m.methodType() == QMetaMethod::Method ||
394 392 m.methodType() == QMetaMethod::Slot) && m.access() == QMetaMethod::Public) {
395 393 QByteArray signa(m.signature());
396 394 if (signa.startsWith("new_")) continue;
397 395 if (signa.startsWith("delete_")) continue;
398 396 if (signa.startsWith("static_")) continue;
399 397 PythonQtSlotInfo slot(m, i);
400 398 l << slot.slotName();
401 399 }
402 400 }
403 401 }
404 402
405 403 {
406 404 // look for dynamic decorators in this class and in derived classes
407 405 PythonQtClassInfo* info = this;
408 406 while (info) {
409 407 info->listDecoratorSlotsFromDecoratorProvider(l, metaOnly);
410 408 if (!info->_parentClassInfoResolved) {
411 409 info->resolveParentClassInfo();
412 410 }
413 411 info = info->_parentClassInfo;
414 412 }
415 413 }
416 414
417 415 // look for decorators
418 416 QList<const char*> names;
419 417 if (!_wrappedClassName.isEmpty()) {
420 418 // CPP wrapper case:
421 419 names << _wrappedClassName.constData();
422 420 // for CPP classes which are wrapped, we do not want to look for decorators of the wrapping qobjects, since they
423 421 // would require a different pointer on the decorator slot call
424 422 } else {
425 423 // QObject case:
426 424 const QMetaObject* meta = _meta;
427 425 while (meta) {
428 426 if (meta==&QObject::staticMetaObject && !_wrappedClassName.isEmpty()) break;
429 427 names << meta->className();
430 428 meta = meta->superClass();
431 429 }
432 430 }
433 431
434 432 QListIterator<const char*> nameIt(names);
435 433 while (nameIt.hasNext()) {
436 434 QListIterator<PythonQtSlotInfo*> it(PythonQt::priv()->getDecoratorSlots(nameIt.next()));
437 435 while (it.hasNext()) {
438 436 PythonQtSlotInfo* slot = it.next();
439 437 if (metaOnly) {
440 438 if (slot->isClassDecorator()) {
441 439 QByteArray first = slot->slotName();
442 440 if (first.startsWith("static_")) {
443 441 int idx = first.indexOf('_');
444 442 idx = first.indexOf('_', idx+1);
445 443 first = first.mid(idx+1);
446 444 }
447 445 l << first;
448 446 }
449 447 } else {
450 448 l << slot->slotName();
451 449 }
452 450 }
453 451 }
454 452
455 453 // List enumerator keys...
456 454 QList<const QMetaObject*> enumMetaObjects;
457 455 if (_meta) {
458 456 enumMetaObjects << _meta;
459 457 }
460 458 // check enums in the class hierachy of CPP classes
461 459 PythonQtClassInfo* info = this;
462 460 while (info) {
463 461 QObject* deco = info->decorator();
464 462 if (deco) {
465 463 enumMetaObjects << deco->metaObject();
466 464 }
467 465 if (!info->_parentClassInfoResolved) {
468 466 info->resolveParentClassInfo();
469 467 }
470 468 info = info->_parentClassInfo;
471 469 }
472 470
473 471 foreach(const QMetaObject* meta, enumMetaObjects) {
474 472 for (int i = 0; i<meta->enumeratorCount(); i++) {
475 473 QMetaEnum e = meta->enumerator(i);
476 474 for (int j=0; j < e.keyCount(); j++) {
477 475 l << QString(e.key(j));
478 476 }
479 477 }
480 478 }
481 479 return l;
482 480 }
483 481
484 482 const char* PythonQtClassInfo::className()
485 483 {
486 484 if (!_wrappedClassName.isEmpty()) {
487 485 return _wrappedClassName.constData();
488 486 } else {
489 487 return _meta->className();
490 488 }
491 489 }
492 490
493 491 bool PythonQtClassInfo::inherits(const char* name)
494 492 {
495 493 resolveParentClassInfo();
496 494 if (isCPPWrapper()) {
497 495 PythonQtClassInfo* info = this;
498 496 while (info) {
499 497 if (_wrappedClassName == name) {
500 498 return true;
501 499 }
502 500 if (!info->_parentClassInfoResolved) {
503 501 info->resolveParentClassInfo();
504 502 }
505 503 info = info->_parentClassInfo;
506 504 }
507 505 } else {
508 506 const QMetaObject* m = _meta;
509 507 while (m) {
510 508 if (strcmp(name, m->className())==0) {
511 509 return true;
512 510 }
513 511 m = m->superClass();
514 512 }
515 513 }
516 514 return false;
517 515 }
518 516
519 517 QString PythonQtClassInfo::help()
520 518 {
521 519 resolveParentClassInfo();
522 520 decorator();
523 521 QString h;
524 522 h += QString("--- ") + QString(className()) + QString(" ---\n");
525 523
526 524 if (_wrappedClassName.isEmpty()) {
527 525 h += "Properties:\n";
528 526
529 527 int i;
530 528 int numProperties = _meta->propertyCount();
531 529 for (i = 0; i < numProperties; i++) {
532 530 QMetaProperty p = _meta->property(i);
533 531 h += QString(p.name()) + " (" + QString(p.typeName()) + " )\n";
534 532 }
535 533 }
536 534
537 535 if (constructors()) {
538 536 h += "Constructors:\n";
539 537 PythonQtSlotInfo* constr = constructors();
540 538 while (constr) {
541 539 h += constr->fullSignature(false) + "\n";
542 540 constr = constr->nextInfo();
543 541 }
544 542 }
545 543
546 544 h += "Slots:\n";
547 545 h += "QString help()\n";
548 546 h += "QString className()\n";
549 547
550 548 if (_meta) {
551 549 int numMethods = _meta->methodCount();
552 550 for (int i = 0; i < numMethods; i++) {
553 551 QMetaMethod m = _meta->method(i);
554 552 if ((m.methodType() == QMetaMethod::Method ||
555 553 m.methodType() == QMetaMethod::Slot) && m.access() == QMetaMethod::Public) {
556 554 QByteArray signa(m.signature());
557 555 if (signa.startsWith("new_")) continue;
558 556 if (signa.startsWith("delete_")) continue;
559 557 if (signa.startsWith("static_")) continue;
560 558 PythonQtSlotInfo slot(m, i);
561 559 h += slot.fullSignature(false)+ "\n";
562 560 }
563 561 }
564 562 }
565 563
566 564 // TODO xxx : decorators and enums from decorator() are missing...
567 565 // maybe we can reuse memberlist()?
568 566
569 567 // look for decorators
570 568 QList<const char*> names;
571 569 if (!_wrappedClassName.isEmpty()) {
572 570 names << _wrappedClassName.constData();
573 571 }
574 572 const QMetaObject* meta = _meta;
575 573 while (meta) {
576 574 names << meta->className();
577 575 meta = meta->superClass();
578 576 }
579 577
580 578 QListIterator<const char*> nameIt(names);
581 579 while (nameIt.hasNext()) {
582 580 QListIterator<PythonQtSlotInfo*> it(PythonQt::priv()->getDecoratorSlots(nameIt.next()));
583 581 while (it.hasNext()) {
584 582 PythonQtSlotInfo* slot = it.next();
585 583 h += slot->fullSignature(slot->isInstanceDecorator()) + "\n";
586 584 }
587 585 }
588 586
589 587 if (_meta && _meta->enumeratorCount()) {
590 588 h += "Enums:\n";
591 589 for (int i = 0; i<_meta->enumeratorCount(); i++) {
592 590 QMetaEnum e = _meta->enumerator(i);
593 591 h += QString(e.name()) + " {";
594 592 for (int j=0; j < e.keyCount(); j++) {
595 593 if (j) { h+= ", "; }
596 594 h += e.key(j);
597 595 }
598 596 h += " }\n";
599 597 }
600 598 }
601 599
602 600 if (_wrappedClassName.isEmpty() && _meta) {
603 601 int numMethods = _meta->methodCount();
604 602 if (numMethods>0) {
605 603 h += "Signals:\n";
606 604 for (int i = 0; i < numMethods; i++) {
607 605 QMetaMethod m = _meta->method(i);
608 606 if (m.methodType() == QMetaMethod::Signal) {
609 607 h += QString(m.signature()) + "\n";
610 608 }
611 609 }
612 610 }
613 611 }
614 612 return h;
615 613 }
616 614
617 615 PythonQtSlotInfo* PythonQtClassInfo::constructors()
618 616 {
619 617 if (!_constructors) {
620 618 // force creation of lazy decorator, which will register the decorators
621 619 decorator();
622 620 _constructors = PythonQt::priv()->getConstructorSlot(!_wrappedClassName.isEmpty()?_wrappedClassName:QByteArray(_meta->className()));
623 621 }
624 622 return _constructors;
625 623 }
626 624
627 625 void PythonQtClassInfo::setMetaObject(const QMetaObject* meta)
628 626 {
629 627 _meta = meta;
630 628 clearCachedMembers();
631 629 }
632 630
633 631 QObject* PythonQtClassInfo::decorator()
634 632 {
635 633 if (!_decoratorProvider && _decoratorProviderCB) {
636 634 _decoratorProvider = (*_decoratorProviderCB)();
637 635 if (_decoratorProvider) {
638 636 _decoratorProvider->setParent(PythonQt::priv());
639 637 PythonQt::priv()->addDecorators(_decoratorProvider, PythonQtPrivate::ConstructorDecorator | PythonQtPrivate::DestructorDecorator);
640 638 }
641 639 }
642 640 return _decoratorProvider;
643 641 }
644 642
645 643 bool PythonQtClassInfo::hasOwnerMethodButNoOwner(void* object)
646 644 {
647 645 PythonQtMemberInfo info = member("hasOwner");
648 646 if (info._type == PythonQtMemberInfo::Slot) {
649 647 void* obj = object;
650 648 bool result = false;
651 649 void* args[2];
652 650 args[0] = &result;
653 651 args[1] = &obj;
654 652 info._slot->decorator()->qt_metacall(QMetaObject::InvokeMetaMethod, info._slot->slotIndex(), args);
655 653 return !result;
656 654 } else {
657 655 return false;
658 656 }
659 657 }
@@ -1,256 +1,256
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 // \file PythonQtMetaObjectWrapper.cpp
35 // \file PythonQtClassWrapper.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 #include "PythonQtMetaObjectWrapper.h"
42 #include "PythonQtClassWrapper.h"
43 43 #include <QObject>
44 44
45 45 #include "PythonQt.h"
46 46 #include "PythonQtSlot.h"
47 47 #include "PythonQtClassInfo.h"
48 48 #include "PythonQtConversion.h"
49 49
50 static void PythonQtMetaObjectWrapper_dealloc(PythonQtMetaObjectWrapper* self)
50 static void PythonQtClassWrapper_dealloc(PythonQtClassWrapper* self)
51 51 {
52 52 self->ob_type->tp_free((PyObject*)self);
53 53 }
54 54
55 static PyObject* PythonQtMetaObjectWrapper_new(PyTypeObject *type, PyObject * /*args*/, PyObject * /*kwds*/)
55 static PyObject* PythonQtClassWrapper_new(PyTypeObject *type, PyObject * /*args*/, PyObject * /*kwds*/)
56 56 {
57 PythonQtMetaObjectWrapper *self;
57 PythonQtClassWrapper *self;
58 58
59 self = (PythonQtMetaObjectWrapper *)type->tp_alloc(type, 0);
59 self = (PythonQtClassWrapper *)type->tp_alloc(type, 0);
60 60 if (self != NULL) {
61 61 self->_info = NULL;
62 62 }
63 63 return (PyObject *)self;
64 64 }
65 65
66 static int PythonQtMetaObjectWrapper_init(PythonQtMetaObjectWrapper * /*self*/, PyObject * /*args*/, PyObject * /*kwds*/)
66 static int PythonQtClassWrapper_init(PythonQtClassWrapper * /*self*/, PyObject * /*args*/, PyObject * /*kwds*/)
67 67 {
68 68 return 0;
69 69 }
70 70
71 PyObject *PythonQtMetaObjectWrapper_call(PyObject *func, PyObject *args, PyObject *kw) {
72 PythonQtMetaObjectWrapper* wrapper = (PythonQtMetaObjectWrapper*)func;
71 PyObject *PythonQtClassWrapper_call(PyObject *func, PyObject *args, PyObject *kw) {
72 PythonQtClassWrapper* wrapper = (PythonQtClassWrapper*)func;
73 73 PyObject* result = NULL;
74 74 QString error;
75 75 PyObject* err = NULL;
76 76 if (wrapper->_info->constructors()) {
77 77 result = PythonQtSlotFunction_CallImpl(NULL, wrapper->_info->constructors(), args, kw);
78 78 err = PyErr_Occurred();
79 79 }
80 80 if (!result) {
81 81 QObject* v = NULL;
82 82 QListIterator<PythonQtConstructorHandler*> it(PythonQt::self()->constructorHandlers());
83 83 while (!v && it.hasNext()) {
84 84 v = it.next()->create(wrapper->_info->metaObject(), args, kw, error);
85 85 }
86 86 if (v) {
87 87 result = PythonQt::priv()->wrapQObject(v);
88 88 }
89 89 }
90 90 if (result) {
91 91 // change ownershipflag to be owned by PythonQt
92 if (result->ob_type == &PythonQtWrapper_Type) {
93 ((PythonQtWrapper*)result)->_ownedByPythonQt = true;
92 if (result->ob_type == &PythonQtInstanceWrapper_Type) {
93 ((PythonQtInstanceWrapper*)result)->_ownedByPythonQt = true;
94 94 }
95 95 } else {
96 96 if (!wrapper->_info->constructors()) {
97 97 if (!err) {
98 98 if (error.isEmpty()) {
99 99 error = QString("No constructors available for ") + wrapper->_info->className();
100 100 }
101 101 PyErr_SetString(PyExc_ValueError, error.toLatin1().data());
102 102 }
103 103 }
104 104 }
105 105 return result;
106 106 }
107 107
108 static PyObject *PythonQtMetaObjectWrapper_classname(PythonQtMetaObjectWrapper* type)
108 static PyObject *PythonQtClassWrapper_classname(PythonQtClassWrapper* type)
109 109 {
110 110 return PyString_FromString((QString("Meta_") + type->_info->className()).toLatin1().data());
111 111 }
112 112
113 static PyObject *PythonQtMetaObjectWrapper_help(PythonQtMetaObjectWrapper* type)
113 static PyObject *PythonQtClassWrapper_help(PythonQtClassWrapper* type)
114 114 {
115 115 return PythonQt::self()->helpCalled(type->_info);
116 116 }
117 117
118 118
119 static PyMethodDef PythonQtMetaObjectWrapper_methods[] = {
120 {"className", (PyCFunction)PythonQtMetaObjectWrapper_classname, METH_NOARGS,
119 static PyMethodDef PythonQtClassWrapper_methods[] = {
120 {"className", (PyCFunction)PythonQtClassWrapper_classname, METH_NOARGS,
121 121 "Return the classname of the object"
122 122 },
123 {"help", (PyCFunction)PythonQtMetaObjectWrapper_help, METH_NOARGS,
123 {"help", (PyCFunction)PythonQtClassWrapper_help, METH_NOARGS,
124 124 "Shows the help of available methods for this class"
125 125 },
126 126 {NULL, NULL, 0 , NULL} /* Sentinel */
127 127 };
128 128
129 129
130 static PyObject *PythonQtMetaObjectWrapper_getattro(PyObject *obj,PyObject *name)
130 static PyObject *PythonQtClassWrapper_getattro(PyObject *obj,PyObject *name)
131 131 {
132 132 const char *attributeName;
133 PythonQtMetaObjectWrapper *wt = (PythonQtMetaObjectWrapper *)obj;
133 PythonQtClassWrapper *wrapper = (PythonQtClassWrapper *)obj;
134 134
135 135 if ((attributeName = PyString_AsString(name)) == NULL) {
136 136 return NULL;
137 137 }
138 138
139 PythonQtMemberInfo member = wt->_info->member(attributeName);
139 PythonQtMemberInfo member = wrapper->_info->member(attributeName);
140 140 if (member._type == PythonQtMemberInfo::EnumValue) {
141 141 return PyInt_FromLong(member._enumValue);
142 142 }
143 143 if (member._type == PythonQtMemberInfo::Slot && member._slot->isClassDecorator()) {
144 144 return PythonQtSlotFunction_New(member._slot, obj, NULL);
145 145 }
146 146
147 147 // look for the interal methods (className(), help())
148 PyObject* internalMethod = Py_FindMethod( PythonQtMetaObjectWrapper_methods, obj, (char*)attributeName);
148 PyObject* internalMethod = Py_FindMethod( PythonQtClassWrapper_methods, obj, (char*)attributeName);
149 149 if (internalMethod) {
150 150 return internalMethod;
151 151 }
152 152 PyErr_Clear();
153 153
154 154 if (qstrcmp(attributeName, "__dict__")==0) {
155 QStringList l = wt->_info->memberList(true);
155 QStringList l = wrapper->_info->memberList(true);
156 156 PyObject* dict = PyDict_New();
157 157 foreach (QString name, l) {
158 158 //PyObject* o = PyObject_GetAttrString(obj, name.toLatin1().data());
159 159 PyDict_SetItemString(dict, name.toLatin1().data(), Py_None);
160 160 //Py_DECREF(o);
161 161 }
162 162 return dict;
163 163 }
164 164
165 QString error = QString(wt->_info->className()) + " has no attribute named '" + QString(attributeName) + "'";
165 QString error = QString(wrapper->_info->className()) + " has no attribute named '" + QString(attributeName) + "'";
166 166 PyErr_SetString(PyExc_AttributeError, error.toLatin1().data());
167 167 return NULL;
168 168 }
169 169
170 static PyObject * PythonQtMetaObjectWrapper_repr(PyObject * obj)
170 static PyObject * PythonQtClassWrapper_repr(PyObject * obj)
171 171 {
172 PythonQtMetaObjectWrapper* wt = (PythonQtMetaObjectWrapper*)obj;
173 if (wt->_info->isCPPWrapper()) {
174 const QMetaObject* meta = wt->_info->metaObject();
172 PythonQtClassWrapper* wrapper = (PythonQtClassWrapper*)obj;
173 if (wrapper->_info->isCPPWrapper()) {
174 const QMetaObject* meta = wrapper->_info->metaObject();
175 175 if (!meta) {
176 QObject* decorator = wt->_info->decorator();
176 QObject* decorator = wrapper->_info->decorator();
177 177 if (decorator) {
178 178 meta = decorator->metaObject();
179 179 }
180 180 }
181 181 if (meta) {
182 return PyString_FromFormat("%s Class (C++ wrapped by %s)", wt->_info->className(), meta->className());
182 return PyString_FromFormat("%s Class (C++ wrapped by %s)", wrapper->_info->className(), meta->className());
183 183 } else {
184 return PyString_FromFormat("%s Class (C++ unwrapped)", wt->_info->className());
184 return PyString_FromFormat("%s Class (C++ unwrapped)", wrapper->_info->className());
185 185 }
186 186 } else {
187 return PyString_FromFormat("%s Class", wt->_info->className());
187 return PyString_FromFormat("%s Class", wrapper->_info->className());
188 188 }
189 189 }
190 190
191 static int PythonQtMetaObjectWrapper_compare(PyObject * obj1, PyObject * obj2)
191 static int PythonQtClassWrapper_compare(PyObject * obj1, PyObject * obj2)
192 192 {
193 if (obj1->ob_type == &PythonQtMetaObjectWrapper_Type &&
194 obj2->ob_type == &PythonQtMetaObjectWrapper_Type) {
193 if (obj1->ob_type == &PythonQtClassWrapper_Type &&
194 obj2->ob_type == &PythonQtClassWrapper_Type) {
195 195
196 PythonQtMetaObjectWrapper* w1 = (PythonQtMetaObjectWrapper*)obj1;
197 PythonQtMetaObjectWrapper* w2 = (PythonQtMetaObjectWrapper*)obj2;
196 PythonQtClassWrapper* w1 = (PythonQtClassWrapper*)obj1;
197 PythonQtClassWrapper* w2 = (PythonQtClassWrapper*)obj2;
198 198 if (w1->_info == w2->_info) {
199 199 return 0;
200 200 } else {
201 201 return -1;
202 202 }
203 203 } else {
204 204 return -1;
205 205 }
206 206 }
207 207
208 static long PythonQtMetaObjectWrapper_hash(PythonQtMetaObjectWrapper *obj)
208 static long PythonQtClassWrapper_hash(PythonQtClassWrapper *obj)
209 209 {
210 210 return reinterpret_cast<long>(obj->_info);
211 211 }
212 212
213 PyTypeObject PythonQtMetaObjectWrapper_Type = {
213 PyTypeObject PythonQtClassWrapper_Type = {
214 214 PyObject_HEAD_INIT(NULL)
215 215 0, /*ob_size*/
216 "PythonQt.PythonQtMetaObjectWrapper", /*tp_name*/
217 sizeof(PythonQtMetaObjectWrapper), /*tp_basicsize*/
216 "PythonQt.PythonQtClassWrapper", /*tp_name*/
217 sizeof(PythonQtClassWrapper), /*tp_basicsize*/
218 218 0, /*tp_itemsize*/
219 (destructor)PythonQtMetaObjectWrapper_dealloc, /*tp_dealloc*/
219 (destructor)PythonQtClassWrapper_dealloc, /*tp_dealloc*/
220 220 0, /*tp_print*/
221 221 0, /*tp_getattr*/
222 222 0, /*tp_setattr*/
223 PythonQtMetaObjectWrapper_compare, /*tp_compare*/
224 PythonQtMetaObjectWrapper_repr, /*tp_repr*/
223 PythonQtClassWrapper_compare, /*tp_compare*/
224 PythonQtClassWrapper_repr, /*tp_repr*/
225 225 0, /*tp_as_number*/
226 226 0, /*tp_as_sequence*/
227 227 0, /*tp_as_mapping*/
228 (hashfunc)PythonQtMetaObjectWrapper_hash, /*tp_hash */
229 PythonQtMetaObjectWrapper_call, /*tp_call*/
228 (hashfunc)PythonQtClassWrapper_hash, /*tp_hash */
229 PythonQtClassWrapper_call, /*tp_call*/
230 230 0, /*tp_str*/
231 PythonQtMetaObjectWrapper_getattro, /*tp_getattro*/
231 PythonQtClassWrapper_getattro, /*tp_getattro*/
232 232 0, /*tp_setattro*/
233 233 0, /*tp_as_buffer*/
234 234 Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE, /*tp_flags*/
235 "PythonQtMetaObjectWrapper object", /* tp_doc */
235 "PythonQtClassWrapper object", /* tp_doc */
236 236 0, /* tp_traverse */
237 237 0, /* tp_clear */
238 238 0, /* tp_richcompare */
239 239 0, /* tp_weaklistoffset */
240 240 0, /* tp_iter */
241 241 0, /* tp_iternext */
242 242 0, /* tp_methods */
243 243 0, /* tp_members */
244 244 0, /* tp_getset */
245 245 0, /* tp_base */
246 246 0, /* tp_dict */
247 247 0, /* tp_descr_get */
248 248 0, /* tp_descr_set */
249 249 0, /* tp_dictoffset */
250 (initproc)PythonQtMetaObjectWrapper_init, /* tp_init */
250 (initproc)PythonQtClassWrapper_init, /* tp_init */
251 251 0, /* tp_alloc */
252 PythonQtMetaObjectWrapper_new, /* tp_new */
252 PythonQtClassWrapper_new, /* tp_new */
253 253 };
254 254
255 255 //-------------------------------------------------------
256 256
@@ -1,79 +1,79
1 1 #ifndef _PYTHONQTMETAOBJECTWRAPPER_H
2 2 #define _PYTHONQTMETAOBJECTWRAPPER_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 // \file PythonQtMetaObjectWrapper.h
38 // \file PythonQtClassWrapper.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 <Python.h>
46 46
47 47 #include "structmember.h"
48 48 #include "methodobject.h"
49 49 #include "compile.h"
50 50 #include "eval.h"
51 51 #include <QString>
52 52
53 53 class PythonQtClassInfo;
54 54 class QObject;
55 55 struct QMetaObject;
56 56
57 extern PyTypeObject PythonQtMetaObjectWrapper_Type;
57 extern PyTypeObject PythonQtClassWrapper_Type;
58 58
59 59 //---------------------------------------------------------------
60 60 //! a Python wrapper object for Qt meta objects
61 61 typedef struct {
62 62 PyObject_HEAD
63 63
64 64 //! the class information (which contains the meta object as well)
65 65 PythonQtClassInfo* _info;
66 66
67 } PythonQtMetaObjectWrapper;
67 } PythonQtClassWrapper;
68 68
69 69 //---------------------------------------------------------------
70 70 // an abstact class for handling construction of objects
71 71 class PythonQtConstructorHandler {
72 72 public:
73 73 //! get rid of warnings
74 74 virtual ~PythonQtConstructorHandler() {}
75 75
76 76 virtual QObject* create(const QMetaObject* meta, PyObject *args, PyObject *kw, QString& error) = 0;
77 77 };
78 78
79 79 #endif No newline at end of file
@@ -1,1076 +1,1076
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 if (info.typeId == QMetaType::Void) {
64 64 Py_INCREF(Py_None);
65 65 return Py_None;
66 66 } else if (info.isPointer && (info.typeId == QMetaType::Char)) {
67 67 // a char ptr will probably be a null terminated string, so we support that:
68 68 return PyString_FromString(*((char**)data));
69 69 } else if ((info.typeId == PythonQtMethodInfo::Unknown || info.typeId >= QMetaType::User) &&
70 70 info.name.startsWith("QList<")) {
71 71 // it is a QList template:
72 72 // (TODO: check what happens if this is a pointer type?!)
73 73 QByteArray innerType = info.name.mid(6,info.name.length()-7);
74 74 if (innerType.endsWith("*")) {
75 75 innerType.truncate(innerType.length()-1);
76 76 return ConvertQListOfPointerTypeToPythonList((QList<void*>*)data, innerType);
77 77 }
78 78 }
79 79
80 80 if (info.typeId >= QMetaType::User) {
81 81 // if a converter is registered, we use is:
82 82 PythonQtConvertMetaTypeToPythonCB* converter = _metaTypeToPythonConverters.value(info.typeId);
83 83 if (converter) {
84 84 return (*converter)(data, info.typeId);
85 85 }
86 86 }
87 87
88 88 // special handling did not match, so we convert the usual way (either pointer or value version):
89 89 if (info.isPointer) {
90 90 // 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)
91 91 return PythonQt::priv()->wrapPtr(*((void**)data), info.name);
92 92 } else {
93 93 // handle values that are not yet handled and not pointers
94 94 return ConvertQtValueToPythonInternal(info.typeId, data);
95 95 }
96 96 }
97 97
98 98 PyObject* PythonQtConv::ConvertQtValueToPythonInternal(int type, const void* data) {
99 99 switch (type) {
100 100 case QMetaType::Void:
101 101 Py_INCREF(Py_None);
102 102 return Py_None;
103 103 case QMetaType::Char:
104 104 return PyInt_FromLong(*((char*)data));
105 105 case QMetaType::UChar:
106 106 return PyInt_FromLong(*((unsigned char*)data));
107 107 case QMetaType::Short:
108 108 return PyInt_FromLong(*((short*)data));
109 109 case QMetaType::UShort:
110 110 return PyInt_FromLong(*((unsigned short*)data));
111 111 case QMetaType::Long:
112 112 return PyInt_FromLong(*((long*)data));
113 113 case QMetaType::ULong:
114 114 // does not fit into simple int of python
115 115 return PyLong_FromUnsignedLong(*((unsigned long*)data));
116 116 case QMetaType::Bool:
117 117 return PythonQtConv::GetPyBool(*((bool*)data));
118 118 case QMetaType::Int:
119 119 return PyInt_FromLong(*((int*)data));
120 120 case QMetaType::UInt:
121 121 return PyInt_FromLong(*((unsigned int*)data));
122 122 case QMetaType::QChar:
123 123 return PyInt_FromLong(*((short*)data));
124 124 case QMetaType::Float:
125 125 return PyFloat_FromDouble(*((float*)data));
126 126 case QMetaType::Double:
127 127 return PyFloat_FromDouble(*((double*)data));
128 128 case QMetaType::LongLong:
129 129 return PyLong_FromLongLong(*((qint64*)data));
130 130 case QMetaType::ULongLong:
131 131 return PyLong_FromUnsignedLongLong(*((quint64*)data));
132 132 case QMetaType::QByteArray: {
133 133 QByteArray* v = (QByteArray*) data;
134 134 return PyString_FromStringAndSize(*v, v->size());
135 135 }
136 136 case QMetaType::QVariantMap:
137 137 return PythonQtConv::QVariantMapToPyObject(*((QVariantMap*)data));
138 138 case QMetaType::QVariantList:
139 139 return PythonQtConv::QVariantListToPyObject(*((QVariantList*)data));
140 140 case QMetaType::QString:
141 141 return PythonQtConv::QStringToPyObject(*((QString*)data));
142 142 case QMetaType::QStringList:
143 143 return PythonQtConv::QStringListToPyObject(*((QStringList*)data));
144 144
145 145 case PythonQtMethodInfo::Variant:
146 146 return PythonQtConv::QVariantToPyObject(*((QVariant*)data));
147 147 case QMetaType::QObjectStar:
148 148 case QMetaType::QWidgetStar:
149 149 return PythonQt::priv()->wrapQObject(*((QObject**)data));
150 150
151 151 default:
152 152 if (PythonQt::priv()->isPythonQtObjectPtrMetaId(type)) {
153 153 // special case, it is a PythonQtObjectPtr which contains a PyObject, take it directly:
154 154 PyObject* o = ((PythonQtObjectPtr*)data)->object();
155 155 Py_INCREF(o);
156 156 return o;
157 157 } else {
158 158 if (type > 0) {
159 159 // if the type is known, we can construct it via QMetaType::construct
160 160 void* newCPPObject = QMetaType::construct(type, data);
161 161 // XXX this could be optimized by using metatypeid directly
162 PythonQtWrapper* wrap = (PythonQtWrapper*)PythonQt::priv()->wrapPtr(newCPPObject, QMetaType::typeName(type));
162 PythonQtInstanceWrapper* wrap = (PythonQtInstanceWrapper*)PythonQt::priv()->wrapPtr(newCPPObject, QMetaType::typeName(type));
163 163 wrap->_ownedByPythonQt = true;
164 164 wrap->_useQMetaTypeDestroy = true;
165 165 return (PyObject*)wrap;
166 166 }
167 167 std::cerr << "Unknown type that can not be converted to Python: " << type << ", in " << __FILE__ << ":" << __LINE__ << std::endl;
168 168 }
169 169 }
170 170 Py_INCREF(Py_None);
171 171 return Py_None;
172 172 }
173 173
174 174 void* PythonQtConv::CreateQtReturnValue(const PythonQtMethodInfo::ParameterInfo& info) {
175 175 void* ptr = NULL;
176 176 if (info.isPointer) {
177 177 PythonQtValueStorage_ADD_VALUE(global_ptrStorage, void*, NULL, ptr);
178 178 } else {
179 179 switch (info.typeId) {
180 180 case QMetaType::Char:
181 181 case QMetaType::UChar:
182 182 case QMetaType::Short:
183 183 case QMetaType::UShort:
184 184 case QMetaType::Long:
185 185 case QMetaType::ULong:
186 186 case QMetaType::Bool:
187 187 case QMetaType::Int:
188 188 case QMetaType::UInt:
189 189 case QMetaType::QChar:
190 190 case QMetaType::Float:
191 191 case QMetaType::Double:
192 192 PythonQtValueStorage_ADD_VALUE(global_valueStorage, long, 0, ptr);
193 193 break;
194 194 case PythonQtMethodInfo::Variant:
195 195 PythonQtValueStorage_ADD_VALUE(global_variantStorage, QVariant, 0, ptr);
196 196 // return the ptr to the variant
197 197 break;
198 198 default:
199 199 if (info.typeId == PythonQtMethodInfo::Unknown) {
200 200 // check if we have a QList of pointers, which we can circumvent with a QList<void*>
201 201 if (info.name.startsWith("QList<")) {
202 202 QByteArray innerType = info.name.mid(6,info.name.length()-7);
203 203 if (innerType.endsWith("*")) {
204 204 static int id = QMetaType::type("QList<void*>");
205 205 PythonQtValueStorage_ADD_VALUE(global_variantStorage, QVariant, QVariant::Type(id), ptr);
206 206 // return the constData pointer that will be filled with the result value later on
207 207 ptr = (void*)((QVariant*)ptr)->constData();
208 208 }
209 209 }
210 210 }
211 211
212 212 if (!ptr) {
213 213 // everything else is stored in a QVariant...
214 214 PythonQtValueStorage_ADD_VALUE(global_variantStorage, QVariant, QVariant::Type(info.typeId), ptr);
215 215 // return the constData pointer that will be filled with the result value later on
216 216 ptr = (void*)((QVariant*)ptr)->constData();
217 217 }
218 218 }
219 219 }
220 220 return ptr;
221 221 }
222 222
223 223 void* PythonQtConv::ConvertPythonToQt(const PythonQtMethodInfo::ParameterInfo& info, PyObject* obj, bool strict, const QMetaObject* meta)
224 224 {
225 225 bool ok;
226 226 void* ptr = NULL;
227 if (obj->ob_type == &PythonQtWrapper_Type && info.typeId != PythonQtMethodInfo::Variant) {
227 if (obj->ob_type == &PythonQtInstanceWrapper_Type && info.typeId != PythonQtMethodInfo::Variant) {
228 228 // if we have a Qt wrapper object and if we do not need a QVariant, we do the following:
229 229 // (the Variant case is handled below in a switch)
230 230
231 231 // a C++ wrapper (can be passed as pointer or reference)
232 PythonQtWrapper* wrap = (PythonQtWrapper*)obj;
232 PythonQtInstanceWrapper* wrap = (PythonQtInstanceWrapper*)obj;
233 233 if (wrap->_info->inherits(info.name)) {
234 234 void* object;
235 235 if (wrap->_info->isCPPWrapper()) {
236 236 object = wrap->_wrappedPtr;
237 237 } else {
238 238 QObject* tmp = wrap->_obj;
239 239 object = tmp;
240 240 }
241 241 if (info.isPointer) {
242 242 // store the wrapped pointer in an extra pointer and let ptr point to the extra pointer
243 243 PythonQtValueStorage_ADD_VALUE(global_ptrStorage, void*, object, ptr);
244 244 } else {
245 245 // store the wrapped pointer directly, since we are a reference
246 246 ptr = object;
247 247 }
248 248 } else {
249 249 // not matching
250 250 }
251 251 } else if (info.isPointer) {
252 252 // a pointer
253 253 if (info.typeId == QMetaType::Char || info.typeId == QMetaType::UChar)
254 254 {
255 255 QString str = PyObjGetString(obj, strict, ok);
256 256 if (ok) {
257 257 void* ptr2 = NULL;
258 258 PythonQtValueStorage_ADD_VALUE(global_variantStorage, QVariant, QVariant(str.toUtf8()), ptr2);
259 259 PythonQtValueStorage_ADD_VALUE(global_ptrStorage, void*, (((QByteArray*)((QVariant*)ptr2)->constData())->data()), ptr);
260 260 }
261 261 } else if (info.name == "PyObject") {
262 262 // handle low level PyObject directly
263 263 PythonQtValueStorage_ADD_VALUE(global_ptrStorage, void*, obj, ptr);
264 264 } else if (obj == Py_None) {
265 265 // None is treated as a NULL ptr
266 266 PythonQtValueStorage_ADD_VALUE(global_ptrStorage, void*, NULL, ptr);
267 267 } else {
268 268 // if we are not strict, we try if we are passed a 0 integer
269 269 if (!strict) {
270 270 bool ok;
271 271 int value = PyObjGetInt(obj, true, ok);
272 272 if (ok && value==0) {
273 273 PythonQtValueStorage_ADD_VALUE(global_ptrStorage, void*, NULL, ptr);
274 274 }
275 275 }
276 276 }
277 277 } else {
278 278 // not a pointer
279 279 switch (info.typeId) {
280 280 case QMetaType::Char:
281 281 {
282 282 int val = PyObjGetInt(obj, strict, ok);
283 283 if (ok) {
284 284 PythonQtValueStorage_ADD_VALUE(global_valueStorage, char, val, ptr);
285 285 }
286 286 }
287 287 break;
288 288 case QMetaType::UChar:
289 289 {
290 290 int val = PyObjGetInt(obj, strict, ok);
291 291 if (ok) {
292 292 PythonQtValueStorage_ADD_VALUE(global_valueStorage, unsigned char, val, ptr);
293 293 }
294 294 }
295 295 break;
296 296 case QMetaType::Short:
297 297 {
298 298 int val = PyObjGetInt(obj, strict, ok);
299 299 if (ok) {
300 300 PythonQtValueStorage_ADD_VALUE(global_valueStorage, short, val, ptr);
301 301 }
302 302 }
303 303 break;
304 304 case QMetaType::UShort:
305 305 {
306 306 int val = PyObjGetInt(obj, strict, ok);
307 307 if (ok) {
308 308 PythonQtValueStorage_ADD_VALUE(global_valueStorage, unsigned short, val, ptr);
309 309 }
310 310 }
311 311 break;
312 312 case QMetaType::Long:
313 313 {
314 314 long val = (long)PyObjGetLongLong(obj, strict, ok);
315 315 if (ok) {
316 316 PythonQtValueStorage_ADD_VALUE(global_valueStorage, long, val, ptr);
317 317 }
318 318 }
319 319 break;
320 320 case QMetaType::ULong:
321 321 {
322 322 unsigned long val = (unsigned long)PyObjGetLongLong(obj, strict, ok);
323 323 if (ok) {
324 324 PythonQtValueStorage_ADD_VALUE(global_valueStorage, unsigned long, val, ptr);
325 325 }
326 326 }
327 327 break;
328 328 case QMetaType::Bool:
329 329 {
330 330 bool val = PyObjGetBool(obj, strict, ok);
331 331 if (ok) {
332 332 PythonQtValueStorage_ADD_VALUE(global_valueStorage, bool, val, ptr);
333 333 }
334 334 }
335 335 break;
336 336 case QMetaType::Int:
337 337 {
338 338 int val = PyObjGetInt(obj, strict, ok);
339 339 if (ok) {
340 340 PythonQtValueStorage_ADD_VALUE(global_valueStorage, int, val, ptr);
341 341 }
342 342 }
343 343 break;
344 344 case QMetaType::UInt:
345 345 {
346 346 unsigned int val = (unsigned int)PyObjGetLongLong(obj, strict, ok);
347 347 if (ok) {
348 348 PythonQtValueStorage_ADD_VALUE(global_valueStorage, unsigned int, val, ptr);
349 349 }
350 350 }
351 351 break;
352 352 case QMetaType::QChar:
353 353 {
354 354 int val = PyObjGetInt(obj, strict, ok);
355 355 if (ok) {
356 356 PythonQtValueStorage_ADD_VALUE(global_valueStorage, short, val, ptr);
357 357 }
358 358 }
359 359 break;
360 360 case QMetaType::Float:
361 361 {
362 362 float val = (float)PyObjGetDouble(obj, strict, ok);
363 363 if (ok) {
364 364 PythonQtValueStorage_ADD_VALUE(global_valueStorage, float, val, ptr);
365 365 }
366 366 }
367 367 break;
368 368 case QMetaType::Double:
369 369 {
370 370 double val = (double)PyObjGetDouble(obj, strict, ok);
371 371 if (ok) {
372 372 PythonQtValueStorage_ADD_VALUE(global_valueStorage, double, val, ptr);
373 373 }
374 374 }
375 375 break;
376 376 case QMetaType::LongLong:
377 377 {
378 378 qint64 val = PyObjGetLongLong(obj, strict, ok);
379 379 if (ok) {
380 380 PythonQtValueStorage_ADD_VALUE(global_valueStorage, qint64, val, ptr);
381 381 }
382 382 }
383 383 break;
384 384 case QMetaType::ULongLong:
385 385 {
386 386 quint64 val = PyObjGetULongLong(obj, strict, ok);
387 387 if (ok) {
388 388 PythonQtValueStorage_ADD_VALUE(global_valueStorage, quint64, val, ptr);
389 389 }
390 390 }
391 391 break;
392 392 case QMetaType::QByteArray:
393 393 {
394 394 QByteArray bytes = PyObjGetBytes(obj, strict, ok);
395 395 if (ok) {
396 396 PythonQtValueStorage_ADD_VALUE(global_variantStorage, QVariant, QVariant(bytes), ptr);
397 397 ptr = (void*)((QVariant*)ptr)->constData();
398 398 }
399 399 }
400 400 break;
401 401 case QMetaType::QString:
402 402 {
403 403 QString str = PyObjGetString(obj, strict, ok);
404 404 if (ok) {
405 405 PythonQtValueStorage_ADD_VALUE(global_variantStorage, QVariant, QVariant(str), ptr);
406 406 ptr = (void*)((QVariant*)ptr)->constData();
407 407 }
408 408 }
409 409 break;
410 410 case QMetaType::QStringList:
411 411 {
412 412 QStringList l = PyObjToStringList(obj, strict, ok);
413 413 if (ok) {
414 414 PythonQtValueStorage_ADD_VALUE(global_variantStorage, QVariant, QVariant(l), ptr);
415 415 ptr = (void*)((QVariant*)ptr)->constData();
416 416 }
417 417 }
418 418 break;
419 419
420 420 case PythonQtMethodInfo::Variant:
421 421 {
422 422 QVariant v = PyObjToQVariant(obj);
423 423 if (v.isValid()) {
424 424 PythonQtValueStorage_ADD_VALUE(global_variantStorage, QVariant, v, ptr);
425 425 }
426 426 }
427 427 break;
428 428 default:
429 429 {
430 430 if (info.typeId == PythonQtMethodInfo::Unknown) {
431 431 // check for enum case
432 432 if (PythonQt::priv()->isEnumType(meta, info.name)) {
433 433 unsigned int val = (unsigned int)PyObjGetLongLong(obj, strict, ok);
434 434 if (ok) {
435 435 PythonQtValueStorage_ADD_VALUE(global_valueStorage, unsigned int, val, ptr);
436 436 return ptr;
437 437 } else {
438 438 return NULL;
439 439 }
440 440 }
441 441 }
442 442 if (info.typeId == PythonQtMethodInfo::Unknown || info.typeId >= QMetaType::User) {
443 443 // check for QList<AnyPtr*> case, where we will use a QList<void*> QVariant
444 444 if (info.name.startsWith("QList<")) {
445 445 QByteArray innerType = info.name.mid(6,info.name.length()-7);
446 446 if (innerType.endsWith("*")) {
447 447 innerType.truncate(innerType.length()-1);
448 448 static int id = QMetaType::type("QList<void*>");
449 449 PythonQtValueStorage_ADD_VALUE(global_variantStorage, QVariant, QVariant::Type(id), ptr);
450 450 ptr = (void*)((QVariant*)ptr)->constData();
451 451 ok = ConvertPythonListToQListOfPointerType(obj, (QList<void*>*)ptr, innerType, strict);
452 452 if (ok) {
453 453 return ptr;
454 454 } else {
455 455 return NULL;
456 456 }
457 457 }
458 458 }
459 459 }
460 460
461 461 // We only do this for registered type > QMetaType::User for performance reasons.
462 462 if (info.typeId >= QMetaType::User) {
463 463 // Maybe we have a special converter that is registered for that type:
464 464 PythonQtConvertPythonToMetaTypeCB* converter = _pythonToMetaTypeConverters.value(info.typeId);
465 465 if (converter) {
466 466 // create a new empty variant of concrete type:
467 467 PythonQtValueStorage_ADD_VALUE(global_variantStorage, QVariant, QVariant::Type(info.typeId), ptr);
468 468 ptr = (void*)((QVariant*)ptr)->constData();
469 469 // now call the converter, passing the internal object of the variant
470 470 ok = (*converter)(obj, ptr, info.typeId, strict);
471 471 if (ok) {
472 472 return ptr;
473 473 } else {
474 474 return NULL;
475 475 }
476 476 }
477 477 }
478 478
479 479 // for all other types, we use the same qvariant conversion and pass out the constData of the variant:
480 480 QVariant v = PyObjToQVariant(obj, info.typeId);
481 481 if (v.isValid()) {
482 482 PythonQtValueStorage_ADD_VALUE(global_variantStorage, QVariant, v, ptr);
483 483 ptr = (void*)((QVariant*)ptr)->constData();
484 484 }
485 485 }
486 486 }
487 487 }
488 488 return ptr;
489 489 }
490 490
491 491
492 492 QStringList PythonQtConv::PyObjToStringList(PyObject* val, bool strict, bool& ok) {
493 493 QStringList v;
494 494 ok = false;
495 495 // if we are strict, we do not want to convert a string to a stringlist
496 496 // (strings in python are detected to be sequences)
497 497 if (strict &&
498 498 (val->ob_type == &PyString_Type ||
499 499 PyUnicode_Check(val))) {
500 500 ok = false;
501 501 return v;
502 502 }
503 503 if (PySequence_Check(val)) {
504 504 int count = PySequence_Size(val);
505 505 for (int i = 0;i<count;i++) {
506 506 PyObject* value = PySequence_GetItem(val,i);
507 507 v.append(PyObjGetString(value,false,ok));
508 508 }
509 509 ok = true;
510 510 }
511 511 return v;
512 512 }
513 513
514 514 QString PythonQtConv::PyObjGetRepresentation(PyObject* val)
515 515 {
516 516 QString r;
517 517 PyObject* str = PyObject_Repr(val);
518 518 if (str) {
519 519 r = QString(PyString_AS_STRING(str));
520 520 Py_DECREF(str);
521 521 }
522 522 return r;
523 523 }
524 524
525 525 QString PythonQtConv::PyObjGetString(PyObject* val, bool strict, bool& ok) {
526 526 QString r;
527 527 ok = true;
528 528 if (val->ob_type == &PyString_Type) {
529 529 r = QString(PyString_AS_STRING(val));
530 530 } else if (PyUnicode_Check(val)) {
531 531 #ifdef WIN32
532 532 r = QString::fromUtf16(PyUnicode_AS_UNICODE(val));
533 533 #else
534 534 PyObject *ptmp = PyUnicode_AsUTF8String(val);
535 535 if(ptmp) {
536 536 r = QString::fromUtf8(PyString_AS_STRING(ptmp));
537 537 Py_DECREF(ptmp);
538 538 }
539 539 #endif
540 540 } else if (!strict) {
541 541 // EXTRA: could also use _Unicode, but why should we?
542 542 PyObject* str = PyObject_Str(val);
543 543 if (str) {
544 544 r = QString(PyString_AS_STRING(str));
545 545 Py_DECREF(str);
546 546 } else {
547 547 ok = false;
548 548 }
549 549 } else {
550 550 ok = false;
551 551 }
552 552 return r;
553 553 }
554 554
555 555 QByteArray PythonQtConv::PyObjGetBytes(PyObject* val, bool /*strict*/, bool& ok) {
556 556 QByteArray r;
557 557 ok = true;
558 558 if (val->ob_type == &PyString_Type) {
559 559 long size = PyString_GET_SIZE(val);
560 560 r = QByteArray(PyString_AS_STRING(val), size);
561 561 } else {
562 562 ok = false;
563 563 }
564 564 return r;
565 565 }
566 566
567 567 bool PythonQtConv::PyObjGetBool(PyObject* val, bool strict, bool &ok) {
568 568 bool d = false;
569 569 ok = false;
570 570 if (val == Py_False) {
571 571 d = false;
572 572 ok = true;
573 573 } else if (val == Py_True) {
574 574 d = true;
575 575 ok = true;
576 576 } else if (!strict) {
577 577 d = PyObjGetInt(val, false, ok)!=0;
578 578 ok = true;
579 579 }
580 580 return d;
581 581 }
582 582
583 583 int PythonQtConv::PyObjGetInt(PyObject* val, bool strict, bool &ok) {
584 584 int d = 0;
585 585 ok = true;
586 586 if (val->ob_type == &PyInt_Type) {
587 587 d = PyInt_AS_LONG(val);
588 588 } else if (!strict) {
589 589 if (val->ob_type == &PyFloat_Type) {
590 590 d = floor(PyFloat_AS_DOUBLE(val));
591 591 } else if (val->ob_type == &PyLong_Type) {
592 592 // handle error on overflow!
593 593 d = PyLong_AsLong(val);
594 594 } else if (val == Py_False) {
595 595 d = 0;
596 596 } else if (val == Py_True) {
597 597 d = 1;
598 598 } else {
599 599 ok = false;
600 600 }
601 601 } else {
602 602 ok = false;
603 603 }
604 604 return d;
605 605 }
606 606
607 607 qint64 PythonQtConv::PyObjGetLongLong(PyObject* val, bool strict, bool &ok) {
608 608 qint64 d = 0;
609 609 ok = true;
610 610 if (val->ob_type == &PyInt_Type) {
611 611 d = PyInt_AS_LONG(val);
612 612 } else if (val->ob_type == &PyLong_Type) {
613 613 d = PyLong_AsLongLong(val);
614 614 } else if (!strict) {
615 615 if (val->ob_type == &PyFloat_Type) {
616 616 d = floor(PyFloat_AS_DOUBLE(val));
617 617 } else if (val == Py_False) {
618 618 d = 0;
619 619 } else if (val == Py_True) {
620 620 d = 1;
621 621 } else {
622 622 ok = false;
623 623 }
624 624 } else {
625 625 ok = false;
626 626 }
627 627 return d;
628 628 }
629 629
630 630 quint64 PythonQtConv::PyObjGetULongLong(PyObject* val, bool strict, bool &ok) {
631 631 quint64 d = 0;
632 632 ok = true;
633 633 if (val->ob_type == &PyInt_Type) {
634 634 d = PyInt_AS_LONG(val);
635 635 } else if (val->ob_type == &PyLong_Type) {
636 636 d = PyLong_AsLongLong(val);
637 637 } else if (!strict) {
638 638 if (val->ob_type == &PyFloat_Type) {
639 639 d = floor(PyFloat_AS_DOUBLE(val));
640 640 } else if (val == Py_False) {
641 641 d = 0;
642 642 } else if (val == Py_True) {
643 643 d = 1;
644 644 } else {
645 645 ok = false;
646 646 }
647 647 } else {
648 648 ok = false;
649 649 }
650 650 return d;
651 651 }
652 652
653 653 double PythonQtConv::PyObjGetDouble(PyObject* val, bool strict, bool &ok) {
654 654 double d = 0;
655 655 ok = true;
656 656 if (val->ob_type == &PyFloat_Type) {
657 657 d = PyFloat_AS_DOUBLE(val);
658 658 } else if (!strict) {
659 659 if (val->ob_type == &PyInt_Type) {
660 660 d = PyInt_AS_LONG(val);
661 661 } else if (val->ob_type == &PyLong_Type) {
662 662 d = PyLong_AsLong(val);
663 663 } else if (val == Py_False) {
664 664 d = 0;
665 665 } else if (val == Py_True) {
666 666 d = 1;
667 667 } else {
668 668 ok = false;
669 669 }
670 670 } else {
671 671 ok = false;
672 672 }
673 673 return d;
674 674 }
675 675
676 676 QVariant PythonQtConv::PyObjToQVariant(PyObject* val, int type)
677 677 {
678 678 QVariant v;
679 679 bool ok = true;
680 680
681 681 if (type==-1) {
682 682 // no special type requested
683 683 if (val->ob_type==&PyString_Type || val->ob_type==&PyUnicode_Type) {
684 684 type = QVariant::String;
685 685 } else if (val->ob_type==&PyInt_Type) {
686 686 type = QVariant::Int;
687 687 } else if (val->ob_type==&PyLong_Type) {
688 688 type = QVariant::LongLong;
689 689 } else if (val->ob_type==&PyFloat_Type) {
690 690 type = QVariant::Double;
691 691 } else if (val == Py_False || val == Py_True) {
692 692 type = QVariant::Bool;
693 } else if (val->ob_type == &PythonQtWrapper_Type) {
694 PythonQtWrapper* wrap = (PythonQtWrapper*)val;
693 } else if (val->ob_type == &PythonQtInstanceWrapper_Type) {
694 PythonQtInstanceWrapper* wrap = (PythonQtInstanceWrapper*)val;
695 695 // c++ wrapper, check if the class names of the c++ objects match
696 696 if (wrap->_info->isCPPWrapper()) {
697 697 if (wrap->_info->metaTypeId()>0) {
698 698 // construct a new variant from the C++ object if it has a meta type
699 699 v = QVariant(wrap->_info->metaTypeId(), wrap->_wrappedPtr);
700 700 } else {
701 701 // is this worth anything? we loose the knowledge of the cpp object type
702 702 v = qVariantFromValue(wrap->_wrappedPtr);
703 703 }
704 704 } else {
705 705 // this gives us a QObject pointer
706 706 QObject* myObject = wrap->_obj;
707 707 v = qVariantFromValue(myObject);
708 708 }
709 709 return v;
710 710 } else if (val->ob_type==&PyDict_Type) {
711 711 type = QVariant::Map;
712 712 } else if (val->ob_type==&PyList_Type || val->ob_type==&PyTuple_Type || PySequence_Check(val)) {
713 713 type = QVariant::List;
714 714 } else if (val == Py_None) {
715 715 // none is invalid
716 716 type = QVariant::Invalid;
717 717 } else {
718 718 // this used to be:
719 719 // type = QVariant::String;
720 720 // but now we want to transport the Python Objects directly:
721 721 PythonQtObjectPtr o(val);
722 722 v = qVariantFromValue(o);
723 723 return v;
724 724 }
725 725 }
726 726 // special type request:
727 727 switch (type) {
728 728 case QVariant::Invalid:
729 729 return v;
730 730 break;
731 731 case QVariant::Int:
732 732 {
733 733 int d = PyObjGetInt(val, false, ok);
734 734 if (ok) return QVariant(d);
735 735 }
736 736 break;
737 737 case QVariant::UInt:
738 738 {
739 739 int d = PyObjGetInt(val, false,ok);
740 740 if (ok) v = QVariant((unsigned int)d);
741 741 }
742 742 break;
743 743 case QVariant::Bool:
744 744 {
745 745 int d = PyObjGetBool(val,false,ok);
746 746 if (ok) v = QVariant((bool)(d!=0));
747 747 }
748 748 break;
749 749 case QVariant::Double:
750 750 {
751 751 double d = PyObjGetDouble(val,false,ok);
752 752 if (ok) v = QVariant(d);
753 753 break;
754 754 }
755 755 case QMetaType::Float:
756 756 {
757 757 float d = (float) PyObjGetDouble(val,false,ok);
758 758 if (ok) v = qVariantFromValue(d);
759 759 break;
760 760 }
761 761 case QMetaType::Long:
762 762 {
763 763 long d = (long) PyObjGetLongLong(val,false,ok);
764 764 if (ok) v = qVariantFromValue(d);
765 765 break;
766 766 }
767 767 case QMetaType::ULong:
768 768 {
769 769 unsigned long d = (unsigned long) PyObjGetLongLong(val,false,ok);
770 770 if (ok) v = qVariantFromValue(d);
771 771 break;
772 772 }
773 773 case QMetaType::Short:
774 774 {
775 775 short d = (short) PyObjGetInt(val,false,ok);
776 776 if (ok) v = qVariantFromValue(d);
777 777 break;
778 778 }
779 779 case QMetaType::UShort:
780 780 {
781 781 unsigned short d = (unsigned short) PyObjGetInt(val,false,ok);
782 782 if (ok) v = qVariantFromValue(d);
783 783 break;
784 784 }
785 785 case QMetaType::Char:
786 786 {
787 787 char d = (char) PyObjGetInt(val,false,ok);
788 788 if (ok) v = qVariantFromValue(d);
789 789 break;
790 790 }
791 791 case QMetaType::UChar:
792 792 {
793 793 unsigned char d = (unsigned char) PyObjGetInt(val,false,ok);
794 794 if (ok) v = qVariantFromValue(d);
795 795 break;
796 796 }
797 797
798 798 case QVariant::ByteArray:
799 799 case QVariant::String:
800 800 {
801 801 bool ok;
802 802 v = QVariant(PyObjGetString(val, false, ok));
803 803 }
804 804 break;
805 805
806 806 // these are important for MeVisLab
807 807 case QVariant::Map:
808 808 {
809 809 if (PyMapping_Check(val)) {
810 810 QMap<QString,QVariant> map;
811 811 PyObject* items = PyMapping_Items(val);
812 812 if (items) {
813 813 int count = PyList_Size(items);
814 814 PyObject* value;
815 815 PyObject* key;
816 816 PyObject* tuple;
817 817 for (int i = 0;i<count;i++) {
818 818 tuple = PyList_GetItem(items,i);
819 819 key = PyTuple_GetItem(tuple, 0);
820 820 value = PyTuple_GetItem(tuple, 1);
821 821 map.insert(PyObjGetString(key), PyObjToQVariant(value,-1));
822 822 }
823 823 Py_DECREF(items);
824 824 v = map;
825 825 }
826 826 }
827 827 }
828 828 break;
829 829 case QVariant::List:
830 830 if (PySequence_Check(val)) {
831 831 QVariantList list;
832 832 int count = PySequence_Size(val);
833 833 PyObject* value;
834 834 for (int i = 0;i<count;i++) {
835 835 value = PySequence_GetItem(val,i);
836 836 list.append(PyObjToQVariant(value, -1));
837 837 }
838 838 v = list;
839 839 }
840 840 break;
841 841 case QVariant::StringList:
842 842 {
843 843 bool ok;
844 844 QStringList l = PyObjToStringList(val, false, ok);
845 845 if (ok) {
846 846 v = l;
847 847 }
848 848 }
849 849 break;
850 850
851 851 default:
852 if (val->ob_type == &PythonQtWrapper_Type) {
853 PythonQtWrapper* wrap = (PythonQtWrapper*)val;
852 if (val->ob_type == &PythonQtInstanceWrapper_Type) {
853 PythonQtInstanceWrapper* wrap = (PythonQtInstanceWrapper*)val;
854 854 if (wrap->_info->isCPPWrapper() && wrap->_info->metaTypeId() == type) {
855 855 // construct a new variant from the C++ object if it has the same meta type
856 856 v = QVariant(type, wrap->_wrappedPtr);
857 857 } else {
858 858 v = QVariant();
859 859 }
860 860 } else {
861 861 v = QVariant();
862 862 }
863 863 }
864 864 return v;
865 865 }
866 866
867 867 PyObject* PythonQtConv::QStringToPyObject(const QString& str)
868 868 {
869 869 if (str.isNull()) {
870 870 return PyString_FromString("");
871 871 } else {
872 872 #ifdef WIN32
873 873 // return PyString_FromString(str.toLatin1().data());
874 874 return PyUnicode_FromUnicode(str.utf16(), str.length());
875 875 #else
876 876 return PyUnicode_DecodeUTF16((const char*)str.utf16(), str.length()*2, NULL, NULL);
877 877 #endif
878 878 }
879 879 }
880 880
881 881 PyObject* PythonQtConv::QStringListToPyObject(const QStringList& list)
882 882 {
883 883 PyObject* result = PyTuple_New(list.count());
884 884 int i = 0;
885 885 QString str;
886 886 foreach (str, list) {
887 887 PyTuple_SET_ITEM(result, i, PythonQtConv::QStringToPyObject(str));
888 888 i++;
889 889 }
890 890 // why is the error state bad after this?
891 891 PyErr_Clear();
892 892 return result;
893 893 }
894 894
895 895 PyObject* PythonQtConv::QStringListToPyList(const QStringList& list)
896 896 {
897 897 PyObject* result = PyList_New(list.count());
898 898 int i = 0;
899 899 for (QStringList::ConstIterator it = list.begin(); it!=list.end(); ++it) {
900 900 PyList_SET_ITEM(result, i, PythonQtConv::QStringToPyObject(*it));
901 901 i++;
902 902 }
903 903 return result;
904 904 }
905 905
906 906 PyObject* PythonQtConv::QVariantToPyObject(const QVariant& v)
907 907 {
908 908 return ConvertQtValueToPythonInternal(v.userType(), (void*)v.constData());
909 909 }
910 910
911 911 PyObject* PythonQtConv::QVariantMapToPyObject(const QVariantMap& m) {
912 912 PyObject* result = PyDict_New();
913 913 QVariantMap::const_iterator t = m.constBegin();
914 914 PyObject* key;
915 915 PyObject* val;
916 916 for (;t!=m.end();t++) {
917 917 key = QStringToPyObject(t.key());
918 918 val = QVariantToPyObject(t.value());
919 919 PyDict_SetItem(result, key, val);
920 920 Py_DECREF(key);
921 921 Py_DECREF(val);
922 922 }
923 923 return result;
924 924 }
925 925
926 926 PyObject* PythonQtConv::QVariantListToPyObject(const QVariantList& l) {
927 927 PyObject* result = PyTuple_New(l.count());
928 928 int i = 0;
929 929 QVariant v;
930 930 foreach (v, l) {
931 931 PyTuple_SET_ITEM(result, i, PythonQtConv::QVariantToPyObject(v));
932 932 i++;
933 933 }
934 934 // why is the error state bad after this?
935 935 PyErr_Clear();
936 936 return result;
937 937 }
938 938
939 939 PyObject* PythonQtConv::ConvertQListOfPointerTypeToPythonList(QList<void*>* list, const QByteArray& typeName)
940 940 {
941 941 PyObject* result = PyTuple_New(list->count());
942 942 int i = 0;
943 943 foreach (void* value, *list) {
944 944 PyTuple_SET_ITEM(result, i, PythonQt::priv()->wrapPtr(value, typeName));
945 945 i++;
946 946 }
947 947 return result;
948 948 }
949 949
950 950 bool PythonQtConv::ConvertPythonListToQListOfPointerType(PyObject* obj, QList<void*>* list, const QByteArray& type, bool /*strict*/)
951 951 {
952 952 bool result = false;
953 953 if (PySequence_Check(obj)) {
954 954 result = true;
955 955 int count = PySequence_Size(obj);
956 956 PyObject* value;
957 957 for (int i = 0;i<count;i++) {
958 958 value = PySequence_GetItem(obj,i);
959 if (value->ob_type == &PythonQtWrapper_Type) {
960 PythonQtWrapper* wrap = (PythonQtWrapper*)value;
959 if (value->ob_type == &PythonQtInstanceWrapper_Type) {
960 PythonQtInstanceWrapper* wrap = (PythonQtInstanceWrapper*)value;
961 961 // both QObjects and CPP wrappers support inherits, so we use that to check of we match
962 962 if (wrap->_info->inherits(type)) {
963 963 if (wrap->_info->isCPPWrapper()) {
964 964 list->append(wrap->_wrappedPtr);
965 965 } else {
966 966 QObject* myObject = wrap->_obj;
967 967 list->append((void*)myObject);
968 968 }
969 969 } else {
970 970 result = false;
971 971 break;
972 972 }
973 973 }
974 974 }
975 975 }
976 976 return result;
977 977 }
978 978
979 979 int PythonQtConv::getInnerTemplateMetaType(const QByteArray& typeName)
980 980 {
981 981 int idx = typeName.indexOf("<");
982 982 if (idx>0) {
983 983 int idx2 = typeName.indexOf(">");
984 984 if (idx2>0) {
985 985 QByteArray innerType = typeName.mid(idx+1,idx2-idx-1);
986 986 return QMetaType::type(innerType.constData());
987 987 }
988 988 }
989 989 return QMetaType::Void;
990 990 }
991 991
992 992
993 993
994 994 QString PythonQtConv::qVariantToString(const QVariant& v) {
995 995 return CPPObjectToString(v.userType(), v.constData());
996 996 }
997 997
998 998 QString PythonQtConv::CPPObjectToString(int type, const void* data) {
999 999 QString r;
1000 1000 switch (type) {
1001 1001 case QVariant::Size: {
1002 1002 const QSize* s = static_cast<const QSize*>(data);
1003 1003 r = QString::number(s->width()) + ", " + QString::number(s->height());
1004 1004 }
1005 1005 break;
1006 1006 case QVariant::SizeF: {
1007 1007 const QSizeF* s = static_cast<const QSizeF*>(data);
1008 1008 r = QString::number(s->width()) + ", " + QString::number(s->height());
1009 1009 }
1010 1010 break;
1011 1011 case QVariant::Point: {
1012 1012 const QPoint* s = static_cast<const QPoint*>(data);
1013 1013 r = QString::number(s->x()) + ", " + QString::number(s->y());
1014 1014 }
1015 1015 break;
1016 1016 case QVariant::PointF: {
1017 1017 const QPointF* s = static_cast<const QPointF*>(data);
1018 1018 r = QString::number(s->x()) + ", " + QString::number(s->y());
1019 1019 }
1020 1020 break;
1021 1021 case QVariant::Rect: {
1022 1022 const QRect* s = static_cast<const QRect*>(data);
1023 1023 r = QString::number(s->x()) + ", " + QString::number(s->y());
1024 1024 r += ", " + QString::number(s->width()) + ", " + QString::number(s->height());
1025 1025 }
1026 1026 break;
1027 1027 case QVariant::RectF: {
1028 1028 const QRectF* s = static_cast<const QRectF*>(data);
1029 1029 r = QString::number(s->x()) + ", " + QString::number(s->y());
1030 1030 r += ", " + QString::number(s->width()) + ", " + QString::number(s->height());
1031 1031 }
1032 1032 break;
1033 1033 case QVariant::Date: {
1034 1034 const QDate* s = static_cast<const QDate*>(data);
1035 1035 r = s->toString(Qt::ISODate);
1036 1036 }
1037 1037 break;
1038 1038 case QVariant::DateTime: {
1039 1039 const QDateTime* s = static_cast<const QDateTime*>(data);
1040 1040 r = s->toString(Qt::ISODate);
1041 1041 }
1042 1042 break;
1043 1043 case QVariant::Time: {
1044 1044 const QTime* s = static_cast<const QTime*>(data);
1045 1045 r = s->toString(Qt::ISODate);
1046 1046 }
1047 1047 break;
1048 1048 case QVariant::Pixmap:
1049 1049 {
1050 1050 const QPixmap* s = static_cast<const QPixmap*>(data);
1051 1051 r = QString("Pixmap ") + QString::number(s->width()) + ", " + QString::number(s->height());
1052 1052 }
1053 1053 break;
1054 1054 case QVariant::Image:
1055 1055 {
1056 1056 const QImage* s = static_cast<const QImage*>(data);
1057 1057 r = QString("Image ") + QString::number(s->width()) + ", " + QString::number(s->height());
1058 1058 }
1059 1059 break;
1060 1060 case QVariant::Url:
1061 1061 {
1062 1062 const QUrl* s = static_cast<const QUrl*>(data);
1063 1063 r = s->toString();
1064 1064 }
1065 1065 break;
1066 1066 //TODO: add more printing for other variant types
1067 1067 default:
1068 1068 // this creates a copy, but that should not be expensive for typical simple variants
1069 1069 // (but we do not want to do this for our won user types!
1070 1070 if (type>0 && type < (int)QVariant::UserType) {
1071 1071 QVariant v(type, data);
1072 1072 r = v.toString();
1073 1073 }
1074 1074 }
1075 1075 return r;
1076 1076 }
@@ -1,485 +1,485
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 // \file PythonQtWrapper.cpp
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 #include "PythonQtWrapper.h"
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
49 static void PythonQtWrapper_deleteObject(PythonQtWrapper* self, bool force = false) {
49 static void PythonQtInstanceWrapper_deleteObject(PythonQtInstanceWrapper* self, bool force = false) {
50 50
51 51 // is this a C++ wrapper?
52 52 if (self->_wrappedPtr) {
53 53 //mlabDebugConst("Python","c++ wrapper removed " << self->_wrappedPtr << " " << self->_obj->className() << " " << self->_info->wrappedClassName().latin1());
54 54
55 55 PythonQt::priv()->removeWrapperPointer(self->_wrappedPtr);
56 56 // we own our qobject, so we delete it now:
57 57 delete self->_obj;
58 58 self->_obj = NULL;
59 59 if (force || self->_info->hasOwnerMethodButNoOwner(self->_wrappedPtr) || self->_ownedByPythonQt) {
60 60 int type = self->_info->metaTypeId();
61 61 if (self->_useQMetaTypeDestroy && type>=0) {
62 62 // use QMetaType to destroy the object
63 63 QMetaType::destroy(type, self->_wrappedPtr);
64 64 } else {
65 65 PythonQtSlotInfo* slot = PythonQt::priv()->getDestructorSlot(self->_info->className());
66 66 if (slot) {
67 67 void* args[2];
68 68 args[0] = NULL;
69 69 args[1] = &self->_wrappedPtr;
70 70 slot->decorator()->qt_metacall(QMetaObject::InvokeMetaMethod, slot->slotIndex(), args);
71 71 self->_wrappedPtr = NULL;
72 72 } else {
73 73 if (type>=0) {
74 74 // use QMetaType to destroy the object
75 75 QMetaType::destroy(type, self->_wrappedPtr);
76 76 } else {
77 77 // TODO: warn about not being able to destroy the object?
78 78 }
79 79 }
80 80 }
81 81 }
82 82 } else {
83 83 //mlabDebugConst("Python","qobject wrapper removed " << self->_obj->className() << " " << self->_info->wrappedClassName().latin1());
84 84 if (self->_objPointerCopy) {
85 85 PythonQt::priv()->removeWrapperPointer(self->_objPointerCopy);
86 86 }
87 87 if (self->_obj) {
88 88 if (force || self->_ownedByPythonQt) {
89 89 if (force || !self->_obj->parent()) {
90 90 delete self->_obj;
91 91 }
92 92 } else {
93 93 if (self->_obj->parent()==NULL) {
94 94 // tell someone who is interested that the qobject is no longer wrapped, if it has no parent
95 95 PythonQt::qObjectNoLongerWrappedCB(self->_obj);
96 96 }
97 97 }
98 98 }
99 99 }
100 100 self->_obj = NULL;
101 101 }
102 102
103 static void PythonQtWrapper_dealloc(PythonQtWrapper* self)
103 static void PythonQtInstanceWrapper_dealloc(PythonQtInstanceWrapper* self)
104 104 {
105 PythonQtWrapper_deleteObject(self);
105 PythonQtInstanceWrapper_deleteObject(self);
106 106 self->_obj.~QPointer<QObject>();
107 107 self->ob_type->tp_free((PyObject*)self);
108 108 }
109 109
110 static PyObject* PythonQtWrapper_new(PyTypeObject *type, PyObject * /*args*/, PyObject * /*kwds*/)
110 static PyObject* PythonQtInstanceWrapper_new(PyTypeObject *type, PyObject * /*args*/, PyObject * /*kwds*/)
111 111 {
112 PythonQtWrapper *self;
112 PythonQtInstanceWrapper *self;
113 113
114 self = (PythonQtWrapper *)type->tp_alloc(type, 0);
114 self = (PythonQtInstanceWrapper *)type->tp_alloc(type, 0);
115 115 if (self != NULL) {
116 116 self->_info = NULL;
117 117 new (&self->_obj) QPointer<QObject>();
118 118 self->_wrappedPtr = NULL;
119 119 self->_ownedByPythonQt = false;
120 120 self->_useQMetaTypeDestroy = false;
121 121 }
122 122 return (PyObject *)self;
123 123 }
124 124
125 static int PythonQtWrapper_init(PythonQtWrapper * /*self*/, PyObject * /*args*/, PyObject * /*kwds*/)
125 static int PythonQtInstanceWrapper_init(PythonQtInstanceWrapper * /*self*/, PyObject * /*args*/, PyObject * /*kwds*/)
126 126 {
127 127 return 0;
128 128 }
129 129
130 static PyObject *PythonQtWrapper_classname(PythonQtWrapper* type)
130 static PyObject *PythonQtInstanceWrapper_classname(PythonQtInstanceWrapper* type)
131 131 {
132 132 return PyString_FromString(type->_info->className());
133 133 }
134 134
135 static PyObject *PythonQtWrapper_help(PythonQtWrapper* type)
135 static PyObject *PythonQtInstanceWrapper_help(PythonQtInstanceWrapper* type)
136 136 {
137 137 return PythonQt::self()->helpCalled(type->_info);
138 138 }
139 139
140 static PyObject *PythonQtWrapper_delete(PythonQtWrapper * self)
140 static PyObject *PythonQtInstanceWrapper_delete(PythonQtInstanceWrapper * self)
141 141 {
142 PythonQtWrapper_deleteObject(self, true);
142 PythonQtInstanceWrapper_deleteObject(self, true);
143 143 Py_INCREF(Py_None);
144 144 return Py_None;
145 145 }
146 146
147 147
148 static PyMethodDef PythonQtWrapper_methods[] = {
149 {"className", (PyCFunction)PythonQtWrapper_classname, METH_NOARGS,
148 static PyMethodDef PythonQtInstanceWrapper_methods[] = {
149 {"className", (PyCFunction)PythonQtInstanceWrapper_classname, METH_NOARGS,
150 150 "Return the classname of the object"
151 151 },
152 {"help", (PyCFunction)PythonQtWrapper_help, METH_NOARGS,
152 {"help", (PyCFunction)PythonQtInstanceWrapper_help, METH_NOARGS,
153 153 "Shows the help of available methods for this class"
154 154 },
155 {"delete", (PyCFunction)PythonQtWrapper_delete, METH_NOARGS,
155 {"delete", (PyCFunction)PythonQtInstanceWrapper_delete, METH_NOARGS,
156 156 "Deletes the C++ object (at your own risk, my friend!)"
157 157 },
158 158 {NULL, NULL, 0, NULL} /* Sentinel */
159 159 };
160 160
161 161
162 static PyObject *PythonQtWrapper_getattro(PyObject *obj,PyObject *name)
162 static PyObject *PythonQtInstanceWrapper_getattro(PyObject *obj,PyObject *name)
163 163 {
164 164 const char *attributeName;
165 PythonQtWrapper *wt = (PythonQtWrapper *)obj;
165 PythonQtInstanceWrapper *wrapper = (PythonQtInstanceWrapper *)obj;
166 166
167 167 if ((attributeName = PyString_AsString(name)) == NULL) {
168 168 return NULL;
169 169 }
170 170
171 if (!wt->_obj && !wt->_wrappedPtr) {
172 QString error = QString("Trying to read attribute '") + attributeName + "' from a destroyed " + wt->_info->className() + " object";
171 if (!wrapper->_obj && !wrapper->_wrappedPtr) {
172 QString error = QString("Trying to read attribute '") + attributeName + "' from a destroyed " + wrapper->_info->className() + " object";
173 173 PyErr_SetString(PyExc_ValueError, error.toLatin1().data());
174 174 return NULL;
175 175 }
176 176
177 177 // mlabDebugConst("Python","get " << attributeName);
178 178
179 179 // TODO: dynamic properties are missing
180 180
181 PythonQtMemberInfo member = wt->_info->member(attributeName);
181 PythonQtMemberInfo member = wrapper->_info->member(attributeName);
182 182 switch (member._type) {
183 183 case PythonQtMemberInfo::Property:
184 if (wt->_obj) {
185 return PythonQtConv::QVariantToPyObject(member._property.read(wt->_obj));
184 if (wrapper->_obj) {
185 return PythonQtConv::QVariantToPyObject(member._property.read(wrapper->_obj));
186 186 }
187 187 break;
188 188 case PythonQtMemberInfo::Slot:
189 189 return PythonQtSlotFunction_New(member._slot, obj, NULL);
190 190 break;
191 191 case PythonQtMemberInfo::EnumValue:
192 192 return PyInt_FromLong(member._enumValue);
193 193 break;
194 194 default:
195 195 // is an invalid type, go on
196 196 break;
197 197 }
198 198
199 199 // look for the interal methods (className(), help())
200 PyObject* internalMethod = Py_FindMethod( PythonQtWrapper_methods, obj, (char*)attributeName);
200 PyObject* internalMethod = Py_FindMethod( PythonQtInstanceWrapper_methods, obj, (char*)attributeName);
201 201 if (internalMethod) {
202 202 return internalMethod;
203 203 }
204 204 PyErr_Clear();
205 205
206 if (wt->_obj) {
206 if (wrapper->_obj) {
207 207 // look for a child
208 QObjectList children = wt->_obj->children();
208 QObjectList children = wrapper->_obj->children();
209 209 for (int i = 0; i < children.count(); i++) {
210 210 QObject *child = children.at(i);
211 211 if (child->objectName() == attributeName) {
212 212 return PythonQt::self()->priv()->wrapQObject(child);
213 213 }
214 214 }
215 215 }
216 216
217 217 if (qstrcmp(attributeName, "__dict__")==0) {
218 QStringList l = wt->_info->memberList(false);
218 QStringList l = wrapper->_info->memberList(false);
219 219 PyObject* dict = PyDict_New();
220 220 foreach (QString name, l) {
221 221 //PyObject* o = PyObject_GetAttrString(obj, name.toLatin1().data());
222 222 PyDict_SetItemString(dict, name.toLatin1().data(), Py_None);
223 223 //Py_DECREF(o);
224 224 }
225 225 // Note: we do not put children into the dict, is would look confusing?!
226 226 return dict;
227 227 }
228 228
229 229
230 QString error = QString(wt->_info->className()) + " has no attribute named '" + QString(attributeName) + "'";
230 QString error = QString(wrapper->_info->className()) + " has no attribute named '" + QString(attributeName) + "'";
231 231 PyErr_SetString(PyExc_AttributeError, error.toLatin1().data());
232 232 return NULL;
233 233 }
234 234
235 static int PythonQtWrapper_setattro(PyObject *obj,PyObject *name,PyObject *value)
235 static int PythonQtInstanceWrapper_setattro(PyObject *obj,PyObject *name,PyObject *value)
236 236 {
237 237 QString error;
238 238 char *attributeName;
239 PythonQtWrapper *wt = (PythonQtWrapper *)obj;
239 PythonQtInstanceWrapper *wrapper = (PythonQtInstanceWrapper *)obj;
240 240
241 241 if ((attributeName = PyString_AsString(name)) == NULL)
242 242 return -1;
243 243
244 if (!wt->_obj) {
245 error = QString("Trying to set attribute '") + attributeName + "' on a destroyed " + wt->_info->className() + " object";
244 if (!wrapper->_obj) {
245 error = QString("Trying to set attribute '") + attributeName + "' on a destroyed " + wrapper->_info->className() + " object";
246 246 PyErr_SetString(PyExc_AttributeError, error.toLatin1().data());
247 247 return -1;
248 248 }
249 249
250 PythonQtMemberInfo member = wt->_info->member(attributeName);
250 PythonQtMemberInfo member = wrapper->_info->member(attributeName);
251 251 if (member._type == PythonQtMemberInfo::Property) {
252 252 QMetaProperty prop = member._property;
253 253 if (prop.isWritable()) {
254 254 QVariant v;
255 255 if (prop.isEnumType()) {
256 256 // this will give us either a string or an int, everything else will probably be an error
257 257 v = PythonQtConv::PyObjToQVariant(value);
258 258 } else {
259 259 int t = prop.userType();
260 260 v = PythonQtConv::PyObjToQVariant(value, t);
261 261 }
262 262 bool success = false;
263 263 if (v.isValid()) {
264 success = prop.write(wt->_obj, v);
264 success = prop.write(wrapper->_obj, v);
265 265 }
266 266 if (success) {
267 267 return 0;
268 268 } else {
269 269 error = QString("Property '") + attributeName + "' of type '" +
270 270 prop.typeName() + "' does not accept an object of type "
271 271 + QString(value->ob_type->tp_name) + " (" + PythonQtConv::PyObjGetRepresentation(value) + ")";
272 272 }
273 273 } else {
274 error = QString("Property '") + attributeName + "' of " + wt->_info->className() + " object is not writable";
274 error = QString("Property '") + attributeName + "' of " + wrapper->_info->className() + " object is not writable";
275 275 }
276 276 } else {
277 277 if (member._type == PythonQtMemberInfo::Slot) {
278 error = QString("Slot '") + attributeName + "' can not be overwritten on " + wt->_info->className() + " object";
278 error = QString("Slot '") + attributeName + "' can not be overwritten on " + wrapper->_info->className() + " object";
279 279 } else if (member._type == PythonQtMemberInfo::EnumValue) {
280 error = QString("EnumValue '") + attributeName + "' can not be overwritten on " + wt->_info->className() + " object";
280 error = QString("EnumValue '") + attributeName + "' can not be overwritten on " + wrapper->_info->className() + " object";
281 281 }
282 282 }
283 283
284 284 PyErr_SetString(PyExc_AttributeError, error.toLatin1().data());
285 285 return -1;
286 286 }
287 287
288 static PyObject * PythonQtWrapper_str(PyObject * obj)
288 static PyObject * PythonQtInstanceWrapper_str(PyObject * obj)
289 289 {
290 PythonQtWrapper* wt = (PythonQtWrapper*)obj;
291 QObject *qobj = wt->_obj;
292 if (wt->_wrappedPtr) {
293 QString str = PythonQtConv::CPPObjectToString(wt->_info->metaTypeId(), wt->_wrappedPtr);
290 PythonQtInstanceWrapper* wrapper = (PythonQtInstanceWrapper*)obj;
291 QObject *qobj = wrapper->_obj;
292 if (wrapper->_wrappedPtr) {
293 QString str = PythonQtConv::CPPObjectToString(wrapper->_info->metaTypeId(), wrapper->_wrappedPtr);
294 294 if (!str.isEmpty()) {
295 295 return PyString_FromFormat("%s", str.toLatin1().constData());
296 296 } else
297 if (wt->_obj) {
298 return PyString_FromFormat("%s (C++ Object %p wrapped by %s %p))", wt->_info->className(), wt->_wrappedPtr, wt->_obj->metaObject()->className(), qobj);
297 if (wrapper->_obj) {
298 return PyString_FromFormat("%s (C++ Object %p wrapped by %s %p))", wrapper->_info->className(), wrapper->_wrappedPtr, wrapper->_obj->metaObject()->className(), qobj);
299 299 } else {
300 return PyString_FromFormat("%s (C++ Object %p)", wt->_info->className(), wt->_wrappedPtr);
300 return PyString_FromFormat("%s (C++ Object %p)", wrapper->_info->className(), wrapper->_wrappedPtr);
301 301 }
302 302 } else {
303 return PyString_FromFormat("%s (QObject %p)", wt->_info->className(), qobj);
303 return PyString_FromFormat("%s (QObject %p)", wrapper->_info->className(), qobj);
304 304 }
305 305 }
306 306
307 static PyObject * PythonQtWrapper_repr(PyObject * obj)
307 static PyObject * PythonQtInstanceWrapper_repr(PyObject * obj)
308 308 {
309 PythonQtWrapper* wt = (PythonQtWrapper*)obj;
310 QObject *qobj = wt->_obj;
311 if (wt->_wrappedPtr) {
312 QString str = PythonQtConv::CPPObjectToString(wt->_info->metaTypeId(), wt->_wrappedPtr);
309 PythonQtInstanceWrapper* wrapper = (PythonQtInstanceWrapper*)obj;
310 QObject *qobj = wrapper->_obj;
311 if (wrapper->_wrappedPtr) {
312 QString str = PythonQtConv::CPPObjectToString(wrapper->_info->metaTypeId(), wrapper->_wrappedPtr);
313 313 if (!str.isEmpty()) {
314 return PyString_FromFormat("%s(%s, %p)", QMetaType::typeName(wt->_info->metaTypeId()), str.toLatin1().constData(), wt->_wrappedPtr);
314 return PyString_FromFormat("%s(%s, %p)", QMetaType::typeName(wrapper->_info->metaTypeId()), str.toLatin1().constData(), wrapper->_wrappedPtr);
315 315 } else
316 if (wt->_obj) {
317 return PyString_FromFormat("%s (C++ Object %p wrapped by %s %p))", wt->_info->className(), wt->_wrappedPtr, wt->_obj->metaObject()->className(), qobj);
316 if (wrapper->_obj) {
317 return PyString_FromFormat("%s (C++ Object %p wrapped by %s %p))", wrapper->_info->className(), wrapper->_wrappedPtr, wrapper->_obj->metaObject()->className(), qobj);
318 318 } else {
319 return PyString_FromFormat("%s (C++ Object %p)", wt->_info->className(), wt->_wrappedPtr);
319 return PyString_FromFormat("%s (C++ Object %p)", wrapper->_info->className(), wrapper->_wrappedPtr);
320 320 }
321 321 } else {
322 return PyString_FromFormat("%s (QObject %p)", wt->_info->className(), qobj);
322 return PyString_FromFormat("%s (QObject %p)", wrapper->_info->className(), qobj);
323 323 }
324 324 }
325 325
326 static int PythonQtWrapper_compare(PyObject * obj1, PyObject * obj2)
326 static int PythonQtInstanceWrapper_compare(PyObject * obj1, PyObject * obj2)
327 327 {
328 if (obj1->ob_type == &PythonQtWrapper_Type &&
329 obj2->ob_type == &PythonQtWrapper_Type) {
328 if (obj1->ob_type == &PythonQtInstanceWrapper_Type &&
329 obj2->ob_type == &PythonQtInstanceWrapper_Type) {
330 330
331 PythonQtWrapper* w1 = (PythonQtWrapper*)obj1;
332 PythonQtWrapper* w2 = (PythonQtWrapper*)obj2;
331 PythonQtInstanceWrapper* w1 = (PythonQtInstanceWrapper*)obj1;
332 PythonQtInstanceWrapper* w2 = (PythonQtInstanceWrapper*)obj2;
333 333 // check pointers directly first:
334 334 if (w1->_wrappedPtr != NULL) {
335 335 if (w1->_wrappedPtr == w2->_wrappedPtr) {
336 336 return 0;
337 337 }
338 338 } else if (w1->_obj == w2->_obj) {
339 339 return 0;
340 340 }
341 341 const char* class1 = w1->_info->className();
342 342 const char* class2 = w2->_info->className();
343 343 if (strcmp(class1, class2) == 0) {
344 344 // same class names, so we can try the operator_equal
345 345 PythonQtMemberInfo info = w1->_info->member("operator_equal");
346 346 if (info._type == PythonQtMemberInfo::Slot) {
347 347 bool result = false;
348 348 void* obj1 = w1->_wrappedPtr;
349 349 if (!obj1) {
350 350 obj1 = w1->_obj;
351 351 }
352 352 if (!obj1) { return -1; }
353 353 void* obj2 = w2->_wrappedPtr;
354 354 if (!obj2) {
355 355 obj2 = w2->_obj;
356 356 }
357 357 if (!obj2) { return -1; }
358 358 if (info._slot->isInstanceDecorator()) {
359 359 // call on decorator QObject
360 360 void* args[3];
361 361 args[0] = &result;
362 362 args[1] = &obj1; // this is a pointer, so it needs a pointer to a pointer
363 363 args[2] = obj2; // this is a reference, so it needs the direct pointer
364 364 info._slot->decorator()->qt_metacall(QMetaObject::InvokeMetaMethod, info._slot->slotIndex(), args);
365 365 return result?0:-1;
366 366 } else {
367 367 // call directly on QObject
368 368 if (w1->_obj && w2->_obj) {
369 369 void* args[2];
370 370 args[0] = &result;
371 371 args[2] = obj2; // this is a reference, so it needs the direct pointer
372 372 w1->_obj->qt_metacall(QMetaObject::InvokeMetaMethod, info._slot->slotIndex(), args);
373 373 }
374 374 }
375 375 }
376 376 }
377 377 }
378 378 return -1;
379 379 }
380 380
381 static int PythonQtWrapper_nonzero(PyObject *obj)
381 static int PythonQtInstanceWrapper_nonzero(PyObject *obj)
382 382 {
383 PythonQtWrapper* wt = (PythonQtWrapper*)obj;
384 return (wt->_wrappedPtr == NULL && wt->_obj == NULL)?0:1;
383 PythonQtInstanceWrapper* wrapper = (PythonQtInstanceWrapper*)obj;
384 return (wrapper->_wrappedPtr == NULL && wrapper->_obj == NULL)?0:1;
385 385 }
386 386
387 387
388 static long PythonQtWrapper_hash(PythonQtWrapper *obj)
388 static long PythonQtInstanceWrapper_hash(PythonQtInstanceWrapper *obj)
389 389 {
390 390 if (obj->_wrappedPtr != NULL) {
391 391 return reinterpret_cast<long>(obj->_wrappedPtr);
392 392 } else {
393 393 QObject* qobj = obj->_obj; // get pointer from QPointer wrapper
394 394 return reinterpret_cast<long>(qobj);
395 395 }
396 396 }
397 397
398 398
399 399
400 400 // we override nb_nonzero, so that one can do 'if' expressions to test for a NULL ptr
401 static PyNumberMethods PythonQtWrapper_as_number = {
401 static PyNumberMethods PythonQtInstanceWrapper_as_number = {
402 402 0, /* nb_add */
403 403 0, /* nb_subtract */
404 404 0, /* nb_multiply */
405 405 0, /* nb_divide */
406 406 0, /* nb_remainder */
407 407 0, /* nb_divmod */
408 408 0, /* nb_power */
409 409 0, /* nb_negative */
410 410 0, /* nb_positive */
411 411 0, /* nb_absolute */
412 PythonQtWrapper_nonzero, /* nb_nonzero */
412 PythonQtInstanceWrapper_nonzero, /* nb_nonzero */
413 413 0, /* nb_invert */
414 414 0, /* nb_lshift */
415 415 0, /* nb_rshift */
416 416 0, /* nb_and */
417 417 0, /* nb_xor */
418 418 0, /* nb_or */
419 419 0, /* nb_coerce */
420 420 0, /* nb_int */
421 421 0, /* nb_long */
422 422 0, /* nb_float */
423 423 0, /* nb_oct */
424 424 0, /* nb_hex */
425 425 0, /* nb_inplace_add */
426 426 0, /* nb_inplace_subtract */
427 427 0, /* nb_inplace_multiply */
428 428 0, /* nb_inplace_divide */
429 429 0, /* nb_inplace_remainder */
430 430 0, /* nb_inplace_power */
431 431 0, /* nb_inplace_lshift */
432 432 0, /* nb_inplace_rshift */
433 433 0, /* nb_inplace_and */
434 434 0, /* nb_inplace_xor */
435 435 0, /* nb_inplace_or */
436 436 0, /* nb_floor_divide */
437 437 0, /* nb_true_divide */
438 438 0, /* nb_inplace_floor_divide */
439 439 0, /* nb_inplace_true_divide */
440 440 };
441 441
442 PyTypeObject PythonQtWrapper_Type = {
442 PyTypeObject PythonQtInstanceWrapper_Type = {
443 443 PyObject_HEAD_INIT(NULL)
444 444 0, /*ob_size*/
445 "PythonQt.PythonQtWrapper", /*tp_name*/
446 sizeof(PythonQtWrapper), /*tp_basicsize*/
445 "PythonQt.PythonQtInstanceWrapper", /*tp_name*/
446 sizeof(PythonQtInstanceWrapper), /*tp_basicsize*/
447 447 0, /*tp_itemsize*/
448 (destructor)PythonQtWrapper_dealloc, /*tp_dealloc*/
448 (destructor)PythonQtInstanceWrapper_dealloc, /*tp_dealloc*/
449 449 0, /*tp_print*/
450 450 0, /*tp_getattr*/
451 451 0, /*tp_setattr*/
452 PythonQtWrapper_compare, /*tp_compare*/
453 PythonQtWrapper_repr, /*tp_repr*/
454 &PythonQtWrapper_as_number, /*tp_as_number*/
452 PythonQtInstanceWrapper_compare, /*tp_compare*/
453 PythonQtInstanceWrapper_repr, /*tp_repr*/
454 &PythonQtInstanceWrapper_as_number, /*tp_as_number*/
455 455 0, /*tp_as_sequence*/
456 456 0, /*tp_as_mapping*/
457 (hashfunc)PythonQtWrapper_hash, /*tp_hash */
457 (hashfunc)PythonQtInstanceWrapper_hash, /*tp_hash */
458 458 0, /*tp_call*/
459 PythonQtWrapper_str, /*tp_str*/
460 PythonQtWrapper_getattro, /*tp_getattro*/
461 PythonQtWrapper_setattro, /*tp_setattro*/
459 PythonQtInstanceWrapper_str, /*tp_str*/
460 PythonQtInstanceWrapper_getattro, /*tp_getattro*/
461 PythonQtInstanceWrapper_setattro, /*tp_setattro*/
462 462 0, /*tp_as_buffer*/
463 463 Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE, /*tp_flags*/
464 "PythonQtWrapper object", /* tp_doc */
464 "PythonQtInstanceWrapper object", /* tp_doc */
465 465 0, /* tp_traverse */
466 466 0, /* tp_clear */
467 467 0, /* tp_richcompare */
468 468 0, /* tp_weaklistoffset */
469 469 0, /* tp_iter */
470 470 0, /* tp_iternext */
471 471 0, /* tp_methods */
472 472 0, /* tp_members */
473 473 0, /* tp_getset */
474 474 0, /* tp_base */
475 475 0, /* tp_dict */
476 476 0, /* tp_descr_get */
477 477 0, /* tp_descr_set */
478 478 0, /* tp_dictoffset */
479 (initproc)PythonQtWrapper_init, /* tp_init */
479 (initproc)PythonQtInstanceWrapper_init, /* tp_init */
480 480 0, /* tp_alloc */
481 PythonQtWrapper_new, /* tp_new */
481 PythonQtInstanceWrapper_new, /* tp_new */
482 482 };
483 483
484 484 //-------------------------------------------------------
485 485
@@ -1,92 +1,92
1 1 #ifndef _PYTHONQTWRAPPER_H
2 2 #define _PYTHONQTWRAPPER_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 // \file PythonQtWrapper.h
38 // \file PythonQtInstanceWrapper.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 <Python.h>
46 46
47 47 #include "PythonQtSystem.h"
48 48 #include <QPointer>
49 49
50 50 #include "structmember.h"
51 51 #include "methodobject.h"
52 52 #include "compile.h"
53 53 #include "eval.h"
54 54
55 55 class PythonQtClassInfo;
56 56 class QObject;
57 57
58 extern PYTHONQT_EXPORT PyTypeObject PythonQtWrapper_Type;
58 extern PYTHONQT_EXPORT PyTypeObject PythonQtInstanceWrapper_Type;
59 59
60 60 //---------------------------------------------------------------
61 61 //! a Python wrapper object for Qt objects and C++ objects (that are themselves wrapped by wrapper QObjects)
62 62 typedef struct {
63 63 PyObject_HEAD
64 64
65 65 //! set the QObject pointer
66 66 void setQObject(QObject* object) {
67 67 _obj = object;
68 68 _objPointerCopy = object;
69 69 }
70 70
71 71 //! pointer to the wrapped Qt object or if _wrappedPtr is set, the Qt object that wraps the C++ Ptr
72 72 QPointer<QObject> _obj;
73 73 //! a copy of the _obj pointer, which is required because the wrapper needs to
74 74 //! deregister itself via the _obj pointer, even when the QPointer<QObject> object was destroyed
75 75 void* _objPointerCopy;
76 76
77 77 //! optional C++ object Ptr that is wrapped by the above _obj
78 78 void* _wrappedPtr;
79 79
80 80 //! the class information, this is set even if the _obj or _wrappedPtr is NULL to support typed NULL pointers
81 81 PythonQtClassInfo* _info;
82 82
83 83 //! flag that stores if the object is owned by pythonQt
84 84 bool _ownedByPythonQt;
85 85
86 86 //! stores that the owned object should be destroyed using QMetaType::destroy()
87 87 bool _useQMetaTypeDestroy;
88 88
89 } PythonQtWrapper;
89 } PythonQtInstanceWrapper;
90 90
91 91
92 92 #endif No newline at end of file
@@ -1,445 +1,445
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 PythonQtSlot.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 "PythonQt.h"
43 43 #include "PythonQtSlot.h"
44 #include "PythonQtWrapper.h"
44 #include "PythonQtInstanceWrapper.h"
45 45 #include "PythonQtClassInfo.h"
46 46 #include "PythonQtMisc.h"
47 47 #include "PythonQtConversion.h"
48 48 #include <iostream>
49 49
50 50 #define PYTHONQT_MAX_ARGS 32
51 51
52 52
53 53 PyObject* PythonQtCallSlot(QObject* objectToCall, PyObject* args, bool strict, PythonQtSlotInfo* info, void* firstArgument)
54 54 {
55 55 static unsigned int recursiveEntry = 0;
56 56
57 57 // store the current storage position, so that we can get back to this state after a slot is called
58 58 // (do this locally, so that we have all positions on the stack
59 59 PythonQtValueStoragePosition globalValueStoragePos;
60 60 PythonQtValueStoragePosition globalPtrStoragePos;
61 61 PythonQtValueStoragePosition globalVariantStoragePos;
62 62 PythonQtConv::global_valueStorage.getPos(globalValueStoragePos);
63 63 PythonQtConv::global_ptrStorage.getPos(globalPtrStoragePos);
64 64 PythonQtConv::global_variantStorage.getPos(globalVariantStoragePos);
65 65
66 66 recursiveEntry++;
67 67
68 68 // the arguments that are passed to qt_metacall
69 69 void* argList[PYTHONQT_MAX_ARGS];
70 70 PyObject* result = NULL;
71 71 int argc = info->parameterCount();
72 72 const QList<PythonQtSlotInfo::ParameterInfo>& params = info->parameters();
73 73
74 74 bool returnValueIsEnum = false;
75 75 const PythonQtSlotInfo::ParameterInfo& returnValueParam = params.at(0);
76 76 // set return argument to NULL
77 77 argList[0] = NULL;
78 78
79 79 if (returnValueParam.typeId != QMetaType::Void) {
80 80 // extra handling of enum return value
81 81 if (!returnValueParam.isPointer && returnValueParam.typeId == PythonQtMethodInfo::Unknown) {
82 82 returnValueIsEnum = PythonQt::priv()->isEnumType(objectToCall->metaObject(), returnValueParam.name);
83 83 if (returnValueIsEnum) {
84 84 // create enum return value
85 85 PythonQtValueStorage_ADD_VALUE(PythonQtConv::global_valueStorage, long, 0, argList[0]);
86 86 }
87 87 }
88 88 if (argList[0]==NULL) {
89 89 // create empty default value for the return value
90 90 argList[0] = PythonQtConv::CreateQtReturnValue(returnValueParam);
91 91 }
92 92 }
93 93
94 94 const QMetaObject* meta = objectToCall?objectToCall->metaObject():NULL;
95 95 bool ok = true;
96 96 bool skipFirst = false;
97 97 if (info->isInstanceDecorator()) {
98 98 skipFirst = true;
99 99 if (!firstArgument) {
100 100 argList[1] = &objectToCall;
101 101 } else {
102 102 // for the variant call we take the ptr to the variant data, for decorators on CPP objects, we take the cpp ptr
103 103 argList[1] = &firstArgument;
104 104 }
105 105 if (ok) {
106 106 for (int i = 2; i<argc && ok; i++) {
107 107 const PythonQtSlotInfo::ParameterInfo& param = params.at(i);
108 108 //std::cout << param.name.data() << " " << param.typeId << (param.isPointer?"*":"") << (param.isConst?" const":"") << std::endl;
109 109 argList[i] = PythonQtConv::ConvertPythonToQt(param, PyTuple_GET_ITEM(args, i-2), strict, meta);
110 110 if (argList[i]==NULL) {
111 111 ok = false;
112 112 break;
113 113 }
114 114 }
115 115 }
116 116 } else {
117 117 for (int i = 1; i<argc && ok; i++) {
118 118 const PythonQtSlotInfo::ParameterInfo& param = params.at(i);
119 119 //std::cout << param.name.data() << " " << param.typeId << (param.isPointer?"*":"") << (param.isConst?" const":"") << std::endl;
120 120 argList[i] = PythonQtConv::ConvertPythonToQt(param, PyTuple_GET_ITEM(args, i-1), strict, meta);
121 121 if (argList[i]==NULL) {
122 122 ok = false;
123 123 break;
124 124 }
125 125 }
126 126 }
127 127
128 128 if (ok) {
129 129 (info->decorator()?info->decorator():objectToCall)->qt_metacall(QMetaObject::InvokeMetaMethod, info->slotIndex(), argList);
130 130
131 131 if (argList[0] || returnValueParam.typeId == QMetaType::Void) {
132 132 if (!returnValueIsEnum) {
133 133 result = PythonQtConv::ConvertQtValueToPython(returnValueParam, argList[0]);
134 134 } else {
135 135 result = PyInt_FromLong(*((unsigned int*)argList[0]));
136 136 }
137 137 } else {
138 138 QString e = QString("Called ") + info->fullSignature(skipFirst) + ", return type is ignored because it is unknown to PythonQt.";
139 139 PyErr_SetString(PyExc_ValueError, e.toLatin1().data());
140 140 result = NULL;
141 141 }
142 142 }
143 143 recursiveEntry--;
144 144
145 145 // reset the parameter storage position to the stored pos to "pop" the parameter stack
146 146 PythonQtConv::global_valueStorage.setPos(globalValueStoragePos);
147 147 PythonQtConv::global_ptrStorage.setPos(globalPtrStoragePos);
148 148 PythonQtConv::global_variantStorage.setPos(globalVariantStoragePos);
149 149
150 150 // NOTE: it is important to only return here, otherwise the stack will not be popped!!!
151 151 return result;
152 152 }
153 153
154 154 //-----------------------------------------------------------------------------------
155 155
156 156 static PythonQtSlotFunctionObject *pythonqtslot_free_list = NULL;
157 157
158 158 PyObject *PythonQtSlotFunction_Call(PyObject *func, PyObject *args, PyObject *kw)
159 159 {
160 160 PythonQtSlotFunctionObject* f = (PythonQtSlotFunctionObject*)func;
161 161 PythonQtSlotInfo* info = f->m_ml;
162 if (f->m_self->ob_type == &PythonQtWrapper_Type) {
163 PythonQtWrapper* self = (PythonQtWrapper*) f->m_self;
162 if (f->m_self->ob_type == &PythonQtInstanceWrapper_Type) {
163 PythonQtInstanceWrapper* self = (PythonQtInstanceWrapper*) f->m_self;
164 164 return PythonQtSlotFunction_CallImpl(self->_obj, info, args, kw, self->_wrappedPtr);
165 } else if (f->m_self->ob_type == &PythonQtMetaObjectWrapper_Type) {
165 } else if (f->m_self->ob_type == &PythonQtClassWrapper_Type) {
166 166 return PythonQtSlotFunction_CallImpl(NULL, info, args, kw);
167 167 } else {
168 168 return NULL;
169 169 }
170 170 }
171 171
172 172 PyObject *PythonQtSlotFunction_CallImpl(QObject* objectToCall, PythonQtSlotInfo* info, PyObject *args, PyObject * /*kw*/, void* firstArg)
173 173 {
174 174 int argc = PyTuple_Size(args);
175 175
176 176 #ifdef PYTHONQT_DEBUG
177 177 std::cout << "called " << info->metaMethod()->typeName() << " " << info->metaMethod()->signature() << std::endl;
178 178 #endif
179 179
180 180 PyObject* r = NULL;
181 181
182 182 if (info->nextInfo()) {
183 183 // overloaded slot call, try on all slots with strict conversion first
184 184 PythonQtSlotInfo* i = info;
185 185 while (i && r==NULL) {
186 186 bool skipFirst = i->isInstanceDecorator();
187 187 if (i->parameterCount()-1-(skipFirst?1:0) == argc) {
188 188 PyErr_Clear();
189 189 r = PythonQtCallSlot(objectToCall, args, true, i, firstArg);
190 190 if (PyErr_Occurred()) break;
191 191 }
192 192 i = i->nextInfo();
193 193 }
194 194 if (!r) {
195 195 // try on all slots with non-strict conversion
196 196 i = info;
197 197 while (i && r==NULL) {
198 198 bool skipFirst = i->isInstanceDecorator();
199 199 if (i->parameterCount()-1-(skipFirst?1:0) == argc) {
200 200 PyErr_Clear();
201 201 r = PythonQtCallSlot(objectToCall, args, false, i, firstArg);
202 202 if (PyErr_Occurred()) break;
203 203 }
204 204 i = i->nextInfo();
205 205 }
206 206 }
207 207 if (r==NULL && !PyErr_Occurred()) {
208 208 QString e = QString("Could not find matching overload for given arguments:\n" + PythonQtConv::PyObjGetString(args) + "\n The following slots are available:\n");
209 209 PythonQtSlotInfo* i = info;
210 210 while (i) {
211 211 bool skipFirst = i->isInstanceDecorator();
212 212 e += QString(i->fullSignature(skipFirst)) + "\n";
213 213 i = i->nextInfo();
214 214 }
215 215 PyErr_SetString(PyExc_ValueError, e.toLatin1().data());
216 216 }
217 217 } else {
218 218 // simple (non-overloaded) slot call
219 219 bool skipFirst = info->isInstanceDecorator();
220 220 if (info->parameterCount()-1-(skipFirst?1:0) == argc) {
221 221 PyErr_Clear();
222 222 r = PythonQtCallSlot(objectToCall, args, false, info, firstArg);
223 223 if (r==NULL && !PyErr_Occurred()) {
224 224 QString e = QString("Called ") + info->fullSignature(skipFirst) + " with wrong arguments: " + PythonQtConv::PyObjGetString(args);
225 225 PyErr_SetString(PyExc_ValueError, e.toLatin1().data());
226 226 }
227 227 } else {
228 228 QString e = QString("Called ") + info->fullSignature(skipFirst) + " with wrong number of arguments: " + PythonQtConv::PyObjGetString(args);
229 229 PyErr_SetString(PyExc_ValueError, e.toLatin1().data());
230 230 }
231 231 }
232 232
233 233 return r;
234 234 }
235 235
236 236 PyObject *
237 237 PythonQtSlotFunction_New(PythonQtSlotInfo *ml, PyObject *self, PyObject *module)
238 238 {
239 239 PythonQtSlotFunctionObject *op;
240 240 op = pythonqtslot_free_list;
241 241 if (op != NULL) {
242 242 pythonqtslot_free_list = (PythonQtSlotFunctionObject *)(op->m_self);
243 243 PyObject_INIT(op, &PythonQtSlotFunction_Type);
244 244 }
245 245 else {
246 246 op = PyObject_GC_New(PythonQtSlotFunctionObject, &PythonQtSlotFunction_Type);
247 247 if (op == NULL)
248 248 return NULL;
249 249 }
250 250 op->m_ml = ml;
251 251 Py_XINCREF(self);
252 252 op->m_self = self;
253 253 Py_XINCREF(module);
254 254 op->m_module = module;
255 255 PyObject_GC_Track(op);
256 256 return (PyObject *)op;
257 257 }
258 258
259 259 PythonQtSlotInfo*
260 260 PythonQtSlotFunction_GetSlotInfo(PyObject *op)
261 261 {
262 262 if (!PythonQtSlotFunction_Check(op)) {
263 263 PyErr_BadInternalCall();
264 264 return NULL;
265 265 }
266 266 return ((PythonQtSlotFunctionObject *)op) -> m_ml;
267 267 }
268 268
269 269 PyObject *
270 270 PythonQtSlotFunction_GetSelf(PyObject *op)
271 271 {
272 272 if (!PythonQtSlotFunction_Check(op)) {
273 273 PyErr_BadInternalCall();
274 274 return NULL;
275 275 }
276 276 return ((PythonQtSlotFunctionObject *)op) -> m_self;
277 277 }
278 278
279 279 /* Methods (the standard built-in methods, that is) */
280 280
281 281 static void
282 282 meth_dealloc(PythonQtSlotFunctionObject *m)
283 283 {
284 284 PyObject_GC_UnTrack(m);
285 285 Py_XDECREF(m->m_self);
286 286 Py_XDECREF(m->m_module);
287 287 m->m_self = (PyObject *)pythonqtslot_free_list;
288 288 pythonqtslot_free_list = m;
289 289 }
290 290
291 291 static PyObject *
292 292 meth_get__doc__(PythonQtSlotFunctionObject * /*m*/, void * /*closure*/)
293 293 {
294 294 Py_INCREF(Py_None);
295 295 return Py_None;
296 296 }
297 297
298 298 static PyObject *
299 299 meth_get__name__(PythonQtSlotFunctionObject *m, void * /*closure*/)
300 300 {
301 301 return PyString_FromString(m->m_ml->metaMethod()->signature());
302 302 }
303 303
304 304 static int
305 305 meth_traverse(PythonQtSlotFunctionObject *m, visitproc visit, void *arg)
306 306 {
307 307 int err;
308 308 if (m->m_self != NULL) {
309 309 err = visit(m->m_self, arg);
310 310 if (err)
311 311 return err;
312 312 }
313 313 if (m->m_module != NULL) {
314 314 err = visit(m->m_module, arg);
315 315 if (err)
316 316 return err;
317 317 }
318 318 return 0;
319 319 }
320 320
321 321 static PyObject *
322 322 meth_get__self__(PythonQtSlotFunctionObject *m, void * /*closure*/)
323 323 {
324 324 PyObject *self;
325 325 if (PyEval_GetRestricted()) {
326 326 PyErr_SetString(PyExc_RuntimeError,
327 327 "method.__self__ not accessible in restricted mode");
328 328 return NULL;
329 329 }
330 330 self = m->m_self;
331 331 if (self == NULL)
332 332 self = Py_None;
333 333 Py_INCREF(self);
334 334 return self;
335 335 }
336 336
337 337 static PyGetSetDef meth_getsets [] = {
338 338 {"__doc__", (getter)meth_get__doc__, NULL, NULL},
339 339 {"__name__", (getter)meth_get__name__, NULL, NULL},
340 340 {"__self__", (getter)meth_get__self__, NULL, NULL},
341 341 {NULL, NULL, NULL,NULL},
342 342 };
343 343
344 344 #if PY_MAJOR_VERSION == 2 && PY_MINOR_VERSION < 6
345 345 #define PY_WRITE_RESTRICTED WRITE_RESTRICTED
346 346 #endif
347 347
348 348 #define OFF(x) offsetof(PythonQtSlotFunctionObject, x)
349 349
350 350 static PyMemberDef meth_members[] = {
351 351 {"__module__", T_OBJECT, OFF(m_module), PY_WRITE_RESTRICTED},
352 352 {NULL}
353 353 };
354 354
355 355 static PyObject *
356 356 meth_repr(PythonQtSlotFunctionObject *m)
357 357 {
358 358 return PyString_FromFormat("<built-in qt slot %s of %s object at %p>",
359 359 m->m_ml->metaMethod()->signature(),
360 360 m->m_self->ob_type->tp_name,
361 361 m->m_self);
362 362 }
363 363
364 364 static int
365 365 meth_compare(PythonQtSlotFunctionObject *a, PythonQtSlotFunctionObject *b)
366 366 {
367 367 if (a->m_self != b->m_self)
368 368 return (a->m_self < b->m_self) ? -1 : 1;
369 369 if (a->m_ml == b->m_ml)
370 370 return 0;
371 371 if (strcmp(a->m_ml->metaMethod()->signature(), b->m_ml->metaMethod()->signature()) < 0)
372 372 return -1;
373 373 else
374 374 return 1;
375 375 }
376 376
377 377 static long
378 378 meth_hash(PythonQtSlotFunctionObject *a)
379 379 {
380 380 long x,y;
381 381 if (a->m_self == NULL)
382 382 x = 0;
383 383 else {
384 384 x = PyObject_Hash(a->m_self);
385 385 if (x == -1)
386 386 return -1;
387 387 }
388 388 y = _Py_HashPointer((void*)(a->m_ml));
389 389 if (y == -1)
390 390 return -1;
391 391 x ^= y;
392 392 if (x == -1)
393 393 x = -2;
394 394 return x;
395 395 }
396 396
397 397
398 398 PyTypeObject PythonQtSlotFunction_Type = {
399 399 PyObject_HEAD_INIT(&PyType_Type)
400 400 0,
401 401 "builtin_qt_slot",
402 402 sizeof(PythonQtSlotFunctionObject),
403 403 0,
404 404 (destructor)meth_dealloc, /* tp_dealloc */
405 405 0, /* tp_print */
406 406 0, /* tp_getattr */
407 407 0, /* tp_setattr */
408 408 (cmpfunc)meth_compare, /* tp_compare */
409 409 (reprfunc)meth_repr, /* tp_repr */
410 410 0, /* tp_as_number */
411 411 0, /* tp_as_sequence */
412 412 0, /* tp_as_mapping */
413 413 (hashfunc)meth_hash, /* tp_hash */
414 414 PythonQtSlotFunction_Call, /* tp_call */
415 415 0, /* tp_str */
416 416 PyObject_GenericGetAttr, /* tp_getattro */
417 417 0, /* tp_setattro */
418 418 0, /* tp_as_buffer */
419 419 Py_TPFLAGS_DEFAULT | Py_TPFLAGS_HAVE_GC,/* tp_flags */
420 420 0, /* tp_doc */
421 421 (traverseproc)meth_traverse, /* tp_traverse */
422 422 0, /* tp_clear */
423 423 0, /* tp_richcompare */
424 424 0, /* tp_weaklistoffset */
425 425 0, /* tp_iter */
426 426 0, /* tp_iternext */
427 427 0, /* tp_methods */
428 428 meth_members, /* tp_members */
429 429 meth_getsets, /* tp_getset */
430 430 0, /* tp_base */
431 431 0, /* tp_dict */
432 432 };
433 433
434 434 /* Clear out the free list */
435 435
436 436 void
437 437 PythonQtSlotFunction_Fini(void)
438 438 {
439 439 while (pythonqtslot_free_list) {
440 440 PythonQtSlotFunctionObject *v = pythonqtslot_free_list;
441 441 pythonqtslot_free_list = (PythonQtSlotFunctionObject *)(v->m_self);
442 442 PyObject_GC_Del(v);
443 443 }
444 444 }
445 445
@@ -1,113 +1,113
1 1 DEFINES += PYTHONQT_EXPORTS
2 2
3 3 HEADERS += \
4 4 $$PWD/PythonQt.h \
5 5 $$PWD/PythonQtStdDecorators.h \
6 6 $$PWD/PythonQtClassInfo.h \
7 7 $$PWD/PythonQtImporter.h \
8 8 $$PWD/PythonQtObjectPtr.h \
9 9 $$PWD/PythonQtSlot.h \
10 10 $$PWD/PythonQtStdOut.h \
11 11 $$PWD/PythonQtMisc.h \
12 12 $$PWD/PythonQtMethodInfo.h \
13 13 $$PWD/PythonQtImportFileInterface.h \
14 14 $$PWD/PythonQtConversion.h \
15 15 $$PWD/PythonQtSignalReceiver.h \
16 $$PWD/PythonQtWrapper.h \
17 $$PWD/PythonQtMetaObjectWrapper.h \
16 $$PWD/PythonQtInstanceWrapper.h \
17 $$PWD/PythonQtClassWrapper.h \
18 18 $$PWD/PythonQtCppWrapperFactory.h \
19 19 $$PWD/PythonQtVariants.h \
20 20 $$PWD/PythonQtQFileImporter.h \
21 21 $$PWD/PythonQtQFileImporter.h \
22 22 $$PWD/gui/PythonQtScriptingConsole.h \
23 23 $$PWD/PythonQtSystem.h \
24 24 \
25 25 $$PWD/../generated_cpp/com_trolltech_qt_core/PythonQtWrapper_Qt.h \
26 26 $$PWD/../generated_cpp/com_trolltech_qt_core/PythonQtWrapper_QBitArray.h \
27 27 $$PWD/../generated_cpp/com_trolltech_qt_core/PythonQtWrapper_QDate.h \
28 28 $$PWD/../generated_cpp/com_trolltech_qt_core/PythonQtWrapper_QTime.h \
29 29 $$PWD/../generated_cpp/com_trolltech_qt_core/PythonQtWrapper_QDateTime.h \
30 30 $$PWD/../generated_cpp/com_trolltech_qt_core/PythonQtWrapper_QUrl.h \
31 31 $$PWD/../generated_cpp/com_trolltech_qt_core/PythonQtWrapper_QLocale.h \
32 32 $$PWD/../generated_cpp/com_trolltech_qt_core/PythonQtWrapper_QRect.h \
33 33 $$PWD/../generated_cpp/com_trolltech_qt_core/PythonQtWrapper_QRectF.h \
34 34 $$PWD/../generated_cpp/com_trolltech_qt_core/PythonQtWrapper_QSize.h \
35 35 $$PWD/../generated_cpp/com_trolltech_qt_core/PythonQtWrapper_QSizeF.h \
36 36 $$PWD/../generated_cpp/com_trolltech_qt_core/PythonQtWrapper_QLine.h \
37 37 $$PWD/../generated_cpp/com_trolltech_qt_core/PythonQtWrapper_QLineF.h \
38 38 $$PWD/../generated_cpp/com_trolltech_qt_core/PythonQtWrapper_QPoint.h \
39 39 $$PWD/../generated_cpp/com_trolltech_qt_core/PythonQtWrapper_QPointF.h \
40 40 $$PWD/../generated_cpp/com_trolltech_qt_core/PythonQtWrapper_QRegExp.h \
41 41 \
42 42 $$PWD/../generated_cpp/com_trolltech_qt_gui/PythonQtWrapper_QFont.h \
43 43 $$PWD/../generated_cpp/com_trolltech_qt_gui/PythonQtWrapper_QPixmap.h \
44 44 $$PWD/../generated_cpp/com_trolltech_qt_gui/PythonQtWrapper_QBrush.h \
45 45 $$PWD/../generated_cpp/com_trolltech_qt_gui/PythonQtWrapper_QColor.h \
46 46 $$PWD/../generated_cpp/com_trolltech_qt_gui/PythonQtWrapper_QPalette.h \
47 47 $$PWD/../generated_cpp/com_trolltech_qt_gui/PythonQtWrapper_QIcon.h \
48 48 $$PWD/../generated_cpp/com_trolltech_qt_gui/PythonQtWrapper_QImage.h \
49 49 $$PWD/../generated_cpp/com_trolltech_qt_gui/PythonQtWrapper_QPolygon.h \
50 50 $$PWD/../generated_cpp/com_trolltech_qt_gui/PythonQtWrapper_QRegion.h \
51 51 $$PWD/../generated_cpp/com_trolltech_qt_gui/PythonQtWrapper_QBitmap.h \
52 52 $$PWD/../generated_cpp/com_trolltech_qt_gui/PythonQtWrapper_QCursor.h \
53 53 $$PWD/../generated_cpp/com_trolltech_qt_gui/PythonQtWrapper_QSizePolicy.h \
54 54 $$PWD/../generated_cpp/com_trolltech_qt_gui/PythonQtWrapper_QKeySequence.h \
55 55 $$PWD/../generated_cpp/com_trolltech_qt_gui/PythonQtWrapper_QPen.h \
56 56 $$PWD/../generated_cpp/com_trolltech_qt_gui/PythonQtWrapper_QTextLength.h \
57 57 $$PWD/../generated_cpp/com_trolltech_qt_gui/PythonQtWrapper_QTextFormat.h \
58 58 $$PWD/../generated_cpp/com_trolltech_qt_gui/PythonQtWrapper_QMatrix.h
59 59
60 60
61 61 SOURCES += \
62 62 $$PWD/PythonQtStdDecorators.cpp \
63 63 $$PWD/PythonQt.cpp \
64 64 $$PWD/PythonQtClassInfo.cpp \
65 65 $$PWD/PythonQtImporter.cpp \
66 66 $$PWD/PythonQtObjectPtr.cpp \
67 67 $$PWD/PythonQtStdOut.cpp \
68 68 $$PWD/PythonQtSlot.cpp \
69 69 $$PWD/PythonQtMisc.cpp \
70 70 $$PWD/PythonQtMethodInfo.cpp \
71 71 $$PWD/PythonQtConversion.cpp \
72 72 $$PWD/PythonQtSignalReceiver.cpp \
73 73 $$PWD/PythonQtVariants.cpp \
74 $$PWD/PythonQtWrapper.cpp \
75 $$PWD/PythonQtQFileImporter.cpp \
76 $$PWD/PythonQtMetaObjectWrapper.cpp \
74 $$PWD/PythonQtInstanceWrapper.cpp \
75 $$PWD/PythonQtQFileImporter.cpp \
76 $$PWD/PythonQtClassWrapper.cpp \
77 77 $$PWD/gui/PythonQtScriptingConsole.cpp \
78 78 \
79 79 $$PWD/../generated_cpp/com_trolltech_qt_core/PythonQtWrapper_Qt.cpp \
80 80 $$PWD/../generated_cpp/com_trolltech_qt_core/PythonQtWrapper_QBitArray.cpp \
81 81 $$PWD/../generated_cpp/com_trolltech_qt_core/PythonQtWrapper_QDate.cpp \
82 82 $$PWD/../generated_cpp/com_trolltech_qt_core/PythonQtWrapper_QTime.cpp \
83 83 $$PWD/../generated_cpp/com_trolltech_qt_core/PythonQtWrapper_QDateTime.cpp \
84 84 $$PWD/../generated_cpp/com_trolltech_qt_core/PythonQtWrapper_QUrl.cpp \
85 85 $$PWD/../generated_cpp/com_trolltech_qt_core/PythonQtWrapper_QLocale.cpp \
86 86 $$PWD/../generated_cpp/com_trolltech_qt_core/PythonQtWrapper_QRect.cpp \
87 87 $$PWD/../generated_cpp/com_trolltech_qt_core/PythonQtWrapper_QRectF.cpp \
88 88 $$PWD/../generated_cpp/com_trolltech_qt_core/PythonQtWrapper_QSize.cpp \
89 89 $$PWD/../generated_cpp/com_trolltech_qt_core/PythonQtWrapper_QSizeF.cpp \
90 90 $$PWD/../generated_cpp/com_trolltech_qt_core/PythonQtWrapper_QLine.cpp \
91 91 $$PWD/../generated_cpp/com_trolltech_qt_core/PythonQtWrapper_QLineF.cpp \
92 92 $$PWD/../generated_cpp/com_trolltech_qt_core/PythonQtWrapper_QPoint.cpp \
93 93 $$PWD/../generated_cpp/com_trolltech_qt_core/PythonQtWrapper_QPointF.cpp \
94 94 $$PWD/../generated_cpp/com_trolltech_qt_core/PythonQtWrapper_QRegExp.cpp \
95 95 \
96 96 $$PWD/../generated_cpp/com_trolltech_qt_gui/PythonQtWrapper_QFont.cpp \
97 97 $$PWD/../generated_cpp/com_trolltech_qt_gui/PythonQtWrapper_QPixmap.cpp \
98 98 $$PWD/../generated_cpp/com_trolltech_qt_gui/PythonQtWrapper_QBrush.cpp \
99 99 $$PWD/../generated_cpp/com_trolltech_qt_gui/PythonQtWrapper_QColor.cpp \
100 100 $$PWD/../generated_cpp/com_trolltech_qt_gui/PythonQtWrapper_QPalette.cpp \
101 101 $$PWD/../generated_cpp/com_trolltech_qt_gui/PythonQtWrapper_QIcon.cpp \
102 102 $$PWD/../generated_cpp/com_trolltech_qt_gui/PythonQtWrapper_QImage.cpp \
103 103 $$PWD/../generated_cpp/com_trolltech_qt_gui/PythonQtWrapper_QPolygon.cpp \
104 104 $$PWD/../generated_cpp/com_trolltech_qt_gui/PythonQtWrapper_QRegion.cpp \
105 105 $$PWD/../generated_cpp/com_trolltech_qt_gui/PythonQtWrapper_QBitmap.cpp \
106 106 $$PWD/../generated_cpp/com_trolltech_qt_gui/PythonQtWrapper_QCursor.cpp \
107 107 $$PWD/../generated_cpp/com_trolltech_qt_gui/PythonQtWrapper_QSizePolicy.cpp \
108 108 $$PWD/../generated_cpp/com_trolltech_qt_gui/PythonQtWrapper_QKeySequence.cpp \
109 109 $$PWD/../generated_cpp/com_trolltech_qt_gui/PythonQtWrapper_QPen.cpp \
110 110 $$PWD/../generated_cpp/com_trolltech_qt_gui/PythonQtWrapper_QTextLength.cpp \
111 111 $$PWD/../generated_cpp/com_trolltech_qt_gui/PythonQtWrapper_QTextFormat.cpp \
112 112 $$PWD/../generated_cpp/com_trolltech_qt_gui/PythonQtWrapper_QMatrix.cpp
113 113
@@ -1,18 +1,19
1 1 # --------- PythonQt profile -------------------
2 2 # Last changed by $Author: florian $
3 3 # $Id: PythonQt.pro 35381 2006-03-16 13:05:52Z florian $
4 4 # $Source$
5 5 # --------------------------------------------------
6 6
7 7 TARGET = PythonQt
8 8 TEMPLATE = lib
9 9
10 10
11 11 DESTDIR = ../lib
12 12
13 13 CONFIG += qt dll
14 CONFIG -= flat
14 15
15 16 include ( ../build/common.prf )
16 17 include ( ../build/python.prf )
17 18
18 19 include ( src.pri )
General Comments 0
You need to be logged in to leave comments. Login now