Skip to content

Upstream patches r445 to r455 #52

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Closed
wants to merge 2 commits into from
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -46,7 +46,7 @@ endif()

# Qt components
set(qt5libs Core Widgets Network OpenGL Sql Svg UiTools Xml XmlPatterns)
if(PythonQt_QT_VERSION VERSION_GREATER "4" AND "${Qt5_VERSION}" VERSION_LESS "5.6.0")
if(PythonQt_QT_VERSION VERSION_GREATER "4")
list(APPEND qt5libs WebKitWidgets)
endif()
set(qt4libs core gui network opengl sql svg uitools webkit xml xmlpatterns)
Expand Down
3 changes: 2 additions & 1 deletion extensions/PythonQt_QtAll/PythonQt_QtAll.pro
Original file line number Diff line number Diff line change
@@ -1,13 +1,14 @@
# If Qt has support for webkit, add it:
qtHaveModule(webkit):CONFIG += PythonQtWebKit

TARGET = PythonQt_QtAll
TARGET = PythonQt_QtAll-Qt5-PythonXY
TEMPLATE = lib

DESTDIR = ../../lib

include ( ../../build/common.prf )
include ( ../../build/PythonQt.prf )
TARGET = $$replace(TARGET, PythonXY, Python$${PYTHON_VERSION})

CONFIG += dll qt

Expand Down
6 changes: 6 additions & 0 deletions generator/qtscript_masterinclude.h
Original file line number Diff line number Diff line change
Expand Up @@ -43,6 +43,12 @@
#define Q_BYTE_ORDER Q_LITTLE_ENDIAN

#define QT_NO_STL
#define override
#define final
#define QOPENGLVERSIONFUNCTIONS_H
#define QOPENGLFUNCTIONS_H
#define QOPENGLEXTRAFUNCTIONS_H

#include <QtCore/QtCore>
#include <QtGui/QtGui>
#include <QtNetwork/QtNetwork>
Expand Down
21 changes: 19 additions & 2 deletions src/PythonQt.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1955,15 +1955,31 @@ const QMetaObject* PythonQtPrivate::getDynamicMetaObject(PythonQtInstanceWrapper
PythonQtDynamicClassInfo* info = wrapper->dynamicClassInfo();
if (info) {
if (!info->_dynamicMetaObject) {
buildDynamicMetaObject(((PythonQtClassWrapper*)Py_TYPE(wrapper)), prototypeMetaObject);
setupDynamicMetaObjectChain(((PythonQtClassWrapper*)Py_TYPE(wrapper)), prototypeMetaObject);
}
return info->_dynamicMetaObject;
}
return prototypeMetaObject;
}

void PythonQtPrivate::buildDynamicMetaObject(PythonQtClassWrapper* type, const QMetaObject* prototypeMetaObject)
const QMetaObject* PythonQtPrivate::setupDynamicMetaObjectChain(PythonQtClassWrapper* type, const QMetaObject* prototypeMetaObject)
{
if (!type->_dynamicClassInfo->_dynamicMetaObject) {
PyTypeObject* superType = ((PyTypeObject *)type)->tp_base;
const QMetaObject* metaObjectOfParent = prototypeMetaObject;
if (((PythonQtClassWrapper*)superType)->_dynamicClassInfo) {
metaObjectOfParent = setupDynamicMetaObjectChain((PythonQtClassWrapper*)superType, prototypeMetaObject);
}
return buildDynamicMetaObject(type, metaObjectOfParent);
} else {
return type->_dynamicClassInfo->_dynamicMetaObject;
}
}

const QMetaObject* PythonQtPrivate::buildDynamicMetaObject(PythonQtClassWrapper* type, const QMetaObject* prototypeMetaObject)
{
//std::cout << "creating " << ((PyTypeObject*)type)->tp_name << " derived from " << prototypeMetaObject->className() << std::endl;

QMetaObjectBuilder builder;
builder.setSuperClass(prototypeMetaObject);
builder.setClassName(((PyTypeObject*)type)->tp_name);
Expand Down Expand Up @@ -2048,6 +2064,7 @@ void PythonQtPrivate::buildDynamicMetaObject(PythonQtClassWrapper* type, const Q
// we don't need an own meta object, just use the one from our base class
type->_dynamicClassInfo->_dynamicMetaObject = prototypeMetaObject;
}
return type->_dynamicClassInfo->_dynamicMetaObject;
}


Expand Down
6 changes: 5 additions & 1 deletion src/PythonQt.h
Original file line number Diff line number Diff line change
Expand Up @@ -742,7 +742,11 @@ class PYTHONQT_EXPORT PythonQtPrivate : public QObject {
//! get the dynamic meta object for the given wrapper. It will contain the signals/slots that have been added in Python
const QMetaObject* getDynamicMetaObject(PythonQtInstanceWrapper* wrapper, const QMetaObject* prototypeMetaObject);

void buildDynamicMetaObject(PythonQtClassWrapper* type, const QMetaObject* prototypeMetaObject);
//! recursively creates the dynamic meta object chain down to the Qt class wrapper.
const QMetaObject* setupDynamicMetaObjectChain(PythonQtClassWrapper* type, const QMetaObject* prototypeMetaObject);

//! builds and returns the dynamic meta object for the given type, derived from prototypeMetaObject.
const QMetaObject* buildDynamicMetaObject(PythonQtClassWrapper* type, const QMetaObject* prototypeMetaObject);

//! redirected from shell classes, tries to call the given meta call on the Python wrapper.
int handleMetaCall(QObject* object, PythonQtInstanceWrapper* wrapper, QMetaObject::Call call, int id, void** args);
Expand Down
50 changes: 43 additions & 7 deletions src/PythonQtClassInfo.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -61,6 +61,7 @@ PythonQtClassInfo::PythonQtClassInfo() {
_typeSlots = 0;
_isQObject = false;
_enumsCreated = false;
_richCompareDetectionDone = false;
_searchPolymorphicHandlerOnParent = true;
_searchRefCountCB = true;
_refCallback = NULL;
Expand Down Expand Up @@ -737,14 +738,14 @@ QObject* PythonQtClassInfo::decorator()
_decoratorProvider->setParent(PythonQt::priv());
// setup enums early, since they might be needed by the constructor decorators:
if (!_enumsCreated) {
createEnumWrappers();
createEnumWrappers(_decoratorProvider);
}
PythonQt::priv()->addDecorators(_decoratorProvider, PythonQtPrivate::ConstructorDecorator | PythonQtPrivate::DestructorDecorator);
}
}
// check if enums need to be created and create them if they are not yet created
if (!_enumsCreated) {
createEnumWrappers();
createEnumWrappers(_decoratorProvider);
}
return _decoratorProvider;
}
Expand Down Expand Up @@ -856,26 +857,30 @@ void PythonQtClassInfo::createEnumWrappers(const QMetaObject* meta)
}
}

void PythonQtClassInfo::createEnumWrappers()
void PythonQtClassInfo::createEnumWrappers(const QObject* decoratorProvider)
{
if (!_enumsCreated) {
_enumsCreated = true;
if (_meta) {
createEnumWrappers(_meta);
}
if (decorator()) {
createEnumWrappers(decorator()->metaObject());
if (decoratorProvider) {
createEnumWrappers(decoratorProvider->metaObject());
}
Q_FOREACH(const ParentClassInfo& info, _parentClasses) {
info._parent->createEnumWrappers();
// trigger decorator() instead of createEnumWrappers(),
// which will then call createEnumWrappers().
info._parent->decorator();
}
}
}

PyObject* PythonQtClassInfo::findEnumWrapper(const char* name) {
// force enum creation
if (!_enumsCreated) {
createEnumWrappers();
// trigger decorator() instead of createEnumWrappers(),
// which will then call createEnumWrappers().
decorator();
}
Q_FOREACH(const PythonQtObjectPtr& p, _enumWrappers) {
const char* className = ((PyTypeObject*)p.object())->tp_name;
Expand Down Expand Up @@ -1029,11 +1034,42 @@ PythonQtClassInfo* PythonQtClassInfo::getClassInfoForProperty( const QString& na
}
}
if (!typeName.isEmpty()) {
if (typeName.endsWith("*")) {
typeName.truncate(typeName.length() - 1);
}
PythonQtClassInfo* classInfo = PythonQt::priv()->getClassInfo(typeName);
return classInfo;
}
return NULL;
}

bool PythonQtClassInfo::supportsRichCompare()
{
if (_typeSlots & PythonQt::Type_RichCompare) {
return true;
}
if (!_richCompareDetectionDone) {
_richCompareDetectionDone = true;
static QList<QByteArray> names;
if (names.isEmpty()) {
names << "__eq__";
names << "__ne__";
names << "__lt__";
names << "__le__";
names << "__gt__";
names << "__ge__";
}
foreach (const QByteArray& name, names) {
if (member(name)._type == PythonQtMemberInfo::Slot) {
// we found one of the operators, so we can support the type slot
_typeSlots |= PythonQt::Type_RichCompare;
break;
}
}
}
return (_typeSlots & PythonQt::Type_RichCompare);
}

//-------------------------------------------------------------------------

PythonQtMemberInfo::PythonQtMemberInfo( PythonQtSlotInfo* info )
Expand Down
11 changes: 9 additions & 2 deletions src/PythonQtClassInfo.h
Original file line number Diff line number Diff line change
Expand Up @@ -185,7 +185,7 @@ class PYTHONQT_EXPORT PythonQtClassInfo {
void setShellSetInstanceWrapperCB(PythonQtShellSetInstanceWrapperCB* cb) {
_shellSetInstanceWrapperCB = cb;
}

//! get the shell set instance wrapper cb
PythonQtShellSetInstanceWrapperCB* shellSetInstanceWrapperCB() {
return _shellSetInstanceWrapperCB;
Expand Down Expand Up @@ -230,10 +230,16 @@ class PYTHONQT_EXPORT PythonQtClassInfo {
//! Returns the class info for given property, if available.
PythonQtClassInfo* getClassInfoForProperty( const QString& name );

//! Returns if the class supports rich compare. This tests for
//! __eq__, __ne__, __lt__, __le__, __gt__, __ge__ slots and if
//! any of the slots is present it returns true and modifies the
//! _typeSlots with Type_RichCompare. The result is cached internally.
bool supportsRichCompare();

private:
void updateRefCountingCBs();

void createEnumWrappers();
void createEnumWrappers(const QObject* decoratorProvider);
void createEnumWrappers(const QMetaObject* meta);
PyObject* findEnumWrapper(const char* name);

Expand Down Expand Up @@ -289,6 +295,7 @@ class PYTHONQT_EXPORT PythonQtClassInfo {

bool _isQObject;
bool _enumsCreated;
bool _richCompareDetectionDone;
bool _searchPolymorphicHandlerOnParent;
bool _searchRefCountCB;

Expand Down
21 changes: 14 additions & 7 deletions src/PythonQtClassWrapper.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -366,8 +366,17 @@ static int PythonQtClassWrapper_init(PythonQtClassWrapper* self, PyObject* args,

// take the class info from the superType
self->_classInfo = ((PythonQtClassWrapper*)superType)->classInfo();

self->_dynamicClassInfo = new PythonQtDynamicClassInfo();

// take the class info from the superType and fill the whole chain
PyTypeObject* typeChain = (PyTypeObject *)self;
while (typeChain && Py_TYPE(typeChain) != &PythonQtClassWrapper_Type) {

((PythonQtClassWrapper*)typeChain)->_classInfo = ((PythonQtClassWrapper*)superType)->classInfo();
((PythonQtClassWrapper*)typeChain)->_dynamicClassInfo = new PythonQtDynamicClassInfo();

typeChain = typeChain->tp_base;
}
}

return 0;
Expand Down Expand Up @@ -457,12 +466,10 @@ static PyObject *PythonQtClassWrapper_getattro(PyObject *obj, PyObject *name)
}
PyObject* dict = PyDict_New();

QStringList l = wrapper->classInfo()->memberList();
Q_FOREACH (QString name, l) {
if (name.startsWith("py_get_")) {
// add slot getters as normal properties
name = name.mid(7);
}
QSet<QString> completeSet = QSet<QString>::fromList(wrapper->classInfo()->memberList());
completeSet.unite(QSet<QString>::fromList(wrapper->classInfo()->propertyList()));

Q_FOREACH (QString name, completeSet) {
if (name.startsWith("py_")) {
// do not expose internal slots
continue;
Expand Down
28 changes: 20 additions & 8 deletions src/PythonQtConversion.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -55,6 +55,8 @@ PythonQtValueStorageWithCleanup<QVariant, 128> PythonQtConv::global_variantStora
QHash<int, PythonQtConvertMetaTypeToPythonCB*> PythonQtConv::_metaTypeToPythonConverters;
QHash<int, PythonQtConvertPythonToMetaTypeCB*> PythonQtConv::_pythonToMetaTypeConverters;

PythonQtConvertPythonSequenceToQVariantListCB* PythonQtConv::_pythonSequenceToQVariantListCB = NULL;

PyObject* PythonQtConv::GetPyBool(bool val)
{
PyObject* r = val?Py_True:Py_False;
Expand Down Expand Up @@ -102,7 +104,7 @@ PyObject* PythonQtConv::ConvertQtValueToPython(const PythonQtMethodInfo::Paramet
}
}

if (info.typeId >= QMetaType::User) {
if (info.typeId >= QMetaType::User || info.typeId == QMetaType::QByteArrayList) {
// if a converter is registered, we use is:
PythonQtConvertMetaTypeToPythonCB* converter = _metaTypeToPythonConverters.value(info.typeId);
if (converter) {
Expand Down Expand Up @@ -668,7 +670,7 @@ void* PythonQtConv::ConvertPythonToQt(const PythonQtMethodInfo::ParameterInfo& i
}

// We only do this for registered type > QMetaType::User for performance reasons.
if (info.typeId >= QMetaType::User) {
if (info.typeId >= QMetaType::User || info.typeId == QMetaType::QByteArrayList) {
// Maybe we have a special converter that is registered for that type:
PythonQtConvertPythonToMetaTypeCB* converter = _pythonToMetaTypeConverters.value(info.typeId);
if (converter) {
Expand Down Expand Up @@ -1028,13 +1030,13 @@ QVariant PythonQtConv::PyObjToQVariant(PyObject* val, int type)
v = qVariantFromValue(myObject);
}
return v;
} else if (val == Py_None) {
// none is invalid
type = QVariant::Invalid;
} else if (PyDict_Check(val)) {
type = QVariant::Map;
} else if (PyList_Check(val) || PyTuple_Check(val) || PySequence_Check(val)) {
type = QVariant::List;
} else if (val == Py_None) {
// none is invalid
type = QVariant::Invalid;
} else {
// this used to be:
// type = QVariant::String;
Expand Down Expand Up @@ -1151,20 +1153,30 @@ QVariant PythonQtConv::PyObjToQVariant(PyObject* val, int type)
pythonToMapVariant<QVariantHash>(val, v);
break;
case QVariant::List:
if (PySequence_Check(val)) {
{
bool isListOrTuple = PyList_Check(val) || PyTuple_Check(val);
if (isListOrTuple || PySequence_Check(val)) {
if (!isListOrTuple && _pythonSequenceToQVariantListCB) {
// Only call this if we don't have a tuple or list.
QVariant result = (*_pythonSequenceToQVariantListCB)(val);
if (result.isValid()) {
return result;
}
}
int count = PySequence_Size(val);
if (count >= 0) {
// only get items if size is valid (>= 0)
QVariantList list;
PyObject* value;
for (int i = 0;i<count;i++) {
value = PySequence_GetItem(val,i);
for (int i = 0; i < count; i++) {
value = PySequence_GetItem(val, i);
list.append(PyObjToQVariant(value, -1));
Py_XDECREF(value);
}
v = list;
}
}
}
break;
case QVariant::StringList:
{
Expand Down
6 changes: 6 additions & 0 deletions src/PythonQtConversion.h
Original file line number Diff line number Diff line change
Expand Up @@ -52,6 +52,7 @@

typedef PyObject* PythonQtConvertMetaTypeToPythonCB(const void* inObject, int metaTypeId);
typedef bool PythonQtConvertPythonToMetaTypeCB(PyObject* inObject, void* outObject, int metaTypeId, bool strict);
typedef QVariant PythonQtConvertPythonSequenceToQVariantListCB(PyObject* inObject);

#define PythonQtRegisterListTemplateConverter(type, innertype) \
{ int typeId = qRegisterMetaType<type<innertype > >(#type"<"#innertype">"); \
Expand Down Expand Up @@ -164,6 +165,10 @@ class PYTHONQT_EXPORT PythonQtConv {
//! register a converter callback from cpp to python for given metatype
static void registerMetaTypeToPythonConverter(int metaTypeId, PythonQtConvertMetaTypeToPythonCB* cb) { _metaTypeToPythonConverters.insert(metaTypeId, cb); }

//! set a callback that is called when a Python sequence should be converted to a QVariantList
//! to allow special conversion.
static void setPythonSequenceToQVariantListCallback(PythonQtConvertPythonSequenceToQVariantListCB* cb) { _pythonSequenceToQVariantListCB = cb; }

//! converts the Qt parameter given in \c data, interpreting it as a \c type registered qvariant/meta type, into a Python object,
static PyObject* convertQtValueToPythonInternal(int type, const void* data);

Expand Down Expand Up @@ -194,6 +199,7 @@ class PYTHONQT_EXPORT PythonQtConv {
protected:
static QHash<int, PythonQtConvertMetaTypeToPythonCB*> _metaTypeToPythonConverters;
static QHash<int, PythonQtConvertPythonToMetaTypeCB*> _pythonToMetaTypeConverters;
static PythonQtConvertPythonSequenceToQVariantListCB* _pythonSequenceToQVariantListCB;

//! handle automatic conversion of some special types (QColor, QBrush, ...)
static void* handlePythonToQtAutoConversion(int typeId, PyObject* obj, void* alreadyAllocatedCPPObject);
Expand Down
Loading