]> www.fi.muni.cz Git - evince.git/blob - shell/ev-jobs.c
Cleanup mime type detection on document load. Fix for the bug #336448.
[evince.git] / shell / ev-jobs.c
1 #include "ev-jobs.h"
2 #include "ev-job-queue.h"
3 #include "ev-document-thumbnails.h"
4 #include "ev-document-links.h"
5 #include "ev-document-factory.h"
6 #include "ev-file-helpers.h"
7 #include "ev-document-fonts.h"
8 #include "ev-selection.h"
9 #include "ev-async-renderer.h"
10
11 #include <libgnomevfs/gnome-vfs-uri.h>
12 #include <libgnomevfs/gnome-vfs-utils.h>
13 #include <libgnomevfs/gnome-vfs-ops.h>
14 #include <libgnomevfs/gnome-vfs-xfer.h>
15
16 static void ev_job_init                 (EvJob               *job);
17 static void ev_job_class_init           (EvJobClass          *class);
18 static void ev_job_links_init           (EvJobLinks          *job);
19 static void ev_job_links_class_init     (EvJobLinksClass     *class);
20 static void ev_job_render_init          (EvJobRender         *job);
21 static void ev_job_render_class_init    (EvJobRenderClass    *class);
22 static void ev_job_thumbnail_init       (EvJobThumbnail      *job);
23 static void ev_job_thumbnail_class_init (EvJobThumbnailClass *class);
24 static void ev_job_xfer_init            (EvJobXfer           *job);
25 static void ev_job_xfer_class_init      (EvJobXferClass      *class);
26
27 enum
28 {
29         FINISHED,
30         LAST_SIGNAL
31 };
32
33 static guint job_signals[LAST_SIGNAL] = { 0 };
34
35 G_DEFINE_TYPE (EvJob, ev_job, G_TYPE_OBJECT)
36 G_DEFINE_TYPE (EvJobLinks, ev_job_links, EV_TYPE_JOB)
37 G_DEFINE_TYPE (EvJobRender, ev_job_render, EV_TYPE_JOB)
38 G_DEFINE_TYPE (EvJobThumbnail, ev_job_thumbnail, EV_TYPE_JOB)
39 G_DEFINE_TYPE (EvJobFonts, ev_job_fonts, EV_TYPE_JOB)
40 G_DEFINE_TYPE (EvJobXfer, ev_job_xfer, EV_TYPE_JOB)
41
42 static void ev_job_init (EvJob *job) { /* Do Nothing */ }
43
44 static void
45 ev_job_dispose (GObject *object)
46 {
47         EvJob *job;
48
49         job = EV_JOB (object);
50
51         if (job->document) {
52                 g_object_unref (job->document);
53                 job->document = NULL;
54         }
55
56         (* G_OBJECT_CLASS (ev_job_parent_class)->dispose) (object);
57 }
58
59 static void
60 ev_job_class_init (EvJobClass *class)
61 {
62         GObjectClass *oclass;
63
64         oclass = G_OBJECT_CLASS (class);
65
66         oclass->dispose = ev_job_dispose;
67
68         job_signals [FINISHED] =
69                 g_signal_new ("finished",
70                               EV_TYPE_JOB,
71                               G_SIGNAL_RUN_LAST,
72                               G_STRUCT_OFFSET (EvJobClass, finished),
73                               NULL, NULL,
74                               g_cclosure_marshal_VOID__VOID,
75                               G_TYPE_NONE, 0);
76 }
77
78
79 static void ev_job_links_init (EvJobLinks *job) { /* Do Nothing */ }
80
81 static void
82 ev_job_links_dispose (GObject *object)
83 {
84         EvJobLinks *job;
85
86         job = EV_JOB_LINKS (object);
87
88         if (job->model) {
89                 g_object_unref (job->model);
90                 job->model = NULL;
91         }
92
93         (* G_OBJECT_CLASS (ev_job_links_parent_class)->dispose) (object);
94 }
95
96 static void
97 ev_job_links_class_init (EvJobLinksClass *class)
98 {
99         GObjectClass *oclass;
100
101         oclass = G_OBJECT_CLASS (class);
102
103         oclass->dispose = ev_job_links_dispose;
104 }
105
106
107 static void ev_job_render_init (EvJobRender *job) { /* Do Nothing */ }
108
109 static void
110 ev_job_render_dispose (GObject *object)
111 {
112         EvJobRender *job;
113
114         job = EV_JOB_RENDER (object);
115
116         if (job->pixbuf) {
117                 g_object_unref (job->pixbuf);
118                 job->pixbuf = NULL;
119         }
120
121         if (job->rc) {
122                 g_object_unref (job->rc);
123                 job->rc = NULL;
124         }
125
126         if (job->selection) {
127                 g_object_unref (job->selection);
128                 job->selection = NULL;
129         }
130
131         if (job->selection_region) {
132                 gdk_region_destroy (job->selection_region);
133                 job->selection_region = NULL;
134         }
135
136         (* G_OBJECT_CLASS (ev_job_render_parent_class)->dispose) (object);
137 }
138
139 static void
140 ev_job_render_class_init (EvJobRenderClass *class)
141 {
142         GObjectClass *oclass;
143
144         oclass = G_OBJECT_CLASS (class);
145
146         oclass->dispose = ev_job_render_dispose;
147 }
148
149 static void ev_job_thumbnail_init (EvJobThumbnail *job) { /* Do Nothing */ }
150
151 static void
152 ev_job_thumbnail_dispose (GObject *object)
153 {
154         EvJobThumbnail *job;
155
156         job = EV_JOB_THUMBNAIL (object);
157
158         if (job->thumbnail) {
159                 g_object_unref (job->thumbnail);
160                 job->thumbnail = NULL;
161         }
162
163         (* G_OBJECT_CLASS (ev_job_thumbnail_parent_class)->dispose) (object);
164 }
165
166 static void
167 ev_job_thumbnail_class_init (EvJobThumbnailClass *class)
168 {
169         GObjectClass *oclass;
170
171         oclass = G_OBJECT_CLASS (class);
172
173         oclass->dispose = ev_job_thumbnail_dispose;
174 }
175
176 /* Public functions */
177 void
178 ev_job_finished (EvJob *job)
179 {
180         g_return_if_fail (EV_IS_JOB (job));
181
182         g_signal_emit (job, job_signals[FINISHED], 0);
183 }
184
185 EvJob *
186 ev_job_links_new (EvDocument *document)
187 {
188         EvJob *job;
189
190         job = g_object_new (EV_TYPE_JOB_LINKS, NULL);
191         job->document = g_object_ref (document);
192
193         return job;
194 }
195
196 void
197 ev_job_links_run (EvJobLinks *job)
198 {
199         g_return_if_fail (EV_IS_JOB_LINKS (job));
200
201         ev_document_doc_mutex_lock ();
202         job->model = ev_document_links_get_links_model (EV_DOCUMENT_LINKS (EV_JOB (job)->document));
203         EV_JOB (job)->finished = TRUE;
204         ev_document_doc_mutex_unlock ();
205 }
206
207
208 EvJob *
209 ev_job_render_new (EvDocument      *document,
210                    EvRenderContext *rc,
211                    gint             width,
212                    gint             height,
213                    EvRectangle     *selection_points,
214                    GdkColor        *text,
215                    GdkColor        *base,
216                    gboolean         include_links,
217                    gboolean         include_text,
218                    gboolean         include_selection)
219 {
220         EvJobRender *job;
221
222         g_return_val_if_fail (EV_IS_RENDER_CONTEXT (rc), NULL);
223         if (include_selection)
224                 g_return_val_if_fail (selection_points != NULL, NULL);
225
226         job = g_object_new (EV_TYPE_JOB_RENDER, NULL);
227
228         EV_JOB (job)->document = g_object_ref (document);
229         job->rc = g_object_ref (rc);
230         job->target_width = width;
231         job->target_height = height;
232         job->text = *text;
233         job->base = *base;
234         job->include_links = include_links;
235         job->include_text = include_text;
236         job->include_selection = include_selection;
237
238         if (include_selection)
239                 job->selection_points = *selection_points;
240
241         if (EV_IS_ASYNC_RENDERER (document)) {  
242                 EV_JOB (job)->async = TRUE;
243         }
244
245         return EV_JOB (job);
246 }
247
248 static void
249 render_finished_cb (EvDocument *document, GdkPixbuf *pixbuf, EvJobRender *job)
250 {
251         g_signal_handlers_disconnect_by_func (EV_JOB (job)->document,
252                                               render_finished_cb, job);
253
254         EV_JOB (job)->finished = TRUE;
255         job->pixbuf = g_object_ref (pixbuf);
256         ev_job_finished (EV_JOB (job));
257 }
258
259 void
260 ev_job_render_run (EvJobRender *job)
261 {
262         g_return_if_fail (EV_IS_JOB_RENDER (job));
263
264         ev_document_doc_mutex_lock ();
265
266         if (EV_JOB (job)->async) {
267                 EvAsyncRenderer *renderer = EV_ASYNC_RENDERER (EV_JOB (job)->document);
268                 ev_async_renderer_render_pixbuf (renderer, job->rc->page, job->rc->scale,
269                                                  job->rc->rotation);
270                 g_signal_connect (EV_JOB (job)->document, "render_finished",
271                                   G_CALLBACK (render_finished_cb), job);
272         } else {
273                 job->pixbuf = ev_document_render_pixbuf (EV_JOB (job)->document, job->rc);
274                 if (job->include_links)
275                         job->link_mapping = ev_document_get_links (EV_JOB (job)->document, job->rc->page);
276                 if (job->include_text && EV_IS_SELECTION (EV_JOB (job)->document))
277                         job->text_mapping = ev_selection_get_selection_map (EV_SELECTION (EV_JOB (job)->document), job->rc);
278                 if (job->include_selection && EV_IS_SELECTION (EV_JOB (job)->document)) {
279                         ev_selection_render_selection (EV_SELECTION (EV_JOB (job)->document),
280                                                        job->rc,
281                                                        &(job->selection),
282                                                        &(job->selection_points),
283                                                        NULL,
284                                                        &(job->text), &(job->base));
285                         job->selection_region =
286                                 ev_selection_get_selection_region (EV_SELECTION (EV_JOB (job)->document),
287                                                                    job->rc,
288                                                                    &(job->selection_points));
289                 }
290
291                 EV_JOB (job)->finished = TRUE;
292         }
293
294         ev_document_doc_mutex_unlock ();
295 }
296
297 EvJob *
298 ev_job_thumbnail_new (EvDocument   *document,
299                       gint          page,
300                       int           rotation,
301                       gint          requested_width)
302 {
303         EvJobThumbnail *job;
304
305         job = g_object_new (EV_TYPE_JOB_THUMBNAIL, NULL);
306
307         EV_JOB (job)->document = g_object_ref (document);
308         job->page = page;
309         job->rotation = rotation;
310         job->requested_width = requested_width;
311
312         return EV_JOB (job);
313 }
314
315 void
316 ev_job_thumbnail_run (EvJobThumbnail *job)
317 {
318         g_return_if_fail (EV_IS_JOB_THUMBNAIL (job));
319
320         ev_document_doc_mutex_lock ();
321
322         job->thumbnail =
323                 ev_document_thumbnails_get_thumbnail (EV_DOCUMENT_THUMBNAILS (EV_JOB (job)->document),
324                                                       job->page,
325                                                       job->rotation,
326                                                       job->requested_width,
327                                                       TRUE);
328         EV_JOB (job)->finished = TRUE;
329
330         ev_document_doc_mutex_unlock ();
331 }
332
333 static void ev_job_fonts_init (EvJobFonts *job) { /* Do Nothing */ }
334
335 static void ev_job_fonts_class_init (EvJobFontsClass *class) { /* Do Nothing */ }
336
337 EvJob *
338 ev_job_fonts_new (EvDocument *document)
339 {
340         EvJobFonts *job;
341
342         job = g_object_new (EV_TYPE_JOB_FONTS, NULL);
343
344         EV_JOB (job)->document = g_object_ref (document);
345
346         return EV_JOB (job);
347 }
348
349 void
350 ev_job_fonts_run (EvJobFonts *job)
351 {
352         EvDocumentFonts *fonts;
353
354         g_return_if_fail (EV_IS_JOB_FONTS (job));
355
356         ev_document_doc_mutex_lock ();
357         
358         fonts = EV_DOCUMENT_FONTS (EV_JOB (job)->document);
359         job->scan_completed = !ev_document_fonts_scan (fonts, 20);
360         
361         EV_JOB (job)->finished = TRUE;
362
363         ev_document_doc_mutex_unlock ();
364 }
365
366 static void ev_job_xfer_init (EvJobXfer *job) { /* Do Nothing */ }
367
368 static void
369 ev_job_xfer_dispose (GObject *object)
370 {
371         EvJobXfer *job = EV_JOB_XFER (object);
372
373         if (job->uri) {
374                 g_free (job->uri);
375                 job->uri = NULL;
376         }
377
378         if (job->local_uri) {
379                 g_free (job->local_uri);
380                 job->local_uri = NULL;
381         }
382
383         if (job->error) {
384                 g_error_free (job->error);
385                 job->error = NULL;
386         }
387
388         (* G_OBJECT_CLASS (ev_job_xfer_parent_class)->dispose) (object);
389 }
390
391 static void
392 ev_job_xfer_class_init (EvJobXferClass *class)
393 {
394         GObjectClass *oclass;
395
396         oclass = G_OBJECT_CLASS (class);
397
398         oclass->dispose = ev_job_xfer_dispose;
399 }
400
401
402 EvJob *
403 ev_job_xfer_new (const gchar *uri)
404 {
405         EvJobXfer *job;
406
407         job = g_object_new (EV_TYPE_JOB_XFER, NULL);
408
409         job->uri = g_strdup (uri);
410
411         return EV_JOB (job);
412 }
413
414 void
415 ev_job_xfer_run (EvJobXfer *job)
416 {
417         GnomeVFSURI *source_uri;
418         GnomeVFSURI *target_uri;
419
420         g_return_if_fail (EV_IS_JOB_XFER (job));
421         
422         if (job->error) {
423                 g_error_free (job->error);
424                 job->error = NULL;
425         }
426
427         source_uri = gnome_vfs_uri_new (job->uri);
428         if (!gnome_vfs_uri_is_local (source_uri) && !job->local_uri) {
429                 char *tmp_name;
430                 char *base_name;
431                 
432                 tmp_name = ev_tmp_filename ();
433                 base_name = g_path_get_basename (job->uri);
434                 job->local_uri = g_strconcat ("file:", tmp_name, base_name, NULL);
435                 g_free (tmp_name);
436                 
437                 target_uri = gnome_vfs_uri_new (job->local_uri);
438
439                 gnome_vfs_xfer_uri (source_uri, target_uri, 
440                                     GNOME_VFS_XFER_DEFAULT | GNOME_VFS_XFER_FOLLOW_LINKS,
441                                     GNOME_VFS_XFER_ERROR_MODE_ABORT,
442                                     GNOME_VFS_XFER_OVERWRITE_MODE_REPLACE,
443                                     NULL,
444                                     job);
445                 gnome_vfs_uri_unref (target_uri);
446         }
447         gnome_vfs_uri_unref (source_uri);
448
449         EV_JOB(job)->document = ev_document_factory_get_document (job->local_uri ? job->local_uri : job->uri, &job->error);
450         EV_JOB (job)->finished = TRUE;
451
452         return;
453 }
454