Skip to content

Commit 28d1f91

Browse files
author
florianlink
committed
merged various changes from MeVisLab repository
git-svn-id: https://pythonqt.svn.sourceforge.net/svnroot/pythonqt/trunk@219 ea8d5007-eb21-0410-b261-ccb3ea6e24a9
1 parent df6ba65 commit 28d1f91

11 files changed

+250
-73
lines changed

src/PythonQt.cpp

Lines changed: 32 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -78,11 +78,12 @@ void PythonQt::init(int flags, const QByteArray& pythonQtModuleName)
7878
PythonQtRegisterToolClassesTemplateConverter(quint64);
7979
// TODO: which other POD types should be available for QList etc.
8080

81-
PythonQt::self()->addDecorators(new PythonQtStdDecorators());
82-
8381
PythonQt_init_QtCoreBuiltin(NULL);
8482
PythonQt_init_QtGuiBuiltin(NULL);
8583

84+
PythonQt::self()->addDecorators(new PythonQtStdDecorators());
85+
PythonQt::self()->registerCPPClass("QMetaObject",0, "QtCore", PythonQtCreateObject<PythonQtWrapper_QMetaObject>);
86+
8687
PythonQtRegisterToolClassesTemplateConverter(QByteArray);
8788
PythonQtRegisterToolClassesTemplateConverter(QDate);
8889
PythonQtRegisterToolClassesTemplateConverter(QTime);
@@ -919,6 +920,13 @@ QStringList PythonQt::introspectObject(PyObject* object, ObjectType type)
919920
}
920921
Py_DECREF(keys);
921922
}
923+
if ((type == Anything) || (type == Variable)) {
924+
if (object->ob_type == &PythonQtClassWrapper_Type) {
925+
PythonQtClassWrapper* o = (PythonQtClassWrapper*)object;
926+
PythonQtClassInfo* info = o->classInfo();
927+
results += info->propertyList();
928+
}
929+
}
922930
}
923931
return results;
924932
}
@@ -958,7 +966,13 @@ QStringList PythonQt::introspectType(const QString& typeName, ObjectType type)
958966
// the last item may be a member, split it away and try again
959967
QStringList tmp = typeName.split(".");
960968
QString memberName = tmp.takeLast();
961-
QString typeName = tmp.takeLast();
969+
QString typeName;
970+
if (tmp.isEmpty()) {
971+
typeName = memberName;
972+
memberName.clear();
973+
} else {
974+
typeName = tmp.takeLast();
975+
}
962976
PyObject* typeObject = getObjectByType(typeName);
963977
if (typeObject) {
964978
object = PyObject_GetAttrString(typeObject, memberName.toLatin1().constData());
@@ -1690,3 +1704,18 @@ QString PythonQtPrivate::getSignature(PyObject* object)
16901704

16911705
return signature;
16921706
}
1707+
1708+
void PythonQtPrivate::shellClassDeleted( void* shellClass )
1709+
{
1710+
PythonQtInstanceWrapper* wrap = _wrappedObjects.value(shellClass);
1711+
if (wrap && wrap->_wrappedPtr) {
1712+
// this is a pure C++ wrapper and the shell has gone, so we need
1713+
// to set the _wrappedPtr to NULL on the wrapper
1714+
wrap->_wrappedPtr = NULL;
1715+
// and then we remove the wrapper, since the wrapped class is gone
1716+
_wrappedObjects.remove(shellClass);
1717+
}
1718+
// if the wrapper is a QObject, we do not handle this here,
1719+
// it will be handled by the QPointer<> to the QObject, which becomes NULL
1720+
// via the QObject destructor.
1721+
}

src/PythonQt.h

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -563,6 +563,9 @@ class PYTHONQT_EXPORT PythonQtPrivate : public QObject {
563563
//! remove the wrapper ptr again
564564
void removeWrapperPointer(void* obj);
565565

566+
//! called by destructor of shells to allow invalidation of the Python wrapper
567+
void shellClassDeleted(void* shellClass);
568+
566569
//! try to unwrap the given object to a C++ pointer using the foreign wrapper factories
567570
void* unwrapForeignWrapper(const QByteArray& classname, PyObject* obj);
568571

src/PythonQtClassInfo.cpp

Lines changed: 34 additions & 43 deletions
Original file line numberDiff line numberDiff line change
@@ -205,46 +205,53 @@ PythonQtSlotInfo* PythonQtClassInfo::findDecoratorSlotsFromDecoratorProvider(con
205205
}
206206

207207
tail = findDecoratorSlots(memberName, memberNameLen, tail, found, memberCache, upcastingOffset);
208-
209-
return tail;
210-
}
211208

212-
bool PythonQtClassInfo::lookForMethodAndCache(const char* memberName)
213-
{
214-
bool found = false;
215-
int memberNameLen = static_cast<int>(strlen(memberName));
216-
PythonQtSlotInfo* tail = NULL;
209+
// now look for slots/signals/methods on this level of the meta object
217210
if (_meta) {
218211
int numMethods = _meta->methodCount();
219-
for (int i = 0; i < numMethods; i++) {
212+
// start from methodOffset, to only add slots which are located in this class,
213+
// and not in the parent class, which is traversed recursively later on.
214+
// (if the class in not a QObject, we are working with a script wrapper QObject
215+
// and need to read all slots/signals starting from 0).
216+
int methodOffset = _isQObject?_meta->methodOffset():0;
217+
for (int i = methodOffset; i < numMethods; i++) {
220218
QMetaMethod m = _meta->method(i);
221219
if (((m.methodType() == QMetaMethod::Method ||
222-
m.methodType() == QMetaMethod::Slot) && m.access() == QMetaMethod::Public)
220+
m.methodType() == QMetaMethod::Slot) && m.access() == QMetaMethod::Public)
223221
|| m.methodType()==QMetaMethod::Signal) {
224-
225-
const char* sigStart = m.signature();
226-
// find the first '('
227-
int offset = findCharOffset(sigStart, '(');
228-
229-
// check if same length and same name
230-
if (memberNameLen == offset && qstrncmp(memberName, sigStart, offset)==0) {
231-
found = true;
232-
PythonQtSlotInfo* info = new PythonQtSlotInfo(this, m, i);
233-
if (tail) {
234-
tail->setNextInfo(info);
235-
} else {
236-
PythonQtMemberInfo newInfo(info);
237-
_cachedMembers.insert(memberName, newInfo);
222+
223+
const char* sigStart = m.signature();
224+
// find the first '('
225+
int offset = findCharOffset(sigStart, '(');
226+
227+
// check if same length and same name
228+
if (memberNameLen == offset && qstrncmp(memberName, sigStart, offset)==0) {
229+
found = true;
230+
PythonQtSlotInfo* info = new PythonQtSlotInfo(this, m, i);
231+
if (tail) {
232+
tail->setNextInfo(info);
233+
} else {
234+
PythonQtMemberInfo newInfo(info);
235+
memberCache.insert(memberName, newInfo);
236+
}
237+
tail = info;
238238
}
239-
tail = info;
240-
}
241239
}
242240
}
243241
}
242+
return tail;
243+
}
244+
245+
bool PythonQtClassInfo::lookForMethodAndCache(const char* memberName)
246+
{
247+
bool found = false;
248+
PythonQtSlotInfo* tail = NULL;
244249

245250
// look for dynamic decorators in this class and in derived classes
251+
// (do this first to allow overloading of existing slots with generated wrappers,
252+
// e.g. QDialog::accept is overloaded with PythonQtWrapper_QDialog::accept decorator)
246253
tail = recursiveFindDecoratorSlotsFromDecoratorProvider(memberName, tail, found, _cachedMembers, 0);
247-
254+
248255
return found;
249256
}
250257

@@ -710,22 +717,6 @@ QObject* PythonQtClassInfo::decorator()
710717
return _decoratorProvider;
711718
}
712719

713-
bool PythonQtClassInfo::hasOwnerMethodButNoOwner(void* object)
714-
{
715-
PythonQtMemberInfo info = member("py_hasOwner");
716-
if (info._type == PythonQtMemberInfo::Slot) {
717-
void* obj = object;
718-
bool result = false;
719-
void* args[2];
720-
args[0] = &result;
721-
args[1] = &obj;
722-
info._slot->decorator()->qt_metacall(QMetaObject::InvokeMetaMethod, info._slot->slotIndex(), args);
723-
return !result;
724-
} else {
725-
return false;
726-
}
727-
}
728-
729720
void* PythonQtClassInfo::recursiveCastDownIfPossible(void* ptr, const char** resultClassName)
730721
{
731722
if (!_polymorphicHandlers.isEmpty()) {

src/PythonQtClassInfo.h

Lines changed: 0 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -159,9 +159,6 @@ class PYTHONQT_EXPORT PythonQtClassInfo {
159159
//! add the parent class info of a CPP object
160160
void addParentClass(const ParentClassInfo& info) { _parentClasses.append(info); }
161161

162-
//! check if the special method "py_hasOwner" is implemented and if it returns false, which means that the object may be destroyed
163-
bool hasOwnerMethodButNoOwner(void* object);
164-
165162
//! set the associated PythonQtClassWrapper (which handles instance creation of this type)
166163
void setPythonQtClassWrapper(PyObject* obj) { _pythonQtClassWrapper = obj; }
167164

src/PythonQtConversion.cpp

Lines changed: 51 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -377,11 +377,32 @@ void* PythonQtConv::ConvertPythonToQt(const PythonQtMethodInfo::ParameterInfo& i
377377
// a pointer
378378
if (info.typeId == QMetaType::Char || info.typeId == QMetaType::UChar)
379379
{
380+
if (obj->ob_type == &PyString_Type) {
381+
// take direct reference to string data
382+
const char* data = PyString_AS_STRING(obj);
383+
PythonQtValueStorage_ADD_VALUE_IF_NEEDED(alreadyAllocatedCPPObject,global_ptrStorage, void*, (void*)data, ptr);
384+
} else {
385+
// convert to string
386+
QString str = PyObjGetString(obj, strict, ok);
387+
if (ok) {
388+
QByteArray bytes;
389+
bytes = str.toUtf8();
390+
if (ok) {
391+
void* ptr2 = NULL;
392+
PythonQtValueStorage_ADD_VALUE_IF_NEEDED(NULL,global_variantStorage, QVariant, QVariant(bytes), ptr2);
393+
PythonQtValueStorage_ADD_VALUE_IF_NEEDED(alreadyAllocatedCPPObject,global_ptrStorage, void*, (((QByteArray*)((QVariant*)ptr2)->constData())->data()), ptr);
394+
}
395+
}
396+
}
397+
} else if (info.typeId == QMetaType::QString) {
398+
// TODO: this is a special case for bad Qt APIs which take a QString*, like QtGui.QFileDialog.getSaveFileName
399+
// In general we would need to decide to either support * args for all basic types (ignoring the fact that the
400+
// result value is not useable in Python), or if all these APIs need to be wrapped manually/differently, like PyQt/PySide do.
380401
QString str = PyObjGetString(obj, strict, ok);
381402
if (ok) {
382403
void* ptr2 = NULL;
383-
PythonQtValueStorage_ADD_VALUE_IF_NEEDED(alreadyAllocatedCPPObject,global_variantStorage, QVariant, QVariant(str.toUtf8()), ptr2);
384-
PythonQtValueStorage_ADD_VALUE_IF_NEEDED(alreadyAllocatedCPPObject,global_ptrStorage, void*, (((QByteArray*)((QVariant*)ptr2)->constData())->data()), ptr);
404+
PythonQtValueStorage_ADD_VALUE_IF_NEEDED(NULL,global_variantStorage, QVariant, QVariant(str), ptr2);
405+
PythonQtValueStorage_ADD_VALUE_IF_NEEDED(alreadyAllocatedCPPObject,global_ptrStorage, void*, (void*)((QVariant*)ptr2)->constData(), ptr);
385406
}
386407
} else if (info.name == "PyObject") {
387408
// handle low level PyObject directly
@@ -746,7 +767,13 @@ int PythonQtConv::PyObjGetInt(PyObject* val, bool strict, bool &ok) {
746767
} else if (val == Py_True) {
747768
d = 1;
748769
} else {
749-
ok = false;
770+
PyErr_Clear();
771+
// PyInt_AsLong will try conversion to an int if the object is not an int:
772+
d = PyInt_AsLong(val);
773+
if (PyErr_Occurred()) {
774+
ok = false;
775+
PyErr_Clear();
776+
}
750777
}
751778
} else {
752779
ok = false;
@@ -772,7 +799,13 @@ qint64 PythonQtConv::PyObjGetLongLong(PyObject* val, bool strict, bool &ok) {
772799
} else if (val == Py_True) {
773800
d = 1;
774801
} else {
775-
ok = false;
802+
PyErr_Clear();
803+
// PyLong_AsLongLong will try conversion to an int if the object is not an int:
804+
d = PyLong_AsLongLong(val);
805+
if (PyErr_Occurred()) {
806+
ok = false;
807+
PyErr_Clear();
808+
}
776809
}
777810
} else {
778811
ok = false;
@@ -798,7 +831,13 @@ quint64 PythonQtConv::PyObjGetULongLong(PyObject* val, bool strict, bool &ok) {
798831
} else if (val == Py_True) {
799832
d = 1;
800833
} else {
801-
ok = false;
834+
PyErr_Clear();
835+
// PyLong_AsLongLong will try conversion to an int if the object is not an int:
836+
d = PyLong_AsLongLong(val);
837+
if (PyErr_Occurred()) {
838+
PyErr_Clear();
839+
ok = false;
840+
}
802841
}
803842
} else {
804843
ok = false;
@@ -821,7 +860,13 @@ double PythonQtConv::PyObjGetDouble(PyObject* val, bool strict, bool &ok) {
821860
} else if (val == Py_True) {
822861
d = 1;
823862
} else {
824-
ok = false;
863+
PyErr_Clear();
864+
// PyFloat_AsDouble will try conversion to a double if the object is not a float:
865+
d = PyFloat_AsDouble(val);
866+
if (PyErr_Occurred()) {
867+
PyErr_Clear();
868+
ok = false;
869+
}
825870
}
826871
} else {
827872
ok = false;

src/PythonQtInstanceWrapper.cpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -64,7 +64,7 @@ static void PythonQtInstanceWrapper_deleteObject(PythonQtInstanceWrapper* self,
6464
// we own our qobject, so we delete it now:
6565
delete self->_obj;
6666
self->_obj = NULL;
67-
if (force || self->classInfo()->hasOwnerMethodButNoOwner(self->_wrappedPtr) || self->_ownedByPythonQt) {
67+
if (force || self->_ownedByPythonQt) {
6868
int type = self->classInfo()->metaTypeId();
6969
if (self->_useQMetaTypeDestroy && type>=0) {
7070
// use QMetaType to destroy the object

src/PythonQtMethodInfo.cpp

Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -197,6 +197,31 @@ int PythonQtMethodInfo::nameToType(const char* name)
197197
_parameterTypeDict.insert("QString", QMetaType::QString);
198198
_parameterTypeDict.insert("", QMetaType::Void);
199199
_parameterTypeDict.insert("void", QMetaType::Void);
200+
201+
// GL types
202+
_parameterTypeDict.insert("GLenum", QMetaType::UInt);
203+
_parameterTypeDict.insert("GLboolean", QMetaType::UChar);
204+
_parameterTypeDict.insert("GLbitfield", QMetaType::UInt);
205+
_parameterTypeDict.insert("GLbyte", QMetaType::Char);
206+
_parameterTypeDict.insert("GLubyte", QMetaType::UChar);
207+
_parameterTypeDict.insert("GLshort", QMetaType::Short);
208+
_parameterTypeDict.insert("GLushort", QMetaType::UShort);
209+
_parameterTypeDict.insert("GLint", QMetaType::Int);
210+
_parameterTypeDict.insert("GLuint", QMetaType::UInt);
211+
_parameterTypeDict.insert("GLsizei", QMetaType::UInt);
212+
_parameterTypeDict.insert("GLclampf", QMetaType::Float);
213+
_parameterTypeDict.insert("GLfloat", QMetaType::Float);
214+
_parameterTypeDict.insert("GLclampd", QMetaType::Double);
215+
_parameterTypeDict.insert("GLdouble", QMetaType::Double);
216+
_parameterTypeDict.insert("GLvoid", QMetaType::Void);
217+
if (QT_POINTER_SIZE == 8) {
218+
_parameterTypeDict.insert("qgl_GLintptr", QMetaType::LongLong);
219+
_parameterTypeDict.insert("qgl_GLsizeiptr", QMetaType::LongLong);
220+
} else {
221+
_parameterTypeDict.insert("qgl_GLintptr", QMetaType::Int);
222+
_parameterTypeDict.insert("qgl_GLsizeiptr", QMetaType::Int);
223+
}
224+
200225
// QVariant names
201226
_parameterTypeDict.insert("Q_LLONG", QMetaType::LongLong);
202227
_parameterTypeDict.insert("Q_ULLONG", QMetaType::ULongLong);

0 commit comments

Comments
 (0)