# copyright 2003-2010 LOGILAB S.A. (Paris, FRANCE), all rights reserved.# contact http://www.logilab.fr/ -- mailto:contact@logilab.fr## This file is part of CubicWeb.## CubicWeb is free software: you can redistribute it and/or modify it under the# terms of the GNU Lesser General Public License as published by the Free# Software Foundation, either version 2.1 of the License, or (at your option)# any later version.## CubicWeb is distributed in the hope that it will be useful, but WITHOUT# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS# FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more# details.## You should have received a copy of the GNU Lesser General Public License along# with CubicWeb. If not, see <http://www.gnu.org/licenses/>."""breadcrumbs components definition for CubicWeb web client"""__docformat__="restructuredtext en"_=unicodefromwarningsimportwarnfromlogilab.mtconverterimportxml_escape#from cubicweb.interfaces import IBreadCrumbsfromcubicweb.selectorsimport(is_instance,one_line_rset,adaptable,one_etype_rset,multi_lines_rset,any_rset)fromcubicweb.viewimportEntityView,Component,EntityAdapter# don't use AnyEntity since this may cause bug with isinstance() due to reloadingfromcubicweb.entityimportEntityfromcubicwebimporttags,uilib# ease bw compatdefibreadcrumb_adapter(entity):ifhasattr(entity,'breadcrumbs'):warn('[3.9] breadcrumbs() method is deprecated, define a custom ''IBreadCrumbsAdapter for %s instead'%entity.__class__,DeprecationWarning)returnentityreturnentity.cw_adapt_to('IBreadCrumbs')classIBreadCrumbsAdapter(EntityAdapter):"""adapters for entities which can be"located" on some path to display in the web ui """__regid__='IBreadCrumbs'__select__=is_instance('Any',accept_none=False)defparent_entity(self):ifhasattr(self.entity,'parent'):warn('[3.9] parent() method is deprecated, define a ''custom IBreadCrumbsAdapter/ITreeAdapter for %s instead'%self.entity.__class__,DeprecationWarning)returnself.entity.parent()itree=self.entity.cw_adapt_to('ITree')ifitreeisnotNone:returnitree.parent()returnNonedefbreadcrumbs(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. """parent=self.parent_entity()ifparentisnotNone:adapter=ibreadcrumb_adapter(parent)path=adapter.breadcrumbs(view,True)+[self.entity]else:path=[self.entity]ifnotrecurs:ifviewisNone:if'vtitle'inself._cw.form:# embeding for instancepath.append(self._cw.form['vtitle'])elifview.__regid__!='primary'andhasattr(view,'title'):path.append(self._cw._(view.title))returnpathclassBreadCrumbEntityVComponent(Component):__regid__='breadcrumbs'__select__=one_line_rset()&adaptable('IBreadCrumbs')cw_property_defs={_('visible'):dict(type='Boolean',default=True,help=_('display the component or not')),}title=_('contentnavigation_breadcrumbs')help=_('contentnavigation_breadcrumbs_description')separator=u' > 'link_template=u'<a href="%s">%s</a>'defcall(self,view=None,first_separator=True):entity=self.cw_rset.get_entity(0,0)adapter=ibreadcrumb_adapter(entity)path=adapter.breadcrumbs(view)ifpath:self.open_breadcrumbs()iffirst_separator:self.w(self.separator)self.render_breadcrumbs(entity,path)self.close_breadcrumbs()defopen_breadcrumbs(self):self.w(u'<span id="breadcrumbs" class="pathbar">')defclose_breadcrumbs(self):self.w(u'</span>')defrender_breadcrumbs(self,contextentity,path):root=path.pop(0)ifisinstance(root,Entity):self.w(self.link_template%(self._cw.build_url(root.__regid__),root.dc_type('plural')))self.w(self.separator)self.wpath_part(root,contextentity,notpath)fori,parentinenumerate(path):self.w(self.separator)self.w(u"\n")self.wpath_part(parent,contextentity,i==len(path)-1)defwpath_part(self,part,contextentity,last=False):# XXX deprecates last argument?ifisinstance(part,Entity):self.w(part.view('breadcrumbs'))elifisinstance(part,tuple):url,title=parttextsize=self._cw.property_value('navigation.short-line-size')self.w(self.link_template%(xml_escape(url),xml_escape(uilib.cut(title,textsize))))else:textsize=self._cw.property_value('navigation.short-line-size')self.w(uilib.cut(unicode(part),textsize))classBreadCrumbETypeVComponent(BreadCrumbEntityVComponent):__select__=multi_lines_rset()&one_etype_rset()& \adaptable('IBreadCrumbs')defrender_breadcrumbs(self,contextentity,path):# XXX hack: only display etype name or first non entity path partroot=path.pop(0)ifisinstance(root,Entity):self.w(u'<a href="%s">%s</a>'%(self._cw.build_url(root.__regid__),root.dc_type('plural')))else:self.wpath_part(root,contextentity,notpath)classBreadCrumbAnyRSetVComponent(BreadCrumbEntityVComponent):__select__=any_rset()defcall(self,view=None,first_separator=True):self.w(u'<span id="breadcrumbs" class="pathbar">')iffirst_separator:self.w(self.separator)self.w(self._cw._('search'))self.w(u'</span>')classBreadCrumbView(EntityView):__regid__='breadcrumbs'defcell_call(self,row,col,**kwargs):entity=self.cw_rset.get_entity(row,col)desc=xml_escape(uilib.cut(entity.dc_description(),50))# XXX remember camember : tags.a autoescapes !self.w(tags.a(entity.view('breadcrumbtext'),href=entity.absolute_url(),title=desc))classBreadCrumbTextView(EntityView):__regid__='breadcrumbtext'defcell_call(self,row,col,**kwargs):entity=self.cw_rset.get_entity(row,col)textsize=self._cw.property_value('navigation.short-line-size')self.w(uilib.cut(entity.dc_title(),textsize))