The latest version of prototype is 84b54fc3af.
Currently it is almost 1000 lines including comments and includes the
following features:
browsing outline
editing headlines
editing bodies
shows basic Leo icons on nodes
inserting new nodes
deleting nodes
moving nodes up, down, left or right
promote / demote
hoist / de-hoist
cloning nodes
undo/redo for outline editing commands
I don't plan to work more on this prototype. Its purpose is to prove my
claims from the beginning of this post. I believe this covers about 5000
lines of code in Leo:
- LeoQTreeWidget ~ 500,
- LeoTree ~ 350,
- leoChapters.py ~ 480,
- qt_tree.py ~ 1430,
- leoUndo.py ~ 1730
- ... total 4490 LOC + about 500 lines for implementing all these
commands.
This means that the bugs have about 4000 lines more space to hide than is
necessary.
It is also 4000 lines more for CPU to execute and a lot of those lines are
inside
loops. By applying all these refactorings Leo's code will be much smaller
and hopefully
it will run much faster.
The prototype is not fully documented. There are a few not very obvious
methods that
I had to rewrite several times to eliminate bugs that I haven't spotted at
first.
Those methods require more detailed explanation.
First is make_undoable_move. Here it is:
def make_undoable_move(self, oldparent, srcindex, newparent, dstindex):
t = self.tree
root = t.invisibleRootItem()
trash = []
newitems = [(x, oldparent.child(srcindex).clone())
for x in all_other_items(root, newparent)]
def domove():
for item in all_other_items(root, oldparent):
trash.append(item.takeChild(srcindex))
for item, child in newitems:
item.insertChild(dstindex, child)
curr = move_treeitem(oldparent, srcindex, newparent, dstindex)
self.tree.setCurrentItem(curr)
def undomove():
for item, child in newitems:
item.takeChild(dstindex)
for item in all_other_items(root, oldparent):
item.insertChild(srcindex, trash.pop())
curr = move_treeitem(newparent, dstindex, oldparent, srcindex)
self.tree.setCurrentItem(curr)
domove()
self.c.addUndo(undomove, domove)
oldparent and newparent are tree widget items, and srcindex/dstindex are
ints. At first I was creating and deleting child items inside functions
domove and undomove. However, this caused exceptions when performing undo
and redo later, because redo would create new items and maybe next undo
block relies on the items that used to be created before. To solve this
issue, all necessary items must be created outside domove/undomove and all
items that will be deleted by this command must be kept in local variable
trash. This pattern I had to repeat in other commands as well.
Generator all_other_items yields tree widget items that point to the same v
node, skipping the given one. This generator uses links between v-nodes so
the order of the execution is important. In this method this order of the
execution doesn't matter but in some other methods it does.
When moving item from one parent to another one, if the oldparent is cloned
or belongs to the cloned subtree it means we have to remove child not only
from the oldparent, but from all other items that point to the same v node
as oldparent. It means we will have to delete some items. The deleted items
will go to trash from where we will be able to collect them again during
the undo command.
OTOH if the newparent is part of cloned subtree, that means we will need
extra items to insert in every other clone. The command moves single item
from oldparent to the newparent and all other clones both on the source
side and on the destination side are processed using all_other_items
generator. Sometimes like in this method the results of this generator are
kept in local variable and iterated again using that variable (like
newitems variable above).
Vitalije
--
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 [email protected].
To view this discussion on the web visit
https://groups.google.com/d/msgid/leo-editor/f22b17c0-aace-45bc-a8b9-a6f6931134b4%40googlegroups.com.