]> Pileus Git - ~andy/gtk/blob - gtk/gtkprintoperation.c
Add a boolean show-progress property, and show a progress dialog if it is
[~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 #include <string.h>
23 #include "gtkprintoperation-private.h"
24 #include "gtkmarshalers.h"
25 #include <cairo-pdf.h>
26 #include "gtkintl.h"
27 #include "gtkprivate.h"
28 #include "gtkmessagedialog.h"
29 #include "gtkalias.h"
30
31 #define SHOW_PROGRESS_TIME 1200
32
33 #define GTK_PRINT_OPERATION_GET_PRIVATE(obj)(G_TYPE_INSTANCE_GET_PRIVATE ((obj), GTK_TYPE_PRINT_OPERATION, GtkPrintOperationPrivate))
34
35 enum {
36   BEGIN_PRINT,
37   PAGINATE,
38   REQUEST_PAGE_SETUP,
39   DRAW_PAGE,
40   END_PRINT,
41   STATUS_CHANGED,
42   CREATE_CUSTOM_WIDGET,
43   CUSTOM_WIDGET_APPLY,
44   LAST_SIGNAL
45 };
46
47 enum {
48   PROP_0,
49   PROP_DEFAULT_PAGE_SETUP,
50   PROP_PRINT_SETTINGS,
51   PROP_JOB_NAME,
52   PROP_N_PAGES,
53   PROP_CURRENT_PAGE,
54   PROP_USE_FULL_PAGE,
55   PROP_TRACK_PRINT_STATUS,
56   PROP_UNIT,
57   PROP_SHOW_DIALOG,
58   PROP_SHOW_PROGRESS,
59   PROP_PDF_TARGET,
60   PROP_STATUS,
61   PROP_STATUS_STRING
62 };
63
64 static guint signals[LAST_SIGNAL] = { 0 };
65 static int job_nr = 0;
66
67 G_DEFINE_TYPE (GtkPrintOperation, gtk_print_operation, G_TYPE_OBJECT)
68
69 /**
70  * gtk_print_error_quark:
71  *
72  * Registers an error quark for #GtkPrintOperation if necessary.
73  * 
74  * Return value: The error quark used for #GtkPrintOperation errors.
75  *
76  * Since: 2.10
77  **/
78 GQuark     
79 gtk_print_error_quark (void)
80 {
81   static GQuark quark = 0;
82   if (quark == 0)
83     quark = g_quark_from_static_string ("gtk-print-error-quark");
84   return quark;
85 }
86      
87 static void
88 gtk_print_operation_finalize (GObject *object)
89 {
90   GtkPrintOperation *print_operation = GTK_PRINT_OPERATION (object);
91   GtkPrintOperationPrivate *priv = print_operation->priv;
92
93   if (priv->free_platform_data &&
94       priv->platform_data)
95     {
96       priv->free_platform_data (priv->platform_data);
97       priv->free_platform_data = NULL;
98     }
99
100   if (priv->default_page_setup)
101     g_object_unref (priv->default_page_setup);
102   
103   if (priv->print_settings)
104     g_object_unref (priv->print_settings);
105   
106   g_free (priv->pdf_target);
107   g_free (priv->job_name);
108
109   if (priv->print_pages_idle_id > 0)
110     g_source_remove (priv->print_pages_idle_id);
111
112   if (priv->show_progress_timeout_id > 0)
113     g_source_remove (priv->show_progress_timeout_id);
114
115   G_OBJECT_CLASS (gtk_print_operation_parent_class)->finalize (object);
116 }
117
118 static void
119 gtk_print_operation_init (GtkPrintOperation *operation)
120 {
121   GtkPrintOperationPrivate *priv;
122   const char *appname;
123
124   priv = operation->priv = GTK_PRINT_OPERATION_GET_PRIVATE (operation);
125
126   priv->status = GTK_PRINT_STATUS_INITIAL;
127   priv->status_string = g_strdup ("");
128   priv->default_page_setup = NULL;
129   priv->print_settings = NULL;
130   priv->nr_of_pages = -1;
131   priv->current_page = -1;
132   priv->use_full_page = FALSE;
133   priv->show_dialog = TRUE;
134   priv->show_progress = FALSE;
135   priv->pdf_target = NULL;
136   priv->track_print_status = FALSE;
137
138   priv->unit = GTK_UNIT_PIXEL;
139
140   appname = g_get_application_name ();
141   priv->job_name = g_strdup_printf ("%s job #%d", appname, ++job_nr);
142 }
143
144 static void
145 gtk_print_operation_set_property (GObject      *object,
146                                   guint         prop_id,
147                                   const GValue *value,
148                                   GParamSpec   *pspec)
149 {
150   GtkPrintOperation *op = GTK_PRINT_OPERATION (object);
151   
152   switch (prop_id)
153     {
154     case PROP_DEFAULT_PAGE_SETUP:
155       gtk_print_operation_set_default_page_setup (op, g_value_get_object (value));
156       break;
157     case PROP_PRINT_SETTINGS:
158       gtk_print_operation_set_print_settings (op, g_value_get_object (value));
159       break;
160     case PROP_JOB_NAME:
161       gtk_print_operation_set_job_name (op, g_value_get_string (value));
162       break;
163     case PROP_N_PAGES:
164       gtk_print_operation_set_n_pages (op, g_value_get_int (value));
165       break;
166     case PROP_CURRENT_PAGE:
167       gtk_print_operation_set_current_page (op, g_value_get_int (value));
168       break;
169     case PROP_USE_FULL_PAGE:
170       gtk_print_operation_set_use_full_page (op, g_value_get_boolean (value));
171       break;
172     case PROP_TRACK_PRINT_STATUS:
173       gtk_print_operation_set_track_print_status (op, g_value_get_boolean (value));
174       break;
175     case PROP_UNIT:
176       gtk_print_operation_set_unit (op, g_value_get_enum (value));
177       break;
178     case PROP_SHOW_DIALOG:
179       gtk_print_operation_set_show_dialog (op, g_value_get_boolean (value));
180       break;
181     case PROP_SHOW_PROGRESS:
182       gtk_print_operation_set_show_progress (op, g_value_get_boolean (value));
183       break;
184     case PROP_PDF_TARGET:
185       gtk_print_operation_set_pdf_target (op, g_value_get_string (value));
186       break;
187     default:
188       G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
189       break;
190     }
191 }
192
193 static void
194 gtk_print_operation_get_property (GObject    *object,
195                                   guint       prop_id,
196                                   GValue     *value,
197                                   GParamSpec *pspec)
198 {
199   GtkPrintOperation *op = GTK_PRINT_OPERATION (object);
200   GtkPrintOperationPrivate *priv = op->priv;
201
202   switch (prop_id)
203     {
204     case PROP_DEFAULT_PAGE_SETUP:
205       g_value_set_object (value, priv->default_page_setup);
206       break;
207     case PROP_PRINT_SETTINGS:
208       g_value_set_object (value, priv->print_settings);
209       break;
210     case PROP_JOB_NAME:
211       g_value_set_string (value, priv->job_name);
212       break;
213     case PROP_N_PAGES:
214       g_value_set_int (value, priv->nr_of_pages);
215       break;
216     case PROP_CURRENT_PAGE:
217       g_value_set_int (value, priv->current_page);
218       break;      
219     case PROP_USE_FULL_PAGE:
220       g_value_set_boolean (value, priv->use_full_page);
221       break;
222     case PROP_TRACK_PRINT_STATUS:
223       g_value_set_boolean (value, priv->track_print_status);
224       break;
225     case PROP_UNIT:
226       g_value_set_enum (value, priv->unit);
227       break;
228     case PROP_SHOW_DIALOG:
229       g_value_set_boolean (value, priv->show_dialog);
230       break;
231     case PROP_SHOW_PROGRESS:
232       g_value_set_boolean (value, priv->show_progress);
233       break;
234     case PROP_PDF_TARGET:
235       g_value_set_string (value, priv->pdf_target);
236       break;
237     case PROP_STATUS:
238       g_value_set_enum (value, priv->status);
239       break;
240     case PROP_STATUS_STRING:
241       g_value_set_string (value, priv->status_string);
242       break;
243     default:
244       G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
245       break;
246     }
247 }
248
249 static GtkWidget *
250 gtk_print_operation_create_custom_widget (GtkPrintOperation *operation)
251 {
252   return NULL;
253 }
254
255 static gboolean
256 custom_widget_accumulator (GSignalInvocationHint *ihint,
257                            GValue                *return_accu,
258                            const GValue          *handler_return,
259                            gpointer               dummy)
260 {
261   gboolean continue_emission;
262   GtkWidget *widget;
263   
264   widget = g_value_get_pointer (handler_return);
265   if (widget != NULL)
266     g_value_set_pointer (return_accu, widget);
267   continue_emission = (widget == NULL);
268   
269   return continue_emission;
270 }
271
272 static void
273 gtk_print_operation_class_init (GtkPrintOperationClass *class)
274 {
275   GObjectClass *gobject_class = (GObjectClass *)class;
276
277   gobject_class->set_property = gtk_print_operation_set_property;
278   gobject_class->get_property = gtk_print_operation_get_property;
279   gobject_class->finalize = gtk_print_operation_finalize;
280
281   class->create_custom_widget = gtk_print_operation_create_custom_widget;
282   
283   g_type_class_add_private (gobject_class, sizeof (GtkPrintOperationPrivate));
284
285   /**
286    * GtkPrintOperation::begin-print:
287    * @operation: the #GtkPrintOperation on which the signal was emitted
288    * @context: the #GtkPrintContext for the current operation
289    *
290    * Gets emitted after the user has finished changing print settings
291    * in the dialog, before the actual rendering starts. 
292    *
293    * A typical use for this signal is to use the parameters from the
294    * #GtkPrintContext and paginate the document accordingly, and then
295    * set the number of pages with gtk_print_operation_set_n_pages().
296    *
297    * Since: 2.10
298    */
299   signals[BEGIN_PRINT] =
300     g_signal_new (I_("begin-print"),
301                   G_TYPE_FROM_CLASS (gobject_class),
302                   G_SIGNAL_RUN_LAST,
303                   G_STRUCT_OFFSET (GtkPrintOperationClass, begin_print),
304                   NULL, NULL,
305                   g_cclosure_marshal_VOID__OBJECT,
306                   G_TYPE_NONE, 1, GTK_TYPE_PRINT_CONTEXT);
307
308    /**
309    * Gtkprintoperation::paginate:
310    * @operation: the #GtkPrintOperation on which the signal was emitted
311    * @context: the #GtkPrintContext for the current operation
312    *
313    * Gets emitted after the begin-print signal, but before the actual 
314    * rendering starts. It keeps getting emitted until it returns %FALSE. 
315    *
316    * This signal is intended to be used for paginating the document
317    * in small chunks, to avoid blocking the user interface for a long
318    * time. The signal handler should update the number of pages using
319    * gtk_print_operation_set_n_pages(), and return %TRUE if the document
320    * has been completely paginated.
321    *
322    * If you don't need to do pagination in chunks, you can simply do
323    * it all in the begin-print handler, and set the number of pages
324    * from there.
325    *
326    * Since: 2.10
327    */
328   signals[PAGINATE] =
329     g_signal_new (I_("paginate"),
330                   G_TYPE_FROM_CLASS (gobject_class),
331                   G_SIGNAL_RUN_LAST,
332                   G_STRUCT_OFFSET (GtkPrintOperationClass, paginate),
333                   _gtk_boolean_handled_accumulator, NULL,
334                   _gtk_marshal_BOOLEAN__OBJECT,
335                   G_TYPE_BOOLEAN, 1, GTK_TYPE_PRINT_CONTEXT);
336
337
338   /**
339    * GtkPrintOperation::request-page-setup:
340    * @operation: the #GtkPrintOperation on which the signal was emitted
341    * @context: the #GtkPrintContext for the current operation
342    * @page_nr: the number of the currently printed page
343    * @setup: the #GtkPageSetup 
344    * 
345    * Gets emitted once for every page that is printed, to give
346    * the application a chance to modify the page setup. Any changes 
347    * done to @setup will be in force only for printing this page.
348    *
349    * Since: 2.10
350    */
351   signals[REQUEST_PAGE_SETUP] =
352     g_signal_new (I_("request-page-setup"),
353                   G_TYPE_FROM_CLASS (gobject_class),
354                   G_SIGNAL_RUN_LAST,
355                   G_STRUCT_OFFSET (GtkPrintOperationClass, request_page_setup),
356                   NULL, NULL,
357                   _gtk_marshal_VOID__OBJECT_INT_OBJECT,
358                   G_TYPE_NONE, 3,
359                   GTK_TYPE_PRINT_CONTEXT,
360                   G_TYPE_INT,
361                   GTK_TYPE_PAGE_SETUP);
362
363   /**
364    * GtkPrintOperation::draw-page:
365    * @operation: the #GtkPrintOperation on which the signal was emitted
366    * @context: the #GtkPrintContext for the current operation
367    * @page_nr: the number of the currently printed page
368    *
369    * Gets emitted for every page that is printed. The signal handler
370    * must render the @page_nr's page onto the cairo context obtained
371    * from @context using gtk_print_context_get_cairo().
372    *
373    * <informalexample><programlisting>
374    *  FIXME: need an example here
375    * </programlisting></informalexample>
376    *
377    * Use gtk_print_operation_set_use_full_page() and 
378    * gtk_print_operation_set_unit() before starting the print operation
379    * to set up the transformation of the cairo context according to your
380    * needs.
381    * 
382    * Since: 2.10
383    */
384   signals[DRAW_PAGE] =
385     g_signal_new (I_("draw-page"),
386                   G_TYPE_FROM_CLASS (gobject_class),
387                   G_SIGNAL_RUN_LAST,
388                   G_STRUCT_OFFSET (GtkPrintOperationClass, draw_page),
389                   NULL, NULL,
390                   _gtk_marshal_VOID__OBJECT_INT,
391                   G_TYPE_NONE, 2,
392                   GTK_TYPE_PRINT_CONTEXT,
393                   G_TYPE_INT);
394
395   /**
396    * GtkPrintOperation::end-print:
397    * @operation: the #GtkPrintOperation on which the signal was emitted
398    * @context: the #GtkPrintContext for the current operation
399    *
400    * Gets emitted after all pages have been rendered. 
401    * A handler for this signal can clean up any resources that have
402    * been allocated in the ::begin-print handler.
403    * 
404    * Since: 2.10
405    */
406   signals[END_PRINT] =
407     g_signal_new (I_("end-print"),
408                   G_TYPE_FROM_CLASS (gobject_class),
409                   G_SIGNAL_RUN_LAST,
410                   G_STRUCT_OFFSET (GtkPrintOperationClass, end_print),
411                   NULL, NULL,
412                   g_cclosure_marshal_VOID__OBJECT,
413                   G_TYPE_NONE, 1, GTK_TYPE_PRINT_CONTEXT);
414
415   /**
416    * GtkPrintOperation::status-changed:
417    * @operation: the #GtkPrintOperation on which the signal was emitted
418    *
419    * Gets emitted at between the various phases of the print operation.
420    * See #GtkPrintStatus for the phases that are being discriminated.
421    * Use gtk_print_operation_get_status() to find out the current
422    * status.
423    *
424    * Since: 2.10
425    */
426   signals[STATUS_CHANGED] =
427     g_signal_new (I_("status-changed"),
428                   G_TYPE_FROM_CLASS (class),
429                   G_SIGNAL_RUN_LAST,
430                   G_STRUCT_OFFSET (GtkPrintOperationClass, status_changed),
431                   NULL, NULL,
432                   g_cclosure_marshal_VOID__VOID,
433                   G_TYPE_NONE, 0);
434
435
436   /**
437    * GtkPrintOperation::create-custom-widget:
438    * @operation: the #GtkPrintOperation on which the signal was emitted
439    *
440    * Gets emitted when displaying the print dialog. If you return a
441    * widget in a handler for this signal it will be added to a custom
442    * tab in the print dialog. You typically return a container widget
443    * with multiple widgets in it.
444    *
445    * The print dialog owns the returned widget, and its lifetime
446    * isn't controlled by the app. However, the widget is guaranteed
447    * to stay around until the custom-widget-apply signal is emitted
448    * on the operation. Then you can read out any information you need
449    * from the widgets.
450    *
451    * Returns: A custom widget that gets embedded in the print dialog,
452    *          or %NULL
453    *
454    * Since: 2.10
455    */
456   signals[CREATE_CUSTOM_WIDGET] =
457     g_signal_new (I_("create-custom-widget"),
458                   G_TYPE_FROM_CLASS (class),
459                   G_SIGNAL_RUN_LAST,
460                   G_STRUCT_OFFSET (GtkPrintOperationClass, create_custom_widget),
461                   custom_widget_accumulator, NULL,
462                   _gtk_marshal_POINTER__VOID,
463                   G_TYPE_POINTER, 0);
464
465   /**
466    * GtkPrintOperation::custom-widget-apply:
467    * @operation: the #GtkPrintOperation on which the signal was emitted
468    * @widget: the custom widget added in create-custom-widget
469    *
470    * This signal gets emitted right before begin-print if you added
471    * a custom widget in the create-custom-widget handler. When you get
472    * this signal you should read the information from the custom widgets,
473    * as the widgets are not guaraneed to be around at a later time.
474    *
475    * Since: 2.10
476    */
477   signals[CUSTOM_WIDGET_APPLY] =
478     g_signal_new (I_("custom-widget-apply"),
479                   G_TYPE_FROM_CLASS (class),
480                   G_SIGNAL_RUN_LAST,
481                   G_STRUCT_OFFSET (GtkPrintOperationClass, custom_widget_apply),
482                   NULL, NULL,
483                   g_cclosure_marshal_VOID__OBJECT,
484                   G_TYPE_NONE, 1, GTK_TYPE_WIDGET);
485
486   /**
487    * GtkPrintOperation:default-page-setup:
488    *
489    * The #GtkPageSetup used by default.
490    * 
491    * This page setup will be used by gtk_print_operation_run(),
492    * but it can be overridden on a per-page basis by connecting
493    * to the ::request-page-setup signal.
494    *
495    * Since: 2.10
496    */
497   g_object_class_install_property (gobject_class,
498                                    PROP_DEFAULT_PAGE_SETUP,
499                                    g_param_spec_object ("default-page-setup",
500                                                         P_("Default Page Setup"),
501                                                         P_("The GtkPageSetup used by default"),
502                                                         GTK_TYPE_PAGE_SETUP,
503                                                         GTK_PARAM_READWRITE));
504
505   /**
506    * GtkPrintOperation:print-settings:
507    *
508    * The #GtkPrintSettings used for initializing the dialog.
509    *
510    * Setting this property is typically used to re-establish 
511    * print settings from a previous print operation, see 
512    * gtk_print_operation_run().
513    *
514    * Since: 2.10
515    */
516   g_object_class_install_property (gobject_class,
517                                    PROP_PRINT_SETTINGS,
518                                    g_param_spec_object ("print-settings",
519                                                         P_("Print Settings"),
520                                                         P_("The GtkPrintSettings used for initializing the dialog"),
521                                                         GTK_TYPE_PRINT_SETTINGS,
522                                                         GTK_PARAM_READWRITE));
523   
524   /**
525    * GtkPrintOperation:job-name:
526    *
527    * A string used to identify the job (e.g. in monitoring 
528    * applications like eggcups). 
529    * 
530    * If you don't set a job name, GTK+ picks a default one 
531    * by numbering successive print jobs.
532    *
533    * Since: 2.10
534    */
535   g_object_class_install_property (gobject_class,
536                                    PROP_JOB_NAME,
537                                    g_param_spec_string ("job-name",
538                                                         P_("Job Name"),
539                                                         P_("A string used for identifying the print job."),
540                                                         "",
541                                                         GTK_PARAM_READWRITE));
542
543   /**
544    * GtkPrintOperation:n-pages:
545    *
546    * The number of pages in the document. 
547    *
548    * This <emphasis>must</emphasis> be set to a positive number
549    * before the rendering starts. It may be set in a ::begin-print 
550    * signal hander.
551    *
552    * Note that the page numbers passed to the ::request-page-setup 
553    * and ::draw-page signals are 0-based, i.e. if the user chooses 
554    * to print all pages, the last ::draw-page signal will be for 
555    * page @n_pages - 1.
556    *
557    * Since: 2.10
558    */
559   g_object_class_install_property (gobject_class,
560                                    PROP_N_PAGES,
561                                    g_param_spec_int ("n-pages",
562                                                      P_("Number of Pages"),
563                                                      P_("The number of pages in the document."),
564                                                      -1,
565                                                      G_MAXINT,
566                                                      -1,
567                                                      GTK_PARAM_READWRITE));
568
569   /**
570    * GtkPrintOperation:current-page:
571    *
572    * The current page in the document.
573    *
574    * If this is set before gtk_print_operation_run(), 
575    * the user will be able to select to print only the current page.
576    *
577    * Note that this only makes sense for pre-paginated documents.
578    *
579    * Since: 2.10
580    */
581   g_object_class_install_property (gobject_class,
582                                    PROP_CURRENT_PAGE,
583                                    g_param_spec_int ("current-page",
584                                                      P_("Current Page"),
585                                                      P_("The current page in the document."),
586                                                      -1,
587                                                      G_MAXINT,
588                                                      -1,
589                                                      GTK_PARAM_READWRITE));
590   
591   /**
592    * GtkPrintOperation:use-full-page:
593    *
594    * If %TRUE, the transformation for the cairo context obtained 
595    * from #GtkPrintContext puts the origin at the top left corner 
596    * of the page (which may not be the top left corner of the sheet, 
597    * depending on page orientation and the number of pages per sheet). 
598    * Otherwise, the origin is at the top left corner of the imageable 
599    * area (i.e. inside the margins).
600    * 
601    * Since: 2.10
602    */
603   g_object_class_install_property (gobject_class,
604                                    PROP_USE_FULL_PAGE,
605                                    g_param_spec_boolean ("use-full-page",
606                                                          P_("Use full page"),
607                                                          P_("TRUE if the the origin of the context should be at the corner of the page and not the corner of the imageable area"),
608                                                          FALSE,
609                                                          GTK_PARAM_READWRITE));
610   
611
612   /**
613    * GtkPrintOperation:track-print-status:
614    *
615    * If %TRUE, the print operation will try to continue report on 
616    * the status of the print job in the printer queues and printer. 
617    * This can allow your application to show things like "out of paper" 
618    * issues, and when the print job actually reaches the printer. 
619    * However, this is often implemented using polling, and should 
620    * not be enabled unless needed.
621    * 
622    * Since: 2.10
623    */
624   g_object_class_install_property (gobject_class,
625                                    PROP_USE_FULL_PAGE,
626                                    g_param_spec_boolean ("track-print-status",
627                                                          P_("Track Print Status"),
628                                                          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."),
629                                                          FALSE,
630                                                          GTK_PARAM_READWRITE));
631   
632
633   /**
634    * GtkPrintOperation:unit:
635    *
636    * The transformation for the cairo context obtained from
637    * #GtkPrintContext is set up in such a way that distances 
638    * are measured in units of @unit.
639    *
640    * Since: 2.10
641    */
642   g_object_class_install_property (gobject_class,
643                                    PROP_UNIT,
644                                    g_param_spec_enum ("unit",
645                                                       P_("Unit"),
646                                                       P_("The unit in which distances can be measured in the context"),
647                                                       GTK_TYPE_UNIT,
648                                                       GTK_UNIT_PIXEL,
649                                                       GTK_PARAM_READWRITE));
650   
651
652   /**
653    * GtkPrintOperation:show-dialog:
654    *
655    * Determines whether calling gtk_print_operation_run() will present
656    * a print dialog to the user, or just print to the default printer.
657    *
658    * Since: 2.10
659    */
660   g_object_class_install_property (gobject_class,
661                                    PROP_SHOW_DIALOG,
662                                    g_param_spec_boolean ("show-dialog",
663                                                          P_("Show Dialog"),
664                                                          P_("TRUE if gtk_print_operation_run() should show the print dialog."),
665                                                          TRUE,
666                                                          GTK_PARAM_READWRITE));
667   
668
669   /**
670    * GtkPrintOperation:show-progress:
671    *
672    * Determines whether to show a progress dialog during the 
673    * print operation.
674    *
675    * Since: 2.10
676    */
677   g_object_class_install_property (gobject_class,
678                                    PROP_SHOW_PROGRESS,
679                                    g_param_spec_boolean ("show-progress",
680                                                          P_("Show Dialog"),
681                                                          P_("TRUE if a progress dialog is shown while printing."),
682                                                          FALSE,
683                                                          GTK_PARAM_READWRITE));
684   
685   
686   /**
687    * GtkPrintOperation:pdf-target:
688    *
689    * The name of a PDF file to generate instead of showing 
690    * the print dialog. 
691    *
692    * The intended use of this property is for implementing 
693    * "Export to PDF" actions.
694    *
695    * "Print to PDF" support is independent of this and is done
696    * by letting the user pick the "Print to PDF" item from the 
697    * list of printers in the print dialog.
698    *
699    * Since: 2.10
700    */
701   g_object_class_install_property (gobject_class,
702                                    PROP_JOB_NAME,
703                                    g_param_spec_string ("pdf-target",
704                                                         P_("PDF target filename"),
705                                                         P_("PDF target filename"),
706                                                         NULL,
707                                                         GTK_PARAM_READWRITE));
708   
709   /**
710    * GtkPrintOperation:status:
711    *
712    * The status of the print operation.
713    * 
714    * Since: 2.10
715    */
716   g_object_class_install_property (gobject_class,
717                                    PROP_STATUS,
718                                    g_param_spec_enum ("status",
719                                                       P_("Status"),
720                                                       P_("The status of the print operation"),
721                                                       GTK_TYPE_PRINT_STATUS,
722                                                       GTK_PRINT_STATUS_INITIAL,
723                                                       GTK_PARAM_READABLE));
724   
725   /**
726    * GtkPrintOperation:status-string:
727    *
728    * A string representation of the status of the print operation. 
729    * The string is translated and suitable for displaying the print 
730    * status e.g. in a #GtkStatusbar.
731    *
732    * See the ::status property for a status value that is suitable 
733    * for programmatic use. 
734    *
735    * Since: 2.10
736    */
737   g_object_class_install_property (gobject_class,
738                                    PROP_STATUS_STRING,
739                                    g_param_spec_string ("status-string",
740                                                         P_("Status String"),
741                                                         P_("A human-readable description of the status"),
742                                                         "",
743                                                         GTK_PARAM_READABLE));
744   
745
746 }
747
748 /**
749  * gtk_print_operation_new:
750  *
751  * Creates a new #GtkPrintOperation. 
752  *
753  * Returns: a new #GtkPrintOperation
754  *
755  * Since: 2.10
756  */
757 GtkPrintOperation *
758 gtk_print_operation_new (void)
759 {
760   GtkPrintOperation *print_operation;
761
762   print_operation = g_object_new (GTK_TYPE_PRINT_OPERATION, NULL);
763   
764   return print_operation;
765 }
766
767 /**
768  * gtk_print_operation_set_default_page_setup:
769  * @op: a #GtkPrintOperation
770  * @default_page_setup: a #GtkPageSetup, or %NULL
771  * 
772  * Makes @default_page_setup the default page setup for @op.
773  *
774  * This page setup will be used by gtk_print_operation_run(),
775  * but it can be overridden on a per-page basis by connecting
776  * to the ::request-page-setup signal.
777  *
778  * Since: 2.10
779  **/
780 void
781 gtk_print_operation_set_default_page_setup (GtkPrintOperation *op,
782                                             GtkPageSetup      *default_page_setup)
783 {
784   GtkPrintOperationPrivate *priv;
785
786   g_return_if_fail (GTK_IS_PRINT_OPERATION (op));
787   g_return_if_fail (default_page_setup == NULL || 
788                     GTK_IS_PAGE_SETUP (default_page_setup));
789
790   priv = op->priv;
791
792   if (default_page_setup != priv->default_page_setup)
793     {
794       if (default_page_setup)
795         g_object_ref (default_page_setup);
796       
797       if (priv->default_page_setup)
798         g_object_unref (priv->default_page_setup);
799       
800       priv->default_page_setup = default_page_setup;
801      
802       g_object_notify (G_OBJECT (op), "default-page-setup");
803     }
804 }
805
806 /**
807  * gtk_print_operation_get_default_page_setup:
808  * @op: a #GtkPrintOperation
809  *
810  * Returns the default page setup, see 
811  * gtk_print_operation_set_default_page_setup().
812  *
813  * Returns: the default page setup 
814  *
815  * Since: 2.10
816  */
817 GtkPageSetup *
818 gtk_print_operation_get_default_page_setup (GtkPrintOperation *op)
819 {
820   g_return_val_if_fail (GTK_IS_PRINT_OPERATION (op), NULL);
821
822   return op->priv->default_page_setup;
823 }
824
825
826 /**
827  * gtk_print_operation_set_print_settings:
828  * @op: a #GtkPrintOperation
829  * @print_settings: #GtkPrintSettings, or %NULL
830  * 
831  * Sets the print settings for @op. This is typically used to
832  * re-establish print settings from a previous print operation,
833  * see gtk_print_operation_run().
834  *
835  * Since: 2.10
836  **/
837 void
838 gtk_print_operation_set_print_settings (GtkPrintOperation *op,
839                                         GtkPrintSettings  *print_settings)
840 {
841   GtkPrintOperationPrivate *priv;
842
843   g_return_if_fail (GTK_IS_PRINT_OPERATION (op));
844   g_return_if_fail (print_settings == NULL || 
845                     GTK_IS_PRINT_SETTINGS (print_settings));
846
847   priv = op->priv;
848
849   if (print_settings != priv->print_settings)
850     {
851       if (print_settings)
852         g_object_ref (print_settings);
853
854       if (priv->print_settings)
855         g_object_unref (priv->print_settings);
856   
857       priv->print_settings = print_settings;
858
859       g_object_notify (G_OBJECT (op), "print-settings");
860     }
861 }
862
863 /**
864  * gtk_print_operation_get_print_settings:
865  * @op: a #GtkPrintOperation
866  * 
867  * Returns the current print settings. 
868  *
869  * Note that the return value is %NULL until either 
870  * gtk_print_operation_set_print_settings() or 
871  * gtk_print_operation_run() have been called.
872  * 
873  * Return value: the current print settings of @op.
874  * 
875  * Since: 2.10
876  **/
877 GtkPrintSettings *
878 gtk_print_operation_get_print_settings (GtkPrintOperation *op)
879 {
880   g_return_val_if_fail (GTK_IS_PRINT_OPERATION (op), NULL);
881
882   return op->priv->print_settings;
883 }
884
885 /**
886  * gtk_print_operation_set_job_name:
887  * @op: a #GtkPrintOperation
888  * @job_name: a string that identifies the print job
889  * 
890  * Sets the name of the print job. The name is used to identify 
891  * the job (e.g. in monitoring applications like eggcups). 
892  * 
893  * If you don't set a job name, GTK+ picks a default one by 
894  * numbering successive print jobs.
895  *
896  * Since: 2.10
897  **/
898 void
899 gtk_print_operation_set_job_name (GtkPrintOperation *op,
900                                   const gchar       *job_name)
901 {
902   GtkPrintOperationPrivate *priv;
903
904   g_return_if_fail (GTK_IS_PRINT_OPERATION (op));
905   g_return_if_fail (g_utf8_validate (job_name, -1, NULL));
906
907   priv = op->priv;
908
909   g_free (priv->job_name);
910   priv->job_name = g_strdup (job_name);
911
912   g_object_notify (G_OBJECT (op), "job-name");
913 }
914
915 /**
916  * gtk_print_operation_set_n_pages:
917  * @op: a #GtkPrintOperation
918  * @n_pages: the number of pages
919  * 
920  * Sets the number of pages in the document. 
921  *
922  * This <emphasis>must</emphasis> be set to a positive number
923  * before the rendering starts. It may be set in a ::begin-print 
924  * signal hander.
925  *
926  * Note that the page numbers passed to the ::request-page-setup 
927  * and ::draw-page signals are 0-based, i.e. if the user chooses
928  * to print all pages, the last ::draw-page signal will be
929  * for page @n_pages - 1.
930  *
931  * Since: 2.10
932  **/
933 void
934 gtk_print_operation_set_n_pages (GtkPrintOperation *op,
935                                  gint               n_pages)
936 {
937   GtkPrintOperationPrivate *priv;
938
939   g_return_if_fail (GTK_IS_PRINT_OPERATION (op));
940   g_return_if_fail (n_pages > 0);
941
942   priv = op->priv;
943   g_return_if_fail (priv->current_page == -1 || 
944                     priv->current_page < n_pages);
945
946   if (priv->nr_of_pages != n_pages)
947     {
948       priv->nr_of_pages = n_pages;
949
950       g_object_notify (G_OBJECT (op), "n-pages");
951     }
952 }
953
954 /**
955  * gtk_print_operation_set_current_page:
956  * @op: a #GtkPrintOperation
957  * @current_page: the current page, 0-based
958  *
959  * Sets the current page.
960  *
961  * If this is called before gtk_print_operation_run(), 
962  * the user will be able to select to print only the current page.
963  *
964  * Note that this only makes sense for pre-paginated documents.
965  * 
966  * Since: 2.10
967  **/
968 void
969 gtk_print_operation_set_current_page (GtkPrintOperation *op,
970                                       gint               current_page)
971 {
972   GtkPrintOperationPrivate *priv;
973
974   g_return_if_fail (GTK_IS_PRINT_OPERATION (op));
975   g_return_if_fail (current_page >= 0);
976
977   priv = op->priv;
978   g_return_if_fail (priv->nr_of_pages == -1 || 
979                     current_page < priv->nr_of_pages);
980
981   if (priv->current_page != current_page)
982     {
983       priv->current_page = current_page;
984
985       g_object_notify (G_OBJECT (op), "current-page");
986     }
987 }
988
989 /**
990  * gtk_print_operation_set_use_full_page:
991  * @op: a #GtkPrintOperation
992  * @full_page: %TRUE to set up the #GtkPrintContext for the full page
993  * 
994  * If @full_page is %TRUE, the transformation for the cairo context 
995  * obtained from #GtkPrintContext puts the origin at the top left 
996  * corner of the page (which may not be the top left corner of the 
997  * sheet, depending on page orientation and the number of pages per 
998  * sheet). Otherwise, the origin is at the top left corner of the
999  * imageable area (i.e. inside the margins).
1000  * 
1001  * Since: 2.10 
1002  */
1003 void
1004 gtk_print_operation_set_use_full_page (GtkPrintOperation *op,
1005                                        gboolean           full_page)
1006 {
1007   GtkPrintOperationPrivate *priv;
1008
1009   g_return_if_fail (GTK_IS_PRINT_OPERATION (op));
1010
1011   full_page = full_page != FALSE;
1012  
1013   priv = op->priv;
1014         
1015   if (priv->use_full_page != full_page)
1016     {
1017       priv->use_full_page = full_page;
1018    
1019       g_object_notify (G_OBJECT (op), "use-full-page");
1020     }
1021 }
1022
1023 /**
1024  * gtk_print_operation_set_unit:
1025  * @op: a #GtkPrintOperation
1026  * @unit: the unit to use
1027  * 
1028  * Sets up the transformation for the cairo context obtained from
1029  * #GtkPrintContext in such a way that distances are measured in 
1030  * units of @unit.
1031  *
1032  * Since: 2.10
1033  */
1034 void
1035 gtk_print_operation_set_unit (GtkPrintOperation *op,
1036                               GtkUnit            unit)
1037 {
1038   GtkPrintOperationPrivate *priv;
1039
1040   g_return_if_fail (GTK_IS_PRINT_OPERATION (op));
1041
1042   priv = op->priv;
1043
1044   if (priv->unit != unit)
1045     {
1046       priv->unit = unit;
1047
1048       g_object_notify (G_OBJECT (op), "unit");
1049     }
1050 }
1051
1052 /**
1053  * gtk_print_operation_set_track_print_status:
1054  * @op: a #GtkPrintOperation
1055  * @track_status: %TRUE to track status after printing
1056  * 
1057  * If track_status is %TRUE, the print operation will try to continue report
1058  * on the status of the print job in the printer queues and printer. This
1059  * can allow your application to show things like "out of paper" issues,
1060  * and when the print job actually reaches the printer.
1061  * 
1062  * This function is often implemented using some form of polling, so it should
1063  * not be enabled unless needed.
1064  *
1065  * Since: 2.10
1066  */
1067 void
1068 gtk_print_operation_set_track_print_status (GtkPrintOperation  *op,
1069                                             gboolean            track_status)
1070 {
1071   GtkPrintOperationPrivate *priv;
1072
1073   g_return_if_fail (GTK_IS_PRINT_OPERATION (op));
1074
1075   priv = op->priv;
1076
1077   if (priv->track_print_status != track_status)
1078     {
1079       priv->track_print_status = track_status;
1080
1081       g_object_notify (G_OBJECT (op), "track-print-status");
1082     }
1083 }
1084
1085 void
1086 _gtk_print_operation_set_status (GtkPrintOperation *op,
1087                                  GtkPrintStatus     status,
1088                                  const gchar       *string)
1089 {
1090   GtkPrintOperationPrivate *priv = op->priv;
1091   static const gchar *status_strs[] = {
1092     /* translators, strip the prefix up to and including the first | */
1093     N_("print operation status|Initial state"),
1094     /* translators, strip the prefix up to and including the first | */
1095     N_("print operation status|Preparing to print"),
1096     /* translators, strip the prefix up to and including the first | */
1097     N_("print operation status|Generating data"),
1098     /* translators, strip the prefix up to and including the first | */
1099     N_("print operation status|Sending data"),
1100     /* translators, strip the prefix up to and including the first | */
1101     N_("print operation status|Waiting"),
1102     /* translators, strip the prefix up to and including the first | */
1103     N_("print operation status|Blocking on issue"),
1104     /* translators, strip the prefix up to and including the first | */
1105     N_("print operation status|Printing"),
1106     /* translators, strip the prefix up to and including the first | */
1107     N_("print operation status|Finished"),
1108     /* translators, strip the prefix up to and including the first | */
1109     N_("print operation status|Finished with error")
1110   };
1111
1112   if (status < 0 || status > GTK_PRINT_STATUS_FINISHED_ABORTED)
1113     status = GTK_PRINT_STATUS_FINISHED_ABORTED;
1114
1115   if (string == NULL)
1116     string = g_strip_context (status_strs[status],
1117                               gettext (status_strs[status]));
1118   
1119   if (priv->status == status &&
1120       strcmp (string, priv->status_string) == 0)
1121     return;
1122   
1123   g_free (priv->status_string);
1124   priv->status_string = g_strdup (string);
1125   priv->status = status;
1126
1127   g_object_notify (G_OBJECT (op), "status");
1128   g_object_notify (G_OBJECT (op), "status-string");
1129
1130   g_signal_emit (op, signals[STATUS_CHANGED], 0);
1131 }
1132
1133
1134 /**
1135  * gtk_print_operation_get_status:
1136  * @op: a #GtkPrintOperation
1137  * 
1138  * Returns the status of the print operation. 
1139  * Also see gtk_print_operation_get_status_string().
1140  * 
1141  * Return value: the status of the print operation
1142  *
1143  * Since: 2.10
1144  **/
1145 GtkPrintStatus
1146 gtk_print_operation_get_status (GtkPrintOperation *op)
1147 {
1148   g_return_val_if_fail (GTK_IS_PRINT_OPERATION (op), 
1149                         GTK_PRINT_STATUS_FINISHED_ABORTED);
1150
1151   return op->priv->status;
1152 }
1153
1154 /**
1155  * gtk_print_operation_get_status_string:
1156  * @op: a #GtkPrintOperation
1157  * 
1158  * Returns a string representation of the status of the 
1159  * print operation. The string is translated and suitable
1160  * for displaying the print status e.g. in a #GtkStatusbar.
1161  *
1162  * Use gtk_print_operation_get_status() to obtain a status
1163  * value that is suitable for programmatic use. 
1164  * 
1165  * Return value: a string representation of the status
1166  *    of the print operation
1167  *
1168  * Since: 2.10
1169  **/
1170 G_CONST_RETURN gchar *
1171 gtk_print_operation_get_status_string (GtkPrintOperation *op)
1172 {
1173   g_return_val_if_fail (GTK_IS_PRINT_OPERATION (op), "");
1174
1175   return op->priv->status_string;
1176 }
1177
1178 /**
1179  * gtk_print_operation_is_finished:
1180  * @op: a #GtkPrintOperation
1181  * 
1182  * A convenience function to find out if the print operation
1183  * is finished, either successfully (%GTK_PRINT_STATUS_FINISHED)
1184  * or unsuccessfully (%GTK_PRINT_STATUS_FINISHED_ABORTED).
1185  * 
1186  * Return value: %TRUE, if the print operation is finished.
1187  *
1188  * Since: 2.10
1189  **/
1190 gboolean
1191 gtk_print_operation_is_finished (GtkPrintOperation *op)
1192 {
1193   GtkPrintOperationPrivate *priv;
1194
1195   g_return_val_if_fail (GTK_IS_PRINT_OPERATION (op), TRUE);
1196
1197   priv = op->priv;
1198   return
1199     priv->status == GTK_PRINT_STATUS_FINISHED_ABORTED ||
1200     priv->status == GTK_PRINT_STATUS_FINISHED;
1201 }
1202
1203
1204 /**
1205  * gtk_print_operation_set_show_dialog:
1206  * @op: a #GtkPrintOperation
1207  * @show_dialog: %TRUE to show the print dialog
1208  * 
1209  * Sets whether calling gtk_print_operation_run() will present
1210  * a print dialog to the user, or just print to the default printer.
1211  *
1212  * Since: 2.10
1213  */
1214 void
1215 gtk_print_operation_set_show_dialog (GtkPrintOperation *op,
1216                                      gboolean           show_dialog)
1217 {
1218   GtkPrintOperationPrivate *priv;
1219
1220   g_return_if_fail (GTK_IS_PRINT_OPERATION (op));
1221
1222   priv = op->priv;
1223
1224   show_dialog = show_dialog != FALSE;
1225
1226   if (priv->show_dialog != show_dialog)
1227     {
1228       priv->show_dialog = show_dialog;
1229
1230       g_object_notify (G_OBJECT (op), "show-dialog");
1231     }
1232 }
1233
1234
1235 /**
1236  * gtk_print_operation_set_show_progress:
1237  * @op: a #GtkPrintOperation
1238  * @show_progress: %TRUE to show a progress dialog
1239  * 
1240  * If @show_progress is %TRUE, the print operation will show a 
1241  * progress dialog during the print operation.
1242  * 
1243  * Since: 2.10
1244  */
1245 void
1246 gtk_print_operation_set_show_progress (GtkPrintOperation  *op,
1247                                        gboolean            show_progress)
1248 {
1249   GtkPrintOperationPrivate *priv;
1250
1251   g_return_if_fail (GTK_IS_PRINT_OPERATION (op));
1252
1253   priv = op->priv;
1254
1255   show_progress = show_progress != FALSE;
1256
1257   if (priv->show_progress != show_progress)
1258     {
1259       priv->show_progress = show_progress;
1260
1261       g_object_notify (G_OBJECT (op), "show-progress");
1262     }
1263 }
1264
1265 /**
1266  * gtk_print_operation_set_pdf_target:
1267  * @op: a #GtkPrintOperation
1268  * @filename: the filename for the PDF file
1269  * 
1270  * Sets up the #GtkPrintOperation to generate a PDF file instead
1271  * of showing the print dialog. The indended use of this function
1272  * is for implementing "Export to PDF" actions.
1273  *
1274  * "Print to PDF" support is independent of this and is done
1275  * by letting the user pick the "Print to PDF" item from the list
1276  * of printers in the print dialog.
1277  *
1278  * Since: 2.10
1279  */
1280 void
1281 gtk_print_operation_set_pdf_target (GtkPrintOperation *op,
1282                                     const gchar       *filename)
1283 {
1284   GtkPrintOperationPrivate *priv;
1285
1286   g_return_if_fail (GTK_IS_PRINT_OPERATION (op));
1287
1288   priv = op->priv;
1289
1290   g_free (priv->pdf_target);
1291   priv->pdf_target = g_strdup (filename);
1292
1293   g_object_notify (G_OBJECT (op), "pdf-target");
1294 }
1295
1296 /* Creates the initial page setup used for printing unless the
1297  * app overrides this on a per-page basis using request_page_setup.
1298  *
1299  * Data is taken from, in order, if existing:
1300  *
1301  * PrintSettings returned from the print dialog
1302  *  (initial dialog values are set from default_page_setup
1303  *   if unset in app specified print_settings)
1304  * default_page_setup
1305  * per-locale default setup
1306  */
1307 static GtkPageSetup *
1308 create_page_setup (GtkPrintOperation *op)
1309 {
1310   GtkPrintOperationPrivate *priv = op->priv;
1311   GtkPageSetup *page_setup;
1312   GtkPrintSettings *settings;
1313   
1314   if (priv->default_page_setup)
1315     page_setup = gtk_page_setup_copy (priv->default_page_setup);
1316   else
1317     page_setup = gtk_page_setup_new ();
1318
1319   settings = priv->print_settings;
1320   if (settings)
1321     {
1322       GtkPaperSize *paper_size;
1323       
1324       if (gtk_print_settings_has_key (settings, GTK_PRINT_SETTINGS_ORIENTATION))
1325         gtk_page_setup_set_orientation (page_setup,
1326                                         gtk_print_settings_get_orientation (settings));
1327
1328
1329       paper_size = gtk_print_settings_get_paper_size (settings);
1330       if (paper_size)
1331         {
1332           gtk_page_setup_set_paper_size (page_setup, paper_size);
1333           gtk_paper_size_free (paper_size);
1334         }
1335
1336       /* TODO: Margins? */
1337     }
1338   
1339   return page_setup;
1340 }
1341
1342 static void 
1343 pdf_start_page (GtkPrintOperation *op,
1344                 GtkPrintContext   *print_context,
1345                 GtkPageSetup      *page_setup)
1346 {
1347   GtkPaperSize *paper_size;
1348   double w, h;
1349
1350   paper_size = gtk_page_setup_get_paper_size (page_setup);
1351
1352   w = gtk_paper_size_get_width (paper_size, GTK_UNIT_POINTS);
1353   h = gtk_paper_size_get_height (paper_size, GTK_UNIT_POINTS);
1354   
1355   cairo_pdf_surface_set_size (op->priv->surface, w, h);
1356 }
1357
1358 static void
1359 pdf_end_page (GtkPrintOperation *op,
1360               GtkPrintContext   *print_context)
1361 {
1362   cairo_t *cr;
1363
1364   cr = gtk_print_context_get_cairo (print_context);
1365   cairo_show_page (cr);
1366 }
1367
1368 static void
1369 pdf_end_run (GtkPrintOperation *op,
1370              gboolean           wait,
1371              gboolean           cancelled)
1372 {
1373   GtkPrintOperationPrivate *priv = op->priv;
1374
1375   cairo_surface_destroy (priv->surface);
1376   priv->surface = NULL;
1377 }
1378
1379 static GtkPrintOperationResult
1380 run_pdf (GtkPrintOperation  *op,
1381          GtkWindow          *parent,
1382          gboolean           *do_print,
1383          GError            **error)
1384 {
1385   GtkPrintOperationPrivate *priv = op->priv;
1386   GtkPageSetup *page_setup;
1387   double width, height;
1388   /* This will be overwritten later by the non-default size, but
1389      we need to pass some size: */
1390   
1391   page_setup = create_page_setup (op);
1392   width = gtk_page_setup_get_paper_width (page_setup, GTK_UNIT_POINTS);
1393   height = gtk_page_setup_get_paper_height (page_setup, GTK_UNIT_POINTS);
1394   g_object_unref (page_setup);
1395   
1396   priv->surface = cairo_pdf_surface_create (priv->pdf_target,
1397                                             width, height);
1398   cairo_pdf_surface_set_dpi (priv->surface, 300, 300);
1399   
1400   priv->dpi_x = 72;
1401   priv->dpi_y = 72;
1402
1403   priv->print_pages = GTK_PRINT_PAGES_ALL;
1404   priv->page_ranges = NULL;
1405   priv->num_page_ranges = 0;
1406
1407   priv->manual_num_copies = 1;
1408   priv->manual_collation = FALSE;
1409   priv->manual_reverse = FALSE;
1410   priv->manual_page_set = GTK_PAGE_SET_ALL;
1411   priv->manual_scale = 1.0;
1412   priv->manual_orientation = TRUE;
1413   
1414   *do_print = TRUE;
1415   
1416   priv->start_page = pdf_start_page;
1417   priv->end_page = pdf_end_page;
1418   priv->end_run = pdf_end_run;
1419   
1420   return GTK_PRINT_OPERATION_RESULT_APPLY; 
1421 }
1422
1423 typedef struct
1424 {
1425   GtkPrintOperation *op;
1426   gboolean wait;
1427   gint uncollated_copies;
1428   gint collated_copies;
1429   gint uncollated, collated, total;
1430
1431   gint range, num_ranges;
1432   GtkPageRange *ranges;
1433   GtkPageRange one_range;
1434
1435   gint page, start, end, inc;
1436
1437   GtkPageSetup *initial_page_setup;
1438   GtkPrintContext *print_context;  
1439
1440   GtkWidget *progress;
1441 } PrintPagesData;
1442
1443 static void
1444 find_range (PrintPagesData *data)
1445 {
1446   GtkPageRange *range;
1447
1448   range = &data->ranges[data->range];
1449
1450   if (data->inc < 0)
1451     {
1452       data->start = range->end;
1453       data->end = range->start - 1;
1454     }
1455   else
1456     {
1457       data->start = range->start;
1458       data->end = range->end + 1;
1459     }
1460 }
1461
1462 static gboolean 
1463 increment_page_sequence (PrintPagesData *data)
1464 {
1465   GtkPrintOperationPrivate *priv = data->op->priv;
1466
1467   do {
1468     data->page += data->inc;
1469     if (data->page == data->end)
1470       {
1471         data->range += data->inc;
1472         if (data->range == -1 || data->range == data->num_ranges)
1473           {
1474             data->uncollated++;
1475             if (data->uncollated == data->uncollated_copies)
1476               return FALSE;
1477
1478             data->range = data->inc < 0 ? data->num_ranges - 1 : 0;
1479           }
1480         find_range (data);
1481         data->page = data->start;
1482       }
1483   }
1484   while ((priv->manual_page_set == GTK_PAGE_SET_EVEN && data->page % 2 == 0) ||
1485          (priv->manual_page_set == GTK_PAGE_SET_ODD && data->page % 2 == 1));
1486
1487   return TRUE;
1488 }
1489
1490 static void
1491 print_pages_idle_done (gpointer user_data)
1492 {
1493   PrintPagesData *data;
1494   GtkPrintOperationPrivate *priv;
1495
1496   GDK_THREADS_ENTER ();
1497
1498   data = (PrintPagesData*)user_data;
1499   priv = data->op->priv;
1500
1501   priv->print_pages_idle_id = 0;
1502
1503   if (priv->show_progress_timeout_id > 0)
1504     {
1505       g_source_remove (priv->show_progress_timeout_id);
1506       priv->show_progress_timeout_id = 0;
1507     }
1508
1509   if (data->progress)
1510     gtk_widget_destroy (data->progress);
1511
1512   g_object_unref (data->print_context);
1513   g_object_unref (data->initial_page_setup);
1514
1515   g_object_unref (data->op);
1516   g_free (data);
1517
1518   GDK_THREADS_LEAVE ();
1519 }
1520
1521 static void
1522 update_progress (PrintPagesData *data)
1523 {
1524   GtkPrintOperationPrivate *priv; 
1525   gchar *text = NULL;
1526   
1527   priv = data->op->priv;
1528  
1529   if (data->progress)
1530     {
1531       if (priv->status == GTK_PRINT_STATUS_PREPARING)
1532         {
1533           if (priv->nr_of_pages > 0)
1534             text = g_strdup_printf (_("Preparing %d"), priv->nr_of_pages);
1535           else
1536             text = g_strdup (_("Preparing"));
1537         }
1538       else if (priv->status == GTK_PRINT_STATUS_GENERATING_DATA)
1539         text = g_strdup_printf (_("Printing %d"), data->total);
1540       
1541       if (text)
1542         {
1543           g_object_set (data->progress, "text", text, NULL);
1544           g_free (text);
1545         }
1546     }
1547  }
1548
1549 static gboolean
1550 print_pages_idle (gpointer user_data)
1551 {
1552   PrintPagesData *data; 
1553   GtkPrintOperationPrivate *priv; 
1554   GtkPageSetup *page_setup;
1555   cairo_t *cr;
1556   gboolean done = FALSE;
1557
1558   GDK_THREADS_ENTER ();
1559
1560   data = (PrintPagesData*)user_data;
1561   priv = data->op->priv;
1562
1563   if (priv->status == GTK_PRINT_STATUS_PREPARING)
1564     {
1565       if (g_signal_has_handler_pending (data->op, signals[PAGINATE], 0, FALSE))
1566         {
1567           gboolean paginated = FALSE;
1568           g_signal_emit (data->op, signals[PAGINATE], 0, data->print_context, &paginated);
1569           if (!paginated)
1570             goto out;
1571         }
1572
1573       /* FIXME handle this better */
1574       if (priv->nr_of_pages == 0)
1575         g_warning ("no pages to print");
1576       
1577       /* Initialize parts of PrintPagesData that depend on nr_of_pages
1578        */
1579       if (priv->print_pages == GTK_PRINT_PAGES_RANGES)
1580         {
1581           data->ranges = priv->page_ranges;
1582           data->num_ranges = priv->num_page_ranges;
1583         }
1584       else if (priv->print_pages == GTK_PRINT_PAGES_CURRENT &&
1585                priv->current_page != -1)
1586         {
1587           data->ranges = &data->one_range;
1588           data->num_ranges = 1;
1589           data->ranges[0].start = priv->current_page;
1590           data->ranges[0].end = priv->current_page;
1591         }
1592       else
1593         {
1594           data->ranges = &data->one_range;
1595           data->num_ranges = 1;
1596           data->ranges[0].start = 0;
1597           data->ranges[0].end = priv->nr_of_pages - 1;
1598         }
1599       
1600       if (data->op->priv->manual_reverse)
1601         {
1602           data->range = data->num_ranges - 1;
1603           data->inc = -1;      
1604         }
1605       else
1606         {
1607           data->range = 0;
1608           data->inc = 1;      
1609         }
1610       find_range (data);
1611      
1612       /* go back one page, since we preincrement below */
1613       data->page = data->start - data->inc;
1614       data->collated = data->collated_copies - 1;
1615
1616       _gtk_print_operation_set_status (data->op, 
1617                                        GTK_PRINT_STATUS_GENERATING_DATA, 
1618                                        NULL);
1619
1620       goto out;
1621     }
1622
1623   data->total++;
1624   data->collated++;
1625   if (data->collated == data->collated_copies)
1626     {
1627       data->collated = 0;
1628       if (!increment_page_sequence (data))
1629         {
1630           done = TRUE;
1631
1632           goto out;
1633         }
1634     }
1635
1636   page_setup = gtk_page_setup_copy (data->initial_page_setup);
1637   g_signal_emit (data->op, signals[REQUEST_PAGE_SETUP], 0, 
1638                  data->print_context, data->page, page_setup);
1639   
1640   _gtk_print_context_set_page_setup (data->print_context, page_setup);
1641   data->op->priv->start_page (data->op, data->print_context, page_setup);
1642   
1643   cr = gtk_print_context_get_cairo (data->print_context);
1644   
1645   cairo_save (cr);
1646   if (priv->manual_scale != 100.0)
1647     cairo_scale (cr,
1648                  priv->manual_scale,
1649                  priv->manual_scale);
1650   
1651   if (priv->manual_orientation)
1652     _gtk_print_context_rotate_according_to_orientation (data->print_context);
1653   
1654   if (!priv->use_full_page)
1655     _gtk_print_context_translate_into_margin (data->print_context);
1656   
1657   g_signal_emit (data->op, signals[DRAW_PAGE], 0, 
1658                  data->print_context, data->page);
1659   
1660   priv->end_page (data->op, data->print_context);
1661   
1662   cairo_restore (cr);
1663   
1664   g_object_unref (page_setup);
1665
1666  out:
1667
1668   if (priv->cancelled)
1669     {
1670       _gtk_print_operation_set_status (data->op, GTK_PRINT_STATUS_FINISHED_ABORTED, NULL);
1671       
1672       done = TRUE;
1673     }
1674
1675   if (done)
1676     {
1677       g_signal_emit (data->op, signals[END_PRINT], 0, data->print_context);
1678       
1679       cairo_surface_finish (data->op->priv->surface);
1680       priv->end_run (data->op, data->wait, priv->cancelled);
1681     }
1682
1683   update_progress (data);
1684
1685   GDK_THREADS_LEAVE ();
1686
1687   return !done;
1688 }
1689   
1690 static void
1691 handle_progress_response (GtkWidget *dialog, 
1692                           gint       response,
1693                           gpointer   data)
1694 {
1695   GtkPrintOperation *op = (GtkPrintOperation *)data;
1696
1697   gtk_widget_hide (dialog);
1698   gtk_print_operation_cancel (op);
1699 }
1700
1701 static gboolean
1702 show_progress_timeout (PrintPagesData *data)
1703 {
1704   GDK_THREADS_ENTER ();
1705
1706   gtk_window_present (data->progress);
1707
1708   data->op->priv->show_progress_timeout_id = 0;
1709
1710   GDK_THREADS_LEAVE ();
1711
1712   return FALSE;
1713 }
1714
1715 static void
1716 print_pages (GtkPrintOperation *op,
1717              GtkWindow         *parent,
1718              gboolean           wait)
1719 {
1720   GtkPrintOperationPrivate *priv = op->priv;
1721   GtkPageSetup *initial_page_setup;
1722   GtkPrintContext *print_context;
1723   int uncollated_copies, collated_copies;
1724   PrintPagesData *data;
1725   GtkWidget *progress = NULL;
1726  
1727   _gtk_print_operation_set_status (op, GTK_PRINT_STATUS_PREPARING, NULL);  
1728
1729   data = g_new0 (PrintPagesData, 1);
1730
1731   if (priv->show_progress)
1732     {
1733       progress = gtk_message_dialog_new (parent, 0, 
1734                                          GTK_MESSAGE_OTHER,
1735                                          GTK_BUTTONS_CANCEL,
1736                                          _("Preparing"));
1737       g_signal_connect (progress, "response", 
1738                         G_CALLBACK (handle_progress_response), op);
1739
1740       priv->show_progress_timeout_id = 
1741         g_timeout_add (SHOW_PROGRESS_TIME, 
1742                        (GSourceFunc)show_progress_timeout,
1743                        data);
1744     }
1745
1746   print_context = _gtk_print_context_new (op);
1747
1748   initial_page_setup = create_page_setup (op);
1749   _gtk_print_context_set_page_setup (print_context, initial_page_setup);
1750
1751   g_signal_emit (op, signals[BEGIN_PRINT], 0, print_context);
1752
1753   if (priv->manual_collation)
1754     {
1755       uncollated_copies = priv->manual_num_copies;
1756       collated_copies = 1;
1757     }
1758   else
1759     {
1760       uncollated_copies = 1;
1761       collated_copies = priv->manual_num_copies;
1762     }
1763
1764   data->op = g_object_ref (op);
1765   data->wait = wait;
1766   data->uncollated_copies = uncollated_copies;
1767   data->collated_copies = collated_copies;
1768   data->initial_page_setup = initial_page_setup;
1769   data->print_context = print_context;
1770   data->progress = progress;
1771
1772   if (wait)
1773     {
1774       /* FIXME replace this with a recursive mainloop */
1775       while (print_pages_idle (data))
1776         {
1777           /* Iterate the mainloop so that we redraw windows */
1778           while (gtk_events_pending ())
1779             gtk_main_iteration ();
1780         }
1781       print_pages_idle_done (data);
1782     }
1783   else
1784     priv->print_pages_idle_id = g_idle_add_full (G_PRIORITY_DEFAULT_IDLE,
1785                                                  print_pages_idle, 
1786                                                  data, 
1787                                                  print_pages_idle_done);}
1788
1789 /**
1790  * gtk_print_operation_run:
1791  * @op: a #GtkPrintOperation
1792  * @parent: Transient parent of the dialog, or %NULL
1793  * @error: Return location for errors, or %NULL
1794  * 
1795  * Runs the print operation, by first letting the user modify
1796  * print settings in the print dialog, and then print the
1797  * document.
1798  *
1799  * Note that this function does not return until the rendering of all 
1800  * pages is complete. You can connect to the ::status-changed signal on
1801  * @op to obtain some information about the progress of the print operation. 
1802  * Furthermore, it may use a recursive mainloop to show the print dialog.
1803  * See gtk_print_operation_run_async() if this is a problem.
1804  *
1805  * <informalexample><programlisting>
1806  *  FIXME: need an example here
1807  * </programlisting></informalexample>
1808  *
1809  * Return value: the result of the print operation. A return value of 
1810  *   %GTK_PRINT_OPERATION_RESULT_APPLY indicates that the printing was
1811  *   completed successfully. In this case, it is a good idea to obtain 
1812  *   the used print settings with gtk_print_operation_get_print_settings() 
1813  *   and store them for reuse with the next print operation.
1814  *
1815  * Since: 2.10
1816  **/
1817 GtkPrintOperationResult
1818 gtk_print_operation_run (GtkPrintOperation  *op,
1819                          GtkWindow          *parent,
1820                          GError            **error)
1821 {
1822   GtkPrintOperationPrivate *priv;
1823   GtkPrintOperationResult result;
1824   gboolean do_print;
1825   
1826   g_return_val_if_fail (GTK_IS_PRINT_OPERATION (op), 
1827                         GTK_PRINT_OPERATION_RESULT_ERROR);
1828
1829   priv = op->priv;
1830
1831   if (priv->pdf_target != NULL)
1832     result = run_pdf (op, parent, &do_print, error);
1833   else
1834     result = _gtk_print_operation_platform_backend_run_dialog (op, 
1835                                                                parent,
1836                                                                &do_print,
1837                                                                error);
1838   if (do_print)
1839     print_pages (op, parent, TRUE);
1840   else 
1841     _gtk_print_operation_set_status (op, GTK_PRINT_STATUS_FINISHED_ABORTED, NULL);
1842
1843   return result;
1844 }
1845
1846 /**
1847  * gtk_print_operation_run_async:
1848  * @op: a #GtkPrintOperation
1849  * @parent: Transient parent of the dialog, or %NULL
1850  * 
1851  * Runs the print operation, by first letting the user modify
1852  * print settings in the print dialog, and then print the
1853  * document.
1854  *
1855  * In contrast to gtk_print_operation_run(), this function returns after 
1856  * showing the print dialog on platforms that support this, and handles 
1857  * the printing by connecting a signal handler to the ::response signal 
1858  * of the dialog. 
1859  * 
1860  * If you use this function, it is recommended that you store the modified
1861  * #GtkPrintSettings in a ::begin-print or ::end-print signal handler.
1862  * 
1863  * Since: 2.10
1864  **/
1865 void
1866 gtk_print_operation_run_async (GtkPrintOperation *op,
1867                                GtkWindow         *parent)
1868 {
1869   GtkPrintOperationPrivate *priv;
1870   gboolean do_print;
1871
1872   g_return_if_fail (GTK_IS_PRINT_OPERATION (op)); 
1873
1874   priv = op->priv;
1875
1876   if (priv->pdf_target != NULL)
1877     {
1878       run_pdf (op, parent, &do_print, NULL);
1879       if (do_print)
1880         print_pages (op, parent, FALSE);
1881       else 
1882         _gtk_print_operation_set_status (op, GTK_PRINT_STATUS_FINISHED_ABORTED, NULL);
1883     }
1884   else
1885     _gtk_print_operation_platform_backend_run_dialog_async (op, 
1886                                                             parent,
1887                                                             print_pages);
1888 }
1889
1890
1891 /**
1892  * gtk_print_operation_cancel:
1893  * @op: a #GtkPrintOperation
1894  *
1895  * Cancels a running print operation. This function may
1896  * be called from a begin-print, paginate or draw-page
1897  * signal handler to stop the currently running print 
1898  * operation.
1899  *
1900  * Since: 2.10
1901  */
1902 void
1903 gtk_print_operation_cancel (GtkPrintOperation *op)
1904 {
1905   g_return_if_fail (GTK_IS_PRINT_OPERATION (op));
1906   
1907   op->priv->cancelled = TRUE;
1908 }
1909
1910
1911
1912 #define __GTK_PRINT_OPERATION_C__
1913 #include "gtkaliasdef.c"