Add option to add pdf page with option information (#198)

This adds options --info and -info-all:
--info to add a page that has all the options used for the PDF file.
--info-all is the same as --info, but includes pages with all the possible options that can be used.
This commit is contained in:
Wendel Voigt 2018-04-06 17:57:49 -05:00 committed by Peter
parent 0a73f57b36
commit 11257093f2
2 changed files with 113 additions and 3 deletions

View File

@ -7,8 +7,8 @@ import pkg_resources
from reportlab.lib.units import cm from reportlab.lib.units import cm
from reportlab.pdfbase import pdfmetrics from reportlab.pdfbase import pdfmetrics
from reportlab.lib.styles import getSampleStyleSheet from reportlab.lib.styles import getSampleStyleSheet
from reportlab.platypus import Paragraph from reportlab.platypus import Paragraph, XPreformatted
from reportlab.lib.enums import TA_JUSTIFY, TA_CENTER from reportlab.lib.enums import TA_JUSTIFY, TA_CENTER, TA_LEFT
from reportlab.pdfgen import canvas from reportlab.pdfgen import canvas
from reportlab.pdfbase.ttfonts import TTFont from reportlab.pdfbase.ttfonts import TTFont
from reportlab.pdfbase.pdfmetrics import stringWidth from reportlab.pdfbase.pdfmetrics import stringWidth
@ -61,6 +61,100 @@ class DividerDrawer(object):
pkg_resources.resource_filename('domdiv', pkg_resources.resource_filename('domdiv',
self.font_mapping[fonttype][0]))) self.font_mapping[fonttype][0])))
self.font_mapping[fonttype] = ftag self.font_mapping[fonttype] = ftag
self.font_mapping['Monospaced'] = 'Courier'
def drawTextPages(self, pages, margin=1.0, fontsize=10, leading=10, spacer=0.05):
s = getSampleStyleSheet()['BodyText']
s.fontName = self.font_mapping['Monospaced']
s.alignment = TA_LEFT
textHorizontalMargin = margin * cm
textVerticalMargin = margin * cm
textBoxWidth = self.options.paperwidth - 2 * textHorizontalMargin
textBoxHeight = self.options.paperheight - 2 * textVerticalMargin
minSpacerHeight = 0.05 * cm
for page in pages:
s.fontsize = fontsize
s.leading = leading
spacerHeight = spacer * cm
text = re.split("\n", page)
while True:
paragraphs = []
# this accounts for the spacers we insert between paragraphs
h = (len(text) - 1) * spacerHeight
for line in text:
p = XPreformatted(line, s)
h += p.wrap(textBoxWidth, textBoxHeight)[1]
paragraphs.append(p)
if h <= textBoxHeight or s.fontSize <= 1 or s.leading <= 1:
break
else:
s.fontSize -= 0.2
s.leading -= 0.2
spacerHeight = max(spacerHeight - 1, minSpacerHeight)
h = self.options.paperheight - textVerticalMargin
for p in paragraphs:
h -= p.height
p.drawOn(self.canvas, textHorizontalMargin, h)
h -= spacerHeight
self.canvas.showPage()
def drawInfo(self, printIt=True):
# Keep track of the number of pages
pageCount = 0
# A unique separator that will not be found in any normal text. Was '@@@***!!!***@@@' at one time.
sep = chr(30) + chr(31)
# Generic space. Other options are ' ', '&nbsp;', '&#xa0;'
space = '&nbsp;'
tab_spaces = 4
blank_line = (space + '\n') * 2
if self.options.info or self.options.info_all:
text = "<para alignment='center'><font size=18><b>Sumpfork's Dominion Tabbed Divider Generator</b></font>\n"
text += blank_line
text += "Online generator at: "
text += "<a href='http://domtabs.sandflea.org/' color='blue'>http://domtabs.sandflea.org</a>\n\n"
text += "Source code on GitHub at: "
text += "<a href='https://github.com/sumpfork/dominiontabs' color='blue'>"
text += "https://github.com/sumpfork/dominiontabs</a>\n\n"
text += "Options for this file:\n"
cmd = " ".join(self.options.argv)
cmd = cmd.replace(' --', sep + '--')
cmd = cmd.replace(' -', sep + '-')
cmd = cmd.replace(sep, '\n' + space * tab_spaces)
text += cmd
text += blank_line
if printIt:
self.drawTextPages([text], margin=1.0, fontsize=10, leading=10, spacer=0.05)
pageCount += 1
if self.options.info_all:
linesPerPage = 80
lines = self.options.help.replace('\n\n', blank_line).replace(' ', space).split('\n')
pages = []
lineCount = 0
text = ""
for line in lines:
lineCount += 1
text += line + '\n'
if lineCount >= linesPerPage:
pages.append(text)
pageCount += 1
lineCount = 0
text = ""
if text:
pages.append(text)
pageCount += 1
if printIt:
self.drawTextPages(pages, margin=0.75, fontsize=6, leading=7, spacer=0.1)
return pageCount
def wantCentreTab(self, card): def wantCentreTab(self, card):
return (card.isExpansion() and self.options.centre_expansion_dividers) or self.options.tab_side == "centre" return (card.isExpansion() and self.options.centre_expansion_dividers) or self.options.tab_side == "centre"
@ -222,6 +316,8 @@ class DividerDrawer(object):
options.outfile, options.outfile,
pagesize=(options.paperwidth, options.paperheight)) pagesize=(options.paperwidth, options.paperheight))
self.drawDividers(cards) self.drawDividers(cards)
if options.info or options.info_all:
self.drawInfo()
self.canvas.save() self.canvas.save()
def add_inline_images(self, text, fontsize): def add_inline_images(self, text, fontsize):

View File

@ -401,6 +401,16 @@ def parse_opts(cmdline_args=None):
dest="tabs_only", dest="tabs_only",
help="Draw only the divider tabs and no divider outlines. " help="Draw only the divider tabs and no divider outlines. "
"Used to print the divider tabs on labels.") "Used to print the divider tabs on labels.")
group_printing.add_argument(
"--info",
action="store_true",
dest="info",
help="Add a page that has all the options used for the file.")
group_printing.add_argument(
"--info-all",
action="store_true",
dest="info_all",
help="Same as --info, but includes pages with all the possible options that can be used.")
group_printing.add_argument( group_printing.add_argument(
"--preview", "--preview",
action='store_true', action='store_true',
@ -425,7 +435,11 @@ def parse_opts(cmdline_args=None):
dest="write_json", dest="write_json",
help="Write json version of card definitions and extras.") help="Write json version of card definitions and extras.")
return parser.parse_args(args=cmdline_args) options = parser.parse_args(args=cmdline_args)
# Need to do these while we have access to the parser
options.argv = sys.argv if options.info or options.info_all else None
options.help = parser.format_help() if options.info_all else None
return options
def clean_opts(options): def clean_opts(options):