+2007-01-24 Carlos Garcia Campos <carlosgc@gnome.org>
+
+ * shell/ev-job-queue.c: (handle_job), (search_for_jobs_unlocked),
+ (no_jobs_available_unlocked), (ev_job_queue_init), (find_queue),
+ (ev_job_queue_remove_job):
+ * shell/ev-jobs.[ch]: (ev_job_load_init), (ev_job_load_class_init),
+ (ev_job_load_dispose), (ev_job_load_new), (ev_job_load_set_uri),
+ (ev_job_load_run):
+ * shell/ev-window.c: (ev_window_is_empty), (password_dialog_response),
+ (ev_window_popup_password_dialog), (ev_window_clear_load_job),
+ (ev_window_load_job_cb), (xfer_update_progress_callback),
+ (ev_window_open_uri), (ev_window_dispose):
+ * shell/main.c: (main):
+
+ Do file transfer asynchronously in the main thread instead of
+ synchronously in the load thread. Fixes bugs #399694, #398307 and
+ #343542.
+
2007-01-24 Carlos Garcia Campos <carlosgc@gnome.org>
* shell/ev-jobs.c: (ev_job_xfer_run):
static GQueue *render_queue_low = NULL;
static GQueue *thumbnail_queue_high = NULL;
static GQueue *thumbnail_queue_low = NULL;
-static GQueue *xfer_queue = NULL;
+static GQueue *load_queue = NULL;
static GQueue *fonts_queue = NULL;
static GQueue *print_queue = NULL;
ev_job_thumbnail_run (EV_JOB_THUMBNAIL (job));
else if (EV_IS_JOB_LINKS (job))
ev_job_links_run (EV_JOB_LINKS (job));
- else if (EV_IS_JOB_XFER (job))
- ev_job_xfer_run (EV_JOB_XFER (job));
+ else if (EV_IS_JOB_LOAD (job))
+ ev_job_load_run (EV_JOB_LOAD (job));
else if (EV_IS_JOB_RENDER (job))
ev_job_render_run (EV_JOB_RENDER (job));
else if (EV_IS_JOB_FONTS (job))
if (job)
return job;
- job = (EvJob *) g_queue_pop_head (xfer_queue);
+ job = (EvJob *) g_queue_pop_head (load_queue);
if (job)
return job;
return g_queue_is_empty (render_queue_high)
&& g_queue_is_empty (render_queue_low)
&& g_queue_is_empty (links_queue)
- && g_queue_is_empty (xfer_queue)
+ && g_queue_is_empty (load_queue)
&& g_queue_is_empty (thumbnail_queue_high)
&& g_queue_is_empty (thumbnail_queue_low)
&& g_queue_is_empty (fonts_queue)
ev_queue_mutex = g_mutex_new ();
links_queue = g_queue_new ();
- xfer_queue = g_queue_new ();
+ load_queue = g_queue_new ();
render_queue_high = g_queue_new ();
render_queue_low = g_queue_new ();
async_render_queue_high = g_queue_new ();
return thumbnail_queue_high;
else
return thumbnail_queue_low;
- } else if (EV_IS_JOB_XFER (job)) {
- /* the priority doesn't effect xfer */
- return xfer_queue;
+ } else if (EV_IS_JOB_LOAD (job)) {
+ /* the priority doesn't effect load */
+ return load_queue;
} else if (EV_IS_JOB_LINKS (job)) {
/* the priority doesn't effect links */
return links_queue;
retval = retval || remove_job_from_queue_locked (render_queue_low, job);
} else if (EV_IS_JOB_LINKS (job)) {
retval = remove_job_from_queue_locked (links_queue, job);
- } else if (EV_IS_JOB_XFER (job)) {
- retval = remove_job_from_queue_locked (xfer_queue, job);
+ } else if (EV_IS_JOB_LOAD (job)) {
+ retval = remove_job_from_queue_locked (load_queue, job);
} else if (EV_IS_JOB_FONTS (job)) {
retval = remove_job_from_queue_locked (fonts_queue, job);
} else if (EV_IS_JOB_PRINT (job)) {
#include <libgnomevfs/gnome-vfs-uri.h>
#include <libgnomevfs/gnome-vfs-utils.h>
#include <libgnomevfs/gnome-vfs-ops.h>
-#include <libgnomevfs/gnome-vfs-xfer.h>
static void ev_job_init (EvJob *job);
static void ev_job_class_init (EvJobClass *class);
static void ev_job_render_class_init (EvJobRenderClass *class);
static void ev_job_thumbnail_init (EvJobThumbnail *job);
static void ev_job_thumbnail_class_init (EvJobThumbnailClass *class);
-static void ev_job_xfer_init (EvJobXfer *job);
-static void ev_job_xfer_class_init (EvJobXferClass *class);
+static void ev_job_load_init (EvJobLoad *job);
+static void ev_job_load_class_init (EvJobLoadClass *class);
static void ev_job_print_init (EvJobPrint *job);
static void ev_job_print_class_init (EvJobPrintClass *class);
G_DEFINE_TYPE (EvJobRender, ev_job_render, EV_TYPE_JOB)
G_DEFINE_TYPE (EvJobThumbnail, ev_job_thumbnail, EV_TYPE_JOB)
G_DEFINE_TYPE (EvJobFonts, ev_job_fonts, EV_TYPE_JOB)
-G_DEFINE_TYPE (EvJobXfer, ev_job_xfer, EV_TYPE_JOB)
+G_DEFINE_TYPE (EvJobLoad, ev_job_load, EV_TYPE_JOB)
G_DEFINE_TYPE (EvJobPrint, ev_job_print, EV_TYPE_JOB)
static void ev_job_init (EvJob *job) { /* Do Nothing */ }
ev_document_doc_mutex_unlock ();
}
-static void ev_job_xfer_init (EvJobXfer *job) { /* Do Nothing */ }
+static void ev_job_load_init (EvJobLoad *job) { /* Do Nothing */ }
static void
-ev_job_xfer_dispose (GObject *object)
+ev_job_load_dispose (GObject *object)
{
- EvJobXfer *job = EV_JOB_XFER (object);
+ EvJobLoad *job = EV_JOB_LOAD (object);
if (job->uri) {
g_free (job->uri);
job->uri = NULL;
}
- if (job->local_uri) {
- g_free (job->local_uri);
- job->local_uri = NULL;
- }
-
if (job->error) {
g_error_free (job->error);
job->error = NULL;
job->dest = NULL;
}
- (* G_OBJECT_CLASS (ev_job_xfer_parent_class)->dispose) (object);
+ (* G_OBJECT_CLASS (ev_job_load_parent_class)->dispose) (object);
}
static void
-ev_job_xfer_class_init (EvJobXferClass *class)
+ev_job_load_class_init (EvJobLoadClass *class)
{
GObjectClass *oclass;
oclass = G_OBJECT_CLASS (class);
- oclass->dispose = ev_job_xfer_dispose;
+ oclass->dispose = ev_job_load_dispose;
}
EvJob *
-ev_job_xfer_new (const gchar *uri, EvLinkDest *dest, EvWindowRunMode mode)
+ev_job_load_new (const gchar *uri, EvLinkDest *dest, EvWindowRunMode mode)
{
- EvJobXfer *job;
+ EvJobLoad *job;
- job = g_object_new (EV_TYPE_JOB_XFER, NULL);
+ job = g_object_new (EV_TYPE_JOB_LOAD, NULL);
job->uri = g_strdup (uri);
if (dest)
}
void
-ev_job_xfer_run (EvJobXfer *job)
+ev_job_load_set_uri (EvJobLoad *job, const gchar *uri)
{
- GnomeVFSURI *source_uri;
- GnomeVFSURI *target_uri;
+ if (job->uri)
+ g_free (job->uri);
+ job->uri = g_strdup (uri);
+}
- g_return_if_fail (EV_IS_JOB_XFER (job));
+void
+ev_job_load_run (EvJobLoad *job)
+{
+ g_return_if_fail (EV_IS_JOB_LOAD (job));
if (job->error) {
g_error_free (job->error);
job->error = NULL;
}
+
+ ev_document_fc_mutex_lock ();
/* This job may already have a document even if the job didn't complete
because, e.g., a password is required - if so, just reload rather than
creating a new instance */
if (EV_JOB (job)->document) {
- ev_document_fc_mutex_lock ();
ev_document_load (EV_JOB (job)->document,
- job->local_uri ? job->local_uri : job->uri,
+ job->uri,
&job->error);
- ev_document_fc_mutex_unlock ();
- EV_JOB (job)->finished = TRUE;
- return;
- }
-
- source_uri = gnome_vfs_uri_new (job->uri);
- if (!gnome_vfs_uri_is_local (source_uri) && !job->local_uri) {
- char *tmp_name;
- char *base_name;
-
- /* We'd like to keep extension of source uri since
- * it helps to resolve some mime types, say cbz */
-
- tmp_name = ev_tmp_filename (NULL);
- base_name = gnome_vfs_uri_extract_short_name (source_uri);
- job->local_uri = g_strconcat ("file:", tmp_name, "-", base_name, NULL);
- g_free (base_name);
- g_free (tmp_name);
-
- target_uri = gnome_vfs_uri_new (job->local_uri);
-
- gnome_vfs_xfer_uri (source_uri, target_uri,
- GNOME_VFS_XFER_DEFAULT | GNOME_VFS_XFER_FOLLOW_LINKS,
- GNOME_VFS_XFER_ERROR_MODE_ABORT,
- GNOME_VFS_XFER_OVERWRITE_MODE_REPLACE,
- NULL,
- job);
- gnome_vfs_uri_unref (target_uri);
+ } else {
+ EV_JOB(job)->document =
+ ev_document_factory_get_document (job->uri,
+ &job->error);
}
- gnome_vfs_uri_unref (source_uri);
- ev_document_fc_mutex_lock ();
- EV_JOB(job)->document = ev_document_factory_get_document (job->local_uri ? job->local_uri : job->uri, &job->error);
ev_document_fc_mutex_unlock ();
EV_JOB (job)->finished = TRUE;
-
- return;
}
EvJob *
typedef struct _EvJobFonts EvJobFonts;
typedef struct _EvJobFontsClass EvJobFontsClass;
-typedef struct _EvJobXfer EvJobXfer;
-typedef struct _EvJobXferClass EvJobXferClass;
+typedef struct _EvJobLoad EvJobLoad;
+typedef struct _EvJobLoadClass EvJobLoadClass;
typedef struct _EvJobPrint EvJobPrint;
typedef struct _EvJobPrintClass EvJobPrintClass;
#define EV_JOB_FONTS_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST((klass), EV_TYPE_JOB_FONTS, EvJobFontsClass))
#define EV_IS_JOB_FONTS(object) (G_TYPE_CHECK_INSTANCE_TYPE((object), EV_TYPE_JOB_FONTS))
-#define EV_TYPE_JOB_XFER (ev_job_xfer_get_type())
-#define EV_JOB_XFER(object) (G_TYPE_CHECK_INSTANCE_CAST((object), EV_TYPE_JOB_XFER, EvJobXfer))
-#define EV_JOB_XFER_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST((klass), EV_TYPE_JOB_XFER, EvJobXferClass))
-#define EV_IS_JOB_XFER(object) (G_TYPE_CHECK_INSTANCE_TYPE((object), EV_TYPE_JOB_XFER))
+#define EV_TYPE_JOB_LOAD (ev_job_load_get_type())
+#define EV_JOB_LOAD(object) (G_TYPE_CHECK_INSTANCE_CAST((object), EV_TYPE_JOB_LOAD, EvJobLoad))
+#define EV_JOB_LOAD_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST((klass), EV_TYPE_JOB_LOAD, EvJobLoadClass))
+#define EV_IS_JOB_LOAD(object) (G_TYPE_CHECK_INSTANCE_TYPE((object), EV_TYPE_JOB_LOAD))
#define EV_TYPE_JOB_PRINT (ev_job_print_get_type())
#define EV_JOB_PRINT(object) (G_TYPE_CHECK_INSTANCE_CAST((object), EV_TYPE_JOB_PRINT, EvJobPrint))
EvJobClass parent_class;
};
-struct _EvJobXfer
+struct _EvJobLoad
{
EvJob parent;
+
EvLinkDest *dest;
EvWindowRunMode mode;
GError *error;
- char *uri;
- char *local_uri;
+ gchar *uri;
};
-struct _EvJobXferClass
+struct _EvJobLoadClass
{
EvJobClass parent_class;
};
EvJob *ev_job_fonts_new (EvDocument *document);
void ev_job_fonts_run (EvJobFonts *fonts);
-/* EvJobXfer */
-GType ev_job_xfer_get_type (void) G_GNUC_CONST;
-EvJob *ev_job_xfer_new (const gchar *uri,
+/* EvJobLoad */
+GType ev_job_load_get_type (void) G_GNUC_CONST;
+EvJob *ev_job_load_new (const gchar *uri,
EvLinkDest *dest,
EvWindowRunMode mode);
-void ev_job_xfer_run (EvJobXfer *xfer);
+void ev_job_load_set_uri (EvJobLoad *load,
+ const gchar *uri);
+void ev_job_load_run (EvJobLoad *load);
/* EvJobPrint */
GType ev_job_print_get_type (void) G_GNUC_CONST;
#include <gtk/gtk.h>
#include <gnome.h>
#include <libgnomevfs/gnome-vfs-utils.h>
+#include <libgnomevfs/gnome-vfs-async-ops.h>
#include <gconf/gconf-client.h>
#include <string.h>
EggRecentViewUIManager *recent_view;
#endif
- EvJob *xfer_job;
+ EvJob *load_job;
#ifdef WITH_GNOME_PRINT
GnomePrintJob *print_job;
#endif
EvWindow *ev_window);
static void ev_window_set_page_mode (EvWindow *window,
EvWindowPageMode page_mode);
-static void ev_window_xfer_job_cb (EvJobXfer *job,
+static void ev_window_load_job_cb (EvJobLoad *job,
gpointer data);
#ifdef WITH_GTK_PRINT
static void ev_window_print_job_cb (EvJobPrint *job,
g_return_val_if_fail (EV_IS_WINDOW (ev_window), FALSE);
return (ev_window->priv->document == NULL) &&
- (ev_window->priv->xfer_job == NULL);
+ (ev_window->priv->load_job == NULL);
}
static void
password = ev_password_dialog_get_password (EV_PASSWORD_DIALOG (password_dialog));
if (password) {
ev_document_doc_mutex_lock ();
- ev_document_security_set_password (EV_DOCUMENT_SECURITY (ev_window->priv->xfer_job->document),
+ ev_document_security_set_password (EV_DOCUMENT_SECURITY (ev_window->priv->load_job->document),
password);
ev_document_doc_mutex_unlock ();
}
ev_password_dialog_save_password (EV_PASSWORD_DIALOG (password_dialog));
ev_window_title_set_type (ev_window->priv->title, EV_WINDOW_TITLE_DOCUMENT);
- ev_job_queue_add_job (ev_window->priv->xfer_job, EV_JOB_PRIORITY_HIGH);
+ ev_job_queue_add_job (ev_window->priv->load_job, EV_JOB_PRIORITY_HIGH);
gtk_widget_destroy (password_dialog);
gtk_widget_destroy (password_dialog);
}
-/* Called either by ev_window_xfer_job_cb or by the "unlock" callback on the
+/* Called either by ev_window_load_job_cb or by the "unlock" callback on the
* password_view page. It assumes that ev_window->priv->password_* has been set
* correctly. These are cleared by password_dialog_response() */
static void
ev_window_popup_password_dialog (EvWindow *ev_window)
{
- g_assert (ev_window->priv->xfer_job);
+ g_assert (ev_window->priv->load_job);
gtk_widget_set_sensitive (ev_window->priv->password_view, FALSE);
}
static void
-ev_window_clear_xfer_job (EvWindow *ev_window)
+ev_window_clear_load_job (EvWindow *ev_window)
{
- if (ev_window->priv->xfer_job != NULL) {
+ if (ev_window->priv->load_job != NULL) {
- if (!ev_window->priv->xfer_job->finished)
- ev_job_queue_remove_job (ev_window->priv->xfer_job);
+ if (!ev_window->priv->load_job->finished)
+ ev_job_queue_remove_job (ev_window->priv->load_job);
- g_signal_handlers_disconnect_by_func (ev_window->priv->xfer_job, ev_window_xfer_job_cb, ev_window);
- g_object_unref (ev_window->priv->xfer_job);
- ev_window->priv->xfer_job = NULL;
+ g_signal_handlers_disconnect_by_func (ev_window->priv->load_job, ev_window_load_job_cb, ev_window);
+ g_object_unref (ev_window->priv->load_job);
+ ev_window->priv->load_job = NULL;
}
}
* function should _not_ necessarily expect those to exist after being
* called. */
static void
-ev_window_xfer_job_cb (EvJobXfer *job,
+ev_window_load_job_cb (EvJobLoad *job,
gpointer data)
{
EvWindow *ev_window = EV_WINDOW (data);
/* Success! */
if (job->error == NULL) {
-
- if (ev_window->priv->uri)
- g_free (ev_window->priv->uri);
- ev_window->priv->uri = g_strdup (job->uri);
-
- if (ev_window->priv->local_uri)
- g_free (ev_window->priv->local_uri);
- ev_window->priv->local_uri =
- job->local_uri ? g_strdup (job->local_uri) : NULL;
-
if (ev_window->priv->document)
g_object_unref (ev_window->priv->document);
ev_window->priv->document = g_object_ref (document);
break;
}
- ev_window_clear_xfer_job (ev_window);
+ ev_window_clear_load_job (ev_window);
return;
}
job->error->code == EV_DOCUMENT_ERROR_ENCRYPTED) {
gchar *base_name, *file_name;
- g_free (ev_window->priv->uri);
- ev_window->priv->uri = g_strdup (job->uri);
setup_view_from_metadata (ev_window);
file_name = gnome_vfs_format_uri_for_display (job->uri);
ev_window_error_dialog (GTK_WINDOW (ev_window),
_("Unable to open document"),
job->error);
- ev_window_clear_xfer_job (ev_window);
+ ev_window_clear_load_job (ev_window);
}
return;
ev_window->priv->properties = NULL;
}
+static gint
+xfer_update_progress_callback (GnomeVFSAsyncHandle *handle,
+ GnomeVFSXferProgressInfo *info,
+ EvWindow *ev_window)
+{
+ switch (info->status) {
+ case GNOME_VFS_XFER_PROGRESS_STATUS_OK:
+ if (info->phase == GNOME_VFS_XFER_PHASE_COMPLETED) {
+ ev_job_queue_add_job (ev_window->priv->load_job, EV_JOB_PRIORITY_HIGH);
+ }
+
+ return 1;
+ case GNOME_VFS_XFER_PROGRESS_STATUS_VFSERROR:
+ case GNOME_VFS_XFER_PROGRESS_STATUS_OVERWRITE:
+ case GNOME_VFS_XFER_PROGRESS_STATUS_DUPLICATE:
+ return 1;
+ default:
+ g_assert_not_reached ();
+ }
+
+ return 0;
+}
+
void
ev_window_open_uri (EvWindow *ev_window,
const char *uri,
EvWindowRunMode mode,
gboolean unlink_temp_file)
{
+ GnomeVFSURI *source_uri;
+ GnomeVFSURI *target_uri;
+
ev_window_close_dialogs (ev_window);
- ev_window_clear_xfer_job (ev_window);
+ ev_window_clear_load_job (ev_window);
ev_window_clear_local_uri (ev_window);
ev_view_set_loading (EV_VIEW (ev_window->priv->view), TRUE);
ev_window->priv->unlink_temp_file = unlink_temp_file;
+
+ if (ev_window->priv->uri)
+ g_free (ev_window->priv->uri);
+ ev_window->priv->uri = g_strdup (uri);
- ev_window->priv->xfer_job = ev_job_xfer_new (uri, dest, mode);
- g_signal_connect (ev_window->priv->xfer_job,
+ ev_window->priv->load_job = ev_job_load_new (uri, dest, mode);
+ g_signal_connect (ev_window->priv->load_job,
"finished",
- G_CALLBACK (ev_window_xfer_job_cb),
+ G_CALLBACK (ev_window_load_job_cb),
ev_window);
- ev_job_queue_add_job (ev_window->priv->xfer_job, EV_JOB_PRIORITY_HIGH);
+
+ source_uri = gnome_vfs_uri_new (uri);
+ if (!gnome_vfs_uri_is_local (source_uri) && !ev_window->priv->local_uri) {
+ GnomeVFSAsyncHandle *handle;
+ GList *slist = NULL;
+ GList *tlist = NULL;
+ char *tmp_name;
+ char *base_name;
+
+ /* We'd like to keep extension of source uri since
+ * it helps to resolve some mime types, say cbz */
+
+ tmp_name = ev_tmp_filename (NULL);
+ base_name = gnome_vfs_uri_extract_short_name (source_uri);
+ ev_window->priv->local_uri = g_strconcat ("file:", tmp_name, "-", base_name, NULL);
+ ev_job_load_set_uri (EV_JOB_LOAD (ev_window->priv->load_job),
+ ev_window->priv->local_uri);
+ g_free (base_name);
+ g_free (tmp_name);
+
+ target_uri = gnome_vfs_uri_new (ev_window->priv->local_uri);
+
+ slist = g_list_prepend (slist, source_uri);
+ tlist = g_list_prepend (tlist, target_uri);
+ gnome_vfs_async_xfer (&handle, slist, tlist,
+ GNOME_VFS_XFER_DEFAULT | GNOME_VFS_XFER_FOLLOW_LINKS,
+ GNOME_VFS_XFER_ERROR_MODE_ABORT,
+ GNOME_VFS_XFER_OVERWRITE_MODE_REPLACE,
+ GNOME_VFS_PRIORITY_DEFAULT,
+ (GnomeVFSAsyncXferProgressCallback)xfer_update_progress_callback,
+ ev_window,
+ NULL, NULL);
+
+ g_list_free (slist);
+ g_list_free (tlist);
+ gnome_vfs_uri_unref (target_uri);
+ gnome_vfs_uri_unref (source_uri);
+
+ return;
+ }
+
+ gnome_vfs_uri_unref (source_uri);
+ ev_job_queue_add_job (ev_window->priv->load_job, EV_JOB_PRIORITY_HIGH);
}
void
priv->password_view = NULL;
}
- if (priv->xfer_job) {
- ev_window_clear_xfer_job (window);
+ if (priv->load_job) {
+ ev_window_clear_load_job (window);
}
if (priv->local_uri) {
}
#endif
- gdk_threads_init ();
gnome_authentication_manager_init ();
if (enable_metadata) {