diff options
-rw-r--r-- | PySide/QtDeclarative/pysideqmlregistertype.cpp | 32 | ||||
-rw-r--r-- | PySide/QtDeclarative/typesystem_declarative.xml | 8 | ||||
-rw-r--r-- | libpyside/pyside.cpp | 47 | ||||
-rw-r--r-- | libpyside/pyside.h | 8 | ||||
-rw-r--r-- | tests/QtDeclarative/CMakeLists.txt | 1 | ||||
-rw-r--r-- | tests/QtDeclarative/bug_926.py | 38 | ||||
-rw-r--r-- | tests/QtDeclarative/bug_926.qml | 17 |
7 files changed, 119 insertions, 32 deletions
diff --git a/PySide/QtDeclarative/pysideqmlregistertype.cpp b/PySide/QtDeclarative/pysideqmlregistertype.cpp index f5b878be3..f769fa020 100644 --- a/PySide/QtDeclarative/pysideqmlregistertype.cpp +++ b/PySide/QtDeclarative/pysideqmlregistertype.cpp @@ -52,9 +52,7 @@ static void propListMetaCall(PySideProperty* pp, PyObject* self, QMetaObject::Ca static PyObject* pyTypes[PYSIDE_MAX_QML_TYPES]; static void (*createFuncs[PYSIDE_MAX_QML_TYPES])(void*); -/// QDeclarativeItem will create objects using placement new then this pointer is non-null. -void* PySide::nextQmlElementMemoryAddr = 0; -// Mutex used to avoid race condition on PySide::nextQmlElementMemoryAddr +// Mutex used to avoid race condition on PySide::nextQObjectMemoryAddr static QMutex nextQmlElementMutex; template<int N> @@ -63,12 +61,12 @@ struct ElementFactoryBase static void createInto(void* memory) { QMutexLocker locker(&nextQmlElementMutex); - PySide::nextQmlElementMemoryAddr = memory; + PySide::setNextQObjectMemoryAddr(memory); Shiboken::GilState state; PyObject* obj = PyObject_CallObject(pyTypes[N], 0); if (!obj || PyErr_Occurred()) PyErr_Print(); - PySide::nextQmlElementMemoryAddr = 0; + PySide::setNextQObjectMemoryAddr(0); } }; @@ -95,8 +93,8 @@ int PySide::qmlRegisterType(PyObject* pyObj, const char* uri, int versionMajor, { using namespace Shiboken; - static PyTypeObject* declarativeItemType = TypeResolver::get("QDeclarativeItem*")->pythonType(); - assert(declarativeItemType); + static PyTypeObject* qobjectType = TypeResolver::get("QObject*")->pythonType(); + assert(qobjectType); static int nextType = 0; if (nextType >= PYSIDE_MAX_QML_TYPES) { @@ -104,8 +102,8 @@ int PySide::qmlRegisterType(PyObject* pyObj, const char* uri, int versionMajor, return -1; } - if (!PySequence_Contains(((PyTypeObject*)pyObj)->tp_mro, (PyObject*)declarativeItemType)) { - PyErr_Format(PyExc_TypeError, "A type inherited from %s expected, got %s.", declarativeItemType->tp_name, ((PyTypeObject*)pyObj)->tp_name); + if (!PySequence_Contains(((PyTypeObject*)pyObj)->tp_mro, (PyObject*)qobjectType)) { + PyErr_Format(PyExc_TypeError, "A type inherited from %s expected, got %s.", qobjectType->tp_name, ((PyTypeObject*)pyObj)->tp_name); return -1; } @@ -118,9 +116,9 @@ int PySide::qmlRegisterType(PyObject* pyObj, const char* uri, int versionMajor, // Init proxy object static meta object QDeclarativePrivate::RegisterType type; type.version = 0; - type.typeId = qMetaTypeId<QDeclarativeItem*>(); - type.listId = qMetaTypeId<QDeclarativeListProperty<QDeclarativeItem> >(); - type.objectSize = sizeof(QDeclarativeItemWrapper); + type.typeId = qMetaTypeId<QObject*>(); + type.listId = qMetaTypeId<QDeclarativeListProperty<QObject> >(); + type.objectSize = PySide::getSizeOfQObject(reinterpret_cast<SbkObjectType*>(pyObj)); type.create = createFuncs[nextType]; type.uri = uri; type.versionMajor = versionMajor; @@ -128,12 +126,12 @@ int PySide::qmlRegisterType(PyObject* pyObj, const char* uri, int versionMajor, type.elementName = qmlName; type.metaObject = metaObject; - type.attachedPropertiesFunction = QDeclarativePrivate::attachedPropertiesFunc<QDeclarativeItem>(); - type.attachedPropertiesMetaObject = QDeclarativePrivate::attachedPropertiesMetaObject<QDeclarativeItem>(); + type.attachedPropertiesFunction = QDeclarativePrivate::attachedPropertiesFunc<QObject>(); + type.attachedPropertiesMetaObject = QDeclarativePrivate::attachedPropertiesMetaObject<QObject>(); - type.parserStatusCast = QDeclarativePrivate::StaticCastSelector<QDeclarativeItem,QDeclarativeParserStatus>::cast(); - type.valueSourceCast = QDeclarativePrivate::StaticCastSelector<QDeclarativeItem,QDeclarativePropertyValueSource>::cast(); - type.valueInterceptorCast = QDeclarativePrivate::StaticCastSelector<QDeclarativeItem,QDeclarativePropertyValueInterceptor>::cast(); + type.parserStatusCast = QDeclarativePrivate::StaticCastSelector<QObject, QDeclarativeParserStatus>::cast(); + type.valueSourceCast = QDeclarativePrivate::StaticCastSelector<QObject, QDeclarativePropertyValueSource>::cast(); + type.valueInterceptorCast = QDeclarativePrivate::StaticCastSelector<QObject, QDeclarativePropertyValueInterceptor>::cast(); type.extensionObjectCreate = 0; type.extensionMetaObject = 0; diff --git a/PySide/QtDeclarative/typesystem_declarative.xml b/PySide/QtDeclarative/typesystem_declarative.xml index e0c7b6d43..a72f601bf 100644 --- a/PySide/QtDeclarative/typesystem_declarative.xml +++ b/PySide/QtDeclarative/typesystem_declarative.xml @@ -103,14 +103,6 @@ <include file-name="pysideqmlregistertype.h" location="local"/> </extra-includes> <enum-type name="TransformOrigin" /> - <modify-function signature="QDeclarativeItem(QDeclarativeItem*)"> - <inject-code class="target"> - if (PySide::nextQmlElementMemoryAddr) - %0 = new (PySide::nextQmlElementMemoryAddr) ::QDeclarativePrivate::QDeclarativeElement<%TYPE>(); - else - %0 = new %TYPE(%1); - </inject-code> - </modify-function> </object-type> <value-type name="QDeclarativeListReference" /> diff --git a/libpyside/pyside.cpp b/libpyside/pyside.cpp index ea48b1785..325e27402 100644 --- a/libpyside/pyside.cpp +++ b/libpyside/pyside.cpp @@ -44,12 +44,14 @@ #include <QDebug> static QStack<PySide::CleanupFunction> cleanupFunctionList; +static void* qobjectNextAddr; namespace PySide { void init(PyObject *module) { + qobjectNextAddr = 0; ClassInfo::init(module); Signal::init(module); Slot::init(module); @@ -148,17 +150,35 @@ void destroyQCoreApplication() delete app; } -void initDynamicMetaObject(SbkObjectType* type, const QMetaObject* base) +struct TypeUserData { + TypeUserData(PyTypeObject* type, const QMetaObject* metaobject) : mo(type, metaobject) {} + DynamicQMetaObject mo; + std::size_t cppObjSize; +}; + +std::size_t getSizeOfQObject(SbkObjectType* type) +{ + using namespace Shiboken::ObjectType; + TypeUserData* userData = reinterpret_cast<TypeUserData*>(getTypeUserData(reinterpret_cast<SbkObjectType*>(type))); + return userData->cppObjSize; +} + +void initDynamicMetaObject(SbkObjectType* type, const QMetaObject* base, const std::size_t& cppObjSize) { //create DynamicMetaObject based on python type - DynamicQMetaObject* mo = new PySide::DynamicQMetaObject(reinterpret_cast<PyTypeObject*>(type), base); - Shiboken::ObjectType::setTypeUserData(type, mo, Shiboken::callCppDestructor<DynamicQMetaObject>); + TypeUserData* userData = new TypeUserData(reinterpret_cast<PyTypeObject*>(type), base); + userData->cppObjSize = cppObjSize; + Shiboken::ObjectType::setTypeUserData(type, userData, Shiboken::callCppDestructor<TypeUserData>); //initialize staticQMetaObject property - PyObject* pyMetaObject = Shiboken::TypeResolver::get("QMetaObject*")->toPython(&mo); - + void* metaObjectPtr = &userData->mo; + Shiboken::AutoDecRef pyMetaObject(Shiboken::TypeResolver::get("QMetaObject*")->toPython(&metaObjectPtr)); PyObject_SetAttrString(reinterpret_cast<PyObject*>(type), "staticMetaObject", pyMetaObject); - Py_DECREF(pyMetaObject); +} + +void initDynamicMetaObject(SbkObjectType* type, const QMetaObject* base) +{ + initDynamicMetaObject(type, base, 0); } void initQObjectSubType(SbkObjectType* type, PyObject* args, PyObject* kwds) @@ -169,11 +189,13 @@ void initQObjectSubType(SbkObjectType* type, PyObject* args, PyObject* kwds) PyObject* bases = PyTuple_GET_ITEM(args, 1); int numBases = PyTuple_GET_SIZE(bases); QMetaObject* baseMo = 0; + SbkObjectType* qobjBase = 0; for (int i = 0; i < numBases; ++i) { PyTypeObject* base = reinterpret_cast<PyTypeObject*>(PyTuple_GET_ITEM(bases, i)); if (PyType_IsSubtype(base, qObjType)) { baseMo = reinterpret_cast<QMetaObject*>(Shiboken::ObjectType::getTypeUserData(reinterpret_cast<SbkObjectType*>(base))); + qobjBase = reinterpret_cast<SbkObjectType*>(base); break; } } @@ -182,7 +204,8 @@ void initQObjectSubType(SbkObjectType* type, PyObject* args, PyObject* kwds) return; } - initDynamicMetaObject(type, baseMo); + TypeUserData* userData = reinterpret_cast<TypeUserData*>(Shiboken::ObjectType::getTypeUserData(qobjBase)); + initDynamicMetaObject(type, baseMo, userData->cppObjSize); } PyObject* getMetaDataFromQObject(QObject* cppSelf, PyObject* self, PyObject* name) @@ -249,5 +272,15 @@ bool inherits(PyTypeObject* objType, const char* class_name) return inherits(base, class_name); } +void* nextQObjectMemoryAddr() +{ + return qobjectNextAddr; +} + +void setNextQObjectMemoryAddr(void* addr) +{ + qobjectNextAddr = addr; +} + } //namespace PySide diff --git a/libpyside/pyside.h b/libpyside/pyside.h index 747b08da8..3ef7d3881 100644 --- a/libpyside/pyside.h +++ b/libpyside/pyside.h @@ -77,9 +77,14 @@ template<typename T> struct initQtMetaType<T, false> { }; +/// \deprecated PYSIDE_API void initDynamicMetaObject(SbkObjectType* type, const QMetaObject* base); +PYSIDE_API void initDynamicMetaObject(SbkObjectType* type, const QMetaObject* base, const std::size_t& cppObjSize); PYSIDE_API void initQObjectSubType(SbkObjectType* type, PyObject* args, PyObject* kwds); +/// Return the size in bytes of a type that inherits QObject. +PYSIDE_API std::size_t getSizeOfQObject(SbkObjectType* type); + typedef void (*CleanupFunction)(void); /** @@ -110,6 +115,9 @@ PYSIDE_API PyObject* getMetaDataFromQObject(QObject* cppSelf, PyObject* self, Py */ PYSIDE_API bool inherits(PyTypeObject* self, const char* class_name); +PYSIDE_API void* nextQObjectMemoryAddr(); +PYSIDE_API void setNextQObjectMemoryAddr(void* addr); + } //namespace PySide diff --git a/tests/QtDeclarative/CMakeLists.txt b/tests/QtDeclarative/CMakeLists.txt index b319d86b7..31ea6e75e 100644 --- a/tests/QtDeclarative/CMakeLists.txt +++ b/tests/QtDeclarative/CMakeLists.txt @@ -6,6 +6,7 @@ PYSIDE_TEST(bug_814.py) PYSIDE_TEST(bug_825.py) PYSIDE_TEST(bug_847.py) PYSIDE_TEST(bug_915.py) +PYSIDE_TEST(bug_926.py) PYSIDE_TEST(qdeclarativenetwork_test.py) PYSIDE_TEST(qdeclarativeview_test.py) PYSIDE_TEST(connect_python_qml.py) diff --git a/tests/QtDeclarative/bug_926.py b/tests/QtDeclarative/bug_926.py new file mode 100644 index 000000000..54b659036 --- /dev/null +++ b/tests/QtDeclarative/bug_926.py @@ -0,0 +1,38 @@ +import sys +import unittest +from helper import adjust_filename +from PySide.QtCore import * +from PySide.QtGui import * +from PySide.QtDeclarative import * + +class MyClass (QObject): + + def __init__(self): + super(MyClass,self).__init__() + self.__url = QUrl() + + def getUrl(self): + return self.__url + + def setUrl(self,value): + newUrl = QUrl(value) + if (newUrl != self.__url): + self.__url = newUrl + self.urlChanged.emit() + + urlChanged = Signal() + urla = Property(QUrl, getUrl, setUrl, notify = urlChanged) + +class TestBug926 (unittest.TestCase): + def testIt(self): + app = QApplication([]) + qmlRegisterType(MyClass,'Example',1,0,'MyClass') + view = QDeclarativeView() + view.setSource(QUrl.fromLocalFile(adjust_filename('bug_926.qml', __file__))) + self.assertEqual(len(view.errors()), 0) + view.show() + QTimer.singleShot(0, app.quit) + app.exec_() + +if __name__ == '__main__': + unittest.main() diff --git a/tests/QtDeclarative/bug_926.qml b/tests/QtDeclarative/bug_926.qml new file mode 100644 index 000000000..50895db1c --- /dev/null +++ b/tests/QtDeclarative/bug_926.qml @@ -0,0 +1,17 @@ +import Qt 4.7 +import Example 1.0 + +Rectangle { + width: 100 + height: 62 + + MyClass { + id: myClass + urla: "http://www.pyside.org" + } + + Text { + id: name + text: myClass.urla + } +} |