[reportlab-users] how can i define chapters and include chapter title in a header?

Andy Robinson reportlab-users@reportlab.com
Mon, 22 Mar 2004 10:28:59 -0000


> Hi,
> 
> The subject says it all. I'd like to define chapters, and put the title 
> of the current chapter in the header, just as the user guide for 
> reportlab is set up.
> 
> TIA,
> Gerry
> 


That's why we publish the userguide source :-)
The template used is in reportlab/tools/docco/rltemplate.

There is no magic in the framework per se, but we hook
into one event.  Our subclass has a 'chapter' attribute and a couple
more too - when initialized it does this...

class RLDocTemplate(BaseDocTemplate):
    def afterInit(self):
	  ---snip----
        self.title = "(Document Title Goes Here)"
        self.chapter = "(No chapter yet)"
        self.chapterNo = 1 #unique keys
        self.sectionNo = 1 # unique keys


After each flowable we do this (I shortened it a little):
    def afterFlowable(self, flowable):
        """Detect Level 1 and 2 headings, build outline,
        and track chapter title."""
        if isinstance(flowable, Paragraph):
            style = flowable.style.name
            if style == 'Title':
                self.title = flowable.getPlainText()
            elif style == 'Heading1':
                self.chapter = flowable.getPlainText()
                key = 'ch%d' % self.chapterNo
                self.canv.bookmarkPage(key)
                self.canv.addOutlineEntry(flowable.getPlainText(),
                                            key, 0, 0)
                self.chapterNo = self.chapterNo + 1
                self.sectionNo = 1
            elif style == 'Heading2':
                self.section = flowable.text
                key = 'ch%ds%d' % (self.chapterNo, self.sectionNo)
                self.canv.bookmarkPage(key)
                self.canv.addOutlineEntry(flowable.getPlainText(),
                                             key, 1, 0)
                self.sectionNo = self.sectionNo + 1


So, as you see, we look at the style of each passing paragraph
and update the chapter and section titles and numbers accordingly.
This is also used to build the outline entries.

And then, in the page template, we draw a string with the current
value of the attribute.

class OneColumnTemplate(PageTemplate):

    ---snip----
    def afterDrawPage(self, canvas, doc):
        y = self.pageHeight - 50
        canvas.saveState()
        canvas.setFont('Times-Roman', 10)
        canvas.drawString(inch, y+8, doc.title)
        canvas.drawRightString(self.pageWidth - inch, y+8, doc.chapter)
                                                           ^^^^^^^^^^^
        ---snip---


I suggest to copy or inherit this template for your own manuals.

Best Regards,

Andy Robinson