On Tue, Mar 10, 2009 at 8:03 PM, Darren Dale <dsdal...@gmail.com> wrote:

> On Tue, Mar 10, 2009 at 5:28 PM, Darren Dale <dsdal...@gmail.com> wrote:
>
>> Hello,
>>
>> I am trying to create a simple model and view for a simple nested
>> dictionary like d:
>>
>>     c1 = {'id':1, 'description':'child 1'}
>>     c2 = {'id':2, 'description':'child 2'}
>>     d = {'id':0, 'description':'whatever', 'children':[c1, c2]}
>>
>> I have a self-contained, relatively simple script attached. When I run it
>> and try to open the top-level entry by clicking on the +, I get errors like:
>>
>> Traceback (most recent call last):
>>   File "tree_test.py", line 111, in parent
>>     parent = index.internalPointer().parent
>> AttributeError: 'ItemDataRole' object has no attribute 'parent'
>> Traceback (most recent call last):
>>   File "tree_test.py", line 111, in parent
>>     parent = index.internalPointer().parent
>> AttributeError: parent
>>
>> Traceback (most recent call last):
>>   File "tree_test.py", line 111, in parent
>>     parent = index.internalPointer().parent
>> AttributeError: 'exceptions.AttributeError' object has no attribute
>> 'parent'
>> Bus error
>>
>> sometimes I get a different error:
>>
>> Traceback (most recent call last):
>>   File "tree_test.py", line 111, in parent
>>     parent = index.internalPointer().parent
>> AttributeError: 'ItemDataRole' object has no attribute 'parent'
>> Segmentation fault
>>
>>
>> Could anyone please help me understand what is happening? I dont
>> understand why index.internalPointer() is returning an ItemDataRole object
>> or an exceptions.AttributeError object.
>>
>> Im running Qt-4.5.0, sip-4.7.9 and PyQt-4.4.4.
>
>
> I just checked this script on a 64-bit kubuntu intrepid system with
> qt-4.4.3 and PyQt4-4.4.4, sip-4.7.9 and python-2.5.2 and I get segfaults
> here too. I guess that rules out some issue specific to qt-4.5.
>

I've been looking into this some more, and I managed to isolate the problem.
The attached script runs ok when CACHE_CHILDREN = True, but it will yield
bus errors or segfaults when CACHE_CHILDREN is False. Unfortunately, I am
modeling an object that can be changed elsewhere in the application, so it
is imperitive that I am able to recalculate the child list. I have done the
exact same thing using Enthought's Traits package with the Traits Qt4
backend, and never saw segfaults, so I know it must be possible.

Please, can anyone suggest why this causes a crash?

Thank you,
Darren
"""
"""

from PyQt4 import QtCore, QtGui


CACHE_CHILDREN = True


class TreeItem(object):

    def __init__(self, data, parent=None):
        self._parent = parent
        self._data = data

    @property
    def children(self):
        return []

    @property
    def columns(self):
        return [self.data['id'], self.data['description']]

    @property
    def data(self):
        return self._data

    @property
    def parent(self):
        return self._parent

    @property
    def row(self):
        if self.parent:
            return self.parent.children.index(self)
        return 0

    @property
    def rows(self):
        return len(self.children)


class RootItem(TreeItem):

    def __init__(self):
        self._parent = None
        self._children = []

    @property
    def children(self):
        return self._children

    @property
    def columns(self):
        return ['ID', 'Description']

    def appendChild(self, child):
        self._children.append(child)


class DictItem(TreeItem):

    def __init__(self, data, parent=None):
        super(DictItem, self).__init__(data, parent)

    @property
    def children(self):
        if CACHE_CHILDREN:
            try:
                return self._children
            except AttributeError:
                self._children = [TreeItem(child, self)
                                  for child in self.data['children']]
                return self._children
        else:
            return [TreeItem(child, self) for child in self.data['children']]


class FileModel(QtCore.QAbstractItemModel):

    """
    """

    def __init__(self, parent=None):
        super(FileModel, self).__init__(parent)
        self._rootItem = RootItem()

    @property
    def rootItem(self):
        return self._rootItem

    def columnCount(self, parent):
        if parent.isValid():
            return len(parent.internalPointer().columns)
        else:
            return len(self.rootItem.columns)

    def data(self, index, role):
        if not index.isValid() or role != QtCore.Qt.DisplayRole:
            return QtCore.QVariant()

        item = index.internalPointer()
        return QtCore.QVariant(item.columns[index.column()])

    def headerData(self, section, orientation, role):
        if orientation == QtCore.Qt.Horizontal and \
                role == QtCore.Qt.DisplayRole:
            return QtCore.QVariant(self.rootItem.columns[section])

        return QtCore.QVariant()

    def index(self, row, column, parent):
        if not self.hasIndex(row, column, parent):
            return QtCore.QModelIndex()

        if parent.isValid():
            parentItem = parent.internalPointer()
        else:
            parentItem = self.rootItem
        child = parentItem.children[row]
        return self.createIndex(row, column, child)

    def parent(self, index):
        if not index.isValid():
            return QtCore.QModelIndex()
        try:
            parent = index.internalPointer().parent
            if parent == self.rootItem or parent is None:
                return QtCore.QModelIndex()
            return self.createIndex(parent.row, 0, parent)
        except AttributeError:
            return QtCore.QModelIndex()

    def rowCount(self, parent):
        if parent.isValid():
            parentItem = parent.internalPointer()
        else:
            parentItem = self.rootItem
        return parentItem.rows

    def appendDict(self, d):
        assert 'id' in d
        assert 'description' in d
        self.rootItem.appendChild(DictItem(d))


class FileView(QtGui.QTreeView):

    def __init__(self, model=None, parent=None):
        super(FileView, self).__init__(parent)
        self.setModel(model)


if __name__ == '__main__':
    import sys
    app = QtGui.QApplication(sys.argv)
    model = FileModel()
    form = FileView(model)
    c1 = {'id':1, 'description':'child 1'}
    c2 = {'id':2, 'description':'child 2'}
    d = {'id':0, 'description':'whatever', 'children':[c1, c2]}
    model.appendDict(d)
    form.show()
    sys.exit(app.exec_())
_______________________________________________
PyQt mailing list    PyQt@riverbankcomputing.com
http://www.riverbankcomputing.com/mailman/listinfo/pyqt

Reply via email to