]> Pileus Git - ~andy/gtk/blob - gtk/gtkprintoperation.c
Replace a lot of idle and timeout calls by the new gdk_threads api.
[~andy/gtk] / gtk / gtkprintoperation.c
1 /* GTK - The GIMP Toolkit
2  * gtkprintoperation.c: Print Operation
3  * Copyright (C) 2006, Red Hat, Inc.
4  *
5  * This library is free software; you can redistribute it and/or
6  * modify it under the terms of the GNU Lesser General Public
7  * License as published by the Free Software Foundation; either
8  * version 2 of the License, or (at your option) any later version.
9  *
10  * This library is distributed in the hope that it will be useful,
11  * but WITHOUT ANY WARRANTY; without even the implied warranty of
12  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
13  * Lesser General Public License for more details.
14  *
15  * You should have received a copy of the GNU Lesser General Public
16  * License along with this library; if not, write to the
17  * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
18  * Boston, MA 02111-1307, USA.
19  */
20
21 #include "config.h"
22
23 #include <errno.h>
24 #include <stdlib.h>       
25
26 #include <string.h>
27 #include "gtkprintoperation-private.h"
28 #include "gtkmarshalers.h"
29 #include <cairo-pdf.h>
30 #include "gtkintl.h"
31 #include "gtkprivate.h"
32 #include "gtkmessagedialog.h"
33 #include "gtkalias.h"
34
35 #define SHOW_PROGRESS_TIME 1200
36
37 #define GTK_PRINT_OPERATION_GET_PRIVATE(obj)(G_TYPE_INSTANCE_GET_PRIVATE ((obj), GTK_TYPE_PRINT_OPERATION, GtkPrintOperationPrivate))
38
39 enum 
40 {
41   DONE,
42   BEGIN_PRINT,
43   PAGINATE,
44   REQUEST_PAGE_SETUP,
45   DRAW_PAGE,
46   END_PRINT,
47   STATUS_CHANGED,
48   CREATE_CUSTOM_WIDGET,
49   CUSTOM_WIDGET_APPLY,
50   PREVIEW,
51   LAST_SIGNAL
52 };
53
54 enum 
55 {
56   PROP_0,
57   PROP_DEFAULT_PAGE_SETUP,
58   PROP_PRINT_SETTINGS,
59   PROP_JOB_NAME,
60   PROP_N_PAGES,
61   PROP_CURRENT_PAGE,
62   PROP_USE_FULL_PAGE,
63   PROP_TRACK_PRINT_STATUS,
64   PROP_UNIT,
65   PROP_SHOW_PROGRESS,
66   PROP_ALLOW_ASYNC,
67   PROP_EXPORT_FILENAME,
68   PROP_STATUS,
69   PROP_STATUS_STRING,
70   PROP_CUSTOM_TAB_LABEL
71 };
72
73 static guint signals[LAST_SIGNAL] = { 0 };
74 static int job_nr = 0;
75
76 static void          preview_iface_init (GtkPrintOperationPreviewIface *iface);
77 static GtkPageSetup *create_page_setup  (GtkPrintOperation             *op);
78 static void          common_render_page (GtkPrintOperation             *op,
79                                          gint                           page_nr);
80
81
82 G_DEFINE_TYPE_WITH_CODE (GtkPrintOperation, gtk_print_operation, G_TYPE_OBJECT,
83                          G_IMPLEMENT_INTERFACE (GTK_TYPE_PRINT_OPERATION_PREVIEW,
84                                                 preview_iface_init))
85
86 /**
87  * gtk_print_error_quark:
88  *
89  * Registers an error quark for #GtkPrintOperation if necessary.
90  * 
91  * Return value: The error quark used for #GtkPrintOperation errors.
92  *
93  * Since: 2.10
94  **/
95 GQuark     
96 gtk_print_error_quark (void)
97 {
98   static GQuark quark = 0;
99   if (quark == 0)
100     quark = g_quark_from_static_string ("gtk-print-error-quark");
101   return quark;
102 }
103      
104 static void
105 gtk_print_operation_finalize (GObject *object)
106 {
107   GtkPrintOperation *print_operation = GTK_PRINT_OPERATION (object);
108   GtkPrintOperationPrivate *priv = print_operation->priv;
109
110   if (priv->free_platform_data &&
111       priv->platform_data)
112     {
113       priv->free_platform_data (priv->platform_data);
114       priv->free_platform_data = NULL;
115     }
116
117   if (priv->default_page_setup)
118     g_object_unref (priv->default_page_setup);
119   
120   if (priv->print_settings)
121     g_object_unref (priv->print_settings);
122   
123   g_free (priv->export_filename);
124   g_free (priv->job_name);
125   g_free (priv->custom_tab_label);
126
127   if (priv->print_pages_idle_id > 0)
128     g_source_remove (priv->print_pages_idle_id);
129
130   if (priv->show_progress_timeout_id > 0)
131     g_source_remove (priv->show_progress_timeout_id);
132
133   if (priv->error)
134     g_error_free (priv->error);
135   
136   G_OBJECT_CLASS (gtk_print_operation_parent_class)->finalize (object);
137 }
138
139 static void
140 gtk_print_operation_init (GtkPrintOperation *operation)
141 {
142   GtkPrintOperationPrivate *priv;
143   const char *appname;
144
145   priv = operation->priv = GTK_PRINT_OPERATION_GET_PRIVATE (operation);
146
147   priv->status = GTK_PRINT_STATUS_INITIAL;
148   priv->status_string = g_strdup ("");
149   priv->default_page_setup = NULL;
150   priv->print_settings = NULL;
151   priv->nr_of_pages = -1;
152   priv->current_page = -1;
153   priv->use_full_page = FALSE;
154   priv->show_progress = FALSE;
155   priv->export_filename = NULL;
156   priv->track_print_status = FALSE;
157   priv->is_sync = FALSE;
158
159   priv->rloop = NULL;
160   priv->unit = GTK_UNIT_PIXEL;
161
162   appname = g_get_application_name ();
163   priv->job_name = g_strdup_printf ("%s job #%d", appname, ++job_nr);
164 }
165
166 static void
167 preview_iface_render_page (GtkPrintOperationPreview *preview,
168                            gint                      page_nr)
169 {
170
171   GtkPrintOperation *op;
172
173   op = GTK_PRINT_OPERATION (preview);
174   common_render_page (op, page_nr);
175 }
176
177 static void
178 preview_iface_end_preview (GtkPrintOperationPreview *preview)
179 {
180   GtkPrintOperation *op;
181   
182   op = GTK_PRINT_OPERATION (preview);
183
184   g_signal_emit (op, signals[END_PRINT], 0, op->priv->print_context);
185
186   if (op->priv->rloop)
187     g_main_loop_quit (op->priv->rloop);
188
189   op->priv->end_run (op, op->priv->is_sync, TRUE);
190   
191   g_signal_emit (op, signals[DONE], 0,
192                  GTK_PRINT_OPERATION_RESULT_APPLY);
193 }
194
195 static gboolean
196 preview_iface_is_selected (GtkPrintOperationPreview *preview,
197                            gint                      page_nr)
198 {
199   GtkPrintOperation *op;
200   GtkPrintOperationPrivate *priv;
201   int i;
202   
203   op = GTK_PRINT_OPERATION (preview);
204   priv = op->priv;
205   
206   switch (priv->print_pages)
207     {
208     case GTK_PRINT_PAGES_ALL:
209       return (page_nr >= 0) && (page_nr < priv->nr_of_pages);
210     case GTK_PRINT_PAGES_CURRENT:
211       return page_nr == priv->current_page;
212     case GTK_PRINT_PAGES_RANGES:
213       for (i = 0; i < priv->num_page_ranges; i++)
214         {
215           if (page_nr >= priv->page_ranges[i].start &&
216               page_nr <= priv->page_ranges[i].end)
217             return TRUE;
218         }
219       return FALSE;
220     }
221   return FALSE;
222 }
223
224 static void
225 preview_iface_init (GtkPrintOperationPreviewIface *iface)
226 {
227   iface->render_page = preview_iface_render_page;
228   iface->end_preview = preview_iface_end_preview;
229   iface->is_selected = preview_iface_is_selected;
230 }
231
232 static void
233 preview_start_page (GtkPrintOperation *op,
234                     GtkPrintContext   *print_context,
235                     GtkPageSetup      *page_setup)
236 {
237   g_signal_emit_by_name (op, "got-page-size", print_context, page_setup);
238 }
239
240 static void
241 preview_end_page (GtkPrintOperation *op,
242                   GtkPrintContext   *print_context)
243 {
244 }
245
246 static void
247 preview_end_run (GtkPrintOperation *op,
248                  gboolean           wait,
249                  gboolean           cancelled)
250 {
251   g_free (op->priv->page_ranges);
252   op->priv->page_ranges = NULL;
253
254   _gtk_print_operation_set_status (op, GTK_PRINT_STATUS_FINISHED, NULL);
255 }
256
257
258 static void
259 gtk_print_operation_set_property (GObject      *object,
260                                   guint         prop_id,
261                                   const GValue *value,
262                                   GParamSpec   *pspec)
263 {
264   GtkPrintOperation *op = GTK_PRINT_OPERATION (object);
265   
266   switch (prop_id)
267     {
268     case PROP_DEFAULT_PAGE_SETUP:
269       gtk_print_operation_set_default_page_setup (op, g_value_get_object (value));
270       break;
271     case PROP_PRINT_SETTINGS:
272       gtk_print_operation_set_print_settings (op, g_value_get_object (value));
273       break;
274     case PROP_JOB_NAME:
275       gtk_print_operation_set_job_name (op, g_value_get_string (value));
276       break;
277     case PROP_N_PAGES:
278       gtk_print_operation_set_n_pages (op, g_value_get_int (value));
279       break;
280     case PROP_CURRENT_PAGE:
281       gtk_print_operation_set_current_page (op, g_value_get_int (value));
282       break;
283     case PROP_USE_FULL_PAGE:
284       gtk_print_operation_set_use_full_page (op, g_value_get_boolean (value));
285       break;
286     case PROP_TRACK_PRINT_STATUS:
287       gtk_print_operation_set_track_print_status (op, g_value_get_boolean (value));
288       break;
289     case PROP_UNIT:
290       gtk_print_operation_set_unit (op, g_value_get_enum (value));
291       break;
292     case PROP_ALLOW_ASYNC:
293       gtk_print_operation_set_allow_async (op, g_value_get_boolean (value));
294       break;
295     case PROP_SHOW_PROGRESS:
296       gtk_print_operation_set_show_progress (op, g_value_get_boolean (value));
297       break;
298     case PROP_EXPORT_FILENAME:
299       gtk_print_operation_set_export_filename (op, g_value_get_string (value));
300       break;
301     case PROP_CUSTOM_TAB_LABEL:
302       gtk_print_operation_set_custom_tab_label (op, g_value_get_string (value));
303       break;
304     default:
305       G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
306       break;
307     }
308 }
309
310 static void
311 gtk_print_operation_get_property (GObject    *object,
312                                   guint       prop_id,
313                                   GValue     *value,
314                                   GParamSpec *pspec)
315 {
316   GtkPrintOperation *op = GTK_PRINT_OPERATION (object);
317   GtkPrintOperationPrivate *priv = op->priv;
318
319   switch (prop_id)
320     {
321     case PROP_DEFAULT_PAGE_SETUP:
322       g_value_set_object (value, priv->default_page_setup);
323       break;
324     case PROP_PRINT_SETTINGS:
325       g_value_set_object (value, priv->print_settings);
326       break;
327     case PROP_JOB_NAME:
328       g_value_set_string (value, priv->job_name);
329       break;
330     case PROP_N_PAGES:
331       g_value_set_int (value, priv->nr_of_pages);
332       break;
333     case PROP_CURRENT_PAGE:
334       g_value_set_int (value, priv->current_page);
335       break;      
336     case PROP_USE_FULL_PAGE:
337       g_value_set_boolean (value, priv->use_full_page);
338       break;
339     case PROP_TRACK_PRINT_STATUS:
340       g_value_set_boolean (value, priv->track_print_status);
341       break;
342     case PROP_UNIT:
343       g_value_set_enum (value, priv->unit);
344       break;
345     case PROP_ALLOW_ASYNC:
346       g_value_set_boolean (value, priv->allow_async);
347       break;
348     case PROP_SHOW_PROGRESS:
349       g_value_set_boolean (value, priv->show_progress);
350       break;
351     case PROP_EXPORT_FILENAME:
352       g_value_set_string (value, priv->export_filename);
353       break;
354     case PROP_STATUS:
355       g_value_set_enum (value, priv->status);
356       break;
357     case PROP_STATUS_STRING:
358       g_value_set_string (value, priv->status_string);
359       break;
360     case PROP_CUSTOM_TAB_LABEL:
361       g_value_set_string (value, priv->custom_tab_label);
362       break;
363     default:
364       G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
365       break;
366     }
367 }
368
369 typedef struct
370 {
371   GtkPrintOperationPreview *preview;
372   GtkPrintContext *print_context;
373   GtkWindow *parent;
374   cairo_surface_t *surface;
375   gchar *filename;
376   guint page_nr;
377   gboolean wait;
378 } PreviewOp;
379
380 static void
381 preview_print_idle_done (gpointer data)
382 {
383   GtkPrintOperation *op;
384   PreviewOp *pop = (PreviewOp *) data;
385
386   op = GTK_PRINT_OPERATION (pop->preview);
387
388   cairo_surface_finish (pop->surface);
389   /* Surface is destroyed in launch_preview */
390   _gtk_print_operation_platform_backend_launch_preview (op,
391                                                         pop->surface,
392                                                         pop->parent,
393                                                         pop->filename);
394
395   g_free (pop->filename);
396
397   gtk_print_operation_preview_end_preview (pop->preview);
398   g_free (pop);
399 }
400
401 static gboolean
402 preview_print_idle (gpointer data)
403 {
404   PreviewOp *pop;
405   GtkPrintOperation *op;
406   gboolean retval = TRUE;
407   cairo_t *cr;
408
409   pop = (PreviewOp *) data;
410   op = GTK_PRINT_OPERATION (pop->preview);
411
412   gtk_print_operation_preview_render_page (pop->preview, pop->page_nr);
413   
414   cr = gtk_print_context_get_cairo_context (pop->print_context);
415   _gtk_print_operation_platform_backend_preview_end_page (op, pop->surface, cr);
416   
417   /* TODO: print out sheets not pages and follow ranges */
418   pop->page_nr++;
419   if (op->priv->nr_of_pages <= pop->page_nr)
420     retval = FALSE;
421
422   return retval;
423 }
424
425 static void
426 preview_got_page_size (GtkPrintOperationPreview *preview, 
427                        GtkPrintContext          *context,
428                        GtkPageSetup             *page_setup,
429                        PreviewOp                *pop)
430 {
431   GtkPrintOperation *op = GTK_PRINT_OPERATION (preview);
432   cairo_t *cr;
433
434   _gtk_print_operation_platform_backend_resize_preview_surface (op, page_setup, pop->surface);
435
436   cr = gtk_print_context_get_cairo_context (pop->print_context);
437   _gtk_print_operation_platform_backend_preview_start_page (op, pop->surface, cr);
438
439 }
440
441 static void
442 preview_ready (GtkPrintOperationPreview *preview,
443                GtkPrintContext          *context,
444                PreviewOp                *pop)
445 {
446   pop->page_nr = 0;
447   pop->print_context = context;
448
449   gdk_threads_add_idle_full (G_PRIORITY_DEFAULT_IDLE + 10,
450                              preview_print_idle,
451                              pop,
452                              preview_print_idle_done);
453 }
454
455
456 static gboolean
457 gtk_print_operation_preview_handler (GtkPrintOperation        *op,
458                                      GtkPrintOperationPreview *preview, 
459                                      GtkPrintContext          *context,
460                                      GtkWindow                *parent)
461 {
462   gdouble dpi_x, dpi_y;
463   PreviewOp *pop;
464   GtkPageSetup *page_setup;
465   cairo_t *cr;
466
467   pop = g_new0 (PreviewOp, 1);
468   pop->filename = NULL;
469   pop->preview = preview;
470   pop->parent = parent;
471
472   page_setup = gtk_print_context_get_page_setup (context);
473
474   pop->surface =
475     _gtk_print_operation_platform_backend_create_preview_surface (op,
476                                                                   page_setup,
477                                                                   &dpi_x, &dpi_y,
478                                                                   &pop->filename);
479
480   cr = cairo_create (pop->surface);
481   gtk_print_context_set_cairo_context (op->priv->print_context, cr,
482                                        dpi_x, dpi_y);
483   cairo_destroy (cr);
484
485   g_signal_connect (preview, "ready", (GCallback) preview_ready, pop);
486   g_signal_connect (preview, "got-page-size", (GCallback) preview_got_page_size, pop);
487   
488   return TRUE;
489 }
490
491 static GtkWidget *
492 gtk_print_operation_create_custom_widget (GtkPrintOperation *operation)
493 {
494   return NULL;
495 }
496
497 static gboolean
498 custom_widget_accumulator (GSignalInvocationHint *ihint,
499                            GValue                *return_accu,
500                            const GValue          *handler_return,
501                            gpointer               dummy)
502 {
503   gboolean continue_emission;
504   GtkWidget *widget;
505   
506   widget = g_value_get_object (handler_return);
507   if (widget != NULL)
508     g_value_set_object (return_accu, widget);
509   continue_emission = (widget == NULL);
510   
511   return continue_emission;
512 }
513
514 static void
515 gtk_print_operation_class_init (GtkPrintOperationClass *class)
516 {
517   GObjectClass *gobject_class = (GObjectClass *)class;
518
519   gobject_class->set_property = gtk_print_operation_set_property;
520   gobject_class->get_property = gtk_print_operation_get_property;
521   gobject_class->finalize = gtk_print_operation_finalize;
522  
523   class->preview = gtk_print_operation_preview_handler; 
524   class->create_custom_widget = gtk_print_operation_create_custom_widget;
525   
526   g_type_class_add_private (gobject_class, sizeof (GtkPrintOperationPrivate));
527
528   /**
529    * GtkPrintOperation::done:
530    * @operation: the #GtkPrintOperation on which the signal was emitted
531    * @result: the result of the print operation
532    *
533    * Emitted when the print operation run has finished doing
534    * everything required for printing. @result gives you information
535    * about what happened during the run. If @result is
536    * %GTK_PRINT_OPERATION_RESULT_ERROR then you can call
537    * gtk_print_operation_get_error() for more information.
538    *
539    * If you enabled print status tracking then 
540    * gtk_print_operation_is_finished() may still return %FALSE 
541    * after this was emitted.
542    *
543    * Since: 2.10
544    */
545   signals[DONE] =
546     g_signal_new (I_("done"),
547                   G_TYPE_FROM_CLASS (gobject_class),
548                   G_SIGNAL_RUN_LAST,
549                   G_STRUCT_OFFSET (GtkPrintOperationClass, done),
550                   NULL, NULL,
551                   g_cclosure_marshal_VOID__ENUM,
552                   G_TYPE_NONE, 1, GTK_TYPE_PRINT_OPERATION_RESULT);
553
554   /**
555    * GtkPrintOperation::begin-print:
556    * @operation: the #GtkPrintOperation on which the signal was emitted
557    * @context: the #GtkPrintContext for the current operation
558    *
559    * Emitted after the user has finished changing print settings
560    * in the dialog, before the actual rendering starts. 
561    *
562    * A typical use for this signal is to use the parameters from the
563    * #GtkPrintContext and paginate the document accordingly, and then
564    * set the number of pages with gtk_print_operation_set_n_pages().
565    *
566    * Since: 2.10
567    */
568   signals[BEGIN_PRINT] =
569     g_signal_new (I_("begin-print"),
570                   G_TYPE_FROM_CLASS (gobject_class),
571                   G_SIGNAL_RUN_LAST,
572                   G_STRUCT_OFFSET (GtkPrintOperationClass, begin_print),
573                   NULL, NULL,
574                   g_cclosure_marshal_VOID__OBJECT,
575                   G_TYPE_NONE, 1, GTK_TYPE_PRINT_CONTEXT);
576
577    /**
578    * GtkPrintOperation::paginate:
579    * @operation: the #GtkPrintOperation on which the signal was emitted
580    * @context: the #GtkPrintContext for the current operation
581    *
582    * Emitted after the begin-print signal, but before the actual 
583    * rendering starts. It keeps getting emitted until it returns %FALSE. 
584    *
585    * This signal is intended to be used for paginating the document
586    * in small chunks, to avoid blocking the user interface for a long
587    * time. The signal handler should update the number of pages using
588    * gtk_print_operation_set_n_pages(), and return %TRUE if the document
589    * has been completely paginated.
590    *
591    * If you don't need to do pagination in chunks, you can simply do
592    * it all in the begin-print handler, and set the number of pages
593    * from there.
594    *
595    * Return value: %TRUE if pagination is complete
596    *
597    * Since: 2.10
598    */
599   signals[PAGINATE] =
600     g_signal_new (I_("paginate"),
601                   G_TYPE_FROM_CLASS (gobject_class),
602                   G_SIGNAL_RUN_LAST,
603                   G_STRUCT_OFFSET (GtkPrintOperationClass, paginate),
604                   _gtk_boolean_handled_accumulator, NULL,
605                   _gtk_marshal_BOOLEAN__OBJECT,
606                   G_TYPE_BOOLEAN, 1, GTK_TYPE_PRINT_CONTEXT);
607
608
609   /**
610    * GtkPrintOperation::request-page-setup:
611    * @operation: the #GtkPrintOperation on which the signal was emitted
612    * @context: the #GtkPrintContext for the current operation
613    * @page_nr: the number of the currently printed page
614    * @setup: the #GtkPageSetup 
615    * 
616    * Emitted once for every page that is printed, to give
617    * the application a chance to modify the page setup. Any changes 
618    * done to @setup will be in force only for printing this page.
619    *
620    * Since: 2.10
621    */
622   signals[REQUEST_PAGE_SETUP] =
623     g_signal_new (I_("request-page-setup"),
624                   G_TYPE_FROM_CLASS (gobject_class),
625                   G_SIGNAL_RUN_LAST,
626                   G_STRUCT_OFFSET (GtkPrintOperationClass, request_page_setup),
627                   NULL, NULL,
628                   _gtk_marshal_VOID__OBJECT_INT_OBJECT,
629                   G_TYPE_NONE, 3,
630                   GTK_TYPE_PRINT_CONTEXT,
631                   G_TYPE_INT,
632                   GTK_TYPE_PAGE_SETUP);
633
634   /**
635    * GtkPrintOperation::draw-page:
636    * @operation: the #GtkPrintOperation on which the signal was emitted
637    * @context: the #GtkPrintContext for the current operation
638    * @page_nr: the number of the currently printed page
639    *
640    * Emitted for every page that is printed. The signal handler
641    * must render the @page_nr's page onto the cairo context obtained
642    * from @context using gtk_print_context_get_cairo_context().
643    *
644    * <informalexample><programlisting>
645    * static void
646    * draw_page (GtkPrintOperation *operation,
647    *            GtkPrintContext   *context,
648    *            gint               page_nr,
649    *            gpointer           user_data)
650    * {
651    *   cairo_t *cr;
652    *   PangoLayout *layout;
653    *   gdouble width, text_height;
654    *   gint layout_height;
655    *   PangoFontDescription *desc;
656    *   
657    *   cr = gtk_print_context_get_cairo_context (context);
658    *   width = gtk_print_context_get_width (context);
659    *   
660    *   cairo_rectangle (cr, 0, 0, width, HEADER_HEIGHT);
661    *   
662    *   cairo_set_source_rgb (cr, 0.8, 0.8, 0.8);
663    *   cairo_fill (cr);
664    *   
665    *   layout = gtk_print_context_create_pango_layout (context);
666    *   
667    *   desc = pango_font_description_from_string ("sans 14");
668    *   pango_layout_set_font_description (layout, desc);
669    *   pango_font_description_free (desc);
670    *   
671    *   pango_layout_set_text (layout, "some text", -1);
672    *   pango_layout_set_width (layout, width);
673    *   pango_layout_set_alignment (layout, PANGO_ALIGN_CENTER);
674    *                          
675    *   pango_layout_get_size (layout, NULL, &amp;layout_height);
676    *   text_height = (gdouble)layout_height / PANGO_SCALE;
677    *   
678    *   cairo_move_to (cr, width / 2,  (HEADER_HEIGHT - text_height) / 2);
679    *   pango_cairo_show_layout (cr, layout);
680    *   
681    *   g_object_unref (layout);
682    * }
683    * </programlisting></informalexample>
684    *
685    * Use gtk_print_operation_set_use_full_page() and 
686    * gtk_print_operation_set_unit() before starting the print operation
687    * to set up the transformation of the cairo context according to your
688    * needs.
689    * 
690    * Since: 2.10
691    */
692   signals[DRAW_PAGE] =
693     g_signal_new (I_("draw-page"),
694                   G_TYPE_FROM_CLASS (gobject_class),
695                   G_SIGNAL_RUN_LAST,
696                   G_STRUCT_OFFSET (GtkPrintOperationClass, draw_page),
697                   NULL, NULL,
698                   _gtk_marshal_VOID__OBJECT_INT,
699                   G_TYPE_NONE, 2,
700                   GTK_TYPE_PRINT_CONTEXT,
701                   G_TYPE_INT);
702
703   /**
704    * GtkPrintOperation::end-print:
705    * @operation: the #GtkPrintOperation on which the signal was emitted
706    * @context: the #GtkPrintContext for the current operation
707    *
708    * Emitted after all pages have been rendered. 
709    * A handler for this signal can clean up any resources that have
710    * been allocated in the ::begin-print handler.
711    * 
712    * Since: 2.10
713    */
714   signals[END_PRINT] =
715     g_signal_new (I_("end-print"),
716                   G_TYPE_FROM_CLASS (gobject_class),
717                   G_SIGNAL_RUN_LAST,
718                   G_STRUCT_OFFSET (GtkPrintOperationClass, end_print),
719                   NULL, NULL,
720                   g_cclosure_marshal_VOID__OBJECT,
721                   G_TYPE_NONE, 1, GTK_TYPE_PRINT_CONTEXT);
722
723   /**
724    * GtkPrintOperation::status-changed:
725    * @operation: the #GtkPrintOperation on which the signal was emitted
726    *
727    * Emitted at between the various phases of the print operation.
728    * See #GtkPrintStatus for the phases that are being discriminated.
729    * Use gtk_print_operation_get_status() to find out the current
730    * status.
731    *
732    * Since: 2.10
733    */
734   signals[STATUS_CHANGED] =
735     g_signal_new (I_("status-changed"),
736                   G_TYPE_FROM_CLASS (class),
737                   G_SIGNAL_RUN_LAST,
738                   G_STRUCT_OFFSET (GtkPrintOperationClass, status_changed),
739                   NULL, NULL,
740                   g_cclosure_marshal_VOID__VOID,
741                   G_TYPE_NONE, 0);
742
743
744   /**
745    * GtkPrintOperation::create-custom-widget:
746    * @operation: the #GtkPrintOperation on which the signal was emitted
747    *
748    * Emitted when displaying the print dialog. If you return a
749    * widget in a handler for this signal it will be added to a custom
750    * tab in the print dialog. You typically return a container widget
751    * with multiple widgets in it.
752    *
753    * The print dialog owns the returned widget, and its lifetime
754    * isn't controlled by the app. However, the widget is guaranteed
755    * to stay around until the custom-widget-apply signal is emitted
756    * on the operation. Then you can read out any information you need
757    * from the widgets.
758    *
759    * Returns: A custom widget that gets embedded in the print dialog,
760    *          or %NULL
761    *
762    * Since: 2.10
763    */
764   signals[CREATE_CUSTOM_WIDGET] =
765     g_signal_new (I_("create-custom-widget"),
766                   G_TYPE_FROM_CLASS (class),
767                   G_SIGNAL_RUN_LAST,
768                   G_STRUCT_OFFSET (GtkPrintOperationClass, create_custom_widget),
769                   custom_widget_accumulator, NULL,
770                   _gtk_marshal_OBJECT__VOID,
771                   G_TYPE_OBJECT, 0);
772
773   /**
774    * GtkPrintOperation::custom-widget-apply:
775    * @operation: the #GtkPrintOperation on which the signal was emitted
776    * @widget: the custom widget added in create-custom-widget
777    *
778    * Emitted right before begin-print if you added
779    * a custom widget in the create-custom-widget handler. When you get
780    * this signal you should read the information from the custom widgets,
781    * as the widgets are not guaraneed to be around at a later time.
782    *
783    * Since: 2.10
784    */
785   signals[CUSTOM_WIDGET_APPLY] =
786     g_signal_new (I_("custom-widget-apply"),
787                   G_TYPE_FROM_CLASS (class),
788                   G_SIGNAL_RUN_LAST,
789                   G_STRUCT_OFFSET (GtkPrintOperationClass, custom_widget_apply),
790                   NULL, NULL,
791                   g_cclosure_marshal_VOID__OBJECT,
792                   G_TYPE_NONE, 1, GTK_TYPE_WIDGET);
793
794    /**
795    * GtkPrintOperation::preview:
796    * @operation: the #GtkPrintOperation on which the signal was emitted
797    * @preview: the #GtkPrintPreviewOperation for the current operation
798    * @context: the #GtkPrintContext that will be used
799    * @parent: the #GtkWindow to use as window parent, or %NULL
800    *
801    * Gets emitted when a preview is requested from the native dialog.
802    *
803    * The default handler for this signal uses an external viewer 
804    * application to preview.
805    *
806    * To implement a custom print preview, an application must return
807    * %TRUE from its handler for this signal. In order to use the
808    * provided @context for the preview implementation, it must be
809    * given a suitable cairo context with gtk_print_context_set_cairo_context().
810    * 
811    * The custom preview implementation can use 
812    * gtk_print_operation_preview_is_selected() and 
813    * gtk_print_operation_preview_render_page() to find pages which
814    * are selected for print and render them. The preview must be
815    * finished by calling gtk_print_operation_preview_end_preview()
816    * (typically in response to the user clicking a close button).
817    *
818    * Returns: %TRUE if the listener wants to take over control of the preview
819    * 
820    * Since: 2.10
821    */
822   signals[PREVIEW] =
823     g_signal_new (I_("preview"),
824                   G_TYPE_FROM_CLASS (gobject_class),
825                   G_SIGNAL_RUN_LAST,
826                   G_STRUCT_OFFSET (GtkPrintOperationClass, preview),
827                   _gtk_boolean_handled_accumulator, NULL,
828                   _gtk_marshal_BOOLEAN__OBJECT_OBJECT_OBJECT,
829                   G_TYPE_BOOLEAN, 3,
830                   GTK_TYPE_PRINT_OPERATION_PREVIEW,
831                   GTK_TYPE_PRINT_CONTEXT,
832                   GTK_TYPE_WINDOW);
833
834   
835   /**
836    * GtkPrintOperation:default-page-setup:
837    *
838    * The #GtkPageSetup used by default.
839    * 
840    * This page setup will be used by gtk_print_operation_run(),
841    * but it can be overridden on a per-page basis by connecting
842    * to the ::request-page-setup signal.
843    *
844    * Since: 2.10
845    */
846   g_object_class_install_property (gobject_class,
847                                    PROP_DEFAULT_PAGE_SETUP,
848                                    g_param_spec_object ("default-page-setup",
849                                                         P_("Default Page Setup"),
850                                                         P_("The GtkPageSetup used by default"),
851                                                         GTK_TYPE_PAGE_SETUP,
852                                                         GTK_PARAM_READWRITE));
853
854   /**
855    * GtkPrintOperation:print-settings:
856    *
857    * The #GtkPrintSettings used for initializing the dialog.
858    *
859    * Setting this property is typically used to re-establish 
860    * print settings from a previous print operation, see 
861    * gtk_print_operation_run().
862    *
863    * Since: 2.10
864    */
865   g_object_class_install_property (gobject_class,
866                                    PROP_PRINT_SETTINGS,
867                                    g_param_spec_object ("print-settings",
868                                                         P_("Print Settings"),
869                                                         P_("The GtkPrintSettings used for initializing the dialog"),
870                                                         GTK_TYPE_PRINT_SETTINGS,
871                                                         GTK_PARAM_READWRITE));
872   
873   /**
874    * GtkPrintOperation:job-name:
875    *
876    * A string used to identify the job (e.g. in monitoring 
877    * applications like eggcups). 
878    * 
879    * If you don't set a job name, GTK+ picks a default one 
880    * by numbering successive print jobs.
881    *
882    * Since: 2.10
883    */
884   g_object_class_install_property (gobject_class,
885                                    PROP_JOB_NAME,
886                                    g_param_spec_string ("job-name",
887                                                         P_("Job Name"),
888                                                         P_("A string used for identifying the print job."),
889                                                         "",
890                                                         GTK_PARAM_READWRITE));
891
892   /**
893    * GtkPrintOperation:n-pages:
894    *
895    * The number of pages in the document. 
896    *
897    * This <emphasis>must</emphasis> be set to a positive number
898    * before the rendering starts. It may be set in a ::begin-print 
899    * signal hander.
900    *
901    * Note that the page numbers passed to the ::request-page-setup 
902    * and ::draw-page signals are 0-based, i.e. if the user chooses 
903    * to print all pages, the last ::draw-page signal will be for 
904    * page @n_pages - 1.
905    *
906    * Since: 2.10
907    */
908   g_object_class_install_property (gobject_class,
909                                    PROP_N_PAGES,
910                                    g_param_spec_int ("n-pages",
911                                                      P_("Number of Pages"),
912                                                      P_("The number of pages in the document."),
913                                                      -1,
914                                                      G_MAXINT,
915                                                      -1,
916                                                      GTK_PARAM_READWRITE));
917
918   /**
919    * GtkPrintOperation:current-page:
920    *
921    * The current page in the document.
922    *
923    * If this is set before gtk_print_operation_run(), 
924    * the user will be able to select to print only the current page.
925    *
926    * Note that this only makes sense for pre-paginated documents.
927    *
928    * Since: 2.10
929    */
930   g_object_class_install_property (gobject_class,
931                                    PROP_CURRENT_PAGE,
932                                    g_param_spec_int ("current-page",
933                                                      P_("Current Page"),
934                                                      P_("The current page in the document"),
935                                                      -1,
936                                                      G_MAXINT,
937                                                      -1,
938                                                      GTK_PARAM_READWRITE));
939   
940   /**
941    * GtkPrintOperation:use-full-page:
942    *
943    * If %TRUE, the transformation for the cairo context obtained 
944    * from #GtkPrintContext puts the origin at the top left corner 
945    * of the page (which may not be the top left corner of the sheet, 
946    * depending on page orientation and the number of pages per sheet). 
947    * Otherwise, the origin is at the top left corner of the imageable 
948    * area (i.e. inside the margins).
949    * 
950    * Since: 2.10
951    */
952   g_object_class_install_property (gobject_class,
953                                    PROP_USE_FULL_PAGE,
954                                    g_param_spec_boolean ("use-full-page",
955                                                          P_("Use full page"),
956                                                          P_("TRUE if the origin of the context should be at the corner of the page and not the corner of the imageable area"),
957                                                          FALSE,
958                                                          GTK_PARAM_READWRITE));
959   
960
961   /**
962    * GtkPrintOperation:track-print-status:
963    *
964    * If %TRUE, the print operation will try to continue report on 
965    * the status of the print job in the printer queues and printer. 
966    * This can allow your application to show things like "out of paper" 
967    * issues, and when the print job actually reaches the printer. 
968    * However, this is often implemented using polling, and should 
969    * not be enabled unless needed.
970    * 
971    * Since: 2.10
972    */
973   g_object_class_install_property (gobject_class,
974                                    PROP_TRACK_PRINT_STATUS,
975                                    g_param_spec_boolean ("track-print-status",
976                                                          P_("Track Print Status"),
977                                                          P_("TRUE if the print operation will continue to report on the print job status after the print data has been sent to the printer or print server."),
978                                                          FALSE,
979                                                          GTK_PARAM_READWRITE));
980   
981
982   /**
983    * GtkPrintOperation:unit:
984    *
985    * The transformation for the cairo context obtained from
986    * #GtkPrintContext is set up in such a way that distances 
987    * are measured in units of @unit.
988    *
989    * Since: 2.10
990    */
991   g_object_class_install_property (gobject_class,
992                                    PROP_UNIT,
993                                    g_param_spec_enum ("unit",
994                                                       P_("Unit"),
995                                                       P_("The unit in which distances can be measured in the context"),
996                                                       GTK_TYPE_UNIT,
997                                                       GTK_UNIT_PIXEL,
998                                                       GTK_PARAM_READWRITE));
999   
1000   
1001   /**
1002    * GtkPrintOperation:show-progress:
1003    *
1004    * Determines whether to show a progress dialog during the 
1005    * print operation.
1006    *
1007    * Since: 2.10
1008    */
1009   g_object_class_install_property (gobject_class,
1010                                    PROP_SHOW_PROGRESS,
1011                                    g_param_spec_boolean ("show-progress",
1012                                                          P_("Show Dialog"),
1013                                                          P_("TRUE if a progress dialog is shown while printing."),
1014                                                          FALSE,
1015                                                          GTK_PARAM_READWRITE));
1016
1017   /**
1018    * GtkPrintOperation:allow-async:
1019    *
1020    * Determines whether the print operation may run asynchronously or not.
1021    *
1022    * Some systems don't support asynchronous printing, but those that do
1023    * will return %GTK_PRINT_OPERATION_RESULT_IN_PROGRESS as the status, and
1024    * emit the done signal when the operation is actually done.
1025    *
1026    * The Windows port does not support asynchronous operation
1027    * at all (this is unlikely to change). On other platforms, all actions
1028    * except for %GTK_PRINT_OPERATION_ACTION_EXPORT support asynchronous
1029    * operation.
1030    *
1031    * Since: 2.10
1032    */
1033   g_object_class_install_property (gobject_class,
1034                                    PROP_ALLOW_ASYNC,
1035                                    g_param_spec_boolean ("allow-async",
1036                                                          P_("Allow Async"),
1037                                                          P_("TRUE if print process may run asynchronous."),
1038                                                          FALSE,
1039                                                          GTK_PARAM_READWRITE));
1040   
1041   /**
1042    * GtkPrintOperation:export-filename:
1043    *
1044    * The name of a file file to generate instead of showing 
1045    * the print dialog. Currently, PDF is the only supported
1046    * format.
1047    *
1048    * The intended use of this property is for implementing 
1049    * "Export to PDF" actions.
1050    *
1051    * "Print to PDF" support is independent of this and is done
1052    * by letting the user pick the "Print to PDF" item from the 
1053    * list of printers in the print dialog.
1054    *
1055    * Since: 2.10
1056    */
1057   g_object_class_install_property (gobject_class,
1058                                    PROP_EXPORT_FILENAME,
1059                                    g_param_spec_string ("export-filename",
1060                                                         P_("Export filename"),
1061                                                         P_("Export filename"),
1062                                                         NULL,
1063                                                         GTK_PARAM_READWRITE));
1064   
1065   /**
1066    * GtkPrintOperation:status:
1067    *
1068    * The status of the print operation.
1069    * 
1070    * Since: 2.10
1071    */
1072   g_object_class_install_property (gobject_class,
1073                                    PROP_STATUS,
1074                                    g_param_spec_enum ("status",
1075                                                       P_("Status"),
1076                                                       P_("The status of the print operation"),
1077                                                       GTK_TYPE_PRINT_STATUS,
1078                                                       GTK_PRINT_STATUS_INITIAL,
1079                                                       GTK_PARAM_READABLE));
1080   
1081   /**
1082    * GtkPrintOperation:status-string:
1083    *
1084    * A string representation of the status of the print operation. 
1085    * The string is translated and suitable for displaying the print 
1086    * status e.g. in a #GtkStatusbar.
1087    *
1088    * See the ::status property for a status value that is suitable 
1089    * for programmatic use. 
1090    *
1091    * Since: 2.10
1092    */
1093   g_object_class_install_property (gobject_class,
1094                                    PROP_STATUS_STRING,
1095                                    g_param_spec_string ("status-string",
1096                                                         P_("Status String"),
1097                                                         P_("A human-readable description of the status"),
1098                                                         "",
1099                                                         GTK_PARAM_READABLE));
1100   
1101
1102   /**
1103    * GtkPrintOperation:custom-tab-label:
1104    *
1105    * Used as the label of the tab containing custom widgets.
1106    * Note that this property may be ignored on some platforms.
1107    * 
1108    * If this is %NULL, GTK+ uses a default label.
1109    *
1110    * Since: 2.10
1111    */
1112   g_object_class_install_property (gobject_class,
1113                                    PROP_CUSTOM_TAB_LABEL,
1114                                    g_param_spec_string ("custom-tab-label",
1115                                                         P_("Custom tab label"),
1116                                                         P_("Label for the tab containing custom widgets."),
1117                                                         NULL,
1118                                                         GTK_PARAM_READWRITE));
1119
1120 }
1121
1122 /**
1123  * gtk_print_operation_new:
1124  *
1125  * Creates a new #GtkPrintOperation. 
1126  *
1127  * Returns: a new #GtkPrintOperation
1128  *
1129  * Since: 2.10
1130  */
1131 GtkPrintOperation *
1132 gtk_print_operation_new (void)
1133 {
1134   GtkPrintOperation *print_operation;
1135
1136   print_operation = g_object_new (GTK_TYPE_PRINT_OPERATION, NULL);
1137   
1138   return print_operation;
1139 }
1140
1141 /**
1142  * gtk_print_operation_set_default_page_setup:
1143  * @op: a #GtkPrintOperation
1144  * @default_page_setup: a #GtkPageSetup, or %NULL
1145  * 
1146  * Makes @default_page_setup the default page setup for @op.
1147  *
1148  * This page setup will be used by gtk_print_operation_run(),
1149  * but it can be overridden on a per-page basis by connecting
1150  * to the ::request-page-setup signal.
1151  *
1152  * Since: 2.10
1153  **/
1154 void
1155 gtk_print_operation_set_default_page_setup (GtkPrintOperation *op,
1156                                             GtkPageSetup      *default_page_setup)
1157 {
1158   GtkPrintOperationPrivate *priv;
1159
1160   g_return_if_fail (GTK_IS_PRINT_OPERATION (op));
1161   g_return_if_fail (default_page_setup == NULL || 
1162                     GTK_IS_PAGE_SETUP (default_page_setup));
1163
1164   priv = op->priv;
1165
1166   if (default_page_setup != priv->default_page_setup)
1167     {
1168       if (default_page_setup)
1169         g_object_ref (default_page_setup);
1170       
1171       if (priv->default_page_setup)
1172         g_object_unref (priv->default_page_setup);
1173       
1174       priv->default_page_setup = default_page_setup;
1175      
1176       g_object_notify (G_OBJECT (op), "default-page-setup");
1177     }
1178 }
1179
1180 /**
1181  * gtk_print_operation_get_default_page_setup:
1182  * @op: a #GtkPrintOperation
1183  *
1184  * Returns the default page setup, see 
1185  * gtk_print_operation_set_default_page_setup().
1186  *
1187  * Returns: the default page setup 
1188  *
1189  * Since: 2.10
1190  */
1191 GtkPageSetup *
1192 gtk_print_operation_get_default_page_setup (GtkPrintOperation *op)
1193 {
1194   g_return_val_if_fail (GTK_IS_PRINT_OPERATION (op), NULL);
1195
1196   return op->priv->default_page_setup;
1197 }
1198
1199
1200 /**
1201  * gtk_print_operation_set_print_settings:
1202  * @op: a #GtkPrintOperation
1203  * @print_settings: #GtkPrintSettings, or %NULL
1204  * 
1205  * Sets the print settings for @op. This is typically used to
1206  * re-establish print settings from a previous print operation,
1207  * see gtk_print_operation_run().
1208  *
1209  * Since: 2.10
1210  **/
1211 void
1212 gtk_print_operation_set_print_settings (GtkPrintOperation *op,
1213                                         GtkPrintSettings  *print_settings)
1214 {
1215   GtkPrintOperationPrivate *priv;
1216
1217   g_return_if_fail (GTK_IS_PRINT_OPERATION (op));
1218   g_return_if_fail (print_settings == NULL || 
1219                     GTK_IS_PRINT_SETTINGS (print_settings));
1220
1221   priv = op->priv;
1222
1223   if (print_settings != priv->print_settings)
1224     {
1225       if (print_settings)
1226         g_object_ref (print_settings);
1227
1228       if (priv->print_settings)
1229         g_object_unref (priv->print_settings);
1230   
1231       priv->print_settings = print_settings;
1232
1233       g_object_notify (G_OBJECT (op), "print-settings");
1234     }
1235 }
1236
1237 /**
1238  * gtk_print_operation_get_print_settings:
1239  * @op: a #GtkPrintOperation
1240  * 
1241  * Returns the current print settings. 
1242  *
1243  * Note that the return value is %NULL until either 
1244  * gtk_print_operation_set_print_settings() or 
1245  * gtk_print_operation_run() have been called.
1246  * 
1247  * Return value: the current print settings of @op.
1248  * 
1249  * Since: 2.10
1250  **/
1251 GtkPrintSettings *
1252 gtk_print_operation_get_print_settings (GtkPrintOperation *op)
1253 {
1254   g_return_val_if_fail (GTK_IS_PRINT_OPERATION (op), NULL);
1255
1256   return op->priv->print_settings;
1257 }
1258
1259 /**
1260  * gtk_print_operation_set_job_name:
1261  * @op: a #GtkPrintOperation
1262  * @job_name: a string that identifies the print job
1263  * 
1264  * Sets the name of the print job. The name is used to identify 
1265  * the job (e.g. in monitoring applications like eggcups). 
1266  * 
1267  * If you don't set a job name, GTK+ picks a default one by 
1268  * numbering successive print jobs.
1269  *
1270  * Since: 2.10
1271  **/
1272 void
1273 gtk_print_operation_set_job_name (GtkPrintOperation *op,
1274                                   const gchar       *job_name)
1275 {
1276   GtkPrintOperationPrivate *priv;
1277
1278   g_return_if_fail (GTK_IS_PRINT_OPERATION (op));
1279   g_return_if_fail (g_utf8_validate (job_name, -1, NULL));
1280
1281   priv = op->priv;
1282
1283   g_free (priv->job_name);
1284   priv->job_name = g_strdup (job_name);
1285
1286   g_object_notify (G_OBJECT (op), "job-name");
1287 }
1288
1289 /**
1290  * gtk_print_operation_set_n_pages:
1291  * @op: a #GtkPrintOperation
1292  * @n_pages: the number of pages
1293  * 
1294  * Sets the number of pages in the document. 
1295  *
1296  * This <emphasis>must</emphasis> be set to a positive number
1297  * before the rendering starts. It may be set in a ::begin-print 
1298  * signal hander.
1299  *
1300  * Note that the page numbers passed to the ::request-page-setup 
1301  * and ::draw-page signals are 0-based, i.e. if the user chooses
1302  * to print all pages, the last ::draw-page signal will be
1303  * for page @n_pages - 1.
1304  *
1305  * Since: 2.10
1306  **/
1307 void
1308 gtk_print_operation_set_n_pages (GtkPrintOperation *op,
1309                                  gint               n_pages)
1310 {
1311   GtkPrintOperationPrivate *priv;
1312
1313   g_return_if_fail (GTK_IS_PRINT_OPERATION (op));
1314   g_return_if_fail (n_pages > 0);
1315
1316   priv = op->priv;
1317   g_return_if_fail (priv->current_page == -1 || 
1318                     priv->current_page < n_pages);
1319
1320   if (priv->nr_of_pages != n_pages)
1321     {
1322       priv->nr_of_pages = n_pages;
1323
1324       g_object_notify (G_OBJECT (op), "n-pages");
1325     }
1326 }
1327
1328 /**
1329  * gtk_print_operation_set_current_page:
1330  * @op: a #GtkPrintOperation
1331  * @current_page: the current page, 0-based
1332  *
1333  * Sets the current page.
1334  *
1335  * If this is called before gtk_print_operation_run(), 
1336  * the user will be able to select to print only the current page.
1337  *
1338  * Note that this only makes sense for pre-paginated documents.
1339  * 
1340  * Since: 2.10
1341  **/
1342 void
1343 gtk_print_operation_set_current_page (GtkPrintOperation *op,
1344                                       gint               current_page)
1345 {
1346   GtkPrintOperationPrivate *priv;
1347
1348   g_return_if_fail (GTK_IS_PRINT_OPERATION (op));
1349   g_return_if_fail (current_page >= 0);
1350
1351   priv = op->priv;
1352   g_return_if_fail (priv->nr_of_pages == -1 || 
1353                     current_page < priv->nr_of_pages);
1354
1355   if (priv->current_page != current_page)
1356     {
1357       priv->current_page = current_page;
1358
1359       g_object_notify (G_OBJECT (op), "current-page");
1360     }
1361 }
1362
1363 /**
1364  * gtk_print_operation_set_use_full_page:
1365  * @op: a #GtkPrintOperation
1366  * @full_page: %TRUE to set up the #GtkPrintContext for the full page
1367  * 
1368  * If @full_page is %TRUE, the transformation for the cairo context 
1369  * obtained from #GtkPrintContext puts the origin at the top left 
1370  * corner of the page (which may not be the top left corner of the 
1371  * sheet, depending on page orientation and the number of pages per 
1372  * sheet). Otherwise, the origin is at the top left corner of the
1373  * imageable area (i.e. inside the margins).
1374  * 
1375  * Since: 2.10 
1376  */
1377 void
1378 gtk_print_operation_set_use_full_page (GtkPrintOperation *op,
1379                                        gboolean           full_page)
1380 {
1381   GtkPrintOperationPrivate *priv;
1382
1383   g_return_if_fail (GTK_IS_PRINT_OPERATION (op));
1384
1385   full_page = full_page != FALSE;
1386  
1387   priv = op->priv;
1388         
1389   if (priv->use_full_page != full_page)
1390     {
1391       priv->use_full_page = full_page;
1392    
1393       g_object_notify (G_OBJECT (op), "use-full-page");
1394     }
1395 }
1396
1397 /**
1398  * gtk_print_operation_set_unit:
1399  * @op: a #GtkPrintOperation
1400  * @unit: the unit to use
1401  * 
1402  * Sets up the transformation for the cairo context obtained from
1403  * #GtkPrintContext in such a way that distances are measured in 
1404  * units of @unit.
1405  *
1406  * Since: 2.10
1407  */
1408 void
1409 gtk_print_operation_set_unit (GtkPrintOperation *op,
1410                               GtkUnit            unit)
1411 {
1412   GtkPrintOperationPrivate *priv;
1413
1414   g_return_if_fail (GTK_IS_PRINT_OPERATION (op));
1415
1416   priv = op->priv;
1417
1418   if (priv->unit != unit)
1419     {
1420       priv->unit = unit;
1421
1422       g_object_notify (G_OBJECT (op), "unit");
1423     }
1424 }
1425
1426 /**
1427  * gtk_print_operation_set_track_print_status:
1428  * @op: a #GtkPrintOperation
1429  * @track_status: %TRUE to track status after printing
1430  * 
1431  * If track_status is %TRUE, the print operation will try to continue report
1432  * on the status of the print job in the printer queues and printer. This
1433  * can allow your application to show things like "out of paper" issues,
1434  * and when the print job actually reaches the printer.
1435  * 
1436  * This function is often implemented using some form of polling, so it should
1437  * not be enabled unless needed.
1438  *
1439  * Since: 2.10
1440  */
1441 void
1442 gtk_print_operation_set_track_print_status (GtkPrintOperation  *op,
1443                                             gboolean            track_status)
1444 {
1445   GtkPrintOperationPrivate *priv;
1446
1447   g_return_if_fail (GTK_IS_PRINT_OPERATION (op));
1448
1449   priv = op->priv;
1450
1451   if (priv->track_print_status != track_status)
1452     {
1453       priv->track_print_status = track_status;
1454
1455       g_object_notify (G_OBJECT (op), "track-print-status");
1456     }
1457 }
1458
1459 void
1460 _gtk_print_operation_set_status (GtkPrintOperation *op,
1461                                  GtkPrintStatus     status,
1462                                  const gchar       *string)
1463 {
1464   GtkPrintOperationPrivate *priv = op->priv;
1465   static const gchar *status_strs[] = {
1466     /* translators, strip the prefix up to and including the first | */
1467     N_("print operation status|Initial state"),
1468     /* translators, strip the prefix up to and including the first | */
1469     N_("print operation status|Preparing to print"),
1470     /* translators, strip the prefix up to and including the first | */
1471     N_("print operation status|Generating data"),
1472     /* translators, strip the prefix up to and including the first | */
1473     N_("print operation status|Sending data"),
1474     /* translators, strip the prefix up to and including the first | */
1475     N_("print operation status|Waiting"),
1476     /* translators, strip the prefix up to and including the first | */
1477     N_("print operation status|Blocking on issue"),
1478     /* translators, strip the prefix up to and including the first | */
1479     N_("print operation status|Printing"),
1480     /* translators, strip the prefix up to and including the first | */
1481     N_("print operation status|Finished"),
1482     /* translators, strip the prefix up to and including the first | */
1483     N_("print operation status|Finished with error")
1484   };
1485
1486   if (status < 0 || status > GTK_PRINT_STATUS_FINISHED_ABORTED)
1487     status = GTK_PRINT_STATUS_FINISHED_ABORTED;
1488
1489   if (string == NULL)
1490     string = g_strip_context (status_strs[status],
1491                               gettext (status_strs[status]));
1492   
1493   if (priv->status == status &&
1494       strcmp (string, priv->status_string) == 0)
1495     return;
1496   
1497   g_free (priv->status_string);
1498   priv->status_string = g_strdup (string);
1499   priv->status = status;
1500
1501   g_object_notify (G_OBJECT (op), "status");
1502   g_object_notify (G_OBJECT (op), "status-string");
1503
1504   g_signal_emit (op, signals[STATUS_CHANGED], 0);
1505 }
1506
1507
1508 /**
1509  * gtk_print_operation_get_status:
1510  * @op: a #GtkPrintOperation
1511  * 
1512  * Returns the status of the print operation. 
1513  * Also see gtk_print_operation_get_status_string().
1514  * 
1515  * Return value: the status of the print operation
1516  *
1517  * Since: 2.10
1518  **/
1519 GtkPrintStatus
1520 gtk_print_operation_get_status (GtkPrintOperation *op)
1521 {
1522   g_return_val_if_fail (GTK_IS_PRINT_OPERATION (op), 
1523                         GTK_PRINT_STATUS_FINISHED_ABORTED);
1524
1525   return op->priv->status;
1526 }
1527
1528 /**
1529  * gtk_print_operation_get_status_string:
1530  * @op: a #GtkPrintOperation
1531  * 
1532  * Returns a string representation of the status of the 
1533  * print operation. The string is translated and suitable
1534  * for displaying the print status e.g. in a #GtkStatusbar.
1535  *
1536  * Use gtk_print_operation_get_status() to obtain a status
1537  * value that is suitable for programmatic use. 
1538  * 
1539  * Return value: a string representation of the status
1540  *    of the print operation
1541  *
1542  * Since: 2.10
1543  **/
1544 G_CONST_RETURN gchar *
1545 gtk_print_operation_get_status_string (GtkPrintOperation *op)
1546 {
1547   g_return_val_if_fail (GTK_IS_PRINT_OPERATION (op), "");
1548
1549   return op->priv->status_string;
1550 }
1551
1552 /**
1553  * gtk_print_operation_is_finished:
1554  * @op: a #GtkPrintOperation
1555  * 
1556  * A convenience function to find out if the print operation
1557  * is finished, either successfully (%GTK_PRINT_STATUS_FINISHED)
1558  * or unsuccessfully (%GTK_PRINT_STATUS_FINISHED_ABORTED).
1559  * 
1560  * Note: when you enable print status tracking the print operation
1561  * can be in a non-finished state even after done has been called, as
1562  * the operation status then tracks the print job status on the printer.
1563  * 
1564  * Return value: %TRUE, if the print operation is finished.
1565  *
1566  * Since: 2.10
1567  **/
1568 gboolean
1569 gtk_print_operation_is_finished (GtkPrintOperation *op)
1570 {
1571   GtkPrintOperationPrivate *priv;
1572
1573   g_return_val_if_fail (GTK_IS_PRINT_OPERATION (op), TRUE);
1574
1575   priv = op->priv;
1576   return
1577     priv->status == GTK_PRINT_STATUS_FINISHED_ABORTED ||
1578     priv->status == GTK_PRINT_STATUS_FINISHED;
1579 }
1580
1581 /**
1582  * gtk_print_operation_set_show_progress:
1583  * @op: a #GtkPrintOperation
1584  * @show_progress: %TRUE to show a progress dialog
1585  * 
1586  * If @show_progress is %TRUE, the print operation will show a 
1587  * progress dialog during the print operation.
1588  * 
1589  * Since: 2.10
1590  */
1591 void
1592 gtk_print_operation_set_show_progress (GtkPrintOperation  *op,
1593                                        gboolean            show_progress)
1594 {
1595   GtkPrintOperationPrivate *priv;
1596
1597   g_return_if_fail (GTK_IS_PRINT_OPERATION (op));
1598
1599   priv = op->priv;
1600
1601   show_progress = show_progress != FALSE;
1602
1603   if (priv->show_progress != show_progress)
1604     {
1605       priv->show_progress = show_progress;
1606
1607       g_object_notify (G_OBJECT (op), "show-progress");
1608     }
1609 }
1610
1611 /**
1612  * gtk_print_operation_set_allow_async:
1613  * @op: a #GtkPrintOperation
1614  * @allow_async: %TRUE to allow asynchronous operation
1615  *
1616  * Sets whether the gtk_print_operation_run() may return
1617  * before the print operation is completed. Note that
1618  * some platforms may not allow asynchronous operation.
1619  *
1620  * Since: 2.10
1621  */
1622 void
1623 gtk_print_operation_set_allow_async (GtkPrintOperation  *op,
1624                                      gboolean            allow_async)
1625 {
1626   GtkPrintOperationPrivate *priv;
1627
1628   g_return_if_fail (GTK_IS_PRINT_OPERATION (op));
1629
1630   priv = op->priv;
1631
1632   allow_async = allow_async != FALSE;
1633
1634   if (priv->allow_async != allow_async)
1635     {
1636       priv->allow_async = allow_async;
1637
1638       g_object_notify (G_OBJECT (op), "allow-async");
1639     }
1640 }
1641
1642
1643 /**
1644  * gtk_print_operation_set_custom_tab_label:
1645  * @op: a #GtkPrintOperation
1646  * @label: the label to use, or %NULL to use the default label
1647  *
1648  * Sets the label for the tab holding custom widgets.
1649  *
1650  * Since: 2.10
1651  */
1652 void
1653 gtk_print_operation_set_custom_tab_label (GtkPrintOperation  *op,
1654                                           const gchar        *label)
1655 {
1656   GtkPrintOperationPrivate *priv;
1657
1658   g_return_if_fail (GTK_IS_PRINT_OPERATION (op));
1659
1660   priv = op->priv;
1661
1662   g_free (priv->custom_tab_label);
1663   priv->custom_tab_label = g_strdup (label);
1664
1665   g_object_notify (G_OBJECT (op), "custom-tab-label");
1666 }
1667
1668
1669 /**
1670  * gtk_print_operation_set_export_filename:
1671  * @op: a #GtkPrintOperation
1672  * @filename: the filename for the exported file
1673  * 
1674  * Sets up the #GtkPrintOperation to generate a file instead
1675  * of showing the print dialog. The indended use of this function
1676  * is for implementing "Export to PDF" actions. Currently, PDF
1677  * is the only supported format.
1678  *
1679  * "Print to PDF" support is independent of this and is done
1680  * by letting the user pick the "Print to PDF" item from the list
1681  * of printers in the print dialog.
1682  *
1683  * Since: 2.10
1684  */
1685 void
1686 gtk_print_operation_set_export_filename (GtkPrintOperation *op,
1687                                          const gchar       *filename)
1688 {
1689   GtkPrintOperationPrivate *priv;
1690
1691   g_return_if_fail (GTK_IS_PRINT_OPERATION (op));
1692
1693   priv = op->priv;
1694
1695   g_free (priv->export_filename);
1696   priv->export_filename = g_strdup (filename);
1697
1698   g_object_notify (G_OBJECT (op), "export-filename");
1699 }
1700
1701 /* Creates the initial page setup used for printing unless the
1702  * app overrides this on a per-page basis using request_page_setup.
1703  *
1704  * Data is taken from, in order, if existing:
1705  *
1706  * PrintSettings returned from the print dialog
1707  *  (initial dialog values are set from default_page_setup
1708  *   if unset in app specified print_settings)
1709  * default_page_setup
1710  * per-locale default setup
1711  */
1712 static GtkPageSetup *
1713 create_page_setup (GtkPrintOperation *op)
1714 {
1715   GtkPrintOperationPrivate *priv = op->priv;
1716   GtkPageSetup *page_setup;
1717   GtkPrintSettings *settings;
1718   
1719   if (priv->default_page_setup)
1720     page_setup = gtk_page_setup_copy (priv->default_page_setup);
1721   else
1722     page_setup = gtk_page_setup_new ();
1723
1724   settings = priv->print_settings;
1725   if (settings)
1726     {
1727       GtkPaperSize *paper_size;
1728       
1729       if (gtk_print_settings_has_key (settings, GTK_PRINT_SETTINGS_ORIENTATION))
1730         gtk_page_setup_set_orientation (page_setup,
1731                                         gtk_print_settings_get_orientation (settings));
1732
1733
1734       paper_size = gtk_print_settings_get_paper_size (settings);
1735       if (paper_size)
1736         {
1737           gtk_page_setup_set_paper_size (page_setup, paper_size);
1738           gtk_paper_size_free (paper_size);
1739         }
1740
1741       /* TODO: Margins? */
1742     }
1743   
1744   return page_setup;
1745 }
1746
1747 static void 
1748 pdf_start_page (GtkPrintOperation *op,
1749                 GtkPrintContext   *print_context,
1750                 GtkPageSetup      *page_setup)
1751 {
1752   GtkPaperSize *paper_size;
1753   cairo_surface_t *surface = op->priv->platform_data;
1754   gdouble w, h;
1755
1756   paper_size = gtk_page_setup_get_paper_size (page_setup);
1757
1758   w = gtk_paper_size_get_width (paper_size, GTK_UNIT_POINTS);
1759   h = gtk_paper_size_get_height (paper_size, GTK_UNIT_POINTS);
1760   
1761   cairo_pdf_surface_set_size (surface, w, h);
1762 }
1763
1764 static void
1765 pdf_end_page (GtkPrintOperation *op,
1766               GtkPrintContext   *print_context)
1767 {
1768   cairo_t *cr;
1769
1770   cr = gtk_print_context_get_cairo_context (print_context);
1771   cairo_show_page (cr);
1772 }
1773
1774 static void
1775 pdf_end_run (GtkPrintOperation *op,
1776              gboolean           wait,
1777              gboolean           cancelled)
1778 {
1779   GtkPrintOperationPrivate *priv = op->priv;
1780   cairo_surface_t *surface = priv->platform_data;
1781
1782   cairo_surface_finish (surface);
1783   cairo_surface_destroy (surface);
1784 }
1785
1786 static GtkPrintOperationResult
1787 run_pdf (GtkPrintOperation  *op,
1788          GtkWindow          *parent,
1789          gboolean           *do_print)
1790 {
1791   GtkPrintOperationPrivate *priv = op->priv;
1792   GtkPageSetup *page_setup;
1793   cairo_surface_t *surface;
1794   cairo_t *cr;
1795   gdouble width, height;
1796   
1797   priv->print_context = _gtk_print_context_new (op);
1798   
1799   page_setup = create_page_setup (op);
1800   _gtk_print_context_set_page_setup (priv->print_context, page_setup);
1801
1802   /* This will be overwritten later by the non-default size, but
1803      we need to pass some size: */
1804   width = gtk_page_setup_get_paper_width (page_setup, GTK_UNIT_POINTS);
1805   height = gtk_page_setup_get_paper_height (page_setup, GTK_UNIT_POINTS);
1806   g_object_unref (page_setup);
1807   
1808   surface = cairo_pdf_surface_create (priv->export_filename,
1809                                       width, height);
1810   cairo_surface_set_fallback_resolution (surface, 300, 300);
1811
1812   priv->platform_data = surface;
1813   priv->free_platform_data = (GDestroyNotify) cairo_surface_destroy;
1814
1815   cr = cairo_create (surface);
1816   gtk_print_context_set_cairo_context (op->priv->print_context,
1817                                        cr, 72, 72);
1818   cairo_destroy (cr);
1819
1820   
1821   priv->print_pages = GTK_PRINT_PAGES_ALL;
1822   priv->page_ranges = NULL;
1823   priv->num_page_ranges = 0;
1824
1825   priv->manual_num_copies = 1;
1826   priv->manual_collation = FALSE;
1827   priv->manual_reverse = FALSE;
1828   priv->manual_page_set = GTK_PAGE_SET_ALL;
1829   priv->manual_scale = 1.0;
1830   priv->manual_orientation = TRUE;
1831   
1832   *do_print = TRUE;
1833   
1834   priv->start_page = pdf_start_page;
1835   priv->end_page = pdf_end_page;
1836   priv->end_run = pdf_end_run;
1837   
1838   return GTK_PRINT_OPERATION_RESULT_APPLY; 
1839 }
1840
1841 typedef struct
1842 {
1843   GtkPrintOperation *op;
1844   gint uncollated_copies;
1845   gint collated_copies;
1846   gint uncollated, collated, total;
1847
1848   gint range, num_ranges;
1849   GtkPageRange *ranges;
1850   GtkPageRange one_range;
1851
1852   gint page, start, end, inc;
1853
1854   GtkWidget *progress;
1855  
1856   gboolean initialized;
1857   gboolean is_preview; 
1858 } PrintPagesData;
1859
1860 static void
1861 find_range (PrintPagesData *data)
1862 {
1863   GtkPageRange *range;
1864
1865   range = &data->ranges[data->range];
1866
1867   if (data->inc < 0)
1868     {
1869       data->start = range->end;
1870       data->end = range->start - 1;
1871     }
1872   else
1873     {
1874       data->start = range->start;
1875       data->end = range->end + 1;
1876     }
1877 }
1878
1879 static gboolean 
1880 increment_page_sequence (PrintPagesData *data)
1881 {
1882   GtkPrintOperationPrivate *priv = data->op->priv;
1883
1884   do {
1885     data->page += data->inc;
1886     if (data->page == data->end)
1887       {
1888         data->range += data->inc;
1889         if (data->range == -1 || data->range == data->num_ranges)
1890           {
1891             data->uncollated++;
1892             if (data->uncollated == data->uncollated_copies)
1893               return FALSE;
1894
1895             data->range = data->inc < 0 ? data->num_ranges - 1 : 0;
1896           }
1897         find_range (data);
1898         data->page = data->start;
1899       }
1900   }
1901   while ((priv->manual_page_set == GTK_PAGE_SET_EVEN && data->page % 2 == 0) ||
1902          (priv->manual_page_set == GTK_PAGE_SET_ODD && data->page % 2 == 1));
1903
1904   return TRUE;
1905 }
1906
1907 static void
1908 print_pages_idle_done (gpointer user_data)
1909 {
1910   PrintPagesData *data;
1911   GtkPrintOperationPrivate *priv;
1912
1913   data = (PrintPagesData*)user_data;
1914   priv = data->op->priv;
1915
1916   priv->print_pages_idle_id = 0;
1917
1918   if (priv->show_progress_timeout_id > 0)
1919     {
1920       g_source_remove (priv->show_progress_timeout_id);
1921       priv->show_progress_timeout_id = 0;
1922     }
1923  
1924   if (data->progress)
1925     gtk_widget_destroy (data->progress);
1926
1927   if (priv->rloop && !data->is_preview) 
1928     g_main_loop_quit (priv->rloop);
1929
1930   if (!data->is_preview)
1931     g_signal_emit (data->op, signals[DONE], 0,
1932                    priv->cancelled ?
1933                    GTK_PRINT_OPERATION_RESULT_CANCEL :
1934                    GTK_PRINT_OPERATION_RESULT_APPLY);
1935   
1936   g_object_unref (data->op);
1937
1938   g_free (data);
1939 }
1940
1941 static void
1942 update_progress (PrintPagesData *data)
1943 {
1944   GtkPrintOperationPrivate *priv; 
1945   gchar *text = NULL;
1946   
1947   priv = data->op->priv;
1948  
1949   if (data->progress)
1950     {
1951       if (priv->status == GTK_PRINT_STATUS_PREPARING)
1952         {
1953           if (priv->nr_of_pages > 0)
1954             text = g_strdup_printf (_("Preparing %d"), priv->nr_of_pages);
1955           else
1956             text = g_strdup (_("Preparing"));
1957         }
1958       else if (priv->status == GTK_PRINT_STATUS_GENERATING_DATA)
1959         text = g_strdup_printf (_("Printing %d"), data->total);
1960       
1961       if (text)
1962         {
1963           g_object_set (data->progress, "text", text, NULL);
1964           g_free (text);
1965         }
1966     }
1967  }
1968
1969 static void
1970 common_render_page (GtkPrintOperation *op,
1971                     gint               page_nr)
1972 {
1973   GtkPrintOperationPrivate *priv = op->priv;
1974   GtkPageSetup *page_setup;
1975   GtkPrintContext *print_context;
1976   cairo_t *cr;
1977
1978   print_context = priv->print_context;
1979   
1980   page_setup = create_page_setup (op);
1981   
1982   g_signal_emit (op, signals[REQUEST_PAGE_SETUP], 0, 
1983                  print_context, page_nr, page_setup);
1984   
1985   _gtk_print_context_set_page_setup (print_context, page_setup);
1986   
1987   priv->start_page (op, print_context, page_setup);
1988   
1989   cr = gtk_print_context_get_cairo_context (print_context);
1990   
1991   cairo_save (cr);
1992   if (priv->manual_scale != 1.0)
1993     cairo_scale (cr,
1994                  priv->manual_scale,
1995                  priv->manual_scale);
1996   
1997   if (priv->manual_orientation)
1998     _gtk_print_context_rotate_according_to_orientation (print_context);
1999   
2000   if (!priv->use_full_page)
2001     _gtk_print_context_translate_into_margin (print_context);
2002   
2003   g_signal_emit (op, signals[DRAW_PAGE], 0, 
2004                  print_context, page_nr);
2005
2006   priv->end_page (op, print_context);
2007   
2008   cairo_restore (cr);
2009
2010   g_object_unref (page_setup);
2011 }
2012
2013 static gboolean
2014 print_pages_idle (gpointer user_data)
2015 {
2016   PrintPagesData *data; 
2017   GtkPrintOperationPrivate *priv; 
2018   GtkPageSetup *page_setup;
2019   gboolean done = FALSE;
2020
2021   data = (PrintPagesData*)user_data;
2022   priv = data->op->priv;
2023
2024   if (priv->status == GTK_PRINT_STATUS_PREPARING)
2025     {
2026       if (!data->initialized)
2027         {
2028           data->initialized = TRUE;
2029           page_setup = create_page_setup (data->op);
2030           _gtk_print_context_set_page_setup (priv->print_context, 
2031                                              page_setup);
2032           g_object_unref (page_setup);
2033       
2034           g_signal_emit (data->op, signals[BEGIN_PRINT], 0, priv->print_context);
2035       
2036           if (priv->manual_collation)
2037             {
2038               data->uncollated_copies = priv->manual_num_copies;
2039               data->collated_copies = 1;
2040             }
2041           else
2042             {
2043               data->uncollated_copies = 1;
2044               data->collated_copies = priv->manual_num_copies;
2045             }
2046
2047           goto out;
2048         }
2049       
2050       if (g_signal_has_handler_pending (data->op, signals[PAGINATE], 0, FALSE))
2051         {
2052           gboolean paginated = FALSE;
2053
2054           g_signal_emit (data->op, signals[PAGINATE], 0, priv->print_context, &paginated);
2055           if (!paginated)
2056             goto out;
2057         }
2058
2059       /* FIXME handle this better */
2060       if (priv->nr_of_pages == 0)
2061         g_warning ("no pages to print");
2062       
2063       /* Initialize parts of PrintPagesData that depend on nr_of_pages
2064        */
2065       if (priv->print_pages == GTK_PRINT_PAGES_RANGES)
2066         {
2067           data->ranges = priv->page_ranges;
2068           data->num_ranges = priv->num_page_ranges;
2069         }
2070       else if (priv->print_pages == GTK_PRINT_PAGES_CURRENT &&
2071                priv->current_page != -1)
2072         {
2073           data->ranges = &data->one_range;
2074           data->num_ranges = 1;
2075           data->ranges[0].start = priv->current_page;
2076           data->ranges[0].end = priv->current_page;
2077         }
2078       else
2079         {
2080           data->ranges = &data->one_range;
2081           data->num_ranges = 1;
2082           data->ranges[0].start = 0;
2083           data->ranges[0].end = priv->nr_of_pages - 1;
2084         }
2085       
2086       if (priv->manual_reverse)
2087         {
2088           data->range = data->num_ranges - 1;
2089           data->inc = -1;      
2090         }
2091       else
2092         {
2093           data->range = 0;
2094           data->inc = 1;      
2095         }
2096       find_range (data);
2097      
2098       /* go back one page, since we preincrement below */
2099       data->page = data->start - data->inc;
2100       data->collated = data->collated_copies - 1;
2101
2102       _gtk_print_operation_set_status (data->op, 
2103                                        GTK_PRINT_STATUS_GENERATING_DATA, 
2104                                        NULL);
2105
2106       goto out;
2107     }
2108
2109   data->total++;
2110   data->collated++;
2111   if (data->collated == data->collated_copies)
2112     {
2113       data->collated = 0;
2114       if (!increment_page_sequence (data))
2115         {
2116           done = TRUE;
2117
2118           goto out;
2119         }
2120     }
2121  
2122   if (data->is_preview)
2123     {
2124       done = TRUE;
2125
2126       g_object_ref (data->op);
2127       
2128       g_signal_emit_by_name (data->op, "ready", priv->print_context);
2129       goto out;
2130     }
2131
2132   common_render_page (data->op, data->page);
2133
2134  out:
2135
2136   if (priv->cancelled)
2137     {
2138       _gtk_print_operation_set_status (data->op, GTK_PRINT_STATUS_FINISHED_ABORTED, NULL);
2139       
2140       done = TRUE;
2141     }
2142
2143   if (done && !data->is_preview)
2144     {
2145       g_signal_emit (data->op, signals[END_PRINT], 0, priv->print_context);
2146       priv->end_run (data->op, priv->is_sync, priv->cancelled);
2147     }
2148
2149   update_progress (data);
2150
2151   return !done;
2152 }
2153   
2154 static void
2155 handle_progress_response (GtkWidget *dialog, 
2156                           gint       response,
2157                           gpointer   data)
2158 {
2159   GtkPrintOperation *op = (GtkPrintOperation *)data;
2160
2161   gtk_widget_hide (dialog);
2162   gtk_print_operation_cancel (op);
2163 }
2164
2165 static gboolean
2166 show_progress_timeout (PrintPagesData *data)
2167 {
2168   gtk_window_present (GTK_WINDOW (data->progress));
2169
2170   data->op->priv->show_progress_timeout_id = 0;
2171
2172   return FALSE;
2173 }
2174
2175 static void
2176 print_pages (GtkPrintOperation       *op,
2177              GtkWindow               *parent,
2178              gboolean                 do_print,
2179              GtkPrintOperationResult  result)
2180 {
2181   GtkPrintOperationPrivate *priv = op->priv;
2182   PrintPagesData *data;
2183  
2184   if (!do_print) 
2185     {
2186       _gtk_print_operation_set_status (op, GTK_PRINT_STATUS_FINISHED_ABORTED, NULL);
2187       g_signal_emit (op, signals[DONE], 0, result);
2188       return;
2189   }
2190   
2191   _gtk_print_operation_set_status (op, GTK_PRINT_STATUS_PREPARING, NULL);  
2192
2193   data = g_new0 (PrintPagesData, 1);
2194   data->op = g_object_ref (op);
2195   data->is_preview = (priv->action == GTK_PRINT_OPERATION_ACTION_PREVIEW);
2196
2197   if (priv->show_progress)
2198     {
2199       GtkWidget *progress;
2200
2201       progress = gtk_message_dialog_new (parent, 0, 
2202                                          GTK_MESSAGE_OTHER,
2203                                          GTK_BUTTONS_CANCEL,
2204                                          _("Preparing"));
2205       g_signal_connect (progress, "response", 
2206                         G_CALLBACK (handle_progress_response), op);
2207
2208       priv->show_progress_timeout_id = 
2209         gdk_threads_add_timeout (SHOW_PROGRESS_TIME, 
2210                        (GSourceFunc)show_progress_timeout,
2211                        data);
2212
2213       data->progress = progress;
2214     }
2215
2216   if (data->is_preview)
2217     {
2218       gboolean handled;
2219       
2220       g_signal_emit_by_name (op, "preview",
2221                              GTK_PRINT_OPERATION_PREVIEW (op),
2222                              priv->print_context,
2223                              parent,
2224                              &handled);
2225       
2226       if (!handled ||
2227           gtk_print_context_get_cairo_context (priv->print_context) == NULL) 
2228         {
2229           /* Programmer error */
2230           g_error ("You must set a cairo context on the print context");
2231         }
2232       
2233       priv->start_page = preview_start_page;
2234       priv->end_page = preview_end_page;
2235       priv->end_run = preview_end_run;
2236
2237       priv->print_pages = gtk_print_settings_get_print_pages (priv->print_settings);
2238       priv->page_ranges = gtk_print_settings_get_page_ranges (priv->print_settings,
2239                                                               &priv->num_page_ranges);
2240       priv->manual_num_copies = 1;
2241       priv->manual_collation = FALSE;
2242       priv->manual_reverse = FALSE;
2243       priv->manual_page_set = GTK_PAGE_SET_ALL;
2244       priv->manual_scale = 1.0;
2245       priv->manual_orientation = TRUE;
2246     }
2247   
2248   priv->print_pages_idle_id = gdk_threads_add_idle_full (G_PRIORITY_DEFAULT_IDLE + 10,
2249                                                          print_pages_idle, 
2250                                                          data, 
2251                                                          print_pages_idle_done);
2252   
2253   /* Recursive main loop to make sure we don't exit  on sync operations  */
2254   if (priv->is_sync)
2255     {
2256       priv->rloop = g_main_loop_new (NULL, FALSE);
2257
2258       g_object_ref (op);
2259       GDK_THREADS_LEAVE ();
2260       g_main_loop_run (priv->rloop);
2261       GDK_THREADS_ENTER ();
2262       
2263       g_main_loop_unref (priv->rloop);
2264       priv->rloop = NULL;
2265       g_object_unref (op);
2266     }
2267 }
2268
2269 /**
2270  * gtk_print_operation_get_error:
2271  * @op: a #GtkPrintOperation
2272  * @error: return location for the error
2273  * 
2274  * Call this when the result of a print operation is
2275  * %GTK_PRINT_OPERATION_RESULT_ERROR, either as returned by 
2276  * gtk_print_operation_run(), or in the ::done signal handler. 
2277  * The returned #GError will contain more details on what went wrong.
2278  *
2279  * Since: 2.10
2280  **/
2281 void
2282 gtk_print_operation_get_error (GtkPrintOperation  *op,
2283                                GError            **error)
2284 {
2285   g_return_if_fail (GTK_IS_PRINT_OPERATION (op));
2286   
2287   g_propagate_error (error, op->priv->error);
2288
2289   op->priv->error = NULL;
2290 }
2291
2292
2293 /**
2294  * gtk_print_operation_run:
2295  * @op: a #GtkPrintOperation
2296  * @action: the action to start
2297  * @parent: Transient parent of the dialog, or %NULL
2298  * @error: Return location for errors, or %NULL
2299  * 
2300  * Runs the print operation, by first letting the user modify
2301  * print settings in the print dialog, and then print the
2302  * document.
2303  *
2304  * Normally that this function does not return until the rendering of all 
2305  * pages is complete. You can connect to the ::status-changed signal on
2306  * @op to obtain some information about the progress of the print operation. 
2307  * Furthermore, it may use a recursive mainloop to show the print dialog.
2308  *
2309  * If you call gtk_print_operation_set_allow_async() or set the allow-async
2310  * property the operation will run asyncronously if this is supported on the
2311  * platform. The ::done signal will be emitted with the operation results when
2312  * the operation is done (i.e. when the dialog is canceled, or when the print
2313  * succeeds or fails).
2314  *
2315  * <informalexample><programlisting>
2316  * if (settings != NULL)
2317  *   gtk_print_operation_set_print_settings (print, settings);
2318  *   
2319  * if (page_setup != NULL)
2320  *   gtk_print_operation_set_default_page_setup (print, page_setup);
2321  *   
2322  * g_signal_connect (print, "begin-print", 
2323  *                   G_CALLBACK (begin_print), &amp;data);
2324  * g_signal_connect (print, "draw-page", 
2325  *                   G_CALLBACK (draw_page), &amp;data);
2326  *  
2327  * res = gtk_print_operation_run (print, GTK_PRINT_OPERATION_ACTION_PRINT_DIALOG, parent, &amp;error);
2328  *  
2329  * if (res == GTK_PRINT_OPERATION_RESULT_ERROR)
2330  *  {
2331  *    error_dialog = gtk_message_dialog_new (GTK_WINDOW (parent),
2332  *                                           GTK_DIALOG_DESTROY_WITH_PARENT,
2333  *                                           GTK_MESSAGE_ERROR,
2334  *                                           GTK_BUTTONS_CLOSE,
2335  *                                           "Error printing file:\n%s",
2336  *                                           error->message);
2337  *    g_signal_connect (error_dialog, "response", 
2338  *                      G_CALLBACK (gtk_widget_destroy), NULL);
2339  *    gtk_widget_show (error_dialog);
2340  *    g_error_free (error);
2341  *  }
2342  * else if (res == GTK_PRINT_OPERATION_RESULT_APPLY)
2343  *  {
2344  *    if (settings != NULL)
2345  *      g_object_unref (settings);
2346  *    settings = g_object_ref (gtk_print_operation_get_print_settings (print));
2347  *  }
2348  * </programlisting></informalexample>
2349  *
2350  * Return value: the result of the print operation. A return value of 
2351  *   %GTK_PRINT_OPERATION_RESULT_APPLY indicates that the printing was
2352  *   completed successfully. In this case, it is a good idea to obtain 
2353  *   the used print settings with gtk_print_operation_get_print_settings() 
2354  *   and store them for reuse with the next print operation. A value of
2355  *   %GTK_PRINT_OPERATION_RESULT_IN_PROGRESS means the operation is running
2356  *   asynchronously, and will emit the ::done signal when done.
2357  *
2358  * Since: 2.10
2359  **/
2360 GtkPrintOperationResult
2361 gtk_print_operation_run (GtkPrintOperation        *op,
2362                          GtkPrintOperationAction   action,
2363                          GtkWindow                *parent,
2364                          GError                  **error)
2365 {
2366   GtkPrintOperationPrivate *priv;
2367   GtkPrintOperationResult result;
2368   GtkPageSetup *page_setup;
2369   gboolean do_print;
2370   
2371   g_return_val_if_fail (GTK_IS_PRINT_OPERATION (op), 
2372                         GTK_PRINT_OPERATION_RESULT_ERROR);
2373
2374   priv = op->priv;
2375
2376   do_print = FALSE;
2377   priv->error = NULL;
2378   priv->action = action;
2379
2380   if (priv->print_settings == NULL)
2381     priv->print_settings = gtk_print_settings_new ();
2382   
2383   if (action == GTK_PRINT_OPERATION_ACTION_EXPORT)
2384     {
2385       /* note: if you implement async EXPORT, update the docs
2386        * docs for the allow-async property.
2387        */
2388       priv->is_sync = TRUE;
2389       g_return_val_if_fail (priv->export_filename != NULL, GTK_PRINT_OPERATION_RESULT_ERROR);
2390       result = run_pdf (op, parent, &do_print);
2391     }
2392   else if (action == GTK_PRINT_OPERATION_ACTION_PREVIEW)
2393     {
2394       priv->is_sync = !priv->allow_async;
2395       priv->print_context = _gtk_print_context_new (op);
2396       page_setup = create_page_setup (op);
2397       _gtk_print_context_set_page_setup (priv->print_context, page_setup);
2398       g_object_unref (page_setup);
2399       do_print = TRUE;
2400       result = priv->is_sync ? GTK_PRINT_OPERATION_RESULT_APPLY : GTK_PRINT_OPERATION_RESULT_IN_PROGRESS;
2401     }
2402 #ifndef G_OS_WIN32
2403   else if (priv->allow_async)
2404     {
2405       priv->is_sync = FALSE;
2406       _gtk_print_operation_platform_backend_run_dialog_async (op,
2407                                                               action == GTK_PRINT_OPERATION_ACTION_PRINT_DIALOG,
2408                                                               parent,
2409                                                               print_pages);
2410       result = GTK_PRINT_OPERATION_RESULT_IN_PROGRESS;
2411     }
2412 #endif
2413   else
2414     {
2415       priv->is_sync = TRUE;
2416       result = _gtk_print_operation_platform_backend_run_dialog (op, 
2417                                                                  action == GTK_PRINT_OPERATION_ACTION_PRINT_DIALOG,
2418                                                                  parent,
2419                                                                  &do_print);
2420     }
2421
2422   if (result != GTK_PRINT_OPERATION_RESULT_IN_PROGRESS)
2423     print_pages (op, parent, do_print, result);
2424
2425   if (priv->error && error)
2426     *error = g_error_copy (priv->error);
2427   
2428   return result;
2429 }
2430
2431 /**
2432  * gtk_print_operation_cancel:
2433  * @op: a #GtkPrintOperation
2434  *
2435  * Cancels a running print operation. This function may
2436  * be called from a begin-print, paginate or draw-page
2437  * signal handler to stop the currently running print 
2438  * operation.
2439  *
2440  * Since: 2.10
2441  */
2442 void
2443 gtk_print_operation_cancel (GtkPrintOperation *op)
2444 {
2445   g_return_if_fail (GTK_IS_PRINT_OPERATION (op));
2446   
2447   op->priv->cancelled = TRUE;
2448 }
2449
2450
2451
2452 #define __GTK_PRINT_OPERATION_C__
2453 #include "gtkaliasdef.c"