This is an Engineering Notebook post, explaining how to greatly improve the 
performance of Leo's outline pane.  I don't have plans to do this at 
present, but it's important to important to discuss the details now, while 
they are fresh in my mind.  This will be pre-writing for an enhancement 
issue, with no particular due date.

*Note*: The ideas discussed below could apply to QGraphicsScene as well as 
Leo's existing QTreeWidget.

*Background*

At present, Leo's core calls c.redraw whenever the outline changes.  There 
are also some shortcut calls, that update only icons.  This is the approach 
that Leo has used from its earliest days, with only fairly minor 
evolutionary changes.  This is usually plenty good enough, but significant 
improvements in speed are possible, and might be useful when scrolling 
rapidly through a large outline.

*Incremental allocation*

The name "c.redraw" is a misnomer.  The actual code *reallocates* the 
entire tree, which then causes Qt to redraw it. Instead of reallocating the 
entire tree whenever any part of it changes, it would be significantly 
faster (for large outlines) to update only those parts of an outline that 
have actually changed. To do this, Leo's core would make *incremental calls* 
to update the outline.  

Something like the following calls would be needed:

c.tree.delete(p) # Delete position p
c.tree.insertAsNthChildOf(p, p2) # Insert p2 as the nth child of p.
c.tree.insertAfter(p,p2) # Insert p2 after p.
c.tree.clone(p) # Clone p, creating a following sibling node.
c.tree.expand(p) # Expand p.
c.tree.contract(p) # Contract p.

*All the operations listed above are complicated*, because they all must 
support clones.  For example, inserting an item (a QTreeWidgetItem 
<http://doc.qt.io/archives/qt-4.8/qtreewidgetitem.html>) anywhere in the 
outline must insert *copies* of the item if the position p is a child of 
any clone.  Even the expand and contract operations can affect arbitrarily 
many *already allocated* items.  The expansion state of each item must be 
set/cleared individually.

The present redraw code in qtree.drawTopTree and helpers does this easily.  
It would be much more complicated to do this incrementally, but the 
performance payoff could be arbitrarily large.

*Changing Leo's core*

There are 210 calls to c.redraw* in Leo's core at present.  Perhaps only a 
dozen or such calls would actually have to be replaced in order to yield 
significantly better performance.  A mix of incremental and complete 
reallocation is possible.

*QGraphicsScene vs QTreeWidget*

Yesterday's work proves, imo, that the QTreeWidget should be always be 
fully populated with items, including items that aren't visible.  This 
allows makes redraw work properly when the user has scrolled the outline 
pane by hand.

If a QGraphicsScene were used, perhaps only the visible nodes would have to 
be allocated.  The tradeoffs in doing so are complicated.  In most cases, 
significantly few nodes/items would *actually* be allocated, but expanding 
and contracting nodes then becomes much more expensive.  And of course the 
scrolling issues that bedevil QTreeWidget would have to be handled.

*Summary*

This project is feasible. The present data structures in the LeoQtTree 
class likely suffice to support these operations, and any required data 
could easily be added.  Replacing just few calls to c.redraw might yield 
significantly better performance, and significantly less load on the GC.

The approach described above applies to any implementation of Leo's outline 
pane, including one based on QGraphicsScene. 

I personally see no great need to do this project, but I would encourage 
anyone to investigate this approach if it appeals to them.

Edward

-- 
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