diff --git a/manual/conversion.rst b/manual/conversion.rst index 2e0876bb7c..14710f3f6a 100644 --- a/manual/conversion.rst +++ b/manual/conversion.rst @@ -794,6 +794,16 @@ template:: This will display the title at the left and the author at the right, in a font size smaller than the main text. +Finally, you can also use the current section in templates, as shown below:: + +
_SECTION_
+ +_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 +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 +the page will be used. + .. note:: When adding headers and footers make sure you set the page top and bottom margins to large enough values, under the Page Setup section of the conversion dialog. diff --git a/resources/compiled_coffeescript.zip b/resources/compiled_coffeescript.zip index 19d15f6f13..d5b7086600 100644 Binary files a/resources/compiled_coffeescript.zip and b/resources/compiled_coffeescript.zip differ diff --git a/src/calibre/ebooks/conversion/plugins/pdf_output.py b/src/calibre/ebooks/conversion/plugins/pdf_output.py index e336336939..dc943eec30 100644 --- a/src/calibre/ebooks/conversion/plugins/pdf_output.py +++ b/src/calibre/ebooks/conversion/plugins/pdf_output.py @@ -104,11 +104,11 @@ class PDFOutput(OutputFormatPlugin): 'specify a footer template, it will take precedence ' 'over this option.')), OptionRecommendation(name='pdf_footer_template', recommended_value=None, - help=_('An HTML template used to generate footers on every page.' - ' The strings _PAGENUM_, _TITLE_ and _AUTHOR_ will be replaced by their current values.')), + help=_('An HTML template used to generate %s on every page.' + ' The strings _PAGENUM_, _TITLE_, _AUTHOR_ and _SECTION_ will be replaced by their current values.')%_('footers')), OptionRecommendation(name='pdf_header_template', recommended_value=None, - help=_('An HTML template used to generate headers on every page.' - ' The strings _PAGENUM_, _TITLE_ and _AUTHOR_ will be replaced by their current values.')), + help=_('An HTML template used to generate %s on every page.' + ' The strings _PAGENUM_, _TITLE_, _AUTHOR_ and _SECTION_ will be replaced by their current values.')%_('headers')), ]) def convert(self, oeb_book, output_path, input_plugin, opts, log): diff --git a/src/calibre/ebooks/oeb/display/paged.coffee b/src/calibre/ebooks/oeb/display/paged.coffee index bb66c20efb..f97f1b3cf8 100644 --- a/src/calibre/ebooks/oeb/display/paged.coffee +++ b/src/calibre/ebooks/oeb/display/paged.coffee @@ -216,10 +216,11 @@ class PagedDisplay this.hf_style.innerHTML = "#pdf_page_header_#{ this.hf_uuid } .#{ cls }, #pdf_page_footer_#{ this.hf_uuid } .#{ cls } { display: none }" title = py_bridge.title() author = py_bridge.author() + section = py_bridge.section() if this.header != null - this.header.innerHTML = this.header_template.replace(/_PAGENUM_/g, pagenum+"").replace(/_TITLE_/g, title+"").replace(/_AUTHOR_/g, author+"") + this.header.innerHTML = this.header_template.replace(/_PAGENUM_/g, pagenum+"").replace(/_TITLE_/g, title+"").replace(/_AUTHOR_/g, author+"").replace(/_SECTION_/g, section+"") if this.footer != null - this.footer.innerHTML = this.footer_template.replace(/_PAGENUM_/g, pagenum+"").replace(/_TITLE_/g, title+"").replace(/_AUTHOR_/g, author+"") + this.footer.innerHTML = this.footer_template.replace(/_PAGENUM_/g, pagenum+"").replace(/_TITLE_/g, title+"").replace(/_AUTHOR_/g, author+"").replace(/_SECTION_/g, section+"") fit_images: () -> # Ensure no images are wider than the available width in a column. Note diff --git a/src/calibre/ebooks/pdf/render/from_html.py b/src/calibre/ebooks/pdf/render/from_html.py index e56375b7d0..ae1083bb56 100644 --- a/src/calibre/ebooks/pdf/render/from_html.py +++ b/src/calibre/ebooks/pdf/render/from_html.py @@ -138,6 +138,10 @@ class PDFWriter(QObject): def author(self): return self.doc_author + @pyqtSlot(result=unicode) + def section(self): + return self.current_section + def __init__(self, opts, log, cover_data=None, toc=None): from calibre.gui2 import is_ok_to_use_qt if not is_ok_to_use_qt(): @@ -162,6 +166,7 @@ class PDFWriter(QObject): self.view.page().mainFrame().setScrollBarPolicy(x, Qt.ScrollBarAlwaysOff) self.report_progress = lambda x, y: x + self.current_section = '' def dump(self, items, out_stream, pdf_metadata): opts = self.opts @@ -287,6 +292,25 @@ class PDFWriter(QObject): self.loop.processEvents(self.loop.ExcludeUserInputEvents) evaljs('document.getElementById("MathJax_Message").style.display="none";') + def get_sections(self, anchor_map): + sections = {} + ci = os.path.abspath(os.path.normcase(self.current_item)) + if self.toc is not None: + for toc in self.toc.flat(): + path = toc.abspath or None + frag = toc.fragment or None + if path is None: + continue + path = os.path.abspath(os.path.normcase(path)) + if path == ci: + col = 0 + if frag and frag in anchor_map: + col = anchor_map[frag]['column'] + if col not in sections: + sections[col] = toc.text or _('Untitled') + + return sections + def do_paged_render(self): if self.paged_js is None: import uuid @@ -321,6 +345,8 @@ class PDFWriter(QObject): amap = self.bridge_value if not isinstance(amap, dict): amap = {'links':[], 'anchors':{}} # Some javascript error occurred + sections = self.get_sections(amap['anchors']) + col = 0 if self.header: self.bridge_value = self.header @@ -335,6 +361,8 @@ class PDFWriter(QObject): mf = self.view.page().mainFrame() while True: + if col in sections: + self.current_section = sections[col] self.doc.init_page() if self.header or self.footer: evaljs('paged_display.update_header_footer(%d)'%self.current_page_num) @@ -348,8 +376,10 @@ class PDFWriter(QObject): evaljs('window.scrollTo(%d, 0); paged_display.position_header_footer();'%nsl[0]) if self.doc.errors_occurred: break + col += 1 if not self.doc.errors_occurred: self.doc.add_links(self.current_item, start_page, amap['links'], amap['anchors']) +