* 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>
* src/Exporter.py: correct crash in export assistent on invalid filenames

View File

@@ -25,6 +25,8 @@
__revision__ = "$Revision$"
DEBUG = True
#------------------------------------------------------------------------
#
# Python modules
@@ -286,8 +288,10 @@ def fontstyle_to_fontdescription(font_style):
"""
fonts = {
BaseDoc.FONT_SERIF: 'serif',
BaseDoc.FONT_SANS_SERIF: 'sans',
#BaseDoc.FONT_SERIF: 'serif',
#BaseDoc.FONT_SANS_SERIF: 'sans',
BaseDoc.FONT_SERIF: 'Times New Roman',
BaseDoc.FONT_SANS_SERIF: 'Arial',
BaseDoc.FONT_MONOSPACE: 'monospace',
}
@@ -426,6 +430,68 @@ def tabstops_to_tabarray(tab_stops, dpi):
##if res == gtk.PRINT_OPERATION_RESULT_APPLY:
##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
@@ -438,14 +504,23 @@ class GtkDocBaseElement(object):
Support document element structuring and can render itself onto
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'
_allowed_children = None
def __init__(self):
def __init__(self, style=None):
self._parent = None
self._children = []
self._style = None
self._style = style
def get_type(self):
"""Get the type of this element.
@@ -481,7 +556,7 @@ class GtkDocBaseElement(object):
return True
def get_children(self):
"""Get the list if children fo this element.
"""Get the list of children of this element.
"""
return self._children
@@ -562,10 +637,11 @@ class GtkDocParagraph(GtkDocBaseElement):
spacing = 2
def __init__(self, style, leader=None):
GtkDocBaseElement.__init__(self)
self._style = style
GtkDocBaseElement.__init__(self, style)
if leader:
self._text = leader + '\t'
# FIXME append new tab to the existing tab list
self._style.set_tabs([-1 * self._style.get_first_indent()])
else:
self._text = ''
@@ -640,9 +716,9 @@ class GtkDocParagraph(GtkDocBaseElement):
new_style = BaseDoc.ParagraphStyle(self._style)
new_style.set_top_margin(0)
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
self._text = self._text[:index]
self._text = self._text.encode('utf-8')[:index]
self._style.set_bottom_margin(0)
# FIXME do we need to return the proper height???
@@ -693,6 +769,7 @@ class GtkDocParagraph(GtkDocBaseElement):
if f_indent < 0:
x += f_indent
cr.move_to(x, t_margin + v_padding)
cr.set_source_rgb(0, 0, 0)
cr.show_layout(layout)
# calculate the full paragraph height
@@ -712,15 +789,202 @@ class GtkDocParagraph(GtkDocBaseElement):
cr.move_to(l_margin, t_margin)
cr.line_to(0, height - t_margin - b_margin)
#cr.move_to(0, 0)
#cr.line_to(layout_width / pango.SCALE, layout_height / pango.SCALE)
cr.set_line_width(1)
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_source_rgb(0, 0, 0)
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)
self._active_element.add_child(new_paragraph)
self._active_element = new_paragraph
def end_paragraph(self):
self._active_element = self._active_element.get_parent()
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):
pass
self._active_element = self._active_element.get_parent()
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):
pass
self._active_element = self._active_element.get_parent()
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):
pass
self._active_element = self._active_element.get_parent()
def write_note(self, text, format, style_name):
log.debug("write_note: %s" % text)
if format == 1:
for line in text.split('\n'):
self.start_paragraph(style_name)
@@ -813,7 +1092,6 @@ class CairoDoc(BaseDoc.BaseDoc, BaseDoc.TextDoc, BaseDoc.DrawDoc):
self.end_paragraph()
def write_text(self, text, mark=None):
log.debug("write_text: %s" % text)
# FIXME this is ugly, do we really need it?
text = text.replace('<super>', '<small><sup>')
text = text.replace('</super>', '</sup></small>')
@@ -855,6 +1133,7 @@ class GtkPrint(CairoDoc):
print_operation = gtk.PrintOperation()
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("draw_page", self.on_draw_page)
print_operation.connect("paginate", self.on_paginate)
@@ -967,6 +1246,12 @@ class GtkPrint(CairoDoc):
dpi_x = context.get_dpi_x()
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)
#def on_preview(self, operation, preview, context, parent, dummy=None):