New docx templates
This commit is contained in:
@@ -4,6 +4,7 @@ Models for the main submission and sample types.
|
|||||||
from __future__ import annotations
|
from __future__ import annotations
|
||||||
|
|
||||||
import sys
|
import sys
|
||||||
|
from copy import deepcopy
|
||||||
from getpass import getuser
|
from getpass import getuser
|
||||||
import logging, uuid, tempfile, re, yaml, base64
|
import logging, uuid, tempfile, re, yaml, base64
|
||||||
from zipfile import ZipFile
|
from zipfile import ZipFile
|
||||||
@@ -728,6 +729,11 @@ class BasicSubmission(BaseClass):
|
|||||||
logger.info(f"Hello from {cls.__mapper_args__['polymorphic_identity']} autofill")
|
logger.info(f"Hello from {cls.__mapper_args__['polymorphic_identity']} autofill")
|
||||||
return input_excel
|
return input_excel
|
||||||
|
|
||||||
|
@classmethod
|
||||||
|
def custom_docx_writer(cls, input_dict):
|
||||||
|
|
||||||
|
return input_dict
|
||||||
|
|
||||||
@classmethod
|
@classmethod
|
||||||
def enforce_name(cls, instr: str, data: dict | None = {}) -> str:
|
def enforce_name(cls, instr: str, data: dict | None = {}) -> str:
|
||||||
"""
|
"""
|
||||||
@@ -1439,7 +1445,7 @@ class Wastewater(BasicSubmission):
|
|||||||
dummy_samples = []
|
dummy_samples = []
|
||||||
for item in input_dict['samples']:
|
for item in input_dict['samples']:
|
||||||
# logger.debug(f"Sample dict: {item}")
|
# logger.debug(f"Sample dict: {item}")
|
||||||
thing = item
|
thing = deepcopy(item)
|
||||||
try:
|
try:
|
||||||
thing['row'] = thing['source_row']
|
thing['row'] = thing['source_row']
|
||||||
thing['column'] = thing['source_column']
|
thing['column'] = thing['source_column']
|
||||||
@@ -1486,6 +1492,28 @@ class Wastewater(BasicSubmission):
|
|||||||
self.update_subsampassoc(sample=sample, input_dict=sample_dict)
|
self.update_subsampassoc(sample=sample, input_dict=sample_dict)
|
||||||
# self.report.add_result(Result(msg=f"We added PCR info to {sub.rsl_plate_num}.", status='Information'))
|
# self.report.add_result(Result(msg=f"We added PCR info to {sub.rsl_plate_num}.", status='Information'))
|
||||||
|
|
||||||
|
@classmethod
|
||||||
|
def custom_docx_writer(cls, input_dict):
|
||||||
|
from backend.excel.writer import DocxWriter
|
||||||
|
input_dict = super().custom_docx_writer(input_dict)
|
||||||
|
well_24 = []
|
||||||
|
samples_copy = deepcopy(input_dict['samples'])
|
||||||
|
for sample in sorted(samples_copy, key=itemgetter('column', 'row')):
|
||||||
|
# for sample in input_dict['samples']:
|
||||||
|
try:
|
||||||
|
row = sample['source_row']
|
||||||
|
except KeyError:
|
||||||
|
continue
|
||||||
|
try:
|
||||||
|
column = sample['source_column']
|
||||||
|
except KeyError:
|
||||||
|
continue
|
||||||
|
copy = dict(submitter_id=sample['submitter_id'], row=row, column=column)
|
||||||
|
well_24.append(copy)
|
||||||
|
input_dict['origin_plate'] = DocxWriter.create_plate_map(sample_list=well_24, rows=4, columns=6)
|
||||||
|
return input_dict
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
class WastewaterArtic(BasicSubmission):
|
class WastewaterArtic(BasicSubmission):
|
||||||
"""
|
"""
|
||||||
|
|||||||
@@ -1,10 +1,11 @@
|
|||||||
import logging
|
import logging
|
||||||
from copy import copy
|
from copy import copy
|
||||||
|
from operator import itemgetter
|
||||||
from pathlib import Path
|
from pathlib import Path
|
||||||
# from pathlib import Path
|
# from pathlib import Path
|
||||||
from pprint import pformat
|
from pprint import pformat
|
||||||
from typing import List
|
from typing import List
|
||||||
|
from collections import OrderedDict
|
||||||
from jinja2 import TemplateNotFound
|
from jinja2 import TemplateNotFound
|
||||||
from openpyxl import load_workbook, Workbook
|
from openpyxl import load_workbook, Workbook
|
||||||
from backend.db.models import SubmissionType, KitType, BasicSubmission
|
from backend.db.models import SubmissionType, KitType, BasicSubmission
|
||||||
@@ -13,6 +14,7 @@ from io import BytesIO
|
|||||||
from collections import OrderedDict
|
from collections import OrderedDict
|
||||||
from tools import jinja_template_loading
|
from tools import jinja_template_loading
|
||||||
from docxtpl import DocxTemplate
|
from docxtpl import DocxTemplate
|
||||||
|
from docx import Document
|
||||||
|
|
||||||
logger = logging.getLogger(f"submissions.{__name__}")
|
logger = logging.getLogger(f"submissions.{__name__}")
|
||||||
|
|
||||||
@@ -460,14 +462,65 @@ class TipWriter(object):
|
|||||||
class DocxWriter(object):
|
class DocxWriter(object):
|
||||||
|
|
||||||
def __init__(self, base_dict: dict):
|
def __init__(self, base_dict: dict):
|
||||||
|
self.sub_obj = BasicSubmission.find_polymorphic_subclass(polymorphic_identity=base_dict['submission_type'])
|
||||||
env = jinja_template_loading()
|
env = jinja_template_loading()
|
||||||
temp_name = f"{base_dict['submission_type'].replace(' ', '').lower()}_document.docx"
|
temp_name = f"{base_dict['submission_type'].replace(' ', '').lower()}_subdocument.docx"
|
||||||
path = Path(env.loader.__getattribute__("searchpath")[0]).joinpath(temp_name)
|
path = Path(env.loader.__getattribute__("searchpath")[0])
|
||||||
template = DocxTemplate(path)
|
main_template = path.joinpath("basicsubmission_document.docx")
|
||||||
|
subdocument = path.joinpath(temp_name)
|
||||||
|
if subdocument.exists():
|
||||||
|
main_template = self.create_merged_template(main_template, subdocument)
|
||||||
|
self.template = DocxTemplate(main_template)
|
||||||
|
base_dict['platemap'] = self.create_plate_map(base_dict['samples'], rows=8, columns=12)
|
||||||
|
# logger.debug(pformat(base_dict['plate_map']))
|
||||||
try:
|
try:
|
||||||
template.render(base_dict)
|
base_dict['excluded'] += ["platemap"]
|
||||||
except FileNotFoundError:
|
except KeyError:
|
||||||
template = DocxTemplate(
|
base_dict['excluded'] = ["platemap"]
|
||||||
Path(env.loader.__getattribute__("searchpath")[0]).joinpath("basicsubmission_document.docx"))
|
base_dict = self.sub_obj.custom_docx_writer(base_dict)
|
||||||
template.render({"sub": base_dict})
|
# logger.debug(f"Base dict: {pformat(base_dict)}")
|
||||||
template.save("test.docx")
|
self.template.render({"sub": base_dict})
|
||||||
|
|
||||||
|
@classmethod
|
||||||
|
def create_plate_map(self, sample_list: List[dict], rows: int = 0, columns: int = 0) -> List[list]:
|
||||||
|
sample_list = sorted(sample_list, key=itemgetter('column', 'row'))
|
||||||
|
if rows == 0:
|
||||||
|
rows = max([sample['row'] for sample in sample_list])
|
||||||
|
if columns == 0:
|
||||||
|
columns = max([sample['column'] for sample in sample_list])
|
||||||
|
output = []
|
||||||
|
for row in range(0, rows):
|
||||||
|
contents = [''] * columns
|
||||||
|
for column in range(0, columns):
|
||||||
|
try:
|
||||||
|
ooi = [item for item in sample_list if item['row']==row+1 and item['column']==column+1][0]
|
||||||
|
except IndexError:
|
||||||
|
continue
|
||||||
|
contents[column] = ooi['submitter_id']
|
||||||
|
# contents = [sample['submitter_id'] for sample in sample_list if sample['row'] == row + 1]
|
||||||
|
# contents = [f"{sample['row']},{sample['column']}" for sample in sample_list if sample['row'] == row + 1]
|
||||||
|
if len(contents) < columns:
|
||||||
|
contents += [''] * (columns - len(contents))
|
||||||
|
if not contents:
|
||||||
|
contents = [''] * columns
|
||||||
|
output.append(contents)
|
||||||
|
return output
|
||||||
|
|
||||||
|
def create_merged_template(self, *args):
|
||||||
|
merged_document = Document()
|
||||||
|
output = BytesIO()
|
||||||
|
for index, file in enumerate(args):
|
||||||
|
sub_doc = Document(file)
|
||||||
|
# Don't add a page break if you've reached the last file.
|
||||||
|
# if index < len(args) - 1:
|
||||||
|
# sub_doc.add_page_break()
|
||||||
|
for element in sub_doc.element.body:
|
||||||
|
merged_document.element.body.append(element)
|
||||||
|
merged_document.save(output)
|
||||||
|
return output
|
||||||
|
|
||||||
|
|
||||||
|
def save(self, filename: Path | str):
|
||||||
|
if isinstance(filename, str):
|
||||||
|
filename = Path(filename)
|
||||||
|
self.template.save(filename)
|
||||||
|
|||||||
@@ -327,17 +327,17 @@ class PydEquipment(BaseModel, extra='ignore'):
|
|||||||
process = Process.query(name=self.processes[0])
|
process = Process.query(name=self.processes[0])
|
||||||
if process is None:
|
if process is None:
|
||||||
logger.error(f"Found unknown process: {process}.")
|
logger.error(f"Found unknown process: {process}.")
|
||||||
from frontend.widgets.pop_ups import QuestionAsker
|
# from frontend.widgets.pop_ups import QuestionAsker
|
||||||
dlg = QuestionAsker(title="Add Process?",
|
# dlg = QuestionAsker(title="Add Process?",
|
||||||
message=f"Unable to find {self.processes[0]} in the database.\nWould you like to add it?")
|
# message=f"Unable to find {self.processes[0]} in the database.\nWould you like to add it?")
|
||||||
if dlg.exec():
|
# if dlg.exec():
|
||||||
kit = submission.extraction_kit
|
# kit = submission.extraction_kit
|
||||||
submission_type = submission.submission_type
|
# submission_type = submission.submission_type
|
||||||
process = Process(name=self.processes[0])
|
# process = Process(name=self.processes[0])
|
||||||
process.kit_types.append(kit)
|
# process.kit_types.append(kit)
|
||||||
process.submission_types.append(submission_type)
|
# process.submission_types.append(submission_type)
|
||||||
process.equipment.append(equipment)
|
# process.equipment.append(equipment)
|
||||||
process.save()
|
# process.save()
|
||||||
assoc.process = process
|
assoc.process = process
|
||||||
assoc.role = self.role
|
assoc.role = self.role
|
||||||
else:
|
else:
|
||||||
@@ -727,7 +727,7 @@ class PydSubmission(BaseModel, extra='allow'):
|
|||||||
if equip is None:
|
if equip is None:
|
||||||
continue
|
continue
|
||||||
equip, association = equip.toSQL(submission=instance)
|
equip, association = equip.toSQL(submission=instance)
|
||||||
if association is not None:
|
if association is not None and association not in instance.submission_equipment_associations:
|
||||||
# association.save()
|
# association.save()
|
||||||
# logger.debug(
|
# logger.debug(
|
||||||
# f"Equipment association SQL object to be added to submission: {association.__dict__}")
|
# f"Equipment association SQL object to be added to submission: {association.__dict__}")
|
||||||
@@ -738,7 +738,7 @@ class PydSubmission(BaseModel, extra='allow'):
|
|||||||
continue
|
continue
|
||||||
logger.debug(f"Converting tips: {tips} to sql.")
|
logger.debug(f"Converting tips: {tips} to sql.")
|
||||||
association = tips.to_sql(submission=instance)
|
association = tips.to_sql(submission=instance)
|
||||||
if association is not None:
|
if association is not None and association not in instance.submission_tips_associations:
|
||||||
# association.save()
|
# association.save()
|
||||||
instance.submission_tips_associations.append(association)
|
instance.submission_tips_associations.append(association)
|
||||||
case item if item in instance.jsons():
|
case item if item in instance.jsons():
|
||||||
|
|||||||
@@ -59,7 +59,7 @@ class EquipmentUsage(QDialog):
|
|||||||
case _:
|
case _:
|
||||||
pass
|
pass
|
||||||
logger.debug(f"parsed output of Equsage form: {pformat(output)}")
|
logger.debug(f"parsed output of Equsage form: {pformat(output)}")
|
||||||
return [item for item in output if item is not None]
|
return [item.strip() for item in output if item is not None]
|
||||||
|
|
||||||
class LabelRow(QWidget):
|
class LabelRow(QWidget):
|
||||||
|
|
||||||
@@ -165,7 +165,7 @@ class RoleComboBox(QWidget):
|
|||||||
try:
|
try:
|
||||||
return PydEquipment(
|
return PydEquipment(
|
||||||
name=eq.name,
|
name=eq.name,
|
||||||
processes=[self.process.currentText()],
|
processes=[self.process.currentText().strip()],
|
||||||
role=self.role.name,
|
role=self.role.name,
|
||||||
asset_number=eq.asset_number,
|
asset_number=eq.asset_number,
|
||||||
nickname=eq.nickname,
|
nickname=eq.nickname,
|
||||||
|
|||||||
@@ -1,3 +1,5 @@
|
|||||||
|
from PyQt6.QtGui import QPageSize
|
||||||
|
from PyQt6.QtPrintSupport import QPrinter
|
||||||
from PyQt6.QtWidgets import (QDialog, QPushButton, QVBoxLayout, QMessageBox,
|
from PyQt6.QtWidgets import (QDialog, QPushButton, QVBoxLayout, QMessageBox,
|
||||||
QDialogButtonBox, QTextEdit)
|
QDialogButtonBox, QTextEdit)
|
||||||
from PyQt6.QtWebEngineWidgets import QWebEngineView
|
from PyQt6.QtWebEngineWidgets import QWebEngineView
|
||||||
@@ -17,6 +19,8 @@ from pprint import pformat
|
|||||||
from html2image import Html2Image
|
from html2image import Html2Image
|
||||||
from PIL import Image
|
from PIL import Image
|
||||||
from typing import List
|
from typing import List
|
||||||
|
from backend.excel.writer import DocxWriter
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
logger = logging.getLogger(f"submissions.{__name__}")
|
logger = logging.getLogger(f"submissions.{__name__}")
|
||||||
@@ -90,13 +94,17 @@ class SubmissionDetails(QDialog):
|
|||||||
# del self.base_dict['id']
|
# del self.base_dict['id']
|
||||||
# logger.debug(f"Creating barcode.")
|
# logger.debug(f"Creating barcode.")
|
||||||
# logger.debug(f"Making platemap...")
|
# logger.debug(f"Making platemap...")
|
||||||
|
|
||||||
self.base_dict['platemap'] = BasicSubmission.make_plate_map(sample_list=submission.hitpick_plate())
|
self.base_dict['platemap'] = BasicSubmission.make_plate_map(sample_list=submission.hitpick_plate())
|
||||||
self.base_dict, self.template = submission.get_details_template(base_dict=self.base_dict)
|
self.base_dict, self.template = submission.get_details_template(base_dict=self.base_dict)
|
||||||
|
template_path = Path(self.template.environment.loader.__getattribute__("searchpath")[0])
|
||||||
|
with open(template_path.joinpath("css", "styles.css"), "r") as f:
|
||||||
|
css = f.read()
|
||||||
logger.debug(f"Submission_details: {pformat(self.base_dict)}")
|
logger.debug(f"Submission_details: {pformat(self.base_dict)}")
|
||||||
self.html = self.template.render(sub=self.base_dict, signing_permission=is_power_user())
|
self.html = self.template.render(sub=self.base_dict, signing_permission=is_power_user(), css=css)
|
||||||
self.webview.setHtml(self.html)
|
self.webview.setHtml(self.html)
|
||||||
# with open("test.html", "w") as f:
|
with open("test.html", "w") as f:
|
||||||
# f.write(self.html)
|
f.write(self.html)
|
||||||
self.setWindowTitle(f"Submission Details - {submission.rsl_plate_num}")
|
self.setWindowTitle(f"Submission Details - {submission.rsl_plate_num}")
|
||||||
|
|
||||||
@pyqtSlot(str)
|
@pyqtSlot(str)
|
||||||
@@ -112,31 +120,32 @@ class SubmissionDetails(QDialog):
|
|||||||
"""
|
"""
|
||||||
Renders submission to html, then creates and saves .pdf file to user selected file.
|
Renders submission to html, then creates and saves .pdf file to user selected file.
|
||||||
"""
|
"""
|
||||||
logger.debug(f"Base dict: {pformat(self.base_dict)}")
|
writer = DocxWriter(base_dict=self.base_dict)
|
||||||
fname = select_save_file(obj=self, default_name=self.base_dict['plate_number'], extension="docx")
|
fname = select_save_file(obj=self, default_name=self.base_dict['plate_number'], extension="docx")
|
||||||
image_io = BytesIO()
|
writer.save(fname)
|
||||||
temp_dir = Path(TemporaryDirectory().name)
|
# image_io = BytesIO()
|
||||||
hti = Html2Image(output_path=temp_dir, size=(2400, 1500))
|
# temp_dir = Path(TemporaryDirectory().name)
|
||||||
temp_file = Path(TemporaryFile(dir=temp_dir, suffix=".png").name)
|
# hti = Html2Image(output_path=temp_dir, size=(2400, 1500))
|
||||||
screenshot = hti.screenshot(self.base_dict['platemap'], save_as=temp_file.name)
|
# temp_file = Path(TemporaryFile(dir=temp_dir, suffix=".png").name)
|
||||||
export_map = Image.open(screenshot[0])
|
# screenshot = hti.screenshot(self.base_dict['platemap'], save_as=temp_file.name)
|
||||||
export_map = export_map.convert('RGB')
|
# export_map = Image.open(screenshot[0])
|
||||||
|
# export_map = export_map.convert('RGB')
|
||||||
|
# try:
|
||||||
|
# export_map.save(image_io, 'JPEG')
|
||||||
|
# except AttributeError:
|
||||||
|
# logger.error(f"No plate map found")
|
||||||
|
# self.base_dict['export_map'] = base64.b64encode(image_io.getvalue()).decode('utf-8')
|
||||||
|
# del self.base_dict['platemap']
|
||||||
|
# self.html2 = self.template.render(sub=self.base_dict)
|
||||||
try:
|
try:
|
||||||
export_map.save(image_io, 'JPEG')
|
html_to_pdf(html=self.html, output_file=fname)
|
||||||
except AttributeError:
|
|
||||||
logger.error(f"No plate map found")
|
|
||||||
self.base_dict['export_map'] = base64.b64encode(image_io.getvalue()).decode('utf-8')
|
|
||||||
del self.base_dict['platemap']
|
|
||||||
self.html2 = self.template.render(sub=self.base_dict)
|
|
||||||
try:
|
|
||||||
html_to_pdf(html=self.html2, output_file=fname)
|
|
||||||
except PermissionError as e:
|
except PermissionError as e:
|
||||||
logger.error(f"Error saving pdf: {e}")
|
logger.error(f"Error saving pdf: {e}")
|
||||||
msg = QMessageBox()
|
# msg = QMessageBox()
|
||||||
msg.setText("Permission Error")
|
# msg.setText("Permission Error")
|
||||||
msg.setInformativeText(f"Looks like {fname.__str__()} is open.\nPlease close it and try again.")
|
# msg.setInformativeText(f"Looks like {fname.__str__()} is open.\nPlease close it and try again.")
|
||||||
msg.setWindowTitle("Permission Error")
|
# msg.setWindowTitle("Permission Error")
|
||||||
msg.exec()
|
# msg.exec()
|
||||||
|
|
||||||
|
|
||||||
class SubmissionComment(QDialog):
|
class SubmissionComment(QDialog):
|
||||||
|
|||||||
@@ -312,6 +312,7 @@ class SubmissionFormWidget(QWidget):
|
|||||||
if dlg.exec():
|
if dlg.exec():
|
||||||
# NOTE: Do not add duplicate reagents.
|
# NOTE: Do not add duplicate reagents.
|
||||||
result = None
|
result = None
|
||||||
|
|
||||||
else:
|
else:
|
||||||
self.app.ctx.database_session.rollback()
|
self.app.ctx.database_session.rollback()
|
||||||
report.add_result(Result(msg="Overwrite cancelled", status="Information"))
|
report.add_result(Result(msg="Overwrite cancelled", status="Information"))
|
||||||
|
|||||||
BIN
src/submissions/templates/bacterialculture_subdocument.docx
Normal file
BIN
src/submissions/templates/bacterialculture_subdocument.docx
Normal file
Binary file not shown.
@@ -2,38 +2,11 @@
|
|||||||
<html>
|
<html>
|
||||||
<head>
|
<head>
|
||||||
{% block head %}
|
{% block head %}
|
||||||
|
{% if css %}
|
||||||
<style>
|
<style>
|
||||||
/* Tooltip container */
|
{{ css }}
|
||||||
.tooltip {
|
|
||||||
position: relative;
|
|
||||||
display: inline-block;
|
|
||||||
border-bottom: 1px dotted black; /* If you want dots under the hoverable text */
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Tooltip text */
|
|
||||||
.tooltip .tooltiptext {
|
|
||||||
visibility: hidden;
|
|
||||||
width: 120px;
|
|
||||||
background-color: black;
|
|
||||||
color: #fff;
|
|
||||||
text-align: center;
|
|
||||||
padding: 5px 0;
|
|
||||||
border-radius: 6px;
|
|
||||||
|
|
||||||
/* Position the tooltip text - see examples below! */
|
|
||||||
position: absolute;
|
|
||||||
z-index: 1;
|
|
||||||
bottom: 100%;
|
|
||||||
left: 50%;
|
|
||||||
margin-left: -60px;
|
|
||||||
}
|
|
||||||
/* Show the tooltip text when you mouse over the tooltip container */
|
|
||||||
.tooltip:hover .tooltiptext {
|
|
||||||
visibility: visible;
|
|
||||||
font-size: large;
|
|
||||||
}
|
|
||||||
|
|
||||||
</style>
|
</style>
|
||||||
|
{% endif %}
|
||||||
<title>Submission Details for {{ sub['Plate Number'] }}</title>
|
<title>Submission Details for {{ sub['Plate Number'] }}</title>
|
||||||
<script src="qrc:///qtwebchannel/qwebchannel.js"></script>
|
<script src="qrc:///qtwebchannel/qwebchannel.js"></script>
|
||||||
{% endblock %}
|
{% endblock %}
|
||||||
|
|||||||
BIN
src/submissions/templates/basicsubmission_document.docx
Normal file
BIN
src/submissions/templates/basicsubmission_document.docx
Normal file
Binary file not shown.
29
src/submissions/templates/css/styles.css
Normal file
29
src/submissions/templates/css/styles.css
Normal file
@@ -0,0 +1,29 @@
|
|||||||
|
/* Tooltip container */
|
||||||
|
.tooltip {
|
||||||
|
position: relative;
|
||||||
|
display: inline-block;
|
||||||
|
border-bottom: 1px dotted black; /* If you want dots under the hoverable text */
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Tooltip text */
|
||||||
|
.tooltip .tooltiptext {
|
||||||
|
visibility: hidden;
|
||||||
|
width: 120px;
|
||||||
|
background-color: black;
|
||||||
|
color: #fff;
|
||||||
|
text-align: center;
|
||||||
|
padding: 5px 0;
|
||||||
|
border-radius: 6px;
|
||||||
|
|
||||||
|
/* Position the tooltip text - see examples below! */
|
||||||
|
position: absolute;
|
||||||
|
z-index: 1;
|
||||||
|
bottom: 100%;
|
||||||
|
left: 50%;
|
||||||
|
margin-left: -60px;
|
||||||
|
}
|
||||||
|
/* Show the tooltip text when you mouse over the tooltip container */
|
||||||
|
.tooltip:hover .tooltiptext {
|
||||||
|
visibility: visible;
|
||||||
|
font-size: large;
|
||||||
|
}
|
||||||
BIN
src/submissions/templates/wastewater_subdocument.docx
Normal file
BIN
src/submissions/templates/wastewater_subdocument.docx
Normal file
Binary file not shown.
@@ -658,11 +658,13 @@ def html_to_pdf(html, output_file: Path | str):
|
|||||||
logger.debug(f"Printing PDF to {output_file}")
|
logger.debug(f"Printing PDF to {output_file}")
|
||||||
document = QWebEngineView()
|
document = QWebEngineView()
|
||||||
document.setHtml(html)
|
document.setHtml(html)
|
||||||
|
# document.show()
|
||||||
printer = QPrinter(QPrinter.PrinterMode.HighResolution)
|
printer = QPrinter(QPrinter.PrinterMode.HighResolution)
|
||||||
printer.setOutputFormat(QPrinter.OutputFormat.PdfFormat)
|
printer.setOutputFormat(QPrinter.OutputFormat.PdfFormat)
|
||||||
printer.setOutputFileName(output_file.absolute().__str__())
|
printer.setOutputFileName(output_file.absolute().__str__())
|
||||||
printer.setPageSize(QPageSize(QPageSize.PageSizeId.A4))
|
printer.setPageSize(QPageSize(QPageSize.PageSizeId.A4))
|
||||||
document.print(printer)
|
document.print(printer)
|
||||||
|
# document.close()
|
||||||
# HTML(string=html).write_pdf(output_file)
|
# HTML(string=html).write_pdf(output_file)
|
||||||
# new_parser = HtmlToDocx()
|
# new_parser = HtmlToDocx()
|
||||||
# docx = new_parser.parse_html_string(html)
|
# docx = new_parser.parse_html_string(html)
|
||||||
|
|||||||
Reference in New Issue
Block a user