mirror of
https://github.com/kovidgoyal/calibre.git
synced 2025-07-09 03:04:10 -04:00
PDF Output: Add an option to add page numbers to the bottom of every page in the generated PDF file
This commit is contained in:
parent
015f3d48a7
commit
f9a5cab366
Binary file not shown.
@ -99,6 +99,18 @@ class PDFOutput(OutputFormatPlugin):
|
||||
recommended_value=False, help=_(
|
||||
'Generate an uncompressed PDF, useful for debugging, '
|
||||
'only works with the new PDF engine.')),
|
||||
OptionRecommendation(name='pdf_page_numbers', recommended_value=False,
|
||||
help=_('Add page numbers to the bottom of every page in the generated PDF file. If you '
|
||||
'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 string _PAGENUM_ will be replaced by the current page'
|
||||
' number.')),
|
||||
OptionRecommendation(name='pdf_header_template', recommended_value=None,
|
||||
help=_('An HTML template used to generate headers on every page.'
|
||||
' The string _PAGENUM_ will be replaced by the current page'
|
||||
' number.')),
|
||||
])
|
||||
|
||||
def convert(self, oeb_book, output_path, input_plugin, opts, log):
|
||||
|
@ -29,6 +29,10 @@ class PagedDisplay
|
||||
this.current_page_height = null
|
||||
this.document_margins = null
|
||||
this.use_document_margins = false
|
||||
this.footer_template = null
|
||||
this.header_template = null
|
||||
this.header = null
|
||||
this.footer = null
|
||||
|
||||
read_document_margins: () ->
|
||||
# Read page margins from the document. First checks for an @page rule.
|
||||
@ -102,6 +106,7 @@ class PagedDisplay
|
||||
# than max_col_width
|
||||
sm += Math.ceil( (col_width - this.max_col_width) / 2*n )
|
||||
col_width = Math.max(100, ((ww - adjust)/n) - 2*sm)
|
||||
this.col_width = col_width
|
||||
this.page_width = col_width + 2*sm
|
||||
this.screen_width = this.page_width * this.cols_per_screen
|
||||
this.current_page_height = window.innerHeight - this.margin_top - this.margin_bottom
|
||||
@ -171,6 +176,30 @@ class PagedDisplay
|
||||
# log('Time to layout:', new Date().getTime() - start_time)
|
||||
return sm
|
||||
|
||||
create_header_footer: () ->
|
||||
if this.header_template != null
|
||||
this.header = document.createElement('div')
|
||||
this.header.setAttribute('style', "overflow:hidden; display:block; position:absolute; left:#{ this.side_margin }px; top: 0px; height: #{ this.margin_top }px; width: #{ this.col_width }px; margin: 0; padding: 0")
|
||||
document.body.appendChild(this.header)
|
||||
if this.footer_template != null
|
||||
this.footer = document.createElement('div')
|
||||
this.footer.setAttribute('style', "overflow:hidden; display:block; position:absolute; left:#{ this.side_margin }px; top: #{ window.innerHeight - this.margin_bottom }px; height: #{ this.margin_bottom }px; width: #{ this.col_width }px; margin: 0; padding: 0")
|
||||
document.body.appendChild(this.footer)
|
||||
this.update_header_footer(1)
|
||||
|
||||
position_header_footer: () ->
|
||||
[left, top] = calibre_utils.viewport_to_document(0, 0, document.body.ownerDocument)
|
||||
if this.header != null
|
||||
this.header.style.setProperty('left', left+'px')
|
||||
if this.footer != null
|
||||
this.footer.style.setProperty('left', left+'px')
|
||||
|
||||
update_header_footer: (pagenum) ->
|
||||
if this.header != null
|
||||
this.header.innerHTML = this.header_template.replace(/_PAGENUM_/g, pagenum+"")
|
||||
if this.footer != null
|
||||
this.footer.innerHTML = this.footer_template.replace(/_PAGENUM_/g, pagenum+"")
|
||||
|
||||
fit_images: () ->
|
||||
# Ensure no images are wider than the available width in a column. Note
|
||||
# that this method use getBoundingClientRect() which means it will
|
||||
|
@ -161,6 +161,17 @@ class PDFWriter(QObject):
|
||||
debug=self.log.debug, compress=not
|
||||
opts.uncompressed_pdf,
|
||||
mark_links=opts.pdf_mark_links)
|
||||
self.footer = opts.pdf_footer_template
|
||||
if self.footer is None and opts.pdf_page_numbers:
|
||||
self.footer = '<p style="text-align:center; text-indent: 0">_PAGENUM_</p>'
|
||||
self.header = opts.pdf_header_template
|
||||
min_margin = 36
|
||||
if self.footer and opts.margin_bottom < min_margin:
|
||||
self.log.warn('Bottom margin is too small for footer, increasing it.')
|
||||
opts.margin_bottom = min_margin
|
||||
if self.header and opts.margin_top < min_margin:
|
||||
self.log.warn('Top margin is too small for header, increasing it.')
|
||||
opts.margin_top = min_margin
|
||||
|
||||
self.page.setViewportSize(QSize(self.doc.width(), self.doc.height()))
|
||||
self.render_queue = items
|
||||
@ -264,6 +275,15 @@ class PDFWriter(QObject):
|
||||
py_bridge.value = book_indexing.all_links_and_anchors();
|
||||
'''%(self.margin_top, 0, self.margin_bottom))
|
||||
|
||||
if self.header:
|
||||
self.bridge_value = self.header
|
||||
evaljs('paged_display.header_template = py_bridge.value')
|
||||
if self.footer:
|
||||
self.bridge_value = self.footer
|
||||
evaljs('paged_display.footer_template = py_bridge.value')
|
||||
if self.header or self.footer:
|
||||
evaljs('paged_display.create_header_footer();')
|
||||
|
||||
amap = self.bridge_value
|
||||
if not isinstance(amap, dict):
|
||||
amap = {'links':[], 'anchors':{}} # Some javascript error occurred
|
||||
@ -272,6 +292,8 @@ class PDFWriter(QObject):
|
||||
mf = self.view.page().mainFrame()
|
||||
while True:
|
||||
self.doc.init_page()
|
||||
if self.header or self.footer:
|
||||
evaljs('paged_display.update_header_footer(%d)'%self.current_page_num)
|
||||
self.painter.save()
|
||||
mf.render(self.painter)
|
||||
self.painter.restore()
|
||||
@ -279,7 +301,7 @@ class PDFWriter(QObject):
|
||||
self.doc.end_page()
|
||||
if not nsl[1] or nsl[0] <= 0:
|
||||
break
|
||||
evaljs('window.scrollTo(%d, 0)'%nsl[0])
|
||||
evaljs('window.scrollTo(%d, 0); paged_display.position_header_footer();'%nsl[0])
|
||||
if self.doc.errors_occurred:
|
||||
break
|
||||
|
||||
|
@ -22,7 +22,7 @@ class PluginWidget(Widget, Ui_Form):
|
||||
'override_profile_size', 'paper_size', 'custom_size',
|
||||
'preserve_cover_aspect_ratio', 'pdf_serif_family', 'unit',
|
||||
'pdf_sans_family', 'pdf_mono_family', 'pdf_standard_font',
|
||||
'pdf_default_font_size', 'pdf_mono_font_size'])
|
||||
'pdf_default_font_size', 'pdf_mono_font_size', 'pdf_page_numbers'])
|
||||
self.db, self.book_id = db, book_id
|
||||
|
||||
for x in get_option('paper_size').option.choices:
|
||||
|
@ -84,7 +84,7 @@
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="5" column="0">
|
||||
<item row="6" column="0">
|
||||
<widget class="QLabel" name="label_4">
|
||||
<property name="text">
|
||||
<string>Se&rif family:</string>
|
||||
@ -94,10 +94,10 @@
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="5" column="1">
|
||||
<item row="6" column="1">
|
||||
<widget class="QFontComboBox" name="opt_pdf_serif_family"/>
|
||||
</item>
|
||||
<item row="6" column="0">
|
||||
<item row="7" column="0">
|
||||
<widget class="QLabel" name="label_5">
|
||||
<property name="text">
|
||||
<string>&Sans family:</string>
|
||||
@ -107,10 +107,10 @@
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="6" column="1">
|
||||
<item row="7" column="1">
|
||||
<widget class="QFontComboBox" name="opt_pdf_sans_family"/>
|
||||
</item>
|
||||
<item row="7" column="0">
|
||||
<item row="8" column="0">
|
||||
<widget class="QLabel" name="label_6">
|
||||
<property name="text">
|
||||
<string>&Monospace family:</string>
|
||||
@ -120,10 +120,10 @@
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="7" column="1">
|
||||
<item row="8" column="1">
|
||||
<widget class="QFontComboBox" name="opt_pdf_mono_family"/>
|
||||
</item>
|
||||
<item row="8" column="0">
|
||||
<item row="9" column="0">
|
||||
<widget class="QLabel" name="label_7">
|
||||
<property name="text">
|
||||
<string>S&tandard font:</string>
|
||||
@ -133,10 +133,10 @@
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="8" column="1">
|
||||
<item row="9" column="1">
|
||||
<widget class="QComboBox" name="opt_pdf_standard_font"/>
|
||||
</item>
|
||||
<item row="9" column="0">
|
||||
<item row="10" column="0">
|
||||
<widget class="QLabel" name="label_8">
|
||||
<property name="text">
|
||||
<string>Default font si&ze:</string>
|
||||
@ -146,14 +146,14 @@
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="9" column="1">
|
||||
<item row="10" column="1">
|
||||
<widget class="QSpinBox" name="opt_pdf_default_font_size">
|
||||
<property name="suffix">
|
||||
<string> px</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="10" column="0">
|
||||
<item row="11" column="0">
|
||||
<widget class="QLabel" name="label_9">
|
||||
<property name="text">
|
||||
<string>Monospace &font size:</string>
|
||||
@ -163,14 +163,14 @@
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="10" column="1">
|
||||
<item row="11" column="1">
|
||||
<widget class="QSpinBox" name="opt_pdf_mono_font_size">
|
||||
<property name="suffix">
|
||||
<string> px</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="11" column="0">
|
||||
<item row="12" column="0">
|
||||
<spacer name="verticalSpacer">
|
||||
<property name="orientation">
|
||||
<enum>Qt::Vertical</enum>
|
||||
@ -183,6 +183,13 @@
|
||||
</property>
|
||||
</spacer>
|
||||
</item>
|
||||
<item row="5" column="0" colspan="2">
|
||||
<widget class="QCheckBox" name="opt_pdf_page_numbers">
|
||||
<property name="text">
|
||||
<string>Add page &numbers to the bottom of every page</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
</widget>
|
||||
<resources/>
|
||||
|
Loading…
x
Reference in New Issue
Block a user