From bca369672136e5ff831ece9832afd42085808fba Mon Sep 17 00:00:00 2001 From: Nickolay V. Shmyrev Date: Tue, 07 Jun 2005 23:28:54 +0000 Subject: PageCache and EvJobs are moved from backend to shell. Two new jobs to load document in background and a statusbar to display this process. FileChooser now can select multiple uris. --- diff --git a/ChangeLog b/ChangeLog index 43d7261..f9e6d9f 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,5 +1,109 @@ 2005-06-08 Nickolay V. Shmyrev + * backend/Makefile.am: + * backend/ev-document-fonts.c: + * backend/ev-document-links.c: + * backend/ev-document.c: (ev_document_load): + * backend/ev-document.h: + * backend/ev-job-queue.c: + * backend/ev-job-queue.h: + * backend/ev-jobs.c: + * backend/ev-jobs.h: + * backend/ev-page-cache.c: + * backend/ev-page-cache.h: + + EvPageCache and EvJobs are moved to shell. + + * lib/ev-file-helpers.c: (ev_file_helpers_shutdown), + (ev_tmp_filename): + * lib/ev-file-helpers.h: + + New helper to work with temporary files + + * shell/Makefile.am: + * shell/ev-application.c: (ev_application_open): + * shell/ev-application.h: + * shell/ev-job-queue.c: (remove_job_from_queue_locked), + (remove_job_from_async_queue), (add_job_to_async_queue), + (add_job_to_queue_locked), (notify_finished), (job_finished_cb), + (handle_job), (search_for_jobs_unlocked), + (no_jobs_available_unlocked), (ev_render_thread), + (ev_job_queue_run_next), (ev_job_queue_init), (find_queue), + (ev_job_queue_add_job), (move_job_async), (move_job), + (ev_job_queue_update_job), (ev_job_queue_remove_job): + * shell/ev-job-queue.h: + * shell/ev-job-xfer.c: (ev_job_xfer_init), (ev_job_xfer_dispose), + (ev_job_xfer_class_init), (ev_job_xfer_new), (ev_job_xfer_run): + * shell/ev-job-xfer.h: + * shell/ev-jobs.c: (ev_job_init), (ev_job_dispose), + (ev_job_class_init), (ev_job_links_init), (ev_job_links_dispose), + (ev_job_links_class_init), (ev_job_render_init), + (ev_job_render_dispose), (ev_job_render_class_init), + (ev_job_thumbnail_init), (ev_job_thumbnail_dispose), + (ev_job_thumbnail_class_init), (ev_job_load_init), + (ev_job_load_dispose), (ev_job_load_class_init), (ev_job_finished), + (ev_job_links_new), (ev_job_links_run), (ev_job_render_new), + (render_finished_cb), (ev_job_render_run), (ev_job_thumbnail_new), + (ev_job_thumbnail_run), (ev_job_load_new), (ev_job_load_run): + * shell/ev-jobs.h: + * shell/ev-page-action.c: (ev_page_action_set_document): + * shell/ev-page-cache.c: (ev_page_cache_init), + (ev_page_cache_class_init), (ev_page_cache_finalize), + (ev_page_cache_new), (ev_page_cache_get_n_pages), + (ev_page_cache_get_current_page), (ev_page_cache_set_current_page), + (ev_page_cache_set_page_label), (ev_page_cache_set_link), + (ev_page_cache_get_title), (ev_page_cache_get_size), + (ev_page_cache_get_max_width), (ev_page_cache_get_max_height), + (ev_page_cache_get_height_to_page), + (ev_page_cache_get_max_label_chars), + (ev_page_cache_get_page_label), + (ev_page_cache_has_nonnumeric_page_labels), + (ev_page_cache_get_info), (ev_page_cache_next_page), + (ev_page_cache_prev_page), (ev_page_cache_get): + * shell/ev-page-cache.h: + * shell/ev-pixbuf-cache.c: (ev_pixbuf_cache_update_range), + (ev_pixbuf_cache_clear_job_sizes), + (ev_pixbuf_cache_add_jobs_if_needed), + (ev_pixbuf_cache_set_page_range): + * shell/ev-print-job.c: (ev_print_job_use_print_dialog_settings): + * shell/ev-sidebar-links.c: (ev_sidebar_links_set_document): + * shell/ev-sidebar-thumbnails.c: + (ev_sidebar_tree_selection_changed), + (ev_sidebar_thumbnails_set_document): + * shell/ev-statusbar.c: (ev_statusbar_destroy), + (ev_statusbar_class_init), (ev_statusbar_init), (ev_statusbar_new), + (ev_statusbar_get_context_id), (ev_statusbar_push), + (ev_statusbar_pop), (ev_statusbar_set_maximized), + (ev_statusbar_pulse), (ev_statusbar_show_progress), + (ev_statusbar_set_progress): + * shell/ev-statusbar.h: + * shell/ev-view.c: (ev_view_set_document), (ev_view_find_next), + (ev_view_find_previous): + * shell/ev-window.c: (ev_window_is_empty), + (ev_window_setup_document), (password_dialog_response), + (ev_window_clear_jobs), (ev_window_load_job_cb), + (ev_window_xfer_job_cb), (ev_window_open_uri), + (ev_window_open_uri_list), (ev_window_cmd_recent_file_activate), + (ev_window_print), (ev_window_print_range), + (ev_window_state_event), (ev_window_cmd_view_reload), + (menu_item_select_cb), (menu_item_deselect_cb), + (view_status_changed_cb), (ev_window_dispose), + (drag_data_received_cb), (ev_window_init): + * shell/ev-window.h: + * shell/main.c: (load_files): + + New statusbar to show progress on idle. Two new jobs - + xfer job and load job to load document in background. And update + of page_cache clients to new location of code. + +2005-06-08 Carlos Garcia Campos + + * shell/ev-application.c, shell/ev-window.[ch]: Allow multiple + selection in open dialog. It also remembers the last visited directory + in the current session. + +2005-06-08 Nickolay V. Shmyrev + * shell/ev-properties.c: (ev_properties_new): * shell/ev-properties.h: * shell/ev-window.c: (ev_window_cmd_file_properties): diff --git a/backend/Makefile.am b/backend/Makefile.am index 322cc7d..b000dc4 100644 --- a/backend/Makefile.am +++ b/backend/Makefile.am @@ -28,12 +28,6 @@ libevbackend_la_SOURCES= \ ev-document-find.c \ ev-document-find.h \ ev-document-info.h \ - ev-job-queue.h \ - ev-job-queue.c \ - ev-jobs.h \ - ev-jobs.c \ - ev-page-cache.h \ - ev-page-cache.c \ ev-ps-exporter.c \ ev-ps-exporter.h \ ev-document-misc.h \ diff --git a/backend/ev-document-fonts.c b/backend/ev-document-fonts.c index 9c4d4d6..fca1976 100644 --- a/backend/ev-document-fonts.c +++ b/backend/ev-document-fonts.c @@ -24,7 +24,6 @@ #include "config.h" #include "ev-document-fonts.h" -#include "ev-job-queue.h" GType ev_document_fonts_get_type (void) diff --git a/backend/ev-document-links.c b/backend/ev-document-links.c index d9baae0..7ab3468 100644 --- a/backend/ev-document-links.c +++ b/backend/ev-document-links.c @@ -24,7 +24,6 @@ #include "config.h" #include "ev-document-links.h" -#include "ev-job-queue.h" GType ev_document_links_get_type (void) diff --git a/backend/ev-document.c b/backend/ev-document.c index 3793050..d413083 100644 --- a/backend/ev-document.c +++ b/backend/ev-document.c @@ -23,7 +23,6 @@ #include "ev-document.h" #include "ev-backend-marshalers.h" -#include "ev-job-queue.h" static void ev_document_class_init (gpointer g_class); @@ -69,24 +68,6 @@ ev_document_class_init (gpointer g_class) { } -#define PAGE_CACHE_STRING "ev-page-cache" - -EvPageCache * -ev_document_get_page_cache (EvDocument *document) -{ - EvPageCache *page_cache; - - g_return_val_if_fail (EV_IS_DOCUMENT (document), NULL); - - page_cache = g_object_get_data (G_OBJECT (document), PAGE_CACHE_STRING); - if (page_cache == NULL) { - page_cache = _ev_page_cache_new (document); - g_object_set_data_full (G_OBJECT (document), PAGE_CACHE_STRING, page_cache, g_object_unref); - } - - return page_cache; -} - GMutex * ev_document_get_doc_mutex (void) { @@ -120,10 +101,6 @@ ev_document_load (EvDocument *document, LOG ("ev_document_load"); retval = iface->load (document, uri, error); - /* Call this to make the initial cached copy */ - if (retval) - ev_document_get_page_cache (document); - return retval; } diff --git a/backend/ev-document.h b/backend/ev-document.h index 6ff356f..ffc9c2e 100644 --- a/backend/ev-document.h +++ b/backend/ev-document.h @@ -43,7 +43,6 @@ typedef struct _EvDocumentIface EvDocumentIface; typedef struct _EvPageCache EvPageCache; typedef struct _EvPageCacheClass EvPageCacheClass; -#include "ev-page-cache.h" #define EV_DOCUMENT_ERROR ev_document_error_quark () @@ -95,7 +94,6 @@ struct _EvDocumentIface GType ev_document_get_type (void); GQuark ev_document_error_quark (void); -EvPageCache *ev_document_get_page_cache (EvDocument *document); GMutex *ev_document_get_doc_mutex (void); void ev_document_doc_mutex_lock (void); void ev_document_doc_mutex_unlock (void); diff --git a/lib/ev-file-helpers.c b/lib/ev-file-helpers.c index d9daf6a..b093853 100644 --- a/lib/ev-file-helpers.c +++ b/lib/ev-file-helpers.c @@ -25,10 +25,13 @@ #include #include #include +#include #include "ev-file-helpers.h" static char *dot_dir = NULL; +static char *tmp_dir = NULL; +static int count = 0; static gboolean ensure_dir_exists (const char *dir) @@ -77,7 +80,47 @@ ev_file_helpers_init (void) void ev_file_helpers_shutdown (void) -{ +{ + rmdir (tmp_dir); + + g_free (tmp_dir); g_free (dot_dir); + dot_dir = NULL; + tmp_dir = NULL; +} + +gchar* +ev_tmp_filename (void) +{ + gchar *basename; + gchar *filename = NULL; + + if (tmp_dir == NULL) { + gboolean exists; + gchar *dirname; + + dirname = g_strdup_printf ("evince-%u", getpid()); + tmp_dir = g_build_filename (g_get_tmp_dir (), + dirname, + NULL); + g_free (dirname); + + exists = ensure_dir_exists (tmp_dir); + g_assert (exists); + } + + + do { + if (filename != NULL) + g_free (filename); + + basename = g_strdup_printf ("document-%d", count ++); + + filename = g_build_filename (tmp_dir, basename, NULL); + + g_free (basename); + } while (g_file_test (filename, G_FILE_TEST_EXISTS)); + + return filename; } diff --git a/lib/ev-file-helpers.h b/lib/ev-file-helpers.h index 43dc75c..1d19c6d 100644 --- a/lib/ev-file-helpers.h +++ b/lib/ev-file-helpers.h @@ -31,6 +31,8 @@ void ev_file_helpers_init (void); void ev_file_helpers_shutdown (void); +gchar* ev_tmp_filename (void); + G_END_DECLS #endif /* EPHY_FILE_HELPERS_H */ diff --git a/shell/Makefile.am b/shell/Makefile.am index 7668e97..c916987 100644 --- a/shell/Makefile.am +++ b/shell/Makefile.am @@ -58,10 +58,18 @@ evince_SOURCES= \ eggfindbar.h \ ev-application.c \ ev-application.h \ + ev-job-queue.h \ + ev-job-queue.c \ + ev-jobs.h \ + ev-jobs.c \ + ev-job-xfer.c \ + ev-job-xfer.h \ ev-marshal.c \ ev-marshal.h \ ev-page-action.c \ ev-page-action.h \ + ev-page-cache.h \ + ev-page-cache.c \ ev-password.h \ ev-password.c \ ev-password-view.h \ @@ -86,6 +94,8 @@ evince_SOURCES= \ ev-sidebar-page.h \ ev-sidebar-thumbnails.c \ ev-sidebar-thumbnails.h \ + ev-statusbar.c \ + ev-statusbar.h \ ev-stock-icons.c \ ev-stock-icons.h \ main.c \ diff --git a/shell/ev-application.c b/shell/ev-application.c index 43c4068..d10914b 100644 --- a/shell/ev-application.c +++ b/shell/ev-application.c @@ -122,6 +122,7 @@ ev_application_open (EvApplication *application, GError *err) GtkFileFilter *ps_filter; GtkFileFilter *pixbuf_filter; GtkFileFilter *all_filter; + static gchar *folder = NULL; #ifdef ENABLE_DJVU GtkFileFilter *djvu_filter; #endif @@ -139,6 +140,11 @@ ev_application_open (EvApplication *application, GError *err) GTK_STOCK_OPEN, GTK_RESPONSE_OK, NULL); + if (folder) { + gtk_file_chooser_set_current_folder (GTK_FILE_CHOOSER (chooser), + folder); + } + documents_filter = gtk_file_filter_new (); gtk_file_filter_set_name (documents_filter, _("All Documents")); @@ -193,14 +199,17 @@ ev_application_open (EvApplication *application, GError *err) gtk_file_chooser_set_filter (GTK_FILE_CHOOSER (chooser), documents_filter); + gtk_file_chooser_set_select_multiple (GTK_FILE_CHOOSER (chooser), TRUE); + if (gtk_dialog_run (GTK_DIALOG (chooser)) == GTK_RESPONSE_OK) { - char *uri; + GSList *uris; - uri = gtk_file_chooser_get_uri (GTK_FILE_CHOOSER (chooser)); - ev_window_open (ev_window, uri); - gtk_widget_show (GTK_WIDGET (ev_window)); - g_free (uri); - + uris = gtk_file_chooser_get_uris (GTK_FILE_CHOOSER (chooser)); + folder = gtk_file_chooser_get_current_folder (GTK_FILE_CHOOSER (chooser)); + + ev_window_open_uri_list (ev_window, uris); + + g_slist_free (uris); } else { if (!GTK_WIDGET_VISIBLE (ev_window)) gtk_widget_destroy (GTK_WIDGET (ev_window)); diff --git a/shell/ev-application.h b/shell/ev-application.h index e6a3cf5..1d70124 100644 --- a/shell/ev-application.h +++ b/shell/ev-application.h @@ -57,7 +57,7 @@ EvApplication *ev_application_get_instance (void); void ev_application_open (EvApplication *application, GError *err); EvWindow *ev_application_new_window (EvApplication *application); -EvWindow * ev_application_get_empty_window (EvApplication *application); +EvWindow * ev_application_get_empty_window (EvApplication *application); G_END_DECLS diff --git a/backend/ev-job-queue.c b/shell/ev-job-queue.c index 1b3e496..877aae8 100644 --- a/backend/ev-job-queue.c +++ b/shell/ev-job-queue.c @@ -12,6 +12,8 @@ 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 *xfer_queue = NULL; /* Queues used for backends supporting EvAsyncRender interface, they are executed on the main thread */ @@ -93,6 +95,10 @@ handle_job (EvJob *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_XFER (job)) + ev_job_xfer_run (EV_JOB_XFER (job)); else if (EV_IS_JOB_RENDER (job)) ev_job_render_run (EV_JOB_RENDER (job)); @@ -126,6 +132,14 @@ search_for_jobs_unlocked (void) if (job) return job; + job = (EvJob *) g_queue_pop_head (load_queue); + if (job) + return job; + + job = (EvJob *) g_queue_pop_head (xfer_queue); + if (job) + return job; + job = (EvJob *) g_queue_pop_head (thumbnail_queue_low); if (job) return job; @@ -139,6 +153,8 @@ 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 (xfer_queue) && g_queue_is_empty (thumbnail_queue_high) && g_queue_is_empty (thumbnail_queue_low); } @@ -196,6 +212,8 @@ ev_job_queue_init (void) ev_queue_mutex = g_mutex_new (); links_queue = g_queue_new (); + load_queue = g_queue_new (); + xfer_queue = g_queue_new (); render_queue_high = g_queue_new (); render_queue_low = g_queue_new (); async_render_queue_high = g_queue_new (); @@ -229,6 +247,12 @@ find_queue (EvJob *job, 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_XFER (job)) { + /* the priority doesn't effect xfer */ + return xfer_queue; } else if (EV_IS_JOB_LINKS (job)) { /* the priority doesn't effect links */ return links_queue; @@ -367,6 +391,10 @@ ev_job_queue_remove_job (EvJob *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_XFER (job)) { + retval = remove_job_from_queue_locked (xfer_queue, job); } else { g_assert_not_reached (); } diff --git a/backend/ev-job-queue.h b/shell/ev-job-queue.h index e6e4c0e..0a2f24c 100644 --- a/backend/ev-job-queue.h +++ b/shell/ev-job-queue.h @@ -22,6 +22,7 @@ #include #include "ev-jobs.h" +#include "ev-job-xfer.h" G_BEGIN_DECLS diff --git a/shell/ev-job-xfer.c b/shell/ev-job-xfer.c new file mode 100644 index 0000000..b75e9d1 --- /dev/null +++ b/shell/ev-job-xfer.c @@ -0,0 +1,130 @@ +/* this file is part of evince, a gnome document viewer + * + * 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. + */ + +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + + +#include "ev-job-xfer.h" +#include "ev-document-types.h" + +#include +#include + +#include +#include +#include + +static void ev_job_xfer_init (EvJobXfer *job); +static void ev_job_xfer_class_init (EvJobXferClass *class); + +G_DEFINE_TYPE (EvJobXfer, ev_job_xfer, EV_TYPE_JOB) + +static void ev_job_xfer_init (EvJobXfer *job) { /* Do Nothing */ } + +static void +ev_job_xfer_dispose (GObject *object) +{ + EvJobXfer *job = EV_JOB_XFER (object); + + if (job->uri) { + g_free (job->uri); + job->uri = NULL; + } + + if (job->error) { + g_error_free (job->error); + job->error = NULL; + } + + (* G_OBJECT_CLASS (ev_job_xfer_parent_class)->dispose) (object); +} + +static void +ev_job_xfer_class_init (EvJobXferClass *class) +{ + GObjectClass *oclass; + + oclass = G_OBJECT_CLASS (class); + + oclass->dispose = ev_job_xfer_dispose; +} + + +EvJob * +ev_job_xfer_new (const gchar *uri) +{ + EvJobXfer *job; + + job = g_object_new (EV_TYPE_JOB_XFER, NULL); + + job->uri = g_strdup (uri); + + return EV_JOB (job); +} + +void +ev_job_xfer_run (EvJobXfer *job) +{ + GnomeVFSURI *vfs_uri; + char *mime_type; + GType document_type; + + g_return_if_fail (EV_IS_JOB_XFER (job)); + + if (job->error) { + g_error_free (job->error); + job->error = NULL; + } + + vfs_uri = gnome_vfs_uri_new (job->uri); + if (vfs_uri) { + if (!gnome_vfs_uri_exists (vfs_uri)) { + g_set_error (&job->error, + EV_DOCUMENT_ERROR, + 0, + _("The file %s does not exist."), + job->uri); + + EV_JOB (job)->finished = TRUE; + return; + } + } + gnome_vfs_uri_unref (vfs_uri); + + document_type = ev_document_type_lookup (job->uri, &mime_type); + + if (document_type != G_TYPE_INVALID) { + EV_JOB (job)->document = g_object_new (document_type, NULL); + } else { + g_set_error (&job->error, + EV_DOCUMENT_ERROR, + 0, + _("Unhandled MIME type: '%s'"), + mime_type ? mime_type : ""); + EV_JOB (job)->finished = TRUE; + return; + } + + EV_JOB (job)->finished = TRUE; + return; +} + + diff --git a/backend/ev-job-queue.h b/shell/ev-job-xfer.h index e6e4c0e..dba9901 100644 --- a/backend/ev-job-queue.h +++ b/shell/ev-job-xfer.h @@ -17,23 +17,40 @@ * 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_XFER_H__ +#define __EV_JOB_XFER_H__ #include +#include "ev-document.h" #include "ev-jobs.h" G_BEGIN_DECLS +typedef struct _EvJobXfer EvJobXfer; +typedef struct _EvJobXferClass EvJobXferClass; -void ev_job_queue_init (void); +#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_CHACK_CLASS_CAST((klass), EV_TYPE_JOB_XFER, EvJobXferClass)) +#define EV_IS_JOB_XFER(object) (G_TYPE_CHECK_INSTANCE_TYPE((object), EV_TYPE_JOB_XFER)) -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); +struct _EvJobXfer +{ + EvJob parent; + GError *error; + gchar *uri; +}; + +struct _EvJobXferClass +{ + EvJobClass parent_class; +}; + +/* EvJobXfer */ +GType ev_job_xfer_get_type (void); +EvJob *ev_job_xfer_new (const gchar *uri); +void ev_job_xfer_run (EvJobXfer *xfer); G_END_DECLS -#endif /* __EV_JOB_QUEUE_H__ */ +#endif /* __EV_JOB_XFER_H__ */ diff --git a/backend/ev-jobs.c b/shell/ev-jobs.c index 73b0614..be1d3bc 100644 --- a/backend/ev-jobs.c +++ b/shell/ev-jobs.c @@ -12,6 +12,8 @@ static void ev_job_render_init (EvJobRender *job); 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_load_init (EvJobLoad *job); +static void ev_job_load_class_init (EvJobLoadClass *class); enum { @@ -25,7 +27,7 @@ G_DEFINE_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) - +G_DEFINE_TYPE (EvJobLoad, ev_job_load, EV_TYPE_JOB) static void ev_job_init (EvJob *job) { /* Do Nothing */ } @@ -146,6 +148,38 @@ ev_job_thumbnail_class_init (EvJobThumbnailClass *class) oclass->dispose = ev_job_thumbnail_dispose; } +static void ev_job_load_init (EvJobLoad *job) { /* Do Nothing */ } + +static void +ev_job_load_dispose (GObject *object) +{ + EvJobLoad *job; + + job = EV_JOB_LOAD (object); + + if (job->uri) { + g_free (job->uri); + job->uri = NULL; + } + + if (job->error) { + g_error_free (job->error); + job->error = NULL; + } + + (* G_OBJECT_CLASS (ev_job_load_parent_class)->dispose) (object); +} + +static void +ev_job_load_class_init (EvJobLoadClass *class) +{ + GObjectClass *oclass; + + oclass = G_OBJECT_CLASS (class); + + oclass->dispose = ev_job_load_dispose; +} + /* Public functions */ void ev_job_finished (EvJob *job) @@ -272,3 +306,38 @@ ev_job_thumbnail_run (EvJobThumbnail *job) ev_document_doc_mutex_unlock (); } + +EvJob * +ev_job_load_new (EvDocument *document, + const gchar *uri) +{ + EvJobLoad *job; + + job = g_object_new (EV_TYPE_JOB_LOAD, NULL); + + EV_JOB (job)->document = g_object_ref (document); + job->uri = g_strdup (uri); + + return EV_JOB (job); +} + +void +ev_job_load_run (EvJobLoad *job) +{ + g_return_if_fail (EV_IS_JOB_LOAD (job)); + + ev_document_doc_mutex_lock (); + + if (job->error) { + g_error_free (job->error); + job->error = NULL; + } + + ev_document_load (EV_JOB(job)->document, job->uri, &job->error); + + EV_JOB (job)->finished = TRUE; + + ev_document_doc_mutex_unlock (); +} + + diff --git a/backend/ev-jobs.h b/shell/ev-jobs.h index c89aa1e..11a3f09 100644 --- a/backend/ev-jobs.h +++ b/shell/ev-jobs.h @@ -37,6 +37,9 @@ typedef struct _EvJobThumbnailClass EvJobThumbnailClass; typedef struct _EvJobLinks EvJobLinks; typedef struct _EvJobLinksClass EvJobLinksClass; +typedef struct _EvJobLoad EvJobLoad; +typedef struct _EvJobLoadClass EvJobLoadClass; + #define EV_TYPE_JOB (ev_job_get_type()) #define EV_JOB(object) (G_TYPE_CHECK_INSTANCE_CAST((object), EV_TYPE_JOB, EvJob)) #define EV_JOB_CLASS(klass) (G_TYPE_CHACK_CLASS_CAST((klass), EV_TYPE_JOB, EvJobClass)) @@ -57,6 +60,11 @@ typedef struct _EvJobLinksClass EvJobLinksClass; #define EV_JOB_THUMBNAIL_CLASS(klass) (G_TYPE_CHACK_CLASS_CAST((klass), EV_TYPE_JOB_THUMBNAIL, EvJobThumbnailClass)) #define EV_IS_JOB_THUMBNAIL(object) (G_TYPE_CHECK_INSTANCE_TYPE((object), EV_TYPE_JOB_THUMBNAIL)) +#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_CHACK_CLASS_CAST((klass), EV_TYPE_JOB_LOAD, EvJobLoadClass)) +#define EV_IS_JOB_LOAD(object) (G_TYPE_CHECK_INSTANCE_TYPE((object), EV_TYPE_JOB_LOAD)) + typedef enum { EV_JOB_PRIORITY_LOW, EV_JOB_PRIORITY_HIGH, @@ -121,6 +129,17 @@ struct _EvJobThumbnailClass EvJobClass parent_class; }; +struct _EvJobLoad +{ + EvJob parent; + GError *error; + gchar *uri; +}; + +struct _EvJobLoadClass +{ + EvJobClass parent_class; +}; /* Base job class */ GType ev_job_get_type (void); @@ -148,6 +167,11 @@ EvJob *ev_job_thumbnail_new (EvDocument *document, gint requested_width); void ev_job_thumbnail_run (EvJobThumbnail *thumbnail); +/* EvJobLoad */ +GType ev_job_load_get_type (void); +EvJob *ev_job_load_new (EvDocument *document, + const gchar *uri); +void ev_job_load_run (EvJobLoad *load); G_END_DECLS diff --git a/shell/ev-page-action.c b/shell/ev-page-action.c index b1c61e6..076dff1 100644 --- a/shell/ev-page-action.c +++ b/shell/ev-page-action.c @@ -22,6 +22,7 @@ #include "config.h" #include "ev-page-action.h" +#include "ev-page-cache.h" #include "ev-window.h" #include "ev-document-links.h" #include "ev-marshal.h" @@ -569,7 +570,7 @@ ev_page_action_set_document (EvPageAction *page, EvDocument *document) EvPageCache *page_cache = NULL; if (document) - page_cache = ev_document_get_page_cache (document); + page_cache = ev_page_cache_get (document); g_object_set (page, "page-cache", page_cache, diff --git a/backend/ev-page-cache.c b/shell/ev-page-cache.c index 573e57e..6c44c9f 100644 --- a/backend/ev-page-cache.c +++ b/shell/ev-page-cache.c @@ -101,7 +101,7 @@ ev_page_cache_finalize (GObject *object) } EvPageCache * -_ev_page_cache_new (EvDocument *document) +ev_page_cache_new (EvDocument *document) { EvPageCache *page_cache; EvPageCacheInfo *info; @@ -464,3 +464,22 @@ ev_page_cache_prev_page (EvPageCache *page_cache) return TRUE; } +#define PAGE_CACHE_STRING "ev-page-cache" + +EvPageCache * +ev_page_cache_get (EvDocument *document) +{ + EvPageCache *page_cache; + + g_return_val_if_fail (EV_IS_DOCUMENT (document), NULL); + + page_cache = g_object_get_data (G_OBJECT (document), PAGE_CACHE_STRING); + if (page_cache == NULL) { + page_cache = ev_page_cache_new (document); + g_object_set_data_full (G_OBJECT (document), PAGE_CACHE_STRING, page_cache, g_object_unref); + } + + return page_cache; +} + + diff --git a/backend/ev-page-cache.h b/shell/ev-page-cache.h index 9de48b8..b0bf6cc 100644 --- a/backend/ev-page-cache.h +++ b/shell/ev-page-cache.h @@ -31,7 +31,7 @@ G_BEGIN_DECLS GType ev_page_cache_get_type (void) G_GNUC_CONST; /* Used by ev-document.c only */ -EvPageCache *_ev_page_cache_new (EvDocument *document); +EvPageCache *ev_page_cache_new (EvDocument *document); gint ev_page_cache_get_n_pages (EvPageCache *page_cache); const char *ev_page_cache_get_title (EvPageCache *page_cache); void ev_page_cache_get_size (EvPageCache *page_cache, @@ -66,7 +66,8 @@ void ev_page_cache_set_link (EvPageCache *page_cache, EvLink *link); gboolean ev_page_cache_next_page (EvPageCache *page_cache); gboolean ev_page_cache_prev_page (EvPageCache *page_cache); - + +EvPageCache* ev_page_cache_get (EvDocument *document); G_END_DECLS diff --git a/shell/ev-pixbuf-cache.c b/shell/ev-pixbuf-cache.c index 083825a..0601de0 100644 --- a/shell/ev-pixbuf-cache.c +++ b/shell/ev-pixbuf-cache.c @@ -1,5 +1,6 @@ #include "ev-pixbuf-cache.h" #include "ev-job-queue.h" +#include "ev-page-cache.h" typedef struct _CacheJobInfo @@ -306,7 +307,7 @@ ev_pixbuf_cache_update_range (EvPixbufCache *pixbuf_cache, pixbuf_cache->end_page == end_page) return; - page_cache = ev_document_get_page_cache (pixbuf_cache->document); + page_cache = ev_page_cache_get (pixbuf_cache->document); new_job_list = g_new0 (CacheJobInfo, (end_page - start_page) + 1); new_prev_job = g_new0 (CacheJobInfo, pixbuf_cache->preload_cache_size); @@ -417,7 +418,7 @@ ev_pixbuf_cache_clear_job_sizes (EvPixbufCache *pixbuf_cache, EvPageCache *page_cache; int i; - page_cache = ev_document_get_page_cache (pixbuf_cache->document); + page_cache = ev_page_cache_get (pixbuf_cache->document); for (i = 0; i < PAGE_CACHE_LEN (pixbuf_cache); i++) { check_job_size_and_unref (pixbuf_cache->job_list + i, page_cache, scale); @@ -473,7 +474,7 @@ ev_pixbuf_cache_add_jobs_if_needed (EvPixbufCache *pixbuf_cache, int page; int i; - page_cache = ev_document_get_page_cache (pixbuf_cache->document); + page_cache = ev_page_cache_get (pixbuf_cache->document); for (i = 0; i < PAGE_CACHE_LEN (pixbuf_cache); i++) { job_info = (pixbuf_cache->job_list + i); @@ -514,7 +515,7 @@ ev_pixbuf_cache_set_page_range (EvPixbufCache *pixbuf_cache, g_return_if_fail (EV_IS_PIXBUF_CACHE (pixbuf_cache)); - page_cache = ev_document_get_page_cache (pixbuf_cache->document); + page_cache = ev_page_cache_get (pixbuf_cache->document); g_return_if_fail (start_page >= 0 && start_page < ev_page_cache_get_n_pages (page_cache)); g_return_if_fail (end_page >= 0 && end_page < ev_page_cache_get_n_pages (page_cache)); diff --git a/shell/ev-print-job.c b/shell/ev-print-job.c index e7c1ce1..f79c1fc 100644 --- a/shell/ev-print-job.c +++ b/shell/ev-print-job.c @@ -34,6 +34,7 @@ #include "ev-ps-exporter.h" #include "ev-print-job.h" +#include "ev-page-cache.h" #define EV_PRINT_JOB_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST((klass), EV_PRINT_JOB, EvPrintJobClass)) #define EV_IS_PRINT_JOB_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE((klass), EV_PRINT_JOB)) @@ -219,7 +220,7 @@ void ev_print_job_use_print_dialog_settings (EvPrintJob *job, GnomePrintDialog *dialog) { GnomePrintConfig *print_config; - EvPageCache *page_cache = ev_document_get_page_cache (job->document); + EvPageCache *page_cache = ev_page_cache_get (job->document); g_return_if_fail (EV_IS_PRINT_JOB (job)); g_return_if_fail (GNOME_IS_PRINT_DIALOG (dialog)); @@ -231,7 +232,7 @@ ev_print_job_use_print_dialog_settings (EvPrintJob *job, GnomePrintDialog *dialo gnome_print_config_get_boolean (print_config, (guchar *)GNOME_PRINT_KEY_DUPLEX, &job->duplex); - page_cache = ev_document_get_page_cache (job->document); + page_cache = ev_page_cache_get (job->document); /* get the printing ranges */ switch (gnome_print_dialog_get_range (dialog)) { diff --git a/shell/ev-sidebar-links.c b/shell/ev-sidebar-links.c index 6882007..ced98c8 100644 --- a/shell/ev-sidebar-links.c +++ b/shell/ev-sidebar-links.c @@ -581,7 +581,7 @@ ev_sidebar_links_set_document (EvSidebarPage *sidebar_page, } priv->document = g_object_ref (document); - priv->page_cache = ev_document_get_page_cache (document); + priv->page_cache = ev_page_cache_get (document); if (priv->job) { g_signal_handlers_disconnect_by_func (priv->job, diff --git a/shell/ev-sidebar-thumbnails.c b/shell/ev-sidebar-thumbnails.c index 7f84be1..5d228f3 100644 --- a/shell/ev-sidebar-thumbnails.c +++ b/shell/ev-sidebar-thumbnails.c @@ -298,7 +298,7 @@ ev_sidebar_tree_selection_changed (GtkTreeSelection *selection, page = gtk_tree_path_get_indices (path)[0]; gtk_tree_path_free (path); - page_cache = ev_document_get_page_cache (priv->document); + page_cache = ev_page_cache_get (priv->document); ev_page_cache_set_current_page (page_cache, page); } @@ -403,7 +403,7 @@ ev_sidebar_thumbnails_set_document (EvSidebarPage *sidebar_page, g_return_if_fail (EV_IS_DOCUMENT_THUMBNAILS (document)); - page_cache = ev_document_get_page_cache (document); + page_cache = ev_page_cache_get (document); n_pages = ev_page_cache_get_n_pages (page_cache); priv->document = document; diff --git a/shell/ev-statusbar.c b/shell/ev-statusbar.c new file mode 100644 index 0000000..b37cff7 --- /dev/null +++ b/shell/ev-statusbar.c @@ -0,0 +1,201 @@ +/* this file is part of evince, a gnome document viewer + * + * Copyright (C) 2004 Red Hat, Inc. + * + * Author: + * Jonathan Blandford + * + * 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. + */ + +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + +#include +#include + +#include "ev-statusbar.h" + +struct _EvStatusbarPrivate { + GtkWidget *bar; + GtkWidget *progress; + + guint help_message_cid; + guint view_message_cid; + guint progress_message_cid; + + guint pulse_timeout_id; + guint progress_timeout_id; +}; + +G_DEFINE_TYPE (EvStatusbar, ev_statusbar, GTK_TYPE_HBOX) + +#define EV_STATUSBAR_GET_PRIVATE(object) \ + (G_TYPE_INSTANCE_GET_PRIVATE ((object), EV_TYPE_STATUSBAR, EvStatusbarPrivate)) + +static void +ev_statusbar_destroy (GtkObject *object) +{ + EvStatusbar *ev_statusbar = EV_STATUSBAR (object); + + ev_statusbar_set_progress (ev_statusbar, FALSE); + + (* GTK_OBJECT_CLASS (ev_statusbar_parent_class)->destroy) (object); +} + +static void +ev_statusbar_class_init (EvStatusbarClass *ev_statusbar_class) +{ + GObjectClass *g_object_class; + GtkWidgetClass *widget_class; + GtkObjectClass *gtk_object_klass; + + g_object_class = G_OBJECT_CLASS (ev_statusbar_class); + widget_class = GTK_WIDGET_CLASS (ev_statusbar_class); + gtk_object_klass = GTK_OBJECT_CLASS (ev_statusbar_class); + + g_type_class_add_private (g_object_class, sizeof (EvStatusbarPrivate)); + + gtk_object_klass->destroy = ev_statusbar_destroy; +} + +static void +ev_statusbar_init (EvStatusbar *ev_statusbar) +{ + ev_statusbar->priv = EV_STATUSBAR_GET_PRIVATE (ev_statusbar); + + ev_statusbar->priv->progress = gtk_progress_bar_new (); + gtk_box_pack_start (GTK_BOX (ev_statusbar), ev_statusbar->priv->progress, FALSE, FALSE, 3); + ev_statusbar->priv->bar = gtk_statusbar_new (); + gtk_box_pack_start (GTK_BOX (ev_statusbar), ev_statusbar->priv->bar, TRUE, TRUE, 0); + + ev_statusbar->priv->help_message_cid = gtk_statusbar_get_context_id + (GTK_STATUSBAR (ev_statusbar->priv->bar), "help_message"); + ev_statusbar->priv->view_message_cid = gtk_statusbar_get_context_id + (GTK_STATUSBAR (ev_statusbar->priv->bar), "view_message"); + ev_statusbar->priv->progress_message_cid = gtk_statusbar_get_context_id + (GTK_STATUSBAR (ev_statusbar->priv->bar), "progress_message"); + + gtk_widget_show (GTK_WIDGET (ev_statusbar->priv->bar)); + gtk_widget_show (GTK_WIDGET (ev_statusbar)); + + ev_statusbar->priv->progress_timeout_id = 0; + ev_statusbar->priv->pulse_timeout_id = 0; +} + +/* Public functions */ + +GtkWidget * +ev_statusbar_new (void) +{ + GtkWidget *ev_statusbar; + + ev_statusbar = g_object_new (EV_TYPE_STATUSBAR, NULL); + + return ev_statusbar; +} + +static guint +ev_statusbar_get_context_id (EvStatusbar *statusbar, EvStatusbarContext context) +{ + switch (context) { + case EV_CONTEXT_HELP: + return statusbar->priv->help_message_cid; + case EV_CONTEXT_VIEW: + return statusbar->priv->view_message_cid; + case EV_CONTEXT_PROGRESS: + return statusbar->priv->progress_message_cid; + } + return -1; +} + +void +ev_statusbar_push (EvStatusbar *ev_statusbar, + EvStatusbarContext context, + const gchar *message) +{ + gtk_statusbar_push (GTK_STATUSBAR (ev_statusbar->priv->bar), + ev_statusbar_get_context_id (ev_statusbar, context), + message); + return; +} + +void +ev_statusbar_pop (EvStatusbar *ev_statusbar, + EvStatusbarContext context) +{ + gtk_statusbar_pop (GTK_STATUSBAR (ev_statusbar->priv->bar), + ev_statusbar_get_context_id (ev_statusbar, context)); + return; +} + +void +ev_statusbar_set_maximized (EvStatusbar *ev_statusbar, + gboolean maximized) +{ + gtk_statusbar_set_has_resize_grip (GTK_STATUSBAR (ev_statusbar->priv->bar), + maximized); + return; +} + +static gboolean +ev_statusbar_pulse (gpointer data) +{ + EvStatusbar *ev_statusbar = EV_STATUSBAR (data); + + gtk_progress_bar_pulse (GTK_PROGRESS_BAR (ev_statusbar->priv->progress)); + + return TRUE; +} + +static gboolean +ev_statusbar_show_progress (gpointer data) +{ + EvStatusbar *ev_statusbar = EV_STATUSBAR (data); + + gtk_widget_show (ev_statusbar->priv->progress); + ev_statusbar->priv->pulse_timeout_id = g_timeout_add (300, ev_statusbar_pulse, ev_statusbar); + ev_statusbar->priv->progress_timeout_id = 0; + + return FALSE; +} + +void +ev_statusbar_set_progress (EvStatusbar *ev_statusbar, + gboolean active) +{ + if (active){ + if (ev_statusbar->priv->progress_timeout_id == 0 + && ev_statusbar->priv->pulse_timeout_id == 0) + ev_statusbar->priv->progress_timeout_id = + g_timeout_add (500, ev_statusbar_show_progress, ev_statusbar); + } else { + if (ev_statusbar->priv->pulse_timeout_id) { + g_source_remove (ev_statusbar->priv->pulse_timeout_id); + gtk_widget_hide (ev_statusbar->priv->progress); + } + + if (ev_statusbar->priv->progress_timeout_id) + g_source_remove (ev_statusbar->priv->progress_timeout_id); + + ev_statusbar->priv->progress_timeout_id = 0; + ev_statusbar->priv->pulse_timeout_id = 0; + + } +} + + + diff --git a/shell/ev-statusbar.h b/shell/ev-statusbar.h new file mode 100644 index 0000000..e742525 --- /dev/null +++ b/shell/ev-statusbar.h @@ -0,0 +1,76 @@ +/* ev-statusbar.h + * this file is part of evince, a gnome document viewer + * + * Copyright (C) 2004 Red Hat, Inc. + * + * Author: + * Jonathan Blandford + * + * 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. + */ + +#ifndef __EV_STATUSBAR_H__ +#define __EV_STATUSBAR_H__ + +#include +#include "ev-document.h" + +G_BEGIN_DECLS + +typedef struct _EvStatusbar EvStatusbar; +typedef struct _EvStatusbarClass EvStatusbarClass; +typedef struct _EvStatusbarPrivate EvStatusbarPrivate; + +#define EV_TYPE_STATUSBAR (ev_statusbar_get_type()) +#define EV_STATUSBAR(object) (G_TYPE_CHECK_INSTANCE_CAST((object), EV_TYPE_STATUSBAR, EvStatusbar)) +#define EV_STATUSBAR_CLASS(klass) (G_TYPE_CHACK_CLASS_CAST((klass), EV_TYPE_STATUSBAR, EvStatusbarClass)) +#define EV_IS_STATUSBAR(object) (G_TYPE_CHECK_INSTANCE_TYPE((object), EV_TYPE_STATUSBAR)) +#define EV_IS_STATUSBAR_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE((klass), EV_TYPE_STATUSBAR)) +#define EV_STATUSBAR_GET_CLASS(object) (G_TYPE_INSTANCE_GET_CLASS((object), EV_TYPE_STATUSBAR, EvStatusbarClass)) + +struct _EvStatusbar { + GtkHBox base_instance; + + EvStatusbarPrivate *priv; +}; + +struct _EvStatusbarClass { + GtkHBoxClass base_class; +}; + +GType ev_statusbar_get_type (void); +GtkWidget *ev_statusbar_new (void); + +typedef enum { + EV_CONTEXT_HELP, + EV_CONTEXT_VIEW, + EV_CONTEXT_PROGRESS, +} EvStatusbarContext; + +void ev_statusbar_push (EvStatusbar *ev_statusbar, + EvStatusbarContext context, + const gchar *message); +void ev_statusbar_pop (EvStatusbar *ev_statusbar, + EvStatusbarContext context); +void ev_statusbar_set_maximized (EvStatusbar *ev_statusbar, + gboolean maximized); +void ev_statusbar_set_progress (EvStatusbar *ev_statusbar, + gboolean active); + +G_END_DECLS + +#endif /* __EV_STATUSBAR_H__ */ + + diff --git a/shell/ev-view.c b/shell/ev-view.c index a4032e9..ff05be2 100644 --- a/shell/ev-view.c +++ b/shell/ev-view.c @@ -1932,7 +1932,7 @@ ev_view_set_document (EvView *view, G_CALLBACK (find_changed_cb), view); } - view->page_cache = ev_document_get_page_cache (view->document); + view->page_cache = ev_page_cache_get (view->document); g_signal_connect (view->page_cache, "page-changed", G_CALLBACK (page_changed_cb), view); view->pixbuf_cache = ev_pixbuf_cache_new (view->document); g_signal_connect (view->pixbuf_cache, "job-finished", G_CALLBACK (job_finished_cb), view); @@ -2505,7 +2505,7 @@ ev_view_find_next (EvView *view) int n_results, n_pages; EvDocumentFind *find = EV_DOCUMENT_FIND (view->document); - page_cache = ev_document_get_page_cache (view->document); + page_cache = ev_page_cache_get (view->document); n_results = ev_document_find_get_n_results (find, view->current_page); n_pages = ev_page_cache_get_n_pages (page_cache); @@ -2534,7 +2534,7 @@ ev_view_find_previous (EvView *view) EvDocumentFind *find = EV_DOCUMENT_FIND (view->document); EvPageCache *page_cache; - page_cache = ev_document_get_page_cache (view->document); + page_cache = ev_page_cache_get (view->document); n_results = ev_document_find_get_n_results (find, view->current_page); diff --git a/shell/ev-window.c b/shell/ev-window.c index 7bdeacd..577ee4c 100644 --- a/shell/ev-window.c +++ b/shell/ev-window.c @@ -41,10 +41,11 @@ #include "ev-document-thumbnails.h" #include "ev-document-links.h" #include "ev-document-fonts.h" -#include "ev-document-types.h" #include "ev-document-find.h" #include "ev-document-security.h" #include "ev-job-queue.h" +#include "ev-jobs.h" +#include "ev-statusbar.h" #include "eggfindbar.h" #include "egg-recent-view-gtk.h" #include "egg-recent-view.h" @@ -62,12 +63,8 @@ #include #include #include - -#include -#include -#include #include - +#include #include #include @@ -87,6 +84,9 @@ typedef enum { } EvChrome; struct _EvWindowPrivate { + /* UI */ + EvChrome chrome; + GtkWidget *main_box; GtkWidget *menubar; GtkWidget *toolbar_dock; @@ -98,31 +98,35 @@ struct _EvWindowPrivate { GtkWidget *view; GtkWidget *page_view; GtkWidget *password_view; + GtkWidget *statusbar; + /* UI Builders */ GtkActionGroup *action_group; GtkUIManager *ui_manager; gchar *toolbar_file; EggToolbarsModel *toolbar_model; - - GtkWidget *statusbar; - guint help_message_cid; - guint view_message_cid; + + /* Fullscreen mode */ GtkWidget *fullscreen_toolbar; GtkWidget *fullscreen_popup; - char *uri; + GSource *fullscreen_timeout_source; + /* Document */ + char *uri; EvDocument *document; EvPageCache *page_cache; EvWindowPageMode page_mode; + /* These members are used temporarily when in PAGE_MODE_PASSWORD */ EvDocument *password_document; GtkWidget *password_dialog; char *password_uri; - EvChrome chrome; - GSource *fullscreen_timeout_source; + /* Job used to load document */ + EvJob *xfer_job; + EvJob *load_job; /* recent file stuff */ EggRecentModel *recent_model; @@ -154,9 +158,10 @@ 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 gboolean start_loading_document (EvWindow *ev_window, - EvDocument *document, - const char *uri); +static void ev_window_load_job_cb (EvJobLoad *job, + gpointer data); +static void ev_window_xfer_job_cb (EvJobXfer *job, + gpointer data); static void ev_window_sizing_mode_changed_cb (EvView *view, GParamSpec *pspec, EvWindow *ev_window); @@ -491,7 +496,9 @@ ev_window_is_empty (const EvWindow *ev_window) { g_return_val_if_fail (EV_IS_WINDOW (ev_window), FALSE); - return ev_window->priv->document == NULL; + return (ev_window->priv->document == NULL) && + (ev_window->priv->load_job == NULL) && + (ev_window->priv->xfer_job == NULL); } static void @@ -603,7 +610,7 @@ ev_window_setup_document (EvWindow *ev_window) GtkAction *action; document = ev_window->priv->document; - ev_window->priv->page_cache = ev_document_get_page_cache (ev_window->priv->document); + ev_window->priv->page_cache = ev_page_cache_get (ev_window->priv->document); g_signal_connect (ev_window->priv->page_cache, "page-changed", G_CALLBACK (page_changed_cb), ev_window); g_signal_connect_object (G_OBJECT (document), @@ -659,11 +666,18 @@ password_dialog_response (GtkWidget *password_dialog, ev_window->priv->password_document = NULL; ev_window->priv->password_uri = NULL; + + ev_job_queue_add_job (ev_window->priv->load_job, EV_JOB_PRIORITY_HIGH); + + ev_statusbar_push (EV_STATUSBAR (ev_window->priv->statusbar), + EV_CONTEXT_PROGRESS, + _("Loading document. Please wait")); - if (start_loading_document (ev_window, document, uri)) { - gtk_widget_destroy (password_dialog); - } - + ev_statusbar_set_progress (EV_STATUSBAR (ev_window->priv->statusbar), + TRUE); + + gtk_widget_destroy (password_dialog); + g_object_unref (document); g_free (uri); @@ -674,7 +688,7 @@ password_dialog_response (GtkWidget *password_dialog, gtk_widget_destroy (password_dialog); } -/* Called either by start_loading_document 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() */ @@ -708,8 +722,32 @@ ev_window_popup_password_dialog (EvWindow *ev_window) } } -/* This wil try to load the document. It might be called multiple times on the - * same document by the password dialog. + +static void +ev_window_clear_jobs (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); + + 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; + } + + if (ev_window->priv->xfer_job != NULL) { + + if (!ev_window->priv->xfer_job->finished) + ev_job_queue_remove_job (ev_window->priv->xfer_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; + } +} + +/* This callback will executed when load job will be finished. * * Since the flow of the error dialog is very confusing, we assume that both * document and uri will go away after this function is called, and thus we need @@ -717,17 +755,23 @@ ev_window_popup_password_dialog (EvWindow *ev_window) * ev_window->priv->password_{uri,document}, and thus people who call this * function should _not_ necessarily expect those to exist after being * called. */ -static gboolean -start_loading_document (EvWindow *ev_window, - EvDocument *document, - const char *uri) +static void +ev_window_load_job_cb (EvJobLoad *job, + gpointer data) { - gboolean result; - GError *error = NULL; + EvWindow *ev_window = EV_WINDOW (data); + EvDocument *document = EV_JOB (job)->document; g_assert (document); g_assert (document != ev_window->priv->document); - g_assert (uri); + g_assert (job->uri); + + ev_statusbar_pop (EV_STATUSBAR (ev_window->priv->statusbar), + EV_CONTEXT_PROGRESS); + + ev_statusbar_set_progress (EV_STATUSBAR (ev_window->priv->statusbar), + FALSE); + if (ev_window->priv->password_document) { g_object_unref (ev_window->priv->password_document); ev_window->priv->password_document = NULL; @@ -737,31 +781,27 @@ start_loading_document (EvWindow *ev_window, ev_window->priv->password_uri = NULL; } - result = ev_document_load (document, uri, &error); - /* Success! */ - if (result) { + if (job->error == NULL) { if (ev_window->priv->document) g_object_unref (ev_window->priv->document); ev_window->priv->document = g_object_ref (document); ev_window_setup_document (ev_window); - ev_window_add_recent (ev_window, uri); - - return TRUE; + ev_window_add_recent (ev_window, job->uri); + ev_window_clear_jobs (ev_window); + + return; } - /* unable to load the document */ - g_assert (error != NULL); - - if (error->domain == EV_DOCUMENT_ERROR && - error->code == EV_DOCUMENT_ERROR_ENCRYPTED) { + if (job->error->domain == EV_DOCUMENT_ERROR && + job->error->code == EV_DOCUMENT_ERROR_ENCRYPTED) { gchar *base_name, *file_name; ev_window->priv->password_document = g_object_ref (document); - ev_window->priv->password_uri = g_strdup (uri); + ev_window->priv->password_uri = g_strdup (job->uri); - base_name = g_path_get_basename (uri); + base_name = g_path_get_basename (job->uri); file_name = gnome_vfs_unescape_string_for_display (base_name); ev_password_view_set_file_name (EV_PASSWORD_VIEW (ev_window->priv->password_view), @@ -772,103 +812,102 @@ start_loading_document (EvWindow *ev_window, ev_window_popup_password_dialog (ev_window); } else { - unable_to_load (ev_window, error->message); - } - g_error_free (error); + unable_to_load (ev_window, job->error->message); + } - return FALSE; + return; } -static gboolean -sanity_check_uri (EvWindow *window, const char *uri) +static void +ev_window_xfer_job_cb (EvJobXfer *job, + gpointer data) { - gboolean result = FALSE; - GnomeVFSURI *vfs_uri; - char *err; + EvWindow *ev_window = EV_WINDOW (data); - vfs_uri = gnome_vfs_uri_new (uri); - if (vfs_uri) { - if (gnome_vfs_uri_exists (vfs_uri)) { - result = TRUE; - } - } + ev_statusbar_pop (EV_STATUSBAR (ev_window->priv->statusbar), + EV_CONTEXT_PROGRESS); - if (!result) { - err = g_strdup_printf (_("The file %s does not exist."), uri); - unable_to_load (window, err); - g_free (err); - } + ev_statusbar_set_progress (EV_STATUSBAR (ev_window->priv->statusbar), + FALSE); + + if (job->error != NULL) { + unable_to_load (ev_window, job->error->message); + ev_window_clear_jobs (ev_window); + } else { + EvDocument *document = g_object_ref (EV_JOB (job)->document); + + ev_window_clear_jobs (ev_window); + + ev_window->priv->load_job = ev_job_load_new (document, ev_window->priv->uri); + g_signal_connect (ev_window->priv->load_job, + "finished", + G_CALLBACK (ev_window_load_job_cb), + ev_window); + ev_job_queue_add_job (ev_window->priv->load_job, EV_JOB_PRIORITY_HIGH); + + ev_statusbar_push (EV_STATUSBAR (ev_window->priv->statusbar), + EV_CONTEXT_PROGRESS, + _("Loading document. Please wait")); + ev_statusbar_set_progress (EV_STATUSBAR (ev_window->priv->statusbar), + TRUE); - return result; + } } void -ev_window_open (EvWindow *ev_window, const char *uri) +ev_window_open_uri (EvWindow *ev_window, const char *uri) { - EvDocument *document = NULL; - GType document_type; - char *mime_type = NULL; - - if (!sanity_check_uri (ev_window, uri)) { - return; - } + if (ev_window->priv->password_dialog) + gtk_widget_destroy (ev_window->priv->password_dialog); g_free (ev_window->priv->uri); ev_window->priv->uri = g_strdup (uri); + + ev_window_clear_jobs (ev_window); + + ev_window->priv->xfer_job = ev_job_xfer_new (uri); + g_signal_connect (ev_window->priv->xfer_job, + "finished", + G_CALLBACK (ev_window_xfer_job_cb), + ev_window); + ev_job_queue_add_job (ev_window->priv->xfer_job, EV_JOB_PRIORITY_HIGH); - document_type = ev_document_type_lookup (uri, &mime_type); - if (document_type != G_TYPE_INVALID) { - document = g_object_new (document_type, NULL); - } - - if (document) { - start_loading_document (ev_window, document, uri); - /* See the comment on start_loading_document on ref counting. - * As the password dialog flow is confusing, we're very explicit - * on ref counting. */ - g_object_unref (document); - } else { - char *error_message; - - error_message = g_strdup_printf (_("Unhandled MIME type: '%s'"), - mime_type?mime_type:""); - unable_to_load (ev_window, error_message); - g_free (error_message); - } - - g_free (mime_type); + ev_statusbar_push (EV_STATUSBAR (ev_window->priv->statusbar), + EV_CONTEXT_PROGRESS, + _("Loading document. Please wait")); + ev_statusbar_set_progress (EV_STATUSBAR (ev_window->priv->statusbar), + TRUE); } -static void -ev_window_open_uri_list (EvWindow *ev_window, GList *uri_list) +void +ev_window_open_uri_list (EvWindow *ev_window, GSList *uri_list) { - GList *list; - gchar *uri; + GSList *list; + gchar *uri; g_return_if_fail (uri_list != NULL); list = uri_list; while (list) { - uri = gnome_vfs_uri_to_string (list->data, GNOME_VFS_URI_HIDE_NONE); + + uri = (gchar *)list->data; - if (ev_document_type_lookup (uri, NULL) != G_TYPE_INVALID) { if (ev_window_is_empty (EV_WINDOW (ev_window))) { - ev_window_open (ev_window, uri); - + ev_window_open_uri (ev_window, uri); + gtk_widget_show (GTK_WIDGET (ev_window)); } else { EvWindow *new_window; - + new_window = ev_application_new_window (EV_APP); - ev_window_open (new_window, uri); - + ev_window_open_uri (new_window, uri); + gtk_widget_show (GTK_WIDGET (new_window)); } - } g_free (uri); - list = g_list_next (list); + list = g_slist_next (list); } } @@ -889,7 +928,7 @@ ev_window_cmd_recent_file_activate (EggRecentViewGtk *view, EggRecentItem *item, window = GTK_WIDGET (ev_application_get_empty_window (EV_APP)); gtk_widget_show (window); - ev_window_open (EV_WINDOW (window), uri); + ev_window_open_uri (EV_WINDOW (window), uri); g_free (uri); } @@ -1092,7 +1131,7 @@ ev_window_print (EvWindow *window) EvPageCache *page_cache; int last_page; - page_cache = ev_document_get_page_cache (window->priv->document); + page_cache = ev_page_cache_get (window->priv->document); last_page = ev_page_cache_get_n_pages (page_cache); ev_window_print_range (window, 1, -1); @@ -1111,7 +1150,7 @@ ev_window_print_range (EvWindow *ev_window, int first_page, int last_page) g_return_if_fail (EV_IS_WINDOW (ev_window)); g_return_if_fail (ev_window->priv->document != NULL); - page_cache = ev_document_get_page_cache (ev_window->priv->document); + page_cache = ev_page_cache_get (ev_window->priv->document); if (last_page == -1) { last_page = ev_page_cache_get_n_pages (page_cache); } @@ -1641,12 +1680,12 @@ ev_window_state_event (GtkWidget *widget, GdkEventWindowState *event) EvWindow *window = EV_WINDOW (widget); if (event->changed_mask & GDK_WINDOW_STATE_MAXIMIZED) { - gboolean show; + gboolean maximized; - show = (event->new_window_state & GDK_WINDOW_STATE_MAXIMIZED) == 0; + maximized = (event->new_window_state & GDK_WINDOW_STATE_MAXIMIZED) == 0; - gtk_statusbar_set_has_resize_grip (GTK_STATUSBAR (window->priv->statusbar), - show); + ev_statusbar_set_maximized (EV_STATUSBAR (window->priv->statusbar), + maximized); } return FALSE; @@ -1828,7 +1867,7 @@ ev_window_cmd_view_reload (GtkAction *action, EvWindow *ev_window) page = ev_page_cache_get_current_page (ev_window->priv->page_cache); uri = g_strdup (ev_window->priv->uri); - ev_window_open (ev_window, uri); + ev_window_open_uri (ev_window, uri); /* In case the number of pages in the document has changed. */ page = CLAMP (page, 0, ev_page_cache_get_n_pages (ev_window->priv->page_cache)); @@ -2130,8 +2169,8 @@ menu_item_select_cb (GtkMenuItem *proxy, EvWindow *ev_window) g_object_get (G_OBJECT (action), "tooltip", &message, NULL); if (message) { - gtk_statusbar_push (GTK_STATUSBAR (ev_window->priv->statusbar), - ev_window->priv->help_message_cid, message); + ev_statusbar_push (EV_STATUSBAR (ev_window->priv->statusbar), + EV_CONTEXT_VIEW, message); g_free (message); } } @@ -2139,8 +2178,8 @@ menu_item_select_cb (GtkMenuItem *proxy, EvWindow *ev_window) static void menu_item_deselect_cb (GtkMenuItem *proxy, EvWindow *ev_window) { - gtk_statusbar_pop (GTK_STATUSBAR (ev_window->priv->statusbar), - ev_window->priv->help_message_cid); + ev_statusbar_pop (EV_STATUSBAR (ev_window->priv->statusbar), + EV_CONTEXT_VIEW); } static void @@ -2175,13 +2214,13 @@ view_status_changed_cb (EvView *view, { const char *message; - gtk_statusbar_pop (GTK_STATUSBAR (ev_window->priv->statusbar), - ev_window->priv->view_message_cid); + ev_statusbar_pop (EV_STATUSBAR (ev_window->priv->statusbar), + EV_CONTEXT_HELP); message = ev_view_get_status (view); if (message) { - gtk_statusbar_push (GTK_STATUSBAR (ev_window->priv->statusbar), - ev_window->priv->view_message_cid, message); + ev_statusbar_push (EV_STATUSBAR (ev_window->priv->statusbar), + EV_CONTEXT_HELP, message); } } @@ -2328,6 +2367,10 @@ ev_window_dispose (GObject *object) priv->page_view = NULL; } + if (priv->load_job || priv->xfer_job) { + ev_window_clear_jobs (window); + } + if (priv->password_document) { g_object_unref (priv->password_document); priv->password_document = NULL; @@ -2338,6 +2381,10 @@ ev_window_dispose (GObject *object) priv->password_uri = NULL; } + if (priv->password_dialog) { + gtk_widget_destroy (priv->password_dialog); + } + if (priv->find_bar) { g_signal_handlers_disconnect_by_func (window->priv->find_bar, @@ -2523,14 +2570,25 @@ drag_data_received_cb (GtkWidget *widget, GdkDragContext *context, gint x, gint y, GtkSelectionData *selection_data, guint info, guint time, gpointer gdata) { - GList *uri_list = NULL; + GList *uri_list = NULL; + GSList *uris = NULL; + gchar *uri; uri_list = gnome_vfs_uri_list_parse ((gchar *) selection_data->data); if (uri_list) { - ev_window_open_uri_list (EV_WINDOW (widget), uri_list); - + while (uri_list) { + uri = gnome_vfs_uri_to_string (uri_list->data, GNOME_VFS_URI_HIDE_NONE); + uris = g_slist_append (uris, (gpointer) uri); + + uri_list = g_list_next (uri_list); + } + gnome_vfs_uri_list_free (uri_list); + + ev_window_open_uri_list (EV_WINDOW (widget), uris); + + g_slist_free (uris); gtk_drag_finish (context, TRUE, FALSE, time); } @@ -2942,15 +3000,11 @@ ev_window_init (EvWindow *ev_window) G_CALLBACK (ev_window_zoom_changed_cb), ev_window); - ev_window->priv->statusbar = gtk_statusbar_new (); + ev_window->priv->statusbar = ev_statusbar_new (); gtk_box_pack_end (GTK_BOX (ev_window->priv->main_box), ev_window->priv->statusbar, FALSE, TRUE, 0); - ev_window->priv->help_message_cid = gtk_statusbar_get_context_id - (GTK_STATUSBAR (ev_window->priv->statusbar), "help_message"); - ev_window->priv->view_message_cid = gtk_statusbar_get_context_id - (GTK_STATUSBAR (ev_window->priv->statusbar), "view_message"); - + ev_window->priv->find_bar = egg_find_bar_new (); gtk_box_pack_end (GTK_BOX (ev_window->priv->main_box), ev_window->priv->find_bar, @@ -3009,3 +3063,4 @@ ev_window_init (EvWindow *ev_window) ev_window_sizing_mode_changed_cb (EV_VIEW (ev_window->priv->view), NULL, ev_window); update_action_sensitivity (ev_window); } + diff --git a/shell/ev-window.h b/shell/ev-window.h index 5523fdd..6864b71 100644 --- a/shell/ev-window.h +++ b/shell/ev-window.h @@ -27,6 +27,7 @@ #include #include "ev-link.h" +#include "ev-page-cache.h" G_BEGIN_DECLS @@ -51,15 +52,16 @@ struct _EvWindowClass { }; GType ev_window_get_type (void); -void ev_window_open (EvWindow *ev_window, +void ev_window_open_uri (EvWindow *ev_window, const char *uri); +void ev_window_open_uri_list (EvWindow *ev_window, + GSList *uris); void ev_window_open_page_label (EvWindow *ev_window, const char *label); gboolean ev_window_is_empty (const EvWindow *ev_window); void ev_window_print_range (EvWindow *ev_window, int first_page, int last_page); - G_END_DECLS #endif /* !EV_WINDOW_H */ diff --git a/shell/main.c b/shell/main.c index 827c696..b0cc803 100644 --- a/shell/main.c +++ b/shell/main.c @@ -61,7 +61,7 @@ load_files (const char **files) window = GTK_WIDGET (ev_application_new_window (EV_APP)); gtk_widget_show (window); - ev_window_open (EV_WINDOW (window), uri); + ev_window_open_uri (EV_WINDOW (window), uri); if (page_label != NULL) ev_window_open_page_label (EV_WINDOW (window), page_label); -- cgit v0.9.1