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_normpath(
g.os_path_join(g.app.loadDir,"..","Icons")))
self.com = 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
try:
# 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 self.com.getIconList(p)
if 'isStatusIndicator' not in i]
path = g.os_path_normpath(self.icon[status]) # set / or \
self.com.appendImageDictToList(icons, self.iconDir, path,
2, on='vnode', isStatusIndicator='1', where = 'beforeIcon')
# beforeBox beforeIcon beforeHeadline afterHeadline
# update icons on node
self.com.setIconList(p, icons)
def markStatus(self, p):
"""Wrapper for redraw around statusPosition()"""
self.c.beginUpdate()
try:
self.statusPosition(p)
finally:
self.c.setChanged(True)
self.c.endUpdate()
marker = StatusSetter()
marker.markStatus(p)