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-document-factory.c File Reference
#include <string.h>
#include <gio/gio.h>
#include <glib/gstdio.h>
#include <glib/gi18n-lib.h>
#include <gtk/gtk.h>
#include "ev-backend-info.h"
#include "ev-document-factory.h"
#include "ev-file-helpers.h"
#include "ev-module.h"
#include "ev-backends-manager.h"
+ Include dependency graph for ev-document-factory.c:

Go to the source code of this file.

Macros

#define BACKEND_DATA_KEY   "ev-backend-info"
 

Functions

static EvDocumentev_document_factory_new_document_for_mime_type (const char *mime_type, GError **error)
 
static EvBackendInfoget_backend_info_for_mime_type (const gchar *mime_type)
 
static EvBackendInfoget_backend_info_for_document (EvDocument *document)
 
static EvDocumentev_document_factory_new_document_for_mime_type (const gchar *mime_type, GError **error)
 
static EvCompressionType get_compression_from_mime_type (const gchar *mime_type)
 
static EvDocumentnew_document_for_uri (const char *uri, gboolean fast, EvCompressionType *compression, GError **error)
 
static void free_uncompressed_uri (gchar *uri_unc)
 
gboolean _ev_document_factory_init (void)
 
void _ev_document_factory_shutdown (void)
 
EvDocumentev_document_factory_get_document_full (const char *uri, EvDocumentLoadFlags flags, GError **error)
 
EvDocumentev_document_factory_get_document (const char *uri, GError **error)
 
EvDocumentev_document_factory_get_document_for_gfile (GFile *file, EvDocumentLoadFlags flags, GCancellable *cancellable, GError **error)
 
EvDocumentev_document_factory_get_document_for_stream (GInputStream *stream, const char *mime_type, EvDocumentLoadFlags flags, GCancellable *cancellable, GError **error)
 
static void file_filter_add_mime_types (EvBackendInfo *info, GtkFileFilter *filter)
 
void ev_document_factory_add_filters (GtkWidget *chooser, EvDocument *document)
 
EvDocumentev_backends_manager_get_document (const gchar *mime_type)
 
const gchar * ev_backends_manager_get_document_module_name (EvDocument *document)
 
EvTypeInfoev_backends_manager_get_document_type_info (EvDocument *document)
 
GList * ev_backends_manager_get_all_types_info (void)
 

Variables

static GList * ev_backends_list = NULL
 
static GHashTable * ev_module_hash = NULL
 
static gchar * ev_backends_dir = NULL
 

Macro Definition Documentation

#define BACKEND_DATA_KEY   "ev-backend-info"

Definition at line 41 of file ev-document-factory.c.

Function Documentation

gboolean _ev_document_factory_init ( void  )

Definition at line 227 of file ev-document-factory.c.

228 {
229  if (ev_backends_list)
230  return TRUE;
231 
232 #ifdef G_OS_WIN32
233 {
234  gchar *dir;
235 
236  dir = g_win32_get_package_installation_directory_of_module (NULL);
237  ev_backends_dir = g_build_filename (dir, "lib", "evince",
238  EV_BACKENDSBINARYVERSION,
239  "backends", NULL);
240  g_free (dir);
241 }
242 #else
243  ev_backends_dir = g_strdup (EV_BACKENDSDIR);
244 #endif
245 
247 
248  return ev_backends_list != NULL;
249 }

+ Here is the caller graph for this function:

void _ev_document_factory_shutdown ( void  )

Definition at line 257 of file ev-document-factory.c.

258 {
259  g_list_foreach (ev_backends_list, (GFunc) _ev_backend_info_unref, NULL);
260  g_list_free (ev_backends_list);
261  ev_backends_list = NULL;
262 
263  if (ev_module_hash != NULL) {
264  g_hash_table_unref (ev_module_hash);
265  ev_module_hash = NULL;
266  }
267 
268  g_free (ev_backends_dir);
269  ev_backends_dir = NULL;
270 }

+ Here is the caller graph for this function:

GList* ev_backends_manager_get_all_types_info ( void  )

Definition at line 641 of file ev-document-factory.c.

642 {
643  return g_list_copy (ev_backends_list);
644 }

+ Here is the caller graph for this function:

EvDocument* ev_backends_manager_get_document ( const gchar *  mime_type)

ev_backends_manager_get_document: : a mime type hint

Returns: (transfer full): a new EvDocument

Definition at line 620 of file ev-document-factory.c.

621 {
622  return ev_document_factory_new_document_for_mime_type (mime_type, NULL);
623 }

+ Here is the caller graph for this function:

const gchar* ev_backends_manager_get_document_module_name ( EvDocument document)

Definition at line 626 of file ev-document-factory.c.

627 {
628  EvBackendInfo *info = get_backend_info_for_document (document);
629  if (info == NULL)
630  return NULL;
631 
632  return info->module_name;
633 }
EvTypeInfo* ev_backends_manager_get_document_type_info ( EvDocument document)

Definition at line 635 of file ev-document-factory.c.

636 {
637  return (EvTypeInfo *) get_backend_info_for_document (document);
638 }
void ev_document_factory_add_filters ( GtkWidget *  chooser,
EvDocument document 
)

ev_document_factory_add_filters: : a #GtkFileChooser : a EvDocument, or NULL

Adds some file filters to .

Always add a "All documents" format.

If is not NULL, adds a #GtkFileFilter for 's MIME type.

If is NULL, adds a #GtkFileFilter for each document type that evince can handle.

Definition at line 567 of file ev-document-factory.c.

568 {
569  GtkFileFilter *filter;
570  GtkFileFilter *default_filter;
571  GtkFileFilter *document_filter;
572 
573  g_return_if_fail (GTK_IS_FILE_CHOOSER (chooser));
574  g_return_if_fail (document == NULL || EV_IS_DOCUMENT (document));
575 
576  default_filter = document_filter = filter = gtk_file_filter_new ();
577  gtk_file_filter_set_name (filter, _("All Documents"));
578  g_list_foreach (ev_backends_list, (GFunc)file_filter_add_mime_types, filter);
579  gtk_file_chooser_add_filter (GTK_FILE_CHOOSER (chooser), filter);
580 
581  if (document) {
582  EvBackendInfo *info;
583 
584  info = get_backend_info_for_document (document);
585  g_assert (info != NULL);
586  default_filter = filter = gtk_file_filter_new ();
587  gtk_file_filter_set_name (filter, info->type_desc);
588  file_filter_add_mime_types (info, filter);
589  gtk_file_chooser_add_filter (GTK_FILE_CHOOSER (chooser), filter);
590  } else {
591  GList *l;
592 
593  for (l = ev_backends_list; l; l = l->next) {
594  EvBackendInfo *info = (EvBackendInfo *) l->data;
595 
596  default_filter = filter = gtk_file_filter_new ();
597  gtk_file_filter_set_name (filter, info->type_desc);
598  file_filter_add_mime_types (info, filter);
599  gtk_file_chooser_add_filter (GTK_FILE_CHOOSER (chooser), filter);
600  }
601  }
602 
603  filter = gtk_file_filter_new ();
604  gtk_file_filter_set_name (filter, _("All Files"));
605  gtk_file_filter_add_pattern (filter, "*");
606  gtk_file_chooser_add_filter (GTK_FILE_CHOOSER (chooser), filter);
607 
608  gtk_file_chooser_set_filter (GTK_FILE_CHOOSER (chooser),
609  document == NULL ? document_filter : default_filter);
610 }

+ Here is the caller graph for this function:

EvDocument* ev_document_factory_get_document ( const char *  uri,
GError **  error 
)

ev_document_factory_get_document: : an URI : a #GError location to store an error, or NULL

Creates a EvDocument for the document at ; or, if no backend handling the document's type is found, or an error occurred on opening the document, returns NULL and fills in . If the document is encrypted, it is returned but also is set to EV_DOCUMENT_ERROR_ENCRYPTED.

Returns: (transfer full): a new EvDocument, or NULL

Definition at line 397 of file ev-document-factory.c.

398 {
401  error);
402 }

+ Here is the caller graph for this function:

EvDocument* ev_document_factory_get_document_for_gfile ( GFile *  file,
EvDocumentLoadFlags  flags,
GCancellable *  cancellable,
GError **  error 
)

Definition at line 422 of file ev-document-factory.c.

426 {
427  EvDocument *document;
428  GFileInfo *file_info;
429  const char *content_type;
430  char *mime_type = NULL;
431 
432  g_return_val_if_fail (G_IS_FILE (file), NULL);
433  g_return_val_if_fail (error == NULL || *error == NULL, NULL);
434 
435 
436  file_info = g_file_query_info (file,
437  G_FILE_ATTRIBUTE_STANDARD_CONTENT_TYPE,
438  G_FILE_QUERY_INFO_NONE,
439  cancellable,
440  error);
441  if (file_info == NULL)
442  return NULL;
443 
444  content_type = g_file_info_get_content_type (file_info);
445  if (content_type == NULL) {
446  g_set_error_literal (error, G_IO_ERROR, G_IO_ERROR_FAILED,
447  "Failed to query file mime type");
448  return NULL;
449  }
450 
451  mime_type = g_content_type_get_mime_type (content_type);
452  g_object_unref (file_info);
453 
454  document = ev_document_factory_new_document_for_mime_type (mime_type, error);
455  g_free (mime_type);
456  if (document == NULL)
457  return NULL;
458 
459  if (!ev_document_load_gfile (document, file, flags, cancellable, error)) {
460  g_object_unref (document);
461  return NULL;
462  }
463 
464  return document;
465 }

+ Here is the caller graph for this function:

EvDocument* ev_document_factory_get_document_for_stream ( GInputStream *  stream,
const char *  mime_type,
EvDocumentLoadFlags  flags,
GCancellable *  cancellable,
GError **  error 
)

ev_document_factory_get_document_for_stream: : a #GInputStream : (allow-none): a mime type hint : flags from EvDocumentLoadFlags : (allow-none): a #GCancellable, or NULL : (allow-none): a #GError location to store an error, or NULL

Synchronously creates a EvDocument for the document from ; or, if no backend handling the document's type is found, or an error occurred on opening the document, returns NULL and fills in . If the document is encrypted, it is returned but also is set to EV_DOCUMENT_ERROR_ENCRYPTED.

If is non-NULL, this overrides any type inferred from the stream. If the mime type cannot be inferred from the stream, and is NULL, an error is returned.

Returns: (transfer full): a new EvDocument, or NULL

Since: 3.6

Definition at line 490 of file ev-document-factory.c.

495 {
496  EvDocument *document;
497  char *mime = NULL;
498 
499  g_return_val_if_fail (G_IS_INPUT_STREAM (stream), NULL);
500  g_return_val_if_fail (error == NULL || *error == NULL, NULL);
501 
502  if (mime_type == NULL && G_IS_FILE_INPUT_STREAM (stream)) {
503  GFileInfo *file_info;
504  const char *content_type;
505 
506  file_info = g_file_input_stream_query_info (G_FILE_INPUT_STREAM (stream),
507  G_FILE_ATTRIBUTE_STANDARD_CONTENT_TYPE,
508  cancellable,
509  error);
510  if (file_info != NULL) {
511  content_type = g_file_info_get_content_type (file_info);
512  if (content_type)
513  mime_type = mime = g_content_type_get_mime_type (content_type);
514  g_object_unref (file_info);
515  }
516  }
517 
518  if (mime_type == NULL) {
519  g_set_error_literal (error, G_IO_ERROR, G_IO_ERROR_NOT_SUPPORTED,
520  "Cannot query mime type from stream");
521  return NULL;
522  }
523 
524  document = ev_document_factory_new_document_for_mime_type (mime_type, error);
525  g_free (mime);
526 
527  if (document == NULL)
528  return NULL;
529 
530  if (!ev_document_load_stream (document, stream, flags, cancellable, error)) {
531  g_object_unref (document);
532  return NULL;
533  }
534 
535  return document;
536 }

+ Here is the caller graph for this function:

EvDocument* ev_document_factory_get_document_full ( const char *  uri,
EvDocumentLoadFlags  flags,
GError **  error 
)

ev_document_factory_get_document_full: : an URI : flags from EvDocumentLoadFlags : a #GError location to store an error, or NULL

Creates a EvDocument for the document at ; or, if no backend handling the document's type is found, or an error occurred on opening the document, returns NULL and fills in . If the document is encrypted, it is returned but also is set to EV_DOCUMENT_ERROR_ENCRYPTED.

Returns: (transfer full): a new EvDocument, or NULL

Definition at line 287 of file ev-document-factory.c.

290 {
291  EvDocument *document;
292  int result;
293  EvCompressionType compression;
294  gchar *uri_unc = NULL;
295  GError *err = NULL;
296 
297  g_return_val_if_fail (uri != NULL, NULL);
298 
299  document = new_document_for_uri (uri, TRUE, &compression, &err);
300  g_assert (document != NULL || err != NULL);
301 
302  if (document != NULL) {
303  uri_unc = ev_file_uncompress (uri, compression, &err);
304  if (uri_unc) {
305  g_object_set_data_full (G_OBJECT (document),
306  "uri-uncompressed",
307  uri_unc,
308  (GDestroyNotify) free_uncompressed_uri);
309  } else if (err != NULL) {
310  /* Error uncompressing file */
311  g_object_unref (document);
312  g_propagate_error (error, err);
313  return NULL;
314  }
315 
316  result = ev_document_load_full (document, uri_unc ? uri_unc : uri, flags, &err);
317 
318  if (result == FALSE || err) {
319  if (err &&
320  g_error_matches (err, EV_DOCUMENT_ERROR, EV_DOCUMENT_ERROR_ENCRYPTED)) {
321  g_propagate_error (error, err);
322  return document;
323  }
324  /* else fall through to slow mime code section below */
325  } else {
326  return document;
327  }
328 
329  g_object_unref (document);
330  document = NULL;
331  }
332 
333  /* Try again with slow mime detection */
334  g_clear_error (&err);
335  uri_unc = NULL;
336 
337  document = new_document_for_uri (uri, FALSE, &compression, &err);
338  if (document == NULL) {
339  g_assert (err != NULL);
340  g_propagate_error (error, err);
341  return NULL;
342  }
343 
344  uri_unc = ev_file_uncompress (uri, compression, &err);
345  if (uri_unc) {
346  g_object_set_data_full (G_OBJECT (document),
347  "uri-uncompressed",
348  uri_unc,
349  (GDestroyNotify) free_uncompressed_uri);
350  } else if (err != NULL) {
351  /* Error uncompressing file */
352  g_propagate_error (error, err);
353 
354  g_object_unref (document);
355  return NULL;
356  }
357 
358  result = ev_document_load_full (document, uri_unc ? uri_unc : uri,
360  if (result == FALSE) {
361  if (err == NULL) {
362  /* FIXME: this really should not happen; the backend should
363  * always return a meaningful error.
364  */
365  g_set_error_literal (&err,
368  _("Unknown MIME Type"));
369  } else if (g_error_matches (err, EV_DOCUMENT_ERROR, EV_DOCUMENT_ERROR_ENCRYPTED)) {
370  g_propagate_error (error, err);
371  return document;
372  }
373 
374  g_object_unref (document);
375  document = NULL;
376 
377  g_propagate_error (error, err);
378  }
379 
380  return document;
381 }

+ Here is the caller graph for this function:

static EvDocument* ev_document_factory_new_document_for_mime_type ( const char *  mime_type,
GError **  error 
)
static

+ Here is the caller graph for this function:

static EvDocument* ev_document_factory_new_document_for_mime_type ( const gchar *  mime_type,
GError **  error 
)
static

Definition at line 81 of file ev-document-factory.c.

83 {
84  EvDocument *document;
85  EvBackendInfo *info;
86  GTypeModule *module = NULL;
87 
88  g_return_val_if_fail (mime_type != NULL, NULL);
89 
90  info = get_backend_info_for_mime_type (mime_type);
91  if (info == NULL) {
92  char *content_type, *mime_desc = NULL;
93 
94  content_type = g_content_type_from_mime_type (mime_type);
95  if (content_type)
96  mime_desc = g_content_type_get_description (content_type);
97 
98  g_set_error (error,
101  _("File type %s (%s) is not supported"),
102  mime_desc ? mime_desc : "(unknown)", mime_type);
103  g_free (mime_desc);
104  g_free (content_type);
105 
106  return NULL;
107  }
108 
109  if (ev_module_hash != NULL) {
110  module = g_hash_table_lookup (ev_module_hash, info->module_name);
111  }
112  if (module == NULL) {
113  gchar *path;
114 
115  path = g_module_build_path (ev_backends_dir, info->module_name);
116  module = G_TYPE_MODULE (_ev_module_new (path, info->resident));
117  g_free (path);
118 
119  if (ev_module_hash == NULL) {
120  ev_module_hash = g_hash_table_new_full (g_str_hash, g_str_equal,
121  g_free,
122  NULL /* leaked on purpose */);
123  }
124  g_hash_table_insert (ev_module_hash, g_strdup (info->module_name), module);
125  }
126 
127  if (!g_type_module_use (module)) {
128  const char *err;
129 
130  err = g_module_error ();
131  g_set_error (error, EV_DOCUMENT_ERROR, EV_DOCUMENT_ERROR_INVALID,
132  "Failed to load backend for '%s': %s",
133  mime_type, err ? err : "unknown error");
134  return NULL;
135  }
136 
137  document = EV_DOCUMENT (_ev_module_new_object (EV_MODULE (module)));
138  g_type_module_unuse (module);
139 
140  g_object_set_data_full (G_OBJECT (document), BACKEND_DATA_KEY,
141  _ev_backend_info_ref (info),
142  (GDestroyNotify) _ev_backend_info_unref);
143 
144  return document;
145 }
static void file_filter_add_mime_types ( EvBackendInfo info,
GtkFileFilter *  filter 
)
static

Definition at line 539 of file ev-document-factory.c.

540 {
541  char **mime_types;
542  guint i;
543 
544  mime_types = info->mime_types;
545  if (mime_types == NULL)
546  return;
547 
548  for (i = 0; mime_types[i] != NULL; ++i)
549  gtk_file_filter_add_mime_type (filter, mime_types[i]);
550 }

+ Here is the caller graph for this function:

static void free_uncompressed_uri ( gchar *  uri_unc)
static

Definition at line 210 of file ev-document-factory.c.

211 {
212  if (!uri_unc)
213  return;
214 
215  ev_tmp_uri_unlink (uri_unc);
216  g_free (uri_unc);
217 }

+ Here is the caller graph for this function:

static EvBackendInfo* get_backend_info_for_document ( EvDocument document)
static

Definition at line 70 of file ev-document-factory.c.

71 {
72  EvBackendInfo *info;
73 
74  info = g_object_get_data (G_OBJECT (document), BACKEND_DATA_KEY);
75 
76  g_warn_if_fail (info != NULL);
77  return info;
78 }

+ Here is the caller graph for this function:

static EvBackendInfo* get_backend_info_for_mime_type ( const gchar *  mime_type)
static

Definition at line 51 of file ev-document-factory.c.

52 {
53  GList *l;
54 
55  for (l = ev_backends_list; l; l = l->next) {
56  EvBackendInfo *info = (EvBackendInfo *) l->data;
57  char **mime_types = info->mime_types;
58  guint i;
59 
60  for (i = 0; mime_types[i] != NULL; ++i) {
61  if (g_ascii_strcasecmp (mime_type, mime_types[i]) == 0)
62  return info;
63  }
64  }
65 
66  return NULL;
67 }

+ Here is the caller graph for this function:

static EvCompressionType get_compression_from_mime_type ( const gchar *  mime_type)
static

Definition at line 148 of file ev-document-factory.c.

149 {
150  gchar type[3];
151  gchar *p;
152 
153  if (!(p = g_strrstr (mime_type, "/")))
154  return EV_COMPRESSION_NONE;
155 
156  if (sscanf (++p, "x-%2s%*s", type) == 1) {
157  if (g_ascii_strcasecmp (type, "gz") == 0)
158  return EV_COMPRESSION_GZIP;
159  else if (g_ascii_strcasecmp (type, "bz") == 0)
160  return EV_COMPRESSION_BZIP2;
161  else if (g_ascii_strcasecmp (type, "xz") == 0)
162  return EV_COMPRESSION_LZMA;
163  }
164 
165  return EV_COMPRESSION_NONE;
166 }

+ Here is the caller graph for this function:

static EvDocument* new_document_for_uri ( const char *  uri,
gboolean  fast,
EvCompressionType compression,
GError **  error 
)
static

Definition at line 184 of file ev-document-factory.c.

188 {
189  EvDocument *document = NULL;
190  gchar *mime_type = NULL;
191 
192  *compression = EV_COMPRESSION_NONE;
193 
194  mime_type = ev_file_get_mime_type (uri, fast, error);
195  if (mime_type == NULL)
196  return NULL;
197 
198  document = ev_document_factory_new_document_for_mime_type (mime_type, error);
199  if (document == NULL)
200  return NULL;
201 
202  *compression = get_compression_from_mime_type (mime_type);
203 
204  g_free (mime_type);
205 
206  return document;
207 }

+ Here is the caller graph for this function:

Variable Documentation

gchar* ev_backends_dir = NULL
static

Definition at line 45 of file ev-document-factory.c.

GList* ev_backends_list = NULL
static

Definition at line 43 of file ev-document-factory.c.

GHashTable* ev_module_hash = NULL
static

Definition at line 44 of file ev-document-factory.c.