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