]> www.fi.muni.cz Git - evince.git/blobdiff - shell/ev-jobs.c
More renames of warning to mdvi_warning in follow up to the fix of the bug
[evince.git] / shell / ev-jobs.c
index 7371dd1a0eb69a15f78ecc83cc53531209dc837f..dee23b8d0f5b5ea2de8002b47ad59bb8f24c06c2 100644 (file)
@@ -30,7 +30,8 @@
 #include "ev-document-misc.h"
 #include "ev-file-helpers.h"
 #include "ev-document-fonts.h"
 #include "ev-document-misc.h"
 #include "ev-file-helpers.h"
 #include "ev-document-fonts.h"
-#include "ev-async-renderer.h"
+#include "ev-document-security.h"
+#include "ev-document-find.h"
 #include "ev-debug.h"
 
 #include <errno.h>
 #include "ev-debug.h"
 
 #include <errno.h>
 #include <glib/gi18n.h>
 #include <unistd.h>
 
 #include <glib/gi18n.h>
 #include <unistd.h>
 
-static void ev_job_init                 (EvJob               *job);
-static void ev_job_class_init           (EvJobClass          *class);
-static void ev_job_links_init           (EvJobLinks          *job);
-static void ev_job_links_class_init     (EvJobLinksClass     *class);
-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);
-static void ev_job_save_init            (EvJobSave           *job);
-static void ev_job_save_class_init      (EvJobSaveClass      *class);
-static void ev_job_print_init           (EvJobPrint          *job);
-static void ev_job_print_class_init     (EvJobPrintClass     *class);
+static void ev_job_init                   (EvJob                 *job);
+static void ev_job_class_init             (EvJobClass            *class);
+static void ev_job_links_init             (EvJobLinks            *job);
+static void ev_job_links_class_init       (EvJobLinksClass       *class);
+static void ev_job_attachments_init       (EvJobAttachments      *job);
+static void ev_job_attachments_class_init (EvJobAttachmentsClass *class);
+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);
+static void ev_job_save_init              (EvJobSave             *job);
+static void ev_job_save_class_init        (EvJobSaveClass        *class);
+static void ev_job_print_init             (EvJobPrint            *job);
+static void ev_job_print_class_init       (EvJobPrintClass       *class);
+static void ev_job_find_init              (EvJobFind             *job);
+static void ev_job_find_class_init        (EvJobFindClass        *class);
 
 enum {
        CANCELLED,
 
 enum {
        CANCELLED,
@@ -65,22 +70,30 @@ enum {
 };
 
 enum {
 };
 
 enum {
-       UPDATED,
+       FONTS_UPDATED,
        FONTS_LAST_SIGNAL
 };
 
        FONTS_LAST_SIGNAL
 };
 
+enum {
+       FIND_UPDATED,
+       FIND_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 };
 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 };
+static guint job_find_signals[FIND_LAST_SIGNAL] = { 0 };
 
 G_DEFINE_ABSTRACT_TYPE (EvJob, ev_job, G_TYPE_OBJECT)
 G_DEFINE_TYPE (EvJobLinks, ev_job_links, EV_TYPE_JOB)
 
 G_DEFINE_ABSTRACT_TYPE (EvJob, ev_job, G_TYPE_OBJECT)
 G_DEFINE_TYPE (EvJobLinks, ev_job_links, EV_TYPE_JOB)
+G_DEFINE_TYPE (EvJobAttachments, ev_job_attachments, 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 (EvJobFonts, ev_job_fonts, EV_TYPE_JOB)
 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)
 G_DEFINE_TYPE (EvJobRender, ev_job_render, EV_TYPE_JOB)
 G_DEFINE_TYPE (EvJobThumbnail, ev_job_thumbnail, EV_TYPE_JOB)
 G_DEFINE_TYPE (EvJobFonts, ev_job_fonts, EV_TYPE_JOB)
 G_DEFINE_TYPE (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)
+G_DEFINE_TYPE (EvJobFind, ev_job_find, EV_TYPE_JOB)
 
 /* EvJob */
 static void
 
 /* EvJob */
 static void
@@ -226,7 +239,7 @@ ev_job_failed (EvJob       *job,
        message = g_strdup_vprintf (format, args);
        va_end (args);
        
        message = g_strdup_vprintf (format, args);
        va_end (args);
        
-       job->error = g_error_new (domain, code, message);
+       job->error = g_error_new_literal (domain, code, message);
        g_free (message);
        
        ev_job_emit_finished (job);                                                                                                               
        g_free (message);
        
        ev_job_emit_finished (job);                                                                                                               
@@ -348,6 +361,71 @@ ev_job_links_new (EvDocument *document)
        return job;
 }
 
        return job;
 }
 
+/* EvJobAttachments */
+static void
+ev_job_attachments_init (EvJobAttachments *job)
+{
+       EV_JOB (job)->run_mode = EV_JOB_RUN_THREAD;
+}
+
+static void
+ev_job_attachments_dispose (GObject *object)
+{
+       EvJobAttachments *job;
+
+       ev_debug_message (DEBUG_JOBS, NULL);
+       
+       job = EV_JOB_ATTACHMENTS (object);
+
+       if (job->attachments) {
+               g_list_foreach (job->attachments, (GFunc)g_object_unref, NULL);
+               g_list_free (job->attachments);
+               job->attachments = NULL;
+       }
+
+       (* G_OBJECT_CLASS (ev_job_attachments_parent_class)->dispose) (object);
+}
+
+static gboolean
+ev_job_attachments_run (EvJob *job)
+{
+       EvJobAttachments *job_attachments = EV_JOB_ATTACHMENTS (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_attachments->attachments = ev_document_get_attachments (job->document);
+       ev_document_doc_mutex_unlock ();
+       
+       ev_job_succeeded (job);
+       
+       return FALSE;
+}
+
+static void
+ev_job_attachments_class_init (EvJobAttachmentsClass *class)
+{
+       GObjectClass *oclass = G_OBJECT_CLASS (class);
+       EvJobClass   *job_class = EV_JOB_CLASS (class);
+
+       oclass->dispose = ev_job_attachments_dispose;
+       job_class->run = ev_job_attachments_run;
+}
+
+EvJob *
+ev_job_attachments_new (EvDocument *document)
+{
+       EvJob *job;
+
+       ev_debug_message (DEBUG_JOBS, NULL);
+
+       job = g_object_new (EV_TYPE_JOB_ATTACHMENTS, NULL);
+       job->document = g_object_ref (document);
+       
+       return job;
+}
+
 /* EvJobRender */
 static void
 ev_job_render_init (EvJobRender *job)
 /* EvJobRender */
 static void
 ev_job_render_init (EvJobRender *job)
@@ -653,7 +731,7 @@ ev_job_fonts_run (EvJob *job)
 #endif
 
        job_fonts->scan_completed = !ev_document_fonts_scan (fonts, 20);
 #endif
 
        job_fonts->scan_completed = !ev_document_fonts_scan (fonts, 20);
-       g_signal_emit (job_fonts, job_fonts_signals[UPDATED], 0,
+       g_signal_emit (job_fonts, job_fonts_signals[FONTS_UPDATED], 0,
                       ev_document_fonts_get_progress (fonts));
 
        ev_document_fc_mutex_unlock ();
                       ev_document_fonts_get_progress (fonts));
 
        ev_document_fc_mutex_unlock ();
@@ -672,7 +750,7 @@ ev_job_fonts_class_init (EvJobFontsClass *class)
        
        job_class->run = ev_job_fonts_run;
        
        
        job_class->run = ev_job_fonts_run;
        
-       job_fonts_signals[UPDATED] =
+       job_fonts_signals[FONTS_UPDATED] =
                g_signal_new ("updated",
                              EV_TYPE_JOB_FONTS,
                              G_SIGNAL_RUN_LAST,
                g_signal_new ("updated",
                              EV_TYPE_JOB_FONTS,
                              G_SIGNAL_RUN_LAST,
@@ -716,6 +794,11 @@ ev_job_load_dispose (GObject *object)
                job->uri = NULL;
        }
 
                job->uri = NULL;
        }
 
+       if (job->password) {
+               g_free (job->password);
+               job->password = NULL;
+       }
+
        if (job->dest) {
                g_object_unref (job->dest);
                job->dest = NULL;
        if (job->dest) {
                g_object_unref (job->dest);
                job->dest = NULL;
@@ -740,11 +823,19 @@ ev_job_load_run (EvJob *job)
        
        ev_document_fc_mutex_lock ();
 
        
        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) {
        /* 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) {
+               if (job_load->password) {
+                       ev_document_security_set_password (EV_DOCUMENT_SECURITY (job->document),
+                                                          job_load->password);
+               }
+               
+               job->failed = FALSE;
+               job->finished = FALSE;
+               g_clear_error (&job->error);
+               
                ev_document_load (job->document,
                                  job_load->uri,
                                  &error);
                ev_document_load (job->document,
                                  job_load->uri,
                                  &error);
@@ -805,6 +896,16 @@ ev_job_load_set_uri (EvJobLoad *job, const gchar *uri)
        job->uri = g_strdup (uri);
 }
 
        job->uri = g_strdup (uri);
 }
 
+void
+ev_job_load_set_password (EvJobLoad *job, const gchar *password)
+{
+       ev_debug_message (DEBUG_JOBS, NULL);
+
+       if (job->password)
+               g_free (job->password);
+       job->password = password ? g_strdup (password) : NULL;
+}
+
 /* EvJobSave */
 static void
 ev_job_save_init (EvJobSave *job)
 /* EvJobSave */
 static void
 ev_job_save_init (EvJobSave *job)
@@ -1275,3 +1376,163 @@ ev_job_print_new (EvDocument    *document,
        return EV_JOB (job);
 }
 
        return EV_JOB (job);
 }
 
+/* EvJobFind */
+static void
+ev_job_find_init (EvJobFind *job)
+{
+       EV_JOB (job)->run_mode = EV_JOB_RUN_MAIN_LOOP;
+}
+
+static void
+ev_job_find_dispose (GObject *object)
+{
+       EvJobFind *job = EV_JOB_FIND (object);
+
+       ev_debug_message (DEBUG_JOBS, NULL);
+
+       if (job->text) {
+               g_free (job->text);
+               job->text = NULL;
+       }
+
+       if (job->pages) {
+               gint i;
+
+               for (i = 0; i < job->n_pages; i++) {
+                       g_list_foreach (job->pages[i], (GFunc)g_free, NULL);
+                       g_list_free (job->pages[i]);
+               }
+
+               g_free (job->pages);
+               job->pages = NULL;
+       }
+       
+       (* G_OBJECT_CLASS (ev_job_find_parent_class)->dispose) (object);
+}
+
+static gboolean
+ev_job_find_run (EvJob *job)
+{
+       EvJobFind      *job_find = EV_JOB_FIND (job);
+       EvDocumentFind *find = EV_DOCUMENT_FIND (job->document);
+       EvPage         *ev_page;
+       GList          *matches;
+
+       ev_debug_message (DEBUG_JOBS, NULL);
+       
+       /* Do not block the main loop */
+       if (!ev_document_doc_mutex_trylock ())
+               return TRUE;
+       
+#ifdef EV_ENABLE_DEBUG
+       /* We use the #ifdef in this case because of the if */
+       if (job_find->current_page == job_find->start_page)
+               ev_profiler_start (EV_PROFILE_JOBS, "%s (%p)", EV_GET_TYPE_NAME (job), job);
+#endif
+
+       ev_page = ev_document_get_page (job->document, job_find->current_page);
+       matches = ev_document_find_find_text (find, ev_page, job_find->text,
+                                             job_find->case_sensitive);
+       g_object_unref (ev_page);
+       
+       ev_document_doc_mutex_unlock ();
+
+       if (!job_find->has_results)
+               job_find->has_results = (matches != NULL);
+
+       job_find->pages[job_find->current_page] = matches;
+       g_signal_emit (job_find, job_find_signals[FIND_UPDATED], 0, job_find->current_page);
+                      
+       job_find->current_page = (job_find->current_page + 1) % job_find->n_pages;
+       if (job_find->current_page == job_find->start_page) {
+               ev_job_succeeded (job);
+
+               return FALSE;
+       }
+
+       return TRUE;
+}
+
+static void
+ev_job_find_class_init (EvJobFindClass *class)
+{
+       EvJobClass   *job_class = EV_JOB_CLASS (class);
+       GObjectClass *gobject_class = G_OBJECT_CLASS (class);
+       
+       job_class->run = ev_job_find_run;
+       gobject_class->dispose = ev_job_find_dispose;
+       
+       job_find_signals[FIND_UPDATED] =
+               g_signal_new ("updated",
+                             EV_TYPE_JOB_FIND,
+                             G_SIGNAL_RUN_LAST,
+                             G_STRUCT_OFFSET (EvJobFindClass, updated),
+                             NULL, NULL,
+                             g_cclosure_marshal_VOID__INT,
+                             G_TYPE_NONE,
+                             1, G_TYPE_INT);
+}
+
+EvJob *
+ev_job_find_new (EvDocument  *document,
+                gint         start_page,
+                gint         n_pages,
+                const gchar *text,
+                gboolean     case_sensitive)
+{
+       EvJobFind *job;
+       
+       ev_debug_message (DEBUG_JOBS, NULL);
+       
+       job = g_object_new (EV_TYPE_JOB_FIND, NULL);
+
+       EV_JOB (job)->document = g_object_ref (document);
+       job->start_page = start_page;
+       job->current_page = start_page;
+       job->n_pages = n_pages;
+       job->pages = g_new0 (GList *, n_pages);
+       job->text = g_strdup (text);
+       job->case_sensitive = case_sensitive;
+       job->has_results = FALSE;
+
+       return EV_JOB (job);
+}
+
+gint
+ev_job_find_get_n_results (EvJobFind *job,
+                          gint       page)
+{
+       return g_list_length (job->pages[page]);
+}
+
+gdouble
+ev_job_find_get_progress (EvJobFind *job)
+{
+       gint pages_done;
+
+       if (ev_job_is_finished (EV_JOB (job)))
+               return 1.0;
+       
+       if (job->current_page > job->start_page) {
+               pages_done = job->current_page - job->start_page + 1;
+       } else if (job->current_page == job->start_page) {
+               pages_done = job->n_pages;
+       } else {
+               pages_done = job->n_pages - job->start_page + job->current_page;
+       }
+
+       return pages_done / (gdouble) job->n_pages;
+}
+
+gboolean
+ev_job_find_has_results (EvJobFind *job)
+{
+       return job->has_results;
+}
+
+GList **
+ev_job_find_get_results (EvJobFind *job)
+{
+       return job->pages;
+}
+