aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorHugo Parente Lima <hugo.pl@gmail.com>2011-07-20 10:41:31 -0300
committerHugo Parente Lima <hugo.pl@gmail.com>2012-03-08 16:54:37 -0300
commite37426c8c4a1f041c2f4b9c0f560751aa4b9a924 (patch)
treecbcd4d631282a8cc7818cb4674bae6227a603c87
parent8ec69343969dd1ef767d9c8d38ce49d4280e5d4c (diff)
Fix bug 926 - "qmlRegisterType does not work with QObject"
Reviewer: Luciano Wolf <luciano.wolf@openbossa.org> Lauro Neto <lauro.neto@openbossa.org>
-rw-r--r--PySide/QtDeclarative/pysideqmlregistertype.cpp32
-rw-r--r--PySide/QtDeclarative/typesystem_declarative.xml8
-rw-r--r--libpyside/pyside.cpp47
-rw-r--r--libpyside/pyside.h8
-rw-r--r--tests/QtDeclarative/CMakeLists.txt1
-rw-r--r--tests/QtDeclarative/bug_926.py38
-rw-r--r--tests/QtDeclarative/bug_926.qml17
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&lt;%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
+ }
+}