reportlab: new index support
authorrgbecker
Tue, 02 Jun 2009 14:30:06 +0000
changeset 3165 cbda9e7d0ee3
parent 3164 0c60143b507e
child 3166 93e3203eab88
reportlab: new index support
src/reportlab/platypus/paragraph.py
src/reportlab/platypus/paraparser.py
src/reportlab/platypus/tableofcontents.py
--- a/src/reportlab/platypus/paragraph.py	Tue Jun 02 12:31:27 2009 +0000
+++ b/src/reportlab/platypus/paragraph.py	Tue Jun 02 14:30:06 2009 +0000
@@ -763,7 +763,8 @@
         <super> ... </super> - superscript
         <sub> ... </sub> - subscript
         <font name=fontfamily/fontname color=colorname size=float>
-        <onDraw name=callable label="a label">
+        <onDraw name=callable label="a label"/>
+        <index [name="callablecanvasattribute"] label="a label"/>
         <link>link text</link>
         attributes of links
         size/fontSize=num
--- a/src/reportlab/platypus/paraparser.py	Tue Jun 02 12:31:27 2009 +0000
+++ b/src/reportlab/platypus/paraparser.py	Tue Jun 02 14:30:06 2009 +0000
@@ -26,6 +26,8 @@
 subFraction = 0.5   # fraction of font size that a sub script should be lowered
 superFraction = 0.5 # fraction of font size that a super script should be raised
 
+DEFAULT_INDEX_NAME='_indexAdd'
+
 
 def _convnum(s, unit=1):
     if s[0] in ['+','-']:
@@ -171,6 +173,10 @@
                 'height':('height',_num),
                 'valign':('valign',_valignpc),
                 }
+_indexAttrMap = {
+                'name': ('name',None),
+                'item': ('item',None),
+                }
 
 def _addAttributeNames(m):
     K = m.keys()
@@ -496,7 +502,8 @@
 #       < sub > < /sub > - subscript
 #       <font name=fontfamily/fontname color=colorname size=float>
 #       < bullet > </bullet> - bullet text (at head of para only)
-#       <onDraw name=callable label="a label">
+#       <onDraw name=callable label="a label"/>
+#       <index [name="callablecanvasattribute"] label="a label"/>
 #       <link>link text</link>
 #           attributes of links 
 #               size/fontSize=num
@@ -883,9 +890,25 @@
         self._push(cbDefn=defn)
         self.handle_data('')
         self._pop()
-
     end_onDraw=end_seq
 
+    def start_index(self,attr):
+        attr=self.getAttributes(attr,_indexAttrMap)
+        defn = ABag()
+        if attr.has_key('item'):
+            defn.label = attr['item']
+        else:
+            self._syntax_error('<index> needs at least an item attribute')
+        if attr.has_key('name'):
+            name = attr['name']
+        else:
+            name = DEFAULT_INDEX_NAME
+        defn.name = name
+        defn.kind='index'
+        self._push(cbDefn=defn)
+        self.handle_data('')
+        self._pop()
+    end_index=end_seq
 
     #---------------------------------------------------------------
     def _push(self,**attr):
--- a/src/reportlab/platypus/tableofcontents.py	Tue Jun 02 12:31:27 2009 +0000
+++ b/src/reportlab/platypus/tableofcontents.py	Tue Jun 02 14:30:06 2009 +0000
@@ -65,14 +65,7 @@
         def add(self,x):
             if x not in self:
                 list.append(self,x)
-    
-def _getArgs(*args,**kw):
-    return args, kw
-    
-def _evalArgs(data):
-    if data[0]!='(': data = '(%s)' % data
-    return eval('_getArgs'+data)
-    
+
 def drawPageNumbers(canvas, style, pages, availWidth, availHeight, dot=' . '):
     '''
     Draws pagestr on the canvas using the given style.
@@ -105,7 +98,7 @@
     tx.setFillColor(style.textColor)
     tx.textLine(text)
     canvas.drawText(tx)
-   
+
     commaw = stringWidth(', ', style.fontName, style.fontSize)
     for p, key in pages:
         if not key:
@@ -231,8 +224,8 @@
             page, level = [ int(x) for x in label.split(',') ]
             style = self.getLevelStyle(level)
             if self.dotsMinLevel >= 0 and level >= self.dotsMinLevel:
-                dot = ' . ' 
-            else: 
+                dot = ' . '
+            else:
                 dot = ''
             drawPageNumbers(canvas, style, [(page, None)], availWidth, availHeight, dot)
         self.canv.drawTOCEntryEnd = drawTOCEntryEnd
@@ -268,7 +261,7 @@
         work to the embedded table object.
         """
         self._table.drawOn(canvas, x, y, _sW)
-        
+
 def makeTuple(x):
     if hasattr(x, '__iter__'):
         return tuple(x)
@@ -285,8 +278,8 @@
         self._lastEntries = {}
         self._flowable = None
         self.setup(**kwargs)
-        
-    def setup(self, style=None, dot=None, tableStyle=None, headers=True):
+
+    def setup(self, style=None, dot=None, tableStyle=None, headers=True, name=None):
         if style is None:
             style = ParagraphStyle(name='index',
                                         fontName='Times-Roman',
@@ -295,30 +288,30 @@
         self.tableStyle = tableStyle or defaultTableStyle
         self.dot = dot
         self.headers = headers
-    
+        if name is None:
+            from reportlab.platypus.paraparser import DEFAULT_INDEX_NAME as name
+        self.name = name
+
+    def __call__(self,canv,kind,label):
+        label = unquote(label)
+        try:
+            label = eval(label,{})
+        except (NameError, SyntaxError):
+            label = makeTuple(label)
+        key = 'idx_%s_p_%s' % (','.join(label), canv.getPageNumber())
+
+        info = canv._curr_tx_info
+        canv.bookmarkHorizontal(key, info['cur_x'], info['cur_y'] + info['leading'])
+        self.addEntry(label, canv.getPageNumber(), key)
+
     def getCanvasMaker(self, canvasmaker=canvas.Canvas):
-        def cb(canv,kind,label):
-            label = unquote(label)
-            try:
-                args, kwargs = _evalArgs(label)
-                if kwargs:
-                    raise SyntaxError()
-            except (NameError, SyntaxError):
-                pass
-            else:
-                label = args
-            key = 'idx_%s_p_%s' % (','.join(label), canv.getPageNumber())
-            
-            info = canv._curr_tx_info
-            canv.bookmarkHorizontal(key, info['cur_x'], info['cur_y'] + info['leading'])
-            self.addEntry(label, canv.getPageNumber(), key)
-        
+
         def newcanvasmaker(*args, **kwargs):
             from reportlab.pdfgen import canvas
             c = canvasmaker(*args, **kwargs)
-            c._indexAdd = cb
+            setattr(c,self.name,self)
             return c
-        
+
         return newcanvasmaker
 
     def isIndexing(self):
@@ -363,7 +356,7 @@
                 return self._entries.items()
             return dummy
         return self._lastEntries.items()
-        
+
     def _build(self,availWidth,availHeight):
         _tempEntries = self._getlastEntries()
         _tempEntries.sort(cmp=lambda a,b: cmp([x.upper() for x in a[0]], [x.upper() for x in b[0]]))