5326: Add Alphabetical Index and Table of Contents generation for pdf reports
svn: r18870
This commit is contained in:
po
src
gen
plug
docgen
plugins
@ -35,6 +35,7 @@
|
||||
#------------------------------------------------------------------------
|
||||
from gen.ggettext import gettext as _
|
||||
from math import radians
|
||||
import re
|
||||
|
||||
#------------------------------------------------------------------------
|
||||
#
|
||||
@ -174,6 +175,18 @@ def tabstops_to_tabarray(tab_stops, dpi):
|
||||
|
||||
return tab_array
|
||||
|
||||
def raw_length(s):
|
||||
"""
|
||||
Return the length of the raw string after all pango markup has been removed.
|
||||
"""
|
||||
s = re.sub('<.*?>', '', s)
|
||||
s = s.replace('&', '&')
|
||||
s = s.replace('<', '<')
|
||||
s = s.replace('>', '>')
|
||||
s = s.replace('"', '"')
|
||||
s = s.replace(''', "'")
|
||||
return len(s)
|
||||
|
||||
###------------------------------------------------------------------------
|
||||
###
|
||||
### Table row style
|
||||
@ -321,6 +334,14 @@ class GtkDocBaseElement(object):
|
||||
"""
|
||||
return self._children
|
||||
|
||||
def get_marks(self):
|
||||
"""Get the list of index marks for this element.
|
||||
"""
|
||||
marks = []
|
||||
for child in self._children:
|
||||
marks.extend(child.get_marks())
|
||||
return marks
|
||||
|
||||
def divide(self, layout, width, height, dpi_x, dpi_y):
|
||||
"""Divide the element into two depending on available space.
|
||||
|
||||
@ -365,7 +386,8 @@ class GtkDocDocument(GtkDocBaseElement):
|
||||
"""The whole document or a page.
|
||||
"""
|
||||
_type = 'DOCUMENT'
|
||||
_allowed_children = ['PARAGRAPH', 'PAGEBREAK', 'TABLE', 'IMAGE', 'FRAME']
|
||||
_allowed_children = ['PARAGRAPH', 'PAGEBREAK', 'TABLE', 'IMAGE', 'FRAME',
|
||||
'TOC', 'INDEX']
|
||||
|
||||
def draw(self, cairo_context, pango_layout, width, dpi_x, dpi_y):
|
||||
|
||||
@ -378,7 +400,19 @@ class GtkDocDocument(GtkDocBaseElement):
|
||||
y += elem_height
|
||||
|
||||
return y
|
||||
|
||||
|
||||
def has_toc(self):
|
||||
for elem in self._children:
|
||||
if elem.get_type() == 'TOC':
|
||||
return True
|
||||
return False
|
||||
|
||||
def has_index(self):
|
||||
for elem in self._children:
|
||||
if elem.get_type() == 'INDEX':
|
||||
return True
|
||||
return False
|
||||
|
||||
class GtkDocPagebreak(GtkDocBaseElement):
|
||||
"""Implement a page break.
|
||||
"""
|
||||
@ -388,6 +422,30 @@ class GtkDocPagebreak(GtkDocBaseElement):
|
||||
def divide(self, layout, width, height, dpi_x, dpi_y):
|
||||
return (None, None), 0
|
||||
|
||||
class GtkDocTableOfContents(GtkDocBaseElement):
|
||||
"""Implement a table of contents.
|
||||
"""
|
||||
_type = 'TOC'
|
||||
_allowed_children = []
|
||||
|
||||
def divide(self, layout, width, height, dpi_x, dpi_y):
|
||||
return (self, None), 0
|
||||
|
||||
def draw(self, cr, layout, width, dpi_x, dpi_y):
|
||||
return 0
|
||||
|
||||
class GtkDocAlphabeticalIndex(GtkDocBaseElement):
|
||||
"""Implement an alphabetical index.
|
||||
"""
|
||||
_type = 'INDEX'
|
||||
_allowed_children = []
|
||||
|
||||
def divide(self, layout, width, height, dpi_x, dpi_y):
|
||||
return (self, None), 0
|
||||
|
||||
def draw(self, cr, layout, width, dpi_x, dpi_y):
|
||||
return 0
|
||||
|
||||
class GtkDocParagraph(GtkDocBaseElement):
|
||||
"""Paragraph.
|
||||
"""
|
||||
@ -410,12 +468,32 @@ class GtkDocParagraph(GtkDocBaseElement):
|
||||
self._plaintext = None
|
||||
self._attrlist = None
|
||||
|
||||
self._marklist = []
|
||||
|
||||
def add_text(self, text):
|
||||
if self._plaintext is not None:
|
||||
raise PluginError('CairoDoc: text is already parsed.'
|
||||
' You cannot add text anymore')
|
||||
self._text = self._text + text
|
||||
|
||||
def add_mark(self, mark):
|
||||
"""
|
||||
Add an index mark to this paragraph
|
||||
"""
|
||||
self._marklist.append((mark, raw_length(self._text)))
|
||||
|
||||
def get_marks(self):
|
||||
"""
|
||||
Return a list of index marks for this paragraph
|
||||
"""
|
||||
return [elem[0] for elem in self._marklist]
|
||||
|
||||
def __set_marklist(self, marklist):
|
||||
"""
|
||||
Internal method to allow for splitting of paragraphs
|
||||
"""
|
||||
self._marklist = marklist
|
||||
|
||||
def __set_plaintext(self, plaintext):
|
||||
"""
|
||||
Internal method to allow for splitting of paragraphs
|
||||
@ -562,7 +640,18 @@ class GtkDocParagraph(GtkDocBaseElement):
|
||||
# then update the first one
|
||||
self.__set_plaintext(self._plaintext.encode('utf-8')[:index])
|
||||
self._style.set_bottom_margin(0)
|
||||
|
||||
|
||||
# split the list of index marks
|
||||
para1 = []
|
||||
para2 = []
|
||||
for mark, position in self._marklist:
|
||||
if position < index:
|
||||
para1.append((mark, position))
|
||||
else:
|
||||
para2.append((mark, position - index))
|
||||
self.__set_marklist(para1)
|
||||
new_paragraph.__set_marklist(para2)
|
||||
|
||||
paragraph_height = endheight - startheight + spacing + t_margin + 2 * v_padding
|
||||
return (self, new_paragraph), paragraph_height
|
||||
|
||||
@ -1374,6 +1463,10 @@ links (like ODF) and write PDF from that format.
|
||||
# The markup in the note editor is not in the text so is not
|
||||
# considered. It must be added by pango too
|
||||
text = self._backend.ESCAPE_FUNC()(text)
|
||||
|
||||
if mark:
|
||||
self._active_element.add_mark(mark)
|
||||
|
||||
self._active_element.add_text(text)
|
||||
|
||||
def write_text(self, text, mark=None, links=False):
|
||||
@ -1416,6 +1509,18 @@ links (like ODF) and write PDF from that format.
|
||||
new_paragraph.add_text('\n'.join(alt))
|
||||
self._active_element.add_child(new_paragraph)
|
||||
|
||||
def insert_toc(self):
|
||||
"""
|
||||
Insert a Table of Contents at this point in the document.
|
||||
"""
|
||||
self._doc.add_child(GtkDocTableOfContents())
|
||||
|
||||
def insert_index(self):
|
||||
"""
|
||||
Insert an Alphabetical Index at this point in the document.
|
||||
"""
|
||||
self._doc.add_child(GtkDocAlphabeticalIndex())
|
||||
|
||||
# DrawDoc implementation
|
||||
|
||||
def start_page(self):
|
||||
@ -1515,6 +1620,12 @@ links (like ODF) and write PDF from that format.
|
||||
"""
|
||||
raise NotImplementedError
|
||||
|
||||
def paginate_document(self, layout, page_width, page_height, dpi_x, dpi_y):
|
||||
"""Paginate the entire document.
|
||||
"""
|
||||
while not self.paginate(layout, page_width, page_height, dpi_x, dpi_y):
|
||||
pass
|
||||
|
||||
def paginate(self, layout, page_width, page_height, dpi_x, dpi_y):
|
||||
"""Paginate the meta document in chunks.
|
||||
|
||||
|
Reference in New Issue
Block a user