diff options
-rw-r--r-- | PySide/QtDeclarative/typesystem_declarative.xml | 9 | ||||
-rw-r--r-- | PySide/QtGui/glue/qlayout_help_functions.h | 2 | ||||
-rw-r--r-- | PySide/QtGui/typesystem_gui_common.xml | 2 | ||||
-rw-r--r-- | doc/codesnippets/doc/src/snippets/network/tcpwait.cpp | 7 | ||||
-rw-r--r-- | libpyside/dynamicqmetaobject.cpp | 47 | ||||
-rw-r--r-- | libpyside/dynamicqmetaobject_p.h | 6 | ||||
-rw-r--r-- | libpyside/globalreceiver.cpp | 9 | ||||
-rw-r--r-- | libpyside/pyside.cpp | 11 | ||||
-rw-r--r-- | libpyside/pysideproperty.cpp | 13 | ||||
-rw-r--r-- | tests/QtCore/qobject_property_test.py | 16 | ||||
-rw-r--r-- | tests/QtGui/CMakeLists.txt | 2 | ||||
-rw-r--r-- | tests/QtGui/bug_467.py | 19 | ||||
-rw-r--r-- | tests/QtGui/bug_480.py | 25 | ||||
-rw-r--r-- | tests/QtNetwork/CMakeLists.txt | 2 | ||||
-rw-r--r-- | tests/QtNetwork/bug_446.py | 48 |
15 files changed, 176 insertions, 42 deletions
diff --git a/PySide/QtDeclarative/typesystem_declarative.xml b/PySide/QtDeclarative/typesystem_declarative.xml index c672a8c78..75c63e093 100644 --- a/PySide/QtDeclarative/typesystem_declarative.xml +++ b/PySide/QtDeclarative/typesystem_declarative.xml @@ -37,7 +37,14 @@ <object-type name="QDeclarativeComponent"> <enum-type name="Status"/> </object-type> - <object-type name="QDeclarativeContext" /> + <object-type name="QDeclarativeContext"> + <modify-function signature="setContextProperty(const QString &, QObject*)"> + <modify-argument index="2"> + <reference-count action="add"/> + </modify-argument> + </modify-function> + </object-type> + <object-type name="QDeclarativeEngine"> <enum-type name="ObjectOwnership" /> <modify-function signature="setNetworkAccessManagerFactory(QDeclarativeNetworkAccessManagerFactory*)"> diff --git a/PySide/QtGui/glue/qlayout_help_functions.h b/PySide/QtGui/glue/qlayout_help_functions.h index b0e8a0e5d..8420cb3ac 100644 --- a/PySide/QtGui/glue/qlayout_help_functions.h +++ b/PySide/QtGui/glue/qlayout_help_functions.h @@ -39,7 +39,7 @@ inline void addLayoutOwnership(QLayout* layout, QLayout* other) } for (int i=0, i_max=other->count(); i < i_max; i++) { - QLayoutItem* item = layout->itemAt(i); + QLayoutItem* item = other->itemAt(i); if (PyErr_Occurred()) return; diff --git a/PySide/QtGui/typesystem_gui_common.xml b/PySide/QtGui/typesystem_gui_common.xml index a5f22d835..cf4b6744c 100644 --- a/PySide/QtGui/typesystem_gui_common.xml +++ b/PySide/QtGui/typesystem_gui_common.xml @@ -2110,7 +2110,7 @@ <enum-type name="MessageIcon"/> <modify-function signature="setContextMenu(QMenu*)"> <modify-argument index="1"> - <parent index="this" action="add"/> + <reference-count action="add"/> </modify-argument> </modify-function> </object-type> diff --git a/doc/codesnippets/doc/src/snippets/network/tcpwait.cpp b/doc/codesnippets/doc/src/snippets/network/tcpwait.cpp index 7ebdc692d..0712b3e5d 100644 --- a/doc/codesnippets/doc/src/snippets/network/tcpwait.cpp +++ b/doc/codesnippets/doc/src/snippets/network/tcpwait.cpp @@ -51,13 +51,12 @@ def main(): //! [0] numRead = 0 numReadTotal = 0 - buffer = "" while(True): - numRead = socket.read(buffer, 50) + buffer = socket.read(50) # do whatever with array - numReadTotal += numRead - if (numRead == 0 && !socket.waitForReadyRead()): + numReadTotal += buffer.size() + if (buffer.size() == 0 && !socket.waitForReadyRead()): break //! [0] return app.exec_() diff --git a/libpyside/dynamicqmetaobject.cpp b/libpyside/dynamicqmetaobject.cpp index 14fbe864e..43aeae66d 100644 --- a/libpyside/dynamicqmetaobject.cpp +++ b/libpyside/dynamicqmetaobject.cpp @@ -132,7 +132,6 @@ static bool isQRealType(const char *type) } - /* * Avoid API break keep this on cpp */ @@ -164,25 +163,31 @@ uint PropertyData::flags() const if (PySide::Property::hasReset(m_data)) flags |= Resettable; - if (!PySide::Property::isDesignable(m_data)) - flags |= ResolveDesignable; - else + if (PySide::Property::isDesignable(m_data)) flags |= Designable; - - if (!PySide::Property::isScriptable(m_data)) - flags |= ResolveScriptable; else - flags |= Scriptable; + flags |= ResolveDesignable; - if (!PySide::Property::isStored(m_data)) - flags |= ResolveStored; + if (PySide::Property::isScriptable(m_data)) + flags |= Scriptable; else - flags |= Stored; + flags |= ResolveScriptable; - if (!PySide::Property::isUser(m_data)) - flags |= ResolveUser; + if (PySide::Property::isStored(m_data)) + flags |= Stored; else + flags |= ResolveStored; + + //EDITABLE + flags |= ResolveEditable; + + if (PySide::Property::isUser(m_data)) flags |= User; + else + flags |= ResolveUser; + + if (m_notifyId != -1) + flags |= Notify; if (PySide::Property::isConstant(m_data)) flags |= Constant; @@ -190,9 +195,6 @@ uint PropertyData::flags() const if (PySide::Property::isFinal(m_data)) flags |= Final; - if (m_notifyId) - flags |= Notify; - return flags; } @@ -247,7 +249,7 @@ PropertyData::PropertyData() { } -PropertyData::PropertyData(const char* name, uint notifyId, PySideProperty* data) +PropertyData::PropertyData(const char* name, int notifyId, PySideProperty* data) : m_name(name), m_notifyId(notifyId), m_data(data) { } @@ -268,7 +270,7 @@ QByteArray PropertyData::name() const return m_name; } -uint PropertyData::notifyId() const +int PropertyData::notifyId() const { return m_notifyId; } @@ -370,10 +372,10 @@ void DynamicQMetaObject::addProperty(const char* propertyName, PyObject* data) // retrieve notifyId PySideProperty* property = reinterpret_cast<PySideProperty*>(data); const char* signalNotify = PySide::Property::getNotifyName(property); - uint notifyId = 0; + int notifyId = -1; if (signalNotify) { QByteArray signalSignature(signalNotify); - notifyId = m_d->m_signals.indexOf(signalNotify) + 1; + notifyId = m_d->m_signals.indexOf(signalNotify); } //search for a empty space @@ -553,9 +555,8 @@ void DynamicQMetaObject::DynamicQMetaObjectPrivate::updateMetaObject(QMetaObject } //write properties notify - foreach(PropertyData pp, m_properties) { - data[index++] = pp.notifyId(); //signal notify index - } + foreach(PropertyData pp, m_properties) + data[index++] = pp.notifyId() >= 0 ? pp.notifyId() : 0; //signal notify index data[index++] = 0; // the end diff --git a/libpyside/dynamicqmetaobject_p.h b/libpyside/dynamicqmetaobject_p.h index d2717524e..e69270041 100644 --- a/libpyside/dynamicqmetaobject_p.h +++ b/libpyside/dynamicqmetaobject_p.h @@ -54,18 +54,18 @@ namespace PySide { public: PropertyData(); - PropertyData(const char* name, uint notifyId=0, PySideProperty* data = 0); + PropertyData(const char* name, int notifyId=0, PySideProperty* data = 0); QByteArray name() const; QByteArray type() const; uint flags() const; bool isValid() const; - uint notifyId() const; + int notifyId() const; bool operator==(const PropertyData& other) const; bool operator==(const char* name) const; private: QByteArray m_name; - uint m_notifyId; + int m_notifyId; PySideProperty* m_data; }; } diff --git a/libpyside/globalreceiver.cpp b/libpyside/globalreceiver.cpp index 2c126044e..d63ebdf66 100644 --- a/libpyside/globalreceiver.cpp +++ b/libpyside/globalreceiver.cpp @@ -116,7 +116,8 @@ GlobalReceiver::GlobalReceiver() GlobalReceiver::~GlobalReceiver() { - foreach(DynamicSlotData* data, m_slotReceivers) { + while(!m_slotReceivers.empty()) { + DynamicSlotData* data = m_slotReceivers.take(m_slotReceivers.begin().key()); data->clear(); delete data; } @@ -203,8 +204,10 @@ int GlobalReceiver::qt_metacall(QMetaObject::Call call, int id, void** args) if (strcmp(slot.signature(), RECEIVER_DESTROYED_SLOT_NAME) == 0) { QObject *arg = *(QObject**)args[1]; - QHash<int, DynamicSlotData*>::iterator i = m_slotReceivers.begin(); - while(i != m_slotReceivers.end()) { + //avoid hash changes during the destruction + QHash<int, DynamicSlotData*> copy = m_slotReceivers; + QHash<int, DynamicSlotData*>::iterator i = copy.begin(); + while(i != copy.end()) { if (i.value()->hasRefTo(arg)) { disconnectNotify(arg, i.key()); break; diff --git a/libpyside/pyside.cpp b/libpyside/pyside.cpp index 2e2f57428..bbec1fa63 100644 --- a/libpyside/pyside.cpp +++ b/libpyside/pyside.cpp @@ -114,12 +114,21 @@ void destroyQCoreApplication() PyTypeObject* pyQObjectType = Shiboken::TypeResolver::get("QObject*")->pythonType(); assert(pyQObjectType); + QList<SbkObject*> objects; + + //filter only QObjects which we have ownership, this will avoid list changes during the destruction of some parent object foreach (SbkObject* pyObj, bm.getAllPyObjects()) { if (pyObj != pyQApp && PyObject_TypeCheck(pyObj, pyQObjectType)) { if (Shiboken::Object::hasOwnership(pyObj)) - Shiboken::callCppDestructor<QObject>(Shiboken::Object::cppPointer(pyObj, Shiboken::SbkType<QObject*>())); + objects << pyObj; } } + + //Now we can destroy all object in the list + foreach (SbkObject* pyObj, objects) + Shiboken::callCppDestructor<QObject>(Shiboken::Object::cppPointer(pyObj, Shiboken::SbkType<QObject*>())); + + // in the end destroy app delete app; } diff --git a/libpyside/pysideproperty.cpp b/libpyside/pysideproperty.cpp index 51f848d67..72b718c58 100644 --- a/libpyside/pysideproperty.cpp +++ b/libpyside/pysideproperty.cpp @@ -117,6 +117,7 @@ int qpropertyTpInit(PyObject* self, PyObject* args, PyObject* kwds) pData->fget = 0; pData->freset = 0; pData->fdel = 0; + pData->final = 0; pData->designable = true; pData->scriptable = true; pData->stored = true; @@ -124,6 +125,7 @@ int qpropertyTpInit(PyObject* self, PyObject* args, PyObject* kwds) pData->doc = 0; pData->notify = 0; pData->notifySignature = 0; + pData->constant = 0; static const char *kwlist[] = {"type", "fget", "fset", "freset", "fdel", "doc", "notify", "designable", "scriptable", "stored", "user", @@ -134,12 +136,17 @@ int qpropertyTpInit(PyObject* self, PyObject* args, PyObject* kwds) /*OOO*/ &(pData->fset), &(pData->freset), &(pData->fdel), /*s*/ &(pData->doc), /*O*/ &(pData->notify), - /*bbbbbb*/ &(pData->designable), &(pData->scriptable), &(pData->stored), &(pData->user), &(pData->constant), &(pData->final))) + /*bbbbbb*/ &(pData->designable), &(pData->scriptable), &(pData->stored), &(pData->user), &(pData->constant), &(pData->final))) { + free(pData); return 0; + } - if (!pData->fset && pData->fget) - pData->constant = true; + if (pData->constant && (pData->fset || pData->notify)) { + free(pData); + PyErr_SetString(PyExc_AttributeError, "A constant property cannot have a WRITE method or a NOTIFY signal."); + return 0; + } pData->typeName = PySide::Signal::getTypeName(type); return 1; } diff --git a/tests/QtCore/qobject_property_test.py b/tests/QtCore/qobject_property_test.py index adb1679f3..bc38dbb18 100644 --- a/tests/QtCore/qobject_property_test.py +++ b/tests/QtCore/qobject_property_test.py @@ -34,7 +34,7 @@ class MyObject(QObject): def trySetPP(self): self.pp = 0 - pp = Property(int, readPP) + pp = Property(int, readPP, constant=True) class MyObjectWithNotifyProperty(QObject): def __init__(self, parent=None): @@ -188,6 +188,20 @@ class PropertyWithNotify(unittest.TestCase): obj.myProperty = 10 self.assert_(self.called_) +class MetaPropertyTest(unittest.TestCase): + def testConstant(self): + obj = MyObject() + mo = obj.metaObject() + self.assertEqual(mo.propertyCount(), 2) + p = mo.property(1) + self.assertTrue(p.isConstant()) + + obj = MyObjectWithNotifyProperty() + mo = obj.metaObject() + self.assertEqual(mo.propertyCount(), 2) + p = mo.property(1) + self.assertFalse(p.isConstant()) + if __name__ == '__main__': unittest.main() diff --git a/tests/QtGui/CMakeLists.txt b/tests/QtGui/CMakeLists.txt index 9086829f8..2ad8269a9 100644 --- a/tests/QtGui/CMakeLists.txt +++ b/tests/QtGui/CMakeLists.txt @@ -16,6 +16,8 @@ PYSIDE_TEST(bug_416.py) PYSIDE_TEST(bug_429.py) PYSIDE_TEST(bug_430.py) PYSIDE_TEST(bug_433.py) +PYSIDE_TEST(bug_467.py) +PYSIDE_TEST(bug_480.py) PYSIDE_TEST(customproxywidget_test.py) PYSIDE_TEST(deepcopy_test.py) PYSIDE_TEST(float_to_int_implicit_conversion_test.py) diff --git a/tests/QtGui/bug_467.py b/tests/QtGui/bug_467.py new file mode 100644 index 000000000..5c5af4b20 --- /dev/null +++ b/tests/QtGui/bug_467.py @@ -0,0 +1,19 @@ +''' Test bug 367: http://bugs.openbossa.org/show_bug.cgi?id=467''' + +import unittest +from helper import UsesQApplication +from PySide.QtGui import QMainWindow, QApplication + +class MyWidget(QMainWindow): + def __init__(self, parent = None): + QMainWindow.__init__(self, parent) + + +class BugTest(UsesQApplication): + def testCase(self): + w = MyWidget() + widgets = QApplication.allWidgets() + self.assert_(w in widgets) + +if __name__ == '__main__': + unittest.main() diff --git a/tests/QtGui/bug_480.py b/tests/QtGui/bug_480.py new file mode 100644 index 000000000..bb28f3661 --- /dev/null +++ b/tests/QtGui/bug_480.py @@ -0,0 +1,25 @@ +import unittest + +from PySide import QtGui + +class BuggyWidget(QtGui.QWidget): + def setup(self): + self.verticalLayout = QtGui.QVBoxLayout(self) + self.gridLayout = QtGui.QGridLayout() + self.lbl = QtGui.QLabel(self) + self.gridLayout.addWidget(self.lbl, 0, 1, 1, 1) + + # this cause a segfault during the ownership transfer + self.verticalLayout.addLayout(self.gridLayout) + +class LayoutTransferOwnerShip(unittest.TestCase): + def testBug(self): + app = QtGui.QApplication([]) + w = BuggyWidget() + w.setup() + w.show() + self.assert_(True) + +if __name__ == '__main__': + unittest.main() + diff --git a/tests/QtNetwork/CMakeLists.txt b/tests/QtNetwork/CMakeLists.txt index 0eb503714..9b0be3abf 100644 --- a/tests/QtNetwork/CMakeLists.txt +++ b/tests/QtNetwork/CMakeLists.txt @@ -1,4 +1,4 @@ - +PYSIDE_TEST(bug_446.py) PYSIDE_TEST(basic_auth_test.py) PYSIDE_TEST(accessManager_test.py) PYSIDE_TEST(http_test.py) diff --git a/tests/QtNetwork/bug_446.py b/tests/QtNetwork/bug_446.py new file mode 100644 index 000000000..d3a9d0986 --- /dev/null +++ b/tests/QtNetwork/bug_446.py @@ -0,0 +1,48 @@ +import unittest + +from PySide.QtCore import * +from PySide.QtNetwork import * + +from helper import UsesQCoreApplication + +class HttpSignalsCase(UsesQCoreApplication): + '''Test case for launching QHttp signals''' + DATA = "PySide rocks" + + def onError(self): + self.assert_(False) + + def onNewConnection(self): + self.serverConnection = self.server.nextPendingConnection() + self.serverConnection.error.connect(self.onError) + self.serverConnection.write(HttpSignalsCase.DATA) + self.server.close() + + def onReadReady(self): + data = self.client.read(100) + self.assertEqual(data.size(), len(HttpSignalsCase.DATA)) + self.assertEqual(data, HttpSignalsCase.DATA) + self.done() + + def onClientConnect(self): + self.client.readyRead.connect(self.onReadReady) + + def initServer(self): + self.server = QTcpServer() + self.server.newConnection.connect(self.onNewConnection) + self.assert_(self.server.listen()) + self.client = QTcpSocket() + self.client.connected.connect(self.onClientConnect) + self.client.connectToHost(QHostAddress(QHostAddress.LocalHost), self.server.serverPort()) + + def done(self): + self.serverConnection.close() + self.client.close() + self.app.quit() + + def testRun(self): + self.initServer() + self.app.exec_() + +if __name__ == '__main__': + unittest.main() |