Fixed layout reference control on layouts.

Reviewer: Luciano Wolf <luciano.wolf@openbossa.org>
This commit is contained in:
Renato Filho 2010-07-09 18:27:39 -03:00
commit 5cc46f2f13
4 changed files with 60 additions and 11 deletions

View file

@ -3,24 +3,40 @@
void addLayoutOwnership(QLayout *layout, QLayoutItem *item); void addLayoutOwnership(QLayout *layout, QLayoutItem *item);
inline QString retrieveObjectName(PyObject *obj)
{
Shiboken::AutoDecRef objName(PyObject_Str(obj));
return QString(PyString_AsString(objName));
}
inline void addLayoutOwnership(QLayout *layout, QWidget *widget) inline void addLayoutOwnership(QLayout *layout, QWidget *widget)
{ {
//transfer ownership to parent widget //transfer ownership to parent widget
QWidget *parent = layout->parentWidget(); QWidget *parent = layout->parentWidget();
if (!parent)
return;
Shiboken::AutoDecRef pyParent(Shiboken::Converter<QWidget*>::toPython(parent)); if (!parent) {
Shiboken::AutoDecRef pyChild(Shiboken::Converter<QWidget*>::toPython(widget)); //keep the reference while the layout is orphan
Shiboken::setParent(pyParent, pyChild); Shiboken::AutoDecRef pyParent(Shiboken::Converter<QWidget*>::toPython(layout));
Shiboken::AutoDecRef pyChild(Shiboken::Converter<QWidget*>::toPython(widget));
Shiboken::keepReference(reinterpret_cast<Shiboken::SbkBaseWrapper*>(pyParent.object()), qPrintable(retrieveObjectName(pyParent)), pyChild, true);
} else {
Shiboken::AutoDecRef pyParent(Shiboken::Converter<QWidget*>::toPython(parent));
Shiboken::AutoDecRef pyChild(Shiboken::Converter<QWidget*>::toPython(widget));
Shiboken::setParent(pyParent, pyChild);
}
} }
inline void addLayoutOwnership(QLayout *layout, QLayout *other) inline void addLayoutOwnership(QLayout *layout, QLayout *other)
{ {
//transfer all children widgetes from other to layout parent widget //transfer all children widgetes from other to layout parent widget
QWidget *parent = layout->parentWidget(); QWidget *parent = layout->parentWidget();
if (!parent) if (!parent) {
//keep the reference while the layout is orphan
Shiboken::AutoDecRef pyParent(Shiboken::Converter<QLayout*>::toPython(layout));
Shiboken::AutoDecRef pyChild(Shiboken::Converter<QLayout*>::toPython(other));
Shiboken::keepReference(reinterpret_cast<Shiboken::SbkBaseWrapper*>(pyParent.object()), qPrintable(retrieveObjectName(pyParent)), pyChild, true);
return; return;
}
for (int i=0, i_max=other->count(); i < i_max; i++) { for (int i=0, i_max=other->count(); i < i_max; i++) {
addLayoutOwnership(layout, other->itemAt(i)); addLayoutOwnership(layout, other->itemAt(i));

View file

@ -1,3 +1,10 @@
static QString retrieveObjectName(PyObject *obj)
{
Shiboken::AutoDecRef objName(PyObject_Str(obj));
return QString(PyString_AsString(objName));
}
/** /**
* Tranfer objects ownership from layout to widget * Tranfer objects ownership from layout to widget
**/ **/
@ -26,6 +33,9 @@ qwidgetReparentLayout(QWidget *parent, QLayout *layout)
Shiboken::AutoDecRef pyChild(Shiboken::Converter<QLayout*>::toPython(layout)); Shiboken::AutoDecRef pyChild(Shiboken::Converter<QLayout*>::toPython(layout));
Shiboken::setParent(pyParent, pyChild); Shiboken::setParent(pyParent, pyChild);
//remove previous references
Shiboken::keepReference(reinterpret_cast<Shiboken::SbkBaseWrapper*>(pyChild.object()), qPrintable(retrieveObjectName(pyChild)), Py_None);
} }
static inline void static inline void

View file

@ -46,7 +46,7 @@ class SaveReference(UsesQApplication):
l = QHBoxLayout() l = QHBoxLayout()
self.assertEqual(getrefcount(self.widget1), 2) self.assertEqual(getrefcount(self.widget1), 2)
l.addWidget(self.widget1) l.addWidget(self.widget1)
self.assertEqual(getrefcount(self.widget1), 2) self.assertEqual(getrefcount(self.widget1), 3)
w = QWidget() w = QWidget()
w.setLayout(l) w.setLayout(l)

View file

@ -2,7 +2,7 @@ import unittest
import sys import sys
from helper import UsesQApplication from helper import UsesQApplication
from PySide.QtGui import QLayout, QWidget, QPushButton, QWidgetItem from PySide.QtGui import QLayout, QWidget, QPushButton, QWidgetItem, QHBoxLayout
class MyLayout(QLayout): class MyLayout(QLayout):
def __init__(self, parent=None): def __init__(self, parent=None):
@ -29,24 +29,47 @@ class MyLayout(QLayout):
#Test if a layout implemented in python, the QWidget.setLayout works #Test if a layout implemented in python, the QWidget.setLayout works
#fine because this implement som layout functions used in glue code of #fine because this implement som layout functions used in glue code of
#QWidget, then in c++ when call a virtual function this need call the QLayout #QWidget, then in c++ when call a virtual function this need call the QLayout
#function implemented in python #function implemented in python
class QLayoutTest(UsesQApplication): class QLayoutTest(UsesQApplication):
def testOwnershipTransfer(self): def testOwnershipTransfer(self):
b = QPushButton("teste") b = QPushButton("teste")
l = MyLayout() l = MyLayout()
l.addWidget(b) l.addWidget(b)
self.assertEqual(sys.getrefcount(b), 2) self.assertEqual(sys.getrefcount(b), 2)
w = QWidget() w = QWidget()
#transfer ref
w.setLayout(l) w.setLayout(l)
self.assertEqual(sys.getrefcount(b), 3) self.assertEqual(sys.getrefcount(b), 3)
def testReferenceTransfer(self):
b = QPushButton("teste")
l = QHBoxLayout()
# keep ref
l.addWidget(b)
self.assertEqual(sys.getrefcount(b), 3)
w = QWidget()
# transfer ref
w.setLayout(l)
self.assertEqual(sys.getrefcount(b), 3)
# release ref
del w
self.assertEqual(sys.getrefcount(b), 2)
if __name__ == '__main__': if __name__ == '__main__':
unittest.main() unittest.main()