In another thread 
<> Edward 

4. Leo's tree drawing code would likely choke on showing more than a few 
> thousand nodes. 

It wasn't the first time that I read about it. Also speaking about 
"rendering" tree and how it is expensive has always seemed a bit strange to 
me, because I was expecting that rendering tree items should do QTreeWidget 
by itself. I've always thought that this vocabulary (rendering tree items) 
was caused by some ancient way the things used to work perhaps in the 
Tkinter time or even before. 

Today I have looked more closely to the implementation of this tree 
rendering methods. I was surprised to see that Leo actually clears all 
items from the QTreeWidget and then recreates those which are visible. It 
looked strange to me and I thought perhaps QTreeWidget can't handle very 
well large number of items, so I made an experiment.

Here is the script:
from leo.core.leoQt import QtWidgets, QtCore
from collections import defaultdict
def demoW():
    DWH = 'demo-window-instance'
    w = c.user_dict.get(DWH)
    if not w:
        w = createDemoWindow()
        c.user_dict[DWH] = w
    return w

def createDemoWindow():

    d = QtWidgets.QDialog()

    def closeEvent(event, d=d):

    d.closeEvent = closeEvent
    w = QtWidgets.QTreeWidget(d)
    layout = QtWidgets.QVBoxLayout(d)
    return d

def showW():
    d = demoW()
    if d.isVisible():
        # The order is important, and tricky.
    return d

def treeW():
    d = demoW()
    return d.findChild(QtWidgets.QTreeWidget, 'tree'), p, useSentinels=False))
d = showW()
tw = treeW()
titems = defaultdict(lambda: list((None,)))
def addnode(tw, par, txt):
    pitem = par or tw
    item = QtWidgets.QTreeWidgetItem(pitem)
    item.setFlags(item.flags() | QtCore.Qt.ItemIsEditable)
    item.setText(0, txt)
    return item
i = 0
def pgn(p):
    pp = p.parent()
    gnx = pp.gnx if pp else 'root'
    return titems[gnx][-1]
i = 0
for p in c.allNodes_iter():
    par = pgn(p)
    item = addnode(tw, par, p.h)
    i += 1
for k, v in titems.items():
    if k is 'root': continue
    if len(c.fileCommands.gnxDict[k].children):
        for item in v[1:]:
            tw.expandItem(item)'total %d nodes'%i)

It fills the tree widget with total of 10313 nodes (LeoPyRef.leo my 
version) and tree seems very responsive. There is no sign of performance 
issues. Expanding and collapsing nodes is smooth. 

This left me wandering. Why Leo doesn't use this widget as it is, and just 
dump all the vnodes to it? Is there something I am not aware of?


PS: Initializing code for QDialog I borrowed from the Leo :-)


You received this message because you are subscribed to the Google Groups 
"leo-editor" group.
To unsubscribe from this group and stop receiving emails from it, send an email 
To post to this group, send email to
Visit this group at
For more options, visit

Reply via email to