]> www.fi.muni.cz Git - evince.git/blob - libview/ev-jobs.c
Remove attachments from EvDocument interface and use EvDocumentAttachments instead
[evince.git] / libview / ev-jobs.c
1 /* this file is part of evince, a gnome document viewer
2  *
3  *  Copyright (C) 2008 Carlos Garcia Campos <carlosgc@gnome.org>
4  *  Copyright (C) 2005 Red Hat, Inc
5  *
6  * Evince is free software; you can redistribute it and/or modify it
7  * under the terms of the GNU General Public License as published by
8  * the Free Software Foundation; either version 2 of the License, or
9  * (at your option) any later version.
10  *
11  * Evince is distributed in the hope that it will be useful, but
12  * WITHOUT ANY WARRANTY; without even the implied warranty of
13  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
14  * General Public License for more details.
15  *
16  * You should have received a copy of the GNU General Public License
17  * along with this program; if not, write to the Free Software
18  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307, USA.
19  */
20
21 #include <config.h>
22
23 #include "ev-jobs.h"
24 #include "ev-document-thumbnails.h"
25 #include "ev-document-links.h"
26 #include "ev-document-images.h"
27 #include "ev-document-forms.h"
28 #include "ev-file-exporter.h"
29 #include "ev-document-factory.h"
30 #include "ev-document-misc.h"
31 #include "ev-file-helpers.h"
32 #include "ev-document-fonts.h"
33 #include "ev-document-security.h"
34 #include "ev-document-find.h"
35 #include "ev-document-layers.h"
36 #include "ev-document-print.h"
37 #include "ev-document-annotations.h"
38 #include "ev-document-attachments.h"
39 #include "ev-debug.h"
40
41 #include <errno.h>
42 #include <glib/gstdio.h>
43 #include <glib/gi18n-lib.h>
44 #include <unistd.h>
45
46 static void ev_job_init                   (EvJob                 *job);
47 static void ev_job_class_init             (EvJobClass            *class);
48 static void ev_job_links_init             (EvJobLinks            *job);
49 static void ev_job_links_class_init       (EvJobLinksClass       *class);
50 static void ev_job_attachments_init       (EvJobAttachments      *job);
51 static void ev_job_attachments_class_init (EvJobAttachmentsClass *class);
52 static void ev_job_render_init            (EvJobRender           *job);
53 static void ev_job_render_class_init      (EvJobRenderClass      *class);
54 static void ev_job_thumbnail_init         (EvJobThumbnail        *job);
55 static void ev_job_thumbnail_class_init   (EvJobThumbnailClass   *class);
56 static void ev_job_load_init              (EvJobLoad             *job);
57 static void ev_job_load_class_init        (EvJobLoadClass        *class);
58 static void ev_job_save_init              (EvJobSave             *job);
59 static void ev_job_save_class_init        (EvJobSaveClass        *class);
60 static void ev_job_find_init              (EvJobFind             *job);
61 static void ev_job_find_class_init        (EvJobFindClass        *class);
62 static void ev_job_layers_init            (EvJobLayers           *job);
63 static void ev_job_layers_class_init      (EvJobLayersClass      *class);
64 static void ev_job_export_init            (EvJobExport           *job);
65 static void ev_job_export_class_init      (EvJobExportClass      *class);
66 static void ev_job_print_init             (EvJobPrint            *job);
67 static void ev_job_print_class_init       (EvJobPrintClass       *class);
68
69 enum {
70         CANCELLED,
71         FINISHED,
72         LAST_SIGNAL
73 };
74
75 enum {
76         PAGE_READY,
77         RENDER_LAST_SIGNAL
78 };
79
80 enum {
81         FONTS_UPDATED,
82         FONTS_LAST_SIGNAL
83 };
84
85 enum {
86         FIND_UPDATED,
87         FIND_LAST_SIGNAL
88 };
89
90 static guint job_signals[LAST_SIGNAL] = { 0 };
91 static guint job_render_signals[RENDER_LAST_SIGNAL] = { 0 };
92 static guint job_fonts_signals[FONTS_LAST_SIGNAL] = { 0 };
93 static guint job_find_signals[FIND_LAST_SIGNAL] = { 0 };
94
95 G_DEFINE_ABSTRACT_TYPE (EvJob, ev_job, G_TYPE_OBJECT)
96 G_DEFINE_TYPE (EvJobLinks, ev_job_links, EV_TYPE_JOB)
97 G_DEFINE_TYPE (EvJobAttachments, ev_job_attachments, EV_TYPE_JOB)
98 G_DEFINE_TYPE (EvJobRender, ev_job_render, EV_TYPE_JOB)
99 G_DEFINE_TYPE (EvJobThumbnail, ev_job_thumbnail, EV_TYPE_JOB)
100 G_DEFINE_TYPE (EvJobFonts, ev_job_fonts, EV_TYPE_JOB)
101 G_DEFINE_TYPE (EvJobLoad, ev_job_load, EV_TYPE_JOB)
102 G_DEFINE_TYPE (EvJobSave, ev_job_save, EV_TYPE_JOB)
103 G_DEFINE_TYPE (EvJobFind, ev_job_find, EV_TYPE_JOB)
104 G_DEFINE_TYPE (EvJobLayers, ev_job_layers, EV_TYPE_JOB)
105 G_DEFINE_TYPE (EvJobExport, ev_job_export, EV_TYPE_JOB)
106 G_DEFINE_TYPE (EvJobPrint, ev_job_print, EV_TYPE_JOB)
107
108 /* EvJob */
109 static void
110 ev_job_init (EvJob *job)
111 {
112         job->cancellable = g_cancellable_new ();
113 }
114
115 static void
116 ev_job_dispose (GObject *object)
117 {
118         EvJob *job;
119
120         job = EV_JOB (object);
121
122         if (job->document) {
123                 g_object_unref (job->document);
124                 job->document = NULL;
125         }
126
127         if (job->cancellable) {
128                 g_object_unref (job->cancellable);
129                 job->cancellable = NULL;
130         }
131
132         if (job->error) {
133                 g_error_free (job->error);
134                 job->error = NULL;
135         }
136
137         (* G_OBJECT_CLASS (ev_job_parent_class)->dispose) (object);
138 }
139
140 static void
141 ev_job_class_init (EvJobClass *class)
142 {
143         GObjectClass *oclass;
144
145         oclass = G_OBJECT_CLASS (class);
146
147         oclass->dispose = ev_job_dispose;
148
149         job_signals[CANCELLED] =
150                 g_signal_new ("cancelled",
151                               EV_TYPE_JOB,
152                               G_SIGNAL_RUN_LAST,
153                               G_STRUCT_OFFSET (EvJobClass, cancelled),
154                               NULL, NULL,
155                               g_cclosure_marshal_VOID__VOID,
156                               G_TYPE_NONE, 0);
157         job_signals [FINISHED] =
158                 g_signal_new ("finished",
159                               EV_TYPE_JOB,
160                               G_SIGNAL_RUN_FIRST,
161                               G_STRUCT_OFFSET (EvJobClass, finished),
162                               NULL, NULL,
163                               g_cclosure_marshal_VOID__VOID,
164                               G_TYPE_NONE, 0);
165 }
166
167 static gboolean
168 emit_finished (EvJob *job)
169 {
170         ev_debug_message (DEBUG_JOBS, "%s (%p)", EV_GET_TYPE_NAME (job), job);
171
172         job->idle_finished_id = 0;
173         
174         if (job->cancelled) {
175                 ev_debug_message (DEBUG_JOBS, "%s (%p) job was cancelled, do not emit finished", EV_GET_TYPE_NAME (job), job);
176         } else {
177                 ev_profiler_stop (EV_PROFILE_JOBS, "%s (%p)", EV_GET_TYPE_NAME (job), job);
178                 g_signal_emit (job, job_signals[FINISHED], 0);
179         }
180         
181         return FALSE;
182 }
183
184 static void
185 ev_job_emit_finished (EvJob *job)
186 {
187         ev_debug_message (DEBUG_JOBS, "%s (%p)", EV_GET_TYPE_NAME (job), job);
188
189         if (g_cancellable_is_cancelled (job->cancellable)) {
190                 ev_debug_message (DEBUG_JOBS, "%s (%p) job was cancelled, returning", EV_GET_TYPE_NAME (job), job);
191                 return;
192         }
193         
194         job->finished = TRUE;
195         
196         if (job->run_mode == EV_JOB_RUN_THREAD) {
197                 job->idle_finished_id =
198                         g_idle_add_full (G_PRIORITY_DEFAULT_IDLE,
199                                          (GSourceFunc)emit_finished,
200                                          g_object_ref (job),
201                                          (GDestroyNotify)g_object_unref);
202         } else {
203                 ev_profiler_stop (EV_PROFILE_JOBS, "%s (%p)", EV_GET_TYPE_NAME (job), job);
204                 g_signal_emit (job, job_signals[FINISHED], 0);
205         }
206 }
207
208 gboolean
209 ev_job_run (EvJob *job)
210 {
211         EvJobClass *class = EV_JOB_GET_CLASS (job);
212         
213         return class->run (job);
214 }
215
216 void
217 ev_job_cancel (EvJob *job)
218 {
219         if (job->cancelled || (job->finished && job->idle_finished_id == 0))
220                 return;
221
222         ev_debug_message (DEBUG_JOBS, "job %s (%p) cancelled", EV_GET_TYPE_NAME (job), job);
223         ev_profiler_stop (EV_PROFILE_JOBS, "%s (%p)", EV_GET_TYPE_NAME (job), job);
224         
225         /* This should never be called from a thread */
226         job->cancelled = TRUE;
227         g_cancellable_cancel (job->cancellable);
228         g_signal_emit (job, job_signals[CANCELLED], 0);
229 }
230
231 void
232 ev_job_failed (EvJob       *job,
233                GQuark       domain,
234                gint         code,
235                const gchar *format,
236                ...)
237 {
238         va_list args;
239         gchar  *message;
240         
241         if (job->failed || job->finished)
242                 return;
243
244         ev_debug_message (DEBUG_JOBS, "job %s (%p) failed", EV_GET_TYPE_NAME (job), job);
245         
246         job->failed = TRUE;
247         
248         va_start (args, format);
249         message = g_strdup_vprintf (format, args);
250         va_end (args);
251         
252         job->error = g_error_new_literal (domain, code, message);
253         g_free (message);
254         
255         ev_job_emit_finished (job);                                                                                                               
256 }
257
258 void
259 ev_job_failed_from_error (EvJob  *job,
260                           GError *error)
261 {
262         if (job->failed || job->finished)
263                 return;
264         
265         ev_debug_message (DEBUG_JOBS, "job %s (%p) failed", EV_GET_TYPE_NAME (job), job);
266
267         job->failed = TRUE;
268         job->error = g_error_copy (error);
269
270         ev_job_emit_finished (job);
271 }
272
273 void
274 ev_job_succeeded (EvJob *job)
275 {
276         if (job->finished)
277                 return;
278
279         ev_debug_message (DEBUG_JOBS, "job %s (%p) succeeded", EV_GET_TYPE_NAME (job), job);
280         
281         job->failed = FALSE;
282         ev_job_emit_finished (job);
283 }
284
285 gboolean
286 ev_job_is_finished (EvJob *job)
287 {
288         return job->finished;
289 }
290
291 gboolean
292 ev_job_is_failed (EvJob *job)
293 {
294         return job->failed;
295 }
296
297 EvJobRunMode
298 ev_job_get_run_mode (EvJob *job)
299 {
300         return job->run_mode;
301 }
302
303 void
304 ev_job_set_run_mode (EvJob       *job,
305                      EvJobRunMode run_mode)
306 {
307         job->run_mode = run_mode;
308 }
309
310 /* EvJobLinks */
311 static void
312 ev_job_links_init (EvJobLinks *job)
313 {
314         EV_JOB (job)->run_mode = EV_JOB_RUN_THREAD;
315 }
316
317 static void
318 ev_job_links_dispose (GObject *object)
319 {
320         EvJobLinks *job;
321
322         ev_debug_message (DEBUG_JOBS, NULL);
323         
324         job = EV_JOB_LINKS (object);
325
326         if (job->model) {
327                 g_object_unref (job->model);
328                 job->model = NULL;
329         }
330
331         (* G_OBJECT_CLASS (ev_job_links_parent_class)->dispose) (object);
332 }
333
334 static gboolean
335 ev_job_links_run (EvJob *job)
336 {
337         EvJobLinks *job_links = EV_JOB_LINKS (job);
338
339         ev_debug_message (DEBUG_JOBS, NULL);
340         ev_profiler_start (EV_PROFILE_JOBS, "%s (%p)", EV_GET_TYPE_NAME (job), job);
341         
342         ev_document_doc_mutex_lock ();
343         job_links->model = ev_document_links_get_links_model (EV_DOCUMENT_LINKS (job->document));
344         ev_document_doc_mutex_unlock ();
345         
346         ev_job_succeeded (job);
347         
348         return FALSE;
349 }
350
351 static void
352 ev_job_links_class_init (EvJobLinksClass *class)
353 {
354         GObjectClass *oclass = G_OBJECT_CLASS (class);
355         EvJobClass   *job_class = EV_JOB_CLASS (class);
356
357         oclass->dispose = ev_job_links_dispose;
358         job_class->run = ev_job_links_run;
359 }
360
361 EvJob *
362 ev_job_links_new (EvDocument *document)
363 {
364         EvJob *job;
365
366         ev_debug_message (DEBUG_JOBS, NULL);
367
368         job = g_object_new (EV_TYPE_JOB_LINKS, NULL);
369         job->document = g_object_ref (document);
370         
371         return job;
372 }
373
374 /* EvJobAttachments */
375 static void
376 ev_job_attachments_init (EvJobAttachments *job)
377 {
378         EV_JOB (job)->run_mode = EV_JOB_RUN_THREAD;
379 }
380
381 static void
382 ev_job_attachments_dispose (GObject *object)
383 {
384         EvJobAttachments *job;
385
386         ev_debug_message (DEBUG_JOBS, NULL);
387         
388         job = EV_JOB_ATTACHMENTS (object);
389
390         if (job->attachments) {
391                 g_list_foreach (job->attachments, (GFunc)g_object_unref, NULL);
392                 g_list_free (job->attachments);
393                 job->attachments = NULL;
394         }
395
396         (* G_OBJECT_CLASS (ev_job_attachments_parent_class)->dispose) (object);
397 }
398
399 static gboolean
400 ev_job_attachments_run (EvJob *job)
401 {
402         EvJobAttachments *job_attachments = EV_JOB_ATTACHMENTS (job);
403
404         ev_debug_message (DEBUG_JOBS, NULL);
405         ev_profiler_start (EV_PROFILE_JOBS, "%s (%p)", EV_GET_TYPE_NAME (job), job);
406
407         ev_document_doc_mutex_lock ();
408         job_attachments->attachments =
409                 ev_document_attachments_get_attachments (EV_DOCUMENT_ATTACHMENTS (job->document));
410         ev_document_doc_mutex_unlock ();
411
412         ev_job_succeeded (job);
413
414         return FALSE;
415 }
416
417 static void
418 ev_job_attachments_class_init (EvJobAttachmentsClass *class)
419 {
420         GObjectClass *oclass = G_OBJECT_CLASS (class);
421         EvJobClass   *job_class = EV_JOB_CLASS (class);
422
423         oclass->dispose = ev_job_attachments_dispose;
424         job_class->run = ev_job_attachments_run;
425 }
426
427 EvJob *
428 ev_job_attachments_new (EvDocument *document)
429 {
430         EvJob *job;
431
432         ev_debug_message (DEBUG_JOBS, NULL);
433
434         job = g_object_new (EV_TYPE_JOB_ATTACHMENTS, NULL);
435         job->document = g_object_ref (document);
436         
437         return job;
438 }
439
440 /* EvJobRender */
441 static void
442 ev_job_render_init (EvJobRender *job)
443 {
444         EV_JOB (job)->run_mode = EV_JOB_RUN_THREAD;
445 }
446
447 static void
448 ev_job_render_dispose (GObject *object)
449 {
450         EvJobRender *job;
451
452         job = EV_JOB_RENDER (object);
453
454         if (job->ev_page) {
455                 ev_debug_message (DEBUG_JOBS, "page: %d (%p)", job->ev_page->index, job);
456                 g_object_unref (job->ev_page);
457                 job->ev_page = NULL;
458         }
459         
460         if (job->surface) {
461                 cairo_surface_destroy (job->surface);
462                 job->surface = NULL;
463         }
464
465         if (job->selection) {
466                 cairo_surface_destroy (job->selection);
467                 job->selection = NULL;
468         }
469
470         if (job->selection_region) {
471                 gdk_region_destroy (job->selection_region);
472                 job->selection_region = NULL;
473         }
474
475         (* G_OBJECT_CLASS (ev_job_render_parent_class)->dispose) (object);
476 }
477
478 static gboolean
479 notify_page_ready (EvJobRender *job)
480 {
481         ev_debug_message (DEBUG_JOBS, "%d (%p)", job->ev_page->index, job);
482         ev_profiler_stop (EV_PROFILE_JOBS, "Rendering page %d", job->ev_page->index);
483
484         if (EV_JOB (job)->cancelled) {
485                 ev_debug_message (DEBUG_JOBS, "%s (%p) job was cancelled, do not emit page_ready", EV_GET_TYPE_NAME (job), job);
486         } else {
487                 g_signal_emit (job, job_render_signals[PAGE_READY], 0);
488         }
489
490         return FALSE;
491 }
492
493 static void
494 ev_job_render_page_ready (EvJobRender *job)
495 {
496         ev_debug_message (DEBUG_JOBS, "%d (%p)", job->ev_page->index, job);
497         
498         job->page_ready = TRUE;
499         g_idle_add_full (G_PRIORITY_HIGH_IDLE,
500                          (GSourceFunc)notify_page_ready,
501                          g_object_ref (job),
502                          (GDestroyNotify)g_object_unref);
503 }
504
505 static gboolean
506 ev_job_render_run (EvJob *job)
507 {
508         EvJobRender     *job_render = EV_JOB_RENDER (job);
509         EvRenderContext *rc;
510
511         ev_debug_message (DEBUG_JOBS, "page: %d (%p)", job_render->page, job);
512         ev_profiler_start (EV_PROFILE_JOBS, "%s (%p)", EV_GET_TYPE_NAME (job), job);
513         
514         ev_document_doc_mutex_lock ();
515
516         ev_profiler_start (EV_PROFILE_JOBS, "Rendering page %d", job_render->page);
517                 
518         ev_document_fc_mutex_lock ();
519
520         job_render->ev_page = ev_document_get_page (job->document, job_render->page);
521         rc = ev_render_context_new (job_render->ev_page, job_render->rotation, job_render->scale);
522                 
523         job_render->surface = ev_document_render (job->document, rc);
524         /* If job was cancelled during the page rendering,
525          * we return now, so that the thread is finished ASAP
526          */
527         if (g_cancellable_is_cancelled (job->cancellable)) {
528                 ev_document_fc_mutex_unlock ();
529                 ev_document_doc_mutex_unlock ();
530                 g_object_unref (rc);
531
532                 return FALSE;
533         }
534         
535         if ((job_render->flags & EV_RENDER_INCLUDE_SELECTION) && EV_IS_SELECTION (job->document)) {
536                 ev_selection_render_selection (EV_SELECTION (job->document),
537                                                rc,
538                                                &(job_render->selection),
539                                                &(job_render->selection_points),
540                                                NULL,
541                                                job_render->selection_style,
542                                                &(job_render->text), &(job_render->base));
543                 job_render->selection_region =
544                         ev_selection_get_selection_region (EV_SELECTION (job->document),
545                                                            rc,
546                                                            job_render->selection_style,
547                                                            &(job_render->selection_points));
548         }
549
550         ev_job_render_page_ready (job_render);
551                 
552         ev_document_fc_mutex_unlock ();
553                 
554         if ((job_render->flags & EV_RENDER_INCLUDE_TEXT) && EV_IS_SELECTION (job->document))
555                 job_render->text_mapping =
556                         ev_selection_get_selection_map (EV_SELECTION (job->document), rc);
557         if ((job_render->flags & EV_RENDER_INCLUDE_LINKS) && EV_IS_DOCUMENT_LINKS (job->document))
558                 job_render->link_mapping =
559                         ev_document_links_get_links (EV_DOCUMENT_LINKS (job->document), job_render->page);
560         if ((job_render->flags & EV_RENDER_INCLUDE_FORMS) && EV_IS_DOCUMENT_FORMS (job->document))
561                 job_render->form_field_mapping =
562                         ev_document_forms_get_form_fields (EV_DOCUMENT_FORMS (job->document),
563                                                            job_render->ev_page);
564         if ((job_render->flags & EV_RENDER_INCLUDE_IMAGES) && EV_IS_DOCUMENT_IMAGES (job->document))
565                 job_render->image_mapping =
566                         ev_document_images_get_image_mapping (EV_DOCUMENT_IMAGES (job->document),
567                                                               job_render->page);
568         if ((job_render->flags & EV_RENDER_INCLUDE_ANNOTS) && EV_IS_DOCUMENT_ANNOTATIONS (job->document))
569                 job_render->annots_mapping =
570                         ev_document_annotations_get_annotations (EV_DOCUMENT_ANNOTATIONS (job->document),
571                                                                  job_render->ev_page);
572         g_object_unref (rc);
573         ev_document_doc_mutex_unlock ();
574         
575         ev_job_succeeded (job);
576         
577         return FALSE;
578 }
579
580 static void
581 ev_job_render_class_init (EvJobRenderClass *class)
582 {
583         GObjectClass *oclass = G_OBJECT_CLASS (class);
584         EvJobClass   *job_class = EV_JOB_CLASS (class);
585
586         job_render_signals [PAGE_READY] =
587                 g_signal_new ("page-ready",
588                               EV_TYPE_JOB_RENDER,
589                               G_SIGNAL_RUN_LAST,
590                               G_STRUCT_OFFSET (EvJobRenderClass, page_ready),
591                               NULL, NULL,
592                               g_cclosure_marshal_VOID__VOID,
593                               G_TYPE_NONE, 0);
594
595         oclass->dispose = ev_job_render_dispose;
596         job_class->run = ev_job_render_run;
597 }
598
599 EvJob *
600 ev_job_render_new (EvDocument   *document,
601                    gint          page,
602                    gint          rotation,
603                    gdouble       scale, 
604                    gint          width,
605                    gint          height,
606                    EvRenderFlags flags)
607 {
608         EvJobRender *job;
609
610         ev_debug_message (DEBUG_JOBS, "page: %d", page);
611         
612         job = g_object_new (EV_TYPE_JOB_RENDER, NULL);
613
614         EV_JOB (job)->document = g_object_ref (document);
615         job->page = page;
616         job->rotation = rotation;
617         job->scale = scale;
618         job->target_width = width;
619         job->target_height = height;
620         job->flags = flags;
621
622         return EV_JOB (job);
623 }
624
625 void
626 ev_job_render_set_selection_info (EvJobRender     *job,
627                                   EvRectangle     *selection_points,
628                                   EvSelectionStyle selection_style,
629                                   GdkColor        *text,
630                                   GdkColor        *base)
631 {
632         job->flags |= EV_RENDER_INCLUDE_SELECTION;
633         
634         job->selection_points = *selection_points;
635         job->selection_style = selection_style;
636         job->text = *text;
637         job->base = *base;
638 }
639
640 /* EvJobThumbnail */
641 static void
642 ev_job_thumbnail_init (EvJobThumbnail *job)
643 {
644         EV_JOB (job)->run_mode = EV_JOB_RUN_THREAD;
645 }
646
647 static void
648 ev_job_thumbnail_dispose (GObject *object)
649 {
650         EvJobThumbnail *job;
651
652         job = EV_JOB_THUMBNAIL (object);
653
654         ev_debug_message (DEBUG_JOBS, "%d (%p)", job->page, job);
655         
656         if (job->thumbnail) {
657                 g_object_unref (job->thumbnail);
658                 job->thumbnail = NULL;
659         }
660
661         (* G_OBJECT_CLASS (ev_job_thumbnail_parent_class)->dispose) (object);
662 }
663
664 static gboolean
665 ev_job_thumbnail_run (EvJob *job)
666 {
667         EvJobThumbnail  *job_thumb = EV_JOB_THUMBNAIL (job);
668         EvRenderContext *rc;
669         EvPage          *page;
670
671         ev_debug_message (DEBUG_JOBS, "%d (%p)", job_thumb->page, job);
672         ev_profiler_start (EV_PROFILE_JOBS, "%s (%p)", EV_GET_TYPE_NAME (job), job);
673         
674         ev_document_doc_mutex_lock ();
675
676         page = ev_document_get_page (job->document, job_thumb->page);
677         rc = ev_render_context_new (page, job_thumb->rotation, job_thumb->scale);
678         g_object_unref (page);
679
680         job_thumb->thumbnail = ev_document_thumbnails_get_thumbnail (EV_DOCUMENT_THUMBNAILS (job->document),
681                                                                      rc, TRUE);
682         g_object_unref (rc);
683         ev_document_doc_mutex_unlock ();
684
685         ev_job_succeeded (job);
686         
687         return FALSE;
688 }
689
690 static void
691 ev_job_thumbnail_class_init (EvJobThumbnailClass *class)
692 {
693         GObjectClass *oclass = G_OBJECT_CLASS (class);
694         EvJobClass   *job_class = EV_JOB_CLASS (class);
695
696         oclass->dispose = ev_job_thumbnail_dispose;
697         job_class->run = ev_job_thumbnail_run;
698 }
699
700 EvJob *
701 ev_job_thumbnail_new (EvDocument *document,
702                       gint        page,
703                       gint        rotation,
704                       gdouble     scale)
705 {
706         EvJobThumbnail *job;
707
708         ev_debug_message (DEBUG_JOBS, "%d", page);
709         
710         job = g_object_new (EV_TYPE_JOB_THUMBNAIL, NULL);
711
712         EV_JOB (job)->document = g_object_ref (document);
713         job->page = page;
714         job->rotation = rotation;
715         job->scale = scale;
716
717         return EV_JOB (job);
718 }
719
720 /* EvJobFonts */
721 static void
722 ev_job_fonts_init (EvJobFonts *job)
723 {
724         EV_JOB (job)->run_mode = EV_JOB_RUN_MAIN_LOOP;
725 }
726
727 static gboolean
728 ev_job_fonts_run (EvJob *job)
729 {
730         EvJobFonts      *job_fonts = EV_JOB_FONTS (job);
731         EvDocumentFonts *fonts = EV_DOCUMENT_FONTS (job->document);
732
733         ev_debug_message (DEBUG_JOBS, NULL);
734         
735         /* Do not block the main loop */
736         if (!ev_document_doc_mutex_trylock ())
737                 return TRUE;
738         
739         if (!ev_document_fc_mutex_trylock ())
740                 return TRUE;
741
742 #ifdef EV_ENABLE_DEBUG
743         /* We use the #ifdef in this case because of the if */
744         if (ev_document_fonts_get_progress (fonts) == 0)
745                 ev_profiler_start (EV_PROFILE_JOBS, "%s (%p)", EV_GET_TYPE_NAME (job), job);
746 #endif
747
748         job_fonts->scan_completed = !ev_document_fonts_scan (fonts, 20);
749         g_signal_emit (job_fonts, job_fonts_signals[FONTS_UPDATED], 0,
750                        ev_document_fonts_get_progress (fonts));
751
752         ev_document_fc_mutex_unlock ();
753         ev_document_doc_mutex_unlock ();
754
755         if (job_fonts->scan_completed)
756                 ev_job_succeeded (job);
757         
758         return !job_fonts->scan_completed;
759 }
760
761 static void
762 ev_job_fonts_class_init (EvJobFontsClass *class)
763 {
764         EvJobClass *job_class = EV_JOB_CLASS (class);
765         
766         job_class->run = ev_job_fonts_run;
767         
768         job_fonts_signals[FONTS_UPDATED] =
769                 g_signal_new ("updated",
770                               EV_TYPE_JOB_FONTS,
771                               G_SIGNAL_RUN_LAST,
772                               G_STRUCT_OFFSET (EvJobFontsClass, updated),
773                               NULL, NULL,
774                               g_cclosure_marshal_VOID__DOUBLE,
775                               G_TYPE_NONE,
776                               1, G_TYPE_DOUBLE);
777 }
778
779 EvJob *
780 ev_job_fonts_new (EvDocument *document)
781 {
782         EvJobFonts *job;
783
784         ev_debug_message (DEBUG_JOBS, NULL);
785         
786         job = g_object_new (EV_TYPE_JOB_FONTS, NULL);
787
788         EV_JOB (job)->document = g_object_ref (document);
789
790         return EV_JOB (job);
791 }
792
793 /* EvJobLoad */
794 static void
795 ev_job_load_init (EvJobLoad *job)
796 {
797         EV_JOB (job)->run_mode = EV_JOB_RUN_THREAD;
798 }
799
800 static void
801 ev_job_load_dispose (GObject *object)
802 {
803         EvJobLoad *job = EV_JOB_LOAD (object);
804
805         ev_debug_message (DEBUG_JOBS, "%s", job->uri);
806         
807         if (job->uri) {
808                 g_free (job->uri);
809                 job->uri = NULL;
810         }
811
812         if (job->password) {
813                 g_free (job->password);
814                 job->password = NULL;
815         }
816
817         (* G_OBJECT_CLASS (ev_job_load_parent_class)->dispose) (object);
818 }
819
820 static gboolean
821 ev_job_load_run (EvJob *job)
822 {
823         EvJobLoad *job_load = EV_JOB_LOAD (job);
824         GError    *error = NULL;
825         
826         ev_debug_message (DEBUG_JOBS, "%s", job_load->uri);
827         ev_profiler_start (EV_PROFILE_JOBS, "%s (%p)", EV_GET_TYPE_NAME (job), job);
828         
829         ev_document_fc_mutex_lock ();
830
831         /* This job may already have a document even if the job didn't complete
832            because, e.g., a password is required - if so, just reload rather than
833            creating a new instance */
834         if (job->document) {
835                 if (job_load->password) {
836                         ev_document_security_set_password (EV_DOCUMENT_SECURITY (job->document),
837                                                            job_load->password);
838                 }
839                 
840                 job->failed = FALSE;
841                 job->finished = FALSE;
842                 g_clear_error (&job->error);
843                 
844                 ev_document_load (job->document,
845                                   job_load->uri,
846                                   &error);
847         } else {
848                 job->document = ev_document_factory_get_document (job_load->uri,
849                                                                   &error);
850         }
851
852         ev_document_fc_mutex_unlock ();
853
854         if (error) {
855                 ev_job_failed_from_error (job, error);
856                 g_error_free (error);
857         } else {
858                 ev_job_succeeded (job);
859         }
860
861         return FALSE;
862 }
863
864 static void
865 ev_job_load_class_init (EvJobLoadClass *class)
866 {
867         GObjectClass *oclass = G_OBJECT_CLASS (class);
868         EvJobClass   *job_class = EV_JOB_CLASS (class);
869
870         oclass->dispose = ev_job_load_dispose;
871         job_class->run = ev_job_load_run;
872 }
873
874 EvJob *
875 ev_job_load_new (const gchar *uri)
876 {
877         EvJobLoad *job;
878
879         ev_debug_message (DEBUG_JOBS, "%s", uri);
880         
881         job = g_object_new (EV_TYPE_JOB_LOAD, NULL);
882         job->uri = g_strdup (uri);
883
884         return EV_JOB (job);
885 }
886
887 void
888 ev_job_load_set_uri (EvJobLoad *job, const gchar *uri)
889 {
890         ev_debug_message (DEBUG_JOBS, "%s", uri);
891         
892         if (job->uri)
893                 g_free (job->uri);
894         job->uri = g_strdup (uri);
895 }
896
897 void
898 ev_job_load_set_password (EvJobLoad *job, const gchar *password)
899 {
900         ev_debug_message (DEBUG_JOBS, NULL);
901
902         if (job->password)
903                 g_free (job->password);
904         job->password = password ? g_strdup (password) : NULL;
905 }
906
907 /* EvJobSave */
908 static void
909 ev_job_save_init (EvJobSave *job)
910 {
911         EV_JOB (job)->run_mode = EV_JOB_RUN_THREAD;
912 }
913
914 static void
915 ev_job_save_dispose (GObject *object)
916 {
917         EvJobSave *job = EV_JOB_SAVE (object);
918
919         ev_debug_message (DEBUG_JOBS, "%s", job->uri);
920         
921         if (job->uri) {
922                 g_free (job->uri);
923                 job->uri = NULL;
924         }
925
926         if (job->document_uri) {
927                 g_free (job->document_uri);
928                 job->document_uri = NULL;
929         }
930
931         (* G_OBJECT_CLASS (ev_job_save_parent_class)->dispose) (object);
932 }
933
934 static gboolean
935 ev_job_save_run (EvJob *job)
936 {
937         EvJobSave *job_save = EV_JOB_SAVE (job);
938         gint       fd;
939         gchar     *filename;
940         gchar     *tmp_filename;
941         gchar     *local_uri;
942         GError    *error = NULL;
943         
944         ev_debug_message (DEBUG_JOBS, "uri: %s, document_uri: %s", job_save->uri, job_save->document_uri);
945         ev_profiler_start (EV_PROFILE_JOBS, "%s (%p)", EV_GET_TYPE_NAME (job), job);
946         
947         filename = ev_tmp_filename ("saveacopy");
948         tmp_filename = g_strdup_printf ("%s.XXXXXX", filename);
949         g_free (filename);
950
951         fd = g_mkstemp (tmp_filename);
952         if (fd == -1) {
953                 gchar *display_name;
954                 gint   save_errno = errno;
955
956                 display_name = g_filename_display_name (tmp_filename);
957                 ev_job_failed (job,
958                                G_FILE_ERROR,
959                                g_file_error_from_errno (save_errno),
960                                _("Failed to create file “%s”: %s"),
961                                display_name, g_strerror (save_errno));
962                 g_free (display_name);
963                 g_free (tmp_filename);
964
965                 return FALSE;
966         }
967
968         ev_document_doc_mutex_lock ();
969
970         /* Save document to temp filename */
971         local_uri = g_filename_to_uri (tmp_filename, NULL, NULL);
972         ev_document_save (job->document, local_uri, &error);
973         close (fd);
974
975         ev_document_doc_mutex_unlock ();
976
977         if (error) {
978                 g_free (local_uri);
979                 ev_job_failed_from_error (job, error);
980                 g_error_free (error);
981                 
982                 return FALSE;
983         }
984
985         /* If original document was compressed,
986          * compress it again before saving
987          */
988         if (g_object_get_data (G_OBJECT (job->document), "uri-uncompressed")) {
989                 EvCompressionType ctype = EV_COMPRESSION_NONE;
990                 const gchar      *ext;
991                 gchar            *uri_comp;
992                 
993                 ext = g_strrstr (job_save->document_uri, ".gz");
994                 if (ext && g_ascii_strcasecmp (ext, ".gz") == 0)
995                         ctype = EV_COMPRESSION_GZIP;
996                 
997                 ext = g_strrstr (job_save->document_uri, ".bz2");
998                 if (ext && g_ascii_strcasecmp (ext, ".bz2") == 0)
999                         ctype = EV_COMPRESSION_BZIP2;
1000
1001                 uri_comp = ev_file_compress (local_uri, ctype, &error);
1002                 g_free (local_uri);
1003                 ev_tmp_filename_unlink (tmp_filename);
1004
1005                 if (!uri_comp || error) {
1006                         local_uri = NULL;
1007                 } else {
1008                         local_uri = uri_comp;
1009                 }
1010         }
1011
1012         g_free (tmp_filename);
1013         
1014         if (error) {
1015                 g_free (local_uri);
1016                 ev_job_failed_from_error (job, error);
1017                 g_error_free (error);
1018                 
1019                 return FALSE;
1020         }
1021
1022         if (!local_uri)
1023                 return FALSE;
1024
1025         ev_xfer_uri_simple (local_uri, job_save->uri, &error);
1026         ev_tmp_uri_unlink (local_uri);
1027
1028         if (error) {
1029                 ev_job_failed_from_error (job, error);
1030                 g_error_free (error);
1031         } else {
1032                 ev_job_succeeded (job);
1033         }
1034         
1035         return FALSE;
1036 }
1037
1038 static void
1039 ev_job_save_class_init (EvJobSaveClass *class)
1040 {
1041         GObjectClass *oclass = G_OBJECT_CLASS (class);
1042         EvJobClass   *job_class = EV_JOB_CLASS (class);
1043
1044         oclass->dispose = ev_job_save_dispose;
1045         job_class->run = ev_job_save_run;
1046 }
1047
1048 EvJob *
1049 ev_job_save_new (EvDocument  *document,
1050                  const gchar *uri,
1051                  const gchar *document_uri)
1052 {
1053         EvJobSave *job;
1054
1055         ev_debug_message (DEBUG_JOBS, "uri: %s, document_uri: %s", uri, document_uri);
1056
1057         job = g_object_new (EV_TYPE_JOB_SAVE, NULL);
1058
1059         EV_JOB (job)->document = g_object_ref (document);
1060         job->uri = g_strdup (uri);
1061         job->document_uri = g_strdup (document_uri);
1062
1063         return EV_JOB (job);
1064 }
1065
1066 /* EvJobFind */
1067 static void
1068 ev_job_find_init (EvJobFind *job)
1069 {
1070         EV_JOB (job)->run_mode = EV_JOB_RUN_MAIN_LOOP;
1071 }
1072
1073 static void
1074 ev_job_find_dispose (GObject *object)
1075 {
1076         EvJobFind *job = EV_JOB_FIND (object);
1077
1078         ev_debug_message (DEBUG_JOBS, NULL);
1079
1080         if (job->text) {
1081                 g_free (job->text);
1082                 job->text = NULL;
1083         }
1084
1085         if (job->pages) {
1086                 gint i;
1087
1088                 for (i = 0; i < job->n_pages; i++) {
1089                         g_list_foreach (job->pages[i], (GFunc)g_free, NULL);
1090                         g_list_free (job->pages[i]);
1091                 }
1092
1093                 g_free (job->pages);
1094                 job->pages = NULL;
1095         }
1096         
1097         (* G_OBJECT_CLASS (ev_job_find_parent_class)->dispose) (object);
1098 }
1099
1100 static gboolean
1101 ev_job_find_run (EvJob *job)
1102 {
1103         EvJobFind      *job_find = EV_JOB_FIND (job);
1104         EvDocumentFind *find = EV_DOCUMENT_FIND (job->document);
1105         EvPage         *ev_page;
1106         GList          *matches;
1107
1108         ev_debug_message (DEBUG_JOBS, NULL);
1109         
1110         /* Do not block the main loop */
1111         if (!ev_document_doc_mutex_trylock ())
1112                 return TRUE;
1113         
1114 #ifdef EV_ENABLE_DEBUG
1115         /* We use the #ifdef in this case because of the if */
1116         if (job_find->current_page == job_find->start_page)
1117                 ev_profiler_start (EV_PROFILE_JOBS, "%s (%p)", EV_GET_TYPE_NAME (job), job);
1118 #endif
1119
1120         ev_page = ev_document_get_page (job->document, job_find->current_page);
1121         matches = ev_document_find_find_text (find, ev_page, job_find->text,
1122                                               job_find->case_sensitive);
1123         g_object_unref (ev_page);
1124         
1125         ev_document_doc_mutex_unlock ();
1126
1127         if (!job_find->has_results)
1128                 job_find->has_results = (matches != NULL);
1129
1130         job_find->pages[job_find->current_page] = matches;
1131         g_signal_emit (job_find, job_find_signals[FIND_UPDATED], 0, job_find->current_page);
1132                        
1133         job_find->current_page = (job_find->current_page + 1) % job_find->n_pages;
1134         if (job_find->current_page == job_find->start_page) {
1135                 ev_job_succeeded (job);
1136
1137                 return FALSE;
1138         }
1139
1140         return TRUE;
1141 }
1142
1143 static void
1144 ev_job_find_class_init (EvJobFindClass *class)
1145 {
1146         EvJobClass   *job_class = EV_JOB_CLASS (class);
1147         GObjectClass *gobject_class = G_OBJECT_CLASS (class);
1148         
1149         job_class->run = ev_job_find_run;
1150         gobject_class->dispose = ev_job_find_dispose;
1151         
1152         job_find_signals[FIND_UPDATED] =
1153                 g_signal_new ("updated",
1154                               EV_TYPE_JOB_FIND,
1155                               G_SIGNAL_RUN_LAST,
1156                               G_STRUCT_OFFSET (EvJobFindClass, updated),
1157                               NULL, NULL,
1158                               g_cclosure_marshal_VOID__INT,
1159                               G_TYPE_NONE,
1160                               1, G_TYPE_INT);
1161 }
1162
1163 EvJob *
1164 ev_job_find_new (EvDocument  *document,
1165                  gint         start_page,
1166                  gint         n_pages,
1167                  const gchar *text,
1168                  gboolean     case_sensitive)
1169 {
1170         EvJobFind *job;
1171         
1172         ev_debug_message (DEBUG_JOBS, NULL);
1173         
1174         job = g_object_new (EV_TYPE_JOB_FIND, NULL);
1175
1176         EV_JOB (job)->document = g_object_ref (document);
1177         job->start_page = start_page;
1178         job->current_page = start_page;
1179         job->n_pages = n_pages;
1180         job->pages = g_new0 (GList *, n_pages);
1181         job->text = g_strdup (text);
1182         job->case_sensitive = case_sensitive;
1183         job->has_results = FALSE;
1184
1185         return EV_JOB (job);
1186 }
1187
1188 gint
1189 ev_job_find_get_n_results (EvJobFind *job,
1190                            gint       page)
1191 {
1192         return g_list_length (job->pages[page]);
1193 }
1194
1195 gdouble
1196 ev_job_find_get_progress (EvJobFind *job)
1197 {
1198         gint pages_done;
1199
1200         if (ev_job_is_finished (EV_JOB (job)))
1201                 return 1.0;
1202         
1203         if (job->current_page > job->start_page) {
1204                 pages_done = job->current_page - job->start_page + 1;
1205         } else if (job->current_page == job->start_page) {
1206                 pages_done = job->n_pages;
1207         } else {
1208                 pages_done = job->n_pages - job->start_page + job->current_page;
1209         }
1210
1211         return pages_done / (gdouble) job->n_pages;
1212 }
1213
1214 gboolean
1215 ev_job_find_has_results (EvJobFind *job)
1216 {
1217         return job->has_results;
1218 }
1219
1220 GList **
1221 ev_job_find_get_results (EvJobFind *job)
1222 {
1223         return job->pages;
1224 }
1225
1226 /* EvJobLayers */
1227 static void
1228 ev_job_layers_init (EvJobLayers *job)
1229 {
1230         EV_JOB (job)->run_mode = EV_JOB_RUN_THREAD;
1231 }
1232
1233 static void
1234 ev_job_layers_dispose (GObject *object)
1235 {
1236         EvJobLayers *job;
1237
1238         ev_debug_message (DEBUG_JOBS, NULL);
1239         
1240         job = EV_JOB_LAYERS (object);
1241
1242         if (job->model) {
1243                 g_object_unref (job->model);
1244                 job->model = NULL;
1245         }
1246
1247         (* G_OBJECT_CLASS (ev_job_layers_parent_class)->dispose) (object);
1248 }
1249
1250 static gboolean
1251 ev_job_layers_run (EvJob *job)
1252 {
1253         EvJobLayers *job_layers = EV_JOB_LAYERS (job);
1254
1255         ev_debug_message (DEBUG_JOBS, NULL);
1256         ev_profiler_start (EV_PROFILE_JOBS, "%s (%p)", EV_GET_TYPE_NAME (job), job);
1257         
1258         ev_document_doc_mutex_lock ();
1259         job_layers->model = ev_document_layers_get_layers (EV_DOCUMENT_LAYERS (job->document));
1260         ev_document_doc_mutex_unlock ();
1261         
1262         ev_job_succeeded (job);
1263         
1264         return FALSE;
1265 }
1266
1267 static void
1268 ev_job_layers_class_init (EvJobLayersClass *class)
1269 {
1270         GObjectClass *oclass = G_OBJECT_CLASS (class);
1271         EvJobClass   *job_class = EV_JOB_CLASS (class);
1272
1273         oclass->dispose = ev_job_layers_dispose;
1274         job_class->run = ev_job_layers_run;
1275 }
1276
1277 EvJob *
1278 ev_job_layers_new (EvDocument *document)
1279 {
1280         EvJob *job;
1281
1282         ev_debug_message (DEBUG_JOBS, NULL);
1283
1284         job = g_object_new (EV_TYPE_JOB_LAYERS, NULL);
1285         job->document = g_object_ref (document);
1286         
1287         return job;
1288 }
1289
1290 /* EvJobExport */
1291 static void
1292 ev_job_export_init (EvJobExport *job)
1293 {
1294         EV_JOB (job)->run_mode = EV_JOB_RUN_THREAD;
1295         job->page = -1;
1296 }
1297
1298 static void
1299 ev_job_export_dispose (GObject *object)
1300 {
1301         EvJobExport *job;
1302
1303         ev_debug_message (DEBUG_JOBS, NULL);
1304         
1305         job = EV_JOB_EXPORT (object);
1306
1307         if (job->rc) {
1308                 g_object_unref (job->rc);
1309                 job->rc = NULL;
1310         }
1311
1312         (* G_OBJECT_CLASS (ev_job_export_parent_class)->dispose) (object);
1313 }
1314
1315 static gboolean
1316 ev_job_export_run (EvJob *job)
1317 {
1318         EvJobExport *job_export = EV_JOB_EXPORT (job);
1319         EvPage      *ev_page;
1320
1321         g_assert (job_export->page != -1);
1322
1323         ev_debug_message (DEBUG_JOBS, NULL);
1324         ev_profiler_start (EV_PROFILE_JOBS, "%s (%p)", EV_GET_TYPE_NAME (job), job);
1325         
1326         ev_document_doc_mutex_lock ();
1327         
1328         ev_page = ev_document_get_page (job->document, job_export->page);
1329         if (job_export->rc) {
1330                 job->failed = FALSE;
1331                 job->finished = FALSE;
1332                 g_clear_error (&job->error);
1333                 
1334                 ev_render_context_set_page (job_export->rc, ev_page);
1335         } else {
1336                 job_export->rc = ev_render_context_new (ev_page, 0, 1.0);
1337         }
1338         g_object_unref (ev_page);
1339         
1340         ev_file_exporter_do_page (EV_FILE_EXPORTER (job->document), job_export->rc);
1341         
1342         ev_document_doc_mutex_unlock ();
1343         
1344         ev_job_succeeded (job);
1345         
1346         return FALSE;
1347 }
1348
1349 static void
1350 ev_job_export_class_init (EvJobExportClass *class)
1351 {
1352         GObjectClass *oclass = G_OBJECT_CLASS (class);
1353         EvJobClass   *job_class = EV_JOB_CLASS (class);
1354
1355         oclass->dispose = ev_job_export_dispose;
1356         job_class->run = ev_job_export_run;
1357 }
1358
1359 EvJob *
1360 ev_job_export_new (EvDocument *document)
1361 {
1362         EvJob *job;
1363
1364         ev_debug_message (DEBUG_JOBS, NULL);
1365
1366         job = g_object_new (EV_TYPE_JOB_EXPORT, NULL);
1367         job->document = g_object_ref (document);
1368         
1369         return job;
1370 }
1371
1372 void
1373 ev_job_export_set_page (EvJobExport *job,
1374                         gint         page)
1375 {
1376         job->page = page;
1377 }
1378
1379 /* EvJobPrint */
1380 static void
1381 ev_job_print_init (EvJobPrint *job)
1382 {
1383         EV_JOB (job)->run_mode = EV_JOB_RUN_THREAD;
1384         job->page = -1;
1385 }
1386
1387 static void
1388 ev_job_print_dispose (GObject *object)
1389 {
1390         EvJobPrint *job;
1391
1392         ev_debug_message (DEBUG_JOBS, NULL);
1393
1394         job = EV_JOB_PRINT (object);
1395
1396         if (job->cr) {
1397                 cairo_destroy (job->cr);
1398                 job->cr = NULL;
1399         }
1400
1401         (* G_OBJECT_CLASS (ev_job_print_parent_class)->dispose) (object);
1402 }
1403
1404 static gboolean
1405 ev_job_print_run (EvJob *job)
1406 {
1407         EvJobPrint     *job_print = EV_JOB_PRINT (job);
1408         EvPage         *ev_page;
1409         cairo_status_t  cr_status;
1410
1411         g_assert (job_print->page != -1);
1412         g_assert (job_print->cr != NULL);
1413
1414         ev_debug_message (DEBUG_JOBS, NULL);
1415         ev_profiler_start (EV_PROFILE_JOBS, "%s (%p)", EV_GET_TYPE_NAME (job), job);
1416
1417         job->failed = FALSE;
1418         job->finished = FALSE;
1419         g_clear_error (&job->error);
1420
1421         ev_document_doc_mutex_lock ();
1422
1423         ev_page = ev_document_get_page (job->document, job_print->page);
1424         ev_document_print_print_page (EV_DOCUMENT_PRINT (job->document),
1425                                       ev_page, job_print->cr);
1426         g_object_unref (ev_page);
1427
1428         ev_document_doc_mutex_unlock ();
1429
1430         cr_status = cairo_status (job_print->cr);
1431         if (cr_status == CAIRO_STATUS_SUCCESS) {
1432                 ev_job_succeeded (job);
1433         } else {
1434                 ev_job_failed (job,
1435                                GTK_PRINT_ERROR,
1436                                GTK_PRINT_ERROR_GENERAL,
1437                                _("Failed to print page %d: %s"),
1438                                job_print->page,
1439                                cairo_status_to_string (cr_status));
1440         }
1441
1442         return FALSE;
1443 }
1444
1445 static void
1446 ev_job_print_class_init (EvJobPrintClass *class)
1447 {
1448         GObjectClass *oclass = G_OBJECT_CLASS (class);
1449         EvJobClass   *job_class = EV_JOB_CLASS (class);
1450
1451         oclass->dispose = ev_job_print_dispose;
1452         job_class->run = ev_job_print_run;
1453 }
1454
1455 EvJob *
1456 ev_job_print_new (EvDocument *document)
1457 {
1458         EvJob *job;
1459
1460         ev_debug_message (DEBUG_JOBS, NULL);
1461
1462         job = g_object_new (EV_TYPE_JOB_PRINT, NULL);
1463         job->document = g_object_ref (document);
1464
1465         return job;
1466 }
1467
1468 void
1469 ev_job_print_set_page (EvJobPrint *job,
1470                        gint        page)
1471 {
1472         job->page = page;
1473 }
1474
1475 void
1476 ev_job_print_set_cairo (EvJobPrint *job,
1477                         cairo_t    *cr)
1478 {
1479         if (job->cr == cr)
1480                 return;
1481
1482         if (job->cr)
1483                 cairo_destroy (job->cr);
1484         job->cr = cr ? cairo_reference (cr) : NULL;
1485 }