delete-trailing-whitespaces, add page_size argument to .paginate
"""Set of HTML generic base views:* noresult, final* primary, sidebox* secondary, oneline, incontext, outofcontext, text* list:organization: Logilab:copyright: 2001-2009 LOGILAB S.A. (Paris, FRANCE), all rights reserved.:contact: http://www.logilab.fr/ -- mailto:contact@logilab.fr"""#from __future__ import with_statement__docformat__="restructuredtext en"fromrqlimportnodesfromlogilab.mtconverterimportTransformError,html_escapefromcubicwebimportNoSelectableObjectfromcubicweb.selectorsimportyes,empty_rsetfromcubicweb.viewimportEntityView,AnyRsetView,Viewfromcubicweb.common.uilibimportcut,printable_value_=unicodeclassNullView(AnyRsetView):"""default view when no result has been found"""id='null'__select__=yes()defcall(self,**kwargs):passcell_call=callclassNoResultView(View):"""default view when no result has been found"""__select__=empty_rset()id='noresult'defcall(self,**kwargs):self.w(u'<div class="searchMessage"><strong>%s</strong></div>\n'%self.req._('No result matching query'))classFinalView(AnyRsetView):"""display values without any transformation (i.e. get a number for entities) """id='final'# record generated i18n catalog messages_('%d years')_('%d months')_('%d weeks')_('%d days')_('%d hours')_('%d minutes')_('%d seconds')_('%d years')_('%d months')_('%d weeks')_('%d days')_('%d hours')_('%d minutes')_('%d seconds')defcell_call(self,row,col,props=None,displaytime=False,format='text/html'):etype=self.rset.description[row][col]value=self.rset.rows[row][col]ifetype=='String':entity,rtype=self.rset.related_entity(row,col)ifentityisnotNone:# yes !self.w(entity.printable_value(rtype,value,format=format))returnifetypein('Time','Interval'):# value is DateTimeDelta but we have no idea about what is the# reference date here, so we can only approximate years and monthsifformat=='text/html':space=' 'else:space=' 'ifvalue.days>730:# 2 yearsself.w(self.req.__('%%d%syears'%space)%(value.days//365))elifvalue.days>60:# 2 monthsself.w(self.req.__('%%d%smonths'%space)%(value.days//30))elifvalue.days>14:# 2 weeksself.w(self.req.__('%%d%sweeks'%space)%(value.days//7))elifvalue.days>2:self.w(self.req.__('%%d%sdays'%space)%int(value.days))elifvalue.hours>2:self.w(self.req.__('%%d%shours'%space)%int(value.hours))elifvalue.minutes>=2:self.w(self.req.__('%%d%sminutes'%space)%int(value.minutes))else:self.w(self.req.__('%%d%sseconds'%space)%int(value.seconds))returnself.wdata(printable_value(self.req,etype,value,props,displaytime=displaytime))classSecondaryView(EntityView):id='secondary'title=_('secondary')defcell_call(self,row,col):"""the secondary view for an entity secondary = icon + view(oneline) """entity=self.entity(row,col)self.w(u' ')self.wview('oneline',self.rset,row=row,col=col)classOneLineView(EntityView):id='oneline'title=_('oneline')defcell_call(self,row,col):"""the one line view for an entity: linked text view """entity=self.entity(row,col)self.w(u'<a href="%s">'%html_escape(entity.absolute_url()))self.w(html_escape(self.view('text',self.rset,row=row,col=col)))self.w(u'</a>')classTextView(EntityView):"""the simplest text view for an entity"""id='text'title=_('text')content_type='text/plain'defcall(self,**kwargs):"""the view is called for an entire result set, by default loop other rows of the result set and call the same view on the particular row Views applicable on None result sets have to override this method """rset=self.rsetifrsetisNone:raiseNotImplementedError,selfforiinxrange(len(rset)):self.wview(self.id,rset,row=i,**kwargs)iflen(rset)>1:self.w(u"\n")defcell_call(self,row,col=0,**kwargs):entity=self.entity(row,col)self.w(cut(entity.dc_title(),self.req.property_value('navigation.short-line-size')))classMetaDataView(EntityView):"""paragraph view of some metadata"""id='metadata'show_eid=Truedefcell_call(self,row,col):_=self.req._entity=self.entity(row,col)self.w(u'<div class="metadata">')ifself.show_eid:self.w(u'#%s - '%entity.eid)ifentity.modification_date!=entity.creation_date:self.w(u'<span>%s</span> '%_('latest update on'))self.w(u'<span class="value">%s</span>, '%self.format_date(entity.modification_date))# entities from external source may not have a creation date (eg ldap)ifentity.creation_date:self.w(u'<span>%s</span> '%_('created on'))self.w(u'<span class="value">%s</span>'%self.format_date(entity.creation_date))ifentity.creator:self.w(u' <span>%s</span> '%_('by'))self.w(u'<span class="value">%s</span>'%entity.creator.name())self.w(u'</div>')# new default views for finner control in general views , to use instead of# oneline / secondaryclassInContextTextView(TextView):id='textincontext'title=None# not listed as a possible viewdefcell_call(self,row,col):entity=self.entity(row,col)self.w(entity.dc_title())classOutOfContextTextView(InContextTextView):id='textoutofcontext'defcell_call(self,row,col):entity=self.entity(row,col)self.w(entity.dc_long_title())classInContextView(EntityView):id='incontext'defcell_call(self,row,col):entity=self.entity(row,col)desc=cut(entity.dc_description(),50)self.w(u'<a href="%s" title="%s">'%(html_escape(entity.absolute_url()),html_escape(desc)))self.w(html_escape(self.view('textincontext',self.rset,row=row,col=col)))self.w(u'</a>')classOutOfContextView(EntityView):id='outofcontext'defcell_call(self,row,col):self.w(u'<a href="%s">'%self.entity(row,col).absolute_url())self.w(html_escape(self.view('textoutofcontext',self.rset,row=row,col=col)))self.w(u'</a>')# list views ##################################################################classListView(EntityView):id='list'title=_('list')item_vid='listitem'defcall(self,klass=None,title=None,subvid=None,listid=None,**kwargs):"""display a list of entities by calling their <item_vid> view :param listid: the DOM id to use for the root element """ifsubvidisNoneand'subvid'inself.req.form:subvid=self.req.form.pop('subvid')# consume itiflistid:listid=u' id="%s"'%listidelse:listid=u''iftitle:self.w(u'<div%s class="%s"><h4>%s</h4>\n'%(listid,klassor'section',title))self.w(u'<ul>\n')else:self.w(u'<ul%s class="%s">\n'%(listid,klassor'section'))foriinxrange(self.rset.rowcount):self.cell_call(row=i,col=0,vid=subvid,**kwargs)self.w(u'</ul>\n')iftitle:self.w(u'</div>\n')defcell_call(self,row,col=0,vid=None,**kwargs):self.w(u'<li>')self.wview(self.item_vid,self.rset,row=row,col=col,vid=vid,**kwargs)self.w(u'</li>\n')defurl(self):"""overrides url method so that by default, the view list is called with sorted entities """coltypes=self.rset.column_types(0)# don't want to generate the rql if there is some restriction on# something else than the entity typeiflen(coltypes)==1:# XXX norestriction is not correct here. For instance, in cases like# Any P,N WHERE P is Project, P name N# norestriction should equal Truerestr=self.rset.syntax_tree().children[0].wherenorestriction=(isinstance(restr,nodes.Relation)andrestr.is_types_restriction())ifnorestriction:etype=iter(coltypes).next()returnself.build_url(etype.lower(),vid=self.id)iflen(self.rset)==1:entity=self.rset.get_entity(0,0)returnself.build_url(entity.rest_path(),vid=self.id)returnself.build_url(rql=self.rset.printable_rql(),vid=self.id)classListItemView(EntityView):id='listitem'@propertydefredirect_vid(self):ifself.req.search_state[0]=='normal':return'outofcontext'return'outofcontext-search'defcell_call(self,row,col,vid=None,**kwargs):ifnotvid:vid=self.redirect_vidtry:self.wview(vid,self.rset,row=row,col=col,**kwargs)exceptNoSelectableObject:ifvid==self.redirect_vid:raiseself.wview(self.redirect_vid,self.rset,row=row,col=col,**kwargs)classSimpleListView(ListItemView):"""list without bullets"""id='simplelist'redirect_vid='incontext'classCSVView(SimpleListView):id='csv'redirect_vid='incontext'defcall(self,**kwargs):rset=self.rsetforiinxrange(len(rset)):self.cell_call(i,0,vid=kwargs.get('vid'))ifi<rset.rowcount-1:self.w(u", ")classTreeItemView(ListItemView):id='treeitem'defcell_call(self,row,col):self.wview('incontext',self.rset,row=row,col=col)classTextSearchResultView(EntityView):"""this view is used to display full-text search It tries to highlight part of data where the search word appears. XXX: finish me (fixed line width, fixed number of lines, CSS, etc.) """id='tsearch'defcell_call(self,row,col,**kwargs):entity=self.complete_entity(row,col)self.w(entity.view('incontext'))searched=self.rset.searched_text()ifsearchedisNone:returnsearched=searched.lower()highlighted='<b>%s</b>'%searchedforattrinentity.e_schema.indexable_attributes():try:value=html_escape(entity.printable_value(attr,format='text/plain').lower())exceptTransformError,ex:continueexcept:continueifsearchedinvalue:contexts=[]forctxinvalue.split(searched):iflen(ctx)>30:contexts.append(u'...'+ctx[-30:])else:contexts.append(ctx)value=u'\n'+highlighted.join(contexts)self.w(value.replace('\n','<br/>'))classTooltipView(EntityView):"""A entity view used in a tooltip"""id='tooltip'defcell_call(self,row,col):self.wview('oneline',self.rset,row=row,col=col)# XXX bw compatfromlogilab.common.deprecationimportclass_movedtry:fromcubicweb.web.views.tableviewimportTableViewTableView=class_moved(TableView)exceptImportError:pass# gae has no tableview module (yet)fromcubicweb.web.viewsimportboxes,xmlrss,primaryPrimaryView=class_moved(primary.PrimaryView)SideBoxView=class_moved(boxes.SideBoxView)XmlView=class_moved(xmlrss.XMLView)XmlItemView=class_moved(xmlrss.XMLItemView)XmlRsetView=class_moved(xmlrss.XMLRsetView)RssView=class_moved(xmlrss.RSSView)RssItemView=class_moved(xmlrss.RSSItemView)