git-svn-id: file:///Users/arjan/backup/gaphor/trunk/gaphor@165 a8418922-720d-0410-834f-a69b97ada669
195 lines
5.5 KiB
Python
Executable File
195 lines
5.5 KiB
Python
Executable File
#!/usr/bin/env python
|
|
'''This application shows a nice tree view of the UML meta model.
|
|
|
|
Somehow, this peace of code seems to crash by X server. I thinnk it's a bug in
|
|
GTK+. ... but how do I isolate the bug?
|
|
'''
|
|
|
|
import sys
|
|
sys.path.append("..")
|
|
|
|
from gaphor.UML import *
|
|
import gtk
|
|
import gobject
|
|
import types
|
|
|
|
|
|
# to create a new GtkTreeModel from python, you must derive from
|
|
# GenericTreeModel.
|
|
class TreeModel(gtk.GenericTreeModel):
|
|
''' The node is defined by a "name" tuple. '''
|
|
|
|
def __init__(self, klass):
|
|
'''constructor for the model. Make sure you call
|
|
PyTreeModel.__init__'''
|
|
self.iter = None # Value used to keep track of iterations.
|
|
self.klass = klass;
|
|
|
|
gtk.GenericTreeModel.__init__(self)
|
|
|
|
def class_from_node(self, node):
|
|
klass = self.klass
|
|
for n in node:
|
|
attrdef = klass._attrdef[n]
|
|
klass = attrdef[1]
|
|
return klass
|
|
|
|
# the implementations for TreeModel methods are prefixed with on_
|
|
def on_get_flags(self):
|
|
'''returns the GtkTreeModelFlags for this particular type of model'''
|
|
return 0
|
|
|
|
def on_get_n_columns(self):
|
|
'''returns the number of columns in the model'''
|
|
return 1
|
|
|
|
def on_get_column_type(self, index):
|
|
'''returns the type of a column in the model'''
|
|
return gobject.TYPE_STRING
|
|
|
|
def on_get_path(self, node):
|
|
'''returns the tree path (a tuple of indices at the various
|
|
levels) for a particular node.'''
|
|
print "on_get_path", node
|
|
return node
|
|
|
|
def on_get_iter(self, path):
|
|
'''returns the node corresponding to the given path. The patch is a
|
|
tuple of values, like (0 1 1). We have to figure out a path that is
|
|
easy to use by on_get_value() and can also be easely extended by
|
|
on_iter_children() and chopped by on_iter_parent()'''
|
|
def get_iter(klass, path):
|
|
item = klass._attrdef.items()[path[0]]
|
|
if len(path) == 1:
|
|
return (item[0],)
|
|
else:
|
|
subklass = klass._attrdef.items()[path[0]][1][1]
|
|
return (item[0],) + get_iter(subklass, path[1:])
|
|
|
|
node = get_iter(self.klass, path)
|
|
|
|
#print "on_get_iter", path, node
|
|
return node
|
|
|
|
def on_get_value(self, node, column):
|
|
'''returns the value stored in a particular column for the node'''
|
|
assert column == 0
|
|
attr = node[-1]
|
|
parent = self.class_from_node(node[:-1])
|
|
attrdef = parent._attrdef[attr]
|
|
#print "on_get_value", node, attrdef
|
|
closing = ")"
|
|
if attrdef[0] == Sequence:
|
|
closing = "*)"
|
|
|
|
if len(attrdef) == 3:
|
|
return attr + " (" + attrdef[1].__name__ + "::" + attrdef[2] + closing
|
|
else:
|
|
return attr + " (" + attrdef[1].__name__ + closing
|
|
|
|
def on_iter_next(self, node):
|
|
'''returns the next node at this level of the tree'''
|
|
attr = node[-1]
|
|
parent = self.class_from_node(node[:-1])
|
|
attrdef = parent._attrdef[attr]
|
|
items = parent._attrdef.items()
|
|
sentinel = 0
|
|
for i in items:
|
|
if sentinel:
|
|
node = node[:-1] + (i[0],)
|
|
#print "on_iter_next", node
|
|
return node
|
|
elif i[0] == attr:
|
|
sentinel = 1 # Use next item
|
|
#print "on_iter_next (None)"
|
|
return None
|
|
|
|
def on_iter_children(self, node):
|
|
'''returns the first child of this node'''
|
|
klass = self.class_from_node(node)
|
|
if klass.__dict__.has_key("_attrdef"):
|
|
item = klass._attrdef.items()[0][0]
|
|
#print "on_iter_children", node, item
|
|
return node + (item,)
|
|
else:
|
|
#print "on_iter_children (None)"
|
|
return None
|
|
|
|
def on_iter_has_child(self, node):
|
|
'''returns true if this node has children'''
|
|
#return 0
|
|
klass = self.class_from_node(node)
|
|
#print "on_iter_has_child", node
|
|
return klass.__dict__.has_key("_attrdef") and len(klass._attrdef) > 0
|
|
|
|
def on_iter_n_children(self, node):
|
|
'''returns the number of children of this node'''
|
|
klass = self.class_from_node(node)
|
|
if klass.__dict__.has_key("_attrdef"):
|
|
items = klass._attrdef.items()
|
|
#print "on_iter_n_children", len(items)
|
|
return len(items) - 1
|
|
else:
|
|
#print "on_iter_n_children (None)"
|
|
return 0
|
|
|
|
def on_iter_nth_child(self, node, n):
|
|
'''returns the nth child of this node'''
|
|
#print "on_iter_nth_child"
|
|
if node == None:
|
|
#print 'result =', n, self.klass._attrdef.items()[0][0]
|
|
return (self.klass._attrdef.items()[0][0],)
|
|
klass = self.class_from_node(node)
|
|
if klass.__dict__.has_key("_attrdef") and len(node) >= n:
|
|
item = klass._attrdef.items()[n][0]
|
|
#print "on_iter_nth_child", node, klass.__name__, item
|
|
#print 'result =', n, node, item
|
|
return node + (item,)
|
|
else:
|
|
#print 'result =', n, None
|
|
return None
|
|
|
|
def on_iter_parent(self, node):
|
|
'''returns the parent of this node'''
|
|
#print "on_iter_parent", node
|
|
return node[:-1]
|
|
|
|
def main():
|
|
args = sys.argv[1:]
|
|
|
|
base_class = None
|
|
try:
|
|
base_class = eval(args[0])
|
|
except NameError:
|
|
print "Invalid class name (" + args[0] + ")"
|
|
sys.exit(1)
|
|
except IndexError:
|
|
print "Use gbrowseUML.py <class>, now using class ModelElement"
|
|
base_class = ModelElement
|
|
|
|
window = gtk.Window()
|
|
window.connect('destroy', lambda win: gtk.main_quit())
|
|
window.set_title('gbrowseUML -- ' + base_class.__name__)
|
|
window.set_default_size(250, 400)
|
|
|
|
scrolled_window = gtk.ScrolledWindow()
|
|
scrolled_window.set_policy(gtk.POLICY_AUTOMATIC, gtk.POLICY_AUTOMATIC)
|
|
window.add(scrolled_window)
|
|
|
|
model = TreeModel(base_class)
|
|
tree_view = gtk.TreeView(model)
|
|
cell = gtk.CellRendererText()
|
|
# the text in the column comes from column 0
|
|
column = gtk.TreeViewColumn(base_class.__name__, cell, text=0)
|
|
tree_view.append_column(column)
|
|
|
|
scrolled_window.add(tree_view)
|
|
window.show_all()
|
|
|
|
gtk.main()
|
|
|
|
if __name__ == '__main__':
|
|
main()
|
|
else:
|
|
del main
|