mirror of
https://github.com/Kalenis/kalenislims.git
synced 2023-12-14 07:13:04 +01:00
103 lines
3.8 KiB
Python
103 lines
3.8 KiB
Python
# This file is part of lims_report_html module for Tryton.
|
|
# The COPYRIGHT file at the top level of this repository contains
|
|
# the full copyright notices and license terms.
|
|
|
|
from weasyprint import HTML, CSS
|
|
|
|
|
|
class PdfGenerator:
|
|
|
|
def __init__(self, main_html, header_html=None, footer_html=None,
|
|
base_url=None, side_margin=2, extra_vertical_margin=30,
|
|
stylesheets=None, page_orientation='portrait'):
|
|
self.main_html = main_html
|
|
self.header_html = header_html
|
|
self.footer_html = footer_html
|
|
self.base_url = base_url
|
|
self.side_margin = side_margin
|
|
self.extra_vertical_margin = extra_vertical_margin
|
|
self.stylesheets = stylesheets or []
|
|
self.page_orientation = page_orientation
|
|
|
|
@staticmethod
|
|
def get_element(boxes, element):
|
|
for box in boxes:
|
|
if box.element_tag == element:
|
|
return box
|
|
return PdfGenerator.get_element(box.all_children(), element)
|
|
|
|
def render_html(self):
|
|
if self.header_html:
|
|
header_body, header_height = self._compute_overlay_element(
|
|
'header')
|
|
else:
|
|
header_body, header_height = None, 0
|
|
|
|
if self.footer_html:
|
|
footer_body, footer_height = self._compute_overlay_element(
|
|
'footer')
|
|
else:
|
|
footer_body, footer_height = None, 0
|
|
|
|
margins = '{header_size}px {side_margin} {footer_size}px {side_margin}'.format(
|
|
header_size=header_height + self.extra_vertical_margin,
|
|
footer_size=footer_height + self.extra_vertical_margin,
|
|
side_margin='{}cm'.format(self.side_margin),
|
|
)
|
|
content_print_layout = ('@page {size: A4 %s; margin: %s;}' %
|
|
(self.page_orientation,
|
|
margins)
|
|
)
|
|
stylesheets = [CSS(string=content_print_layout)]
|
|
for sheet in self.stylesheets:
|
|
stylesheets.append(CSS(string=sheet))
|
|
|
|
html = HTML(
|
|
string=self.main_html,
|
|
base_url=self.base_url,
|
|
)
|
|
main_doc = html.render(stylesheets=stylesheets)
|
|
|
|
if self.header_html or self.footer_html:
|
|
self._apply_overlay_on_main(main_doc, header_body, footer_body)
|
|
|
|
return main_doc
|
|
|
|
def _compute_overlay_element(self, element: str):
|
|
overlay_layout = (
|
|
'@page {size: A4 %s; margin: 0;}' % self.page_orientation +
|
|
'\nheader {position: fixed; width: 100%; top: 0;}' +
|
|
'\nfooter {position: fixed; width: 100%; bottom: 0;}')
|
|
stylesheets = [CSS(string=overlay_layout)]
|
|
for sheet in self.stylesheets:
|
|
stylesheets.append(CSS(string=sheet))
|
|
|
|
html = HTML(
|
|
string=getattr(self, '{}_html'.format(element)),
|
|
base_url=self.base_url,
|
|
)
|
|
element_doc = html.render(stylesheets=stylesheets)
|
|
element_page = element_doc.pages[0]
|
|
element_body = PdfGenerator.get_element(
|
|
element_page._page_box.all_children(), 'body')
|
|
element_body = element_body.copy_with_children(
|
|
element_body.all_children())
|
|
element_html = PdfGenerator.get_element(
|
|
element_page._page_box.all_children(), element)
|
|
|
|
if element == 'header':
|
|
element_height = element_html.height
|
|
if element == 'footer':
|
|
element_height = element_page.height - element_html.position_y
|
|
|
|
return element_body, element_height
|
|
|
|
def _apply_overlay_on_main(self, main_doc,
|
|
header_body=None, footer_body=None):
|
|
for page in main_doc.pages:
|
|
page_body = PdfGenerator.get_element(
|
|
page._page_box.all_children(), 'body')
|
|
if header_body:
|
|
page_body.children += header_body.all_children()
|
|
if footer_body:
|
|
page_body.children += footer_body.all_children()
|