Evince
Evince is a document viewer capable of displaying multiple and single page document formats like PDF and Postscript.
 All Data Structures Files Functions Variables Typedefs Enumerations Enumerator Macros Pages
ev-jobs.c
Go to the documentation of this file.
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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
19  */
20 
21 #include <config.h>
22 
23 #include "ev-jobs.h"
24 #include "ev-document-links.h"
25 #include "ev-document-images.h"
26 #include "ev-document-forms.h"
27 #include "ev-file-exporter.h"
28 #include "ev-document-factory.h"
29 #include "ev-document-misc.h"
30 #include "ev-file-helpers.h"
31 #include "ev-document-fonts.h"
32 #include "ev-document-security.h"
33 #include "ev-document-find.h"
34 #include "ev-document-layers.h"
35 #include "ev-document-print.h"
38 #include "ev-document-media.h"
39 #include "ev-document-text.h"
40 #include "ev-debug.h"
41 
42 #include <errno.h>
43 #include <glib/gstdio.h>
44 #include <glib/gi18n-lib.h>
45 #include <unistd.h>
46 
47 static void ev_job_init (EvJob *job);
48 static void ev_job_class_init (EvJobClass *class);
49 static void ev_job_links_init (EvJobLinks *job);
50 static void ev_job_links_class_init (EvJobLinksClass *class);
51 static void ev_job_attachments_init (EvJobAttachments *job);
53 static void ev_job_annots_init (EvJobAnnots *job);
54 static void ev_job_annots_class_init (EvJobAnnotsClass *class);
55 static void ev_job_render_init (EvJobRender *job);
56 static void ev_job_render_class_init (EvJobRenderClass *class);
57 static void ev_job_page_data_init (EvJobPageData *job);
59 static void ev_job_thumbnail_init (EvJobThumbnail *job);
61 static void ev_job_load_init (EvJobLoad *job);
62 static void ev_job_load_class_init (EvJobLoadClass *class);
63 static void ev_job_save_init (EvJobSave *job);
64 static void ev_job_save_class_init (EvJobSaveClass *class);
65 static void ev_job_find_init (EvJobFind *job);
66 static void ev_job_find_class_init (EvJobFindClass *class);
67 static void ev_job_layers_init (EvJobLayers *job);
68 static void ev_job_layers_class_init (EvJobLayersClass *class);
69 static void ev_job_export_init (EvJobExport *job);
70 static void ev_job_export_class_init (EvJobExportClass *class);
71 static void ev_job_print_init (EvJobPrint *job);
72 static void ev_job_print_class_init (EvJobPrintClass *class);
73 
74 enum {
78 };
79 
80 enum {
83 };
84 
85 enum {
88 };
89 
90 static guint job_signals[LAST_SIGNAL] = { 0 };
91 static guint job_fonts_signals[FONTS_LAST_SIGNAL] = { 0 };
92 static guint job_find_signals[FIND_LAST_SIGNAL] = { 0 };
93 
94 G_DEFINE_ABSTRACT_TYPE (EvJob, ev_job, G_TYPE_OBJECT)
95 G_DEFINE_TYPE (EvJobLinks, ev_job_links, EV_TYPE_JOB)
96 G_DEFINE_TYPE (EvJobAttachments, ev_job_attachments, EV_TYPE_JOB)
97 G_DEFINE_TYPE (EvJobAnnots, ev_job_annots, EV_TYPE_JOB)
98 G_DEFINE_TYPE (EvJobRender, ev_job_render, EV_TYPE_JOB)
99 G_DEFINE_TYPE (EvJobPageData, ev_job_page_data, EV_TYPE_JOB)
100 G_DEFINE_TYPE (EvJobThumbnail, ev_job_thumbnail, EV_TYPE_JOB)
101 G_DEFINE_TYPE (EvJobFonts, ev_job_fonts, EV_TYPE_JOB)
102 G_DEFINE_TYPE (EvJobLoad, ev_job_load, EV_TYPE_JOB)
103 G_DEFINE_TYPE (EvJobLoadStream, ev_job_load_stream, EV_TYPE_JOB)
104 G_DEFINE_TYPE (EvJobLoadGFile, ev_job_load_gfile, EV_TYPE_JOB)
105 G_DEFINE_TYPE (EvJobSave, ev_job_save, EV_TYPE_JOB)
106 G_DEFINE_TYPE (EvJobFind, ev_job_find, EV_TYPE_JOB)
107 G_DEFINE_TYPE (EvJobLayers, ev_job_layers, EV_TYPE_JOB)
108 G_DEFINE_TYPE (EvJobExport, ev_job_export, EV_TYPE_JOB)
109 G_DEFINE_TYPE (EvJobPrint, ev_job_print, EV_TYPE_JOB)
110 
111 /* EvJob */
112 static void
114 {
115  job->cancellable = g_cancellable_new ();
116 }
117 
118 static void
119 ev_job_dispose (GObject *object)
120 {
121  EvJob *job;
122 
123  job = EV_JOB (object);
124 
125  if (job->document) {
126  g_object_unref (job->document);
127  job->document = NULL;
128  }
129 
130  if (job->cancellable) {
131  g_object_unref (job->cancellable);
132  job->cancellable = NULL;
133  }
134 
135  if (job->error) {
136  g_error_free (job->error);
137  job->error = NULL;
138  }
139 
140  (* G_OBJECT_CLASS (ev_job_parent_class)->dispose) (object);
141 }
142 
143 static void
145 {
146  GObjectClass *oclass;
147 
148  oclass = G_OBJECT_CLASS (class);
149 
150  oclass->dispose = ev_job_dispose;
151 
153  g_signal_new ("cancelled",
154  EV_TYPE_JOB,
155  G_SIGNAL_RUN_LAST,
156  G_STRUCT_OFFSET (EvJobClass, cancelled),
157  NULL, NULL,
158  g_cclosure_marshal_VOID__VOID,
159  G_TYPE_NONE, 0);
161  g_signal_new ("finished",
162  EV_TYPE_JOB,
163  G_SIGNAL_RUN_FIRST,
164  G_STRUCT_OFFSET (EvJobClass, finished),
165  NULL, NULL,
166  g_cclosure_marshal_VOID__VOID,
167  G_TYPE_NONE, 0);
168 }
169 
170 static gboolean
172 {
173  ev_debug_message (DEBUG_JOBS, "%s (%p)", EV_GET_TYPE_NAME (job), job);
174 
175  job->idle_finished_id = 0;
176 
177  if (job->cancelled) {
178  ev_debug_message (DEBUG_JOBS, "%s (%p) job was cancelled, do not emit finished", EV_GET_TYPE_NAME (job), job);
179  } else {
180  ev_profiler_stop (EV_PROFILE_JOBS, "%s (%p)", EV_GET_TYPE_NAME (job), job);
181  g_signal_emit (job, job_signals[FINISHED], 0);
182  }
183 
184  return FALSE;
185 }
186 
187 static void
189 {
190  ev_debug_message (DEBUG_JOBS, "%s (%p)", EV_GET_TYPE_NAME (job), job);
191 
192  if (g_cancellable_is_cancelled (job->cancellable)) {
193  ev_debug_message (DEBUG_JOBS, "%s (%p) job was cancelled, returning", EV_GET_TYPE_NAME (job), job);
194  return;
195  }
196 
197  job->finished = TRUE;
198 
199  if (job->run_mode == EV_JOB_RUN_THREAD) {
200  job->idle_finished_id =
201  g_idle_add_full (G_PRIORITY_DEFAULT_IDLE,
202  (GSourceFunc)emit_finished,
203  g_object_ref (job),
204  (GDestroyNotify)g_object_unref);
205  } else {
206  ev_profiler_stop (EV_PROFILE_JOBS, "%s (%p)", EV_GET_TYPE_NAME (job), job);
207  g_signal_emit (job, job_signals[FINISHED], 0);
208  }
209 }
210 
211 gboolean
213 {
214  EvJobClass *class = EV_JOB_GET_CLASS (job);
215 
216  return class->run (job);
217 }
218 
219 void
221 {
222  if (job->cancelled)
223  return;
224 
225  ev_debug_message (DEBUG_JOBS, "job %s (%p) cancelled", EV_GET_TYPE_NAME (job), job);
226  ev_profiler_stop (EV_PROFILE_JOBS, "%s (%p)", EV_GET_TYPE_NAME (job), job);
227 
228  /* This should never be called from a thread */
229  job->cancelled = TRUE;
230  g_cancellable_cancel (job->cancellable);
231 
232  if (job->finished && job->idle_finished_id == 0)
233  return;
234 
235  g_signal_emit (job, job_signals[CANCELLED], 0);
236 }
237 
238 void
240  GQuark domain,
241  gint code,
242  const gchar *format,
243  ...)
244 {
245  va_list args;
246  gchar *message;
247 
248  if (job->failed || job->finished)
249  return;
250 
251  ev_debug_message (DEBUG_JOBS, "job %s (%p) failed", EV_GET_TYPE_NAME (job), job);
252 
253  job->failed = TRUE;
254 
255  va_start (args, format);
256  message = g_strdup_vprintf (format, args);
257  va_end (args);
258 
259  job->error = g_error_new_literal (domain, code, message);
260  g_free (message);
261 
262  ev_job_emit_finished (job);
263 }
264 
272 void
274  GError *error)
275 {
276  if (job->failed || job->finished)
277  return;
278 
279  ev_debug_message (DEBUG_JOBS, "job %s (%p) failed", EV_GET_TYPE_NAME (job), job);
280 
281  job->failed = TRUE;
282  job->error = g_error_copy (error);
283 
284  ev_job_emit_finished (job);
285 }
286 
287 void
289 {
290  if (job->finished)
291  return;
292 
293  ev_debug_message (DEBUG_JOBS, "job %s (%p) succeeded", EV_GET_TYPE_NAME (job), job);
294 
295  job->failed = FALSE;
296  ev_job_emit_finished (job);
297 }
298 
299 gboolean
301 {
302  return job->finished;
303 }
304 
305 gboolean
307 {
308  return job->failed;
309 }
310 
313 {
314  return job->run_mode;
315 }
316 
317 void
319  EvJobRunMode run_mode)
320 {
321  job->run_mode = run_mode;
322 }
323 
324 /* EvJobLinks */
325 static void
327 {
328  EV_JOB (job)->run_mode = EV_JOB_RUN_THREAD;
329 }
330 
331 static void
332 ev_job_links_dispose (GObject *object)
333 {
334  EvJobLinks *job;
335 
336  ev_debug_message (DEBUG_JOBS, NULL);
337 
338  job = EV_JOB_LINKS (object);
339 
340  if (job->model) {
341  g_object_unref (job->model);
342  job->model = NULL;
343  }
344 
345  (* G_OBJECT_CLASS (ev_job_links_parent_class)->dispose) (object);
346 }
347 
348 static gboolean
349 fill_page_labels (GtkTreeModel *tree_model,
350  GtkTreePath *path,
351  GtkTreeIter *iter,
352  EvJob *job)
353 {
354  EvDocumentLinks *document_links;
355  EvLink *link;
356  gchar *page_label;
357 
358  gtk_tree_model_get (tree_model, iter,
360  -1);
361 
362  if (!link)
363  return FALSE;
364 
365  document_links = EV_DOCUMENT_LINKS (job->document);
366  page_label = ev_document_links_get_link_page_label (document_links, link);
367  if (!page_label)
368  return FALSE;
369 
370  gtk_tree_store_set (GTK_TREE_STORE (tree_model), iter,
372  -1);
373 
374  g_free (page_label);
375  g_object_unref (link);
376 
377  return FALSE;
378 }
379 
380 static gboolean
382 {
383  EvJobLinks *job_links = EV_JOB_LINKS (job);
384 
385  ev_debug_message (DEBUG_JOBS, NULL);
386  ev_profiler_start (EV_PROFILE_JOBS, "%s (%p)", EV_GET_TYPE_NAME (job), job);
387 
389  job_links->model = ev_document_links_get_links_model (EV_DOCUMENT_LINKS (job->document));
391 
392  gtk_tree_model_foreach (job_links->model, (GtkTreeModelForeachFunc)fill_page_labels, job);
393 
394  ev_job_succeeded (job);
395 
396  return FALSE;
397 }
398 
399 static void
401 {
402  GObjectClass *oclass = G_OBJECT_CLASS (class);
403  EvJobClass *job_class = EV_JOB_CLASS (class);
404 
405  oclass->dispose = ev_job_links_dispose;
406  job_class->run = ev_job_links_run;
407 }
408 
409 EvJob *
411 {
412  EvJob *job;
413 
414  ev_debug_message (DEBUG_JOBS, NULL);
415 
416  job = g_object_new (EV_TYPE_JOB_LINKS, NULL);
417  job->document = g_object_ref (document);
418 
419  return job;
420 }
421 
432 GtkTreeModel *
434 {
435  return job->model;
436 }
437 
438 /* EvJobAttachments */
439 static void
441 {
442  EV_JOB (job)->run_mode = EV_JOB_RUN_THREAD;
443 }
444 
445 static void
446 ev_job_attachments_dispose (GObject *object)
447 {
448  EvJobAttachments *job;
449 
450  ev_debug_message (DEBUG_JOBS, NULL);
451 
452  job = EV_JOB_ATTACHMENTS (object);
453 
454  if (job->attachments) {
455  g_list_foreach (job->attachments, (GFunc)g_object_unref, NULL);
456  g_list_free (job->attachments);
457  job->attachments = NULL;
458  }
459 
460  (* G_OBJECT_CLASS (ev_job_attachments_parent_class)->dispose) (object);
461 }
462 
463 static gboolean
465 {
466  EvJobAttachments *job_attachments = EV_JOB_ATTACHMENTS (job);
467 
468  ev_debug_message (DEBUG_JOBS, NULL);
469  ev_profiler_start (EV_PROFILE_JOBS, "%s (%p)", EV_GET_TYPE_NAME (job), job);
470 
472  job_attachments->attachments =
475 
476  ev_job_succeeded (job);
477 
478  return FALSE;
479 }
480 
481 static void
483 {
484  GObjectClass *oclass = G_OBJECT_CLASS (class);
485  EvJobClass *job_class = EV_JOB_CLASS (class);
486 
487  oclass->dispose = ev_job_attachments_dispose;
488  job_class->run = ev_job_attachments_run;
489 }
490 
491 EvJob *
493 {
494  EvJob *job;
495 
496  ev_debug_message (DEBUG_JOBS, NULL);
497 
498  job = g_object_new (EV_TYPE_JOB_ATTACHMENTS, NULL);
499  job->document = g_object_ref (document);
500 
501  return job;
502 }
503 
504 /* EvJobAnnots */
505 static void
507 {
508  EV_JOB (job)->run_mode = EV_JOB_RUN_THREAD;
509 }
510 
511 static void
512 ev_job_annots_dispose (GObject *object)
513 {
514  EvJobAnnots *job;
515 
516  ev_debug_message (DEBUG_JOBS, NULL);
517 
518  job = EV_JOB_ANNOTS (object);
519 
520  if (job->annots) {
521  g_list_foreach (job->annots, (GFunc)ev_mapping_list_unref, NULL);
522  g_list_free (job->annots);
523  job->annots = NULL;
524  }
525 
526  G_OBJECT_CLASS (ev_job_annots_parent_class)->dispose (object);
527 }
528 
529 static gboolean
531 {
532  EvJobAnnots *job_annots = EV_JOB_ANNOTS (job);
533  gint i;
534 
535  ev_debug_message (DEBUG_JOBS, NULL);
536  ev_profiler_start (EV_PROFILE_JOBS, "%s (%p)", EV_GET_TYPE_NAME (job), job);
537 
539  for (i = 0; i < ev_document_get_n_pages (job->document); i++) {
540  EvMappingList *mapping_list;
541  EvPage *page;
542 
543  page = ev_document_get_page (job->document, i);
545  page);
546  g_object_unref (page);
547 
548  if (mapping_list)
549  job_annots->annots = g_list_prepend (job_annots->annots, mapping_list);
550  }
552 
553  job_annots->annots = g_list_reverse (job_annots->annots);
554 
555  ev_job_succeeded (job);
556 
557  return FALSE;
558 }
559 
560 static void
562 {
563  GObjectClass *oclass = G_OBJECT_CLASS (class);
564  EvJobClass *job_class = EV_JOB_CLASS (class);
565 
566  oclass->dispose = ev_job_annots_dispose;
567  job_class->run = ev_job_annots_run;
568 }
569 
570 EvJob *
572 {
573  EvJob *job;
574 
575  ev_debug_message (DEBUG_JOBS, NULL);
576 
577  job = g_object_new (EV_TYPE_JOB_ANNOTS, NULL);
578  job->document = g_object_ref (document);
579 
580  return job;
581 }
582 
583 /* EvJobRender */
584 static void
586 {
587  EV_JOB (job)->run_mode = EV_JOB_RUN_THREAD;
588 }
589 
590 static void
591 ev_job_render_dispose (GObject *object)
592 {
593  EvJobRender *job;
594 
595  job = EV_JOB_RENDER (object);
596 
597  ev_debug_message (DEBUG_JOBS, "page: %d (%p)", job->page, job);
598 
599  if (job->surface) {
600  cairo_surface_destroy (job->surface);
601  job->surface = NULL;
602  }
603 
604  if (job->selection) {
605  cairo_surface_destroy (job->selection);
606  job->selection = NULL;
607  }
608 
609  if (job->selection_region) {
610  cairo_region_destroy (job->selection_region);
611  job->selection_region = NULL;
612  }
613 
614  (* G_OBJECT_CLASS (ev_job_render_parent_class)->dispose) (object);
615 }
616 
617 static gboolean
619 {
620  EvJobRender *job_render = EV_JOB_RENDER (job);
621  EvPage *ev_page;
622  EvRenderContext *rc;
623 
624  ev_debug_message (DEBUG_JOBS, "page: %d (%p)", job_render->page, job);
625  ev_profiler_start (EV_PROFILE_JOBS, "%s (%p)", EV_GET_TYPE_NAME (job), job);
626 
628 
629  ev_profiler_start (EV_PROFILE_JOBS, "Rendering page %d", job_render->page);
630 
632 
633  ev_page = ev_document_get_page (job->document, job_render->page);
634  rc = ev_render_context_new (ev_page, job_render->rotation, job_render->scale);
636  job_render->target_width, job_render->target_height);
637  g_object_unref (ev_page);
638 
639  job_render->surface = ev_document_render (job->document, rc);
640 
641  if (job_render->surface == NULL) {
644  g_object_unref (rc);
645 
646  ev_job_failed (job,
649  _("Failed to render page %d"),
650  job_render->page);
651 
652  return FALSE;
653  }
654 
655  /* If job was cancelled during the page rendering,
656  * we return now, so that the thread is finished ASAP
657  */
658  if (g_cancellable_is_cancelled (job->cancellable)) {
661  g_object_unref (rc);
662 
663  return FALSE;
664  }
665 
666  if (job_render->include_selection && EV_IS_SELECTION (job->document)) {
668  rc,
669  &(job_render->selection),
670  &(job_render->selection_points),
671  NULL,
672  job_render->selection_style,
673  &(job_render->text), &(job_render->base));
674  job_render->selection_region =
676  rc,
677  job_render->selection_style,
678  &(job_render->selection_points));
679  }
680 
681  g_object_unref (rc);
682 
685 
686  ev_job_succeeded (job);
687 
688  return FALSE;
689 }
690 
691 static void
693 {
694  GObjectClass *oclass = G_OBJECT_CLASS (class);
695  EvJobClass *job_class = EV_JOB_CLASS (class);
696 
697  oclass->dispose = ev_job_render_dispose;
698  job_class->run = ev_job_render_run;
699 }
700 
701 EvJob *
703  gint page,
704  gint rotation,
705  gdouble scale,
706  gint width,
707  gint height)
708 {
709  EvJobRender *job;
710 
711  ev_debug_message (DEBUG_JOBS, "page: %d", page);
712 
713  job = g_object_new (EV_TYPE_JOB_RENDER, NULL);
714 
715  EV_JOB (job)->document = g_object_ref (document);
716  job->page = page;
717  job->rotation = rotation;
718  job->scale = scale;
719  job->target_width = width;
720  job->target_height = height;
721 
722  return EV_JOB (job);
723 }
724 
725 void
727  EvRectangle *selection_points,
728  EvSelectionStyle selection_style,
729  GdkColor *text,
730  GdkColor *base)
731 {
732  job->include_selection = TRUE;
733 
734  job->selection_points = *selection_points;
735  job->selection_style = selection_style;
736  job->text = *text;
737  job->base = *base;
738 }
739 
740 /* EvJobPageData */
741 static void
743 {
744  EV_JOB (job)->run_mode = EV_JOB_RUN_THREAD;
745 }
746 
747 static gboolean
749 {
750  EvJobPageData *job_pd = EV_JOB_PAGE_DATA (job);
751  EvPage *ev_page;
752 
753  ev_debug_message (DEBUG_JOBS, "page: %d (%p)", job_pd->page, job);
754  ev_profiler_start (EV_PROFILE_JOBS, "%s (%p)", EV_GET_TYPE_NAME (job), job);
755 
757  ev_page = ev_document_get_page (job->document, job_pd->page);
758 
759  if ((job_pd->flags & EV_PAGE_DATA_INCLUDE_TEXT_MAPPING) && EV_IS_DOCUMENT_TEXT (job->document))
760  job_pd->text_mapping =
761  ev_document_text_get_text_mapping (EV_DOCUMENT_TEXT (job->document), ev_page);
762  if ((job_pd->flags & EV_PAGE_DATA_INCLUDE_TEXT) && EV_IS_DOCUMENT_TEXT (job->document))
763  job_pd->text =
764  ev_document_text_get_text (EV_DOCUMENT_TEXT (job->document), ev_page);
765  if ((job_pd->flags & EV_PAGE_DATA_INCLUDE_TEXT_LAYOUT) && EV_IS_DOCUMENT_TEXT (job->document))
767  ev_page,
768  &(job_pd->text_layout),
769  &(job_pd->text_layout_length));
770  if ((job_pd->flags & EV_PAGE_DATA_INCLUDE_TEXT_ATTRS) && EV_IS_DOCUMENT_TEXT (job->document))
771  job_pd ->text_attrs =
773  ev_page);
774  if ((job_pd->flags & EV_PAGE_DATA_INCLUDE_TEXT_LOG_ATTRS) && job_pd->text) {
775  job_pd->text_log_attrs_length = g_utf8_strlen (job_pd->text, -1);
776  job_pd->text_log_attrs = g_new0 (PangoLogAttr, job_pd->text_log_attrs_length + 1);
777 
778  /* FIXME: We need API to get the language of the document */
779  pango_get_log_attrs (job_pd->text, -1, -1, NULL, job_pd->text_log_attrs, job_pd->text_log_attrs_length + 1);
780  }
781  if ((job_pd->flags & EV_PAGE_DATA_INCLUDE_LINKS) && EV_IS_DOCUMENT_LINKS (job->document))
782  job_pd->link_mapping =
783  ev_document_links_get_links (EV_DOCUMENT_LINKS (job->document), ev_page);
784  if ((job_pd->flags & EV_PAGE_DATA_INCLUDE_FORMS) && EV_IS_DOCUMENT_FORMS (job->document))
785  job_pd->form_field_mapping =
787  ev_page);
788  if ((job_pd->flags & EV_PAGE_DATA_INCLUDE_IMAGES) && EV_IS_DOCUMENT_IMAGES (job->document))
789  job_pd->image_mapping =
791  ev_page);
792  if ((job_pd->flags & EV_PAGE_DATA_INCLUDE_ANNOTS) && EV_IS_DOCUMENT_ANNOTATIONS (job->document))
793  job_pd->annot_mapping =
795  ev_page);
796  if ((job_pd->flags & EV_PAGE_DATA_INCLUDE_MEDIA) && EV_IS_DOCUMENT_MEDIA (job->document))
797  job_pd->media_mapping =
799  ev_page);
800  g_object_unref (ev_page);
802 
803  ev_job_succeeded (job);
804 
805  return FALSE;
806 }
807 
808 static void
810 {
811  EvJobClass *job_class = EV_JOB_CLASS (class);
812 
813  job_class->run = ev_job_page_data_run;
814 }
815 
816 EvJob *
818  gint page,
819  EvJobPageDataFlags flags)
820 {
821  EvJobPageData *job;
822 
823  ev_debug_message (DEBUG_JOBS, "%d", page);
824 
825  job = g_object_new (EV_TYPE_JOB_PAGE_DATA, NULL);
826 
827  EV_JOB (job)->document = g_object_ref (document);
828  job->page = page;
829  job->flags = flags;
830 
831  return EV_JOB (job);
832 }
833 
834 /* EvJobThumbnail */
835 static void
837 {
838  EV_JOB (job)->run_mode = EV_JOB_RUN_THREAD;
839 }
840 
841 static void
842 ev_job_thumbnail_dispose (GObject *object)
843 {
844  EvJobThumbnail *job;
845 
846  job = EV_JOB_THUMBNAIL (object);
847 
848  ev_debug_message (DEBUG_JOBS, "%d (%p)", job->page, job);
849 
850  if (job->thumbnail) {
851  g_object_unref (job->thumbnail);
852  job->thumbnail = NULL;
853  }
854 
855  if (job->thumbnail_surface) {
856  cairo_surface_destroy (job->thumbnail_surface);
857  job->thumbnail_surface = NULL;
858  }
859 
860  (* G_OBJECT_CLASS (ev_job_thumbnail_parent_class)->dispose) (object);
861 }
862 
863 static gboolean
865 {
866  EvJobThumbnail *job_thumb = EV_JOB_THUMBNAIL (job);
867  EvRenderContext *rc;
868  GdkPixbuf *pixbuf = NULL;
869  EvPage *page;
870 
871  ev_debug_message (DEBUG_JOBS, "%d (%p)", job_thumb->page, job);
872  ev_profiler_start (EV_PROFILE_JOBS, "%s (%p)", EV_GET_TYPE_NAME (job), job);
873 
875 
876  page = ev_document_get_page (job->document, job_thumb->page);
877  rc = ev_render_context_new (page, job_thumb->rotation, job_thumb->scale);
879  job_thumb->target_width, job_thumb->target_height);
880  g_object_unref (page);
881 
882  if (job_thumb->format == EV_JOB_THUMBNAIL_PIXBUF)
883  pixbuf = ev_document_get_thumbnail (job->document, rc);
884  else
885  job_thumb->thumbnail_surface = ev_document_get_thumbnail_surface (job->document, rc);
886  g_object_unref (rc);
888 
889  /* EV_JOB_THUMBNAIL_SURFACE is not compatible with has_frame = TRUE */
890  if (job_thumb->format == EV_JOB_THUMBNAIL_PIXBUF && pixbuf) {
891  job_thumb->thumbnail = job_thumb->has_frame ?
892  ev_document_misc_get_thumbnail_frame (-1, -1, pixbuf) : g_object_ref (pixbuf);
893  g_object_unref (pixbuf);
894  }
895 
896  if ((job_thumb->format == EV_JOB_THUMBNAIL_PIXBUF && pixbuf == NULL) ||
897  job_thumb->thumbnail_surface == NULL) {
898  ev_job_failed (job,
901  _("Failed to create thumbnail for page %d"),
902  job_thumb->page);
903  } else {
904  ev_job_succeeded (job);
905  }
906 
907  return FALSE;
908 }
909 
910 static void
912 {
913  GObjectClass *oclass = G_OBJECT_CLASS (class);
914  EvJobClass *job_class = EV_JOB_CLASS (class);
915 
916  oclass->dispose = ev_job_thumbnail_dispose;
917  job_class->run = ev_job_thumbnail_run;
918 }
919 
920 EvJob *
922  gint page,
923  gint rotation,
924  gdouble scale)
925 {
926  EvJobThumbnail *job;
927 
928  ev_debug_message (DEBUG_JOBS, "%d", page);
929 
930  job = g_object_new (EV_TYPE_JOB_THUMBNAIL, NULL);
931 
932  EV_JOB (job)->document = g_object_ref (document);
933  job->page = page;
934  job->rotation = rotation;
935  job->scale = scale;
936  job->has_frame = TRUE;
938  job->target_width = -1;
939  job->target_height = -1;
940 
941  return EV_JOB (job);
942 }
943 
944 EvJob *
946  gint page,
947  gint rotation,
948  gint target_width,
949  gint target_height)
950 {
951  EvJob *job = ev_job_thumbnail_new (document, page, rotation, 1.);
952  EvJobThumbnail *job_thumb = EV_JOB_THUMBNAIL (job);
953 
954  job_thumb->target_width = target_width;
955  job_thumb->target_height = target_height;
956 
957  return job;
958 }
959 
967 void
969  gboolean has_frame)
970 {
971  job->has_frame = has_frame;
972 }
973 
983 void
985  EvJobThumbnailFormat format)
986 {
987  job->format = format;
988 }
989 
990 /* EvJobFonts */
991 static void
993 {
994  EV_JOB (job)->run_mode = EV_JOB_RUN_MAIN_LOOP;
995 }
996 
997 static gboolean
999 {
1000  EvJobFonts *job_fonts = EV_JOB_FONTS (job);
1001  EvDocumentFonts *fonts = EV_DOCUMENT_FONTS (job->document);
1002 
1003  ev_debug_message (DEBUG_JOBS, NULL);
1004 
1005  /* Do not block the main loop */
1007  return TRUE;
1008 
1010  return TRUE;
1011 
1012 #ifdef EV_ENABLE_DEBUG
1013  /* We use the #ifdef in this case because of the if */
1014  if (ev_document_fonts_get_progress (fonts) == 0)
1015  ev_profiler_start (EV_PROFILE_JOBS, "%s (%p)", EV_GET_TYPE_NAME (job), job);
1016 #endif
1017 
1018  job_fonts->scan_completed = !ev_document_fonts_scan (fonts, 20);
1019  g_signal_emit (job_fonts, job_fonts_signals[FONTS_UPDATED], 0,
1021 
1024 
1025  if (job_fonts->scan_completed)
1026  ev_job_succeeded (job);
1027 
1028  return !job_fonts->scan_completed;
1029 }
1030 
1031 static void
1033 {
1034  EvJobClass *job_class = EV_JOB_CLASS (class);
1035 
1036  job_class->run = ev_job_fonts_run;
1037 
1039  g_signal_new ("updated",
1041  G_SIGNAL_RUN_LAST,
1042  G_STRUCT_OFFSET (EvJobFontsClass, updated),
1043  NULL, NULL,
1044  g_cclosure_marshal_VOID__DOUBLE,
1045  G_TYPE_NONE,
1046  1, G_TYPE_DOUBLE);
1047 }
1048 
1049 EvJob *
1051 {
1052  EvJobFonts *job;
1053 
1054  ev_debug_message (DEBUG_JOBS, NULL);
1055 
1056  job = g_object_new (EV_TYPE_JOB_FONTS, NULL);
1057 
1058  EV_JOB (job)->document = g_object_ref (document);
1059 
1060  return EV_JOB (job);
1061 }
1062 
1063 /* EvJobLoad */
1064 static void
1066 {
1067  EV_JOB (job)->run_mode = EV_JOB_RUN_THREAD;
1068 }
1069 
1070 static void
1071 ev_job_load_dispose (GObject *object)
1072 {
1073  EvJobLoad *job = EV_JOB_LOAD (object);
1074 
1075  ev_debug_message (DEBUG_JOBS, "%s", job->uri);
1076 
1077  if (job->uri) {
1078  g_free (job->uri);
1079  job->uri = NULL;
1080  }
1081 
1082  if (job->password) {
1083  g_free (job->password);
1084  job->password = NULL;
1085  }
1086 
1087  (* G_OBJECT_CLASS (ev_job_load_parent_class)->dispose) (object);
1088 }
1089 
1090 static gboolean
1092 {
1093  EvJobLoad *job_load = EV_JOB_LOAD (job);
1094  GError *error = NULL;
1095 
1096  ev_debug_message (DEBUG_JOBS, "%s", job_load->uri);
1097  ev_profiler_start (EV_PROFILE_JOBS, "%s (%p)", EV_GET_TYPE_NAME (job), job);
1098 
1100 
1101  /* This job may already have a document even if the job didn't complete
1102  because, e.g., a password is required - if so, just reload rather than
1103  creating a new instance */
1104  if (job->document) {
1105  const gchar *uncompressed_uri;
1106 
1107  if (job_load->password) {
1109  job_load->password);
1110  }
1111 
1112  job->failed = FALSE;
1113  job->finished = FALSE;
1114  g_clear_error (&job->error);
1115 
1116  uncompressed_uri = g_object_get_data (G_OBJECT (job->document),
1117  "uri-uncompressed");
1118  ev_document_load (job->document,
1119  uncompressed_uri ? uncompressed_uri : job_load->uri,
1120  &error);
1121  } else {
1122  job->document = ev_document_factory_get_document (job_load->uri,
1123  &error);
1124  }
1125 
1127 
1128  if (error) {
1129  ev_job_failed_from_error (job, error);
1130  g_error_free (error);
1131  } else {
1132  ev_job_succeeded (job);
1133  }
1134 
1135  return FALSE;
1136 }
1137 
1138 static void
1140 {
1141  GObjectClass *oclass = G_OBJECT_CLASS (class);
1142  EvJobClass *job_class = EV_JOB_CLASS (class);
1143 
1144  oclass->dispose = ev_job_load_dispose;
1145  job_class->run = ev_job_load_run;
1146 }
1147 
1148 EvJob *
1149 ev_job_load_new (const gchar *uri)
1150 {
1151  EvJobLoad *job;
1152 
1153  ev_debug_message (DEBUG_JOBS, "%s", uri);
1154 
1155  job = g_object_new (EV_TYPE_JOB_LOAD, NULL);
1156  job->uri = g_strdup (uri);
1157 
1158  return EV_JOB (job);
1159 }
1160 
1161 void
1162 ev_job_load_set_uri (EvJobLoad *job, const gchar *uri)
1163 {
1164  ev_debug_message (DEBUG_JOBS, "%s", uri);
1165 
1166  if (job->uri)
1167  g_free (job->uri);
1168  job->uri = g_strdup (uri);
1169 }
1170 
1171 void
1172 ev_job_load_set_password (EvJobLoad *job, const gchar *password)
1173 {
1174  ev_debug_message (DEBUG_JOBS, NULL);
1175 
1176  if (job->password)
1177  g_free (job->password);
1178  job->password = password ? g_strdup (password) : NULL;
1179 }
1180 
1181 /* EvJobLoadStream */
1182 
1191 static void
1193 {
1195 
1196  EV_JOB (job)->run_mode = EV_JOB_RUN_THREAD;
1197 }
1198 
1199 static void
1201 {
1202  EvJobLoadStream *job = EV_JOB_LOAD_STREAM (object);
1203 
1204  if (job->stream) {
1205  g_object_unref (job->stream);
1206  job->stream = NULL;
1207  }
1208 
1209  g_free (job->password);
1210  job->password = NULL;
1211 
1212  G_OBJECT_CLASS (ev_job_load_stream_parent_class)->dispose (object);
1213 }
1214 
1215 static gboolean
1217 {
1218  EvJobLoadStream *job_load_stream = EV_JOB_LOAD_STREAM (job);
1219  GError *error = NULL;
1220 
1221  ev_profiler_start (EV_PROFILE_JOBS, "%s (%p)", EV_GET_TYPE_NAME (job), job);
1222 
1224 
1225  /* This job may already have a document even if the job didn't complete
1226  because, e.g., a password is required - if so, just reload_stream rather than
1227  creating a new instance */
1228  /* FIXME: do we need to rewind the stream here?? */
1229  if (job->document) {
1230 
1231  if (job_load_stream->password) {
1233  job_load_stream->password);
1234  }
1235 
1236  job->failed = FALSE;
1237  job->finished = FALSE;
1238  g_clear_error (&job->error);
1239 
1240  ev_document_load_stream (job->document,
1241  job_load_stream->stream,
1242  job_load_stream->flags,
1243  job->cancellable,
1244  &error);
1245  } else {
1246  job->document = ev_document_factory_get_document_for_stream (job_load_stream->stream,
1247  NULL /* mime-type FIXME? */,
1248  job_load_stream->flags,
1249  job->cancellable,
1250  &error);
1251  }
1252 
1254 
1255  if (error) {
1256  ev_job_failed_from_error (job, error);
1257  g_error_free (error);
1258  } else {
1259  ev_job_succeeded (job);
1260  }
1261 
1262  return FALSE;
1263 }
1264 
1265 static void
1267 {
1268  GObjectClass *oclass = G_OBJECT_CLASS (class);
1269  EvJobClass *job_class = EV_JOB_CLASS (class);
1270 
1271  oclass->dispose = ev_job_load_stream_dispose;
1272  job_class->run = ev_job_load_stream_run;
1273 }
1274 
1275 EvJob *
1276 ev_job_load_stream_new (GInputStream *stream,
1277  EvDocumentLoadFlags flags)
1278 {
1279  EvJobLoadStream *job;
1280 
1281  job = g_object_new (EV_TYPE_JOB_LOAD_STREAM, NULL);
1282  ev_job_load_stream_set_stream (job, stream);
1283  ev_job_load_stream_set_load_flags (job, flags);
1284 
1285  return EV_JOB (job);
1286 }
1287 
1288 void
1290  GInputStream *stream)
1291 {
1292  g_return_if_fail (EV_IS_JOB_LOAD_STREAM (job));
1293  g_return_if_fail (G_IS_INPUT_STREAM (stream));
1294 
1295  g_object_ref (stream);
1296  if (job->stream)
1297  g_object_unref (job->stream);
1298  job->stream = stream;
1299 }
1300 
1301 void
1303  EvDocumentLoadFlags flags)
1304 {
1305  g_return_if_fail (EV_IS_JOB_LOAD_STREAM (job));
1306 
1307  job->flags = flags;
1308 }
1309 
1310 void
1312  const char *password)
1313 {
1314  char *old_password;
1315 
1316  ev_debug_message (DEBUG_JOBS, NULL);
1317 
1318  g_return_if_fail (EV_IS_JOB_LOAD_STREAM (job));
1319 
1320  old_password = job->password;
1321  job->password = g_strdup (password);
1322  g_free (old_password);
1323 }
1324 
1325 /* EvJobLoadGFile */
1326 
1335 static void
1337 {
1339 
1340  EV_JOB (job)->run_mode = EV_JOB_RUN_THREAD;
1341 }
1342 
1343 static void
1344 ev_job_load_gfile_dispose (GObject *object)
1345 {
1346  EvJobLoadGFile *job = EV_JOB_LOAD_GFILE (object);
1347 
1348  if (job->gfile) {
1349  g_object_unref (job->gfile);
1350  job->gfile = NULL;
1351  }
1352 
1353  g_free (job->password);
1354  job->password = NULL;
1355 
1356  G_OBJECT_CLASS (ev_job_load_gfile_parent_class)->dispose (object);
1357 }
1358 
1359 static gboolean
1361 {
1362  EvJobLoadGFile *job_load_gfile = EV_JOB_LOAD_GFILE (job);
1363  GError *error = NULL;
1364 
1365  ev_profiler_start (EV_PROFILE_JOBS, "%s (%p)", EV_GET_TYPE_NAME (job), job);
1366 
1368 
1369  /* This job may already have a document even if the job didn't complete
1370  because, e.g., a password is required - if so, just reload_gfile rather than
1371  creating a new instance */
1372  if (job->document) {
1373 
1374  if (job_load_gfile->password) {
1376  job_load_gfile->password);
1377  }
1378 
1379  job->failed = FALSE;
1380  job->finished = FALSE;
1381  g_clear_error (&job->error);
1382 
1383  ev_document_load_gfile (job->document,
1384  job_load_gfile->gfile,
1385  job_load_gfile->flags,
1386  job->cancellable,
1387  &error);
1388  } else {
1389  job->document = ev_document_factory_get_document_for_gfile (job_load_gfile->gfile,
1390  job_load_gfile->flags,
1391  job->cancellable,
1392  &error);
1393  }
1394 
1396 
1397  if (error) {
1398  ev_job_failed_from_error (job, error);
1399  g_error_free (error);
1400  } else {
1401  ev_job_succeeded (job);
1402  }
1403 
1404  return FALSE;
1405 }
1406 
1407 static void
1409 {
1410  GObjectClass *oclass = G_OBJECT_CLASS (class);
1411  EvJobClass *job_class = EV_JOB_CLASS (class);
1412 
1413  oclass->dispose = ev_job_load_gfile_dispose;
1414  job_class->run = ev_job_load_gfile_run;
1415 }
1416 
1417 EvJob *
1419  EvDocumentLoadFlags flags)
1420 {
1421  EvJobLoadGFile *job;
1422 
1423  job = g_object_new (EV_TYPE_JOB_LOAD_GFILE, NULL);
1424  ev_job_load_gfile_set_gfile (job, gfile);
1425  ev_job_load_gfile_set_load_flags (job, flags);
1426 
1427  return EV_JOB (job);
1428 }
1429 
1430 void
1432  GFile *gfile)
1433 {
1434  g_return_if_fail (EV_IS_JOB_LOAD_GFILE (job));
1435  g_return_if_fail (G_IS_FILE (gfile));
1436 
1437  g_object_ref (gfile);
1438  if (job->gfile)
1439  g_object_unref (job->gfile);
1440  job->gfile = gfile;
1441 }
1442 
1443 void
1445  EvDocumentLoadFlags flags)
1446 {
1447  g_return_if_fail (EV_IS_JOB_LOAD_GFILE (job));
1448 
1449  job->flags = flags;
1450 }
1451 
1452 void
1454  const char *password)
1455 {
1456  char *old_password;
1457 
1458  ev_debug_message (DEBUG_JOBS, NULL);
1459 
1460  g_return_if_fail (EV_IS_JOB_LOAD_GFILE (job));
1461 
1462  old_password = job->password;
1463  job->password = g_strdup (password);
1464  g_free (old_password);
1465 }
1466 
1467 /* EvJobSave */
1468 static void
1470 {
1471  EV_JOB (job)->run_mode = EV_JOB_RUN_THREAD;
1472 }
1473 
1474 static void
1475 ev_job_save_dispose (GObject *object)
1476 {
1477  EvJobSave *job = EV_JOB_SAVE (object);
1478 
1479  ev_debug_message (DEBUG_JOBS, "%s", job->uri);
1480 
1481  if (job->uri) {
1482  g_free (job->uri);
1483  job->uri = NULL;
1484  }
1485 
1486  if (job->document_uri) {
1487  g_free (job->document_uri);
1488  job->document_uri = NULL;
1489  }
1490 
1491  (* G_OBJECT_CLASS (ev_job_save_parent_class)->dispose) (object);
1492 }
1493 
1494 static gboolean
1496 {
1497  EvJobSave *job_save = EV_JOB_SAVE (job);
1498  gint fd;
1499  gchar *tmp_filename = NULL;
1500  gchar *local_uri;
1501  GError *error = NULL;
1502 
1503  ev_debug_message (DEBUG_JOBS, "uri: %s, document_uri: %s", job_save->uri, job_save->document_uri);
1504  ev_profiler_start (EV_PROFILE_JOBS, "%s (%p)", EV_GET_TYPE_NAME (job), job);
1505 
1506  fd = ev_mkstemp ("saveacopy.XXXXXX", &tmp_filename, &error);
1507  if (fd == -1) {
1508  ev_job_failed_from_error (job, error);
1509  g_error_free (error);
1510 
1511  return FALSE;
1512  }
1513  close (fd);
1514 
1516 
1517  /* Save document to temp filename */
1518  local_uri = g_filename_to_uri (tmp_filename, NULL, &error);
1519  if (local_uri != NULL) {
1520  ev_document_save (job->document, local_uri, &error);
1521  }
1522 
1524 
1525  if (error) {
1526  g_free (local_uri);
1527  ev_job_failed_from_error (job, error);
1528  g_error_free (error);
1529 
1530  return FALSE;
1531  }
1532 
1533  /* If original document was compressed,
1534  * compress it again before saving
1535  */
1536  if (g_object_get_data (G_OBJECT (job->document), "uri-uncompressed")) {
1538  const gchar *ext;
1539  gchar *uri_comp;
1540 
1541  ext = g_strrstr (job_save->document_uri, ".gz");
1542  if (ext && g_ascii_strcasecmp (ext, ".gz") == 0)
1543  ctype = EV_COMPRESSION_GZIP;
1544 
1545  ext = g_strrstr (job_save->document_uri, ".bz2");
1546  if (ext && g_ascii_strcasecmp (ext, ".bz2") == 0)
1547  ctype = EV_COMPRESSION_BZIP2;
1548 
1549  uri_comp = ev_file_compress (local_uri, ctype, &error);
1550  g_free (local_uri);
1551  g_unlink (tmp_filename);
1552 
1553  if (!uri_comp || error) {
1554  local_uri = NULL;
1555  } else {
1556  local_uri = uri_comp;
1557  }
1558  }
1559 
1560  g_free (tmp_filename);
1561 
1562  if (error) {
1563  g_free (local_uri);
1564  ev_job_failed_from_error (job, error);
1565  g_error_free (error);
1566 
1567  return FALSE;
1568  }
1569 
1570  if (!local_uri)
1571  return FALSE;
1572 
1573  ev_xfer_uri_simple (local_uri, job_save->uri, &error);
1574  ev_tmp_uri_unlink (local_uri);
1575 
1576  /* Copy the metadata from the original file */
1577  if (!error) {
1578  /* Ignore errors here. Failure to copy metadata is not a hard error */
1579  ev_file_copy_metadata (job_save->document_uri, job_save->uri, NULL);
1580  }
1581 
1582  if (error) {
1583  ev_job_failed_from_error (job, error);
1584  g_error_free (error);
1585  } else {
1586  ev_job_succeeded (job);
1587  }
1588 
1589  return FALSE;
1590 }
1591 
1592 static void
1594 {
1595  GObjectClass *oclass = G_OBJECT_CLASS (class);
1596  EvJobClass *job_class = EV_JOB_CLASS (class);
1597 
1598  oclass->dispose = ev_job_save_dispose;
1599  job_class->run = ev_job_save_run;
1600 }
1601 
1602 EvJob *
1604  const gchar *uri,
1605  const gchar *document_uri)
1606 {
1607  EvJobSave *job;
1608 
1609  ev_debug_message (DEBUG_JOBS, "uri: %s, document_uri: %s", uri, document_uri);
1610 
1611  job = g_object_new (EV_TYPE_JOB_SAVE, NULL);
1612 
1613  EV_JOB (job)->document = g_object_ref (document);
1614  job->uri = g_strdup (uri);
1615  job->document_uri = g_strdup (document_uri);
1616 
1617  return EV_JOB (job);
1618 }
1619 
1620 /* EvJobFind */
1621 static void
1623 {
1624  EV_JOB (job)->run_mode = EV_JOB_RUN_MAIN_LOOP;
1625 }
1626 
1627 static void
1628 ev_job_find_dispose (GObject *object)
1629 {
1630  EvJobFind *job = EV_JOB_FIND (object);
1631 
1632  ev_debug_message (DEBUG_JOBS, NULL);
1633 
1634  if (job->text) {
1635  g_free (job->text);
1636  job->text = NULL;
1637  }
1638 
1639  if (job->pages) {
1640  gint i;
1641 
1642  for (i = 0; i < job->n_pages; i++) {
1643  g_list_foreach (job->pages[i], (GFunc)ev_rectangle_free, NULL);
1644  g_list_free (job->pages[i]);
1645  }
1646 
1647  g_free (job->pages);
1648  job->pages = NULL;
1649  }
1650 
1651  (* G_OBJECT_CLASS (ev_job_find_parent_class)->dispose) (object);
1652 }
1653 
1654 static gboolean
1656 {
1657  EvJobFind *job_find = EV_JOB_FIND (job);
1658  EvDocumentFind *find = EV_DOCUMENT_FIND (job->document);
1659  EvPage *ev_page;
1660  GList *matches;
1661 
1662  ev_debug_message (DEBUG_JOBS, NULL);
1663 
1664  /* Do not block the main loop */
1666  return TRUE;
1667 
1668 #ifdef EV_ENABLE_DEBUG
1669  /* We use the #ifdef in this case because of the if */
1670  if (job_find->current_page == job_find->start_page)
1671  ev_profiler_start (EV_PROFILE_JOBS, "%s (%p)", EV_GET_TYPE_NAME (job), job);
1672 #endif
1673 
1674  ev_page = ev_document_get_page (job->document, job_find->current_page);
1675  matches = ev_document_find_find_text_with_options (find, ev_page, job_find->text,
1676  job_find->options);
1677  g_object_unref (ev_page);
1678 
1680 
1681  if (!job_find->has_results)
1682  job_find->has_results = (matches != NULL);
1683 
1684  job_find->pages[job_find->current_page] = matches;
1685  g_signal_emit (job_find, job_find_signals[FIND_UPDATED], 0, job_find->current_page);
1686 
1687  job_find->current_page = (job_find->current_page + 1) % job_find->n_pages;
1688  if (job_find->current_page == job_find->start_page) {
1689  ev_job_succeeded (job);
1690 
1691  return FALSE;
1692  }
1693 
1694  return TRUE;
1695 }
1696 
1697 static void
1699 {
1700  EvJobClass *job_class = EV_JOB_CLASS (class);
1701  GObjectClass *gobject_class = G_OBJECT_CLASS (class);
1702 
1703  job_class->run = ev_job_find_run;
1704  gobject_class->dispose = ev_job_find_dispose;
1705 
1707  g_signal_new ("updated",
1709  G_SIGNAL_RUN_LAST,
1710  G_STRUCT_OFFSET (EvJobFindClass, updated),
1711  NULL, NULL,
1712  g_cclosure_marshal_VOID__INT,
1713  G_TYPE_NONE,
1714  1, G_TYPE_INT);
1715 }
1716 
1717 EvJob *
1719  gint start_page,
1720  gint n_pages,
1721  const gchar *text,
1722  gboolean case_sensitive)
1723 {
1724  EvJobFind *job;
1725 
1726  ev_debug_message (DEBUG_JOBS, NULL);
1727 
1728  job = g_object_new (EV_TYPE_JOB_FIND, NULL);
1729 
1730  EV_JOB (job)->document = g_object_ref (document);
1731  job->start_page = start_page;
1732  job->current_page = start_page;
1733  job->n_pages = n_pages;
1734  job->pages = g_new0 (GList *, n_pages);
1735  job->text = g_strdup (text);
1736  /* Keep for compatibility */
1737  job->case_sensitive = case_sensitive;
1738  job->has_results = FALSE;
1739  if (case_sensitive)
1741 
1742  return EV_JOB (job);
1743 }
1744 
1752 void
1754  EvFindOptions options)
1755 {
1756  job->options = options;
1757  /* Keep compatibility */
1758  job->case_sensitive = options & EV_FIND_CASE_SENSITIVE;
1759 }
1760 
1771 {
1772  return job->options;
1773 }
1774 
1775 gint
1777  gint page)
1778 {
1779  return g_list_length (job->pages[page]);
1780 }
1781 
1782 gdouble
1784 {
1785  gint pages_done;
1786 
1787  if (ev_job_is_finished (EV_JOB (job)))
1788  return 1.0;
1789 
1790  if (job->current_page > job->start_page) {
1791  pages_done = job->current_page - job->start_page + 1;
1792  } else if (job->current_page == job->start_page) {
1793  pages_done = job->n_pages;
1794  } else {
1795  pages_done = job->n_pages - job->start_page + job->current_page;
1796  }
1797 
1798  return pages_done / (gdouble) job->n_pages;
1799 }
1800 
1801 gboolean
1803 {
1804  return job->has_results;
1805 }
1806 
1813 GList **
1815 {
1816  return job->pages;
1817 }
1818 
1819 /* EvJobLayers */
1820 static void
1822 {
1823  EV_JOB (job)->run_mode = EV_JOB_RUN_THREAD;
1824 }
1825 
1826 static void
1827 ev_job_layers_dispose (GObject *object)
1828 {
1829  EvJobLayers *job;
1830 
1831  ev_debug_message (DEBUG_JOBS, NULL);
1832 
1833  job = EV_JOB_LAYERS (object);
1834 
1835  if (job->model) {
1836  g_object_unref (job->model);
1837  job->model = NULL;
1838  }
1839 
1840  (* G_OBJECT_CLASS (ev_job_layers_parent_class)->dispose) (object);
1841 }
1842 
1843 static gboolean
1845 {
1846  EvJobLayers *job_layers = EV_JOB_LAYERS (job);
1847 
1848  ev_debug_message (DEBUG_JOBS, NULL);
1849  ev_profiler_start (EV_PROFILE_JOBS, "%s (%p)", EV_GET_TYPE_NAME (job), job);
1850 
1852  job_layers->model = ev_document_layers_get_layers (EV_DOCUMENT_LAYERS (job->document));
1854 
1855  ev_job_succeeded (job);
1856 
1857  return FALSE;
1858 }
1859 
1860 static void
1862 {
1863  GObjectClass *oclass = G_OBJECT_CLASS (class);
1864  EvJobClass *job_class = EV_JOB_CLASS (class);
1865 
1866  oclass->dispose = ev_job_layers_dispose;
1867  job_class->run = ev_job_layers_run;
1868 }
1869 
1870 EvJob *
1872 {
1873  EvJob *job;
1874 
1875  ev_debug_message (DEBUG_JOBS, NULL);
1876 
1877  job = g_object_new (EV_TYPE_JOB_LAYERS, NULL);
1878  job->document = g_object_ref (document);
1879 
1880  return job;
1881 }
1882 
1883 /* EvJobExport */
1884 static void
1886 {
1887  EV_JOB (job)->run_mode = EV_JOB_RUN_THREAD;
1888  job->page = -1;
1889 }
1890 
1891 static void
1892 ev_job_export_dispose (GObject *object)
1893 {
1894  EvJobExport *job;
1895 
1896  ev_debug_message (DEBUG_JOBS, NULL);
1897 
1898  job = EV_JOB_EXPORT (object);
1899 
1900  if (job->rc) {
1901  g_object_unref (job->rc);
1902  job->rc = NULL;
1903  }
1904 
1905  (* G_OBJECT_CLASS (ev_job_export_parent_class)->dispose) (object);
1906 }
1907 
1908 static gboolean
1910 {
1911  EvJobExport *job_export = EV_JOB_EXPORT (job);
1912  EvPage *ev_page;
1913 
1914  g_assert (job_export->page != -1);
1915 
1916  ev_debug_message (DEBUG_JOBS, NULL);
1917  ev_profiler_start (EV_PROFILE_JOBS, "%s (%p)", EV_GET_TYPE_NAME (job), job);
1918 
1920 
1921  ev_page = ev_document_get_page (job->document, job_export->page);
1922  if (job_export->rc) {
1923  job->failed = FALSE;
1924  job->finished = FALSE;
1925  g_clear_error (&job->error);
1926 
1927  ev_render_context_set_page (job_export->rc, ev_page);
1928  } else {
1929  job_export->rc = ev_render_context_new (ev_page, 0, 1.0);
1930  }
1931  g_object_unref (ev_page);
1932 
1933  ev_file_exporter_do_page (EV_FILE_EXPORTER (job->document), job_export->rc);
1934 
1936 
1937  ev_job_succeeded (job);
1938 
1939  return FALSE;
1940 }
1941 
1942 static void
1944 {
1945  GObjectClass *oclass = G_OBJECT_CLASS (class);
1946  EvJobClass *job_class = EV_JOB_CLASS (class);
1947 
1948  oclass->dispose = ev_job_export_dispose;
1949  job_class->run = ev_job_export_run;
1950 }
1951 
1952 EvJob *
1954 {
1955  EvJob *job;
1956 
1957  ev_debug_message (DEBUG_JOBS, NULL);
1958 
1959  job = g_object_new (EV_TYPE_JOB_EXPORT, NULL);
1960  job->document = g_object_ref (document);
1961 
1962  return job;
1963 }
1964 
1965 void
1967  gint page)
1968 {
1969  job->page = page;
1970 }
1971 
1972 /* EvJobPrint */
1973 static void
1975 {
1976  EV_JOB (job)->run_mode = EV_JOB_RUN_THREAD;
1977  job->page = -1;
1978 }
1979 
1980 static void
1981 ev_job_print_dispose (GObject *object)
1982 {
1983  EvJobPrint *job;
1984 
1985  ev_debug_message (DEBUG_JOBS, NULL);
1986 
1987  job = EV_JOB_PRINT (object);
1988 
1989  if (job->cr) {
1990  cairo_destroy (job->cr);
1991  job->cr = NULL;
1992  }
1993 
1994  (* G_OBJECT_CLASS (ev_job_print_parent_class)->dispose) (object);
1995 }
1996 
1997 static gboolean
1999 {
2000  EvJobPrint *job_print = EV_JOB_PRINT (job);
2001  EvPage *ev_page;
2002  cairo_status_t cr_status;
2003 
2004  g_assert (job_print->page != -1);
2005  g_assert (job_print->cr != NULL);
2006 
2007  ev_debug_message (DEBUG_JOBS, NULL);
2008  ev_profiler_start (EV_PROFILE_JOBS, "%s (%p)", EV_GET_TYPE_NAME (job), job);
2009 
2010  job->failed = FALSE;
2011  job->finished = FALSE;
2012  g_clear_error (&job->error);
2013 
2015 
2016  ev_page = ev_document_get_page (job->document, job_print->page);
2018  ev_page, job_print->cr);
2019  g_object_unref (ev_page);
2020 
2022 
2023  if (g_cancellable_is_cancelled (job->cancellable))
2024  return FALSE;
2025 
2026  cr_status = cairo_status (job_print->cr);
2027  if (cr_status == CAIRO_STATUS_SUCCESS) {
2028  ev_job_succeeded (job);
2029  } else {
2030  ev_job_failed (job,
2031  GTK_PRINT_ERROR,
2032  GTK_PRINT_ERROR_GENERAL,
2033  _("Failed to print page %d: %s"),
2034  job_print->page,
2035  cairo_status_to_string (cr_status));
2036  }
2037 
2038  return FALSE;
2039 }
2040 
2041 static void
2043 {
2044  GObjectClass *oclass = G_OBJECT_CLASS (class);
2045  EvJobClass *job_class = EV_JOB_CLASS (class);
2046 
2047  oclass->dispose = ev_job_print_dispose;
2048  job_class->run = ev_job_print_run;
2049 }
2050 
2051 EvJob *
2053 {
2054  EvJob *job;
2055 
2056  ev_debug_message (DEBUG_JOBS, NULL);
2057 
2058  job = g_object_new (EV_TYPE_JOB_PRINT, NULL);
2059  job->document = g_object_ref (document);
2060 
2061  return job;
2062 }
2063 
2064 void
2066  gint page)
2067 {
2068  job->page = page;
2069 }
2070 
2071 void
2073  cairo_t *cr)
2074 {
2075  if (job->cr == cr)
2076  return;
2077 
2078  if (job->cr)
2079  cairo_destroy (job->cr);
2080  job->cr = cr ? cairo_reference (cr) : NULL;
2081 }