##// END OF EJS Templates
updated to upstream state in MeVisLab repository...
florianlink -
r157:78da86ccde11
parent child
Show More
@@ -245,6 +245,14 void PythonQtPrivate::registerClass(const QMetaObject* metaobject, const char* p
245 245 PythonQtClassInfo* parentInfo = lookupClassInfoAndCreateIfNotPresent(m->superClass()->className());
246 246 info->addParentClass(PythonQtClassInfo::ParentClassInfo(parentInfo));
247 247 }
248 } else if (first && module) {
249 // There is a wrapper already, but if we got a module, we want to place the wrapper into that module as well,
250 // since it might have been placed into "private" earlier on.
251 // If the wrapper was already added to module before, it is just readded, which does no harm.
252 PyObject* classWrapper = info->pythonQtClassWrapper();
253 // AddObject steals a reference, so we need to INCREF
254 Py_INCREF(classWrapper);
255 PyModule_AddObject(module, info->className(), classWrapper);
248 256 }
249 257 if (first) {
250 258 first = false;
@@ -913,6 +921,7 PythonQtPrivate::PythonQtPrivate()
913 921 _noLongerWrappedCB = NULL;
914 922 _wrappedCB = NULL;
915 923 _currentClassInfoForClassWrapperCreation = NULL;
924 _profilingCB = NULL;
916 925 }
917 926
918 927 void PythonQtPrivate::setupSharedLibrarySuffixes()
@@ -922,6 +931,14 void PythonQtPrivate::setupSharedLibrarySuffixes()
922 931 imp.setNewRef(PyImport_ImportModule("imp"));
923 932 int cExtensionCode = imp.getVariable("C_EXTENSION").toInt();
924 933 QVariant result = imp.call("get_suffixes");
934 #ifdef __linux
935 #ifdef _DEBUG
936 // First look for shared libraries with the '_d' suffix in debug mode on Linux.
937 // This is a workaround, because python does not append the '_d' suffix on Linux
938 // and would always load the release library otherwise.
939 _sharedLibrarySuffixes << "_d.so";
940 #endif
941 #endif
925 942 foreach (QVariant entry, result.toList()) {
926 943 QVariantList suffixEntry = entry.toList();
927 944 if (suffixEntry.count()==3) {
@@ -1066,6 +1083,10 void PythonQt::setQObjectNoLongerWrappedCallback(PythonQtQObjectNoLongerWrappedC
1066 1083 _p->_noLongerWrappedCB = cb;
1067 1084 }
1068 1085
1086 void PythonQt::setProfilingCallback(ProfilingCB* cb)
1087 {
1088 _p->_profilingCB = cb;
1089 }
1069 1090
1070 1091
1071 1092 static PyMethodDef PythonQtMethods[] = {
@@ -1194,6 +1215,13 PyObject* PythonQt::helpCalled(PythonQtClassInfo* info)
1194 1215 }
1195 1216 }
1196 1217
1218 void PythonQt::clearNotFoundCachedMembers()
1219 {
1220 foreach(PythonQtClassInfo* info, _p->_knownClassInfos) {
1221 info->clearNotFoundCachedMembers();
1222 }
1223 }
1224
1197 1225 void PythonQtPrivate::removeWrapperPointer(void* obj)
1198 1226 {
1199 1227 _wrappedObjects.remove(obj);
@@ -143,6 +143,16 public:
143 143
144 144 };
145 145
146 //! enum for profiling callback
147 enum ProfilingCallbackState {
148 Enter = 1,
149 Leave = 2
150 };
151
152 //! callback for profiling. className and methodName are only passed when state == Enter, otherwise
153 //! they are NULL.
154 typedef void ProfilingCB(ProfilingCallbackState state, const char* className, const char* methodName);
155
146 156 //---------------------------------------------------------------------------
147 157 //! \name Singleton Initialization
148 158 //@{
@@ -427,6 +437,10 public:
427 437 //! The error is currently just output to the python stderr, future version might implement better trace printing
428 438 bool handleError();
429 439
440 //! clear all NotFound entries on all class infos, to ensure that
441 //! newly loaded wrappers can add methods even when the object was wrapped by PythonQt before the wrapper was loaded
442 void clearNotFoundCachedMembers();
443
430 444 //! set a callback that is called when a QObject with parent == NULL is wrapped by pythonqt
431 445 void setQObjectWrappedCallback(PythonQtQObjectWrappedCB* cb);
432 446 //! set a callback that is called when a QObject with parent == NULL is no longer wrapped by pythonqt
@@ -442,6 +456,9 public:
442 456 //! @return new reference
443 457 PythonQtObjectPtr lookupObject(PyObject* module, const QString& name);
444 458
459 //! sets a callback that is called before and after function calls for profiling
460 void setProfilingCallback(ProfilingCB* cb);
461
445 462 //@}
446 463
447 464 signals:
@@ -575,6 +592,9 public:
575 592 //! get access to the PythonQt module
576 593 PythonQtObjectPtr pythonQtModule() const { return _pythonQtModule; }
577 594
595 //! returns the profiling callback, which may be NULL
596 PythonQt::ProfilingCB* profilingCB() const { return _profilingCB; }
597
578 598 private:
579 599 //! Setup the shared library suffixes by getting them from the "imp" module.
580 600 void setupSharedLibrarySuffixes();
@@ -625,6 +645,8 private:
625 645
626 646 PythonQtClassInfo* _currentClassInfoForClassWrapperCreation;
627 647
648 PythonQt::ProfilingCB* _profilingCB;
649
628 650 int _initFlags;
629 651 int _PythonQtObjectPtr_metaId;
630 652
@@ -847,3 +847,22 PyObject* PythonQtClassInfo::findEnumWrapper(const char* name) {
847 847 return NULL;
848 848 }
849 849
850 void PythonQtClassInfo::setDecoratorProvider( PythonQtQObjectCreatorFunctionCB* cb )
851 {
852 _decoratorProviderCB = cb;
853 _decoratorProvider = NULL;
854 _enumsCreated = false;
855 }
856
857 void PythonQtClassInfo::clearNotFoundCachedMembers()
858 {
859 // remove all not found entries, since a new decorator means new slots,
860 // which might have been cached as "NotFound" already.
861 QMutableHashIterator<QByteArray, PythonQtMemberInfo> it(_cachedMembers);
862 while (it.hasNext()) {
863 it.next();
864 if (it.value()._type == PythonQtMemberInfo::NotFound) {
865 it.remove();
866 }
867 }
868 }
@@ -166,7 +166,7 public:
166 166 int metaTypeId() { return _metaTypeId; }
167 167
168 168 //! set an additional decorator provider that offers additional decorator slots for this class
169 void setDecoratorProvider(PythonQtQObjectCreatorFunctionCB* cb) { _decoratorProviderCB = cb; _decoratorProvider = NULL; }
169 void setDecoratorProvider(PythonQtQObjectCreatorFunctionCB* cb);
170 170
171 171 //! get the decorator qobject instance
172 172 QObject* decorator();
@@ -202,6 +202,9 public:
202 202 //! returns if the localScope has an enum of that type name or if the enum contains a :: scope, if that class contails the enum
203 203 static PyObject* findEnumWrapper(const QByteArray& name, PythonQtClassInfo* localScope, bool* isLocalEnum = NULL);
204 204
205 //! clear all members that where cached as "NotFound"
206 void clearNotFoundCachedMembers();
207
205 208 private:
206 209 void createEnumWrappers();
207 210 void createEnumWrappers(const QMetaObject* meta);
@@ -266,6 +266,31 static PyObject *PythonQtClassWrapper_help(PythonQtClassWrapper* type)
266 266 return PythonQt::self()->helpCalled(type->classInfo());
267 267 }
268 268
269 PyObject *PythonQtClassWrapper_delete(PythonQtClassWrapper *type, PyObject *args)
270 {
271 Q_UNUSED(type);
272
273 Py_ssize_t argc = PyTuple_Size(args);
274 if (argc>0) {
275 PyObject* self = PyTuple_GET_ITEM(args, 0);
276 if (PyObject_TypeCheck(self, &PythonQtInstanceWrapper_Type)) {
277 return PythonQtInstanceWrapper_delete((PythonQtInstanceWrapper*)self);
278 }
279 }
280 return NULL;
281 }
282
283 PyObject *PythonQtClassWrapper_inherits(PythonQtClassWrapper *type, PyObject *args)
284 {
285 Q_UNUSED(type);
286 PythonQtInstanceWrapper* wrapper = NULL;
287 char *name = NULL;
288 if (!PyArg_ParseTuple(args, "O!s:PythonQtClassWrapper.inherits",&PythonQtInstanceWrapper_Type, &wrapper, &name)) {
289 return NULL;
290 }
291 return PythonQtConv::GetPyBool(wrapper->classInfo()->inherits(name));
292 }
293
269 294 PyObject *PythonQtClassWrapper__init__(PythonQtClassWrapper *type, PyObject *args)
270 295 {
271 296 Py_ssize_t argc = PyTuple_Size(args);
@@ -295,16 +320,23 PyObject *PythonQtClassWrapper__init__(PythonQtClassWrapper *type, PyObject *arg
295 320 return NULL;
296 321 }
297 322
323
298 324 static PyMethodDef PythonQtClassWrapper_methods[] = {
299 325 {"__init__", (PyCFunction)PythonQtClassWrapper__init__, METH_VARARGS,
300 "Return the classname of the object"
326 "Init function"
301 327 },
302 328 {"className", (PyCFunction)PythonQtClassWrapper_classname, METH_NOARGS,
303 329 "Return the classname of the object"
304 330 },
331 {"inherits", (PyCFunction)PythonQtClassWrapper_inherits, METH_VARARGS,
332 "Returns if the class inherits or is of given type name"
333 },
305 334 {"help", (PyCFunction)PythonQtClassWrapper_help, METH_NOARGS,
306 335 "Shows the help of available methods for this class"
307 336 },
337 {"delete", (PyCFunction)PythonQtClassWrapper_delete, METH_VARARGS,
338 "Deletes the given C++ object"
339 },
308 340 {NULL, NULL, 0 , NULL} /* Sentinel */
309 341 };
310 342
@@ -344,7 +376,7 static PyObject *PythonQtClassWrapper_getattro(PyObject *obj, PyObject *name)
344 376 PyDict_SetItemString(dict, "__init__", func);
345 377 Py_DECREF(func);
346 378 }
347 for (int i = 1;i<3;i++) {
379 for (int i = 1; PythonQtClassWrapper_methods[i].ml_name != NULL; i++) {
348 380 PyObject* func = PyCFunction_New(&PythonQtClassWrapper_methods[i], obj);
349 381 PyDict_SetItemString(dict, PythonQtClassWrapper_methods[i].ml_name, func);
350 382 Py_DECREF(func);
@@ -47,7 +47,7
47 47
48 48 PythonQtValueStorage<qint64, 128> PythonQtConv::global_valueStorage;
49 49 PythonQtValueStorage<void*, 128> PythonQtConv::global_ptrStorage;
50 PythonQtValueStorage<QVariant, 32> PythonQtConv::global_variantStorage;
50 PythonQtValueStorageWithCleanup<QVariant, 128> PythonQtConv::global_variantStorage;
51 51
52 52 QHash<int, PythonQtConvertMetaTypeToPythonCB*> PythonQtConv::_metaTypeToPythonConverters;
53 53 QHash<int, PythonQtConvertPythonToMetaTypeCB*> PythonQtConv::_pythonToMetaTypeConverters;
@@ -144,7 +144,7 public:
144 144
145 145 static PythonQtValueStorage<qint64, 128> global_valueStorage;
146 146 static PythonQtValueStorage<void*, 128> global_ptrStorage;
147 static PythonQtValueStorage<QVariant, 32> global_variantStorage;
147 static PythonQtValueStorageWithCleanup<QVariant, 128> global_variantStorage;
148 148
149 149 protected:
150 150 static QHash<int, PythonQtConvertMetaTypeToPythonCB*> _metaTypeToPythonConverters;
1 NO CONTENT: modified file
@@ -67,6 +67,9 public:
67 67 //! get the last modified data of a file
68 68 virtual QDateTime lastModifiedDate(const QString& filename) = 0;
69 69
70 //! indicates that *.py files which are newer than their corresponding *.pyc files
71 //! are ignored
72 virtual bool ignoreUpdatedPythonSourceFiles() { return false; }
70 73 };
71 74
72 75 #endif
@@ -114,6 +114,7 PythonQtImport::ModuleInfo PythonQtImport::getModuleInfo(PythonQtImporter* self,
114 114 info.fullPath = test;
115 115 info.moduleName = subname;
116 116 info.type = MI_SHAREDLIBRARY;
117 return info;
117 118 }
118 119 }
119 120 return info;
@@ -276,12 +277,21 PythonQtImporter_load_module(PyObject *obj, PyObject *args)
276 277 args.append(QVariant::fromValue(pathList));
277 278 QVariant result = imp.call("find_module", args);
278 279 if (result.isValid()) {
279 // This will return a tuple with (file, pathname, description)
280 // This will return a tuple with (file, pathname, description=(suffix,mode,type))
280 281 QVariantList list = result.toList();
281 282 if (list.count()==3) {
282 283 // We prepend the full module name (including package prefix)
283 284 list.prepend(fullname);
284 // And call "load_module" with (fullname, file, pathname, description)
285 #ifdef __linux
286 #ifdef _DEBUG
287 // imp_find_module() does not respect the debug suffix '_d' on Linux,
288 // so it does not return the correct file path and we correct it now
289 // find_module opened a file to the release library, but that file handle is
290 // ignored on Linux and Windows, maybe on MacOS also.
291 list[2] = info.fullPath;
292 #endif
293 #endif
294 // And call "load_module" with (fullname, file, pathname, description=(suffix,mode,type))
285 295 PythonQtObjectPtr module = imp.call("load_module", list);
286 296 mod = module.object();
287 297 if (mod) {
@@ -559,13 +569,17 PythonQtImport::unmarshalCode(const QString& path, const QByteArray& data, time_
559 569 return Py_None;
560 570 }
561 571
562 if (mtime != 0 && !(getLong((unsigned char *)buf + 4) == mtime)) {
572 if (mtime != 0) {
573 time_t timeDiff = getLong((unsigned char *)buf + 4) - mtime;
574 if (timeDiff<0) { timeDiff = -timeDiff; }
575 if (timeDiff > 1) {
563 576 if (Py_VerboseFlag)
564 577 PySys_WriteStderr("# %s has bad mtime\n",
565 578 path.toLatin1().constData());
566 579 Py_INCREF(Py_None);
567 580 return Py_None;
568 581 }
582 }
569 583
570 584 code = PyMarshal_ReadObjectFromString(buf + 8, size - 8);
571 585 if (code == NULL)
@@ -645,7 +659,10 PythonQtImport::getMTimeOfSource(const QString& path)
645 659 path2.truncate(path.length()-1);
646 660
647 661 if (PythonQt::importInterface()->exists(path2)) {
648 mtime = PythonQt::importInterface()->lastModifiedDate(path2).toTime_t();
662 QDateTime t = PythonQt::importInterface()->lastModifiedDate(path2);
663 if (t.isValid()) {
664 mtime = t.toTime_t();
665 }
649 666 }
650 667
651 668 return mtime;
@@ -675,7 +692,12 PythonQtImport::getModuleCode(PythonQtImporter *self, const char* fullname, QStr
675 692 int ispackage = zso->type & IS_PACKAGE;
676 693 int isbytecode = zso->type & IS_BYTECODE;
677 694
678 if (isbytecode) {
695 // if ignoreUpdatedPythonSourceFiles() returns true, then mtime stays 0
696 // and unmarshalCode() in getCodeFromData() will always read an existing *.pyc file,
697 // even if a newer *.py file exists. This is a release optimization where
698 // typically only *.pyc files are delivered without *.py files and reading file
699 // modification time is slow.
700 if (isbytecode && !PythonQt::importInterface()->ignoreUpdatedPythonSourceFiles()) {
679 701 mtime = getMTimeOfSource(test);
680 702 }
681 703 code = getCodeFromData(test, isbytecode, ispackage, mtime);
@@ -713,7 +735,14 PyObject* PythonQtImport::getCodeFromPyc(const QString& file)
713 735 QString pyc = replaceExtension(file, pycStr);
714 736 if (PythonQt::importInterface()->exists(pyc)) {
715 737 time_t mtime = 0;
738 // if ignoreUpdatedPythonSourceFiles() returns true, then mtime stays 0
739 // and unmarshalCode() in getCodeFromData() will always read an existing *.pyc file,
740 // even if a newer *.py file exists. This is a release optimization where
741 // typically only *.pyc files are delivered without *.py files and reading file
742 // modification time is slow.
743 if (!PythonQt::importInterface()->ignoreUpdatedPythonSourceFiles()) {
716 744 mtime = getMTimeOfSource(pyc);
745 }
717 746 code = getCodeFromData(pyc, true, false, mtime);
718 747 if (code != Py_None && code != NULL) {
719 748 return code;
@@ -288,12 +288,21 static PyObject *PythonQtInstanceWrapper_classname(PythonQtInstanceWrapper* obj)
288 288 return PyString_FromString(obj->ob_type->tp_name);
289 289 }
290 290
291 PyObject *PythonQtInstanceWrapper_inherits(PythonQtInstanceWrapper* obj, PyObject *args)
292 {
293 char *name = NULL;
294 if (!PyArg_ParseTuple(args, "s:PythonQtInstanceWrapper.inherits",&name)) {
295 return NULL;
296 }
297 return PythonQtConv::GetPyBool(obj->classInfo()->inherits(name));
298 }
299
291 300 static PyObject *PythonQtInstanceWrapper_help(PythonQtInstanceWrapper* obj)
292 301 {
293 302 return PythonQt::self()->helpCalled(obj->classInfo());
294 303 }
295 304
296 static PyObject *PythonQtInstanceWrapper_delete(PythonQtInstanceWrapper * self)
305 PyObject *PythonQtInstanceWrapper_delete(PythonQtInstanceWrapper * self)
297 306 {
298 307 PythonQtInstanceWrapper_deleteObject(self, true);
299 308 Py_INCREF(Py_None);
@@ -305,6 +314,9 static PyMethodDef PythonQtInstanceWrapper_methods[] = {
305 314 {"className", (PyCFunction)PythonQtInstanceWrapper_classname, METH_NOARGS,
306 315 "Return the classname of the object"
307 316 },
317 {"inherits", (PyCFunction)PythonQtInstanceWrapper_inherits, METH_VARARGS,
318 "Returns if the class inherits or is of given type name"
319 },
308 320 {"help", (PyCFunction)PythonQtInstanceWrapper_help, METH_NOARGS,
309 321 "Shows the help of available methods for this class"
310 322 },
@@ -371,7 +383,23 static PyObject *PythonQtInstanceWrapper_getattro(PyObject *obj,PyObject *name)
371 383 case PythonQtMemberInfo::Property:
372 384 if (wrapper->_obj) {
373 385 if (member._property.userType() != QVariant::Invalid) {
374 return PythonQtConv::QVariantToPyObject(member._property.read(wrapper->_obj));
386
387 PythonQt::ProfilingCB* profilingCB = PythonQt::priv()->profilingCB();
388 if (profilingCB) {
389 QString methodName = "getProperty(";
390 methodName += attributeName;
391 methodName += ")";
392 profilingCB(PythonQt::Enter, wrapper->_obj->metaObject()->className(), methodName.toLatin1());
393 }
394
395 PyObject* value = PythonQtConv::QVariantToPyObject(member._property.read(wrapper->_obj));
396
397 if (profilingCB) {
398 profilingCB(PythonQt::Leave, NULL, NULL);
399 }
400
401 return value;
402
375 403 } else {
376 404 Py_INCREF(Py_None);
377 405 return Py_None;
@@ -475,7 +503,19 static int PythonQtInstanceWrapper_setattro(PyObject *obj,PyObject *name,PyObjec
475 503 }
476 504 bool success = false;
477 505 if (v.isValid()) {
506 PythonQt::ProfilingCB* profilingCB = PythonQt::priv()->profilingCB();
507 if (profilingCB) {
508 QString methodName = "setProperty(";
509 methodName += attributeName;
510 methodName += ")";
511 profilingCB(PythonQt::Enter, wrapper->_obj->metaObject()->className(), methodName.toLatin1());
512 }
513
478 514 success = prop.write(wrapper->_obj, v);
515
516 if (profilingCB) {
517 profilingCB(PythonQt::Leave, NULL, NULL);
518 }
479 519 }
480 520 if (success) {
481 521 return 0;
@@ -605,17 +645,17 static PyObject * PythonQtInstanceWrapper_repr(PyObject * obj)
605 645 if (str.startsWith(typeName)) {
606 646 return PyString_FromFormat("%s", str.toLatin1().constData());
607 647 } else {
608 return PyString_FromFormat("%s(%s, %p)", typeName, str.toLatin1().constData(), wrapper->_wrappedPtr);
648 return PyString_FromFormat("%s (%s, at: %p)", typeName, str.toLatin1().constData(), wrapper->_wrappedPtr ? wrapper->_wrappedPtr : qobj);
609 649 }
610 650 }
611 651 if (wrapper->_wrappedPtr) {
612 652 if (wrapper->_obj) {
613 return PyString_FromFormat("%s (C++ Object %p wrapped by %s %p))", typeName, wrapper->_wrappedPtr, wrapper->_obj->metaObject()->className(), qobj);
653 return PyString_FromFormat("%s (C++ object at: %p wrapped by %s at: %p)", typeName, wrapper->_wrappedPtr, wrapper->_obj->metaObject()->className(), qobj);
614 654 } else {
615 return PyString_FromFormat("%s (C++ Object %p)", typeName, wrapper->_wrappedPtr);
655 return PyString_FromFormat("%s (C++ object at: %p)", typeName, wrapper->_wrappedPtr);
616 656 }
617 657 } else {
618 return PyString_FromFormat("%s (%s %p)", typeName, wrapper->classInfo()->className(), qobj);
658 return PyString_FromFormat("%s (%s at: %p)", typeName, wrapper->classInfo()->className(), qobj);
619 659 }
620 660 }
621 661
@@ -95,4 +95,6 typedef struct PythonQtInstanceWrapperStruct {
95 95
96 96 int PythonQtInstanceWrapper_init(PythonQtInstanceWrapper * self, PyObject * args, PyObject * kwds);
97 97
98 PyObject *PythonQtInstanceWrapper_delete(PythonQtInstanceWrapper * self);
99
98 100 #endif
@@ -192,7 +192,6 int PythonQtMethodInfo::nameToType(const char* name)
192 192 _parameterTypeDict.insert("qreal", QMetaType::Double);
193 193 _parameterTypeDict.insert("QChar", QMetaType::QChar);
194 194 _parameterTypeDict.insert("QByteArray", QMetaType::QByteArray);
195 _parameterTypeDict.insert("Q3CString", QMetaType::QByteArray);
196 195 _parameterTypeDict.insert("QString", QMetaType::QString);
197 196 _parameterTypeDict.insert("", QMetaType::Void);
198 197 _parameterTypeDict.insert("void", QMetaType::Void);
@@ -203,7 +202,6 int PythonQtMethodInfo::nameToType(const char* name)
203 202 _parameterTypeDict.insert("qulonglong", QMetaType::ULongLong);
204 203 _parameterTypeDict.insert("qint64", QMetaType::LongLong);
205 204 _parameterTypeDict.insert("quint64", QMetaType::ULongLong);
206 _parameterTypeDict.insert("QIconSet", QMetaType::QIcon);
207 205 _parameterTypeDict.insert("QVariantMap", QMetaType::QVariantMap);
208 206 _parameterTypeDict.insert("QVariantList", QMetaType::QVariantList);
209 207 _parameterTypeDict.insert("QMap<QString,QVariant>", QMetaType::QVariantMap);
@@ -216,15 +214,14 int PythonQtMethodInfo::nameToType(const char* name)
216 214 _parameterTypeDict.insert("QUrl", QMetaType::QUrl);
217 215 _parameterTypeDict.insert("QLocale", QMetaType::QLocale);
218 216 _parameterTypeDict.insert("QRect", QMetaType::QRect);
219 _parameterTypeDict.insert("QRectf", QMetaType::QRectF);
217 _parameterTypeDict.insert("QRectF", QMetaType::QRectF);
220 218 _parameterTypeDict.insert("QSize", QMetaType::QSize);
221 _parameterTypeDict.insert("QSizef", QMetaType::QSizeF);
219 _parameterTypeDict.insert("QSizeF", QMetaType::QSizeF);
222 220 _parameterTypeDict.insert("QLine", QMetaType::QLine);
223 _parameterTypeDict.insert("QLinef", QMetaType::QLineF);
221 _parameterTypeDict.insert("QLineF", QMetaType::QLineF);
224 222 _parameterTypeDict.insert("QPoint", QMetaType::QPoint);
225 _parameterTypeDict.insert("QPointf", QMetaType::QPointF);
223 _parameterTypeDict.insert("QPointF", QMetaType::QPointF);
226 224 _parameterTypeDict.insert("QRegExp", QMetaType::QRegExp);
227 // _parameterTypeDict.insert("QColorGroup", QMetaType::QColorGroup);
228 225 _parameterTypeDict.insert("QFont", QMetaType::QFont);
229 226 _parameterTypeDict.insert("QPixmap", QMetaType::QPixmap);
230 227 _parameterTypeDict.insert("QBrush", QMetaType::QBrush);
@@ -232,7 +229,7 int PythonQtMethodInfo::nameToType(const char* name)
232 229 _parameterTypeDict.insert("QCursor", QMetaType::QCursor);
233 230 _parameterTypeDict.insert("QPalette", QMetaType::QPalette);
234 231 _parameterTypeDict.insert("QIcon", QMetaType::QIcon);
235 _parameterTypeDict.insert("QImage", QMetaType::QPolygon);
232 _parameterTypeDict.insert("QImage", QMetaType::QImage);
236 233 _parameterTypeDict.insert("QRegion", QMetaType::QRegion);
237 234 _parameterTypeDict.insert("QBitmap", QMetaType::QBitmap);
238 235 _parameterTypeDict.insert("QSizePolicy", QMetaType::QSizePolicy);
@@ -89,13 +89,6 public:
89 89 _chunks.clear();
90 90 }
91 91
92 //! reset the storage to 0 (without freeing memory, thus caching old entries for reuse)
93 void reset() {
94 _chunkIdx = 0;
95 _chunkOffset = 0;
96 _currentChunk = _chunks.at(0);
97 }
98
99 92 //! get the current position to be restored with setPos
100 93 void getPos(PythonQtValueStoragePosition & pos) {
101 94 pos.chunkIdx = _chunkIdx;
@@ -129,7 +122,7 public:
129 122 return newEntry;
130 123 };
131 124
132 private:
125 protected:
133 126 QList<T*> _chunks;
134 127
135 128 int _chunkIdx;
@@ -138,5 +131,45 private:
138 131
139 132 };
140 133
134 //! a helper class that stores basic C++ value types in chunks and clears the unused values on setPos() usage.
135 template <typename T, int chunkEntries> class PythonQtValueStorageWithCleanup : public PythonQtValueStorage<T, chunkEntries>
136 {
137 public:
138 void setPos(const PythonQtValueStoragePosition& pos) {
139 if (_chunkIdx > pos.chunkIdx) {
140 T* firstChunk = _chunks.at(pos.chunkIdx);
141 // clear region in first chunk
142 for (int i = pos.chunkOffset; i < chunkEntries; i++) {
143 firstChunk[i] = T();
144 }
145 for (int chunk = pos.chunkIdx + 1; chunk < _chunkIdx; chunk++) {
146 // clear the full chunks between the first and last chunk
147 T* fullChunk = _chunks.at(chunk);
148 for (int i = 0; i < chunkEntries; i++) {
149 fullChunk[i] = T();
150 }
151 }
152 // clear region in last chunk
153 T* lastChunk = _chunks.at(_chunkIdx);
154 for (int i = 0; i < _chunkOffset; i++) {
155 lastChunk[i] = T();
156 }
157 } else if (_chunkIdx == pos.chunkIdx) {
158 // clear the region in the last chunk only
159 T* lastChunk = _chunks.at(_chunkIdx);
160 for (int i = pos.chunkOffset; i<_chunkOffset; i++) {
161 lastChunk[i] = T();
162 }
163 }
164
165 PythonQtValueStorage<T, chunkEntries>::setPos(pos);
166 }
167
168 private:
169 using PythonQtValueStorage<T, chunkEntries>::_chunks;
170 using PythonQtValueStorage<T, chunkEntries>::_chunkIdx;
171 using PythonQtValueStorage<T, chunkEntries>::_chunkOffset;
172 using PythonQtValueStorage<T, chunkEntries>::_currentChunk;
173 };
141 174
142 175 #endif
@@ -67,7 +67,7 public:
67 67 if (o) Py_INCREF(_object);
68 68 }
69 69
70 ~PythonQtObjectPtr() { if (_object) Py_DECREF(_object); }
70 ~PythonQtObjectPtr() { if (_object) { Py_DECREF(_object); } }
71 71
72 72 //! If the given variant holds a PythonQtObjectPtr, extract the value from it and hold onto the reference. This results in an increment of the reference count.
73 73 bool fromVariant(const QVariant& variant);
@@ -116,7 +116,7 public:
116 116 //! sets the object and passes the ownership (stealing the reference, in Python slang)
117 117 void setNewRef(PyObject* o) {
118 118 if (o != _object) {
119 if (_object) Py_DECREF(_object);
119 if (_object) { Py_DECREF(_object); }
120 120 _object = o;
121 121 }
122 122 }
@@ -157,9 +157,9 protected:
157 157
158 158 void setObject(PyObject* o) {
159 159 if (o != _object) {
160 if (_object) Py_DECREF(_object);
160 if (_object) { Py_DECREF(_object); }
161 161 _object = o;
162 if (_object) Py_INCREF(_object);
162 if (_object) { Py_INCREF(_object); }
163 163 }
164 164 }
165 165
@@ -56,6 +56,8 void PythonQtSignalTarget::call(void **arguments) const {
56 56
57 57 PyObject* PythonQtSignalTarget::call(PyObject* callable, const PythonQtMethodInfo* methodInfos, void **arguments, bool skipFirstArgumentOfMethodInfo)
58 58 {
59 Q_UNUSED(skipFirstArgumentOfMethodInfo)
60
59 61 // Note: we check if the callable is a PyFunctionObject and has a fixed number of arguments
60 62 // if that is the case, we only pass these arguments to python and skip the additional arguments from the signal
61 63
@@ -50,7 +50,7 class PythonQtMethodInfo;
50 50 class PythonQtClassInfo;
51 51
52 52 //! stores information about a signal target
53 /*! copy construction and assignment works fine with the C++ standard behaviour and are thus not implemented
53 /*! copy construction and assignment works fine with the C++ standard behavior and are thus not implemented
54 54 */
55 55 class PYTHONQT_EXPORT PythonQtSignalTarget {
56 56 public:
@@ -142,9 +142,26 bool PythonQtCallSlot(PythonQtClassInfo* classInfo, QObject* objectToCall, PyObj
142 142 }
143 143 }
144 144
145
146 PythonQt::ProfilingCB* profilingCB = PythonQt::priv()->profilingCB();
147 if (profilingCB) {
148 const char* className = NULL;
149 if (info->decorator()) {
150 className = info->decorator()->metaObject()->className();
151 } else {
152 className = objectToCall->metaObject()->className();
153 }
154
155 profilingCB(PythonQt::Enter, className, info->metaMethod()->signature());
156 }
157
145 158 // invoke the slot via metacall
146 159 (info->decorator()?info->decorator():objectToCall)->qt_metacall(QMetaObject::InvokeMetaMethod, info->slotIndex(), argList);
147 160
161 if (profilingCB) {
162 profilingCB(PythonQt::Leave, NULL, NULL);
163 }
164
148 165 // handle the return value (which in most cases still needs to be converted to a Python object)
149 166 if (argList[0] || returnValueParam.typeId == QMetaType::Void) {
150 167 if (directReturnValuePointer) {
@@ -126,15 +126,6 bool PythonQtStdDecorators::disconnect(QObject* sender, const QByteArray& signal
126 126 return r;
127 127 }
128 128
129 #undef emit
130 void PythonQtStdDecorators::emit(QObject* sender, const QByteArray& signal, PyObject* arg1 ,PyObject* arg2 ,
131 PyObject* arg3 ,PyObject* arg4 ,PyObject* arg5 ,PyObject* arg6 ,PyObject* arg7 )
132 {
133 // TODO xxx
134 // use normal PythonQtSlot calling code, add "allowSignal" to member lookup?!
135 }
136 #define emit
137
138 129 QObject* PythonQtStdDecorators::parent(QObject* o) {
139 130 return o->parent();
140 131 }
@@ -62,11 +62,6 public slots:
62 62 bool disconnect(QObject* sender, const QByteArray& signal, PyObject* callable);
63 63 bool disconnect(QObject* sender, const QByteArray& signal, QObject* receiver, const QByteArray& slot);
64 64
65 #undef emit
66 void emit(QObject* sender, const QByteArray& signal, PyObject* arg1 = NULL,PyObject* arg2 = NULL,
67 PyObject* arg3 = NULL,PyObject* arg4 = NULL,PyObject* arg5 = NULL,PyObject* arg6 = NULL,PyObject* arg7 = NULL);
68 #define emit
69
70 65 QObject* parent(QObject* o);
71 66 void setParent(QObject* o, QObject* parent);
72 67
@@ -80,13 +75,13 public slots:
80 75
81 76 double static_Qt_qAbs(double a) { return qAbs(a); }
82 77 double static_Qt_qBound(double a,double b,double c) { return qBound(a,b,c); }
83 void static_Qt_qDebug(const QByteArray& msg) { qDebug(msg.constData()); }
78 void static_Qt_qDebug(const QByteArray& msg) { qDebug("%s", msg.constData()); }
84 79 // TODO: multi arg qDebug...
85 void static_Qt_qWarning(const QByteArray& msg) { qWarning(msg.constData()); }
80 void static_Qt_qWarning(const QByteArray& msg) { qWarning("%s", msg.constData()); }
86 81 // TODO: multi arg qWarning...
87 void static_Qt_qCritical(const QByteArray& msg) { qCritical(msg.constData()); }
82 void static_Qt_qCritical(const QByteArray& msg) { qCritical("%s", msg.constData()); }
88 83 // TODO: multi arg qCritical...
89 void static_Qt_qFatal(const QByteArray& msg) { qFatal(msg.constData()); }
84 void static_Qt_qFatal(const QByteArray& msg) { qFatal("%s", msg.constData()); }
90 85 // TODO: multi arg qFatal...
91 86 bool static_Qt_qFuzzyCompare(double a, double b) { return qFuzzyCompare(a, b); }
92 87 double static_Qt_qMax(double a, double b) { return qMax(a, b); }
General Comments 0
You need to be logged in to leave comments. Login now