Part 1 basedoc changes: move out backend stuff from BaseDoc, use backend in
the docs. As a dir change will be done, backend itself will be committed later, trunk will be broken till then svn: r12590
This commit is contained in:
parent
e4b2162bd1
commit
f999ba9cc4
183
src/BaseDoc.py
183
src/BaseDoc.py
@ -1405,41 +1405,13 @@ class BaseDoc(object):
|
||||
# TextDoc
|
||||
#
|
||||
#------------------------------------------------------------------------
|
||||
def noescape(text):
|
||||
return text
|
||||
|
||||
|
||||
class TextDoc(object):
|
||||
"""
|
||||
Abstract Interface for text document generators. Output formats for
|
||||
text reports must implment this interface to be used by the report
|
||||
system.
|
||||
"""
|
||||
BOLD = 0
|
||||
ITALIC = 1
|
||||
UNDERLINE = 2
|
||||
FONTFACE = 3
|
||||
FONTSIZE = 4
|
||||
FONTCOLOR = 5
|
||||
HIGHLIGHT = 6
|
||||
SUPERSCRIPT = 7
|
||||
|
||||
SUPPORTED_MARKUP = []
|
||||
|
||||
ESCAPE_FUNC = lambda x: noescape
|
||||
#Map between styletypes and internally used values. This map is needed
|
||||
# to make TextDoc officially independant of gen.lib.styledtexttag
|
||||
STYLETYPE_MAP = {
|
||||
}
|
||||
CLASSMAP = None
|
||||
|
||||
#STYLETAGTABLE to store markup for write_markup associated with style tags
|
||||
STYLETAG_MARKUP = {
|
||||
BOLD : ("", ""),
|
||||
ITALIC : ("", ""),
|
||||
UNDERLINE : ("", ""),
|
||||
SUPERSCRIPT : ("", ""),
|
||||
}
|
||||
|
||||
def page_break(self):
|
||||
"Forces a page break, creating a new page"
|
||||
raise NotImplementedError
|
||||
@ -1592,159 +1564,6 @@ class TextDoc(object):
|
||||
@param h_cm: height in centimeters
|
||||
"""
|
||||
raise NotImplementedError
|
||||
|
||||
def find_tag_by_stag(self, s_tag):
|
||||
"""
|
||||
@param s_tag: object: assumed styledtexttag
|
||||
@param s_tagvalue: None/int/str: value associated with the tag
|
||||
|
||||
A styled tag is type with a value.
|
||||
Every styled tag must be converted to the tags used in the corresponding
|
||||
markup for the backend, eg <b>text</b> for bold in html.
|
||||
These markups are stored in STYLETAG_MARKUP. They are tuples for begin
|
||||
and end tag
|
||||
If a markup is not present yet, it is created, using the
|
||||
_create_xmltag method you can overwrite
|
||||
"""
|
||||
type = s_tag.name
|
||||
|
||||
if not self.STYLETYPE_MAP or \
|
||||
self.CLASSMAP <> type.__class__.__name__ :
|
||||
self.CLASSMAP == type.__class__.__name__
|
||||
self.STYLETYPE_MAP[type.__class__.BOLD] = self.BOLD
|
||||
self.STYLETYPE_MAP[type.ITALIC] = self.ITALIC
|
||||
self.STYLETYPE_MAP[type.UNDERLINE] = self.UNDERLINE
|
||||
self.STYLETYPE_MAP[type.FONTFACE] = self.FONTFACE
|
||||
self.STYLETYPE_MAP[type.FONTSIZE] = self.FONTSIZE
|
||||
self.STYLETYPE_MAP[type.FONTCOLOR] = self.FONTCOLOR
|
||||
self.STYLETYPE_MAP[type.HIGHLIGHT] = self.HIGHLIGHT
|
||||
self.STYLETYPE_MAP[type.SUPERSCRIPT] = self.SUPERSCRIPT
|
||||
|
||||
typeval = int(s_tag.name)
|
||||
s_tagvalue = s_tag.value
|
||||
tag_name = None
|
||||
if type.STYLE_TYPE[typeval] == bool:
|
||||
return self.STYLETAG_MARKUP[self.STYLETYPE_MAP[typeval]]
|
||||
elif type.STYLE_TYPE[typeval] == str:
|
||||
tag_name = "%d %s" % (typeval, s_tagvalue)
|
||||
elif type.STYLE_TYPE[typeval] == int:
|
||||
tag_name = "%d %d" % (typeval, s_tagvalue)
|
||||
if not tag_name:
|
||||
return None
|
||||
|
||||
tags = self.STYLETAG_MARKUP.get(tag_name)
|
||||
if tags is not None:
|
||||
return tags
|
||||
#no tag known yet, create the markup, add to lookup, and return
|
||||
tags = self._create_xmltag(self.STYLETYPE_MAP[typeval], s_tagvalue)
|
||||
self.STYLETAG_MARKUP[tag_name] = tags
|
||||
return tags
|
||||
|
||||
def _create_xmltag(self, type, value):
|
||||
"""
|
||||
Create the xmltags for the backend.
|
||||
Overwrite this method to create functionality with a backend
|
||||
"""
|
||||
if type not in self.SUPPORTED_MARKUP:
|
||||
return None
|
||||
return ('', '')
|
||||
|
||||
def _add_markup_from_styled(self, text, s_tags, split=''):
|
||||
"""
|
||||
Input is plain text, output is text with markup added according to the
|
||||
s_tags which are assumed to be styledtexttags.
|
||||
When split is given the text will be split over the value given, and
|
||||
tags applied in such a way that it the text can be safely splitted in
|
||||
pieces along split
|
||||
|
||||
@param text : str, a piece of text
|
||||
@param s_tags : styledtexttags that must be applied to the text
|
||||
@param split : str, optional. A string along which the output can
|
||||
be safely split without breaking the styling.
|
||||
As adding markup means original text must be escaped, ESCAPE_FUNC is
|
||||
used
|
||||
This can be used to convert the text of a styledtext to the format
|
||||
needed for a document backend
|
||||
Do not call this method in a report, use the write_markup method
|
||||
|
||||
@note: the algorithm is complex as it assumes mixing of tags is not
|
||||
allowed: eg <b>text<i> here</b> not</i> is assumed invalid
|
||||
as markup. If the s_tags require such a setup, what is returned
|
||||
is <b>text</b><i><b> here</b> not</i>
|
||||
overwrite this method if this complexity is not needed.
|
||||
"""
|
||||
FIRST = 0
|
||||
LAST = 1
|
||||
tagspos = {}
|
||||
for s_tag in s_tags:
|
||||
tag = self.find_tag_by_stag(s_tag)
|
||||
if tag is not None:
|
||||
for (start, end) in s_tag.ranges:
|
||||
if start in tagspos:
|
||||
tagspos[start] += [(tag, FIRST)]
|
||||
else:
|
||||
tagspos[start] = [(tag, FIRST)]
|
||||
if end in tagspos:
|
||||
tagspos[end] += [(tag, LAST)]
|
||||
else:
|
||||
tagspos[end] = [(tag, LAST)]
|
||||
start = 0
|
||||
end = len(text)
|
||||
keylist = tagspos.keys()
|
||||
keylist.sort()
|
||||
keylist = [x for x in keylist if x<=len(text)]
|
||||
opentags = []
|
||||
otext = u"" #the output, text with markup
|
||||
lensplit = len(split)
|
||||
for pos in keylist:
|
||||
#write text up to tag
|
||||
if pos > start:
|
||||
if split:
|
||||
#make sure text can split
|
||||
splitpos = text[start:pos].find(split)
|
||||
while splitpos <> -1:
|
||||
otext += self.ESCAPE_FUNC()(text[start:start+splitpos])
|
||||
#close open tags
|
||||
for opentag in reversed(opentags):
|
||||
otext += opentag[1]
|
||||
#add split text
|
||||
otext += self.ESCAPE_FUNC()(split)
|
||||
#open the tags again
|
||||
for opentag in opentags:
|
||||
otext += opentag[0]
|
||||
#obtain new values
|
||||
start = start + splitpos + lensplit
|
||||
splitpos = text[start:pos].find(split)
|
||||
|
||||
otext += self.ESCAPE_FUNC()(text[start:pos])
|
||||
#write out tags
|
||||
for tag in tagspos[pos]:
|
||||
#close open tags starting from last open
|
||||
for opentag in reversed(opentags):
|
||||
otext += opentag[1]
|
||||
#if start, add to opentag in beginning as first to open
|
||||
if tag[1] == FIRST:
|
||||
opentags = [tag[0]] + opentags
|
||||
else:
|
||||
#end tag, is closed already, remove from opentag
|
||||
opentags = [x for x in opentags if not x == tag[0] ]
|
||||
#now all tags are closed, open the ones that should open
|
||||
for opentag in opentags:
|
||||
otext += opentag[0]
|
||||
start = pos
|
||||
#add remainder of text, no markup present there
|
||||
otext += self.ESCAPE_FUNC()(text[start:end])
|
||||
|
||||
#opentags should be empty. If not, user gave tags on positions that
|
||||
# are over the end of the text. Just close the tags still open
|
||||
if opentags:
|
||||
print 'WARNING: TextDoc : More style tags in text than length '\
|
||||
'of text allows.\n', opentags
|
||||
for opentag in reversed(opentags):
|
||||
otext += opentag[1]
|
||||
|
||||
return otext
|
||||
|
||||
|
||||
#------------------------------------------------------------------------
|
||||
#
|
||||
|
@ -40,6 +40,7 @@ from gettext import gettext as _
|
||||
#
|
||||
#------------------------------------------------------------------------
|
||||
import BaseDoc
|
||||
from docbackend.latexbackend import LateXBackend, latexescape
|
||||
from gen.plug import PluginManager, DocGenPlugin
|
||||
import ImgManip
|
||||
import Errors
|
||||
@ -128,81 +129,18 @@ class TexFont(object):
|
||||
#
|
||||
#------------------------------------------------------------------------
|
||||
|
||||
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
|
||||
|
||||
class LaTeXDoc(BaseDoc.BaseDoc,BaseDoc.TextDoc):
|
||||
"""LaTeX document interface class. Derived from BaseDoc"""
|
||||
|
||||
# overwrite base class attributes, they become static var of LaTeXDoc
|
||||
SUPPORTED_MARKUP = [
|
||||
BaseDoc.TextDoc.BOLD,
|
||||
BaseDoc.TextDoc.ITALIC,
|
||||
BaseDoc.TextDoc.UNDERLINE,
|
||||
BaseDoc.TextDoc.FONTSIZE,
|
||||
BaseDoc.TextDoc.FONTFACE,
|
||||
BaseDoc.TextDoc.SUPERSCRIPT ]
|
||||
|
||||
STYLETAG_MARKUP = {
|
||||
BaseDoc.TextDoc.BOLD : ("\\textbf{", "}"),
|
||||
BaseDoc.TextDoc.ITALIC : ("\\textit{", "}"),
|
||||
BaseDoc.TextDoc.UNDERLINE : ("\\underline{", "}"),
|
||||
BaseDoc.TextDoc.SUPERSCRIPT : ("\\textsuperscript{", "}"),
|
||||
}
|
||||
|
||||
ESCAPE_FUNC = lambda x: latexescape
|
||||
|
||||
def page_break(self):
|
||||
"Forces a page break, creating a new page"
|
||||
self.f.write('\\newpage ')
|
||||
self._backend.write('\\newpage ')
|
||||
|
||||
def open(self,filename):
|
||||
def open(self, filename):
|
||||
"""Opens the specified file, making sure that it has the
|
||||
extension of .tex"""
|
||||
|
||||
if filename[-4:] != ".tex":
|
||||
self.filename = filename + ".tex"
|
||||
else:
|
||||
self.filename = filename
|
||||
|
||||
try:
|
||||
self.f = open(self.filename,"w")
|
||||
except IOError,msg:
|
||||
errmsg = "%s\n%s" % (_("Could not create %s") % self.filename, msg)
|
||||
raise Errors.ReportError(errmsg)
|
||||
except:
|
||||
raise Errors.ReportError(_("Could not create %s") % self.filename)
|
||||
self._backend = LateXBackend(filename)
|
||||
self._backend.open()
|
||||
|
||||
# Font size control seems to be limited. For now, ignore
|
||||
# any style constraints, and use 12pt has the default
|
||||
@ -229,45 +167,45 @@ class LaTeXDoc(BaseDoc.BaseDoc,BaseDoc.TextDoc):
|
||||
|
||||
# Use the article template, T1 font encodings, and specify
|
||||
# that we should use Latin1 and unicode character encodings.
|
||||
self.f.write('\\documentclass[%s]{article}\n' % options)
|
||||
self.f.write('\\usepackage[T1]{fontenc}\n')
|
||||
self.f.write('%\n% We use latin1 encoding at a minimum by default.\n')
|
||||
self.f.write('% GRAMPS uses unicode UTF-8 encoding for its\n')
|
||||
self.f.write('% international support. LaTeX can deal gracefully\n')
|
||||
self.f.write('% with unicode encoding by using the ucs style invoked\n')
|
||||
self.f.write('% when utf8 is specified as an option to the inputenc\n')
|
||||
self.f.write('% package. This package is included by default in some\n')
|
||||
self.f.write('% installations, but not in others, so we do not make it\n')
|
||||
self.f.write('% the default. Uncomment the second line if you wish to use it\n')
|
||||
self.f.write('% (If you do not have ucs.sty, you may obtain it from\n')
|
||||
self.f.write('% http://www.tug.org/tex-archive/macros/latex/contrib/supported/unicode/)\n')
|
||||
self.f.write('%\n')
|
||||
self.f.write('\\usepackage[latin1]{inputenc}\n')
|
||||
self.f.write('%\\usepackage[latin1,utf8]{inputenc}\n')
|
||||
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')
|
||||
# add packages (should be standard on a default installation)
|
||||
# for finer output control. Put comments in file for user to read
|
||||
self.f.write('\\usepackage{graphicx} % Extended graphics support\n')
|
||||
self.f.write('\\usepackage{longtable} % For multi-page tables\n')
|
||||
self.f.write('\\usepackage{calc} % For margin indents\n')
|
||||
self.f.write('%\n% Depending on your LaTeX installation, the')
|
||||
self.f.write(' margins may be too\n% narrow. ')
|
||||
self.f.write(' This can be corrected by uncommenting the following\n')
|
||||
self.f.write('% two lines and adjusting the width appropriately.')
|
||||
self.f.write(' The example\n% removes 0.5in from each margin.')
|
||||
self.f.write(' (Adds 1 inch to the text)\n')
|
||||
self.f.write('%\\addtolength{\\oddsidemargin}{-0.5in}\n')
|
||||
self.f.write('%\\addtolength{\\textwidth}{1.0in}\n%\n')
|
||||
self.f.write('% Create a margin-adjusting command that allows LaTeX\n')
|
||||
self.f.write('% to behave like the other gramps-supported output formats\n')
|
||||
self.f.write('\\newlength{\\leftedge}\n')
|
||||
self.f.write('\\setlength{\\leftedge}{\\parindent}\n')
|
||||
self.f.write('\\newlength{\\grampstext}\n')
|
||||
self.f.write('\\setlength{\\grampstext}{\\textwidth}\n')
|
||||
self.f.write('\\newcommand{\\grampsindent}[1]{%\n')
|
||||
self.f.write(' \\setlength{\\parindent}{\\leftedge + #1}%\n')
|
||||
self.f.write(' \\setlength{\\textwidth}{\\grampstext - #1}%\n')
|
||||
self.f.write('}\n\n')
|
||||
self.f.write('\\begin{document}\n\n')
|
||||
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')
|
||||
|
||||
self.in_list = 0
|
||||
self.in_table = 0
|
||||
@ -351,15 +289,15 @@ class LaTeXDoc(BaseDoc.BaseDoc,BaseDoc.TextDoc):
|
||||
def close(self):
|
||||
"""Clean up and close the document"""
|
||||
if self.in_list:
|
||||
self.f.write('\\end{enumerate}\n')
|
||||
self.f.write('\n\\end{document}\n')
|
||||
self.f.close()
|
||||
self._backend.write('\\end{enumerate}\n')
|
||||
self._backend.write('\n\\end{document}\n')
|
||||
self._backend.close()
|
||||
if self.open_req:
|
||||
Utils.open_file_with_default_application(self.filename)
|
||||
Utils.open_file_with_default_application(self._backend.filename)
|
||||
|
||||
def end_page(self):
|
||||
"""Issue a new page command"""
|
||||
self.f.write('\\newpage')
|
||||
self._backend.write('\\newpage')
|
||||
|
||||
def start_paragraph(self,style_name,leader=None):
|
||||
"""Paragraphs handling - A Gramps paragraph is any
|
||||
@ -378,11 +316,11 @@ class LaTeXDoc(BaseDoc.BaseDoc,BaseDoc.TextDoc):
|
||||
|
||||
if self.indent is not None and not self.in_table:
|
||||
myspace = '%scm' % str(self.indent)
|
||||
self.f.write('\\grampsindent{%s}\n' % myspace)
|
||||
self._backend.write('\\grampsindent{%s}\n' % myspace)
|
||||
self.fix_indent = 1
|
||||
|
||||
if leader is not None and not self.in_list:
|
||||
self.f.write('\\begin{enumerate}\n')
|
||||
self._backend.write('\\begin{enumerate}\n')
|
||||
self.in_list = 1
|
||||
if leader is not None:
|
||||
# try obtaining integer
|
||||
@ -394,22 +332,22 @@ class LaTeXDoc(BaseDoc.BaseDoc,BaseDoc.TextDoc):
|
||||
num = int(leader_1)
|
||||
except ValueError:
|
||||
num = 1
|
||||
self.f.write(' \\renewcommand\\theenumi{\\arabic{enumi}}')
|
||||
self._backend.write(' \\renewcommand\\theenumi{\\arabic{enumi}}')
|
||||
else:
|
||||
# roman, set the case correctly
|
||||
if leader_1.islower():
|
||||
self.f.write(' \\renewcommand\\theenumi{\\roman{enumi}}')
|
||||
self._backend.write(' \\renewcommand\\theenumi{\\roman{enumi}}')
|
||||
else:
|
||||
self.f.write(' \\renewcommand\\theenumi{\\Roman{enumi}}')
|
||||
self._backend.write(' \\renewcommand\\theenumi{\\Roman{enumi}}')
|
||||
|
||||
self.f.write(' \\setcounter{enumi}{%d} ' % num)
|
||||
self.f.write(' \\addtocounter{enumi}{-1}\n')
|
||||
self.f.write(' \\item ')
|
||||
self._backend.write(' \\setcounter{enumi}{%d} ' % num)
|
||||
self._backend.write(' \\addtocounter{enumi}{-1}\n')
|
||||
self._backend.write(' \\item ')
|
||||
|
||||
if leader is None and not self.in_list and not self.in_table:
|
||||
self.f.write('\n')
|
||||
self._backend.write('\n')
|
||||
|
||||
self.f.write('%s ' % self.fbeg)
|
||||
self._backend.write('%s ' % self.fbeg)
|
||||
|
||||
def end_paragraph(self):
|
||||
"""End the current paragraph"""
|
||||
@ -417,30 +355,30 @@ class LaTeXDoc(BaseDoc.BaseDoc,BaseDoc.TextDoc):
|
||||
|
||||
if self.in_list:
|
||||
self.in_list = 0
|
||||
self.f.write('\n\\end{enumerate}\n')
|
||||
self._backend.write('\n\\end{enumerate}\n')
|
||||
newline = ''
|
||||
|
||||
elif self.in_table:
|
||||
newline = ('')
|
||||
|
||||
self.f.write('%s%s' % (self.fend, newline))
|
||||
self._backend.write('%s%s' % (self.fend, newline))
|
||||
if self.fix_indent == 1:
|
||||
self.fix_indent = 0
|
||||
self.f.write('\\grampsindent{0cm}\n')
|
||||
self._backend.write('\\grampsindent{0cm}\n')
|
||||
|
||||
def start_bold(self):
|
||||
"""Bold face"""
|
||||
self.f.write('\\textbf{')
|
||||
self._backend.write('\\textbf{')
|
||||
|
||||
def end_bold(self):
|
||||
"""End bold face"""
|
||||
self.f.write('}')
|
||||
self._backend.write('}')
|
||||
|
||||
def start_superscript(self):
|
||||
self.f.write('\\textsuperscript{')
|
||||
self._backend.write('\\textsuperscript{')
|
||||
|
||||
def end_superscript(self):
|
||||
self.f.write('}')
|
||||
self._backend.write('}')
|
||||
|
||||
def start_table(self, name,style_name):
|
||||
"""Begin new table"""
|
||||
@ -453,13 +391,13 @@ class LaTeXDoc(BaseDoc.BaseDoc,BaseDoc.TextDoc):
|
||||
self.numcols = self.tblstyle.get_columns()
|
||||
|
||||
tblfmt = '*{%d}{l}' % self.numcols
|
||||
self.f.write('\n\n\\begin{longtable}[l]{%s}\n' % tblfmt)
|
||||
self._backend.write('\n\n\\begin{longtable}[l]{%s}\n' % tblfmt)
|
||||
|
||||
def end_table(self):
|
||||
"""Close the table environment"""
|
||||
self.in_table = 0
|
||||
# Create a paragraph separation below the table.
|
||||
self.f.write('\\end{longtable}\n\\par\n')
|
||||
self._backend.write('\\end{longtable}\n\\par\n')
|
||||
|
||||
def start_row(self):
|
||||
"""Begin a new row"""
|
||||
@ -471,14 +409,14 @@ class LaTeXDoc(BaseDoc.BaseDoc,BaseDoc.TextDoc):
|
||||
|
||||
def end_row(self):
|
||||
"""End the row (new line)"""
|
||||
self.f.write('\\\\ ')
|
||||
self._backend.write('\\\\ ')
|
||||
if self.doline == 1:
|
||||
if self.skipfirst == 1:
|
||||
self.f.write('\\cline{2-%d}\n' % self.numcols)
|
||||
self._backend.write('\\cline{2-%d}\n' % self.numcols)
|
||||
else:
|
||||
self.f.write('\\hline \\\\ \n')
|
||||
self._backend.write('\\hline \\\\ \n')
|
||||
else:
|
||||
self.f.write('\n')
|
||||
self._backend.write('\n')
|
||||
|
||||
def start_cell(self,style_name,span=1):
|
||||
"""Add an entry to the table.
|
||||
@ -513,14 +451,14 @@ class LaTeXDoc(BaseDoc.BaseDoc,BaseDoc.TextDoc):
|
||||
self.skipfirst = 1
|
||||
|
||||
if self.tborder != 0:
|
||||
self.f.write('\\hline\n')
|
||||
self.f.write ('\\multicolumn{%d}{%s}{' % (span,cellfmt))
|
||||
self._backend.write('\\hline\n')
|
||||
self._backend.write ('\\multicolumn{%d}{%s}{' % (span,cellfmt))
|
||||
|
||||
def end_cell(self):
|
||||
"""Prepares for next cell"""
|
||||
self.f.write('} ')
|
||||
self._backend.write('} ')
|
||||
if self.curcol < self.numcols:
|
||||
self.f.write('& ')
|
||||
self._backend.write('& ')
|
||||
|
||||
def add_media_object(self, name,pos,x,y):
|
||||
"""Add photo to report"""
|
||||
@ -538,11 +476,11 @@ class LaTeXDoc(BaseDoc.BaseDoc,BaseDoc.TextDoc):
|
||||
# x and y will be maximum width OR height in units of cm
|
||||
mysize = 'width=%dcm, height=%dcm,keepaspectratio' % (x,y)
|
||||
if pos == "right":
|
||||
self.f.write('\\hfill\\includegraphics[%s]{%s}\n' % (mysize,picf))
|
||||
self._backend.write('\\hfill\\includegraphics[%s]{%s}\n' % (mysize,picf))
|
||||
elif pos == "left":
|
||||
self.f.write('\\includegraphics[%s]{%s}\\hfill\n' % (mysize,picf))
|
||||
self._backend.write('\\includegraphics[%s]{%s}\\hfill\n' % (mysize,picf))
|
||||
else:
|
||||
self.f.write('\\centerline{\\includegraphics[%s]{%s}}\n' % (mysize,picf))
|
||||
self._backend.write('\\centerline{\\includegraphics[%s]{%s}}\n' % (mysize,picf))
|
||||
|
||||
def write_text(self,text,mark=None):
|
||||
"""Write the text to the file"""
|
||||
@ -552,7 +490,7 @@ class LaTeXDoc(BaseDoc.BaseDoc,BaseDoc.TextDoc):
|
||||
#hard coded replace of the underline used for missing names/data
|
||||
text = text.replace('\\_\\_\\_\\_\\_\\_\\_\\_\\_\\_\\_\\_\\_',
|
||||
'\\underline{\hspace{3cm}}')
|
||||
self.f.write(text)
|
||||
self._backend.write(text)
|
||||
|
||||
def write_styled_note(self, styledtext, format, style_name):
|
||||
"""
|
||||
@ -569,72 +507,34 @@ class LaTeXDoc(BaseDoc.BaseDoc,BaseDoc.TextDoc):
|
||||
s_tags = styledtext.get_tags()
|
||||
if format == 1:
|
||||
#preformatted, use different escape function
|
||||
BaseDoc.TextDoc.ESCAPE_FUNC = lambda x: latexescapeverbatim
|
||||
self._backend.setescape(True)
|
||||
|
||||
markuptext = self._add_markup_from_styled(text, s_tags)
|
||||
markuptext = self._backend.add_markup_from_styled(text, s_tags)
|
||||
|
||||
#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
|
||||
self.f.write("\\begin{minipage}{{0.8\\linewidth}}\n")
|
||||
self._backend.write("\\begin{minipage}{{0.8\\linewidth}}\n")
|
||||
self.start_paragraph(style_name)
|
||||
self.f.write(markuptext)
|
||||
self._backend.write(markuptext)
|
||||
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.
|
||||
self.f.write("\n\\vspace*{0.5cm} \n\end{minipage}\n")
|
||||
self._backend.write("\n\\vspace*{0.5cm} \n\end{minipage}\n\n")
|
||||
if format == 1:
|
||||
#preformatted finished, go back to normal escape function
|
||||
BaseDoc.TextDoc.ESCAPE_FUNC = lambda x: latexescape
|
||||
|
||||
def _create_xmltag(self, type, value):
|
||||
"""
|
||||
overwrites the method in BaseDoc.TextDoc.
|
||||
creates the latex tags needed for non bool style types we support:
|
||||
BaseDoc.TextDoc.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 == BaseDoc.TextDoc.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 == BaseDoc.TextDoc.FONTFACE:
|
||||
if 'MONO' in value.upper():
|
||||
return ("{\\ttfamily ", "}")
|
||||
elif 'ROMAN' in value.upper():
|
||||
return ("{\\rmfamily ", "}")
|
||||
return None
|
||||
self._backend.setescape(False)
|
||||
|
||||
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:
|
||||
self.f.write('\\begin{verbatim}')
|
||||
self._backend.write('\\begin{verbatim}')
|
||||
self.write_text(text)
|
||||
if format == 1:
|
||||
self.f.write('\\end{verbatim}')
|
||||
self._backend.write('\\end{verbatim}')
|
||||
self.end_paragraph()
|
||||
|
||||
#------------------------------------------------------------------------
|
||||
|
@ -86,7 +86,7 @@ class PdfDoc(libcairodoc.CairoDoc):
|
||||
top_margin = self.paper.get_top_margin() * DPI / 2.54
|
||||
|
||||
# create cairo context and pango layout
|
||||
surface = cairo.PDFSurface(self._filename, paper_width, paper_height)
|
||||
surface = cairo.PDFSurface(self._backend.filename, paper_width, paper_height)
|
||||
surface.set_fallback_resolution(300, 300)
|
||||
cr = pangocairo.CairoContext(cairo.Context(surface))
|
||||
|
||||
@ -125,7 +125,7 @@ class PdfDoc(libcairodoc.CairoDoc):
|
||||
|
||||
# load the result into an external viewer
|
||||
if self.open_req:
|
||||
Utils.open_file_with_default_application(self._filename)
|
||||
Utils.open_file_with_default_application(self._backend.filename)
|
||||
|
||||
#------------------------------------------------------------------------
|
||||
#
|
||||
|
@ -32,7 +32,6 @@
|
||||
#------------------------------------------------------------------------
|
||||
from gettext import gettext as _
|
||||
from math import radians
|
||||
from xml.sax.saxutils import escape
|
||||
|
||||
#------------------------------------------------------------------------
|
||||
#
|
||||
@ -43,6 +42,7 @@ import BaseDoc
|
||||
from ReportBase import ReportUtils
|
||||
from Errors import PluginError
|
||||
from gen.plug import PluginManager, Plugin
|
||||
from docbackend import CairoBackend
|
||||
|
||||
#------------------------------------------------------------------------
|
||||
#
|
||||
@ -1200,37 +1200,11 @@ class CairoDoc(BaseDoc.BaseDoc, BaseDoc.TextDoc, BaseDoc.DrawDoc):
|
||||
page style.
|
||||
|
||||
"""
|
||||
STYLETAG_TO_PROPERTY = {
|
||||
BaseDoc.TextDoc.FONTCOLOR : 'foreground',
|
||||
BaseDoc.TextDoc.HIGHLIGHT : 'background',
|
||||
BaseDoc.TextDoc.FONTFACE : 'face',
|
||||
BaseDoc.TextDoc.FONTSIZE : 'size',
|
||||
}
|
||||
|
||||
# overwrite base class attributes, they become static var of CairoDoc
|
||||
SUPPORTED_MARKUP = [
|
||||
BaseDoc.TextDoc.BOLD,
|
||||
BaseDoc.TextDoc.ITALIC,
|
||||
BaseDoc.TextDoc.UNDERLINE,
|
||||
BaseDoc.TextDoc.FONTFACE,
|
||||
BaseDoc.TextDoc.FONTSIZE,
|
||||
BaseDoc.TextDoc.FONTCOLOR,
|
||||
BaseDoc.TextDoc.HIGHLIGHT,
|
||||
BaseDoc.TextDoc.SUPERSCRIPT ]
|
||||
|
||||
STYLETAG_MARKUP = {
|
||||
BaseDoc.TextDoc.BOLD : ("<b>", "</b>"),
|
||||
BaseDoc.TextDoc.ITALIC : ("<i>", "</i>"),
|
||||
BaseDoc.TextDoc.UNDERLINE : ("<u>", "</u>"),
|
||||
BaseDoc.TextDoc.SUPERSCRIPT : ("<sup>", "</sup>"),
|
||||
}
|
||||
|
||||
ESCAPE_FUNC = lambda x: escape
|
||||
|
||||
# BaseDoc implementation
|
||||
|
||||
def open(self, filename):
|
||||
self._filename = filename
|
||||
self._backend = CairoBackend(filename)
|
||||
self._doc = GtkDocDocument()
|
||||
self._active_element = self._doc
|
||||
self._pages = []
|
||||
@ -1303,21 +1277,6 @@ class CairoDoc(BaseDoc.BaseDoc, BaseDoc.TextDoc, BaseDoc.DrawDoc):
|
||||
def end_cell(self):
|
||||
self._active_element = self._active_element.get_parent()
|
||||
|
||||
def _create_xmltag(self, type, value):
|
||||
"""
|
||||
overwrites the method in BaseDoc.TextDoc.
|
||||
creates the pango xml tags needed for non bool style types
|
||||
"""
|
||||
if type not in self.SUPPORTED_MARKUP:
|
||||
return None
|
||||
if type == BaseDoc.TextDoc.FONTSIZE:
|
||||
#size is in thousandths of a point in pango
|
||||
value = str(1000 * value)
|
||||
|
||||
return ('<span %s="%s">' % (self.STYLETAG_TO_PROPERTY[type],
|
||||
self.ESCAPE_FUNC()(value)),
|
||||
'</span>')
|
||||
|
||||
def write_note(self, text, format, style_name):
|
||||
"""
|
||||
Method to write the note objects text on a
|
||||
@ -1358,7 +1317,8 @@ class CairoDoc(BaseDoc.BaseDoc, BaseDoc.TextDoc, BaseDoc.DrawDoc):
|
||||
|
||||
s_tags = styledtext.get_tags()
|
||||
#FIXME: following split should be regex to match \n\s*\n instead?
|
||||
markuptext = self._add_markup_from_styled(text, s_tags, split='\n\n')
|
||||
markuptext = self._backend.add_markup_from_styled(text, s_tags,
|
||||
split='\n\n')
|
||||
|
||||
if format == 1:
|
||||
#preformatted, retain whitespace. Cairo retains \n automatically,
|
||||
@ -1391,7 +1351,7 @@ class CairoDoc(BaseDoc.BaseDoc, BaseDoc.TextDoc, BaseDoc.DrawDoc):
|
||||
# calls. This way we save the markup created by the report
|
||||
# The markup in the note editor is not in the text so is not
|
||||
# considered. It must be added by pango too
|
||||
text = escape(text)
|
||||
text = self._backend.ESCAPE_FUNC()(text)
|
||||
self._active_element.add_text(text)
|
||||
|
||||
def write_text(self, text, mark=None):
|
||||
@ -1411,7 +1371,7 @@ class CairoDoc(BaseDoc.BaseDoc, BaseDoc.TextDoc, BaseDoc.DrawDoc):
|
||||
@param s_tags: assumed to be list of styledtexttags to apply to the
|
||||
text
|
||||
"""
|
||||
markuptext = self._add_markup_from_styled(text, s_tags)
|
||||
markuptext = self._backend.add_markup_from_styled(text, s_tags)
|
||||
self.__write_text(text, markup=True)
|
||||
|
||||
def add_media_object(self, name, pos, x_cm, y_cm):
|
||||
|
Loading…
Reference in New Issue
Block a user