2007-08-11 Zsolt Foldvari <zfoldvar@users.sourceforge.net>

* src/docgen/GtkPrint.py: Work in progress.



svn: r8807
This commit is contained in:
Zsolt Foldvari 2007-08-10 23:14:12 +00:00
parent 215595a56b
commit aaae97ca86
2 changed files with 516 additions and 275 deletions

View File

@ -1,3 +1,6 @@
2007-08-11 Zsolt Foldvari <zfoldvar@users.sourceforge.net>
* src/docgen/GtkPrint.py: Work in progress.
2007-08-09 Don Allingham <don@gramps-project.org> 2007-08-09 Don Allingham <don@gramps-project.org>
* GrampsDbUtils/_WriteGedcom.py: use utf8 encoding only * GrampsDbUtils/_WriteGedcom.py: use utf8 encoding only
* GrampsDbUtils/gedcomexport.glade: use utf8 encoding only * GrampsDbUtils/gedcomexport.glade: use utf8 encoding only

View File

@ -20,7 +20,8 @@
# $Id$ # $Id$
"Printing interface based on gtk.Print*" """Printing interface based on gtk.Print*.
"""
__revision__ = "$Revision$" __revision__ = "$Revision$"
@ -53,156 +54,154 @@ log = logging.getLogger(".GtkDoc")
# GTK modules # GTK modules
# #
#------------------------------------------------------------------------- #-------------------------------------------------------------------------
##import pygtk
import gtk import gtk
import cairo import cairo
import pango import pango
##if not hasattr(gtk, "PrintOperation"):
if gtk.pygtk_version < (2,10,0): if gtk.pygtk_version < (2,10,0):
raise Errors.UnavailableError( raise Errors.UnavailableError(
_("Cannot be loaded because PyGtk 2.10 or later is not installed")) _("Cannot be loaded because PyGtk 2.10 or later is not installed"))
#------------------------------------------------------------------------ ###------------------------------------------------------------------------
# ###
# PreviewCanvas and PreviewWindow ### PreviewCanvas and PreviewWindow
# ###
# These classes provide a simple print preview functionality. ### These classes provide a simple print preview functionality.
# They do not actually render anything themselves, they rely ### They do not actually render anything themselves, they rely
# upon the Print opertaion to do the rendering. ### upon the Print opertaion to do the rendering.
# ###
#------------------------------------------------------------------------ ###------------------------------------------------------------------------
class PreviewCanvas(gtk.DrawingArea): ##class PreviewCanvas(gtk.DrawingArea):
"""This provides a simple widget for displaying a ##"""Provide a simple widget for displaying a
cairo rendering used to show print preview windows. ##cairo rendering used to show print preview windows.
""" ##"""
def __init__(self, ##def __init__(self,
operation, ##operation,
preview_operation, ##preview_operation,
print_context): ##print_context):
gtk.DrawingArea.__init__(self) ##gtk.DrawingArea.__init__(self)
self._operation = operation ##self._operation = operation
self._preview_operation = preview_operation ##self._preview_operation = preview_operation
self._print_context = print_context ##self._print_context = print_context
self.connect("expose_event",self.expose) ##self.connect("expose_event",self.expose)
self.connect("realize",self.realize) ##self.connect("realize",self.realize)
self._page_no = 1 # always start on page 1 ##self._page_no = 1 # always start on page 1
def set_page(self,page): ##def set_page(self,page):
"""Change which page is displayed""" ##"""Change which page is displayed"""
if page > 0: ##if page > 0:
self._page_no = page ##self._page_no = page
self.queue_draw() ##self.queue_draw()
def realize(self, dummy=None): ##def realize(self, dummy=None):
"""Generate the cairo context for this drawing area ##"""Generate the cairo context for this drawing area
and pass it to the print context.""" ##and pass it to the print context."""
gtk.DrawingArea.realize(self) ##gtk.DrawingArea.realize(self)
self._context = self.window.cairo_create() ##self._context = self.window.cairo_create()
self._print_context.set_cairo_context(self._context,72,72) ##self._print_context.set_cairo_context(self._context,72,72)
def expose(self, widget, event): ##def expose(self, widget, event):
"""Ask the print operation to actually draw the page.""" ##"""Ask the print operation to actually draw the page."""
self.window.clear() ##self.window.clear()
self._preview_operation.render_page(self._page_no) ##self._preview_operation.render_page(self._page_no)
# need to calculate how large the widget now is and ### need to calculate how large the widget now is and
# set it so that the scrollbars are updated. ### set it so that the scrollbars are updated.
# I can't work out how to do this. ### I can't work out how to do this.
#self.set_size_request(200, 300) ###self.set_size_request(200, 300)
class PreviewWindow(gtk.Window): ##class PreviewWindow(gtk.Window):
"""A dialog to show a print preview.""" ##"""A dialog to show a print preview."""
def __init__(self, ##def __init__(self,
operation, ##operation,
preview_operation, ##preview_operation,
print_context, ##print_context,
parent): ##parent):
gtk.Window.__init__(self) ##gtk.Window.__init__(self)
self.set_default_size(640, 480) ##self.set_default_size(640, 480)
self._operation = operation ##self._operation = operation
self._preview_operation = preview_operation ##self._preview_operation = preview_operation
self.connect("delete_event", self.delete_event) ##self.connect("delete_event", self.delete_event)
self.set_title("Print Preview") ##self.set_title("Print Preview")
self.set_transient_for(parent) ##self.set_transient_for(parent)
# Setup widgets ### Setup widgets
self._vbox = gtk.VBox() ##self._vbox = gtk.VBox()
self.add(self._vbox) ##self.add(self._vbox)
self._spin = gtk.SpinButton() ##self._spin = gtk.SpinButton()
self._spin.set_value(1) ##self._spin.set_value(1)
self._close_bt = gtk.Button(stock=gtk.STOCK_CLOSE) ##self._close_bt = gtk.Button(stock=gtk.STOCK_CLOSE)
self._close_bt.connect("clicked",self.close) ##self._close_bt.connect("clicked",self.close)
self._hbox = gtk.HBox() ##self._hbox = gtk.HBox()
self._hbox.pack_start(self._spin) ##self._hbox.pack_start(self._spin)
self._hbox.pack_start(self._close_bt,expand=False) ##self._hbox.pack_start(self._close_bt,expand=False)
self._vbox.pack_start(self._hbox,expand=False) ##self._vbox.pack_start(self._hbox,expand=False)
self._scroll = gtk.ScrolledWindow(None,None) ##self._scroll = gtk.ScrolledWindow(None,None)
self._canvas = PreviewCanvas(operation,preview_operation,print_context) ##self._canvas = PreviewCanvas(operation,preview_operation,print_context)
self._scroll.add_with_viewport(self._canvas) ##self._scroll.add_with_viewport(self._canvas)
self._vbox.pack_start(self._scroll,expand=True,fill=True) ##self._vbox.pack_start(self._scroll,expand=True,fill=True)
# The print operation does not know how many pages there are until ### The print operation does not know how many pages there are until
# after the first expose event, so we use the expose event to ### after the first expose event, so we use the expose event to
# trigger an update of the spin box. ### trigger an update of the spin box.
# This still does not work properly, sometimes the first expose event ### This still does not work properly, sometimes the first expose event
# happends before this gets connected and the spin box does not get ### happends before this gets connected and the spin box does not get
# updated, I am probably just not doing it very cleverly. ### updated, I am probably just not doing it very cleverly.
self._change_n_pages_connect_id = self._canvas.connect("expose_event", self.change_n_pages) ##self._change_n_pages_connect_id = self._canvas.connect("expose_event", self.change_n_pages)
self._spin.connect("value-changed", ##self._spin.connect("value-changed",
lambda spinbutton: self._canvas.set_page(spinbutton.get_value_as_int())) ##lambda spinbutton: self._canvas.set_page(spinbutton.get_value_as_int()))
self._canvas.set_double_buffered(False) ##self._canvas.set_double_buffered(False)
self.show_all() ##self.show_all()
def change_n_pages(self, widget, event ): ##def change_n_pages(self, widget, event ):
"""Update the spin box to have the correct number of pages for the ##"""Update the spin box to have the correct number of pages for the
print operation""" ##print operation"""
n_pages = self._preview_operation.get_property("n_pages") ##n_pages = self._preview_operation.get_property("n_pages")
if n_pages != -1: ##if n_pages != -1:
# As soon as we have a valid number of pages we no ### As soon as we have a valid number of pages we no
# longer need this call back so we can disconnect it. ### longer need this call back so we can disconnect it.
self._canvas.disconnect(self._change_n_pages_connect_id) ##self._canvas.disconnect(self._change_n_pages_connect_id)
value = int(self._spin.get_value()) ##value = int(self._spin.get_value())
if value == -1: value = 1 ##if value == -1: value = 1
self._spin.configure(gtk.Adjustment(value,1, ##self._spin.configure(gtk.Adjustment(value,1,
n_pages, ##n_pages,
1,1,1),1,0) ##1,1,1),1,0)
def end_preview(self): ##def end_preview(self):
self._operation.end_preview() ##self._operation.end_preview()
def delete_event(self, widget, event, data=None): ##def delete_event(self, widget, event, data=None):
self.end_preview() ##self.end_preview()
return False ##return False
def close(self,btn): ##def close(self,btn):
self.end_preview() ##self.end_preview()
self.destroy() ##self.destroy()
# I am not sure that this is the correct way to do this ### I am not sure that this is the correct way to do this
# but I expect the print dialog to reappear after I ### but I expect the print dialog to reappear after I
# close the print preview button. ### close the print preview button.
self._operation.do_print() ##self._operation.do_print()
return False ##return False
def paperstyle_to_pagesetup(paper_style): def paperstyle_to_pagesetup(paper_style):
"""Convert a BaseDoc.PaperStyle instance into a gtk.PageSetup instance. """Convert a BaseDoc.PaperStyle instance into a gtk.PageSetup instance.
@ -241,13 +240,16 @@ def paperstyle_to_pagesetup(paper_style):
if gramps_to_gtk.has_key(gramps_paper_name): if gramps_to_gtk.has_key(gramps_paper_name):
paper_size = gtk.PaperSize(gramps_to_gtk[gramps_paper_name]) paper_size = gtk.PaperSize(gramps_to_gtk[gramps_paper_name])
elif gramps_paper_name == "Custom Size": elif gramps_paper_name == "Custom Size":
paper_size = gtk.paper_size_new_custom("name", paper_size = gtk.paper_size_new_custom("custom",
"display_name", "Custom Size",
gramps_paper_size.get_width()*10, gramps_paper_size.get_width()*10,
gramps_paper_size.get_height()*10, gramps_paper_size.get_height()*10,
gtk.UNIT_MM) gtk.UNIT_MM)
else: else:
log.error("Unknown paper size") def_paper_size_name = gtk.paper_size_get_default()
paper_size = gtk.PaperSize(def_paper_size_name)
log.debug("Unknown paper size, falling back to the default: %s" %
def_paper_size_name)
page_setup = gtk.PageSetup() page_setup = gtk.PageSetup()
page_setup.set_paper_size(paper_size) page_setup.set_paper_size(paper_size)
@ -259,8 +261,8 @@ def paperstyle_to_pagesetup(paper_style):
page_setup.set_orientation(gtk.PAGE_ORIENTATION_LANDSCAPE) page_setup.set_orientation(gtk.PAGE_ORIENTATION_LANDSCAPE)
# gtk.PageSize provides default margins for the standard papers. # gtk.PageSize provides default margins for the standard papers.
# Anyhow we overwrite those with the settings from Gramps, # Anyhow, we overwrite those with the settings from Gramps,
# though at the moment all are fixed at 1 inch. # though at the moment all of them are fixed at 1 inch.
page_setup.set_top_margin(paper_style.get_top_margin()*10, gtk.UNIT_MM) page_setup.set_top_margin(paper_style.get_top_margin()*10, gtk.UNIT_MM)
page_setup.set_bottom_margin(paper_style.get_bottom_margin()*10, gtk.UNIT_MM) page_setup.set_bottom_margin(paper_style.get_bottom_margin()*10, gtk.UNIT_MM)
page_setup.set_left_margin(paper_style.get_left_margin()*10, gtk.UNIT_MM) page_setup.set_left_margin(paper_style.get_left_margin()*10, gtk.UNIT_MM)
@ -268,204 +270,311 @@ def paperstyle_to_pagesetup(paper_style):
return page_setup return page_setup
class PrintFacade(gtk.PrintOperation): def fontstyle_to_fontdescription(font_style):
"""Provide the main print operation functions.""" """Convert a BaseDoc.FontStyle instance to a pango.FontDescription one.
def __init__(self, renderer, page_setup): Font color and underline is not implemented in pango.FontDescription,
""" and has to be set with pango.Layout.set_attributes(attrlist) method.
@param renderer: the renderer object
@param type: an object like:
class renderer:
def render(operation, context, page_nr)
# renders the page_nr page onto the provided context.
def get_n_pages(operation, context)
# returns the number of pages that would be needed
# to render onto the given context.
@param page_setup: to be used as default page setup
@param type: gtk.PageSetup
"""
gtk.PrintOperation.__init__(self)
self._renderer = renderer
self.set_default_page_setup(page_setup)
self.connect("begin_print", self.on_begin_print)
self.connect("draw_page", self.on_draw_page)
self.connect("paginate", self.on_paginate)
self.connect("preview", self.on_preview)
self._settings = None
self._print_op = None
def on_begin_print(self, operation, context):
"""
The "begin-print" signal is emitted after the user has finished
changing print settings in the dialog, before the actual rendering
starts.
A typical use for this signal is to use the parameters from the
gtk.PrintContext and paginate the document accordingly, and then set
the number of pages with gtk.PrintOperation.set_n_pages().
""" """
operation.set_n_pages(self._renderer.get_n_pages(operation, context)) if font_style.face == BaseDoc.FONT_SERIF:
font_family = 'serif'
elif font_style.face == BaseDoc.FONT_SANS_SERIF:
font_family = 'sans serif'
else:
font_family = 'monospace'
def on_paginate(self, operation, context): if font_style.get_bold():
""" font_weight = pango.WEIGHT_BOLD
else:
font_weight = pango.WEIGHT_NORMAL
The "paginate" signal is emitted after the "begin-print" signal, if font_style.get_italic():
but before the actual rendering starts. It keeps getting emitted until font_style = pango.STYLE_ITALIC
it returns False. else:
font_style = pango.STYLE_NORMAL
This signal is intended to be used for paginating the document in font_description = pango.FontDescription(font_family)
small chunks, to avoid blocking the user interface for a long time. font_description.set_size(font_style.get_size() * pango.SCALE)
The signal handler should update the number of pages using the font_description.set_weight(font_weight)
gtk.PrintOperation.set_n_pages() method, and return True if the font_description.set_style(font_style)
document has been completely paginated.
If you don't need to do pagination in chunks, you can simply do it all return font_description
in the "begin-print" handler, and set the number of pages from there.
""" ##class PrintFacade(gtk.PrintOperation):
return True ##"""Provide the main print operation functions."""
def on_draw_page(self,operation, context, page_nr): ##def __init__(self, renderer, page_setup):
""" ##"""
##@param renderer: the renderer object
##@param type: an object like:
##class renderer:
##def render(operation, context, page_nr)
### renders the page_nr page onto the provided context.
##def get_n_pages(operation, context)
### returns the number of pages that would be needed
### to render onto the given context.
The "draw-page" signal is emitted for every page that is printed. ##@param page_setup: to be used as default page setup
The signal handler must render the page_nr's page onto the cairo ##@param type: gtk.PageSetup
context obtained from context using ##"""
gtk.PrintContext.get_cairo_context(). ##gtk.PrintOperation.__init__(self)
Use the gtk.PrintOperation.set_use_full_page() and ##self._renderer = renderer
gtk.PrintOperation.set_unit() methods before starting the print
operation to set up the transformation of the cairo context according
to your needs.
""" ##self.set_default_page_setup(page_setup)
self._renderer.render(operation, context, page_nr)
def on_preview(self, operation, preview, context, parent, dummy=None): ##self.connect("begin_print", self.on_begin_print)
""" ##self.connect("draw_page", self.on_draw_page)
##self.connect("paginate", self.on_paginate)
###self.connect("preview", self.on_preview)
The "preview" signal is emitted when a preview is requested from the ##self._settings = None
native dialog. If you handle this you must set the cairo context on ##self._print_op = None
the printing context.
If you don't override this, a default implementation using an external ##def on_begin_print(self, operation, context):
viewer will be used. ##"""
""" ##The "begin-print" signal is emitted after the user has finished
preview = PreviewWindow(self,preview,context,parent) ##changing print settings in the dialog, before the actual rendering
return True ##starts.
def do_print(self, widget=None, data=None): ##A typical use for this signal is to use the parameters from the
"""This is the method that actually runs the Gtk Print operation.""" ##gtk.PrintContext and paginate the document accordingly, and then set
##the number of pages with gtk.PrintOperation.set_n_pages().
# We need to store the settings somewhere so that they are remembered ##"""
# each time the dialog is restarted. ##operation.set_n_pages(self._renderer.get_n_pages(operation, context))
if self._settings != None:
self.set_print_settings(self._settings)
res = self.run(gtk.PRINT_OPERATION_ACTION_PRINT_DIALOG, None) ##def on_paginate(self, operation, context):
##"""
if res == gtk.PRINT_OPERATION_RESULT_APPLY: ##The "paginate" signal is emitted after the "begin-print" signal,
self._settings = self.get_print_settings() ##but before the actual rendering starts. It keeps getting emitted until
##it returns False.
##This signal is intended to be used for paginating the document in
##small chunks, to avoid blocking the user interface for a long time.
##The signal handler should update the number of pages using the
##gtk.PrintOperation.set_n_pages() method, and return True if the
##document has been completely paginated.
##If you don't need to do pagination in chunks, you can simply do it all
##in the "begin-print" handler, and set the number of pages from there.
##"""
##return True
##def on_draw_page(self,operation, context, page_nr):
##"""
##The "draw-page" signal is emitted for every page that is printed.
##The signal handler must render the page_nr's page onto the cairo
##context obtained from context using
##gtk.PrintContext.get_cairo_context().
##Use the gtk.PrintOperation.set_use_full_page() and
##gtk.PrintOperation.set_unit() methods before starting the print
##operation to set up the transformation of the cairo context according
##to your needs.
##"""
##self._renderer.render(operation, context, page_nr)
###def on_preview(self, operation, preview, context, parent, dummy=None):
###"""
###The "preview" signal is emitted when a preview is requested from the
###native dialog. If you handle this you must set the cairo context on
###the printing context.
###If you don't override this, a default implementation using an external
###viewer will be used.
###"""
###preview = PreviewWindow(self, preview, context, parent)
###return True
##def do_print(self, widget=None, data=None):
##"""This is the method that actually runs the Gtk Print operation."""
### We need to store the settings somewhere so that they are remembered
### each time the dialog is restarted.
##if self._settings != None:
##self.set_print_settings(self._settings)
##res = self.run(gtk.PRINT_OPERATION_ACTION_PRINT_DIALOG, None)
##if res == gtk.PRINT_OPERATION_RESULT_APPLY:
##self._settings = self.get_print_settings()
#------------------------------------------------------------------------ #------------------------------------------------------------------------
# #
# CairoJob and GtkDoc # Document element classes
#
# These classes to the real work. GtkDoc provides the BaseDoc interface
# and CairoJob performs the job that gnomeprintjob does. It has to
# maintain an abstract model of the document and then render it onto
# a cairo context when asked.
# #
#------------------------------------------------------------------------ #------------------------------------------------------------------------
class CairoJob(object):
"""Act as an abstract document that can render onto a cairo context.""" class GtkDocBaseElement(object):
"""Base of all document elements.
Support document element structuring and can render itself onto
a Cairo surface.
"""
_type = 'BASE'
_allowed_children = None
def __init__(self): def __init__(self):
self._doc = [] self._parent = None
self._children = []
self._style = None
# def get_type(self):
# interface required for PrintFacade """Get the type of this element.
#
def render(self, operation, context, page_nr):
"""Renders the document on the cairo context.
A useful reference is: http://www.tortall.net/mu/wiki/CairoTutorial
""" """
cr = context.get_cairo_context() return self._type
y = 20 def set_parent(self, parent):
x = 30 """Set the parent element of this element.
"""
self._parent = parent
text="\n".join(self._doc) def get_parent(self):
"""Get the parent element of this element.
"""
return self._parent
# Draw some text def add_child(self, element):
layout = context.create_pango_layout() """Add a child element.
layout.set_text(text)
desc = pango.FontDescription("sans 28")
layout.set_font_description(desc)
cr.move_to(x, y) Returns False if the child cannot be added (e.g. not an allowed type),
cr.show_layout(layout) or True otherwise.
"""
# check if it is an allowed child for this type
if element.get_type() not in self._allowed_children:
log.debug("%r is not an allowed child for %r" %
(element.__class__, self.__class__))
return False
def get_n_pages(self, operation, context): # append the child and set it's parent
"""Get the number of pages required to print onto the given context.""" self._children.append(element)
element.set_parent(self)
return True
return 3 def get_children(self):
"""Get the list if children fo this element.
"""
return self._children
# def divide(self, width, height):
# methods to add content to abstract document. """Divide the element into two.
# """
raise NotImplementedError
def write_text(self,text): def draw(self, pages):
self._doc.append(text) """Draw itself onto the received page(s).
Must be implemented in the subclasses.
@param pages: class handling the pages
@param type: CairoPages()
"""
raise NotImplementedError
class GtkDocDocument(GtkDocBaseElement):
"""The whole document.
"""
_type = 'DOCUMENT'
_allowed_children = ['PARAGRAPH', 'PAGEBREAK', 'TABLE', 'MEDIA']
class GtkDocPagebreak(GtkDocBaseElement):
"""Implement a page break.
"""
_type = 'PAGEBREAK'
_allowed_children = None
def divide(self, width, height):
return (None, None), 0
class GtkDocParagraph(GtkDocBaseElement):
"""Paragraph.
"""
_type = 'PARAGRAPH'
_allowed_children = None
def __init__(self, style, text):
GtkDocBaseElement.__init__(self)
self._style = style
self._text = text
if self._text:
self._text = self._text + ' '
def add_text(self, text):
self._text = self._text + text
def divide(self, width, height):
return (self, None), 0
def draw(self, pages):
pass
#------------------------------------------------------------------------ #------------------------------------------------------------------------
# #
# GtkDoc class # CairoDoc and GtkPrint class
# #
#------------------------------------------------------------------------ #------------------------------------------------------------------------
class GtkDoc(BaseDoc.BaseDoc, BaseDoc.TextDoc, BaseDoc.DrawDoc): class CairoDoc(BaseDoc.BaseDoc, BaseDoc.TextDoc, BaseDoc.DrawDoc):
"""Act as an abstract document that can render onto a cairo context.
Maintains an abstract model of the document. The root of this abstract
document is self._doc. The model is build via the subclassed BaseDoc, and
the implemented TextDoc, DrawDoc interface methods.
It can render the model onto cairo context pages, according to the received
page style.
"""
# BaseDoc implementation # BaseDoc implementation
def open(self, filename): def open(self, filename):
self._job = CairoJob() self._doc = GtkDocDocument()
self._active_element = self._doc
self._pages = []
def close(self): def close(self):
pfacade = PrintFacade(self._job, paperstyle_to_pagesetup(self.paper)) raise NotImplementedError
pfacade.do_print()
# TextDoc implementation # TextDoc implementation
def page_break(self): def page_break(self):
pass self._active_element.add_child(GtkDocPagebreak())
def start_bold(self): def start_bold(self):
pass self.write_text('<b>')
def end_bold(self): def end_bold(self):
pass self.write_text('</b>')
def start_superscript(self): def start_superscript(self):
pass self.write_text('<sup>')
def end_superscript(self): def end_superscript(self):
pass self.write_text('</sup>')
def start_paragraph(self, style_name, leader=None): def start_paragraph(self, style_name, leader=''):
pass style_sheet = self.get_style_sheet()
style = style_sheet.get_paragraph_style(style_name)
new_paragraph = GtkDocParagraph(style, leader)
self._active_element.add_child(new_paragraph)
self._active_element = new_paragraph
def end_paragraph(self): def end_paragraph(self):
pass self._active_element = self._active_element.get_parent()
def start_table(self, name, style_name): def start_table(self, name, style_name):
pass pass
@ -487,11 +596,23 @@ class GtkDoc(BaseDoc.BaseDoc, BaseDoc.TextDoc, BaseDoc.DrawDoc):
def write_note(self, text, format, style_name): def write_note(self, text, format, style_name):
log.debug("write_note: %s" % text) log.debug("write_note: %s" % text)
self._job.write_text(text)
if format == 1:
for line in text.split('\n'):
self.start_paragraph(style_name)
self.write_text(line)
self.end_paragraph()
elif format == 0:
for line in text.split('\n\n'):
self.start_paragraph(style_name)
line = line.replace('\n',' ')
line = ' '.join(line.split())
self.write_text(line)
self.end_paragraph()
def write_text(self, text, mark=None): def write_text(self, text, mark=None):
log.debug("write_text: %s" % text) log.debug("write_text: %s" % text)
self._job.write_text(text) self._active_element.add_text(text)
def add_media_object(self, name, pos, x_cm, y_cm): def add_media_object(self, name, pos, x_cm, y_cm):
pass pass
@ -522,11 +643,127 @@ class GtkDoc(BaseDoc.BaseDoc, BaseDoc.TextDoc, BaseDoc.DrawDoc):
def rotate_text(self, style, text, x, y, angle): def rotate_text(self, style, text, x, y, angle):
pass pass
##def center_print(self,lines,font,x,y,w,h): class GtkPrint(CairoDoc):
##pass
##def left_print(self,lines,font,x,y): def close(self):
##pass page_setup = paperstyle_to_pagesetup(self.paper)
print_operation = gtk.PrintOperation()
print_operation.set_default_page_setup(page_setup)
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)
#print_operation.run(gtk.PRINT_OPERATION_ACTION_PRINT_DIALOG, None)
self.print_settings = None
self.do_print(print_operation)
def do_print(self, operation):
"""Run the Gtk Print operation.
"""
# set print settings if it was stored previously
if self.print_settings is not None:
operation.set_print_settings(self.print_settings)
# run print dialog
res = operation.run(gtk.PRINT_OPERATION_ACTION_PRINT_DIALOG, None)
# store print settings if printing was successful
if res == gtk.PRINT_OPERATION_RESULT_APPLY:
self.print_settings = operation.get_print_settings()
def on_begin_print(self, operation, context):
"""Handler for 'begin-print' signal.
The "begin-print" signal is emitted after the user has finished
changing print settings in the dialog, before the actual rendering
starts.
A typical use for this signal is to use the parameters from the
gtk.PrintContext and paginate the document accordingly, and then set
the number of pages with gtk.PrintOperation.set_n_pages().
"""
# set context parameters to pages
self.page_width = context.get_width()
self.page_height = context.get_height()
self.elements_to_paginate = self._doc.get_children()
self._pages.append(GtkDocDocument())
self.available_height = self.page_height
def on_paginate(self, operation, context):
"""Handler for 'paginate' signal.
The "paginate" signal is emitted after the "begin-print" signal,
but before the actual rendering starts. It keeps getting emitted until
it returns False.
This signal is intended to be used for paginating the document in
small chunks, to avoid blocking the user interface for a long time.
The signal handler should update the number of pages using the
gtk.PrintOperation.set_n_pages() method, and return True if the
document has been completely paginated.
If you don't need to do pagination in chunks, you can simply do it all
in the "begin-print" handler, and set the number of pages from there.
"""
# try to fit the next element to current page, divide it if needed
elem = self.elements_to_paginate.pop(0)
(e1, e2), e1_h = elem.divide(self.page_width, self.available_height)
# if (part of) it fits on current page add it
if e1 is not None:
self._pages[len(self._pages) - 1].add_child(e1)
# if elem was divided rememeber the second half to be processed
if e2 is not None:
self.elements_to_paginate.insert(0, e2)
# calculate how much space left on current page
self.available_height -= e1_h
# start new page if needed
if (e1 is None) or (e2 is not None):
self._pages.append(GtkDocDocument())
self.available_height = self.page_height
# update page number
operation.set_n_pages(len(self._pages))
# tell operation whether we finished or not
finished = len(self.elements_to_paginate) == 0
return finished
def on_draw_page(self,operation, context, page_nr):
"""
The "draw-page" signal is emitted for every page that is printed.
The signal handler must render the page_nr's page onto the cairo
context obtained from context using
gtk.PrintContext.get_cairo_context().
Use the gtk.PrintOperation.set_use_full_page() and
gtk.PrintOperation.set_unit() methods before starting the print
operation to set up the transformation of the cairo context according
to your needs.
"""
pass
#def on_preview(self, operation, preview, context, parent, dummy=None):
#"""
#The "preview" signal is emitted when a preview is requested from the
#native dialog. If you handle this you must set the cairo context on
#the printing context.
#If you don't override this, a default implementation using an external
#viewer will be used.
#"""
#preview = PreviewWindow(self, preview, context, parent)
#return True
#------------------------------------------------------------------------ #------------------------------------------------------------------------
@ -534,6 +771,7 @@ class GtkDoc(BaseDoc.BaseDoc, BaseDoc.TextDoc, BaseDoc.DrawDoc):
# Register the document generator with the GRAMPS plugin system # Register the document generator with the GRAMPS plugin system
# #
#------------------------------------------------------------------------ #------------------------------------------------------------------------
register_text_doc(_('GtkPrint'), GtkDoc, 1, 1, 1, "", None) register_text_doc(_('Print... (Gtk+)'), GtkPrint, 1, 1, 1, "", None)
register_draw_doc(_('GtkPrint'), GtkDoc, 1, 1, "", None) ##register_draw_doc(_('GtkPrint'), GtkPrint, 1, 1, "", None)
register_book_doc(_("GtkPrint"), GtkDoc, 1, 1, 1, "", None) ##register_book_doc(_("GtkPrint"), GtkPrint, 1, 1, 1, "", None)
raise Errors.UnavailableError("Work in progress...")