web/views/ibreadcrumbs.py
changeset 5556 9ab2b4c74baf
parent 5424 8ecbcbff9777
child 5569 cb14af012a96
equal deleted inserted replaced
5555:a64f48dd5fe4 5556:9ab2b4c74baf
    19 
    19 
    20 """
    20 """
    21 __docformat__ = "restructuredtext en"
    21 __docformat__ = "restructuredtext en"
    22 _ = unicode
    22 _ = unicode
    23 
    23 
       
    24 from warnings import warn
       
    25 
    24 from logilab.mtconverter import xml_escape
    26 from logilab.mtconverter import xml_escape
    25 
    27 
    26 from cubicweb.interfaces import IBreadCrumbs
    28 #from cubicweb.interfaces import IBreadCrumbs
    27 from cubicweb.selectors import (one_line_rset, implements, one_etype_rset,
    29 from cubicweb.selectors import (implements, one_line_rset, adaptable,
    28                                 multi_lines_rset, any_rset)
    30                                 one_etype_rset, multi_lines_rset, any_rset)
    29 from cubicweb.view import EntityView, Component
    31 from cubicweb.view import EntityView, Component, EntityAdapter
    30 # don't use AnyEntity since this may cause bug with isinstance() due to reloading
    32 # don't use AnyEntity since this may cause bug with isinstance() due to reloading
    31 from cubicweb.entity import Entity
    33 from cubicweb.entity import Entity
    32 from cubicweb import tags, uilib
    34 from cubicweb import tags, uilib
    33 
    35 
    34 
    36 
       
    37 # ease bw compat
       
    38 def ibreadcrumb_adapter(entity):
       
    39     if hasattr(entity, 'breadcrumbs'):
       
    40         warn('[3.9] breadcrumbs() method is deprecated, define a custom '
       
    41              'IBreadCrumbsAdapter for %s instead' % entity.__class__,
       
    42              DeprecationWarning)
       
    43         return entity
       
    44     return entity.cw_adapt_to('IBreadCrumbs')
       
    45 
       
    46 
       
    47 class IBreadCrumbsAdapter(EntityAdapter):
       
    48     """adapters for entities which can be"located" on some path to display in
       
    49     the web ui
       
    50     """
       
    51     __regid__ = 'IBreadCrumbs'
       
    52     __select__ = implements('Any', accept_none=False)
       
    53 
       
    54     def parent_entity(self):
       
    55         if hasattr(self.entity, 'parent'):
       
    56             warn('[3.9] parent() method is deprecated, define a '
       
    57                  'custom IBreadCrumbsAdapter/ITreeAdapter for %s instead'
       
    58                  % self.entity.__class__, DeprecationWarning)
       
    59             return self.entity.parent()
       
    60         itree = self.entity.cw_adapt_to('ITree')
       
    61         if itree is not None:
       
    62             return itree.parent()
       
    63         return None
       
    64 
       
    65     def breadcrumbs(self, view=None, recurs=False):
       
    66         """return a list containing some:
       
    67 
       
    68         * tuple (url, label)
       
    69         * entity
       
    70         * simple label string
       
    71 
       
    72         defining path from a root to the current view
       
    73 
       
    74         the main view is given as argument so breadcrumbs may vary according
       
    75         to displayed view (may be None). When recursing on a parent entity,
       
    76         the `recurs` argument should be set to True.
       
    77         """
       
    78         path = [self.entity]
       
    79         parent = self.parent_entity()
       
    80         if parent is not None:
       
    81             adapter = ibreadcrumb_adapter(self.entity)
       
    82             path = adapter.breadcrumbs(view, True) + [self.entity]
       
    83         if not recurs:
       
    84             if view is None:
       
    85                 if 'vtitle' in self._cw.form:
       
    86                     # embeding for instance
       
    87                     path.append( self._cw.form['vtitle'] )
       
    88             elif view.__regid__ != 'primary' and hasattr(view, 'title'):
       
    89                 path.append( self._cw._(view.title) )
       
    90         return path
       
    91 
       
    92 
    35 class BreadCrumbEntityVComponent(Component):
    93 class BreadCrumbEntityVComponent(Component):
    36     __regid__ = 'breadcrumbs'
    94     __regid__ = 'breadcrumbs'
    37     __select__ = one_line_rset() & implements(IBreadCrumbs, accept_none=False)
    95     __select__ = one_line_rset() & adaptable('IBreadCrumbs')
    38 
    96 
    39     cw_property_defs = {
    97     cw_property_defs = {
    40         _('visible'):  dict(type='Boolean', default=True,
    98         _('visible'):  dict(type='Boolean', default=True,
    41                             help=_('display the component or not')),
    99                             help=_('display the component or not')),
    42         }
   100         }
    45     separator = u' > '
   103     separator = u' > '
    46     link_template = u'<a href="%s">%s</a>'
   104     link_template = u'<a href="%s">%s</a>'
    47 
   105 
    48     def call(self, view=None, first_separator=True):
   106     def call(self, view=None, first_separator=True):
    49         entity = self.cw_rset.get_entity(0, 0)
   107         entity = self.cw_rset.get_entity(0, 0)
    50         path = entity.breadcrumbs(view)
   108         adapter = ibreadcrumb_adapter(entity)
       
   109         path = adapter.breadcrumbs(view)
    51         if path:
   110         if path:
    52             self.open_breadcrumbs()
   111             self.open_breadcrumbs()
    53             if first_separator:
   112             if first_separator:
    54                 self.w(self.separator)
   113                 self.w(self.separator)
    55             self.render_breadcrumbs(entity, path)
   114             self.render_breadcrumbs(entity, path)
    71         for i, parent in enumerate(path):
   130         for i, parent in enumerate(path):
    72             self.w(self.separator)
   131             self.w(self.separator)
    73             self.w(u"\n")
   132             self.w(u"\n")
    74             self.wpath_part(parent, contextentity, i == len(path) - 1)
   133             self.wpath_part(parent, contextentity, i == len(path) - 1)
    75 
   134 
    76     def wpath_part(self, part, contextentity, last=False):
   135     def wpath_part(self, part, contextentity, last=False): # XXX deprecates last argument?
    77         if isinstance(part, Entity):
   136         if isinstance(part, Entity):
    78             self.w(part.view('breadcrumbs'))
   137             self.w(part.view('breadcrumbs'))
    79         elif isinstance(part, tuple):
   138         elif isinstance(part, tuple):
    80             url, title = part
   139             url, title = part
    81             textsize = self._cw.property_value('navigation.short-line-size')
   140             textsize = self._cw.property_value('navigation.short-line-size')
    86             self.w(uilib.cut(unicode(part), textsize))
   145             self.w(uilib.cut(unicode(part), textsize))
    87 
   146 
    88 
   147 
    89 class BreadCrumbETypeVComponent(BreadCrumbEntityVComponent):
   148 class BreadCrumbETypeVComponent(BreadCrumbEntityVComponent):
    90     __select__ = multi_lines_rset() & one_etype_rset() & \
   149     __select__ = multi_lines_rset() & one_etype_rset() & \
    91                  implements(IBreadCrumbs, accept_none=False)
   150                  adaptable('IBreadCrumbs')
    92 
   151 
    93     def render_breadcrumbs(self, contextentity, path):
   152     def render_breadcrumbs(self, contextentity, path):
    94         # XXX hack: only display etype name or first non entity path part
   153         # XXX hack: only display etype name or first non entity path part
    95         root = path.pop(0)
   154         root = path.pop(0)
    96         if isinstance(root, Entity):
   155         if isinstance(root, Entity):