web/views/dynimages.py
changeset 1808 aa09e20dd8c0
parent 1693 49075f57cf2c
parent 1807 6d541c610165
child 1810 e95e876be17c
--- a/web/views/dynimages.py	Tue May 05 17:18:49 2009 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,198 +0,0 @@
-"""dynamically generated image views
-
-:organization: Logilab
-:copyright: 2001-2008 LOGILAB S.A. (Paris, FRANCE), all rights reserved.
-:contact: http://www.logilab.fr/ -- mailto:contact@logilab.fr
-"""
-__docformat__ = "restructuredtext en"
-
-import os
-from tempfile import mktemp
-from itertools import cycle
-
-from logilab.common.graph import escape, GraphGenerator, DotBackend
-from yams import schema2dot as s2d
-
-from cubicweb.common.view import EntityView, StartupView
-
-
-class RestrictedSchemaDotPropsHandler(s2d.SchemaDotPropsHandler):
-    def __init__(self, req):
-        # FIXME: colors are arbitrary
-        self.nextcolor = cycle( ('#aa0000', '#00aa00', '#0000aa',
-                                 '#000000', '#888888') ).next
-        self.req = req
-        
-    def display_attr(self, rschema):
-        return not rschema.meta and (rschema.has_local_role('read')
-                                     or rschema.has_perm(self.req, 'read'))
-    
-    # XXX remove this method once yams > 0.20 is out
-    def node_properties(self, eschema):
-        """return default DOT drawing options for an entity schema"""
-        label = ['{',eschema.type,'|']
-        label.append(r'\l'.join(rel.type for rel in eschema.subject_relations()
-                                if rel.final and self.display_attr(rel)))
-        label.append(r'\l}') # trailing \l ensure alignement of the last one
-        return {'label' : ''.join(label), 'shape' : "record",
-                'fontname' : "Courier", 'style' : "filled"}
-
-    def edge_properties(self, rschema, subjnode, objnode):
-        kwargs = super(RestrictedSchemaDotPropsHandler, self).edge_properties(rschema, subjnode, objnode)
-        # symetric rels are handled differently, let yams decide what's best
-        if not rschema.symetric:
-            kwargs['color'] = self.nextcolor()
-        kwargs['fontcolor'] = kwargs['color']
-        # dot label decoration is just awful (1 line underlining the label
-        # + 1 line going to the closest edge spline point)
-        kwargs['decorate'] = 'false'
-        return kwargs
-    
-
-class RestrictedSchemaVisitorMiIn:
-    def __init__(self, req, *args, **kwargs):
-        # hack hack hack
-        assert len(self.__class__.__bases__) == 2
-        self.__parent = self.__class__.__bases__[1]
-        self.__parent.__init__(self, *args, **kwargs)
-        self.req = req
-        
-    def nodes(self):
-        for etype, eschema in self.__parent.nodes(self):
-            if eschema.has_local_role('read') or eschema.has_perm(self.req, 'read'):
-                yield eschema.type, eschema
-            
-    def edges(self):
-        for setype, oetype, rschema in self.__parent.edges(self):
-            if rschema.has_local_role('read') or rschema.has_perm(self.req, 'read'):
-                yield setype, oetype, rschema
-
-class FullSchemaVisitor(RestrictedSchemaVisitorMiIn, s2d.FullSchemaVisitor):
-    pass
-
-class OneHopESchemaVisitor(RestrictedSchemaVisitorMiIn, s2d.OneHopESchemaVisitor):
-    pass
-
-class OneHopRSchemaVisitor(RestrictedSchemaVisitorMiIn, s2d.OneHopRSchemaVisitor):
-    pass
-                
-        
-class TmpFileViewMixin(object):
-    binary = True
-    content_type = 'application/octet-stream'
-    cache_max_age = 60*60*2 # stay in http cache for 2 hours by default 
-    
-    def call(self):
-        self.cell_call()
-        
-    def cell_call(self, row=0, col=0):
-        self.row, self.col = row, col # in case one need it
-        tmpfile = mktemp('.png')
-        try:
-            self._generate(tmpfile)
-            self.w(open(tmpfile).read())
-        finally:
-            os.unlink(tmpfile)
-    
-class SchemaImageView(TmpFileViewMixin, StartupView):
-    id = 'schemagraph'
-    content_type = 'image/png'
-    skip_rels = ('owned_by', 'created_by', 'identity', 'is', 'is_instance_of')
-    def _generate(self, tmpfile):
-        """display global schema information"""
-        skipmeta = not int(self.req.form.get('withmeta', 0))
-        visitor = FullSchemaVisitor(self.req, self.schema, skiprels=self.skip_rels, skipmeta=skipmeta)
-        s2d.schema2dot(outputfile=tmpfile, visitor=visitor,
-                       prophdlr=RestrictedSchemaDotPropsHandler(self.req))
-
-class EETypeSchemaImageView(TmpFileViewMixin, EntityView):
-    id = 'eschemagraph'
-    content_type = 'image/png'
-    accepts = ('EEType',)
-    skip_rels = ('owned_by', 'created_by', 'identity', 'is', 'is_instance_of')
-    
-    def _generate(self, tmpfile):
-        """display schema information for an entity"""
-        entity = self.entity(self.row, self.col)
-        eschema = self.vreg.schema.eschema(entity.name)
-        visitor = OneHopESchemaVisitor(self.req, eschema, skiprels=self.skip_rels)
-        s2d.schema2dot(outputfile=tmpfile, visitor=visitor,
-                       prophdlr=RestrictedSchemaDotPropsHandler(self.req))
-
-class ERTypeSchemaImageView(EETypeSchemaImageView):
-    accepts = ('ERType',)
-    
-    def _generate(self, tmpfile):
-        """display schema information for an entity"""
-        entity = self.entity(self.row, self.col)
-        rschema = self.vreg.schema.rschema(entity.name)
-        visitor = OneHopRSchemaVisitor(self.req, rschema)
-        s2d.schema2dot(outputfile=tmpfile, visitor=visitor,
-                       prophdlr=RestrictedSchemaDotPropsHandler(self.req))
-
-
-
-class WorkflowDotPropsHandler(object):
-    def __init__(self, req):
-        self._ = req._
-        
-    def node_properties(self, stateortransition):
-        """return default DOT drawing options for a state or transition"""
-        props = {'label': stateortransition.name, 
-                 'fontname': 'Courier'}
-        if hasattr(stateortransition, 'state_of'):
-            props['shape'] = 'box'
-            props['style'] = 'filled'
-            if stateortransition.reverse_initial_state:
-                props['color'] = '#88CC88'
-        else:
-            props['shape'] = 'ellipse'
-            descr = []
-            tr = stateortransition
-            if tr.require_group:
-                descr.append('%s %s'% (
-                    self._('groups:'),
-                    ','.join(g.name for g in tr.require_group)))
-            if tr.condition:
-                descr.append('%s %s'% (self._('condition:'), tr.condition))
-            if descr:
-                props['label'] += escape('\n'.join(descr))
-        return props
-    
-    def edge_properties(self, transition, fromstate, tostate):
-        return {'label': '', 'dir': 'forward',
-                'color': 'black', 'style': 'filled'}
-
-class WorkflowVisitor:
-    def __init__(self, entity):
-        self.entity = entity
-
-    def nodes(self):
-        for state in self.entity.reverse_state_of:
-            state.complete()
-            yield state.eid, state
-            
-        for transition in self.entity.reverse_transition_of:
-            transition.complete()
-            yield transition.eid, transition
-            
-    def edges(self):
-        for transition in self.entity.reverse_transition_of:
-            for incomingstate in transition.reverse_allowed_transition:
-                yield incomingstate.eid, transition.eid, transition
-            yield transition.eid, transition.destination().eid, transition
-
-
-class EETypeWorkflowImageView(TmpFileViewMixin, EntityView):
-    id = 'ewfgraph'
-    content_type = 'image/png'
-    accepts = ('EEType',)
-    
-    def _generate(self, tmpfile):
-        """display schema information for an entity"""
-        entity = self.entity(self.row, self.col)
-        visitor = WorkflowVisitor(entity)
-        prophdlr = WorkflowDotPropsHandler(self.req)
-        generator = GraphGenerator(DotBackend('workflow', 'LR',
-                                              ratio='compress', size='30,12'))
-        return generator.generate(visitor, prophdlr, tmpfile)