You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
127 lines
3.7 KiB
127 lines
3.7 KiB
"""Generates PDF cards from a calibre metadata.db."""
|
|
|
|
import os
|
|
import shutil
|
|
from pathlib import Path
|
|
from textwrap import shorten
|
|
|
|
from calibrestekje import Book, Comment, Publisher, init_session
|
|
from reportlab.lib.pagesizes import *
|
|
from reportlab.lib.styles import ParagraphStyle, getSampleStyleSheet
|
|
from reportlab.pdfgen import canvas
|
|
from reportlab.platypus import PageBreak, Paragraph, SimpleDocTemplate, Spacer
|
|
|
|
CWD = Path().resolve()
|
|
NUM_WORDS_COMMENT = 50
|
|
|
|
from html.parser import HTMLParser
|
|
from io import StringIO
|
|
|
|
|
|
class MLStripper(HTMLParser):
|
|
"""https://stackoverflow.com/a/925630"""
|
|
|
|
def __init__(self):
|
|
super().__init__()
|
|
self.reset()
|
|
self.strict = False
|
|
self.convert_charrefs = True
|
|
self.text = StringIO()
|
|
|
|
def handle_data(self, d):
|
|
self.text.write(d)
|
|
|
|
def get_data(self):
|
|
return self.text.getvalue()
|
|
|
|
|
|
def strip_tags(html):
|
|
"""HTML stripper."""
|
|
s = MLStripper()
|
|
s.feed(html)
|
|
return s.get_data()
|
|
|
|
|
|
def make_cards(filepath, db_path, side_a, side_b):
|
|
"""The main entrypoint for card generation."""
|
|
filename = os.path.basename(filepath)
|
|
doc = create_doc(filename)
|
|
content = get_fields(db_path, side_a, side_b)
|
|
doc.build(content)
|
|
shutil.move(os.path.join(CWD, filename), filepath)
|
|
|
|
|
|
def select_fields(fields, content, styles, book):
|
|
appended = True
|
|
|
|
if "title" in fields:
|
|
tag = "<font size=12>{}</font>".format(strip_tags(book.title))
|
|
ptitle = Paragraph(tag, styles["Italic"])
|
|
content.append(ptitle)
|
|
content.append(Spacer(1, 12))
|
|
|
|
if "timestamp" in fields:
|
|
tag = "<font size=10>Timestamp: {}</font>".format(book.timestamp)
|
|
ptime = Paragraph(tag, styles["Normal"])
|
|
content.append(ptime)
|
|
content.append(Spacer(1, 12))
|
|
|
|
if "comments" in fields:
|
|
trimmed = " ".join([c.text for c in book.comments]).split()
|
|
if len(trimmed) > NUM_WORDS_COMMENT:
|
|
comments = "{}...".format(" ".join(trimmed[:NUM_WORDS_COMMENT]))
|
|
else:
|
|
comments = "{}".format(" ".join(trimmed[:NUM_WORDS_COMMENT]))
|
|
tag = "<font size=10>{}</font>".format(strip_tags(comments))
|
|
pcomments = Paragraph(tag)
|
|
content.append(pcomments)
|
|
content.append(Spacer(6, 12))
|
|
|
|
if "authors" in fields:
|
|
format_string = "<font size=12>{}</font>"
|
|
all_authors = [strip_tags(author.name) for author in book.authors]
|
|
glued_together = format_string.format(", ".join(all_authors))
|
|
|
|
p = Paragraph(glued_together, styles["Normal"])
|
|
content.append(p)
|
|
content.append(Spacer(6, 12))
|
|
|
|
if "tags" in fields:
|
|
format_string = "<font size=10>{}</font>"
|
|
all_tags = [strip_tags(tag.name) for tag in book.tags]
|
|
if not all_tags:
|
|
appended = False
|
|
tags_glued_together = format_string.format(", ".join(all_tags))
|
|
p = Paragraph(tags_glued_together, styles["Normal"])
|
|
content.append(p)
|
|
content.append(Spacer(6, 12))
|
|
|
|
return content, appended
|
|
|
|
|
|
def get_fields(db_path, side_a, side_b):
|
|
"""Retrieve fields from the metadata."""
|
|
content = []
|
|
styles = getSampleStyleSheet()
|
|
session = init_session(db_path)
|
|
|
|
for book in session.query(Book).all():
|
|
content, _ = select_fields(side_a, content, styles, book)
|
|
content.append(PageBreak())
|
|
content, appended = select_fields(side_b, content, styles, book)
|
|
if appended:
|
|
content.append(PageBreak())
|
|
|
|
return content
|
|
|
|
|
|
def create_doc(filename):
|
|
"""Build the Report Lab document template."""
|
|
return SimpleDocTemplate(
|
|
filename,
|
|
pagesize=landscape(A6),
|
|
rightMargin=18,
|
|
leftMargin=18,
|
|
topMargin=0,
|
|
bottomMargin=18,
|
|
)
|
|
|