]> www.fi.muni.cz Git - evince.git/blob - shell/ev-print-operation.c
First step of the printing system rework. EvJobPrint has been replaced by
[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 GTK_CHECK_VERSION (2, 14, 0)
25 #include <gtk/gtkunixprint.h>
26 #else
27 #include <gtk/gtkprintunixdialog.h>
28 #endif
29
30 #include <glib/gi18n.h>
31 #include <glib/gstdio.h>
32 #include <unistd.h>
33
34 #include "ev-page-cache.h"
35 #include "ev-file-exporter.h"
36 #include "ev-jobs.h"
37 #include "ev-job-scheduler.h"
38 #include "ev-application.h"
39 #include "ev-file-helpers.h"
40
41 enum {
42         PROP_0,
43         PROP_DOCUMENT
44 };
45
46 enum {
47         DONE,
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
59 struct _EvPrintOperationClass {
60         GObjectClass parent_class;
61
62         void              (* set_current_page)       (EvPrintOperation       *op,
63                                                       gint                    current_page);
64         void              (* set_print_settings)     (EvPrintOperation       *op,
65                                                       GtkPrintSettings       *print_settings);
66         GtkPrintSettings *(* get_print_settings)     (EvPrintOperation       *op);
67         void              (* set_default_page_setup) (EvPrintOperation       *op,
68                                                       GtkPageSetup           *page_setup);
69         GtkPageSetup     *(* get_default_page_setup) (EvPrintOperation       *op);
70         void              (* set_job_name)           (EvPrintOperation       *op,
71                                                       const gchar            *job_name);
72         void              (* run)                    (EvPrintOperation       *op,
73                                                       GtkWindow              *parent);
74         void              (* cancel)                 (EvPrintOperation       *op);
75         void              (* get_error)              (EvPrintOperation       *op,
76                                                       GError                **error);
77
78         /* signals */
79         void              (* done)                   (EvPrintOperation       *op,
80                                                       GtkPrintOperationResult result);
81 };
82
83 G_DEFINE_ABSTRACT_TYPE (EvPrintOperation, ev_print_operation, G_TYPE_OBJECT)
84
85 static void
86 ev_print_operation_finalize (GObject *object)
87 {
88         EvPrintOperation *op = EV_PRINT_OPERATION (object);
89
90         if (op->document) {
91                 g_object_unref (op->document);
92                 op->document = NULL;
93         }
94
95         (* G_OBJECT_CLASS (ev_print_operation_parent_class)->finalize) (object);
96 }
97
98 static void
99 ev_print_operation_set_property (GObject      *object,
100                                  guint         prop_id,
101                                  const GValue *value,
102                                  GParamSpec   *pspec)
103 {
104         EvPrintOperation *op = EV_PRINT_OPERATION (object);
105
106         switch (prop_id) {
107         case PROP_DOCUMENT:
108                 op->document = g_value_dup_object (value);
109                 break;
110         default:
111                 G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
112         }
113 }
114
115 static void
116 ev_print_operation_init (EvPrintOperation *op)
117 {
118 }
119
120 static void
121 ev_print_operation_class_init (EvPrintOperationClass *klass)
122 {
123         GObjectClass *g_object_class = G_OBJECT_CLASS (klass);
124
125         g_object_class->set_property = ev_print_operation_set_property;
126         g_object_class->finalize = ev_print_operation_finalize;
127
128         g_object_class_install_property (g_object_class,
129                                          PROP_DOCUMENT,
130                                          g_param_spec_object ("document",
131                                                               "Document",
132                                                               "The document to print",
133                                                               EV_TYPE_DOCUMENT,
134                                                               G_PARAM_WRITABLE |
135                                                               G_PARAM_CONSTRUCT_ONLY));
136         signals[DONE] =
137                 g_signal_new ("done",
138                               G_TYPE_FROM_CLASS (g_object_class),
139                               G_SIGNAL_RUN_LAST,
140                               G_STRUCT_OFFSET (EvPrintOperationClass, done),
141                               NULL, NULL,
142                               g_cclosure_marshal_VOID__ENUM,
143                               G_TYPE_NONE, 1,
144                               GTK_TYPE_PRINT_OPERATION_RESULT);
145         
146 }
147
148 /* Public methods */
149 void
150 ev_print_operation_set_current_page (EvPrintOperation *op,
151                                      gint              current_page)
152 {
153         EvPrintOperationClass *class = EV_PRINT_OPERATION_GET_CLASS (op);
154
155         g_return_if_fail (EV_IS_PRINT_OPERATION (op));
156         g_return_if_fail (current_page >= 0);
157
158         class->set_current_page (op, current_page);
159 }
160
161 void
162 ev_print_operation_set_print_settings (EvPrintOperation *op,
163                                        GtkPrintSettings *print_settings)
164 {
165         EvPrintOperationClass *class = EV_PRINT_OPERATION_GET_CLASS (op);
166
167         g_return_if_fail (EV_IS_PRINT_OPERATION (op));
168         g_return_if_fail (GTK_IS_PRINT_SETTINGS (print_settings));
169
170         class->set_print_settings (op, print_settings);
171 }
172
173 GtkPrintSettings *
174 ev_print_operation_get_print_settings (EvPrintOperation *op)
175 {
176         EvPrintOperationClass *class = EV_PRINT_OPERATION_GET_CLASS (op);
177
178         g_return_val_if_fail (EV_IS_PRINT_OPERATION (op), NULL);
179
180         return class->get_print_settings (op);
181 }
182
183 void
184 ev_print_operation_set_default_page_setup (EvPrintOperation *op,
185                                            GtkPageSetup     *page_setup)
186 {
187         EvPrintOperationClass *class = EV_PRINT_OPERATION_GET_CLASS (op);
188
189         g_return_if_fail (EV_IS_PRINT_OPERATION (op));
190         g_return_if_fail (GTK_IS_PAGE_SETUP (page_setup));
191
192         class->set_default_page_setup (op, page_setup);
193 }
194
195 GtkPageSetup *
196 ev_print_operation_get_default_page_setup (EvPrintOperation *op)
197 {
198         EvPrintOperationClass *class = EV_PRINT_OPERATION_GET_CLASS (op);
199
200         g_return_val_if_fail (EV_IS_PRINT_OPERATION (op), NULL);
201
202         return class->get_default_page_setup (op);
203 }
204
205 void
206 ev_print_operation_set_job_name (EvPrintOperation *op,
207                                  const gchar      *job_name)
208 {
209         EvPrintOperationClass *class = EV_PRINT_OPERATION_GET_CLASS (op);
210
211         g_return_if_fail (EV_IS_PRINT_OPERATION (op));
212         g_return_if_fail (job_name != NULL);
213
214         class->set_job_name (op, job_name);
215 }
216
217 void
218 ev_print_operation_run (EvPrintOperation *op,
219                         GtkWindow        *parent)
220 {
221         EvPrintOperationClass *class = EV_PRINT_OPERATION_GET_CLASS (op);
222
223         g_return_if_fail (EV_IS_PRINT_OPERATION (op));
224
225         class->run (op, parent);
226 }
227
228 void
229 ev_print_operation_cancel (EvPrintOperation *op)
230 {
231         EvPrintOperationClass *class = EV_PRINT_OPERATION_GET_CLASS (op);
232
233         g_return_if_fail (EV_IS_PRINT_OPERATION (op));
234
235         class->cancel (op);
236 }
237
238 void
239 ev_print_operation_get_error (EvPrintOperation *op,
240                               GError          **error)
241 {
242         EvPrintOperationClass *class = EV_PRINT_OPERATION_GET_CLASS (op);
243
244         g_return_if_fail (EV_IS_PRINT_OPERATION (op));
245
246         class->get_error (op, error);
247 }
248
249 /* Export interface */
250 #define EV_TYPE_PRINT_OPERATION_EXPORT         (ev_print_operation_export_get_type())
251 #define EV_PRINT_OPERATION_EXPORT(object)      (G_TYPE_CHECK_INSTANCE_CAST((object), EV_TYPE_PRINT_OPERATION_EXPORT, EvPrintOperationExport))
252 #define EV_PRINT_OPERATION_EXPORT_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST((klass), EV_TYPE_PRINT_OPERATION_EXPORT, EvPrintOperationExportClass))
253 #define EV_IS_PRINT_OPERATION_EXPORT(object)   (G_TYPE_CHECK_INSTANCE_TYPE((object), EV_TYPE_PRINT_OPERATION_EXPORT))
254
255 typedef struct _EvPrintOperationExport      EvPrintOperationExport;
256 typedef struct _EvPrintOperationExportClass EvPrintOperationExportClass;
257
258 GType           ev_print_operation_export_get_type (void) G_GNUC_CONST;
259
260 static gboolean export_print_page                  (EvPrintOperationExport *export);
261
262 struct _EvPrintOperationExport {
263         EvPrintOperation parent;
264
265         GtkWindow *parent_window;
266         EvJob *job_export;
267         GError *error;
268
269         gboolean print_preview;
270         gint n_pages;
271         gint current_page;
272         GtkPrinter *printer;
273         GtkPageSetup *page_setup;
274         GtkPrintSettings *print_settings;
275         GtkPageSet page_set;
276         gint copies;
277         guint collate     : 1;
278         guint reverse     : 1;
279         gint pages_per_sheet;
280         gint fd;
281         gchar *temp_file;
282         gchar *job_name;
283         
284         guint idle_id;
285         
286         /* Context */
287         gint uncollated_copies;
288         gint collated_copies;
289         gint uncollated, collated, total;
290
291         gint range, n_ranges;
292         GtkPageRange *ranges;
293         GtkPageRange one_range;
294
295         gint page, start, end, inc;
296 };
297
298 struct _EvPrintOperationExportClass {
299         EvPrintOperationClass parent_class;
300 };
301
302 G_DEFINE_TYPE (EvPrintOperationExport, ev_print_operation_export, EV_TYPE_PRINT_OPERATION)
303
304 static void
305 ev_print_operation_export_set_current_page (EvPrintOperation *op,
306                                             gint              current_page)
307 {
308         EvPrintOperationExport *export = EV_PRINT_OPERATION_EXPORT (op);
309
310         g_return_if_fail (current_page < export->n_pages);
311         
312         export->current_page = current_page;
313 }
314
315 static void
316 ev_print_operation_export_set_print_settings (EvPrintOperation *op,
317                                               GtkPrintSettings *print_settings)
318 {
319         EvPrintOperationExport *export = EV_PRINT_OPERATION_EXPORT (op);
320
321         if (print_settings == export->print_settings)
322                 return;
323
324         g_object_ref (print_settings);
325         if (export->print_settings)
326                 g_object_unref (export->print_settings);
327         export->print_settings = print_settings;
328 }
329
330 static GtkPrintSettings *
331 ev_print_operation_export_get_print_settings (EvPrintOperation *op)
332 {
333         EvPrintOperationExport *export = EV_PRINT_OPERATION_EXPORT (op);
334
335         return export->print_settings;
336 }
337
338 static void
339 ev_print_operation_export_set_default_page_setup (EvPrintOperation *op,
340                                                   GtkPageSetup     *page_setup)
341 {
342         EvPrintOperationExport *export = EV_PRINT_OPERATION_EXPORT (op);
343
344         if (page_setup == export->page_setup)
345                 return;
346
347         g_object_ref (page_setup);
348         if (export->page_setup)
349                 g_object_unref (export->page_setup);
350         export->page_setup = page_setup;
351 }
352
353 static GtkPageSetup *
354 ev_print_operation_export_get_default_page_setup (EvPrintOperation *op)
355 {
356         EvPrintOperationExport *export = EV_PRINT_OPERATION_EXPORT (op);
357
358         return export->page_setup;
359 }
360
361 static void
362 ev_print_operation_export_set_job_name (EvPrintOperation *op,
363                                         const gchar      *job_name)
364 {
365         EvPrintOperationExport *export = EV_PRINT_OPERATION_EXPORT (op);
366
367         g_free (export->job_name);
368         export->job_name = g_strdup (job_name);
369 }
370
371 static void
372 ev_print_operation_export_set_printer (EvPrintOperationExport *export,
373                                        GtkPrinter             *printer)
374 {
375         if (printer == export->printer)
376                 return;
377
378         g_object_ref (printer);
379         if (export->printer)
380                 g_object_unref (export->printer);
381         export->printer = printer;
382 }
383
384 static void
385 find_range (EvPrintOperationExport *export)
386 {
387         GtkPageRange *range;
388
389         range = &export->ranges[export->range];
390
391         if (export->inc < 0) {
392                 export->start = range->end;
393                 export->end = range->start - 1;
394         } else {
395                 export->start = range->start;
396                 export->end = range->end + 1;
397         }
398 }
399
400 static void
401 clamp_ranges (EvPrintOperationExport *export)
402 {
403         gint num_of_correct_ranges = 0;
404         gint i;
405
406         for (i = 0; i < export->n_ranges; i++) {
407                 if ((export->ranges[i].start >= 0) &&
408                     (export->ranges[i].start < export->n_pages) &&
409                     (export->ranges[i].end >= 0) &&
410                     (export->ranges[i].end < export->n_pages)) {
411                         export->ranges[num_of_correct_ranges] = export->ranges[i];
412                         num_of_correct_ranges++;
413                 } else if ((export->ranges[i].start >= 0) &&
414                            (export->ranges[i].start < export->n_pages) &&
415                            (export->ranges[i].end >= export->n_pages)) {
416                         export->ranges[i].end = export->n_pages - 1;
417                         export->ranges[num_of_correct_ranges] = export->ranges[i];
418                         num_of_correct_ranges++;
419                 } else if ((export->ranges[i].end >= 0) &&
420                            (export->ranges[i].end < export->n_pages) &&
421                            (export->ranges[i].start < 0)) {
422                         export->ranges[i].start = 0;
423                         export->ranges[num_of_correct_ranges] = export->ranges[i];
424                         num_of_correct_ranges++;
425                 }
426         }
427
428         export->n_ranges = num_of_correct_ranges;
429 }
430
431 static gint
432 get_first_page (EvPrintOperationExport *export)
433 {
434         gint i;
435         gint first_page = G_MAXINT;
436
437         if (export->n_ranges == 0)
438                 return 0;
439
440         for (i = 0; i < export->n_ranges; i++) {
441                 if (export->ranges[i].start < first_page)
442                         first_page = export->ranges[i].start;
443         }
444
445         return MAX (0, first_page);
446 }
447
448 static gint
449 get_last_page (EvPrintOperationExport *export)
450 {
451         gint i;
452         gint last_page = G_MININT;
453         gint max_page = export->n_pages - 1;
454
455         if (export->n_ranges == 0)
456                 return max_page;
457
458         for (i = 0; i < export->n_ranges; i++) {
459                 if (export->ranges[i].end > last_page)
460                         last_page = export->ranges[i].end;
461         }
462
463         return MIN (max_page, last_page);
464 }
465
466 static gboolean
467 export_print_inc_page (EvPrintOperationExport *export)
468 {
469         do {
470                 export->page += export->inc;
471                 if (export->page == export->end) {
472                         export->range += export->inc;
473                         if (export->range == -1 || export->range == export->n_ranges) {
474                                 export->uncollated++;
475                                 if (export->uncollated == export->uncollated_copies)
476                                         return FALSE;
477
478                                 export->range = export->inc < 0 ? export->n_ranges - 1 : 0;
479                         }
480                         find_range (export);
481                         export->page = export->start;
482                 }
483         } while ((export->page_set == GTK_PAGE_SET_EVEN && export->page % 2 == 0) ||
484                  (export->page_set == GTK_PAGE_SET_ODD && export->page % 2 == 1));
485
486         return TRUE;
487 }
488
489 static void
490 ev_print_operation_export_clear_temp_file (EvPrintOperationExport *export)
491 {
492         if (!export->temp_file)
493                 return;
494
495         g_unlink (export->temp_file);
496         g_free (export->temp_file);
497         export->temp_file = NULL;
498 }
499
500 static void
501 print_job_finished (GtkPrintJob            *print_job,
502                     EvPrintOperationExport *export,
503                     GError                 *error)
504 {
505         EvPrintOperation *op = EV_PRINT_OPERATION (export);
506         
507         if (error) {
508                 g_set_error_literal (&export->error,
509                                      GTK_PRINT_ERROR,
510                                      GTK_PRINT_ERROR_GENERAL,
511                                      error->message);
512                 g_signal_emit (op, signals[DONE], 0, GTK_PRINT_OPERATION_RESULT_ERROR);
513         } else {
514                 g_signal_emit (op, signals[DONE], 0, GTK_PRINT_OPERATION_RESULT_APPLY);
515         }
516
517         ev_print_operation_export_clear_temp_file (export);
518         g_object_unref (print_job);
519 }
520
521 static void
522 export_print_done (EvPrintOperationExport *export)
523 {
524         EvPrintOperation *op = EV_PRINT_OPERATION (export);
525         GtkPrintSettings *settings;
526         EvFileExporterCapabilities capabilities;
527
528         /* Some printers take into account some print settings,
529          * and others don't. However we have exported the document
530          * to a ps or pdf file according to such print settings. So,
531          * we want to send the exported file to printer with those
532          * settings set to default values.
533          */
534         settings = gtk_print_settings_copy (export->print_settings);
535         capabilities = ev_file_exporter_get_capabilities (EV_FILE_EXPORTER (op->document));
536
537         gtk_print_settings_set_page_ranges (settings, NULL, 0);
538         gtk_print_settings_set_print_pages (settings, GTK_PRINT_PAGES_ALL);
539         if (capabilities & EV_FILE_EXPORTER_CAN_COPIES)
540                 gtk_print_settings_set_n_copies (settings, 1);
541         if (capabilities & EV_FILE_EXPORTER_CAN_PAGE_SET)
542                 gtk_print_settings_set_page_set (settings, GTK_PAGE_SET_ALL);
543         if (capabilities & EV_FILE_EXPORTER_CAN_SCALE)
544                 gtk_print_settings_set_scale (settings, 1.0);
545         if (capabilities & EV_FILE_EXPORTER_CAN_COLLATE)
546                 gtk_print_settings_set_collate (settings, FALSE);
547         if (capabilities & EV_FILE_EXPORTER_CAN_REVERSE)
548                 gtk_print_settings_set_reverse (settings, FALSE);
549         if (capabilities & EV_FILE_EXPORTER_CAN_NUMBER_UP) {
550                 gtk_print_settings_set_number_up (settings, 1);
551                 gtk_print_settings_set_int (settings, "cups-"GTK_PRINT_SETTINGS_NUMBER_UP, 1);
552         }
553
554         if (export->print_preview) {
555                 gchar *uri;
556                 gchar *print_settings_file = NULL;
557
558                 print_settings_file = ev_tmp_filename ("print-settings");
559                 gtk_print_settings_to_file (settings, print_settings_file, NULL);
560
561                 uri = g_filename_to_uri (export->temp_file, NULL, NULL);
562                 ev_application_open_uri_at_dest (EV_APP,
563                                                  uri,
564                                                  gtk_window_get_screen (export->parent_window),
565                                                  NULL,
566                                                  EV_WINDOW_MODE_PREVIEW,
567                                                  NULL,
568                                                  TRUE,
569                                                  print_settings_file,
570                                                  GDK_CURRENT_TIME);
571                 g_free (print_settings_file);
572                 g_free (uri);
573
574                 g_signal_emit (op, signals[DONE], 0, GTK_PRINT_OPERATION_RESULT_APPLY);
575                 /* temp_file will be deleted by the previewer */
576         } else {
577                 GtkPrintJob *job;
578                 GError      *error = NULL;
579                 
580                 job = gtk_print_job_new (export->job_name,
581                                          export->printer,
582                                          settings,
583                                          export->page_setup);
584                 gtk_print_job_set_source_file (job, export->temp_file, &error);
585                 if (error) {
586                         g_set_error_literal (&export->error,
587                                              GTK_PRINT_ERROR,
588                                              GTK_PRINT_ERROR_GENERAL,
589                                              error->message);
590                         g_error_free (error);
591                         ev_print_operation_export_clear_temp_file (export);
592                         g_signal_emit (op, signals[DONE], 0, GTK_PRINT_OPERATION_RESULT_ERROR);
593                 } else {
594                         gtk_print_job_send (job,
595                                             (GtkPrintJobCompleteFunc)print_job_finished,
596                                             g_object_ref (export),
597                                             (GDestroyNotify)g_object_unref);
598                 }
599         }
600         g_object_unref (settings);
601 }
602
603 static void
604 export_print_page_idle_finished (EvPrintOperationExport *export)
605 {
606         export->idle_id = 0;
607 }
608
609 static void
610 export_job_finished (EvJobExport            *job,
611                      EvPrintOperationExport *export)
612 {
613         EvPrintOperation *op = EV_PRINT_OPERATION (export);
614
615         if (export->pages_per_sheet == 1 || export->total % export->pages_per_sheet == 0) {
616                 ev_document_doc_mutex_lock ();
617                 ev_file_exporter_end_page (EV_FILE_EXPORTER (op->document));
618                 ev_document_doc_mutex_unlock ();
619         }
620
621         /* Reschedule */
622         export->idle_id = g_idle_add_full (G_PRIORITY_DEFAULT_IDLE,
623                                            (GSourceFunc)export_print_page,
624                                            export,
625                                            (GDestroyNotify)export_print_page_idle_finished);
626 }
627
628 static void
629 export_job_cancelled (EvJobExport            *job,
630                       EvPrintOperationExport *export)
631 {
632         EvPrintOperation *op = EV_PRINT_OPERATION (export);
633
634         if (export->idle_id > 0)
635                 g_source_remove (export->idle_id);
636         export->idle_id = 0;
637
638         g_signal_handlers_disconnect_by_func (export->job_export,
639                                               export_job_finished,
640                                               export);
641         g_signal_handlers_disconnect_by_func (export->job_export,
642                                               export_job_cancelled,
643                                               export);
644         g_object_unref (export->job_export);
645         export->job_export = NULL;
646
647         if (export->fd != -1) {
648                 close (export->fd);
649                 export->fd = -1;
650         }
651
652         ev_print_operation_export_clear_temp_file (export);
653
654         g_signal_emit (op, signals[DONE], 0, GTK_PRINT_OPERATION_RESULT_CANCEL);
655 }
656
657 static gboolean
658 export_print_page (EvPrintOperationExport *export)
659 {
660         EvPrintOperation *op = EV_PRINT_OPERATION (export);
661         
662         export->total++;
663         export->collated++;
664
665         if (export->collated == export->collated_copies) {
666                 export->collated = 0;
667                 if (!export_print_inc_page (export)) {
668                         ev_document_doc_mutex_lock ();
669                         if (export->pages_per_sheet > 1 &&
670                             export->total - 1 % export->pages_per_sheet == 0)
671                                 ev_file_exporter_end_page (EV_FILE_EXPORTER (op->document));
672                         ev_file_exporter_end (EV_FILE_EXPORTER (op->document));
673                         ev_document_doc_mutex_unlock ();
674
675                         close (export->fd);
676                         export->fd = -1;
677
678                         export_print_done (export);
679                         
680                         return FALSE;
681                 }
682         }
683
684         if (export->pages_per_sheet == 1 || export->total % export->pages_per_sheet == 1) {
685                 ev_document_doc_mutex_lock ();
686                 ev_file_exporter_begin_page (EV_FILE_EXPORTER (op->document));
687                 ev_document_doc_mutex_unlock ();
688         }
689         
690         if (!export->job_export) {
691                 export->job_export = ev_job_export_new (op->document);
692                 g_signal_connect (G_OBJECT (export->job_export), "finished",
693                                   G_CALLBACK (export_job_finished),
694                                   (gpointer)export);
695                 g_signal_connect (G_OBJECT (export->job_export), "cancelled",
696                                   G_CALLBACK (export_job_cancelled),
697                                   (gpointer)export);
698         }
699
700         ev_job_export_set_page (EV_JOB_EXPORT (export->job_export), export->page);
701         ev_job_scheduler_push_job (export->job_export, EV_JOB_PRIORITY_NONE);
702         
703         return FALSE;
704 }
705
706 static gboolean
707 ev_print_operation_export_print_dialog_response_cb (GtkDialog              *dialog,
708                                                     gint                    response,
709                                                     EvPrintOperationExport *export)
710 {
711         GtkPrintPages         print_pages;
712         GtkPrintSettings     *print_settings;
713         GtkPageSetup         *page_setup;
714         GtkPrinter           *printer;
715         gdouble               scale;
716         gdouble               width;
717         gdouble               height;
718         gint                  first_page;
719         gint                  last_page;
720         const gchar          *file_format;
721         gchar                *filename;
722         EvFileExporterContext fc;
723         GError               *error = NULL;
724         EvPrintOperation     *op = EV_PRINT_OPERATION (export);
725         
726         if (response != GTK_RESPONSE_OK &&
727             response != GTK_RESPONSE_APPLY) {
728                 gtk_widget_destroy (GTK_WIDGET (dialog));
729
730                 return FALSE;
731         }
732
733         export->print_preview = (response == GTK_RESPONSE_APPLY);
734         
735         printer = gtk_print_unix_dialog_get_selected_printer (GTK_PRINT_UNIX_DIALOG (dialog));
736         ev_print_operation_export_set_printer (export, printer);
737
738         print_settings = gtk_print_unix_dialog_get_settings (GTK_PRINT_UNIX_DIALOG (dialog));
739         ev_print_operation_export_set_print_settings (op, print_settings);
740
741         page_setup = gtk_print_unix_dialog_get_page_setup (GTK_PRINT_UNIX_DIALOG (dialog));
742         ev_print_operation_export_set_default_page_setup (op, page_setup);
743
744         if (!gtk_printer_accepts_ps (export->printer)) {
745                 g_set_error (&export->error,
746                              GTK_PRINT_ERROR,
747                              GTK_PRINT_ERROR_GENERAL,
748                              "%s", _("Printing is not supported on this printer."));
749                 g_signal_emit (op, signals[DONE], 0, GTK_PRINT_OPERATION_RESULT_ERROR);
750                 gtk_widget_destroy (GTK_WIDGET (dialog));
751                 
752                 return FALSE;
753         }
754
755         file_format = gtk_print_settings_get (print_settings, GTK_PRINT_SETTINGS_OUTPUT_FILE_FORMAT);
756         
757         filename = g_strdup_printf ("evince_print.%s.XXXXXX", file_format);
758         export->fd = g_file_open_tmp (filename, &export->temp_file, &error);
759         g_free (filename);
760         if (export->fd <= -1) {
761                 g_set_error_literal (&export->error,
762                                      GTK_PRINT_ERROR,
763                                      GTK_PRINT_ERROR_GENERAL,
764                                      error->message);
765                 g_error_free (error);
766                 g_signal_emit (op, signals[DONE], 0, GTK_PRINT_OPERATION_RESULT_ERROR);
767                 gtk_widget_destroy (GTK_WIDGET (dialog));
768
769                 return FALSE;
770         }
771
772         export->current_page = gtk_print_unix_dialog_get_current_page (GTK_PRINT_UNIX_DIALOG (dialog));
773         print_pages = gtk_print_settings_get_print_pages (print_settings);
774         
775         switch (print_pages) {
776         case GTK_PRINT_PAGES_CURRENT:
777                 export->ranges = &export->one_range;
778                 
779                 export->ranges[0].start = export->current_page;
780                 export->ranges[0].end = export->current_page;
781                 export->n_ranges = 1;
782                                 
783                 break;
784         case GTK_PRINT_PAGES_RANGES: {
785                 gint i;
786                 
787                 export->ranges = gtk_print_settings_get_page_ranges (print_settings, &export->n_ranges);
788                 for (i = 0; i < export->n_ranges; i++)
789                         if (export->ranges[i].end == -1 || export->ranges[i].end >= export->n_pages)
790                                 export->ranges[i].end = export->n_pages - 1;
791         }
792                 break;
793         case GTK_PRINT_PAGES_ALL:
794                 export->ranges = &export->one_range;
795
796                 export->ranges[0].start = 0;
797                 export->ranges[0].end = export->n_pages - 1;
798                 export->n_ranges = 1;
799                 
800                 break;
801         }
802         clamp_ranges (export);
803
804         export->page_set = gtk_print_settings_get_page_set (print_settings);
805
806         width = gtk_page_setup_get_paper_width (page_setup, GTK_UNIT_POINTS);
807         height = gtk_page_setup_get_paper_height (page_setup, GTK_UNIT_POINTS);
808         scale = gtk_print_settings_get_scale (print_settings) * 0.01;
809         if (scale != 1.0) {
810                 width *= scale;
811                 height *= scale;
812         }
813
814         export->pages_per_sheet = gtk_print_settings_get_number_up (print_settings);
815         
816         export->copies = gtk_print_settings_get_n_copies (print_settings);
817         export->collate = gtk_print_settings_get_collate (print_settings);
818         export->reverse = gtk_print_settings_get_reverse (print_settings);
819
820         if (export->collate) {
821                 export->uncollated_copies = export->copies;
822                 export->collated_copies = 1;
823         } else {
824                 export->uncollated_copies = 1;
825                 export->collated_copies = export->copies;
826         }
827
828         if (export->reverse) {
829                 export->range = export->n_ranges - 1;
830                 export->inc = -1;
831         } else {
832                 export->range = 0;
833                 export->inc = 1;
834         }
835         find_range (export);
836
837         export->page = export->start - export->inc;
838         export->collated = export->collated_copies - 1;
839
840         first_page = get_first_page (export);
841         last_page = get_last_page (export);
842
843         fc.format = g_ascii_strcasecmp (file_format, "pdf") == 0 ?
844                 EV_FILE_FORMAT_PDF : EV_FILE_FORMAT_PS;
845         fc.filename = export->temp_file;
846         fc.first_page = MIN (first_page, last_page);
847         fc.last_page = MAX (first_page, last_page);
848         fc.paper_width = width;
849         fc.paper_height = height;
850         fc.duplex = FALSE;
851         fc.pages_per_sheet = MAX (1, export->pages_per_sheet);
852
853         ev_document_doc_mutex_lock ();
854         ev_file_exporter_begin (EV_FILE_EXPORTER (op->document), &fc);
855         ev_document_doc_mutex_unlock ();
856
857         export->idle_id = g_idle_add_full (G_PRIORITY_DEFAULT_IDLE,
858                                            (GSourceFunc)export_print_page,
859                                            export,
860                                            (GDestroyNotify)export_print_page_idle_finished);
861         
862         gtk_widget_destroy (GTK_WIDGET (dialog));
863
864         return TRUE;
865 }
866
867 static void
868 ev_print_operation_export_run (EvPrintOperation *op,
869                                GtkWindow        *parent)
870 {
871         EvPrintOperationExport *export = EV_PRINT_OPERATION_EXPORT (op);
872         GtkWidget              *dialog;
873         GtkPrintCapabilities    capabilities;
874
875         export->parent_window = parent;
876         export->error = NULL;
877         
878         dialog = gtk_print_unix_dialog_new (_("Print"), parent);
879         gtk_window_set_modal (GTK_WINDOW (dialog), TRUE);
880         
881         capabilities = GTK_PRINT_CAPABILITY_PREVIEW |
882                 ev_file_exporter_get_capabilities (EV_FILE_EXPORTER (op->document));
883         gtk_print_unix_dialog_set_manual_capabilities (GTK_PRINT_UNIX_DIALOG (dialog),
884                                                        capabilities);
885
886         gtk_print_unix_dialog_set_current_page (GTK_PRINT_UNIX_DIALOG (dialog),
887                                                 export->current_page);
888         
889         gtk_print_unix_dialog_set_settings (GTK_PRINT_UNIX_DIALOG (dialog),
890                                             export->print_settings);
891         
892         if (export->page_setup)
893                 gtk_print_unix_dialog_set_page_setup (GTK_PRINT_UNIX_DIALOG (dialog),
894                                                       export->page_setup);
895         
896         g_signal_connect (G_OBJECT (dialog), "response",
897                           G_CALLBACK (ev_print_operation_export_print_dialog_response_cb),
898                           export);
899
900         gtk_window_present (GTK_WINDOW (dialog));
901 }
902
903 static void
904 ev_print_operation_export_cancel (EvPrintOperation *op)
905 {
906         EvPrintOperationExport *export = EV_PRINT_OPERATION_EXPORT (op);
907
908         if (export->job_export) {
909                 ev_job_cancel (export->job_export);
910         }
911 }
912
913 static void
914 ev_print_operation_export_get_error (EvPrintOperation *op,
915                                      GError          **error)
916 {
917         EvPrintOperationExport *export = EV_PRINT_OPERATION_EXPORT (op);
918
919         g_propagate_error (error, export->error);
920         export->error = NULL;
921 }
922
923 static void
924 ev_print_operation_export_finalize (GObject *object)
925 {
926         EvPrintOperationExport *export = EV_PRINT_OPERATION_EXPORT (object);
927
928         if (export->idle_id > 0) {
929                 g_source_remove (export->idle_id);
930                 export->idle_id = 0;
931         }
932
933         if (export->fd != -1) {
934                 close (export->fd);
935                 export->fd = -1;
936         }
937         
938         if (export->ranges) {
939                 if (export->ranges != &export->one_range)
940                         g_free (export->ranges);
941                 export->ranges = NULL;
942                 export->n_ranges = 0;
943         }
944
945         if (export->temp_file) {
946                 g_free (export->temp_file);
947                 export->temp_file = NULL;
948         }
949
950         if (export->job_name) {
951                 g_free (export->job_name);
952                 export->job_name = NULL;
953         }
954
955         if (export->job_export) {
956                 if (!ev_job_is_finished (export->job_export))
957                         ev_job_cancel (export->job_export);
958                 g_signal_handlers_disconnect_by_func (export->job_export,
959                                                       export_job_finished,
960                                                       export);
961                 g_signal_handlers_disconnect_by_func (export->job_export,
962                                                       export_job_cancelled,
963                                                       export);
964                 g_object_unref (export->job_export);
965                 export->job_export = NULL;
966         }
967
968         if (export->error) {
969                 g_error_free (export->error);
970                 export->error = NULL;
971         }
972
973         if (export->print_settings) {
974                 g_object_unref (export->print_settings);
975                 export->print_settings = NULL;
976         }
977
978         if (export->page_setup) {
979                 g_object_unref (export->page_setup);
980                 export->page_setup = NULL;
981         }
982
983         if (export->printer) {
984                 g_object_unref (export->printer);
985                 export->printer = NULL;
986         }
987
988         (* G_OBJECT_CLASS (ev_print_operation_export_parent_class)->finalize) (object);
989 }
990
991 static void
992 ev_print_operation_export_init (EvPrintOperationExport *export)
993 {
994 }
995
996 static GObject *
997 ev_print_operation_export_constructor (GType                  type,
998                                        guint                  n_construct_properties,
999                                        GObjectConstructParam *construct_params)
1000 {
1001         GObject                *object;
1002         EvPrintOperationExport *export;
1003         EvPrintOperation       *op;
1004         
1005         object = G_OBJECT_CLASS (ev_print_operation_export_parent_class)->constructor (type,
1006                                                                                        n_construct_properties,
1007                                                                                        construct_params);
1008         export = EV_PRINT_OPERATION_EXPORT (object);
1009         op = EV_PRINT_OPERATION (object);
1010         export->n_pages = ev_page_cache_get_n_pages (ev_page_cache_get (op->document));
1011
1012         return object;
1013 }
1014
1015 static void
1016 ev_print_operation_export_class_init (EvPrintOperationExportClass *klass)
1017 {
1018         GObjectClass          *g_object_class = G_OBJECT_CLASS (klass);
1019         EvPrintOperationClass *ev_print_op_class = EV_PRINT_OPERATION_CLASS (klass);
1020
1021         ev_print_op_class->set_current_page = ev_print_operation_export_set_current_page;
1022         ev_print_op_class->set_print_settings = ev_print_operation_export_set_print_settings;
1023         ev_print_op_class->get_print_settings = ev_print_operation_export_get_print_settings;
1024         ev_print_op_class->set_default_page_setup = ev_print_operation_export_set_default_page_setup;
1025         ev_print_op_class->get_default_page_setup = ev_print_operation_export_get_default_page_setup;
1026         ev_print_op_class->set_job_name = ev_print_operation_export_set_job_name;
1027         ev_print_op_class->run = ev_print_operation_export_run;
1028         ev_print_op_class->cancel = ev_print_operation_export_cancel;
1029         ev_print_op_class->get_error = ev_print_operation_export_get_error;
1030
1031         g_object_class->constructor = ev_print_operation_export_constructor;
1032         g_object_class->finalize = ev_print_operation_export_finalize;
1033 }
1034
1035 /* Factory method */
1036 EvPrintOperation *
1037 ev_print_operation_new (EvDocument *document)
1038 {
1039         /* TODO: EvPrintOperationPrint */
1040
1041         return EV_PRINT_OPERATION (g_object_new (EV_TYPE_PRINT_OPERATION_EXPORT,
1042                                                  "document", document, NULL));
1043 }