]> www.fi.muni.cz Git - evince.git/blobdiff - shell/ev-print-operation.c
Updated Slovenian translation
[evince.git] / shell / ev-print-operation.c
index e583dfbfe81d3985b985d6780f5c528ccaa53900..8d4df9f81dd41cfeed5fa84a6cd486293c5f1785 100644 (file)
 
 #include "ev-print-operation.h"
 
+#if GTKUNIXPRINT_ENABLED
 #include <gtk/gtkunixprint.h>
+#endif
 #include <glib/gi18n.h>
 #include <glib/gstdio.h>
 #include <unistd.h>
 
-#include "ev-page-cache.h"
 #include "ev-file-exporter.h"
 #include "ev-jobs.h"
 #include "ev-job-scheduler.h"
@@ -77,6 +78,9 @@ struct _EvPrintOperationClass {
        void              (* cancel)                 (EvPrintOperation       *op);
        void              (* get_error)              (EvPrintOperation       *op,
                                                      GError                **error);
+       void              (* set_embed_page_setup)   (EvPrintOperation       *op,
+                                                     gboolean                embed);
+       gboolean          (* get_embed_page_setup)   (EvPrintOperation       *op);
 
        /* signals */
        void              (* done)                   (EvPrintOperation       *op,
@@ -281,6 +285,33 @@ ev_print_operation_get_error (EvPrintOperation *op,
        class->get_error (op, error);
 }
 
+void
+ev_print_operation_set_embed_page_setup (EvPrintOperation *op,
+                                        gboolean          embed)
+{
+#if GTK_CHECK_VERSION (2, 17, 4)
+       EvPrintOperationClass *class = EV_PRINT_OPERATION_GET_CLASS (op);
+
+       g_return_if_fail (EV_IS_PRINT_OPERATION (op));
+
+       class->set_embed_page_setup (op, embed);
+#endif
+}
+
+gboolean
+ev_print_operation_get_embed_page_setup (EvPrintOperation *op)
+{
+#if GTK_CHECK_VERSION (2, 17, 4)
+       EvPrintOperationClass *class = EV_PRINT_OPERATION_GET_CLASS (op);
+
+       g_return_val_if_fail (EV_IS_PRINT_OPERATION (op), FALSE);
+
+       return class->get_embed_page_setup (op);
+#else
+       return FALSE;
+#endif
+}
+
 const gchar *
 ev_print_operation_get_status (EvPrintOperation *op)
 {
@@ -297,6 +328,7 @@ ev_print_operation_get_progress (EvPrintOperation *op)
        return op->progress;
 }
 
+#if GTK_CHECK_VERSION (2, 17, 1) | GTKUNIXPRINT_ENABLED
 static void
 ev_print_operation_update_status (EvPrintOperation *op,
                                  gint              page,
@@ -322,6 +354,9 @@ ev_print_operation_update_status (EvPrintOperation *op,
 
        g_signal_emit (op, signals[STATUS_CHANGED], 0);
 }
+#endif
+
+#if GTKUNIXPRINT_ENABLED
 
 /* Export interface */
 #define EV_TYPE_PRINT_OPERATION_EXPORT         (ev_print_operation_export_get_type())
@@ -359,7 +394,8 @@ struct _EvPrintOperationExport {
        gint fd;
        gchar *temp_file;
        gchar *job_name;
-       
+       gboolean embed_page_setup;
+
        guint idle_id;
        
        /* Context */
@@ -367,7 +403,9 @@ struct _EvPrintOperationExport {
        gint n_pages_to_print;
        gint uncollated_copies;
        gint collated_copies;
-       gint uncollated, collated, total, blank;
+       gint uncollated, collated, total;
+
+       gint sheet, page_count;
 
        gint range, n_ranges;
        GtkPageRange *ranges;
@@ -664,10 +702,40 @@ export_print_inc_page (EvPrintOperationExport *export)
 {
        do {
                export->page += export->inc;
+
+               /* note: when NOT collating, page_count is increased in export_print_page */
+               if (export->collate) {
+                       export->page_count++;
+                       export->sheet = 1 + (export->page_count - 1) / export->pages_per_sheet;
+               }
+
                if (export->page == export->end) {
                        export->range += export->inc;
                        if (export->range == -1 || export->range == export->n_ranges) {
                                export->uncollated++;
+
+                               /* when printing multiple collated copies & multiple pages per sheet we want to
+                                * prevent the next copy bleeding into the last sheet of the previous one
+                                * we've reached the last range to be printed now, so this is the time to do it */
+                               if (export->pages_per_sheet > 1 && export->collate == 1 &&
+                                   (export->page_count - 1) % export->pages_per_sheet != 0) {
+
+                                       EvPrintOperation *op = EV_PRINT_OPERATION (export);
+                                       ev_document_doc_mutex_lock ();
+
+                                       /* keep track of all blanks but only actualise those
+                                        * which are in the current odd / even sheet set */
+
+                                       export->page_count += export->pages_per_sheet - (export->page_count - 1) % export->pages_per_sheet;
+                                       if (export->page_set == GTK_PAGE_SET_ALL ||
+                                               (export->page_set == GTK_PAGE_SET_EVEN && export->sheet % 2 == 0) ||
+                                               (export->page_set == GTK_PAGE_SET_ODD && export->sheet % 2 == 1) ) {
+                                               ev_file_exporter_end_page (EV_FILE_EXPORTER (op->document));
+                                       }
+                                       ev_document_doc_mutex_unlock ();
+                                       export->sheet = 1 + (export->page_count - 1) / export->pages_per_sheet;
+                               }
+
                                if (export->uncollated == export->uncollated_copies)
                                        return FALSE;
 
@@ -676,8 +744,12 @@ export_print_inc_page (EvPrintOperationExport *export)
                        find_range (export);
                        export->page = export->start;
                }
-       } while ((export->page_set == GTK_PAGE_SET_EVEN && (export->page / export->pages_per_sheet) % 2 == 0) ||
-                (export->page_set == GTK_PAGE_SET_ODD && (export->page  / export->pages_per_sheet) % 2 == 1));
+
+       /* in/decrement the page number until we reach the first page on the next EVEN or ODD sheet
+        * if we're not collating, we have to make sure that this is done only once! */
+       } while ( export->collate == 1 &&
+               ((export->page_set == GTK_PAGE_SET_EVEN && export->sheet % 2 == 1) ||
+               (export->page_set == GTK_PAGE_SET_ODD && export->sheet % 2 == 0)));
 
        return TRUE;
 }
@@ -875,7 +947,12 @@ export_job_finished (EvJobExport            *job,
 {
        EvPrintOperation *op = EV_PRINT_OPERATION (export);
 
-       if (export->pages_per_sheet == 1 || (export->total + export->blank) % export->pages_per_sheet == 0 ) {
+       if (export->pages_per_sheet == 1 ||
+          ( export->page_count % export->pages_per_sheet == 0 &&
+          ( export->page_set == GTK_PAGE_SET_ALL ||
+          ( export->page_set == GTK_PAGE_SET_EVEN && export->sheet % 2 == 0 ) ||
+          ( export->page_set == GTK_PAGE_SET_ODD && export->sheet % 2 == 1 ) ) ) ) {
+
                ev_document_doc_mutex_lock ();
                ev_file_exporter_end_page (EV_FILE_EXPORTER (op->document));
                ev_document_doc_mutex_unlock ();
@@ -944,28 +1021,16 @@ export_print_page (EvPrintOperationExport *export)
 
        if (!export->temp_file)
                return FALSE; /* cancelled */
-       
+
        export->total++;
        export->collated++;
 
-       /* when printing multiple collated copies & multiple pages per sheet we want to
-          prevent the next copy bleeding into the last sheet of the previous one
-          we therefore check whether we've reached the last page in a document
-          if that is the case and the given sheet is not filled with pages,
-          we introduce a few blank pages to finish off the sheet
-          to make sure nothing goes wrong, the final condition ensures that
-          we're not at the end of a sheet, otherwise we'd introduce a blank sheet! */
-
-       if (export->collate == 1 && export->total > 1 && export->pages_per_sheet > 1 &&
-           (export->page + 1) % export->n_pages == 0 && (export->total - 1 + export->blank) % export->pages_per_sheet != 0) {
-               ev_document_doc_mutex_lock ();
-               ev_file_exporter_end_page (EV_FILE_EXPORTER (op->document));
-               /* keep track of how many blank pages have been added */
-               export->blank += export->pages_per_sheet - (export->total - 1 + export->blank) % export->pages_per_sheet;
-               ev_document_doc_mutex_unlock ();
+       /* note: when collating, page_count is increased in export_print_inc_page */
+       if (!export->collate) {
+               export->page_count++;
+               export->sheet = 1 + (export->page_count - 1) / export->pages_per_sheet;
        }
 
-
        if (export->collated == export->collated_copies) {
                export->collated = 0;
                if (!export_print_inc_page (export)) {
@@ -982,12 +1047,49 @@ export_print_page (EvPrintOperationExport *export)
                }
        }
 
-       if (export->pages_per_sheet == 1 || (export->total + export->blank) % export->pages_per_sheet == 1) {
+       /* we're not collating and we've reached a sheet from the wrong sheet set */
+       if (!export->collate &&
+           ((export->page_set == GTK_PAGE_SET_EVEN && export->sheet % 2 != 0) ||
+           (export->page_set == GTK_PAGE_SET_ODD && export->sheet % 2 != 1))) {
+
+               do {
+                       export->page_count++;
+                       export->collated++;
+                       export->sheet = 1 + (export->page_count - 1) / export->pages_per_sheet;
+
+                       if (export->collated == export->collated_copies) {
+                               export->collated = 0;
+
+                               if (!export_print_inc_page (export)) {
+                                       ev_document_doc_mutex_lock ();
+                                       ev_file_exporter_end (EV_FILE_EXPORTER (op->document));
+                                       ev_document_doc_mutex_unlock ();
+
+                                       close (export->fd);
+                                       export->fd = -1;
+
+                                       update_progress (export);
+
+                                       export_print_done (export);
+                                       return FALSE;
+                               }
+                       }
+
+               } while ((export->page_set == GTK_PAGE_SET_EVEN && export->sheet % 2 != 0) ||
+                         (export->page_set == GTK_PAGE_SET_ODD && export->sheet % 2 != 1));
+
+       }
+
+       if (export->pages_per_sheet == 1 ||
+           (export->page_count % export->pages_per_sheet == 1 &&
+           (export->page_set == GTK_PAGE_SET_ALL ||
+           (export->page_set == GTK_PAGE_SET_EVEN && export->sheet % 2 == 0) ||
+           (export->page_set == GTK_PAGE_SET_ODD && export->sheet % 2 == 1)))) {
                ev_document_doc_mutex_lock ();
                ev_file_exporter_begin_page (EV_FILE_EXPORTER (op->document));
                ev_document_doc_mutex_unlock ();
        }
-       
+
        if (!export->job_export) {
                export->job_export = ev_job_export_new (op->document);
                g_signal_connect (export->job_export, "finished",
@@ -1076,7 +1178,7 @@ ev_print_operation_export_print_dialog_response_cb (GtkDialog              *dial
 
        file_format = gtk_print_settings_get (print_settings, GTK_PRINT_SETTINGS_OUTPUT_FILE_FORMAT);
        
-       filename = g_strdup_printf ("evince_print.%s.XXXXXX", file_format);
+       filename = g_strdup_printf ("evince_print.%s.XXXXXX", file_format != NULL ? file_format : "");
        export->fd = g_file_open_tmp (filename, &export->temp_file, &error);
        g_free (filename);
        if (export->fd <= -1) {
@@ -1114,6 +1216,8 @@ ev_print_operation_export_print_dialog_response_cb (GtkDialog              *dial
                                export->ranges[i].end = export->n_pages - 1;
        }
                break;
+       default:
+               g_warning ("Unsupported print pages setting\n");
        case GTK_PRINT_PAGES_ALL:
                export->ranges = &export->one_range;
 
@@ -1123,6 +1227,7 @@ ev_print_operation_export_print_dialog_response_cb (GtkDialog              *dial
                
                break;
        }
+
        if (export->n_ranges < 1 || !clamp_ranges (export)) {
                GtkWidget *message_dialog;
 
@@ -1218,6 +1323,10 @@ ev_print_operation_export_run (EvPrintOperation *op,
                ev_file_exporter_get_capabilities (EV_FILE_EXPORTER (op->document));
        gtk_print_unix_dialog_set_manual_capabilities (GTK_PRINT_UNIX_DIALOG (dialog),
                                                       capabilities);
+#if GTK_CHECK_VERSION (2, 17, 4)
+       gtk_print_unix_dialog_set_embed_page_setup (GTK_PRINT_UNIX_DIALOG (dialog),
+                                                   export->embed_page_setup);
+#endif
 
        gtk_print_unix_dialog_set_current_page (GTK_PRINT_UNIX_DIALOG (dialog),
                                                export->current_page);
@@ -1228,7 +1337,7 @@ ev_print_operation_export_run (EvPrintOperation *op,
        if (export->page_setup)
                gtk_print_unix_dialog_set_page_setup (GTK_PRINT_UNIX_DIALOG (dialog),
                                                      export->page_setup);
-       
+
        g_signal_connect (dialog, "response",
                          G_CALLBACK (ev_print_operation_export_print_dialog_response_cb),
                          export);
@@ -1259,6 +1368,25 @@ ev_print_operation_export_get_error (EvPrintOperation *op,
        export->error = NULL;
 }
 
+static void
+ev_print_operation_export_set_embed_page_setup (EvPrintOperation *op,
+                                               gboolean          embed)
+{
+#if GTK_CHECK_VERSION (2, 17, 4)
+       EvPrintOperationExport *export = EV_PRINT_OPERATION_EXPORT (op);
+
+       export->embed_page_setup = embed;
+#endif
+}
+
+static gboolean
+ev_print_operation_export_get_embed_page_setup (EvPrintOperation *op)
+{
+       EvPrintOperationExport *export = EV_PRINT_OPERATION_EXPORT (op);
+
+       return export->embed_page_setup;
+}
+
 static void
 ev_print_operation_export_finalize (GObject *object)
 {
@@ -1330,6 +1458,8 @@ ev_print_operation_export_finalize (GObject *object)
 static void
 ev_print_operation_export_init (EvPrintOperationExport *export)
 {
+       /* sheets are counted from 1 to be physical */
+       export->sheet = 1;
 }
 
 static GObject *
@@ -1346,7 +1476,7 @@ ev_print_operation_export_constructor (GType                  type,
                                                                                       construct_params);
        export = EV_PRINT_OPERATION_EXPORT (object);
        op = EV_PRINT_OPERATION (object);
-       export->n_pages = ev_page_cache_get_n_pages (ev_page_cache_get (op->document));
+       export->n_pages = ev_document_get_n_pages (op->document);
 
        return object;
 }
@@ -1367,11 +1497,15 @@ ev_print_operation_export_class_init (EvPrintOperationExportClass *klass)
        ev_print_op_class->run = ev_print_operation_export_run;
        ev_print_op_class->cancel = ev_print_operation_export_cancel;
        ev_print_op_class->get_error = ev_print_operation_export_get_error;
+       ev_print_op_class->set_embed_page_setup = ev_print_operation_export_set_embed_page_setup;
+       ev_print_op_class->get_embed_page_setup = ev_print_operation_export_get_embed_page_setup;
 
        g_object_class->constructor = ev_print_operation_export_constructor;
        g_object_class->finalize = ev_print_operation_export_finalize;
 }
 
+#endif /* GTKUNIXPRINT_ENABLED */
+
 #if GTK_CHECK_VERSION (2, 17, 1)
 /* Print to cairo interface */
 #define EV_TYPE_PRINT_OPERATION_PRINT         (ev_print_operation_print_get_type())
@@ -1388,6 +1522,8 @@ struct _EvPrintOperationPrint {
        EvPrintOperation parent;
 
        GtkPrintOperation *op;
+       gint               n_pages_to_print;
+       gint               total;
        EvJob             *job_print;
        gchar             *job_name;
 };
@@ -1496,6 +1632,29 @@ ev_print_operation_print_get_error (EvPrintOperation *op,
        gtk_print_operation_get_error (print->op, error);
 }
 
+static void
+ev_print_operation_print_set_embed_page_setup (EvPrintOperation *op,
+                                              gboolean          embed)
+{
+#if GTK_CHECK_VERSION (2, 17, 4)
+       EvPrintOperationPrint *print = EV_PRINT_OPERATION_PRINT (op);
+
+       gtk_print_operation_set_embed_page_setup (print->op, embed);
+#endif
+}
+
+static gboolean
+ev_print_operation_print_get_embed_page_setup (EvPrintOperation *op)
+{
+#if GTK_CHECK_VERSION (2, 17, 4)
+       EvPrintOperationPrint *print = EV_PRINT_OPERATION_PRINT (op);
+
+       return gtk_print_operation_get_embed_page_setup (print->op);
+#else
+       return FALSE;
+#endif
+}
+
 static void
 ev_print_operation_print_begin_print (EvPrintOperationPrint *print,
                                      GtkPrintContext       *context)
@@ -1503,10 +1662,8 @@ ev_print_operation_print_begin_print (EvPrintOperationPrint *print,
        EvPrintOperation *op = EV_PRINT_OPERATION (print);
        gint              n_pages;
 
-       n_pages = ev_page_cache_get_n_pages (ev_page_cache_get (op->document));
+       n_pages = ev_document_get_n_pages (op->document);
        gtk_print_operation_set_n_pages (print->op, n_pages);
-
-       /* FIXME: gtk_print should provide the progress */
        ev_print_operation_update_status (op, -1, n_pages, 0);
 
        g_signal_emit (op, signals[BEGIN_PRINT], 0);
@@ -1518,17 +1675,36 @@ ev_print_operation_print_done (EvPrintOperationPrint  *print,
 {
        EvPrintOperation *op = EV_PRINT_OPERATION (print);
 
-       /* FIXME: gtk_print should provide the progress */
-       ev_print_operation_update_status (op, 0, 1, 1.0);
+       ev_print_operation_update_status (op, 0, print->n_pages_to_print, 1.0);
 
        g_signal_emit (op, signals[DONE], 0, result);
 }
 
+static void
+ev_print_operation_print_status_changed (EvPrintOperationPrint *print)
+{
+#ifdef HAVE_GTK_PRINT_OPERATION_GET_N_PAGES_TO_PRINT
+       GtkPrintStatus status;
+
+       status = gtk_print_operation_get_status (print->op);
+       if (status == GTK_PRINT_STATUS_GENERATING_DATA)
+               print->n_pages_to_print = gtk_print_operation_get_n_pages_to_print (print->op);
+#endif
+}
+
 static void
 print_job_finished (EvJobPrint            *job,
                    EvPrintOperationPrint *print)
 {
+       EvPrintOperation *op = EV_PRINT_OPERATION (print);
+
        gtk_print_operation_draw_page_finish (print->op);
+#ifdef HAVE_GTK_PRINT_OPERATION_GET_N_PAGES_TO_PRINT
+       print->total++;
+       ev_print_operation_update_status (op, print->total,
+                                         print->n_pages_to_print,
+                                         print->total / (gdouble)print->n_pages_to_print);
+#endif
        ev_job_print_set_cairo (job, NULL);
 }
 
@@ -1539,6 +1715,23 @@ print_job_cancelled (EvJobPrint            *job,
        gtk_print_operation_cancel (print->op);
 }
 
+static void
+ev_print_operation_print_request_page_setup (EvPrintOperationPrint *print,
+                                            GtkPrintContext       *context,
+                                            gint                   page_nr,
+                                            GtkPageSetup          *setup)
+{
+       EvPrintOperation *op = EV_PRINT_OPERATION (print);
+       gdouble           width, height;
+
+       ev_document_get_page_size (op->document, page_nr,
+                                  &width, &height);
+       if (width > height)
+               gtk_page_setup_set_orientation (setup, GTK_PAGE_ORIENTATION_LANDSCAPE);
+       else
+               gtk_page_setup_set_orientation (setup, GTK_PAGE_ORIENTATION_PORTRAIT);
+}
+
 static void
 ev_print_operation_print_draw_page (EvPrintOperationPrint *print,
                                    GtkPrintContext       *context,
@@ -1547,7 +1740,7 @@ ev_print_operation_print_draw_page (EvPrintOperationPrint *print,
        EvPrintOperation *op = EV_PRINT_OPERATION (print);
        cairo_t          *cr;
        gdouble           cr_width, cr_height;
-       gint              width, height;
+       gdouble           width, height, scale;
 
        gtk_print_operation_set_defer_drawing (print->op);
 
@@ -1566,10 +1759,13 @@ ev_print_operation_print_draw_page (EvPrintOperationPrint *print,
        cr = gtk_print_context_get_cairo_context (context);
        cr_width = gtk_print_context_get_width (context);
        cr_height = gtk_print_context_get_height (context);
-       ev_page_cache_get_size (ev_page_cache_get (op->document),
-                               page, 0, 1.0,
-                               &width, &height);
-       cairo_scale (cr, cr_width / (gdouble)width, cr_height / (gdouble)height);
+       ev_document_get_page_size (op->document, page,
+                                  &width, &height);
+       if (cr_width / width < cr_height / height)
+               scale = cr_width / width;
+       else
+               scale = cr_height / height;
+       cairo_scale (cr, scale, scale);
 
        ev_job_print_set_cairo (EV_JOB_PRINT (print->job_print), cr);
        ev_job_scheduler_push_job (print->job_print, EV_JOB_PRIORITY_NONE);
@@ -1619,6 +1815,12 @@ ev_print_operation_print_init (EvPrintOperationPrint *print)
        g_signal_connect_swapped (print->op, "draw_page",
                                  G_CALLBACK (ev_print_operation_print_draw_page),
                                  print);
+       g_signal_connect_swapped (print->op, "status_changed",
+                                 G_CALLBACK (ev_print_operation_print_status_changed),
+                                 print);
+       g_signal_connect_swapped (print->op, "request_page_setup",
+                                 G_CALLBACK (ev_print_operation_print_request_page_setup),
+                                 print);
        gtk_print_operation_set_allow_async (print->op, TRUE);
 }
 
@@ -1638,6 +1840,8 @@ ev_print_operation_print_class_init (EvPrintOperationPrintClass *klass)
        ev_print_op_class->run = ev_print_operation_print_run;
        ev_print_op_class->cancel = ev_print_operation_print_cancel;
        ev_print_op_class->get_error = ev_print_operation_print_get_error;
+       ev_print_op_class->set_embed_page_setup = ev_print_operation_print_set_embed_page_setup;
+       ev_print_op_class->get_embed_page_setup = ev_print_operation_print_get_embed_page_setup;
 
        g_object_class->finalize = ev_print_operation_print_finalize;
 }
@@ -1645,18 +1849,28 @@ ev_print_operation_print_class_init (EvPrintOperationPrintClass *klass)
 
 gboolean ev_print_operation_exists_for_document (EvDocument *document)
 {
+#if GTKUNIXPRINT_ENABLED
 #if GTK_CHECK_VERSION (2, 17, 1)
        return (EV_IS_FILE_EXPORTER(document) || EV_IS_DOCUMENT_PRINT(document));
 #else
        return EV_IS_FILE_EXPORTER(document);
 #endif
+#else /* ! GTKUNIXPRINT_ENABLED */
+#if GTK_CHECK_VERSION (2, 17, 1)
+       return EV_IS_DOCUMENT_PRINT(document);
+#else
+       return FALSE;
+#endif
+#endif /* GTKUNIXPRINT_ENABLED */
 }
 
 /* Factory method */
 EvPrintOperation *
 ev_print_operation_new (EvDocument *document)
 {
-       EvPrintOperation *op;
+       EvPrintOperation *op = NULL;
+
+       g_return_val_if_fail (ev_print_operation_exists_for_document (document), NULL);
 
 #if GTK_CHECK_VERSION (2, 17, 1)
        if (EV_IS_DOCUMENT_PRINT (document))
@@ -1664,8 +1878,9 @@ ev_print_operation_new (EvDocument *document)
                                                       "document", document, NULL));
        else
 #endif
+#if GTKUNIXPRINT_ENABLED
                op = EV_PRINT_OPERATION (g_object_new (EV_TYPE_PRINT_OPERATION_EXPORT,
                                                       "document", document, NULL));
-
+#endif
        return op;
 }