The ownership of the editor returned by the Python override of
QAbstractItemDelegate.createEditor(...) is now transferred to C++.

A test was added to simulate the situation that triggers the bug,
instead of relying on an example with a view, model and editable cells.

See: http://bugs.openbossa.org/show_bug.cgi?id=502

Reviewed by Lauro Moura <lauro.neto@openbossa.org>
Reviewed by Renato Araújo <renato.filho@openbossa.org>
This commit is contained in:
Marcelo Lira 2010-12-17 19:37:35 -03:00
commit 14a5405837
6 changed files with 91 additions and 7 deletions

View file

@ -3047,6 +3047,9 @@
<modify-argument index="1"> <modify-argument index="1">
<define-ownership owner="c++"/> <define-ownership owner="c++"/>
</modify-argument> </modify-argument>
<modify-argument index="return">
<define-ownership class="native" owner="c++"/>
</modify-argument>
</modify-function> </modify-function>
</object-type> </object-type>
<object-type name="QTableWidgetItem" > <object-type name="QTableWidgetItem" >

View file

@ -32,8 +32,8 @@ set(GENERATOR_EXTRA_FLAGS --generatorSet=shiboken --enable-parent-ctor-heuristic
add_custom_command(OUTPUT ${testbinding_SRC} add_custom_command(OUTPUT ${testbinding_SRC}
COMMAND ${GENERATORRUNNER_BINARY} ${GENERATOR_EXTRA_FLAGS} COMMAND ${GENERATORRUNNER_BINARY} ${GENERATOR_EXTRA_FLAGS}
${CMAKE_CURRENT_SOURCE_DIR}/global.h ${CMAKE_CURRENT_SOURCE_DIR}/global.h
--include-paths=${CMAKE_CURRENT_SOURCE_DIR}${PATH_SEP}${QT_INCLUDE_DIR}${PATH_SEP}${QT_QTCORE_INCLUDE_DIR} --include-paths=${CMAKE_CURRENT_SOURCE_DIR}${PATH_SEP}${QT_INCLUDE_DIR}${PATH_SEP}${QT_QTCORE_INCLUDE_DIR}${PATH_SEP}${QT_QTGUI_INCLUDE_DIR}
--typesystem-paths=${CMAKE_CURRENT_SOURCE_DIR}${PATH_SEP}${pyside_SOURCE_DIR}${PATH_SEP}${QtCore_SOURCE_DIR} --typesystem-paths=${CMAKE_CURRENT_SOURCE_DIR}${PATH_SEP}${pyside_SOURCE_DIR}${PATH_SEP}${QtCore_SOURCE_DIR}${PATH_SEP}${QtGui_SOURCE_DIR}${PATH_SEP}${QtGui_BINARY_DIR}
--output-directory=${CMAKE_CURRENT_BINARY_DIR} --output-directory=${CMAKE_CURRENT_BINARY_DIR}
${CMAKE_CURRENT_SOURCE_DIR}/typesystem_pysidetest.xml ${CMAKE_CURRENT_SOURCE_DIR}/typesystem_pysidetest.xml
WORKING_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR} WORKING_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR}
@ -44,8 +44,11 @@ include_directories(${CMAKE_CURRENT_SOURCE_DIR}
${CMAKE_CURRENT_BINARY_DIR} ${CMAKE_CURRENT_BINARY_DIR}
${QT_INCLUDE_DIR} ${QT_INCLUDE_DIR}
${QT_QTCORE_INCLUDE_DIR} ${QT_QTCORE_INCLUDE_DIR}
${QT_QTGUI_INCLUDE_DIR}
${SHIBOKEN_INCLUDE_DIR} ${SHIBOKEN_INCLUDE_DIR}
${pyside_SOURCE_DIR}
${QtCore_BINARY_DIR}/PySide/QtCore ${QtCore_BINARY_DIR}/PySide/QtCore
${QtGui_BINARY_DIR}/PySide/QtGui
${libpyside_SOURCE_DIR} ${libpyside_SOURCE_DIR}
${PYTHON_INCLUDE_PATH}) ${PYTHON_INCLUDE_PATH})
@ -63,12 +66,14 @@ target_link_libraries(testbinding
${PYTHON_LIBRARIES} ${PYTHON_LIBRARIES}
${SHIBOKEN_LIBRARY} ${SHIBOKEN_LIBRARY}
${QT_QTCORE_LIBRARY} ${QT_QTCORE_LIBRARY}
${QT_QTGUI_LIBRARY}
${SBK_PYTHON_LIBRARIES}) ${SBK_PYTHON_LIBRARIES})
add_dependencies(testbinding pyside QtCore libpyside pysidetest) add_dependencies(testbinding pyside QtCore libpyside pysidetest)
PYSIDE_TEST(homonymoussignalandmethod_test.py) PYSIDE_TEST(homonymoussignalandmethod_test.py)
PYSIDE_TEST(delegatecreateseditor_test.py)
PYSIDE_TEST(modelview_test.py) PYSIDE_TEST(modelview_test.py)
PYSIDE_TEST(version_test.py) PYSIDE_TEST(version_test.py)

View file

@ -0,0 +1,55 @@
#!/usr/bin/python
import unittest
from helper import UsesQApplication
from testbinding import TestView
from PySide.QtCore import Qt
from PySide.QtGui import QAbstractItemDelegate, QComboBox
id_text = 'This is me'
class DelegateDoesntKeepReferenceToEditor(QAbstractItemDelegate):
def createEditor(self, parent, option, index):
comboBox = QComboBox(parent)
comboBox.addItem(id_text)
return comboBox
class DelegateKeepsReferenceToEditor(QAbstractItemDelegate):
def __init__(self, parent=None):
QAbstractItemDelegate.__init__(self, parent)
self.comboBox = QComboBox()
self.comboBox.addItem(id_text)
def createEditor(self, parent, option, index):
self.comboBox.setParent(parent)
return self.comboBox
class EditorCreatedByDelegateTest(UsesQApplication):
def testDelegateDoesntKeepReferenceToEditor(self):
view = TestView(None)
delegate = DelegateDoesntKeepReferenceToEditor()
view.setItemDelegate(delegate)
editor = view.getEditorWidgetFromItemDelegate()
self.assertEqual(type(editor), QComboBox)
self.assertEqual(editor.count(), 1)
self.assertEqual(editor.itemData(0, Qt.DisplayRole), id_text)
editor.metaObject()
def testDelegateKeepsReferenceToEditor(self):
view = TestView(None)
delegate = DelegateKeepsReferenceToEditor()
view.setItemDelegate(delegate)
editor = view.getEditorWidgetFromItemDelegate()
self.assertEqual(type(editor), QComboBox)
self.assertEqual(editor.count(), 1)
self.assertEqual(editor.itemData(0, Qt.DisplayRole), id_text)
editor.metaObject()
if __name__ == '__main__':
unittest.main()

View file

@ -1,12 +1,24 @@
#include "testview.h" #include "testview.h"
#include <QDebug>
#include <stdio.h> #include <QWidget>
#include <QAbstractListModel>
#include <QAbstractItemDelegate>
QVariant QVariant
TestView::getData() TestView::getData()
{ {
QModelIndex index; QModelIndex index;
QVariant data = m_model->data(index); return m_model->data(index);
return data; }
QWidget*
TestView::getEditorWidgetFromItemDelegate() const
{
if (!m_delegate)
return 0;
QModelIndex index;
QStyleOptionViewItem options;
return m_delegate->createEditor(0, options, index);
} }

View file

@ -2,12 +2,15 @@
#define TESTVIEW_H #define TESTVIEW_H
#include <QObject> #include <QObject>
#include <QAbstractListModel>
#ifdef pysidetest_EXPORTS #ifdef pysidetest_EXPORTS
#define PYSIDE_EXPORTS 1 #define PYSIDE_EXPORTS 1
#endif #endif
#include "pysidemacros.h" #include "pysidemacros.h"
class QWidget;
class QAbstractListModel;
class QAbstractItemDelegate;
class PYSIDE_API TestView : public QObject class PYSIDE_API TestView : public QObject
{ {
Q_OBJECT Q_OBJECT
@ -15,8 +18,13 @@ public:
TestView(QAbstractListModel* model, QObject* parent = 0) : QObject(parent), m_model(model) {} TestView(QAbstractListModel* model, QObject* parent = 0) : QObject(parent), m_model(model) {}
QAbstractListModel* model() { return m_model; } QAbstractListModel* model() { return m_model; }
QVariant getData(); QVariant getData();
void setItemDelegate(QAbstractItemDelegate* delegate) { m_delegate = delegate; }
QWidget* getEditorWidgetFromItemDelegate() const;
private: private:
QAbstractListModel* m_model; QAbstractListModel* m_model;
QAbstractItemDelegate* m_delegate;
}; };
#endif // TESTVIEW_H #endif // TESTVIEW_H

View file

@ -1,6 +1,7 @@
<?xml version="1.0"?> <?xml version="1.0"?>
<typesystem package="testbinding"> <typesystem package="testbinding">
<load-typesystem name="typesystem_core.xml" generate="no" /> <load-typesystem name="typesystem_core.xml" generate="no" />
<load-typesystem name="typesystem_gui.xml" generate="no"/>
<object-type name="TestObject" /> <object-type name="TestObject" />
<object-type name="TestView" > <object-type name="TestView" >
<modify-function signature="TestView(QAbstractListModel*,QObject*)"> <modify-function signature="TestView(QAbstractListModel*,QObject*)">