← Back to team overview

gtg-contributors team mailing list archive

Re: (no subject)

 

Hello,

First of all, I want to say that it's normal if test are currently broken
because I'm trying another implementation strategie in the filteredtree.

The nearly working code is commented out currently.


On Sun, 22 Aug 2010 21:00:17 +0200, Luca Invernizzi
<invernizzi.l@xxxxxxxxx> wrote:
> Lionel, could you explain when, why and by who signals are emitted in
> liblarch? I'm a bit confused.
> 
> Let's take the case of adding a node to a parent node. From what I
> understood:
>   - we start from the Tree (add_node function), which just passes the
call
>   to
>     MainTree

Correct

>   - we are in MainTree.add_node:
>      - we call node.set_tree(), which recreates all tree pending
>      relationships
>        (I haven't figured out why)

To build relationships, you have to be in a tree. A node alone cannot have
any relationship. Thus, when you create a relationship into a node not
already into a tree, the relationship is not created but saved into
pending_relationship.

When you add a node to a tree, all the relationships for that node are
then created.

This is useful to allow backends to build a task before adding the task to
the tree.

As soon as the task is in a tree, pending_relationship is not used anymore
in that node. (there's also a pending_relationship in the tree itself,
which is used when at least one of the two involved node is not yet present
in the tree.

Both pending_relationship thus have the same purpose but are used in a
different context. Pending_relationship in the node is used when you deal
with a node before adding it to a tree. Pending_relationship in the tree is
used when you deal directly with a tree and you might be waiting for one of
the task.

Take the example of the localfile backend. It saves only a "children" kind
of relationship. When built, tasks are not aware of their parents.

It means that:

1) you create the parent node. You create a parent-child relationship
which is pending in the node.
2) You add the parent to the tree. The pending parent-child is set in the
tree.
3) If child is not yet loaded, the parent-child is set as pending in the
tree.
4) You load the child node. When you set the tree for it, the tree
recognize it has a pending relationship for that node and create it.

>   - the "relationship" is created and kept as pending (to avoid race
>   conditions)
>   - we add the node to the list of nodes of the tree
>   - the pending relationship is updated to be no more pending
>   - we execute the "added" callback for the new node. A comment
>     says that the "added" callback will take care of executing the
>     "modified" callback for the parent (which, from rev. 1040 on,
doesn't
>     work anymore).

The "added" callback is independant of anyrelationship. Added means "in a
tree". The fact that a relationship exists or not is irrelevant. Also, keep
in mind that a pending relationship doesn't exist. (it wouldn't make sense
anyway).

I'm aware of that missing "modified" callback. It's part of my experiment.
Indeed, I fear that by doing that, we refresh each node all the time as,
before, when a node was modified, it was sending a "modified" signal to its
parents and childrens. See the loop ?

>   - the "added" callback is caught by the filtered tree. This, puts it
in a
>     queue of signals (so that signal callbacks are not executed
>     concurrently)

Indeed. That queue doesn't seem to be required but was there as a
protection.

>   - when its turn comes, it calls FilteredTree.__add_node
>   - this first does something with the node parents (which is not clear
to
>   me),

Remember that FT is a view. This view is, basically, another tree
renconstructed. This tree is stored in a python dic. (self.cache_nodes).
Each displayed node is a key to a node_dic. A node_dic contains two keys :
'parents' and 'children. This is thus a bidirectionnal tree.

As an optimisation, each key without parent is also kept in a virtual root
: self.cache_vr).

The difficulty is then to keep that dic in a consistent state (children of
the parents should always be in sync with parents of the children and
cache_vr have to be also in sync).

Previously, the paths for node were also stored in the dic_node, which
added a lot of complexity to keep cache_nodes consistent.

So, what does __add_node do ?

First, it computes what should be the parents of the displayed node. Then,
if those parents are not yet displayed in the FT, they are added.

Then, it really add the nodes : putting children in the parents, creating
the node_dic and adding it to self.cache_nodes.



>     then, through a callback, calls the viewtree, which emits the signal
>     node-added-inview.
>   - that goes into liblarch-gtk that should be just a thin layer around
the
>     tree.
> 
>   Is this correct? I haven't found where the modified signal for the
parent
>   should be emitted.

You are 100% correct. The modified signal for the parent should indeed be
sent when the node is added. 

I'm really happy that you are interested in the code and I want to answer
all the questions you might have. I'm surprized that you understood the
code so well the first time ;-)


Don't hesitate to contact me on Jabber when you feel it to discuss that or
to experiment.

Yours,

Lionel



Follow ups

References