Dear all,

I am trying to use a Python list as a model for QTreeView, or to be precise, 
the model is a subclass of list, the 
daughter nodes are the elements on this list object, and they themselves are 
the same subclass of list.

Somehow I cannot get the data to show correctly. Only the first row is shown 
and although the top row indicates 
that is has subrows, expanding the toprow does not show the subrows.  I adapted 
the sample program that comes 
with the PyQt source distribution to illustrate the problem. Uncomment the code 
at line 194/195 to select the 
working code or my failing code.

I observe this problem when I run this on a Mac Book Pro (Mac OS X 10.6.4, 
Python 2.6, Qt 4.6.3, PyQt 4.7.4). I 
haven't had the opportunity to test this on other platforms. I'm not sure if 
there is some mistake in my code or this 
is a bug in PyQt or Qt.

Iv'e found one reference on the web to what sounds like a similar problem: 
http://www.python-forum.org/pythonforum/viewtopic.php?f=4&t=14676. 

Could anyone offer any insights? Many thanks in advance.

Best,

Herbert

#!/usr/bin/env python

############################################################################
##
## Copyright (C) 2005-2005 Trolltech AS. All rights reserved.
##
## This file is part of the example classes of the Qt Toolkit.
##
## This file may be used under the terms of the GNU General Public
## License version 2.0 as published by the Free Software Foundation
## and appearing in the file LICENSE.GPL included in the packaging of
## this file.  Please review the following information to ensure GNU
## General Public Licensing requirements will be met:
## http://www.trolltech.com/products/qt/opensource.html
##
## If you are unsure which license is appropriate for your use, please
## review the following information:
## http://www.trolltech.com/products/qt/licensing.html or contact the
## sales department at sa...@trolltech.com.
##
## This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE
## WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
##
############################################################################

# Modified to illustrate that QTreeView does not handle a model that is
# subclassed from a Python list.

from PyQt4 import QtCore, QtGui

# set dbg = True on the line below to see that only the first row is ever
# requested, altough rowCount() returns 2.
dbg = False

# Everything works when creating a new class for the model
class TreeItem_Works(object):
    def __init__(self, data):
        self.parentItem = None
        self.itemData = data
        self.dtrs = []

    def appendChild(self, item):
        item.parentItem = self
        self.dtrs.append(item)

    def child(self, row):
        return self.dtrs[row]

    def childCount(self):
        return len(self.dtrs)

    def columnCount(self):
        return len(self.itemData)

    def get_data(self, column):
        try:
            return self.itemData[column]
        except IndexError:
            return None

    def parent(self):
        return self.parentItem

    def row(self):
        if self.parentItem:
            return self.parentItem.dtrs.index(self)
        return 0

    def __str__( self ) :
        return self.to_string( indent = 0 )

    def to_string( self, indent = 0 ) :
        string = ' ' * indent + repr( self.itemData ) + '\n'
        d_indent = indent + 2
        for index in range( 0, self.childCount() ) :
            dtr = self.child( index )
            string += dtr.to_string( d_indent )
        return string

# Only the first row is shown (but not its daughters) when using this class
# that equates the list of daughters with the TreeItem itself by subclassing 
# from list. (Btw. subclassing from UserList.UserList has the same result.)

#import UserList
#class TreeItem_Fails(TreeItem_Works, UserList.UserList):
#    def __init__(self, data):
#        UserList.UserList.__init__( self )
#        self.parentItem = None
#        self.itemData = data

class TreeItem_Fails(TreeItem_Works, list):
    def __init__(self, data):
        list.__init__( self )
        self.parentItem = None
        self.itemData = data

    def appendChild(self, item):
        item.parentItem = self
        self.append(item)

    def child(self, row):
        return self[row]

    def childCount(self):
        return len(self)

    def row(self):
        if self.parentItem:
            return self.parentItem.index(self)
        return 0

class TreeModel(QtCore.QAbstractItemModel):
    def __init__(self, root_item, parent=None):
        QtCore.QAbstractItemModel.__init__(self, parent)
        self.rootItem = root_item

    def columnCount(self, parent):
        if parent.isValid():
            source = parent.internalPointer()
        else:
            source = self.rootItem
        if dbg : print "%s columns for %s" % ( source.columnCount(), 
                                                        source.itemData )
        return source.columnCount()

    def rowCount(self, parent):
        if parent.column() > 0:
            return 0
        if not parent.isValid():
            parentItem = self.rootItem
        else:
            parentItem = parent.internalPointer()
        if dbg : print "%s rows for %s" % ( parentItem.childCount(), 
                                                    parentItem.itemData )
        return parentItem.childCount()

    def index(self, row, column, parent):
        if not self.hasIndex(row, column, parent):
            return QtCore.QModelIndex()
        if not parent.isValid():
            parentItem = self.rootItem
        else:
            parentItem = parent.internalPointer()
        childItem = parentItem.child(row)
        if childItem:
            if dbg : print "%s at %s,%s is %s" % ( parentItem.itemData, 
                                            row, column, childItem.itemData )
            return self.createIndex(row, column, childItem)
        else:
            return QtCore.QModelIndex()

    def parent(self, index):
        if not index.isValid():
            return QtCore.QModelIndex()
        childItem = index.internalPointer()
        parentItem = childItem.parent()
        if parentItem == self.rootItem:
            return QtCore.QModelIndex()
        if dbg : print "%s at %s,%s has parent %s at %s,%s" % ( 
                            childItem.itemData, index.row(), index.column(), 
                                    parentItem.itemData, parentItem.row(), 0 )
        return self.createIndex(parentItem.row(), 0, parentItem)

    def data(self, index, role):
        if not index.isValid():
            return None
        if role != QtCore.Qt.DisplayRole:
            return None
        item = index.internalPointer()
        if dbg : print "%s at %s,%s is %s" % (item.itemData, index.row(), 
                                index.column(), item.get_data(index.column()) )
        return item.get_data(index.column())

    def flags(self, index):
        if not index.isValid():
            return QtCore.Qt.NoItemFlags
        return QtCore.Qt.ItemIsEnabled | QtCore.Qt.ItemIsSelectable

    def headerData(self, section, orientation, role):
        if orientation == QtCore.Qt.Horizontal and role == \
                                                    QtCore.Qt.DisplayRole:
            return self.rootItem.get_data(section)
        return None


if __name__ == '__main__':

    import sys

    # Select TreeItem_Works for a working example.
    # Select TreeItem_Fails to show that subclassing from list shows only
    # the first row

    TreeItem = TreeItem_Works
    #TreeItem = TreeItem_Fails

    node = TreeItem( ( '1', 'i' ) )
    node.appendChild( TreeItem( ( 'A', 'a' ) ) )
    leaf = TreeItem( ( 'B', 'b' ) )
    root_item = TreeItem(("Title", "Summary"))
    root_item.appendChild( node )
    root_item.appendChild( leaf )

    print root_item

    app = QtGui.QApplication(sys.argv)
    model = TreeModel( root_item )
    view = QtGui.QTreeView()
    view.setModel(model)
    view.setWindowTitle("Simple Tree Model")
    view.show()
    sys.exit(app.exec_())



_______________________________________________
PyQt mailing list    PyQt@riverbankcomputing.com
http://www.riverbankcomputing.com/mailman/listinfo/pyqt

Reply via email to