*** empty log message ***

git-svn-id: file:///Users/arjan/backup/gaphor/trunk/gaphor@37 a8418922-720d-0410-834f-a69b97ada669
This commit is contained in:
Arjan Molenaar 2002-02-07 11:15:15 +00:00
parent b28d7bfba8
commit 4b063063d9
9 changed files with 457 additions and 76 deletions

50
doc/storage.txt Normal file
View File

@ -0,0 +1,50 @@
Saving and loading Gaphor diagrams
The idea is to keep the file format as simple and extensible as possible.
This is the format as used by Gaphor.
Everything interesting is between the `Gaphor' start and end tag.
The file is as flat as possible: UML elements (including Diagram) are at
toplevel, no nesting.
A UML element can have two tags: `Reference' and `Value'. Reference is used to
point to other UML elements, Value has a value inside (an integer or astring).
Diagram is a special case. Since this element contains a diagram canvas inside,
it may become pretty big (with lots of nested elements).
This is handled by the load and save function of the Diagram class.
All elements inside a canvas have a tag `Item'.
<?xml version="1.0" ?>
<Gaphor version="1.0">
<Model id="1">
<Reference name="ownedElement" refid="2"/>
<Reference name="ownedElement" refid="3"/>
<Reference name="ownedElement" refid="4"/>
</Model>
<Diagram id="2">
<Reference name="namespace" refid="1"/>
<Canvas extents="(9.0, 9.0, 189.0, 247.0)" grid_bg="0xFFFFFFFF"
grid_color="0x80ff" grid_int_x="10.0" grid_int_y="10.0"
grid_ofs_x="0.0" grid_ofs_y="0.0" snap_to_grid="0"
static_extents="0">
<CanvasItem affine="(1.0, 0.0, 0.0, 1.0, 0.0, 0.0)" cid="0x8292114"
type="CanvasGroup">
<CanvasItem affine="(1.0, 0.0, 0.0, 1.0, 150.0, 50.0)" cid="0x8293e74"
height="78.0" subject="3" type="Actor" width="38.0"/>
<CanvasItem affine="(1.0, 0.0, 0.0, 1.0, 10.0, 10.0)" cid="0x82e7d74"
height="26.0" subject="5" type="Comment" width="100.0"/>
</CanvasItem>
</Canvas>
</Diagram>
<Actor id="3">
<Value name="name">
<![CDATA[Actor]]> </Value>
<Reference name="namespace" refid="1"/>
</Actor>
<UseCase id="4">
<Reference name="namespace" refid="1"/>
</UseCase>
<Comment id="5"/>
</Gaphor>

View File

@ -32,6 +32,14 @@ Geometry = types.ListType
FALSE = 0 FALSE = 0
TRUE = not FALSE TRUE = not FALSE
elements = { }
def lookup (id):
if elements.has_key(id):
return elements[id]
else:
return None
class Enumeration_: class Enumeration_:
'''The Enumerration class is an abstract class that can be used to create '''The Enumerration class is an abstract class that can be used to create
enumerated types. One should inherit from Enumeration and define a variable enumerated types. One should inherit from Enumeration and define a variable
@ -105,7 +113,7 @@ class Element:
attributes and relations are defined by a <class>._attrdef structure. attributes and relations are defined by a <class>._attrdef structure.
A class does not need to define any local variables itself: Element will A class does not need to define any local variables itself: Element will
retrieve all information from the _attrdef structure. retrieve all information from the _attrdef structure.
Element._hash is a table containing all assigned objects as weak references. elements is a table containing all assigned objects as weak references.
This class has its own __del__() method. This means that it can not be freed This class has its own __del__() method. This means that it can not be freed
by the garbage collector. Instead you should call Element::unlink() to by the garbage collector. Instead you should call Element::unlink() to
remove all relationships with the element and then it will remove itself if remove all relationships with the element and then it will remove itself if
@ -120,37 +128,39 @@ object if references are lehd by the object on the undo stack.
_index = 1 _index = 1
_attrdef = { 'presentation': ( Sequence, types.ObjectType ), _attrdef = { 'presentation': ( Sequence, types.ObjectType ),
'itemsOnUndoStack': (0, types.IntType ) } 'itemsOnUndoStack': (0, types.IntType ) }
_hash = { }
def __init__(self): def __init__(self):
print "New object of type", self.__class__ #print "New object of type", self.__class__
self.__dict__['__id'] = Element._index self.__dict__['__id'] = Element._index
self.__dict__['__signals'] = [ ] self.__dict__['__signals'] = [ ]
#Element._hash[Element._index] = weakref.ref (self) #Element._hash[Element._index] = weakref.ref (self)
Element._hash[Element._index] = self elements[Element._index] = self
Element._index += 1 Element._index += 1
def unlink(self): def unlink(self):
'''Remove all references to the object.''' '''Remove all references to the object.'''
#print 'Element.unlink()' #print 'Element.unlink():', self
self.emit("unlink") self.emit("unlink")
if Element._hash.has_key(self.__dict__['__id']): if elements.has_key(self.__dict__['__id']):
del Element._hash[self.__dict__['__id']] del elements[self.__dict__['__id']]
for key in self.__dict__.keys(): for key in self.__dict__.keys():
# In case of a cyclic reference, we should check if the element # In case of a cyclic reference, we should check if the element
# not yet has been removed. # not yet has been removed.
if self.__dict__.has_key (key) and \ if self.__dict__.has_key (key) and \
key not in ( 'presentation', '__signals', '__id' ): key not in ( 'presentation', 'itemsOnUndoStack', \
'__signals', '__id' ):
if isinstance (self.__dict__[key], Sequence): if isinstance (self.__dict__[key], Sequence):
# Remove each item in the sequence, then remove # Remove each item in the sequence, then remove
# the sequence from __dict__. # the sequence from __dict__.
for s in self.__dict__[key].list: list = self.__dict__[key].list
del self.__dict__[key][s] while len (list) > 0:
del self.__dict__[key][list[0]]
del self.__dict__[key] del self.__dict__[key]
else: else:
# do a 'del self.key' # do a 'del self.key'
if isinstance (self.__dict__[key], Element): #if isinstance (self.__dict__[key], Element):
self.__delattr__(key) #print '\tunlink:', key
self.__delattr__(key)
return self return self
# Hooks for presentation elements to add themselves: # Hooks for presentation elements to add themselves:
@ -167,6 +177,9 @@ object if references are lehd by the object on the undo stack.
def undo_presentation (self, presentation): def undo_presentation (self, presentation):
if not presentation in self.presentation: if not presentation in self.presentation:
# Add myself to the 'elements' hash
if len (self.presentation) == 0:
elements[self.id] = self
self.presentation = presentation self.presentation = presentation
self.itemsOnUndoStack -= 1 self.itemsOnUndoStack -= 1
assert self.itemsOnUndoStack >= 0 assert self.itemsOnUndoStack >= 0
@ -175,8 +188,14 @@ object if references are lehd by the object on the undo stack.
if presentation in self.presentation: if presentation in self.presentation:
del self.presentation[presentation] del self.presentation[presentation]
self.itemsOnUndoStack += 1 self.itemsOnUndoStack += 1
# Remove yourself from the 'elements' hash
if len (self.presentation) == 0:
if lookup (self.id):
del elements[self.id]
def remove_undoability (self): def remove_undoability (self):
if not self.__dict__.has_key ('itemsOnUndoStack'):
return
self.itemsOnUndoStack -= 1 self.itemsOnUndoStack -= 1
assert self.itemsOnUndoStack >= 0 assert self.itemsOnUndoStack >= 0
if len (self.presentation) == 0 and self.itemsOnUndoStack == 0: if len (self.presentation) == 0 and self.itemsOnUndoStack == 0:
@ -184,7 +203,7 @@ object if references are lehd by the object on the undo stack.
self.unlink() self.unlink()
def __get_attr_info(self, key, klass): def __get_attr_info(self, key, klass):
'''Find the record for 'key' in the <class>._attrdef map.''' '''Find the record for 'key' in the <klass>._attrdef map.'''
done = [ ] done = [ ]
def real_get_attr_info(key, klass): def real_get_attr_info(key, klass):
if klass in done: if klass in done:
@ -211,21 +230,23 @@ object if references are lehd by the object on the undo stack.
self.__dict__[key] = Sequence(self, type) self.__dict__[key] = Sequence(self, type)
return self.__dict__[key] return self.__dict__[key]
def __del_seq_item(self, seq, val): #def __del_seq_item(self, seq, val):
try: #try:
index = seq.list.index(val) #index = seq.list.index(val)
del seq.list[index] #del seq.list[index]
except ValueError: # seq.list.remove (val)
pass #except ValueError:
# pass
def __getattr__(self, key): def __getattr__(self, key):
#print 'Element.__getattr__(' + key + ')'
if key == 'id': if key == 'id':
return self.__dict__['__id'] return self.__dict__['__id']
elif self.__dict__.has_key(key): elif self.__dict__.has_key(key):
# Key is already in the object # Key is already in the object
return self.__dict__[key] return self.__dict__[key]
else: else:
#if key[0] != '_':
#print 'Unknown attr: Element.__getattr__(' + key + ')'
rec = self.__get_attr_info (key, self.__class__) rec = self.__get_attr_info (key, self.__class__)
if rec[0] is Sequence: if rec[0] is Sequence:
# We do not have a sequence here... create it and return it. # We do not have a sequence here... create it and return it.
@ -264,13 +285,16 @@ object if references are lehd by the object on the undo stack.
if rec[0] is not Sequence or xrec[0] is not Sequence: if rec[0] is not Sequence or xrec[0] is not Sequence:
if rec[0] is Sequence: if rec[0] is Sequence:
#print 'del-seq-item rec' #print 'del-seq-item rec'
self.__del_seq_item(self.__dict__[key], xself) #self.__del_seq_item(self.__dict__[key], xself)
if xself in self.__dict__[key].list:
self.__dict__[key].list.remove(xself)
elif self.__dict__.has_key(key): elif self.__dict__.has_key(key):
#print 'del-item rec' #print 'del-item rec'
del self.__dict__[key] del self.__dict__[key]
if xrec[0] is Sequence: if xrec[0] is Sequence:
#print 'del-seq-item xrec' #print 'del-seq-item xrec'
xself.__del_seq_item(xself.__dict__[rec[2]], self) #xself.__del_seq_item(xself.__dict__[rec[2]], self)
xself.__dict__[rec[2]].list.remove (self)
elif xself.__dict__.has_key(rec[2]): elif xself.__dict__.has_key(rec[2]):
#print 'del-item xrec' #print 'del-item xrec'
del xself.__dict__[rec[2]] del xself.__dict__[rec[2]]
@ -297,15 +321,18 @@ object if references are lehd by the object on the undo stack.
if not self.__dict__.has_key(key): if not self.__dict__.has_key(key):
return return
xval = self.__dict__[key] xval = self.__dict__[key]
del self.__dict__[key]
if len(rec) > 2: # Bi-directional relationship if len(rec) > 2: # Bi-directional relationship
xrec = xval.__get_attr_info (rec[2], rec[1]) xrec = xval.__get_attr_info (rec[2], rec[1])
if xrec[0] is Sequence: if xrec[0] is Sequence:
xval.__del_seq_item(xval.__dict__[rec[2]], self) #xval.__del_seq_item(xval.__dict__[rec[2]], self)
#xval.__dict__[rec[2]].list.remove (self)
# Handle it via sequence_remove()
del xval.__dict__[rec[2]][self]
else: else:
del xval.__dict__[rec[2]] del xval.__dict__[rec[2]]
xval.emit(rec[2]) del self.__dict__[key]
self.emit (key) self.emit (key)
xval.emit(rec[2])
def sequence_remove(self, seq, obj): def sequence_remove(self, seq, obj):
'''Remove an entry. Should only be called by Sequence's implementation. '''Remove an entry. Should only be called by Sequence's implementation.
@ -315,20 +342,24 @@ object if references are lehd by the object on the undo stack.
if self.__dict__[key] is seq: if self.__dict__[key] is seq:
break break
#print 'Element.sequence_remove', key #print 'Element.sequence_remove', key
seq_len = len (seq)
rec = self.__get_attr_info (key, self.__class__) rec = self.__get_attr_info (key, self.__class__)
if rec[0] is not Sequence: if rec[0] is not Sequence:
raise AttributeError, 'Element: This should be called from Sequence' raise AttributeError, 'Element: This should be called from Sequence'
seq.list.remove(obj) seq.list.remove(obj)
if len(rec) > 2: # Bi-directional relationship if len(rec) > 2: # Bi-directional relationship
xrec = obj.__get_attr_info (rec[2], rec[1]) xrec = obj.__get_attr_info (rec[2], obj.__class__) #rec[1])
if xrec[0] is Sequence: if xrec[0] is Sequence:
obj.__del_seq_item(obj.__dict__[rec[2]], self) #obj.__del_seq_item(obj.__dict__[rec[2]], self)
#print 'sequence_remove: Sequence'
obj.__dict__[rec[2]].list.remove (self)
else: else:
try: #try:
del obj.__dict__[rec[2]] #print 'sequence_remove: item'
except Exception, e: del obj.__dict__[rec[2]]
print 'ERROR: (Element.sequence_remove)', e #except Exception, e:
# print 'ERROR: (Element.sequence_remove)', e
assert len (seq) == seq_len - 1
# Functions used by the signal functions # Functions used by the signal functions
def connect (self, signal_func, *data): def connect (self, signal_func, *data):
self.__dict__['__signals'].append ((signal_func,) + data) self.__dict__['__signals'].append ((signal_func,) + data)
@ -338,24 +369,81 @@ object if references are lehd by the object on the undo stack.
self.__dict__['__signals']) self.__dict__['__signals'])
def emit (self, key): def emit (self, key):
if not self.__dict__.has_key ('__signals'): print 'emit', self, key
print 'No __signals attribute in object', self #if not self.__dict__.has_key ('__signals'):
return # print 'No __signals attribute in object', self
# return
for signal in self.__dict__['__signals']: for signal in self.__dict__['__signals']:
signal_func = signal[0] signal_func = signal[0]
data = signal[1:] data = signal[1:]
#print 'signal:', signal_func, 'data:', data
signal_func (key, *data) signal_func (key, *data)
#def update_model(): def save(self, document, parent):
# '''Do a garbage collection on the hash table, also removing def save_children (obj):
# weak references that do not point to valid objects.''' if isinstance (obj, Element):
# gc.collect() #subnode = document.createElement (key)
# for k in Element._hash.keys(): subnode = document.createElement ('Reference')
# if Element._hash[k]() is None: node.appendChild (subnode)
# del Element._hash[k] subnode.setAttribute ('name', key)
subnode.setAttribute ('refid', str(obj.__dict__['__id']))
elif isinstance (obj, types.IntType) or \
isinstance (obj, types.LongType) or \
isinstance (obj, types.FloatType):
subnode = document.createElement ('Value')
node.appendChild (subnode)
subnode.setAttribute ('name', key)
text = document.createTextNode (str(obj))
subnode.appendChild (text)
elif isinstance (obj, types.StringType):
subnode = document.createElement ('Value')
node.appendChild (subnode)
subnode.setAttribute ('name', key)
cdata = document.createCDATASection (str(obj))
subnode.appendChild (cdata)
#Element_hash_gc = update_model node = document.createElement (self.__class__.__name__)
parent.appendChild (node)
node.setAttribute ('id', str (self.__dict__['__id']))
for key in self.__dict__.keys():
if key not in ( 'presentation', 'itemsOnUndoStack', \
'__signals', '__id' ):
obj = self.__dict__[key]
if isinstance (obj, Sequence):
for item in obj.list:
save_children (item)
else:
save_children (obj)
return node
def load(self, node):
for child in node.childNodes:
if child.tagName == 'Reference':
name = child.getAttribute ('name')
refid = int (child.getAttribute ('refid'))
refelement = lookup (refid)
attr_info = self.__get_attr_info (name, self.__class__)
if not isinstance (refelement, attr_info[1]):
raise ValueError, 'Referenced item is of the wrong type'
if attr_info[0] is Sequence:
self.__ensure_seq (name, attr_info[1]).list.append (refelement)
else:
self.__dict__[name] = refelement
elif child.tagName == 'Value':
name = child.getAttribute ('name')
subchild = child.firstChild
attr_info = self.__get_attr_info (name, self.__class__)
if issubclass (attr_info[1], types.IntType) or \
issubclass (attr_info[1], types.LongType):
self.__dict__[name] = int (subchild.data)
elif issubclass (attr_info[1], types.FloatType):
self.__dict__[name] = float (subchild.data)
else:
self.__dict__[name] = subchild.data
###################################
# Testing
if __name__ == '__main__': if __name__ == '__main__':
print '\n============== Starting Element tests... ============\n' print '\n============== Starting Element tests... ============\n'
@ -389,7 +477,7 @@ if __name__ == '__main__':
a.unlink() a.unlink()
del a del a
assert len (Element._hash) == 0 assert len (elements) == 0
print '\tOK ===' print '\tOK ==='
@ -421,7 +509,7 @@ if __name__ == '__main__':
a.unlink() a.unlink()
assert len (Element._hash) == 0 assert len (elements) == 0
print '\tOK ===' print '\tOK ==='
@ -468,7 +556,7 @@ if __name__ == '__main__':
a.unlink() a.unlink()
b.unlink() b.unlink()
assert len (Element._hash) == 0 assert len (elements) == 0
print '\tOK ===' print '\tOK ==='
@ -496,6 +584,18 @@ if __name__ == '__main__':
assert a.ref is a assert a.ref is a
assert a.seq.list == [ a ] assert a.seq.list == [ a ]
b = A()
a.seq = b
assert b.ref is a
assert a.seq.list == [ a, b ]
del a.seq[a]
assert a.ref is None
assert b.ref is a
assert a.seq.list == [ b ]
b.unlink()
a.unlink() a.unlink()
a = A() a = A()
b = A() b = A()
@ -539,8 +639,8 @@ if __name__ == '__main__':
a.unlink() a.unlink()
b.unlink() b.unlink()
#print Element._hash #print elements
assert len (Element._hash) == 0 assert len (elements) == 0
print '\tOK ===' print '\tOK ==='
@ -603,7 +703,7 @@ if __name__ == '__main__':
a.unlink() a.unlink()
b.unlink() b.unlink()
assert len (Element._hash) == 0 assert len (elements) == 0
print '\tOK ===' print '\tOK ==='
@ -660,7 +760,7 @@ if __name__ == '__main__':
b.unlink() b.unlink()
del b del b
assert len (Element._hash) == 0 assert len (elements) == 0
print '\tOK ===' print '\tOK ==='
@ -674,14 +774,14 @@ if __name__ == '__main__':
a = A() a = A()
b = A() b = A()
assert len (Element._hash) == 2 assert len (elements) == 2
a.rel = b a.rel = b
a.unlink() a.unlink()
b.unlink() b.unlink()
assert len (Element._hash) == 0 assert len (elements) == 0
print '\tOK ===' print '\tOK ==='

View File

@ -9,4 +9,4 @@ ModelElements.py: $(GEN_UML) $(METAMODEL_XMI)
grep -v "PresentationElement" genModelElements.py > ModelElements.py grep -v "PresentationElement" genModelElements.py > ModelElements.py
rm -f genModelElements.py rm -f genModelElements.py
EXTRA_DIST=Element.py ModelElements.py __init__.py EXTRA_DIST=Element.py ModelElements.py management.py __init__.py

View File

@ -3,6 +3,7 @@
# #
from Element import * from Element import *
from ModelElements import * from ModelElements import *
from management import *
Attribute._attrdef['rawAttribute'] = ( '', String ) Attribute._attrdef['rawAttribute'] = ( '', String )
Operation._attrdef['rawOperation'] = ( '', String ) Operation._attrdef['rawOperation'] = ( '', String )

128
gaphor/UML/management.py Normal file
View File

@ -0,0 +1,128 @@
# vim: sw=4
import UML, diagram
from xmllib import XMLParser
from xml.dom.minidom import Document
# Somehow I did not manage it to use the minidom/SAX stuff to create a
# decent parser, do I use this depricated (but workin ;) peace of code...
# The GaphorParser reads a Gaphor file and creates a DOM representation of
# the file.
class GaphorParser (XMLParser):
'''GaphorParser
The GaphorParser examines an inut strream and creates a Document object
using the elements found in the XML file. The only restruction that we
test is the Gaphor tag and the version (currently only 1.0)'''
def __init__ (self, **kw):
self.doit = 0
self.doc = Document()
self.elements = { 'Gaphor': (self.start_Gaphor, self.end_Gaphor) }
self.__stack = [ ]
apply(XMLParser.__init__, (self,), kw)
def syntax_error(self, message):
raise IOError, "XML document contains syntax errors: " + message
def start_Gaphor (self, attrs):
if attrs['version'] != '1.0':
raise Exception, 'Wrong version of Gaphor (' + \
attrs['version'] + ')'
else:
node = self.doc.createElement('Gaphor')
self.doc.appendChild (node)
self.__stack.append (node)
self.doit += 1
def end_Gaphor (self):
self.doit -= 1
def unknown_starttag(self, tag, attrs):
if self.doit:
node = self.doc.createElement(tag)
self.__stack[-1].appendChild (node)
self.__stack.append (node)
for key in attrs.keys():
node.setAttribute (key, attrs[key])
def unknown_endtag(self, tag):
self.__stack = self.__stack[:-1]
def handle_cdata(self, tag):
cdata = self.doc.createCDATASection (tag)
self.__stack[-1].appendChild (cdata)
def unknown_entityref(self, ref):
raise ValueError, tag + " not supported."
def unknown_charref(self, ref):
raise ValueError, tag + " not supported."
def save (filename=None):
document = Document()
rootnode = document.createElement ('Gaphor')
document.appendChild (rootnode)
rootnode.setAttribute ('version', '1.0')
for e in UML.elements.values():
print 'Saving object', e
e.save(document, rootnode)
if not filename:
print document.toxml(indent=' ', newl='\n')
else:
file = open (filename, 'w')
if not file:
raise IOError, 'Could not open file `%s\'' % (filename)
document.writexml (file, indent='', addindent=' ', newl='\n')
file.close()
def load (filename):
'''Load a file and create a model if possible.
Exceptions: IOError, ValueError.'''
parser = GaphorParser()
f = open (filename, 'r')
while 1:
data = f.read(512)
parser.feed (data)
if len(data) != 512:
break;
parser.close()
f.close()
# Now iterate over the tree and create every element in the UML.elements
# table.
rootnode = parser.doc.firstChild
for node in rootnode.childNodes:
try:
if node.tagName == 'Diagram':
cls = getattr (diagram, node.tagName)
else:
cls = getattr (UML, node.tagName)
except:
raise ValueError, 'Invalid field in Gaphor file: ' + node.tagName
id = int (node.getAttribute('id'))
old_index = UML.Element._index
UML.Element._index = id
cls()
if old_index > id:
UML.Element._index = old_index
#print node.tagName, node.getAttribute('id')
# Second step: call Element.load() for every object in the element hash.
# We also provide the XML node, so it can recreate it's state
for node in rootnode.childNodes:
id = int (node.getAttribute('id'))
element = UML.lookup (id)
assert element != None
element.load (node)
def flush():
'''Flush all elements in the UML.elements'''
while 1:
try:
(key, value) = UML.elements.popitem()
except KeyError:
break;
value.unlink()
UML.elements.clear()

View File

@ -10,9 +10,12 @@ import diacanvas
import UML import UML
import tree import tree
uc = getattr (UML, 'UseCase')
print 'getattr (UML, "UseCase") ->', uc
def mainquit(*args): def mainquit(*args):
for k in UML.Element._hash.keys(): for k in UML.elements.keys():
print "Element", k, ":", UML.Element._hash[k].__dict__ print "Element", k, ":", UML.elements[k].__dict__
print "Forcing Garbage collection:" print "Forcing Garbage collection:"
gtk.main_quit() gtk.main_quit()
@ -30,21 +33,21 @@ treemodel = tree.NamespaceModel(model)
#item.move (30, 50) #item.move (30, 50)
#item = canvas.root.add (diagram.Actor) #item = canvas.root.add (diagram.Actor)
#item.move (150, 50) #item.move (150, 50)
item = dia.create_item (diagram.UseCase, (50, 150))
usecase = item.get_subject()
#dia.create_item (diagram.UseCase, (50, 200), subject=usecase)
item = dia.create_item (diagram.Actor, (150, 50)) item = dia.create_item (diagram.Actor, (150, 50))
actor = item.get_subject() actor = item.get_subject()
actor.name = "Actor" actor.name = "Actor"
item = dia.create_item (diagram.UseCase, (50, 150))
usecase = item.get_subject()
dia.create_item (diagram.UseCase, (50, 200), subject=usecase)
item = dia.create_item (diagram.Comment, (10,10)) item = dia.create_item (diagram.Comment, (10,10))
comment = item.get_subject() comment = item.get_subject()
del item del item#, actor, usecase, comment
#print "Comment.presentation:", comment.presentation.list print "Comment.presentation:", comment.presentation.list
#print "Actor.presentation:", actor.presentation.list print "Actor.presentation:", actor.presentation.list
print "UseCase.presentation:", usecase.presentation.list print "UseCase.presentation:", usecase.presentation.list
#view = diacanvas.CanvasView().set_canvas (dia.canvas) #view = diacanvas.CanvasView().set_canvas (dia.canvas)
#display_diagram (dia) #display_diagram (dia)
@ -61,16 +64,15 @@ treemodel.dump()
print 'Going into main' print 'Going into main'
gtk.main() gtk.main()
UML.save('x.xml')
del win del win
treemodel.dump() treemodel.dump()
#print "Comment.ann.Elem.:", comment.annotatedElement.list #print "Comment.presentation:", comment.presentation.list
#print "Actor.comment:", actor.comment.list #print "Actor.presentation:", actor.presentation.list
#print "UseCase.comment:", usecase.comment.list #print "UseCase.presentation:", usecase.presentation.list
print "Comment.presentation:", comment.presentation.list
print "Actor.presentation:", actor.presentation.list
print "UseCase.presentation:", usecase.presentation.list
print "removing diagram..." print "removing diagram..."
dia.unlink() dia.unlink()
del dia del dia
@ -78,17 +80,15 @@ del dia
print "Comment.presentation:", comment.presentation.list print "Comment.presentation:", comment.presentation.list
print "Actor.presentation:", actor.presentation.list print "Actor.presentation:", actor.presentation.list
print "UseCase.presentation:", usecase.presentation.list print "UseCase.presentation:", usecase.presentation.list
actor.unlink()
del actor del actor
usecase.unlink()
del usecase del usecase
comment.unlink()
del comment del comment
#del dia
print "Garbage collection after gtk.main() has finished:" UML.flush()
print "Garbage collection after gtk.main() has finished (should be empty):",
#UML.update_model() #UML.update_model()
for k in UML.Element._hash.keys(): for k in UML.elements.keys():
print "Element", k, ":", UML.Element._hash[k].__dict__ print "Element", k, ":", UML.elements[k].__dict__
print "Program ended normally..." print "Program ended normally..."

63
tests/diagram-destroy.py Normal file
View File

@ -0,0 +1,63 @@
#
# Test the behavior of a UML tree with a Diagram as leaf. The whole tree
# should be freed...
#
import UML
import diagram as dia
import gc
model = UML.Model()
model.name = "MyModel"
package = UML.Package()
package.name = "Package"
model.ownedElement = package
assert len(model.ownedElement.list) == 1
assert model.ownedElement.list[0] is package
assert package.namespace is model
actor = UML.Actor()
actor.namespace = package
assert len(package.ownedElement.list) == 1
assert package.ownedElement.list[0] is actor
assert actor.namespace is package
usecase = UML.UseCase()
usecase.namespace = package
assert len(package.ownedElement.list) == 2
assert package.ownedElement.list[0] is actor
assert package.ownedElement.list[1] is usecase
assert usecase.namespace is package
diagram = dia.Diagram()
diagram.namespace = package
assert len(package.ownedElement.list) == 3
assert package.ownedElement.list[0] is actor
assert package.ownedElement.list[1] is usecase
assert package.ownedElement.list[2] is diagram
assert diagram.namespace is package
diagram.create_item (dia.Actor, pos=(0, 0), subject=actor)
diagram.create_item (dia.UseCase, pos=(100, 100), subject=usecase)
#dia.destroy_diagrams()
model.unlink()
del model
usecase.unlink()
del usecase
actor.unlink()
del actor
package.unlink()
del package
diagram.unlink()
del diagram
gc.collect()
gc.set_debug (gc.DEBUG_LEAK)
print "Uncollectable objects found:", gc.garbage

31
tests/test-treemodel.py Normal file
View File

@ -0,0 +1,31 @@
import UML, gtk
from tree.namespace import *
import CreateModel
window = gtk.Window()
window.connect('destroy', lambda win: gtk.main_quit())
window.set_title('TreeView test')
window.set_default_size(250, 400)
scrolled_window = gtk.ScrolledWindow()
scrolled_window.set_policy(gtk.POLICY_AUTOMATIC, gtk.POLICY_AUTOMATIC)
window.add(scrolled_window)
tree_model = NamespaceModel(CreateModel.model)
tree_view = gtk.TreeView(tree_model)
cell = gtk.CellRendererText()
# the text in the column comes from column 0
column = gtk.TreeViewColumn('', cell, text=0)
tree_view.append_column(column)
scrolled_window.add(tree_view)
window.show_all()
tree_model.dump()
gtk.main()
tree_model.dump()

8
tests/test-xml.py Normal file
View File

@ -0,0 +1,8 @@
#
# A simple parser
#
import UML
UML.load ('../gaphor/x.xml')
UML.save ('aa.xml')