web/views/autoform.py
changeset 4277 35cd057339b2
parent 4252 6c4f109c2b03
child 4295 b9590e68c543
--- a/web/views/autoform.py	Wed Jan 20 08:43:41 2010 +0100
+++ b/web/views/autoform.py	Wed Jan 20 10:06:12 2010 +0100
@@ -9,12 +9,12 @@
 __docformat__ = "restructuredtext en"
 _ = unicode
 
-from logilab.common.decorators import cached
+from logilab.common.decorators import cached, iclassmethod
 
 from cubicweb import typed_eid
 from cubicweb.web import stdmsgs, uicfg
 from cubicweb.web import form, formwidgets as fwdgs
-from cubicweb.web.views import forms, editforms
+from cubicweb.web.views import forms, editforms, editviews
 
 _afs = uicfg.autoform_section
 
@@ -44,6 +44,31 @@
     # which relations should be edited
     display_fields = None
 
+    def _generic_relations_field(self):
+        try:
+            srels_by_cat = self.srelations_by_category('generic', 'add', strict=True)
+            warn('[3.6] %s: srelations_by_category is deprecated, use uicfg or '
+                 'override editable_relations instead' % classid(form),
+                 DeprecationWarning)
+        except AttributeError:
+            srels_by_cat = self.editable_relations()
+        if not srels_by_cat:
+            raise form.FieldNotFound('_cw_generic_field')
+        return editviews.GenericRelationsField(self.editable_relations())
+
+    @iclassmethod
+    def field_by_name(cls_or_self, name, role=None, eschema=None):
+        """return field with the given name and role. If field is not explicitly
+        defined for the form but `eclass` is specified, guess_field will be
+        called.
+        """
+        try:
+            return super(AutomaticEntityForm, cls_or_self).field_by_name(name, role, eschema)
+        except form.FieldNotFound:
+            if name == '_cw_generic_field' and not isinstance(cls_or_self, type):
+                return cls_or_self._generic_relations_field()
+            raise
+
     # base automatic entity form methods #######################################
 
     def __init__(self, *args, **kwargs):
@@ -64,6 +89,12 @@
                 except form.FieldNotFound:
                     # meta attribute such as <attr>_format
                     continue
+        if self.formtype == 'main' and entity.has_eid():
+            try:
+                self.fields.append(self.field_by_name('_cw_generic_field'))
+            except form.FieldNotFound:
+                # no editable relation
+                pass
         self.maxrelitems = self._cw.property_value('navigation.related-limit')
         self.force_display = bool(self._cw.form.get('__force_display'))
         fnum = len(self.fields)
@@ -163,63 +194,6 @@
 
     # generic relations modifier ###############################################
 
-    def relations_table(self):
-        """yiels 3-tuples (rtype, target, related_list)
-        where <related_list> itself a list of :
-          - node_id (will be the entity element's DOM id)
-          - appropriate javascript's togglePendingDelete() function call
-          - status 'pendingdelete' or ''
-          - oneline view of related entity
-        """
-        entity = self.edited_entity
-        pending_deletes = self._cw.get_pending_deletes(entity.eid)
-        for label, rschema, role in self.editable_relations():
-            relatedrset = entity.related(rschema, role, limit=self.related_limit)
-            if rschema.has_perm(self._cw, 'delete'):
-                toggleable_rel_link_func = editforms.toggleable_relation_link
-            else:
-                toggleable_rel_link_func = lambda x, y, z: u''
-            related = []
-            for row in xrange(relatedrset.rowcount):
-                nodeid = editforms.relation_id(entity.eid, rschema, role,
-                                               relatedrset[row][0])
-                if nodeid in pending_deletes:
-                    status = u'pendingDelete'
-                    label = '+'
-                else:
-                    status = u''
-                    label = 'x'
-                dellink = toggleable_rel_link_func(entity.eid, nodeid, label)
-                eview = self._cw.view('oneline', relatedrset, row=row)
-                related.append((nodeid, dellink, status, eview))
-            yield (rschema, role, related)
-
-    def restore_pending_inserts(self, cell=False):
-        """used to restore edition page as it was before clicking on
-        'search for <some entity type>'
-        """
-        eid = self.edited_entity.eid
-        cell = cell and "div_insert_" or "tr"
-        pending_inserts = set(self._cw.get_pending_inserts(eid))
-        for pendingid in pending_inserts:
-            eidfrom, rtype, eidto = pendingid.split(':')
-            if typed_eid(eidfrom) == eid: # subject
-                label = display_name(self._cw, rtype, 'subject',
-                                     self.edited_entity.__regid__)
-                reid = eidto
-            else:
-                label = display_name(self._cw, rtype, 'object',
-                                     self.edited_entity.__regid__)
-                reid = eidfrom
-            jscall = "javascript: cancelPendingInsert('%s', '%s', null, %s);" \
-                     % (pendingid, cell, eid)
-            rset = self._cw.eid_rset(reid)
-            eview = self._cw.view('text', rset, row=0)
-            # XXX find a clean way to handle baskets
-            if rset.description[0][0] == 'Basket':
-                eview = '%s (%s)' % (eview, display_name(self._cw, 'Basket'))
-            yield rtype, pendingid, jscall, label, reid, eview
-
     # inlined forms support ####################################################
 
     @cached