In another thread 
<https://groups.google.com/d/msg/leo-editor/ZgPQ-f7jL3g/de6LbvTSAQAJ> Edward 
wrote:

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):
        event.ignore()
        d.hide()

    d.closeEvent = closeEvent
    w = QtWidgets.QTreeWidget(d)
    w.setObjectName('tree')
    layout = QtWidgets.QVBoxLayout(d)
    layout.addWidget(w)
    d.setLayout(layout)
    d.setModal(False)
    d.setWindowFlags(d.windowFlags().__or__(0x40000))
    return d

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

def treeW():
    d = demoW()
    return d.findChild(QtWidgets.QTreeWidget, 'tree')

g.app.gui.replaceClipboardWith(g.getScript(c, 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
tw.clear()
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)
    titems[p.gnx].append(item)
    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)
g.es('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?

Vitalije

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 leo-editor+unsubscr...@googlegroups.com.
To post to this group, send email to leo-editor@googlegroups.com.
Visit this group at https://groups.google.com/group/leo-editor.
For more options, visit https://groups.google.com/d/optout.

Reply via email to