"""inline help system, using ReST file in products `wdoc` directory:organization: Logilab:copyright: 2008 LOGILAB S.A. (Paris, FRANCE), all rights reserved.:contact: http://www.logilab.fr/ -- mailto:contact@logilab.fr"""__docformat__="restructuredtext en"fromitertoolsimportchainfromos.pathimportjoinfrombisectimportbisect_rightfrommx.DateTimeimportstrptime,todayfromlogilab.common.changelogimportChangeLogfromlogilab.mtconverterimportCHARSET_DECL_RGXfromcubicweb.common.selectorsimportreq_form_params_selectorfromcubicweb.common.viewimportStartupViewfromcubicweb.common.uilibimportrest_publishfromcubicweb.webimportNotFound_=unicode# table of content management #################################################try:fromxml.etree.ElementTreeimportparseexceptImportError:fromelementtree.ElementTreeimportparsedefbuild_toc_index(node,index):try:nodeidx=node.attrib['resource']assertnotnodeidxinindex,nodeidxindex[nodeidx]=nodeexceptKeyError:passforchildinnode:build_toc_index(child,index)child.parent=nodedefget_insertion_point(section,index):ifsection.attrib.get('insertafter'):snode=index[section.attrib['insertafter']]node=snode.parentidx=node.getchildren().index(snode)+1elifsection.attrib.get('insertbefore'):snode=index[section.attrib['insertbefore']]node=snode.parentidx=node.getchildren().index(snode)else:node=index[section.attrib['appendto']]idx=Nonereturnnode,idxdefbuild_toc(config):alltocfiles=reversed(tuple(config.locate_all_files('toc.xml')))maintoc=parse(alltocfiles.next()).getroot()maintoc.parent=Noneindex={}build_toc_index(maintoc,index)# insert component documentation into the tree according to their toc.xml# file forfpathinalltocfiles:toc=parse(fpath).getroot()forsectionintoc:node,idx=get_insertion_point(section,index)ifidxisNone:node.append(section)else:node.insert(idx,section)section.parent=nodebuild_toc_index(section,index)returnindexdeftitle(node,lang):fortitleinnode.findall('title'):iftitle.attrib['{http://www.w3.org/XML/1998/namespace}lang']==lang:returnunicode(title.text)defsubsections(node):return[childforchildinnodeifchild.tag=='section']# help views ##################################################################classInlineHelpView(StartupView):__selectors__=(req_form_params_selector,)form_params=('fid',)id='wdoc'title=_('site documentation')defcall(self):fid=self.req.form['fid']forlanginchain((self.req.lang,self.vreg.property_value('ui.language')),self.config.available_languages()):rid='%s_%s.rst'%(fid,lang)resourcedir=self.config.locate_doc_file(rid)ifresourcedir:breakelse:raiseNotFoundself.tocindex=build_toc(self.config)try:node=self.tocindex[fid]exceptKeyError:node=Noneelse:self.navigation_links(node)self.w(u'<div class="hr"></div>')self.w(u'<h1>%s</h1>'%(title(node,self.req.lang)))data=open(join(resourcedir,rid)).read()self.w(rest_publish(self,data))ifnodeisnotNone:self.subsections_links(node)self.w(u'<div class="hr"></div>')self.navigation_links(node)defnavigation_links(self,node):req=self.reqparent=node.parentifparentisNone:returnbrothers=subsections(parent)self.w(u'<div class="docnav">\n')previousidx=brothers.index(node)-1ifpreviousidx>=0:self.navsection(brothers[previousidx],'prev')self.navsection(parent,'up')nextidx=brothers.index(node)+1ifnextidx<len(brothers):self.navsection(brothers[nextidx],'next')self.w(u'</div>\n')navinfo={'prev':('','data/previous.png',_('i18nprevnext_previous')),'next':('','data/next.png',_('i18nprevnext_next')),'up':('','data/up.png',_('i18nprevnext_up'))}defnavsection(self,node,navtype):htmlclass,imgpath,msgid=self.navinfo[navtype]self.w(u'<span class="%s">'%htmlclass)self.w(u'%s : '%self.req._(msgid))self.w(u'<a href="%s">%s</a>'%(self.req.build_url('doc/'+node.attrib['resource']),title(node,self.req.lang)))self.w(u'</span>\n')defsubsections_links(self,node,first=True):sub=subsections(node)ifnotsub:returniffirst:self.w(u'<div class="hr"></div>')self.w(u'<ul class="docsum">')forchildinsub:self.w(u'<li><a href="%s">%s</a>'%(self.req.build_url('doc/'+child.attrib['resource']),title(child,self.req.lang)))self.subsections_links(child,False)self.w(u'</li>')self.w(u'</ul>\n')classInlineHelpImageView(StartupView):__selectors__=(req_form_params_selector,)form_params=('fid',)id='wdocimages'binary=Truetemplatable=Falsecontent_type='image/png'defcall(self):fid=self.req.form['fid']forlanginchain((self.req.lang,self.vreg.property_value('ui.language')),self.config.available_languages()):rid=join('images','%s_%s.png'%(fid,lang))resourcedir=self.config.locate_doc_file(rid)ifresourcedir:breakelse:raiseNotFoundself.w(open(join(resourcedir,rid)).read())classChangeLogView(StartupView):id='changelog'title=_('What\'s new?')maxentries=25defcall(self):rid='ChangeLog_%s'%(self.req.lang)allentries=[]title=self.req._(self.title)restdata=['.. -*- coding: utf-8 -*-','',title,'='*len(title),'']w=restdata.appendforfpathinself.config.locate_all_files(rid):cl=ChangeLog(fpath)encoding='utf-8'# additional content may be found in titleforlinein(cl.title+cl.additional_content).splitlines():m=CHARSET_DECL_RGX.search(line)ifmisnotNone:encoding=m.group(1)continueelifline.startswith('.. '):w(unicode(line,encoding))forentryincl.entries:ifentry.date:date=strptime(entry.date,'%Y-%m-%d')else:date=today()messages=[]formsglines,submsgsinentry.messages:msgstr=unicode(' '.join(l.strip()forlinmsglines),encoding)msgstr+=u'\n\n'forsubmsglinesinsubmsgs:msgstr+=' - '+unicode(' '.join(l.strip()forlinsubmsglines),encoding)msgstr+=u'\n'messages.append(msgstr)entry=(date,messages)allentries.insert(bisect_right(allentries,entry),entry)latestdate=Nonei=0fordate,messagesinreversed(allentries):iflatestdate!=date:fdate=self.format_date(date)w(u'\n%s'%fdate)w('~'*len(fdate))latestdate=dateformsginmessages:w(u'* %s'%msg)i+=1ifi>self.maxentries:breakw('')# blank lineself.w(rest_publish(self,'\n'.join(restdata)))