2002-10-20 19:55:16 +05:30
|
|
|
#
|
|
|
|
# Gramps - a GTK+/GNOME based genealogy program
|
|
|
|
#
|
2006-03-11 06:42:06 +05:30
|
|
|
# Copyright (C) 2000-2006 Donald N. Allingham
|
2009-03-19 07:54:29 +05:30
|
|
|
# Copyright (C) 2007-2009 Brian G. Matherly
|
2008-01-07 13:34:45 +05:30
|
|
|
# Copyright (C) 2008 Raphael Ackermann
|
2003-08-29 08:38:02 +05:30
|
|
|
# 2002-2003 Donald A. Peterson
|
2009-02-08 23:33:10 +05:30
|
|
|
# 2003 Alex Roitman
|
|
|
|
# 2009 Benny Malengier
|
2002-10-20 19:55:16 +05:30
|
|
|
#
|
|
|
|
# This program is free software; you can redistribute it and/or modify
|
|
|
|
# it under the terms of the GNU General Public License as published by
|
|
|
|
# the Free Software Foundation; either version 2 of the License, or
|
|
|
|
# (at your option) any later version.
|
|
|
|
#
|
|
|
|
# This program is distributed in the hope that it will be useful,
|
|
|
|
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
|
|
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
|
|
# GNU General Public License for more details.
|
|
|
|
#
|
|
|
|
# You should have received a copy of the GNU General Public License
|
|
|
|
# along with this program; if not, write to the Free Software
|
|
|
|
# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
|
|
|
#
|
|
|
|
|
2008-02-24 19:25:55 +05:30
|
|
|
# $Id:LaTeXDoc.py 9912 2008-01-22 09:17:46Z acraphae $
|
2005-12-06 12:08:09 +05:30
|
|
|
|
2002-10-20 19:55:16 +05:30
|
|
|
"""LaTeX document generator"""
|
|
|
|
|
2003-01-15 10:55:50 +05:30
|
|
|
#------------------------------------------------------------------------
|
|
|
|
#
|
|
|
|
# python modules
|
|
|
|
#
|
|
|
|
#------------------------------------------------------------------------
|
2006-04-07 03:32:46 +05:30
|
|
|
from gettext import gettext as _
|
2003-01-15 10:55:50 +05:30
|
|
|
|
2002-10-20 19:55:16 +05:30
|
|
|
#------------------------------------------------------------------------
|
|
|
|
#
|
|
|
|
# gramps modules
|
|
|
|
#
|
|
|
|
#------------------------------------------------------------------------
|
2009-05-30 03:55:44 +05:30
|
|
|
|
2009-03-19 07:54:29 +05:30
|
|
|
from gen.plug import PluginManager, DocGenPlugin
|
2009-05-31 20:29:56 +05:30
|
|
|
from gen.plug.docgen import BaseDoc, TextDoc, PAPER_LANDSCAPE, FONT_SANS_SERIF
|
2009-06-03 00:12:41 +05:30
|
|
|
from gen.plug.docbackend import DocBackend
|
2002-10-20 19:55:16 +05:30
|
|
|
import ImgManip
|
2003-06-16 10:27:25 +05:30
|
|
|
import Errors
|
2008-01-07 13:34:45 +05:30
|
|
|
import Utils
|
|
|
|
|
2009-06-03 00:12:41 +05:30
|
|
|
#------------------------------------------------------------------------
|
|
|
|
#
|
|
|
|
# Functions for docbackend
|
|
|
|
#
|
|
|
|
#------------------------------------------------------------------------
|
|
|
|
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('}','\\}')
|
|
|
|
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
|
|
|
|
"""
|
|
|
|
text = text.replace('&', '\\&')
|
|
|
|
text = text.replace('$', '\\$')
|
|
|
|
text = text.replace('%', '\\%')
|
|
|
|
text = text.replace('#', '\\#')
|
|
|
|
text = text.replace('_', '\\_')
|
|
|
|
text = text.replace('{', '\\{')
|
|
|
|
text = text.replace('}', '\\}')
|
|
|
|
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.1cm}\\ ')
|
|
|
|
return text
|
|
|
|
|
|
|
|
#------------------------------------------------------------------------
|
|
|
|
#
|
|
|
|
# Document Backend class for cairo docs
|
|
|
|
#
|
|
|
|
#------------------------------------------------------------------------
|
|
|
|
|
|
|
|
class LateXBackend(DocBackend):
|
|
|
|
"""
|
|
|
|
Implementation of docbackend for latex docs.
|
|
|
|
File and File format management for latex docs
|
|
|
|
"""
|
|
|
|
# overwrite base class attributes, they become static var of LaTeXDoc
|
|
|
|
SUPPORTED_MARKUP = [
|
|
|
|
DocBackend.BOLD,
|
|
|
|
DocBackend.ITALIC,
|
|
|
|
DocBackend.UNDERLINE,
|
|
|
|
DocBackend.FONTSIZE,
|
|
|
|
DocBackend.FONTFACE,
|
|
|
|
DocBackend.SUPERSCRIPT ]
|
|
|
|
|
|
|
|
STYLETAG_MARKUP = {
|
|
|
|
DocBackend.BOLD : ("\\textbf{", "}"),
|
|
|
|
DocBackend.ITALIC : ("\\textit{", "}"),
|
|
|
|
DocBackend.UNDERLINE : ("\\underline{", "}"),
|
|
|
|
DocBackend.SUPERSCRIPT : ("\\textsuperscript{", "}"),
|
|
|
|
}
|
|
|
|
|
|
|
|
ESCAPE_FUNC = lambda x: latexescape
|
|
|
|
|
|
|
|
def setescape(self, preformatted=False):
|
|
|
|
"""
|
|
|
|
Latex needs two different escape functions depending on the type.
|
|
|
|
This function allows to switch the escape function
|
|
|
|
"""
|
|
|
|
if not preformatted:
|
|
|
|
LateXBackend.ESCAPE_FUNC = lambda x: latexescape
|
|
|
|
else:
|
|
|
|
LateXBackend.ESCAPE_FUNC = lambda x: latexescapeverbatim
|
|
|
|
|
|
|
|
def _create_xmltag(self, type, value):
|
|
|
|
"""
|
|
|
|
overwrites the method in DocBackend.
|
|
|
|
creates the latex tags needed for non bool style types we support:
|
|
|
|
FONTSIZE : use different \large denomination based
|
|
|
|
on size
|
|
|
|
: very basic, in mono in the font face
|
|
|
|
then we use {\ttfamily }
|
|
|
|
"""
|
|
|
|
if type not in self.SUPPORTED_MARKUP:
|
|
|
|
return None
|
|
|
|
elif type == DocBackend.FONTSIZE:
|
|
|
|
#translate size in point to something LaTeX can work with
|
|
|
|
if value >= 22:
|
|
|
|
return ("{\\Huge ", "}")
|
|
|
|
elif value >= 20:
|
|
|
|
return ("{\\huge ", "}")
|
|
|
|
elif value >= 18:
|
|
|
|
return ("{\\LARGE ", "}")
|
|
|
|
elif value >= 16:
|
|
|
|
return ("{\\Large ", "}")
|
|
|
|
elif value >= 14:
|
|
|
|
return ("{\\large ", "}")
|
|
|
|
elif value < 8:
|
|
|
|
return ("{\\scriptsize ", "}")
|
|
|
|
elif value < 10:
|
|
|
|
return ("{\\footnotesize ", "}")
|
|
|
|
elif value < 12:
|
|
|
|
return ("{\\small ", "}")
|
|
|
|
else:
|
|
|
|
return ("", "")
|
|
|
|
elif type == DocBackend.FONTFACE:
|
|
|
|
if 'MONO' in value.upper():
|
|
|
|
return ("{\\ttfamily ", "}")
|
|
|
|
elif 'ROMAN' in value.upper():
|
|
|
|
return ("{\\rmfamily ", "}")
|
|
|
|
return None
|
|
|
|
|
|
|
|
def _checkfilename(self):
|
|
|
|
"""
|
|
|
|
Check to make sure filename satisfies the standards for this filetype
|
|
|
|
"""
|
|
|
|
if self._filename[-4:] != ".tex":
|
|
|
|
self._filename = self._filename + ".tex"
|
|
|
|
|
2005-12-06 12:08:09 +05:30
|
|
|
#------------------------------------------------------------------------
|
|
|
|
#
|
|
|
|
# Convert from roman to arabic numbers
|
|
|
|
#
|
|
|
|
#------------------------------------------------------------------------
|
|
|
|
def roman2arabic(strval):
|
|
|
|
"""
|
|
|
|
Roman to arabic converter for 0 < num < 4000.
|
|
|
|
|
|
|
|
Always returns an integer.
|
|
|
|
On an invalid input zero is returned.
|
|
|
|
"""
|
|
|
|
# Return zero if the type is not str
|
|
|
|
try:
|
|
|
|
strval = str(strval).upper()
|
|
|
|
if not strval:
|
|
|
|
return 0
|
|
|
|
except:
|
|
|
|
return 0
|
|
|
|
|
|
|
|
# Return None if there are chars outside of valid roman numerals
|
|
|
|
if [char for char in strval if char not in 'MDCLXVI']:
|
|
|
|
return 0
|
|
|
|
|
|
|
|
vals2 = ['CM', 'CD', 'XC', 'XL', 'IX', 'IV']
|
|
|
|
nums2 = ( 900, 400, 90, 40, 9, 4)
|
|
|
|
|
|
|
|
vals1 = [ 'M', 'D', 'C', 'L', 'X', 'V', 'I']
|
|
|
|
nums1 = (1000, 500, 100, 50, 10, 5, 1)
|
|
|
|
|
|
|
|
ret = 0
|
|
|
|
max_num = 1000
|
|
|
|
# Start unrolling strval from left to right,
|
|
|
|
# up to the penultimate char
|
|
|
|
i = 0
|
|
|
|
while i < len(strval):
|
|
|
|
first_index = vals1.index(strval[i])
|
|
|
|
|
|
|
|
if i+1 < len(strval) and strval[i:i+2] in vals2:
|
|
|
|
this_num = nums2[vals2.index(strval[i:i+2])]
|
|
|
|
if first_index+1 < len(nums1):
|
|
|
|
new_max_num = nums1[first_index+1]
|
|
|
|
else:
|
|
|
|
new_max_num = 0
|
|
|
|
i += 2
|
|
|
|
else:
|
|
|
|
this_num = nums1[first_index]
|
|
|
|
new_max_num = this_num
|
|
|
|
i += 1
|
|
|
|
|
|
|
|
# prohibit larger numbers following smaller ones,
|
|
|
|
# except for the above 2-char combinations
|
|
|
|
if this_num > max_num:
|
|
|
|
return 0
|
|
|
|
ret += this_num
|
|
|
|
max_num = new_max_num
|
|
|
|
|
|
|
|
return ret
|
|
|
|
|
2002-10-20 19:55:16 +05:30
|
|
|
#------------------------------------------------------------------------
|
|
|
|
#
|
|
|
|
# Paragraph Handling
|
|
|
|
#
|
|
|
|
#------------------------------------------------------------------------
|
2009-05-21 22:49:50 +05:30
|
|
|
class TexFont(object):
|
2002-10-20 19:55:16 +05:30
|
|
|
def __init__(self, style=None):
|
2007-05-05 09:31:35 +05:30
|
|
|
if style:
|
|
|
|
self.font_beg = style.font_beg
|
|
|
|
self.font_end = style.font_end
|
|
|
|
self.leftIndent = style.left_indent
|
|
|
|
self.firstLineIndent = style.firstLineIndent
|
|
|
|
else:
|
|
|
|
self.font_beg = ""
|
|
|
|
self.font_end = ""
|
|
|
|
self.leftIndent = ""
|
|
|
|
self.firstLineIndent = ""
|
2002-10-20 19:55:16 +05:30
|
|
|
|
|
|
|
#------------------------------------------------------------------------
|
|
|
|
#
|
2009-02-08 23:33:10 +05:30
|
|
|
# LaTeXDoc
|
2002-10-20 19:55:16 +05:30
|
|
|
#
|
|
|
|
#------------------------------------------------------------------------
|
2009-02-08 23:33:10 +05:30
|
|
|
|
2009-05-30 03:55:44 +05:30
|
|
|
class LaTeXDoc(BaseDoc, TextDoc):
|
2003-08-25 08:41:40 +05:30
|
|
|
"""LaTeX document interface class. Derived from BaseDoc"""
|
2009-02-08 23:33:10 +05:30
|
|
|
|
|
|
|
def page_break(self):
|
|
|
|
"Forces a page break, creating a new page"
|
2009-05-30 01:22:57 +05:30
|
|
|
self._backend.write('\\newpage ')
|
2002-10-20 19:55:16 +05:30
|
|
|
|
2009-05-30 01:22:57 +05:30
|
|
|
def open(self, filename):
|
2002-10-20 19:55:16 +05:30
|
|
|
"""Opens the specified file, making sure that it has the
|
|
|
|
extension of .tex"""
|
2009-05-30 01:22:57 +05:30
|
|
|
self._backend = LateXBackend(filename)
|
|
|
|
self._backend.open()
|
2002-10-20 19:55:16 +05:30
|
|
|
|
|
|
|
# Font size control seems to be limited. For now, ignore
|
|
|
|
# any style constraints, and use 12pt has the default
|
|
|
|
|
|
|
|
options = "12pt"
|
|
|
|
|
2009-05-30 03:55:44 +05:30
|
|
|
if self.paper.get_orientation() == PAPER_LANDSCAPE:
|
2002-10-20 19:55:16 +05:30
|
|
|
options = options + ",landscape"
|
|
|
|
|
|
|
|
# Paper selections are somewhat limited on a stock installation.
|
|
|
|
# If the user picks something not listed here, we'll just accept
|
|
|
|
# the default of the user's LaTeX installation (usually letter).
|
2007-02-25 02:45:21 +05:30
|
|
|
paper_name = self.paper.get_size().get_name()
|
|
|
|
if paper_name == "A4":
|
2002-10-20 19:55:16 +05:30
|
|
|
options = options + ",a4paper"
|
2007-02-25 02:45:21 +05:30
|
|
|
elif paper_name == "A5":
|
2002-10-20 19:55:16 +05:30
|
|
|
options = options + ",a5paper"
|
2007-02-25 02:45:21 +05:30
|
|
|
elif paper_name == "B5":
|
2002-10-20 19:55:16 +05:30
|
|
|
options = options + ",b4paper"
|
2007-02-25 02:45:21 +05:30
|
|
|
elif paper_name == "Legal":
|
2002-10-20 19:55:16 +05:30
|
|
|
options = options + ",legalpaper"
|
2007-02-25 02:45:21 +05:30
|
|
|
elif paper_name == "Letter":
|
2002-10-20 19:55:16 +05:30
|
|
|
options = options + ",letterpaper"
|
|
|
|
|
|
|
|
# Use the article template, T1 font encodings, and specify
|
2003-07-11 21:00:44 +05:30
|
|
|
# that we should use Latin1 and unicode character encodings.
|
2009-05-30 01:22:57 +05:30
|
|
|
self._backend.write('\\documentclass[%s]{article}\n' % options)
|
|
|
|
self._backend.write('\\usepackage[T1]{fontenc}\n')
|
|
|
|
self._backend.write('%\n% We use latin1 encoding at a minimum by default.\n')
|
|
|
|
self._backend.write('% GRAMPS uses unicode UTF-8 encoding for its\n')
|
|
|
|
self._backend.write('% international support. LaTeX can deal gracefully\n')
|
|
|
|
self._backend.write('% with unicode encoding by using the ucs style invoked\n')
|
|
|
|
self._backend.write('% when utf8 is specified as an option to the inputenc\n')
|
|
|
|
self._backend.write('% package. This package is included by default in some\n')
|
|
|
|
self._backend.write('% installations, but not in others, so we do not make it\n')
|
|
|
|
self._backend.write('% the default. Uncomment the second line if you wish to use it\n')
|
|
|
|
self._backend.write('% (If you do not have ucs.sty, you may obtain it from\n')
|
|
|
|
self._backend.write('% http://www.tug.org/tex-archive/macros/latex/contrib/supported/unicode/)\n')
|
|
|
|
self._backend.write('%\n')
|
|
|
|
self._backend.write('\\usepackage[latin1]{inputenc}\n')
|
|
|
|
self._backend.write('%\\usepackage[latin1,utf8]{inputenc}\n')
|
2007-05-05 09:31:35 +05:30
|
|
|
# add packages (should be standard on a default installation)
|
|
|
|
# for finer output control. Put comments in file for user to read
|
2009-05-30 01:22:57 +05:30
|
|
|
self._backend.write('\\usepackage{graphicx} % Extended graphics support\n')
|
|
|
|
self._backend.write('\\usepackage{longtable} % For multi-page tables\n')
|
|
|
|
self._backend.write('\\usepackage{calc} % For margin indents\n')
|
|
|
|
self._backend.write('%\n% Depending on your LaTeX installation, the')
|
|
|
|
self._backend.write(' margins may be too\n% narrow. ')
|
|
|
|
self._backend.write(' This can be corrected by uncommenting the following\n')
|
|
|
|
self._backend.write('% two lines and adjusting the width appropriately.')
|
|
|
|
self._backend.write(' The example\n% removes 0.5in from each margin.')
|
|
|
|
self._backend.write(' (Adds 1 inch to the text)\n')
|
|
|
|
self._backend.write('%\\addtolength{\\oddsidemargin}{-0.5in}\n')
|
|
|
|
self._backend.write('%\\addtolength{\\textwidth}{1.0in}\n%\n')
|
|
|
|
self._backend.write('% Create a margin-adjusting command that allows LaTeX\n')
|
|
|
|
self._backend.write('% to behave like the other gramps-supported output formats\n')
|
|
|
|
self._backend.write('\\newlength{\\leftedge}\n')
|
|
|
|
self._backend.write('\\setlength{\\leftedge}{\\parindent}\n')
|
|
|
|
self._backend.write('\\newlength{\\grampstext}\n')
|
|
|
|
self._backend.write('\\setlength{\\grampstext}{\\textwidth}\n')
|
|
|
|
self._backend.write('\\newcommand{\\grampsindent}[1]{%\n')
|
|
|
|
self._backend.write(' \\setlength{\\parindent}{\\leftedge + #1}%\n')
|
|
|
|
self._backend.write(' \\setlength{\\textwidth}{\\grampstext - #1}%\n')
|
|
|
|
self._backend.write('}\n\n')
|
|
|
|
self._backend.write('\\begin{document}\n\n')
|
2007-05-05 09:31:35 +05:30
|
|
|
|
2002-10-20 19:55:16 +05:30
|
|
|
self.in_list = 0
|
2007-05-05 09:31:35 +05:30
|
|
|
self.in_table = 0
|
|
|
|
self.imagenum = 0
|
|
|
|
|
|
|
|
#Establish some local styles for the report
|
|
|
|
self.latexstyle = {}
|
|
|
|
self.latex_font = {}
|
|
|
|
|
|
|
|
style_sheet = self.get_style_sheet()
|
|
|
|
for style_name in style_sheet.get_paragraph_style_names():
|
|
|
|
style = style_sheet.get_paragraph_style(style_name)
|
|
|
|
font = style.get_font()
|
|
|
|
size = font.get_size()
|
|
|
|
|
|
|
|
self.latex_font[style_name] = TexFont()
|
|
|
|
thisstyle = self.latex_font[style_name]
|
|
|
|
|
|
|
|
thisstyle.font_beg = ""
|
|
|
|
thisstyle.font_end = ""
|
|
|
|
# Is there special alignment? (default is left)
|
|
|
|
align = style.get_alignment_text()
|
|
|
|
if align == "center":
|
|
|
|
thisstyle.font_beg = thisstyle.font_beg + "\\centerline{"
|
|
|
|
thisstyle.font_end = "}" + thisstyle.font_end
|
|
|
|
elif align == "right":
|
|
|
|
thisstyle.font_beg = thisstyle.font_beg + "\\hfill"
|
|
|
|
|
|
|
|
# Establish font face and shape
|
2009-05-30 03:55:44 +05:30
|
|
|
if font.get_type_face() == FONT_SANS_SERIF:
|
2007-05-05 09:31:35 +05:30
|
|
|
thisstyle.font_beg = thisstyle.font_beg + "\\sffamily"
|
|
|
|
thisstyle.font_end = "\\rmfamily" + thisstyle.font_end
|
|
|
|
if font.get_bold():
|
|
|
|
thisstyle.font_beg = thisstyle.font_beg + "\\bfseries"
|
|
|
|
thisstyle.font_end = "\\mdseries" + thisstyle.font_end
|
|
|
|
if font.get_italic() or font.get_underline():
|
|
|
|
thisstyle.font_beg = thisstyle.font_beg + "\\itshape"
|
|
|
|
thisstyle.font_end = "\\upshape" + thisstyle.font_end
|
|
|
|
|
|
|
|
# Now determine font size
|
|
|
|
sflag = 0
|
|
|
|
if size >= 22:
|
|
|
|
thisstyle.font_beg = thisstyle.font_beg + "\\Huge"
|
|
|
|
sflag = 1
|
|
|
|
elif size >= 20:
|
|
|
|
thisstyle.font_beg = thisstyle.font_beg + "\\huge"
|
|
|
|
sflag = 1
|
|
|
|
elif size >= 18:
|
|
|
|
thisstyle.font_beg = thisstyle.font_beg + "\\LARGE"
|
|
|
|
sflag = 1
|
|
|
|
elif size >= 16:
|
|
|
|
thisstyle.font_beg = thisstyle.font_beg + "\\Large"
|
|
|
|
sflag = 1
|
|
|
|
elif size >= 14:
|
|
|
|
thisstyle.font_beg = thisstyle.font_beg + "\\large"
|
|
|
|
sflag = 1
|
|
|
|
elif size < 8:
|
|
|
|
thisstyle.font_beg = thisstyle.font_beg + "\\scriptsize"
|
|
|
|
sflag = 1
|
|
|
|
elif size < 10:
|
|
|
|
thisstyle.font_beg = thisstyle.font_beg + "\\footnotesize"
|
|
|
|
sflag = 1
|
|
|
|
elif size < 12:
|
|
|
|
thisstyle.font_beg = thisstyle.font_beg + "\\small"
|
|
|
|
sflag = 1
|
|
|
|
|
|
|
|
if sflag == 1:
|
|
|
|
thisstyle.font_end = thisstyle.font_end + "\\normalsize"
|
|
|
|
|
|
|
|
thisstyle.font_beg = thisstyle.font_beg + " "
|
|
|
|
thisstyle.font_end = thisstyle.font_end + " "
|
|
|
|
|
|
|
|
left = style.get_left_margin()
|
|
|
|
first = style.get_first_indent() + left
|
|
|
|
|
|
|
|
thisstyle.leftIndent = left
|
|
|
|
thisstyle.firstLineIndent = first
|
|
|
|
|
|
|
|
self.latexstyle[style_name] = thisstyle
|
2002-10-20 19:55:16 +05:30
|
|
|
|
|
|
|
def close(self):
|
|
|
|
"""Clean up and close the document"""
|
|
|
|
if self.in_list:
|
2009-05-30 01:22:57 +05:30
|
|
|
self._backend.write('\\end{enumerate}\n')
|
|
|
|
self._backend.write('\n\\end{document}\n')
|
|
|
|
self._backend.close()
|
2009-02-01 09:51:17 +05:30
|
|
|
if self.open_req:
|
2009-05-30 01:22:57 +05:30
|
|
|
Utils.open_file_with_default_application(self._backend.filename)
|
2002-10-20 19:55:16 +05:30
|
|
|
|
|
|
|
def end_page(self):
|
|
|
|
"""Issue a new page command"""
|
2009-05-30 01:22:57 +05:30
|
|
|
self._backend.write('\\newpage')
|
2002-10-20 19:55:16 +05:30
|
|
|
|
|
|
|
def start_paragraph(self,style_name,leader=None):
|
|
|
|
"""Paragraphs handling - A Gramps paragraph is any
|
2007-05-05 09:31:35 +05:30
|
|
|
single body of text from a single word to several sentences.
|
|
|
|
We assume a linebreak at the end of each paragraph."""
|
|
|
|
style_sheet = self.get_style_sheet()
|
|
|
|
|
|
|
|
style = style_sheet.get_paragraph_style(style_name)
|
|
|
|
ltxstyle = self.latexstyle[style_name]
|
|
|
|
self.level = style.get_header_level()
|
|
|
|
|
|
|
|
self.fbeg = ltxstyle.font_beg
|
|
|
|
self.fend = ltxstyle.font_end
|
|
|
|
self.indent = ltxstyle.leftIndent
|
|
|
|
self.FLindent = ltxstyle.firstLineIndent
|
|
|
|
|
2008-06-16 20:31:46 +05:30
|
|
|
if self.indent is not None and not self.in_table:
|
2007-05-05 09:31:35 +05:30
|
|
|
myspace = '%scm' % str(self.indent)
|
2009-05-30 01:22:57 +05:30
|
|
|
self._backend.write('\\grampsindent{%s}\n' % myspace)
|
2007-05-05 09:31:35 +05:30
|
|
|
self.fix_indent = 1
|
|
|
|
|
2008-06-16 20:31:46 +05:30
|
|
|
if leader is not None and not self.in_list:
|
2009-05-30 01:22:57 +05:30
|
|
|
self._backend.write('\\begin{enumerate}\n')
|
2007-05-05 09:31:35 +05:30
|
|
|
self.in_list = 1
|
2008-06-16 20:31:46 +05:30
|
|
|
if leader is not None:
|
2007-05-05 09:31:35 +05:30
|
|
|
# try obtaining integer
|
|
|
|
leader_1 = leader[:-1]
|
|
|
|
num = roman2arabic(leader_1)
|
|
|
|
if num == 0:
|
|
|
|
# Not roman, try arabic or fallback to 1
|
|
|
|
try:
|
|
|
|
num = int(leader_1)
|
|
|
|
except ValueError:
|
|
|
|
num = 1
|
2009-05-30 01:22:57 +05:30
|
|
|
self._backend.write(' \\renewcommand\\theenumi{\\arabic{enumi}}')
|
2005-12-06 12:08:09 +05:30
|
|
|
else:
|
2007-05-05 09:31:35 +05:30
|
|
|
# roman, set the case correctly
|
|
|
|
if leader_1.islower():
|
2009-05-30 01:22:57 +05:30
|
|
|
self._backend.write(' \\renewcommand\\theenumi{\\roman{enumi}}')
|
2007-05-05 09:31:35 +05:30
|
|
|
else:
|
2009-05-30 01:22:57 +05:30
|
|
|
self._backend.write(' \\renewcommand\\theenumi{\\Roman{enumi}}')
|
2007-05-05 09:31:35 +05:30
|
|
|
|
2009-05-30 01:22:57 +05:30
|
|
|
self._backend.write(' \\setcounter{enumi}{%d} ' % num)
|
|
|
|
self._backend.write(' \\addtocounter{enumi}{-1}\n')
|
|
|
|
self._backend.write(' \\item ')
|
2002-10-20 19:55:16 +05:30
|
|
|
|
2008-06-16 20:31:46 +05:30
|
|
|
if leader is None and not self.in_list and not self.in_table:
|
2009-05-30 01:22:57 +05:30
|
|
|
self._backend.write('\n')
|
2007-05-05 09:31:35 +05:30
|
|
|
|
2009-05-30 01:22:57 +05:30
|
|
|
self._backend.write('%s ' % self.fbeg)
|
2002-10-20 19:55:16 +05:30
|
|
|
|
|
|
|
def end_paragraph(self):
|
|
|
|
"""End the current paragraph"""
|
2007-05-05 09:31:35 +05:30
|
|
|
newline = '\ \\newline\n'
|
|
|
|
|
|
|
|
if self.in_list:
|
|
|
|
self.in_list = 0
|
2009-05-30 01:22:57 +05:30
|
|
|
self._backend.write('\n\\end{enumerate}\n')
|
2007-05-05 09:31:35 +05:30
|
|
|
newline = ''
|
|
|
|
|
|
|
|
elif self.in_table:
|
|
|
|
newline = ('')
|
|
|
|
|
2009-05-30 01:22:57 +05:30
|
|
|
self._backend.write('%s%s' % (self.fend, newline))
|
2007-05-05 09:31:35 +05:30
|
|
|
if self.fix_indent == 1:
|
|
|
|
self.fix_indent = 0
|
2009-05-30 01:22:57 +05:30
|
|
|
self._backend.write('\\grampsindent{0cm}\n')
|
2002-10-20 19:55:16 +05:30
|
|
|
|
|
|
|
def start_bold(self):
|
|
|
|
"""Bold face"""
|
2009-05-30 01:22:57 +05:30
|
|
|
self._backend.write('\\textbf{')
|
2002-10-20 19:55:16 +05:30
|
|
|
|
|
|
|
def end_bold(self):
|
|
|
|
"""End bold face"""
|
2009-05-30 01:22:57 +05:30
|
|
|
self._backend.write('}')
|
2007-01-31 08:43:31 +05:30
|
|
|
|
|
|
|
def start_superscript(self):
|
2009-05-30 01:22:57 +05:30
|
|
|
self._backend.write('\\textsuperscript{')
|
2007-01-31 08:43:31 +05:30
|
|
|
|
|
|
|
def end_superscript(self):
|
2009-05-30 01:22:57 +05:30
|
|
|
self._backend.write('}')
|
2002-10-20 19:55:16 +05:30
|
|
|
|
2008-02-24 19:25:55 +05:30
|
|
|
def start_table(self, name,style_name):
|
2002-10-20 19:55:16 +05:30
|
|
|
"""Begin new table"""
|
2007-04-23 17:16:26 +05:30
|
|
|
self.in_table = 1
|
|
|
|
self.currow = 0
|
2002-10-20 19:55:16 +05:30
|
|
|
|
2007-04-23 17:16:26 +05:30
|
|
|
# We need to know a priori how many columns are in this table
|
|
|
|
styles = self.get_style_sheet()
|
|
|
|
self.tblstyle = styles.get_table_style(style_name)
|
|
|
|
self.numcols = self.tblstyle.get_columns()
|
2002-10-20 19:55:16 +05:30
|
|
|
|
2007-04-23 17:16:26 +05:30
|
|
|
tblfmt = '*{%d}{l}' % self.numcols
|
2009-05-30 01:22:57 +05:30
|
|
|
self._backend.write('\n\n\\begin{longtable}[l]{%s}\n' % tblfmt)
|
2002-10-20 19:55:16 +05:30
|
|
|
|
|
|
|
def end_table(self):
|
|
|
|
"""Close the table environment"""
|
2007-05-05 09:31:35 +05:30
|
|
|
self.in_table = 0
|
|
|
|
# Create a paragraph separation below the table.
|
2009-05-30 01:22:57 +05:30
|
|
|
self._backend.write('\\end{longtable}\n\\par\n')
|
2002-10-20 19:55:16 +05:30
|
|
|
|
|
|
|
def start_row(self):
|
|
|
|
"""Begin a new row"""
|
2007-05-05 09:31:35 +05:30
|
|
|
# doline/skipfirst are flags for adding hor. rules
|
|
|
|
self.doline = 0
|
|
|
|
self.skipfirst = 0
|
2002-10-20 19:55:16 +05:30
|
|
|
self.curcol = 0
|
2007-05-05 09:31:35 +05:30
|
|
|
self.currow = self.currow + 1
|
|
|
|
|
2002-10-20 19:55:16 +05:30
|
|
|
def end_row(self):
|
|
|
|
"""End the row (new line)"""
|
2009-05-30 01:22:57 +05:30
|
|
|
self._backend.write('\\\\ ')
|
2007-05-05 09:31:35 +05:30
|
|
|
if self.doline == 1:
|
|
|
|
if self.skipfirst == 1:
|
2009-05-30 01:22:57 +05:30
|
|
|
self._backend.write('\\cline{2-%d}\n' % self.numcols)
|
2007-05-05 09:31:35 +05:30
|
|
|
else:
|
2009-05-30 01:22:57 +05:30
|
|
|
self._backend.write('\\hline \\\\ \n')
|
2007-05-05 09:31:35 +05:30
|
|
|
else:
|
2009-05-30 01:22:57 +05:30
|
|
|
self._backend.write('\n')
|
2007-05-05 09:31:35 +05:30
|
|
|
|
2002-10-20 19:55:16 +05:30
|
|
|
def start_cell(self,style_name,span=1):
|
|
|
|
"""Add an entry to the table.
|
2007-04-23 17:16:26 +05:30
|
|
|
We always place our data inside braces
|
|
|
|
for safety of formatting."""
|
|
|
|
self.colspan = span
|
|
|
|
self.curcol = self.curcol + self.colspan
|
|
|
|
|
|
|
|
styles = self.get_style_sheet()
|
|
|
|
self.cstyle = styles.get_cell_style(style_name)
|
|
|
|
self.lborder = self.cstyle.get_left_border()
|
|
|
|
self.rborder = self.cstyle.get_right_border()
|
|
|
|
self.bborder = self.cstyle.get_bottom_border()
|
|
|
|
self.tborder = self.cstyle.get_top_border()
|
|
|
|
self.llist = self.cstyle.get_longlist()
|
|
|
|
|
|
|
|
if self.llist == 1:
|
|
|
|
cellfmt = "p{\linewidth-3cm}"
|
|
|
|
else:
|
|
|
|
cellfmt = "l"
|
2007-05-05 09:31:35 +05:30
|
|
|
|
2007-04-23 17:16:26 +05:30
|
|
|
# Account for vertical rules
|
|
|
|
if self.lborder == 1:
|
|
|
|
cellfmt = '|' + cellfmt
|
|
|
|
if self.rborder == 1:
|
|
|
|
cellfmt = cellfmt + '|'
|
|
|
|
|
|
|
|
# and Horizontal rules
|
|
|
|
if self.bborder == 1:
|
|
|
|
self.doline = 1
|
|
|
|
elif self.curcol == 1:
|
2008-01-06 01:40:26 +05:30
|
|
|
self.skipfirst = 1
|
2007-04-23 17:16:26 +05:30
|
|
|
|
|
|
|
if self.tborder != 0:
|
2009-05-30 01:22:57 +05:30
|
|
|
self._backend.write('\\hline\n')
|
|
|
|
self._backend.write ('\\multicolumn{%d}{%s}{' % (span,cellfmt))
|
2007-05-05 09:31:35 +05:30
|
|
|
|
2002-10-20 19:55:16 +05:30
|
|
|
def end_cell(self):
|
|
|
|
"""Prepares for next cell"""
|
2009-05-30 01:22:57 +05:30
|
|
|
self._backend.write('} ')
|
2007-05-05 09:31:35 +05:30
|
|
|
if self.curcol < self.numcols:
|
2009-05-30 01:22:57 +05:30
|
|
|
self._backend.write('& ')
|
2002-10-20 19:55:16 +05:30
|
|
|
|
2009-06-09 04:49:37 +05:30
|
|
|
def add_media_object(self, name, pos, x, y, alt=''):
|
2002-10-20 19:55:16 +05:30
|
|
|
"""Add photo to report"""
|
2007-09-11 09:21:35 +05:30
|
|
|
return
|
2003-10-27 09:18:13 +05:30
|
|
|
|
|
|
|
try:
|
|
|
|
pic = ImgManip.ImgManip(name)
|
|
|
|
except:
|
|
|
|
return
|
|
|
|
|
2007-05-05 09:31:35 +05:30
|
|
|
self.imagenum = self.imagenum + 1
|
|
|
|
picf = self.filename[:-4] + '_img' + str(self.imagenum) + '.eps'
|
|
|
|
pic.eps_convert(picf)
|
|
|
|
|
|
|
|
# x and y will be maximum width OR height in units of cm
|
2008-02-24 19:25:55 +05:30
|
|
|
mysize = 'width=%dcm, height=%dcm,keepaspectratio' % (x,y)
|
2007-05-05 09:31:35 +05:30
|
|
|
if pos == "right":
|
2009-05-30 01:22:57 +05:30
|
|
|
self._backend.write('\\hfill\\includegraphics[%s]{%s}\n' % (mysize,picf))
|
2007-05-05 09:31:35 +05:30
|
|
|
elif pos == "left":
|
2009-05-30 01:22:57 +05:30
|
|
|
self._backend.write('\\includegraphics[%s]{%s}\\hfill\n' % (mysize,picf))
|
2007-05-05 09:31:35 +05:30
|
|
|
else:
|
2009-05-30 01:22:57 +05:30
|
|
|
self._backend.write('\\centerline{\\includegraphics[%s]{%s}}\n' % (mysize,picf))
|
2009-02-08 23:33:10 +05:30
|
|
|
|
|
|
|
def write_text(self,text,mark=None):
|
|
|
|
"""Write the text to the file"""
|
|
|
|
if text == '\n':
|
|
|
|
text = '\\newline\n'
|
|
|
|
text = latexescape(text)
|
|
|
|
#hard coded replace of the underline used for missing names/data
|
2009-02-11 04:37:35 +05:30
|
|
|
text = text.replace('\\_\\_\\_\\_\\_\\_\\_\\_\\_\\_\\_\\_\\_',
|
|
|
|
'\\underline{\hspace{3cm}}')
|
2009-05-30 01:22:57 +05:30
|
|
|
self._backend.write(text)
|
2009-02-08 23:33:10 +05:30
|
|
|
|
|
|
|
def write_styled_note(self, styledtext, format, style_name):
|
|
|
|
"""
|
|
|
|
Convenience function to write a styledtext to the latex doc.
|
|
|
|
styledtext : assumed a StyledText object to write
|
|
|
|
format : = 0 : Flowed, = 1 : Preformatted
|
|
|
|
style_name : name of the style to use for default presentation
|
|
|
|
"""
|
|
|
|
text = str(styledtext)
|
|
|
|
|
|
|
|
s_tags = styledtext.get_tags()
|
|
|
|
if format == 1:
|
|
|
|
#preformatted, use different escape function
|
2009-05-30 01:22:57 +05:30
|
|
|
self._backend.setescape(True)
|
2007-05-05 09:31:35 +05:30
|
|
|
|
2009-05-30 01:22:57 +05:30
|
|
|
markuptext = self._backend.add_markup_from_styled(text, s_tags)
|
2009-02-08 23:33:10 +05:30
|
|
|
|
|
|
|
#there is a problem if we write out a note in a table. No newline is
|
|
|
|
# possible, the note runs over the margin into infinity.
|
|
|
|
# A good solution for this ???
|
|
|
|
# A quick solution: create a minipage for the note and add that always
|
|
|
|
# hoping that the user will have left sufficient room for the page
|
2009-05-30 01:22:57 +05:30
|
|
|
self._backend.write("\\begin{minipage}{{0.8\\linewidth}}\n")
|
2009-02-08 23:33:10 +05:30
|
|
|
self.start_paragraph(style_name)
|
2009-05-30 01:22:57 +05:30
|
|
|
self._backend.write(markuptext)
|
2009-02-08 23:33:10 +05:30
|
|
|
self.end_paragraph()
|
|
|
|
#end the minipage, add trick to have a white line at bottom of note,
|
|
|
|
# we assume here a note should be distinct from its surrounding.
|
2009-05-30 01:22:57 +05:30
|
|
|
self._backend.write("\n\\vspace*{0.5cm} \n\end{minipage}\n\n")
|
2009-02-08 23:33:10 +05:30
|
|
|
if format == 1:
|
|
|
|
#preformatted finished, go back to normal escape function
|
2009-05-30 01:22:57 +05:30
|
|
|
self._backend.setescape(False)
|
2009-02-08 23:33:10 +05:30
|
|
|
|
2003-12-13 09:35:01 +05:30
|
|
|
def write_note(self,text,format,style_name):
|
|
|
|
"""Write the note's text to the file, respecting the format"""
|
|
|
|
self.start_paragraph(style_name)
|
|
|
|
if format == 1:
|
2009-05-30 01:22:57 +05:30
|
|
|
self._backend.write('\\begin{verbatim}')
|
2003-12-13 09:35:01 +05:30
|
|
|
self.write_text(text)
|
|
|
|
if format == 1:
|
2009-05-30 01:22:57 +05:30
|
|
|
self._backend.write('\\end{verbatim}')
|
2003-12-13 09:35:01 +05:30
|
|
|
self.end_paragraph()
|
|
|
|
|
2002-10-20 19:55:16 +05:30
|
|
|
#------------------------------------------------------------------------
|
|
|
|
#
|
2009-03-19 07:54:29 +05:30
|
|
|
# register_plugin
|
2002-10-20 19:55:16 +05:30
|
|
|
#
|
|
|
|
#------------------------------------------------------------------------
|
2009-03-19 07:54:29 +05:30
|
|
|
def register_plugin():
|
|
|
|
"""
|
|
|
|
Register the document generator with the GRAMPS plugin system.
|
|
|
|
"""
|
|
|
|
pmgr = PluginManager.get_instance()
|
|
|
|
plugin = DocGenPlugin(name = _('LaTeX'),
|
|
|
|
description = _("Generates documents in LaTeX "
|
|
|
|
"format."),
|
|
|
|
basedoc = LaTeXDoc,
|
|
|
|
paper = True,
|
|
|
|
style = False,
|
|
|
|
extension = "tex" )
|
|
|
|
pmgr.register_plugin(plugin)
|
|
|
|
|
|
|
|
register_plugin()
|