[evince/wip/bug654832: 10/13] libdocument: Add API to load EvDocument from GIO stream and file
- From: Christian Persch <chpe src gnome org>
- To: commits-list gnome org
- Cc:
- Subject: [evince/wip/bug654832: 10/13] libdocument: Add API to load EvDocument from GIO stream and file
- Date: Sun, 3 Jun 2012 16:57:16 +0000 (UTC)
commit 4d9b997c2575c0e671bdc3cf1c753eff613c1f9d
Author: Christian Persch <chpe gnome org>
Date: Wed May 9 19:22:47 2012 +0200
libdocument: Add API to load EvDocument from GIO stream and file
Part of bug #654832.
.../libdocument/libevdocument-sections.txt | 4 +
libdocument/ev-document-factory.c | 134 ++++++++++
libdocument/ev-document-factory.h | 10 +
libdocument/ev-document.c | 256 ++++++++++++++------
libdocument/ev-document.h | 27 ++
5 files changed, 351 insertions(+), 80 deletions(-)
---
diff --git a/help/reference/libdocument/libevdocument-sections.txt b/help/reference/libdocument/libevdocument-sections.txt
index ad72e04..14626b7 100644
--- a/help/reference/libdocument/libevdocument-sections.txt
+++ b/help/reference/libdocument/libevdocument-sections.txt
@@ -343,6 +343,8 @@ ev_document_fc_mutex_trylock
ev_document_get_info
ev_document_get_backend_info
ev_document_load
+ev_document_load_stream
+ev_document_load_gfile
ev_document_save
ev_document_get_n_pages
ev_document_get_page
@@ -659,6 +661,8 @@ EV_DOCUMENT_FONTS_GET_IFACE
<SECTION>
<FILE>ev-document-factory</FILE>
ev_document_factory_get_document
+ev_document_factory_get_document_for_gfile
+ev_document_factory_get_document_for_stream
ev_document_factory_add_filters
</SECTION>
diff --git a/libdocument/ev-document-factory.c b/libdocument/ev-document-factory.c
index 954b525..1df8154 100644
--- a/libdocument/ev-document-factory.c
+++ b/libdocument/ev-document-factory.c
@@ -376,6 +376,140 @@ ev_document_factory_get_document (const char *uri, GError **error)
return document;
}
+/**
+ * ev_document_factory_get_document_for_gfile:
+ * @file: a #GFile
+ * @flags: flags from #EvDocumentLoadFlags
+ * @cancellable: (allow-none): a #GCancellable, or %NULL
+ * @error: (allow-none): a #GError location to store an error, or %NULL
+ *
+ * Synchronously creates a #EvDocument for the document at @file; or, if no
+ * backend handling the document's type is found, or an error occurred on
+ * opening the document, returns %NULL and fills in @error.
+ * If the document is encrypted, it is returned but also @error is set to
+ * %EV_DOCUMENT_ERROR_ENCRYPTED.
+ *
+ * Returns: a new #EvDocument, or %NULL
+ *
+ * Since: 3.6
+ */
+EvDocument*
+ev_document_factory_get_document_for_gfile (GFile *file,
+ EvDocumentLoadFlags flags,
+ GCancellable *cancellable,
+ GError **error)
+{
+ EvDocument *document;
+ GFileInfo *file_info;
+ const char *content_type;
+ char *mime_type = NULL;
+
+ g_return_val_if_fail (G_IS_FILE (file), NULL);
+ g_return_val_if_fail (error == NULL || *error == NULL, NULL);
+
+
+ file_info = g_file_query_info (file,
+ G_FILE_ATTRIBUTE_STANDARD_CONTENT_TYPE,
+ G_FILE_QUERY_INFO_NONE,
+ cancellable,
+ error);
+ if (file_info == NULL)
+ return NULL;
+
+ content_type = g_file_info_get_content_type (file_info);
+ if (content_type == NULL) {
+ g_set_error_literal (error, G_IO_ERROR, G_IO_ERROR_FAILED,
+ "Failed to query file mime type");
+ return NULL;
+ }
+
+ mime_type = g_content_type_get_mime_type (content_type);
+ g_object_unref (file_info);
+
+ document = ev_document_factory_new_document_for_mime_type (mime_type, error);
+ g_free (mime_type);
+ if (document == NULL)
+ return NULL;
+
+ if (!ev_document_load_gfile (document, file, flags, cancellable, error)) {
+ g_object_unref (document);
+ return NULL;
+ }
+
+ return document;
+}
+
+/**
+ * ev_document_factory_get_document_for_stream:
+ * @stream: a #GInputStream
+ * @mime_type: (allow-none): a mime type hint
+ * @flags: flags from #EvDocumentLoadFlags
+ * @cancellable: (allow-none): a #GCancellable, or %NULL
+ * @error: (allow-none): a #GError location to store an error, or %NULL
+ *
+ * Synchronously creates a #EvDocument for the document from @stream; or, if no
+ * backend handling the document's type is found, or an error occurred
+ * on opening the document, returns %NULL and fills in @error.
+ * If the document is encrypted, it is returned but also @error is set to
+ * %EV_DOCUMENT_ERROR_ENCRYPTED.
+ *
+ * If @mime_type is non-%NULL, this overrides any type inferred from the stream.
+ * If the mime type cannot be inferred from the stream, and @mime_type is %NULL,
+ * an error is returned.
+ *
+ * Returns: a new #EvDocument, or %NULL
+ *
+ * Since: 3.6
+ */
+EvDocument*
+ev_document_factory_get_document_for_stream (GInputStream *stream,
+ const char *mime_type,
+ EvDocumentLoadFlags flags,
+ GCancellable *cancellable,
+ GError **error)
+{
+ EvDocument *document;
+ char *mime = NULL;
+
+ g_return_val_if_fail (G_IS_INPUT_STREAM (stream), NULL);
+ g_return_val_if_fail (error == NULL || *error == NULL, NULL);
+
+ if (mime_type == NULL && G_IS_FILE_INPUT_STREAM (stream)) {
+ GFileInfo *file_info;
+ const char *content_type;
+
+ file_info = g_file_input_stream_query_info (G_FILE_INPUT_STREAM (stream),
+ G_FILE_ATTRIBUTE_STANDARD_CONTENT_TYPE,
+ cancellable,
+ error);
+ if (file_info != NULL) {
+ content_type = g_file_info_get_content_type (file_info);
+ if (content_type)
+ mime_type = mime = g_content_type_get_mime_type (content_type);
+ g_object_unref (file_info);
+ }
+ }
+
+ if (mime_type == NULL) {
+ g_set_error_literal (error, G_IO_ERROR, G_IO_ERROR_NOT_SUPPORTED,
+ "Cannot query mime type from stream");
+ return NULL;
+ }
+
+ document = ev_document_factory_new_document_for_mime_type (mime_type, error);
+ g_free (mime);
+
+ if (document == NULL)
+ return NULL;
+
+ if (!ev_document_load_stream (document, stream, flags, cancellable, error)) {
+ g_object_unref (document);
+ return NULL;
+ }
+
+ return document;
+}
+
static void
file_filter_add_mime_types (EvBackendInfo *info, GtkFileFilter *filter)
{
diff --git a/libdocument/ev-document-factory.h b/libdocument/ev-document-factory.h
index b06b11d..b0e6d23 100644
--- a/libdocument/ev-document-factory.h
+++ b/libdocument/ev-document-factory.h
@@ -35,6 +35,16 @@ gboolean _ev_document_factory_init (void);
void _ev_document_factory_shutdown (void);
EvDocument* ev_document_factory_get_document (const char *uri, GError **error);
+EvDocument* ev_document_factory_get_document_for_gfile (GFile *file,
+ EvDocumentLoadFlags flags,
+ GCancellable *cancellable,
+ GError **error);
+EvDocument* ev_document_factory_get_document_for_stream (GInputStream *stream,
+ const char *mime_type,
+ EvDocumentLoadFlags flags,
+ GCancellable *cancellable,
+ GError **error);
+
void ev_document_factory_add_filters (GtkWidget *chooser, EvDocument *document);
G_END_DECLS
diff --git a/libdocument/ev-document.c b/libdocument/ev-document.c
index a75862c..0596a88 100644
--- a/libdocument/ev-document.c
+++ b/libdocument/ev-document.c
@@ -208,6 +208,79 @@ ev_document_fc_mutex_trylock (void)
return g_mutex_trylock (p_ev_fc_mutex);
}
+static void
+ev_document_setup_cache (EvDocument *document)
+{
+ EvDocumentPrivate *priv = document->priv;
+ gint i;
+
+ /* Cache some info about the document to avoid
+ * going to the backends since it requires locks
+ */
+ priv->n_pages = _ev_document_get_n_pages (document);
+
+ for (i = 0; i < priv->n_pages; i++) {
+ EvPage *page = ev_document_get_page (document, i);
+ gdouble page_width = 0;
+ gdouble page_height = 0;
+ EvPageSize *page_size;
+ gchar *page_label;
+
+ _ev_document_get_page_size (document, page, &page_width, &page_height);
+
+ if (i == 0) {
+ priv->uniform_width = page_width;
+ priv->uniform_height = page_height;
+ priv->max_width = priv->uniform_width;
+ priv->max_height = priv->uniform_height;
+ priv->min_width = priv->uniform_width;
+ priv->min_height = priv->uniform_height;
+ } else if (priv->uniform &&
+ (priv->uniform_width != page_width ||
+ priv->uniform_height != page_height)) {
+ /* It's a different page size. Backfill the array. */
+ int j;
+
+ priv->page_sizes = g_new0 (EvPageSize, priv->n_pages);
+
+ for (j = 0; j < i; j++) {
+ page_size = &(priv->page_sizes[j]);
+ page_size->width = priv->uniform_width;
+ page_size->height = priv->uniform_height;
+ }
+ priv->uniform = FALSE;
+ }
+ if (!priv->uniform) {
+ page_size = &(priv->page_sizes[i]);
+
+ page_size->width = page_width;
+ page_size->height = page_height;
+
+ if (page_width > priv->max_width)
+ priv->max_width = page_width;
+ if (page_width < priv->min_width)
+ priv->min_width = page_width;
+
+ if (page_height > priv->max_height)
+ priv->max_height = page_height;
+ if (page_height < priv->min_height)
+ priv->min_height = page_height;
+ }
+
+ page_label = _ev_document_get_page_label (document, page);
+ if (page_label) {
+ if (!priv->page_labels)
+ priv->page_labels = g_new0 (gchar *, priv->n_pages);
+
+ priv->page_labels[i] = page_label;
+ priv->max_label = MAX (priv->max_label,
+ g_utf8_strlen (page_label, 256));
+ }
+
+ g_object_unref (page);
+ }
+}
+
/**
* ev_document_load:
* @document: a #EvDocument
@@ -249,90 +322,113 @@ ev_document_load (EvDocument *document,
"Internal error in backend");
}
} else {
- gint i;
- EvDocumentPrivate *priv = document->priv;
-
- /* Cache some info about the document to avoid
- * going to the backends since it requires locks
- */
- priv->uri = g_strdup (uri);
- priv->n_pages = _ev_document_get_n_pages (document);
-
- for (i = 0; i < priv->n_pages; i++) {
- EvPage *page = ev_document_get_page (document, i);
- gdouble page_width = 0;
- gdouble page_height = 0;
- EvPageSize *page_size;
- gchar *page_label;
-
- _ev_document_get_page_size (document, page, &page_width, &page_height);
-
- if (i == 0) {
- priv->uniform_width = page_width;
- priv->uniform_height = page_height;
- priv->max_width = priv->uniform_width;
- priv->max_height = priv->uniform_height;
- priv->min_width = priv->uniform_width;
- priv->min_height = priv->uniform_height;
- } else if (priv->uniform &&
- (priv->uniform_width != page_width ||
- priv->uniform_height != page_height)) {
- /* It's a different page size. Backfill the array. */
- int j;
-
- priv->page_sizes = g_new0 (EvPageSize, priv->n_pages);
-
- for (j = 0; j < i; j++) {
- page_size = &(priv->page_sizes[j]);
- page_size->width = priv->uniform_width;
- page_size->height = priv->uniform_height;
- }
- priv->uniform = FALSE;
- }
- if (!priv->uniform) {
- page_size = &(priv->page_sizes[i]);
+ EvDocumentPrivate *priv = document->priv;
- page_size->width = page_width;
- page_size->height = page_height;
+ ev_document_setup_cache (document);
- if (page_width > priv->max_width)
- priv->max_width = page_width;
- if (page_width < priv->min_width)
- priv->min_width = page_width;
+ priv->uri = g_strdup (uri);
+ priv->info = _ev_document_get_info (document);
+ if (_ev_document_support_synctex (document)) {
+ gchar *filename;
- if (page_height > priv->max_height)
- priv->max_height = page_height;
- if (page_height < priv->min_height)
- priv->min_height = page_height;
- }
+ filename = g_filename_from_uri (uri, NULL, NULL);
+ if (filename != NULL) {
+ priv->synctex_scanner =
+ synctex_scanner_new_with_output_file (filename, NULL, 1);
+ g_free (filename);
+ }
+ }
+ }
- page_label = _ev_document_get_page_label (document, page);
- if (page_label) {
- if (!priv->page_labels)
- priv->page_labels = g_new0 (gchar *, priv->n_pages);
+ return retval;
+}
- priv->page_labels[i] = page_label;
- priv->max_label = MAX (priv->max_label,
- g_utf8_strlen (page_label, 256));
- }
+/**
+ * ev_document_load_stream:
+ * @document: a #EvDocument
+ * @stream: a #GInputStream
+ * @flags: flags from #EvDocumentLoadFlags
+ * @cancellable: (allow-none): a #GCancellable, or %NULL
+ * @error: (allow-none): a #GError location to store an error, or %NULL
+ *
+ * Synchronously loads the document from @stream.
+ * See ev_document_load() for more information.
+ *
+ * Returns: %TRUE if loading succeeded, or %FALSE on error with @error filled in
+ *
+ * Since: 3.6
+ */
+gboolean
+ev_document_load_stream (EvDocument *document,
+ GInputStream *stream,
+ EvDocumentLoadFlags flags,
+ GCancellable *cancellable,
+ GError **error)
+{
+ EvDocumentClass *klass;
+
+ g_return_val_if_fail (EV_IS_DOCUMENT (document), FALSE);
+ g_return_val_if_fail (G_IS_INPUT_STREAM (stream), FALSE);
+ g_return_val_if_fail (cancellable == NULL || G_IS_CANCELLABLE (cancellable), FALSE);
+ g_return_val_if_fail (error == NULL || *error == NULL, FALSE);
+
+ klass = EV_DOCUMENT_GET_CLASS (document);
+ if (!klass->load_stream) {
+ g_set_error_literal (error, G_IO_ERROR, G_IO_ERROR_NOT_SUPPORTED,
+ "Backend does not support loading from stream");
+ return FALSE;
+ }
- g_object_unref (page);
- }
+ if (!klass->load_stream (document, stream, flags, cancellable, error))
+ return FALSE;
- priv->info = _ev_document_get_info (document);
- if (_ev_document_support_synctex (document)) {
- gchar *filename;
+ ev_document_setup_cache (document);
- filename = g_filename_from_uri (uri, NULL, NULL);
- if (filename != NULL) {
- priv->synctex_scanner =
- synctex_scanner_new_with_output_file (filename, NULL, 1);
- g_free (filename);
- }
- }
- }
+ return TRUE;
+}
- return retval;
+/**
+ * ev_document_load_gfile:
+ * @document: a #EvDocument
+ * @file: a #GFile
+ * @flags: flags from #EvDocumentLoadFlags
+ * @cancellable: (allow-none): a #GCancellable, or %NULL
+ * @error: (allow-none): a #GError location to store an error, or %NULL
+ *
+ * Synchronously loads the document from @file.
+ * See ev_document_load() for more information.
+ *
+ * Returns: %TRUE if loading succeeded, or %FALSE on error with @error filled in
+ *
+ * Since: 3.6
+ */
+gboolean
+ev_document_load_gfile (EvDocument *document,
+ GFile *file,
+ EvDocumentLoadFlags flags,
+ GCancellable *cancellable,
+ GError **error)
+{
+ EvDocumentClass *klass;
+
+ g_return_val_if_fail (EV_IS_DOCUMENT (document), FALSE);
+ g_return_val_if_fail (G_IS_FILE (file), FALSE);
+ g_return_val_if_fail (cancellable == NULL || G_IS_CANCELLABLE (cancellable), FALSE);
+ g_return_val_if_fail (error == NULL || *error == NULL, FALSE);
+
+ klass = EV_DOCUMENT_GET_CLASS (document);
+ if (!klass->load_gfile) {
+ g_set_error_literal (error, G_IO_ERROR, G_IO_ERROR_NOT_SUPPORTED,
+ "Backend does not support loading from GFile");
+ return FALSE;
+ }
+
+ if (!klass->load_gfile (document, file, flags, cancellable, error))
+ return FALSE;
+
+ ev_document_setup_cache (document);
+
+ return TRUE;
}
/**
diff --git a/libdocument/ev-document.h b/libdocument/ev-document.h
index e1e01c0..ba3520f 100644
--- a/libdocument/ev-document.h
+++ b/libdocument/ev-document.h
@@ -29,6 +29,7 @@
#include <glib-object.h>
#include <glib.h>
+#include <gio/gio.h>
#include <gdk/gdk.h>
#include <cairo.h>
@@ -53,6 +54,10 @@ typedef struct _EvDocumentPrivate EvDocumentPrivate;
#define EV_DOC_MUTEX_LOCK (ev_document_doc_mutex_lock ())
#define EV_DOC_MUTEX_UNLOCK (ev_document_doc_mutex_unlock ())
+typedef enum /*< flags >*/ {
+ EV_DOCUMENT_LOAD_FLAG_NONE = 0
+} EvDocumentLoadFlags;
+
typedef enum
{
EV_DOCUMENT_ERROR_INVALID,
@@ -110,6 +115,18 @@ struct _EvDocumentClass
gboolean (* get_backend_info)(EvDocument *document,
EvDocumentBackendInfo *info);
gboolean (* support_synctex) (EvDocument *document);
+
+ /* GIO streams */
+ gboolean (* load_stream) (EvDocument *document,
+ GInputStream *stream,
+ EvDocumentLoadFlags flags,
+ GCancellable *cancellable,
+ GError **error);
+ gboolean (* load_gfile) (EvDocument *document,
+ GFile *file,
+ EvDocumentLoadFlags flags,
+ GCancellable *cancellable,
+ GError **error);
};
GType ev_document_get_type (void) G_GNUC_CONST;
@@ -133,6 +150,16 @@ gboolean ev_document_get_backend_info (EvDocument *document,
gboolean ev_document_load (EvDocument *document,
const char *uri,
GError **error);
+gboolean ev_document_load_stream (EvDocument *document,
+ GInputStream *stream,
+ EvDocumentLoadFlags flags,
+ GCancellable *cancellable,
+ GError **error);
+gboolean ev_document_load_gfile (EvDocument *document,
+ GFile *file,
+ EvDocumentLoadFlags flags,
+ GCancellable *cancellable,
+ GError **error);
gboolean ev_document_save (EvDocument *document,
const char *uri,
GError **error);
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]