Tuesday, January 27, 2015

PySide Tree Tutorial IIC: Cross-examining simpletreemodel

Part of a series on treebuilding in PySide: see Table of Contents
 
In this tutorial, we are following simpletreemodel to the letter, simply trying to understand the code as given. But we should not assume that there is no room for improvement. For instance, in the code in post IIB, when initializing a TreeItem it would be helpful to add:

if parent is not None:
      parent.appendChild(self)

This would let us add a child to its parent immediately, right when the child is created. A significant simplification of the code. If you have other ways we might optimize the code, by all means let us know in the comments!

Further, if our goal was truly to build a simple, read-only model with a data store as small as the one that comes with this example, then we would weigh options other than QAbstractItemModel. In particular, we would want to consider using QTreeWidget or QStandardItemModel, which provide simplicity and ease-of-use in exchange for diminished speed and flexibility. In Part V, we will see how to create a tree like the one in our example using these tools. You'll see that the code is much simpler.

However, for larger models that require more flexibility and speed, you will probably end up subclassing QAbstractItemModel. In that case, simpletreemodel provides a useful template. While it was never meant to be a fully optimized industrial-grade example, it is helpful precisely because it provides a minimal working prototype to help people get their bearings, and contains little extraneous fluff.

3 comments:

Coderboi said...

(Note to MOD: this is a fixed version of the code in my earlier comment which I found bugs in)

I had a hard time following the logic of the original TreeModel.setupModelData(), so I rewrote it as follows. This code depends on the abovementioned automatic child append behavior that was added to the TreeItem constructor.

Would welcome constructive criticism wrt performance, correctness, clarity, etc... of the below:


def setupModelData(self, lines):
    for l in lines:
        data = [col for col in l.split('\t') if col]
        if data:
            indent = data[0].lastIndexOf(data[0].trimmed())
            data[0]=data[0].trimmed()
            if indent==0:
                currNode = TreeItem( data, self.rootItem )
                currRoot = [ {"indent":0, "node":currNode} ]
            else:
                if indent > currRoot[-1]["indent"]:
                    currNode = TreeItem( data, currRoot[-1]["node"] )
                    currRoot.append( {"indent":indent, "node":currNode} )
                else:
                    if indent < currRoot[-1]["indent"]:
                        while indent<currRoot[-1]["indent"]: currRoot.pop()
                    currNode = TreeItem( data, currRoot[-2]["node"] )
                    currRoot[-1]["node"] = currNode

Eric Thomson said...

Coderboi: thanks a lot I'm glad you read my post. Frankly it has been so long since I looked at this code, it would take me some time to evaluate or test anything, but I do appreciate your contribution and it does seem very clean (assuming it works). Trees in Qt are complicated beasts!

Coderboi said...

NP Eric.

Thanks for taking the time to reply!