]> www.fi.muni.cz Git - evince.git/blob - shell/ev-print-operation.c
a6f8d53aecfeb818d9ac1ed0ea11cd0a6f0fcd99
[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;
377
378         gint sheet, page_count;
379
380         gint range, n_ranges;
381         GtkPageRange *ranges;
382         GtkPageRange one_range;
383
384         gint page, start, end, inc;
385 };
386
387 struct _EvPrintOperationExportClass {
388         EvPrintOperationClass parent_class;
389 };
390
391 G_DEFINE_TYPE (EvPrintOperationExport, ev_print_operation_export, EV_TYPE_PRINT_OPERATION)
392
393 /* Internal print queue */
394 static GHashTable *print_queue = NULL;
395
396 static void
397 queue_free (GQueue *queue)
398 {
399         g_queue_foreach (queue, (GFunc)g_object_unref, NULL);
400         g_queue_free (queue);
401 }
402
403 static void
404 ev_print_queue_init (void)
405 {
406         if (G_UNLIKELY (print_queue == NULL)) {
407                 print_queue = g_hash_table_new_full (g_direct_hash,
408                                                      g_direct_equal,
409                                                      NULL,
410                                                      (GDestroyNotify)queue_free);
411         }
412 }
413
414 static void
415 remove_document_queue (gpointer data,
416                        GObject *document)
417 {
418         if (print_queue)
419                 g_hash_table_remove (print_queue, document);
420 }
421
422 static gboolean
423 ev_print_queue_is_empty (EvDocument *document)
424 {
425         GQueue *queue;
426
427         queue = g_hash_table_lookup (print_queue, document);
428         return (!queue || g_queue_is_empty (queue));
429 }
430
431 static void
432 ev_print_queue_push (EvPrintOperation *op)
433 {
434         GQueue *queue;
435
436         queue = g_hash_table_lookup (print_queue, op->document);
437         if (!queue) {
438                 queue = g_queue_new ();
439                 g_hash_table_insert (print_queue,
440                                      op->document,
441                                      queue);
442                 g_object_weak_ref (G_OBJECT (op->document),
443                                    (GWeakNotify)remove_document_queue,
444                                    NULL);
445         }
446
447         g_queue_push_head (queue, g_object_ref (op));
448 }
449
450 static EvPrintOperation *
451 ev_print_queue_pop (EvDocument *document)
452 {
453         EvPrintOperation *op;
454         GQueue           *queue;
455
456         queue = g_hash_table_lookup (print_queue, document);
457         if (!queue || g_queue_is_empty (queue))
458                 return NULL;
459         
460         op = g_queue_pop_tail (queue);
461         g_object_unref (op);
462
463         return op;
464 }
465
466 static EvPrintOperation *
467 ev_print_queue_peek (EvDocument *document)
468 {
469         GQueue *queue;
470
471         queue = g_hash_table_lookup (print_queue, document);
472         if (!queue || g_queue_is_empty (queue))
473                 return NULL;
474
475         return g_queue_peek_tail (queue);
476 }
477
478 static void
479 ev_print_operation_export_set_current_page (EvPrintOperation *op,
480                                             gint              current_page)
481 {
482         EvPrintOperationExport *export = EV_PRINT_OPERATION_EXPORT (op);
483
484         g_return_if_fail (current_page < export->n_pages);
485         
486         export->current_page = current_page;
487 }
488
489 static void
490 ev_print_operation_export_set_print_settings (EvPrintOperation *op,
491                                               GtkPrintSettings *print_settings)
492 {
493         EvPrintOperationExport *export = EV_PRINT_OPERATION_EXPORT (op);
494
495         if (print_settings == export->print_settings)
496                 return;
497
498         g_object_ref (print_settings);
499         if (export->print_settings)
500                 g_object_unref (export->print_settings);
501         export->print_settings = print_settings;
502 }
503
504 static GtkPrintSettings *
505 ev_print_operation_export_get_print_settings (EvPrintOperation *op)
506 {
507         EvPrintOperationExport *export = EV_PRINT_OPERATION_EXPORT (op);
508
509         return export->print_settings;
510 }
511
512 static void
513 ev_print_operation_export_set_default_page_setup (EvPrintOperation *op,
514                                                   GtkPageSetup     *page_setup)
515 {
516         EvPrintOperationExport *export = EV_PRINT_OPERATION_EXPORT (op);
517
518         if (page_setup == export->page_setup)
519                 return;
520
521         g_object_ref (page_setup);
522         if (export->page_setup)
523                 g_object_unref (export->page_setup);
524         export->page_setup = page_setup;
525 }
526
527 static GtkPageSetup *
528 ev_print_operation_export_get_default_page_setup (EvPrintOperation *op)
529 {
530         EvPrintOperationExport *export = EV_PRINT_OPERATION_EXPORT (op);
531
532         return export->page_setup;
533 }
534
535 static void
536 ev_print_operation_export_set_job_name (EvPrintOperation *op,
537                                         const gchar      *job_name)
538 {
539         EvPrintOperationExport *export = EV_PRINT_OPERATION_EXPORT (op);
540
541         g_free (export->job_name);
542         export->job_name = g_strdup (job_name);
543 }
544
545 static const gchar *
546 ev_print_operation_export_get_job_name (EvPrintOperation *op)
547 {
548         EvPrintOperationExport *export = EV_PRINT_OPERATION_EXPORT (op);
549
550         return export->job_name;
551 }
552
553 static void
554 ev_print_operation_export_set_printer (EvPrintOperationExport *export,
555                                        GtkPrinter             *printer)
556 {
557         if (printer == export->printer)
558                 return;
559
560         g_object_ref (printer);
561         if (export->printer)
562                 g_object_unref (export->printer);
563         export->printer = printer;
564 }
565
566 static void
567 find_range (EvPrintOperationExport *export)
568 {
569         GtkPageRange *range;
570
571         range = &export->ranges[export->range];
572
573         if (export->inc < 0) {
574                 export->start = range->end;
575                 export->end = range->start - 1;
576         } else {
577                 export->start = range->start;
578                 export->end = range->end + 1;
579         }
580 }
581
582 static gboolean
583 clamp_ranges (EvPrintOperationExport *export)
584 {
585         gint num_of_correct_ranges = 0;
586         gint n_pages_to_print = 0;
587         gint i;
588         gboolean null_flag = FALSE;
589
590         for (i = 0; i < export->n_ranges; i++) {
591                 gint n_pages;
592                 
593                 if ((export->ranges[i].start >= 0) &&
594                     (export->ranges[i].start < export->n_pages) &&
595                     (export->ranges[i].end >= 0) &&
596                     (export->ranges[i].end < export->n_pages)) {
597                         export->ranges[num_of_correct_ranges] = export->ranges[i];
598                         num_of_correct_ranges++;
599                 } else if ((export->ranges[i].start >= 0) &&
600                            (export->ranges[i].start < export->n_pages) &&
601                            (export->ranges[i].end >= export->n_pages)) {
602                         export->ranges[i].end = export->n_pages - 1;
603                         export->ranges[num_of_correct_ranges] = export->ranges[i];
604                         num_of_correct_ranges++;
605                 } else if ((export->ranges[i].end >= 0) &&
606                            (export->ranges[i].end < export->n_pages) &&
607                            (export->ranges[i].start < 0)) {
608                         export->ranges[i].start = 0;
609                         export->ranges[num_of_correct_ranges] = export->ranges[i];
610                         num_of_correct_ranges++;
611                 }
612                 
613                 n_pages = export->ranges[i].end - export->ranges[i].start + 1;
614                 if (export->page_set == GTK_PAGE_SET_ALL) {
615                         n_pages_to_print += n_pages;
616                 } else if (n_pages % 2 == 0) {
617                         n_pages_to_print += n_pages / 2;
618                 } else if (export->page_set == GTK_PAGE_SET_EVEN) {
619                         if (n_pages==1 && export->ranges[i].start % 2 == 0)
620                                 null_flag = TRUE;
621                         else 
622                                 n_pages_to_print += export->ranges[i].start % 2 == 0 ?
623                                 n_pages / 2 : (n_pages / 2) + 1;
624                 } else if (export->page_set == GTK_PAGE_SET_ODD) {
625                         if (n_pages==1 && export->ranges[i].start % 2 != 0) 
626                                 null_flag = TRUE;
627                         else 
628                                 n_pages_to_print += export->ranges[i].start % 2 == 0 ?
629                                 (n_pages / 2) + 1 : n_pages / 2;
630                 }
631         }
632
633         if (null_flag && !n_pages_to_print) {
634                 return FALSE;
635         } else {
636                 export->n_ranges = num_of_correct_ranges;
637                 export->n_pages_to_print = n_pages_to_print;
638                 return TRUE;
639         }
640 }
641
642 static void
643 get_first_and_last_page (EvPrintOperationExport *export,
644                          gint                   *first,
645                          gint                   *last)
646 {
647         gint i;
648         gint first_page = G_MAXINT;
649         gint last_page = G_MININT;
650         gint max_page = export->n_pages - 1;
651
652         if (export->n_ranges == 0) {
653                 *first = 0;
654                 *last = max_page;
655
656                 return;
657         }
658
659         for (i = 0; i < export->n_ranges; i++) {
660                 if (export->ranges[i].start < first_page)
661                         first_page = export->ranges[i].start;
662                 if (export->ranges[i].end > last_page)
663                         last_page = export->ranges[i].end;
664         }
665
666         *first = MAX (0, first_page);
667         *last = MIN (max_page, last_page);
668 }
669
670 static gboolean
671 export_print_inc_page (EvPrintOperationExport *export)
672 {
673         do {
674                 export->page += export->inc;
675
676                 /* note: when NOT collating, page_count is increased in export_print_page */
677                 if (export->collate) {
678                         export->page_count++;
679                         export->sheet = 1 + (export->page_count - 1) / export->pages_per_sheet;
680                 }
681
682                 if (export->page == export->end) {
683                         export->range += export->inc;
684                         if (export->range == -1 || export->range == export->n_ranges) {
685                                 export->uncollated++;
686
687                                 /* when printing multiple collated copies & multiple pages per sheet we want to
688                                  * prevent the next copy bleeding into the last sheet of the previous one
689                                  * we've reached the last range to be printed now, so this is the time to do it */
690                                 if (export->pages_per_sheet > 1 && export->collate == 1 &&
691                                     (export->page_count - 1) % export->pages_per_sheet != 0) {
692
693                                         EvPrintOperation *op = EV_PRINT_OPERATION (export);
694                                         ev_document_doc_mutex_lock ();
695
696                                         /* keep track of all blanks but only actualise those
697                                          * which are in the current odd / even sheet set */
698
699                                         export->page_count += export->pages_per_sheet - (export->page_count - 1) % export->pages_per_sheet;
700                                         if (export->page_set == GTK_PAGE_SET_ALL ||
701                                                 (export->page_set == GTK_PAGE_SET_EVEN && export->sheet % 2 == 0) ||
702                                                 (export->page_set == GTK_PAGE_SET_ODD && export->sheet % 2 == 1) ) {
703                                                 ev_file_exporter_end_page (EV_FILE_EXPORTER (op->document));
704                                         }
705                                         ev_document_doc_mutex_unlock ();
706                                         export->sheet = 1 + (export->page_count - 1) / export->pages_per_sheet;
707                                 }
708
709                                 if (export->uncollated == export->uncollated_copies)
710                                         return FALSE;
711
712                                 export->range = export->inc < 0 ? export->n_ranges - 1 : 0;
713                         }
714                         find_range (export);
715                         export->page = export->start;
716                 }
717
718         /* in/decrement the page number until we reach the first page on the next EVEN or ODD sheet
719          * if we're not collating, we have to make sure that this is done only once! */
720         } while ( export->collate == 1 &&
721                 ((export->page_set == GTK_PAGE_SET_EVEN && export->sheet % 2 == 1) ||
722                 (export->page_set == GTK_PAGE_SET_ODD && export->sheet % 2 == 0)));
723
724         return TRUE;
725 }
726
727 static void
728 ev_print_operation_export_clear_temp_file (EvPrintOperationExport *export)
729 {
730         if (!export->temp_file)
731                 return;
732
733         g_unlink (export->temp_file);
734         g_free (export->temp_file);
735         export->temp_file = NULL;
736 }
737
738 static void
739 ev_print_operation_export_run_next (EvPrintOperationExport *export)
740 {
741         EvPrintOperation *op = EV_PRINT_OPERATION (export);
742         EvPrintOperation *next;
743         EvDocument       *document;
744
745         /* First pop the current job */
746         document = op->document;
747         ev_print_queue_pop (document);
748         
749         next = ev_print_queue_peek (document);
750         if (next)
751                 ev_print_operation_export_begin (EV_PRINT_OPERATION_EXPORT (next));
752 }
753
754 static void
755 gtk_print_job_finished (GtkPrintJob            *print_job,
756                         EvPrintOperationExport *export,
757                         GError                 *error)
758 {
759         EvPrintOperation *op = EV_PRINT_OPERATION (export);
760
761         if (error) {
762                 g_set_error_literal (&export->error,
763                                      GTK_PRINT_ERROR,
764                                      GTK_PRINT_ERROR_GENERAL,
765                                      error->message);
766                 g_signal_emit (op, signals[DONE], 0, GTK_PRINT_OPERATION_RESULT_ERROR);
767         } else {
768                 g_signal_emit (op, signals[DONE], 0, GTK_PRINT_OPERATION_RESULT_APPLY);
769         }
770
771         ev_print_operation_export_clear_temp_file (export);
772         g_object_unref (print_job);
773
774         ev_print_operation_export_run_next (export);
775 }
776
777 static void
778 export_print_done (EvPrintOperationExport *export)
779 {
780         EvPrintOperation *op = EV_PRINT_OPERATION (export);
781         GtkPrintSettings *settings;
782         EvFileExporterCapabilities capabilities;
783         GError *error = NULL;
784
785         g_assert (export->temp_file != NULL);
786         
787         /* Some printers take into account some print settings,
788          * and others don't. However we have exported the document
789          * to a ps or pdf file according to such print settings. So,
790          * we want to send the exported file to printer with those
791          * settings set to default values.
792          */
793         settings = gtk_print_settings_copy (export->print_settings);
794         capabilities = ev_file_exporter_get_capabilities (EV_FILE_EXPORTER (op->document));
795
796         gtk_print_settings_set_page_ranges (settings, NULL, 0);
797         gtk_print_settings_set_print_pages (settings, GTK_PRINT_PAGES_ALL);
798         if (capabilities & EV_FILE_EXPORTER_CAN_COPIES)
799                 gtk_print_settings_set_n_copies (settings, 1);
800         if (capabilities & EV_FILE_EXPORTER_CAN_PAGE_SET)
801                 gtk_print_settings_set_page_set (settings, GTK_PAGE_SET_ALL);
802         if (capabilities & EV_FILE_EXPORTER_CAN_SCALE)
803                 gtk_print_settings_set_scale (settings, 1.0);
804         if (capabilities & EV_FILE_EXPORTER_CAN_COLLATE)
805                 gtk_print_settings_set_collate (settings, FALSE);
806         if (capabilities & EV_FILE_EXPORTER_CAN_REVERSE)
807                 gtk_print_settings_set_reverse (settings, FALSE);
808         if (capabilities & EV_FILE_EXPORTER_CAN_NUMBER_UP) {
809                 gtk_print_settings_set_number_up (settings, 1);
810                 gtk_print_settings_set_int (settings, "cups-"GTK_PRINT_SETTINGS_NUMBER_UP, 1);
811         }
812
813         if (export->print_preview) {
814                 GKeyFile *key_file;
815                 gchar    *data = NULL;
816                 gsize     data_len;
817                 gchar    *print_settings_file = NULL;
818
819                 key_file = g_key_file_new ();
820
821                 gtk_print_settings_to_key_file (settings, key_file, NULL);
822                 gtk_page_setup_to_key_file (export->page_setup, key_file, NULL);
823                 g_key_file_set_string (key_file, "Print Job", "title", export->job_name);
824
825                 data = g_key_file_to_data (key_file, &data_len, &error);
826                 if (data) {
827                         gint fd;
828                         
829                         fd = g_file_open_tmp ("print-settingsXXXXXX", &print_settings_file, &error);
830                         if (!error)
831                                 g_file_set_contents (print_settings_file, data, data_len, &error);
832                         close (fd);
833                         
834                         g_free (data);
835                 }
836
837                 g_key_file_free (key_file);
838
839                 if (!error) {
840                         gint    argc;
841                         gchar **argv;
842                         gchar  *cmd;
843                         gchar  *quoted_filename;
844                         gchar  *quoted_settings_filename;
845
846                         quoted_filename = g_shell_quote (export->temp_file);
847                         quoted_settings_filename = g_shell_quote (print_settings_file);
848                         cmd = g_strdup_printf ("evince-previewer --unlink-tempfile --print-settings %s %s",
849                                                quoted_settings_filename, quoted_filename);
850
851                         g_shell_parse_argv (cmd, &argc, &argv, &error);
852
853                         g_free (quoted_filename);
854                         g_free (quoted_settings_filename);
855                         g_free (cmd);
856
857                         if (!error) {
858                                 gdk_spawn_on_screen (gtk_window_get_screen (export->parent_window),
859                                                      NULL, argv, NULL,
860                                                      G_SPAWN_SEARCH_PATH,
861                                                      NULL, NULL, NULL,
862                                                      &error);
863                         }
864
865                         g_strfreev (argv);
866                 }
867
868                 if (error) {
869                         if (print_settings_file)
870                                 g_unlink (print_settings_file);
871                         g_free (print_settings_file);
872                 } else {
873                         g_signal_emit (op, signals[DONE], 0, GTK_PRINT_OPERATION_RESULT_APPLY);
874                         /* temp_file will be deleted by the previewer */
875
876                         ev_print_operation_export_run_next (export);
877                 }
878         } else {
879                 GtkPrintJob *job;
880                 
881                 job = gtk_print_job_new (export->job_name,
882                                          export->printer,
883                                          settings,
884                                          export->page_setup);
885                 gtk_print_job_set_source_file (job, export->temp_file, &error);
886                 if (!error){
887                         gtk_print_job_send (job,
888                                             (GtkPrintJobCompleteFunc)gtk_print_job_finished,
889                                             g_object_ref (export),
890                                             (GDestroyNotify)g_object_unref);
891                 }
892         }
893         g_object_unref (settings);
894
895         if (error) {
896                 g_set_error_literal (&export->error,
897                                      GTK_PRINT_ERROR,
898                                      GTK_PRINT_ERROR_GENERAL,
899                                      error->message);
900                 g_error_free (error);
901                 ev_print_operation_export_clear_temp_file (export);
902                 g_signal_emit (op, signals[DONE], 0, GTK_PRINT_OPERATION_RESULT_ERROR);
903
904                 ev_print_operation_export_run_next (export);
905         }
906 }
907
908 static void
909 export_print_page_idle_finished (EvPrintOperationExport *export)
910 {
911         export->idle_id = 0;
912 }
913
914 static void
915 export_job_finished (EvJobExport            *job,
916                      EvPrintOperationExport *export)
917 {
918         EvPrintOperation *op = EV_PRINT_OPERATION (export);
919
920         if (export->pages_per_sheet == 1 ||
921            ( export->page_count % export->pages_per_sheet == 0 &&
922            ( export->page_set == GTK_PAGE_SET_ALL ||
923            ( export->page_set == GTK_PAGE_SET_EVEN && export->sheet % 2 == 0 ) ||
924            ( export->page_set == GTK_PAGE_SET_ODD && export->sheet % 2 == 1 ) ) ) ) {
925
926                 ev_document_doc_mutex_lock ();
927                 ev_file_exporter_end_page (EV_FILE_EXPORTER (op->document));
928                 ev_document_doc_mutex_unlock ();
929         }
930
931         /* Reschedule */
932         export->idle_id = g_idle_add_full (G_PRIORITY_DEFAULT_IDLE,
933                                            (GSourceFunc)export_print_page,
934                                            export,
935                                            (GDestroyNotify)export_print_page_idle_finished);
936 }
937
938 static void
939 export_job_cancelled (EvJobExport            *job,
940                       EvPrintOperationExport *export)
941 {
942         export_cancel (export);
943 }
944
945 static void
946 export_cancel (EvPrintOperationExport *export)
947 {
948         EvPrintOperation *op = EV_PRINT_OPERATION (export);
949
950         if (export->idle_id > 0)
951                 g_source_remove (export->idle_id);
952         export->idle_id = 0;
953
954         if (export->job_export) {
955                 g_signal_handlers_disconnect_by_func (export->job_export,
956                                                       export_job_finished,
957                                                       export);
958                 g_signal_handlers_disconnect_by_func (export->job_export,
959                                                       export_job_cancelled,
960                                                       export);
961                 g_object_unref (export->job_export);
962                 export->job_export = NULL;
963         }
964         
965         if (export->fd != -1) {
966                 close (export->fd);
967                 export->fd = -1;
968         }
969
970         ev_print_operation_export_clear_temp_file (export);
971
972         g_signal_emit (op, signals[DONE], 0, GTK_PRINT_OPERATION_RESULT_CANCEL);
973
974         ev_print_operation_export_run_next (export);
975 }
976
977 static void
978 update_progress (EvPrintOperationExport *export)
979 {
980         EvPrintOperation *op = EV_PRINT_OPERATION (export);
981
982         ev_print_operation_update_status (op, export->total,
983                                           export->n_pages_to_print,
984                                           export->total / (gdouble)export->n_pages_to_print);
985 }
986
987 static gboolean
988 export_print_page (EvPrintOperationExport *export)
989 {
990         EvPrintOperation *op = EV_PRINT_OPERATION (export);
991
992         if (!export->temp_file)
993                 return FALSE; /* cancelled */
994
995         export->total++;
996         export->collated++;
997
998         /* note: when collating, page_count is increased in export_print_inc_page */
999         if (!export->collate) {
1000                 export->page_count++;
1001                 export->sheet = 1 + (export->page_count - 1) / export->pages_per_sheet;
1002         }
1003
1004         if (export->collated == export->collated_copies) {
1005                 export->collated = 0;
1006                 if (!export_print_inc_page (export)) {
1007                         ev_document_doc_mutex_lock ();
1008                         ev_file_exporter_end (EV_FILE_EXPORTER (op->document));
1009                         ev_document_doc_mutex_unlock ();
1010
1011                         close (export->fd);
1012                         export->fd = -1;
1013                         update_progress (export);
1014                         export_print_done (export);
1015
1016                         return FALSE;
1017                 }
1018         }
1019
1020         /* we're not collating and we've reached a sheet from the wrong sheet set */
1021         if (!export->collate &&
1022             ((export->page_set == GTK_PAGE_SET_EVEN && export->sheet % 2 != 0) ||
1023             (export->page_set == GTK_PAGE_SET_ODD && export->sheet % 2 != 1))) {
1024
1025                 do {
1026                         export->page_count++;
1027                         export->collated++;
1028                         export->sheet = 1 + (export->page_count - 1) / export->pages_per_sheet;
1029
1030                         if (export->collated == export->collated_copies) {
1031                                 export->collated = 0;
1032
1033                                 if (!export_print_inc_page (export)) {
1034                                         ev_document_doc_mutex_lock ();
1035                                         ev_file_exporter_end (EV_FILE_EXPORTER (op->document));
1036                                         ev_document_doc_mutex_unlock ();
1037
1038                                         close (export->fd);
1039                                         export->fd = -1;
1040
1041                                         update_progress (export);
1042
1043                                         export_print_done (export);
1044                                         return FALSE;
1045                                 }
1046                         }
1047
1048                 } while ((export->page_set == GTK_PAGE_SET_EVEN && export->sheet % 2 != 0) ||
1049                           (export->page_set == GTK_PAGE_SET_ODD && export->sheet % 2 != 1));
1050
1051         }
1052
1053         if (export->pages_per_sheet == 1 ||
1054             (export->page_count % export->pages_per_sheet == 1 &&
1055             (export->page_set == GTK_PAGE_SET_ALL ||
1056             (export->page_set == GTK_PAGE_SET_EVEN && export->sheet % 2 == 0) ||
1057             (export->page_set == GTK_PAGE_SET_ODD && export->sheet % 2 == 1)))) {
1058                 ev_document_doc_mutex_lock ();
1059                 ev_file_exporter_begin_page (EV_FILE_EXPORTER (op->document));
1060                 ev_document_doc_mutex_unlock ();
1061         }
1062
1063         if (!export->job_export) {
1064                 export->job_export = ev_job_export_new (op->document);
1065                 g_signal_connect (export->job_export, "finished",
1066                                   G_CALLBACK (export_job_finished),
1067                                   (gpointer)export);
1068                 g_signal_connect (export->job_export, "cancelled",
1069                                   G_CALLBACK (export_job_cancelled),
1070                                   (gpointer)export);
1071         }
1072
1073         ev_job_export_set_page (EV_JOB_EXPORT (export->job_export), export->page);
1074         ev_job_scheduler_push_job (export->job_export, EV_JOB_PRIORITY_NONE);
1075
1076         update_progress (export);
1077         
1078         return FALSE;
1079 }
1080
1081 static void
1082 ev_print_operation_export_begin (EvPrintOperationExport *export)
1083 {
1084         EvPrintOperation *op = EV_PRINT_OPERATION (export);
1085
1086         if (!export->temp_file)
1087                 return; /* cancelled */
1088         
1089         ev_document_doc_mutex_lock ();
1090         ev_file_exporter_begin (EV_FILE_EXPORTER (op->document), &export->fc);
1091         ev_document_doc_mutex_unlock ();
1092
1093         export->idle_id = g_idle_add_full (G_PRIORITY_DEFAULT_IDLE,
1094                                            (GSourceFunc)export_print_page,
1095                                            export,
1096                                            (GDestroyNotify)export_print_page_idle_finished);    
1097 }
1098
1099 static void
1100 ev_print_operation_export_print_dialog_response_cb (GtkDialog              *dialog,
1101                                                     gint                    response,
1102                                                     EvPrintOperationExport *export)
1103 {
1104         GtkPrintPages     print_pages;
1105         GtkPrintSettings *print_settings;
1106         GtkPageSetup     *page_setup;
1107         GtkPrinter       *printer;
1108         gdouble           scale;
1109         gdouble           width;
1110         gdouble           height;
1111         gint              first_page;
1112         gint              last_page;
1113         const gchar      *file_format;
1114         gchar            *filename;
1115         GError           *error = NULL;
1116         EvPrintOperation *op = EV_PRINT_OPERATION (export);
1117         
1118         if (response != GTK_RESPONSE_OK &&
1119             response != GTK_RESPONSE_APPLY) {
1120                 gtk_widget_destroy (GTK_WIDGET (dialog));
1121                 g_signal_emit (op, signals[DONE], 0, GTK_PRINT_OPERATION_RESULT_CANCEL);
1122
1123                 return;
1124         }
1125
1126         export->print_preview = (response == GTK_RESPONSE_APPLY);
1127         
1128         printer = gtk_print_unix_dialog_get_selected_printer (GTK_PRINT_UNIX_DIALOG (dialog));
1129         ev_print_operation_export_set_printer (export, printer);
1130
1131         print_settings = gtk_print_unix_dialog_get_settings (GTK_PRINT_UNIX_DIALOG (dialog));
1132         ev_print_operation_export_set_print_settings (op, print_settings);
1133
1134         page_setup = gtk_print_unix_dialog_get_page_setup (GTK_PRINT_UNIX_DIALOG (dialog));
1135         ev_print_operation_export_set_default_page_setup (op, page_setup);
1136
1137         if (!gtk_printer_accepts_ps (export->printer)) {
1138                 gtk_widget_destroy (GTK_WIDGET (dialog));
1139                 
1140                 g_set_error_literal (&export->error,
1141                                      GTK_PRINT_ERROR,
1142                                      GTK_PRINT_ERROR_GENERAL,
1143                                      _("Printing is not supported on this printer."));
1144                 g_signal_emit (op, signals[DONE], 0, GTK_PRINT_OPERATION_RESULT_ERROR);
1145                 
1146                 return;
1147         }
1148
1149         file_format = gtk_print_settings_get (print_settings, GTK_PRINT_SETTINGS_OUTPUT_FILE_FORMAT);
1150         
1151         filename = g_strdup_printf ("evince_print.%s.XXXXXX", file_format != NULL ? file_format : "");
1152         export->fd = g_file_open_tmp (filename, &export->temp_file, &error);
1153         g_free (filename);
1154         if (export->fd <= -1) {
1155                 gtk_widget_destroy (GTK_WIDGET (dialog));
1156                 
1157                 g_set_error_literal (&export->error,
1158                                      GTK_PRINT_ERROR,
1159                                      GTK_PRINT_ERROR_GENERAL,
1160                                      error->message);
1161                 g_error_free (error);
1162                 g_signal_emit (op, signals[DONE], 0, GTK_PRINT_OPERATION_RESULT_ERROR);
1163
1164                 return;
1165         }
1166
1167         export->current_page = gtk_print_unix_dialog_get_current_page (GTK_PRINT_UNIX_DIALOG (dialog));
1168         export->page_set = gtk_print_settings_get_page_set (print_settings);
1169         print_pages = gtk_print_settings_get_print_pages (print_settings);
1170         
1171         switch (print_pages) {
1172         case GTK_PRINT_PAGES_CURRENT:
1173                 export->ranges = &export->one_range;
1174                 
1175                 export->ranges[0].start = export->current_page;
1176                 export->ranges[0].end = export->current_page;
1177                 export->n_ranges = 1;
1178                                 
1179                 break;
1180         case GTK_PRINT_PAGES_RANGES: {
1181                 gint i;
1182                 
1183                 export->ranges = gtk_print_settings_get_page_ranges (print_settings, &export->n_ranges);
1184                 for (i = 0; i < export->n_ranges; i++)
1185                         if (export->ranges[i].end == -1 || export->ranges[i].end >= export->n_pages)
1186                                 export->ranges[i].end = export->n_pages - 1;
1187         }
1188                 break;
1189         default:
1190                 g_warning ("Unsupported print pages setting\n");
1191         case GTK_PRINT_PAGES_ALL:
1192                 export->ranges = &export->one_range;
1193
1194                 export->ranges[0].start = 0;
1195                 export->ranges[0].end = export->n_pages - 1;
1196                 export->n_ranges = 1;
1197                 
1198                 break;
1199         }
1200
1201         if (export->n_ranges < 1 || !clamp_ranges (export)) {
1202                 GtkWidget *message_dialog;
1203
1204                 message_dialog = gtk_message_dialog_new (GTK_WINDOW (dialog),
1205                                                  GTK_DIALOG_MODAL,
1206                                                  GTK_MESSAGE_WARNING,
1207                                                  GTK_BUTTONS_CLOSE,
1208                                                  "%s", _("Invalid page selection"));
1209                 gtk_window_set_title (GTK_WINDOW (message_dialog), _("Warning"));
1210                 gtk_message_dialog_format_secondary_text (GTK_MESSAGE_DIALOG (message_dialog),
1211                                                           "%s", _("Your print range selection does not include any page"));
1212                 g_signal_connect (message_dialog, "response",
1213                                   G_CALLBACK (gtk_widget_destroy),
1214                                   NULL);
1215                 gtk_widget_show (message_dialog);
1216
1217                 return;
1218         } else  ev_print_operation_update_status (op, -1, -1, 0.0);
1219  
1220         width = gtk_page_setup_get_paper_width (page_setup, GTK_UNIT_POINTS);
1221         height = gtk_page_setup_get_paper_height (page_setup, GTK_UNIT_POINTS);
1222         scale = gtk_print_settings_get_scale (print_settings) * 0.01;
1223         if (scale != 1.0) {
1224                 width *= scale;
1225                 height *= scale;
1226         }
1227
1228         export->pages_per_sheet = MAX (1, gtk_print_settings_get_number_up (print_settings));
1229         
1230         export->copies = gtk_print_settings_get_n_copies (print_settings);
1231         export->collate = gtk_print_settings_get_collate (print_settings);
1232         export->reverse = gtk_print_settings_get_reverse (print_settings);
1233
1234         if (export->collate) {
1235                 export->uncollated_copies = export->copies;
1236                 export->collated_copies = 1;
1237         } else {
1238                 export->uncollated_copies = 1;
1239                 export->collated_copies = export->copies;
1240         }
1241
1242         if (export->reverse) {
1243                 export->range = export->n_ranges - 1;
1244                 export->inc = -1;
1245         } else {
1246                 export->range = 0;
1247                 export->inc = 1;
1248         }
1249         find_range (export);
1250
1251         export->page = export->start - export->inc;
1252         export->collated = export->collated_copies - 1;
1253
1254         get_first_and_last_page (export, &first_page, &last_page);
1255
1256         if (file_format) {
1257                 export->fc.format = g_ascii_strcasecmp (file_format, "pdf") == 0 ?
1258                         EV_FILE_FORMAT_PDF : EV_FILE_FORMAT_PS;
1259         } else {
1260                 export->fc.format = gtk_printer_accepts_pdf (printer) ?
1261                         EV_FILE_FORMAT_PDF : EV_FILE_FORMAT_PS;
1262         }
1263         export->fc.filename = export->temp_file;
1264         export->fc.first_page = MIN (first_page, last_page);
1265         export->fc.last_page = MAX (first_page, last_page);
1266         export->fc.paper_width = width;
1267         export->fc.paper_height = height;
1268         export->fc.duplex = FALSE;
1269         export->fc.pages_per_sheet = export->pages_per_sheet;
1270
1271         if (ev_print_queue_is_empty (op->document))
1272                 ev_print_operation_export_begin (export);
1273
1274         ev_print_queue_push (op);
1275
1276         g_signal_emit (op, signals[BEGIN_PRINT], 0);
1277         
1278         gtk_widget_destroy (GTK_WIDGET (dialog));
1279 }
1280
1281 static void
1282 ev_print_operation_export_run (EvPrintOperation *op,
1283                                GtkWindow        *parent)
1284 {
1285         EvPrintOperationExport *export = EV_PRINT_OPERATION_EXPORT (op);
1286         GtkWidget              *dialog;
1287         GtkPrintCapabilities    capabilities;
1288
1289         ev_print_queue_init ();
1290
1291         export->parent_window = parent;
1292         export->error = NULL;
1293         
1294         dialog = gtk_print_unix_dialog_new (_("Print"), parent);
1295         gtk_window_set_modal (GTK_WINDOW (dialog), TRUE);
1296         
1297         capabilities = GTK_PRINT_CAPABILITY_PREVIEW |
1298                 ev_file_exporter_get_capabilities (EV_FILE_EXPORTER (op->document));
1299         gtk_print_unix_dialog_set_manual_capabilities (GTK_PRINT_UNIX_DIALOG (dialog),
1300                                                        capabilities);
1301
1302         gtk_print_unix_dialog_set_current_page (GTK_PRINT_UNIX_DIALOG (dialog),
1303                                                 export->current_page);
1304         
1305         gtk_print_unix_dialog_set_settings (GTK_PRINT_UNIX_DIALOG (dialog),
1306                                             export->print_settings);
1307         
1308         if (export->page_setup)
1309                 gtk_print_unix_dialog_set_page_setup (GTK_PRINT_UNIX_DIALOG (dialog),
1310                                                       export->page_setup);
1311         
1312         g_signal_connect (dialog, "response",
1313                           G_CALLBACK (ev_print_operation_export_print_dialog_response_cb),
1314                           export);
1315
1316         gtk_window_present (GTK_WINDOW (dialog));
1317 }
1318
1319 static void
1320 ev_print_operation_export_cancel (EvPrintOperation *op)
1321 {
1322         EvPrintOperationExport *export = EV_PRINT_OPERATION_EXPORT (op);
1323
1324         if (export->job_export &&
1325             !ev_job_is_finished (export->job_export)) {
1326                 ev_job_cancel (export->job_export);
1327         } else {
1328                 export_cancel (export);
1329         }
1330 }
1331
1332 static void
1333 ev_print_operation_export_get_error (EvPrintOperation *op,
1334                                      GError          **error)
1335 {
1336         EvPrintOperationExport *export = EV_PRINT_OPERATION_EXPORT (op);
1337
1338         g_propagate_error (error, export->error);
1339         export->error = NULL;
1340 }
1341
1342 static void
1343 ev_print_operation_export_finalize (GObject *object)
1344 {
1345         EvPrintOperationExport *export = EV_PRINT_OPERATION_EXPORT (object);
1346
1347         if (export->idle_id > 0) {
1348                 g_source_remove (export->idle_id);
1349                 export->idle_id = 0;
1350         }
1351
1352         if (export->fd != -1) {
1353                 close (export->fd);
1354                 export->fd = -1;
1355         }
1356         
1357         if (export->ranges) {
1358                 if (export->ranges != &export->one_range)
1359                         g_free (export->ranges);
1360                 export->ranges = NULL;
1361                 export->n_ranges = 0;
1362         }
1363
1364         if (export->temp_file) {
1365                 g_free (export->temp_file);
1366                 export->temp_file = NULL;
1367         }
1368
1369         if (export->job_name) {
1370                 g_free (export->job_name);
1371                 export->job_name = NULL;
1372         }
1373
1374         if (export->job_export) {
1375                 if (!ev_job_is_finished (export->job_export))
1376                         ev_job_cancel (export->job_export);
1377                 g_signal_handlers_disconnect_by_func (export->job_export,
1378                                                       export_job_finished,
1379                                                       export);
1380                 g_signal_handlers_disconnect_by_func (export->job_export,
1381                                                       export_job_cancelled,
1382                                                       export);
1383                 g_object_unref (export->job_export);
1384                 export->job_export = NULL;
1385         }
1386
1387         if (export->error) {
1388                 g_error_free (export->error);
1389                 export->error = NULL;
1390         }
1391
1392         if (export->print_settings) {
1393                 g_object_unref (export->print_settings);
1394                 export->print_settings = NULL;
1395         }
1396
1397         if (export->page_setup) {
1398                 g_object_unref (export->page_setup);
1399                 export->page_setup = NULL;
1400         }
1401
1402         if (export->printer) {
1403                 g_object_unref (export->printer);
1404                 export->printer = NULL;
1405         }
1406
1407         (* G_OBJECT_CLASS (ev_print_operation_export_parent_class)->finalize) (object);
1408 }
1409
1410 static void
1411 ev_print_operation_export_init (EvPrintOperationExport *export)
1412 {
1413         /* sheets are counted from 1 to be physical */
1414         export->sheet = 1;
1415 }
1416
1417 static GObject *
1418 ev_print_operation_export_constructor (GType                  type,
1419                                        guint                  n_construct_properties,
1420                                        GObjectConstructParam *construct_params)
1421 {
1422         GObject                *object;
1423         EvPrintOperationExport *export;
1424         EvPrintOperation       *op;
1425         
1426         object = G_OBJECT_CLASS (ev_print_operation_export_parent_class)->constructor (type,
1427                                                                                        n_construct_properties,
1428                                                                                        construct_params);
1429         export = EV_PRINT_OPERATION_EXPORT (object);
1430         op = EV_PRINT_OPERATION (object);
1431         export->n_pages = ev_page_cache_get_n_pages (ev_page_cache_get (op->document));
1432
1433         return object;
1434 }
1435
1436 static void
1437 ev_print_operation_export_class_init (EvPrintOperationExportClass *klass)
1438 {
1439         GObjectClass          *g_object_class = G_OBJECT_CLASS (klass);
1440         EvPrintOperationClass *ev_print_op_class = EV_PRINT_OPERATION_CLASS (klass);
1441
1442         ev_print_op_class->set_current_page = ev_print_operation_export_set_current_page;
1443         ev_print_op_class->set_print_settings = ev_print_operation_export_set_print_settings;
1444         ev_print_op_class->get_print_settings = ev_print_operation_export_get_print_settings;
1445         ev_print_op_class->set_default_page_setup = ev_print_operation_export_set_default_page_setup;
1446         ev_print_op_class->get_default_page_setup = ev_print_operation_export_get_default_page_setup;
1447         ev_print_op_class->set_job_name = ev_print_operation_export_set_job_name;
1448         ev_print_op_class->get_job_name = ev_print_operation_export_get_job_name;
1449         ev_print_op_class->run = ev_print_operation_export_run;
1450         ev_print_op_class->cancel = ev_print_operation_export_cancel;
1451         ev_print_op_class->get_error = ev_print_operation_export_get_error;
1452
1453         g_object_class->constructor = ev_print_operation_export_constructor;
1454         g_object_class->finalize = ev_print_operation_export_finalize;
1455 }
1456
1457 #endif /* GTKUNIXPRINT_ENABLED */
1458
1459 #if GTK_CHECK_VERSION (2, 17, 1)
1460 /* Print to cairo interface */
1461 #define EV_TYPE_PRINT_OPERATION_PRINT         (ev_print_operation_print_get_type())
1462 #define EV_PRINT_OPERATION_PRINT(object)      (G_TYPE_CHECK_INSTANCE_CAST((object), EV_TYPE_PRINT_OPERATION_PRINT, EvPrintOperationPrint))
1463 #define EV_PRINT_OPERATION_PRINT_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST((klass), EV_TYPE_PRINT_OPERATION_PRINT, EvPrintOperationPrintClass))
1464 #define EV_IS_PRINT_OPERATION_PRINT(object)   (G_TYPE_CHECK_INSTANCE_TYPE((object), EV_TYPE_PRINT_OPERATION_PRINT))
1465
1466 typedef struct _EvPrintOperationPrint      EvPrintOperationPrint;
1467 typedef struct _EvPrintOperationPrintClass EvPrintOperationPrintClass;
1468
1469 static GType ev_print_operation_print_get_type (void) G_GNUC_CONST;
1470
1471 struct _EvPrintOperationPrint {
1472         EvPrintOperation parent;
1473
1474         GtkPrintOperation *op;
1475         gint               n_pages_to_print;
1476         gint               total;
1477         EvJob             *job_print;
1478         gchar             *job_name;
1479 };
1480
1481 struct _EvPrintOperationPrintClass {
1482         EvPrintOperationClass parent_class;
1483 };
1484
1485 G_DEFINE_TYPE (EvPrintOperationPrint, ev_print_operation_print, EV_TYPE_PRINT_OPERATION)
1486
1487 static void
1488 ev_print_operation_print_set_current_page (EvPrintOperation *op,
1489                                            gint              current_page)
1490 {
1491         EvPrintOperationPrint *print = EV_PRINT_OPERATION_PRINT (op);
1492
1493         gtk_print_operation_set_current_page (print->op, current_page);
1494 }
1495
1496 static void
1497 ev_print_operation_print_set_print_settings (EvPrintOperation *op,
1498                                              GtkPrintSettings *print_settings)
1499 {
1500         EvPrintOperationPrint *print = EV_PRINT_OPERATION_PRINT (op);
1501
1502         gtk_print_operation_set_print_settings (print->op, print_settings);
1503 }
1504
1505 static GtkPrintSettings *
1506 ev_print_operation_print_get_print_settings (EvPrintOperation *op)
1507 {
1508         EvPrintOperationPrint *print = EV_PRINT_OPERATION_PRINT (op);
1509
1510         return gtk_print_operation_get_print_settings (print->op);
1511 }
1512
1513 static void
1514 ev_print_operation_print_set_default_page_setup (EvPrintOperation *op,
1515                                                  GtkPageSetup     *page_setup)
1516 {
1517         EvPrintOperationPrint *print = EV_PRINT_OPERATION_PRINT (op);
1518
1519         gtk_print_operation_set_default_page_setup (print->op, page_setup);
1520 }
1521
1522 static GtkPageSetup *
1523 ev_print_operation_print_get_default_page_setup (EvPrintOperation *op)
1524 {
1525         EvPrintOperationPrint *print = EV_PRINT_OPERATION_PRINT (op);
1526
1527         return gtk_print_operation_get_default_page_setup (print->op);
1528 }
1529
1530 static void
1531 ev_print_operation_print_set_job_name (EvPrintOperation *op,
1532                                        const gchar      *job_name)
1533 {
1534         EvPrintOperationPrint *print = EV_PRINT_OPERATION_PRINT (op);
1535
1536         g_free (print->job_name);
1537         print->job_name = g_strdup (job_name);
1538
1539         gtk_print_operation_set_job_name (print->op, print->job_name);
1540 }
1541
1542 static const gchar *
1543 ev_print_operation_print_get_job_name (EvPrintOperation *op)
1544 {
1545         EvPrintOperationPrint *print = EV_PRINT_OPERATION_PRINT (op);
1546
1547         if (!print->job_name) {
1548                 gchar *name;
1549
1550                 g_object_get (print->op, "job_name", &name, NULL);
1551                 print->job_name = name;
1552         }
1553
1554         return print->job_name;
1555 }
1556
1557 static void
1558 ev_print_operation_print_run (EvPrintOperation *op,
1559                               GtkWindow        *parent)
1560 {
1561         EvPrintOperationPrint *print = EV_PRINT_OPERATION_PRINT (op);
1562
1563         gtk_print_operation_run (print->op,
1564                                  GTK_PRINT_OPERATION_ACTION_PRINT_DIALOG,
1565                                  parent, NULL);
1566 }
1567
1568 static void
1569 ev_print_operation_print_cancel (EvPrintOperation *op)
1570 {
1571         EvPrintOperationPrint *print = EV_PRINT_OPERATION_PRINT (op);
1572
1573         gtk_print_operation_cancel (print->op);
1574 }
1575
1576 static void
1577 ev_print_operation_print_get_error (EvPrintOperation *op,
1578                                     GError          **error)
1579 {
1580         EvPrintOperationPrint *print = EV_PRINT_OPERATION_PRINT (op);
1581
1582         gtk_print_operation_get_error (print->op, error);
1583 }
1584
1585 static void
1586 ev_print_operation_print_begin_print (EvPrintOperationPrint *print,
1587                                       GtkPrintContext       *context)
1588 {
1589         EvPrintOperation *op = EV_PRINT_OPERATION (print);
1590         gint              n_pages;
1591
1592         n_pages = ev_page_cache_get_n_pages (ev_page_cache_get (op->document));
1593         gtk_print_operation_set_n_pages (print->op, n_pages);
1594         ev_print_operation_update_status (op, -1, n_pages, 0);
1595
1596         g_signal_emit (op, signals[BEGIN_PRINT], 0);
1597 }
1598
1599 static void
1600 ev_print_operation_print_done (EvPrintOperationPrint  *print,
1601                                GtkPrintOperationResult result)
1602 {
1603         EvPrintOperation *op = EV_PRINT_OPERATION (print);
1604
1605         ev_print_operation_update_status (op, 0, print->n_pages_to_print, 1.0);
1606
1607         g_signal_emit (op, signals[DONE], 0, result);
1608 }
1609
1610 static void
1611 ev_print_operation_print_status_changed (EvPrintOperationPrint *print)
1612 {
1613 #ifdef HAVE_GTK_PRINT_OPERATION_GET_N_PAGES_TO_PRINT
1614         GtkPrintStatus status;
1615
1616         status = gtk_print_operation_get_status (print->op);
1617         if (status == GTK_PRINT_STATUS_GENERATING_DATA)
1618                 print->n_pages_to_print = gtk_print_operation_get_n_pages_to_print (print->op);
1619 #endif
1620 }
1621
1622 static void
1623 print_job_finished (EvJobPrint            *job,
1624                     EvPrintOperationPrint *print)
1625 {
1626         EvPrintOperation *op = EV_PRINT_OPERATION (print);
1627
1628         gtk_print_operation_draw_page_finish (print->op);
1629 #ifdef HAVE_GTK_PRINT_OPERATION_GET_N_PAGES_TO_PRINT
1630         print->total++;
1631         ev_print_operation_update_status (op, print->total,
1632                                           print->n_pages_to_print,
1633                                           print->total / (gdouble)print->n_pages_to_print);
1634 #endif
1635         ev_job_print_set_cairo (job, NULL);
1636 }
1637
1638 static void
1639 print_job_cancelled (EvJobPrint            *job,
1640                      EvPrintOperationPrint *print)
1641 {
1642         gtk_print_operation_cancel (print->op);
1643 }
1644
1645 static void
1646 ev_print_operation_print_draw_page (EvPrintOperationPrint *print,
1647                                     GtkPrintContext       *context,
1648                                     gint                   page)
1649 {
1650         EvPrintOperation *op = EV_PRINT_OPERATION (print);
1651         cairo_t          *cr;
1652         gdouble           cr_width, cr_height;
1653         gint              width, height;
1654
1655         gtk_print_operation_set_defer_drawing (print->op);
1656
1657         if (!print->job_print) {
1658                 print->job_print = ev_job_print_new (op->document);
1659                 g_signal_connect (G_OBJECT (print->job_print), "finished",
1660                                   G_CALLBACK (print_job_finished),
1661                                   (gpointer)print);
1662                 g_signal_connect (G_OBJECT (print->job_print), "cancelled",
1663                                   G_CALLBACK (print_job_cancelled),
1664                                   (gpointer)print);
1665         }
1666
1667         ev_job_print_set_page (EV_JOB_PRINT (print->job_print), page);
1668
1669         cr = gtk_print_context_get_cairo_context (context);
1670         cr_width = gtk_print_context_get_width (context);
1671         cr_height = gtk_print_context_get_height (context);
1672         ev_page_cache_get_size (ev_page_cache_get (op->document),
1673                                 page, 0, 1.0,
1674                                 &width, &height);
1675         cairo_scale (cr, cr_width / (gdouble)width, cr_height / (gdouble)height);
1676
1677         ev_job_print_set_cairo (EV_JOB_PRINT (print->job_print), cr);
1678         ev_job_scheduler_push_job (print->job_print, EV_JOB_PRIORITY_NONE);
1679 }
1680
1681 static void
1682 ev_print_operation_print_finalize (GObject *object)
1683 {
1684         EvPrintOperationPrint *print = EV_PRINT_OPERATION_PRINT (object);
1685
1686         if (print->op) {
1687                 g_object_unref (print->op);
1688                 print->op = NULL;
1689         }
1690
1691         if (print->job_name) {
1692                 g_free (print->job_name);
1693                 print->job_name = NULL;
1694         }
1695
1696         if (print->job_print) {
1697                 if (!ev_job_is_finished (print->job_print))
1698                         ev_job_cancel (print->job_print);
1699                 g_signal_handlers_disconnect_by_func (print->job_print,
1700                                                       print_job_finished,
1701                                                       print);
1702                 g_signal_handlers_disconnect_by_func (print->job_print,
1703                                                       print_job_cancelled,
1704                                                       print);
1705                 g_object_unref (print->job_print);
1706                 print->job_print = NULL;
1707         }
1708
1709         (* G_OBJECT_CLASS (ev_print_operation_print_parent_class)->finalize) (object);
1710 }
1711
1712 static void
1713 ev_print_operation_print_init (EvPrintOperationPrint *print)
1714 {
1715         print->op = gtk_print_operation_new ();
1716         g_signal_connect_swapped (print->op, "begin_print",
1717                                   G_CALLBACK (ev_print_operation_print_begin_print),
1718                                   print);
1719         g_signal_connect_swapped (print->op, "done",
1720                                   G_CALLBACK (ev_print_operation_print_done),
1721                                   print);
1722         g_signal_connect_swapped (print->op, "draw_page",
1723                                   G_CALLBACK (ev_print_operation_print_draw_page),
1724                                   print);
1725         g_signal_connect_swapped (print->op, "status_changed",
1726                                   G_CALLBACK (ev_print_operation_print_status_changed),
1727                                   print);
1728         gtk_print_operation_set_allow_async (print->op, TRUE);
1729 }
1730
1731 static void
1732 ev_print_operation_print_class_init (EvPrintOperationPrintClass *klass)
1733 {
1734         GObjectClass          *g_object_class = G_OBJECT_CLASS (klass);
1735         EvPrintOperationClass *ev_print_op_class = EV_PRINT_OPERATION_CLASS (klass);
1736
1737         ev_print_op_class->set_current_page = ev_print_operation_print_set_current_page;
1738         ev_print_op_class->set_print_settings = ev_print_operation_print_set_print_settings;
1739         ev_print_op_class->get_print_settings = ev_print_operation_print_get_print_settings;
1740         ev_print_op_class->set_default_page_setup = ev_print_operation_print_set_default_page_setup;
1741         ev_print_op_class->get_default_page_setup = ev_print_operation_print_get_default_page_setup;
1742         ev_print_op_class->set_job_name = ev_print_operation_print_set_job_name;
1743         ev_print_op_class->get_job_name = ev_print_operation_print_get_job_name;
1744         ev_print_op_class->run = ev_print_operation_print_run;
1745         ev_print_op_class->cancel = ev_print_operation_print_cancel;
1746         ev_print_op_class->get_error = ev_print_operation_print_get_error;
1747
1748         g_object_class->finalize = ev_print_operation_print_finalize;
1749 }
1750 #endif /* GTK_CHECK_VERSION (2, 17, 1) */
1751
1752 gboolean ev_print_operation_exists_for_document (EvDocument *document)
1753 {
1754 #if GTKUNIXPRINT_ENABLED
1755 #if GTK_CHECK_VERSION (2, 17, 1)
1756         return (EV_IS_FILE_EXPORTER(document) || EV_IS_DOCUMENT_PRINT(document));
1757 #else
1758         return EV_IS_FILE_EXPORTER(document);
1759 #endif
1760 #else /* ! GTKUNIXPRINT_ENABLED */
1761 #if GTK_CHECK_VERSION (2, 17, 1)
1762         return EV_IS_DOCUMENT_PRINT(document);
1763 #else
1764         return FALSE;
1765 #endif
1766 #endif /* GTKUNIXPRINT_ENABLED */
1767 }
1768
1769 /* Factory method */
1770 EvPrintOperation *
1771 ev_print_operation_new (EvDocument *document)
1772 {
1773         EvPrintOperation *op = NULL;
1774
1775         g_return_val_if_fail (ev_print_operation_exists_for_document (document), NULL);
1776
1777 #if GTK_CHECK_VERSION (2, 17, 1)
1778         if (EV_IS_DOCUMENT_PRINT (document))
1779                 op = EV_PRINT_OPERATION (g_object_new (EV_TYPE_PRINT_OPERATION_PRINT,
1780                                                        "document", document, NULL));
1781         else
1782 #endif
1783 #if GTKUNIXPRINT_ENABLED
1784                 op = EV_PRINT_OPERATION (g_object_new (EV_TYPE_PRINT_OPERATION_EXPORT,
1785                                                        "document", document, NULL));
1786 #endif
1787         return op;
1788 }