]> www.fi.muni.cz Git - evince.git/blob - shell/ev-jobs.c
Updated German translation.
[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 && EV_IS_DOCUMENT_LINKS (EV_JOB (job)->document))
275                         job->link_mapping =
276                                 ev_document_links_get_links (EV_DOCUMENT_LINKS (EV_JOB (job)->document),
277                                                              job->rc->page);
278                 if (job->include_text && EV_IS_SELECTION (EV_JOB (job)->document))
279                         job->text_mapping =
280                                 ev_selection_get_selection_map (EV_SELECTION (EV_JOB (job)->document),
281                                                                 job->rc);
282                 if (job->include_selection && EV_IS_SELECTION (EV_JOB (job)->document)) {
283                         ev_selection_render_selection (EV_SELECTION (EV_JOB (job)->document),
284                                                        job->rc,
285                                                        &(job->selection),
286                                                        &(job->selection_points),
287                                                        NULL,
288                                                        &(job->text), &(job->base));
289                         job->selection_region =
290                                 ev_selection_get_selection_region (EV_SELECTION (EV_JOB (job)->document),
291                                                                    job->rc,
292                                                                    &(job->selection_points));
293                 }
294
295                 EV_JOB (job)->finished = TRUE;
296         }
297
298         ev_document_doc_mutex_unlock ();
299 }
300
301 EvJob *
302 ev_job_thumbnail_new (EvDocument   *document,
303                       gint          page,
304                       int           rotation,
305                       gint          requested_width)
306 {
307         EvJobThumbnail *job;
308
309         job = g_object_new (EV_TYPE_JOB_THUMBNAIL, NULL);
310
311         EV_JOB (job)->document = g_object_ref (document);
312         job->page = page;
313         job->rotation = rotation;
314         job->requested_width = requested_width;
315
316         return EV_JOB (job);
317 }
318
319 void
320 ev_job_thumbnail_run (EvJobThumbnail *job)
321 {
322         g_return_if_fail (EV_IS_JOB_THUMBNAIL (job));
323
324         ev_document_doc_mutex_lock ();
325
326         job->thumbnail =
327                 ev_document_thumbnails_get_thumbnail (EV_DOCUMENT_THUMBNAILS (EV_JOB (job)->document),
328                                                       job->page,
329                                                       job->rotation,
330                                                       job->requested_width,
331                                                       TRUE);
332         EV_JOB (job)->finished = TRUE;
333
334         ev_document_doc_mutex_unlock ();
335 }
336
337 static void ev_job_fonts_init (EvJobFonts *job) { /* Do Nothing */ }
338
339 static void ev_job_fonts_class_init (EvJobFontsClass *class) { /* Do Nothing */ }
340
341 EvJob *
342 ev_job_fonts_new (EvDocument *document)
343 {
344         EvJobFonts *job;
345
346         job = g_object_new (EV_TYPE_JOB_FONTS, NULL);
347
348         EV_JOB (job)->document = g_object_ref (document);
349
350         return EV_JOB (job);
351 }
352
353 void
354 ev_job_fonts_run (EvJobFonts *job)
355 {
356         EvDocumentFonts *fonts;
357
358         g_return_if_fail (EV_IS_JOB_FONTS (job));
359
360         ev_document_doc_mutex_lock ();
361         
362         fonts = EV_DOCUMENT_FONTS (EV_JOB (job)->document);
363         job->scan_completed = !ev_document_fonts_scan (fonts, 20);
364         
365         EV_JOB (job)->finished = TRUE;
366
367         ev_document_doc_mutex_unlock ();
368 }
369
370 static void ev_job_xfer_init (EvJobXfer *job) { /* Do Nothing */ }
371
372 static void
373 ev_job_xfer_dispose (GObject *object)
374 {
375         EvJobXfer *job = EV_JOB_XFER (object);
376
377         if (job->uri) {
378                 g_free (job->uri);
379                 job->uri = NULL;
380         }
381
382         if (job->local_uri) {
383                 g_free (job->local_uri);
384                 job->local_uri = NULL;
385         }
386
387         if (job->error) {
388                 g_error_free (job->error);
389                 job->error = NULL;
390         }
391
392         if (job->dest) {
393                 g_object_unref (job->dest);
394                 job->dest = NULL;
395         }
396
397         (* G_OBJECT_CLASS (ev_job_xfer_parent_class)->dispose) (object);
398 }
399
400 static void
401 ev_job_xfer_class_init (EvJobXferClass *class)
402 {
403         GObjectClass *oclass;
404
405         oclass = G_OBJECT_CLASS (class);
406
407         oclass->dispose = ev_job_xfer_dispose;
408 }
409
410
411 EvJob *
412 ev_job_xfer_new (const gchar *uri, EvLinkDest *dest)
413 {
414         EvJobXfer *job;
415
416         job = g_object_new (EV_TYPE_JOB_XFER, NULL);
417
418         job->uri = g_strdup (uri);
419         if (dest)
420                 job->dest = g_object_ref (dest);
421
422         return EV_JOB (job);
423 }
424
425 void
426 ev_job_xfer_run (EvJobXfer *job)
427 {
428         GnomeVFSURI *source_uri;
429         GnomeVFSURI *target_uri;
430
431         g_return_if_fail (EV_IS_JOB_XFER (job));
432         
433         if (job->error) {
434                 g_error_free (job->error);
435                 job->error = NULL;
436         }
437         
438         /* This job may already have a document even if the job didn't complete
439            because, e.g., a password is required - if so, just reload rather than
440            creating a new instance */
441         if (EV_JOB (job)->document) {
442                 ev_document_load (EV_JOB (job)->document,
443                                   job->local_uri ? job->local_uri : job->uri,
444                                   &job->error);
445                 EV_JOB (job)->finished = TRUE;
446                 return;
447         }
448
449         source_uri = gnome_vfs_uri_new (job->uri);
450         if (!gnome_vfs_uri_is_local (source_uri) && !job->local_uri) {
451                 char *tmp_name;
452                 char *base_name;
453                 
454                 /* We'd like to keep extension of source uri since
455                  * it helps to resolve some mime types, say cbz */
456                 
457                 tmp_name = ev_tmp_filename ();
458                 base_name = gnome_vfs_uri_extract_short_name (source_uri);
459                 job->local_uri = g_strconcat ("file:", tmp_name, "-", base_name, NULL);
460                 g_free (base_name);
461                 g_free (tmp_name);
462                 
463                 target_uri = gnome_vfs_uri_new (job->local_uri);
464
465                 gnome_vfs_xfer_uri (source_uri, target_uri, 
466                                     GNOME_VFS_XFER_DEFAULT | GNOME_VFS_XFER_FOLLOW_LINKS,
467                                     GNOME_VFS_XFER_ERROR_MODE_ABORT,
468                                     GNOME_VFS_XFER_OVERWRITE_MODE_REPLACE,
469                                     NULL,
470                                     job);
471                 gnome_vfs_uri_unref (target_uri);
472         }
473         gnome_vfs_uri_unref (source_uri);
474
475         EV_JOB(job)->document = ev_document_factory_get_document (job->local_uri ? job->local_uri : job->uri, &job->error);
476         EV_JOB (job)->finished = TRUE;
477
478         return;
479 }
480