web/views/ibreadcrumbs.py
changeset 5556 9ab2b4c74baf
parent 5424 8ecbcbff9777
child 5569 cb14af012a96
--- a/web/views/ibreadcrumbs.py	Thu May 20 20:47:13 2010 +0200
+++ b/web/views/ibreadcrumbs.py	Thu May 20 20:47:55 2010 +0200
@@ -21,20 +21,78 @@
 __docformat__ = "restructuredtext en"
 _ = unicode
 
+from warnings import warn
+
 from logilab.mtconverter import xml_escape
 
-from cubicweb.interfaces import IBreadCrumbs
-from cubicweb.selectors import (one_line_rset, implements, one_etype_rset,
-                                multi_lines_rset, any_rset)
-from cubicweb.view import EntityView, Component
+#from cubicweb.interfaces import IBreadCrumbs
+from cubicweb.selectors import (implements, one_line_rset, adaptable,
+                                one_etype_rset, multi_lines_rset, any_rset)
+from cubicweb.view import EntityView, Component, EntityAdapter
 # don't use AnyEntity since this may cause bug with isinstance() due to reloading
 from cubicweb.entity import Entity
 from cubicweb import tags, uilib
 
 
+# ease bw compat
+def ibreadcrumb_adapter(entity):
+    if hasattr(entity, 'breadcrumbs'):
+        warn('[3.9] breadcrumbs() method is deprecated, define a custom '
+             'IBreadCrumbsAdapter for %s instead' % entity.__class__,
+             DeprecationWarning)
+        return entity
+    return entity.cw_adapt_to('IBreadCrumbs')
+
+
+class IBreadCrumbsAdapter(EntityAdapter):
+    """adapters for entities which can be"located" on some path to display in
+    the web ui
+    """
+    __regid__ = 'IBreadCrumbs'
+    __select__ = implements('Any', accept_none=False)
+
+    def parent_entity(self):
+        if hasattr(self.entity, 'parent'):
+            warn('[3.9] parent() method is deprecated, define a '
+                 'custom IBreadCrumbsAdapter/ITreeAdapter for %s instead'
+                 % self.entity.__class__, DeprecationWarning)
+            return self.entity.parent()
+        itree = self.entity.cw_adapt_to('ITree')
+        if itree is not None:
+            return itree.parent()
+        return None
+
+    def breadcrumbs(self, view=None, recurs=False):
+        """return a list containing some:
+
+        * tuple (url, label)
+        * entity
+        * simple label string
+
+        defining path from a root to the current view
+
+        the main view is given as argument so breadcrumbs may vary according
+        to displayed view (may be None). When recursing on a parent entity,
+        the `recurs` argument should be set to True.
+        """
+        path = [self.entity]
+        parent = self.parent_entity()
+        if parent is not None:
+            adapter = ibreadcrumb_adapter(self.entity)
+            path = adapter.breadcrumbs(view, True) + [self.entity]
+        if not recurs:
+            if view is None:
+                if 'vtitle' in self._cw.form:
+                    # embeding for instance
+                    path.append( self._cw.form['vtitle'] )
+            elif view.__regid__ != 'primary' and hasattr(view, 'title'):
+                path.append( self._cw._(view.title) )
+        return path
+
+
 class BreadCrumbEntityVComponent(Component):
     __regid__ = 'breadcrumbs'
-    __select__ = one_line_rset() & implements(IBreadCrumbs, accept_none=False)
+    __select__ = one_line_rset() & adaptable('IBreadCrumbs')
 
     cw_property_defs = {
         _('visible'):  dict(type='Boolean', default=True,
@@ -47,7 +105,8 @@
 
     def call(self, view=None, first_separator=True):
         entity = self.cw_rset.get_entity(0, 0)
-        path = entity.breadcrumbs(view)
+        adapter = ibreadcrumb_adapter(entity)
+        path = adapter.breadcrumbs(view)
         if path:
             self.open_breadcrumbs()
             if first_separator:
@@ -73,7 +132,7 @@
             self.w(u"\n")
             self.wpath_part(parent, contextentity, i == len(path) - 1)
 
-    def wpath_part(self, part, contextentity, last=False):
+    def wpath_part(self, part, contextentity, last=False): # XXX deprecates last argument?
         if isinstance(part, Entity):
             self.w(part.view('breadcrumbs'))
         elif isinstance(part, tuple):
@@ -88,7 +147,7 @@
 
 class BreadCrumbETypeVComponent(BreadCrumbEntityVComponent):
     __select__ = multi_lines_rset() & one_etype_rset() & \
-                 implements(IBreadCrumbs, accept_none=False)
+                 adaptable('IBreadCrumbs')
 
     def render_breadcrumbs(self, contextentity, path):
         # XXX hack: only display etype name or first non entity path part