Here's a demo illustrating the use of icons to show status in the tree. Put the code in a @button script node and you can update the status display by clicking that button.

I have an HTML page with a hierarchical structure, and I tend to turn off various parts of it using comments. This code allows Leo to show you the status of each node with icons:


As well as "on" (green arrow) and "off" (blue dash) status, the code marks "error" (red x) status, when an XML syntax error is found.

But the code is flexible, you don't need to be using XML, any case where you can determine status from body content could use this code.

Heres the code:

from lxml import etree  # only needed for XML in this use case

class StatusSetter:
    """Add and update icons on nodes to indicate status based on content
    and hierachy.

    Usage:  ss = StatusSetter(); ss.markStatus(p)

    Override statusBody() to change status detection.

    # icons for statuses, relative to .../leo/Icons directory
    icon = {
    'off' : 'Tango/16x16/actions/remove.png',
    'on' : 'Tango/16x16/actions/stock_right.png',
    'bad' : 'Tango/16x16/actions/stock_stop.png',

    # precedence ranks for the statuses
    rank = {
    'off' : 0,
    'on' : 10,
    'bad' : 20,

    def __init__(self):
        """minor setup"""
        self.c = c
        self.iconDir = g.os_path_abspath(
            g.os_path_join(,"..","Icons"))) = self.c.editCommands

    def statusBody(self, p):
        """Determine if the body text of p is active"""

        # this version checks if the body is valid, non-empty, XML

            # wrap in <ROOT/> so that "<p>this would be</p><p>valid</p>"
            doc = etree.fromstring('<ROOT>'+p.bodyString().replace('<<<','')+'</ROOT>')
            if len(doc.xpath('//*')) > 1:  # len()==1 if all commented out
                return 'on'
        except etree.XMLSyntaxError:
            return 'bad'

        return 'off'

    def statusPosition(self, p):
        """Upate status markers for p and its descendents"""

        status = self.statusBody(p)

        for n in p.children_iter():
            statpos = self.statusPosition(n)
            if self.rank[statpos] > self.rank[status]:
                status = statpos

        self.setStatusIndicator(p, status)
        return status

    def setStatusIndicator(self, p, status):
        """Marks nodes' status"""

        # icons placed on node by other code
        icons = [i for i in
                 if 'isStatusIndicator' not in i]

        path = g.os_path_normpath(self.icon[status])  # set / or \, self.iconDir, path,
            2, on='vnode', isStatusIndicator='1', where = 'beforeIcon')
            # beforeBox beforeIcon beforeHeadline afterHeadline

        # update icons on node, icons)

    def markStatus(self, p):
        """Wrapper for redraw around statusPosition()"""


marker = StatusSetter()