Back to index

moin  1.9.0~rc2
Navigation.py
Go to the documentation of this file.
00001 # -*- coding: iso-8859-1 -*-
00002 """
00003     MoinMoin - Navigation Macro
00004 
00005     @copyright: 2003 Juergen Hermann <jh@web.de>
00006                 2008 MoinMoin:RadomirDopieralski
00007     @license: GNU GPL, see COPYING for details.
00008 """
00009 
00010 import re
00011 from MoinMoin.Page import Page
00012 from MoinMoin import wikiutil
00013 
00014 Dependencies = ["namespace"]
00015 
00016 # helpers
00017 #!!! refactor these to an util module?
00018 def _getParent(pagename):
00019     """ Return parent of pagename.
00020     """
00021     pos = pagename.rfind('/')
00022     if pos >= 0:
00023         return pagename[:pos]
00024     return None
00025 
00026 
00027 def _getPages(request, filter_regex=None):
00028     """ Return a (filtered) list of pages names.
00029     """
00030     filterfn = None
00031     if filter_regex:
00032         filterfn = re.compile(filter_regex).match
00033     pages = request.rootpage.getPageList(filter=filterfn)
00034     pages.sort()
00035     return pages
00036 
00037 
00038 def _getLinks(request, pagename, filter_regex=None):
00039     """ Return pagename for up, first, prev, next, last; each can be None.
00040     """
00041     pos, first, prev, next, last = 0, None, None, None, None
00042 
00043     all_pages = _getPages(request, filter_regex)
00044     size = len(all_pages)
00045 
00046     if all_pages:
00047         try:
00048             pos = all_pages.index(pagename)
00049         except ValueError:
00050             # this should never happen in theory, but let's be sure
00051             pass
00052         else:
00053             if pos > 0:
00054                 first = all_pages[0]
00055                 prev = all_pages[pos-1]
00056             if pos+1 < len(all_pages):
00057                 next = all_pages[pos+1]
00058                 last = all_pages[-1]
00059 
00060     return pos, size, (first, prev, next, last)
00061 
00062 
00063 class Navigation:
00064     """ Dispatcher class implementing the navigation schemes.
00065     """
00066 
00067     # querystring for slideshow links
00068     PROJECTION = {'action': 'print', 'media': 'projection', }
00069 
00070     def __init__(self, macro, scheme, depth):
00071         """ Prepare common values used during processing.
00072         """
00073         self.macro = macro
00074         self.scheme = scheme
00075         self.depth = depth
00076         self._ = self.macro.request.getText
00077 
00078         self.pagename = self.macro.formatter.page.page_name
00079         self.print_mode = self.macro.request.action == 'print'
00080         self.media = self.macro.request.values.get('media')
00081         self.querystr = self.print_mode and self.PROJECTION or {}
00082 
00083 
00084     def dispatch(self):
00085         """ Return None if in plain print mode (no navigational
00086             elements in printouts), else the proper HTML code.
00087         """
00088         if self.print_mode and self.media != 'projection':
00089             return None
00090 
00091         return getattr(self, 'do_%s' % self.scheme, self.badscheme)()
00092 
00093 
00094     def badscheme(self):
00095         """ Bad scheme argument.
00096         """
00097         _ = self._
00098         return (self.macro.formatter.sysmsg(1) +
00099                 self.macro.formatter.text(
00100             _("Unsupported navigation scheme '%(scheme)s'!") %
00101             {'scheme': self.scheme}) +
00102                 self.macro.formatter.sysmsg(0))
00103 
00104 
00105     def do_children(self):
00106         """ Navigate to subpages from a parent page.
00107         """
00108         # delegate to siblings code, setting the parent explicitely
00109         return self.do_siblings(root=self.pagename)
00110 
00111 
00112     def do_siblings(self, root=None):
00113         """ Navigate from a subpage to its siblings.
00114         """
00115         _ = self._
00116         request = self.macro.request
00117         # get parent page name
00118         parent = root or _getParent(self.pagename)
00119         if not parent:
00120             return (self.macro.formatter.sysmsg(1) +
00121                     self.macro.formatter.text(_('No parent page found!'))+
00122                     self.macro.formatter.sysmsg(0))
00123 
00124         # iterate over children, adding links to all of them
00125         result = []
00126         children = _getPages(request, '^%s/' % re.escape(parent))
00127         for child in children:
00128             # display short page name, leaving out the parent path
00129             # (and make sure the name doesn't get wrapped)
00130             shortname = child[len(parent):]
00131 
00132             # possibly limit depth
00133             if self.depth and shortname.count('/') > self.depth:
00134                 continue
00135 
00136             if child == self.pagename:
00137                 # do not link to focus
00138                 result.append(self.macro.formatter.text(shortname))
00139             else:
00140                 # link to sibling / child
00141                 result.append(Page(request, child).link_to(request, text=shortname, querystr=self.querystr))
00142             result.append(' &nbsp; ')
00143 
00144         return ''.join(result)
00145 
00146 
00147     def do_slideshow(self, focus=None):
00148         """ Slideshow master page links.
00149 
00150             If `focus` is set, it is the name of a slide page; these only
00151             get the mode toggle and edit links.
00152         """
00153         _ = self._
00154         curpage = focus or self.pagename
00155         result = []
00156         request = self.macro.request
00157         pg = Page(request, curpage)
00158         if self.print_mode:
00159             # projection mode
00160             label = _('Wiki')
00161             toggle = {}
00162             result.append(pg.link_to(request, text=_('Edit'), querystr={'action': 'edit'}))
00163             result.append(' &nbsp; ')
00164         else:
00165             # wiki mode
00166             label = _('Slideshow')
00167             toggle = self.PROJECTION
00168 
00169         # add mode toggle link
00170         result.append(pg.link_to(request, text=label, querystr=toggle))
00171 
00172         # leave out the following on slide pages
00173         if focus is None:
00174             children = _getPages(request, '^%s/' % re.escape(self.pagename))
00175             if children:
00176                 # add link to first child if one exists
00177                 result.append(' &nbsp; ')
00178                 result.append(Page(request, children[0]).link_to(request, text=_('Start'), querystr=self.querystr))
00179 
00180         return ''.join(result)
00181 
00182 
00183     def do_slides(self, root=None):
00184         """ Navigate within a slide show.
00185         """
00186         _ = self._
00187         request = self.macro.request
00188         parent = root or _getParent(self.pagename)
00189         if not parent:
00190             return (self.macro.formatter.sysmsg(1) +
00191                     self.macro.formatter.text(_('No parent page found!')) +
00192                     self.macro.formatter.sysmsg(0))
00193 
00194         # prepare link generation
00195         result = []
00196         labels = ['^', '|<', '<<', '>>', '>|']
00197         filter_regex = '^%s/' % re.escape(parent)
00198         pos, size, links = _getLinks(request, self.pagename, filter_regex)
00199         pos += 1
00200         links = zip(labels, (parent, ) + links)
00201 
00202         # generate links to neighborhood
00203         for label, name in links:
00204             result.append(' ')
00205             if name:
00206                 # active link
00207                 result.append(Page(request, name).link_to(request, text=label, querystr=self.querystr))
00208             else:
00209                 # ghosted link
00210                 result.append(self.macro.formatter.text(label))
00211             result.append(' ')
00212 
00213             # position indicator in the middle
00214             if label == labels[2]:
00215                 result.append(_('Slide %(pos)d of %(size)d') % {'pos': pos, 'size': size})
00216 
00217         return self.do_slideshow(focus=self.pagename) + ''.join(result)
00218 
00219 
00220 def macro_Navigation(macro,
00221                     scheme=wikiutil.required_arg((u'children', u'siblings',
00222                                                   u'slideshow', u'slides')),
00223                     depth=0):
00224     # get HTML code with the links
00225     navi = Navigation(macro, scheme, depth).dispatch()
00226 
00227     if navi:
00228         # return links packed into a table
00229         return u'<table class="navigation"><tr><td>%s</td></tr></table>' % navi
00230 
00231     # navigation disabled in plain print mode
00232     return u''
00233