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:
parent
10c8599867
commit
a177da80b0
@ -169,7 +169,6 @@ src/gen/plug/docbackend/Makefile
|
||||
src/gen/plug/docgen/Makefile
|
||||
src/gen/plug/menu/Makefile
|
||||
src/data/Makefile
|
||||
src/data/templates/Makefile
|
||||
src/glade/Makefile
|
||||
src/images/Makefile
|
||||
src/images/scalable/Makefile
|
||||
|
@ -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.
@ -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>
|
@ -315,7 +315,7 @@ class TextBufDoc(BaseDoc, TextDoc):
|
||||
if self.cell_lines[self.cellnum] > self.maxlines:
|
||||
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
|
||||
|
||||
this_text = '(photo)'
|
||||
|
@ -49,7 +49,7 @@ from docbackend import DocBackend
|
||||
#
|
||||
#------------------------------------------------------------------------
|
||||
import logging
|
||||
log = logging.getLogger(".cairobackend.py")
|
||||
LOG = logging.getLogger(".cairobackend.py")
|
||||
|
||||
#------------------------------------------------------------------------
|
||||
#
|
||||
@ -89,17 +89,17 @@ class CairoBackend(DocBackend):
|
||||
|
||||
ESCAPE_FUNC = lambda x: escape
|
||||
|
||||
def _create_xmltag(self, type, value):
|
||||
def _create_xmltag(self, tagtype, value):
|
||||
"""
|
||||
overwrites the method in DocBackend
|
||||
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
|
||||
if type == DocBackend.FONTSIZE:
|
||||
if tagtype == DocBackend.FONTSIZE:
|
||||
#size is in thousandths of a point in pango
|
||||
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)),
|
||||
'</span>')
|
||||
|
@ -48,7 +48,7 @@ from gettext import gettext as _
|
||||
#
|
||||
#------------------------------------------------------------------------
|
||||
import logging
|
||||
log = logging.getLogger(".docbackend.py")
|
||||
LOG = logging.getLogger(".docbackend.py")
|
||||
|
||||
#------------------------------------------------------------------------
|
||||
#
|
||||
@ -57,6 +57,9 @@ log = logging.getLogger(".docbackend.py")
|
||||
#------------------------------------------------------------------------
|
||||
|
||||
def noescape(text):
|
||||
"""
|
||||
Function that does not escape the text passed. Default for backends
|
||||
"""
|
||||
return text
|
||||
|
||||
#-------------------------------------------------------------------------
|
||||
@ -122,9 +125,17 @@ class DocBackend(object):
|
||||
self._filename = filename
|
||||
|
||||
def getf(self):
|
||||
"""
|
||||
Obtain the filename on which backend writes
|
||||
"""
|
||||
return self._filename
|
||||
|
||||
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:
|
||||
raise ValueError, _('Close file first')
|
||||
self._filename = value
|
||||
@ -156,17 +167,20 @@ class DocBackend(object):
|
||||
pass
|
||||
|
||||
def close(self):
|
||||
"""
|
||||
Closes the file that is written on.
|
||||
"""
|
||||
if self.__file is None:
|
||||
raise IOError, 'No file open'
|
||||
self.__file.close()
|
||||
self.__file = None
|
||||
|
||||
def write(self, str):
|
||||
def write(self, string):
|
||||
"""Write a string to the file. There is no return value.
|
||||
Due to buffering, the string may not actually show up untill the
|
||||
close() method is called.
|
||||
"""
|
||||
self.__file.write(str)
|
||||
self.__file.write(string)
|
||||
|
||||
def writelines(self, sequence):
|
||||
"""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
|
||||
_create_xmltag method you can overwrite
|
||||
"""
|
||||
type = s_tag.name
|
||||
tagtype = 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
|
||||
self.CLASSMAP != tagtype.__class__.__name__ :
|
||||
self.CLASSMAP == tagtype.__class__.__name__
|
||||
self.STYLETYPE_MAP[tagtype.__class__.BOLD] = self.BOLD
|
||||
self.STYLETYPE_MAP[tagtype.ITALIC] = self.ITALIC
|
||||
self.STYLETYPE_MAP[tagtype.UNDERLINE] = self.UNDERLINE
|
||||
self.STYLETYPE_MAP[tagtype.FONTFACE] = self.FONTFACE
|
||||
self.STYLETYPE_MAP[tagtype.FONTSIZE] = self.FONTSIZE
|
||||
self.STYLETYPE_MAP[tagtype.FONTCOLOR] = self.FONTCOLOR
|
||||
self.STYLETYPE_MAP[tagtype.HIGHLIGHT] = self.HIGHLIGHT
|
||||
self.STYLETYPE_MAP[tagtype.SUPERSCRIPT] = self.SUPERSCRIPT
|
||||
|
||||
typeval = int(s_tag.name)
|
||||
s_tagvalue = s_tag.value
|
||||
tag_name = None
|
||||
if type.STYLE_TYPE[typeval] == bool:
|
||||
if tagtype.STYLE_TYPE[typeval] == bool:
|
||||
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)
|
||||
elif type.STYLE_TYPE[typeval] == int:
|
||||
elif tagtype.STYLE_TYPE[typeval] == int:
|
||||
tag_name = "%d %d" % (typeval, s_tagvalue)
|
||||
if not tag_name:
|
||||
return None
|
||||
@ -231,12 +245,12 @@ class DocBackend(object):
|
||||
self.STYLETAG_MARKUP[tag_name] = tags
|
||||
return tags
|
||||
|
||||
def _create_xmltag(self, type, value):
|
||||
def _create_xmltag(self, tagtype, value):
|
||||
"""
|
||||
Create the xmltags for the 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 ('', '')
|
||||
|
||||
@ -293,7 +307,7 @@ class DocBackend(object):
|
||||
if split:
|
||||
#make sure text can split
|
||||
splitpos = text[start:pos].find(split)
|
||||
while splitpos <> -1:
|
||||
while splitpos != -1:
|
||||
otext += self.ESCAPE_FUNC()(text[start:start+splitpos])
|
||||
#close open tags
|
||||
for opentag in reversed(opentags):
|
||||
|
@ -225,7 +225,7 @@ class TextDoc(object):
|
||||
else:
|
||||
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)
|
||||
|
||||
@ -234,5 +234,6 @@ class TextDoc(object):
|
||||
'right', 'center', and 'single'
|
||||
@param w_cm: width in centimeters
|
||||
@param h_cm: height in centimeters
|
||||
@param alt: an alternative text to use. Usefull for eg html reports
|
||||
"""
|
||||
raise NotImplementedError
|
||||
|
@ -336,7 +336,7 @@ class AsciiDoc(BaseDoc,TextDoc):
|
||||
if self.cell_lines[self.cellnum] > self.maxlines:
|
||||
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)'
|
||||
if self.in_cell:
|
||||
self.cellpars[self.cellnum] = self.cellpars[self.cellnum] + this_text
|
||||
|
@ -22,13 +22,18 @@
|
||||
|
||||
# $Id:HtmlDoc.py 9912 2008-01-22 09:17:46Z acraphae $
|
||||
|
||||
|
||||
"""
|
||||
Report output generator for html documents, based on Html and HtmlBackend
|
||||
"""
|
||||
|
||||
#------------------------------------------------------------------------
|
||||
#
|
||||
# python modules
|
||||
#
|
||||
#------------------------------------------------------------------------
|
||||
import os
|
||||
import re
|
||||
import shutil
|
||||
import time
|
||||
from gettext import gettext as _
|
||||
|
||||
@ -39,77 +44,42 @@ from gettext import gettext as _
|
||||
#------------------------------------------------------------------------
|
||||
from gen.plug import PluginManager, DocGenPlugin
|
||||
import ImgManip
|
||||
import tarfile
|
||||
import const
|
||||
import Errors
|
||||
from gen.plug.docgen import BaseDoc, TextDoc, FONT_SANS_SERIF
|
||||
from libhtmlbackend import HtmlBackend
|
||||
from QuestionDialog import ErrorDialog, WarningDialog
|
||||
import Utils
|
||||
from libhtml import Html
|
||||
from QuestionDialog import WarningDialog
|
||||
|
||||
#------------------------------------------------------------------------
|
||||
#
|
||||
# Constant regular expressions
|
||||
# Set up logging
|
||||
#
|
||||
#------------------------------------------------------------------------
|
||||
t_header_line_re = re.compile(
|
||||
r"(.*)<TITLE>(.*)</TITLE>(.*)",
|
||||
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'
|
||||
]
|
||||
import logging
|
||||
LOG = logging.getLogger(".htmldoc")
|
||||
|
||||
_HTMLSCREEN = 'grampshtml.css'
|
||||
#------------------------------------------------------------------------
|
||||
#
|
||||
# HtmlDoc
|
||||
#
|
||||
#------------------------------------------------------------------------
|
||||
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)
|
||||
self.year = time.localtime(time.time())[0]
|
||||
self.ext = '.html'
|
||||
self.meta = ""
|
||||
self.copyright = 'Copyright © %d' % (self.year)
|
||||
self.map = None
|
||||
self.f = None
|
||||
self.filename = None
|
||||
self.base = ""
|
||||
self.build_header()
|
||||
self.style_declaration = None
|
||||
self.image_dir = "images"
|
||||
self.style_declaration = ''
|
||||
self.htmllist = []
|
||||
self._backend = None
|
||||
self.css_filename = None
|
||||
self.warn_dir = True
|
||||
self._col = 0
|
||||
self._tbl = None
|
||||
self._empty = 1
|
||||
|
||||
def set_css_filename(self, css_filename):
|
||||
"""
|
||||
@ -118,47 +88,47 @@ class HtmlDoc(BaseDoc, TextDoc):
|
||||
"""
|
||||
self.css_filename = css_filename
|
||||
|
||||
def set_extension(self,val):
|
||||
if val[0] != '.':
|
||||
val = "." + val
|
||||
self.ext = val
|
||||
|
||||
def set_image_dir(self,dirname):
|
||||
self.image_dir = dirname
|
||||
|
||||
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):
|
||||
(r,e) = os.path.splitext(filename)
|
||||
if e == self.ext:
|
||||
self.filename = filename
|
||||
else:
|
||||
self.filename = filename + self.ext
|
||||
"""
|
||||
Overwrite base method
|
||||
"""
|
||||
self._backend = HtmlBackend(filename)
|
||||
#self._backend.set_title(....)
|
||||
self._backend.open()
|
||||
self.htmllist += [self._backend.html_body]
|
||||
|
||||
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)
|
||||
self.build_header()
|
||||
|
||||
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):
|
||||
"""
|
||||
Convert the styles of the report into inline css for the html doc
|
||||
"""
|
||||
styles = self.get_style_sheet()
|
||||
|
||||
text = ['<style type="text/css">\n<!--']
|
||||
@ -233,142 +203,265 @@ class HtmlDoc(BaseDoc, TextDoc):
|
||||
self.style_declaration = '\n'.join(text)
|
||||
|
||||
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()
|
||||
|
||||
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):
|
||||
if self.map:
|
||||
for name, handle in self.map.iteritems():
|
||||
if name == 'template.html':
|
||||
continue
|
||||
fname = '%s%s%s' % (self.base, os.path.sep, name)
|
||||
try:
|
||||
f = open(fname, 'wb')
|
||||
f.write(handle.read())
|
||||
f.close()
|
||||
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)
|
||||
"""
|
||||
Copy support files to the datadir that needs to hold them
|
||||
"""
|
||||
#css file
|
||||
self.copy_file(os.path.join(const.DATA_DIR, self.css_filename),
|
||||
_HTMLSCREEN)
|
||||
#favicon
|
||||
self.copy_file(os.path.join(const.IMAGE_DIR, 'favicon.ico'),
|
||||
'favicon.ico')
|
||||
|
||||
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)
|
||||
def __reduce_list(self):
|
||||
"""
|
||||
Takes the internal list of html objects, and adds the last to the
|
||||
previous. This closes the upper tag
|
||||
"""
|
||||
self.htmllist[-2] += self.htmllist[-1]
|
||||
self.htmllist.pop()
|
||||
|
||||
if self.image_dir:
|
||||
imdir = '%s%s%s' % (self.base, os.path.sep,self.image_dir)
|
||||
else:
|
||||
imdir = self.base
|
||||
def __write_text(self, text, mark=None, markup=False):
|
||||
"""
|
||||
@param text: text to write.
|
||||
@param mark: IndexMark to use for indexing (if supported)
|
||||
@param markup: True if text already contains markup info.
|
||||
Then text will no longer be escaped
|
||||
"""
|
||||
if not markup:
|
||||
text = self._backend.ESCAPE_FUNC()(text)
|
||||
self.htmllist[-1] += text
|
||||
|
||||
if not os.path.isdir(imdir):
|
||||
try:
|
||||
os.mkdir(imdir)
|
||||
except:
|
||||
return
|
||||
def __empty_char(self):
|
||||
"""
|
||||
Output a non breaking whitespace so as to have browser behave ok on
|
||||
empty content
|
||||
"""
|
||||
self.__write_text(' ', markup=True)
|
||||
|
||||
try:
|
||||
ImgManip.resize_to_jpeg(name, refname, size, size)
|
||||
except:
|
||||
return
|
||||
|
||||
if pos == "right":
|
||||
xtra = ' align="right"'
|
||||
elif pos == "left" :
|
||||
xtra = ' align="left"'
|
||||
else:
|
||||
xtra = ''
|
||||
|
||||
if self.image_dir:
|
||||
self.f.write('<img src="%s/%s" border="0" alt="%s"%s>\n' % \
|
||||
(self.image_dir, refname, alt, xtra))
|
||||
else:
|
||||
self.f.write('<img src="%s" border="0" alt="%s"%s>\n'
|
||||
% (refname, alt, xtra))
|
||||
def write_text(self, text, mark=None):
|
||||
"""
|
||||
Overwrite base method
|
||||
"""
|
||||
if text != "":
|
||||
self._empty = 0
|
||||
self.__write_text(text, mark)
|
||||
|
||||
def start_table(self, name, style):
|
||||
"""
|
||||
Overwrite base method
|
||||
"""
|
||||
styles = self.get_style_sheet()
|
||||
self.tbl = styles.get_table_style(style)
|
||||
self.f.write('<table width="%d%%" ' % self.tbl.get_width())
|
||||
self.f.write('cellspacing="0">\n')
|
||||
self._tbl = styles.get_table_style(style)
|
||||
self.htmllist += [Html('table', width=str(self._tbl.get_width())+'%%',
|
||||
cellspacing='0')]
|
||||
|
||||
def end_table(self):
|
||||
self.f.write('</table>\n')
|
||||
"""
|
||||
Overwrite base method
|
||||
"""
|
||||
self.__reduce_list()
|
||||
|
||||
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):
|
||||
self.f.write('</tr>\n')
|
||||
"""
|
||||
Overwrite base method
|
||||
"""
|
||||
self.__reduce_list()
|
||||
|
||||
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:
|
||||
self.f.write(' colspan="' + str(span) + '"')
|
||||
self.col = self.col + 1
|
||||
self.htmllist += [Html('td', colspan=str(span),
|
||||
_class=style_name)]
|
||||
self._col += span
|
||||
else:
|
||||
self.f.write(' width="')
|
||||
self.f.write(str(self.tbl.get_column_width(self.col)))
|
||||
self.f.write('%"')
|
||||
self.f.write(' class="')
|
||||
self.f.write(style_name)
|
||||
self.f.write('">')
|
||||
self.col = self.col + 1
|
||||
self.htmllist += [Html('td', colspan=str(span),
|
||||
width=str(self._tbl.get_column_width(
|
||||
self._col))+ '%%',
|
||||
_class=style_name)]
|
||||
self._col += 1
|
||||
|
||||
def end_cell(self):
|
||||
self.f.write('</td>\n')
|
||||
"""
|
||||
Overwrite base method
|
||||
"""
|
||||
self.__reduce_list()
|
||||
|
||||
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:
|
||||
self.f.write(leader)
|
||||
self.f.write(' ')
|
||||
self.write_text(leader+' ')
|
||||
|
||||
def end_paragraph(self):
|
||||
if self.empty == 1:
|
||||
self.f.write(' ')
|
||||
self.empty = 0
|
||||
self.f.write('</p>\n')
|
||||
"""
|
||||
Overwrite base method
|
||||
"""
|
||||
if self._empty == 1:
|
||||
self.__empty_char()
|
||||
self._empty = 0
|
||||
self.__reduce_list()
|
||||
|
||||
def start_bold(self):
|
||||
self.f.write('<b>')
|
||||
"""
|
||||
Overwrite base method
|
||||
"""
|
||||
self.htmllist += [Html('strong')]
|
||||
|
||||
def end_bold(self):
|
||||
self.f.write('</b>')
|
||||
"""
|
||||
Overwrite base method
|
||||
"""
|
||||
self.__reduce_list()
|
||||
|
||||
def start_superscript(self):
|
||||
self.f.write('<sup>')
|
||||
"""
|
||||
Overwrite base method
|
||||
"""
|
||||
self.htmllist += [Html('sup')]
|
||||
|
||||
def end_superscript(self):
|
||||
self.f.write('</sup>')
|
||||
"""
|
||||
Overwrite base method
|
||||
"""
|
||||
self.__reduce_list()
|
||||
|
||||
def write_note(self, text, format, style_name):
|
||||
"""
|
||||
Overwrite base method
|
||||
"""
|
||||
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.f.write('</pre>')
|
||||
self.__reduce_list()
|
||||
elif format == 0:
|
||||
for line in text.split('\n\n'):
|
||||
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()
|
||||
|
||||
def write_text(self,text,mark=None):
|
||||
text = text.replace('&','&'); # Must be first
|
||||
text = text.replace('<','<');
|
||||
text = text.replace('>','>');
|
||||
text = text.replace('\n','<br>')
|
||||
if text != "":
|
||||
self.empty = 0
|
||||
self.f.write(text)
|
||||
def add_media_object(self, name, pos, w_cm, h_cm, alt=''):
|
||||
"""
|
||||
Overwrite base method
|
||||
"""
|
||||
self._empty = 0
|
||||
size = int(max(w_cm, h_cm) * float(150.0/2.54))
|
||||
refname = "is%s" % os.path.basename(name)
|
||||
|
||||
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):
|
||||
"""
|
||||
overwrite base method so page break has no effect
|
||||
"""
|
||||
pass
|
||||
|
||||
#------------------------------------------------------------------------
|
||||
|
@ -584,7 +584,7 @@ class LaTeXDoc(BaseDoc, TextDoc):
|
||||
if self.curcol < self.numcols:
|
||||
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"""
|
||||
return
|
||||
|
||||
@ -622,9 +622,6 @@ class LaTeXDoc(BaseDoc, TextDoc):
|
||||
styledtext : assumed a StyledText object to write
|
||||
format : = 0 : Flowed, = 1 : Preformatted
|
||||
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)
|
||||
|
||||
|
@ -437,7 +437,7 @@ class ODFDoc(BaseDoc, TextDoc, DrawDoc):
|
||||
if self.open_req:
|
||||
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
|
||||
# a valid image (could be a PDF, or a non-image)
|
||||
|
@ -360,7 +360,7 @@ class RTFDoc(BaseDoc,TextDoc):
|
||||
# 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)
|
||||
|
||||
|
@ -1311,9 +1311,6 @@ class CairoDoc(BaseDoc, TextDoc, DrawDoc):
|
||||
styledtext : assumed a StyledText object to write
|
||||
format : = 0 : Flowed, = 1 : Preformatted
|
||||
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)
|
||||
|
||||
@ -1376,7 +1373,7 @@ class CairoDoc(BaseDoc, TextDoc, DrawDoc):
|
||||
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):
|
||||
def add_media_object(self, name, pos, x_cm, y_cm, alt=''):
|
||||
new_image = GtkDocPicture(pos, name, x_cm, y_cm)
|
||||
self._active_element.add_child(new_image)
|
||||
|
||||
|
@ -29,6 +29,7 @@
|
||||
#
|
||||
#------------------------------------------------------------------------
|
||||
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 libhtml import Html
|
||||
from Utils import xml_lang
|
||||
|
||||
try:
|
||||
from gen.plug import PluginManager, Plugin
|
||||
@ -100,35 +102,58 @@ class HtmlBackend(DocBackend):
|
||||
self.html_page = None
|
||||
self.html_header = 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
|
||||
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
|
||||
if type == DocBackend.FONTSIZE:
|
||||
if tagtype == DocBackend.FONTSIZE:
|
||||
#size is in points
|
||||
value = str(value)
|
||||
|
||||
return ('<span style="%s">' % (self.STYLETAG_TO_PROPERTY[type] %
|
||||
return ('<span style="%s">' % (self.STYLETAG_TO_PROPERTY[tagtype] %
|
||||
(value)),
|
||||
'</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):
|
||||
"""
|
||||
overwrite method, htmlbackend creates a html object that is written on
|
||||
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
|
||||
"""
|
||||
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
|
||||
"""
|
||||
self.html_body += obj
|
||||
@ -137,10 +162,15 @@ class HtmlBackend(DocBackend):
|
||||
"""
|
||||
write out the html to the page
|
||||
"""
|
||||
DocBackend.open(self)
|
||||
self._html.write(self.__write)
|
||||
self.html_page.write(self.__write)
|
||||
DocBackend.close(self)
|
||||
|
||||
def datadir(self):
|
||||
"""
|
||||
the directory where to save extra files
|
||||
"""
|
||||
return self._subdir
|
||||
|
||||
# ------------------------------------------
|
||||
#
|
||||
# Register Plugin
|
||||
|
@ -26,6 +26,10 @@
|
||||
|
||||
# $Id: NarrativeWeb.py 12593 2009-05-30 08:46:12Z robhealey1 $
|
||||
|
||||
"""
|
||||
General constants used in different html enabled plugins
|
||||
"""
|
||||
|
||||
#------------------------------------------------------------------------
|
||||
#
|
||||
# GRAMPS modules
|
||||
@ -38,6 +42,7 @@ try:
|
||||
except ImportError:
|
||||
print 'Plugin manager not imported.'
|
||||
|
||||
|
||||
#------------------------------------------------------------------------
|
||||
#
|
||||
# Constants
|
||||
@ -88,13 +93,17 @@ _CC = [
|
||||
'src="%(gif_fname)s" /></a>',
|
||||
|
||||
'<a rel="license" href="http://creativecommons.org/licenses/by-nc-nd/2.5/">'
|
||||
'<img alt="Creative Commons License - By attribution, Non-commercial, No derivations" '
|
||||
'title="Creative Commons License - By attribution, Non-commercial, No derivations" '
|
||||
'<img alt="Creative Commons License - By attribution, Non-commercial, '
|
||||
'No derivations" '
|
||||
'title="Creative Commons License - By attribution, Non-commercial, '
|
||||
'No derivations" '
|
||||
'src="%(gif_fname)s" /></a>',
|
||||
|
||||
'<a rel="license" href="http://creativecommons.org/licenses/by-nc-sa/2.5/">'
|
||||
'<img alt="Creative Commons License - By attribution, Non-commerical, Share-alike" '
|
||||
'title="Creative Commons License - By attribution, Non-commerical, Share-alike" '
|
||||
'<img alt="Creative Commons License - By attribution, Non-commerical, '
|
||||
'Share-alike" '
|
||||
'title="Creative Commons License - By attribution, Non-commerical, '
|
||||
'Share-alike" '
|
||||
'src="%(gif_fname)s" /></a>'
|
||||
]
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user