Web   ·   Wiki   ·   Activities   ·   Blog   ·   Lists   ·   Chat   ·   Meeting   ·   Bugs   ·   Git   ·   Translate   ·   Archive   ·   People   ·   Donate
summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--ChangeLog55
-rw-r--r--libdocument/ev-document.c12
-rw-r--r--libdocument/ev-document.h2
-rw-r--r--shell/Makefile.am4
-rw-r--r--shell/ev-job-queue.c517
-rw-r--r--shell/ev-job-scheduler.c305
-rw-r--r--shell/ev-job-scheduler.h (renamed from shell/ev-job-queue.h)31
-rw-r--r--shell/ev-jobs.c1058
-rw-r--r--shell/ev-jobs.h61
-rw-r--r--shell/ev-page-cache.c1
-rw-r--r--shell/ev-pixbuf-cache.c28
-rw-r--r--shell/ev-pixbuf-cache.h1
-rw-r--r--shell/ev-properties-fonts.c51
-rw-r--r--shell/ev-sidebar-links.c6
-rw-r--r--shell/ev-sidebar-thumbnails.c12
-rw-r--r--shell/ev-view-private.h1
-rw-r--r--shell/ev-view.c1
-rw-r--r--shell/ev-window.c107
-rw-r--r--shell/main.c2
19 files changed, 1187 insertions, 1068 deletions
diff --git a/ChangeLog b/ChangeLog
index efd08f1..1f45cec 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,58 @@
+2008-08-03 Carlos Garcia Campos <carlosgc@gnome.org>
+
+ * libdocument/ev-document.[ch]: (ev_document_doc_mutex_trylock),
+ (ev_document_fc_mutex_trylock):
+ * shell/Makefile.am:
+ * shell/ev-job-queue.[ch]:
+ * shell/ev-job-scheduler.[ch]:
+ * shell/ev-jobs.[ch]: (ev_job_init), (ev_job_dispose),
+ (ev_job_class_init), (emit_finished), (ev_job_emit_finished),
+ (ev_job_run), (ev_job_cancel), (ev_job_failed),
+ (ev_job_failed_from_error), (ev_job_succeeded),
+ (ev_job_is_finished), (ev_job_is_failed), (ev_job_get_run_mode),
+ (ev_job_set_run_mode), (ev_job_links_init), (ev_job_links_run),
+ (ev_job_links_class_init), (ev_job_render_init),
+ (notify_page_ready), (ev_job_render_page_ready),
+ (ev_job_render_run), (ev_job_render_class_init),
+ (ev_job_thumbnail_init), (ev_job_thumbnail_run),
+ (ev_job_thumbnail_class_init), (ev_job_fonts_init),
+ (ev_job_fonts_run), (ev_job_fonts_class_init), (ev_job_load_init),
+ (ev_job_load_run), (ev_job_load_class_init), (ev_job_save_init),
+ (ev_job_save_dispose), (ev_job_save_run),
+ (ev_job_save_class_init), (ev_job_print_init),
+ (ev_job_print_dispose), (ev_job_print_run),
+ (ev_job_print_class_init):
+ * shell/ev-page-cache.c:
+ * shell/ev-pixbuf-cache.[ch]: (dispose_cache_job_info),
+ (check_job_size_and_unref), (move_one_job),
+ (copy_job_to_job_info), (add_job),
+ (ev_pixbuf_cache_add_jobs_if_needed):
+ * shell/ev-properties-fonts.c: (ev_properties_fonts_dispose),
+ (job_fonts_finished_cb), (job_fonts_updated_cb),
+ (ev_properties_fonts_set_document):
+ * shell/ev-sidebar-links.c: (ev_sidebar_links_dispose),
+ (ev_sidebar_links_set_document):
+ * shell/ev-sidebar-thumbnails.c: (clear_range), (add_range),
+ (ev_sidebar_thumbnails_set_document),
+ (ev_sidebar_thumbnails_clear_job):
+ * shell/ev-view-private.h:
+ * shell/ev-view.c:
+ * shell/ev-window.c: (ev_window_clear_thumbnail_job),
+ (ev_window_refresh_window_thumbnail), (password_dialog_response),
+ (ev_window_clear_load_job), (ev_window_clear_reload_job),
+ (ev_window_load_job_cb), (ev_window_reload_job_cb),
+ (window_open_file_copy_ready_cb), (ev_window_open_uri),
+ (ev_window_reload_document), (ev_window_clear_save_job),
+ (ev_window_save_job_cb), (file_save_dialog_response_cb),
+ (ev_window_clear_print_job), (ev_window_print_job_cb),
+ (ev_window_print_dialog_response_cb):
+ * shell/main.c: (main):
+
+ Rework the jobs system in order to make it simpler and more
+ extensible. It allows to run jobs in the main loop instead of
+ using a thread when it's appropriate like the fonts job. Now it's
+ also possible to cancel jobs that are currently running.
+
2008-07-27 Carlos Garcia Campos <carlosgc@gnome.org>
* libdocument/ev-debug.c: (profile_init):
diff --git a/libdocument/ev-document.c b/libdocument/ev-document.c
index 7bb86be..1171509 100644
--- a/libdocument/ev-document.c
+++ b/libdocument/ev-document.c
@@ -89,6 +89,12 @@ ev_document_doc_mutex_unlock (void)
g_mutex_unlock (ev_document_get_doc_mutex ());
}
+gboolean
+ev_document_doc_mutex_trylock (void)
+{
+ return g_mutex_trylock (ev_document_get_doc_mutex ());
+}
+
GMutex *
ev_document_get_fc_mutex (void)
{
@@ -111,6 +117,12 @@ ev_document_fc_mutex_unlock (void)
}
gboolean
+ev_document_fc_mutex_trylock (void)
+{
+ return g_mutex_trylock (ev_document_get_fc_mutex ());
+}
+
+gboolean
ev_document_load (EvDocument *document,
const char *uri,
GError **error)
diff --git a/libdocument/ev-document.h b/libdocument/ev-document.h
index cfcccdb..367d6e6 100644
--- a/libdocument/ev-document.h
+++ b/libdocument/ev-document.h
@@ -101,11 +101,13 @@ GQuark ev_document_error_quark (void);
GMutex *ev_document_get_doc_mutex (void);
void ev_document_doc_mutex_lock (void);
void ev_document_doc_mutex_unlock (void);
+gboolean ev_document_doc_mutex_trylock(void);
/* FontConfig mutex */
GMutex *ev_document_get_fc_mutex (void);
void ev_document_fc_mutex_lock (void);
void ev_document_fc_mutex_unlock (void);
+gboolean ev_document_fc_mutex_trylock (void);
EvDocumentInfo *ev_document_get_info (EvDocument *document);
gboolean ev_document_load (EvDocument *document,
diff --git a/shell/Makefile.am b/shell/Makefile.am
index 3d85771..d2c14a9 100644
--- a/shell/Makefile.am
+++ b/shell/Makefile.am
@@ -28,8 +28,8 @@ evince_SOURCES= \
eggfindbar.h \
ev-application.c \
ev-application.h \
- ev-job-queue.h \
- ev-job-queue.c \
+ ev-job-scheduler.h \
+ ev-job-scheduler.c \
ev-jobs.h \
ev-jobs.c \
ev-file-monitor.h \
diff --git a/shell/ev-job-queue.c b/shell/ev-job-queue.c
deleted file mode 100644
index 8280aab..0000000
--- a/shell/ev-job-queue.c
+++ /dev/null
@@ -1,517 +0,0 @@
-#include <config.h>
-#include "ev-job-queue.h"
-
-/* Like glib calling convention, all functions with _locked in their name assume
- * that we've already locked the doc mutex and can freely and safely access
- * data.
- */
-GCond *render_cond = NULL;
-GMutex *ev_queue_mutex = NULL;
-
-static GQueue *links_queue = NULL;
-static GQueue *render_queue_high = NULL;
-static GQueue *render_queue_low = NULL;
-static GQueue *thumbnail_queue_high = NULL;
-static GQueue *thumbnail_queue_low = NULL;
-static GQueue *load_queue = NULL;
-static GQueue *save_queue = NULL;
-static GQueue *fonts_queue = NULL;
-static GQueue *print_queue = NULL;
-
-/* Queues used for backends supporting EvAsyncRender interface,
- they are executed on the main thread */
-static GQueue *async_render_queue_high = NULL;
-static GQueue *async_render_queue_low = NULL;
-static gboolean async_rendering = FALSE;
-
-static void ev_job_queue_run_next (void);
-
-static gboolean
-remove_job_from_queue_locked (GQueue *queue, EvJob *job)
-{
- GList *list;
-
- list = g_queue_find (queue, job);
- if (list) {
- g_object_unref (G_OBJECT (job));
- g_queue_delete_link (queue, list);
-
- return TRUE;
- }
- return FALSE;
-}
-
-static gboolean
-remove_job_from_async_queue (GQueue *queue, EvJob *job)
-{
- return remove_job_from_queue_locked (queue, job);
-}
-
-static void
-add_job_to_async_queue (GQueue *queue, EvJob *job)
-{
- g_object_ref (job);
- g_queue_push_tail (queue, job);
-}
-
-/**
- * add_job_to_queue_locked:
- * @queue: a #GQueue where the #EvJob will be added.
- * @job: an #EvJob to be added to the specified #GQueue.
- *
- * Add the #EvJob to the specified #GQueue and woke up the ev_render_thread who
- * is waiting for render_cond.
- */
-static void
-add_job_to_queue_locked (GQueue *queue,
- EvJob *job)
-{
- g_object_ref (job);
- g_queue_push_tail (queue, job);
- g_cond_broadcast (render_cond);
-}
-
-/**
- * notify_finished:
- * @job: the object that signal will be reseted.
- *
- * It does emit the job finished signal and returns %FALSE.
- *
- * Returns: %FALSE.
- */
-static gboolean
-notify_finished (GObject *job)
-{
- ev_job_finished (EV_JOB (job));
-
- return FALSE;
-}
-
-/**
- * job_finished_cb:
- * @job: the #EvJob that has been handled.
- *
- * It does finish the job last work and look if there is any more job to be
- * handled.
- */
-static void
-job_finished_cb (EvJob *job)
-{
- g_object_unref (job);
- async_rendering = FALSE;
- ev_job_queue_run_next ();
-}
-
-/**
- * handle_job:
- * @job: the #EvJob to be handled.
- *
- * First, it does check if the job is async and then it does attend it if
- * possible giving a failed assertion otherwise. If the job isn't async it does
- * attend it and notify that the job has been finished.
- */
-static void
-handle_job (EvJob *job)
-{
- g_object_ref (G_OBJECT (job));
-
- if (EV_JOB (job)->async) {
- async_rendering = TRUE;
- if (EV_IS_JOB_RENDER (job)) {
- g_signal_connect (job, "finished",
- G_CALLBACK (job_finished_cb), NULL);
- } else {
- g_assert_not_reached ();
- }
- }
-
- if (EV_IS_JOB_THUMBNAIL (job))
- 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_LOAD (job))
- ev_job_load_run (EV_JOB_LOAD (job));
- else if (EV_IS_JOB_SAVE (job))
- ev_job_save_run (EV_JOB_SAVE (job));
- else if (EV_IS_JOB_RENDER (job))
- ev_job_render_run (EV_JOB_RENDER (job));
- else if (EV_IS_JOB_FONTS (job))
- ev_job_fonts_run (EV_JOB_FONTS (job));
- else if (EV_IS_JOB_PRINT (job))
- ev_job_print_run (EV_JOB_PRINT (job));
-
- if (!EV_JOB (job)->async) {
- /* We let the idle own a ref, as we (the queue) are done with the job. */
- g_idle_add_full (G_PRIORITY_DEFAULT_IDLE,
- (GSourceFunc) notify_finished,
- job,
- g_object_unref);
- }
-}
-
-/**
- * search_for_jobs_unlocked:
- *
- * Check if there is any job at the synchronized queues and return any existing
- * job in them taking in account the next priority:
- *
- * render_queue_high >
- * thumbnail_queue_high >
- * render_queue_low >
- * links_queue >
- * load_queue >
- * thumbnail_queue_low >
- * fonts_queue >
- * print_queue >
- *
- * Returns: an available #EvJob in the queues taking in account stablished queue
- * priorities.
- */
-static EvJob *
-search_for_jobs_unlocked (void)
-{
- EvJob *job;
-
- job = (EvJob *) g_queue_pop_head (render_queue_high);
- if (job)
- return job;
-
- job = (EvJob *) g_queue_pop_head (thumbnail_queue_high);
- if (job)
- return job;
-
- job = (EvJob *) g_queue_pop_head (render_queue_low);
- if (job)
- return job;
-
- job = (EvJob *) g_queue_pop_head (links_queue);
- if (job)
- return job;
-
- job = (EvJob *) g_queue_pop_head (load_queue);
- if (job)
- return job;
-
- job = (EvJob *) g_queue_pop_head (save_queue);
- if (job)
- return job;
-
- job = (EvJob *) g_queue_pop_head (thumbnail_queue_low);
- if (job)
- return job;
-
- job = (EvJob *) g_queue_pop_head (fonts_queue);
- if (job)
- return job;
-
- job = (EvJob *) g_queue_pop_head (print_queue);
- if (job)
- return job;
-
- return NULL;
-}
-
-/**
- * no_jobs_available_unlocked:
- *
- * Looks if there is any job at render, links, load, thumbnail. fonts and print
- * queues.
- *
- * Returns: %TRUE if the render, links, load, thumbnail, fonts and print queues
- * are empty, %FALSE in other case.
- */
-static gboolean
-no_jobs_available_unlocked (void)
-{
- 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 (load_queue)
- && g_queue_is_empty (save_queue)
- && g_queue_is_empty (thumbnail_queue_high)
- && g_queue_is_empty (thumbnail_queue_low)
- && g_queue_is_empty (fonts_queue)
- && g_queue_is_empty (print_queue);
-}
-
-/* the thread mainloop function */
-/**
- * ev_render_thread:
- * @data: data passed to the thread.
- *
- * The thread mainloop function. It does wait for any available job in synced
- * queues to handle it.
- *
- * Returns: the return value of the thread, which will be returned by
- * g_thread_join().
- */
-static gpointer
-ev_render_thread (gpointer data)
-{
- while (TRUE) {
- EvJob *job;
-
- g_mutex_lock (ev_queue_mutex);
- if (no_jobs_available_unlocked ()) {
- g_cond_wait (render_cond, ev_queue_mutex);
- }
-
- job = search_for_jobs_unlocked ();
- g_mutex_unlock (ev_queue_mutex);
-
- /* Now that we have our job, we handle it */
- if (job) {
- handle_job (job);
- g_object_unref (G_OBJECT (job));
- }
- }
- return NULL;
-
-}
-
-/**
- * ev_job_queue_run_next:
- *
- * It does look for any job on the render high priority queue first and after
- * in the render low priority one, and then it does handle it.
- */
-static void
-ev_job_queue_run_next (void)
-{
- EvJob *job;
-
- job = (EvJob *) g_queue_pop_head (async_render_queue_high);
-
- if (job == NULL) {
- job = (EvJob *) g_queue_pop_head (async_render_queue_low);
- }
-
- /* Now that we have our job, we handle it */
- if (job) {
- handle_job (job);
- g_object_unref (G_OBJECT (job));
- }
-}
-
-/* Public Functions */
-/**
- * ev_job_queue_init:
- *
- * Creates a new cond, new mutex, a thread for evince job handling and inits
- * every queue.
- */
-void
-ev_job_queue_init (void)
-{
- if (!g_thread_supported ()) g_thread_init (NULL);
-
- render_cond = g_cond_new ();
- ev_queue_mutex = g_mutex_new ();
-
- links_queue = g_queue_new ();
- load_queue = g_queue_new ();
- save_queue = g_queue_new ();
- render_queue_high = g_queue_new ();
- render_queue_low = g_queue_new ();
- async_render_queue_high = g_queue_new ();
- async_render_queue_low = g_queue_new ();
- thumbnail_queue_high = g_queue_new ();
- thumbnail_queue_low = g_queue_new ();
- fonts_queue = g_queue_new ();
- print_queue = g_queue_new ();
-
- g_thread_create (ev_render_thread, NULL, FALSE, NULL);
-
-}
-
-static GQueue *
-find_queue (EvJob *job,
- EvJobPriority priority)
-{
- if (EV_JOB (job)->async) {
- if (EV_IS_JOB_RENDER (job)) {
- if (priority == EV_JOB_PRIORITY_HIGH)
- return async_render_queue_high;
- else
- return async_render_queue_low;
- }
- } else {
- if (EV_IS_JOB_RENDER (job)) {
- if (priority == EV_JOB_PRIORITY_HIGH)
- return render_queue_high;
- else
- return render_queue_low;
- } else if (EV_IS_JOB_THUMBNAIL (job)) {
- if (priority == EV_JOB_PRIORITY_HIGH)
- return thumbnail_queue_high;
- else
- return thumbnail_queue_low;
- } else if (EV_IS_JOB_LOAD (job)) {
- /* the priority doesn't effect load */
- return load_queue;
- } else if (EV_IS_JOB_SAVE (job)) {
- /* the priority doesn't effect save */
- return save_queue;
- } else if (EV_IS_JOB_LINKS (job)) {
- /* the priority doesn't effect links */
- return links_queue;
- } else if (EV_IS_JOB_FONTS (job)) {
- /* the priority doesn't effect fonts */
- return fonts_queue;
- } else if (EV_IS_JOB_PRINT (job)) {
- /* the priority doesn't effect print */
- return print_queue;
- }
- }
-
- g_assert_not_reached ();
- return NULL;
-}
-
-void
-ev_job_queue_add_job (EvJob *job,
- EvJobPriority priority)
-{
- GQueue *queue;
-
- g_return_if_fail (EV_IS_JOB (job));
-
- queue = find_queue (job, priority);
-
- if (!EV_JOB (job)->async) {
- g_mutex_lock (ev_queue_mutex);
- add_job_to_queue_locked (queue, job);
- g_mutex_unlock (ev_queue_mutex);
- } else {
- add_job_to_async_queue (queue, job);
- if (!async_rendering) {
- ev_job_queue_run_next ();
- }
- }
-}
-
-static gboolean
-move_job_async (EvJob *job, GQueue *old_queue, GQueue *new_queue)
-{
- gboolean retval = FALSE;
-
- g_object_ref (job);
-
- if (remove_job_from_queue_locked (old_queue, job)) {
- add_job_to_async_queue (new_queue, job);
- retval = TRUE;
- }
-
- g_object_unref (job);
-
- return retval;
-}
-
-static gboolean
-move_job (EvJob *job, GQueue *old_queue, GQueue *new_queue)
-{
- gboolean retval = FALSE;
-
- g_mutex_lock (ev_queue_mutex);
- g_object_ref (job);
-
- if (remove_job_from_queue_locked (old_queue, job)) {
- add_job_to_queue_locked (new_queue, job);
- retval = TRUE;
- }
-
- g_object_unref (job);
- g_mutex_unlock (ev_queue_mutex);
-
- return retval;
-}
-
-gboolean
-ev_job_queue_update_job (EvJob *job,
- EvJobPriority new_priority)
-{
- gboolean retval = FALSE;
-
- g_return_val_if_fail (EV_IS_JOB (job), FALSE);
-
- if (EV_JOB (job)->async) {
- if (EV_IS_JOB_RENDER (job)) {
- if (new_priority == EV_JOB_PRIORITY_LOW) {
- retval = move_job_async (job, async_render_queue_high,
- async_render_queue_low);
- } else if (new_priority == EV_JOB_PRIORITY_HIGH) {
- retval = move_job_async (job, async_render_queue_low,
- async_render_queue_high);
- }
- } else {
- g_assert_not_reached ();
- }
- } else {
- if (EV_IS_JOB_THUMBNAIL (job)) {
- if (new_priority == EV_JOB_PRIORITY_LOW) {
- retval = move_job (job, thumbnail_queue_high,
- thumbnail_queue_low);
- } else if (new_priority == EV_JOB_PRIORITY_HIGH) {
- retval = move_job (job, thumbnail_queue_low,
- thumbnail_queue_high);
- }
- } else if (EV_IS_JOB_RENDER (job)) {
- if (new_priority == EV_JOB_PRIORITY_LOW) {
- retval = move_job (job, render_queue_high,
- render_queue_low);
- } else if (new_priority == EV_JOB_PRIORITY_HIGH) {
- retval = move_job (job, render_queue_low,
- render_queue_high);
- }
- } else {
- g_assert_not_reached ();
- }
- }
-
- return retval;
-}
-
-gboolean
-ev_job_queue_remove_job (EvJob *job)
-{
- gboolean retval = FALSE;
-
- g_return_val_if_fail (EV_IS_JOB (job), FALSE);
-
- if (EV_JOB (job)->async) {
- if (EV_IS_JOB_RENDER (job)) {
- retval = remove_job_from_async_queue (async_render_queue_high, job);
- retval = retval || remove_job_from_async_queue (async_render_queue_low, job);
- } else {
- g_assert_not_reached ();
- }
- } else {
- g_mutex_lock (ev_queue_mutex);
-
- if (EV_IS_JOB_THUMBNAIL (job)) {
- retval = remove_job_from_queue_locked (thumbnail_queue_high, job);
- retval = retval || remove_job_from_queue_locked (thumbnail_queue_low, job);
- } else if (EV_IS_JOB_RENDER (job)) {
- retval = remove_job_from_queue_locked (render_queue_high, job);
- 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_LOAD (job)) {
- retval = remove_job_from_queue_locked (load_queue, job);
- } else if (EV_IS_JOB_SAVE (job)) {
- retval = remove_job_from_queue_locked (save_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)) {
- retval = remove_job_from_queue_locked (print_queue, job);
- } else {
- g_assert_not_reached ();
- }
-
- g_mutex_unlock (ev_queue_mutex);
- }
-
- return retval;
-}
-
-
diff --git a/shell/ev-job-scheduler.c b/shell/ev-job-scheduler.c
new file mode 100644
index 0000000..900714e
--- /dev/null
+++ b/shell/ev-job-scheduler.c
@@ -0,0 +1,305 @@
+/* ev-job-scheduler.c
+ * this file is part of evince, a gnome document viewer
+ *
+ * Copyright (C) 2008 Carlos Garcia Campos <carlosgc@gnome.org>
+ *
+ * Evince is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * Evince is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307, USA.
+ */
+
+#include "ev-debug.h"
+#include "ev-job-scheduler.h"
+
+typedef struct _EvSchedulerJob {
+ EvJob *job;
+ EvJobPriority priority;
+ GSList *job_link;
+} EvSchedulerJob;
+
+G_LOCK_DEFINE_STATIC(job_list);
+static GSList *job_list = NULL;
+
+static gpointer ev_job_thread_proxy (gpointer data);
+static void ev_scheduler_thread_job_cancelled (EvSchedulerJob *job,
+ GCancellable *cancellable);
+
+/* EvJobQueue */
+static GQueue queue_urgent = G_QUEUE_INIT;
+static GQueue queue_high = G_QUEUE_INIT;
+static GQueue queue_low = G_QUEUE_INIT;
+static GQueue queue_none = G_QUEUE_INIT;
+
+static GCond *job_queue_cond = NULL;
+static GMutex *job_queue_mutex = NULL;
+static GQueue *job_queue[EV_JOB_N_PRIORITIES] = {
+ &queue_urgent,
+ &queue_high,
+ &queue_low,
+ &queue_none
+};
+
+static void
+ev_job_queue_push (EvSchedulerJob *job,
+ EvJobPriority priority)
+{
+ ev_debug_message (DEBUG_JOBS, "%s priority %d", EV_GET_TYPE_NAME (job->job), priority);
+
+ g_mutex_lock (job_queue_mutex);
+
+ g_queue_push_tail (job_queue[priority], job);
+ g_cond_broadcast (job_queue_cond);
+
+ g_mutex_unlock (job_queue_mutex);
+}
+
+static EvSchedulerJob *
+ev_job_queue_get_next_unlocked (void)
+{
+ gint i;
+ EvSchedulerJob *job = NULL;
+
+ for (i = EV_JOB_PRIORITY_URGENT; i < EV_JOB_N_PRIORITIES; i++) {
+ job = (EvSchedulerJob *) g_queue_pop_head (job_queue[i]);
+ if (job)
+ break;
+ }
+
+ ev_debug_message (DEBUG_JOBS, "%s", job ? EV_GET_TYPE_NAME (job->job) : "No jobs in queue");
+
+ return job;
+}
+
+static gpointer
+ev_job_scheduler_init (gpointer data)
+{
+ job_queue_cond = g_cond_new ();
+ job_queue_mutex = g_mutex_new ();
+ g_thread_create (ev_job_thread_proxy, NULL, FALSE, NULL);
+
+ return NULL;
+}
+
+static void
+ev_scheduler_job_list_add (EvSchedulerJob *job)
+{
+ ev_debug_message (DEBUG_JOBS, "%s", EV_GET_TYPE_NAME (job->job));
+
+ G_LOCK (job_list);
+
+ job_list = g_slist_prepend (job_list, job);
+ job->job_link = job_list;
+
+ G_UNLOCK (job_list);
+}
+
+static void
+ev_scheduler_job_list_remove (EvSchedulerJob *job)
+{
+ ev_debug_message (DEBUG_JOBS, "%s", EV_GET_TYPE_NAME (job->job));
+
+ G_LOCK (job_list);
+
+ job_list = g_slist_delete_link (job_list, job->job_link);
+
+ G_UNLOCK (job_list);
+}
+
+static void
+ev_scheduler_job_free (EvSchedulerJob *job)
+{
+ if (!job)
+ return;
+
+ g_object_unref (job->job);
+ g_free (job);
+}
+
+static void
+ev_scheduler_job_destroy (EvSchedulerJob *job)
+{
+ ev_debug_message (DEBUG_JOBS, "%s", EV_GET_TYPE_NAME (job->job));
+
+ if (job->job->run_mode == EV_JOB_RUN_MAIN_LOOP) {
+ g_signal_handlers_disconnect_by_func (job->job,
+ G_CALLBACK (ev_scheduler_job_destroy),
+ job);
+ } else {
+ g_signal_handlers_disconnect_by_func (job->job->cancellable,
+ G_CALLBACK (ev_scheduler_thread_job_cancelled),
+ job);
+ }
+
+ ev_scheduler_job_list_remove (job);
+ ev_scheduler_job_free (job);
+}
+
+static void
+ev_scheduler_thread_job_cancelled (EvSchedulerJob *job,
+ GCancellable *cancellable)
+{
+ GList *list;
+
+ ev_debug_message (DEBUG_JOBS, "%s", EV_GET_TYPE_NAME (job->job));
+
+ g_mutex_lock (job_queue_mutex);
+
+ /* If the job is not still running,
+ * remove it from the job queue and job list.
+ * If the job is currently running, it will be
+ * destroyed as soon as it finishes.
+ */
+ list = g_queue_find (job_queue[job->priority], job);
+ if (list) {
+ g_queue_delete_link (job_queue[job->priority], list);
+ g_mutex_unlock (job_queue_mutex);
+ ev_scheduler_job_destroy (job);
+ } else {
+ g_mutex_unlock (job_queue_mutex);
+ }
+}
+
+static void
+ev_job_thread (EvJob *job)
+{
+ gboolean result;
+
+ ev_debug_message (DEBUG_JOBS, "%s", EV_GET_TYPE_NAME (job));
+
+ do {
+ if (g_cancellable_is_cancelled (job->cancellable))
+ result = FALSE;
+ else
+ result = ev_job_run (job);
+ } while (result);
+}
+
+static gboolean
+ev_job_idle (EvJob *job)
+{
+ ev_debug_message (DEBUG_JOBS, "%s", EV_GET_TYPE_NAME (job));
+
+ if (g_cancellable_is_cancelled (job->cancellable))
+ return FALSE;
+
+ return ev_job_run (job);
+}
+
+static gpointer
+ev_job_thread_proxy (gpointer data)
+{
+ while (TRUE) {
+ EvSchedulerJob *job;
+
+ g_mutex_lock (job_queue_mutex);
+ job = ev_job_queue_get_next_unlocked ();
+ if (!job) {
+ g_cond_wait (job_queue_cond, job_queue_mutex);
+ g_mutex_unlock (job_queue_mutex);
+ continue;
+ }
+ g_mutex_unlock (job_queue_mutex);
+
+ ev_job_thread (job->job);
+ ev_scheduler_job_destroy (job);
+ }
+
+ return NULL;
+}
+
+void
+ev_job_scheduler_push_job (EvJob *job,
+ EvJobPriority priority)
+{
+ static GOnce once_init = G_ONCE_INIT;
+ EvSchedulerJob *s_job;
+
+ g_once (&once_init, ev_job_scheduler_init, NULL);
+
+ ev_debug_message (DEBUG_JOBS, "%s pirority %d", EV_GET_TYPE_NAME (job), priority);
+
+ s_job = g_new0 (EvSchedulerJob, 1);
+ s_job->job = g_object_ref (job);
+ s_job->priority = priority;
+
+ ev_scheduler_job_list_add (s_job);
+
+ switch (ev_job_get_run_mode (job)) {
+ case EV_JOB_RUN_THREAD:
+ g_signal_connect_swapped (job->cancellable, "cancelled",
+ G_CALLBACK (ev_scheduler_thread_job_cancelled),
+ s_job);
+ ev_job_queue_push (s_job, priority);
+ break;
+ case EV_JOB_RUN_MAIN_LOOP:
+ g_signal_connect_swapped (job, "finished",
+ G_CALLBACK (ev_scheduler_job_destroy),
+ s_job);
+ g_signal_connect_swapped (job, "cancelled",
+ G_CALLBACK (ev_scheduler_job_destroy),
+ s_job);
+ g_idle_add_full (G_PRIORITY_DEFAULT_IDLE,
+ (GSourceFunc)ev_job_idle,
+ g_object_ref (job),
+ (GDestroyNotify)g_object_unref);
+ break;
+ default:
+ g_assert_not_reached ();
+ }
+}
+
+void
+ev_job_scheduler_update_job (EvJob *job,
+ EvJobPriority priority)
+{
+ GSList *l;
+ EvSchedulerJob *s_job = NULL;
+ gboolean need_resort = FALSE;
+
+ /* Main loop jobs are scheduled inmediately */
+ if (ev_job_get_run_mode (job) == EV_JOB_RUN_MAIN_LOOP)
+ return;
+
+ ev_debug_message (DEBUG_JOBS, "%s pirority %d", EV_GET_TYPE_NAME (job), priority);
+
+ G_LOCK (job_list);
+
+ for (l = job_list; l; l = l->next) {
+ s_job = (EvSchedulerJob *)l->data;
+
+ if (s_job->job == job) {
+ need_resort = (s_job->priority != priority);
+ break;
+ }
+ }
+
+ G_UNLOCK (job_list);
+
+ if (need_resort) {
+ GList *list;
+
+ g_mutex_lock (job_queue_mutex);
+
+ list = g_queue_find (job_queue[s_job->priority], s_job);
+ if (list) {
+ ev_debug_message (DEBUG_JOBS, "Moving job %s from pirority %d to %d",
+ EV_GET_TYPE_NAME (job), s_job->priority, priority);
+ g_queue_delete_link (job_queue[s_job->priority], list);
+ g_queue_push_tail (job_queue[priority], s_job);
+ g_cond_broadcast (job_queue_cond);
+ }
+
+ g_mutex_unlock (job_queue_mutex);
+ }
+}
+
diff --git a/shell/ev-job-queue.h b/shell/ev-job-scheduler.h
index e6e4c0e..66f9f80 100644
--- a/shell/ev-job-queue.h
+++ b/shell/ev-job-scheduler.h
@@ -1,6 +1,7 @@
-/* this file is part of evince, a gnome document viewer
+/* ev-job-scheduler.h
+ * this file is part of evince, a gnome document viewer
*
- * Copyright (C) 2005 Red Hat, Inc
+ * Copyright (C) 2008 Carlos Garcia Campos <carlosgc@gnome.org>
*
* Evince is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by
@@ -17,23 +18,27 @@
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307, USA.
*/
-#ifndef __EV_JOB_QUEUE_H__
-#define __EV_JOB_QUEUE_H__
+#ifndef EV_JOB_SCHEDULER_H
+#define EV_JOB_SCHEDULER_H
-#include <gtk/gtk.h>
+#include <glib.h>
#include "ev-jobs.h"
G_BEGIN_DECLS
+typedef enum {
+ EV_JOB_PRIORITY_URGENT, /* Rendering current page range */
+ EV_JOB_PRIORITY_HIGH, /* Rendering current thumbnail range */
+ EV_JOB_PRIORITY_LOW, /* Rendering pages not in current range */
+ EV_JOB_PRIORITY_NONE, /* Any other job: load, save, print, ... */
+ EV_JOB_N_PRIORITIES
+} EvJobPriority;
-void ev_job_queue_init (void);
-
-void ev_job_queue_add_job (EvJob *job,
- EvJobPriority priority);
-gboolean ev_job_queue_update_job (EvJob *job,
- EvJobPriority new_priority);
-gboolean ev_job_queue_remove_job (EvJob *job);
+void ev_job_scheduler_push_job (EvJob *job,
+ EvJobPriority priority);
+void ev_job_scheduler_update_job (EvJob *job,
+ EvJobPriority priority);
G_END_DECLS
-#endif /* __EV_JOB_QUEUE_H__ */
+#endif /* EV_JOB_SCHEDULER_H */
diff --git a/shell/ev-jobs.c b/shell/ev-jobs.c
index 196bad6..7371dd1 100644
--- a/shell/ev-jobs.c
+++ b/shell/ev-jobs.c
@@ -1,6 +1,26 @@
+/* this file is part of evince, a gnome document viewer
+ *
+ * Copyright (C) 2008 Carlos Garcia Campos <carlosgc@gnome.org>
+ * Copyright (C) 2005 Red Hat, Inc
+ *
+ * Evince is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * Evince is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307, USA.
+ */
+
#include <config.h>
+
#include "ev-jobs.h"
-#include "ev-job-queue.h"
#include "ev-document-thumbnails.h"
#include "ev-document-links.h"
#include "ev-document-images.h"
@@ -34,6 +54,7 @@ static void ev_job_print_init (EvJobPrint *job);
static void ev_job_print_class_init (EvJobPrintClass *class);
enum {
+ CANCELLED,
FINISHED,
LAST_SIGNAL
};
@@ -43,10 +64,16 @@ enum {
RENDER_LAST_SIGNAL
};
+enum {
+ UPDATED,
+ FONTS_LAST_SIGNAL
+};
+
static guint job_signals[LAST_SIGNAL] = { 0 };
static guint job_render_signals[RENDER_LAST_SIGNAL] = { 0 };
+static guint job_fonts_signals[FONTS_LAST_SIGNAL] = { 0 };
-G_DEFINE_TYPE (EvJob, ev_job, G_TYPE_OBJECT)
+G_DEFINE_ABSTRACT_TYPE (EvJob, ev_job, G_TYPE_OBJECT)
G_DEFINE_TYPE (EvJobLinks, ev_job_links, EV_TYPE_JOB)
G_DEFINE_TYPE (EvJobRender, ev_job_render, EV_TYPE_JOB)
G_DEFINE_TYPE (EvJobThumbnail, ev_job_thumbnail, EV_TYPE_JOB)
@@ -55,7 +82,12 @@ G_DEFINE_TYPE (EvJobLoad, ev_job_load, EV_TYPE_JOB)
G_DEFINE_TYPE (EvJobSave, ev_job_save, EV_TYPE_JOB)
G_DEFINE_TYPE (EvJobPrint, ev_job_print, EV_TYPE_JOB)
-static void ev_job_init (EvJob *job) { /* Do Nothing */ }
+/* EvJob */
+static void
+ev_job_init (EvJob *job)
+{
+ job->cancellable = g_cancellable_new ();
+}
static void
ev_job_dispose (GObject *object)
@@ -69,6 +101,16 @@ ev_job_dispose (GObject *object)
job->document = NULL;
}
+ if (job->cancellable) {
+ g_object_unref (job->cancellable);
+ job->cancellable = NULL;
+ }
+
+ if (job->error) {
+ g_error_free (job->error);
+ job->error = NULL;
+ }
+
(* G_OBJECT_CLASS (ev_job_parent_class)->dispose) (object);
}
@@ -81,18 +123,173 @@ ev_job_class_init (EvJobClass *class)
oclass->dispose = ev_job_dispose;
+ job_signals[CANCELLED] =
+ g_signal_new ("cancelled",
+ EV_TYPE_JOB,
+ G_SIGNAL_RUN_LAST,
+ G_STRUCT_OFFSET (EvJobClass, cancelled),
+ NULL, NULL,
+ g_cclosure_marshal_VOID__VOID,
+ G_TYPE_NONE, 0);
job_signals [FINISHED] =
g_signal_new ("finished",
EV_TYPE_JOB,
- G_SIGNAL_RUN_LAST,
+ G_SIGNAL_RUN_FIRST,
G_STRUCT_OFFSET (EvJobClass, finished),
NULL, NULL,
g_cclosure_marshal_VOID__VOID,
G_TYPE_NONE, 0);
}
+static gboolean
+emit_finished (EvJob *job)
+{
+ ev_debug_message (DEBUG_JOBS, "%s (%p)", EV_GET_TYPE_NAME (job), job);
+
+ job->idle_finished_id = 0;
+
+ if (job->cancelled) {
+ ev_debug_message (DEBUG_JOBS, "%s (%p) job was cancelled, do not emit finished", EV_GET_TYPE_NAME (job), job);
+ } else {
+ ev_profiler_stop (EV_PROFILE_JOBS, "%s (%p)", EV_GET_TYPE_NAME (job), job);
+ g_signal_emit (job, job_signals[FINISHED], 0);
+ }
+
+ return FALSE;
+}
+
+static void
+ev_job_emit_finished (EvJob *job)
+{
+ ev_debug_message (DEBUG_JOBS, "%s (%p)", EV_GET_TYPE_NAME (job), job);
+
+ if (g_cancellable_is_cancelled (job->cancellable)) {
+ ev_debug_message (DEBUG_JOBS, "%s (%p) job was cancelled, returning", EV_GET_TYPE_NAME (job), job);
+ return;
+ }
+
+ job->finished = TRUE;
+
+ if (job->run_mode == EV_JOB_RUN_THREAD) {
+ job->idle_finished_id =
+ g_idle_add_full (G_PRIORITY_DEFAULT_IDLE,
+ (GSourceFunc)emit_finished,
+ g_object_ref (job),
+ (GDestroyNotify)g_object_unref);
+ } else {
+ ev_profiler_stop (EV_PROFILE_JOBS, "%s (%p)", EV_GET_TYPE_NAME (job), job);
+ g_signal_emit (job, job_signals[FINISHED], 0);
+ }
+}
+
+gboolean
+ev_job_run (EvJob *job)
+{
+ EvJobClass *class = EV_JOB_GET_CLASS (job);
+
+ return class->run (job);
+}
+
+void
+ev_job_cancel (EvJob *job)
+{
+ if (job->cancelled || (job->finished && job->idle_finished_id == 0))
+ return;
+
+ ev_debug_message (DEBUG_JOBS, "job %s (%p) cancelled", EV_GET_TYPE_NAME (job), job);
+ ev_profiler_stop (EV_PROFILE_JOBS, "%s (%p)", EV_GET_TYPE_NAME (job), job);
+
+ /* This should never be called from a thread */
+ job->cancelled = TRUE;
+ g_cancellable_cancel (job->cancellable);
+ g_signal_emit (job, job_signals[CANCELLED], 0);
+}
+
+void
+ev_job_failed (EvJob *job,
+ GQuark domain,
+ gint code,
+ const gchar *format,
+ ...)
+{
+ va_list args;
+ gchar *message;
+
+ if (job->failed || job->finished)
+ return;
+
+ ev_debug_message (DEBUG_JOBS, "job %s (%p) failed", EV_GET_TYPE_NAME (job), job);
+
+ job->failed = TRUE;
+
+ va_start (args, format);
+ message = g_strdup_vprintf (format, args);
+ va_end (args);
+
+ job->error = g_error_new (domain, code, message);
+ g_free (message);
+
+ ev_job_emit_finished (job);
+}
+
+void
+ev_job_failed_from_error (EvJob *job,
+ GError *error)
+{
+ if (job->failed || job->finished)
+ return;
+
+ ev_debug_message (DEBUG_JOBS, "job %s (%p) failed", EV_GET_TYPE_NAME (job), job);
+
+ job->failed = TRUE;
+ job->error = g_error_copy (error);
+
+ ev_job_emit_finished (job);
+}
+
+void
+ev_job_succeeded (EvJob *job)
+{
+ if (job->finished)
+ return;
+
+ ev_debug_message (DEBUG_JOBS, "job %s (%p) succeeded", EV_GET_TYPE_NAME (job), job);
+
+ job->failed = FALSE;
+ ev_job_emit_finished (job);
+}
+
+gboolean
+ev_job_is_finished (EvJob *job)
+{
+ return job->finished;
+}
-static void ev_job_links_init (EvJobLinks *job) { /* Do Nothing */ }
+gboolean
+ev_job_is_failed (EvJob *job)
+{
+ return job->failed;
+}
+
+EvJobRunMode
+ev_job_get_run_mode (EvJob *job)
+{
+ return job->run_mode;
+}
+
+void
+ev_job_set_run_mode (EvJob *job,
+ EvJobRunMode run_mode)
+{
+ job->run_mode = run_mode;
+}
+
+/* EvJobLinks */
+static void
+ev_job_links_init (EvJobLinks *job)
+{
+ EV_JOB (job)->run_mode = EV_JOB_RUN_THREAD;
+}
static void
ev_job_links_dispose (GObject *object)
@@ -111,18 +308,52 @@ ev_job_links_dispose (GObject *object)
(* G_OBJECT_CLASS (ev_job_links_parent_class)->dispose) (object);
}
+static gboolean
+ev_job_links_run (EvJob *job)
+{
+ EvJobLinks *job_links = EV_JOB_LINKS (job);
+
+ ev_debug_message (DEBUG_JOBS, NULL);
+ ev_profiler_start (EV_PROFILE_JOBS, "%s (%p)", EV_GET_TYPE_NAME (job), job);
+
+ ev_document_doc_mutex_lock ();
+ job_links->model = ev_document_links_get_links_model (EV_DOCUMENT_LINKS (job->document));
+ ev_document_doc_mutex_unlock ();
+
+ ev_job_succeeded (job);
+
+ return FALSE;
+}
+
static void
ev_job_links_class_init (EvJobLinksClass *class)
{
- GObjectClass *oclass;
-
- oclass = G_OBJECT_CLASS (class);
+ GObjectClass *oclass = G_OBJECT_CLASS (class);
+ EvJobClass *job_class = EV_JOB_CLASS (class);
oclass->dispose = ev_job_links_dispose;
+ job_class->run = ev_job_links_run;
}
+EvJob *
+ev_job_links_new (EvDocument *document)
+{
+ EvJob *job;
-static void ev_job_render_init (EvJobRender *job) { /* Do Nothing */ }
+ ev_debug_message (DEBUG_JOBS, NULL);
+
+ job = g_object_new (EV_TYPE_JOB_LINKS, NULL);
+ job->document = g_object_ref (document);
+
+ return job;
+}
+
+/* EvJobRender */
+static void
+ev_job_render_init (EvJobRender *job)
+{
+ EV_JOB (job)->run_mode = EV_JOB_RUN_THREAD;
+}
static void
ev_job_render_dispose (GObject *object)
@@ -132,7 +363,7 @@ ev_job_render_dispose (GObject *object)
job = EV_JOB_RENDER (object);
if (job->ev_page) {
- ev_debug_message (DEBUG_JOBS, "page: %d", job->ev_page->index);
+ ev_debug_message (DEBUG_JOBS, "page: %d (%p)", job->ev_page->index, job);
g_object_unref (job->ev_page);
job->ev_page = NULL;
}
@@ -155,132 +386,121 @@ ev_job_render_dispose (GObject *object)
(* G_OBJECT_CLASS (ev_job_render_parent_class)->dispose) (object);
}
-static void
-ev_job_render_class_init (EvJobRenderClass *class)
+static gboolean
+notify_page_ready (EvJobRender *job)
{
- GObjectClass *oclass;
-
- oclass = G_OBJECT_CLASS (class);
+ ev_debug_message (DEBUG_JOBS, "%d (%p)", job->ev_page->index, job);
+ ev_profiler_stop (EV_PROFILE_JOBS, "Rendering page %d", job->ev_page->index);
- job_render_signals [PAGE_READY] =
- g_signal_new ("page-ready",
- EV_TYPE_JOB_RENDER,
- G_SIGNAL_RUN_LAST,
- G_STRUCT_OFFSET (EvJobRenderClass, page_ready),
- NULL, NULL,
- g_cclosure_marshal_VOID__VOID,
- G_TYPE_NONE, 0);
+ if (EV_JOB (job)->cancelled) {
+ ev_debug_message (DEBUG_JOBS, "%s (%p) job was cancelled, do not emit page_ready", EV_GET_TYPE_NAME (job), job);
+ } else {
+ g_signal_emit (job, job_render_signals[PAGE_READY], 0);
+ }
- oclass->dispose = ev_job_render_dispose;
+ return FALSE;
}
-static void ev_job_thumbnail_init (EvJobThumbnail *job) { /* Do Nothing */ }
-
static void
-ev_job_thumbnail_dispose (GObject *object)
+ev_job_render_page_ready (EvJobRender *job)
{
- EvJobThumbnail *job;
-
- job = EV_JOB_THUMBNAIL (object);
-
- ev_debug_message (DEBUG_JOBS, "%d", job->page);
+ ev_debug_message (DEBUG_JOBS, "%d (%p)", job->ev_page->index, job);
- if (job->thumbnail) {
- g_object_unref (job->thumbnail);
- job->thumbnail = NULL;
- }
-
- (* G_OBJECT_CLASS (ev_job_thumbnail_parent_class)->dispose) (object);
+ job->page_ready = TRUE;
+ g_idle_add_full (G_PRIORITY_HIGH_IDLE,
+ (GSourceFunc)notify_page_ready,
+ g_object_ref (job),
+ (GDestroyNotify)g_object_unref);
}
-static void
-ev_job_thumbnail_class_init (EvJobThumbnailClass *class)
+static gboolean
+ev_job_render_run (EvJob *job)
{
- GObjectClass *oclass;
-
- oclass = G_OBJECT_CLASS (class);
-
- oclass->dispose = ev_job_thumbnail_dispose;
-}
-
-static void ev_job_print_init (EvJobPrint *job) { /* Do Nothing */ }
+ EvJobRender *job_render = EV_JOB_RENDER (job);
+ EvRenderContext *rc;
-static void
-ev_job_print_dispose (GObject *object)
-{
- EvJobPrint *job;
+ ev_debug_message (DEBUG_JOBS, "page: %d (%p)", job_render->page, job);
+ ev_profiler_start (EV_PROFILE_JOBS, "%s (%p)", EV_GET_TYPE_NAME (job), job);
+
+ ev_document_doc_mutex_lock ();
- job = EV_JOB_PRINT (object);
+ ev_profiler_start (EV_PROFILE_JOBS, "Rendering page %d", job_render->page);
+
+ ev_document_fc_mutex_lock ();
- ev_debug_message (DEBUG_JOBS, NULL);
-
- if (job->temp_file) {
- g_unlink (job->temp_file);
- g_free (job->temp_file);
- job->temp_file = NULL;
- }
+ job_render->ev_page = ev_document_get_page (job->document, job_render->page);
+ rc = ev_render_context_new (job_render->ev_page, job_render->rotation, job_render->scale);
+
+ job_render->surface = ev_document_render (job->document, rc);
+ /* If job was cancelled during the page rendering,
+ * we return now, so that the thread is finished ASAP
+ */
+ if (g_cancellable_is_cancelled (job->cancellable)) {
+ ev_document_fc_mutex_unlock ();
+ ev_document_doc_mutex_unlock ();
+ g_object_unref (rc);
- if (job->error) {
- g_error_free (job->error);
- job->error = NULL;
+ return FALSE;
}
-
- if (job->ranges) {
- g_free (job->ranges);
- job->ranges = NULL;
- job->n_ranges = 0;
+
+ if ((job_render->flags & EV_RENDER_INCLUDE_SELECTION) && EV_IS_SELECTION (job->document)) {
+ ev_selection_render_selection (EV_SELECTION (job->document),
+ rc,
+ &(job_render->selection),
+ &(job_render->selection_points),
+ NULL,
+ job_render->selection_style,
+ &(job_render->text), &(job_render->base));
+ job_render->selection_region =
+ ev_selection_get_selection_region (EV_SELECTION (job->document),
+ rc,
+ job_render->selection_style,
+ &(job_render->selection_points));
}
- (* G_OBJECT_CLASS (ev_job_print_parent_class)->dispose) (object);
-}
-
-static void
-ev_job_print_class_init (EvJobPrintClass *class)
-{
- GObjectClass *oclass;
-
- oclass = G_OBJECT_CLASS (class);
-
- oclass->dispose = ev_job_print_dispose;
-}
-
-/* Public functions */
-void
-ev_job_finished (EvJob *job)
-{
- ev_debug_message (DEBUG_JOBS, EV_GET_TYPE_NAME (job));
- ev_profiler_stop (EV_PROFILE_JOBS, "%s (%p)", EV_GET_TYPE_NAME (job), job);
+ ev_job_render_page_ready (job_render);
+
+ ev_document_fc_mutex_unlock ();
+
+ if ((job_render->flags & EV_RENDER_INCLUDE_TEXT) && EV_IS_SELECTION (job->document))
+ job_render->text_mapping =
+ ev_selection_get_selection_map (EV_SELECTION (job->document), rc);
+ if ((job_render->flags & EV_RENDER_INCLUDE_LINKS) && EV_IS_DOCUMENT_LINKS (job->document))
+ job_render->link_mapping =
+ ev_document_links_get_links (EV_DOCUMENT_LINKS (job->document), job_render->page);
+ if ((job_render->flags & EV_RENDER_INCLUDE_FORMS) && EV_IS_DOCUMENT_FORMS (job->document))
+ job_render->form_field_mapping =
+ ev_document_forms_get_form_fields (EV_DOCUMENT_FORMS (job->document),
+ job_render->ev_page);
+ if ((job_render->flags & EV_RENDER_INCLUDE_IMAGES) && EV_IS_DOCUMENT_IMAGES (job->document))
+ job_render->image_mapping =
+ ev_document_images_get_image_mapping (EV_DOCUMENT_IMAGES (job->document),
+ job_render->page);
+ g_object_unref (rc);
+ ev_document_doc_mutex_unlock ();
- g_return_if_fail (EV_IS_JOB (job));
+ ev_job_succeeded (job);
- g_signal_emit (job, job_signals[FINISHED], 0);
+ return FALSE;
}
-EvJob *
-ev_job_links_new (EvDocument *document)
+static void
+ev_job_render_class_init (EvJobRenderClass *class)
{
- EvJob *job;
+ GObjectClass *oclass = G_OBJECT_CLASS (class);
+ EvJobClass *job_class = EV_JOB_CLASS (class);
- ev_debug_message (DEBUG_JOBS, NULL);
-
- job = g_object_new (EV_TYPE_JOB_LINKS, NULL);
- job->document = g_object_ref (document);
-
- return job;
-}
-
-void
-ev_job_links_run (EvJobLinks *job)
-{
- ev_debug_message (DEBUG_JOBS, NULL);
- ev_profiler_start (EV_PROFILE_JOBS, "%s (%p)", EV_GET_TYPE_NAME (job), job);
-
- g_return_if_fail (EV_IS_JOB_LINKS (job));
+ job_render_signals [PAGE_READY] =
+ g_signal_new ("page-ready",
+ EV_TYPE_JOB_RENDER,
+ G_SIGNAL_RUN_LAST,
+ G_STRUCT_OFFSET (EvJobRenderClass, page_ready),
+ NULL, NULL,
+ g_cclosure_marshal_VOID__VOID,
+ G_TYPE_NONE, 0);
- ev_document_doc_mutex_lock ();
- job->model = ev_document_links_get_links_model (EV_DOCUMENT_LINKS (EV_JOB (job)->document));
- EV_JOB (job)->finished = TRUE;
- ev_document_doc_mutex_unlock ();
+ oclass->dispose = ev_job_render_dispose;
+ job_class->run = ev_job_render_run;
}
EvJob *
@@ -306,10 +526,6 @@ ev_job_render_new (EvDocument *document,
job->target_height = height;
job->flags = flags;
- if (EV_IS_ASYNC_RENDERER (document)) {
- EV_JOB (job)->async = TRUE;
- }
-
return EV_JOB (job);
}
@@ -328,111 +544,64 @@ ev_job_render_set_selection_info (EvJobRender *job,
job->base = *base;
}
+/* EvJobThumbnail */
static void
-render_finished_cb (EvDocument *document,
- GdkPixbuf *pixbuf,
- EvJobRender *job)
+ev_job_thumbnail_init (EvJobThumbnail *job)
{
- g_signal_handlers_disconnect_by_func (EV_JOB (job)->document,
- render_finished_cb, job);
-
- job->surface = ev_document_misc_surface_from_pixbuf (pixbuf);
- job->page_ready = TRUE;
- g_signal_emit (job, job_render_signals[PAGE_READY], 0);
- EV_JOB (job)->finished = TRUE;
- ev_job_finished (EV_JOB (job));
+ EV_JOB (job)->run_mode = EV_JOB_RUN_THREAD;
}
-static gboolean
-notify_page_ready (EvJobRender *job)
+static void
+ev_job_thumbnail_dispose (GObject *object)
{
- ev_debug_message (DEBUG_JOBS, "%d", job->ev_page->index);
- ev_profiler_stop (EV_PROFILE_JOBS, "Rendering page %d", job->ev_page->index);
-
- g_signal_emit (job, job_render_signals[PAGE_READY], 0);
+ EvJobThumbnail *job;
- return FALSE;
-}
+ job = EV_JOB_THUMBNAIL (object);
-static void
-ev_job_render_page_ready (EvJobRender *job)
-{
- ev_debug_message (DEBUG_JOBS, "%d", job->ev_page->index);
+ ev_debug_message (DEBUG_JOBS, "%d (%p)", job->page, job);
- job->page_ready = TRUE;
- g_idle_add_full (G_PRIORITY_HIGH_IDLE,
- (GSourceFunc)notify_page_ready,
- g_object_ref (job),
- (GDestroyNotify)g_object_unref);
+ if (job->thumbnail) {
+ g_object_unref (job->thumbnail);
+ job->thumbnail = NULL;
+ }
+
+ (* G_OBJECT_CLASS (ev_job_thumbnail_parent_class)->dispose) (object);
}
-void
-ev_job_render_run (EvJobRender *job)
+static gboolean
+ev_job_thumbnail_run (EvJob *job)
{
- g_return_if_fail (EV_IS_JOB_RENDER (job));
+ EvJobThumbnail *job_thumb = EV_JOB_THUMBNAIL (job);
+ EvRenderContext *rc;
+ EvPage *page;
- ev_debug_message (DEBUG_JOBS, "page: %d", job->page);
+ ev_debug_message (DEBUG_JOBS, "%d (%p)", job_thumb->page, job);
ev_profiler_start (EV_PROFILE_JOBS, "%s (%p)", EV_GET_TYPE_NAME (job), job);
ev_document_doc_mutex_lock ();
- if (EV_JOB (job)->async) {
- EvAsyncRenderer *renderer = EV_ASYNC_RENDERER (EV_JOB (job)->document);
- ev_async_renderer_render_pixbuf (renderer, job->page, job->scale,
- job->rotation);
- g_signal_connect (EV_JOB (job)->document, "render_finished",
- G_CALLBACK (render_finished_cb), job);
- } else {
- EvRenderContext *rc;
-
- ev_profiler_start (EV_PROFILE_JOBS, "Rendering page %d", job->page);
-
- ev_document_fc_mutex_lock ();
+ page = ev_document_get_page (job->document, job_thumb->page);
+ rc = ev_render_context_new (page, job_thumb->rotation, job_thumb->scale);
+ g_object_unref (page);
- job->ev_page = ev_document_get_page (EV_JOB (job)->document, job->page);
+ job_thumb->thumbnail = ev_document_thumbnails_get_thumbnail (EV_DOCUMENT_THUMBNAILS (job->document),
+ rc, TRUE);
+ g_object_unref (rc);
+ ev_document_doc_mutex_unlock ();
- rc = ev_render_context_new (job->ev_page, job->rotation, job->scale);
-
- job->surface = ev_document_render (EV_JOB (job)->document, rc);
- if ((job->flags & EV_RENDER_INCLUDE_SELECTION) && EV_IS_SELECTION (EV_JOB (job)->document)) {
- ev_selection_render_selection (EV_SELECTION (EV_JOB (job)->document),
- rc,
- &(job->selection),
- &(job->selection_points),
- NULL,
- job->selection_style,
- &(job->text), &(job->base));
- job->selection_region =
- ev_selection_get_selection_region (EV_SELECTION (EV_JOB (job)->document),
- rc,
- job->selection_style,
- &(job->selection_points));
- }
+ ev_job_succeeded (job);
+
+ return FALSE;
+}
- ev_job_render_page_ready (job);
-
- ev_document_fc_mutex_unlock ();
-
- if ((job->flags & EV_RENDER_INCLUDE_TEXT) && EV_IS_SELECTION (EV_JOB (job)->document))
- job->text_mapping =
- ev_selection_get_selection_map (EV_SELECTION (EV_JOB (job)->document), rc);
- if ((job->flags & EV_RENDER_INCLUDE_LINKS) && EV_IS_DOCUMENT_LINKS (EV_JOB (job)->document))
- job->link_mapping =
- ev_document_links_get_links (EV_DOCUMENT_LINKS (EV_JOB (job)->document), job->page);
- if ((job->flags & EV_RENDER_INCLUDE_FORMS) && EV_IS_DOCUMENT_FORMS (EV_JOB (job)->document))
- job->form_field_mapping =
- ev_document_forms_get_form_fields (EV_DOCUMENT_FORMS (EV_JOB (job)->document),
- job->ev_page);
- if ((job->flags & EV_RENDER_INCLUDE_IMAGES) && EV_IS_DOCUMENT_IMAGES (EV_JOB (job)->document))
- job->image_mapping =
- ev_document_images_get_image_mapping (EV_DOCUMENT_IMAGES (EV_JOB (job)->document),
- job->page);
- g_object_unref (rc);
-
- EV_JOB (job)->finished = TRUE;
- }
+static void
+ev_job_thumbnail_class_init (EvJobThumbnailClass *class)
+{
+ GObjectClass *oclass = G_OBJECT_CLASS (class);
+ EvJobClass *job_class = EV_JOB_CLASS (class);
- ev_document_doc_mutex_unlock ();
+ oclass->dispose = ev_job_thumbnail_dispose;
+ job_class->run = ev_job_thumbnail_run;
}
EvJob *
@@ -455,35 +624,64 @@ ev_job_thumbnail_new (EvDocument *document,
return EV_JOB (job);
}
-void
-ev_job_thumbnail_run (EvJobThumbnail *job)
+/* EvJobFonts */
+static void
+ev_job_fonts_init (EvJobFonts *job)
{
- EvRenderContext *rc;
- EvPage *page;
+ EV_JOB (job)->run_mode = EV_JOB_RUN_MAIN_LOOP;
+}
- ev_debug_message (DEBUG_JOBS, "%d", job->page);
- ev_profiler_start (EV_PROFILE_JOBS, "%s (%p)", EV_GET_TYPE_NAME (job), job);
+static gboolean
+ev_job_fonts_run (EvJob *job)
+{
+ EvJobFonts *job_fonts = EV_JOB_FONTS (job);
+ EvDocumentFonts *fonts = EV_DOCUMENT_FONTS (job->document);
+
+ ev_debug_message (DEBUG_JOBS, NULL);
+
+ /* Do not block the main loop */
+ if (!ev_document_doc_mutex_trylock ())
+ return TRUE;
- g_return_if_fail (EV_IS_JOB_THUMBNAIL (job));
+ if (!ev_document_fc_mutex_trylock ())
+ return TRUE;
- ev_document_doc_mutex_lock ();
+#ifdef EV_ENABLE_DEBUG
+ /* We use the #ifdef in this case because of the if */
+ if (ev_document_fonts_get_progress (fonts) == 0)
+ ev_profiler_start (EV_PROFILE_JOBS, "%s (%p)", EV_GET_TYPE_NAME (job), job);
+#endif
- page = ev_document_get_page (EV_JOB (job)->document, job->page);
- rc = ev_render_context_new (page, job->rotation, job->scale);
- g_object_unref (page);
+ job_fonts->scan_completed = !ev_document_fonts_scan (fonts, 20);
+ g_signal_emit (job_fonts, job_fonts_signals[UPDATED], 0,
+ ev_document_fonts_get_progress (fonts));
- job->thumbnail =
- ev_document_thumbnails_get_thumbnail (EV_DOCUMENT_THUMBNAILS (EV_JOB (job)->document),
- rc, TRUE);
- g_object_unref (rc);
+ ev_document_fc_mutex_unlock ();
ev_document_doc_mutex_unlock ();
+
+ if (job_fonts->scan_completed)
+ ev_job_succeeded (job);
- EV_JOB (job)->finished = TRUE;
+ return !job_fonts->scan_completed;
}
-static void ev_job_fonts_init (EvJobFonts *job) { /* Do Nothing */ }
-
-static void ev_job_fonts_class_init (EvJobFontsClass *class) { /* Do Nothing */ }
+static void
+ev_job_fonts_class_init (EvJobFontsClass *class)
+{
+ EvJobClass *job_class = EV_JOB_CLASS (class);
+
+ job_class->run = ev_job_fonts_run;
+
+ job_fonts_signals[UPDATED] =
+ g_signal_new ("updated",
+ EV_TYPE_JOB_FONTS,
+ G_SIGNAL_RUN_LAST,
+ G_STRUCT_OFFSET (EvJobFontsClass, updated),
+ NULL, NULL,
+ g_cclosure_marshal_VOID__DOUBLE,
+ G_TYPE_NONE,
+ 1, G_TYPE_DOUBLE);
+}
EvJob *
ev_job_fonts_new (EvDocument *document)
@@ -499,30 +697,13 @@ ev_job_fonts_new (EvDocument *document)
return EV_JOB (job);
}
-void
-ev_job_fonts_run (EvJobFonts *job)
+/* EvJobLoad */
+static void
+ev_job_load_init (EvJobLoad *job)
{
- EvDocumentFonts *fonts;
-
- ev_debug_message (DEBUG_JOBS, NULL);
- ev_profiler_start (EV_PROFILE_JOBS, "%s (%p)", EV_GET_TYPE_NAME (job), job);
-
- g_return_if_fail (EV_IS_JOB_FONTS (job));
-
- ev_document_doc_mutex_lock ();
-
- fonts = EV_DOCUMENT_FONTS (EV_JOB (job)->document);
- ev_document_fc_mutex_lock ();
- job->scan_completed = !ev_document_fonts_scan (fonts, 20);
- ev_document_fc_mutex_unlock ();
-
- EV_JOB (job)->finished = TRUE;
-
- ev_document_doc_mutex_unlock ();
+ EV_JOB (job)->run_mode = EV_JOB_RUN_THREAD;
}
-static void ev_job_load_init (EvJobLoad *job) { /* Do Nothing */ }
-
static void
ev_job_load_dispose (GObject *object)
{
@@ -535,11 +716,6 @@ ev_job_load_dispose (GObject *object)
job->uri = NULL;
}
- if (job->error) {
- g_error_free (job->error);
- job->error = NULL;
- }
-
if (job->dest) {
g_object_unref (job->dest);
job->dest = NULL;
@@ -553,17 +729,52 @@ ev_job_load_dispose (GObject *object)
(* G_OBJECT_CLASS (ev_job_load_parent_class)->dispose) (object);
}
+static gboolean
+ev_job_load_run (EvJob *job)
+{
+ EvJobLoad *job_load = EV_JOB_LOAD (job);
+ GError *error = NULL;
+
+ ev_debug_message (DEBUG_JOBS, "%s", job_load->uri);
+ ev_profiler_start (EV_PROFILE_JOBS, "%s (%p)", EV_GET_TYPE_NAME (job), job);
+
+ ev_document_fc_mutex_lock ();
+
+ /* TODO: reuse the job!!! */
+ /* 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 (job->document) {
+ ev_document_load (job->document,
+ job_load->uri,
+ &error);
+ } else {
+ job->document = ev_document_factory_get_document (job_load->uri,
+ &error);
+ }
+
+ ev_document_fc_mutex_unlock ();
+
+ if (error) {
+ ev_job_failed_from_error (job, error);
+ g_error_free (error);
+ } else {
+ ev_job_succeeded (job);
+ }
+
+ return FALSE;
+}
+
static void
ev_job_load_class_init (EvJobLoadClass *class)
{
- GObjectClass *oclass;
-
- oclass = G_OBJECT_CLASS (class);
+ GObjectClass *oclass = G_OBJECT_CLASS (class);
+ EvJobClass *job_class = EV_JOB_CLASS (class);
oclass->dispose = ev_job_load_dispose;
+ job_class->run = ev_job_load_run;
}
-
EvJob *
ev_job_load_new (const gchar *uri,
EvLinkDest *dest,
@@ -577,12 +788,9 @@ ev_job_load_new (const gchar *uri,
job = g_object_new (EV_TYPE_JOB_LOAD, NULL);
job->uri = g_strdup (uri);
- if (dest)
- job->dest = g_object_ref (dest);
-
+ job->dest = dest ? g_object_ref (dest) : NULL;
job->mode = mode;
- if (search_string)
- job->search_string = g_strdup (search_string);
+ job->search_string = search_string ? g_strdup (search_string) : NULL;
return EV_JOB (job);
}
@@ -597,40 +805,13 @@ ev_job_load_set_uri (EvJobLoad *job, const gchar *uri)
job->uri = g_strdup (uri);
}
-void
-ev_job_load_run (EvJobLoad *job)
+/* EvJobSave */
+static void
+ev_job_save_init (EvJobSave *job)
{
- g_return_if_fail (EV_IS_JOB_LOAD (job));
-
- ev_debug_message (DEBUG_JOBS, "%s", job->uri);
- ev_profiler_start (EV_PROFILE_JOBS, "%s (%p)", EV_GET_TYPE_NAME (job), 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_load (EV_JOB (job)->document,
- job->uri,
- &job->error);
- } else {
- EV_JOB(job)->document =
- ev_document_factory_get_document (job->uri,
- &job->error);
- }
-
- ev_document_fc_mutex_unlock ();
- EV_JOB (job)->finished = TRUE;
+ EV_JOB (job)->run_mode = EV_JOB_RUN_THREAD;
}
-static void ev_job_save_init (EvJobSave *job) { /* Do Nothing */ }
-
static void
ev_job_save_dispose (GObject *object)
{
@@ -648,52 +829,20 @@ ev_job_save_dispose (GObject *object)
job->document_uri = NULL;
}
- if (job->error) {
- g_error_free (job->error);
- job->error = NULL;
- }
-
(* G_OBJECT_CLASS (ev_job_save_parent_class)->dispose) (object);
}
-static void
-ev_job_save_class_init (EvJobSaveClass *class)
-{
- GObjectClass *oclass;
-
- oclass = G_OBJECT_CLASS (class);
-
- oclass->dispose = ev_job_save_dispose;
-}
-
-EvJob *
-ev_job_save_new (EvDocument *document,
- const gchar *uri,
- const gchar *document_uri)
-{
- EvJobSave *job;
-
- ev_debug_message (DEBUG_JOBS, "uri: %s, document_uri: %s", uri, document_uri);
-
- job = g_object_new (EV_TYPE_JOB_SAVE, NULL);
-
- EV_JOB (job)->document = g_object_ref (document);
- job->uri = g_strdup (uri);
- job->document_uri = g_strdup (document_uri);
- job->error = NULL;
-
- return EV_JOB (job);
-}
-
-void
-ev_job_save_run (EvJobSave *job)
+static gboolean
+ev_job_save_run (EvJob *job)
{
- gint fd;
- gchar *filename;
- gchar *tmp_filename;
- gchar *local_uri;
-
- ev_debug_message (DEBUG_JOBS, "uri: %s, document_uri: %s", job->uri, job->document_uri);
+ EvJobSave *job_save = EV_JOB_SAVE (job);
+ gint fd;
+ gchar *filename;
+ gchar *tmp_filename;
+ gchar *local_uri;
+ GError *error = NULL;
+
+ ev_debug_message (DEBUG_JOBS, "uri: %s, document_uri: %s", job_save->uri, job_save->document_uri);
ev_profiler_start (EV_PROFILE_JOBS, "%s (%p)", EV_GET_TYPE_NAME (job), job);
filename = ev_tmp_filename ("saveacopy");
@@ -706,53 +855,55 @@ ev_job_save_run (EvJobSave *job)
gint save_errno = errno;
display_name = g_filename_display_name (tmp_filename);
- g_set_error (&(job->error),
- G_FILE_ERROR,
- g_file_error_from_errno (save_errno),
- _("Failed to create file ā€œ%sā€: %s"),
- display_name, g_strerror (save_errno));
+ ev_job_failed (job,
+ G_FILE_ERROR,
+ g_file_error_from_errno (save_errno),
+ _("Failed to create file ā€œ%sā€: %s"),
+ display_name, g_strerror (save_errno));
g_free (display_name);
g_free (tmp_filename);
- return;
+ return FALSE;
}
ev_document_doc_mutex_lock ();
/* Save document to temp filename */
local_uri = g_filename_to_uri (tmp_filename, NULL, NULL);
- ev_document_save (EV_JOB (job)->document, local_uri, &(job->error));
+ ev_document_save (job->document, local_uri, &error);
close (fd);
ev_document_doc_mutex_unlock ();
- if (job->error) {
+ if (error) {
g_free (local_uri);
- return;
+ ev_job_failed_from_error (job, error);
+ g_error_free (error);
+
+ return FALSE;
}
/* If original document was compressed,
* compress it again before saving
*/
- if (g_object_get_data (G_OBJECT (EV_JOB (job)->document),
- "uri-uncompressed")) {
+ if (g_object_get_data (G_OBJECT (job->document), "uri-uncompressed")) {
EvCompressionType ctype = EV_COMPRESSION_NONE;
const gchar *ext;
gchar *uri_comp;
- ext = g_strrstr (job->document_uri, ".gz");
+ ext = g_strrstr (job_save->document_uri, ".gz");
if (ext && g_ascii_strcasecmp (ext, ".gz") == 0)
ctype = EV_COMPRESSION_GZIP;
- ext = g_strrstr (job->document_uri, ".bz2");
+ ext = g_strrstr (job_save->document_uri, ".bz2");
if (ext && g_ascii_strcasecmp (ext, ".bz2") == 0)
ctype = EV_COMPRESSION_BZIP2;
- uri_comp = ev_file_compress (local_uri, ctype, &(job->error));
+ uri_comp = ev_file_compress (local_uri, ctype, &error);
g_free (local_uri);
ev_tmp_filename_unlink (tmp_filename);
- if (!uri_comp || job->error) {
+ if (!uri_comp || error) {
local_uri = NULL;
} else {
local_uri = uri_comp;
@@ -761,63 +912,87 @@ ev_job_save_run (EvJobSave *job)
g_free (tmp_filename);
- if (job->error) {
+ if (error) {
g_free (local_uri);
- return;
+ ev_job_failed_from_error (job, error);
+ g_error_free (error);
+
+ return FALSE;
}
if (!local_uri)
- return;
+ return FALSE;
- ev_xfer_uri_simple (local_uri, job->uri, &(job->error));
+ ev_xfer_uri_simple (local_uri, job_save->uri, &error);
ev_tmp_uri_unlink (local_uri);
+
+ if (error) {
+ ev_job_failed_from_error (job, error);
+ g_error_free (error);
+ } else {
+ ev_job_succeeded (job);
+ }
+
+ return FALSE;
+}
+
+static void
+ev_job_save_class_init (EvJobSaveClass *class)
+{
+ GObjectClass *oclass = G_OBJECT_CLASS (class);
+ EvJobClass *job_class = EV_JOB_CLASS (class);
+
+ oclass->dispose = ev_job_save_dispose;
+ job_class->run = ev_job_save_run;
}
EvJob *
-ev_job_print_new (EvDocument *document,
- const gchar *format,
- gdouble width,
- gdouble height,
- EvPrintRange *ranges,
- gint n_ranges,
- EvPrintPageSet page_set,
- gint pages_per_sheet,
- gint copies,
- gdouble collate,
- gdouble reverse)
+ev_job_save_new (EvDocument *document,
+ const gchar *uri,
+ const gchar *document_uri)
{
- EvJobPrint *job;
+ EvJobSave *job;
- ev_debug_message (DEBUG_JOBS, "format: %s, width: %f, height:%f,"
- "n_ranges: %d, pages_per_sheet: %d, copies: %d,"
- "collate: %s, reverse: %s",
- format, width, height, n_ranges, pages_per_sheet, copies,
- collate ? "True" : "False", reverse ? "True" : "False");
+ ev_debug_message (DEBUG_JOBS, "uri: %s, document_uri: %s", uri, document_uri);
- job = g_object_new (EV_TYPE_JOB_PRINT, NULL);
+ job = g_object_new (EV_TYPE_JOB_SAVE, NULL);
EV_JOB (job)->document = g_object_ref (document);
+ job->uri = g_strdup (uri);
+ job->document_uri = g_strdup (document_uri);
- job->format = format;
-
- job->temp_file = NULL;
- job->error = NULL;
+ return EV_JOB (job);
+}
- job->width = width;
- job->height = height;
+/* EvJobPrint */
+static void
+ev_job_print_init (EvJobPrint *job)
+{
+ EV_JOB (job)->run_mode = EV_JOB_RUN_THREAD;
+}
- job->ranges = ranges;
- job->n_ranges = n_ranges;
+static void
+ev_job_print_dispose (GObject *object)
+{
+ EvJobPrint *job;
- job->page_set = page_set;
+ job = EV_JOB_PRINT (object);
- job->pages_per_sheet = CLAMP (pages_per_sheet, 1, 16);
-
- job->copies = copies;
- job->collate = collate;
- job->reverse = reverse;
+ ev_debug_message (DEBUG_JOBS, NULL);
- return EV_JOB (job);
+ if (job->temp_file) {
+ g_unlink (job->temp_file);
+ g_free (job->temp_file);
+ job->temp_file = NULL;
+ }
+
+ if (job->ranges) {
+ g_free (job->ranges);
+ job->ranges = NULL;
+ job->n_ranges = 0;
+ }
+
+ (* G_OBJECT_CLASS (ev_job_print_parent_class)->dispose) (object);
}
static gint
@@ -933,10 +1108,11 @@ ev_job_print_get_page_list (EvJobPrint *job,
return page_list;
}
-void
-ev_job_print_run (EvJobPrint *job)
+static gboolean
+ev_job_print_run (EvJob *job)
{
EvDocument *document = EV_JOB (job)->document;
+ EvJobPrint *job_print = EV_JOB_PRINT (job);
EvFileExporterContext fc;
EvRenderContext *rc;
gint fd;
@@ -946,68 +1122,67 @@ ev_job_print_run (EvJobPrint *job)
gint first_page;
gint i, j;
gchar *filename;
+ GError *error = NULL;
- g_return_if_fail (EV_IS_JOB_PRINT (job));
-
ev_debug_message (DEBUG_JOBS, NULL);
ev_profiler_start (EV_PROFILE_JOBS, "%s (%p)", EV_GET_TYPE_NAME (job), job);
- if (job->temp_file)
- g_free (job->temp_file);
- job->temp_file = NULL;
+ if (job_print->temp_file)
+ g_free (job_print->temp_file);
+ job_print->temp_file = NULL;
- if (job->error)
- g_error_free (job->error);
- job->error = NULL;
-
- filename = g_strdup_printf ("evince_print.%s.XXXXXX", job->format);
- fd = g_file_open_tmp (filename, &job->temp_file, &job->error);
+ filename = g_strdup_printf ("evince_print.%s.XXXXXX", job_print->format);
+ fd = g_file_open_tmp (filename, &job_print->temp_file, &error);
g_free (filename);
if (fd <= -1) {
- EV_JOB (job)->finished = TRUE;
- return;
+ ev_job_failed_from_error (job, error);
+ g_error_free (error);
+
+ return FALSE;
}
- page_list = ev_job_print_get_page_list (job, &n_pages);
+ page_list = ev_job_print_get_page_list (job_print, &n_pages);
if (n_pages == 0) {
close (fd);
- EV_JOB (job)->finished = TRUE;
- return;
+ /* TODO: error */
+ ev_job_succeeded (job);
+
+ return FALSE;
}
- first_page = ev_print_job_get_first_page (job);
- last_page = ev_print_job_get_last_page (job);
+ first_page = ev_print_job_get_first_page (job_print);
+ last_page = ev_print_job_get_last_page (job_print);
- fc.format = g_ascii_strcasecmp (job->format, "pdf") == 0 ?
+ fc.format = g_ascii_strcasecmp (job_print->format, "pdf") == 0 ?
EV_FILE_FORMAT_PDF : EV_FILE_FORMAT_PS;
- fc.filename = job->temp_file;
+ fc.filename = job_print->temp_file;
fc.first_page = MIN (first_page, last_page);
fc.last_page = MAX (first_page, last_page);
- fc.paper_width = job->width;
- fc.paper_height = job->height;
+ fc.paper_width = job_print->width;
+ fc.paper_height = job_print->height;
fc.duplex = FALSE;
- fc.pages_per_sheet = MAX (1, job->pages_per_sheet);
+ fc.pages_per_sheet = MAX (1, job_print->pages_per_sheet);
rc = ev_render_context_new (NULL, 0, 1.0);
ev_document_doc_mutex_lock ();
ev_file_exporter_begin (EV_FILE_EXPORTER (document), &fc);
- for (i = 0; i < job->copies; i++) {
+ for (i = 0; i < job_print->copies; i++) {
gint page, step;
gint n_copies;
- step = job->reverse ? -1 * job->pages_per_sheet : job->pages_per_sheet;
- page = job->reverse ? ((n_pages - 1) / job->pages_per_sheet) * job->pages_per_sheet : 0;
- n_copies = job->collate ? 1 : job->copies;
+ step = job_print->reverse ? -1 * job_print->pages_per_sheet : job_print->pages_per_sheet;
+ page = job_print->reverse ? ((n_pages - 1) / job_print->pages_per_sheet) * job_print->pages_per_sheet : 0;
+ n_copies = job_print->collate ? 1 : job_print->copies;
- while ((job->reverse && (page >= 0)) || (!job->reverse && (page < n_pages))) {
+ while ((job_print->reverse && (page >= 0)) || (!job_print->reverse && (page < n_pages))) {
gint k;
for (k = 0; k < n_copies; k++) {
ev_file_exporter_begin_page (EV_FILE_EXPORTER (document));
- for (j = 0; j < job->pages_per_sheet; j++) {
+ for (j = 0; j < job_print->pages_per_sheet; j++) {
EvPage *ev_page;
gint p = page + j;
@@ -1028,7 +1203,7 @@ ev_job_print_run (EvJobPrint *job)
page += step;
}
- if (!job->collate)
+ if (!job_print->collate)
break;
}
@@ -1039,5 +1214,64 @@ ev_job_print_run (EvJobPrint *job)
close (fd);
g_object_unref (rc);
- EV_JOB (job)->finished = TRUE;
+ ev_job_succeeded (job);
+
+ return FALSE;
}
+
+static void
+ev_job_print_class_init (EvJobPrintClass *class)
+{
+ GObjectClass *oclass = G_OBJECT_CLASS (class);
+ EvJobClass *job_class = EV_JOB_CLASS (class);
+
+ oclass->dispose = ev_job_print_dispose;
+ job_class->run = ev_job_print_run;
+}
+
+EvJob *
+ev_job_print_new (EvDocument *document,
+ const gchar *format,
+ gdouble width,
+ gdouble height,
+ EvPrintRange *ranges,
+ gint n_ranges,
+ EvPrintPageSet page_set,
+ gint pages_per_sheet,
+ gint copies,
+ gdouble collate,
+ gdouble reverse)
+{
+ EvJobPrint *job;
+
+ ev_debug_message (DEBUG_JOBS, "format: %s, width: %f, height:%f,"
+ "n_ranges: %d, pages_per_sheet: %d, copies: %d,"
+ "collate: %s, reverse: %s",
+ format, width, height, n_ranges, pages_per_sheet, copies,
+ collate ? "True" : "False", reverse ? "True" : "False");
+
+ job = g_object_new (EV_TYPE_JOB_PRINT, NULL);
+
+ EV_JOB (job)->document = g_object_ref (document);
+
+ job->format = format;
+
+ job->temp_file = NULL;
+
+ job->width = width;
+ job->height = height;
+
+ job->ranges = ranges;
+ job->n_ranges = n_ranges;
+
+ job->page_set = page_set;
+
+ job->pages_per_sheet = CLAMP (pages_per_sheet, 1, 16);
+
+ job->copies = copies;
+ job->collate = collate;
+ job->reverse = reverse;
+
+ return EV_JOB (job);
+}
+
diff --git a/shell/ev-jobs.h b/shell/ev-jobs.h
index c63a32c..c0f9572 100644
--- a/shell/ev-jobs.h
+++ b/shell/ev-jobs.h
@@ -1,5 +1,6 @@
/* this file is part of evince, a gnome document viewer
*
+ * Copyright (C) 2008 Carlos Garcia Campos <carlosgc@gnome.org>
* Copyright (C) 2005 Red Hat, Inc
*
* Evince is free software; you can redistribute it and/or modify it
@@ -55,6 +56,7 @@ typedef struct _EvJobPrintClass EvJobPrintClass;
#define EV_JOB(object) (G_TYPE_CHECK_INSTANCE_CAST((object), EV_TYPE_JOB, EvJob))
#define EV_JOB_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST((klass), EV_TYPE_JOB, EvJobClass))
#define EV_IS_JOB(object) (G_TYPE_CHECK_INSTANCE_TYPE((object), EV_TYPE_JOB))
+#define EV_JOB_GET_CLASS(object) (G_TYPE_INSTANCE_GET_CLASS((object), EV_TYPE_JOB, EvJobClass))
#define EV_TYPE_JOB_LINKS (ev_job_links_get_type())
#define EV_JOB_LINKS(object) (G_TYPE_CHECK_INSTANCE_CAST((object), EV_TYPE_JOB_LINKS, EvJobLinks))
@@ -92,23 +94,38 @@ typedef struct _EvJobPrintClass EvJobPrintClass;
#define EV_IS_JOB_PRINT(object) (G_TYPE_CHECK_INSTANCE_TYPE((object), EV_TYPE_JOB_PRINT))
typedef enum {
- EV_JOB_PRIORITY_LOW,
- EV_JOB_PRIORITY_HIGH,
-} EvJobPriority;
+ EV_JOB_RUN_THREAD,
+ EV_JOB_RUN_MAIN_LOOP
+} EvJobRunMode;
struct _EvJob
{
GObject parent;
+
EvDocument *document;
- gboolean finished;
- gboolean async;
+
+ EvJobRunMode run_mode;
+
+ guint cancelled : 1;
+ guint finished : 1;
+ guint failed : 1;
+
+ GError *error;
+ GCancellable *cancellable;
+
+ guint idle_finished_id;
+ guint idle_cancelled_id;
};
struct _EvJobClass
{
GObjectClass parent_class;
- void (* finished) (EvJob *job);
+ gboolean (*run) (EvJob *job);
+
+ /* Signals */
+ void (* cancelled) (EvJob *job);
+ void (* finished) (EvJob *job);
};
struct _EvJobLinks
@@ -194,6 +211,9 @@ struct _EvJobFonts
struct _EvJobFontsClass
{
EvJobClass parent_class;
+
+ /* Signals */
+ void (* updated) (EvJobFonts *job);
};
struct _EvJobLoad
@@ -203,7 +223,6 @@ struct _EvJobLoad
EvLinkDest *dest;
EvWindowRunMode mode;
gchar *search_string;
- GError *error;
gchar *uri;
};
@@ -216,7 +235,6 @@ struct _EvJobSave
{
EvJob parent;
- GError *error;
gchar *uri;
gchar *document_uri;
};
@@ -230,7 +248,6 @@ struct _EvJobPrint
{
EvJob parent;
- GError *error;
const gchar *format;
gchar *temp_file;
EvPrintRange *ranges;
@@ -251,12 +268,26 @@ struct _EvJobPrintClass
/* Base job class */
GType ev_job_get_type (void) G_GNUC_CONST;
-void ev_job_finished (EvJob *job);
+gboolean ev_job_run (EvJob *job);
+void ev_job_cancel (EvJob *job);
+void ev_job_failed (EvJob *job,
+ GQuark domain,
+ gint code,
+ const gchar *format,
+ ...);
+void ev_job_failed_from_error (EvJob *job,
+ GError *error);
+void ev_job_succeeded (EvJob *job);
+gboolean ev_job_is_cancelled (EvJob *job);
+gboolean ev_job_is_finished (EvJob *job);
+gboolean ev_job_is_failed (EvJob *job);
+EvJobRunMode ev_job_get_run_mode (EvJob *job);
+void ev_job_set_run_mode (EvJob *job,
+ EvJobRunMode run_mode);
/* EvJobLinks */
GType ev_job_links_get_type (void) G_GNUC_CONST;
EvJob *ev_job_links_new (EvDocument *document);
-void ev_job_links_run (EvJobLinks *thumbnail);
/* EvJobRender */
GType ev_job_render_get_type (void) G_GNUC_CONST;
@@ -272,20 +303,15 @@ void ev_job_render_set_selection_info (EvJobRender *job,
EvSelectionStyle selection_style,
GdkColor *text,
GdkColor *base);
-void ev_job_render_run (EvJobRender *thumbnail);
-
/* EvJobThumbnail */
GType ev_job_thumbnail_get_type (void) G_GNUC_CONST;
EvJob *ev_job_thumbnail_new (EvDocument *document,
gint page,
gint rotation,
gdouble scale);
-void ev_job_thumbnail_run (EvJobThumbnail *thumbnail);
-
/* EvJobFonts */
GType ev_job_fonts_get_type (void) G_GNUC_CONST;
EvJob *ev_job_fonts_new (EvDocument *document);
-void ev_job_fonts_run (EvJobFonts *fonts);
/* EvJobLoad */
GType ev_job_load_get_type (void) G_GNUC_CONST;
@@ -295,14 +321,12 @@ EvJob *ev_job_load_new (const gchar *uri,
const gchar *search_string);
void ev_job_load_set_uri (EvJobLoad *load,
const gchar *uri);
-void ev_job_load_run (EvJobLoad *load);
/* EvJobSave */
GType ev_job_save_get_type (void) G_GNUC_CONST;
EvJob *ev_job_save_new (EvDocument *document,
const gchar *uri,
const gchar *document_uri);
-void ev_job_save_run (EvJobSave *save);
/* EvJobPrint */
GType ev_job_print_get_type (void) G_GNUC_CONST;
@@ -317,7 +341,6 @@ EvJob *ev_job_print_new (EvDocument *document,
gint copies,
gdouble collate,
gdouble reverse);
-void ev_job_print_run (EvJobPrint *print);
G_END_DECLS
diff --git a/shell/ev-page-cache.c b/shell/ev-page-cache.c
index 8b8bedc..bbddbbc 100644
--- a/shell/ev-page-cache.c
+++ b/shell/ev-page-cache.c
@@ -1,6 +1,5 @@
#include <config.h>
#include "ev-page-cache.h"
-#include "ev-job-queue.h"
#include "ev-document-thumbnails.h"
#include "ev-page.h"
#include <stdlib.h>
diff --git a/shell/ev-pixbuf-cache.c b/shell/ev-pixbuf-cache.c
index 25b6f2c..91c2478 100644
--- a/shell/ev-pixbuf-cache.c
+++ b/shell/ev-pixbuf-cache.c
@@ -1,6 +1,6 @@
#include <config.h>
#include "ev-pixbuf-cache.h"
-#include "ev-job-queue.h"
+#include "ev-job-scheduler.h"
#include "ev-page-cache.h"
#include "ev-document-images.h"
#include "ev-document-forms.h"
@@ -163,8 +163,8 @@ dispose_cache_job_info (CacheJobInfo *job_info,
g_signal_handlers_disconnect_by_func (job_info->job,
G_CALLBACK (job_finished_cb),
data);
- ev_job_queue_remove_job (job_info->job);
- g_object_unref (G_OBJECT (job_info->job));
+ ev_job_cancel (job_info->job);
+ g_object_unref (job_info->job);
job_info->job = NULL;
}
if (job_info->surface) {
@@ -313,7 +313,7 @@ check_job_size_and_unref (EvPixbufCache *pixbuf_cache,
g_signal_handlers_disconnect_by_func (job_info->job,
G_CALLBACK (job_finished_cb),
pixbuf_cache);
- ev_job_queue_remove_job (job_info->job);
+ ev_job_cancel (job_info->job);
g_object_unref (job_info->job);
job_info->job = NULL;
}
@@ -330,11 +330,11 @@ move_one_job (CacheJobInfo *job_info,
CacheJobInfo *new_next_job,
int start_page,
int end_page,
- EvJobPriority priority)
+ gint priority)
{
CacheJobInfo *target_page = NULL;
int page_offset;
- EvJobPriority new_priority;
+ gint new_priority;
if (page < (start_page - pixbuf_cache->preload_cache_size) ||
page > (end_page + pixbuf_cache->preload_cache_size)) {
@@ -361,7 +361,7 @@ move_one_job (CacheJobInfo *job_info,
page_offset = page - start_page;
g_assert (page_offset >= 0 &&
page_offset <= ((end_page - start_page) + 1));
- new_priority = EV_JOB_PRIORITY_HIGH;
+ new_priority = EV_JOB_PRIORITY_URGENT;
target_page = new_job_list + page_offset;
}
@@ -374,7 +374,7 @@ move_one_job (CacheJobInfo *job_info,
job_info->form_field_mapping = NULL;
if (new_priority != priority && target_page->job) {
- ev_job_queue_update_job (target_page->job, new_priority);
+ ev_job_scheduler_update_job (target_page->job, new_priority);
}
}
@@ -421,7 +421,7 @@ ev_pixbuf_cache_update_range (EvPixbufCache *pixbuf_cache,
move_one_job (pixbuf_cache->job_list + i,
pixbuf_cache, page,
new_job_list, new_prev_job, new_next_job,
- start_page, end_page, EV_JOB_PRIORITY_HIGH);
+ start_page, end_page, EV_JOB_PRIORITY_URGENT);
page ++;
}
@@ -529,8 +529,8 @@ copy_job_to_job_info (EvJobRender *job_render,
g_signal_handlers_disconnect_by_func (job_info->job,
G_CALLBACK (job_finished_cb),
pixbuf_cache);
- ev_job_queue_remove_job (job_info->job);
- g_object_unref (G_OBJECT (job_info->job));
+ ev_job_cancel (job_info->job);
+ g_object_unref (job_info->job);
job_info->job = NULL;
}
}
@@ -647,13 +647,13 @@ add_job (EvPixbufCache *pixbuf_cache,
text, base);
}
- ev_job_queue_add_job (job_info->job, priority);
g_signal_connect (G_OBJECT (job_info->job), "page-ready",
G_CALLBACK (job_page_ready_cb),
pixbuf_cache);
g_signal_connect (G_OBJECT (job_info->job), "finished",
G_CALLBACK (job_finished_cb),
pixbuf_cache);
+ ev_job_scheduler_push_job (job_info->job, priority);
}
static void
@@ -701,7 +701,7 @@ ev_pixbuf_cache_add_jobs_if_needed (EvPixbufCache *pixbuf_cache,
add_job_if_needed (pixbuf_cache, job_info,
page_cache, page, rotation, scale,
- EV_JOB_PRIORITY_HIGH);
+ EV_JOB_PRIORITY_URGENT);
}
for (i = FIRST_VISABLE_PREV(pixbuf_cache); i < pixbuf_cache->preload_cache_size; i++) {
@@ -1235,7 +1235,7 @@ ev_pixbuf_cache_reload_page (EvPixbufCache *pixbuf_cache,
add_job (pixbuf_cache, job_info, page_cache, region,
width, height, page, rotation, scale,
- EV_JOB_PRIORITY_HIGH);
+ EV_JOB_PRIORITY_URGENT);
}
diff --git a/shell/ev-pixbuf-cache.h b/shell/ev-pixbuf-cache.h
index ed1c1ec..0b65bf8 100644
--- a/shell/ev-pixbuf-cache.h
+++ b/shell/ev-pixbuf-cache.h
@@ -27,7 +27,6 @@
#include <gtk/gtkwidget.h>
#include "ev-document.h"
#include "ev-selection.h"
-#include "ev-job-queue.h"
G_BEGIN_DECLS
diff --git a/shell/ev-properties-fonts.c b/shell/ev-properties-fonts.c
index 54ed063..385cda1 100644
--- a/shell/ev-properties-fonts.c
+++ b/shell/ev-properties-fonts.c
@@ -25,7 +25,7 @@
#include "ev-properties-fonts.h"
#include "ev-document-fonts.h"
#include "ev-jobs.h"
-#include "ev-job-queue.h"
+#include "ev-job-scheduler.h"
#include <glib/gi18n.h>
#include <gtk/gtktreeview.h>
@@ -63,12 +63,10 @@ ev_properties_fonts_dispose (GObject *object)
}
if (properties->fonts_job) {
-
- g_signal_handlers_disconnect_by_func
- (properties->fonts_job,
- job_fonts_finished_cb,
- properties);
- ev_job_queue_remove_job (properties->fonts_job);
+ g_signal_handlers_disconnect_by_func (properties->fonts_job,
+ job_fonts_finished_cb,
+ properties);
+ ev_job_cancel (properties->fonts_job);
g_object_unref (properties->fonts_job);
properties->fonts_job = NULL;
@@ -161,29 +159,23 @@ update_progress_label (GtkWidget *label, double progress)
static void
job_fonts_finished_cb (EvJob *job, EvPropertiesFonts *properties)
-{
- EvDocumentFonts *document_fonts = EV_DOCUMENT_FONTS (job->document);
- double progress;
-
- progress = ev_document_fonts_get_progress (document_fonts);
- update_progress_label (properties->fonts_progress_label, progress);
+{
+ g_signal_handlers_disconnect_by_func (job, job_fonts_finished_cb, properties);
+ g_object_unref (properties->fonts_job);
+ properties->fonts_job = NULL;
+}
- if (EV_JOB_FONTS (job)->scan_completed) {
- g_signal_handlers_disconnect_by_func
- (job, job_fonts_finished_cb, properties);
- g_object_unref (properties->fonts_job);
- properties->fonts_job = NULL;
- } else {
- GtkTreeModel *model;
+static void
+job_fonts_updated_cb (EvJobFonts *job, gdouble progress, EvPropertiesFonts *properties)
+{
+ GtkTreeModel *model;
+ EvDocumentFonts *document_fonts = EV_DOCUMENT_FONTS (properties->document);
- model = gtk_tree_view_get_model
- (GTK_TREE_VIEW (properties->fonts_treeview));
- ev_document_doc_mutex_lock ();
- ev_document_fonts_fill_model (document_fonts, model);
- ev_document_doc_mutex_unlock ();
+ update_progress_label (properties->fonts_progress_label, progress);
- ev_job_queue_add_job (job, EV_JOB_PRIORITY_LOW);
- }
+ model = gtk_tree_view_get_model (GTK_TREE_VIEW (properties->fonts_treeview));
+ /* Documen lock is already held by the jop */
+ ev_document_fonts_fill_model (document_fonts, model);
}
void
@@ -200,10 +192,13 @@ ev_properties_fonts_set_document (EvPropertiesFonts *properties,
gtk_tree_view_set_model (tree_view, GTK_TREE_MODEL (list_store));
properties->fonts_job = ev_job_fonts_new (properties->document);
+ g_signal_connect (properties->fonts_job, "updated",
+ G_CALLBACK (job_fonts_updated_cb),
+ properties);
g_signal_connect (properties->fonts_job, "finished",
G_CALLBACK (job_fonts_finished_cb),
properties);
- ev_job_queue_add_job (properties->fonts_job, EV_JOB_PRIORITY_LOW);
+ ev_job_scheduler_push_job (properties->fonts_job, EV_JOB_PRIORITY_NONE);
}
GtkWidget *
diff --git a/shell/ev-sidebar-links.c b/shell/ev-sidebar-links.c
index f623f1e..1389edd 100644
--- a/shell/ev-sidebar-links.c
+++ b/shell/ev-sidebar-links.c
@@ -30,7 +30,7 @@
#include "ev-sidebar-page.h"
#include "ev-sidebar-links.h"
-#include "ev-job-queue.h"
+#include "ev-job-scheduler.h"
#include "ev-document-links.h"
#include "ev-window.h"
@@ -145,7 +145,7 @@ ev_sidebar_links_dispose (GObject *object)
if (sidebar->priv->job) {
g_signal_handlers_disconnect_by_func (sidebar->priv->job,
job_finished_callback, sidebar);
- ev_job_queue_remove_job (sidebar->priv->job);
+ ev_job_cancel (sidebar->priv->job);
g_object_unref (sidebar->priv->job);
sidebar->priv->job = NULL;
}
@@ -702,7 +702,7 @@ ev_sidebar_links_set_document (EvSidebarPage *sidebar_page,
G_CALLBACK (job_finished_callback),
sidebar_links);
/* The priority doesn't matter for this job */
- ev_job_queue_add_job (priv->job, EV_JOB_PRIORITY_LOW);
+ ev_job_scheduler_push_job (priv->job, EV_JOB_PRIORITY_NONE);
}
static gboolean
diff --git a/shell/ev-sidebar-thumbnails.c b/shell/ev-sidebar-thumbnails.c
index 74b4ab7..7fe62f1 100644
--- a/shell/ev-sidebar-thumbnails.c
+++ b/shell/ev-sidebar-thumbnails.c
@@ -34,7 +34,7 @@
#include "ev-sidebar-thumbnails.h"
#include "ev-document-thumbnails.h"
#include "ev-document-misc.h"
-#include "ev-job-queue.h"
+#include "ev-job-scheduler.h"
#include "ev-window.h"
#include "ev-utils.h"
@@ -207,7 +207,7 @@ clear_range (EvSidebarThumbnails *sidebar_thumbnails,
if (job) {
g_signal_handlers_disconnect_by_func (job, thumbnail_job_completed_callback, sidebar_thumbnails);
- ev_job_queue_remove_job (EV_JOB (job));
+ ev_job_cancel (EV_JOB (job));
g_object_unref (job);
}
@@ -263,7 +263,7 @@ add_range (EvSidebarThumbnails *sidebar_thumbnails,
job = ev_job_thumbnail_new (priv->document,
page, priv->rotation,
get_scale_for_page (sidebar_thumbnails, page));
- ev_job_queue_add_job (EV_JOB (job), EV_JOB_PRIORITY_HIGH);
+ ev_job_scheduler_push_job (EV_JOB (job), EV_JOB_PRIORITY_HIGH);
g_object_set_data_full (G_OBJECT (job), "tree_iter",
gtk_tree_iter_copy (&iter),
@@ -688,8 +688,8 @@ ev_sidebar_thumbnails_set_document (EvSidebarPage *sidebar_page,
static gboolean
ev_sidebar_thumbnails_clear_job (GtkTreeModel *model,
- GtkTreePath *path,
- GtkTreeIter *iter,
+ GtkTreePath *path,
+ GtkTreeIter *iter,
gpointer data)
{
EvJob *job;
@@ -697,7 +697,7 @@ ev_sidebar_thumbnails_clear_job (GtkTreeModel *model,
gtk_tree_model_get (model, iter, COLUMN_JOB, &job, -1);
if (job != NULL) {
- ev_job_queue_remove_job (job);
+ ev_job_cancel (job);
g_signal_handlers_disconnect_by_func (job, thumbnail_job_completed_callback, data);
g_object_unref (job);
}
diff --git a/shell/ev-view-private.h b/shell/ev-view-private.h
index 3e72e82..1618417 100644
--- a/shell/ev-view-private.h
+++ b/shell/ev-view-private.h
@@ -24,6 +24,7 @@
#include "ev-view.h"
#include "ev-pixbuf-cache.h"
#include "ev-page-cache.h"
+#include "ev-jobs.h"
#include "ev-image.h"
#include "ev-form-field.h"
#include "ev-selection.h"
diff --git a/shell/ev-view.c b/shell/ev-view.c
index bc3cb98..49b604b 100644
--- a/shell/ev-view.c
+++ b/shell/ev-view.c
@@ -39,7 +39,6 @@
#include "ev-document-transition.h"
#include "ev-document-forms.h"
#include "ev-document-misc.h"
-#include "ev-job-queue.h"
#include "ev-page-cache.h"
#include "ev-pixbuf-cache.h"
#include "ev-transition-animation.h"
diff --git a/shell/ev-window.c b/shell/ev-window.c
index 7d08ebf..4c312ea 100644
--- a/shell/ev-window.c
+++ b/shell/ev-window.c
@@ -49,7 +49,7 @@
#include "ev-document-images.h"
#include "ev-document-security.h"
#include "ev-document-factory.h"
-#include "ev-job-queue.h"
+#include "ev-job-scheduler.h"
#include "ev-jobs.h"
#include "ev-sidebar-page.h"
#include "eggfindbar.h"
@@ -221,16 +221,16 @@ static void ev_window_sidebar_visibility_changed_cb (EvSidebar *ev_si
EvWindow *ev_window);
static void ev_window_set_page_mode (EvWindow *window,
EvWindowPageMode page_mode);
-static void ev_window_load_job_cb (EvJobLoad *job,
+static void ev_window_load_job_cb (EvJob *job,
gpointer data);
static void ev_window_reload_document (EvWindow *window);
-static void ev_window_reload_job_cb (EvJobLoad *job,
+static void ev_window_reload_job_cb (EvJob *job,
EvWindow *window);
static void ev_window_set_icon_from_thumbnail (EvJobThumbnail *job,
EvWindow *ev_window);
-static void ev_window_print_job_cb (EvJobPrint *job,
+static void ev_window_print_job_cb (EvJob *job,
EvWindow *window);
-static void ev_window_save_job_cb (EvJobSave *save,
+static void ev_window_save_job_cb (EvJob *save,
EvWindow *window);
static void ev_window_sizing_mode_changed_cb (EvView *view,
GParamSpec *pspec,
@@ -1080,8 +1080,9 @@ static void
ev_window_clear_thumbnail_job (EvWindow *ev_window)
{
if (ev_window->priv->thumbnail_job != NULL) {
- ev_job_queue_remove_job (ev_window->priv->thumbnail_job);
-
+ if (!ev_job_is_finished (ev_window->priv->thumbnail_job))
+ ev_job_cancel (ev_window->priv->thumbnail_job);
+
g_signal_handlers_disconnect_by_func (ev_window->priv->thumbnail_job,
ev_window_set_icon_from_thumbnail,
ev_window);
@@ -1125,7 +1126,7 @@ ev_window_refresh_window_thumbnail (EvWindow *ev_window, int rotation)
g_signal_connect (ev_window->priv->thumbnail_job, "finished",
G_CALLBACK (ev_window_set_icon_from_thumbnail),
ev_window);
- ev_job_queue_add_job (EV_JOB (ev_window->priv->thumbnail_job), EV_JOB_PRIORITY_LOW);
+ ev_job_scheduler_push_job (ev_window->priv->thumbnail_job, EV_JOB_PRIORITY_NONE);
}
static gboolean
@@ -1231,7 +1232,7 @@ password_dialog_response (GtkWidget *password_dialog,
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->load_job, EV_JOB_PRIORITY_HIGH);
+ ev_job_scheduler_push_job (ev_window->priv->load_job, EV_JOB_PRIORITY_NONE);
gtk_widget_destroy (password_dialog);
@@ -1277,9 +1278,8 @@ static void
ev_window_clear_load_job (EvWindow *ev_window)
{
if (ev_window->priv->load_job != NULL) {
-
- if (!ev_window->priv->load_job->finished)
- ev_job_queue_remove_job (ev_window->priv->load_job);
+ if (!ev_job_is_finished (ev_window->priv->load_job))
+ ev_job_cancel (ev_window->priv->load_job);
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);
@@ -1291,9 +1291,8 @@ static void
ev_window_clear_reload_job (EvWindow *ev_window)
{
if (ev_window->priv->reload_job != NULL) {
-
- if (!ev_window->priv->reload_job->finished)
- ev_job_queue_remove_job (ev_window->priv->reload_job);
+ if (!ev_job_is_finished (ev_window->priv->reload_job))
+ ev_job_cancel (ev_window->priv->reload_job);
g_signal_handlers_disconnect_by_func (ev_window->priv->reload_job, ev_window_reload_job_cb, ev_window);
g_object_unref (ev_window->priv->reload_job);
@@ -1349,21 +1348,22 @@ ev_window_clear_temp_file (EvWindow *ev_window)
* function should _not_ necessarily expect those to exist after being
* called. */
static void
-ev_window_load_job_cb (EvJobLoad *job,
+ev_window_load_job_cb (EvJob *job,
gpointer data)
{
EvWindow *ev_window = EV_WINDOW (data);
EvDocument *document = EV_JOB (job)->document;
+ EvJobLoad *job_load = EV_JOB_LOAD (job);
- g_assert (job->uri);
+ g_assert (job_load->uri);
ev_view_set_loading (EV_VIEW (ev_window->priv->view), FALSE);
/* Success! */
- if (job->error == NULL) {
+ if (!ev_job_is_failed (job)) {
ev_window_set_document (ev_window, document);
- if (job->mode != EV_WINDOW_MODE_PREVIEW) {
+ if (job_load->mode != EV_WINDOW_MODE_PREVIEW) {
setup_view_from_metadata (ev_window);
}
@@ -1371,17 +1371,17 @@ ev_window_load_job_cb (EvJobLoad *job,
ev_window_add_recent (ev_window, ev_window->priv->uri);
}
- if (job->dest) {
+ if (job_load->dest) {
EvLink *link;
EvLinkAction *link_action;
- link_action = ev_link_action_new_dest (g_object_ref (job->dest));
+ link_action = ev_link_action_new_dest (g_object_ref (job_load->dest));
link = ev_link_new (NULL, link_action);
ev_view_handle_link (EV_VIEW (ev_window->priv->view), link);
g_object_unref (link);
}
- switch (job->mode) {
+ switch (job_load->mode) {
case EV_WINDOW_MODE_FULLSCREEN:
ev_window_run_fullscreen (ev_window);
break;
@@ -1395,14 +1395,23 @@ ev_window_load_job_cb (EvJobLoad *job,
break;
}
- if (job->search_string && EV_IS_DOCUMENT_FIND (document)) {
+ /* Restart the search after reloading */
+ if (ev_window->priv->in_reload) {
+ GtkWidget *widget;
+
+ widget = gtk_window_get_focus (GTK_WINDOW (ev_window));
+ if (widget && gtk_widget_get_ancestor (widget, EGG_TYPE_FIND_BAR)) {
+ find_bar_search_changed_cb (EGG_FIND_BAR (ev_window->priv->find_bar),
+ NULL, ev_window);
+ }
+ } else if (job_load->search_string && EV_IS_DOCUMENT_FIND (document)) {
ev_window_cmd_edit_find (NULL, ev_window);
egg_find_bar_set_search_string (EGG_FIND_BAR (ev_window->priv->find_bar),
- job->search_string);
+ job_load->search_string);
}
/* Create a monitor for the document */
- ev_window->priv->monitor = ev_file_monitor_new (job->uri);
+ ev_window->priv->monitor = ev_file_monitor_new (job_load->uri);
g_signal_connect_swapped (G_OBJECT (ev_window->priv->monitor), "changed",
G_CALLBACK (ev_window_document_changed),
ev_window);
@@ -1418,7 +1427,7 @@ ev_window_load_job_cb (EvJobLoad *job,
setup_view_from_metadata (ev_window);
- file = g_file_new_for_uri (job->uri);
+ file = g_file_new_for_uri (job_load->uri);
base_name = g_file_get_basename (file);
ev_password_view_set_file_name (EV_PASSWORD_VIEW (ev_window->priv->password_view),
base_name);
@@ -1436,18 +1445,18 @@ ev_window_load_job_cb (EvJobLoad *job,
}
static void
-ev_window_reload_job_cb (EvJobLoad *job,
- EvWindow *ev_window)
+ev_window_reload_job_cb (EvJob *job,
+ EvWindow *ev_window)
{
GtkWidget *widget;
-
- if (job->error) {
+
+ if (ev_job_is_failed (job)) {
ev_window_clear_reload_job (ev_window);
ev_window->priv->in_reload = FALSE;
return;
}
- ev_window_set_document (ev_window, EV_JOB (job)->document);
+ ev_window_set_document (ev_window, job->document);
/* Restart the search after reloading */
widget = gtk_window_get_focus (GTK_WINDOW (ev_window));
@@ -1539,7 +1548,7 @@ window_open_file_copy_ready_cb (GFile *source,
g_file_copy_finish (source, async_result, &error);
if (!error) {
- ev_job_queue_add_job (ev_window->priv->load_job, EV_JOB_PRIORITY_HIGH);
+ ev_job_scheduler_push_job (ev_window->priv->load_job, EV_JOB_PRIORITY_NONE);
g_object_unref (source);
return;
@@ -1649,7 +1658,7 @@ ev_window_open_uri (EvWindow *ev_window,
ev_window_load_file_remote (ev_window, source_file);
} else {
g_object_unref (source_file);
- ev_job_queue_add_job (ev_window->priv->load_job, EV_JOB_PRIORITY_HIGH);
+ ev_job_scheduler_push_job (ev_window->priv->load_job, EV_JOB_PRIORITY_NONE);
}
}
@@ -1666,7 +1675,7 @@ ev_window_reload_document (EvWindow *ev_window)
g_signal_connect (ev_window->priv->reload_job, "finished",
G_CALLBACK (ev_window_reload_job_cb),
ev_window);
- ev_job_queue_add_job (ev_window->priv->reload_job, EV_JOB_PRIORITY_LOW);
+ ev_job_scheduler_push_job (ev_window->priv->reload_job, EV_JOB_PRIORITY_NONE);
}
static void
@@ -2067,8 +2076,8 @@ static void
ev_window_clear_save_job (EvWindow *ev_window)
{
if (ev_window->priv->save_job != NULL) {
- if (!ev_window->priv->save_job->finished)
- ev_job_queue_remove_job (ev_window->priv->save_job);
+ if (!ev_job_is_finished (ev_window->priv->save_job))
+ ev_job_cancel (ev_window->priv->save_job);
g_signal_handlers_disconnect_by_func (ev_window->priv->save_job,
ev_window_save_job_cb,
@@ -2079,13 +2088,14 @@ ev_window_clear_save_job (EvWindow *ev_window)
}
static void
-ev_window_save_job_cb (EvJobSave *job,
+ev_window_save_job_cb (EvJob *job,
EvWindow *window)
{
- if (job->error) {
+ if (ev_job_is_failed (job)) {
gchar *msg;
- msg = g_strdup_printf (_("The file could not be saved as ā€œ%sā€."), job->uri);
+ msg = g_strdup_printf (_("The file could not be saved as ā€œ%sā€."),
+ EV_JOB_SAVE (job)->uri);
ev_window_error_message (GTK_WINDOW (window), msg, job->error);
g_free (msg);
}
@@ -2114,10 +2124,9 @@ file_save_dialog_response_cb (GtkWidget *fc,
G_CALLBACK (ev_window_save_job_cb),
ev_window);
/* The priority doesn't matter for this job */
- ev_job_queue_add_job (ev_window->priv->save_job, EV_JOB_PRIORITY_LOW);
+ ev_job_scheduler_push_job (ev_window->priv->save_job, EV_JOB_PRIORITY_NONE);
g_free (uri);
-
gtk_widget_destroy (fc);
}
@@ -2187,8 +2196,8 @@ static void
ev_window_clear_print_job (EvWindow *window)
{
if (window->priv->print_job) {
- if (!window->priv->print_job->finished)
- ev_job_queue_remove_job (window->priv->print_job);
+ if (!ev_job_is_finished (window->priv->print_job))
+ ev_job_cancel (window->priv->print_job);
g_signal_handlers_disconnect_by_func (window->priv->print_job,
ev_window_print_job_cb,
@@ -2349,18 +2358,18 @@ ev_window_print_send (EvWindow *window,
}
static void
-ev_window_print_job_cb (EvJobPrint *job,
- EvWindow *window)
+ev_window_print_job_cb (EvJob *job,
+ EvWindow *window)
{
- if (job->error) {
+ if (ev_job_is_failed (job)) {
g_warning ("%s", job->error->message);
ev_window_clear_print_job (window);
return;
}
- g_assert (job->temp_file != NULL);
+ g_assert (EV_JOB_PRINT (job)->temp_file != NULL);
- ev_window_print_send (window, job->temp_file);
+ ev_window_print_send (window, EV_JOB_PRINT (job)->temp_file);
}
static gboolean
@@ -2494,7 +2503,7 @@ ev_window_print_dialog_response_cb (GtkDialog *dialog,
G_CALLBACK (ev_window_print_job_cb),
window);
/* The priority doesn't matter for this job */
- ev_job_queue_add_job (window->priv->print_job, EV_JOB_PRIORITY_LOW);
+ ev_job_scheduler_push_job (window->priv->print_job, EV_JOB_PRIORITY_NONE);
gtk_widget_destroy (GTK_WIDGET (dialog));
window->priv->print_dialog = NULL;
diff --git a/shell/main.c b/shell/main.c
index f230ea8..eb5c08a 100644
--- a/shell/main.c
+++ b/shell/main.c
@@ -41,7 +41,6 @@
#endif
#include "ev-stock-icons.h"
-#include "ev-job-queue.h"
#include "ev-file-helpers.h"
#include "ev-backends-manager.h"
@@ -391,7 +390,6 @@ main (int argc, char *argv[])
ev_metadata_manager_init ();
}
- ev_job_queue_init ();
g_set_application_name (_("Evince Document Viewer"));
ev_file_helpers_init ();