]> www.fi.muni.cz Git - evince.git/blob - shell/ev-print-operation.c
e737d296be3d7f1dabf03421151491c86f7e42a4
[evince.git] / shell / ev-print-operation.c
1 /* this file is part of evince, a gnome document viewer
2  *
3  *  Copyright (C) 2008 Carlos Garcia Campos <carlosgc@gnome.org>
4  *
5  * Evince is free software; you can redistribute it and/or modify it
6  * under the terms of the GNU General Public License as published by
7  * the Free Software Foundation; either version 2 of the License, or
8  * (at your option) any later version.
9  *
10  * Evince is distributed in the hope that it will be useful, but
11  * WITHOUT ANY WARRANTY; without even the implied warranty of
12  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
13  * General Public License for more details.
14  *
15  * You should have received a copy of the GNU General Public License
16  * along with this program; if not, write to the Free Software
17  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307, USA.
18  */
19
20 #include <config.h>
21
22 #include "ev-print-operation.h"
23
24 #include <gtk/gtkunixprint.h>
25 #include <glib/gi18n.h>
26 #include <glib/gstdio.h>
27 #include <unistd.h>
28
29 #include "ev-page-cache.h"
30 #include "ev-file-exporter.h"
31 #include "ev-jobs.h"
32 #include "ev-job-scheduler.h"
33 #include "ev-application.h"
34 #include "ev-file-helpers.h"
35 #include "ev-document-print.h"
36
37 enum {
38         PROP_0,
39         PROP_DOCUMENT
40 };
41
42 enum {
43         DONE,
44         BEGIN_PRINT,
45         STATUS_CHANGED,
46         LAST_SIGNAL
47 };
48
49 static guint signals[LAST_SIGNAL] = { 0 };
50
51 struct _EvPrintOperation {
52         GObject parent;
53
54         EvDocument *document;
55
56         /* Progress */
57         gchar      *status;
58         gdouble     progress;
59 };
60
61 struct _EvPrintOperationClass {
62         GObjectClass parent_class;
63
64         void              (* set_current_page)       (EvPrintOperation       *op,
65                                                       gint                    current_page);
66         void              (* set_print_settings)     (EvPrintOperation       *op,
67                                                       GtkPrintSettings       *print_settings);
68         GtkPrintSettings *(* get_print_settings)     (EvPrintOperation       *op);
69         void              (* set_default_page_setup) (EvPrintOperation       *op,
70                                                       GtkPageSetup           *page_setup);
71         GtkPageSetup     *(* get_default_page_setup) (EvPrintOperation       *op);
72         void              (* set_job_name)           (EvPrintOperation       *op,
73                                                       const gchar            *job_name);
74         const gchar      *(* get_job_name)           (EvPrintOperation       *op);
75         void              (* run)                    (EvPrintOperation       *op,
76                                                       GtkWindow              *parent);
77         void              (* cancel)                 (EvPrintOperation       *op);
78         void              (* get_error)              (EvPrintOperation       *op,
79                                                       GError                **error);
80
81         /* signals */
82         void              (* done)                   (EvPrintOperation       *op,
83                                                       GtkPrintOperationResult result);
84         void              (* begin_print)            (EvPrintOperation       *op);
85         void              (* status_changed)         (EvPrintOperation       *op);
86 };
87
88 G_DEFINE_ABSTRACT_TYPE (EvPrintOperation, ev_print_operation, G_TYPE_OBJECT)
89
90 static void
91 ev_print_operation_finalize (GObject *object)
92 {
93         EvPrintOperation *op = EV_PRINT_OPERATION (object);
94
95         if (op->document) {
96                 g_object_unref (op->document);
97                 op->document = NULL;
98         }
99
100         if (op->status) {
101                 g_free (op->status);
102                 op->status = NULL;
103         }
104
105         (* G_OBJECT_CLASS (ev_print_operation_parent_class)->finalize) (object);
106 }
107
108 static void
109 ev_print_operation_set_property (GObject      *object,
110                                  guint         prop_id,
111                                  const GValue *value,
112                                  GParamSpec   *pspec)
113 {
114         EvPrintOperation *op = EV_PRINT_OPERATION (object);
115
116         switch (prop_id) {
117         case PROP_DOCUMENT:
118                 op->document = g_value_dup_object (value);
119                 break;
120         default:
121                 G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
122         }
123 }
124
125 static void
126 ev_print_operation_init (EvPrintOperation *op)
127 {
128 }
129
130 static void
131 ev_print_operation_class_init (EvPrintOperationClass *klass)
132 {
133         GObjectClass *g_object_class = G_OBJECT_CLASS (klass);
134
135         g_object_class->set_property = ev_print_operation_set_property;
136         g_object_class->finalize = ev_print_operation_finalize;
137
138         g_object_class_install_property (g_object_class,
139                                          PROP_DOCUMENT,
140                                          g_param_spec_object ("document",
141                                                               "Document",
142                                                               "The document to print",
143                                                               EV_TYPE_DOCUMENT,
144                                                               G_PARAM_WRITABLE |
145                                                               G_PARAM_CONSTRUCT_ONLY));
146         signals[DONE] =
147                 g_signal_new ("done",
148                               G_TYPE_FROM_CLASS (g_object_class),
149                               G_SIGNAL_RUN_LAST,
150                               G_STRUCT_OFFSET (EvPrintOperationClass, done),
151                               NULL, NULL,
152                               g_cclosure_marshal_VOID__ENUM,
153                               G_TYPE_NONE, 1,
154                               GTK_TYPE_PRINT_OPERATION_RESULT);
155         signals[BEGIN_PRINT] =
156                 g_signal_new ("begin_print",
157                               G_TYPE_FROM_CLASS (g_object_class),
158                               G_SIGNAL_RUN_LAST,
159                               G_STRUCT_OFFSET (EvPrintOperationClass, begin_print),
160                               NULL, NULL,
161                               g_cclosure_marshal_VOID__VOID,
162                               G_TYPE_NONE, 0);
163         signals[STATUS_CHANGED] =
164                 g_signal_new ("status_changed",
165                               G_TYPE_FROM_CLASS (g_object_class),
166                               G_SIGNAL_RUN_LAST,
167                               G_STRUCT_OFFSET (EvPrintOperationClass, status_changed),
168                               NULL, NULL,
169                               g_cclosure_marshal_VOID__VOID,
170                               G_TYPE_NONE, 0);
171 }
172
173 /* Public methods */
174 void
175 ev_print_operation_set_current_page (EvPrintOperation *op,
176                                      gint              current_page)
177 {
178         EvPrintOperationClass *class = EV_PRINT_OPERATION_GET_CLASS (op);
179
180         g_return_if_fail (EV_IS_PRINT_OPERATION (op));
181         g_return_if_fail (current_page >= 0);
182
183         class->set_current_page (op, current_page);
184 }
185
186 void
187 ev_print_operation_set_print_settings (EvPrintOperation *op,
188                                        GtkPrintSettings *print_settings)
189 {
190         EvPrintOperationClass *class = EV_PRINT_OPERATION_GET_CLASS (op);
191
192         g_return_if_fail (EV_IS_PRINT_OPERATION (op));
193         g_return_if_fail (GTK_IS_PRINT_SETTINGS (print_settings));
194
195         class->set_print_settings (op, print_settings);
196 }
197
198 GtkPrintSettings *
199 ev_print_operation_get_print_settings (EvPrintOperation *op)
200 {
201         EvPrintOperationClass *class = EV_PRINT_OPERATION_GET_CLASS (op);
202
203         g_return_val_if_fail (EV_IS_PRINT_OPERATION (op), NULL);
204
205         return class->get_print_settings (op);
206 }
207
208 void
209 ev_print_operation_set_default_page_setup (EvPrintOperation *op,
210                                            GtkPageSetup     *page_setup)
211 {
212         EvPrintOperationClass *class = EV_PRINT_OPERATION_GET_CLASS (op);
213
214         g_return_if_fail (EV_IS_PRINT_OPERATION (op));
215         g_return_if_fail (GTK_IS_PAGE_SETUP (page_setup));
216
217         class->set_default_page_setup (op, page_setup);
218 }
219
220 GtkPageSetup *
221 ev_print_operation_get_default_page_setup (EvPrintOperation *op)
222 {
223         EvPrintOperationClass *class = EV_PRINT_OPERATION_GET_CLASS (op);
224
225         g_return_val_if_fail (EV_IS_PRINT_OPERATION (op), NULL);
226
227         return class->get_default_page_setup (op);
228 }
229
230 void
231 ev_print_operation_set_job_name (EvPrintOperation *op,
232                                  const gchar      *job_name)
233 {
234         EvPrintOperationClass *class = EV_PRINT_OPERATION_GET_CLASS (op);
235
236         g_return_if_fail (EV_IS_PRINT_OPERATION (op));
237         g_return_if_fail (job_name != NULL);
238
239         class->set_job_name (op, job_name);
240 }
241
242 const gchar *
243 ev_print_operation_get_job_name (EvPrintOperation *op)
244 {
245         EvPrintOperationClass *class = EV_PRINT_OPERATION_GET_CLASS (op);
246
247         g_return_val_if_fail (EV_IS_PRINT_OPERATION (op), NULL);
248
249         return class->get_job_name (op);
250 }
251
252 void
253 ev_print_operation_run (EvPrintOperation *op,
254                         GtkWindow        *parent)
255 {
256         EvPrintOperationClass *class = EV_PRINT_OPERATION_GET_CLASS (op);
257
258         g_return_if_fail (EV_IS_PRINT_OPERATION (op));
259
260         class->run (op, parent);
261 }
262
263 void
264 ev_print_operation_cancel (EvPrintOperation *op)
265 {
266         EvPrintOperationClass *class = EV_PRINT_OPERATION_GET_CLASS (op);
267
268         g_return_if_fail (EV_IS_PRINT_OPERATION (op));
269
270         class->cancel (op);
271 }
272
273 void
274 ev_print_operation_get_error (EvPrintOperation *op,
275                               GError          **error)
276 {
277         EvPrintOperationClass *class = EV_PRINT_OPERATION_GET_CLASS (op);
278
279         g_return_if_fail (EV_IS_PRINT_OPERATION (op));
280
281         class->get_error (op, error);
282 }
283
284 const gchar *
285 ev_print_operation_get_status (EvPrintOperation *op)
286 {
287         g_return_val_if_fail (EV_IS_PRINT_OPERATION (op), NULL);
288
289         return op->status ? op->status : "";
290 }
291
292 gdouble
293 ev_print_operation_get_progress (EvPrintOperation *op)
294 {
295         g_return_val_if_fail (EV_IS_PRINT_OPERATION (op), 0.0);
296
297         return op->progress;
298 }
299
300 static void
301 ev_print_operation_update_status (EvPrintOperation *op,
302                                   gint              page,
303                                   gint              n_pages,
304                                   gdouble           progress)
305 {
306         if (op->status && op->progress == progress)
307                 return;
308
309         g_free (op->status);
310
311         if (page == -1) {
312                 /* Initial state */
313                 op->status = g_strdup (_("Preparing to print ..."));
314         } else if (page > n_pages) {
315                 op->status = g_strdup (_("Finishing..."));
316         } else {
317                 op->status = g_strdup_printf (_("Printing page %d of %d..."),
318                                               page, n_pages);
319         }
320
321         op->progress = MIN (1.0, progress);
322
323         g_signal_emit (op, signals[STATUS_CHANGED], 0);
324 }
325
326 /* Export interface */
327 #define EV_TYPE_PRINT_OPERATION_EXPORT         (ev_print_operation_export_get_type())
328 #define EV_PRINT_OPERATION_EXPORT(object)      (G_TYPE_CHECK_INSTANCE_CAST((object), EV_TYPE_PRINT_OPERATION_EXPORT, EvPrintOperationExport))
329 #define EV_PRINT_OPERATION_EXPORT_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST((klass), EV_TYPE_PRINT_OPERATION_EXPORT, EvPrintOperationExportClass))
330 #define EV_IS_PRINT_OPERATION_EXPORT(object)   (G_TYPE_CHECK_INSTANCE_TYPE((object), EV_TYPE_PRINT_OPERATION_EXPORT))
331
332 typedef struct _EvPrintOperationExport      EvPrintOperationExport;
333 typedef struct _EvPrintOperationExportClass EvPrintOperationExportClass;
334
335 static GType    ev_print_operation_export_get_type (void) G_GNUC_CONST;
336
337 static void     ev_print_operation_export_begin    (EvPrintOperationExport *export);
338 static gboolean export_print_page                  (EvPrintOperationExport *export);
339 static void     export_cancel                      (EvPrintOperationExport *export);
340
341 struct _EvPrintOperationExport {
342         EvPrintOperation parent;
343
344         GtkWindow *parent_window;
345         EvJob *job_export;
346         GError *error;
347
348         gboolean print_preview;
349         gint n_pages;
350         gint current_page;
351         GtkPrinter *printer;
352         GtkPageSetup *page_setup;
353         GtkPrintSettings *print_settings;
354         GtkPageSet page_set;
355         gint copies;
356         guint collate     : 1;
357         guint reverse     : 1;
358         gint pages_per_sheet;
359         gint fd;
360         gchar *temp_file;
361         gchar *job_name;
362         
363         guint idle_id;
364         
365         /* Context */
366         EvFileExporterContext fc;
367         gint n_pages_to_print;
368         gint uncollated_copies;
369         gint collated_copies;
370         gint uncollated, collated, total, blank;
371
372         gint range, n_ranges;
373         GtkPageRange *ranges;
374         GtkPageRange one_range;
375
376         gint page, start, end, inc;
377 };
378
379 struct _EvPrintOperationExportClass {
380         EvPrintOperationClass parent_class;
381 };
382
383 G_DEFINE_TYPE (EvPrintOperationExport, ev_print_operation_export, EV_TYPE_PRINT_OPERATION)
384
385 /* Internal print queue */
386 static GHashTable *print_queue = NULL;
387
388 static void
389 queue_free (GQueue *queue)
390 {
391         g_queue_foreach (queue, (GFunc)g_object_unref, NULL);
392         g_queue_free (queue);
393 }
394
395 static void
396 ev_print_queue_init (void)
397 {
398         if (G_UNLIKELY (print_queue == NULL)) {
399                 print_queue = g_hash_table_new_full (g_direct_hash,
400                                                      g_direct_equal,
401                                                      NULL,
402                                                      (GDestroyNotify)queue_free);
403         }
404 }
405
406 static void
407 remove_document_queue (gpointer data,
408                        GObject *document)
409 {
410         if (print_queue)
411                 g_hash_table_remove (print_queue, document);
412 }
413
414 static gboolean
415 ev_print_queue_is_empty (EvDocument *document)
416 {
417         GQueue *queue;
418
419         queue = g_hash_table_lookup (print_queue, document);
420         return (!queue || g_queue_is_empty (queue));
421 }
422
423 static void
424 ev_print_queue_push (EvPrintOperation *op)
425 {
426         GQueue *queue;
427
428         queue = g_hash_table_lookup (print_queue, op->document);
429         if (!queue) {
430                 queue = g_queue_new ();
431                 g_hash_table_insert (print_queue,
432                                      op->document,
433                                      queue);
434                 g_object_weak_ref (G_OBJECT (op->document),
435                                    (GWeakNotify)remove_document_queue,
436                                    NULL);
437         }
438
439         g_queue_push_head (queue, g_object_ref (op));
440 }
441
442 static EvPrintOperation *
443 ev_print_queue_pop (EvDocument *document)
444 {
445         EvPrintOperation *op;
446         GQueue           *queue;
447
448         queue = g_hash_table_lookup (print_queue, document);
449         if (!queue || g_queue_is_empty (queue))
450                 return NULL;
451         
452         op = g_queue_pop_tail (queue);
453         g_object_unref (op);
454
455         return op;
456 }
457
458 static EvPrintOperation *
459 ev_print_queue_peek (EvDocument *document)
460 {
461         GQueue *queue;
462
463         queue = g_hash_table_lookup (print_queue, document);
464         if (!queue || g_queue_is_empty (queue))
465                 return NULL;
466
467         return g_queue_peek_tail (queue);
468 }
469
470 static void
471 ev_print_operation_export_set_current_page (EvPrintOperation *op,
472                                             gint              current_page)
473 {
474         EvPrintOperationExport *export = EV_PRINT_OPERATION_EXPORT (op);
475
476         g_return_if_fail (current_page < export->n_pages);
477         
478         export->current_page = current_page;
479 }
480
481 static void
482 ev_print_operation_export_set_print_settings (EvPrintOperation *op,
483                                               GtkPrintSettings *print_settings)
484 {
485         EvPrintOperationExport *export = EV_PRINT_OPERATION_EXPORT (op);
486
487         if (print_settings == export->print_settings)
488                 return;
489
490         g_object_ref (print_settings);
491         if (export->print_settings)
492                 g_object_unref (export->print_settings);
493         export->print_settings = print_settings;
494 }
495
496 static GtkPrintSettings *
497 ev_print_operation_export_get_print_settings (EvPrintOperation *op)
498 {
499         EvPrintOperationExport *export = EV_PRINT_OPERATION_EXPORT (op);
500
501         return export->print_settings;
502 }
503
504 static void
505 ev_print_operation_export_set_default_page_setup (EvPrintOperation *op,
506                                                   GtkPageSetup     *page_setup)
507 {
508         EvPrintOperationExport *export = EV_PRINT_OPERATION_EXPORT (op);
509
510         if (page_setup == export->page_setup)
511                 return;
512
513         g_object_ref (page_setup);
514         if (export->page_setup)
515                 g_object_unref (export->page_setup);
516         export->page_setup = page_setup;
517 }
518
519 static GtkPageSetup *
520 ev_print_operation_export_get_default_page_setup (EvPrintOperation *op)
521 {
522         EvPrintOperationExport *export = EV_PRINT_OPERATION_EXPORT (op);
523
524         return export->page_setup;
525 }
526
527 static void
528 ev_print_operation_export_set_job_name (EvPrintOperation *op,
529                                         const gchar      *job_name)
530 {
531         EvPrintOperationExport *export = EV_PRINT_OPERATION_EXPORT (op);
532
533         g_free (export->job_name);
534         export->job_name = g_strdup (job_name);
535 }
536
537 static const gchar *
538 ev_print_operation_export_get_job_name (EvPrintOperation *op)
539 {
540         EvPrintOperationExport *export = EV_PRINT_OPERATION_EXPORT (op);
541
542         return export->job_name;
543 }
544
545 static void
546 ev_print_operation_export_set_printer (EvPrintOperationExport *export,
547                                        GtkPrinter             *printer)
548 {
549         if (printer == export->printer)
550                 return;
551
552         g_object_ref (printer);
553         if (export->printer)
554                 g_object_unref (export->printer);
555         export->printer = printer;
556 }
557
558 static void
559 find_range (EvPrintOperationExport *export)
560 {
561         GtkPageRange *range;
562
563         range = &export->ranges[export->range];
564
565         if (export->inc < 0) {
566                 export->start = range->end;
567                 export->end = range->start - 1;
568         } else {
569                 export->start = range->start;
570                 export->end = range->end + 1;
571         }
572 }
573
574 static gboolean
575 clamp_ranges (EvPrintOperationExport *export)
576 {
577         gint num_of_correct_ranges = 0;
578         gint n_pages_to_print = 0;
579         gint i;
580         gboolean null_flag = FALSE;
581
582         for (i = 0; i < export->n_ranges; i++) {
583                 gint n_pages;
584                 
585                 if ((export->ranges[i].start >= 0) &&
586                     (export->ranges[i].start < export->n_pages) &&
587                     (export->ranges[i].end >= 0) &&
588                     (export->ranges[i].end < export->n_pages)) {
589                         export->ranges[num_of_correct_ranges] = export->ranges[i];
590                         num_of_correct_ranges++;
591                 } else if ((export->ranges[i].start >= 0) &&
592                            (export->ranges[i].start < export->n_pages) &&
593                            (export->ranges[i].end >= export->n_pages)) {
594                         export->ranges[i].end = export->n_pages - 1;
595                         export->ranges[num_of_correct_ranges] = export->ranges[i];
596                         num_of_correct_ranges++;
597                 } else if ((export->ranges[i].end >= 0) &&
598                            (export->ranges[i].end < export->n_pages) &&
599                            (export->ranges[i].start < 0)) {
600                         export->ranges[i].start = 0;
601                         export->ranges[num_of_correct_ranges] = export->ranges[i];
602                         num_of_correct_ranges++;
603                 }
604                 
605                 n_pages = export->ranges[i].end - export->ranges[i].start + 1;
606                 if (export->page_set == GTK_PAGE_SET_ALL) {
607                         n_pages_to_print += n_pages;
608                 } else if (n_pages % 2 == 0) {
609                         n_pages_to_print += n_pages / 2;
610                 } else if (export->page_set == GTK_PAGE_SET_EVEN) {
611                         if (n_pages==1 && export->ranges[i].start % 2 == 0)
612                                 null_flag = TRUE;
613                         else 
614                                 n_pages_to_print += export->ranges[i].start % 2 == 0 ?
615                                 n_pages / 2 : (n_pages / 2) + 1;
616                 } else if (export->page_set == GTK_PAGE_SET_ODD) {
617                         if (n_pages==1 && export->ranges[i].start % 2 != 0) 
618                                 null_flag = TRUE;
619                         else 
620                                 n_pages_to_print += export->ranges[i].start % 2 == 0 ?
621                                 (n_pages / 2) + 1 : n_pages / 2;
622                 }
623         }
624
625         if (null_flag && !n_pages_to_print) {
626                 return FALSE;
627         } else {
628                 export->n_ranges = num_of_correct_ranges;
629                 export->n_pages_to_print = n_pages_to_print;
630                 return TRUE;
631         }
632 }
633
634 static void
635 get_first_and_last_page (EvPrintOperationExport *export,
636                          gint                   *first,
637                          gint                   *last)
638 {
639         gint i;
640         gint first_page = G_MAXINT;
641         gint last_page = G_MININT;
642         gint max_page = export->n_pages - 1;
643
644         if (export->n_ranges == 0) {
645                 *first = 0;
646                 *last = max_page;
647
648                 return;
649         }
650
651         for (i = 0; i < export->n_ranges; i++) {
652                 if (export->ranges[i].start < first_page)
653                         first_page = export->ranges[i].start;
654                 if (export->ranges[i].end > last_page)
655                         last_page = export->ranges[i].end;
656         }
657
658         *first = MAX (0, first_page);
659         *last = MIN (max_page, last_page);
660 }
661
662 static gboolean
663 export_print_inc_page (EvPrintOperationExport *export)
664 {
665         do {
666                 export->page += export->inc;
667                 if (export->page == export->end) {
668                         export->range += export->inc;
669                         if (export->range == -1 || export->range == export->n_ranges) {
670                                 export->uncollated++;
671                                 if (export->uncollated == export->uncollated_copies)
672                                         return FALSE;
673
674                                 export->range = export->inc < 0 ? export->n_ranges - 1 : 0;
675                         }
676                         find_range (export);
677                         export->page = export->start;
678                 }
679         } while ((export->page_set == GTK_PAGE_SET_EVEN && (export->page / export->pages_per_sheet) % 2 == 0) ||
680                  (export->page_set == GTK_PAGE_SET_ODD && (export->page  / export->pages_per_sheet) % 2 == 1));
681
682         return TRUE;
683 }
684
685 static void
686 ev_print_operation_export_clear_temp_file (EvPrintOperationExport *export)
687 {
688         if (!export->temp_file)
689                 return;
690
691         g_unlink (export->temp_file);
692         g_free (export->temp_file);
693         export->temp_file = NULL;
694 }
695
696 static void
697 ev_print_operation_export_run_next (EvPrintOperationExport *export)
698 {
699         EvPrintOperation *op = EV_PRINT_OPERATION (export);
700         EvPrintOperation *next;
701         EvDocument       *document;
702
703         /* First pop the current job */
704         document = op->document;
705         ev_print_queue_pop (document);
706         
707         next = ev_print_queue_peek (document);
708         if (next)
709                 ev_print_operation_export_begin (EV_PRINT_OPERATION_EXPORT (next));
710 }
711
712 static void
713 gtk_print_job_finished (GtkPrintJob            *print_job,
714                         EvPrintOperationExport *export,
715                         GError                 *error)
716 {
717         EvPrintOperation *op = EV_PRINT_OPERATION (export);
718
719         if (error) {
720                 g_set_error_literal (&export->error,
721                                      GTK_PRINT_ERROR,
722                                      GTK_PRINT_ERROR_GENERAL,
723                                      error->message);
724                 g_signal_emit (op, signals[DONE], 0, GTK_PRINT_OPERATION_RESULT_ERROR);
725         } else {
726                 g_signal_emit (op, signals[DONE], 0, GTK_PRINT_OPERATION_RESULT_APPLY);
727         }
728
729         ev_print_operation_export_clear_temp_file (export);
730         g_object_unref (print_job);
731
732         ev_print_operation_export_run_next (export);
733 }
734
735 static void
736 export_print_done (EvPrintOperationExport *export)
737 {
738         EvPrintOperation *op = EV_PRINT_OPERATION (export);
739         GtkPrintSettings *settings;
740         EvFileExporterCapabilities capabilities;
741         GError *error = NULL;
742
743         g_assert (export->temp_file != NULL);
744         
745         /* Some printers take into account some print settings,
746          * and others don't. However we have exported the document
747          * to a ps or pdf file according to such print settings. So,
748          * we want to send the exported file to printer with those
749          * settings set to default values.
750          */
751         settings = gtk_print_settings_copy (export->print_settings);
752         capabilities = ev_file_exporter_get_capabilities (EV_FILE_EXPORTER (op->document));
753
754         gtk_print_settings_set_page_ranges (settings, NULL, 0);
755         gtk_print_settings_set_print_pages (settings, GTK_PRINT_PAGES_ALL);
756         if (capabilities & EV_FILE_EXPORTER_CAN_COPIES)
757                 gtk_print_settings_set_n_copies (settings, 1);
758         if (capabilities & EV_FILE_EXPORTER_CAN_PAGE_SET)
759                 gtk_print_settings_set_page_set (settings, GTK_PAGE_SET_ALL);
760         if (capabilities & EV_FILE_EXPORTER_CAN_SCALE)
761                 gtk_print_settings_set_scale (settings, 1.0);
762         if (capabilities & EV_FILE_EXPORTER_CAN_COLLATE)
763                 gtk_print_settings_set_collate (settings, FALSE);
764         if (capabilities & EV_FILE_EXPORTER_CAN_REVERSE)
765                 gtk_print_settings_set_reverse (settings, FALSE);
766         if (capabilities & EV_FILE_EXPORTER_CAN_NUMBER_UP) {
767                 gtk_print_settings_set_number_up (settings, 1);
768                 gtk_print_settings_set_int (settings, "cups-"GTK_PRINT_SETTINGS_NUMBER_UP, 1);
769         }
770
771         if (export->print_preview) {
772                 GKeyFile *key_file;
773                 gchar    *data = NULL;
774                 gsize     data_len;
775                 gchar    *print_settings_file = NULL;
776
777                 key_file = g_key_file_new ();
778
779                 gtk_print_settings_to_key_file (settings, key_file, NULL);
780                 gtk_page_setup_to_key_file (export->page_setup, key_file, NULL);
781                 g_key_file_set_string (key_file, "Print Job", "title", export->job_name);
782
783                 data = g_key_file_to_data (key_file, &data_len, &error);
784                 if (data) {
785                         gint fd;
786                         
787                         fd = g_file_open_tmp ("print-settingsXXXXXX", &print_settings_file, &error);
788                         if (!error)
789                                 g_file_set_contents (print_settings_file, data, data_len, &error);
790                         close (fd);
791                         
792                         g_free (data);
793                 }
794
795                 g_key_file_free (key_file);
796
797                 if (!error) {
798                         gint    argc;
799                         gchar **argv;
800                         gchar  *cmd;
801                         gchar  *quoted_filename;
802                         gchar  *quoted_settings_filename;
803
804                         quoted_filename = g_shell_quote (export->temp_file);
805                         quoted_settings_filename = g_shell_quote (print_settings_file);
806                         cmd = g_strdup_printf ("evince-previewer --unlink-tempfile --print-settings %s %s",
807                                                quoted_settings_filename, quoted_filename);
808
809                         g_shell_parse_argv (cmd, &argc, &argv, &error);
810
811                         g_free (quoted_filename);
812                         g_free (quoted_settings_filename);
813                         g_free (cmd);
814
815                         if (!error) {
816                                 gdk_spawn_on_screen (gtk_window_get_screen (export->parent_window),
817                                                      NULL, argv, NULL,
818                                                      G_SPAWN_SEARCH_PATH,
819                                                      NULL, NULL, NULL,
820                                                      &error);
821                         }
822
823                         g_strfreev (argv);
824                 }
825
826                 if (error) {
827                         if (print_settings_file)
828                                 g_unlink (print_settings_file);
829                         g_free (print_settings_file);
830                 } else {
831                         g_signal_emit (op, signals[DONE], 0, GTK_PRINT_OPERATION_RESULT_APPLY);
832                         /* temp_file will be deleted by the previewer */
833
834                         ev_print_operation_export_run_next (export);
835                 }
836         } else {
837                 GtkPrintJob *job;
838                 
839                 job = gtk_print_job_new (export->job_name,
840                                          export->printer,
841                                          settings,
842                                          export->page_setup);
843                 gtk_print_job_set_source_file (job, export->temp_file, &error);
844                 if (!error){
845                         gtk_print_job_send (job,
846                                             (GtkPrintJobCompleteFunc)gtk_print_job_finished,
847                                             g_object_ref (export),
848                                             (GDestroyNotify)g_object_unref);
849                 }
850         }
851         g_object_unref (settings);
852
853         if (error) {
854                 g_set_error_literal (&export->error,
855                                      GTK_PRINT_ERROR,
856                                      GTK_PRINT_ERROR_GENERAL,
857                                      error->message);
858                 g_error_free (error);
859                 ev_print_operation_export_clear_temp_file (export);
860                 g_signal_emit (op, signals[DONE], 0, GTK_PRINT_OPERATION_RESULT_ERROR);
861
862                 ev_print_operation_export_run_next (export);
863         }
864 }
865
866 static void
867 export_print_page_idle_finished (EvPrintOperationExport *export)
868 {
869         export->idle_id = 0;
870 }
871
872 static void
873 export_job_finished (EvJobExport            *job,
874                      EvPrintOperationExport *export)
875 {
876         EvPrintOperation *op = EV_PRINT_OPERATION (export);
877
878         if (export->pages_per_sheet == 1 || (export->total + export->blank) % export->pages_per_sheet == 0 ) {
879                 ev_document_doc_mutex_lock ();
880                 ev_file_exporter_end_page (EV_FILE_EXPORTER (op->document));
881                 ev_document_doc_mutex_unlock ();
882         }
883
884         /* Reschedule */
885         export->idle_id = g_idle_add_full (G_PRIORITY_DEFAULT_IDLE,
886                                            (GSourceFunc)export_print_page,
887                                            export,
888                                            (GDestroyNotify)export_print_page_idle_finished);
889 }
890
891 static void
892 export_job_cancelled (EvJobExport            *job,
893                       EvPrintOperationExport *export)
894 {
895         export_cancel (export);
896 }
897
898 static void
899 export_cancel (EvPrintOperationExport *export)
900 {
901         EvPrintOperation *op = EV_PRINT_OPERATION (export);
902
903         if (export->idle_id > 0)
904                 g_source_remove (export->idle_id);
905         export->idle_id = 0;
906
907         if (export->job_export) {
908                 g_signal_handlers_disconnect_by_func (export->job_export,
909                                                       export_job_finished,
910                                                       export);
911                 g_signal_handlers_disconnect_by_func (export->job_export,
912                                                       export_job_cancelled,
913                                                       export);
914                 g_object_unref (export->job_export);
915                 export->job_export = NULL;
916         }
917         
918         if (export->fd != -1) {
919                 close (export->fd);
920                 export->fd = -1;
921         }
922
923         ev_print_operation_export_clear_temp_file (export);
924
925         g_signal_emit (op, signals[DONE], 0, GTK_PRINT_OPERATION_RESULT_CANCEL);
926
927         ev_print_operation_export_run_next (export);
928 }
929
930 static void
931 update_progress (EvPrintOperationExport *export)
932 {
933         EvPrintOperation *op = EV_PRINT_OPERATION (export);
934
935         ev_print_operation_update_status (op, export->total,
936                                           export->n_pages_to_print,
937                                           export->total / (gdouble)export->n_pages_to_print);
938 }
939
940 static gboolean
941 export_print_page (EvPrintOperationExport *export)
942 {
943         EvPrintOperation *op = EV_PRINT_OPERATION (export);
944
945         if (!export->temp_file)
946                 return FALSE; /* cancelled */
947         
948         export->total++;
949         export->collated++;
950
951         /* when printing multiple collated copies & multiple pages per sheet we want to
952            prevent the next copy bleeding into the last sheet of the previous one
953            we therefore check whether we've reached the last page in a document
954            if that is the case and the given sheet is not filled with pages,
955            we introduce a few blank pages to finish off the sheet
956            to make sure nothing goes wrong, the final condition ensures that
957            we're not at the end of a sheet, otherwise we'd introduce a blank sheet! */
958
959         if (export->collate == 1 && export->total > 1 && export->pages_per_sheet > 1 &&
960             (export->page + 1) % export->n_pages == 0 && (export->total - 1 + export->blank) % export->pages_per_sheet != 0) {
961                 ev_document_doc_mutex_lock ();
962                 ev_file_exporter_end_page (EV_FILE_EXPORTER (op->document));
963                 /* keep track of how many blank pages have been added */
964                 export->blank += export->pages_per_sheet - (export->total - 1 + export->blank) % export->pages_per_sheet;
965                 ev_document_doc_mutex_unlock ();
966         }
967
968
969         if (export->collated == export->collated_copies) {
970                 export->collated = 0;
971                 if (!export_print_inc_page (export)) {
972                         ev_document_doc_mutex_lock ();
973                         ev_file_exporter_end (EV_FILE_EXPORTER (op->document));
974                         ev_document_doc_mutex_unlock ();
975
976                         close (export->fd);
977                         export->fd = -1;
978                         update_progress (export);
979                         export_print_done (export);
980
981                         return FALSE;
982                 }
983         }
984
985         if (export->pages_per_sheet == 1 || (export->total + export->blank) % export->pages_per_sheet == 1) {
986                 ev_document_doc_mutex_lock ();
987                 ev_file_exporter_begin_page (EV_FILE_EXPORTER (op->document));
988                 ev_document_doc_mutex_unlock ();
989         }
990         
991         if (!export->job_export) {
992                 export->job_export = ev_job_export_new (op->document);
993                 g_signal_connect (export->job_export, "finished",
994                                   G_CALLBACK (export_job_finished),
995                                   (gpointer)export);
996                 g_signal_connect (export->job_export, "cancelled",
997                                   G_CALLBACK (export_job_cancelled),
998                                   (gpointer)export);
999         }
1000
1001         ev_job_export_set_page (EV_JOB_EXPORT (export->job_export), export->page);
1002         ev_job_scheduler_push_job (export->job_export, EV_JOB_PRIORITY_NONE);
1003
1004         update_progress (export);
1005         
1006         return FALSE;
1007 }
1008
1009 static void
1010 ev_print_operation_export_begin (EvPrintOperationExport *export)
1011 {
1012         EvPrintOperation *op = EV_PRINT_OPERATION (export);
1013
1014         if (!export->temp_file)
1015                 return; /* cancelled */
1016         
1017         ev_document_doc_mutex_lock ();
1018         ev_file_exporter_begin (EV_FILE_EXPORTER (op->document), &export->fc);
1019         ev_document_doc_mutex_unlock ();
1020
1021         export->idle_id = g_idle_add_full (G_PRIORITY_DEFAULT_IDLE,
1022                                            (GSourceFunc)export_print_page,
1023                                            export,
1024                                            (GDestroyNotify)export_print_page_idle_finished);    
1025 }
1026
1027 static void
1028 ev_print_operation_export_print_dialog_response_cb (GtkDialog              *dialog,
1029                                                     gint                    response,
1030                                                     EvPrintOperationExport *export)
1031 {
1032         GtkPrintPages     print_pages;
1033         GtkPrintSettings *print_settings;
1034         GtkPageSetup     *page_setup;
1035         GtkPrinter       *printer;
1036         gdouble           scale;
1037         gdouble           width;
1038         gdouble           height;
1039         gint              first_page;
1040         gint              last_page;
1041         const gchar      *file_format;
1042         gchar            *filename;
1043         GError           *error = NULL;
1044         EvPrintOperation *op = EV_PRINT_OPERATION (export);
1045         
1046         if (response != GTK_RESPONSE_OK &&
1047             response != GTK_RESPONSE_APPLY) {
1048                 gtk_widget_destroy (GTK_WIDGET (dialog));
1049                 g_signal_emit (op, signals[DONE], 0, GTK_PRINT_OPERATION_RESULT_CANCEL);
1050
1051                 return;
1052         }
1053
1054         export->print_preview = (response == GTK_RESPONSE_APPLY);
1055         
1056         printer = gtk_print_unix_dialog_get_selected_printer (GTK_PRINT_UNIX_DIALOG (dialog));
1057         ev_print_operation_export_set_printer (export, printer);
1058
1059         print_settings = gtk_print_unix_dialog_get_settings (GTK_PRINT_UNIX_DIALOG (dialog));
1060         ev_print_operation_export_set_print_settings (op, print_settings);
1061
1062         page_setup = gtk_print_unix_dialog_get_page_setup (GTK_PRINT_UNIX_DIALOG (dialog));
1063         ev_print_operation_export_set_default_page_setup (op, page_setup);
1064
1065         if (!gtk_printer_accepts_ps (export->printer)) {
1066                 gtk_widget_destroy (GTK_WIDGET (dialog));
1067                 
1068                 g_set_error_literal (&export->error,
1069                                      GTK_PRINT_ERROR,
1070                                      GTK_PRINT_ERROR_GENERAL,
1071                                      _("Printing is not supported on this printer."));
1072                 g_signal_emit (op, signals[DONE], 0, GTK_PRINT_OPERATION_RESULT_ERROR);
1073                 
1074                 return;
1075         }
1076
1077         file_format = gtk_print_settings_get (print_settings, GTK_PRINT_SETTINGS_OUTPUT_FILE_FORMAT);
1078         
1079         filename = g_strdup_printf ("evince_print.%s.XXXXXX", file_format);
1080         export->fd = g_file_open_tmp (filename, &export->temp_file, &error);
1081         g_free (filename);
1082         if (export->fd <= -1) {
1083                 gtk_widget_destroy (GTK_WIDGET (dialog));
1084                 
1085                 g_set_error_literal (&export->error,
1086                                      GTK_PRINT_ERROR,
1087                                      GTK_PRINT_ERROR_GENERAL,
1088                                      error->message);
1089                 g_error_free (error);
1090                 g_signal_emit (op, signals[DONE], 0, GTK_PRINT_OPERATION_RESULT_ERROR);
1091
1092                 return;
1093         }
1094
1095         export->current_page = gtk_print_unix_dialog_get_current_page (GTK_PRINT_UNIX_DIALOG (dialog));
1096         export->page_set = gtk_print_settings_get_page_set (print_settings);
1097         print_pages = gtk_print_settings_get_print_pages (print_settings);
1098         
1099         switch (print_pages) {
1100         case GTK_PRINT_PAGES_CURRENT:
1101                 export->ranges = &export->one_range;
1102                 
1103                 export->ranges[0].start = export->current_page;
1104                 export->ranges[0].end = export->current_page;
1105                 export->n_ranges = 1;
1106                                 
1107                 break;
1108         case GTK_PRINT_PAGES_RANGES: {
1109                 gint i;
1110                 
1111                 export->ranges = gtk_print_settings_get_page_ranges (print_settings, &export->n_ranges);
1112                 for (i = 0; i < export->n_ranges; i++)
1113                         if (export->ranges[i].end == -1 || export->ranges[i].end >= export->n_pages)
1114                                 export->ranges[i].end = export->n_pages - 1;
1115         }
1116                 break;
1117         case GTK_PRINT_PAGES_ALL:
1118                 export->ranges = &export->one_range;
1119
1120                 export->ranges[0].start = 0;
1121                 export->ranges[0].end = export->n_pages - 1;
1122                 export->n_ranges = 1;
1123                 
1124                 break;
1125         }
1126         if (export->n_ranges < 1 || !clamp_ranges (export)) {
1127                 GtkWidget *message_dialog;
1128
1129                 message_dialog = gtk_message_dialog_new (GTK_WINDOW (dialog),
1130                                                  GTK_DIALOG_MODAL,
1131                                                  GTK_MESSAGE_WARNING,
1132                                                  GTK_BUTTONS_CLOSE,
1133                                                  "%s", _("Invalid page selection"));
1134                 gtk_window_set_title (GTK_WINDOW (message_dialog), _("Warning"));
1135                 gtk_message_dialog_format_secondary_text (GTK_MESSAGE_DIALOG (message_dialog),
1136                                                           "%s", _("Your print range selection does not include any page"));
1137                 g_signal_connect (message_dialog, "response",
1138                                   G_CALLBACK (gtk_widget_destroy),
1139                                   NULL);
1140                 gtk_widget_show (message_dialog);
1141
1142                 return;
1143         } else  ev_print_operation_update_status (op, -1, -1, 0.0);
1144  
1145         width = gtk_page_setup_get_paper_width (page_setup, GTK_UNIT_POINTS);
1146         height = gtk_page_setup_get_paper_height (page_setup, GTK_UNIT_POINTS);
1147         scale = gtk_print_settings_get_scale (print_settings) * 0.01;
1148         if (scale != 1.0) {
1149                 width *= scale;
1150                 height *= scale;
1151         }
1152
1153         export->pages_per_sheet = MAX (1, gtk_print_settings_get_number_up (print_settings));
1154         
1155         export->copies = gtk_print_settings_get_n_copies (print_settings);
1156         export->collate = gtk_print_settings_get_collate (print_settings);
1157         export->reverse = gtk_print_settings_get_reverse (print_settings);
1158
1159         if (export->collate) {
1160                 export->uncollated_copies = export->copies;
1161                 export->collated_copies = 1;
1162         } else {
1163                 export->uncollated_copies = 1;
1164                 export->collated_copies = export->copies;
1165         }
1166
1167         if (export->reverse) {
1168                 export->range = export->n_ranges - 1;
1169                 export->inc = -1;
1170         } else {
1171                 export->range = 0;
1172                 export->inc = 1;
1173         }
1174         find_range (export);
1175
1176         export->page = export->start - export->inc;
1177         export->collated = export->collated_copies - 1;
1178
1179         get_first_and_last_page (export, &first_page, &last_page);
1180
1181         export->fc.format = file_format && g_ascii_strcasecmp (file_format, "pdf") == 0 ?
1182                 EV_FILE_FORMAT_PDF : EV_FILE_FORMAT_PS;
1183         export->fc.filename = export->temp_file;
1184         export->fc.first_page = MIN (first_page, last_page);
1185         export->fc.last_page = MAX (first_page, last_page);
1186         export->fc.paper_width = width;
1187         export->fc.paper_height = height;
1188         export->fc.duplex = FALSE;
1189         export->fc.pages_per_sheet = export->pages_per_sheet;
1190
1191         if (ev_print_queue_is_empty (op->document))
1192                 ev_print_operation_export_begin (export);
1193
1194         ev_print_queue_push (op);
1195
1196         g_signal_emit (op, signals[BEGIN_PRINT], 0);
1197         
1198         gtk_widget_destroy (GTK_WIDGET (dialog));
1199 }
1200
1201 static void
1202 ev_print_operation_export_run (EvPrintOperation *op,
1203                                GtkWindow        *parent)
1204 {
1205         EvPrintOperationExport *export = EV_PRINT_OPERATION_EXPORT (op);
1206         GtkWidget              *dialog;
1207         GtkPrintCapabilities    capabilities;
1208
1209         ev_print_queue_init ();
1210
1211         export->parent_window = parent;
1212         export->error = NULL;
1213         
1214         dialog = gtk_print_unix_dialog_new (_("Print"), parent);
1215         gtk_window_set_modal (GTK_WINDOW (dialog), TRUE);
1216         
1217         capabilities = GTK_PRINT_CAPABILITY_PREVIEW |
1218                 ev_file_exporter_get_capabilities (EV_FILE_EXPORTER (op->document));
1219         gtk_print_unix_dialog_set_manual_capabilities (GTK_PRINT_UNIX_DIALOG (dialog),
1220                                                        capabilities);
1221
1222         gtk_print_unix_dialog_set_current_page (GTK_PRINT_UNIX_DIALOG (dialog),
1223                                                 export->current_page);
1224         
1225         gtk_print_unix_dialog_set_settings (GTK_PRINT_UNIX_DIALOG (dialog),
1226                                             export->print_settings);
1227         
1228         if (export->page_setup)
1229                 gtk_print_unix_dialog_set_page_setup (GTK_PRINT_UNIX_DIALOG (dialog),
1230                                                       export->page_setup);
1231         
1232         g_signal_connect (dialog, "response",
1233                           G_CALLBACK (ev_print_operation_export_print_dialog_response_cb),
1234                           export);
1235
1236         gtk_window_present (GTK_WINDOW (dialog));
1237 }
1238
1239 static void
1240 ev_print_operation_export_cancel (EvPrintOperation *op)
1241 {
1242         EvPrintOperationExport *export = EV_PRINT_OPERATION_EXPORT (op);
1243
1244         if (export->job_export &&
1245             !ev_job_is_finished (export->job_export)) {
1246                 ev_job_cancel (export->job_export);
1247         } else {
1248                 export_cancel (export);
1249         }
1250 }
1251
1252 static void
1253 ev_print_operation_export_get_error (EvPrintOperation *op,
1254                                      GError          **error)
1255 {
1256         EvPrintOperationExport *export = EV_PRINT_OPERATION_EXPORT (op);
1257
1258         g_propagate_error (error, export->error);
1259         export->error = NULL;
1260 }
1261
1262 static void
1263 ev_print_operation_export_finalize (GObject *object)
1264 {
1265         EvPrintOperationExport *export = EV_PRINT_OPERATION_EXPORT (object);
1266
1267         if (export->idle_id > 0) {
1268                 g_source_remove (export->idle_id);
1269                 export->idle_id = 0;
1270         }
1271
1272         if (export->fd != -1) {
1273                 close (export->fd);
1274                 export->fd = -1;
1275         }
1276         
1277         if (export->ranges) {
1278                 if (export->ranges != &export->one_range)
1279                         g_free (export->ranges);
1280                 export->ranges = NULL;
1281                 export->n_ranges = 0;
1282         }
1283
1284         if (export->temp_file) {
1285                 g_free (export->temp_file);
1286                 export->temp_file = NULL;
1287         }
1288
1289         if (export->job_name) {
1290                 g_free (export->job_name);
1291                 export->job_name = NULL;
1292         }
1293
1294         if (export->job_export) {
1295                 if (!ev_job_is_finished (export->job_export))
1296                         ev_job_cancel (export->job_export);
1297                 g_signal_handlers_disconnect_by_func (export->job_export,
1298                                                       export_job_finished,
1299                                                       export);
1300                 g_signal_handlers_disconnect_by_func (export->job_export,
1301                                                       export_job_cancelled,
1302                                                       export);
1303                 g_object_unref (export->job_export);
1304                 export->job_export = NULL;
1305         }
1306
1307         if (export->error) {
1308                 g_error_free (export->error);
1309                 export->error = NULL;
1310         }
1311
1312         if (export->print_settings) {
1313                 g_object_unref (export->print_settings);
1314                 export->print_settings = NULL;
1315         }
1316
1317         if (export->page_setup) {
1318                 g_object_unref (export->page_setup);
1319                 export->page_setup = NULL;
1320         }
1321
1322         if (export->printer) {
1323                 g_object_unref (export->printer);
1324                 export->printer = NULL;
1325         }
1326
1327         (* G_OBJECT_CLASS (ev_print_operation_export_parent_class)->finalize) (object);
1328 }
1329
1330 static void
1331 ev_print_operation_export_init (EvPrintOperationExport *export)
1332 {
1333 }
1334
1335 static GObject *
1336 ev_print_operation_export_constructor (GType                  type,
1337                                        guint                  n_construct_properties,
1338                                        GObjectConstructParam *construct_params)
1339 {
1340         GObject                *object;
1341         EvPrintOperationExport *export;
1342         EvPrintOperation       *op;
1343         
1344         object = G_OBJECT_CLASS (ev_print_operation_export_parent_class)->constructor (type,
1345                                                                                        n_construct_properties,
1346                                                                                        construct_params);
1347         export = EV_PRINT_OPERATION_EXPORT (object);
1348         op = EV_PRINT_OPERATION (object);
1349         export->n_pages = ev_page_cache_get_n_pages (ev_page_cache_get (op->document));
1350
1351         return object;
1352 }
1353
1354 static void
1355 ev_print_operation_export_class_init (EvPrintOperationExportClass *klass)
1356 {
1357         GObjectClass          *g_object_class = G_OBJECT_CLASS (klass);
1358         EvPrintOperationClass *ev_print_op_class = EV_PRINT_OPERATION_CLASS (klass);
1359
1360         ev_print_op_class->set_current_page = ev_print_operation_export_set_current_page;
1361         ev_print_op_class->set_print_settings = ev_print_operation_export_set_print_settings;
1362         ev_print_op_class->get_print_settings = ev_print_operation_export_get_print_settings;
1363         ev_print_op_class->set_default_page_setup = ev_print_operation_export_set_default_page_setup;
1364         ev_print_op_class->get_default_page_setup = ev_print_operation_export_get_default_page_setup;
1365         ev_print_op_class->set_job_name = ev_print_operation_export_set_job_name;
1366         ev_print_op_class->get_job_name = ev_print_operation_export_get_job_name;
1367         ev_print_op_class->run = ev_print_operation_export_run;
1368         ev_print_op_class->cancel = ev_print_operation_export_cancel;
1369         ev_print_op_class->get_error = ev_print_operation_export_get_error;
1370
1371         g_object_class->constructor = ev_print_operation_export_constructor;
1372         g_object_class->finalize = ev_print_operation_export_finalize;
1373 }
1374
1375 #if GTK_CHECK_VERSION (2, 17, 1)
1376 /* Print to cairo interface */
1377 #define EV_TYPE_PRINT_OPERATION_PRINT         (ev_print_operation_print_get_type())
1378 #define EV_PRINT_OPERATION_PRINT(object)      (G_TYPE_CHECK_INSTANCE_CAST((object), EV_TYPE_PRINT_OPERATION_PRINT, EvPrintOperationPrint))
1379 #define EV_PRINT_OPERATION_PRINT_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST((klass), EV_TYPE_PRINT_OPERATION_PRINT, EvPrintOperationPrintClass))
1380 #define EV_IS_PRINT_OPERATION_PRINT(object)   (G_TYPE_CHECK_INSTANCE_TYPE((object), EV_TYPE_PRINT_OPERATION_PRINT))
1381
1382 typedef struct _EvPrintOperationPrint      EvPrintOperationPrint;
1383 typedef struct _EvPrintOperationPrintClass EvPrintOperationPrintClass;
1384
1385 static GType ev_print_operation_print_get_type (void) G_GNUC_CONST;
1386
1387 struct _EvPrintOperationPrint {
1388         EvPrintOperation parent;
1389
1390         GtkPrintOperation *op;
1391         EvJob             *job_print;
1392         gchar             *job_name;
1393 };
1394
1395 struct _EvPrintOperationPrintClass {
1396         EvPrintOperationClass parent_class;
1397 };
1398
1399 G_DEFINE_TYPE (EvPrintOperationPrint, ev_print_operation_print, EV_TYPE_PRINT_OPERATION)
1400
1401 static void
1402 ev_print_operation_print_set_current_page (EvPrintOperation *op,
1403                                            gint              current_page)
1404 {
1405         EvPrintOperationPrint *print = EV_PRINT_OPERATION_PRINT (op);
1406
1407         gtk_print_operation_set_current_page (print->op, current_page);
1408 }
1409
1410 static void
1411 ev_print_operation_print_set_print_settings (EvPrintOperation *op,
1412                                              GtkPrintSettings *print_settings)
1413 {
1414         EvPrintOperationPrint *print = EV_PRINT_OPERATION_PRINT (op);
1415
1416         gtk_print_operation_set_print_settings (print->op, print_settings);
1417 }
1418
1419 static GtkPrintSettings *
1420 ev_print_operation_print_get_print_settings (EvPrintOperation *op)
1421 {
1422         EvPrintOperationPrint *print = EV_PRINT_OPERATION_PRINT (op);
1423
1424         return gtk_print_operation_get_print_settings (print->op);
1425 }
1426
1427 static void
1428 ev_print_operation_print_set_default_page_setup (EvPrintOperation *op,
1429                                                  GtkPageSetup     *page_setup)
1430 {
1431         EvPrintOperationPrint *print = EV_PRINT_OPERATION_PRINT (op);
1432
1433         gtk_print_operation_set_default_page_setup (print->op, page_setup);
1434 }
1435
1436 static GtkPageSetup *
1437 ev_print_operation_print_get_default_page_setup (EvPrintOperation *op)
1438 {
1439         EvPrintOperationPrint *print = EV_PRINT_OPERATION_PRINT (op);
1440
1441         return gtk_print_operation_get_default_page_setup (print->op);
1442 }
1443
1444 static void
1445 ev_print_operation_print_set_job_name (EvPrintOperation *op,
1446                                        const gchar      *job_name)
1447 {
1448         EvPrintOperationPrint *print = EV_PRINT_OPERATION_PRINT (op);
1449
1450         g_free (print->job_name);
1451         print->job_name = g_strdup (job_name);
1452
1453         gtk_print_operation_set_job_name (print->op, print->job_name);
1454 }
1455
1456 static const gchar *
1457 ev_print_operation_print_get_job_name (EvPrintOperation *op)
1458 {
1459         EvPrintOperationPrint *print = EV_PRINT_OPERATION_PRINT (op);
1460
1461         if (!print->job_name) {
1462                 gchar *name;
1463
1464                 g_object_get (print->op, "job_name", &name, NULL);
1465                 print->job_name = name;
1466         }
1467
1468         return print->job_name;
1469 }
1470
1471 static void
1472 ev_print_operation_print_run (EvPrintOperation *op,
1473                               GtkWindow        *parent)
1474 {
1475         EvPrintOperationPrint *print = EV_PRINT_OPERATION_PRINT (op);
1476
1477         gtk_print_operation_run (print->op,
1478                                  GTK_PRINT_OPERATION_ACTION_PRINT_DIALOG,
1479                                  parent, NULL);
1480 }
1481
1482 static void
1483 ev_print_operation_print_cancel (EvPrintOperation *op)
1484 {
1485         EvPrintOperationPrint *print = EV_PRINT_OPERATION_PRINT (op);
1486
1487         gtk_print_operation_cancel (print->op);
1488 }
1489
1490 static void
1491 ev_print_operation_print_get_error (EvPrintOperation *op,
1492                                     GError          **error)
1493 {
1494         EvPrintOperationPrint *print = EV_PRINT_OPERATION_PRINT (op);
1495
1496         gtk_print_operation_get_error (print->op, error);
1497 }
1498
1499 static void
1500 ev_print_operation_print_begin_print (EvPrintOperationPrint *print,
1501                                       GtkPrintContext       *context)
1502 {
1503         EvPrintOperation *op = EV_PRINT_OPERATION (print);
1504         gint              n_pages;
1505
1506         n_pages = ev_page_cache_get_n_pages (ev_page_cache_get (op->document));
1507         gtk_print_operation_set_n_pages (print->op, n_pages);
1508
1509         /* FIXME: gtk_print should provide the progress */
1510         ev_print_operation_update_status (op, -1, n_pages, 0);
1511
1512         g_signal_emit (op, signals[BEGIN_PRINT], 0);
1513 }
1514
1515 static void
1516 ev_print_operation_print_done (EvPrintOperationPrint  *print,
1517                                GtkPrintOperationResult result)
1518 {
1519         EvPrintOperation *op = EV_PRINT_OPERATION (print);
1520
1521         /* FIXME: gtk_print should provide the progress */
1522         ev_print_operation_update_status (op, 0, 1, 1.0);
1523
1524         g_signal_emit (op, signals[DONE], 0, result);
1525 }
1526
1527 static void
1528 print_job_finished (EvJobPrint            *job,
1529                     EvPrintOperationPrint *print)
1530 {
1531         gtk_print_operation_draw_page_finish (print->op);
1532         ev_job_print_set_cairo (job, NULL);
1533 }
1534
1535 static void
1536 print_job_cancelled (EvJobPrint            *job,
1537                      EvPrintOperationPrint *print)
1538 {
1539         gtk_print_operation_cancel (print->op);
1540 }
1541
1542 static void
1543 ev_print_operation_print_draw_page (EvPrintOperationPrint *print,
1544                                     GtkPrintContext       *context,
1545                                     gint                   page)
1546 {
1547         EvPrintOperation *op = EV_PRINT_OPERATION (print);
1548         cairo_t          *cr;
1549         gdouble           cr_width, cr_height;
1550         gint              width, height;
1551
1552         gtk_print_operation_set_defer_drawing (print->op);
1553
1554         if (!print->job_print) {
1555                 print->job_print = ev_job_print_new (op->document);
1556                 g_signal_connect (G_OBJECT (print->job_print), "finished",
1557                                   G_CALLBACK (print_job_finished),
1558                                   (gpointer)print);
1559                 g_signal_connect (G_OBJECT (print->job_print), "cancelled",
1560                                   G_CALLBACK (print_job_cancelled),
1561                                   (gpointer)print);
1562         }
1563
1564         ev_job_print_set_page (EV_JOB_PRINT (print->job_print), page);
1565
1566         cr = gtk_print_context_get_cairo_context (context);
1567         cr_width = gtk_print_context_get_width (context);
1568         cr_height = gtk_print_context_get_height (context);
1569         ev_page_cache_get_size (ev_page_cache_get (op->document),
1570                                 page, 0, 1.0,
1571                                 &width, &height);
1572         cairo_scale (cr, cr_width / (gdouble)width, cr_height / (gdouble)height);
1573
1574         ev_job_print_set_cairo (EV_JOB_PRINT (print->job_print), cr);
1575         ev_job_scheduler_push_job (print->job_print, EV_JOB_PRIORITY_NONE);
1576 }
1577
1578 static void
1579 ev_print_operation_print_finalize (GObject *object)
1580 {
1581         EvPrintOperationPrint *print = EV_PRINT_OPERATION_PRINT (object);
1582
1583         if (print->op) {
1584                 g_object_unref (print->op);
1585                 print->op = NULL;
1586         }
1587
1588         if (print->job_name) {
1589                 g_free (print->job_name);
1590                 print->job_name = NULL;
1591         }
1592
1593         if (print->job_print) {
1594                 if (!ev_job_is_finished (print->job_print))
1595                         ev_job_cancel (print->job_print);
1596                 g_signal_handlers_disconnect_by_func (print->job_print,
1597                                                       print_job_finished,
1598                                                       print);
1599                 g_signal_handlers_disconnect_by_func (print->job_print,
1600                                                       print_job_cancelled,
1601                                                       print);
1602                 g_object_unref (print->job_print);
1603                 print->job_print = NULL;
1604         }
1605
1606         (* G_OBJECT_CLASS (ev_print_operation_print_parent_class)->finalize) (object);
1607 }
1608
1609 static void
1610 ev_print_operation_print_init (EvPrintOperationPrint *print)
1611 {
1612         print->op = gtk_print_operation_new ();
1613         g_signal_connect_swapped (print->op, "begin_print",
1614                                   G_CALLBACK (ev_print_operation_print_begin_print),
1615                                   print);
1616         g_signal_connect_swapped (print->op, "done",
1617                                   G_CALLBACK (ev_print_operation_print_done),
1618                                   print);
1619         g_signal_connect_swapped (print->op, "draw_page",
1620                                   G_CALLBACK (ev_print_operation_print_draw_page),
1621                                   print);
1622         gtk_print_operation_set_allow_async (print->op, TRUE);
1623 }
1624
1625 static void
1626 ev_print_operation_print_class_init (EvPrintOperationPrintClass *klass)
1627 {
1628         GObjectClass          *g_object_class = G_OBJECT_CLASS (klass);
1629         EvPrintOperationClass *ev_print_op_class = EV_PRINT_OPERATION_CLASS (klass);
1630
1631         ev_print_op_class->set_current_page = ev_print_operation_print_set_current_page;
1632         ev_print_op_class->set_print_settings = ev_print_operation_print_set_print_settings;
1633         ev_print_op_class->get_print_settings = ev_print_operation_print_get_print_settings;
1634         ev_print_op_class->set_default_page_setup = ev_print_operation_print_set_default_page_setup;
1635         ev_print_op_class->get_default_page_setup = ev_print_operation_print_get_default_page_setup;
1636         ev_print_op_class->set_job_name = ev_print_operation_print_set_job_name;
1637         ev_print_op_class->get_job_name = ev_print_operation_print_get_job_name;
1638         ev_print_op_class->run = ev_print_operation_print_run;
1639         ev_print_op_class->cancel = ev_print_operation_print_cancel;
1640         ev_print_op_class->get_error = ev_print_operation_print_get_error;
1641
1642         g_object_class->finalize = ev_print_operation_print_finalize;
1643 }
1644 #endif /* GTK_CHECK_VERSION (2, 17, 1) */
1645
1646 /* Factory method */
1647 EvPrintOperation *
1648 ev_print_operation_new (EvDocument *document)
1649 {
1650         EvPrintOperation *op;
1651
1652 #if GTK_CHECK_VERSION (2, 17, 1)
1653         if (EV_IS_DOCUMENT_PRINT (document))
1654                 op = EV_PRINT_OPERATION (g_object_new (EV_TYPE_PRINT_OPERATION_PRINT,
1655                                                        "document", document, NULL));
1656         else
1657 #endif
1658                 op = EV_PRINT_OPERATION (g_object_new (EV_TYPE_PRINT_OPERATION_EXPORT,
1659                                                        "document", document, NULL));
1660
1661         return op;
1662 }