remove rtags/methods to handle the action box from Entity, move it to the action box... tls-sprint
authorsylvain.thenault@logilab.fr
Thu, 26 Mar 2009 19:15:57 +0100
branchtls-sprint
changeset 1150 2d1b721fded9
parent 1149 1e19b6ef53a1
child 1151 b20677336ee6
remove rtags/methods to handle the action box from Entity, move it to the action box...
devtools/devctl.py
entities/__init__.py
web/views/boxes.py
--- a/devtools/devctl.py	Thu Mar 26 19:00:20 2009 +0100
+++ b/devtools/devctl.py	Thu Mar 26 19:15:57 2009 +0100
@@ -143,10 +143,10 @@
             add_msg(w, rschema.description)
     w('# add related box generated message\n')
     w('\n')
+    actionbox = self.vreg['actions']['edit_box'][0]
     for eschema in schema.entities():
         if eschema.is_final():
             continue
-        entity = vreg.etype_class(eschema)(None, None)
         for x, rschemas in (('subject', eschema.subject_relations()),
                             ('object', eschema.object_relations())):
             for rschema in rschemas:
@@ -155,7 +155,7 @@
                 for teschema in rschema.targets(eschema, x):
                     if defined_in_library(libschema, eschema, rschema, teschema, x):
                         continue
-                    if entity.relation_mode(rschema.type, teschema.type, x) == 'create':
+                    if actionbox.relation_mode(rschema.type, teschema.type, x) == 'create':
                         if x == 'subject':
                             label = 'add %s %s %s %s' % (eschema, rschema, teschema, x)
                             label2 = "creating %s (%s %%(linkto)s %s %s)" % (teschema, eschema, rschema, teschema)
--- a/entities/__init__.py	Thu Mar 26 19:00:20 2009 +0100
+++ b/entities/__init__.py	Thu Mar 26 19:15:57 2009 +0100
@@ -201,39 +201,6 @@
             return self.printable_value(rtype, format='text/plain').lower()
         return value
 
-    def add_related_schemas(self):
-        """this is actually used ui method to generate 'addrelated' actions from
-        the schema.
-
-        If you're using explicit 'addrelated' actions for an entity types, you
-        should probably overrides this method to return an empty list else you
-        may get some unexpected actions.
-        """
-        req = self.req
-        eschema = self.e_schema
-        for role, rschemas in (('subject', eschema.subject_relations()),
-                               ('object', eschema.object_relations())):
-            for rschema in rschemas:
-                if rschema.is_final():
-                    continue
-                # check the relation can be added as well
-                if role == 'subject'and not rschema.has_perm(req, 'add', fromeid=self.eid):
-                    continue
-                if role == 'object'and not rschema.has_perm(req, 'add', toeid=self.eid):
-                    continue
-                # check the target types can be added as well
-                for teschema in rschema.targets(eschema, role):
-                    if not self.relation_mode(rschema, teschema, role) == 'create':
-                        continue
-                    if teschema.has_local_role('add') or teschema.has_perm(req, 'add'):
-                        yield rschema, teschema, role
-
-    def relation_mode(self, rtype, targettype, role='subject'):
-        """return a string telling if the given relation is usually created
-        to a new entity ('create' mode) or to an existant entity ('link' mode)
-        """
-        return self.rtags.get_mode(rtype, targettype, role)
-
     # edition helper functions ################################################    
 
     def linked_to(self, rtype, target, remove=True):
--- a/web/views/boxes.py	Thu Mar 26 19:00:20 2009 +0100
+++ b/web/views/boxes.py	Thu Mar 26 19:15:57 2009 +0100
@@ -16,6 +16,7 @@
 
 from logilab.mtconverter import html_escape
 
+from cubicweb.rtags import RelationTags
 from cubicweb.selectors import match_user_groups, non_final_entity
 from cubicweb.web.htmlwidgets import BoxWidget, BoxMenu, BoxHtml, RawBoxItem
 from cubicweb.view import EntityView
@@ -29,10 +30,55 @@
     box with all actions impacting the entity displayed: edit, copy, delete
     change state, add related entities
     """
+    id = 'edit_box'
     __select__ = BoxTemplate.__select__ & non_final_entity()
-    id = 'edit_box'
+
     title = _('actions')
     order = 2
+    # 'link' / 'create' relation tags, used to control the "add entity" submenu
+    rmode = RelationTags() 
+
+    @classmethod
+    def registered(cls, registry):
+        """build class using descriptor at registration time"""
+        super(AutomaticEntityForm, cls).registered(registry)
+        cls.init_rtags_mode()
+        return cls
+        
+    @classmethod
+    def init_rtags_mode(cls):
+        """set default category tags for relations where it's not yet defined in
+        the category relation tags
+        """
+        for eschema in cls.schema.entities():
+            for rschema, tschemas, role in eschema.relation_definitions(True):
+                for tschema in tschemas:
+                    if role == 'subject':
+                        X, Y = eschema, tschema
+                        card = rschema.rproperty(X, Y, 'cardinality')[0]
+                    else:
+                        X, Y = tschema, eschema
+                        card = rschema.rproperty(X, Y, 'cardinality')[1]
+                    if not cls.rmode.rtag(role, rschema, X, Y):
+                        if card in '?1':
+                            # by default, suppose link mode if cardinality doesn't allow
+                            # more than one relation
+                            mode = 'link'
+                        elif rschema.rproperty(X, Y, 'composite') == role:
+                            # if self is composed of the target type, create mode
+                            mode = 'create'
+                        else:
+                            # link mode by default
+                            mode = 'link'
+                        cls.rmode.set_rtag(category, role, rschema, X, Y)
+
+    @classmethod
+    def relation_mode(cls, rtype, etype, targettype, role='subject'):
+        """return a string telling if the given relation is usually created
+        to a new entity ('create' mode) or to an existant entity ('link' mode)
+        """
+        return cls.rmode.rtag(role, rtype, etype, targettype)
+
 
     def call(self, **kwargs):
         _ = self.req._
@@ -92,7 +138,7 @@
         actions = []
         _ = self.req._
         eschema = entity.e_schema
-        for rschema, teschema, x in entity.add_related_schemas():
+        for rschema, teschema, x in self.add_related_schemas(entity):
             if x == 'subject':
                 label = 'add %s %s %s %s' % (eschema, rschema, teschema, x)
                 url = self.linkto_url(entity, rschema, teschema, 'object')
@@ -102,6 +148,33 @@
             actions.append(self.mk_action(_(label), url))
         return actions
 
+    def add_related_schemas(self, entity):
+        """this is actually used ui method to generate 'addrelated' actions from
+        the schema.
+
+        If you're using explicit 'addrelated' actions for an entity types, you
+        should probably overrides this method to return an empty list else you
+        may get some unexpected actions.
+        """
+        req = self.req
+        eschema = entity.e_schema
+        for role, rschemas in (('subject', eschema.subject_relations()),
+                               ('object', eschema.object_relations())):
+            for rschema in rschemas:
+                if rschema.is_final():
+                    continue
+                # check the relation can be added as well
+                if role == 'subject'and not rschema.has_perm(req, 'add', fromeid=entity.eid):
+                    continue
+                if role == 'object'and not rschema.has_perm(req, 'add', toeid=entity.eid):
+                    continue
+                # check the target types can be added as well
+                for teschema in rschema.targets(eschema, role):
+                    if not self.relation_mode(rschema, eschema, teschema, role) == 'create':
+                        continue
+                    if teschema.has_local_role('add') or teschema.has_perm(req, 'add'):
+                        yield rschema, teschema, role
+
 
     def workflow_actions(self, entity, box):
         if 'in_state' in entity.e_schema.subject_relations() and entity.in_state: