2707: Add markup notes to html output

Part 2: enable css, clean up code.
      TODO: better output, support in default css files, test


svn: r12644
This commit is contained in:
Benny Malengier 2009-06-08 23:19:37 +00:00
parent 10c8599867
commit a177da80b0
20 changed files with 382 additions and 259 deletions

View File

@ -169,7 +169,6 @@ src/gen/plug/docbackend/Makefile
src/gen/plug/docgen/Makefile src/gen/plug/docgen/Makefile
src/gen/plug/menu/Makefile src/gen/plug/menu/Makefile
src/data/Makefile src/data/Makefile
src/data/templates/Makefile
src/glade/Makefile src/glade/Makefile
src/images/Makefile src/images/Makefile
src/images/scalable/Makefile src/images/scalable/Makefile

View File

@ -1,10 +0,0 @@
# This is the src/data/templates level Makefile
pkgdata_DATA = marble.tpkg \
pink_marble.tpkg \
sepia.tpkg \
sky_border.tpkg \
blue_edge.tpkg \
templates.xml
pkgdatadir = $(datadir)/@PACKAGE@/data/templates
EXTRA_DIST = $(pkgdata_DATA)

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

View File

@ -1,7 +0,0 @@
<templates>
<template title="Blue Edge" file="blue_edge.tpkg"/>
<template title="Pink Marble" file="pink_marble.tpkg"/>
<template title="Sky Border" file="sky_border.tpkg"/>
<template title="Marble" file="marble.tpkg"/>
<template title="Sepia" file="sepia.tpkg"/>
</templates>

View File

@ -315,7 +315,7 @@ class TextBufDoc(BaseDoc, TextDoc):
if self.cell_lines[self.cellnum] > self.maxlines: if self.cell_lines[self.cellnum] > self.maxlines:
self.maxlines = self.cell_lines[self.cellnum] self.maxlines = self.cell_lines[self.cellnum]
def add_media_object(self, name, align, w_cm, h_cm): def add_media_object(self, name, align, w_cm, h_cm, alt=''):
return return
this_text = '(photo)' this_text = '(photo)'

View File

@ -49,7 +49,7 @@ from docbackend import DocBackend
# #
#------------------------------------------------------------------------ #------------------------------------------------------------------------
import logging import logging
log = logging.getLogger(".cairobackend.py") LOG = logging.getLogger(".cairobackend.py")
#------------------------------------------------------------------------ #------------------------------------------------------------------------
# #
@ -89,17 +89,17 @@ class CairoBackend(DocBackend):
ESCAPE_FUNC = lambda x: escape ESCAPE_FUNC = lambda x: escape
def _create_xmltag(self, type, value): def _create_xmltag(self, tagtype, value):
""" """
overwrites the method in DocBackend overwrites the method in DocBackend
creates the pango xml tags needed for non bool style types creates the pango xml tags needed for non bool style types
""" """
if type not in self.SUPPORTED_MARKUP: if tagtype not in self.SUPPORTED_MARKUP:
return None return None
if type == DocBackend.FONTSIZE: if tagtype == DocBackend.FONTSIZE:
#size is in thousandths of a point in pango #size is in thousandths of a point in pango
value = str(1000 * value) value = str(1000 * value)
return ('<span %s="%s">' % (self.STYLETAG_TO_PROPERTY[type], return ('<span %s="%s">' % (self.STYLETAG_TO_PROPERTY[tagtype],
self.ESCAPE_FUNC()(value)), self.ESCAPE_FUNC()(value)),
'</span>') '</span>')

View File

@ -48,7 +48,7 @@ from gettext import gettext as _
# #
#------------------------------------------------------------------------ #------------------------------------------------------------------------
import logging import logging
log = logging.getLogger(".docbackend.py") LOG = logging.getLogger(".docbackend.py")
#------------------------------------------------------------------------ #------------------------------------------------------------------------
# #
@ -57,6 +57,9 @@ log = logging.getLogger(".docbackend.py")
#------------------------------------------------------------------------ #------------------------------------------------------------------------
def noescape(text): def noescape(text):
"""
Function that does not escape the text passed. Default for backends
"""
return text return text
#------------------------------------------------------------------------- #-------------------------------------------------------------------------
@ -122,9 +125,17 @@ class DocBackend(object):
self._filename = filename self._filename = filename
def getf(self): def getf(self):
"""
Obtain the filename on which backend writes
"""
return self._filename return self._filename
def setf(self, value): def setf(self, value):
"""
Set the filename on which the backend writes, changing the value
passed on initialization
Can only be done if the previous filename is not open
"""
if self.__file is not None: if self.__file is not None:
raise ValueError, _('Close file first') raise ValueError, _('Close file first')
self._filename = value self._filename = value
@ -156,17 +167,20 @@ class DocBackend(object):
pass pass
def close(self): def close(self):
"""
Closes the file that is written on.
"""
if self.__file is None: if self.__file is None:
raise IOError, 'No file open' raise IOError, 'No file open'
self.__file.close() self.__file.close()
self.__file = None self.__file = None
def write(self, str): def write(self, string):
"""Write a string to the file. There is no return value. """Write a string to the file. There is no return value.
Due to buffering, the string may not actually show up untill the Due to buffering, the string may not actually show up untill the
close() method is called. close() method is called.
""" """
self.__file.write(str) self.__file.write(string)
def writelines(self, sequence): def writelines(self, sequence):
"""Write a sequence of strings to the file. The sequence can be any """Write a sequence of strings to the file. The sequence can be any
@ -197,28 +211,28 @@ class DocBackend(object):
If a markup is not present yet, it is created, using the If a markup is not present yet, it is created, using the
_create_xmltag method you can overwrite _create_xmltag method you can overwrite
""" """
type = s_tag.name tagtype = s_tag.name
if not self.STYLETYPE_MAP or \ if not self.STYLETYPE_MAP or \
self.CLASSMAP <> type.__class__.__name__ : self.CLASSMAP != tagtype.__class__.__name__ :
self.CLASSMAP == type.__class__.__name__ self.CLASSMAP == tagtype.__class__.__name__
self.STYLETYPE_MAP[type.__class__.BOLD] = self.BOLD self.STYLETYPE_MAP[tagtype.__class__.BOLD] = self.BOLD
self.STYLETYPE_MAP[type.ITALIC] = self.ITALIC self.STYLETYPE_MAP[tagtype.ITALIC] = self.ITALIC
self.STYLETYPE_MAP[type.UNDERLINE] = self.UNDERLINE self.STYLETYPE_MAP[tagtype.UNDERLINE] = self.UNDERLINE
self.STYLETYPE_MAP[type.FONTFACE] = self.FONTFACE self.STYLETYPE_MAP[tagtype.FONTFACE] = self.FONTFACE
self.STYLETYPE_MAP[type.FONTSIZE] = self.FONTSIZE self.STYLETYPE_MAP[tagtype.FONTSIZE] = self.FONTSIZE
self.STYLETYPE_MAP[type.FONTCOLOR] = self.FONTCOLOR self.STYLETYPE_MAP[tagtype.FONTCOLOR] = self.FONTCOLOR
self.STYLETYPE_MAP[type.HIGHLIGHT] = self.HIGHLIGHT self.STYLETYPE_MAP[tagtype.HIGHLIGHT] = self.HIGHLIGHT
self.STYLETYPE_MAP[type.SUPERSCRIPT] = self.SUPERSCRIPT self.STYLETYPE_MAP[tagtype.SUPERSCRIPT] = self.SUPERSCRIPT
typeval = int(s_tag.name) typeval = int(s_tag.name)
s_tagvalue = s_tag.value s_tagvalue = s_tag.value
tag_name = None tag_name = None
if type.STYLE_TYPE[typeval] == bool: if tagtype.STYLE_TYPE[typeval] == bool:
return self.STYLETAG_MARKUP[self.STYLETYPE_MAP[typeval]] return self.STYLETAG_MARKUP[self.STYLETYPE_MAP[typeval]]
elif type.STYLE_TYPE[typeval] == str: elif tagtype.STYLE_TYPE[typeval] == str:
tag_name = "%d %s" % (typeval, s_tagvalue) tag_name = "%d %s" % (typeval, s_tagvalue)
elif type.STYLE_TYPE[typeval] == int: elif tagtype.STYLE_TYPE[typeval] == int:
tag_name = "%d %d" % (typeval, s_tagvalue) tag_name = "%d %d" % (typeval, s_tagvalue)
if not tag_name: if not tag_name:
return None return None
@ -231,12 +245,12 @@ class DocBackend(object):
self.STYLETAG_MARKUP[tag_name] = tags self.STYLETAG_MARKUP[tag_name] = tags
return tags return tags
def _create_xmltag(self, type, value): def _create_xmltag(self, tagtype, value):
""" """
Create the xmltags for the backend. Create the xmltags for the backend.
Overwrite this method to create functionality with a backend Overwrite this method to create functionality with a backend
""" """
if type not in self.SUPPORTED_MARKUP: if tagtype not in self.SUPPORTED_MARKUP:
return None return None
return ('', '') return ('', '')
@ -283,7 +297,7 @@ class DocBackend(object):
end = len(text) end = len(text)
keylist = tagspos.keys() keylist = tagspos.keys()
keylist.sort() keylist.sort()
keylist = [x for x in keylist if x<=len(text)] keylist = [x for x in keylist if x <= len(text)]
opentags = [] opentags = []
otext = u"" #the output, text with markup otext = u"" #the output, text with markup
lensplit = len(split) lensplit = len(split)
@ -293,7 +307,7 @@ class DocBackend(object):
if split: if split:
#make sure text can split #make sure text can split
splitpos = text[start:pos].find(split) splitpos = text[start:pos].find(split)
while splitpos <> -1: while splitpos != -1:
otext += self.ESCAPE_FUNC()(text[start:start+splitpos]) otext += self.ESCAPE_FUNC()(text[start:start+splitpos])
#close open tags #close open tags
for opentag in reversed(opentags): for opentag in reversed(opentags):

View File

@ -225,7 +225,7 @@ class TextDoc(object):
else: else:
self.write_text(piece) self.write_text(piece)
def add_media_object(self, name, align, w_cm, h_cm): def add_media_object(self, name, align, w_cm, h_cm, alt=''):
""" """
Add a photo of the specified width (in centimeters) Add a photo of the specified width (in centimeters)
@ -234,5 +234,6 @@ class TextDoc(object):
'right', 'center', and 'single' 'right', 'center', and 'single'
@param w_cm: width in centimeters @param w_cm: width in centimeters
@param h_cm: height in centimeters @param h_cm: height in centimeters
@param alt: an alternative text to use. Usefull for eg html reports
""" """
raise NotImplementedError raise NotImplementedError

View File

@ -336,7 +336,7 @@ class AsciiDoc(BaseDoc,TextDoc):
if self.cell_lines[self.cellnum] > self.maxlines: if self.cell_lines[self.cellnum] > self.maxlines:
self.maxlines = self.cell_lines[self.cellnum] self.maxlines = self.cell_lines[self.cellnum]
def add_media_object(self, name, align, w_cm, h_cm): def add_media_object(self, name, align, w_cm, h_cm, alt=''):
this_text = '(photo)' this_text = '(photo)'
if self.in_cell: if self.in_cell:
self.cellpars[self.cellnum] = self.cellpars[self.cellnum] + this_text self.cellpars[self.cellnum] = self.cellpars[self.cellnum] + this_text

View File

@ -22,13 +22,18 @@
# $Id:HtmlDoc.py 9912 2008-01-22 09:17:46Z acraphae $ # $Id:HtmlDoc.py 9912 2008-01-22 09:17:46Z acraphae $
"""
Report output generator for html documents, based on Html and HtmlBackend
"""
#------------------------------------------------------------------------ #------------------------------------------------------------------------
# #
# python modules # python modules
# #
#------------------------------------------------------------------------ #------------------------------------------------------------------------
import os import os
import re import shutil
import time import time
from gettext import gettext as _ from gettext import gettext as _
@ -39,77 +44,42 @@ from gettext import gettext as _
#------------------------------------------------------------------------ #------------------------------------------------------------------------
from gen.plug import PluginManager, DocGenPlugin from gen.plug import PluginManager, DocGenPlugin
import ImgManip import ImgManip
import tarfile
import const import const
import Errors
from gen.plug.docgen import BaseDoc, TextDoc, FONT_SANS_SERIF from gen.plug.docgen import BaseDoc, TextDoc, FONT_SANS_SERIF
from libhtmlbackend import HtmlBackend from libhtmlbackend import HtmlBackend
from QuestionDialog import ErrorDialog, WarningDialog from libhtml import Html
import Utils from QuestionDialog import WarningDialog
#------------------------------------------------------------------------ #------------------------------------------------------------------------
# #
# Constant regular expressions # Set up logging
# #
#------------------------------------------------------------------------ #------------------------------------------------------------------------
t_header_line_re = re.compile( import logging
r"(.*)<TITLE>(.*)</TITLE>(.*)", LOG = logging.getLogger(".htmldoc")
re.DOTALL|re.IGNORECASE|re.MULTILINE)
t_keyword_line_re = re.compile(
r'(.*name="keywords"\s+content=")([^\"]*)(".*)$',
re.DOTALL|re.IGNORECASE|re.MULTILINE)
#------------------------------------------------------------------------
#
# Default template
#
#------------------------------------------------------------------------
_top = [
'<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN" "http://www.w3.org/TR/REC-html40/loose.dtd">\n',
'<HTML>\n',
'<HEAD>\n',
' <META HTTP-EQUIV="Content-Type" CONTENT="text/html; charset=utf-8">\n',
' <META NAME="keywords" CONTENT="">\n',
' <TITLE>\n',
' </TITLE>\n',
' <STYLE type="text/css">\n',
' <!--\n',
' BODY { background-color: #ffffff }\n',
' .parent_name { font-family: Arial; font-style: bold }\n',
' .child_name { font-family: Arial; font-style: bold }\n',
' -->\n',
' </STYLE>\n',
'</HEAD>\n',
'<BODY>\n',
' <!-- START -->\n'
]
_bottom = [
' <!-- STOP -->\n',
'</BODY>\n',
'</HTML>\n'
]
_HTMLSCREEN = 'grampshtml.css'
#------------------------------------------------------------------------ #------------------------------------------------------------------------
# #
# HtmlDoc # HtmlDoc
# #
#------------------------------------------------------------------------ #------------------------------------------------------------------------
class HtmlDoc(BaseDoc, TextDoc): class HtmlDoc(BaseDoc, TextDoc):
"""Implementation of the BaseDoc and TextDoc gen.plug.docgen api for the
creation of Html files. This is achieved by writing on a HtmlBackend
object
"""
def __init__(self,styles,type): def __init__(self, styles, paper_style):
BaseDoc.__init__(self, styles, None) BaseDoc.__init__(self, styles, None)
self.year = time.localtime(time.time())[0] self.style_declaration = ''
self.ext = '.html' self.htmllist = []
self.meta = "" self._backend = None
self.copyright = 'Copyright &copy; %d' % (self.year) self.css_filename = None
self.map = None self.warn_dir = True
self.f = None self._col = 0
self.filename = None self._tbl = None
self.base = "" self._empty = 1
self.build_header()
self.style_declaration = None
self.image_dir = "images"
def set_css_filename(self, css_filename): def set_css_filename(self, css_filename):
""" """
@ -118,47 +88,47 @@ class HtmlDoc(BaseDoc, TextDoc):
""" """
self.css_filename = css_filename self.css_filename = css_filename
def set_extension(self,val): def open(self, filename):
if val[0] != '.': """
val = "." + val Overwrite base method
self.ext = val """
self._backend = HtmlBackend(filename)
def set_image_dir(self,dirname): #self._backend.set_title(....)
self.image_dir = dirname self._backend.open()
self.htmllist += [self._backend.html_body]
def set_keywords(self,keywords):
self.meta = ",".join(keywords)
def process_line(self,line):
l = line.replace('$VERSION',const.VERSION)
return l.replace('$COPYRIGHT',self.copyright)
def open(self,filename): self.build_header()
(r,e) = os.path.splitext(filename)
if e == self.ext:
self.filename = filename
else:
self.filename = filename + self.ext
self.base = os.path.dirname(self.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)
if not self.style_declaration:
self.build_style_declaration()
self.f.write(self.style_declaration)
def build_header(self): def build_header(self):
## TODO REMOVE ?? """
pass Build up the header of the html file over the defaults of Html()
"""
# add additional meta tags and stylesheet links to head section
# create additional meta tags
_meta1 = 'name="generator" content="%s %s %s"' % (const.PROGRAM_NAME,
const.VERSION, const.URL_HOMEPAGE)
meta = Html('meta', attr = _meta1)
#set styles of the report as inline css
self.build_style_declaration()
self._backend.html_header += self.style_declaration
# GRAMPS favicon en css
fname1 = '/'.join([self._backend.datadir(), 'favicon.ico'])
fname2 = '/'.join([self._backend.datadir(), _HTMLSCREEN])
# links for GRAMPS favicon and stylesheets
links = Html('link', rel='shortcut icon', href=fname1,
type='image/x-icon') + (
Html('link', rel='stylesheet', href=fname2, type='text/css',
media='screen', indent=False)
)
self._backend.html_header += (meta, links)
def build_style_declaration(self): def build_style_declaration(self):
"""
Convert the styles of the report into inline css for the html doc
"""
styles = self.get_style_sheet() styles = self.get_style_sheet()
text = ['<style type="text/css">\n<!--'] text = ['<style type="text/css">\n<!--']
@ -179,7 +149,7 @@ class HtmlDoc(BaseDoc, TextDoc):
'\tpadding: %s %s %s %s;\n' '\tpadding: %s %s %s %s;\n'
'\tborder-top:%s; border-bottom:%s;\n' '\tborder-top:%s; border-bottom:%s;\n'
'\tborder-left:%s; border-right:%s;\n}' '\tborder-left:%s; border-right:%s;\n}'
% (sname, pad, pad, pad, pad, top, bottom, left, right)) % (sname, pad, pad, pad, pad, top, bottom, left, right))
for style_name in styles.get_paragraph_style_names(): for style_name in styles.get_paragraph_style_names():
@ -233,142 +203,265 @@ class HtmlDoc(BaseDoc, TextDoc):
self.style_declaration = '\n'.join(text) self.style_declaration = '\n'.join(text)
def close(self): def close(self):
self.f.close() """
Overwrite base method
"""
while len(self.htmllist)>1 :
self.__reduce_list()
#now write the actual file
self._backend.close()
self.write_support_files() self.write_support_files()
if self.open_req: if self.open_req:
Utils.open_file_with_default_application(self.filename) import Utils
Utils.open_file_with_default_application(self._backend.getf())
def copy_file(self, from_fname, to_fname, to_dir=''):
"""
Copy a file from a source to a (report) destination.
If to_dir is not present, then the destination directory will be created.
Normally 'to_fname' will be just a filename, without directory path.
'to_dir' is the relative path name in the destination root. It will
be prepended before 'to_fname'.
"""
dest = os.path.join(self._backend.datadir(), to_dir, to_fname)
destdir = os.path.dirname(dest)
if not os.path.isdir(destdir):
os.makedirs(destdir)
if from_fname != dest:
shutil.copyfile(from_fname, dest)
elif self.warn_dir:
WarningDialog(
_("Possible destination error") + "\n" +
_("You appear to have set your target directory "
"to a directory used for data storage. This "
"could create problems with file management. "
"It is recommended that you consider using "
"a different directory to store your generated "
"web pages."))
self.warn_dir = False
def write_support_files(self): def write_support_files(self):
if self.map: """
for name, handle in self.map.iteritems(): Copy support files to the datadir that needs to hold them
if name == 'template.html': """
continue #css file
fname = '%s%s%s' % (self.base, os.path.sep, name) self.copy_file(os.path.join(const.DATA_DIR, self.css_filename),
try: _HTMLSCREEN)
f = open(fname, 'wb') #favicon
f.write(handle.read()) self.copy_file(os.path.join(const.IMAGE_DIR, 'favicon.ico'),
f.close() 'favicon.ico')
except IOError,msg:
errmsg = "%s\n%s" % (_("Could not create %s") % fname, msg)
raise Errors.ReportError(errmsg)
except:
raise Errors.ReportError(_("Could not create %s") % fname)
def add_media_object(self, name,pos,x,y,alt=''):
self.empty = 0
size = int(max(x,y) * float(150.0/2.54))
refname = "is%s" % os.path.basename(name)
if self.image_dir: def __reduce_list(self):
imdir = '%s%s%s' % (self.base, os.path.sep,self.image_dir) """
else: Takes the internal list of html objects, and adds the last to the
imdir = self.base previous. This closes the upper tag
"""
if not os.path.isdir(imdir): self.htmllist[-2] += self.htmllist[-1]
try: self.htmllist.pop()
os.mkdir(imdir)
except: def __write_text(self, text, mark=None, markup=False):
return """
@param text: text to write.
try: @param mark: IndexMark to use for indexing (if supported)
ImgManip.resize_to_jpeg(name, refname, size, size) @param markup: True if text already contains markup info.
except: Then text will no longer be escaped
return """
if not markup:
if pos == "right": text = self._backend.ESCAPE_FUNC()(text)
xtra = ' align="right"' self.htmllist[-1] += text
elif pos == "left" :
xtra = ' align="left"' def __empty_char(self):
else: """
xtra = '' Output a non breaking whitespace so as to have browser behave ok on
empty content
if self.image_dir: """
self.f.write('<img src="%s/%s" border="0" alt="%s"%s>\n' % \ self.__write_text('&nbsp;', markup=True)
(self.image_dir, refname, alt, xtra))
else: def write_text(self, text, mark=None):
self.f.write('<img src="%s" border="0" alt="%s"%s>\n' """
% (refname, alt, xtra)) Overwrite base method
"""
def start_table(self, name,style): if text != "":
self._empty = 0
self.__write_text(text, mark)
def start_table(self, name, style):
"""
Overwrite base method
"""
styles = self.get_style_sheet() styles = self.get_style_sheet()
self.tbl = styles.get_table_style(style) self._tbl = styles.get_table_style(style)
self.f.write('<table width="%d%%" ' % self.tbl.get_width()) self.htmllist += [Html('table', width=str(self._tbl.get_width())+'%%',
self.f.write('cellspacing="0">\n') cellspacing='0')]
def end_table(self): def end_table(self):
self.f.write('</table>\n') """
Overwrite base method
"""
self.__reduce_list()
def start_row(self): def start_row(self):
self.col = 0 """
self.f.write('<tr>\n') Overwrite base method
"""
self.htmllist += [Html('tr')]
self._col = 0
def end_row(self): def end_row(self):
self.f.write('</tr>\n') """
Overwrite base method
"""
self.__reduce_list()
def start_cell(self,style_name,span=1): def start_cell(self, style_name, span=1):
self.empty = 1 """
self.f.write('<td valign="top"') Overwrite base method
"""
self._empty = 1
#self.f.write('<td valign="top"')
if span > 1: if span > 1:
self.f.write(' colspan="' + str(span) + '"') self.htmllist += [Html('td', colspan=str(span),
self.col = self.col + 1 _class=style_name)]
self._col += span
else: else:
self.f.write(' width="') self.htmllist += [Html('td', colspan=str(span),
self.f.write(str(self.tbl.get_column_width(self.col))) width=str(self._tbl.get_column_width(
self.f.write('%"') self._col))+ '%%',
self.f.write(' class="') _class=style_name)]
self.f.write(style_name) self._col += 1
self.f.write('">')
self.col = self.col + 1
def end_cell(self): def end_cell(self):
self.f.write('</td>\n') """
Overwrite base method
"""
self.__reduce_list()
def start_paragraph(self,style_name,leader=None): def start_paragraph(self, style_name, leader=None):
self.f.write('<p class="' + style_name + '">') """
Overwrite base method
"""
self.htmllist += [Html('p', _class=style_name)]
if leader is not None: if leader is not None:
self.f.write(leader) self.write_text(leader+' ')
self.f.write(' ')
def end_paragraph(self): def end_paragraph(self):
if self.empty == 1: """
self.f.write('&nbsp;') Overwrite base method
self.empty = 0 """
self.f.write('</p>\n') if self._empty == 1:
self.__empty_char()
self._empty = 0
self.__reduce_list()
def start_bold(self): def start_bold(self):
self.f.write('<b>') """
Overwrite base method
"""
self.htmllist += [Html('strong')]
def end_bold(self): def end_bold(self):
self.f.write('</b>') """
Overwrite base method
"""
self.__reduce_list()
def start_superscript(self): def start_superscript(self):
self.f.write('<sup>') """
Overwrite base method
"""
self.htmllist += [Html('sup')]
def end_superscript(self): def end_superscript(self):
self.f.write('</sup>') """
Overwrite base method
"""
self.__reduce_list()
def write_note(self,text,format,style_name): def write_note(self, text, format, style_name):
"""
Overwrite base method
"""
if format == 1: if format == 1:
self.f.write('<pre class=%s style="font-family: courier, monospace">' % style_name) #preformatted, retain whitespace.
# User should use write_styled_note for correct behavior, in this
# more basic method we convert all to a monospace character
self.htmllist += [Html('pre', _class=style_name,
style = 'font-family: courier, monospace')]
self.write_text(text) self.write_text(text)
self.f.write('</pre>') self.__reduce_list()
elif format == 0: elif format == 0:
for line in text.split('\n\n'): for line in text.split('\n\n'):
self.start_paragraph(style_name) self.start_paragraph(style_name)
self.write_text(line.strip().replace('\n',' ')) self.write_text(line)
self.end_paragraph()
else:
raise NotImplementedError
def write_styled_note(self, styledtext, format, style_name):
"""
Convenience function to write a styledtext to the html 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()
#FIXME: following split should be regex to match \n\s*\n instead?
markuptext = self._backend.add_markup_from_styled(text, s_tags,
split='\n\n')
if format == 1:
#preformatted, retain whitespace.
#so use \n\n for paragraph detection
#FIXME: following split should be regex to match \n\s*\n instead?
for line in markuptext.split('\n\n'):
self.start_paragraph(style_name)
for realline in line.split('\n'):
self.__write_text(realline, markup=True)
self.htmllist[-1] += Html('br')
self.end_paragraph()
elif format == 0:
#flowed
#FIXME: following split should be regex to match \n\s*\n instead?
for line in markuptext.split('\n\n'):
self.start_paragraph(style_name)
self.__write_text(line, markup=True)
self.end_paragraph() self.end_paragraph()
def write_text(self,text,mark=None): def add_media_object(self, name, pos, w_cm, h_cm, alt=''):
text = text.replace('&','&amp;'); # Must be first """
text = text.replace('<','&lt;'); Overwrite base method
text = text.replace('>','&gt;'); """
text = text.replace('\n','<br>') self._empty = 0
if text != "": size = int(max(w_cm, h_cm) * float(150.0/2.54))
self.empty = 0 refname = "is%s" % os.path.basename(name)
self.f.write(text)
imdir = self._backend.datadir()
try:
ImgManip.resize_to_jpeg(name, imdir + os.sep + refname, size, size)
except:
LOG.warn(_("Could not create jpeg version of image %(name)s") %
{'name' : name})
return
if pos not in ["right", "left"] :
self.htmllist[-1] += Html('img', src= imdir + os.sep + refname,
border = '0', alt=alt)
else:
self.htmllist[-1] += Html('img', src= imdir + os.sep + refname,
border = '0', alt=alt, align=pos)
def page_break(self): def page_break(self):
"""
overwrite base method so page break has no effect
"""
pass pass
#------------------------------------------------------------------------ #------------------------------------------------------------------------

View File

@ -584,7 +584,7 @@ class LaTeXDoc(BaseDoc, TextDoc):
if self.curcol < self.numcols: if self.curcol < self.numcols:
self._backend.write('& ') self._backend.write('& ')
def add_media_object(self, name,pos,x,y): def add_media_object(self, name, pos, x, y, alt=''):
"""Add photo to report""" """Add photo to report"""
return return
@ -622,9 +622,6 @@ class LaTeXDoc(BaseDoc, TextDoc):
styledtext : assumed a StyledText object to write styledtext : assumed a StyledText object to write
format : = 0 : Flowed, = 1 : Preformatted format : = 0 : Flowed, = 1 : Preformatted
style_name : name of the style to use for default presentation style_name : name of the style to use for default presentation
@note: text=normal text, p_text=text with pango markup, s_tags=styled
text tags, p
""" """
text = str(styledtext) text = str(styledtext)

View File

@ -437,7 +437,7 @@ class ODFDoc(BaseDoc, TextDoc, DrawDoc):
if self.open_req: if self.open_req:
Utils.open_file_with_default_application(self.filename) Utils.open_file_with_default_application(self.filename)
def add_media_object(self, file_name, pos, x_cm, y_cm): def add_media_object(self, file_name, pos, x_cm, y_cm, alt=''):
# try to open the image. If the open fails, it probably wasn't # try to open the image. If the open fails, it probably wasn't
# a valid image (could be a PDF, or a non-image) # a valid image (could be a PDF, or a non-image)

View File

@ -360,7 +360,7 @@ class RTFDoc(BaseDoc,TextDoc):
# dumped as a string of HEX numbers. # dumped as a string of HEX numbers.
# #
#-------------------------------------------------------------------- #--------------------------------------------------------------------
def add_media_object(self, name,pos,x_cm,y_cm): def add_media_object(self, name, pos, x_cm, y_cm, alt=''):
nx, ny = ImgManip.image_size(name) nx, ny = ImgManip.image_size(name)

View File

@ -1311,9 +1311,6 @@ class CairoDoc(BaseDoc, TextDoc, DrawDoc):
styledtext : assumed a StyledText object to write styledtext : assumed a StyledText object to write
format : = 0 : Flowed, = 1 : Preformatted format : = 0 : Flowed, = 1 : Preformatted
style_name : name of the style to use for default presentation style_name : name of the style to use for default presentation
@note: text=normal text, p_text=text with pango markup, s_tags=styled
text tags, p
""" """
text = str(styledtext) text = str(styledtext)
@ -1376,7 +1373,7 @@ class CairoDoc(BaseDoc, TextDoc, DrawDoc):
markuptext = self._backend.add_markup_from_styled(text, s_tags) markuptext = self._backend.add_markup_from_styled(text, s_tags)
self.__write_text(text, markup=True) self.__write_text(text, markup=True)
def add_media_object(self, name, pos, x_cm, y_cm): def add_media_object(self, name, pos, x_cm, y_cm, alt=''):
new_image = GtkDocPicture(pos, name, x_cm, y_cm) new_image = GtkDocPicture(pos, name, x_cm, y_cm)
self._active_element.add_child(new_image) self._active_element.add_child(new_image)

View File

@ -29,6 +29,7 @@
# #
#------------------------------------------------------------------------ #------------------------------------------------------------------------
from xml.sax.saxutils import escape from xml.sax.saxutils import escape
import os.path
#------------------------------------------------------------------------- #-------------------------------------------------------------------------
# #
@ -43,6 +44,7 @@ from xml.sax.saxutils import escape
#------------------------------------------------------------------------ #------------------------------------------------------------------------
from gen.plug.docbackend import DocBackend from gen.plug.docbackend import DocBackend
from libhtml import Html from libhtml import Html
from Utils import xml_lang
try: try:
from gen.plug import PluginManager, Plugin from gen.plug import PluginManager, Plugin
@ -100,35 +102,58 @@ class HtmlBackend(DocBackend):
self.html_page = None self.html_page = None
self.html_header = None self.html_header = None
self.html_body = None self.html_body = None
self._subdir = None
self.title = 'GRAMPS Html Document'
def _create_xmltag(self, type, value): def _create_xmltag(self, tagtype, value):
""" """
overwrites the method in DocBackend overwrites the method in DocBackend
creates the pango xml tags needed for non bool style types creates the pango xml tags needed for non bool style types
""" """
if type not in self.SUPPORTED_MARKUP: if tagtype not in self.SUPPORTED_MARKUP:
return None return None
if type == DocBackend.FONTSIZE: if tagtype == DocBackend.FONTSIZE:
#size is in points #size is in points
value = str(value) value = str(value)
return ('<span style="%s">' % (self.STYLETAG_TO_PROPERTY[type] % return ('<span style="%s">' % (self.STYLETAG_TO_PROPERTY[tagtype] %
(value)), (value)),
'</span>') '</span>')
def _checkfilename(self):
"""
Check to make sure filename satisfies the standards for this filetype
"""
fparts = os.path.basename(self._filename).split('.')
if not len(fparts) >= 2 and not (fparts[-1] == 'html' or
fparts[-1] == 'htm' or fparts[-1] == 'php'):
self._filename = self._filename + ".htm"
fparts = self._filename.split('.')
self._subdir = '.'.join(fparts[:-1])
def set_title(self, title):
"""
Set the title to use for the html page
"""
self.title = title
def open(self): def open(self):
""" """
overwrite method, htmlbackend creates a html object that is written on overwrite method, htmlbackend creates a html object that is written on
close close
""" """
self.html_page, self.html_header, self.html_body = Html.page() DocBackend.open(self)
if not os.path.isdir(self._subdir):
os.mkdir(self._subdir)
self.html_page, self.html_header, self.html_body = Html.page(
lang=xml_lang(), title=self.title)
def __write(self, str): def __write(self, string):
""" a write to the file """ a write to the file
""" """
DocBackend.write(self, str) DocBackend.write(self, string)
def write(obj): def write(self, obj):
""" write to the html page. One can pass a html object, or a string """ write to the html page. One can pass a html object, or a string
""" """
self.html_body += obj self.html_body += obj
@ -137,9 +162,14 @@ class HtmlBackend(DocBackend):
""" """
write out the html to the page write out the html to the page
""" """
DocBackend.open(self) self.html_page.write(self.__write)
self._html.write(self.__write)
DocBackend.close(self) DocBackend.close(self)
def datadir(self):
"""
the directory where to save extra files
"""
return self._subdir
# ------------------------------------------ # ------------------------------------------
# #

View File

@ -26,6 +26,10 @@
# $Id: NarrativeWeb.py 12593 2009-05-30 08:46:12Z robhealey1 $ # $Id: NarrativeWeb.py 12593 2009-05-30 08:46:12Z robhealey1 $
"""
General constants used in different html enabled plugins
"""
#------------------------------------------------------------------------ #------------------------------------------------------------------------
# #
# GRAMPS modules # GRAMPS modules
@ -38,6 +42,7 @@ try:
except ImportError: except ImportError:
print 'Plugin manager not imported.' print 'Plugin manager not imported.'
#------------------------------------------------------------------------ #------------------------------------------------------------------------
# #
# Constants # Constants
@ -88,13 +93,17 @@ _CC = [
'src="%(gif_fname)s" /></a>', 'src="%(gif_fname)s" /></a>',
'<a rel="license" href="http://creativecommons.org/licenses/by-nc-nd/2.5/">' '<a rel="license" href="http://creativecommons.org/licenses/by-nc-nd/2.5/">'
'<img alt="Creative Commons License - By attribution, Non-commercial, No derivations" ' '<img alt="Creative Commons License - By attribution, Non-commercial, '
'title="Creative Commons License - By attribution, Non-commercial, No derivations" ' 'No derivations" '
'title="Creative Commons License - By attribution, Non-commercial, '
'No derivations" '
'src="%(gif_fname)s" /></a>', 'src="%(gif_fname)s" /></a>',
'<a rel="license" href="http://creativecommons.org/licenses/by-nc-sa/2.5/">' '<a rel="license" href="http://creativecommons.org/licenses/by-nc-sa/2.5/">'
'<img alt="Creative Commons License - By attribution, Non-commerical, Share-alike" ' '<img alt="Creative Commons License - By attribution, Non-commerical, '
'title="Creative Commons License - By attribution, Non-commerical, Share-alike" ' 'Share-alike" '
'title="Creative Commons License - By attribution, Non-commerical, '
'Share-alike" '
'src="%(gif_fname)s" /></a>' 'src="%(gif_fname)s" /></a>'
] ]