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