[PyQt] segfault!...and more

Alberto Berti alberto at metapensiero.it
Thu Jan 17 19:14:14 GMT 2008


Hi all, 

i'm quite new to this list, but i'm working with PyQT4 with great
satisfaction to develop a framework, and an application, to build
database driven applications using the model/view/delegate approach
with SQLAlchemy (http://sqlalchemy.org) instead of the standard SQL
enabled tree of models in QT.  I've finished the low-level of
sqlalchemy related storages and i'm completing the AbstractTableModel
subclass that is usable as a QSQLRelationalTableModel replacement,
with semi-automatic wiring of the realtions thanks to SQLAlchemy
metadata introspection. Now it supports 1-1 relations, with 1-n
realtions to be completed for the end of the week:-).  I've
encountered a problem during the coding of a demo which i don't know
handle. I know it's related to the fact of a qt component that is
taking ownership of python objects, but nothing more.

Aside from this, does someone know the location of the repositories
for PyQt4 and PyKDE?

There is an updated QT 4.3 doxygen api available online?

Thanks in advance, especially to those that worked to make pyqt4:)

 Here is the relevant code (it's long, I hope that someone will find
te time to read it), commented to help your reading:

if __name__ == '__main__':

    # A simple displaying combo boxes on 1-to-1 relations
    from pypapi.db.interfaces import IIterProcedurale, IElementoAnagrafico, IDatabase
    from pypapi.db.model import ElementoAnagrafico, IterProcedurale
    from pypapi.db.storage import SAListStore
    from zope.schema import getFieldsInOrder
    
    # database initialization
    db = getUtility(IDatabase)
    db.open('sqlite:///procedimenti.sqlite')

    # creation of the low-level stores that handle the join or the
    # deletion of enitities instances from the persistence using
    # standard list semantics. The 2nd and 3rd SAListStore are built
    # using prconfigured lookup sources
    iter_proc = SAListStore(db.session.query(IterProcedurale))
    enti = SAListStore(IIterProcedurale.get('ente').source(IterProcedurale))
    uffici = SAListStore(IIterProcedurale.get('ufficioattribuito').source(IterProcedurale))

    # Now i create the three model classes, selecting proper subset of fields
    # and generating "QtModel" oriented "views" of these field on the fly

    class IterProcModel(TableModel):
        # the last 3 fields are not rendered because they are 1-n
        # relations, still unsupported
        columns = [IColumn(field) for name, field in getFieldsInOrder(IIterProcedurale)][:-3]

    class EnteModel(TableModel):
        columns = [Column('getCaption', 'Enti')]

    class UfficioModel(TableModel):
        columns = [Column('getCaption', 'Uffici')]

    from PyQt4.QtGui import QApplication, QTableView
    
    # QT App init
    app = QApplication([])

    # Here the actual model instances are created, using the stores
    ip_model = IterProcModel(iter_proc, app)
    e_model = EnteModel(enti, app)
    u_model = UfficioModel(uffici, app)
 
    # wiring of the relations. This step and the latter over here will
    # be automated inside form's code
    col_ente = ip_model.getColumnByName('ente')
    col_ente.setLookupModel(e_model, 'getCaption')
    col_ufficio = ip_model.getColumnByName('ufficioattribuito')
    col_ufficio.setLookupModel(u_model, 'getCaption')

    from PyQt4.QtGui import QItemEditorCreatorBase, QComboBox, \
         QItemEditorFactory, QSpinBox, QLineEdit
         
    # here i define a couple of editor creators. The first and most
    # important redefines the standard editing of Int cells to render
    # a QComboBox when the cell looks up its value on another table.
    # The second is there just to handle the editing o string cells,
    # Using the standard behavior. It's there just to allow editing
    # because installing just LookupEditorCreator in the default
    # factory doesn't work. So i create my own factory and install it.
    class LookupEditorCreator(QItemEditorCreatorBase):

        def createWidget(self, parent):

           # qui parent è in delegato, perciò parent.parent() è la
           # tabella
            view = parent.parent()
            index = view.currentIndex()
            item = index.internalPointer()
            if isinstance(item, LookupItem):
                widget = QComboBox(parent)
                widget.setModel(item.column.lookup_model)
            else:
                widget = QSpinBox(parent)
                # piccola fix per permettere valori > 99
                widget.setMaximum(10000)
            return widget

        def valuePropertyName(self):

            return 'currentIndex'

    class StringEditorCreator(QItemEditorCreatorBase):

        def createWidget(self, parent):

            return QLineEdit(parent)

    #!!! This code works as expected, but a Segmentation Fault is
    # raised on application termination, why?
    edit_fac = QItemEditorFactory()
    creator = LookupEditorCreator()
    s_creator = StringEditorCreator()
    edit_fac.registerEditor(QVariant.Int, creator)
    edit_fac.registerEditor(QVariant.String, s_creator)
    QItemEditorFactory.setDefaultFactory(edit_fac)

    ip_view = QTableView()
    ip_view.setModel(ip_model)
    ip_view.show()

    app.exec_()
    db.close()



More information about the PyQt mailing list