summaryrefslogtreecommitdiffstats
path: root/lib.py
diff options
context:
space:
mode:
authorJan Pokorný <jpokorny@redhat.com>2013-05-13 23:06:56 +0200
committerJan Pokorný <jpokorny@redhat.com>2013-05-13 23:06:56 +0200
commitb143f3179a87cbdda4c47f149eceb96bd3db9942 (patch)
tree93d3a12ff2bd97f8d7931275658e3b04f45a51d3 /lib.py
parentd133ee25c72e4da3e32d1e7d6858a82bd764eadf (diff)
downloadcluster-overview-b143f3179a87cbdda4c47f149eceb96bd3db9942.tar.gz
cluster-overview-b143f3179a87cbdda4c47f149eceb96bd3db9942.tar.xz
cluster-overview-b143f3179a87cbdda4c47f149eceb96bd3db9942.zip
Implement graph elements filter in UI
Signed-off-by: Jan Pokorný <jpokorny@redhat.com>
Diffstat (limited to 'lib.py')
-rw-r--r--lib.py157
1 files changed, 147 insertions, 10 deletions
diff --git a/lib.py b/lib.py
index 4126999..2f49ce6 100644
--- a/lib.py
+++ b/lib.py
@@ -6,7 +6,7 @@
# (to view a copy, visit http://creativecommons.org/licenses/by-sa/3.0/)
"""Elements library incl. visual aspects"""
-from sys import path
+#from sys import path
from os.path import expanduser, extsep
from pydot import Dot, Edge, Node, Subgraph
@@ -21,9 +21,25 @@ BLACKLIST = []
# Customization via meta level
#
-def bl_test(x):
- return \
- not set((x.__class__,) + x.__class__.__bases__).intersection(BLACKLIST)
+# obfuscation contest in recursively yielding base classes up to given set
+bases = lambda x: (lambda f_, *xs_: f_(f_, *xs_)) \
+ (lambda f, x=[], *xs:
+ [x] + f(f, *x.__bases__) + f(f, *xs)
+ if x not in ([], LibSubgraph, LibNode, LibEdge)
+ else [],
+ x)
+bl_test = lambda ix: not set(bases(ix.__class__)).intersection(BLACKLIST)
+
+
+def bl_map_nodes_edges(nodes, edges, prev_nnames=None):
+ nnames = prev_nnames if prev_nnames is not None else set()
+ for n in nodes:
+ n.get_attributes()['style'] = 'invis'
+ nnames.add(n.get_name())
+ for e in edges:
+ if not bl_test(e) \
+ or e.get_source() in nnames or e.get_destination() in nnames:
+ e.get_attributes()['style'] = 'invis'
class LibMeta(type):
@@ -35,10 +51,24 @@ class LibMeta(type):
subgraphs = kwargs.pop('_subgraphs', ())
nodes = kwargs.pop('_nodes', ())
edges = kwargs.pop('_edges', ())
+
+ if not hasattr(self, 'nnames'):
+ self.nnames = set()
+ nnames = self.nnames
+ map(lambda x: nnames.update(getattr(x, 'nnames')),
+ tuple(subgraphs) + tuple(nodes) + tuple(edges))
+
old_init(self, *args, **kwargs)
- for s in filter(bl_test, subgraphs): s and self.add_subgraph(s)
- for n in filter(bl_test, nodes): n and self.add_node(n)
- for e in filter(bl_test, edges): e and self.add_edge(e)
+
+ bl_map_nodes_edges(filter(lambda x: not bl_test(x), nodes),
+ edges, nnames)
+ for n in nodes:
+ self.add_node(n)
+ for e in edges:
+ self.add_edge(e)
+
+ for s in filter(bl_test, subgraphs):
+ s and self.add_subgraph(s)
cls.__init__ = new_init
@@ -47,10 +77,14 @@ class LibDot(Dot):
def __init__(self, *args, **kwargs):
kwargs.setdefault('graph_type', 'digraph')
super(LibDot, self).__init__(*args, **kwargs)
+ self.set_suppress_disconnected(True)
class LibSubgraph(Subgraph):
__metaclass__ = LibMeta
+ def __init__(self, *args, **kwargs):
+ super(LibSubgraph, self).__init__(*args, **kwargs)
+ #self.set_suppress_disconnected(True)
class LibNode(Node):
@@ -248,7 +282,6 @@ class DelegateCIM(Delegate, CIM):
# main-helpers
#
-
def export(fnc):
__all__.append(fnc.__name__)
return fnc
@@ -272,8 +305,112 @@ def xdot_graph(*args, **kwargs):
#import xdot
print 'missing xdot; use "pip install xdot" or equivalent'
raise
- window = xdot.DotWindow()
- window.set_dotcode(gen_graph(*args, **kwargs).to_string())
+
+ class LibDotWindow(xdot.DotWindow):
+ # heavily inspired from http://zetcode.com/gui/pygtk/menus/
+ def on_change_view(self, widget):
+ label = widget.get_label()
+ bl = self._kwargs.setdefault('blacklist', [])
+ change = False
+ if widget.active and globals()[label] in bl:
+ bl.remove(globals()[label])
+ change = True
+ elif not widget.active and label not in bl:
+ bl.append(globals()[label])
+ change = True
+ if change:
+ self.set_dotcode(
+ gen_graph(*self._args, **self._kwargs).to_string())
+
+ def on_clean_all(self, widget):
+ for item in widget.get_parent().get_children():
+ if not isinstance(item, gtk.CheckMenuItem):
+ continue
+ item.set_active(False)
+ item.set_active(True)
+ item.activate()
+
+ def on_set_all(self, widget):
+ for item in widget.get_parent().get_children():
+ if not isinstance(item, gtk.CheckMenuItem):
+ continue
+ item.set_active(True)
+ item.set_active(False)
+ item.activate()
+
+ def __init__(self, *args, **kwargs):
+ self._args = args
+ self._kwargs = kwargs
+ super(LibDotWindow, self).__init__()
+ self.set_dotcode(gen_graph(*args, **kwargs).to_string())
+
+ mb = gtk.MenuBar()
+
+ filemenu = gtk.Menu()
+ filem = gtk.MenuItem("File")
+ filem.set_submenu(filemenu)
+
+ edgemenu = gtk.Menu()
+ edge = gtk.MenuItem("Edge")
+ edge.set_submenu(edgemenu)
+ edgemenuitem = gtk.MenuItem("Clean all")
+ edgemenuitem.connect("activate", self.on_clean_all)
+ edgemenu.append(edgemenuitem)
+ edgemenuitem = gtk.MenuItem("Set all")
+ edgemenuitem.connect("activate", self.on_set_all)
+ edgemenu.append(edgemenuitem)
+ edgemenu.append(gtk.SeparatorMenuItem())
+
+ nodemenu = gtk.Menu()
+ node = gtk.MenuItem("Node")
+ node.set_submenu(nodemenu)
+ nodemenuitem = gtk.MenuItem("Clean all")
+ nodemenuitem.connect("activate", self.on_clean_all)
+ nodemenu.append(nodemenuitem)
+ nodemenuitem = gtk.MenuItem("Set all")
+ nodemenuitem.connect("activate", self.on_set_all)
+ nodemenu.append(nodemenuitem)
+ nodemenu.append(gtk.SeparatorMenuItem())
+
+ for i in __all__:
+ try:
+ i = globals()[i]
+ if issubclass(i, LibEdge):
+ if i is LibEdge:
+ continue
+ imenuitem = gtk.CheckMenuItem("%s" % i.__name__)
+ imenuitem.set_active(True)
+ imenuitem.connect("activate", self.on_change_view)
+ edgemenu.append(imenuitem)
+ elif issubclass(i, LibNode):
+ if i is LibNode:
+ continue
+ imenuitem = gtk.CheckMenuItem("%s" % i.__name__)
+ imenuitem.set_active(True)
+ imenuitem.connect("activate", self.on_change_view)
+ nodemenu.append(imenuitem)
+ except:
+ pass
+
+ exit = gtk.MenuItem("Exit")
+ exit.connect("activate", gtk.main_quit)
+ filemenu.append(exit)
+
+ mb.append(filem)
+ mb.append(edge)
+ mb.append(node)
+
+ #vbox = gtk.VBox(False, 2)
+ vbox = self.get_children()[0]
+ vbox.pack_start(mb, False, False, 0)
+ vbox.reorder_child(mb, 0)
+ #vbox.pack_start(gtk.Label(), True, False, 0)
+ #vbox.pack_start(self.statusbar, False, False, 0)
+
+ self.connect("destroy", gtk.main_quit)
+ self.show_all()
+
+ window = LibDotWindow(*args, **kwargs)
window.connect('destroy', gtk.main_quit)
gtk.main()