1# Gramps - a GTK+/GNOME based genealogy program
2#
3# Copyright (C) 2001-2007  Donald N. Allingham, Martin Hawlisch
4# Copyright (C) 2009 Douglas S. Blank
5# Copyright (C) 2009-2016 Serge Noiraud
6#
7# This program is free software; you can redistribute it and/or modify
8# it under the terms of the GNU General Public License as published by
9# the Free Software Foundation; either version 2 of the License, or
10# (at your option) any later version.
11#
12# This program is distributed in the hope that it will be useful,
13# but WITHOUT ANY WARRANTY; without even the implied warranty of
14# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
15# GNU General Public License for more details.
16#
17# You should have received a copy of the GNU General Public License
18# along with this program; if not, write to the Free Software
19# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
20
21#-------------------------------------------------------------------------
22#
23# Python modules
24#
25#-------------------------------------------------------------------------
26from gi.repository import Gtk
27
28#-------------------------------------------------------------------------
29#
30# Gramps modules
31#
32#-------------------------------------------------------------------------
33
34# the print settings to remember between print sessions
35PRINT_SETTINGS = None
36
37# pylint: disable=no-member
38# pylint: disable=maybe-no-member
39# pylint: disable=unused-argument
40
41#------------------------------------------------------------------------
42#
43# CairoPrintSave class
44#
45#------------------------------------------------------------------------
46class CairoPrintSave:
47    """
48    Act as an abstract document that can render onto a cairo context.
49
50    It can render the model onto cairo context pages, according to the received
51    page style.
52
53    """
54
55    def __init__(self, widthpx, heightpx, drawfunc, parent):
56        """
57        This class provides the things needed so as to dump a cairo drawing on
58        a context to output
59        """
60        # We try to adapt the cairo dump to an A4 page.
61        widthpx += 30
62        heightpx += 30
63        self.scale = 100.0
64        self.widthpx = widthpx
65        self.heightpx = heightpx
66        self.drawfunc = drawfunc
67        self.parent = parent
68        self.preview = None
69
70    def run(self):
71        """
72        Create the physical output from the meta document.
73
74        """
75        global PRINT_SETTINGS
76
77        # set up a print operation
78        operation = Gtk.PrintOperation()
79        operation.connect("draw_page", self.on_draw_page)
80        operation.connect("preview", self.on_preview)
81        operation.set_n_pages(1)
82        page_setup = Gtk.PageSetup()
83        if PRINT_SETTINGS is None:
84            PRINT_SETTINGS = Gtk.PrintSettings()
85        page_setup = Gtk.print_run_page_setup_dialog(None, page_setup,
86                                                     PRINT_SETTINGS)
87        paper_size_used = page_setup.get_paper_size()
88        if self.widthpx > self.heightpx:
89            szw = self.widthpx
90            szh = self.heightpx
91        else:
92            szh = self.widthpx
93            szw = self.heightpx
94        height_used = paper_size_used.get_height(Gtk.Unit.POINTS)
95        width_used = paper_size_used.get_width(Gtk.Unit.POINTS)
96        coefx = szw / height_used # width and height depends on the selected
97                                  # page (A4, A3, ...)
98        coefy = szh / width_used
99        if coefx < coefy:
100            self.scale = 100.0 / coefy
101        else:
102            self.scale = 100.0 / coefx
103        PRINT_SETTINGS.set_scale(self.scale)
104        if self.widthpx > self.heightpx:
105            page_setup.set_orientation(Gtk.PageOrientation.LANDSCAPE)
106        else:
107            page_setup.set_orientation(Gtk.PageOrientation.PORTRAIT)
108        operation.set_default_page_setup(page_setup)
109
110        if PRINT_SETTINGS is not None:
111            operation.set_print_settings(PRINT_SETTINGS)
112
113        # run print dialog
114        while True:
115            self.preview = None
116            res = operation.run(Gtk.PrintOperationAction.PRINT_DIALOG, None)
117            if self.preview is None: # cancel or print
118                break
119            # set up printing again; can't reuse PrintOperation?
120            operation = Gtk.PrintOperation()
121            operation.set_default_page_setup(page_setup)
122            operation.connect("draw_page", self.on_draw_page)
123            operation.connect("preview", self.on_preview)
124            # set print settings if it was stored previously
125            if PRINT_SETTINGS is not None:
126                operation.set_print_settings(PRINT_SETTINGS)
127
128        # store print settings if printing was successful
129        if res == Gtk.PrintOperationResult.APPLY:
130            PRINT_SETTINGS = operation.get_print_settings()
131
132    def on_draw_page(self, operation, context, page_nr):
133        """Draw a page on a Cairo context.
134        """
135        ctx = context.get_cairo_context()
136        self.drawfunc(self.parent, ctx)
137
138    def on_preview(self, operation, preview, context, parent):
139        """Implement custom print preview functionality.
140           We provide a dummy holder here, because on_preview crashes if no
141           default application is set with gir 3.3.2 (typically evince not
142           installed)!
143        """
144        operation.run(Gtk.PrintOperationAction.PREVIEW, None)
145        return False
146
147