* src/docgen/GtkPrint.py: Text report generation is almost ready...



svn: r8827
This commit is contained in:
Zsolt Foldvari
2007-08-17 19:15:05 +00:00
parent 2da3c3931d
commit 679bbcc469
2 changed files with 411 additions and 123 deletions

View File

@@ -1,3 +1,6 @@
2007-08-17 Zsolt Foldvari <zfoldvar@users.sourceforge.net>
* src/docgen/GtkPrint.py: Text report generation is almost ready...
2007-08-16 Benny Malengier <bm@cage.ugent.be> 2007-08-16 Benny Malengier <bm@cage.ugent.be>
* src/Exporter.py: correct crash in export assistent on invalid filenames * src/Exporter.py: correct crash in export assistent on invalid filenames

View File

@@ -25,6 +25,8 @@
__revision__ = "$Revision$" __revision__ = "$Revision$"
DEBUG = True
#------------------------------------------------------------------------ #------------------------------------------------------------------------
# #
# Python modules # Python modules
@@ -286,8 +288,10 @@ def fontstyle_to_fontdescription(font_style):
""" """
fonts = { fonts = {
BaseDoc.FONT_SERIF: 'serif', #BaseDoc.FONT_SERIF: 'serif',
BaseDoc.FONT_SANS_SERIF: 'sans', #BaseDoc.FONT_SANS_SERIF: 'sans',
BaseDoc.FONT_SERIF: 'Times New Roman',
BaseDoc.FONT_SANS_SERIF: 'Arial',
BaseDoc.FONT_MONOSPACE: 'monospace', BaseDoc.FONT_MONOSPACE: 'monospace',
} }
@@ -426,6 +430,68 @@ def tabstops_to_tabarray(tab_stops, dpi):
##if res == gtk.PRINT_OPERATION_RESULT_APPLY: ##if res == gtk.PRINT_OPERATION_RESULT_APPLY:
##self._settings = self.get_print_settings() ##self._settings = self.get_print_settings()
#------------------------------------------------------------------------
#
# Table row style
#
#------------------------------------------------------------------------
class RowStyle(list):
"""Specifies the format of a table row.
RowStyle extents the available styles in BaseDoc.
The RowStyle contains the width of each column as a percentage of the
width of the full row. Note! The width of the row is not know until
divide() or draw() method is called.
"""
def __init__(self):
self.columns = []
def set_columns(self, columns):
"""Set the number of columns.
@param columns: number of columns that should be used.
@param type: int
"""
self.columns = columns
def get_columns(self):
"""Return the number of columns.
"""
return self.columns
def set_column_widths(self, clist):
"""Set the width of all the columns at once.
@param clist: list of width of columns in % of the full row.
@param tyle: list
"""
self.columns = len(clist)
for i in range(self.columns):
self.colwid[i] = clist[i]
def set_column_width(self, index, width):
"""
Sets the width of a specified column to the specified width.
@param index: column being set (index starts at 0)
@param width: percentage of the table width assigned to the column
"""
self.colwid[index] = width
def get_column_width(self, index):
"""
Returns the column width of the specified column as a percentage of
the entire table width.
@param index: column to return (index starts at 0)
"""
return self.colwid[index]
#------------------------------------------------------------------------ #------------------------------------------------------------------------
# #
# Document element classes # Document element classes
@@ -438,14 +504,23 @@ class GtkDocBaseElement(object):
Support document element structuring and can render itself onto Support document element structuring and can render itself onto
a Cairo surface. a Cairo surface.
There are two cathegories of methods:
1. hierarchy building methods (add_child, get_children, set_parent,
get_parent);
2. rendering methods (divide, draw).
The hierarchy building methods generally don't have to be overriden in
the subclass, while the rendering methods (divide, draw) must be
implemented in the subclasses.
""" """
_type = 'BASE' _type = 'BASE'
_allowed_children = None _allowed_children = None
def __init__(self): def __init__(self, style=None):
self._parent = None self._parent = None
self._children = [] self._children = []
self._style = None self._style = style
def get_type(self): def get_type(self):
"""Get the type of this element. """Get the type of this element.
@@ -481,7 +556,7 @@ class GtkDocBaseElement(object):
return True return True
def get_children(self): def get_children(self):
"""Get the list if children fo this element. """Get the list of children of this element.
""" """
return self._children return self._children
@@ -562,10 +637,11 @@ class GtkDocParagraph(GtkDocBaseElement):
spacing = 2 spacing = 2
def __init__(self, style, leader=None): def __init__(self, style, leader=None):
GtkDocBaseElement.__init__(self) GtkDocBaseElement.__init__(self, style)
self._style = style
if leader: if leader:
self._text = leader + '\t' self._text = leader + '\t'
# FIXME append new tab to the existing tab list
self._style.set_tabs([-1 * self._style.get_first_indent()]) self._style.set_tabs([-1 * self._style.get_first_indent()])
else: else:
self._text = '' self._text = ''
@@ -640,9 +716,9 @@ class GtkDocParagraph(GtkDocBaseElement):
new_style = BaseDoc.ParagraphStyle(self._style) new_style = BaseDoc.ParagraphStyle(self._style)
new_style.set_top_margin(0) new_style.set_top_margin(0)
new_paragraph = GtkDocParagraph(new_style) new_paragraph = GtkDocParagraph(new_style)
new_paragraph.add_text(self._text[index:]) new_paragraph.add_text(self._text.encode('utf-8')[index:])
# then update the first one # then update the first one
self._text = self._text[:index] self._text = self._text.encode('utf-8')[:index]
self._style.set_bottom_margin(0) self._style.set_bottom_margin(0)
# FIXME do we need to return the proper height??? # FIXME do we need to return the proper height???
@@ -693,6 +769,7 @@ class GtkDocParagraph(GtkDocBaseElement):
if f_indent < 0: if f_indent < 0:
x += f_indent x += f_indent
cr.move_to(x, t_margin + v_padding) cr.move_to(x, t_margin + v_padding)
cr.set_source_rgb(0, 0, 0)
cr.show_layout(layout) cr.show_layout(layout)
# calculate the full paragraph height # calculate the full paragraph height
@@ -712,15 +789,202 @@ class GtkDocParagraph(GtkDocBaseElement):
cr.move_to(l_margin, t_margin) cr.move_to(l_margin, t_margin)
cr.line_to(0, height - t_margin - b_margin) cr.line_to(0, height - t_margin - b_margin)
#cr.move_to(0, 0) cr.set_line_width(1)
#cr.line_to(layout_width / pango.SCALE, layout_height / pango.SCALE) cr.set_source_rgb(0, 0, 0)
cr.stroke()
if DEBUG:
cr.set_line_width(0.1)
cr.set_source_rgb(1.0, 0, 0)
cr.rectangle(0, 0, width, height)
cr.stroke()
cr.set_source_rgb(0, 0, 1.0)
cr.rectangle(l_margin, t_margin,
width-l_margin-r_margin, height-t_margin-b_margin)
cr.stroke()
return height
class GtkDocTable(GtkDocBaseElement):
"""Implement a table.
"""
_type = 'TABLE'
_allowed_children = ['ROW']
def divide(self, layout, width, height, dpi_x, dpi_y):
#calculate real table width
table_width = width * self._style.get_width() / 100
# calculate the height of each row
table_height = 0
row_index = 0
while row_index < len(self._children):
row = self._children[row_index]
(r1, r2), row_height = row.divide(layout, table_width, height,
dpi_x, dpi_y)
if table_height + row_height >= height:
break
table_height += row_height
row_index += 1
# divide the table if any row did not fit
new_table = None
if row_index < len(self._children):
new_table = GtkDocTable(self._style)
for row in self._children[row_index:]:
new_table.add_child(row)
del self._children[row_index:]
return (self, new_table), table_height
def draw(self, cr, layout, width, dpi_x, dpi_y):
#calculate real table width
table_width = width * self._style.get_width() / 100
# TODO is a table always left aligned??
table_height = 0
# draw all the rows
for row in self._children:
cr.save()
cr.translate(0, table_height)
row_height = row.draw(cr, layout, table_width, dpi_x, dpi_y)
cr.restore()
table_height += row_height
if DEBUG:
cr.set_line_width(0.1)
cr.set_source_rgb(1.0, 0, 0)
cr.rectangle(0, 0, table_width, table_height)
cr.stroke()
return table_height
class GtkDocTableRow(GtkDocBaseElement):
"""Implement a row in a table.
"""
_type = 'ROW'
_allowed_children = ['CELL']
def divide(self, layout, width, height, dpi_x, dpi_y):
# the highest cell gives the height of the row
cell_heights = []
cell_width_iter = self._style.__iter__()
for cell in self._children:
cell_width = 0
for i in range(cell.get_span()):
cell_width += cell_width_iter.next()
cell_width = cell_width * width / 100
(c1, c2), cell_height = cell.divide(layout, cell_width, height,
dpi_x, dpi_y)
cell_heights.append(cell_height)
return (self, None), max(cell_heights)
def draw(self, cr, layout, width, dpi_x, dpi_y):
cr.save()
# draw all the cells
cell_heights = []
cell_width_iter = self._style.__iter__()
for cell in self._children:
cell_width = 0
for i in range(cell.get_span()):
cell_width += cell_width_iter.next()
cell_width = cell_width * width / 100
cell_height = cell.draw(cr, layout, cell_width, dpi_x, dpi_y)
cell_heights.append(cell_height)
cr.translate(cell_width, 0)
row_height = max(cell_heights)
cr.restore()
if DEBUG:
cr.set_line_width(0.1)
cr.set_source_rgb(0, 0, 1.0)
cr.rectangle(0, 0, width, row_height)
cr.stroke()
return row_height
class GtkDocTableCell(GtkDocBaseElement):
"""Implement a cell in a table row.
"""
_type = 'CELL'
_allowed_children = ['PARAGRAPH', 'MEDIA']
def __init__(self, style, span=1):
GtkDocBaseElement.__init__(self, style)
self._span = span
def get_span(self):
return self._span
def divide(self, layout, width, height, dpi_x, dpi_y):
h_padding = self._style.get_padding() * dpi_x / 2.54
v_padding = self._style.get_padding() * dpi_y / 2.54
# calculate real available width
width -= 2 * h_padding
# calculate height of each children
cell_height = 0
for child in self._children:
(e1, e2), child_height = child.divide(layout, width, height,
dpi_x, dpi_y)
cell_height += child_height
# calculate real height
cell_height += 2 * v_padding
return (self, None), cell_height
def draw(self, cr, layout, width, dpi_x, dpi_y):
h_padding = self._style.get_padding() * dpi_x / 2.54
v_padding = self._style.get_padding() * dpi_y / 2.54
# calculate real available width
i_width = width - 2 * h_padding
# draw children
cr.save()
cr.translate(h_padding, v_padding)
cell_height = 0
for child in self._children:
child_height = child.draw(cr, layout, i_width, dpi_x, dpi_y)
cell_height += child_height
cr.translate(0, child_height)
cr.restore()
# calculate real height
cell_height += 2 * v_padding
# draw the borders
if self._style.get_top_border():
cr.move_to(0, 0)
cr.rel_line_to(width , 0)
if self._style.get_right_border():
cr.move_to(width, 0)
cr.rel_line_to(0, cell_height)
if self._style.get_bottom_border():
cr.move_to(0, cell_height)
cr.rel_line_to(width, 0)
if self._style.get_left_border():
cr.move_to(0, 0)
cr.line_to(0, cell_height)
cr.set_line_width(1) cr.set_line_width(1)
cr.set_source_rgb(0, 0, 0) cr.set_source_rgb(0, 0, 0)
cr.stroke() cr.stroke()
return height if DEBUG:
cr.set_line_width(0.1)
cr.set_source_rgb(0, 1.0, 0)
cr.rectangle(0, 0, width, cell_height)
cr.stroke()
return cell_height
#------------------------------------------------------------------------ #------------------------------------------------------------------------
# #
@@ -772,33 +1036,48 @@ class CairoDoc(BaseDoc.BaseDoc, BaseDoc.TextDoc, BaseDoc.DrawDoc):
new_paragraph = GtkDocParagraph(style, leader) new_paragraph = GtkDocParagraph(style, leader)
self._active_element.add_child(new_paragraph) self._active_element.add_child(new_paragraph)
self._active_element = new_paragraph self._active_element = new_paragraph
def end_paragraph(self): def end_paragraph(self):
self._active_element = self._active_element.get_parent() self._active_element = self._active_element.get_parent()
def start_table(self, name, style_name): def start_table(self, name, style_name):
pass style_sheet = self.get_style_sheet()
style = style_sheet.get_table_style(style_name)
new_table = GtkDocTable(style)
self._active_element.add_child(new_table)
self._active_element = new_table
# we need to remember the column width list from the table style.
# this is an ugly hack, but got no better idea.
self._active_row_style = []
for i in range(style.get_columns()):
self._active_row_style.append(style.get_column_width(i))
def end_table(self): def end_table(self):
pass self._active_element = self._active_element.get_parent()
def start_row(self): def start_row(self):
pass new_row = GtkDocTableRow(self._active_row_style)
self._active_element.add_child(new_row)
self._active_element = new_row
def end_row(self): def end_row(self):
pass self._active_element = self._active_element.get_parent()
def start_cell(self, style_name, span=1): def start_cell(self, style_name, span=1):
pass style_sheet = self.get_style_sheet()
style = style_sheet.get_cell_style(style_name)
new_cell = GtkDocTableCell(style, span)
self._active_element.add_child(new_cell)
self._active_element = new_cell
def end_cell(self): def end_cell(self):
pass self._active_element = self._active_element.get_parent()
def write_note(self, text, format, style_name): def write_note(self, text, format, style_name):
log.debug("write_note: %s" % text)
if format == 1: if format == 1:
for line in text.split('\n'): for line in text.split('\n'):
self.start_paragraph(style_name) self.start_paragraph(style_name)
@@ -813,7 +1092,6 @@ class CairoDoc(BaseDoc.BaseDoc, BaseDoc.TextDoc, BaseDoc.DrawDoc):
self.end_paragraph() self.end_paragraph()
def write_text(self, text, mark=None): def write_text(self, text, mark=None):
log.debug("write_text: %s" % text)
# FIXME this is ugly, do we really need it? # FIXME this is ugly, do we really need it?
text = text.replace('<super>', '<small><sup>') text = text.replace('<super>', '<small><sup>')
text = text.replace('</super>', '</sup></small>') text = text.replace('</super>', '</sup></small>')
@@ -855,6 +1133,7 @@ class GtkPrint(CairoDoc):
print_operation = gtk.PrintOperation() print_operation = gtk.PrintOperation()
print_operation.set_default_page_setup(page_setup) print_operation.set_default_page_setup(page_setup)
print_operation.set_show_progress(True)
print_operation.connect("begin_print", self.on_begin_print) print_operation.connect("begin_print", self.on_begin_print)
print_operation.connect("draw_page", self.on_draw_page) print_operation.connect("draw_page", self.on_draw_page)
print_operation.connect("paginate", self.on_paginate) print_operation.connect("paginate", self.on_paginate)
@@ -967,6 +1246,12 @@ class GtkPrint(CairoDoc):
dpi_x = context.get_dpi_x() dpi_x = context.get_dpi_x()
dpi_y = context.get_dpi_y() dpi_y = context.get_dpi_y()
if DEBUG:
cr.set_line_width(0.1)
cr.set_source_rgb(0, 1.0, 0)
cr.rectangle(0, 0, self.page_width, self.page_height)
cr.stroke()
self._pages[page_nr].draw(cr, layout, self.page_width, dpi_x, dpi_y) self._pages[page_nr].draw(cr, layout, self.page_width, dpi_x, dpi_y)
#def on_preview(self, operation, preview, context, parent, dummy=None): #def on_preview(self, operation, preview, context, parent, dummy=None):