src/reportlab/platypus/tableofcontents.py
author robin
Thu, 24 Oct 2019 16:07:15 +0100
changeset 4551 d357e2acc856
parent 4528 e09377955af8
child 4709 1dcf7b3f7127
permissions -rw-r--r--
improve usage of eval/exec; version --> 3.5.32
Ignore whitespace changes - Everywhere: Within whitespace: At end of lines:
4330
617ffa6bbdc8 changes for release 3.4.0
robin <robin@reportlab.com>
parents: 4252
diff changeset
     1
#Copyright ReportLab Europe Ltd. 2000-2017
817
8c3a399effda License text changes
rgbecker
parents: 754
diff changeset
     2
#see license.txt for license details
4528
e09377955af8 try to eliminate changed bitbucket.org references
robin
parents: 4370
diff changeset
     3
#history https://hg.reportlab.com/hg-public/reportlab/log/tip/src/reportlab/platypus/tableofcontents.py
3032
22224b1b4d24 New docstrings mainly for module titles
damian
parents: 2964
diff changeset
     4
4551
d357e2acc856 improve usage of eval/exec; version --> 3.5.32
robin
parents: 4528
diff changeset
     5
__version__='3.5.32'
3032
22224b1b4d24 New docstrings mainly for module titles
damian
parents: 2964
diff changeset
     6
__doc__="""Experimental class to generate Tables of Contents easily
22224b1b4d24 New docstrings mainly for module titles
damian
parents: 2964
diff changeset
     7
1440
243d35446390 Removed 0 from multiBuild stuff prior to further changes;
andy_robinson
parents: 817
diff changeset
     8
This module defines a single TableOfContents() class that can be used to
754
ac7d1e99bd3e Replaced trailing digit file.
dinu_gherman
parents:
diff changeset
     9
create automatically a table of tontents for Platypus documents like
ac7d1e99bd3e Replaced trailing digit file.
dinu_gherman
parents:
diff changeset
    10
this:
ac7d1e99bd3e Replaced trailing digit file.
dinu_gherman
parents:
diff changeset
    11
ac7d1e99bd3e Replaced trailing digit file.
dinu_gherman
parents:
diff changeset
    12
    story = []
1440
243d35446390 Removed 0 from multiBuild stuff prior to further changes;
andy_robinson
parents: 817
diff changeset
    13
    toc = TableOfContents()
754
ac7d1e99bd3e Replaced trailing digit file.
dinu_gherman
parents:
diff changeset
    14
    story.append(toc)
ac7d1e99bd3e Replaced trailing digit file.
dinu_gherman
parents:
diff changeset
    15
    # some heading paragraphs here...
ac7d1e99bd3e Replaced trailing digit file.
dinu_gherman
parents:
diff changeset
    16
    doc = MyTemplate(path)
1440
243d35446390 Removed 0 from multiBuild stuff prior to further changes;
andy_robinson
parents: 817
diff changeset
    17
    doc.multiBuild(story)
754
ac7d1e99bd3e Replaced trailing digit file.
dinu_gherman
parents:
diff changeset
    18
ac7d1e99bd3e Replaced trailing digit file.
dinu_gherman
parents:
diff changeset
    19
The data needed to create the table is a list of (level, text, pageNum)
ac7d1e99bd3e Replaced trailing digit file.
dinu_gherman
parents:
diff changeset
    20
triplets, plus some paragraph styles for each level of the table itself.
ac7d1e99bd3e Replaced trailing digit file.
dinu_gherman
parents:
diff changeset
    21
The triplets will usually be created in a document template's method
1440
243d35446390 Removed 0 from multiBuild stuff prior to further changes;
andy_robinson
parents: 817
diff changeset
    22
like afterFlowable(), making notification calls using the notify()
754
ac7d1e99bd3e Replaced trailing digit file.
dinu_gherman
parents:
diff changeset
    23
method with appropriate data like this:
ac7d1e99bd3e Replaced trailing digit file.
dinu_gherman
parents:
diff changeset
    24
ac7d1e99bd3e Replaced trailing digit file.
dinu_gherman
parents:
diff changeset
    25
    (level, text, pageNum) = ...
1440
243d35446390 Removed 0 from multiBuild stuff prior to further changes;
andy_robinson
parents: 817
diff changeset
    26
    self.notify('TOCEntry', (level, text, pageNum))
754
ac7d1e99bd3e Replaced trailing digit file.
dinu_gherman
parents:
diff changeset
    27
3060
eeedb611fa67 Added feature to have clickable TableOfContents entries (ToDo 978).
jonas
parents: 3049
diff changeset
    28
Optionally the list can contain four items in which case the last item
eeedb611fa67 Added feature to have clickable TableOfContents entries (ToDo 978).
jonas
parents: 3049
diff changeset
    29
is a destination key which the entry should point to. A bookmark
eeedb611fa67 Added feature to have clickable TableOfContents entries (ToDo 978).
jonas
parents: 3049
diff changeset
    30
with this key needs to be created first like this:
eeedb611fa67 Added feature to have clickable TableOfContents entries (ToDo 978).
jonas
parents: 3049
diff changeset
    31
eeedb611fa67 Added feature to have clickable TableOfContents entries (ToDo 978).
jonas
parents: 3049
diff changeset
    32
    key = 'ch%s' % self.seq.nextf('chapter')
eeedb611fa67 Added feature to have clickable TableOfContents entries (ToDo 978).
jonas
parents: 3049
diff changeset
    33
    self.canv.bookmarkPage(key)
eeedb611fa67 Added feature to have clickable TableOfContents entries (ToDo 978).
jonas
parents: 3049
diff changeset
    34
    self.notify('TOCEntry', (level, text, pageNum, key))
eeedb611fa67 Added feature to have clickable TableOfContents entries (ToDo 978).
jonas
parents: 3049
diff changeset
    35
754
ac7d1e99bd3e Replaced trailing digit file.
dinu_gherman
parents:
diff changeset
    36
As the table of contents need at least two passes over the Platypus
4180
2ee5e4cd860f add formatter and argument processing to tabelOfContents; version-->3.1.52
robin
parents: 4178
diff changeset
    37
story which is why the multiBuild() method must be called.
754
ac7d1e99bd3e Replaced trailing digit file.
dinu_gherman
parents:
diff changeset
    38
ac7d1e99bd3e Replaced trailing digit file.
dinu_gherman
parents:
diff changeset
    39
The level<NUMBER>ParaStyle variables are the paragraph styles used
ac7d1e99bd3e Replaced trailing digit file.
dinu_gherman
parents:
diff changeset
    40
to format the entries in the table of contents. Their indentation
ac7d1e99bd3e Replaced trailing digit file.
dinu_gherman
parents:
diff changeset
    41
is calculated like this: each entry starts at a multiple of some
ac7d1e99bd3e Replaced trailing digit file.
dinu_gherman
parents:
diff changeset
    42
constant named delta. If one entry spans more than one line, all
ac7d1e99bd3e Replaced trailing digit file.
dinu_gherman
parents:
diff changeset
    43
lines after the first are indented by the same constant named
1683
7fa753e4420a Removed all trailing whitespace
andy_robinson
parents: 1559
diff changeset
    44
epsilon.
754
ac7d1e99bd3e Replaced trailing digit file.
dinu_gherman
parents:
diff changeset
    45
"""
3032
22224b1b4d24 New docstrings mainly for module titles
damian
parents: 2964
diff changeset
    46
754
ac7d1e99bd3e Replaced trailing digit file.
dinu_gherman
parents:
diff changeset
    47
from reportlab.lib import enums
ac7d1e99bd3e Replaced trailing digit file.
dinu_gherman
parents:
diff changeset
    48
from reportlab.lib.units import cm
4338
6223e7fa13f6 reproducibility fixes; version --> 3.4.3
robin <robin@reportlab.com>
parents: 4330
diff changeset
    49
from reportlab.lib.utils import commasplit, escapeOnce, encode_label, decode_label, strTypes, asUnicode, asNative
3368
afa025c34493 reportlab: new base font mechanism more fully applied
rgbecker
parents: 3349
diff changeset
    50
from reportlab.lib.styles import ParagraphStyle, _baseFontName
4551
d357e2acc856 improve usage of eval/exec; version --> 3.5.32
robin
parents: 4528
diff changeset
    51
from reportlab.lib import sequencer as rl_sequencer
754
ac7d1e99bd3e Replaced trailing digit file.
dinu_gherman
parents:
diff changeset
    52
from reportlab.platypus.paragraph import Paragraph
1440
243d35446390 Removed 0 from multiBuild stuff prior to further changes;
andy_robinson
parents: 817
diff changeset
    53
from reportlab.platypus.doctemplate import IndexingFlowable
754
ac7d1e99bd3e Replaced trailing digit file.
dinu_gherman
parents:
diff changeset
    54
from reportlab.platypus.tables import TableStyle, Table
3111
86a3158c50bd reportlab: improved support for onDraw and SimpleIndex
rgbecker
parents: 3060
diff changeset
    55
from reportlab.platypus.flowables import Spacer, Flowable
3049
6e9ca03c4dbe Added dotted lines to TableOfContents.
jonas
parents: 3045
diff changeset
    56
from reportlab.pdfbase.pdfmetrics import stringWidth
3162
77afde998aa9 Made Index entries clickable.
jonas
parents: 3146
diff changeset
    57
from reportlab.pdfgen import canvas
4178
b2c73e04465c fix indexing for accented stuff contributed by alexandrel_sgi @ bitbucket, version-->3.1.50
robin
parents: 4121
diff changeset
    58
import unicodedata
4551
d357e2acc856 improve usage of eval/exec; version --> 3.5.32
robin
parents: 4528
diff changeset
    59
from ast import literal_eval
3162
77afde998aa9 Made Index entries clickable.
jonas
parents: 3146
diff changeset
    60
77afde998aa9 Made Index entries clickable.
jonas
parents: 3146
diff changeset
    61
def unquote(txt):
3170
91786d2240d0 Using base 64 encoding to make sure sgmllib does not mess with the whitespace in the attribute.
jonas
parents: 3167
diff changeset
    62
    from xml.sax.saxutils import unescape
3162
77afde998aa9 Made Index entries clickable.
jonas
parents: 3146
diff changeset
    63
    return unescape(txt, {"&apos;": "'", "&quot;": '"'})
77afde998aa9 Made Index entries clickable.
jonas
parents: 3146
diff changeset
    64
3111
86a3158c50bd reportlab: improved support for onDraw and SimpleIndex
rgbecker
parents: 3060
diff changeset
    65
try:
86a3158c50bd reportlab: improved support for onDraw and SimpleIndex
rgbecker
parents: 3060
diff changeset
    66
    set
86a3158c50bd reportlab: improved support for onDraw and SimpleIndex
rgbecker
parents: 3060
diff changeset
    67
except:
86a3158c50bd reportlab: improved support for onDraw and SimpleIndex
rgbecker
parents: 3060
diff changeset
    68
    class set(list):
86a3158c50bd reportlab: improved support for onDraw and SimpleIndex
rgbecker
parents: 3060
diff changeset
    69
        def add(self,x):
86a3158c50bd reportlab: improved support for onDraw and SimpleIndex
rgbecker
parents: 3060
diff changeset
    70
            if x not in self:
86a3158c50bd reportlab: improved support for onDraw and SimpleIndex
rgbecker
parents: 3060
diff changeset
    71
                list.append(self,x)
3165
cbda9e7d0ee3 reportlab: new index support
rgbecker
parents: 3164
diff changeset
    72
4180
2ee5e4cd860f add formatter and argument processing to tabelOfContents; version-->3.1.52
robin
parents: 4178
diff changeset
    73
def drawPageNumbers(canvas, style, pages, availWidth, availHeight, dot=' . ', formatter=None):
3135
3a2a8a52c1c1 reportlab.platypus: Fixes for SimpleIndex and TableOfContents.
jonas
parents: 3111
diff changeset
    74
    '''
3136
3a4e339ebac8 platypus.tableofcontents: allow more flexibility for drawing dots in Index and TableOfContents. Set default for Index back to none.
jonas
parents: 3135
diff changeset
    75
    Draws pagestr on the canvas using the given style.
3a4e339ebac8 platypus.tableofcontents: allow more flexibility for drawing dots in Index and TableOfContents. Set default for Index back to none.
jonas
parents: 3135
diff changeset
    76
    If dot is None, pagestr is drawn at the current position in the canvas.
3a4e339ebac8 platypus.tableofcontents: allow more flexibility for drawing dots in Index and TableOfContents. Set default for Index back to none.
jonas
parents: 3135
diff changeset
    77
    If dot is a string, pagestr is drawn right-aligned. If the string is not empty,
3a4e339ebac8 platypus.tableofcontents: allow more flexibility for drawing dots in Index and TableOfContents. Set default for Index back to none.
jonas
parents: 3135
diff changeset
    78
    the gap is filled with it.
3135
3a2a8a52c1c1 reportlab.platypus: Fixes for SimpleIndex and TableOfContents.
jonas
parents: 3111
diff changeset
    79
    '''
3166
93e3203eab88 Removed some post python 2.3 constructs.
jonas
parents: 3165
diff changeset
    80
    pagestr = ', '.join([str(p) for p, _ in pages])
3135
3a2a8a52c1c1 reportlab.platypus: Fixes for SimpleIndex and TableOfContents.
jonas
parents: 3111
diff changeset
    81
    x, y = canvas._curr_tx_info['cur_x'], canvas._curr_tx_info['cur_y']
4121
3b9e6fa286ad tableofcontents.py, doctemplate.py: fix indexing page number ordering bug found by Greg Jones bitbucket issue #40
robin
parents: 4058
diff changeset
    82
3348
d44de6313b58 workaround for widow/orphan control in simpleindex
andy
parents: 3327
diff changeset
    83
    fontSize = style.fontSize
d44de6313b58 workaround for widow/orphan control in simpleindex
andy
parents: 3327
diff changeset
    84
    pagestrw = stringWidth(pagestr, style.fontName, fontSize)
4121
3b9e6fa286ad tableofcontents.py, doctemplate.py: fix indexing page number ordering bug found by Greg Jones bitbucket issue #40
robin
parents: 4058
diff changeset
    85
3348
d44de6313b58 workaround for widow/orphan control in simpleindex
andy
parents: 3327
diff changeset
    86
    #if it's too long to fit, we need to shrink to fit in 10% increments.
d44de6313b58 workaround for widow/orphan control in simpleindex
andy
parents: 3327
diff changeset
    87
    #it would be very hard to output multiline entries.
d44de6313b58 workaround for widow/orphan control in simpleindex
andy
parents: 3327
diff changeset
    88
    #however, we impose a minimum size of 1 point as we don't want an
d44de6313b58 workaround for widow/orphan control in simpleindex
andy
parents: 3327
diff changeset
    89
    #infinite loop.   Ultimately we should allow a TOC entry to spill
d44de6313b58 workaround for widow/orphan control in simpleindex
andy
parents: 3327
diff changeset
    90
    #over onto a second line if needed.
d44de6313b58 workaround for widow/orphan control in simpleindex
andy
parents: 3327
diff changeset
    91
    freeWidth = availWidth-x
d44de6313b58 workaround for widow/orphan control in simpleindex
andy
parents: 3327
diff changeset
    92
    while pagestrw > freeWidth and fontSize >= 1.0:
d44de6313b58 workaround for widow/orphan control in simpleindex
andy
parents: 3327
diff changeset
    93
        fontSize = 0.9 * fontSize
d44de6313b58 workaround for widow/orphan control in simpleindex
andy
parents: 3327
diff changeset
    94
        pagestrw = stringWidth(pagestr, style.fontName, fontSize)
4121
3b9e6fa286ad tableofcontents.py, doctemplate.py: fix indexing page number ordering bug found by Greg Jones bitbucket issue #40
robin
parents: 4058
diff changeset
    95
3b9e6fa286ad tableofcontents.py, doctemplate.py: fix indexing page number ordering bug found by Greg Jones bitbucket issue #40
robin
parents: 4058
diff changeset
    96
4058
a97a88afcfe8 tableofcontents.py: try and allow for differecnt dot kinds
robin
parents: 3853
diff changeset
    97
    if isinstance(dot, strTypes):
3136
3a4e339ebac8 platypus.tableofcontents: allow more flexibility for drawing dots in Index and TableOfContents. Set default for Index back to none.
jonas
parents: 3135
diff changeset
    98
        if dot:
3348
d44de6313b58 workaround for widow/orphan control in simpleindex
andy
parents: 3327
diff changeset
    99
            dotw = stringWidth(dot, style.fontName, fontSize)
3136
3a4e339ebac8 platypus.tableofcontents: allow more flexibility for drawing dots in Index and TableOfContents. Set default for Index back to none.
jonas
parents: 3135
diff changeset
   100
            dotsn = int((availWidth-x-pagestrw)/dotw)
3a4e339ebac8 platypus.tableofcontents: allow more flexibility for drawing dots in Index and TableOfContents. Set default for Index back to none.
jonas
parents: 3135
diff changeset
   101
        else:
3a4e339ebac8 platypus.tableofcontents: allow more flexibility for drawing dots in Index and TableOfContents. Set default for Index back to none.
jonas
parents: 3135
diff changeset
   102
            dotsn = dotw = 0
3a4e339ebac8 platypus.tableofcontents: allow more flexibility for drawing dots in Index and TableOfContents. Set default for Index back to none.
jonas
parents: 3135
diff changeset
   103
        text = '%s%s' % (dotsn * dot, pagestr)
3162
77afde998aa9 Made Index entries clickable.
jonas
parents: 3146
diff changeset
   104
        newx = availWidth - dotsn*dotw - pagestrw
77afde998aa9 Made Index entries clickable.
jonas
parents: 3146
diff changeset
   105
        pagex = availWidth - pagestrw
3136
3a4e339ebac8 platypus.tableofcontents: allow more flexibility for drawing dots in Index and TableOfContents. Set default for Index back to none.
jonas
parents: 3135
diff changeset
   106
    elif dot is None:
3143
c704253bc72a Added support for multi-level and alphabetical indexes.
jonas
parents: 3141
diff changeset
   107
        text = ',  ' + pagestr
3136
3a4e339ebac8 platypus.tableofcontents: allow more flexibility for drawing dots in Index and TableOfContents. Set default for Index back to none.
jonas
parents: 3135
diff changeset
   108
        newx = x
3162
77afde998aa9 Made Index entries clickable.
jonas
parents: 3146
diff changeset
   109
        pagex = newx
3135
3a2a8a52c1c1 reportlab.platypus: Fixes for SimpleIndex and TableOfContents.
jonas
parents: 3111
diff changeset
   110
    else:
3136
3a4e339ebac8 platypus.tableofcontents: allow more flexibility for drawing dots in Index and TableOfContents. Set default for Index back to none.
jonas
parents: 3135
diff changeset
   111
        raise TypeError('Argument dot should either be None or an instance of basestring.')
3135
3a2a8a52c1c1 reportlab.platypus: Fixes for SimpleIndex and TableOfContents.
jonas
parents: 3111
diff changeset
   112
3136
3a4e339ebac8 platypus.tableofcontents: allow more flexibility for drawing dots in Index and TableOfContents. Set default for Index back to none.
jonas
parents: 3135
diff changeset
   113
    tx = canvas.beginText(newx, y)
3348
d44de6313b58 workaround for widow/orphan control in simpleindex
andy
parents: 3327
diff changeset
   114
    tx.setFont(style.fontName, fontSize)
3135
3a2a8a52c1c1 reportlab.platypus: Fixes for SimpleIndex and TableOfContents.
jonas
parents: 3111
diff changeset
   115
    tx.setFillColor(style.textColor)
3a2a8a52c1c1 reportlab.platypus: Fixes for SimpleIndex and TableOfContents.
jonas
parents: 3111
diff changeset
   116
    tx.textLine(text)
3a2a8a52c1c1 reportlab.platypus: Fixes for SimpleIndex and TableOfContents.
jonas
parents: 3111
diff changeset
   117
    canvas.drawText(tx)
3165
cbda9e7d0ee3 reportlab: new index support
rgbecker
parents: 3164
diff changeset
   118
3348
d44de6313b58 workaround for widow/orphan control in simpleindex
andy
parents: 3327
diff changeset
   119
    commaw = stringWidth(', ', style.fontName, fontSize)
3162
77afde998aa9 Made Index entries clickable.
jonas
parents: 3146
diff changeset
   120
    for p, key in pages:
77afde998aa9 Made Index entries clickable.
jonas
parents: 3146
diff changeset
   121
        if not key:
77afde998aa9 Made Index entries clickable.
jonas
parents: 3146
diff changeset
   122
            continue
3348
d44de6313b58 workaround for widow/orphan control in simpleindex
andy
parents: 3327
diff changeset
   123
        w = stringWidth(str(p), style.fontName, fontSize)
3162
77afde998aa9 Made Index entries clickable.
jonas
parents: 3146
diff changeset
   124
        canvas.linkRect('', key, (pagex, y, pagex+w, y+style.leading), relative=1)
77afde998aa9 Made Index entries clickable.
jonas
parents: 3146
diff changeset
   125
        pagex += w + commaw
3135
3a2a8a52c1c1 reportlab.platypus: Fixes for SimpleIndex and TableOfContents.
jonas
parents: 3111
diff changeset
   126
754
ac7d1e99bd3e Replaced trailing digit file.
dinu_gherman
parents:
diff changeset
   127
# Default paragraph styles for tables of contents.
ac7d1e99bd3e Replaced trailing digit file.
dinu_gherman
parents:
diff changeset
   128
# (This could also be generated automatically or even
ac7d1e99bd3e Replaced trailing digit file.
dinu_gherman
parents:
diff changeset
   129
# on-demand if it is not known how many levels the
ac7d1e99bd3e Replaced trailing digit file.
dinu_gherman
parents:
diff changeset
   130
# TOC will finally need to display...)
ac7d1e99bd3e Replaced trailing digit file.
dinu_gherman
parents:
diff changeset
   131
ac7d1e99bd3e Replaced trailing digit file.
dinu_gherman
parents:
diff changeset
   132
delta = 1*cm
ac7d1e99bd3e Replaced trailing digit file.
dinu_gherman
parents:
diff changeset
   133
epsilon = 0.5*cm
ac7d1e99bd3e Replaced trailing digit file.
dinu_gherman
parents:
diff changeset
   134
3146
4732d02eae94 Added support for an unlimited number of TOC levels with default styles.
jonas
parents: 3145
diff changeset
   135
defaultLevelStyles = [
4732d02eae94 Added support for an unlimited number of TOC levels with default styles.
jonas
parents: 3145
diff changeset
   136
    ParagraphStyle(
4732d02eae94 Added support for an unlimited number of TOC levels with default styles.
jonas
parents: 3145
diff changeset
   137
        name='Level 0',
3368
afa025c34493 reportlab: new base font mechanism more fully applied
rgbecker
parents: 3349
diff changeset
   138
        fontName=_baseFontName,
3146
4732d02eae94 Added support for an unlimited number of TOC levels with default styles.
jonas
parents: 3145
diff changeset
   139
        fontSize=10,
4732d02eae94 Added support for an unlimited number of TOC levels with default styles.
jonas
parents: 3145
diff changeset
   140
        leading=11,
4732d02eae94 Added support for an unlimited number of TOC levels with default styles.
jonas
parents: 3145
diff changeset
   141
        firstLineIndent = 0,
4732d02eae94 Added support for an unlimited number of TOC levels with default styles.
jonas
parents: 3145
diff changeset
   142
        leftIndent = epsilon)]
754
ac7d1e99bd3e Replaced trailing digit file.
dinu_gherman
parents:
diff changeset
   143
ac7d1e99bd3e Replaced trailing digit file.
dinu_gherman
parents:
diff changeset
   144
defaultTableStyle = \
3135
3a2a8a52c1c1 reportlab.platypus: Fixes for SimpleIndex and TableOfContents.
jonas
parents: 3111
diff changeset
   145
    TableStyle([
3a2a8a52c1c1 reportlab.platypus: Fixes for SimpleIndex and TableOfContents.
jonas
parents: 3111
diff changeset
   146
        ('VALIGN', (0,0), (-1,-1), 'TOP'),
3a2a8a52c1c1 reportlab.platypus: Fixes for SimpleIndex and TableOfContents.
jonas
parents: 3111
diff changeset
   147
        ('RIGHTPADDING', (0,0), (-1,-1), 0),
3a2a8a52c1c1 reportlab.platypus: Fixes for SimpleIndex and TableOfContents.
jonas
parents: 3111
diff changeset
   148
        ('LEFTPADDING', (0,0), (-1,-1), 0),
3a2a8a52c1c1 reportlab.platypus: Fixes for SimpleIndex and TableOfContents.
jonas
parents: 3111
diff changeset
   149
    ])
754
ac7d1e99bd3e Replaced trailing digit file.
dinu_gherman
parents:
diff changeset
   150
1440
243d35446390 Removed 0 from multiBuild stuff prior to further changes;
andy_robinson
parents: 817
diff changeset
   151
class TableOfContents(IndexingFlowable):
754
ac7d1e99bd3e Replaced trailing digit file.
dinu_gherman
parents:
diff changeset
   152
    """This creates a formatted table of contents.
ac7d1e99bd3e Replaced trailing digit file.
dinu_gherman
parents:
diff changeset
   153
ac7d1e99bd3e Replaced trailing digit file.
dinu_gherman
parents:
diff changeset
   154
    It presumes a correct block of data is passed in.
ac7d1e99bd3e Replaced trailing digit file.
dinu_gherman
parents:
diff changeset
   155
    The data block contains a list of (level, text, pageNumber)
ac7d1e99bd3e Replaced trailing digit file.
dinu_gherman
parents:
diff changeset
   156
    triplets.  You can supply a paragraph style for each level
ac7d1e99bd3e Replaced trailing digit file.
dinu_gherman
parents:
diff changeset
   157
    (starting at zero).
3049
6e9ca03c4dbe Added dotted lines to TableOfContents.
jonas
parents: 3045
diff changeset
   158
    Set dotsMinLevel to determine from which level on a line of
6e9ca03c4dbe Added dotted lines to TableOfContents.
jonas
parents: 3045
diff changeset
   159
    dots should be drawn between the text and the page number.
6e9ca03c4dbe Added dotted lines to TableOfContents.
jonas
parents: 3045
diff changeset
   160
    If dotsMinLevel is set to a negative value, no dotted lines are drawn.
754
ac7d1e99bd3e Replaced trailing digit file.
dinu_gherman
parents:
diff changeset
   161
    """
ac7d1e99bd3e Replaced trailing digit file.
dinu_gherman
parents:
diff changeset
   162
4180
2ee5e4cd860f add formatter and argument processing to tabelOfContents; version-->3.1.52
robin
parents: 4178
diff changeset
   163
    def __init__(self,**kwds):
4369
46b44c48cdc0 fix bug in TableOfContents.__init__ reported by danilovmy @ bitbucket
robin <robin@reportlab.com>
parents: 4339
diff changeset
   164
        self.rightColumnWidth = kwds.pop('rightColumnWidth',72)
46b44c48cdc0 fix bug in TableOfContents.__init__ reported by danilovmy @ bitbucket
robin <robin@reportlab.com>
parents: 4339
diff changeset
   165
        self.levelStyles = kwds.pop('levelStyles',defaultLevelStyles)
46b44c48cdc0 fix bug in TableOfContents.__init__ reported by danilovmy @ bitbucket
robin <robin@reportlab.com>
parents: 4339
diff changeset
   166
        self.tableStyle = kwds.pop('tableStyle',defaultTableStyle)
46b44c48cdc0 fix bug in TableOfContents.__init__ reported by danilovmy @ bitbucket
robin <robin@reportlab.com>
parents: 4339
diff changeset
   167
        self.dotsMinLevel = kwds.pop('dotsMinLevel',1)
46b44c48cdc0 fix bug in TableOfContents.__init__ reported by danilovmy @ bitbucket
robin <robin@reportlab.com>
parents: 4339
diff changeset
   168
        self.formatter = kwds.pop('formatter',None)
4180
2ee5e4cd860f add formatter and argument processing to tabelOfContents; version-->3.1.52
robin
parents: 4178
diff changeset
   169
        if kwds: raise ValueError('unexpected keyword arguments %s' % ', '.join(kwds.keys()))
754
ac7d1e99bd3e Replaced trailing digit file.
dinu_gherman
parents:
diff changeset
   170
        self._table = None
ac7d1e99bd3e Replaced trailing digit file.
dinu_gherman
parents:
diff changeset
   171
        self._entries = []
ac7d1e99bd3e Replaced trailing digit file.
dinu_gherman
parents:
diff changeset
   172
        self._lastEntries = []
ac7d1e99bd3e Replaced trailing digit file.
dinu_gherman
parents:
diff changeset
   173
ac7d1e99bd3e Replaced trailing digit file.
dinu_gherman
parents:
diff changeset
   174
    def beforeBuild(self):
ac7d1e99bd3e Replaced trailing digit file.
dinu_gherman
parents:
diff changeset
   175
        # keep track of the last run
ac7d1e99bd3e Replaced trailing digit file.
dinu_gherman
parents:
diff changeset
   176
        self._lastEntries = self._entries[:]
ac7d1e99bd3e Replaced trailing digit file.
dinu_gherman
parents:
diff changeset
   177
        self.clearEntries()
ac7d1e99bd3e Replaced trailing digit file.
dinu_gherman
parents:
diff changeset
   178
ac7d1e99bd3e Replaced trailing digit file.
dinu_gherman
parents:
diff changeset
   179
    def isIndexing(self):
ac7d1e99bd3e Replaced trailing digit file.
dinu_gherman
parents:
diff changeset
   180
        return 1
ac7d1e99bd3e Replaced trailing digit file.
dinu_gherman
parents:
diff changeset
   181
ac7d1e99bd3e Replaced trailing digit file.
dinu_gherman
parents:
diff changeset
   182
    def isSatisfied(self):
ac7d1e99bd3e Replaced trailing digit file.
dinu_gherman
parents:
diff changeset
   183
        return (self._entries == self._lastEntries)
ac7d1e99bd3e Replaced trailing digit file.
dinu_gherman
parents:
diff changeset
   184
ac7d1e99bd3e Replaced trailing digit file.
dinu_gherman
parents:
diff changeset
   185
    def notify(self, kind, stuff):
ac7d1e99bd3e Replaced trailing digit file.
dinu_gherman
parents:
diff changeset
   186
        """The notification hook called to register all kinds of events.
ac7d1e99bd3e Replaced trailing digit file.
dinu_gherman
parents:
diff changeset
   187
ac7d1e99bd3e Replaced trailing digit file.
dinu_gherman
parents:
diff changeset
   188
        Here we are interested in 'TOCEntry' events only.
ac7d1e99bd3e Replaced trailing digit file.
dinu_gherman
parents:
diff changeset
   189
        """
ac7d1e99bd3e Replaced trailing digit file.
dinu_gherman
parents:
diff changeset
   190
        if kind == 'TOCEntry':
3060
eeedb611fa67 Added feature to have clickable TableOfContents entries (ToDo 978).
jonas
parents: 3049
diff changeset
   191
            self.addEntry(*stuff)
754
ac7d1e99bd3e Replaced trailing digit file.
dinu_gherman
parents:
diff changeset
   192
ac7d1e99bd3e Replaced trailing digit file.
dinu_gherman
parents:
diff changeset
   193
    def clearEntries(self):
ac7d1e99bd3e Replaced trailing digit file.
dinu_gherman
parents:
diff changeset
   194
        self._entries = []
ac7d1e99bd3e Replaced trailing digit file.
dinu_gherman
parents:
diff changeset
   195
3146
4732d02eae94 Added support for an unlimited number of TOC levels with default styles.
jonas
parents: 3145
diff changeset
   196
    def getLevelStyle(self, n):
4732d02eae94 Added support for an unlimited number of TOC levels with default styles.
jonas
parents: 3145
diff changeset
   197
        '''Returns the style for level n, generating and caching styles on demand if not present.'''
4732d02eae94 Added support for an unlimited number of TOC levels with default styles.
jonas
parents: 3145
diff changeset
   198
        try:
4732d02eae94 Added support for an unlimited number of TOC levels with default styles.
jonas
parents: 3145
diff changeset
   199
            return self.levelStyles[n]
4732d02eae94 Added support for an unlimited number of TOC levels with default styles.
jonas
parents: 3145
diff changeset
   200
        except IndexError:
4732d02eae94 Added support for an unlimited number of TOC levels with default styles.
jonas
parents: 3145
diff changeset
   201
            prevstyle = self.getLevelStyle(n-1)
4732d02eae94 Added support for an unlimited number of TOC levels with default styles.
jonas
parents: 3145
diff changeset
   202
            self.levelStyles.append(ParagraphStyle(
4732d02eae94 Added support for an unlimited number of TOC levels with default styles.
jonas
parents: 3145
diff changeset
   203
                    name='%s-%d-indented' % (prevstyle.name, n),
4732d02eae94 Added support for an unlimited number of TOC levels with default styles.
jonas
parents: 3145
diff changeset
   204
                    parent=prevstyle,
4732d02eae94 Added support for an unlimited number of TOC levels with default styles.
jonas
parents: 3145
diff changeset
   205
                    firstLineIndent = prevstyle.firstLineIndent+delta,
4732d02eae94 Added support for an unlimited number of TOC levels with default styles.
jonas
parents: 3145
diff changeset
   206
                    leftIndent = prevstyle.leftIndent+delta))
4732d02eae94 Added support for an unlimited number of TOC levels with default styles.
jonas
parents: 3145
diff changeset
   207
            return self.levelStyles[n]
754
ac7d1e99bd3e Replaced trailing digit file.
dinu_gherman
parents:
diff changeset
   208
3060
eeedb611fa67 Added feature to have clickable TableOfContents entries (ToDo 978).
jonas
parents: 3049
diff changeset
   209
    def addEntry(self, level, text, pageNum, key=None):
754
ac7d1e99bd3e Replaced trailing digit file.
dinu_gherman
parents:
diff changeset
   210
        """Adds one entry to the table of contents.
ac7d1e99bd3e Replaced trailing digit file.
dinu_gherman
parents:
diff changeset
   211
ac7d1e99bd3e Replaced trailing digit file.
dinu_gherman
parents:
diff changeset
   212
        This allows incremental buildup by a doctemplate.
ac7d1e99bd3e Replaced trailing digit file.
dinu_gherman
parents:
diff changeset
   213
        Requires that enough styles are defined."""
ac7d1e99bd3e Replaced trailing digit file.
dinu_gherman
parents:
diff changeset
   214
ac7d1e99bd3e Replaced trailing digit file.
dinu_gherman
parents:
diff changeset
   215
        assert type(level) == type(1), "Level must be an integer"
3060
eeedb611fa67 Added feature to have clickable TableOfContents entries (ToDo 978).
jonas
parents: 3049
diff changeset
   216
        self._entries.append((level, text, pageNum, key))
754
ac7d1e99bd3e Replaced trailing digit file.
dinu_gherman
parents:
diff changeset
   217
ac7d1e99bd3e Replaced trailing digit file.
dinu_gherman
parents:
diff changeset
   218
ac7d1e99bd3e Replaced trailing digit file.
dinu_gherman
parents:
diff changeset
   219
    def addEntries(self, listOfEntries):
ac7d1e99bd3e Replaced trailing digit file.
dinu_gherman
parents:
diff changeset
   220
        """Bulk creation of entries in the table of contents.
ac7d1e99bd3e Replaced trailing digit file.
dinu_gherman
parents:
diff changeset
   221
ac7d1e99bd3e Replaced trailing digit file.
dinu_gherman
parents:
diff changeset
   222
        If you knew the titles but not the page numbers, you could
ac7d1e99bd3e Replaced trailing digit file.
dinu_gherman
parents:
diff changeset
   223
        supply them to get sensible output on the first run."""
1683
7fa753e4420a Removed all trailing whitespace
andy_robinson
parents: 1559
diff changeset
   224
3060
eeedb611fa67 Added feature to have clickable TableOfContents entries (ToDo 978).
jonas
parents: 3049
diff changeset
   225
        for entryargs in listOfEntries:
eeedb611fa67 Added feature to have clickable TableOfContents entries (ToDo 978).
jonas
parents: 3049
diff changeset
   226
            self.addEntry(*entryargs)
754
ac7d1e99bd3e Replaced trailing digit file.
dinu_gherman
parents:
diff changeset
   227
ac7d1e99bd3e Replaced trailing digit file.
dinu_gherman
parents:
diff changeset
   228
ac7d1e99bd3e Replaced trailing digit file.
dinu_gherman
parents:
diff changeset
   229
    def wrap(self, availWidth, availHeight):
ac7d1e99bd3e Replaced trailing digit file.
dinu_gherman
parents:
diff changeset
   230
        "All table properties should be known by now."
ac7d1e99bd3e Replaced trailing digit file.
dinu_gherman
parents:
diff changeset
   231
ac7d1e99bd3e Replaced trailing digit file.
dinu_gherman
parents:
diff changeset
   232
        # makes an internal table which does all the work.
ac7d1e99bd3e Replaced trailing digit file.
dinu_gherman
parents:
diff changeset
   233
        # we draw the LAST RUN's entries!  If there are
ac7d1e99bd3e Replaced trailing digit file.
dinu_gherman
parents:
diff changeset
   234
        # none, we make some dummy data to keep the table
ac7d1e99bd3e Replaced trailing digit file.
dinu_gherman
parents:
diff changeset
   235
        # from complaining
ac7d1e99bd3e Replaced trailing digit file.
dinu_gherman
parents:
diff changeset
   236
        if len(self._lastEntries) == 0:
3060
eeedb611fa67 Added feature to have clickable TableOfContents entries (ToDo 978).
jonas
parents: 3049
diff changeset
   237
            _tempEntries = [(0,'Placeholder for table of contents',0,None)]
754
ac7d1e99bd3e Replaced trailing digit file.
dinu_gherman
parents:
diff changeset
   238
        else:
ac7d1e99bd3e Replaced trailing digit file.
dinu_gherman
parents:
diff changeset
   239
            _tempEntries = self._lastEntries
ac7d1e99bd3e Replaced trailing digit file.
dinu_gherman
parents:
diff changeset
   240
3049
6e9ca03c4dbe Added dotted lines to TableOfContents.
jonas
parents: 3045
diff changeset
   241
        def drawTOCEntryEnd(canvas, kind, label):
6e9ca03c4dbe Added dotted lines to TableOfContents.
jonas
parents: 3045
diff changeset
   242
            '''Callback to draw dots and page numbers after each entry.'''
3294
f60b7cb499aa tableofcontents.py: fix passing of key to onDraw for TOC
rgbecker
parents: 3187
diff changeset
   243
            label = label.split(',')
4551
d357e2acc856 improve usage of eval/exec; version --> 3.5.32
robin
parents: 4528
diff changeset
   244
            page, level, key = int(label[0]), int(label[1]), literal_eval(label[2])
3146
4732d02eae94 Added support for an unlimited number of TOC levels with default styles.
jonas
parents: 3145
diff changeset
   245
            style = self.getLevelStyle(level)
3145
afc8212b1ed8 fixed 2.6-ism
andy
parents: 3143
diff changeset
   246
            if self.dotsMinLevel >= 0 and level >= self.dotsMinLevel:
3165
cbda9e7d0ee3 reportlab: new index support
rgbecker
parents: 3164
diff changeset
   247
                dot = ' . '
cbda9e7d0ee3 reportlab: new index support
rgbecker
parents: 3164
diff changeset
   248
            else:
3145
afc8212b1ed8 fixed 2.6-ism
andy
parents: 3143
diff changeset
   249
                dot = ''
4180
2ee5e4cd860f add formatter and argument processing to tabelOfContents; version-->3.1.52
robin
parents: 4178
diff changeset
   250
            if self.formatter: page = self.formatter(page)
3294
f60b7cb499aa tableofcontents.py: fix passing of key to onDraw for TOC
rgbecker
parents: 3187
diff changeset
   251
            drawPageNumbers(canvas, style, [(page, key)], availWidth, availHeight, dot)
3049
6e9ca03c4dbe Added dotted lines to TableOfContents.
jonas
parents: 3045
diff changeset
   252
        self.canv.drawTOCEntryEnd = drawTOCEntryEnd
6e9ca03c4dbe Added dotted lines to TableOfContents.
jonas
parents: 3045
diff changeset
   253
754
ac7d1e99bd3e Replaced trailing digit file.
dinu_gherman
parents:
diff changeset
   254
        tableData = []
3060
eeedb611fa67 Added feature to have clickable TableOfContents entries (ToDo 978).
jonas
parents: 3049
diff changeset
   255
        for (level, text, pageNum, key) in _tempEntries:
3146
4732d02eae94 Added support for an unlimited number of TOC levels with default styles.
jonas
parents: 3145
diff changeset
   256
            style = self.getLevelStyle(level)
3060
eeedb611fa67 Added feature to have clickable TableOfContents entries (ToDo 978).
jonas
parents: 3049
diff changeset
   257
            if key:
eeedb611fa67 Added feature to have clickable TableOfContents entries (ToDo 978).
jonas
parents: 3049
diff changeset
   258
                text = '<a href="#%s">%s</a>' % (key, text)
3294
f60b7cb499aa tableofcontents.py: fix passing of key to onDraw for TOC
rgbecker
parents: 3187
diff changeset
   259
                keyVal = repr(key).replace(',','\\x2c').replace('"','\\x2c')
f60b7cb499aa tableofcontents.py: fix passing of key to onDraw for TOC
rgbecker
parents: 3187
diff changeset
   260
            else:
f60b7cb499aa tableofcontents.py: fix passing of key to onDraw for TOC
rgbecker
parents: 3187
diff changeset
   261
                keyVal = None
f60b7cb499aa tableofcontents.py: fix passing of key to onDraw for TOC
rgbecker
parents: 3187
diff changeset
   262
            para = Paragraph('%s<onDraw name="drawTOCEntryEnd" label="%d,%d,%s"/>' % (text, pageNum, level, keyVal), style)
3049
6e9ca03c4dbe Added dotted lines to TableOfContents.
jonas
parents: 3045
diff changeset
   263
            if style.spaceBefore:
6e9ca03c4dbe Added dotted lines to TableOfContents.
jonas
parents: 3045
diff changeset
   264
                tableData.append([Spacer(1, style.spaceBefore),])
6e9ca03c4dbe Added dotted lines to TableOfContents.
jonas
parents: 3045
diff changeset
   265
            tableData.append([para,])
754
ac7d1e99bd3e Replaced trailing digit file.
dinu_gherman
parents:
diff changeset
   266
3135
3a2a8a52c1c1 reportlab.platypus: Fixes for SimpleIndex and TableOfContents.
jonas
parents: 3111
diff changeset
   267
        self._table = Table(tableData, colWidths=(availWidth,), style=self.tableStyle)
754
ac7d1e99bd3e Replaced trailing digit file.
dinu_gherman
parents:
diff changeset
   268
1493
bfcdeed2f9e7 Propogate the canvas
rgbecker
parents: 1444
diff changeset
   269
        self.width, self.height = self._table.wrapOn(self.canv,availWidth, availHeight)
754
ac7d1e99bd3e Replaced trailing digit file.
dinu_gherman
parents:
diff changeset
   270
        return (self.width, self.height)
ac7d1e99bd3e Replaced trailing digit file.
dinu_gherman
parents:
diff changeset
   271
ac7d1e99bd3e Replaced trailing digit file.
dinu_gherman
parents:
diff changeset
   272
ac7d1e99bd3e Replaced trailing digit file.
dinu_gherman
parents:
diff changeset
   273
    def split(self, availWidth, availHeight):
ac7d1e99bd3e Replaced trailing digit file.
dinu_gherman
parents:
diff changeset
   274
        """At this stage we do not care about splitting the entries,
ac7d1e99bd3e Replaced trailing digit file.
dinu_gherman
parents:
diff changeset
   275
        we will just return a list of platypus tables.  Presumably the
ac7d1e99bd3e Replaced trailing digit file.
dinu_gherman
parents:
diff changeset
   276
        calling app has a pointer to the original TableOfContents object;
ac7d1e99bd3e Replaced trailing digit file.
dinu_gherman
parents:
diff changeset
   277
        Platypus just sees tables.
ac7d1e99bd3e Replaced trailing digit file.
dinu_gherman
parents:
diff changeset
   278
        """
1493
bfcdeed2f9e7 Propogate the canvas
rgbecker
parents: 1444
diff changeset
   279
        return self._table.splitOn(self.canv,availWidth, availHeight)
754
ac7d1e99bd3e Replaced trailing digit file.
dinu_gherman
parents:
diff changeset
   280
ac7d1e99bd3e Replaced trailing digit file.
dinu_gherman
parents:
diff changeset
   281
ac7d1e99bd3e Replaced trailing digit file.
dinu_gherman
parents:
diff changeset
   282
    def drawOn(self, canvas, x, y, _sW=0):
ac7d1e99bd3e Replaced trailing digit file.
dinu_gherman
parents:
diff changeset
   283
        """Don't do this at home!  The standard calls for implementing
ac7d1e99bd3e Replaced trailing digit file.
dinu_gherman
parents:
diff changeset
   284
        draw(); we are hooking this in order to delegate ALL the drawing
ac7d1e99bd3e Replaced trailing digit file.
dinu_gherman
parents:
diff changeset
   285
        work to the embedded table object.
ac7d1e99bd3e Replaced trailing digit file.
dinu_gherman
parents:
diff changeset
   286
        """
ac7d1e99bd3e Replaced trailing digit file.
dinu_gherman
parents:
diff changeset
   287
        self._table.drawOn(canvas, x, y, _sW)
3165
cbda9e7d0ee3 reportlab: new index support
rgbecker
parents: 3164
diff changeset
   288
3143
c704253bc72a Added support for multi-level and alphabetical indexes.
jonas
parents: 3141
diff changeset
   289
def makeTuple(x):
4339
02f586bd5209 fix 3.x bug in makeTuple
robin <robin@reportlab.com>
parents: 4338
diff changeset
   290
    if isinstance(x,(list,tuple)):
3143
c704253bc72a Added support for multi-level and alphabetical indexes.
jonas
parents: 3141
diff changeset
   291
        return tuple(x)
c704253bc72a Added support for multi-level and alphabetical indexes.
jonas
parents: 3141
diff changeset
   292
    return (x,)
1444
454d117af3a5 Missed a checkin
andy_robinson
parents: 1440
diff changeset
   293
454d117af3a5 Missed a checkin
andy_robinson
parents: 1440
diff changeset
   294
class SimpleIndex(IndexingFlowable):
3173
ded6e2bbf425 More documentation for SimpleIndex.
jonas
parents: 3171
diff changeset
   295
    """Creates multi level indexes.
ded6e2bbf425 More documentation for SimpleIndex.
jonas
parents: 3171
diff changeset
   296
    The styling can be cutomized and alphabetic headers turned on and off.
ded6e2bbf425 More documentation for SimpleIndex.
jonas
parents: 3171
diff changeset
   297
    """
1444
454d117af3a5 Missed a checkin
andy_robinson
parents: 1440
diff changeset
   298
3164
0c60143b507e Added setup method and headers parameter. AlphabeticalIndex is now deprecated.
jonas
parents: 3162
diff changeset
   299
    def __init__(self, **kwargs):
3173
ded6e2bbf425 More documentation for SimpleIndex.
jonas
parents: 3171
diff changeset
   300
        """
ded6e2bbf425 More documentation for SimpleIndex.
jonas
parents: 3171
diff changeset
   301
        Constructor of SimpleIndex.
ded6e2bbf425 More documentation for SimpleIndex.
jonas
parents: 3171
diff changeset
   302
        Accepts the same arguments as the setup method.
ded6e2bbf425 More documentation for SimpleIndex.
jonas
parents: 3171
diff changeset
   303
        """
1444
454d117af3a5 Missed a checkin
andy_robinson
parents: 1440
diff changeset
   304
        #keep stuff in a dictionary while building
454d117af3a5 Missed a checkin
andy_robinson
parents: 1440
diff changeset
   305
        self._entries = {}
454d117af3a5 Missed a checkin
andy_robinson
parents: 1440
diff changeset
   306
        self._lastEntries = {}
3140
c79e6a56495d tableofcontents: add support for index tableStyle
rgbecker
parents: 3136
diff changeset
   307
        self._flowable = None
3164
0c60143b507e Added setup method and headers parameter. AlphabeticalIndex is now deprecated.
jonas
parents: 3162
diff changeset
   308
        self.setup(**kwargs)
3165
cbda9e7d0ee3 reportlab: new index support
rgbecker
parents: 3164
diff changeset
   309
4551
d357e2acc856 improve usage of eval/exec; version --> 3.5.32
robin
parents: 4528
diff changeset
   310
    def getFormatFunc(self,formatName):
3187
2d5a6655556e tableofcontents/paraparser: allow for format and offset parameters
rgbecker
parents: 3173
diff changeset
   311
        try:
4551
d357e2acc856 improve usage of eval/exec; version --> 3.5.32
robin
parents: 4528
diff changeset
   312
            return getattr(rl_sequencer,'_format_%s' % formatName)
3187
2d5a6655556e tableofcontents/paraparser: allow for format and offset parameters
rgbecker
parents: 3173
diff changeset
   313
        except ImportError:
4551
d357e2acc856 improve usage of eval/exec; version --> 3.5.32
robin
parents: 4528
diff changeset
   314
            raise ValueError('Unknown sequencer format %r' % formatName)
3187
2d5a6655556e tableofcontents/paraparser: allow for format and offset parameters
rgbecker
parents: 3173
diff changeset
   315
2d5a6655556e tableofcontents/paraparser: allow for format and offset parameters
rgbecker
parents: 3173
diff changeset
   316
    def setup(self, style=None, dot=None, tableStyle=None, headers=True, name=None, format='123', offset=0):
3173
ded6e2bbf425 More documentation for SimpleIndex.
jonas
parents: 3171
diff changeset
   317
        """
ded6e2bbf425 More documentation for SimpleIndex.
jonas
parents: 3171
diff changeset
   318
        This method makes it possible to change styling and other parameters on an existing object.
4121
3b9e6fa286ad tableofcontents.py, doctemplate.py: fix indexing page number ordering bug found by Greg Jones bitbucket issue #40
robin
parents: 4058
diff changeset
   319
3173
ded6e2bbf425 More documentation for SimpleIndex.
jonas
parents: 3171
diff changeset
   320
        style is the paragraph style to use for index entries.
ded6e2bbf425 More documentation for SimpleIndex.
jonas
parents: 3171
diff changeset
   321
        dot can either be None or a string. If it's None, entries are immediatly followed by their
ded6e2bbf425 More documentation for SimpleIndex.
jonas
parents: 3171
diff changeset
   322
            corresponding page numbers. If it's a string, page numbers are aligned on the right side
ded6e2bbf425 More documentation for SimpleIndex.
jonas
parents: 3171
diff changeset
   323
            of the document and the gap filled with a repeating sequence of the string.
ded6e2bbf425 More documentation for SimpleIndex.
jonas
parents: 3171
diff changeset
   324
        tableStyle is the style used by the table which the index uses to draw itself. Use this to
ded6e2bbf425 More documentation for SimpleIndex.
jonas
parents: 3171
diff changeset
   325
            change properties like spacing between elements.
3348
d44de6313b58 workaround for widow/orphan control in simpleindex
andy
parents: 3327
diff changeset
   326
        headers is a boolean. If it is True, alphabetic headers are displayed in the Index when the first
4121
3b9e6fa286ad tableofcontents.py, doctemplate.py: fix indexing page number ordering bug found by Greg Jones bitbucket issue #40
robin
parents: 4058
diff changeset
   327
        letter changes. If False, we just output some extra space before the next item
3173
ded6e2bbf425 More documentation for SimpleIndex.
jonas
parents: 3171
diff changeset
   328
        name makes it possible to use several indexes in one document. If you want this use this
ded6e2bbf425 More documentation for SimpleIndex.
jonas
parents: 3171
diff changeset
   329
            parameter to give each index a unique name. You can then index a term by refering to the
ded6e2bbf425 More documentation for SimpleIndex.
jonas
parents: 3171
diff changeset
   330
            name of the index which it should appear in:
4121
3b9e6fa286ad tableofcontents.py, doctemplate.py: fix indexing page number ordering bug found by Greg Jones bitbucket issue #40
robin
parents: 4058
diff changeset
   331
3173
ded6e2bbf425 More documentation for SimpleIndex.
jonas
parents: 3171
diff changeset
   332
                <index item="term" name="myindex" />
3187
2d5a6655556e tableofcontents/paraparser: allow for format and offset parameters
rgbecker
parents: 3173
diff changeset
   333
2d5a6655556e tableofcontents/paraparser: allow for format and offset parameters
rgbecker
parents: 3173
diff changeset
   334
        format can be 'I', 'i', '123',  'ABC', 'abc'
3173
ded6e2bbf425 More documentation for SimpleIndex.
jonas
parents: 3171
diff changeset
   335
        """
4121
3b9e6fa286ad tableofcontents.py, doctemplate.py: fix indexing page number ordering bug found by Greg Jones bitbucket issue #40
robin
parents: 4058
diff changeset
   336
3135
3a2a8a52c1c1 reportlab.platypus: Fixes for SimpleIndex and TableOfContents.
jonas
parents: 3111
diff changeset
   337
        if style is None:
3a2a8a52c1c1 reportlab.platypus: Fixes for SimpleIndex and TableOfContents.
jonas
parents: 3111
diff changeset
   338
            style = ParagraphStyle(name='index',
3368
afa025c34493 reportlab: new base font mechanism more fully applied
rgbecker
parents: 3349
diff changeset
   339
                                        fontName=_baseFontName,
3135
3a2a8a52c1c1 reportlab.platypus: Fixes for SimpleIndex and TableOfContents.
jonas
parents: 3111
diff changeset
   340
                                        fontSize=11)
3a2a8a52c1c1 reportlab.platypus: Fixes for SimpleIndex and TableOfContents.
jonas
parents: 3111
diff changeset
   341
        self.textStyle = style
3140
c79e6a56495d tableofcontents: add support for index tableStyle
rgbecker
parents: 3136
diff changeset
   342
        self.tableStyle = tableStyle or defaultTableStyle
3136
3a4e339ebac8 platypus.tableofcontents: allow more flexibility for drawing dots in Index and TableOfContents. Set default for Index back to none.
jonas
parents: 3135
diff changeset
   343
        self.dot = dot
3164
0c60143b507e Added setup method and headers parameter. AlphabeticalIndex is now deprecated.
jonas
parents: 3162
diff changeset
   344
        self.headers = headers
3165
cbda9e7d0ee3 reportlab: new index support
rgbecker
parents: 3164
diff changeset
   345
        if name is None:
cbda9e7d0ee3 reportlab: new index support
rgbecker
parents: 3164
diff changeset
   346
            from reportlab.platypus.paraparser import DEFAULT_INDEX_NAME as name
cbda9e7d0ee3 reportlab: new index support
rgbecker
parents: 3164
diff changeset
   347
        self.name = name
3187
2d5a6655556e tableofcontents/paraparser: allow for format and offset parameters
rgbecker
parents: 3173
diff changeset
   348
        self.formatFunc = self.getFormatFunc(format)
2d5a6655556e tableofcontents/paraparser: allow for format and offset parameters
rgbecker
parents: 3173
diff changeset
   349
        self.offset = offset
3165
cbda9e7d0ee3 reportlab: new index support
rgbecker
parents: 3164
diff changeset
   350
cbda9e7d0ee3 reportlab: new index support
rgbecker
parents: 3164
diff changeset
   351
    def __call__(self,canv,kind,label):
4338
6223e7fa13f6 reproducibility fixes; version --> 3.4.3
robin <robin@reportlab.com>
parents: 4330
diff changeset
   352
        label = asNative(label,'latin1')
3187
2d5a6655556e tableofcontents/paraparser: allow for format and offset parameters
rgbecker
parents: 3173
diff changeset
   353
        try:
3850
52c3600611ec utils.py: fix encode/decode_label
robin
parents: 3818
diff changeset
   354
            terms, format, offset = decode_label(label)
3187
2d5a6655556e tableofcontents/paraparser: allow for format and offset parameters
rgbecker
parents: 3173
diff changeset
   355
        except:
2d5a6655556e tableofcontents/paraparser: allow for format and offset parameters
rgbecker
parents: 3173
diff changeset
   356
            terms = label
2d5a6655556e tableofcontents/paraparser: allow for format and offset parameters
rgbecker
parents: 3173
diff changeset
   357
            format = offset = None
2d5a6655556e tableofcontents/paraparser: allow for format and offset parameters
rgbecker
parents: 3173
diff changeset
   358
        if format is None:
2d5a6655556e tableofcontents/paraparser: allow for format and offset parameters
rgbecker
parents: 3173
diff changeset
   359
            formatFunc = self.formatFunc
2d5a6655556e tableofcontents/paraparser: allow for format and offset parameters
rgbecker
parents: 3173
diff changeset
   360
        else:
2d5a6655556e tableofcontents/paraparser: allow for format and offset parameters
rgbecker
parents: 3173
diff changeset
   361
            formatFunc = self.getFormatFunc(format)
2d5a6655556e tableofcontents/paraparser: allow for format and offset parameters
rgbecker
parents: 3173
diff changeset
   362
        if offset is None:
2d5a6655556e tableofcontents/paraparser: allow for format and offset parameters
rgbecker
parents: 3173
diff changeset
   363
            offset = self.offset
2d5a6655556e tableofcontents/paraparser: allow for format and offset parameters
rgbecker
parents: 3173
diff changeset
   364
2d5a6655556e tableofcontents/paraparser: allow for format and offset parameters
rgbecker
parents: 3173
diff changeset
   365
        terms = commasplit(terms)
4121
3b9e6fa286ad tableofcontents.py, doctemplate.py: fix indexing page number ordering bug found by Greg Jones bitbucket issue #40
robin
parents: 4058
diff changeset
   366
        cPN = canv.getPageNumber()
3b9e6fa286ad tableofcontents.py, doctemplate.py: fix indexing page number ordering bug found by Greg Jones bitbucket issue #40
robin
parents: 4058
diff changeset
   367
        pns = formatFunc(cPN-offset)
3187
2d5a6655556e tableofcontents/paraparser: allow for format and offset parameters
rgbecker
parents: 3173
diff changeset
   368
        key = 'ix_%s_%s_p_%s' % (self.name, label, pns)
3165
cbda9e7d0ee3 reportlab: new index support
rgbecker
parents: 3164
diff changeset
   369
cbda9e7d0ee3 reportlab: new index support
rgbecker
parents: 3164
diff changeset
   370
        info = canv._curr_tx_info
cbda9e7d0ee3 reportlab: new index support
rgbecker
parents: 3164
diff changeset
   371
        canv.bookmarkHorizontal(key, info['cur_x'], info['cur_y'] + info['leading'])
4121
3b9e6fa286ad tableofcontents.py, doctemplate.py: fix indexing page number ordering bug found by Greg Jones bitbucket issue #40
robin
parents: 4058
diff changeset
   372
        self.addEntry(terms, (cPN,pns), key)
3165
cbda9e7d0ee3 reportlab: new index support
rgbecker
parents: 3164
diff changeset
   373
3162
77afde998aa9 Made Index entries clickable.
jonas
parents: 3146
diff changeset
   374
    def getCanvasMaker(self, canvasmaker=canvas.Canvas):
3165
cbda9e7d0ee3 reportlab: new index support
rgbecker
parents: 3164
diff changeset
   375
3162
77afde998aa9 Made Index entries clickable.
jonas
parents: 3146
diff changeset
   376
        def newcanvasmaker(*args, **kwargs):
77afde998aa9 Made Index entries clickable.
jonas
parents: 3146
diff changeset
   377
            from reportlab.pdfgen import canvas
77afde998aa9 Made Index entries clickable.
jonas
parents: 3146
diff changeset
   378
            c = canvasmaker(*args, **kwargs)
3165
cbda9e7d0ee3 reportlab: new index support
rgbecker
parents: 3164
diff changeset
   379
            setattr(c,self.name,self)
3162
77afde998aa9 Made Index entries clickable.
jonas
parents: 3146
diff changeset
   380
            return c
3165
cbda9e7d0ee3 reportlab: new index support
rgbecker
parents: 3164
diff changeset
   381
3162
77afde998aa9 Made Index entries clickable.
jonas
parents: 3146
diff changeset
   382
        return newcanvasmaker
3135
3a2a8a52c1c1 reportlab.platypus: Fixes for SimpleIndex and TableOfContents.
jonas
parents: 3111
diff changeset
   383
1444
454d117af3a5 Missed a checkin
andy_robinson
parents: 1440
diff changeset
   384
    def isIndexing(self):
454d117af3a5 Missed a checkin
andy_robinson
parents: 1440
diff changeset
   385
        return 1
454d117af3a5 Missed a checkin
andy_robinson
parents: 1440
diff changeset
   386
454d117af3a5 Missed a checkin
andy_robinson
parents: 1440
diff changeset
   387
    def isSatisfied(self):
454d117af3a5 Missed a checkin
andy_robinson
parents: 1440
diff changeset
   388
        return (self._entries == self._lastEntries)
1683
7fa753e4420a Removed all trailing whitespace
andy_robinson
parents: 1559
diff changeset
   389
1444
454d117af3a5 Missed a checkin
andy_robinson
parents: 1440
diff changeset
   390
    def beforeBuild(self):
454d117af3a5 Missed a checkin
andy_robinson
parents: 1440
diff changeset
   391
        # keep track of the last run
454d117af3a5 Missed a checkin
andy_robinson
parents: 1440
diff changeset
   392
        self._lastEntries = self._entries.copy()
454d117af3a5 Missed a checkin
andy_robinson
parents: 1440
diff changeset
   393
        self.clearEntries()
454d117af3a5 Missed a checkin
andy_robinson
parents: 1440
diff changeset
   394
454d117af3a5 Missed a checkin
andy_robinson
parents: 1440
diff changeset
   395
    def clearEntries(self):
454d117af3a5 Missed a checkin
andy_robinson
parents: 1440
diff changeset
   396
        self._entries = {}
454d117af3a5 Missed a checkin
andy_robinson
parents: 1440
diff changeset
   397
454d117af3a5 Missed a checkin
andy_robinson
parents: 1440
diff changeset
   398
    def notify(self, kind, stuff):
454d117af3a5 Missed a checkin
andy_robinson
parents: 1440
diff changeset
   399
        """The notification hook called to register all kinds of events.
454d117af3a5 Missed a checkin
andy_robinson
parents: 1440
diff changeset
   400
454d117af3a5 Missed a checkin
andy_robinson
parents: 1440
diff changeset
   401
        Here we are interested in 'IndexEntry' events only.
454d117af3a5 Missed a checkin
andy_robinson
parents: 1440
diff changeset
   402
        """
454d117af3a5 Missed a checkin
andy_robinson
parents: 1440
diff changeset
   403
        if kind == 'IndexEntry':
4121
3b9e6fa286ad tableofcontents.py, doctemplate.py: fix indexing page number ordering bug found by Greg Jones bitbucket issue #40
robin
parents: 4058
diff changeset
   404
            text, pageNum = stuff
3b9e6fa286ad tableofcontents.py, doctemplate.py: fix indexing page number ordering bug found by Greg Jones bitbucket issue #40
robin
parents: 4058
diff changeset
   405
            self.addEntry(text, (self._canv.getPageNumber(),pageNum))
1444
454d117af3a5 Missed a checkin
andy_robinson
parents: 1440
diff changeset
   406
3162
77afde998aa9 Made Index entries clickable.
jonas
parents: 3146
diff changeset
   407
    def addEntry(self, text, pageNum, key=None):
1444
454d117af3a5 Missed a checkin
andy_robinson
parents: 1440
diff changeset
   408
        """Allows incremental buildup"""
3162
77afde998aa9 Made Index entries clickable.
jonas
parents: 3146
diff changeset
   409
        self._entries.setdefault(makeTuple(text),set([])).add((pageNum, key))
1444
454d117af3a5 Missed a checkin
andy_robinson
parents: 1440
diff changeset
   410
454d117af3a5 Missed a checkin
andy_robinson
parents: 1440
diff changeset
   411
    def split(self, availWidth, availHeight):
454d117af3a5 Missed a checkin
andy_robinson
parents: 1440
diff changeset
   412
        """At this stage we do not care about splitting the entries,
454d117af3a5 Missed a checkin
andy_robinson
parents: 1440
diff changeset
   413
        we will just return a list of platypus tables.  Presumably the
454d117af3a5 Missed a checkin
andy_robinson
parents: 1440
diff changeset
   414
        calling app has a pointer to the original TableOfContents object;
454d117af3a5 Missed a checkin
andy_robinson
parents: 1440
diff changeset
   415
        Platypus just sees tables.
454d117af3a5 Missed a checkin
andy_robinson
parents: 1440
diff changeset
   416
        """
3140
c79e6a56495d tableofcontents: add support for index tableStyle
rgbecker
parents: 3136
diff changeset
   417
        return self._flowable.splitOn(self.canv,availWidth, availHeight)
1444
454d117af3a5 Missed a checkin
andy_robinson
parents: 1440
diff changeset
   418
3162
77afde998aa9 Made Index entries clickable.
jonas
parents: 3146
diff changeset
   419
    def _getlastEntries(self, dummy=[(['Placeholder for index'],enumerate((None,)*3))]):
3143
c704253bc72a Added support for multi-level and alphabetical indexes.
jonas
parents: 3141
diff changeset
   420
        '''Return the last run's entries!  If there are none, returns dummy.'''
4338
6223e7fa13f6 reproducibility fixes; version --> 3.4.3
robin <robin@reportlab.com>
parents: 4330
diff changeset
   421
        lE = self._lastEntries or self._entries
6223e7fa13f6 reproducibility fixes; version --> 3.4.3
robin <robin@reportlab.com>
parents: 4330
diff changeset
   422
        if not lE:
3143
c704253bc72a Added support for multi-level and alphabetical indexes.
jonas
parents: 3141
diff changeset
   423
            return dummy
4338
6223e7fa13f6 reproducibility fixes; version --> 3.4.3
robin <robin@reportlab.com>
parents: 4330
diff changeset
   424
        return list(sorted(lE.items()))
3165
cbda9e7d0ee3 reportlab: new index support
rgbecker
parents: 3164
diff changeset
   425
3140
c79e6a56495d tableofcontents: add support for index tableStyle
rgbecker
parents: 3136
diff changeset
   426
    def _build(self,availWidth,availHeight):
4178
b2c73e04465c fix indexing for accented stuff contributed by alexandrel_sgi @ bitbucket, version-->3.1.50
robin
parents: 4121
diff changeset
   427
        _tempEntries = [(tuple(asUnicode(t) for t in texts),pageNumbers)
b2c73e04465c fix indexing for accented stuff contributed by alexandrel_sgi @ bitbucket, version-->3.1.50
robin
parents: 4121
diff changeset
   428
                            for texts, pageNumbers in self._getlastEntries()]
3327
512eb20b0c3d more 2to3ing
andy
parents: 3294
diff changeset
   429
        def getkey(seq):
4178
b2c73e04465c fix indexing for accented stuff contributed by alexandrel_sgi @ bitbucket, version-->3.1.50
robin
parents: 4121
diff changeset
   430
            return [''.join((c for c in unicodedata.normalize('NFD', x.upper()) if unicodedata.category(c) != 'Mn')) for x in seq[0]]
3327
512eb20b0c3d more 2to3ing
andy
parents: 3294
diff changeset
   431
        _tempEntries.sort(key=getkey)
3164
0c60143b507e Added setup method and headers parameter. AlphabeticalIndex is now deprecated.
jonas
parents: 3162
diff changeset
   432
        leveloffset = self.headers and 1 or 0
1444
454d117af3a5 Missed a checkin
andy_robinson
parents: 1440
diff changeset
   433
3135
3a2a8a52c1c1 reportlab.platypus: Fixes for SimpleIndex and TableOfContents.
jonas
parents: 3111
diff changeset
   434
        def drawIndexEntryEnd(canvas, kind, label):
3a2a8a52c1c1 reportlab.platypus: Fixes for SimpleIndex and TableOfContents.
jonas
parents: 3111
diff changeset
   435
            '''Callback to draw dots and page numbers after each entry.'''
3164
0c60143b507e Added setup method and headers parameter. AlphabeticalIndex is now deprecated.
jonas
parents: 3162
diff changeset
   436
            style = self.getLevelStyle(leveloffset)
4121
3b9e6fa286ad tableofcontents.py, doctemplate.py: fix indexing page number ordering bug found by Greg Jones bitbucket issue #40
robin
parents: 4058
diff changeset
   437
            pages = [(p[1],k) for p,k in sorted(decode_label(label))]
3162
77afde998aa9 Made Index entries clickable.
jonas
parents: 3146
diff changeset
   438
            drawPageNumbers(canvas, style, pages, availWidth, availHeight, self.dot)
3135
3a2a8a52c1c1 reportlab.platypus: Fixes for SimpleIndex and TableOfContents.
jonas
parents: 3111
diff changeset
   439
        self.canv.drawIndexEntryEnd = drawIndexEntryEnd
3a2a8a52c1c1 reportlab.platypus: Fixes for SimpleIndex and TableOfContents.
jonas
parents: 3111
diff changeset
   440
3164
0c60143b507e Added setup method and headers parameter. AlphabeticalIndex is now deprecated.
jonas
parents: 3162
diff changeset
   441
        alpha = ''
1444
454d117af3a5 Missed a checkin
andy_robinson
parents: 1440
diff changeset
   442
        tableData = []
3143
c704253bc72a Added support for multi-level and alphabetical indexes.
jonas
parents: 3141
diff changeset
   443
        lastTexts = []
3348
d44de6313b58 workaround for widow/orphan control in simpleindex
andy
parents: 3327
diff changeset
   444
        alphaStyle = self.getLevelStyle(0)
3143
c704253bc72a Added support for multi-level and alphabetical indexes.
jonas
parents: 3141
diff changeset
   445
        for texts, pageNumbers in _tempEntries:
c704253bc72a Added support for multi-level and alphabetical indexes.
jonas
parents: 3141
diff changeset
   446
            texts = list(texts)
3348
d44de6313b58 workaround for widow/orphan control in simpleindex
andy
parents: 3327
diff changeset
   447
            #track when the first character changes; either output some extra
d44de6313b58 workaround for widow/orphan control in simpleindex
andy
parents: 3327
diff changeset
   448
            #space, or the first letter on a row of its own.  We cannot do
d44de6313b58 workaround for widow/orphan control in simpleindex
andy
parents: 3327
diff changeset
   449
            #widow/orphan control, sadly.
4178
b2c73e04465c fix indexing for accented stuff contributed by alexandrel_sgi @ bitbucket, version-->3.1.50
robin
parents: 4121
diff changeset
   450
            nalpha = ''.join((c for c in unicodedata.normalize('NFD', texts[0][0].upper()) if unicodedata.category(c) != 'Mn'))
3348
d44de6313b58 workaround for widow/orphan control in simpleindex
andy
parents: 3327
diff changeset
   451
            if alpha != nalpha:
d44de6313b58 workaround for widow/orphan control in simpleindex
andy
parents: 3327
diff changeset
   452
                alpha = nalpha
d44de6313b58 workaround for widow/orphan control in simpleindex
andy
parents: 3327
diff changeset
   453
                if self.headers:
d44de6313b58 workaround for widow/orphan control in simpleindex
andy
parents: 3327
diff changeset
   454
                    header = alpha
d44de6313b58 workaround for widow/orphan control in simpleindex
andy
parents: 3327
diff changeset
   455
                else:
d44de6313b58 workaround for widow/orphan control in simpleindex
andy
parents: 3327
diff changeset
   456
                    header = ' '
d44de6313b58 workaround for widow/orphan control in simpleindex
andy
parents: 3327
diff changeset
   457
                tableData.append([Spacer(1, alphaStyle.spaceBefore),])
d44de6313b58 workaround for widow/orphan control in simpleindex
andy
parents: 3327
diff changeset
   458
                tableData.append([Paragraph(header, alphaStyle),])
d44de6313b58 workaround for widow/orphan control in simpleindex
andy
parents: 3327
diff changeset
   459
                tableData.append([Spacer(1, alphaStyle.spaceAfter),])
3164
0c60143b507e Added setup method and headers parameter. AlphabeticalIndex is now deprecated.
jonas
parents: 3162
diff changeset
   460
4121
3b9e6fa286ad tableofcontents.py, doctemplate.py: fix indexing page number ordering bug found by Greg Jones bitbucket issue #40
robin
parents: 4058
diff changeset
   461
3143
c704253bc72a Added support for multi-level and alphabetical indexes.
jonas
parents: 3141
diff changeset
   462
            i, diff = listdiff(lastTexts, texts)
c704253bc72a Added support for multi-level and alphabetical indexes.
jonas
parents: 3141
diff changeset
   463
            if diff:
c704253bc72a Added support for multi-level and alphabetical indexes.
jonas
parents: 3141
diff changeset
   464
                lastTexts = texts
c704253bc72a Added support for multi-level and alphabetical indexes.
jonas
parents: 3141
diff changeset
   465
                texts = texts[i:]
3850
52c3600611ec utils.py: fix encode/decode_label
robin
parents: 3818
diff changeset
   466
            label = encode_label(list(pageNumbers))
3170
91786d2240d0 Using base 64 encoding to make sure sgmllib does not mess with the whitespace in the attribute.
jonas
parents: 3167
diff changeset
   467
            texts[-1] = '%s<onDraw name="drawIndexEntryEnd" label="%s"/>' % (texts[-1], label)
3143
c704253bc72a Added support for multi-level and alphabetical indexes.
jonas
parents: 3141
diff changeset
   468
            for text in texts:
4121
3b9e6fa286ad tableofcontents.py, doctemplate.py: fix indexing page number ordering bug found by Greg Jones bitbucket issue #40
robin
parents: 4058
diff changeset
   469
                #Platypus and RML differ on how parsed XML attributes are escaped.
3349
b67514b01536 Index display code now handles 'M&S'-like attributes however they are escaped
andy
parents: 3348
diff changeset
   470
                #e.g. <index item="M&S"/>.  The only place this seems to bite us is in
b67514b01536 Index display code now handles 'M&S'-like attributes however they are escaped
andy
parents: 3348
diff changeset
   471
                #the index entries so work around it here.
4121
3b9e6fa286ad tableofcontents.py, doctemplate.py: fix indexing page number ordering bug found by Greg Jones bitbucket issue #40
robin
parents: 4058
diff changeset
   472
                text = escapeOnce(text)
3b9e6fa286ad tableofcontents.py, doctemplate.py: fix indexing page number ordering bug found by Greg Jones bitbucket issue #40
robin
parents: 4058
diff changeset
   473
3164
0c60143b507e Added setup method and headers parameter. AlphabeticalIndex is now deprecated.
jonas
parents: 3162
diff changeset
   474
                style = self.getLevelStyle(i+leveloffset)
3143
c704253bc72a Added support for multi-level and alphabetical indexes.
jonas
parents: 3141
diff changeset
   475
                para = Paragraph(text, style)
c704253bc72a Added support for multi-level and alphabetical indexes.
jonas
parents: 3141
diff changeset
   476
                if style.spaceBefore:
c704253bc72a Added support for multi-level and alphabetical indexes.
jonas
parents: 3141
diff changeset
   477
                    tableData.append([Spacer(1, style.spaceBefore),])
c704253bc72a Added support for multi-level and alphabetical indexes.
jonas
parents: 3141
diff changeset
   478
                tableData.append([para,])
c704253bc72a Added support for multi-level and alphabetical indexes.
jonas
parents: 3141
diff changeset
   479
                i += 1
3164
0c60143b507e Added setup method and headers parameter. AlphabeticalIndex is now deprecated.
jonas
parents: 3162
diff changeset
   480
3140
c79e6a56495d tableofcontents: add support for index tableStyle
rgbecker
parents: 3136
diff changeset
   481
        self._flowable = Table(tableData, colWidths=[availWidth], style=self.tableStyle)
1444
454d117af3a5 Missed a checkin
andy_robinson
parents: 1440
diff changeset
   482
3140
c79e6a56495d tableofcontents: add support for index tableStyle
rgbecker
parents: 3136
diff changeset
   483
    def wrap(self, availWidth, availHeight):
c79e6a56495d tableofcontents: add support for index tableStyle
rgbecker
parents: 3136
diff changeset
   484
        "All table properties should be known by now."
c79e6a56495d tableofcontents: add support for index tableStyle
rgbecker
parents: 3136
diff changeset
   485
        self._build(availWidth,availHeight)
c79e6a56495d tableofcontents: add support for index tableStyle
rgbecker
parents: 3136
diff changeset
   486
        self.width, self.height = self._flowable.wrapOn(self.canv,availWidth, availHeight)
3111
86a3158c50bd reportlab: improved support for onDraw and SimpleIndex
rgbecker
parents: 3060
diff changeset
   487
        return self.width, self.height
1444
454d117af3a5 Missed a checkin
andy_robinson
parents: 1440
diff changeset
   488
454d117af3a5 Missed a checkin
andy_robinson
parents: 1440
diff changeset
   489
    def drawOn(self, canvas, x, y, _sW=0):
454d117af3a5 Missed a checkin
andy_robinson
parents: 1440
diff changeset
   490
        """Don't do this at home!  The standard calls for implementing
454d117af3a5 Missed a checkin
andy_robinson
parents: 1440
diff changeset
   491
        draw(); we are hooking this in order to delegate ALL the drawing
454d117af3a5 Missed a checkin
andy_robinson
parents: 1440
diff changeset
   492
        work to the embedded table object.
454d117af3a5 Missed a checkin
andy_robinson
parents: 1440
diff changeset
   493
        """
3140
c79e6a56495d tableofcontents: add support for index tableStyle
rgbecker
parents: 3136
diff changeset
   494
        self._flowable.drawOn(canvas, x, y, _sW)
1444
454d117af3a5 Missed a checkin
andy_robinson
parents: 1440
diff changeset
   495
3111
86a3158c50bd reportlab: improved support for onDraw and SimpleIndex
rgbecker
parents: 3060
diff changeset
   496
    def draw(self):
3140
c79e6a56495d tableofcontents: add support for index tableStyle
rgbecker
parents: 3136
diff changeset
   497
        t = self._flowable
3111
86a3158c50bd reportlab: improved support for onDraw and SimpleIndex
rgbecker
parents: 3060
diff changeset
   498
        ocanv = getattr(t,'canv',None)
86a3158c50bd reportlab: improved support for onDraw and SimpleIndex
rgbecker
parents: 3060
diff changeset
   499
        if not ocanv:
86a3158c50bd reportlab: improved support for onDraw and SimpleIndex
rgbecker
parents: 3060
diff changeset
   500
            t.canv = self.canv
86a3158c50bd reportlab: improved support for onDraw and SimpleIndex
rgbecker
parents: 3060
diff changeset
   501
        try:
86a3158c50bd reportlab: improved support for onDraw and SimpleIndex
rgbecker
parents: 3060
diff changeset
   502
            t.draw()
86a3158c50bd reportlab: improved support for onDraw and SimpleIndex
rgbecker
parents: 3060
diff changeset
   503
        finally:
86a3158c50bd reportlab: improved support for onDraw and SimpleIndex
rgbecker
parents: 3060
diff changeset
   504
            if not ocanv:
86a3158c50bd reportlab: improved support for onDraw and SimpleIndex
rgbecker
parents: 3060
diff changeset
   505
                del t.canv
86a3158c50bd reportlab: improved support for onDraw and SimpleIndex
rgbecker
parents: 3060
diff changeset
   506
3143
c704253bc72a Added support for multi-level and alphabetical indexes.
jonas
parents: 3141
diff changeset
   507
    def getLevelStyle(self, n):
c704253bc72a Added support for multi-level and alphabetical indexes.
jonas
parents: 3141
diff changeset
   508
        '''Returns the style for level n, generating and caching styles on demand if not present.'''
c704253bc72a Added support for multi-level and alphabetical indexes.
jonas
parents: 3141
diff changeset
   509
        if not hasattr(self.textStyle, '__iter__'):
c704253bc72a Added support for multi-level and alphabetical indexes.
jonas
parents: 3141
diff changeset
   510
            self.textStyle = [self.textStyle]
c704253bc72a Added support for multi-level and alphabetical indexes.
jonas
parents: 3141
diff changeset
   511
        try:
c704253bc72a Added support for multi-level and alphabetical indexes.
jonas
parents: 3141
diff changeset
   512
            return self.textStyle[n]
c704253bc72a Added support for multi-level and alphabetical indexes.
jonas
parents: 3141
diff changeset
   513
        except IndexError:
c704253bc72a Added support for multi-level and alphabetical indexes.
jonas
parents: 3141
diff changeset
   514
            self.textStyle = list(self.textStyle)
c704253bc72a Added support for multi-level and alphabetical indexes.
jonas
parents: 3141
diff changeset
   515
            prevstyle = self.getLevelStyle(n-1)
c704253bc72a Added support for multi-level and alphabetical indexes.
jonas
parents: 3141
diff changeset
   516
            self.textStyle.append(ParagraphStyle(
c704253bc72a Added support for multi-level and alphabetical indexes.
jonas
parents: 3141
diff changeset
   517
                    name='%s-%d-indented' % (prevstyle.name, n),
c704253bc72a Added support for multi-level and alphabetical indexes.
jonas
parents: 3141
diff changeset
   518
                    parent=prevstyle,
3146
4732d02eae94 Added support for an unlimited number of TOC levels with default styles.
jonas
parents: 3145
diff changeset
   519
                    firstLineIndent = prevstyle.firstLineIndent+.2*cm,
4732d02eae94 Added support for an unlimited number of TOC levels with default styles.
jonas
parents: 3145
diff changeset
   520
                    leftIndent = prevstyle.leftIndent+.2*cm))
3143
c704253bc72a Added support for multi-level and alphabetical indexes.
jonas
parents: 3141
diff changeset
   521
            return self.textStyle[n]
c704253bc72a Added support for multi-level and alphabetical indexes.
jonas
parents: 3141
diff changeset
   522
3164
0c60143b507e Added setup method and headers parameter. AlphabeticalIndex is now deprecated.
jonas
parents: 3162
diff changeset
   523
AlphabeticIndex =  SimpleIndex
3141
e080fe8ab372 platypus.tableofcontents: Added an alphabetic grouping indexing class.
jonas
parents: 3140
diff changeset
   524
3143
c704253bc72a Added support for multi-level and alphabetical indexes.
jonas
parents: 3141
diff changeset
   525
def listdiff(l1, l2):
c704253bc72a Added support for multi-level and alphabetical indexes.
jonas
parents: 3141
diff changeset
   526
    m = min(len(l1), len(l2))
c704253bc72a Added support for multi-level and alphabetical indexes.
jonas
parents: 3141
diff changeset
   527
    for i in range(m):
c704253bc72a Added support for multi-level and alphabetical indexes.
jonas
parents: 3141
diff changeset
   528
        if l1[i] != l2[i]:
c704253bc72a Added support for multi-level and alphabetical indexes.
jonas
parents: 3141
diff changeset
   529
            return i, l2[i:]
c704253bc72a Added support for multi-level and alphabetical indexes.
jonas
parents: 3141
diff changeset
   530
    return m, l2[m:]
c704253bc72a Added support for multi-level and alphabetical indexes.
jonas
parents: 3141
diff changeset
   531
1444
454d117af3a5 Missed a checkin
andy_robinson
parents: 1440
diff changeset
   532
class ReferenceText(IndexingFlowable):
454d117af3a5 Missed a checkin
andy_robinson
parents: 1440
diff changeset
   533
    """Fakery to illustrate how a reference would work if we could
454d117af3a5 Missed a checkin
andy_robinson
parents: 1440
diff changeset
   534
    put it in a paragraph."""
454d117af3a5 Missed a checkin
andy_robinson
parents: 1440
diff changeset
   535
    def __init__(self, textPattern, targetKey):
454d117af3a5 Missed a checkin
andy_robinson
parents: 1440
diff changeset
   536
        self.textPattern = textPattern
454d117af3a5 Missed a checkin
andy_robinson
parents: 1440
diff changeset
   537
        self.target = targetKey
454d117af3a5 Missed a checkin
andy_robinson
parents: 1440
diff changeset
   538
        self.paraStyle = ParagraphStyle('tmp')
454d117af3a5 Missed a checkin
andy_robinson
parents: 1440
diff changeset
   539
        self._lastPageNum = None
454d117af3a5 Missed a checkin
andy_robinson
parents: 1440
diff changeset
   540
        self._pageNum = -999
454d117af3a5 Missed a checkin
andy_robinson
parents: 1440
diff changeset
   541
        self._para = None
454d117af3a5 Missed a checkin
andy_robinson
parents: 1440
diff changeset
   542
454d117af3a5 Missed a checkin
andy_robinson
parents: 1440
diff changeset
   543
    def beforeBuild(self):
454d117af3a5 Missed a checkin
andy_robinson
parents: 1440
diff changeset
   544
        self._lastPageNum = self._pageNum
454d117af3a5 Missed a checkin
andy_robinson
parents: 1440
diff changeset
   545
454d117af3a5 Missed a checkin
andy_robinson
parents: 1440
diff changeset
   546
    def notify(self, kind, stuff):
454d117af3a5 Missed a checkin
andy_robinson
parents: 1440
diff changeset
   547
        if kind == 'Target':
454d117af3a5 Missed a checkin
andy_robinson
parents: 1440
diff changeset
   548
            (key, pageNum) = stuff
454d117af3a5 Missed a checkin
andy_robinson
parents: 1440
diff changeset
   549
            if key == self.target:
454d117af3a5 Missed a checkin
andy_robinson
parents: 1440
diff changeset
   550
                self._pageNum = pageNum
454d117af3a5 Missed a checkin
andy_robinson
parents: 1440
diff changeset
   551
454d117af3a5 Missed a checkin
andy_robinson
parents: 1440
diff changeset
   552
    def wrap(self, availWidth, availHeight):
454d117af3a5 Missed a checkin
andy_robinson
parents: 1440
diff changeset
   553
        text = self.textPattern % self._lastPageNum
454d117af3a5 Missed a checkin
andy_robinson
parents: 1440
diff changeset
   554
        self._para = Paragraph(text, self.paraStyle)
454d117af3a5 Missed a checkin
andy_robinson
parents: 1440
diff changeset
   555
        return self._para.wrap(availWidth, availHeight)
1683
7fa753e4420a Removed all trailing whitespace
andy_robinson
parents: 1559
diff changeset
   556
1444
454d117af3a5 Missed a checkin
andy_robinson
parents: 1440
diff changeset
   557
    def drawOn(self, canvas, x, y, _sW=0):
454d117af3a5 Missed a checkin
andy_robinson
parents: 1440
diff changeset
   558
        self._para.drawOn(canvas, x, y, _sW)