]> www.fi.muni.cz Git - evince.git/blob - shell/ev-print-operation.c
[printing] Make use of gtk+-unix-print optional
[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         case GTK_PRINT_PAGES_ALL:
1124                 export->ranges = &export->one_range;
1125
1126                 export->ranges[0].start = 0;
1127                 export->ranges[0].end = export->n_pages - 1;
1128                 export->n_ranges = 1;
1129                 
1130                 break;
1131         }
1132         if (export->n_ranges < 1 || !clamp_ranges (export)) {
1133                 GtkWidget *message_dialog;
1134
1135                 message_dialog = gtk_message_dialog_new (GTK_WINDOW (dialog),
1136                                                  GTK_DIALOG_MODAL,
1137                                                  GTK_MESSAGE_WARNING,
1138                                                  GTK_BUTTONS_CLOSE,
1139                                                  "%s", _("Invalid page selection"));
1140                 gtk_window_set_title (GTK_WINDOW (message_dialog), _("Warning"));
1141                 gtk_message_dialog_format_secondary_text (GTK_MESSAGE_DIALOG (message_dialog),
1142                                                           "%s", _("Your print range selection does not include any page"));
1143                 g_signal_connect (message_dialog, "response",
1144                                   G_CALLBACK (gtk_widget_destroy),
1145                                   NULL);
1146                 gtk_widget_show (message_dialog);
1147
1148                 return;
1149         } else  ev_print_operation_update_status (op, -1, -1, 0.0);
1150  
1151         width = gtk_page_setup_get_paper_width (page_setup, GTK_UNIT_POINTS);
1152         height = gtk_page_setup_get_paper_height (page_setup, GTK_UNIT_POINTS);
1153         scale = gtk_print_settings_get_scale (print_settings) * 0.01;
1154         if (scale != 1.0) {
1155                 width *= scale;
1156                 height *= scale;
1157         }
1158
1159         export->pages_per_sheet = MAX (1, gtk_print_settings_get_number_up (print_settings));
1160         
1161         export->copies = gtk_print_settings_get_n_copies (print_settings);
1162         export->collate = gtk_print_settings_get_collate (print_settings);
1163         export->reverse = gtk_print_settings_get_reverse (print_settings);
1164
1165         if (export->collate) {
1166                 export->uncollated_copies = export->copies;
1167                 export->collated_copies = 1;
1168         } else {
1169                 export->uncollated_copies = 1;
1170                 export->collated_copies = export->copies;
1171         }
1172
1173         if (export->reverse) {
1174                 export->range = export->n_ranges - 1;
1175                 export->inc = -1;
1176         } else {
1177                 export->range = 0;
1178                 export->inc = 1;
1179         }
1180         find_range (export);
1181
1182         export->page = export->start - export->inc;
1183         export->collated = export->collated_copies - 1;
1184
1185         get_first_and_last_page (export, &first_page, &last_page);
1186
1187         export->fc.format = file_format && g_ascii_strcasecmp (file_format, "pdf") == 0 ?
1188                 EV_FILE_FORMAT_PDF : EV_FILE_FORMAT_PS;
1189         export->fc.filename = export->temp_file;
1190         export->fc.first_page = MIN (first_page, last_page);
1191         export->fc.last_page = MAX (first_page, last_page);
1192         export->fc.paper_width = width;
1193         export->fc.paper_height = height;
1194         export->fc.duplex = FALSE;
1195         export->fc.pages_per_sheet = export->pages_per_sheet;
1196
1197         if (ev_print_queue_is_empty (op->document))
1198                 ev_print_operation_export_begin (export);
1199
1200         ev_print_queue_push (op);
1201
1202         g_signal_emit (op, signals[BEGIN_PRINT], 0);
1203         
1204         gtk_widget_destroy (GTK_WIDGET (dialog));
1205 }
1206
1207 static void
1208 ev_print_operation_export_run (EvPrintOperation *op,
1209                                GtkWindow        *parent)
1210 {
1211         EvPrintOperationExport *export = EV_PRINT_OPERATION_EXPORT (op);
1212         GtkWidget              *dialog;
1213         GtkPrintCapabilities    capabilities;
1214
1215         ev_print_queue_init ();
1216
1217         export->parent_window = parent;
1218         export->error = NULL;
1219         
1220         dialog = gtk_print_unix_dialog_new (_("Print"), parent);
1221         gtk_window_set_modal (GTK_WINDOW (dialog), TRUE);
1222         
1223         capabilities = GTK_PRINT_CAPABILITY_PREVIEW |
1224                 ev_file_exporter_get_capabilities (EV_FILE_EXPORTER (op->document));
1225         gtk_print_unix_dialog_set_manual_capabilities (GTK_PRINT_UNIX_DIALOG (dialog),
1226                                                        capabilities);
1227
1228         gtk_print_unix_dialog_set_current_page (GTK_PRINT_UNIX_DIALOG (dialog),
1229                                                 export->current_page);
1230         
1231         gtk_print_unix_dialog_set_settings (GTK_PRINT_UNIX_DIALOG (dialog),
1232                                             export->print_settings);
1233         
1234         if (export->page_setup)
1235                 gtk_print_unix_dialog_set_page_setup (GTK_PRINT_UNIX_DIALOG (dialog),
1236                                                       export->page_setup);
1237         
1238         g_signal_connect (dialog, "response",
1239                           G_CALLBACK (ev_print_operation_export_print_dialog_response_cb),
1240                           export);
1241
1242         gtk_window_present (GTK_WINDOW (dialog));
1243 }
1244
1245 static void
1246 ev_print_operation_export_cancel (EvPrintOperation *op)
1247 {
1248         EvPrintOperationExport *export = EV_PRINT_OPERATION_EXPORT (op);
1249
1250         if (export->job_export &&
1251             !ev_job_is_finished (export->job_export)) {
1252                 ev_job_cancel (export->job_export);
1253         } else {
1254                 export_cancel (export);
1255         }
1256 }
1257
1258 static void
1259 ev_print_operation_export_get_error (EvPrintOperation *op,
1260                                      GError          **error)
1261 {
1262         EvPrintOperationExport *export = EV_PRINT_OPERATION_EXPORT (op);
1263
1264         g_propagate_error (error, export->error);
1265         export->error = NULL;
1266 }
1267
1268 static void
1269 ev_print_operation_export_finalize (GObject *object)
1270 {
1271         EvPrintOperationExport *export = EV_PRINT_OPERATION_EXPORT (object);
1272
1273         if (export->idle_id > 0) {
1274                 g_source_remove (export->idle_id);
1275                 export->idle_id = 0;
1276         }
1277
1278         if (export->fd != -1) {
1279                 close (export->fd);
1280                 export->fd = -1;
1281         }
1282         
1283         if (export->ranges) {
1284                 if (export->ranges != &export->one_range)
1285                         g_free (export->ranges);
1286                 export->ranges = NULL;
1287                 export->n_ranges = 0;
1288         }
1289
1290         if (export->temp_file) {
1291                 g_free (export->temp_file);
1292                 export->temp_file = NULL;
1293         }
1294
1295         if (export->job_name) {
1296                 g_free (export->job_name);
1297                 export->job_name = NULL;
1298         }
1299
1300         if (export->job_export) {
1301                 if (!ev_job_is_finished (export->job_export))
1302                         ev_job_cancel (export->job_export);
1303                 g_signal_handlers_disconnect_by_func (export->job_export,
1304                                                       export_job_finished,
1305                                                       export);
1306                 g_signal_handlers_disconnect_by_func (export->job_export,
1307                                                       export_job_cancelled,
1308                                                       export);
1309                 g_object_unref (export->job_export);
1310                 export->job_export = NULL;
1311         }
1312
1313         if (export->error) {
1314                 g_error_free (export->error);
1315                 export->error = NULL;
1316         }
1317
1318         if (export->print_settings) {
1319                 g_object_unref (export->print_settings);
1320                 export->print_settings = NULL;
1321         }
1322
1323         if (export->page_setup) {
1324                 g_object_unref (export->page_setup);
1325                 export->page_setup = NULL;
1326         }
1327
1328         if (export->printer) {
1329                 g_object_unref (export->printer);
1330                 export->printer = NULL;
1331         }
1332
1333         (* G_OBJECT_CLASS (ev_print_operation_export_parent_class)->finalize) (object);
1334 }
1335
1336 static void
1337 ev_print_operation_export_init (EvPrintOperationExport *export)
1338 {
1339 }
1340
1341 static GObject *
1342 ev_print_operation_export_constructor (GType                  type,
1343                                        guint                  n_construct_properties,
1344                                        GObjectConstructParam *construct_params)
1345 {
1346         GObject                *object;
1347         EvPrintOperationExport *export;
1348         EvPrintOperation       *op;
1349         
1350         object = G_OBJECT_CLASS (ev_print_operation_export_parent_class)->constructor (type,
1351                                                                                        n_construct_properties,
1352                                                                                        construct_params);
1353         export = EV_PRINT_OPERATION_EXPORT (object);
1354         op = EV_PRINT_OPERATION (object);
1355         export->n_pages = ev_page_cache_get_n_pages (ev_page_cache_get (op->document));
1356
1357         return object;
1358 }
1359
1360 static void
1361 ev_print_operation_export_class_init (EvPrintOperationExportClass *klass)
1362 {
1363         GObjectClass          *g_object_class = G_OBJECT_CLASS (klass);
1364         EvPrintOperationClass *ev_print_op_class = EV_PRINT_OPERATION_CLASS (klass);
1365
1366         ev_print_op_class->set_current_page = ev_print_operation_export_set_current_page;
1367         ev_print_op_class->set_print_settings = ev_print_operation_export_set_print_settings;
1368         ev_print_op_class->get_print_settings = ev_print_operation_export_get_print_settings;
1369         ev_print_op_class->set_default_page_setup = ev_print_operation_export_set_default_page_setup;
1370         ev_print_op_class->get_default_page_setup = ev_print_operation_export_get_default_page_setup;
1371         ev_print_op_class->set_job_name = ev_print_operation_export_set_job_name;
1372         ev_print_op_class->get_job_name = ev_print_operation_export_get_job_name;
1373         ev_print_op_class->run = ev_print_operation_export_run;
1374         ev_print_op_class->cancel = ev_print_operation_export_cancel;
1375         ev_print_op_class->get_error = ev_print_operation_export_get_error;
1376
1377         g_object_class->constructor = ev_print_operation_export_constructor;
1378         g_object_class->finalize = ev_print_operation_export_finalize;
1379 }
1380
1381 #endif /* GTKUNIXPRINT_ENABLED */
1382
1383 #if GTK_CHECK_VERSION (2, 17, 1)
1384 /* Print to cairo interface */
1385 #define EV_TYPE_PRINT_OPERATION_PRINT         (ev_print_operation_print_get_type())
1386 #define EV_PRINT_OPERATION_PRINT(object)      (G_TYPE_CHECK_INSTANCE_CAST((object), EV_TYPE_PRINT_OPERATION_PRINT, EvPrintOperationPrint))
1387 #define EV_PRINT_OPERATION_PRINT_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST((klass), EV_TYPE_PRINT_OPERATION_PRINT, EvPrintOperationPrintClass))
1388 #define EV_IS_PRINT_OPERATION_PRINT(object)   (G_TYPE_CHECK_INSTANCE_TYPE((object), EV_TYPE_PRINT_OPERATION_PRINT))
1389
1390 typedef struct _EvPrintOperationPrint      EvPrintOperationPrint;
1391 typedef struct _EvPrintOperationPrintClass EvPrintOperationPrintClass;
1392
1393 static GType ev_print_operation_print_get_type (void) G_GNUC_CONST;
1394
1395 struct _EvPrintOperationPrint {
1396         EvPrintOperation parent;
1397
1398         GtkPrintOperation *op;
1399         EvJob             *job_print;
1400         gchar             *job_name;
1401 };
1402
1403 struct _EvPrintOperationPrintClass {
1404         EvPrintOperationClass parent_class;
1405 };
1406
1407 G_DEFINE_TYPE (EvPrintOperationPrint, ev_print_operation_print, EV_TYPE_PRINT_OPERATION)
1408
1409 static void
1410 ev_print_operation_print_set_current_page (EvPrintOperation *op,
1411                                            gint              current_page)
1412 {
1413         EvPrintOperationPrint *print = EV_PRINT_OPERATION_PRINT (op);
1414
1415         gtk_print_operation_set_current_page (print->op, current_page);
1416 }
1417
1418 static void
1419 ev_print_operation_print_set_print_settings (EvPrintOperation *op,
1420                                              GtkPrintSettings *print_settings)
1421 {
1422         EvPrintOperationPrint *print = EV_PRINT_OPERATION_PRINT (op);
1423
1424         gtk_print_operation_set_print_settings (print->op, print_settings);
1425 }
1426
1427 static GtkPrintSettings *
1428 ev_print_operation_print_get_print_settings (EvPrintOperation *op)
1429 {
1430         EvPrintOperationPrint *print = EV_PRINT_OPERATION_PRINT (op);
1431
1432         return gtk_print_operation_get_print_settings (print->op);
1433 }
1434
1435 static void
1436 ev_print_operation_print_set_default_page_setup (EvPrintOperation *op,
1437                                                  GtkPageSetup     *page_setup)
1438 {
1439         EvPrintOperationPrint *print = EV_PRINT_OPERATION_PRINT (op);
1440
1441         gtk_print_operation_set_default_page_setup (print->op, page_setup);
1442 }
1443
1444 static GtkPageSetup *
1445 ev_print_operation_print_get_default_page_setup (EvPrintOperation *op)
1446 {
1447         EvPrintOperationPrint *print = EV_PRINT_OPERATION_PRINT (op);
1448
1449         return gtk_print_operation_get_default_page_setup (print->op);
1450 }
1451
1452 static void
1453 ev_print_operation_print_set_job_name (EvPrintOperation *op,
1454                                        const gchar      *job_name)
1455 {
1456         EvPrintOperationPrint *print = EV_PRINT_OPERATION_PRINT (op);
1457
1458         g_free (print->job_name);
1459         print->job_name = g_strdup (job_name);
1460
1461         gtk_print_operation_set_job_name (print->op, print->job_name);
1462 }
1463
1464 static const gchar *
1465 ev_print_operation_print_get_job_name (EvPrintOperation *op)
1466 {
1467         EvPrintOperationPrint *print = EV_PRINT_OPERATION_PRINT (op);
1468
1469         if (!print->job_name) {
1470                 gchar *name;
1471
1472                 g_object_get (print->op, "job_name", &name, NULL);
1473                 print->job_name = name;
1474         }
1475
1476         return print->job_name;
1477 }
1478
1479 static void
1480 ev_print_operation_print_run (EvPrintOperation *op,
1481                               GtkWindow        *parent)
1482 {
1483         EvPrintOperationPrint *print = EV_PRINT_OPERATION_PRINT (op);
1484
1485         gtk_print_operation_run (print->op,
1486                                  GTK_PRINT_OPERATION_ACTION_PRINT_DIALOG,
1487                                  parent, NULL);
1488 }
1489
1490 static void
1491 ev_print_operation_print_cancel (EvPrintOperation *op)
1492 {
1493         EvPrintOperationPrint *print = EV_PRINT_OPERATION_PRINT (op);
1494
1495         gtk_print_operation_cancel (print->op);
1496 }
1497
1498 static void
1499 ev_print_operation_print_get_error (EvPrintOperation *op,
1500                                     GError          **error)
1501 {
1502         EvPrintOperationPrint *print = EV_PRINT_OPERATION_PRINT (op);
1503
1504         gtk_print_operation_get_error (print->op, error);
1505 }
1506
1507 static void
1508 ev_print_operation_print_begin_print (EvPrintOperationPrint *print,
1509                                       GtkPrintContext       *context)
1510 {
1511         EvPrintOperation *op = EV_PRINT_OPERATION (print);
1512         gint              n_pages;
1513
1514         n_pages = ev_page_cache_get_n_pages (ev_page_cache_get (op->document));
1515         gtk_print_operation_set_n_pages (print->op, n_pages);
1516
1517         /* FIXME: gtk_print should provide the progress */
1518         ev_print_operation_update_status (op, -1, n_pages, 0);
1519
1520         g_signal_emit (op, signals[BEGIN_PRINT], 0);
1521 }
1522
1523 static void
1524 ev_print_operation_print_done (EvPrintOperationPrint  *print,
1525                                GtkPrintOperationResult result)
1526 {
1527         EvPrintOperation *op = EV_PRINT_OPERATION (print);
1528
1529         /* FIXME: gtk_print should provide the progress */
1530         ev_print_operation_update_status (op, 0, 1, 1.0);
1531
1532         g_signal_emit (op, signals[DONE], 0, result);
1533 }
1534
1535 static void
1536 print_job_finished (EvJobPrint            *job,
1537                     EvPrintOperationPrint *print)
1538 {
1539         gtk_print_operation_draw_page_finish (print->op);
1540         ev_job_print_set_cairo (job, NULL);
1541 }
1542
1543 static void
1544 print_job_cancelled (EvJobPrint            *job,
1545                      EvPrintOperationPrint *print)
1546 {
1547         gtk_print_operation_cancel (print->op);
1548 }
1549
1550 static void
1551 ev_print_operation_print_draw_page (EvPrintOperationPrint *print,
1552                                     GtkPrintContext       *context,
1553                                     gint                   page)
1554 {
1555         EvPrintOperation *op = EV_PRINT_OPERATION (print);
1556         cairo_t          *cr;
1557         gdouble           cr_width, cr_height;
1558         gint              width, height;
1559
1560         gtk_print_operation_set_defer_drawing (print->op);
1561
1562         if (!print->job_print) {
1563                 print->job_print = ev_job_print_new (op->document);
1564                 g_signal_connect (G_OBJECT (print->job_print), "finished",
1565                                   G_CALLBACK (print_job_finished),
1566                                   (gpointer)print);
1567                 g_signal_connect (G_OBJECT (print->job_print), "cancelled",
1568                                   G_CALLBACK (print_job_cancelled),
1569                                   (gpointer)print);
1570         }
1571
1572         ev_job_print_set_page (EV_JOB_PRINT (print->job_print), page);
1573
1574         cr = gtk_print_context_get_cairo_context (context);
1575         cr_width = gtk_print_context_get_width (context);
1576         cr_height = gtk_print_context_get_height (context);
1577         ev_page_cache_get_size (ev_page_cache_get (op->document),
1578                                 page, 0, 1.0,
1579                                 &width, &height);
1580         cairo_scale (cr, cr_width / (gdouble)width, cr_height / (gdouble)height);
1581
1582         ev_job_print_set_cairo (EV_JOB_PRINT (print->job_print), cr);
1583         ev_job_scheduler_push_job (print->job_print, EV_JOB_PRIORITY_NONE);
1584 }
1585
1586 static void
1587 ev_print_operation_print_finalize (GObject *object)
1588 {
1589         EvPrintOperationPrint *print = EV_PRINT_OPERATION_PRINT (object);
1590
1591         if (print->op) {
1592                 g_object_unref (print->op);
1593                 print->op = NULL;
1594         }
1595
1596         if (print->job_name) {
1597                 g_free (print->job_name);
1598                 print->job_name = NULL;
1599         }
1600
1601         if (print->job_print) {
1602                 if (!ev_job_is_finished (print->job_print))
1603                         ev_job_cancel (print->job_print);
1604                 g_signal_handlers_disconnect_by_func (print->job_print,
1605                                                       print_job_finished,
1606                                                       print);
1607                 g_signal_handlers_disconnect_by_func (print->job_print,
1608                                                       print_job_cancelled,
1609                                                       print);
1610                 g_object_unref (print->job_print);
1611                 print->job_print = NULL;
1612         }
1613
1614         (* G_OBJECT_CLASS (ev_print_operation_print_parent_class)->finalize) (object);
1615 }
1616
1617 static void
1618 ev_print_operation_print_init (EvPrintOperationPrint *print)
1619 {
1620         print->op = gtk_print_operation_new ();
1621         g_signal_connect_swapped (print->op, "begin_print",
1622                                   G_CALLBACK (ev_print_operation_print_begin_print),
1623                                   print);
1624         g_signal_connect_swapped (print->op, "done",
1625                                   G_CALLBACK (ev_print_operation_print_done),
1626                                   print);
1627         g_signal_connect_swapped (print->op, "draw_page",
1628                                   G_CALLBACK (ev_print_operation_print_draw_page),
1629                                   print);
1630         gtk_print_operation_set_allow_async (print->op, TRUE);
1631 }
1632
1633 static void
1634 ev_print_operation_print_class_init (EvPrintOperationPrintClass *klass)
1635 {
1636         GObjectClass          *g_object_class = G_OBJECT_CLASS (klass);
1637         EvPrintOperationClass *ev_print_op_class = EV_PRINT_OPERATION_CLASS (klass);
1638
1639         ev_print_op_class->set_current_page = ev_print_operation_print_set_current_page;
1640         ev_print_op_class->set_print_settings = ev_print_operation_print_set_print_settings;
1641         ev_print_op_class->get_print_settings = ev_print_operation_print_get_print_settings;
1642         ev_print_op_class->set_default_page_setup = ev_print_operation_print_set_default_page_setup;
1643         ev_print_op_class->get_default_page_setup = ev_print_operation_print_get_default_page_setup;
1644         ev_print_op_class->set_job_name = ev_print_operation_print_set_job_name;
1645         ev_print_op_class->get_job_name = ev_print_operation_print_get_job_name;
1646         ev_print_op_class->run = ev_print_operation_print_run;
1647         ev_print_op_class->cancel = ev_print_operation_print_cancel;
1648         ev_print_op_class->get_error = ev_print_operation_print_get_error;
1649
1650         g_object_class->finalize = ev_print_operation_print_finalize;
1651 }
1652 #endif /* GTK_CHECK_VERSION (2, 17, 1) */
1653
1654 gboolean ev_print_operation_exists_for_document (EvDocument *document)
1655 {
1656 #if GTKUNIXPRINT_ENABLED
1657 #if GTK_CHECK_VERSION (2, 17, 1)
1658         return (EV_IS_FILE_EXPORTER(document) || EV_IS_DOCUMENT_PRINT(document));
1659 #else
1660         return EV_IS_FILE_EXPORTER(document);
1661 #endif
1662 #else /* ! GTKUNIXPRINT_ENABLED */
1663 #if GTK_CHECK_VERSION (2, 17, 1)
1664         return EV_IS_DOCUMENT_PRINT(document);
1665 #else
1666         return FALSE;
1667 #endif
1668 #endif /* GTKUNIXPRINT_ENABLED */
1669 }
1670
1671 /* Factory method */
1672 EvPrintOperation *
1673 ev_print_operation_new (EvDocument *document)
1674 {
1675         EvPrintOperation *op = NULL;
1676
1677         g_return_val_if_fail (ev_print_operation_exists_for_document (document), NULL);
1678
1679 #if GTK_CHECK_VERSION (2, 17, 1)
1680         if (EV_IS_DOCUMENT_PRINT (document))
1681                 op = EV_PRINT_OPERATION (g_object_new (EV_TYPE_PRINT_OPERATION_PRINT,
1682                                                        "document", document, NULL));
1683         else
1684 #endif
1685 #if GTKUNIXPRINT_ENABLED
1686                 op = EV_PRINT_OPERATION (g_object_new (EV_TYPE_PRINT_OPERATION_EXPORT,
1687                                                        "document", document, NULL));
1688 #endif
1689         return op;
1690 }