PDF Output: Add a new variable _TOP_LEVEL_SECTION_ for use in header/footer templates that resolves to the current top-most section in the Table of Contents

This commit is contained in:
Kovid Goyal 2016-08-08 09:52:46 +05:30
parent 324a5a2635
commit a699cbc09a
4 changed files with 23 additions and 14 deletions

View File

@ -846,7 +846,8 @@ _SECTION_ is replaced by whatever the name of the current section is. These
names are taken from the metadata Table of Contents in the document (the PDF names are taken from the metadata Table of Contents in the document (the PDF
Outline). If the document has no table of contents then it will be replaced by Outline). If the document has no table of contents then it will be replaced by
empty text. If a single PDF page has multiple sections, the first section on empty text. If a single PDF page has multiple sections, the first section on
the page will be used. the page will be used. Similarly, there is a variable named _TOP_LEVEL_SECTION_
that can be used to ge the name of the current top-level section.
You can even use javascript inside the header and footer templates, for You can even use javascript inside the header and footer templates, for
example, the following template will cause page numbers to start at 4 instead example, the following template will cause page numbers to start at 4 instead

Binary file not shown.

View File

@ -309,11 +309,12 @@ class PagedDisplay
title = py_bridge.title() title = py_bridge.title()
author = py_bridge.author() author = py_bridge.author()
section = py_bridge.section() section = py_bridge.section()
tl_section = py_bridge.tl_section()
if this.header != null if this.header != null
this.header.innerHTML = this.header_template.replace(/_PAGENUM_/g, pagenum+"").replace(/_TITLE_/g, title+"").replace(/_AUTHOR_/g, author+"").replace(/_SECTION_/g, section+"") this.header.innerHTML = this.header_template.replace(/_PAGENUM_/g, pagenum+"").replace(/_TITLE_/g, title+"").replace(/_AUTHOR_/g, author+"").replace(/_TOP_LEVEL_SECTION_/g, tl_section+"").replace(/_SECTION_/g, section+"")
runscripts(this.header) runscripts(this.header)
if this.footer != null if this.footer != null
this.footer.innerHTML = this.footer_template.replace(/_PAGENUM_/g, pagenum+"").replace(/_TITLE_/g, title+"").replace(/_AUTHOR_/g, author+"").replace(/_SECTION_/g, section+"") this.footer.innerHTML = this.footer_template.replace(/_PAGENUM_/g, pagenum+"").replace(/_TITLE_/g, title+"").replace(/_AUTHOR_/g, author+"").replace(/_TOP_LEVEL_SECTION_/g, tl_section+"").replace(/_SECTION_/g, section+"")
runscripts(this.footer) runscripts(this.footer)
fit_images: () -> fit_images: () ->

View File

@ -145,6 +145,10 @@ class PDFWriter(QObject):
def section(self): def section(self):
return self.current_section return self.current_section
@pyqtSlot(result=unicode)
def tl_section(self):
return self.current_tl_section
def __init__(self, opts, log, cover_data=None, toc=None): def __init__(self, opts, log, cover_data=None, toc=None):
from calibre.gui2 import must_use_qt from calibre.gui2 import must_use_qt
must_use_qt() must_use_qt()
@ -169,6 +173,7 @@ class PDFWriter(QObject):
Qt.ScrollBarAlwaysOff) Qt.ScrollBarAlwaysOff)
self.report_progress = lambda x, y: x self.report_progress = lambda x, y: x
self.current_section = '' self.current_section = ''
self.current_tl_section = ''
def dump(self, items, out_stream, pdf_metadata): def dump(self, items, out_stream, pdf_metadata):
opts = self.opts opts = self.opts
@ -310,11 +315,12 @@ class PDFWriter(QObject):
self.loop.processEvents(self.loop.ExcludeUserInputEvents) self.loop.processEvents(self.loop.ExcludeUserInputEvents)
evaljs('document.getElementById("MathJax_Message").style.display="none";') evaljs('document.getElementById("MathJax_Message").style.display="none";')
def get_sections(self, anchor_map): def get_sections(self, anchor_map, only_top_level=False):
sections = defaultdict(list) sections = defaultdict(list)
ci = os.path.abspath(os.path.normcase(self.current_item)) ci = os.path.abspath(os.path.normcase(self.current_item))
if self.toc is not None: if self.toc is not None:
for toc in self.toc.flat(): tocentries = self.toc.top_level_items() if only_top_level else self.toc.flat()
for toc in tocentries:
path = toc.abspath or None path = toc.abspath or None
frag = toc.fragment or None frag = toc.fragment or None
if path is None: if path is None:
@ -362,6 +368,7 @@ class PDFWriter(QObject):
if not isinstance(amap, dict): if not isinstance(amap, dict):
amap = {'links':[], 'anchors':{}} # Some javascript error occurred amap = {'links':[], 'anchors':{}} # Some javascript error occurred
sections = self.get_sections(amap['anchors']) sections = self.get_sections(amap['anchors'])
tl_sections = self.get_sections(amap['anchors'], True)
col = 0 col = 0
if self.header: if self.header:
@ -376,13 +383,16 @@ class PDFWriter(QObject):
start_page = self.current_page_num start_page = self.current_page_num
mf = self.view.page().mainFrame() mf = self.view.page().mainFrame()
def set_section(col, sections, attr):
# If this page has no section, use the section from the previous page
idx = col if col in sections else col - 1 if col - 1 in sections else None
if idx is not None:
setattr(self, attr, sections[idx][0])
while True: while True:
if col in sections: set_section(col, sections, 'current_section')
self.current_section = sections[col][0] set_section(col, tl_sections, 'current_tl_section')
elif col - 1 in sections:
# Ensure we are using the last section on the previous page as
# the section for this page, since this page has no sections
self.current_section = sections[col-1][-1]
self.doc.init_page() self.doc.init_page()
if self.header or self.footer: if self.header or self.footer:
evaljs('paged_display.update_header_footer(%d)'%self.current_page_num) evaljs('paged_display.update_header_footer(%d)'%self.current_page_num)
@ -404,6 +414,3 @@ class PDFWriter(QObject):
if not self.doc.errors_occurred: if not self.doc.errors_occurred:
self.doc.add_links(self.current_item, start_page, amap['links'], self.doc.add_links(self.current_item, start_page, amap['links'],
amap['anchors']) amap['anchors'])