~ubuntu-branches/ubuntu/oneiric/evince/oneiric-updates

« back to all changes in this revision

Viewing changes to libdocument/ev-document-factory.c

  • Committer: Bazaar Package Importer
  • Author(s): Sebastien Bacher
  • Date: 2007-01-10 19:35:11 UTC
  • mto: (1.3.1 experimental) (52.1.1 hardy-proposed)
  • mto: This revision was merged to the branch mainline in revision 20.
  • Revision ID: james.westby@ubuntu.com-20070110193511-yjrnndv8e8wv03yy
Tags: upstream-0.7.1
Import upstream version 0.7.1

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8; c-indent-level: 8 -*- */
 
2
/*
 
3
 *  Copyright (C) 2005, Red Hat, Inc. 
 
4
 *
 
5
 *  This program is free software; you can redistribute it and/or modify
 
6
 *  it under the terms of the GNU General Public License as published by
 
7
 *  the Free Software Foundation; either version 2, or (at your option)
 
8
 *  any later version.
 
9
 *
 
10
 *  This program is distributed in the hope that it will be useful,
 
11
 *  but WITHOUT ANY WARRANTY; without even the implied warranty of
 
12
 *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 
13
 *  GNU General Public License for more details.
 
14
 *
 
15
 *  You should have received a copy of the GNU General Public License
 
16
 *  along with this program; if not, write to the Free Software
 
17
 *  Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
 
18
 *
 
19
 */
 
20
 
 
21
#ifdef HAVE_CONFIG_H
 
22
#include "config.h"
 
23
#endif
 
24
 
 
25
#include "ev-document-factory.h"
 
26
 
 
27
/* The various document type backends: */
 
28
#ifdef ENABLE_PDF
 
29
#include "ev-poppler.h"
 
30
#endif
 
31
#ifdef ENABLE_PS
 
32
#include "ps-document.h"
 
33
#endif
 
34
#ifdef ENABLE_TIFF
 
35
#include "tiff-document.h"
 
36
#endif
 
37
#ifdef ENABLE_DVI
 
38
#include "dvi-document.h"
 
39
#endif
 
40
#ifdef ENABLE_PIXBUF
 
41
#include "pixbuf-document.h"
 
42
#endif
 
43
#ifdef ENABLE_DJVU
 
44
#include "djvu-document.h"
 
45
#endif
 
46
#ifdef ENABLE_COMICS
 
47
#include "comics-document.h"
 
48
#endif
 
49
#ifdef ENABLE_IMPRESS
 
50
#include "impress-document.h"
 
51
#endif
 
52
 
 
53
#include <string.h>
 
54
#include <glib/gi18n.h>
 
55
#include <libgnomevfs/gnome-vfs-mime-utils.h>
 
56
#include <libgnomevfs/gnome-vfs-file-info.h>
 
57
#include <libgnomevfs/gnome-vfs-ops.h>
 
58
#include <gtk/gtkfilechooserdialog.h>
 
59
 
 
60
typedef struct _EvDocumentType EvDocumentType;
 
61
struct _EvDocumentType
 
62
{
 
63
        const char *mime_type;
 
64
        EvBackend backend;
 
65
        GType (*document_type_factory_callback)();
 
66
};
 
67
 
 
68
const EvDocumentType document_types[] = {
 
69
#ifdef ENABLE_PDF
 
70
        /* PDF: */
 
71
        {"application/pdf",            EV_BACKEND_PDF,  pdf_document_get_type},
 
72
#endif
 
73
 
 
74
#ifdef ENABLE_PS
 
75
        /* Postscript: */
 
76
        {"application/postscript",     EV_BACKEND_PS,   ps_document_get_type},
 
77
        {"application/x-gzpostscript", EV_BACKEND_PS,   ps_document_get_type},
 
78
        {"image/x-eps",                EV_BACKEND_PS,   ps_document_get_type},
 
79
#endif
 
80
 
 
81
#ifdef ENABLE_TIFF
 
82
        /* Tiff: */
 
83
        {"image/tiff",                 EV_BACKEND_TIFF, tiff_document_get_type},
 
84
#endif
 
85
 
 
86
#ifdef ENABLE_DJVU
 
87
        /* djvu: */
 
88
        {"image/vnd.djvu",             EV_BACKEND_DJVU, djvu_document_get_type},
 
89
#endif          
 
90
 
 
91
#ifdef ENABLE_DVI
 
92
        /* dvi: */
 
93
        {"application/x-dvi",          EV_BACKEND_DVI,  dvi_document_get_type},
 
94
#endif
 
95
 
 
96
#ifdef ENABLE_COMICS
 
97
        /* cbr/cbz: */
 
98
        {"application/x-cbr",           EV_BACKEND_COMICS,  comics_document_get_type},
 
99
        {"application/x-cbz",           EV_BACKEND_COMICS,  comics_document_get_type},
 
100
#endif
 
101
 
 
102
#ifdef ENABLE_IMPRESS
 
103
        /* Impress slides: */
 
104
        {"application/vnd.sun.xml.impress", EV_BACKEND_IMPRESS, impress_document_get_type},
 
105
        {"application/vnd.oasis.opendocument.presentation", EV_BACKEND_IMPRESS, impress_document_get_type},
 
106
#endif
 
107
 
 
108
};
 
109
 
 
110
#ifdef ENABLE_PIXBUF
 
111
 
 
112
static GList*
 
113
gdk_pixbuf_mime_type_list ()
 
114
{
 
115
        GSList *formats, *list;
 
116
        GList *result;
 
117
 
 
118
        formats = gdk_pixbuf_get_formats ();
 
119
        result = NULL;
 
120
 
 
121
        for (list = formats; list != NULL; list = list->next) {
 
122
                GdkPixbufFormat *format = list->data;
 
123
                int i;
 
124
                gchar **mime_types;
 
125
 
 
126
                if (gdk_pixbuf_format_is_disabled (format))
 
127
                        continue;
 
128
 
 
129
                mime_types = gdk_pixbuf_format_get_mime_types (format);
 
130
 
 
131
                for (i = 0; mime_types[i] != NULL; i++) {
 
132
                        result = g_list_append (result, mime_types[i]);
 
133
                }
 
134
        }
 
135
        g_slist_free (formats);
 
136
 
 
137
        return result;
 
138
}
 
139
 
 
140
/* Would be nice to have this in gdk-pixbuf */
 
141
static gboolean
 
142
mime_type_supported_by_gdk_pixbuf (const gchar *mime_type)
 
143
{
 
144
        GList *mime_types;
 
145
        GList *list;
 
146
        gboolean retval = FALSE;
 
147
        
 
148
        mime_types = gdk_pixbuf_mime_type_list ();
 
149
        for (list = mime_types; list; list = list->next) {
 
150
                if (strcmp ((char *)list->data, mime_type) == 0) {
 
151
                        retval = TRUE;
 
152
                        break;
 
153
                }
 
154
        }
 
155
        
 
156
        g_list_foreach (mime_types, (GFunc)g_free, NULL);
 
157
        g_list_free (mime_types);
 
158
 
 
159
        return retval;
 
160
}
 
161
#endif
 
162
 
 
163
static EvDocument*
 
164
ev_document_factory_get_from_mime (const char *mime_type)
 
165
{
 
166
        int i;
 
167
        GType type = G_TYPE_INVALID;
 
168
        EvDocument *document = NULL;
 
169
        
 
170
        g_return_val_if_fail (mime_type, G_TYPE_INVALID);
 
171
 
 
172
        for (i = 0; i < G_N_ELEMENTS (document_types); i++) {
 
173
                if (strcmp (mime_type, document_types[i].mime_type) == 0) {
 
174
                        g_assert (document_types[i].document_type_factory_callback != NULL);
 
175
                        type = document_types[i].document_type_factory_callback();
 
176
                        break;
 
177
                }
 
178
        }
 
179
#ifdef ENABLE_PIXBUF
 
180
        if (type == G_TYPE_INVALID && mime_type_supported_by_gdk_pixbuf (mime_type)) {
 
181
                type = pixbuf_document_get_type ();
 
182
        }
 
183
#endif
 
184
        if (type != G_TYPE_INVALID) {
 
185
                document = g_object_new (type, NULL);
 
186
        } 
 
187
 
 
188
        return document;
 
189
}
 
190
 
 
191
EvBackend
 
192
ev_document_factory_get_backend (EvDocument *document)
 
193
{
 
194
        int i;
 
195
 
 
196
        for (i = 0; i < G_N_ELEMENTS (document_types); i++) {
 
197
                GType type = document_types[i].document_type_factory_callback ();
 
198
                if (type == G_TYPE_FROM_INSTANCE (document)) {
 
199
                        return  document_types[i].backend;
 
200
                }
 
201
        }
 
202
 
 
203
#ifdef ENABLE_PIXBUF
 
204
        if (G_TYPE_FROM_INSTANCE (document) == pixbuf_document_get_type ())
 
205
                return EV_BACKEND_PIXBUF;
 
206
#endif
 
207
        g_assert_not_reached ();
 
208
        
 
209
        return 0;
 
210
}
 
211
 
 
212
static GList *
 
213
ev_document_factory_get_mime_types (EvBackend backend)
 
214
{
 
215
        GList *types = NULL;
 
216
        int i;
 
217
        
 
218
#ifdef ENABLE_PIXBUF
 
219
        if (backend == EV_BACKEND_PIXBUF) {
 
220
                return gdk_pixbuf_mime_type_list ();
 
221
        }
 
222
#endif
 
223
        
 
224
        for (i = 0; i < G_N_ELEMENTS (document_types); i++) {
 
225
                if (document_types[i].backend == backend) {
 
226
                        types = g_list_append (types, g_strdup (document_types[i].mime_type));
 
227
                }
 
228
        }
 
229
 
 
230
        return types;
 
231
}
 
232
 
 
233
static GList *
 
234
ev_document_factory_get_all_mime_types (void)
 
235
{
 
236
        GList *types = NULL;
 
237
        int i;
 
238
        
 
239
        for (i = 0; i < G_N_ELEMENTS (document_types); i++) {
 
240
                types = g_list_append (types, g_strdup (document_types[i].mime_type));
 
241
        }
 
242
        
 
243
#ifdef ENABLE_PIXBUF
 
244
        types = g_list_concat (types, gdk_pixbuf_mime_type_list ());
 
245
#endif
 
246
 
 
247
        return types;
 
248
}
 
249
 
 
250
static EvDocument *
 
251
get_document_from_uri (const char *uri, gboolean slow, GError **error)
 
252
{
 
253
        EvDocument *document = NULL;
 
254
 
 
255
        GnomeVFSFileInfo *info;
 
256
        GnomeVFSResult result;
 
257
 
 
258
        info = gnome_vfs_file_info_new ();
 
259
        result = gnome_vfs_get_file_info (uri, info,
 
260
                                          GNOME_VFS_FILE_INFO_GET_MIME_TYPE |
 
261
                                          GNOME_VFS_FILE_INFO_FOLLOW_LINKS | 
 
262
                                          (slow ? GNOME_VFS_FILE_INFO_FORCE_SLOW_MIME_TYPE : 0));
 
263
        if (result != GNOME_VFS_OK) {
 
264
                g_set_error (error,
 
265
                             EV_DOCUMENT_ERROR,
 
266
                             0,
 
267
                             gnome_vfs_result_to_string (result));                      
 
268
                gnome_vfs_file_info_unref (info);
 
269
                return NULL;
 
270
        } 
 
271
        
 
272
        if (info->mime_type == NULL) {
 
273
                g_set_error (error,
 
274
                             EV_DOCUMENT_ERROR, 
 
275
                             0,
 
276
                             _("Unknown MIME Type"));
 
277
                gnome_vfs_file_info_unref (info);
 
278
                return NULL;
 
279
        }
 
280
 
 
281
        document = ev_document_factory_get_from_mime (info->mime_type);
 
282
                
 
283
        if (document == NULL) {
 
284
                g_set_error (error,
 
285
                             EV_DOCUMENT_ERROR, 
 
286
                             0,
 
287
                             _("Unhandled MIME type: “%s”"), info->mime_type);
 
288
                gnome_vfs_file_info_unref (info);
 
289
                return NULL;
 
290
        }                       
 
291
 
 
292
        gnome_vfs_file_info_unref (info);
 
293
        
 
294
        return document;
 
295
}
 
296
 
 
297
EvDocument *
 
298
ev_document_factory_get_document (const char *uri, GError **error)
 
299
{
 
300
        EvDocument *document;
 
301
        int result;
 
302
 
 
303
        document = get_document_from_uri (uri, FALSE, error);
 
304
 
 
305
        if (*error == NULL) {
 
306
                result = ev_document_load (document, uri, error);
 
307
 
 
308
                if (result == FALSE || *error) {
 
309
                        if (*error &&
 
310
                            (*error)->domain == EV_DOCUMENT_ERROR &&
 
311
                            (*error)->code == EV_DOCUMENT_ERROR_ENCRYPTED)
 
312
                                return document;
 
313
                } else {
 
314
                        return document;
 
315
                }
 
316
        }
 
317
        
 
318
        /* Try again with slow mime detection */
 
319
        if (document)
 
320
                g_object_unref (document);
 
321
        document = NULL;
 
322
 
 
323
        if (*error)
 
324
                g_error_free (*error);
 
325
        *error = NULL;
 
326
 
 
327
        document = get_document_from_uri (uri, TRUE, error);
 
328
 
 
329
        if (*error != NULL) {
 
330
                return NULL;
 
331
        }
 
332
 
 
333
        result = ev_document_load (document, uri, error);
 
334
 
 
335
        if (result == FALSE) {
 
336
                if (*error == NULL) {
 
337
                        g_set_error (error,
 
338
                                     EV_DOCUMENT_ERROR,
 
339
                                     0,
 
340
                                     _("Unknown MIME Type"));
 
341
                } else if ((*error)->domain == EV_DOCUMENT_ERROR &&
 
342
                           (*error)->code == EV_DOCUMENT_ERROR_ENCRYPTED) {
 
343
                        return document;
 
344
                }
 
345
 
 
346
                if (document)
 
347
                        g_object_unref (document);
 
348
                document = NULL;
 
349
        }
 
350
        
 
351
        return document;
 
352
}
 
353
 
 
354
static void
 
355
file_filter_add_mime_list_and_free (GtkFileFilter *filter, GList *mime_types)
 
356
{
 
357
        GList *l;
 
358
 
 
359
        for (l = mime_types; l != NULL; l = l->next) {
 
360
                gtk_file_filter_add_mime_type (filter, l->data);
 
361
        }
 
362
 
 
363
        g_list_foreach (mime_types, (GFunc)g_free, NULL);
 
364
        g_list_free (mime_types);
 
365
}
 
366
 
 
367
void 
 
368
ev_document_factory_add_filters (GtkWidget *chooser, EvDocument *document)
 
369
{
 
370
        EvBackend backend = 0;
 
371
        GList *mime_types;
 
372
        GtkFileFilter *filter;
 
373
        GtkFileFilter *default_filter;
 
374
        GtkFileFilter *document_filter;
 
375
 
 
376
        if (document != NULL) {
 
377
                backend = ev_document_factory_get_backend (document);
 
378
        }
 
379
 
 
380
        default_filter = document_filter = filter = gtk_file_filter_new ();
 
381
        gtk_file_filter_set_name (filter, _("All Documents"));
 
382
        mime_types = ev_document_factory_get_all_mime_types ();
 
383
        file_filter_add_mime_list_and_free (filter, mime_types);
 
384
        gtk_file_chooser_add_filter (GTK_FILE_CHOOSER (chooser), filter);
 
385
 
 
386
#ifdef ENABLE_PS
 
387
        if (document == NULL || backend == EV_BACKEND_PS) {
 
388
                default_filter = filter = gtk_file_filter_new ();
 
389
                gtk_file_filter_set_name (filter, _("PostScript Documents"));
 
390
                mime_types = ev_document_factory_get_mime_types (EV_BACKEND_PS);
 
391
                file_filter_add_mime_list_and_free (filter, mime_types);
 
392
                gtk_file_chooser_add_filter (GTK_FILE_CHOOSER (chooser), filter);
 
393
        }
 
394
#endif
 
395
 
 
396
#ifdef ENABLE_PDF
 
397
        if (document == NULL || backend == EV_BACKEND_PDF) {
 
398
                default_filter = filter = gtk_file_filter_new ();
 
399
                gtk_file_filter_set_name (filter, _("PDF Documents"));
 
400
                mime_types = ev_document_factory_get_mime_types (EV_BACKEND_PDF);
 
401
                file_filter_add_mime_list_and_free (filter, mime_types);
 
402
                gtk_file_chooser_add_filter (GTK_FILE_CHOOSER (chooser), filter);
 
403
        }
 
404
#endif
 
405
 
 
406
#ifdef ENABLE_PIXBUF
 
407
        if (document == NULL || backend == EV_BACKEND_PIXBUF) {
 
408
                default_filter = filter = gtk_file_filter_new ();
 
409
                gtk_file_filter_set_name (filter, _("Images"));
 
410
                mime_types = ev_document_factory_get_mime_types (EV_BACKEND_PIXBUF);
 
411
                file_filter_add_mime_list_and_free (filter, mime_types);
 
412
                gtk_file_chooser_add_filter (GTK_FILE_CHOOSER (chooser), filter);
 
413
        }
 
414
#endif
 
415
 
 
416
#ifdef ENABLE_DVI
 
417
        if (document == NULL || backend == EV_BACKEND_DVI) {
 
418
                default_filter = filter = gtk_file_filter_new ();
 
419
                gtk_file_filter_set_name (filter, _("DVI Documents"));
 
420
                mime_types = ev_document_factory_get_mime_types (EV_BACKEND_DVI);
 
421
                file_filter_add_mime_list_and_free (filter, mime_types);
 
422
                gtk_file_chooser_add_filter (GTK_FILE_CHOOSER (chooser), filter);
 
423
        }
 
424
#endif
 
425
 
 
426
#ifdef ENABLE_DJVU
 
427
        if (document == NULL || backend == EV_BACKEND_DJVU) {
 
428
                default_filter = filter = gtk_file_filter_new ();
 
429
                gtk_file_filter_set_name (filter, _("Djvu Documents"));
 
430
                mime_types = ev_document_factory_get_mime_types (EV_BACKEND_DJVU);
 
431
                file_filter_add_mime_list_and_free (filter, mime_types);
 
432
                gtk_file_chooser_add_filter (GTK_FILE_CHOOSER (chooser), filter);
 
433
        }
 
434
#endif  
 
435
 
 
436
#ifdef ENABLE_COMICS
 
437
        if (document == NULL || backend == EV_BACKEND_COMICS) {
 
438
                default_filter = filter = gtk_file_filter_new ();
 
439
                gtk_file_filter_set_name (filter, _("Comic Books"));
 
440
                mime_types = ev_document_factory_get_mime_types (EV_BACKEND_COMICS);
 
441
                file_filter_add_mime_list_and_free (filter, mime_types);
 
442
                gtk_file_chooser_add_filter (GTK_FILE_CHOOSER (chooser), filter);
 
443
        }
 
444
#endif  
 
445
 
 
446
#ifdef ENABLE_IMPRESS
 
447
        if (document == NULL || backend == EV_BACKEND_IMPRESS) {
 
448
                default_filter = filter = gtk_file_filter_new ();
 
449
                gtk_file_filter_set_name (filter, _("Impress Slides"));
 
450
                mime_types = ev_document_factory_get_mime_types (EV_BACKEND_IMPRESS);
 
451
                file_filter_add_mime_list_and_free (filter, mime_types);
 
452
                gtk_file_chooser_add_filter (GTK_FILE_CHOOSER (chooser), filter);
 
453
        }
 
454
#endif  
 
455
 
 
456
        filter = gtk_file_filter_new ();
 
457
        gtk_file_filter_set_name (filter, _("All Files"));
 
458
        gtk_file_filter_add_pattern (filter, "*");
 
459
        gtk_file_chooser_add_filter (GTK_FILE_CHOOSER (chooser), filter);
 
460
 
 
461
        gtk_file_chooser_set_filter (GTK_FILE_CHOOSER (chooser),
 
462
                                     document == NULL ? document_filter : default_filter);
 
463
}