[gnome-documents] pdf-loader: rewrite the PDF loader with an async/cancellable API
- From: Cosimo Cecchi <cosimoc src gnome org>
- To: commits-list gnome org
- Cc:
- Subject: [gnome-documents] pdf-loader: rewrite the PDF loader with an async/cancellable API
- Date: Thu, 28 Jul 2011 11:04:52 +0000 (UTC)
commit d2b2c4013d903749cde2b0b4df2dcf845d7fed46
Author: Cosimo Cecchi <cosimoc gnome org>
Date: Tue Jul 26 19:05:01 2011 +0200
pdf-loader: rewrite the PDF loader with an async/cancellable API
This allows more flexibility and reporting load errors to the calling
application.
src/lib/gd-pdf-loader.c | 508 ++++++++++++++++++++++++++---------------------
src/lib/gd-pdf-loader.h | 14 +-
src/mainWindow.js | 32 ++--
3 files changed, 313 insertions(+), 241 deletions(-)
---
diff --git a/src/lib/gd-pdf-loader.c b/src/lib/gd-pdf-loader.c
index 342ebb8..afdbd77 100644
--- a/src/lib/gd-pdf-loader.c
+++ b/src/lib/gd-pdf-loader.c
@@ -30,72 +30,189 @@
#include <evince-view.h>
/* TODO:
- * - error forwarding to the caller, don't die silently
- * - possibly better to turn the loader into an explicit
- * _load() API passing a GCancellable, so we can control it
- * from the application too
* - investigate the GDataDocumentsType bug
*/
G_DEFINE_TYPE (GdPdfLoader, gd_pdf_loader, G_TYPE_OBJECT);
enum {
- PROP_DOCUMENT = 1,
- PROP_URI,
- PROP_SOURCE_ID
+ PROP_SOURCE_ID = 1,
};
-struct _GdPdfLoaderPrivate {
+typedef struct {
+ GSimpleAsyncResult *result;
+ GCancellable *cancellable;
+
EvDocument *document;
gchar *uri;
gchar *pdf_path;
- gchar *source_id;
-
GPid unoconv_pid;
GDataDownloadStream *stream;
+} PdfLoadJob;
+
+struct _GdPdfLoaderPrivate {
+ gchar *source_id;
};
+/* --------------------------- utils -------------------------------- */
+
+#define GOA_DOCS_TRACKER_PREFIX "goa:documents:"
+
+static gchar *
+strip_tracker_prefix (const gchar *source_id)
+{
+ if (g_str_has_prefix (source_id, GOA_DOCS_TRACKER_PREFIX))
+ return g_strdup (source_id + strlen (GOA_DOCS_TRACKER_PREFIX));
+
+ return NULL;
+}
+
+static gchar **
+query_supported_document_types (void)
+{
+ GList *infos, *l;
+ gchar **retval = NULL;
+ GPtrArray *array;
+ EvTypeInfo *info;
+ gint idx;
+
+ infos = ev_backends_manager_get_all_types_info ();
+
+ if (infos == NULL)
+ return NULL;
+
+ array = g_ptr_array_new ();
+
+ for (l = infos; l != NULL; l = l->next) {
+ info = l->data;
+
+ for (idx = 0; info->mime_types[idx] != NULL; idx++)
+ g_ptr_array_add (array, g_strdup (info->mime_types[idx]));
+ }
+
+ g_ptr_array_add (array, NULL);
+ retval = (gchar **) g_ptr_array_free (array, FALSE);
+
+ return retval;
+}
+
+static gboolean
+content_type_is_native (const gchar *content_type)
+{
+ gchar **native_types;
+ gint idx;
+ gboolean found = FALSE;
+
+ native_types = query_supported_document_types ();
+
+ for (idx = 0; native_types[idx] != NULL; idx++) {
+ found = g_content_type_is_a (content_type, native_types[idx]);
+ if (found)
+ break;
+ }
+
+ g_strfreev (native_types);
+
+ return found;
+}
+
+/* ----------------------- load job ------------------------------ */
+
static void
-load_job_done (EvJob *job,
- gpointer user_data)
+pdf_load_job_free (PdfLoadJob *job)
{
- GdPdfLoader *self = user_data;
+ g_clear_object (&job->document);
+ g_clear_object (&job->result);
+ g_clear_object (&job->cancellable);
+ g_clear_object (&job->stream);
- if (ev_job_is_failed (job)) {
- g_print ("Failed to load document: %s", job->error->message);
- g_object_unref (job);
+ g_free (job->uri);
- return;
+ if (job->pdf_path != NULL) {
+ g_unlink (job->pdf_path);
+ g_free (job->pdf_path);
}
- self->priv->document = g_object_ref (job->document);
- g_object_unref (job);
+ if (job->unoconv_pid != -1) {
+ kill (job->unoconv_pid, SIGKILL);
+ job->unoconv_pid = -1;
+ }
- g_object_notify (G_OBJECT (self), "document");
+ g_slice_free (PdfLoadJob, job);
+}
+
+static PdfLoadJob *
+pdf_load_job_new (GSimpleAsyncResult *result,
+ const gchar *uri,
+ GCancellable *cancellable)
+{
+ PdfLoadJob *retval;
+
+ retval = g_slice_new0 (PdfLoadJob);
+ retval->result = g_object_ref (result);
+ retval->cancellable = g_object_ref (cancellable);
+ retval->uri = g_strdup (uri);
+ retval->unoconv_pid = -1;
+
+ return retval;
}
static void
-load_pdf (GdPdfLoader *self,
- const gchar *uri)
+pdf_load_job_complete_error (PdfLoadJob *job,
+ GError *error)
{
- EvJob *job;
+ g_simple_async_result_take_error (job->result, error);
+ g_simple_async_result_complete_in_idle (job->result);
+
+ pdf_load_job_free (job);
+}
- job = ev_job_load_new (uri);
- g_signal_connect (job, "finished",
- G_CALLBACK (load_job_done), self);
+static void
+pdf_load_job_complete_success (PdfLoadJob *job)
+{
+ g_simple_async_result_set_op_res_gpointer (job->result, g_object_ref (job->document), NULL);
+ g_simple_async_result_complete_in_idle (job->result);
- ev_job_scheduler_push_job (job, EV_JOB_PRIORITY_NONE);
+ pdf_load_job_free (job);
}
-#define GOA_DOCS_TRACKER_PREFIX "goa:documents:"
+static void
+ev_load_job_done (EvJob *ev_job,
+ gpointer user_data)
+{
+ PdfLoadJob *job = user_data;
-static gchar *
-strip_tracker_prefix (const gchar *source_id)
+ if (ev_job_is_failed (ev_job)) {
+ pdf_load_job_complete_error (job, g_error_copy (ev_job->error));
+ return;
+ }
+
+ job->document = g_object_ref (ev_job->document);
+ g_object_unref (ev_job);
+
+ pdf_load_job_complete_success (job);
+}
+
+static void
+pdf_load_job_from_pdf (PdfLoadJob *job)
{
- if (g_str_has_prefix (source_id, GOA_DOCS_TRACKER_PREFIX))
- return g_strdup (source_id + strlen (GOA_DOCS_TRACKER_PREFIX));
+ EvJob *ev_job;
+ gchar *uri = NULL;
+ GFile *file;
- return NULL;
+ if (job->pdf_path != NULL) {
+ file = g_file_new_for_path (job->pdf_path);
+ uri = g_file_get_uri (file);
+ g_object_unref (file);
+ }
+
+ ev_job = ev_job_load_new ((uri != NULL) ? (uri) : (job->uri));
+ g_signal_connect (ev_job, "finished",
+ G_CALLBACK (ev_load_job_done), job);
+
+ ev_job_scheduler_push_job (ev_job, EV_JOB_PRIORITY_NONE);
+
+ g_free (uri);
}
static void
@@ -103,25 +220,19 @@ os_splice_ready_cb (GObject *source,
GAsyncResult *res,
gpointer user_data)
{
- GdPdfLoader *self = user_data;
GError *error = NULL;
GFile *file;
gchar *uri;
+ PdfLoadJob *job = user_data;
g_output_stream_splice_finish (G_OUTPUT_STREAM (source), res, &error);
if (error != NULL) {
- g_warning ("Unable to download the PDF file from google: %s\n", error->message);
- g_error_free (error);
+ pdf_load_job_complete_error (job, error);
return;
}
- file = g_file_new_for_path (self->priv->pdf_path);
- uri = g_file_get_uri (file);
- load_pdf (self, uri);
-
- g_object_unref (file);
- g_free (uri);
+ pdf_load_job_from_pdf (job);
}
static void
@@ -131,23 +242,22 @@ file_replace_ready_cb (GObject *source,
{
GFileOutputStream *os;
GError *error = NULL;
- GdPdfLoader *self = user_data;
+ PdfLoadJob *job = user_data;
os = g_file_replace_finish (G_FILE (source), res, &error);
if (error != NULL) {
- g_warning ("Unable to open the temp file for writing: %s\n", error->message);
- g_error_free (error);
+ pdf_load_job_complete_error (job, error);
return;
}
g_output_stream_splice_async (G_OUTPUT_STREAM (os),
- G_INPUT_STREAM (self->priv->stream),
+ G_INPUT_STREAM (job->stream),
G_OUTPUT_STREAM_SPLICE_CLOSE_SOURCE |
G_OUTPUT_STREAM_SPLICE_CLOSE_TARGET,
G_PRIORITY_DEFAULT,
- NULL,
- os_splice_ready_cb, self);
+ job->cancellable,
+ os_splice_ready_cb, job);
g_object_unref (os);
}
@@ -158,36 +268,34 @@ single_entry_ready_cb (GObject *source,
gpointer user_data)
{
GDataEntry *entry;
- GdPdfLoader *self = user_data;
GDataDownloadStream *stream;
GError *error = NULL;
gchar *tmp_name;
gchar *tmp_path, *pdf_path;
GFile *pdf_file;
+ PdfLoadJob *job = user_data;
entry = gdata_service_query_single_entry_finish (GDATA_SERVICE (source), res, &error);
if (error != NULL) {
- g_warning ("Unable to query the requested entry from GData: %s\n", error->message);
- g_error_free (error);
+ pdf_load_job_complete_error (job, error);
return;
}
stream = gdata_documents_document_download (GDATA_DOCUMENTS_DOCUMENT (entry),
GDATA_DOCUMENTS_SERVICE (source),
- "pdf", NULL, &error);
+ "pdf", job->cancellable, &error);
if (error != NULL) {
- g_warning ("Unable to get the download stream for the requested document from GData: %s\n", error->message);
- g_error_free (error);
+ pdf_load_job_complete_error (job, error);
return;
}
- self->priv->stream = stream;
+ job->stream = stream;
tmp_name = g_strdup_printf ("gnome-documents-%d.pdf", getpid ());
tmp_path = g_build_filename (g_get_user_cache_dir (), "gnome-documents", NULL);
- self->priv->pdf_path = pdf_path =
+ job->pdf_path = pdf_path =
g_build_filename (tmp_path, tmp_name, NULL);
g_mkdir_with_parents (tmp_path, 0700);
@@ -195,8 +303,8 @@ single_entry_ready_cb (GObject *source,
g_file_replace_async (pdf_file, NULL, FALSE,
G_FILE_CREATE_PRIVATE,
G_PRIORITY_DEFAULT,
- NULL, file_replace_ready_cb,
- self);
+ job->cancellable, file_replace_ready_cb,
+ job);
g_free (tmp_name);
g_free (tmp_path);
@@ -205,8 +313,8 @@ single_entry_ready_cb (GObject *source,
}
static void
-load_from_google_documents_with_object (GdPdfLoader *self,
- GoaObject *object)
+pdf_load_job_from_google_documents_with_object (PdfLoadJob *job,
+ GoaObject *object)
{
EGDataGoaAuthorizer *authorizer;
GDataDocumentsService *service;
@@ -222,9 +330,9 @@ load_from_google_documents_with_object (GdPdfLoader *self,
*/
gdata_service_query_single_entry_async (GDATA_SERVICE (service),
gdata_documents_service_get_primary_authorization_domain (),
- self->priv->uri,
+ job->uri,
NULL, GDATA_TYPE_DOCUMENTS_TEXT,
- NULL, single_entry_ready_cb, self);
+ job->cancellable, single_entry_ready_cb, job);
g_object_unref (service);
g_object_unref (authorizer);
@@ -241,22 +349,26 @@ client_ready_cb (GObject *source,
GError *error = NULL;
GList *accounts, *l;
gchar *stripped_id;
- GdPdfLoader *self = user_data;
+ PdfLoadJob *job = user_data;
+ GdPdfLoader *self;
client = goa_client_new_finish (res, &error);
if (error != NULL) {
- g_warning ("Error while getting the GOA client: %s",
- error->message);
- g_error_free (error);
-
+ pdf_load_job_complete_error (job, error);
return;
}
+ self = GD_PDF_LOADER (g_async_result_get_source_object (G_ASYNC_RESULT (job->result)));
stripped_id = strip_tracker_prefix (self->priv->source_id);
+ g_object_unref (self);
if (stripped_id == NULL) {
- g_warning ("Wrong source ID; passed in a google URL, but the source ID is not coming from GOA");
+ pdf_load_job_complete_error
+ (job,
+ g_error_new_literal (G_IO_ERROR, 0,
+ "Wrong source ID; passed in a google URL, "
+ "but the source ID is not coming from GOA"));
return;
}
@@ -277,8 +389,14 @@ client_ready_cb (GObject *source,
}
}
- if (target != NULL)
- load_from_google_documents_with_object (self, target);
+ if (target != NULL) {
+ pdf_load_job_from_google_documents_with_object (job, target);
+ } else {
+ pdf_load_job_complete_error
+ (job,
+ g_error_new_literal (G_IO_ERROR, 0,
+ "Cannot find the specified GOA account"));
+ }
g_free (stripped_id);
g_list_free_full (accounts, g_object_unref);
@@ -286,9 +404,9 @@ client_ready_cb (GObject *source,
}
static void
-load_from_google_documents (GdPdfLoader *self)
+pdf_load_job_from_google_documents (PdfLoadJob *job)
{
- goa_client_new (NULL, client_ready_cb, self);
+ goa_client_new (job->cancellable, client_ready_cb, job);
}
static void
@@ -296,27 +414,28 @@ unoconv_child_watch_cb (GPid pid,
gint status,
gpointer user_data)
{
- GdPdfLoader *self = user_data;
- GFile *file;
- gchar *uri;
+ PdfLoadJob *job = user_data;
g_spawn_close_pid (pid);
- self->priv->unoconv_pid = -1;
+ job->unoconv_pid = -1;
- file = g_file_new_for_path (self->priv->pdf_path);
- uri = g_file_get_uri (file);
- load_pdf (self, uri);
+ if (g_cancellable_is_cancelled (job->cancellable)) {
+ pdf_load_job_complete_error
+ (job,
+ g_error_new_literal (G_IO_ERROR, G_IO_ERROR_CANCELLED,
+ "Operation cancelled"));
- g_object_unref (file);
- g_free (uri);
+ return;
+ }
+
+ pdf_load_job_from_pdf (job);
}
static void
-load_openoffice (GdPdfLoader *self)
+pdf_load_job_from_openoffice (PdfLoadJob *job)
{
gchar *doc_path, *pdf_path, *tmp_name, *tmp_path;
GFile *file;
- gboolean res;
gchar *cmd;
gint argc;
@@ -324,100 +443,50 @@ load_openoffice (GdPdfLoader *self)
gchar **argv = NULL;
GError *error = NULL;
- file = g_file_new_for_uri (self->priv->uri);
+ /* build the temporary PDF file path */
+ file = g_file_new_for_uri (job->uri);
doc_path = g_file_get_path (file);
g_object_unref (file);
tmp_name = g_strdup_printf ("gnome-documents-%d.pdf", getpid ());
tmp_path = g_build_filename (g_get_user_cache_dir (), "gnome-documents", NULL);
- self->priv->pdf_path = pdf_path =
+ job->pdf_path = pdf_path =
g_build_filename (tmp_path, tmp_name, NULL);
g_mkdir_with_parents (tmp_path, 0700);
+ /* call into the unoconv executable to convert the OpenOffice document
+ * to the temporary PDF.
+ */
cmd = g_strdup_printf ("unoconv -f pdf -o %s %s", pdf_path, doc_path);
g_free (doc_path);
g_free (tmp_name);
g_free (tmp_path);
- res = g_shell_parse_argv (cmd, &argc, &argv, &error);
+ g_shell_parse_argv (cmd, &argc, &argv, &error);
g_free (cmd);
- if (!res) {
- g_warning ("Error while parsing the unoconv command line: %s",
- error->message);
- g_error_free (error);
-
+ if (error != NULL) {
+ pdf_load_job_complete_error (job, error);
return;
}
- res = g_spawn_async (NULL, argv, NULL,
- G_SPAWN_DO_NOT_REAP_CHILD |
- G_SPAWN_SEARCH_PATH,
- NULL, NULL,
- &pid, &error);
+ g_spawn_async (NULL, argv, NULL,
+ G_SPAWN_DO_NOT_REAP_CHILD |
+ G_SPAWN_SEARCH_PATH,
+ NULL, NULL,
+ &pid, &error);
g_strfreev (argv);
- if (!res) {
- g_warning ("Error while spawning unoconv: %s",
- error->message);
- g_error_free (error);
-
+ if (error != NULL) {
+ pdf_load_job_complete_error (job, error);
return;
}
- g_child_watch_add (pid, unoconv_child_watch_cb, self);
- self->priv->unoconv_pid = pid;
-}
-
-static gchar **
-query_supported_document_types (void)
-{
- GList *infos, *l;
- gchar **retval = NULL;
- GPtrArray *array;
- EvTypeInfo *info;
- gint idx;
-
- infos = ev_backends_manager_get_all_types_info ();
-
- if (infos == NULL)
- return NULL;
-
- array = g_ptr_array_new ();
-
- for (l = infos; l != NULL; l = l->next) {
- info = l->data;
-
- for (idx = 0; info->mime_types[idx] != NULL; idx++)
- g_ptr_array_add (array, g_strdup (info->mime_types[idx]));
- }
-
- g_ptr_array_add (array, NULL);
- retval = (gchar **) g_ptr_array_free (array, FALSE);
-
- return retval;
-}
-
-static gboolean
-content_type_is_native (const gchar *content_type)
-{
- gchar **native_types;
- gint idx;
- gboolean found = FALSE;
-
- native_types = query_supported_document_types ();
-
- for (idx = 0; native_types[idx] != NULL; idx++) {
- found = g_content_type_is_a (content_type, native_types[idx]);
- if (found)
- break;
- }
-
- g_strfreev (native_types);
-
- return found;
+ /* now watch when the unoconv child process dies */
+ g_child_watch_add (pid, unoconv_child_watch_cb, job);
+ job->unoconv_pid = pid;
}
static void
@@ -425,7 +494,7 @@ query_info_ready_cb (GObject *obj,
GAsyncResult *res,
gpointer user_data)
{
- GdPdfLoader *self = user_data;
+ PdfLoadJob *job = user_data;
GError *error = NULL;
GFileInfo *info;
const gchar *content_type;
@@ -434,66 +503,44 @@ query_info_ready_cb (GObject *obj,
res, &error);
if (error != NULL) {
- g_warning ("Unable to query the mimetype of %s: %s",
- self->priv->uri, error->message);
- g_error_free (error);
-
+ pdf_load_job_complete_error (job, error);
return;
}
content_type = g_file_info_get_content_type (info);
- g_object_unref (info);
if (content_type_is_native (content_type))
- load_pdf (self, self->priv->uri);
+ pdf_load_job_from_pdf (job);
else
- load_openoffice (self);
+ pdf_load_job_from_openoffice (job);
+
+ g_object_unref (info);
}
static void
-start_loading_document (GdPdfLoader *self)
+pdf_load_job_from_regular_file (PdfLoadJob *job)
{
GFile *file;
- if (g_str_has_prefix (self->priv->uri, "https://docs.google.com")) {
- load_from_google_documents (self);
- return;
- }
-
- file = g_file_new_for_uri (self->priv->uri);
+ file = g_file_new_for_uri (job->uri);
g_file_query_info_async (file,
G_FILE_ATTRIBUTE_STANDARD_CONTENT_TYPE,
G_FILE_QUERY_INFO_NONE,
G_PRIORITY_DEFAULT,
- NULL,
+ job->cancellable,
query_info_ready_cb,
- self);
+ job);
g_object_unref (file);
}
static void
-gd_pdf_loader_set_uri (GdPdfLoader *self,
- const gchar *uri)
+pdf_load_job_start (PdfLoadJob *job)
{
- g_clear_object (&self->priv->document);
- g_free (self->priv->uri);
-
- self->priv->uri = g_strdup (uri);
- start_loading_document (self);
-}
-
-void
-gd_pdf_loader_cleanup_document (GdPdfLoader *self)
-{
- if (self->priv->pdf_path) {
- g_unlink (self->priv->pdf_path);
- g_free (self->priv->pdf_path);
- }
-
- if (self->priv->unoconv_pid != -1) {
- kill (self->priv->unoconv_pid, SIGKILL);
- self->priv->unoconv_pid = -1;
+ if (g_str_has_prefix (job->uri, "https://docs.google.com")) {
+ pdf_load_job_from_google_documents (job);
+ } else {
+ pdf_load_job_from_regular_file (job);
}
}
@@ -502,11 +549,6 @@ gd_pdf_loader_dispose (GObject *object)
{
GdPdfLoader *self = GD_PDF_LOADER (object);
- gd_pdf_loader_cleanup_document (self);
-
- g_clear_object (&self->priv->document);
- g_clear_object (&self->priv->stream);
- g_free (self->priv->uri);
g_free (self->priv->source_id);
G_OBJECT_CLASS (gd_pdf_loader_parent_class)->dispose (object);
@@ -521,12 +563,6 @@ gd_pdf_loader_get_property (GObject *object,
GdPdfLoader *self = GD_PDF_LOADER (object);
switch (prop_id) {
- case PROP_DOCUMENT:
- g_value_set_object (value, self->priv->document);
- break;
- case PROP_URI:
- g_value_set_string (value, self->priv->uri);
- break;
case PROP_SOURCE_ID:
g_value_set_string (value, self->priv->source_id);
break;
@@ -545,9 +581,6 @@ gd_pdf_loader_set_property (GObject *object,
GdPdfLoader *self = GD_PDF_LOADER (object);
switch (prop_id) {
- case PROP_URI:
- gd_pdf_loader_set_uri (self, g_value_get_string (value));
- break;
case PROP_SOURCE_ID:
self->priv->source_id = g_value_dup_string (value);
break;
@@ -569,30 +602,12 @@ gd_pdf_loader_class_init (GdPdfLoaderClass *klass)
g_object_class_install_property
(oclass,
- PROP_DOCUMENT,
- g_param_spec_object ("document",
- "Document",
- "The loaded document",
- EV_TYPE_DOCUMENT,
- G_PARAM_READABLE));
-
- g_object_class_install_property
- (oclass,
- PROP_URI,
- g_param_spec_string ("uri",
- "URI",
- "The URI to load",
- NULL,
- G_PARAM_READWRITE));
-
- g_object_class_install_property
- (oclass,
PROP_SOURCE_ID,
g_param_spec_string ("source-id",
"Source ID",
"The ID of the source we're loading from",
NULL,
- G_PARAM_READWRITE));
+ G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY | G_PARAM_STATIC_STRINGS));
g_type_class_add_private (klass, sizeof (GdPdfLoaderPrivate));
}
@@ -604,13 +619,56 @@ gd_pdf_loader_init (GdPdfLoader *self)
G_TYPE_INSTANCE_GET_PRIVATE (self,
GD_TYPE_PDF_LOADER,
GdPdfLoaderPrivate);
- self->priv->unoconv_pid = -1;
}
GdPdfLoader *
-gd_pdf_loader_new (const gchar *uri)
+gd_pdf_loader_new (const gchar *source_id)
{
return g_object_new (GD_TYPE_PDF_LOADER,
- "uri", uri,
+ "source-id", source_id,
NULL);
}
+
+void
+gd_pdf_loader_load_uri_async (GdPdfLoader *self,
+ const gchar *uri,
+ GCancellable *cancellable,
+ GAsyncReadyCallback callback,
+ gpointer user_data)
+{
+ PdfLoadJob *job;
+ GSimpleAsyncResult *result;
+
+ result = g_simple_async_result_new (G_OBJECT (self), callback, user_data,
+ gd_pdf_loader_load_uri_async);
+
+ job = pdf_load_job_new (result, uri, cancellable);
+
+ pdf_load_job_start (job);
+
+ g_object_unref (result);
+ g_object_unref (cancellable);
+}
+
+/**
+ * gd_pdf_loader_load_uri_finish:
+ * @self:
+ * @res:
+ * @error: (allow-none) (out):
+ *
+ * Returns: (transfer full):
+ */
+EvDocument *
+gd_pdf_loader_load_uri_finish (GdPdfLoader *self,
+ GAsyncResult *res,
+ GError **error)
+{
+ gpointer r;
+ EvDocument *retval;
+
+ if (g_simple_async_result_propagate_error (G_SIMPLE_ASYNC_RESULT (res), error))
+ return NULL;
+
+ retval = g_simple_async_result_get_op_res_gpointer (G_SIMPLE_ASYNC_RESULT (res));
+ return retval;
+}
diff --git a/src/lib/gd-pdf-loader.h b/src/lib/gd-pdf-loader.h
index 3d66fd7..81a4d12 100644
--- a/src/lib/gd-pdf-loader.h
+++ b/src/lib/gd-pdf-loader.h
@@ -24,6 +24,8 @@
#define __GD_PDF_LOADER_H__
#include <glib-object.h>
+#include <gio/gio.h>
+#include <evince-document.h>
G_BEGIN_DECLS
@@ -52,8 +54,16 @@ struct _GdPdfLoaderClass
GType gd_pdf_loader_get_type (void) G_GNUC_CONST;
-GdPdfLoader *gd_pdf_loader_new (const gchar *uri);
-void gd_pdf_loader_cleanup_document (GdPdfLoader *self);
+GdPdfLoader *gd_pdf_loader_new (const gchar *source_id);
+
+void gd_pdf_loader_load_uri_async (GdPdfLoader *self,
+ const gchar *uri,
+ GCancellable *cancellable,
+ GAsyncReadyCallback callback,
+ gpointer user_data);
+EvDocument *gd_pdf_loader_load_uri_finish (GdPdfLoader *self,
+ GAsyncResult *res,
+ GError **error);
G_END_DECLS
diff --git a/src/mainWindow.js b/src/mainWindow.js
index d30052d..ce0c933 100644
--- a/src/mainWindow.js
+++ b/src/mainWindow.js
@@ -21,6 +21,7 @@
const EvView = imports.gi.EvinceView;
const Gd = imports.gi.Gd;
+const Gio = imports.gi.Gio;
const GLib = imports.gi.GLib;
const GObject = imports.gi.GObject;
const Gtk = imports.gi.Gtk;
@@ -50,8 +51,9 @@ function MainWindow() {
MainWindow.prototype = {
_init: function() {
+ this._pdfLoader = null;
+ this._loaderCancellable = null;
this._loaderTimeout = 0;
- this._loaderSignal = 0;
this._lastFilter = '';
//TODO save this in GSettings?
@@ -160,15 +162,13 @@ MainWindow.prototype = {
},
_prepareForOverview: function() {
- if (this._loaderSignal) {
- this._pdfLoader.disconnect(this._loaderSignal);
- this._loaderSignal = 0;
+ if (this._loaderCancellable) {
+ this._loaderCancellable.cancel();
+ this._loaderCancellable = null;
}
- if (this._pdfLodaer) {
- this._pdfLoader.cleanup_document();
+ if (this._pdfLodaer)
this._pdfLoader = null;
- }
if (this._preview) {
this._preview.destroy();
@@ -202,10 +202,9 @@ MainWindow.prototype = {
this._model.sourceIdFromResourceUrn(resource, Lang.bind(this,
function(sourceId) {
+ this._loaderCancellable = new Gio.Cancellable();
this._pdfLoader = new Gd.PdfLoader({ source_id: sourceId });
- this._loaderSignal =
- this._pdfLoader.connect('notify::document', Lang.bind(this, this._onDocumentLoaded));
- this._pdfLoader.uri = uri;
+ this._pdfLoader.load_uri_async(uri, this._loaderCancellable, Lang.bind(this, this._onDocumentLoaded));
this._loaderTimeout = Mainloop.timeout_add(_PDF_LOADER_TIMEOUT,
Lang.bind(this, this._onPdfLoaderTimeout));
@@ -223,11 +222,16 @@ MainWindow.prototype = {
return false;
},
- _onDocumentLoaded: function(loader) {
- let document = loader.document;
- let model = EvView.DocumentModel.new_with_document(document);
+ _onDocumentLoaded: function(loader, res) {
+ let document = null;
+ try {
+ document = loader.load_uri_finish(res);
+ } catch (e) {
+ log("Unable to load the PDF document: " + e.toString());
+ return;
+ }
- this._loaderSignal = 0;
+ let model = EvView.DocumentModel.new_with_document(document);
if (this._loaderTimeout) {
Mainloop.source_remove(this._loaderTimeout);
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]