PySide Bugzilla Closed for New Bugs

PySide is now a Qt Add-on and uses the Qt Project's JIRA Bug Tracker instead of this Bugzilla instance. This Bugzilla is left for reference purposes.

Bug 392 - Segfault with acions in .ui files
: Segfault with acions in .ui files
Status: CLOSED FIXED
Product: PySide
Classification: Unclassified
Component: PySide
: HEAD
: All Linux
: P3 normal
Assigned To: renato filho
:
:
:
  Show dependency treegraph
 
Reported: 2010-09-29 07:46 EEST by Bajusz Tamás
Modified: 2010-11-25 17:48 EET (History)
9 users (show)

See Also:


Attachments
.ui file producing the segfault (429 bytes, application/xml)
2010-09-29 07:48 EEST, Bajusz Tamás
Details
customwidget.ui for producing the remaining issue (737 bytes, application/xml)
2010-10-02 10:59 EEST, Bajusz Tamás
Details
unit test with custom widgets (864 bytes, text/x-python)
2010-10-05 12:10 EEST, renato filho
Details
custom widget ui file created with designer. (1.10 KB, application/x-designer)
2010-10-05 12:11 EEST, renato filho
Details
testcase for mapping more than 1 custom widget (2.55 KB, text/plain)
2010-10-08 17:16 EEST, Bajusz Tamás
Details
testcase for mapping more than 1 custom widget (947 bytes, application/xml)
2010-10-08 17:17 EEST, Bajusz Tamás
Details

Note You need to log in before you can comment on or make changes to this bug.
Description Bajusz Tamás 2010-09-29 07:46:34 EEST
USE_PYSIDE = False
USE_PYSIDE = True

if USE_PYSIDE:
    from PySide import QtCore
    from PySide import QtGui
    from PySide.QtUiTools import QUiLoader

    class MyQUiLoader(QUiLoader):
        def __init__(self, baseinstance):
            QUiLoader.__init__(self)
            self.baseinstance = baseinstance

        def createAction(self, parent=None, name=""):
            action = QUiLoader.createAction(self, parent, name)
            print parent, name, action, action.metaObject().className()   
            setattr(self.baseinstance, name, action)
            return action

        def createWidget(self, className, parent=None, name=""):
            widget = QUiLoader.createWidget(self, className, parent, name)
            print className, parent, name, widget,
widget.metaObject().className()   
            if parent is None:
                return self.baseinstance
            else:
                setattr(self.baseinstance, name, widget)
                return widget

    def loadUi(uifile, baseinstance=None):
        loader = MyQUiLoader(baseinstance)
        ui = loader.load(uifile)
        QtCore.QMetaObject.connectSlotsByName(ui)
        return ui
else:
    import sip
    sip.setapi('QString', 2)
    sip.setapi('QVariant', 2)
    from PyQt4 import QtCore
    from PyQt4 import QtGui
    from PyQt4.uic import loadUi

class Window(QtGui.QMainWindow):
    def __init__(self, parent = None):
        QtGui.QMainWindow.__init__(self)
        loadUi('mainwindow.ui', self)

if __name__ == '__main__':
    import sys
    app = QtGui.QApplication(sys.argv)
    window = Window()
    window.show()
    sys.exit(app.exec_())
Comment 1 Bajusz Tamás 2010-09-29 07:48:21 EEST
Created attachment 103 [details]
.ui file producing the segfault
Comment 2 renato filho 2010-09-30 17:28:53 EEST
fixed on commit:

commit 7633675d1154eda8d799aa340c5513baa34621b9
Author: renatofilho <renato.filho@openbossa.org>
Date:   Thu Sep 30 15:36:20 2010 -0300


this kind of function demonstrated on this example is implemented on c++
QtUiLoader.load function, check unit test on commit:

commit 846c9a151f23ec727540f1bda8d6b43609f5ad43
Author: renatofilho <renato.filho@openbossa.org>
Date:   Thu Sep 30 15:35:49 2010 -0300
Comment 3 Bajusz Tamás 2010-10-02 10:58:34 EEST
It's OK now, except using custom widgets in .ui files.

customwidget.py
---------------
USE_PYSIDE = False
USE_PYSIDE = True

if USE_PYSIDE:
    from PySide import QtCore
    from PySide import QtGui
    from PySide.QtUiTools import QUiLoader
    from PySide.QtCore import Property as pyqtProperty

    class MyQUiLoader(QUiLoader):
        def __init__(self, baseinstance):
            QUiLoader.__init__(self)
            self.baseinstance = baseinstance

        def createWidget(self, className, parent=None, name=""):
            widget = QUiLoader.createWidget(self, className, parent, name)
            #print className, parent, name, widget,
widget.metaObject().className()   
            if parent is None:
                return self.baseinstance
            else:
                setattr(self.baseinstance, name, widget)
                return widget

    def loadUi(uifile, baseinstance=None):
        loader = MyQUiLoader(baseinstance)
        ui = loader.load(uifile)
        QtCore.QMetaObject.connectSlotsByName(ui)
        return ui
else:
    import sip
    sip.setapi('QString', 2)
    sip.setapi('QVariant', 2)
    from PyQt4 import QtCore
    from PyQt4 import QtGui
    from PyQt4.uic import loadUi
    from PyQt4.QtCore import pyqtProperty


class MyComboBox(QtGui.QComboBox):
    def __init__(self, parent):
        QtGui.QComboBox.__init__(self, parent)

    def getId(self):
        return self.itemData(self.currentIndex(), QtCore.Qt.UserRole)

    def setId(self, id):
        self.setCurrentIndex(self.findData(id, QtCore.Qt.UserRole))

    itemId = pyqtProperty('int', getId, setId, user=True)

    def populateList(self, rows):
        for row in rows:
            self.addItem(row[0], row[1])


class Window(QtGui.QWidget):
    def __init__(self, parent = None):
        QtGui.QWidget.__init__(self, parent)
        loadUi('customwidget.ui', self)

if __name__ == '__main__':
    import sys
    app = QtGui.QApplication(sys.argv)
    window = Window()
    window.myComboBox.populateList((('first', 1), ('second', 2)))
    window.show()
    sys.exit(app.exec_())
Comment 4 Bajusz Tamás 2010-10-02 10:59:55 EEST
Created attachment 105 [details]
customwidget.ui for producing the remaining issue
Comment 5 renato filho 2010-10-05 12:10:42 EEST
Created attachment 108 [details]
unit test with custom widgets
Comment 6 renato filho 2010-10-05 12:11:08 EEST
Created attachment 109 [details]
custom widget ui file created with designer.
Comment 7 renato filho 2010-10-05 12:12:35 EEST
I created a .ui file using designer with a custom widget and works fine. With
your .ui file I got a  internal Qt warning message I think there is some syntax
error on your .ui file.

Can you check this?
Comment 8 renato filho 2010-10-05 12:14:56 EEST
The message I got is:

"QFormBuilder was unable to create a custom widget of the class 'MyComboBox';
defaulting to base class 'QComboBox'."
Comment 9 Bajusz Tamás 2010-10-08 17:15:08 EEST
The new registerCustomWidget method seems Ok, but got another issue when trying
to map more than 1 custom widget with QDataWidgetMapper.
Testcase is attached. Traceback is:

Traceback (most recent call last):
  File "customwidget.py", line 85, in <module>
    mapper.addMapping(cmb1, 1)
RuntimeError: Internal C++ object already deleted.
Comment 10 Bajusz Tamás 2010-10-08 17:16:38 EEST
Created attachment 113 [details]
testcase for mapping more than 1 custom widget
Comment 11 Bajusz Tamás 2010-10-08 17:17:06 EEST
Created attachment 114 [details]
testcase for mapping more than 1 custom widget
Comment 12 renato filho 2010-10-13 17:11:20 EEST
reference leak fixed on commit:

commit e71b215f0bb4c6b53bd74a66ab856426df51f140
Author: renatofilho <renato.filho@openbossa.org>
Date:   Wed Oct 13 16:42:50 2010 -0300
Comment 13 Bajusz Tamás 2010-10-15 11:09:05 EEST
It's Ok now, thx!
Comment 14 renato filho 2010-11-25 17:48:09 EET
released on 1.0.0~beta1