Further pylint improvements to document generators
This commit is contained in:
parent
36f5a6addc
commit
a3fd7c06be
@ -27,27 +27,8 @@
|
||||
# Python modules
|
||||
#
|
||||
#------------------------------------------------------------------------
|
||||
from gramps.gen.const import GRAMPS_LOCALE as glocale
|
||||
_ = glocale.translation.gettext
|
||||
from math import radians
|
||||
|
||||
#------------------------------------------------------------------------
|
||||
#
|
||||
# Gramps modules
|
||||
#
|
||||
#------------------------------------------------------------------------
|
||||
from gramps.gen.plug.docgen import PAPER_PORTRAIT
|
||||
import gramps.plugins.lib.libcairodoc as libcairodoc
|
||||
from gramps.gen.errors import UnavailableError
|
||||
#import constfunc
|
||||
|
||||
#------------------------------------------------------------------------
|
||||
#
|
||||
# Set up logging
|
||||
#
|
||||
#------------------------------------------------------------------------
|
||||
import logging
|
||||
log = logging.getLogger(".GtkPrint")
|
||||
|
||||
#-------------------------------------------------------------------------
|
||||
#
|
||||
@ -61,6 +42,23 @@ try: # the Gramps-Connect server has no DISPLAY
|
||||
except:
|
||||
pass
|
||||
|
||||
#------------------------------------------------------------------------
|
||||
#
|
||||
# Gramps modules
|
||||
#
|
||||
#------------------------------------------------------------------------
|
||||
from gramps.gen.plug.docgen import PAPER_PORTRAIT
|
||||
import gramps.plugins.lib.libcairodoc as libcairodoc
|
||||
from gramps.gen.const import GRAMPS_LOCALE as glocale
|
||||
_ = glocale.translation.gettext
|
||||
|
||||
#------------------------------------------------------------------------
|
||||
#
|
||||
# Set up logging
|
||||
#
|
||||
#------------------------------------------------------------------------
|
||||
LOG = logging.getLogger(".GtkPrint")
|
||||
|
||||
#------------------------------------------------------------------------
|
||||
#
|
||||
# Constants
|
||||
@ -128,7 +126,7 @@ def paperstyle_to_pagesetup(paper_style):
|
||||
# are handled as custom format, because we are not intelligent enough.
|
||||
if gramps_paper_name in gramps_to_gtk:
|
||||
paper_size = Gtk.PaperSize.new(name=gramps_to_gtk[gramps_paper_name])
|
||||
log.debug("Selected paper size: %s" % gramps_to_gtk[gramps_paper_name])
|
||||
LOG.debug("Selected paper size: %s", gramps_to_gtk[gramps_paper_name])
|
||||
else:
|
||||
if paper_style.get_orientation() == PAPER_PORTRAIT:
|
||||
paper_width = gramps_paper_size.get_width() * 10
|
||||
@ -139,7 +137,7 @@ def paperstyle_to_pagesetup(paper_style):
|
||||
paper_size = Gtk.PaperSize.new_custom("custom", "Custom Size",
|
||||
paper_width, paper_height,
|
||||
Gtk.Unit.MM)
|
||||
log.debug("Selected paper size: (%f,%f)" % (paper_width, paper_height))
|
||||
LOG.debug("Selected paper size: (%f,%f)", paper_width, paper_height)
|
||||
|
||||
page_setup = Gtk.PageSetup()
|
||||
page_setup.set_paper_size(paper_size)
|
||||
@ -234,7 +232,7 @@ class PrintPreview:
|
||||
|
||||
##"""
|
||||
##if page_no >= len(self._page_numbers):
|
||||
##log.debug("Page number %d doesn't exist." % page_no)
|
||||
##LOG.debug("Page number %d doesn't exist." % page_no)
|
||||
##page_no = 0
|
||||
|
||||
##if page_no not in self._page_surfaces:
|
||||
|
@ -32,28 +32,34 @@
|
||||
|
||||
#------------------------------------------------------------------------
|
||||
#
|
||||
# python modules
|
||||
# Python modules
|
||||
#
|
||||
#------------------------------------------------------------------------
|
||||
from gramps.gen.const import GRAMPS_LOCALE as glocale
|
||||
_ = glocale.translation.gettext
|
||||
from bisect import bisect
|
||||
import re, os, sys
|
||||
import re
|
||||
import os
|
||||
import logging
|
||||
_LOG = logging.getLogger(".latexdoc")
|
||||
|
||||
#----------------------------------------------------------------------- -
|
||||
#
|
||||
# gramps modules
|
||||
#
|
||||
#------------------------------------------------------------------------
|
||||
from gramps.gen.plug.docgen import BaseDoc, TextDoc, PAPER_LANDSCAPE, FONT_SANS_SERIF, URL_PATTERN
|
||||
from gramps.gen.plug.docbackend import DocBackend
|
||||
HAVE_PIL = False
|
||||
try:
|
||||
from PIL import Image
|
||||
HAVE_PIL = True
|
||||
except:
|
||||
except ImportError:
|
||||
HAVE_PIL = False
|
||||
|
||||
#----------------------------------------------------------------------- -
|
||||
#
|
||||
# Gramps modules
|
||||
#
|
||||
#------------------------------------------------------------------------
|
||||
from gramps.gen.plug.docgen import (BaseDoc, TextDoc, PAPER_LANDSCAPE,
|
||||
FONT_SANS_SERIF, URL_PATTERN)
|
||||
from gramps.gen.plug.docbackend import DocBackend
|
||||
from gramps.gen.const import GRAMPS_LOCALE as glocale
|
||||
_ = glocale.translation.gettext
|
||||
|
||||
|
||||
_LOG = logging.getLogger(".latexdoc")
|
||||
if not HAVE_PIL:
|
||||
_LOG.warning(_("PIL (Python Imaging Library) not loaded. "
|
||||
"Production of jpg images from non-jpg images "
|
||||
"in LaTeX documents will not be available. "
|
||||
@ -435,8 +441,8 @@ def map_font_size(fontsize):
|
||||
TBLFMT_PAT = re.compile(r'({\|?)l(\|?})')
|
||||
|
||||
# constants for routing in table construction:
|
||||
(CELL_BEG, CELL_TEXT, CELL_END,
|
||||
ROW_BEG, ROW_END, TAB_BEG, TAB_END) = list(range(7))
|
||||
(CELL_BEG, CELL_TEXT, CELL_END, ROW_BEG, ROW_END, TAB_BEG,
|
||||
TAB_END) = list(range(7))
|
||||
FIRST_ROW, SUBSEQ_ROW = list(range(2))
|
||||
|
||||
|
||||
@ -489,22 +495,22 @@ def str_incr(str_counter):
|
||||
#
|
||||
#------------------------------------------------------------------------
|
||||
|
||||
class Tab_Cell:
|
||||
class TabCell:
|
||||
def __init__(self, colchar, span, head, content):
|
||||
self.colchar = colchar
|
||||
self.span = span
|
||||
self.head = head
|
||||
self.content = content
|
||||
class Tab_Row:
|
||||
class TabRow:
|
||||
def __init__(self):
|
||||
self.cells =[]
|
||||
self.cells = []
|
||||
self.tail = ''
|
||||
self.addit = '' # for: \\hline, \\cline{}
|
||||
class Tab_Mem:
|
||||
class TabMem:
|
||||
def __init__(self, head):
|
||||
self.head = head
|
||||
self.tail =''
|
||||
self.rows =[]
|
||||
self.tail = ''
|
||||
self.rows = []
|
||||
|
||||
#------------------------------------------------------------------------
|
||||
#
|
||||
@ -513,25 +519,7 @@ class Tab_Mem:
|
||||
#------------------------------------------------------------------------
|
||||
def latexescape(text):
|
||||
"""
|
||||
change text in text that latex shows correctly
|
||||
special characters: \& \$ \% \# \_ \{ \}
|
||||
"""
|
||||
text = text.replace('&','\\&')
|
||||
text = text.replace('$','\\$')
|
||||
text = text.replace('%','\\%')
|
||||
text = text.replace('#','\\#')
|
||||
text = text.replace('_','\\_')
|
||||
text = text.replace('{','\\{')
|
||||
text = text.replace('}','\\}')
|
||||
# replace character unknown to LaTeX
|
||||
text = text.replace('→','$\\longrightarrow$')
|
||||
return text
|
||||
|
||||
def latexescapeverbatim(text):
|
||||
"""
|
||||
change text in text that latex shows correctly respecting whitespace
|
||||
special characters: \& \$ \% \# \_ \{ \}
|
||||
Now also make sure space and newline is respected
|
||||
Escape the following special characters: & $ % # _ { }
|
||||
"""
|
||||
text = text.replace('&', '\\&')
|
||||
text = text.replace('$', '\\$')
|
||||
@ -540,14 +528,22 @@ def latexescapeverbatim(text):
|
||||
text = text.replace('_', '\\_')
|
||||
text = text.replace('{', '\\{')
|
||||
text = text.replace('}', '\\}')
|
||||
# replace character unknown to LaTeX
|
||||
text = text.replace('→', '$\\longrightarrow$')
|
||||
return text
|
||||
|
||||
def latexescapeverbatim(text):
|
||||
"""
|
||||
Escape special characters and also make sure that LaTeX respects whitespace
|
||||
and newlines correctly.
|
||||
"""
|
||||
text = latexescape(text)
|
||||
text = text.replace(' ', '\\ ')
|
||||
text = text.replace('\n', '~\\newline \n')
|
||||
#spaces at begin are normally ignored, make sure they are not.
|
||||
#due to above a space at begin is now \newline\n\
|
||||
text = text.replace('\\newline\n\\ ',
|
||||
'\\newline\n\\hspace*{0.1\\grbaseindent}\\ ')
|
||||
# replace character unknown to LaTeX
|
||||
text = text.replace('→','$\\longrightarrow$')
|
||||
return text
|
||||
|
||||
#------------------------------------------------------------------------
|
||||
@ -568,7 +564,7 @@ class LateXBackend(DocBackend):
|
||||
DocBackend.UNDERLINE,
|
||||
DocBackend.FONTSIZE,
|
||||
DocBackend.FONTFACE,
|
||||
DocBackend.SUPERSCRIPT ]
|
||||
DocBackend.SUPERSCRIPT]
|
||||
|
||||
STYLETAG_MARKUP = {
|
||||
DocBackend.BOLD : ("\\textbf{", "}"),
|
||||
@ -634,13 +630,13 @@ class TexFont:
|
||||
if style:
|
||||
self.font_beg = style.font_beg
|
||||
self.font_end = style.font_end
|
||||
self.leftIndent = style.left_indent
|
||||
self.firstLineIndent = style.firstLineIndent
|
||||
self.left_indent = style.left_indent
|
||||
self.first_line_indent = style.first_line_indent
|
||||
else:
|
||||
self.font_beg = ""
|
||||
self.font_end = ""
|
||||
self.leftIndent = ""
|
||||
self.firstLineIndent = ""
|
||||
self.left_indent = ""
|
||||
self.first_line_indent = ""
|
||||
|
||||
|
||||
#------------------------------------------------------------------
|
||||
@ -691,9 +687,9 @@ class LaTeXDoc(BaseDoc, TextDoc):
|
||||
if span > 1: # phantom columns prior to multicolumns
|
||||
for col in range(self.curcol - span, self.curcol - 1):
|
||||
col_char = get_charform(col)
|
||||
phantom = Tab_Cell(col_char, 0, '', '')
|
||||
phantom = TabCell(col_char, 0, '', '')
|
||||
self.tabrow.cells.append(phantom)
|
||||
self.tabcell = Tab_Cell(self.curcol_char, span, text, '')
|
||||
self.tabcell = TabCell(self.curcol_char, span, text, '')
|
||||
elif tab_state == CELL_TEXT:
|
||||
self.textmem.append(text)
|
||||
elif tab_state == CELL_END: # text == ''
|
||||
@ -707,7 +703,7 @@ class LaTeXDoc(BaseDoc, TextDoc):
|
||||
self.tabrow.cells.append(self.tabcell)
|
||||
self.textmem = []
|
||||
elif tab_state == ROW_BEG:
|
||||
self.tabrow = Tab_Row()
|
||||
self.tabrow = TabRow()
|
||||
elif tab_state == ROW_END:
|
||||
self.tabrow.addit = text # text: \\hline, \\cline{}
|
||||
self.tabrow.tail = ''.join(self.textmem) # \\\\ row-termination
|
||||
@ -718,7 +714,7 @@ class LaTeXDoc(BaseDoc, TextDoc):
|
||||
elif tab_state == TAB_BEG: # text: \\begin{longtable}[l]{
|
||||
self._backend.write(''.join(('\\grinittab{\\textwidth}{',
|
||||
repr(1.0/self.numcols), '}%\n')))
|
||||
self.tabmem = Tab_Mem(text)
|
||||
self.tabmem = TabMem(text)
|
||||
elif tab_state == TAB_END: # text: \\end{longtable}
|
||||
self.tabmem.tail = text
|
||||
|
||||
@ -740,8 +736,8 @@ class LaTeXDoc(BaseDoc, TextDoc):
|
||||
|
||||
# extract cell.contents
|
||||
bare_contents = [cell.content.strip(SEPARATION_PAT).replace(
|
||||
'\n', '').split(SEPARATION_PAT)
|
||||
for cell in self.tabrow.cells]
|
||||
'\n', '').split(SEPARATION_PAT) for cell in self.tabrow.cells]
|
||||
|
||||
# mk equal length & transpose
|
||||
num_new_rows = max([len(mult_row_cont)
|
||||
for mult_row_cont in bare_contents])
|
||||
@ -759,15 +755,18 @@ class LaTeXDoc(BaseDoc, TextDoc):
|
||||
self.pict = transp_cont[0][-1]
|
||||
last_cell -= 1
|
||||
self.numcols -= 1
|
||||
self._backend.write(''.join(('\\addtolength{\\grtabwidth}{-',
|
||||
repr(self.pict_width), '\\grbaseindent -2\\tabcolsep}%\n')))
|
||||
self._backend.write(''.join(
|
||||
('\\addtolength{\\grtabwidth}{-',
|
||||
repr(self.pict_width),
|
||||
'\\grbaseindent -2\\tabcolsep}%\n')))
|
||||
self.pict_in_table = False
|
||||
|
||||
# new row-col structure
|
||||
for row in range(num_new_rows):
|
||||
new_row = Tab_Row()
|
||||
new_row = TabRow()
|
||||
for i in range(first_cell, last_cell):
|
||||
new_cell = Tab_Cell(get_charform(i + first_cell),
|
||||
new_cell = TabCell(
|
||||
get_charform(i + first_cell),
|
||||
self.tabrow.cells[i].span, self.tabrow.cells[i].head,
|
||||
transp_cont[row][i + first_cell])
|
||||
new_row.cells.append(new_cell)
|
||||
@ -796,43 +795,50 @@ class LaTeXDoc(BaseDoc, TextDoc):
|
||||
if cell.span == 0:
|
||||
continue
|
||||
if cell.content.startswith('\\grmkpicture'):
|
||||
self._backend.write(''.join(('\\setlength{\\grpictsize}{',
|
||||
self._backend.write(
|
||||
''.join(('\\setlength{\\grpictsize}{',
|
||||
self.pict_width, '\\grbaseindent}%\n')))
|
||||
else:
|
||||
for part in cell.content.split(SEPARATION_PAT):
|
||||
self._backend.write(''.join(('\\grtextneedwidth{',
|
||||
part, '}%\n')))
|
||||
self._backend.write(
|
||||
''.join(('\\grtextneedwidth{', part, '}%\n')))
|
||||
row.cells[col_num].content = cell.content.replace(
|
||||
SEPARATION_PAT, '~\\newline \n')
|
||||
|
||||
if cell.span == 1:
|
||||
self._backend.write(''.join(('\\grsetreqfull%\n')))
|
||||
elif cell.span > 1:
|
||||
self._backend.write(''.join(('\\grsetreqpart{\\grcolbeg',
|
||||
get_charform(get_numform(cell.colchar) - cell.span +1),
|
||||
self._backend.write(
|
||||
''.join(('\\grsetreqpart{\\grcolbeg',
|
||||
get_charform(get_numform(cell.colchar) -
|
||||
cell.span +1),
|
||||
'}%\n')))
|
||||
|
||||
self._backend.write(''.join(('\\grcolsfirstfix',
|
||||
self._backend.write(
|
||||
''.join(('\\grcolsfirstfix',
|
||||
' {\\grcolbeg', col_char, '}{\\grtempwidth', col_char,
|
||||
'}{\\grfinalwidth', col_char, '}{\\grpictreq', col_char,
|
||||
'}{\\grtextreq', col_char, '}%\n')))
|
||||
'}{\\grfinalwidth', col_char, '}{\\grpictreq',
|
||||
col_char, '}{\\grtextreq', col_char, '}%\n')))
|
||||
|
||||
self._backend.write(''.join(('\\grdividelength%\n')))
|
||||
for col_char in tabcol_chars:
|
||||
self._backend.write(''.join(('\\grcolssecondfix',
|
||||
self._backend.write(
|
||||
''.join(('\\grcolssecondfix',
|
||||
' {\\grcolbeg', col_char, '}{\\grtempwidth', col_char,
|
||||
'}{\\grfinalwidth', col_char, '}{\\grpictreq', col_char,
|
||||
'}%\n')))
|
||||
'}{\\grfinalwidth', col_char, '}{\\grpictreq',
|
||||
col_char, '}%\n')))
|
||||
|
||||
self._backend.write(''.join(('\\grdividelength%\n')))
|
||||
for col_char in tabcol_chars:
|
||||
self._backend.write(''.join(('\\grcolsthirdfix',
|
||||
self._backend.write(
|
||||
''.join(('\\grcolsthirdfix',
|
||||
' {\\grcolbeg', col_char, '}{\\grtempwidth', col_char,
|
||||
'}{\\grfinalwidth', col_char, '}%\n')))
|
||||
|
||||
self._backend.write(''.join(('\\grdividelength%\n')))
|
||||
for col_char in tabcol_chars:
|
||||
self._backend.write(''.join(('\\grcolsfourthfix',
|
||||
self._backend.write(
|
||||
''.join(('\\grcolsfourthfix',
|
||||
' {\\grcolbeg', col_char, '}{\\grtempwidth', col_char,
|
||||
'}{\\grfinalwidth', col_char, '}%\n')))
|
||||
|
||||
@ -841,10 +847,11 @@ class LaTeXDoc(BaseDoc, TextDoc):
|
||||
for cell in row.cells:
|
||||
if cell.span > 1:
|
||||
multcol_alph_id = next(self.multcol_alph_counter)
|
||||
self._backend.write(''.join(('\\grgetspanwidth{',
|
||||
self._backend.write(
|
||||
''.join(('\\grgetspanwidth{',
|
||||
'\\grspanwidth', multcol_alph_id,
|
||||
'}{\\grcolbeg', get_charform(get_numform(cell.colchar)-
|
||||
cell.span + 1),
|
||||
'}{\\grcolbeg', get_charform(
|
||||
get_numform(cell.colchar)- cell.span + 1),
|
||||
'}{\\grcolbeg', cell.colchar,
|
||||
'}{\\grtempwidth', cell.colchar,
|
||||
'}%\n')))
|
||||
@ -852,7 +859,8 @@ class LaTeXDoc(BaseDoc, TextDoc):
|
||||
def write_table(self):
|
||||
# Choosing RaggedRight (with hyphenation) in table and
|
||||
# provide manually adjusting of column widths
|
||||
self._backend.write(''.join((
|
||||
self._backend.write(
|
||||
''.join((
|
||||
'%\n', self.pict,
|
||||
'%\n%\n',
|
||||
'% ==> Comment out one of the two lines ',
|
||||
@ -862,13 +870,15 @@ class LaTeXDoc(BaseDoc, TextDoc):
|
||||
'% ==> You may add pos or neg values ',
|
||||
'to the following ', repr(self.numcols), ' column widths %\n')))
|
||||
for col_num in range(self.numcols):
|
||||
self._backend.write(''.join(('\\addtolength{\\grtempwidth',
|
||||
self._backend.write(
|
||||
''.join(('\\addtolength{\\grtempwidth',
|
||||
get_charform(col_num), '}{+0.0cm}%\n')))
|
||||
self._backend.write('% === %\n')
|
||||
|
||||
# adjust & open table':
|
||||
if self.pict:
|
||||
self._backend.write(''.join(('%\n\\vspace{\\grtabprepos}%\n',
|
||||
self._backend.write(
|
||||
''.join(('%\n\\vspace{\\grtabprepos}%\n',
|
||||
'\\setlength{\\grtabprepos}{0ex}%\n')))
|
||||
self.pict = ''
|
||||
self._backend.write(''.join(self.tabmem.head))
|
||||
@ -887,7 +897,7 @@ class LaTeXDoc(BaseDoc, TextDoc):
|
||||
self._backend.write('\\endfoot%\n')
|
||||
if self.head_line:
|
||||
self._backend.write('\\hline%\n')
|
||||
self.head_line= False
|
||||
self.head_line = False
|
||||
else:
|
||||
self._backend.write('%\n')
|
||||
self._backend.write(complete_row)
|
||||
@ -902,7 +912,7 @@ class LaTeXDoc(BaseDoc, TextDoc):
|
||||
self._backend.write(''.join((''.join(self.tabmem.tail), '}%\n\n')))
|
||||
|
||||
def mk_splitting_row(self, row):
|
||||
splitting =[]
|
||||
splitting = []
|
||||
add_vdots = '\\grempty'
|
||||
for cell in row.cells:
|
||||
if cell.span == 0:
|
||||
@ -915,12 +925,13 @@ class LaTeXDoc(BaseDoc, TextDoc):
|
||||
else:
|
||||
cell_width = ''.join(('\\grspanwidth',
|
||||
next(self.multcol_alph_counter)))
|
||||
splitting.append(''.join(('\\grtabpgbreak{', cell.head, '}{',
|
||||
splitting.append(
|
||||
''.join(('\\grtabpgbreak{', cell.head, '}{',
|
||||
cell_width, '}{', add_vdots, '}{+2ex}%\n')))
|
||||
return ''.join((' & '.join(splitting), '%\n', row.tail))
|
||||
|
||||
def mk_complete_row(self, row):
|
||||
complete =[]
|
||||
complete = []
|
||||
for cell in row.cells:
|
||||
if cell.span == 0:
|
||||
continue
|
||||
@ -929,8 +940,9 @@ class LaTeXDoc(BaseDoc, TextDoc):
|
||||
else:
|
||||
cell_width = ''.join(('\\grspanwidth',
|
||||
next(self.multcol_alph_counter)))
|
||||
complete.append(''.join(('\\grcolpart{%\n ', cell.head,
|
||||
'}{%\n', cell_width, '}{%\n ', cell.content, '%\n}%\n')))
|
||||
complete.append(
|
||||
''.join(('\\grcolpart{%\n ', cell.head, '}{%\n', cell_width,
|
||||
'}{%\n ', cell.content, '%\n}%\n')))
|
||||
return ''.join((' & '.join(complete), '%\n', row.tail, row.addit))
|
||||
|
||||
# ---------------------------------------------------------------------
|
||||
@ -1016,8 +1028,8 @@ class LaTeXDoc(BaseDoc, TextDoc):
|
||||
|
||||
left = style.get_left_margin()
|
||||
first = style.get_first_indent() + left
|
||||
thisstyle.leftIndent = left
|
||||
thisstyle.firstLineIndent = first
|
||||
thisstyle.left_indent = left
|
||||
thisstyle.first_line_indent = first
|
||||
self.latexstyle[style_name] = thisstyle
|
||||
|
||||
|
||||
@ -1045,10 +1057,10 @@ class LaTeXDoc(BaseDoc, TextDoc):
|
||||
self.fbeg = ltxstyle.font_beg
|
||||
self.fend = ltxstyle.font_end
|
||||
|
||||
self.indent = ltxstyle.leftIndent
|
||||
self.FLindent = ltxstyle.firstLineIndent
|
||||
self.indent = ltxstyle.left_indent
|
||||
self.first_line_indent = ltxstyle.first_line_indent
|
||||
if self.indent == 0:
|
||||
self.indent = self.FLindent
|
||||
self.indent = self.first_line_indent
|
||||
|
||||
# For additional vertical space beneath title line(s)
|
||||
# i.e. when the first centering ended:
|
||||
@ -1059,8 +1071,8 @@ class LaTeXDoc(BaseDoc, TextDoc):
|
||||
self.in_multrow_cell = True
|
||||
else:
|
||||
if leader:
|
||||
self._backend.write(''.join(('\\grprepleader{', leader,
|
||||
'}%\n')))
|
||||
self._backend.write(
|
||||
''.join(('\\grprepleader{', leader, '}%\n')))
|
||||
else:
|
||||
self._backend.write('\\grprepnoleader%\n')
|
||||
|
||||
@ -1070,8 +1082,9 @@ class LaTeXDoc(BaseDoc, TextDoc):
|
||||
# there another value might be choosen.
|
||||
# -------------------------------------------------------------------
|
||||
if self.indent is not None:
|
||||
self._backend.write(''.join(('\\grminpghead{',
|
||||
repr(self.indent), '}{', repr(self.pict_width), '}%\n')))
|
||||
self._backend.write(
|
||||
''.join(('\\grminpghead{', repr(self.indent), '}{',
|
||||
repr(self.pict_width), '}%\n')))
|
||||
self.fix_indent = True
|
||||
|
||||
if leader is not None and not self.in_list:
|
||||
@ -1116,7 +1129,7 @@ class LaTeXDoc(BaseDoc, TextDoc):
|
||||
def end_superscript(self):
|
||||
self.emit('}')
|
||||
|
||||
def start_table(self, name,style_name):
|
||||
def start_table(self, name, style_name):
|
||||
"""Begin new table"""
|
||||
self.in_table = True
|
||||
self.currow = 0
|
||||
@ -1171,10 +1184,10 @@ class LaTeXDoc(BaseDoc, TextDoc):
|
||||
# values imported here are used for test '==1' and '!=0'. To get
|
||||
# local boolean values the tests are now transfered to the import lines
|
||||
# ------------------------------------------------------------------
|
||||
self.lborder = 1 == self.cstyle.get_left_border()
|
||||
self.rborder = 1 == self.cstyle.get_right_border()
|
||||
self.bborder = 1 == self.cstyle.get_bottom_border()
|
||||
self.tborder = 0 != self.cstyle.get_top_border()
|
||||
self.lborder = self.cstyle.get_left_border() == 1
|
||||
self.rborder = self.cstyle.get_right_border() == 1
|
||||
self.bborder = self.cstyle.get_bottom_border() == 1
|
||||
self.tborder = self.cstyle.get_top_border() != 0
|
||||
|
||||
# self.llist not needed any longer.
|
||||
# now column widths are arranged in self.calc_latex_widths()
|
||||
@ -1207,21 +1220,20 @@ class LaTeXDoc(BaseDoc, TextDoc):
|
||||
self.emit('', CELL_END)
|
||||
|
||||
|
||||
def add_media(self, infile, pos, x, y, alt='',
|
||||
style_name=None, crop=None):
|
||||
def add_media(self, infile, pos, x, y, alt='', style_name=None, crop=None):
|
||||
"""Add photo to report"""
|
||||
outfile = os.path.splitext(infile)[0]
|
||||
pictname = latexescape(os.path.split(outfile)[1])
|
||||
outfile = ''.join((outfile, '.jpg'))
|
||||
outfile2 = ''.join((outfile, '.jpeg'))
|
||||
outfile3 = ''.join((outfile, '.png'))
|
||||
if HAVE_PIL and infile not in [outfile, outfile2, outfile3] :
|
||||
if HAVE_PIL and infile not in [outfile, outfile2, outfile3]:
|
||||
try:
|
||||
curr_img = Image.open(infile)
|
||||
curr_img.save(outfile)
|
||||
px, py = curr_img.size
|
||||
if py > px:
|
||||
y = y*py/px
|
||||
width, height = curr_img.size
|
||||
if height > width:
|
||||
y = y*height/width
|
||||
except IOError:
|
||||
self.emit(''.join(('%\n *** Error: cannot convert ', infile,
|
||||
'\n *** to ', outfile,
|
||||
@ -1239,13 +1251,13 @@ class LaTeXDoc(BaseDoc, TextDoc):
|
||||
self.pict_width = x
|
||||
self.pict_height = y
|
||||
|
||||
def write_text(self,text,mark=None,links=False):
|
||||
def write_text(self, text, mark=None, links=False):
|
||||
"""Write the text to the file"""
|
||||
if text == '\n':
|
||||
text = ''
|
||||
text = latexescape(text)
|
||||
|
||||
if links == True:
|
||||
if links is True:
|
||||
text = re.sub(URL_PATTERN, _CLICKABLE, text)
|
||||
|
||||
#hard coded replace of the underline used for missing names/data
|
||||
@ -1277,7 +1289,7 @@ class LaTeXDoc(BaseDoc, TextDoc):
|
||||
|
||||
markuptext = self._backend.add_markup_from_styled(text, s_tags)
|
||||
|
||||
if links == True:
|
||||
if links is True:
|
||||
markuptext = re.sub(URL_PATTERN, _CLICKABLE, markuptext)
|
||||
markuptext = self._backend.add_markup_from_styled(text, s_tags)
|
||||
|
||||
|
@ -28,34 +28,6 @@
|
||||
ODFDoc : used to generate Open Office Document
|
||||
"""
|
||||
|
||||
#-------------------------------------------------------------------------
|
||||
#
|
||||
# pylint : disable messages ...
|
||||
#
|
||||
#-------------------------------------------------------------------------
|
||||
# disable-msg=C0302 # Too many lines in module
|
||||
# pylint: disable-msg=C0302
|
||||
# disable-msg # Regular expression which should only match
|
||||
# pylint: disable-msg=C0103
|
||||
# disable-msg=R0902 # Too many instance attributes
|
||||
# pylint: disable-msg=R0902
|
||||
# disable-msg=R0904 # Too many public methods
|
||||
# pylint: disable-msg=R0904
|
||||
# disable-msg=R0912 # Too many branches
|
||||
# pylint: disable-msg=R0912
|
||||
# disable-msg=R0913 # Too many arguments
|
||||
# pylint: disable-msg=R0913
|
||||
# disable-msg=R0914 # Too many local variables
|
||||
# pylint: disable-msg=R0914
|
||||
# disable-msg=R0915 # Too many statements
|
||||
# pylint: disable-msg=R0915
|
||||
# warnings :
|
||||
# disable-msg=W0613 # Unused argument
|
||||
# pylint: disable-msg=W0613
|
||||
# errors :
|
||||
# disable-msg=E1101 # has no member
|
||||
# pylint: disable-msg=E1101
|
||||
|
||||
#-------------------------------------------------------------------------
|
||||
#
|
||||
# Standard Python Modules
|
||||
@ -66,19 +38,20 @@ from hashlib import md5
|
||||
import zipfile
|
||||
import time
|
||||
from io import StringIO
|
||||
from math import pi, cos, sin, degrees, radians
|
||||
from math import cos, sin, radians
|
||||
from xml.sax.saxutils import escape
|
||||
import re
|
||||
|
||||
#-------------------------------------------------------------------------
|
||||
#
|
||||
# Gramps modules
|
||||
#
|
||||
#-------------------------------------------------------------------------
|
||||
from gramps.gen.plug.docgen import (BaseDoc, TextDoc, DrawDoc, graphicstyle,
|
||||
FONT_SANS_SERIF, SOLID, PAPER_PORTRAIT,
|
||||
INDEX_TYPE_TOC, PARA_ALIGN_CENTER, PARA_ALIGN_LEFT,
|
||||
INDEX_TYPE_ALP, PARA_ALIGN_RIGHT, URL_PATTERN,
|
||||
LOCAL_HYPERLINK, LOCAL_TARGET)
|
||||
from gramps.gen.plug.docgen import (
|
||||
BaseDoc, TextDoc, DrawDoc, graphicstyle, FONT_SANS_SERIF, SOLID,
|
||||
PAPER_PORTRAIT, INDEX_TYPE_TOC, PARA_ALIGN_CENTER, PARA_ALIGN_LEFT,
|
||||
INDEX_TYPE_ALP, PARA_ALIGN_RIGHT, URL_PATTERN, LOCAL_HYPERLINK,
|
||||
LOCAL_TARGET)
|
||||
from gramps.gen.plug.docgen.fontscale import string_width
|
||||
from gramps.plugins.lib.libodfbackend import OdfBackend
|
||||
from gramps.gen.const import PROGRAM_NAME, URL_HOMEPAGE
|
||||
@ -96,9 +69,9 @@ from gramps.gen.errors import ReportError
|
||||
from gramps.gen.const import GRAMPS_LOCALE as glocale
|
||||
_ = glocale.translation.gettext
|
||||
|
||||
_apptype = 'application/vnd.oasis.opendocument.text'
|
||||
APP_TYPE = 'application/vnd.oasis.opendocument.text'
|
||||
|
||||
_esc_map = {
|
||||
ESC_MAP = {
|
||||
'\x1a' : '',
|
||||
'\x0c' : '',
|
||||
'\n' : '<text:line-break/>',
|
||||
@ -110,9 +83,8 @@ _esc_map = {
|
||||
# regexp for Styled Notes ...
|
||||
#
|
||||
#-------------------------------------------------------------------------
|
||||
import re
|
||||
# Hyphen is added because it is used to replace spaces in the font name
|
||||
NewStyle = re.compile('style-name="([a-zA-Z0-9]*)__([#a-zA-Z0-9 -]*)__">')
|
||||
NEW_STYLE = re.compile('style-name="([a-zA-Z0-9]*)__([#a-zA-Z0-9 -]*)__">')
|
||||
|
||||
#-------------------------------------------------------------------------
|
||||
#
|
||||
@ -457,15 +429,15 @@ class ODFDoc(BaseDoc, TextDoc, DrawDoc):
|
||||
self.new_cell = 0
|
||||
self.page = 0
|
||||
self.first_page = 1
|
||||
self.StyleList_notes = [] # styles to create depending on styled notes.
|
||||
self.StyleList_photos = [] # styles to create depending on clipped images.
|
||||
self.stylelist_notes = [] # styles to create for styled notes.
|
||||
self.stylelist_photos = [] # styles to create for clipped images.
|
||||
|
||||
def open(self, filename):
|
||||
"""
|
||||
Open the new document
|
||||
"""
|
||||
t = time.localtime(time.time())
|
||||
self.time = "%04d-%02d-%02dT%02d:%02d:%02d" % t[:6]
|
||||
now = time.localtime(time.time())
|
||||
self.time = "%04d-%02d-%02dT%02d:%02d:%02d" % now[:6]
|
||||
|
||||
self.filename = filename
|
||||
if not filename.endswith("odt"):
|
||||
@ -482,7 +454,7 @@ class ODFDoc(BaseDoc, TextDoc, DrawDoc):
|
||||
Create the document header
|
||||
"""
|
||||
|
||||
assert (not self.init_called)
|
||||
assert not self.init_called
|
||||
self.init_called = True
|
||||
wrt = self.cntnt.write
|
||||
wrt1, wrt2 = self.cntnt1.write, self.cntnt2.write
|
||||
@ -490,8 +462,8 @@ class ODFDoc(BaseDoc, TextDoc, DrawDoc):
|
||||
self.lang = glocale.lang
|
||||
self.lang = self.lang.replace('_', '-') if self.lang else "en-US"
|
||||
|
||||
self.StyleList_notes = [] # styles to create depending on styled notes.
|
||||
wrt1('<?xml version="1.0" encoding="UTF-8"?>\n'
|
||||
self.stylelist_notes = [] # styles to create depending on styled notes.
|
||||
wrt1('<?xml version="1.0" encoding="UTF-8"?>\n' +
|
||||
'<office:document-content\n' +
|
||||
_XMLNS +
|
||||
'office:version="1.0">\n' +
|
||||
@ -500,8 +472,7 @@ class ODFDoc(BaseDoc, TextDoc, DrawDoc):
|
||||
wrt1('<office:font-face-decls>\n' +
|
||||
_FONTS
|
||||
)
|
||||
wrt2(
|
||||
'</office:font-face-decls>\n' +
|
||||
wrt2('</office:font-face-decls>\n' +
|
||||
'<office:automatic-styles>\n' +
|
||||
_AUTOMATIC_STYLES
|
||||
)
|
||||
@ -510,16 +481,14 @@ class ODFDoc(BaseDoc, TextDoc, DrawDoc):
|
||||
|
||||
for style_name in styles.get_draw_style_names():
|
||||
style = styles.get_draw_style(style_name)
|
||||
wrt(
|
||||
'<style:style ' +
|
||||
wrt('<style:style ' +
|
||||
'style:name="%s" ' % style_name +
|
||||
'style:family="graphic">\n'
|
||||
'<style:graphic-properties '
|
||||
)
|
||||
|
||||
if style.get_line_width():
|
||||
wrt(
|
||||
'svg:stroke-width="%.2f" '
|
||||
wrt('svg:stroke-width="%.2f" '
|
||||
% (style.get_line_width()*10) +
|
||||
'draw:marker-start="" '
|
||||
'draw:marker-start-width="0.0" '
|
||||
@ -529,17 +498,16 @@ class ODFDoc(BaseDoc, TextDoc, DrawDoc):
|
||||
)
|
||||
if style.get_line_style() != SOLID:
|
||||
#wrt('svg:fill-color="#ff0000" ')
|
||||
wrt('draw:stroke="dash" draw:stroke-dash="gramps_%s" ' % style.get_dash_style_name())
|
||||
wrt('draw:stroke="dash" draw:stroke-dash="gramps_%s" ' %
|
||||
style.get_dash_style_name())
|
||||
else:
|
||||
wrt('draw:stroke="solid" ')
|
||||
else:
|
||||
wrt(
|
||||
'draw:stroke="none" '
|
||||
wrt('draw:stroke="none" '
|
||||
'draw:stroke-color="#000000" '
|
||||
)
|
||||
|
||||
wrt(
|
||||
'svg:fill-color="#%02x%02x%02x" '
|
||||
wrt('svg:fill-color="#%02x%02x%02x" '
|
||||
% style.get_color() +
|
||||
'draw:fill-color="#%02x%02x%02x" '
|
||||
% style.get_fill_color() +
|
||||
@ -612,24 +580,20 @@ class ODFDoc(BaseDoc, TextDoc, DrawDoc):
|
||||
elif align == PARA_ALIGN_RIGHT:
|
||||
wrt('fo:text-align="end" ')
|
||||
elif align == PARA_ALIGN_CENTER:
|
||||
wrt(
|
||||
'fo:text-align="center" '
|
||||
wrt('fo:text-align="center" '
|
||||
'style:justify-single-word="false" '
|
||||
)
|
||||
else:
|
||||
wrt(
|
||||
'fo:text-align="justify" '
|
||||
wrt('fo:text-align="justify" '
|
||||
'style:justify-single-word="false" '
|
||||
)
|
||||
font = style.get_font()
|
||||
wrt('style:font-name="%s" ' %
|
||||
("Arial"
|
||||
if font.get_type_face() == FONT_SANS_SERIF else
|
||||
"Times New Roman")
|
||||
("Arial" if font.get_type_face() == FONT_SANS_SERIF
|
||||
else "Times New Roman")
|
||||
)
|
||||
|
||||
wrt(
|
||||
'fo:font-size="%.2fpt" ' % font.get_size() +
|
||||
wrt('fo:font-size="%.2fpt" ' % font.get_size() +
|
||||
'style:font-size-asian="%.2fpt" ' % font.get_size() +
|
||||
'fo:color="#%02x%02x%02x" ' % font.get_color()
|
||||
)
|
||||
@ -639,13 +603,11 @@ class ODFDoc(BaseDoc, TextDoc, DrawDoc):
|
||||
if font.get_italic():
|
||||
wrt('fo:font-style="italic" ')
|
||||
if font.get_underline():
|
||||
wrt(
|
||||
'style:text-underline="single" '
|
||||
wrt('style:text-underline="single" '
|
||||
'style:text-underline-color="font-color" '
|
||||
)
|
||||
|
||||
wrt(
|
||||
'fo:text-indent="%.2fcm"\n' % style.get_first_indent() +
|
||||
wrt('fo:text-indent="%.2fcm"\n' % style.get_first_indent() +
|
||||
'fo:margin-right="%.2fcm"\n' % style.get_right_margin() +
|
||||
'fo:margin-left="%.2fcm"\n' % style.get_left_margin() +
|
||||
'fo:margin-top="%.2fcm"\n' % style.get_top_margin() +
|
||||
@ -654,8 +616,7 @@ class ODFDoc(BaseDoc, TextDoc, DrawDoc):
|
||||
'</style:style>\n'
|
||||
)
|
||||
|
||||
wrt(
|
||||
'<style:style style:name="F%s" ' % style_name +
|
||||
wrt('<style:style style:name="F%s" ' % style_name +
|
||||
'style:family="text">\n' +
|
||||
'<style:text-properties '
|
||||
)
|
||||
@ -666,16 +627,14 @@ class ODFDoc(BaseDoc, TextDoc, DrawDoc):
|
||||
elif align == PARA_ALIGN_RIGHT:
|
||||
wrt('fo:text-align="end" ')
|
||||
elif align == PARA_ALIGN_CENTER:
|
||||
wrt(
|
||||
'fo:text-align="center" '
|
||||
wrt('fo:text-align="center" '
|
||||
'style:justify-single-word="false" '
|
||||
)
|
||||
|
||||
font = style.get_font()
|
||||
wrt('style:font-name="%s" ' %
|
||||
("Arial"
|
||||
if font.get_type_face() == FONT_SANS_SERIF else
|
||||
"Times New Roman")
|
||||
("Arial" if font.get_type_face() == FONT_SANS_SERIF
|
||||
else "Times New Roman")
|
||||
)
|
||||
|
||||
color = font.get_color()
|
||||
@ -685,8 +644,7 @@ class ODFDoc(BaseDoc, TextDoc, DrawDoc):
|
||||
if font.get_italic():
|
||||
wrt('fo:font-style="italic" ')
|
||||
|
||||
wrt(
|
||||
'fo:font-size="%.2fpt" ' % font.get_size() +
|
||||
wrt('fo:font-size="%.2fpt" ' % font.get_size() +
|
||||
'style:font-size-asian="%.2fpt"/> ' % font.get_size() +
|
||||
'</style:style>\n'
|
||||
)
|
||||
@ -695,8 +653,7 @@ class ODFDoc(BaseDoc, TextDoc, DrawDoc):
|
||||
style = styles.get_table_style(style_name)
|
||||
table_width = float(self.get_usable_width())
|
||||
table_width_str = "%.2f" % table_width
|
||||
wrt(
|
||||
'<style:style style:name="%s" ' % style_name +
|
||||
wrt('<style:style style:name="%s" ' % style_name +
|
||||
'style:family="table-properties">\n'
|
||||
'<style:table-properties-properties ' +
|
||||
'style:width="%scm" ' % table_width_str +
|
||||
@ -707,8 +664,7 @@ class ODFDoc(BaseDoc, TextDoc, DrawDoc):
|
||||
for col in range(0, min(style.get_columns(), 50)):
|
||||
width = table_width * float(style.get_column_width(col) / 100.0)
|
||||
width_str = "%.4f" % width
|
||||
wrt(
|
||||
'<style:style style:name="%s.%s" '
|
||||
wrt('<style:style style:name="%s.%s" '
|
||||
% (style_name, chr(ord('A')+col)) +
|
||||
'style:family="table-column">' +
|
||||
'<style:table-column-properties ' +
|
||||
@ -718,38 +674,32 @@ class ODFDoc(BaseDoc, TextDoc, DrawDoc):
|
||||
|
||||
for cell in styles.get_cell_style_names():
|
||||
cell_style = styles.get_cell_style(cell)
|
||||
wrt(
|
||||
'<style:style style:name="%s" ' % cell +
|
||||
wrt('<style:style style:name="%s" ' % cell +
|
||||
'style:family="table-cell">\n' +
|
||||
'<style:table-cell-properties' +
|
||||
' fo:padding="%.2fcm"' % cell_style.get_padding()
|
||||
)
|
||||
wrt(' fo:border-top="%s"' %
|
||||
("0.002cm solid #000000"
|
||||
if cell_style.get_top_border() else
|
||||
"none")
|
||||
("0.002cm solid #000000" if cell_style.get_top_border()
|
||||
else "none")
|
||||
)
|
||||
|
||||
wrt(' fo:border-bottom="%s"' %
|
||||
("0.002cm solid #000000"
|
||||
if cell_style.get_bottom_border() else
|
||||
"none")
|
||||
("0.002cm solid #000000" if cell_style.get_bottom_border()
|
||||
else "none")
|
||||
)
|
||||
|
||||
wrt(' fo:border-left="%s"' %
|
||||
("0.002cm solid #000000"
|
||||
if cell_style.get_left_border() else
|
||||
"none")
|
||||
("0.002cm solid #000000" if cell_style.get_left_border()
|
||||
else "none")
|
||||
)
|
||||
|
||||
wrt(' fo:border-right="%s"' %
|
||||
("0.002cm solid #000000"
|
||||
if cell_style.get_right_border() else
|
||||
"none")
|
||||
("0.002cm solid #000000" if cell_style.get_right_border()
|
||||
else "none")
|
||||
)
|
||||
|
||||
wrt(
|
||||
'/>\n'
|
||||
wrt('/>\n'
|
||||
'</style:style>\n'
|
||||
)
|
||||
|
||||
@ -771,7 +721,7 @@ class ODFDoc(BaseDoc, TextDoc, DrawDoc):
|
||||
We want no duplicate in the list
|
||||
"""
|
||||
# order preserving
|
||||
funct = funct or (lambda x:x)
|
||||
funct = funct or (lambda x: x)
|
||||
seen = set()
|
||||
result = []
|
||||
for item in list_:
|
||||
@ -789,7 +739,7 @@ class ODFDoc(BaseDoc, TextDoc, DrawDoc):
|
||||
The content.xml file is closed.
|
||||
"""
|
||||
self.cntntx = StringIO()
|
||||
self.StyleList_notes = self.uniq(self.StyleList_notes)
|
||||
self.stylelist_notes = self.uniq(self.stylelist_notes)
|
||||
self.add_styled_notes_fonts()
|
||||
self.add_styled_notes_styles()
|
||||
self.add_styled_photo_styles()
|
||||
@ -823,12 +773,11 @@ class ODFDoc(BaseDoc, TextDoc, DrawDoc):
|
||||
"""
|
||||
# Need to add new font for styled notes here.
|
||||
wrt1 = self.cntnt1.write
|
||||
for style in self.StyleList_notes:
|
||||
for style in self.stylelist_notes:
|
||||
if style[1] == "FontFace":
|
||||
# Restore any spaces that were replaced by hyphens in
|
||||
# libodfbackend
|
||||
wrt1(
|
||||
'<style:font-face ' +
|
||||
wrt1('<style:font-face ' +
|
||||
' style:name="%s"\n' % style[2].replace("-", " ") +
|
||||
' svg:font-family="'%s'"\n' %
|
||||
style[2].replace("-", " ") +
|
||||
@ -841,10 +790,9 @@ class ODFDoc(BaseDoc, TextDoc, DrawDoc):
|
||||
"""
|
||||
# Need to add new style for styled notes here.
|
||||
wrt2 = self.cntnt2.write
|
||||
for style in self.StyleList_notes:
|
||||
for style in self.stylelist_notes:
|
||||
if style[1] == "FontSize":
|
||||
wrt2(
|
||||
'<style:style ' +
|
||||
wrt2('<style:style ' +
|
||||
'style:name="FontSize__%s__"\n' % style[2] +
|
||||
' style:family="text">\n' +
|
||||
' <style:text-properties\n' +
|
||||
@ -857,8 +805,7 @@ class ODFDoc(BaseDoc, TextDoc, DrawDoc):
|
||||
elif style[1] == "FontColor":
|
||||
# Restore the hash at the start that was removed by
|
||||
# libodfbackend
|
||||
wrt2(
|
||||
'<style:style ' +
|
||||
wrt2('<style:style ' +
|
||||
'style:name="FontColor__%s__"\n' % style[2] +
|
||||
' style:family="text">\n' +
|
||||
' <style:text-properties\n' +
|
||||
@ -867,8 +814,7 @@ class ODFDoc(BaseDoc, TextDoc, DrawDoc):
|
||||
)
|
||||
|
||||
elif style[1] == "FontHighlight":
|
||||
wrt2(
|
||||
'<style:style ' +
|
||||
wrt2('<style:style ' +
|
||||
'style:name="FontHighlight__%s__"\n' % style[2] +
|
||||
' style:family="text">\n' +
|
||||
' <style:text-properties\n' +
|
||||
@ -879,8 +825,7 @@ class ODFDoc(BaseDoc, TextDoc, DrawDoc):
|
||||
elif style[1] == "FontFace":
|
||||
# Restore any spaces that were replaced by hyphens in
|
||||
# libodfbackend
|
||||
wrt2(
|
||||
'<style:style ' +
|
||||
wrt2('<style:style ' +
|
||||
'style:name="FontFace__%s__"\n' % style[2] +
|
||||
' style:family="text">\n' +
|
||||
' <style:text-properties\n' +
|
||||
@ -895,10 +840,9 @@ class ODFDoc(BaseDoc, TextDoc, DrawDoc):
|
||||
Add the new styles for clipped images in the automatic-styles section.
|
||||
"""
|
||||
wrt2 = self.cntnt2.write
|
||||
for style in self.StyleList_photos:
|
||||
for style in self.stylelist_photos:
|
||||
if style[0] == "Left":
|
||||
wrt2(
|
||||
'<style:style ' +
|
||||
wrt2('<style:style ' +
|
||||
'style:name="Left_%s" ' % str(style[1]) +
|
||||
'style:family="graphic" ' +
|
||||
'style:parent-style-name="photo">' +
|
||||
@ -925,8 +869,7 @@ class ODFDoc(BaseDoc, TextDoc, DrawDoc):
|
||||
'</style:style>\n'
|
||||
)
|
||||
elif style[0] == "Right":
|
||||
wrt2(
|
||||
'<style:style ' +
|
||||
wrt2('<style:style ' +
|
||||
'style:name="Right_%s" ' % str(style[1]) +
|
||||
'style:family="graphic" ' +
|
||||
'style:parent-style-name="photo">' +
|
||||
@ -953,8 +896,7 @@ class ODFDoc(BaseDoc, TextDoc, DrawDoc):
|
||||
'</style:style>\n'
|
||||
)
|
||||
elif style[0] == "Single":
|
||||
wrt2(
|
||||
'<style:style ' +
|
||||
wrt2('<style:style ' +
|
||||
'style:name="Single_%s" ' % str(style[1]) +
|
||||
'style:family="graphic" ' +
|
||||
'style:parent-style-name="photo">' +
|
||||
@ -974,8 +916,7 @@ class ODFDoc(BaseDoc, TextDoc, DrawDoc):
|
||||
'</style:style>\n'
|
||||
)
|
||||
else:
|
||||
wrt2(
|
||||
'<style:style ' +
|
||||
wrt2('<style:style ' +
|
||||
'style:name="Row_%s" ' % str(style[1]) +
|
||||
'style:family="graphic" ' +
|
||||
'style:parent-style-name="Graphics">' +
|
||||
@ -998,7 +939,8 @@ class ODFDoc(BaseDoc, TextDoc, DrawDoc):
|
||||
'</style:style>\n'
|
||||
)
|
||||
|
||||
def add_media(self, file_name, pos, x_cm, y_cm, alt='', style_name=None, crop=None):
|
||||
def add_media(self, file_name, pos, x_cm, y_cm, alt='', style_name=None,
|
||||
crop=None):
|
||||
"""
|
||||
Add multi-media documents : photos
|
||||
"""
|
||||
@ -1015,7 +957,7 @@ class ODFDoc(BaseDoc, TextDoc, DrawDoc):
|
||||
odf_name = md5(file_name_hash).hexdigest() + extension
|
||||
|
||||
media_list_item = (file_name, odf_name)
|
||||
if not media_list_item in self.media_list:
|
||||
if media_list_item not in self.media_list:
|
||||
self.media_list.append(media_list_item)
|
||||
|
||||
base = escape(os.path.basename(file_name))
|
||||
@ -1027,11 +969,11 @@ class ODFDoc(BaseDoc, TextDoc, DrawDoc):
|
||||
pos = pos.title() if pos in ['left', 'right', 'single'] else 'Row'
|
||||
|
||||
if crop:
|
||||
(start_x, start_y, end_x, end_y
|
||||
) = crop_percentage_to_subpixel(x, y, crop)
|
||||
(start_x, start_y,
|
||||
end_x, end_y) = crop_percentage_to_subpixel(x, y, crop)
|
||||
|
||||
# Need to keep the ratio intact, otherwise scaled images look stretched
|
||||
# if the dimensions aren't close in size
|
||||
# Need to keep the ratio intact, otherwise scaled images look
|
||||
# stretched if the dimensions aren't close in size
|
||||
(act_width, act_height) = image_actual_size(
|
||||
x_cm, y_cm, int(end_x-start_x), int(end_y-start_y)
|
||||
)
|
||||
@ -1045,7 +987,7 @@ class ODFDoc(BaseDoc, TextDoc, DrawDoc):
|
||||
bottom = (y - end_y)/dpi[1]
|
||||
crop = (top, right, bottom, left)
|
||||
|
||||
self.StyleList_photos.append(
|
||||
self.stylelist_photos.append(
|
||||
[pos, crop]
|
||||
)
|
||||
|
||||
@ -1174,12 +1116,12 @@ class ODFDoc(BaseDoc, TextDoc, DrawDoc):
|
||||
"""
|
||||
self.cntnt.write('</text:span>')
|
||||
|
||||
def _add_zip(self, zfile, name, data, t):
|
||||
def _add_zip(self, zfile, name, data, date_time):
|
||||
"""
|
||||
Add a zip file to an archive
|
||||
"""
|
||||
zipinfo = zipfile.ZipInfo(name)
|
||||
zipinfo.date_time = t
|
||||
zipinfo.date_time = date_time
|
||||
zipinfo.compress_type = zipfile.ZIP_DEFLATED
|
||||
zipinfo.external_attr = 0o644 << 16
|
||||
zfile.writestr(zipinfo, data)
|
||||
@ -1196,14 +1138,15 @@ class ODFDoc(BaseDoc, TextDoc, DrawDoc):
|
||||
except:
|
||||
raise ReportError(_("Could not create %s") % self.filename)
|
||||
|
||||
t = time.localtime(time.time())[:6]
|
||||
now = time.localtime(time.time())[:6]
|
||||
|
||||
self._add_zip(zfile, "META-INF/manifest.xml", self.mfile.getvalue(), t)
|
||||
self._add_zip(zfile, "content.xml", self.cntntx.getvalue(), t)
|
||||
self._add_zip(zfile, "meta.xml", self.meta.getvalue(), t)
|
||||
self._add_zip(zfile, "settings.xml", self.stfile.getvalue(), t)
|
||||
self._add_zip(zfile, "styles.xml", self.sfile.getvalue(), t)
|
||||
self._add_zip(zfile, "mimetype", self.mimetype.getvalue(), t)
|
||||
self._add_zip(zfile, "META-INF/manifest.xml", self.mfile.getvalue(),
|
||||
now)
|
||||
self._add_zip(zfile, "content.xml", self.cntntx.getvalue(), now)
|
||||
self._add_zip(zfile, "meta.xml", self.meta.getvalue(), now)
|
||||
self._add_zip(zfile, "settings.xml", self.stfile.getvalue(), now)
|
||||
self._add_zip(zfile, "styles.xml", self.sfile.getvalue(), now)
|
||||
self._add_zip(zfile, "mimetype", self.mimetype.getvalue(), now)
|
||||
|
||||
self.mfile.close()
|
||||
self.cntnt.close()
|
||||
@ -1215,7 +1158,8 @@ class ODFDoc(BaseDoc, TextDoc, DrawDoc):
|
||||
for image in self.media_list:
|
||||
try:
|
||||
with open(image[0], mode='rb') as ifile:
|
||||
self._add_zip(zfile, "Pictures/%s" % image[1], ifile.read(), t)
|
||||
self._add_zip(zfile, "Pictures/%s" % image[1],
|
||||
ifile.read(), now)
|
||||
except OSError as msg:
|
||||
errmsg = "%s\n%s" % (_("Could not open %s") % image[0],
|
||||
msg)
|
||||
@ -1248,8 +1192,7 @@ class ODFDoc(BaseDoc, TextDoc, DrawDoc):
|
||||
|
||||
for style_name in styles.get_paragraph_style_names():
|
||||
style = styles.get_paragraph_style(style_name)
|
||||
wrtf(
|
||||
'<style:style style:name="%s" ' % style_name +
|
||||
wrtf('<style:style style:name="%s" ' % style_name +
|
||||
'style:family="paragraph" ' +
|
||||
'style:parent-style-name="Standard" ' +
|
||||
'style:class="text">\n' +
|
||||
@ -1279,18 +1222,15 @@ class ODFDoc(BaseDoc, TextDoc, DrawDoc):
|
||||
elif align == PARA_ALIGN_RIGHT:
|
||||
wrtf('fo:text-align="end" ')
|
||||
elif align == PARA_ALIGN_CENTER:
|
||||
wrtf(
|
||||
'fo:text-align="center" '
|
||||
wrtf('fo:text-align="center" '
|
||||
'style:justify-single-word="false" '
|
||||
)
|
||||
else:
|
||||
wrtf(
|
||||
'fo:text-align="justify" '
|
||||
wrtf('fo:text-align="justify" '
|
||||
'style:justify-single-word="false" '
|
||||
)
|
||||
|
||||
wrtf(
|
||||
'fo:text-indent="%.2fcm" ' % style.get_first_indent() +
|
||||
wrtf('fo:text-indent="%.2fcm" ' % style.get_first_indent() +
|
||||
'style:auto-text-indent="false"/> ' +
|
||||
'<style:text-properties '
|
||||
)
|
||||
@ -1300,9 +1240,8 @@ class ODFDoc(BaseDoc, TextDoc, DrawDoc):
|
||||
wrtf('fo:color="#%02x%02x%02x" ' % color)
|
||||
|
||||
wrtf('style:font-name="%s" ' %
|
||||
("Arial"
|
||||
if font.get_type_face() == FONT_SANS_SERIF else
|
||||
"Times New Roman")
|
||||
("Arial" if font.get_type_face() == FONT_SANS_SERIF
|
||||
else "Times New Roman")
|
||||
)
|
||||
|
||||
wrtf('fo:font-size="%.0fpt" ' % font.get_size())
|
||||
@ -1312,8 +1251,7 @@ class ODFDoc(BaseDoc, TextDoc, DrawDoc):
|
||||
wrtf('fo:font-weight="bold" ')
|
||||
|
||||
if font.get_underline():
|
||||
wrtf(
|
||||
'style:text-underline="single" ' +
|
||||
wrtf('style:text-underline="single" ' +
|
||||
'style:text-underline-color="font-color" ' +
|
||||
'fo:text-indent="%.2fcm" ' % style.get_first_indent() +
|
||||
'fo:margin-right="%.2fcm" ' % style.get_right_margin() +
|
||||
@ -1321,8 +1259,7 @@ class ODFDoc(BaseDoc, TextDoc, DrawDoc):
|
||||
'fo:margin-top="%.2fcm" ' % style.get_top_margin() +
|
||||
'fo:margin-bottom="%.2fcm"\n' % style.get_bottom_margin()
|
||||
)
|
||||
wrtf(
|
||||
'/>\n'
|
||||
wrtf('/>\n'
|
||||
'</style:style>\n'
|
||||
)
|
||||
|
||||
@ -1332,7 +1269,9 @@ class ODFDoc(BaseDoc, TextDoc, DrawDoc):
|
||||
wrtf('<draw:stroke-dash draw:name="gramps_%s" draw:style="rect" '
|
||||
'draw:dots1="%d" draw:dots1-length="0.102cm" '
|
||||
'draw:dots2="%d" draw:dots2-length="0.102cm" '
|
||||
'draw:distance="%5.3fcm" />\n' % (line_style, dash_array[0], dash_array[0], dash_array[1] * 0.051))
|
||||
'draw:distance="%5.3fcm" />\n' %
|
||||
(line_style, dash_array[0], dash_array[0],
|
||||
dash_array[1] * 0.051))
|
||||
|
||||
|
||||
# Current no leading number format for headers
|
||||
@ -1360,8 +1299,7 @@ class ODFDoc(BaseDoc, TextDoc, DrawDoc):
|
||||
#wrtf('text:level="10" style:num-format=""/>\n')
|
||||
#wrtf('</text:outline-style>\n')
|
||||
|
||||
wrtf(
|
||||
'<text:notes-configuration '
|
||||
wrtf('<text:notes-configuration '
|
||||
'text:note-class="footnote" '
|
||||
'style:num-format="1" '
|
||||
'text:start-value="0" '
|
||||
@ -1369,15 +1307,13 @@ class ODFDoc(BaseDoc, TextDoc, DrawDoc):
|
||||
'text:start-numbering-at="document"/> '
|
||||
)
|
||||
|
||||
wrtf(
|
||||
'<text:notes-configuration '
|
||||
wrtf('<text:notes-configuration '
|
||||
'text:note-class="endnote" '
|
||||
'style:num-format="i" '
|
||||
'text:start-value="0"/> '
|
||||
)
|
||||
|
||||
wrtf(
|
||||
'<text:linenumbering-configuration '
|
||||
wrtf('<text:linenumbering-configuration '
|
||||
'text:number-lines="false" '
|
||||
'text:offset="0.499cm" '
|
||||
'style:num-format="1" '
|
||||
@ -1386,8 +1322,7 @@ class ODFDoc(BaseDoc, TextDoc, DrawDoc):
|
||||
)
|
||||
|
||||
wrtf('</office:styles>\n')
|
||||
wrtf(
|
||||
'<office:automatic-styles>\n' +
|
||||
wrtf('<office:automatic-styles>\n' +
|
||||
_SHEADER_FOOTER +
|
||||
'<style:page-layout style:name="pm1">\n' +
|
||||
'<style:page-layout-properties ' +
|
||||
@ -1399,13 +1334,11 @@ class ODFDoc(BaseDoc, TextDoc, DrawDoc):
|
||||
)
|
||||
|
||||
wrtf('style:print-orientation="%s" ' %
|
||||
("portrait"
|
||||
if self.paper.get_orientation() == PAPER_PORTRAIT else
|
||||
"landscape")
|
||||
("portrait" if self.paper.get_orientation() == PAPER_PORTRAIT
|
||||
else "landscape")
|
||||
)
|
||||
|
||||
wrtf(
|
||||
'fo:margin-top="%.2fcm" '
|
||||
wrtf('fo:margin-top="%.2fcm" '
|
||||
% self.paper.get_top_margin() +
|
||||
'fo:margin-bottom="%.2fcm" '
|
||||
% self.paper.get_bottom_margin() +
|
||||
@ -1424,30 +1357,26 @@ class ODFDoc(BaseDoc, TextDoc, DrawDoc):
|
||||
)
|
||||
|
||||
# header
|
||||
wrtf(
|
||||
'<style:header-style>\n'
|
||||
wrtf('<style:header-style>\n'
|
||||
'<style:header-footer-properties '
|
||||
'fo:min-height="0cm" fo:margin-bottom="0.499cm"/>\n'
|
||||
'</style:header-style>\n'
|
||||
)
|
||||
|
||||
# footer
|
||||
wrtf(
|
||||
'<style:footer-style>\n'
|
||||
wrtf('<style:footer-style>\n'
|
||||
'<style:header-footer-properties '
|
||||
'fo:min-height="0cm" fo:margin-bottom="0.499cm"/>\n'
|
||||
'</style:footer-style>\n'
|
||||
)
|
||||
|
||||
# End of page layout
|
||||
wrtf(
|
||||
'</style:page-layout>\n'
|
||||
wrtf('</style:page-layout>\n'
|
||||
'</office:automatic-styles>\n'
|
||||
)
|
||||
|
||||
# Master Styles
|
||||
wrtf(
|
||||
'<office:master-styles>\n'
|
||||
wrtf('<office:master-styles>\n'
|
||||
'<style:master-page style:name="Standard" '
|
||||
'style:page-layout-name="pm1">\n'
|
||||
# header
|
||||
@ -1540,7 +1469,7 @@ class ODFDoc(BaseDoc, TextDoc, DrawDoc):
|
||||
s_tags = styledtext.get_tags()
|
||||
markuptext = self._backend.add_markup_from_styled(text, s_tags, '\n')
|
||||
|
||||
if links == True:
|
||||
if links is True:
|
||||
markuptext = re.sub(URL_PATTERN, _CLICKABLE, markuptext)
|
||||
|
||||
# we need to know if we have new styles to add.
|
||||
@ -1551,10 +1480,10 @@ class ODFDoc(BaseDoc, TextDoc, DrawDoc):
|
||||
# The first element is the StyleType and the second one is the value
|
||||
start = 0
|
||||
while 1:
|
||||
m = NewStyle.search(markuptext, start)
|
||||
m = NEW_STYLE.search(markuptext, start)
|
||||
if not m:
|
||||
break
|
||||
self.StyleList_notes.append([m.group(1)+m.group(2),
|
||||
self.stylelist_notes.append([m.group(1)+m.group(2),
|
||||
m.group(1),
|
||||
m.group(2)])
|
||||
start = m.end()
|
||||
@ -1567,7 +1496,7 @@ class ODFDoc(BaseDoc, TextDoc, DrawDoc):
|
||||
self.start_paragraph(style_name)
|
||||
linenb = 1
|
||||
else:
|
||||
if ( linenb > 1 ):
|
||||
if linenb > 1:
|
||||
self.cntnt.write('<text:line-break/>')
|
||||
self.cntnt.write(line)
|
||||
linenb += 1
|
||||
@ -1576,13 +1505,13 @@ class ODFDoc(BaseDoc, TextDoc, DrawDoc):
|
||||
def write_text(self, text, mark=None, links=False):
|
||||
"""
|
||||
Uses the xml.sax.saxutils.escape function to convert XML
|
||||
entities. The _esc_map dictionary allows us to add our own
|
||||
entities. The ESC_MAP dictionary allows us to add our own
|
||||
mappings.
|
||||
@param mark: IndexMark to use for indexing
|
||||
"""
|
||||
text = escape(text, _esc_map)
|
||||
text = escape(text, ESC_MAP)
|
||||
|
||||
if links == True:
|
||||
if links is True:
|
||||
text = re.sub(URL_PATTERN, _CLICKABLE, text)
|
||||
|
||||
self._write_mark(mark, text)
|
||||
@ -1594,7 +1523,7 @@ class ODFDoc(BaseDoc, TextDoc, DrawDoc):
|
||||
Insert a mark at this point in the document.
|
||||
"""
|
||||
if mark:
|
||||
key = escape(mark.key, _esc_map)
|
||||
key = escape(mark.key, ESC_MAP)
|
||||
key = key.replace('"', '"')
|
||||
if mark.type == INDEX_TYPE_ALP:
|
||||
self.cntnt.write(
|
||||
@ -1705,7 +1634,7 @@ class ODFDoc(BaseDoc, TextDoc, DrawDoc):
|
||||
'xmlns:manifest="urn:oasis:names:tc:opendocument' +
|
||||
':xmlns:manifest:1.0">' +
|
||||
'<manifest:file-entry ' +
|
||||
'manifest:media-type="%s" ' % _apptype +
|
||||
'manifest:media-type="%s" ' % APP_TYPE +
|
||||
'manifest:full-path="/"/>'
|
||||
)
|
||||
|
||||
@ -1780,8 +1709,8 @@ class ODFDoc(BaseDoc, TextDoc, DrawDoc):
|
||||
style_sheet = self.get_style_sheet()
|
||||
stype = style_sheet.get_draw_style(style)
|
||||
pname = stype.get_paragraph_style()
|
||||
p = style_sheet.get_paragraph_style(pname)
|
||||
font = p.get_font()
|
||||
para = style_sheet.get_paragraph_style(pname)
|
||||
font = para.get_font()
|
||||
size = font.get_size()
|
||||
|
||||
height = size * (len(text))
|
||||
@ -1809,7 +1738,7 @@ class ODFDoc(BaseDoc, TextDoc, DrawDoc):
|
||||
'<draw:text-box>\n' +
|
||||
'<text:p text:style-name="X%s">' % pname +
|
||||
'<text:span text:style-name="F%s">' % pname +
|
||||
escape('\n'.join(text), _esc_map) +
|
||||
escape('\n'.join(text), ESC_MAP) +
|
||||
'</text:span></text:p>\n</draw:text-box>\n' +
|
||||
'</draw:frame>\n')
|
||||
|
||||
@ -1894,7 +1823,7 @@ class ODFDoc(BaseDoc, TextDoc, DrawDoc):
|
||||
'<text:p text:style-name="F%s">' % para_name +
|
||||
'<text:span text:style-name="F%s">' % para_name +
|
||||
#' fo:max-height="%.2f">' % font.get_size() +
|
||||
escape(text, _esc_map) +
|
||||
escape(text, ESC_MAP) +
|
||||
'</text:span>' +
|
||||
'</text:p>' +
|
||||
'</draw:text-box>\n' +
|
||||
@ -1940,7 +1869,7 @@ class ODFDoc(BaseDoc, TextDoc, DrawDoc):
|
||||
self.cntnt.write(
|
||||
'<text:p text:style-name="%s">' % para_name +
|
||||
'<text:span text:style-name="F%s">' % para_name +
|
||||
escape(text, _esc_map) +
|
||||
escape(text, ESC_MAP) +
|
||||
'</text:span>'
|
||||
'</text:p>\n'
|
||||
)
|
||||
@ -1976,7 +1905,7 @@ class ODFDoc(BaseDoc, TextDoc, DrawDoc):
|
||||
'<draw:text-box>' +
|
||||
'<text:p text:style-name="X%s">' % para_name +
|
||||
'<text:span text:style-name="F%s">' % para_name +
|
||||
escape(text, _esc_map) +
|
||||
escape(text, ESC_MAP) +
|
||||
'</text:span>\n' +
|
||||
'</text:p>\n' +
|
||||
'</draw:text-box>'
|
||||
@ -1991,27 +1920,29 @@ def process_spaces(line, format):
|
||||
|
||||
If the text is flowed (format==0), then leading spaces (after ignoring XML)
|
||||
are removed. Embedded multiple spaces are reduced to one by ODF
|
||||
If the text is pre-formatted (format==1). then all spaces (after ignoring XML)
|
||||
are replaced by "<text:s/>"
|
||||
If the text is pre-formatted (format==1), then all spaces (after ignoring
|
||||
XML) are replaced by "<text:s/>"
|
||||
|
||||
Returns the processed text, and the number of significant (i.e. non-white-space) chars.
|
||||
Returns the processed text, and the number of significant
|
||||
(i.e. non-white-space) chars.
|
||||
"""
|
||||
txt = ""
|
||||
xml = False
|
||||
sigcount = 0
|
||||
# we loop through every character, which is very inefficient, but an attempt to use
|
||||
# a regex replace didn't always work. This was the code that was replaced.
|
||||
# We loop through every character, which is very inefficient, but an attempt
|
||||
# to use a regex replace didn't always work. This was the code that was
|
||||
# replaced.
|
||||
# Problem, we may not replace ' ' in xml tags, so we use a regex
|
||||
# self.cntnt.write(re.sub(' (?=([^(<|>)]*<[^>]*>)*[^>]*$)',
|
||||
# "<text:s/>", line))
|
||||
for char in line:
|
||||
if char == '<' and xml == False:
|
||||
if char == '<' and xml is False:
|
||||
xml = True
|
||||
txt += char
|
||||
elif char == '>' and xml == True:
|
||||
elif char == '>' and xml is True:
|
||||
xml = False
|
||||
txt += char
|
||||
elif xml == True:
|
||||
elif xml is True:
|
||||
txt += char
|
||||
elif char == " " or char == "\t":
|
||||
if format == 0 and sigcount == 0:
|
||||
|
@ -24,24 +24,26 @@
|
||||
|
||||
#------------------------------------------------------------------------
|
||||
#
|
||||
# python modules
|
||||
# Python modules
|
||||
#
|
||||
#------------------------------------------------------------------------
|
||||
from gramps.gen.const import GRAMPS_LOCALE as glocale
|
||||
_ = glocale.translation.gettext
|
||||
import logging
|
||||
LOG = logging.getLogger(".rtfdoc")
|
||||
|
||||
#------------------------------------------------------------------------
|
||||
#
|
||||
# Load the base BaseDoc class
|
||||
# Gramps modules
|
||||
#
|
||||
#------------------------------------------------------------------------
|
||||
from gramps.gen.plug.docgen import (BaseDoc, TextDoc, FONT_SERIF, PARA_ALIGN_RIGHT,
|
||||
PARA_ALIGN_CENTER, PARA_ALIGN_JUSTIFY,
|
||||
URL_PATTERN)
|
||||
from gramps.gen.utils.image import image_size, image_actual_size, resize_to_jpeg_buffer
|
||||
from gramps.gen.plug.docgen import (
|
||||
BaseDoc, TextDoc, FONT_SERIF, PARA_ALIGN_RIGHT, PARA_ALIGN_CENTER,
|
||||
PARA_ALIGN_JUSTIFY, URL_PATTERN)
|
||||
from gramps.gen.utils.image import (image_size, image_actual_size,
|
||||
resize_to_jpeg_buffer)
|
||||
from gramps.gen.errors import ReportError
|
||||
from gramps.gen.const import GRAMPS_LOCALE as glocale
|
||||
_ = glocale.translation.gettext
|
||||
|
||||
LOG = logging.getLogger(".rtfdoc")
|
||||
|
||||
#------------------------------------------------------------------------
|
||||
#
|
||||
@ -52,15 +54,18 @@ _CLICKABLE = r'''{\\field{\\*\\fldinst HYPERLINK "\1"}{\\fldrslt \1}}'''
|
||||
|
||||
#------------------------------------------------------------------------
|
||||
#
|
||||
# RTF uses a unit called "twips" for its measurements. According to the
|
||||
# RTF specification, 1 point is 20 twips. This routines converts
|
||||
# centimeters to twips
|
||||
#
|
||||
# 2.54 cm/inch 72pts/inch, 20twips/pt
|
||||
# Functions
|
||||
#
|
||||
#------------------------------------------------------------------------
|
||||
def twips(cm):
|
||||
return int(((cm/2.54)*72)+0.5)*20
|
||||
def twips(length_cm):
|
||||
"""
|
||||
RTF uses a unit called "twips" for its measurements. According to the
|
||||
RTF specification, 1 point is 20 twips. This routines converts
|
||||
centimeters to twips
|
||||
|
||||
2.54 cm/inch 72pts/inch, 20twips/pt
|
||||
"""
|
||||
return int(((length_cm/2.54)*72)+0.5)*20
|
||||
|
||||
#------------------------------------------------------------------------
|
||||
#
|
||||
@ -68,25 +73,21 @@ def twips(cm):
|
||||
# use style sheets. Instead it writes raw formatting.
|
||||
#
|
||||
#------------------------------------------------------------------------
|
||||
class RTFDoc(BaseDoc,TextDoc):
|
||||
|
||||
#--------------------------------------------------------------------
|
||||
#
|
||||
# Opens the file, and writes the header. Builds the color and font
|
||||
# tables. Fonts are chosen using the MS TrueType fonts, since it
|
||||
# is assumed that if you are generating RTF, you are probably
|
||||
# targeting Word. This generator assumes a Western Europe character
|
||||
# set.
|
||||
#
|
||||
#--------------------------------------------------------------------
|
||||
def open(self,filename):
|
||||
class RTFDoc(BaseDoc, TextDoc):
|
||||
"""
|
||||
Opens the file, and writes the header. Builds the color and font tables.
|
||||
Fonts are chosen using the MS TrueType fonts, since it is assumed that if
|
||||
you are generating RTF, you are probably targeting Word. This generator
|
||||
assumes a Western Europe character set.
|
||||
"""
|
||||
def open(self, filename):
|
||||
if filename[-4:] != ".rtf":
|
||||
self.filename = filename + ".rtf"
|
||||
else:
|
||||
self.filename = filename
|
||||
|
||||
try:
|
||||
self.f = open(self.filename,"w")
|
||||
self.file = open(self.filename, "w")
|
||||
except IOError as msg:
|
||||
errmsg = "%s\n%s" % (_("Could not create %s") % self.filename, msg)
|
||||
raise ReportError(errmsg)
|
||||
@ -95,7 +96,7 @@ class RTFDoc(BaseDoc,TextDoc):
|
||||
|
||||
style_sheet = self.get_style_sheet()
|
||||
|
||||
self.f.write(
|
||||
self.file.write(
|
||||
'{\\rtf1\\ansi\\ansicpg1252\\deff0\n'
|
||||
'{\\fonttbl\n'
|
||||
'{\\f0\\froman\\fcharset0\\fprq0 Times New Roman;}\n'
|
||||
@ -105,22 +106,22 @@ class RTFDoc(BaseDoc,TextDoc):
|
||||
|
||||
self.color_map = {}
|
||||
index = 1
|
||||
self.color_map[(0,0,0)] = 0
|
||||
self.f.write('\\red0\\green0\\blue0;')
|
||||
self.color_map[(0, 0, 0)] = 0
|
||||
self.file.write('\\red0\\green0\\blue0;')
|
||||
for style_name in style_sheet.get_paragraph_style_names():
|
||||
style = style_sheet.get_paragraph_style(style_name)
|
||||
fgcolor = style.get_font().get_color()
|
||||
bgcolor = style.get_background_color()
|
||||
if fgcolor not in self.color_map:
|
||||
self.color_map[fgcolor] = index
|
||||
self.f.write('\\red%d\\green%d\\blue%d;' % fgcolor)
|
||||
self.file.write('\\red%d\\green%d\\blue%d;' % fgcolor)
|
||||
index += 1
|
||||
if bgcolor not in self.color_map:
|
||||
self.f.write('\\red%d\\green%d\\blue%d;' % bgcolor)
|
||||
self.file.write('\\red%d\\green%d\\blue%d;' % bgcolor)
|
||||
self.color_map[bgcolor] = index
|
||||
index += 1
|
||||
self.f.write('}\n')
|
||||
self.f.write(
|
||||
self.file.write('}\n')
|
||||
self.file.write(
|
||||
'\\kerning0\\cf0\\viewkind1' +
|
||||
'\\paperw%d' % twips(self.paper.get_size().get_width()) +
|
||||
'\\paperh%d' % twips(self.paper.get_size().get_height()) +
|
||||
@ -139,8 +140,8 @@ class RTFDoc(BaseDoc,TextDoc):
|
||||
#
|
||||
#--------------------------------------------------------------------
|
||||
def close(self):
|
||||
self.f.write('}\n')
|
||||
self.f.close()
|
||||
self.file.write('}\n')
|
||||
self.file.close()
|
||||
|
||||
#--------------------------------------------------------------------
|
||||
#
|
||||
@ -148,7 +149,7 @@ class RTFDoc(BaseDoc,TextDoc):
|
||||
#
|
||||
#--------------------------------------------------------------------
|
||||
def end_page(self):
|
||||
self.f.write('\\sbkpage\n')
|
||||
self.file.write('\\sbkpage\n')
|
||||
|
||||
#--------------------------------------------------------------------
|
||||
#
|
||||
@ -157,70 +158,70 @@ class RTFDoc(BaseDoc,TextDoc):
|
||||
# does work.
|
||||
#
|
||||
#--------------------------------------------------------------------
|
||||
def start_paragraph(self,style_name,leader=None):
|
||||
def start_paragraph(self, style_name, leader=None):
|
||||
self.opened = 0
|
||||
style_sheet = self.get_style_sheet()
|
||||
p = style_sheet.get_paragraph_style(style_name)
|
||||
para = style_sheet.get_paragraph_style(style_name)
|
||||
|
||||
# build font information
|
||||
|
||||
f = p.get_font()
|
||||
size = f.get_size()*2
|
||||
bgindex = self.color_map[p.get_background_color()]
|
||||
fgindex = self.color_map[f.get_color()]
|
||||
if f.get_type_face() == FONT_SERIF:
|
||||
font = para.get_font()
|
||||
size = font.get_size()*2
|
||||
bgindex = self.color_map[para.get_background_color()]
|
||||
fgindex = self.color_map[font.get_color()]
|
||||
if font.get_type_face() == FONT_SERIF:
|
||||
self.font_type = '\\f0'
|
||||
else:
|
||||
self.font_type = '\\f1'
|
||||
self.font_type += '\\fs%d\\cf%d\\cb%d' % (size,fgindex,bgindex)
|
||||
self.font_type += '\\fs%d\\cf%d\\cb%d' % (size, fgindex, bgindex)
|
||||
|
||||
if f.get_bold():
|
||||
if font.get_bold():
|
||||
self.font_type += "\\b"
|
||||
if f.get_underline():
|
||||
if font.get_underline():
|
||||
self.font_type += "\\ul"
|
||||
if f.get_italic():
|
||||
if font.get_italic():
|
||||
self.font_type += "\\i"
|
||||
|
||||
# build paragraph information
|
||||
|
||||
if not self.in_table:
|
||||
self.f.write('\\pard')
|
||||
if p.get_alignment() == PARA_ALIGN_RIGHT:
|
||||
self.f.write('\\qr')
|
||||
elif p.get_alignment() == PARA_ALIGN_CENTER:
|
||||
self.f.write('\\qc')
|
||||
self.f.write(
|
||||
'\\ri%d' % twips(p.get_right_margin()) +
|
||||
'\\li%d' % twips(p.get_left_margin()) +
|
||||
'\\fi%d' % twips(p.get_first_indent())
|
||||
self.file.write('\\pard')
|
||||
if para.get_alignment() == PARA_ALIGN_RIGHT:
|
||||
self.file.write('\\qr')
|
||||
elif para.get_alignment() == PARA_ALIGN_CENTER:
|
||||
self.file.write('\\qc')
|
||||
self.file.write(
|
||||
'\\ri%d' % twips(para.get_right_margin()) +
|
||||
'\\li%d' % twips(para.get_left_margin()) +
|
||||
'\\fi%d' % twips(para.get_first_indent())
|
||||
)
|
||||
if p.get_alignment() == PARA_ALIGN_JUSTIFY:
|
||||
self.f.write('\\qj')
|
||||
if p.get_padding():
|
||||
self.f.write('\\sa%d' % twips(p.get_padding()/2.0))
|
||||
if p.get_top_border():
|
||||
self.f.write('\\brdrt\\brdrs')
|
||||
if p.get_bottom_border():
|
||||
self.f.write('\\brdrb\\brdrs')
|
||||
if p.get_left_border():
|
||||
self.f.write('\\brdrl\\brdrs')
|
||||
if p.get_right_border():
|
||||
self.f.write('\\brdrr\\brdrs')
|
||||
if p.get_first_indent():
|
||||
self.f.write('\\fi%d' % twips(p.get_first_indent()))
|
||||
if p.get_left_margin():
|
||||
self.f.write('\\li%d' % twips(p.get_left_margin()))
|
||||
if p.get_right_margin():
|
||||
self.f.write('\\ri%d' % twips(p.get_right_margin()))
|
||||
if para.get_alignment() == PARA_ALIGN_JUSTIFY:
|
||||
self.file.write('\\qj')
|
||||
if para.get_padding():
|
||||
self.file.write('\\sa%d' % twips(para.get_padding()/2.0))
|
||||
if para.get_top_border():
|
||||
self.file.write('\\brdrt\\brdrs')
|
||||
if para.get_bottom_border():
|
||||
self.file.write('\\brdrb\\brdrs')
|
||||
if para.get_left_border():
|
||||
self.file.write('\\brdrl\\brdrs')
|
||||
if para.get_right_border():
|
||||
self.file.write('\\brdrr\\brdrs')
|
||||
if para.get_first_indent():
|
||||
self.file.write('\\fi%d' % twips(para.get_first_indent()))
|
||||
if para.get_left_margin():
|
||||
self.file.write('\\li%d' % twips(para.get_left_margin()))
|
||||
if para.get_right_margin():
|
||||
self.file.write('\\ri%d' % twips(para.get_right_margin()))
|
||||
|
||||
if leader:
|
||||
self.opened = 1
|
||||
self.f.write('\\tx%d' % twips(p.get_left_margin()))
|
||||
self.f.write('{%s ' % self.font_type)
|
||||
self.file.write('\\tx%d' % twips(para.get_left_margin()))
|
||||
self.file.write('{%s ' % self.font_type)
|
||||
self.write_text(leader)
|
||||
self.f.write(self.text)
|
||||
self.file.write(self.text)
|
||||
self.text = ""
|
||||
self.f.write('\\tab}')
|
||||
self.file.write('\\tab}')
|
||||
self.opened = 0
|
||||
|
||||
#--------------------------------------------------------------------
|
||||
@ -233,20 +234,21 @@ class RTFDoc(BaseDoc,TextDoc):
|
||||
#--------------------------------------------------------------------
|
||||
def end_paragraph(self):
|
||||
# FIXME: I don't understand why no end paragraph marker is output when
|
||||
# we are inside a table. Since at least version 3.2.2, this seems to mean that
|
||||
# there is no new paragraph after the first line of a table entry.
|
||||
# we are inside a table. Since at least version 3.2.2, this seems to
|
||||
# mean that there is no new paragraph after the first line of a table
|
||||
# entry.
|
||||
# For example in the birth cell, the first paragraph should be the
|
||||
# description (21 Jan 1900 in London); if there is a note following this,
|
||||
# there is no newline between the description and the note.
|
||||
# description (21 Jan 1900 in London); if there is a note following
|
||||
# this, there is no newline between the description and the note.
|
||||
if not self.in_table:
|
||||
self.f.write(self.text)
|
||||
LOG.debug("end_paragraph: opened: %d write: %s" %
|
||||
(self.opened,
|
||||
self.text + '}' if self.opened else "" + "newline"))
|
||||
self.file.write(self.text)
|
||||
LOG.debug("end_paragraph: opened: %d write: %s",
|
||||
self.opened,
|
||||
self.text + '}' if self.opened else "" + "newline")
|
||||
if self.opened:
|
||||
self.f.write('}')
|
||||
self.file.write('}')
|
||||
self.opened = 0
|
||||
self.f.write('\n\\par')
|
||||
self.file.write('\n\\par')
|
||||
self.text = ""
|
||||
else:
|
||||
if self.text == "":
|
||||
@ -259,7 +261,7 @@ class RTFDoc(BaseDoc,TextDoc):
|
||||
#
|
||||
#--------------------------------------------------------------------
|
||||
def page_break(self):
|
||||
self.f.write('\\page\n')
|
||||
self.file.write('\\page\n')
|
||||
|
||||
#--------------------------------------------------------------------
|
||||
#
|
||||
@ -267,9 +269,8 @@ class RTFDoc(BaseDoc,TextDoc):
|
||||
#
|
||||
#--------------------------------------------------------------------
|
||||
def start_bold(self):
|
||||
LOG.debug("start_bold: opened: %d saved text: %s" %
|
||||
(self.opened,
|
||||
'}' if self.opened else "" + '{%s\\b ' % self.font_type))
|
||||
LOG.debug("start_bold: opened: %d saved text: %s", self.opened,
|
||||
'}' if self.opened else "" + '{%s\\b ' % self.font_type)
|
||||
if self.opened:
|
||||
self.text += '}'
|
||||
self.text += '{%s\\b ' % self.font_type
|
||||
@ -281,9 +282,8 @@ class RTFDoc(BaseDoc,TextDoc):
|
||||
#
|
||||
#--------------------------------------------------------------------
|
||||
def end_bold(self):
|
||||
LOG.debug("end_bold: opened: %d saved text: %s" %
|
||||
(self.opened,
|
||||
self.text + '}'))
|
||||
LOG.debug("end_bold: opened: %d saved text: %s", self.opened,
|
||||
self.text + '}')
|
||||
if not self.opened == 1:
|
||||
print(self.opened)
|
||||
raise RuntimeError
|
||||
@ -304,7 +304,7 @@ class RTFDoc(BaseDoc,TextDoc):
|
||||
# table, since a table is treated as a bunch of rows.
|
||||
#
|
||||
#--------------------------------------------------------------------
|
||||
def start_table(self, name,style_name):
|
||||
def start_table(self, name, style_name):
|
||||
self.in_table = 1
|
||||
styles = self.get_style_sheet()
|
||||
self.tbl_style = styles.get_table_style(style_name)
|
||||
@ -330,7 +330,7 @@ class RTFDoc(BaseDoc,TextDoc):
|
||||
self.cell = 0
|
||||
self.prev = 0
|
||||
self.cell_percent = 0.0
|
||||
self.f.write('\\trowd\n')
|
||||
self.file.write('\\trowd\n')
|
||||
|
||||
#--------------------------------------------------------------------
|
||||
#
|
||||
@ -339,11 +339,11 @@ class RTFDoc(BaseDoc,TextDoc):
|
||||
#
|
||||
#--------------------------------------------------------------------
|
||||
def end_row(self):
|
||||
self.f.write('{')
|
||||
self.file.write('{')
|
||||
for line in self.contents:
|
||||
self.f.write(line)
|
||||
self.f.write('\\cell ')
|
||||
self.f.write('}\\pard\\intbl\\row\n')
|
||||
self.file.write(line)
|
||||
self.file.write('\\cell ')
|
||||
self.file.write('}\\pard\\intbl\\row\n')
|
||||
|
||||
#--------------------------------------------------------------------
|
||||
#
|
||||
@ -354,23 +354,23 @@ class RTFDoc(BaseDoc,TextDoc):
|
||||
# previous cells plus its own width.
|
||||
#
|
||||
#--------------------------------------------------------------------
|
||||
def start_cell(self,style_name,span=1):
|
||||
def start_cell(self, style_name, span=1):
|
||||
styles = self.get_style_sheet()
|
||||
s = styles.get_cell_style(style_name)
|
||||
self.remain = span -1
|
||||
if s.get_top_border():
|
||||
self.f.write('\\clbrdrt\\brdrs\\brdrw10\n')
|
||||
self.file.write('\\clbrdrt\\brdrs\\brdrw10\n')
|
||||
if s.get_bottom_border():
|
||||
self.f.write('\\clbrdrb\\brdrs\\brdrw10\n')
|
||||
self.file.write('\\clbrdrb\\brdrs\\brdrw10\n')
|
||||
if s.get_left_border():
|
||||
self.f.write('\\clbrdrl\\brdrs\\brdrw10\n')
|
||||
self.file.write('\\clbrdrl\\brdrs\\brdrw10\n')
|
||||
if s.get_right_border():
|
||||
self.f.write('\\clbrdrr\\brdrs\\brdrw10\n')
|
||||
self.file.write('\\clbrdrr\\brdrs\\brdrw10\n')
|
||||
table_width = float(self.paper.get_usable_width())
|
||||
for cell in range(self.cell,self.cell+span):
|
||||
for cell in range(self.cell, self.cell+span):
|
||||
self.cell_percent += float(self.tbl_style.get_column_width(cell))
|
||||
cell_width = twips((table_width * self.cell_percent)/100.0)
|
||||
self.f.write('\\cellx%d\\pard\intbl\n' % cell_width)
|
||||
self.file.write('\\cellx%d\\pard\intbl\n' % cell_width)
|
||||
self.cell += 1
|
||||
|
||||
#--------------------------------------------------------------------
|
||||
@ -391,35 +391,37 @@ class RTFDoc(BaseDoc,TextDoc):
|
||||
# dumped as a string of HEX numbers.
|
||||
#
|
||||
#--------------------------------------------------------------------
|
||||
def add_media(self, name, pos, x_cm, y_cm, alt='', style_name=None, crop=None):
|
||||
def add_media(self, name, pos, x_cm, y_cm, alt='', style_name=None,
|
||||
crop=None):
|
||||
|
||||
nx, ny = image_size(name)
|
||||
width, height = image_size(name)
|
||||
|
||||
if (nx, ny) == (0,0):
|
||||
if (width, height) == (0, 0):
|
||||
return
|
||||
|
||||
(act_width, act_height) = image_actual_size(x_cm, y_cm, nx, ny)
|
||||
(act_width, act_height) = image_actual_size(x_cm, y_cm, width, height)
|
||||
|
||||
act_width = twips(act_width)
|
||||
act_height = twips(act_height)
|
||||
|
||||
size = [act_width, act_height]
|
||||
buf = resize_to_jpeg_buffer(name, size, crop=crop)
|
||||
act_width = size[0] # In case it changed because of cropping or keeping the ratio
|
||||
# The size may change because of cropping or keeping the ratio
|
||||
act_width = size[0]
|
||||
act_height = size[1]
|
||||
|
||||
self.f.write('{\*\shppict{\\pict\\jpegblip')
|
||||
self.f.write('\\picwgoal%d\\pichgoal%d\n' % (act_width,act_height))
|
||||
self.file.write('{\*\shppict{\\pict\\jpegblip')
|
||||
self.file.write('\\picwgoal%d\\pichgoal%d\n' % (act_width, act_height))
|
||||
index = 1
|
||||
for i in buf:
|
||||
self.f.write('%02x' % i)
|
||||
if index%32==0:
|
||||
self.f.write('\n')
|
||||
self.file.write('%02x' % i)
|
||||
if index%32 == 0:
|
||||
self.file.write('\n')
|
||||
index = index+1
|
||||
self.f.write('}}\\par\n')
|
||||
self.file.write('}}\\par\n')
|
||||
|
||||
if len(alt):
|
||||
self.f.write('%s\n\\par\n' % '\\par'.join(alt))
|
||||
self.file.write('%s\n\\par\n' % '\\par'.join(alt))
|
||||
|
||||
def write_styled_note(self, styledtext, format, style_name,
|
||||
contains_html=False, links=False):
|
||||
@ -447,15 +449,15 @@ class RTFDoc(BaseDoc,TextDoc):
|
||||
self.start_paragraph(style_name)
|
||||
linenb = 1
|
||||
else:
|
||||
if ( linenb > 1 ):
|
||||
if linenb > 1:
|
||||
self.write_text('\\line ')
|
||||
self.write_text(line, links=links)
|
||||
linenb += 1
|
||||
# FIXME: I don't understand why these newlines are necessary.
|
||||
# It may be related to the behaviour of end_paragraph inside tables, and
|
||||
# write_text converting \n to end paragraph.
|
||||
# This code prevents the whole document going wrong, but seems to produce an extra
|
||||
# paragraph mark at the end of each table cell.
|
||||
# It may be related to the behaviour of end_paragraph inside tables,
|
||||
# and write_text converting \n to end paragraph.
|
||||
# This code prevents the whole document going wrong, but seems to
|
||||
# produce an extra paragraph mark at the end of each table cell.
|
||||
if self.in_table:
|
||||
# # Add LF when in table as in indiv_complete report
|
||||
self.write_text('\n')
|
||||
@ -472,9 +474,7 @@ class RTFDoc(BaseDoc,TextDoc):
|
||||
def write_text(self, text, mark=None, links=False):
|
||||
# Convert to unicode, just in case it's not. Fix of bug 2449.
|
||||
text = str(text)
|
||||
LOG.debug("write_text: opened: %d input text: %s" %
|
||||
(self.opened,
|
||||
text))
|
||||
LOG.debug("write_text: opened: %d input text: %s", self.opened, text)
|
||||
if self.opened == 0:
|
||||
self.opened = 1
|
||||
self.text += '{%s ' % self.font_type
|
||||
@ -488,18 +488,17 @@ class RTFDoc(BaseDoc,TextDoc):
|
||||
# RTF req valus in decimal, not hex.
|
||||
self.text += '{\\uc1\\u%d\\uc0}' % ord(i)
|
||||
elif i == '\n':
|
||||
self.text += '\n\\par ';
|
||||
self.text += '\n\\par '
|
||||
elif i == '{' or i == '}' or i == '\\':
|
||||
self.text += '\\%s' % i
|
||||
else:
|
||||
self.text += i
|
||||
|
||||
if links == True:
|
||||
if links is True:
|
||||
import re
|
||||
self.text = re.sub(URL_PATTERN, _CLICKABLE, self.text)
|
||||
LOG.debug("write_text, exit: opened: %d saved text: %s" %
|
||||
(self.opened,
|
||||
self.text))
|
||||
LOG.debug("write_text, exit: opened: %d saved text: %s", self.opened,
|
||||
self.text)
|
||||
|
||||
def process_spaces(line, format):
|
||||
"""
|
||||
@ -511,26 +510,27 @@ def process_spaces(line, format):
|
||||
are removed, and multiple spaces are reduced to one.
|
||||
If the text is pre-formatted (format==1). then all spaces are preserved
|
||||
|
||||
Note that xml is just treated like any other text,
|
||||
because it will be from the original note, and it is just printed, not interpreted.
|
||||
Returns the processed text, and the number of significant (i.e. non-white-space) chars.
|
||||
Note that xml is just treated like any other text, because it will be from
|
||||
the original note, and it is just printed, not interpreted.
|
||||
Returns the processed text, and the number of significant
|
||||
(i.e. non-white-space) chars.
|
||||
"""
|
||||
txt = ""
|
||||
xml = False
|
||||
space = False
|
||||
sigcount = 0
|
||||
# we loop through every character, which is very inefficient, but an attempt to use
|
||||
# a regex replace didn't always work.
|
||||
# we loop through every character, which is very inefficient, but an
|
||||
# attempt to use a regex replace didn't always work.
|
||||
for char in line:
|
||||
if char == " " or char == "\t":
|
||||
if format == 1:
|
||||
txt += char
|
||||
elif format == 0 and sigcount == 0:
|
||||
pass
|
||||
elif format == 0 and space == False:
|
||||
elif format == 0 and space is False:
|
||||
space = True
|
||||
txt += char
|
||||
elif format == 0 and space == True:
|
||||
elif format == 0 and space is True:
|
||||
pass
|
||||
else:
|
||||
sigcount += 1
|
||||
|
@ -27,7 +27,7 @@ SVG document generator.
|
||||
|
||||
#-------------------------------------------------------------------------
|
||||
#
|
||||
# python modules
|
||||
# Python modules
|
||||
#
|
||||
#-------------------------------------------------------------------------
|
||||
from io import StringIO
|
||||
@ -37,12 +37,12 @@ from io import StringIO
|
||||
# Gramps modules
|
||||
#
|
||||
#-------------------------------------------------------------------------
|
||||
from gramps.gen.const import GRAMPS_LOCALE as glocale
|
||||
_ = glocale.translation.gettext
|
||||
from gramps.gen.plug.docgen import BaseDoc, DrawDoc, SOLID, FONT_SANS_SERIF
|
||||
from gramps.gen.errors import ReportError
|
||||
from gramps.gen.plug.menu import EnumeratedListOption
|
||||
from gramps.gen.plug.report import DocOptions
|
||||
from gramps.gen.const import GRAMPS_LOCALE as glocale
|
||||
_ = glocale.translation.gettext
|
||||
|
||||
#-------------------------------------------------------------------------
|
||||
#
|
||||
@ -53,7 +53,7 @@ class SvgDrawDoc(BaseDoc, DrawDoc):
|
||||
|
||||
def __init__(self, styles, type, options=None):
|
||||
BaseDoc.__init__(self, styles, type)
|
||||
self.f = None
|
||||
self.file = None
|
||||
self.filename = None
|
||||
self.level = 0
|
||||
self.time = "0000-00-00T00:00:00"
|
||||
@ -83,18 +83,18 @@ class SvgDrawDoc(BaseDoc, DrawDoc):
|
||||
name = "%s.svg" % self.root
|
||||
|
||||
try:
|
||||
self.f = open(name,"w", encoding="utf-8")
|
||||
self.file = open(name, "w", encoding="utf-8")
|
||||
except IOError as msg:
|
||||
raise ReportError(_("Could not create %s") % name, msg)
|
||||
except:
|
||||
raise ReportError(_("Could not create %s") % name)
|
||||
|
||||
self.t = StringIO()
|
||||
self.buffer = StringIO()
|
||||
|
||||
width = self.paper.get_size().get_width()
|
||||
height = self.paper.get_size().get_height()
|
||||
|
||||
self.f.write(
|
||||
self.file.write(
|
||||
'<?xml version="1.0" encoding="UTF-8" standalone="no"?>\n'
|
||||
'<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.0//EN" '
|
||||
'"http://www.w3.org/TR/2001/REC-SVG-20010904/DTD/svg10.dtd">\n'
|
||||
@ -110,8 +110,8 @@ class SvgDrawDoc(BaseDoc, DrawDoc):
|
||||
style_sheet = self.get_style_sheet()
|
||||
stype = style_sheet.get_draw_style(style)
|
||||
pname = stype.get_paragraph_style()
|
||||
p = style_sheet.get_paragraph_style(pname)
|
||||
font = p.get_font()
|
||||
para = style_sheet.get_paragraph_style(pname)
|
||||
font = para.get_font()
|
||||
size = font.get_size()
|
||||
|
||||
width = height = 0
|
||||
@ -119,45 +119,45 @@ class SvgDrawDoc(BaseDoc, DrawDoc):
|
||||
width = max(width, self.string_width(font, line))
|
||||
height += size
|
||||
|
||||
centerx, centery = units(( x+self.paper.get_left_margin(),
|
||||
y+self.paper.get_top_margin() ))
|
||||
centerx, centery = units((x+self.paper.get_left_margin(),
|
||||
y+self.paper.get_top_margin()))
|
||||
xpos = (centerx - (width/2.0))
|
||||
ypos = (centery - (height/2.0))
|
||||
|
||||
self.t.write(
|
||||
self.buffer.write(
|
||||
'<text ' +
|
||||
'x="%4.2f" y="%4.2f" ' % (xpos, ypos) +
|
||||
'transform="rotate(%d %4.2f %4.2f)" ' % (angle, centerx, centery) +
|
||||
'style="fill:#%02x%02x%02x; '% font.get_color()
|
||||
)
|
||||
if font.get_bold():
|
||||
self.t.write('font-weight:bold;')
|
||||
self.buffer.write('font-weight:bold;')
|
||||
if font.get_italic():
|
||||
self.t.write('font-style:italic;')
|
||||
self.t.write('font-size:%dpt; ' % size)
|
||||
self.buffer.write('font-style:italic;')
|
||||
self.buffer.write('font-size:%dpt; ' % size)
|
||||
if font.get_type_face() == FONT_SANS_SERIF:
|
||||
self.t.write('font-family:sans-serif;')
|
||||
self.buffer.write('font-family:sans-serif;')
|
||||
else:
|
||||
self.t.write('font-family:serif;')
|
||||
self.t.write('">')
|
||||
self.buffer.write('font-family:serif;')
|
||||
self.buffer.write('">')
|
||||
|
||||
for line in text:
|
||||
# Center this line relative to the rest of the text
|
||||
linex = xpos + (width - self.string_width(font, line) ) / 2
|
||||
self.t.write(
|
||||
linex = xpos + (width - self.string_width(font, line)) / 2
|
||||
self.buffer.write(
|
||||
'<tspan x="%4.2f" dy="%d">' % (linex, size) +
|
||||
line +
|
||||
'</tspan>'
|
||||
)
|
||||
self.t.write('</text>\n')
|
||||
self.buffer.write('</text>\n')
|
||||
|
||||
def end_page(self):
|
||||
# Print the text last for each page so that it is rendered on top of
|
||||
# other graphic elements.
|
||||
self.f.write(self.t.getvalue())
|
||||
self.t.close()
|
||||
self.f.write('</svg>\n')
|
||||
self.f.close()
|
||||
self.file.write(self.buffer.getvalue())
|
||||
self.buffer.close()
|
||||
self.file.write('</svg>\n')
|
||||
self.file.close()
|
||||
|
||||
def draw_line(self, style, x1, y1, x2, y2):
|
||||
x1 += self.paper.get_left_margin()
|
||||
@ -166,17 +166,17 @@ class SvgDrawDoc(BaseDoc, DrawDoc):
|
||||
y2 += self.paper.get_top_margin()
|
||||
|
||||
style_sheet = self.get_style_sheet()
|
||||
s = style_sheet.get_draw_style(style)
|
||||
draw_style = style_sheet.get_draw_style(style)
|
||||
|
||||
line_out = '<line x1="%4.2fcm" y1="%4.2fcm" ' % (x1, y1)
|
||||
line_out += 'x2="%4.2fcm" y2="%4.2fcm" ' % (x2, y2)
|
||||
line_out += 'style="stroke:#%02x%02x%02x; ' % s.get_color()
|
||||
if s.get_line_style() != SOLID:
|
||||
line_out += 'style="stroke:#%02x%02x%02x; ' % draw_style.get_color()
|
||||
if draw_style.get_line_style() != SOLID:
|
||||
line_out += 'stroke-dasharray: %s; ' % (
|
||||
",".join(map(str, s.get_dash_style()))
|
||||
",".join(map(str, draw_style.get_dash_style()))
|
||||
)
|
||||
line_out += 'stroke-width:%.2fpt;"/>\n' % s.get_line_width()
|
||||
self.f.write(line_out)
|
||||
line_out += 'stroke-width:%.2fpt;"/>\n' % draw_style.get_line_width()
|
||||
self.file.write(line_out)
|
||||
|
||||
def draw_path(self, style, path):
|
||||
style_sheet = self.get_style_sheet()
|
||||
@ -190,16 +190,17 @@ class SvgDrawDoc(BaseDoc, DrawDoc):
|
||||
",".join(map(str, stype.get_dash_style()))
|
||||
)
|
||||
line_out += ' stroke-width:%.2fpt;"' % stype.get_line_width()
|
||||
line_out += ' points="%.2f,%.2f' % units((point[0]+self.paper.get_left_margin(),
|
||||
line_out += ' points="%.2f,%.2f' % units(
|
||||
(point[0]+self.paper.get_left_margin(),
|
||||
point[1]+self.paper.get_top_margin()))
|
||||
self.f.write(line_out)
|
||||
self.file.write(line_out)
|
||||
for point in path[1:]:
|
||||
self.f.write(
|
||||
self.file.write(
|
||||
' %.2f,%.2f'
|
||||
% units((point[0]+self.paper.get_left_margin(),
|
||||
point[1]+self.paper.get_top_margin()))
|
||||
)
|
||||
self.f.write('"/>\n')
|
||||
self.file.write('"/>\n')
|
||||
|
||||
def draw_box(self, style, text, x, y, w, h, mark=None):
|
||||
""" @param mark: IndexMark to use for indexing (not supported) """
|
||||
@ -211,7 +212,7 @@ class SvgDrawDoc(BaseDoc, DrawDoc):
|
||||
shadow_width = box_style.get_shadow_space()
|
||||
|
||||
if box_style.get_shadow() and shadow_width > 0:
|
||||
self.f.write(
|
||||
self.file.write(
|
||||
'<rect ' +
|
||||
'x="%4.2fcm" ' % (x + shadow_width) +
|
||||
'y="%4.2fcm" ' % (y + shadow_width) +
|
||||
@ -232,37 +233,37 @@ class SvgDrawDoc(BaseDoc, DrawDoc):
|
||||
",".join(map(str, box_style.get_dash_style()))
|
||||
)
|
||||
line_out += 'stroke-width:%f;"/>\n' % box_style.get_line_width()
|
||||
self.f.write(line_out)
|
||||
self.file.write(line_out)
|
||||
|
||||
if text:
|
||||
para_name = box_style.get_paragraph_style()
|
||||
assert( para_name != '' )
|
||||
p = style_sheet.get_paragraph_style(para_name)
|
||||
font = p.get_font()
|
||||
assert para_name != ''
|
||||
para = style_sheet.get_paragraph_style(para_name)
|
||||
font = para.get_font()
|
||||
font_size = font.get_size()
|
||||
lines = text.split('\n')
|
||||
mar = 10/28.35
|
||||
fs = (font_size/28.35) * 1.2
|
||||
center = y + (h + fs)/2.0 + (fs*0.2)
|
||||
ystart = center - (fs/2.0) * len(lines)
|
||||
fsize = (font_size/28.35) * 1.2
|
||||
center = y + (h + fsize)/2.0 + (fsize*0.2)
|
||||
ystart = center - (fsize/2.0) * len(lines)
|
||||
for i, line in enumerate(lines):
|
||||
ypos = ystart + (i * fs)
|
||||
self.t.write(
|
||||
ypos = ystart + (i * fsize)
|
||||
self.buffer.write(
|
||||
'<text ' +
|
||||
'x="%4.2fcm" ' % (x+mar) +
|
||||
'y="%4.2fcm" ' % ypos +
|
||||
'style="fill:#%02x%02x%02x; '% font.get_color()
|
||||
)
|
||||
if font.get_bold():
|
||||
self.t.write(' font-weight:bold;')
|
||||
self.buffer.write(' font-weight:bold;')
|
||||
if font.get_italic():
|
||||
self.t.write(' font-style:italic;')
|
||||
self.t.write(' font-size:%dpt;' % font_size)
|
||||
self.buffer.write(' font-style:italic;')
|
||||
self.buffer.write(' font-size:%dpt;' % font_size)
|
||||
if font.get_type_face() == FONT_SANS_SERIF:
|
||||
self.t.write(' font-family:sans-serif;')
|
||||
self.buffer.write(' font-family:sans-serif;')
|
||||
else:
|
||||
self.t.write(' font-family:serif;')
|
||||
self.t.write(
|
||||
self.buffer.write(' font-family:serif;')
|
||||
self.buffer.write(
|
||||
'">' +
|
||||
line +
|
||||
'</text>\n'
|
||||
@ -276,27 +277,27 @@ class SvgDrawDoc(BaseDoc, DrawDoc):
|
||||
style_sheet = self.get_style_sheet()
|
||||
box_style = style_sheet.get_draw_style(style)
|
||||
para_name = box_style.get_paragraph_style()
|
||||
p = style_sheet.get_paragraph_style(para_name)
|
||||
para = style_sheet.get_paragraph_style(para_name)
|
||||
|
||||
font = p.get_font()
|
||||
font = para.get_font()
|
||||
font_size = font.get_size()
|
||||
fs = (font_size/28.35) * 1.2
|
||||
self.t.write(
|
||||
fsize = (font_size/28.35) * 1.2
|
||||
self.buffer.write(
|
||||
'<text ' +
|
||||
'x="%4.2fcm" ' % x +
|
||||
'y="%4.2fcm" ' % (y+fs) +
|
||||
'y="%4.2fcm" ' % (y+fsize) +
|
||||
'style="fill:#%02x%02x%02x;'% font.get_color()
|
||||
)
|
||||
if font.get_bold():
|
||||
self.t.write('font-weight:bold;')
|
||||
self.buffer.write('font-weight:bold;')
|
||||
if font.get_italic():
|
||||
self.t.write('font-style:italic;')
|
||||
self.t.write('font-size:%dpt; ' % font_size)
|
||||
self.buffer.write('font-style:italic;')
|
||||
self.buffer.write('font-size:%dpt; ' % font_size)
|
||||
if font.get_type_face() == FONT_SANS_SERIF:
|
||||
self.t.write('font-family:sans-serif;')
|
||||
self.buffer.write('font-family:sans-serif;')
|
||||
else:
|
||||
self.t.write('font-family:serif;')
|
||||
self.t.write(
|
||||
self.buffer.write('font-family:serif;')
|
||||
self.buffer.write(
|
||||
'">' +
|
||||
text +
|
||||
'</text>\n'
|
||||
@ -307,8 +308,8 @@ class SvgDrawDoc(BaseDoc, DrawDoc):
|
||||
style_sheet = self.get_style_sheet()
|
||||
box_style = style_sheet.get_draw_style(style)
|
||||
para_name = box_style.get_paragraph_style()
|
||||
p = style_sheet.get_paragraph_style(para_name)
|
||||
font = p.get_font()
|
||||
para = style_sheet.get_paragraph_style(para_name)
|
||||
font = para.get_font()
|
||||
width = self.string_width(font, text) / 72
|
||||
x -= width
|
||||
self.draw_text(style, text, x, y)
|
||||
@ -345,6 +346,6 @@ class SvgDrawDocOptions(DocOptions):
|
||||
('blue', _('blue')),
|
||||
('cyan', _('cyan')),
|
||||
('magenta', _('magenta')),
|
||||
('yellow', _('yellow')) ])
|
||||
('yellow', _('yellow'))])
|
||||
background.set_help(_('The color, if any, of the SVG background'))
|
||||
menu.add_option(category_name, 'svg_background', background)
|
||||
|
Loading…
x
Reference in New Issue
Block a user