"""navigation 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"fromrql.nodesimportVariableRef,Constantfromlogilab.mtconverterimporthtml_escapefromcubicweb.interfacesimportIPrevNextfromcubicweb.common.selectorsimport(largerset_selector,sortedrset_selector,primaryview_selector,contextprop_selector,onelinerset_selector,interface_selector)fromcubicweb.common.uilibimportcutfromcubicweb.web.componentimportEntityVComponent,NavigationComponent_=unicodeclassPageNavigation(NavigationComponent):defcall(self):"""displays a resultset by page"""w=self.wreq=self.reqrset=self.rsetpage_size=self.page_sizestart=0blocklist=[]params=dict(req.form)self.clean_params(params)basepath=req.relative_path(includeparams=False)whilestart<rset.rowcount:stop=min(start+page_size-1,rset.rowcount-1)blocklist.append(self.page_link(basepath,params,start,stop,u'%s - %s'%(start+1,stop+1)))start=stop+1w(u'<div class="pagination">')w(u'%s '%self.previous_link(params))w(u'[ %s ]'%u' | '.join(blocklist))w(u' %s'%self.next_link(params))w(u'</div>')classSortedNavigation(NavigationComponent):"""sorted navigation apply if navigation is needed (according to page size) and if the result set is sorted """__selectors__=(largerset_selector,sortedrset_selector)# number of considered chars to build page linksnb_chars=5defdisplay_func(self,rset,col,attrname):req=self.reqifattrnameisnotNone:defindex_display(row):entity=rset.get_entity(row,col)returnentity.printable_value(attrname,format='text/plain')elifself.schema.eschema(rset.description[0][col]).is_final():defindex_display(row):returnunicode(rset[row][col])else:defindex_display(row):returnrset.get_entity(row,col).view('text')returnindex_displaydefcall(self):"""displays links to navigate accross pages of a result set Displayed result is done according to a variable on which the sort is done, and looks like: [ana - cro] | [cro - ghe] | ... | [tim - zou] """w=self.wrset=self.rsetpage_size=self.page_sizerschema=self.schema.rschema# attrname = the name of attribute according to which the sort# is done if anyforsorterminrset.syntax_tree().children[0].orderby:ifisinstance(sorterm.term,Constant):col=sorterm.term.value-1index_display=self.display_func(rset,col,None)breakvar=sorterm.term.get_nodes(VariableRef)[0].variablecol=Noneforrefinvar.references():rel=ref.relation()ifrelisNone:continueattrname=rel.r_typeifattrname=='is':continueifnotrschema(attrname).is_final():col=var.selected_index()attrname=NoneifcolisNone:# final relation or not selected non final relationifvarisrel.children[0]:relvar=rel.children[1].children[0].get_nodes(VariableRef)[0]else:relvar=rel.children[0].variablecol=relvar.selected_index()ifcolisnotNone:breakelse:# no relation but maybe usable anyway if selectedcol=var.selected_index()attrname=NoneifcolisnotNone:index_display=self.display_func(rset,col,attrname)breakelse:# nothing usable found, use the first columnindex_display=self.display_func(rset,0,None)blocklist=[]params=dict(self.req.form)self.clean_params(params)start=0basepath=self.req.relative_path(includeparams=False)whilestart<rset.rowcount:stop=min(start+page_size-1,rset.rowcount-1)cell=self.format_link_content(index_display(start),index_display(stop))blocklist.append(self.page_link(basepath,params,start,stop,cell))start=stop+1self.write_links(params,blocklist)defformat_link_content(self,startstr,stopstr):text=u'%s - %s'%(startstr.lower()[:self.nb_chars],stopstr.lower()[:self.nb_chars])returnhtml_escape(text)defwrite_links(self,params,blocklist):self.w(u'<div class="pagination">')self.w(u'%s '%self.previous_link(params))self.w(u'[ %s ]'%u' | '.join(blocklist))self.w(u' %s'%self.next_link(params))self.w(u'</div>')deflimit_rset_using_paged_nav(self,req,rset,w,forcedisplay=False,show_all_option=True):showall=forcedisplayorreq.form.get('__force_display')isnotNonenav=notshowallandself.vreg.select_component('navigation',req,rset)ifnav:# get boundaries before component renderingstart,stop=nav.page_boundaries()nav.dispatch(w=w)params=dict(req.form)nav.clean_params(params)# make a link to see them allifshow_all_option:url=html_escape(self.build_url(__force_display=1,**params))w(u'<p><a href="%s">%s</a></p>\n'%(url,req._('show %s results')%len(rset)))rset.limit(offset=start,limit=stop-start,inplace=True)# monkey patch base View class to add a .pagination(req, rset, w, forcedisplay)# method to be called on view's result set and printing pages index in the viewfromcubicweb.common.viewimportView# XXX deprecated, use paginateView.pagination=limit_rset_using_paged_navdefpaginate(view,show_all_option=True,w=None):limit_rset_using_paged_nav(view,view.req,view.rset,worview.w,notview.need_navigation,show_all_option)View.paginate=paginateclassNextPrevNavigationComponent(EntityVComponent):id='prevnext'# register msg not generated since no entity implements IPrevNext in cubicweb# itselftitle=_('contentnavigation_prevnext')help=_('contentnavigation_prevnext_description')__selectors__=(onelinerset_selector,primaryview_selector,contextprop_selector,interface_selector)accepts_interfaces=(IPrevNext,)context='navbottom'order=10defcall(self,view=None):entity=self.entity(0)previous=entity.previous_entity()next=entity.next_entity()ifpreviousornext:textsize=self.req.property_value('navigation.short-line-size')self.w(u'<div class="prevnext">')ifprevious:self.w(u'<div class="previousEntity left">')self.w(self.previous_link(previous,textsize))self.w(u'</div>')self.req.html_headers.add_raw('<link rel="prev" href="%s" />'%html_escape(previous.absolute_url()))ifnext:self.w(u'<div class="nextEntity right">')self.w(self.next_link(next,textsize))self.w(u'</div>')self.req.html_headers.add_raw('<link rel="next" href="%s" />'%html_escape(next.absolute_url()))self.w(u'</div>')self.w(u'<div class="clear"></div>')defprevious_link(self,previous,textsize):returnu'<a href="%s" title="%s"><< %s</a>'%(html_escape(previous.absolute_url()),self.req._('i18nprevnext_previous'),html_escape(cut(previous.dc_title(),textsize)))defnext_link(self,next,textsize):returnu'<a href="%s" title="%s">%s >></a>'%(html_escape(next.absolute_url()),self.req._('i18nprevnext_next'),html_escape(cut(next.dc_title(),textsize)))