# copyright 2003-2012 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/>."""inline help system, using ReST file in products `wdoc` directory"""__docformat__="restructuredtext en"fromitertoolsimportchainfromos.pathimportjoinfrombisectimportbisect_rightfromdatetimeimportdatefromlogilab.common.changelogimportChangeLogfromlogilab.common.dateimportstrptime,todatefromlogilab.common.registryimportyesfromlogilab.mtconverterimportCHARSET_DECL_RGXfromcubicweb.predicatesimportmatch_form_paramsfromcubicweb.viewimportStartupViewfromcubicweb.uilibimportrest_publishfromcubicweb.webimportNotFound,action_=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)elif'appendto'insection.attrib:node=index[section.attrib['appendto']]idx=Noneelse:node,idx=None,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# fileforfpathinalltocfiles:toc=parse(fpath).getroot()forsectionintoc:node,idx=get_insertion_point(section,index)ifnodeisNone:continueifidxisNone:node.append(section)else:node.insert(idx,section)section.parent=nodebuild_toc_index(section,index)returnindexdeftitle_for_lang(node,lang):fallback_title=Nonefortitleinnode.findall('title'):title_lang=title.attrib['{http://www.w3.org/XML/1998/namespace}lang']iftitle_lang==lang:returnunicode(title.text)iftitle_lang=='en':fallback_title=unicode(title.text)returnfallback_titledefsubsections(node):return[childforchildinnodeifchild.tag=='section']# help views ##################################################################classInlineHelpView(StartupView):__select__=match_form_params('fid')__regid__='wdoc'title=_('site documentation')defcall(self):fid=self._cw.form['fid']vreg=self._cw.vregforlanginchain((self._cw.lang,vreg.property_value('ui.language')),vreg.config.available_languages()):rid='%s_%s.rst'%(fid,lang)resourcedir=vreg.config.locate_doc_file(rid)ifresourcedir:breakelse:raiseNotFoundself.tocindex=build_toc(vreg.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_for_lang(node,self._cw.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._cwparent=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._cw._(msgid))self.w(u'<a href="%s">%s</a>'%(self._cw.build_url('doc/'+node.attrib['resource']),title_for_lang(node,self._cw.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._cw.build_url('doc/'+child.attrib['resource']),title_for_lang(child,self._cw.lang)))self.subsections_links(child,False)self.w(u'</li>')self.w(u'</ul>\n')classInlineHelpImageView(StartupView):__regid__='wdocimages'__select__=match_form_params('fid')binary=Truetemplatable=Falsecontent_type='image/png'defcall(self):fid=self._cw.form['fid']forlanginchain((self._cw.lang,self._cw.vreg.property_value('ui.language')),self._cw.vreg.config.available_languages()):rid=join('images','%s_%s.png'%(fid,lang))resourcedir=self._cw.vreg.config.locate_doc_file(rid)ifresourcedir:breakelse:raiseNotFoundself.w(open(join(resourcedir,rid)).read())classChangeLogView(StartupView):__regid__='changelog'title=_('What\'s new?')maxentries=25defcall(self):rid='ChangeLog_%s'%(self._cw.lang)allentries=[]title=self._cw._(self.title)restdata=['.. -*- coding: utf-8 -*-','',title,'='*len(title),'']w=restdata.appendtoday=date.today()forfpathinself._cw.vreg.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:edate=todate(strptime(entry.date,'%Y-%m-%d'))else:edate=todaymessages=[]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=(edate,messages)allentries.insert(bisect_right(allentries,entry),entry)latestdate=Nonei=0foredate,messagesinreversed(allentries):iflatestdate!=edate:fdate=self._cw.format_date(edate)w(u'\n%s'%fdate)w('~'*len(fdate))latestdate=edateformsginmessages:w(u'* %s'%msg)i+=1ifi>self.maxentries:breakw('')# blank lineself.w(rest_publish(self,'\n'.join(restdata)))classHelpAction(action.Action):__regid__='help'__select__=yes()category='footer'order=0title=_('Help')defurl(self):returnself._cw.build_url('doc/main')classChangeLogAction(action.Action):__regid__='changelog'__select__=yes()category='footer'order=1title=ChangeLogView.titledefurl(self):returnself._cw.build_url('changelog')classAboutAction(action.Action):__regid__='about'__select__=yes()category='footer'order=2title=_('About this site')defurl(self):returnself._cw.build_url('doc/about')