[doc] Better title? Brief introduction of the chapter.
"""abstract component class and base components definition for CubicWeb web client:organization: Logilab:copyright: 2001-2008 LOGILAB S.A. (Paris, FRANCE), all rights reserved.:contact: http://www.logilab.fr/ -- mailto:contact@logilab.fr"""__docformat__="restructuredtext en"fromcubicweb.common.appobjectimportComponent,SingletonComponentfromcubicweb.common.utilsimportmerge_dictsfromcubicweb.common.viewimportVComponent,SingletonVComponentfromcubicweb.common.registerersimportaction_registererfromcubicweb.common.selectorsimport(paginated_rset,one_line_rset,etype_rtype_selector,rqlcondition_selector,accept_selector,contextprop_selector,primaryview_selector,accept_rtype_selector)fromcubicweb.common.uilibimporthtml_escape_=unicodeclassEntityVComponent(VComponent):"""abstract base class for additinal components displayed in content headers and footer according to: * the displayed entity's type * a context (currently 'header' or 'footer') it should be configured using .accepts, .etype, .rtype, .target and .context class attributes """__registry__='contentnavigation'__registerer__=action_registerer__selectors__=(one_line_rset,primaryview_selector,contextprop_selector,etype_rtype_selector,accept_rtype_selector,accept_selector,rqlcondition_selector)property_defs={_('visible'):dict(type='Boolean',default=True,help=_('display the box or not')),_('order'):dict(type='Int',default=99,help=_('display order of the component')),_('context'):dict(type='String',default='header',vocabulary=(_('navtop'),_('navbottom'),_('navcontenttop'),_('navcontentbottom')),#vocabulary=(_('header'), _('incontext'), _('footer')),help=_('context where this component should be displayed')),_('htmlclass'):dict(type='String',default='mainRelated',help=_('html class of the component')),}accepts=('Any',)context='navcontentbottom'# 'footer' | 'header' | 'incontext'condition=Nonedefcall(self,view):raiseRuntimeError()classNavigationComponent(VComponent):"""abstract base class for navigation components"""__selectors__=(paginated_rset,)id='navigation'page_size_property='navigation.page-size'start_param='__start'stop_param='__stop'page_link_templ=u'<span class="slice"><a href="%s" title="%s">%s</a></span>'selected_page_link_templ=u'<span class="selectedSlice"><a href="%s" title="%s">%s</a></span>'previous_page_link_templ=next_page_link_templ=page_link_templno_previous_page_link=no_next_page_link=u''def__init__(self,req,rset):super(NavigationComponent,self).__init__(req,rset)self.starting_from=0self.total=rset.rowcountdefget_page_size(self):try:returnself._page_sizeexceptAttributeError:self._page_size=self.req.property_value(self.page_size_property)returnself._page_sizedefset_page_size(self,page_size):self._page_size=page_sizepage_size=property(get_page_size,set_page_size)defpage_boundaries(self):try:stop=int(self.req.form[self.stop_param])+1start=int(self.req.form[self.start_param])exceptKeyError:start,stop=0,self.page_sizeself.starting_from=startreturnstart,stopdefclean_params(self,params):ifself.start_paraminparams:delparams[self.start_param]ifself.stop_paraminparams:delparams[self.stop_param]defpage_link(self,path,params,start,stop,content):url=self.build_url(path,**merge_dicts(params,{self.start_param:start,self.stop_param:stop,}))url=html_escape(url)ifstart==self.starting_from:returnself.selected_page_link_templ%(url,content,content)returnself.page_link_templ%(url,content,content)defprevious_link(self,params,content='<<',title=_('previous_results')):start=self.starting_fromifnotstart:returnself.no_previous_page_linkstart=max(0,start-self.page_size)stop=start+self.page_size-1url=self.build_url(**merge_dicts(params,{self.start_param:start,self.stop_param:stop,}))url=html_escape(url)returnself.previous_page_link_templ%(url,title,content)defnext_link(self,params,content='>>',title=_('next_results')):start=self.starting_from+self.page_sizeifstart>=self.total:returnself.no_next_page_linkstop=start+self.page_size-1url=self.build_url(**merge_dicts(params,{self.start_param:start,self.stop_param:stop,}))url=html_escape(url)returnself.next_page_link_templ%(url,title,content)classRelatedObjectsVComponent(EntityVComponent):"""a section to display some related entities"""__selectors__=(one_line_rset,primaryview_selector,etype_rtype_selector,accept_rtype_selector,contextprop_selector,accept_selector)vid='list'defrql(self):"""override this method if you want to use a custom rql query. """returnNonedefcall(self,view=None):rql=self.rql()ifrqlisNone:entity=self.rset.get_entity(0,0)ifself.target=='object':role='subject'else:role='object'rset=entity.related(self.rtype,role)else:eid=self.rset[0][0]rset=self.req.execute(self.rql(),{'x':eid},'x')ifnotrset.rowcount:returnself.w(u'<div class="%s">'%self.div_class())self.wview(self.vid,rset,title=self.req._(self.title).capitalize())self.w(u'</div>')