diff --git a/src/ImgManip.py b/src/ImgManip.py index aeaf22de7..d655e80f2 100644 --- a/src/ImgManip.py +++ b/src/ImgManip.py @@ -2,6 +2,7 @@ # Gramps - a GTK+/GNOME based genealogy program # # Copyright (C) 2000-2006 Donald N. Allingham +# Copyright (C) 2011 Adam Stein # # This program is free software; you can redistribute it and/or modify # it under the terms of the GNU General Public License as published by @@ -69,6 +70,150 @@ def resize_to_jpeg(source, destination, width, height): scaled = img.scale_simple(width, height, gtk.gdk.INTERP_BILINEAR) scaled.save(destination, 'jpeg') +#------------------------------------------------------------------------- +# +# image_dpi +# +#------------------------------------------------------------------------- +def image_dpi(source): + """ + Return the dpi found in the image header. None is returned if no dpi attribute + is available. + + :param source: source image file, in any format that PIL recognizes + :type source: unicode + :rtype: int + :returns: the DPI setting in the image header + """ + try: + import PIL.Image + except ImportError: + import sys + print >> sys.stderr, _("WARNING: PIL module not loaded. " + "Image cropping in report files will not be available.") + + dpi = None + else: + try: + img = PIL.Image.open(source) + except IOError: + dpi = None + else: + try: + dpi = img.info["dpi"] + except AttributeError, KeyError: + dpi = None + + return dpi + +#------------------------------------------------------------------------- +# +# image_dpi +# +#------------------------------------------------------------------------- +def image_dpi(source): + """ + Return the dpi found in the image header. None is returned if no dpi attribute + is available. + + :param source: source image file, in any format that PIL recognizes + :type source: unicode + :rtype: int + :returns: the DPI setting in the image header + """ + try: + import PIL.Image + except ImportError: + import sys + print >> sys.stderr, _("WARNING: PIL module not loaded. " + "Image cropping in report files will not be available.") + + dpi = None + else: + try: + img = PIL.Image.open(source) + except IOError: + dpi = None + else: + try: + dpi = img.info["dpi"] + except AttributeError, KeyError: + dpi = None + + return dpi + +#------------------------------------------------------------------------- +# +# image_dpi +# +#------------------------------------------------------------------------- +def image_dpi(source): + """ + Return the dpi found in the image header. None is returned if no dpi attribute + is available. + + :param source: source image file, in any format that PIL recognizes + :type source: unicode + :rtype: int + :returns: the DPI setting in the image header + """ + try: + import PIL.Image + except ImportError: + import sys + print >> sys.stderr, _("WARNING: PIL module not loaded. " + "Image cropping in report files will not be available.") + + dpi = None + else: + try: + img = PIL.Image.open(source) + except IOError: + dpi = None + else: + try: + dpi = img.info["dpi"] + except AttributeError, KeyError: + dpi = None + + return dpi + +#------------------------------------------------------------------------- +# +# image_dpi +# +#------------------------------------------------------------------------- +def image_dpi(source): + """ + Return the dpi found in the image header. None is returned if no dpi attribute + is available. + + :param source: source image file, in any format that PIL recognizes + :type source: unicode + :rtype: int + :returns: the DPI setting in the image header + """ + try: + import PIL.Image + except ImportError: + import sys + print >> sys.stderr, _("WARNING: PIL module not loaded. " + "Image cropping in report files will not be available.") + + dpi = None + else: + try: + img = PIL.Image.open(source) + except IOError: + dpi = None + else: + try: + dpi = img.info["dpi"] + except AttributeError, KeyError: + dpi = None + + return dpi + #------------------------------------------------------------------------- # # image_size @@ -94,6 +239,138 @@ def image_size(source): height = 0 return (width, height) +#------------------------------------------------------------------------- +# +# image_cropped_size +# +#------------------------------------------------------------------------- +def image_actual_size(x_cm, y_cm, x, y): + """ + Calculate what the actual width & height of the image should be. + + :param x_cm: width in centimeters + :type source: int + :param y_cm: height in centimeters + :type source: int + :param x: desired width in pixels + :type source: int + :param y: desired height in pixels + :type source: int + :rtype: tuple(int, int) + :returns: a tuple consisting of the width and height in centimeters + """ + + print "[Actual Size] CM = [", x_cm, ",", y_cm, "], Desired = [", x, ",", y, "]" + ratio = float(x_cm)*float(y)/(float(y_cm)*float(x)) + + if ratio < 1: + act_width = x_cm + act_height = y_cm*ratio + else: + act_height = y_cm + act_width = x_cm/ratio + + print "[Actual Size] Size = [", act_width, ",", act_height, "]" + return (act_width, act_height) + +#------------------------------------------------------------------------- +# +# image_cropped_size +# +#------------------------------------------------------------------------- +def image_actual_size(x_cm, y_cm, x, y): + """ + Calculate what the actual width & height of the image should be. + + :param x_cm: width in centimeters + :type source: int + :param y_cm: height in centimeters + :type source: int + :param x: desired width in pixels + :type source: int + :param y: desired height in pixels + :type source: int + :rtype: tuple(int, int) + :returns: a tuple consisting of the width and height in centimeters + """ + + print "[Actual Size] CM = [", x_cm, ",", y_cm, "], Desired = [", x, ",", y, "]" + ratio = float(x_cm)*float(y)/(float(y_cm)*float(x)) + + if ratio < 1: + act_width = x_cm + act_height = y_cm*ratio + else: + act_height = y_cm + act_width = x_cm/ratio + + print "[Actual Size] Size = [", act_width, ",", act_height, "]" + return (act_width, act_height) + +#------------------------------------------------------------------------- +# +# image_cropped_size +# +#------------------------------------------------------------------------- +def image_actual_size(x_cm, y_cm, x, y): + """ + Calculate what the actual width & height of the image should be. + + :param x_cm: width in centimeters + :type source: int + :param y_cm: height in centimeters + :type source: int + :param x: desired width in pixels + :type source: int + :param y: desired height in pixels + :type source: int + :rtype: tuple(int, int) + :returns: a tuple consisting of the width and height in centimeters + """ + + ratio = float(x_cm)*float(y)/(float(y_cm)*float(x)) + + if ratio < 1: + act_width = x_cm + act_height = y_cm*ratio + else: + act_height = y_cm + act_width = x_cm/ratio + + return (act_width, act_height) + +#------------------------------------------------------------------------- +# +# image_cropped_size +# +#------------------------------------------------------------------------- +def image_actual_size(x_cm, y_cm, x, y): + """ + Calculate what the actual width & height of the image should be. + + :param x_cm: width in centimeters + :type source: int + :param y_cm: height in centimeters + :type source: int + :param x: desired width in pixels + :type source: int + :param y: desired height in pixels + :type source: int + :rtype: tuple(int, int) + :returns: a tuple consisting of the width and height in centimeters + """ + + ratio = float(x_cm)*float(y)/(float(y_cm)*float(x)) + + if ratio < 1: + act_width = x_cm + act_height = y_cm*ratio + else: + act_height = y_cm + act_width = x_cm/ratio + + return (act_width, act_height) + #------------------------------------------------------------------------- # # resize_to_jpeg_buffer diff --git a/src/gen/plug/docgen/__init__.py b/src/gen/plug/docgen/__init__.py index e359821a5..e1960fde3 100644 --- a/src/gen/plug/docgen/__init__.py +++ b/src/gen/plug/docgen/__init__.py @@ -3,6 +3,7 @@ # # Copyright (C) 2009 B. Malengier # Copyright (C) 2010 Jakim Friant +# Copyright (C) 2011 Adam Stein # # This program is free software; you can redistribute it and/or modify # it under the terms of the GNU General Public License as published by @@ -34,6 +35,6 @@ from paragraphstyle import ParagraphStyle, PARA_ALIGN_CENTER, PARA_ALIGN_LEFT,\ from tablestyle import TableStyle, TableCellStyle from stylesheet import StyleSheetList, StyleSheet, SheetParser from graphicstyle import GraphicsStyle, SOLID, DASHED, DOTTED -from textdoc import TextDoc, IndexMark,INDEX_TYPE_ALP, INDEX_TYPE_TOC +from textdoc import TextDoc, IndexMark,INDEX_TYPE_ALP, INDEX_TYPE_TOC, URL_PATTERN from drawdoc import DrawDoc from graphdoc import GVDoc diff --git a/src/gen/plug/docgen/textdoc.py b/src/gen/plug/docgen/textdoc.py index 81f120175..aeea87cb2 100644 --- a/src/gen/plug/docgen/textdoc.py +++ b/src/gen/plug/docgen/textdoc.py @@ -7,6 +7,7 @@ # Copyright (C) 2009 Benny Malengier # Copyright (C) 2009 Gary Burton # Copyright (C) 2010 Peter Landgren +# Copyright (C) 2011 Adam Stein # # This program is free software; you can redistribute it and/or modify # it under the terms of the GNU General Public License as published by @@ -47,6 +48,13 @@ import logging log = logging.getLogger(".textdoc") +#------------------------------------------------------------------------- +# +# URL string pattern +# +#------------------------------------------------------------------------- +URL_PATTERN = r'''(((https?|mailto):)(//([^/?#"]*))?([^?#"]*)(\?([^#"]*))?(#([^"]*))?)''' + #------------------------------------------------------------------------- # # IndexMark types @@ -160,13 +168,14 @@ class TextDoc(object): """ raise NotImplementedError - def write_text(self, text, mark=None): + def write_text(self, text, mark=None, links=False): """ Writes the text in the current paragraph. Should only be used after a start_paragraph and before an end_paragraph. @param text: text to write. @param mark: IndexMark to use for indexing (if supported) + @param links: make URLs in the text clickable (if supported) """ raise NotImplementedError @@ -194,17 +203,18 @@ class TextDoc(object): """ raise NotImplementedError - def write_endnotes_ref(self, text, style_name): + def write_endnotes_ref(self, text, style_name, links=False): """ Writes the note's text and take care of paragraphs, @param text: text to write. @param style_name: style to be used. + @param links: make URLs in the text clickable (if supported) """ raise NotImplementedError def write_styled_note(self, styledtext, format, style_name, - contains_html=False): + contains_html=False, links=False): """ Convenience function to write a styledtext to the cairo doc. styledtext : assumed a StyledText object to write @@ -214,6 +224,7 @@ class TextDoc(object): If contains_html=True, then the textdoc is free to handle that in some way. Eg, a textdoc could remove all tags, or could make sure a link is clickable. + links: bool, make URLs in the text clickable (if supported) overwrite this method if the backend supports styled notes """ @@ -252,7 +263,7 @@ class TextDoc(object): else: self.write_text(piece) - def add_media_object(self, name, align, w_cm, h_cm, alt=''): + def add_media_object(self, name, align, w_cm, h_cm, alt='', style_name=None, crop=None): """ Add a photo of the specified width (in centimeters). @@ -262,6 +273,8 @@ class TextDoc(object): @param w_cm: width in centimeters @param h_cm: height in centimeters @param alt: an alternative text to use. Useful for eg html reports + @param style_name: style to use for captions + @param crop: image cropping parameters """ raise NotImplementedError @@ -293,3 +306,4 @@ class TextDoc(object): so that docgen ntypes are not required to have this. """ pass + diff --git a/src/gen/plug/report/endnotes.py b/src/gen/plug/report/endnotes.py index 2da931133..b7af8bb83 100644 --- a/src/gen/plug/report/endnotes.py +++ b/src/gen/plug/report/endnotes.py @@ -4,6 +4,7 @@ # Copyright (C) 2007 Brian G. Matherly # Copyright (C) 2010 Peter Landgren # Copyright (C) 2010 Jakim Friant +# Copyright (C) 2011 Adam Stein # # This program is free software; you can redistribute it and/or modify # it under the terms of the GNU General Public License as published by @@ -90,7 +91,7 @@ def cite_source(bibliography, obj): txt += key return txt -def write_endnotes(bibliography, database, doc, printnotes=False): +def write_endnotes(bibliography, database, doc, printnotes=False, links=False): """ Write all the entries in the bibliography as endnotes. @@ -103,6 +104,8 @@ def write_endnotes(bibliography, database, doc, printnotes=False): @param printnotes: Indicate if the notes attached to a source must be written too. @type printnotes: bool + @param links: Indicate if URL links should be makde 'clickable'. + @type links: bool """ if bibliography.get_citation_count() == 0: return @@ -121,7 +124,7 @@ def write_endnotes(bibliography, database, doc, printnotes=False): src_txt = _format_source_text(source) - doc.write_text(src_txt) + doc.write_text(src_txt, links=links) doc.end_paragraph() ref_list = citation.get_ref_list() @@ -136,7 +139,7 @@ def write_endnotes(bibliography, database, doc, printnotes=False): first = False else: reflines += ('\n%s' % txt) - doc.write_endnotes_ref(reflines,'Endnotes-Ref') + doc.write_endnotes_ref(reflines,'Endnotes-Ref', links=links) if printnotes: note_list = source.get_note_list() @@ -151,7 +154,8 @@ def write_endnotes(bibliography, database, doc, printnotes=False): doc.write_styled_note(note.get_styledtext(), note.get_format(),'Endnotes-Notes', contains_html= note.get_type() \ - == NoteType.HTML_CODE) + == NoteType.HTML_CODE, + links=links) ind += 1 def _format_source_text(source): diff --git a/src/plugins/docgen/AsciiDoc.py b/src/plugins/docgen/AsciiDoc.py index f6c30c646..10cc3a788 100644 --- a/src/plugins/docgen/AsciiDoc.py +++ b/src/plugins/docgen/AsciiDoc.py @@ -5,6 +5,7 @@ # Copyright (C) 2007-2009 Brian G. Matherly # Copyright (C) 2009-2010 Benny Malengier # Copyright (C) 2010 Peter Landgren +# Copyright (C) 2011 Adam Stein # # This program is free software; you can redistribute it and/or modify # it under the terms of the GNU General Public License as published by @@ -361,7 +362,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, alt=''): + def add_media_object(self, name, align, w_cm, h_cm, alt='', style_name=None, crop=None): this_text = '(photo)' if self.in_cell: self.cellpars[self.cellnum] += this_text @@ -369,7 +370,7 @@ class AsciiDoc(BaseDoc,TextDoc): self.f.write(this_text) def write_styled_note(self, styledtext, format, style_name, - contains_html=False): + contains_html=False, links=False): """ Convenience function to write a styledtext to the ASCII doc. styledtext : assumed a StyledText object to write @@ -379,6 +380,7 @@ class AsciiDoc(BaseDoc,TextDoc): If contains_html=True, then the textdoc is free to handle that in some way. Eg, a textdoc could remove all tags, or could make sure a link is clickable. AsciiDoc prints the html without handling it + links: bool, make the URL in the text clickable (if supported) """ if contains_html: return @@ -402,7 +404,7 @@ class AsciiDoc(BaseDoc,TextDoc): self.write_text(line) self.end_paragraph() - def write_endnotes_ref(self, text, style_name): + def write_endnotes_ref(self, text, style_name, links=False): """ Overwrite base method for lines of endnotes references """ @@ -415,5 +417,5 @@ class AsciiDoc(BaseDoc,TextDoc): # # Writes text. #-------------------------------------------------------------------- - def write_text(self,text,mark=None): + def write_text(self,text,mark=None,links=False): self.text = self.text + text diff --git a/src/plugins/docgen/HtmlDoc.py b/src/plugins/docgen/HtmlDoc.py index 3135ce0ad..b7e85ec41 100644 --- a/src/plugins/docgen/HtmlDoc.py +++ b/src/plugins/docgen/HtmlDoc.py @@ -6,6 +6,7 @@ # Copyright (C) 2009-2010 Benny Malengier # Copyright (C) 2010 Peter Landgren # Copyright (C) 2010 Tim Lyons +# Copyright (C) 2011 Adam Stein # # This program is free software; you can redistribute it and/or modify @@ -316,7 +317,7 @@ class HtmlDoc(BaseDoc, TextDoc): """ self.__write_text(' ', markup=True) - def write_text(self, text, mark=None): + def write_text(self, text, mark=None, links=False): """ Overwrite base method """ @@ -448,7 +449,7 @@ class HtmlDoc(BaseDoc, TextDoc): """ self.__reduce_list() - def write_endnotes_ref(self, text, style_name): + def write_endnotes_ref(self, text, style_name, links=False): """ Overwrite base method for lines of endnotes references """ @@ -465,7 +466,7 @@ class HtmlDoc(BaseDoc, TextDoc): self.__reduce_list() def write_styled_note(self, styledtext, format, style_name, - contains_html=False): + contains_html=False, links=False): """ Convenience function to write a styledtext to the html doc. styledtext : assumed a StyledText object to write @@ -532,7 +533,7 @@ class HtmlDoc(BaseDoc, TextDoc): #end div element self.__reduce_list() - def add_media_object(self, name, pos, w_cm, h_cm, alt=''): + def add_media_object(self, name, pos, w_cm, h_cm, alt='', style_name=None, crop=None): """ Overwrite base method """ diff --git a/src/plugins/docgen/LaTeXDoc.py b/src/plugins/docgen/LaTeXDoc.py index 3fdc0f2c4..854e644e2 100644 --- a/src/plugins/docgen/LaTeXDoc.py +++ b/src/plugins/docgen/LaTeXDoc.py @@ -8,6 +8,7 @@ # 2003 Alex Roitman # 2009 Benny Malengier # 2010 Peter Landgren +# Copyright (C) 2011 Adam Stein # # This program is free software; you can redistribute it and/or modify # it under the terms of the GNU General Public License as published by @@ -569,7 +570,7 @@ class LaTeXDoc(BaseDoc, TextDoc): if self.curcol < self.numcols: self._backend.write('& ') - def add_media_object(self, name, pos, x, y, alt=''): + def add_media_object(self, name, pos, x, y, alt='', style_name=None, crop=None): """Add photo to report""" return @@ -591,7 +592,7 @@ class LaTeXDoc(BaseDoc, TextDoc): else: self._backend.write('\\centerline{\\includegraphics[%s]{%s}}\n' % (mysize,picf)) - def write_text(self,text,mark=None): + def write_text(self,text,mark=None,links=False): """Write the text to the file""" if text == '\n': text = '\\newline\n' @@ -601,7 +602,7 @@ class LaTeXDoc(BaseDoc, TextDoc): self._backend.write(text) def write_styled_note(self, styledtext, format, style_name, - contains_html=False): + contains_html=False, links=False): """ Convenience function to write a styledtext to the latex doc. styledtext : assumed a StyledText object to write @@ -644,7 +645,7 @@ class LaTeXDoc(BaseDoc, TextDoc): self.end_paragraph() self._backend.write("\n\\vspace*{0.5cm} \n\\end{minipage}\n\n") - def write_endnotes_ref(self, text, style_name): + def write_endnotes_ref(self, text, style_name, links=False): """ Overwrite base method for lines of endnotes references """ diff --git a/src/plugins/docgen/ODFDoc.py b/src/plugins/docgen/ODFDoc.py index 91ee81e4d..9e1fa7453 100644 --- a/src/plugins/docgen/ODFDoc.py +++ b/src/plugins/docgen/ODFDoc.py @@ -6,6 +6,7 @@ # Copyright (C) 2007-2009 Brian G. Matherly # Copyright (C) 2010 Peter Landgren # Copyright (C) 2010 Jakim Friant +# Copyright (C) 2011 Adam Stein # # This program is free software; you can redistribute it and/or modify # it under the terms of the GNU General Public License as published by @@ -81,7 +82,7 @@ from xml.sax.saxutils import escape from gen.plug.docgen import (BaseDoc, TextDoc, DrawDoc, graphicstyle, FONT_SANS_SERIF, SOLID, PAPER_PORTRAIT, INDEX_TYPE_TOC, PARA_ALIGN_CENTER, PARA_ALIGN_LEFT, - INDEX_TYPE_ALP, PARA_ALIGN_RIGHT) + INDEX_TYPE_ALP, PARA_ALIGN_RIGHT, URL_PATTERN) from gen.plug.docgen.fontscale import string_width from libodfbackend import OdfBackend import const @@ -416,6 +417,8 @@ _SHEADER_FOOTER = '''\ \n ''' +_CLICKABLE = r'''\1''' + #------------------------------------------------------------------------- # # ODFDoc @@ -451,7 +454,8 @@ class ODFDoc(BaseDoc, TextDoc, DrawDoc): self.new_cell = 0 self.page = 0 self.first_page = 1 - self.StyleList = [] # styles to create depending on styled notes. + self.StyleList_notes = [] # styles to create depending on styled notes. + self.StyleList_photos = [] # styles to create depending on clipped images. def open(self, filename): """ @@ -484,7 +488,7 @@ class ODFDoc(BaseDoc, TextDoc, DrawDoc): self.lang = current_locale[0] self.lang = self.lang.replace('_', '-') if self.lang else "en-US" - self.StyleList = [] # styles to create depending on styled notes. + self.StyleList_notes = [] # styles to create depending on styled notes. wrt1('\n' '\n' ) - def add_media_object(self, file_name, pos, x_cm, y_cm, alt=''): + def add_styled_photo_styles(self): + """ + Add the new styles for clipped images in the automatic-styles section. + """ + wrt2 = self.cntnt2.write + for style in self.StyleList_photos: + if style[0] == "Left": + wrt2( + '' + + '' + + '\n' + ) + elif style[0] == "Right": + wrt2( + '' + + '' + + '\n' + ) + elif style[0] == "Single": + wrt2( + '' + + '\n' + ) + else: + wrt2( + '' + + '' + + '\n' + ) + + def add_media_object(self, file_name, pos, x_cm, y_cm, alt='', style_name=None, crop=None): """ Add multi-media documents : photos """ @@ -885,14 +998,6 @@ class ODFDoc(BaseDoc, TextDoc, DrawDoc): if (x, y) == (0, 0): return - ratio = float(x_cm) * float(y) / (float(y_cm) * float(x)) - if ratio < 1: - act_width = x_cm - act_height = y_cm * ratio - else: - act_height = y_cm - act_width = x_cm / ratio - not_extension, extension = os.path.splitext(file_name) odf_name = md5(file_name).hexdigest() + extension @@ -907,6 +1012,37 @@ class ODFDoc(BaseDoc, TextDoc, DrawDoc): self.cntnt.write('') pos = pos.title() if pos in ['left', 'right', 'single'] else 'Row' + + if crop: + dpi = ImgManip.image_dpi(file_name) + + if dpi: + (act_width, act_height) = ImgManip.image_actual_size( + x_cm, y_cm, crop[2] - crop[0], crop[3] - crop[1] + ) + + left = ((crop[0]/100.0)*x)/dpi[0] + right = (x - ((crop[2]/100.0)*x))/dpi[0] + top = ((crop[1]/100.0)*y)/dpi[1] + bottom = (y - ((crop[3]/100.0)*y))/dpi[1] + + crop = (top, right, bottom, left) + + self.StyleList_photos.append( + [pos, crop] + ) + + pos += "_" + str(crop) + else: + (act_width, act_height) = ImgManip.image_actual_size(x_cm, y_cm, x, y) + else: + (act_width, act_height) = ImgManip.image_actual_size(x_cm, y_cm, x, y) + + if len(alt): + self.cntnt.write(' ' % (pos, tag, act_width)) + self.cntnt.write(' ' % act_height) + self.cntnt.write('' % style_name) + self.cntnt.write( '\n' ) + if len(alt): + self.cntnt.write( + '%s' % alt + + '' + + '' + + '' + ) + if self.new_cell: self.cntnt.write('\n') @@ -1355,7 +1499,7 @@ class ODFDoc(BaseDoc, TextDoc, DrawDoc): ) self.new_cell = 1 - def write_endnotes_ref(self, text, style_name): + def write_endnotes_ref(self, text, style_name, links=False): """ Overwrite base method for lines of endnotes references """ @@ -1364,6 +1508,10 @@ class ODFDoc(BaseDoc, TextDoc, DrawDoc): # Replace multiple spaces: have to go from the largest number down for n in range(text.count(' '), 1, -1): text = text.replace(' '*n, ' ' % (n-1) ) + + if links == True: + text = re.sub(URL_PATTERN, _CLICKABLE, text) + self.start_paragraph(style_name) # self.cntnt.write('') self.cntnt.write( @@ -1374,7 +1522,7 @@ class ODFDoc(BaseDoc, TextDoc, DrawDoc): self.end_paragraph() def write_styled_note(self, styledtext, format, style_name, - contains_html=False): + contains_html=False, links=False): """ Convenience function to write a styledtext to the ODF doc. styledtext : assumed a StyledText object to write @@ -1384,10 +1532,15 @@ class ODFDoc(BaseDoc, TextDoc, DrawDoc): If contains_html=True, then the textdoc is free to handle that in some way. Eg, a textdoc could remove all tags, or could make sure a link is clickable. ODFDoc prints the html without handling it + links: bool, make URLs clickable if True """ text = str(styledtext) s_tags = styledtext.get_tags() markuptext = self._backend.add_markup_from_styled(text, s_tags, '\n') + + if links == True: + markuptext = re.sub(URL_PATTERN, _CLICKABLE, markuptext) + # we need to know if we have new styles to add. # if markuptext contains : FontColor, FontFace, FontSize ... # we must prepare the new styles for the styles.xml file. @@ -1399,9 +1552,9 @@ class ODFDoc(BaseDoc, TextDoc, DrawDoc): m = NewStyle.search(markuptext, start) if not m: break - self.StyleList.append([m.group(1)+m.group(2), - m.group(1), - m.group(2)]) + self.StyleList_notes.append([m.group(1)+m.group(2), + m.group(1), + m.group(2)]) start = m.end() linenb = 1 self.start_paragraph(style_name) @@ -1418,12 +1571,15 @@ class ODFDoc(BaseDoc, TextDoc, DrawDoc): linenb += 1 self.end_paragraph() - def write_text(self, text, mark=None): + def write_text(self, text, mark=None, links=False): """ Uses the xml.sax.saxutils.escape function to convert XML entities. The _esc_map dictionary allows us to add our own mappings. """ + if links == True: + text = re.sub(URL_PATTERN, _CLICKABLE, text) + if mark: key = escape(mark.key, _esc_map) key = key.replace('"', '"') @@ -1743,4 +1899,4 @@ def process_spaces(line, format): sigcount += 1 txt += char return [txt, sigcount] - \ No newline at end of file + diff --git a/src/plugins/docgen/PSDrawDoc.py b/src/plugins/docgen/PSDrawDoc.py index 0c35b6e03..06308bddb 100644 --- a/src/plugins/docgen/PSDrawDoc.py +++ b/src/plugins/docgen/PSDrawDoc.py @@ -4,6 +4,7 @@ # Copyright (C) 2000-2006 Donald N. Allingham # Copyright (C) 2007-2009 Brian G. Matherly # Copyright (C) 2010 Jakim Friant +# Copyright (C) 2011 Adam Stein # # This program is free software; you can redistribute it and/or modify # it under the terms of the GNU General Public License as published by @@ -147,7 +148,7 @@ class PSDrawDoc(BaseDoc, DrawDoc): ) self.file.close() - def write_text(self, text, mark=None): + def write_text(self, text, mark=None, links=False): pass def start_page(self): diff --git a/src/plugins/docgen/RTFDoc.py b/src/plugins/docgen/RTFDoc.py index 381016ef0..3f8f941d3 100644 --- a/src/plugins/docgen/RTFDoc.py +++ b/src/plugins/docgen/RTFDoc.py @@ -5,6 +5,7 @@ # Copyright (C) 2007-2009 Brian G. Matherly # Copyright (C) 2009 Gary Burton # Copyright (C) 2010 Peter Landgren +# Copyright (C) 2011 Adam Stein # # This program is free software; you can redistribute it and/or modify # it under the terms of the GNU General Public License as published by @@ -372,7 +373,7 @@ class RTFDoc(BaseDoc,TextDoc): # dumped as a string of HEX numbers. # #-------------------------------------------------------------------- - def add_media_object(self, name, pos, x_cm, y_cm, alt=''): + def add_media_object(self, name, pos, x_cm, y_cm, alt='', style_name=None, crop=None): nx, ny = ImgManip.image_size(name) @@ -408,7 +409,7 @@ class RTFDoc(BaseDoc,TextDoc): self.f.write('}}\\par\n') def write_styled_note(self, styledtext, format, style_name, - contains_html=False): + contains_html=False, links=False): """ Convenience function to write a styledtext to the RTF doc. styledtext : assumed a StyledText object to write @@ -446,7 +447,7 @@ class RTFDoc(BaseDoc,TextDoc): self.write_text('\n') self.end_paragraph() - def write_endnotes_ref(self,text,style_name): + def write_endnotes_ref(self,text,style_name,links=False): """ Overwrite base method for lines of endnotes references """ @@ -469,7 +470,7 @@ class RTFDoc(BaseDoc,TextDoc): # the form of \`XX. Make sure to escape braces. # #-------------------------------------------------------------------- - def write_text(self,text,mark=None): + def write_text(self,text,mark=None,links=False): # Convert to unicode, just in case it's not. Fix of bug 2449. text = unicode(text) text = text.replace('\n','\n\\par ')