#include "ev-print-operation.h"
-#if GTK_CHECK_VERSION (2, 14, 0)
+#if GTKUNIXPRINT_ENABLED
#include <gtk/gtkunixprint.h>
-#else
-#include <gtk/gtkprintunixdialog.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"
#include "ev-application.h"
#include "ev-file-helpers.h"
+#include "ev-document-print.h"
enum {
PROP_0,
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,
GtkPrintOperationResult result);
void (* begin_print) (EvPrintOperation *op);
void (* status_changed) (EvPrintOperation *op);
-
};
G_DEFINE_ABSTRACT_TYPE (EvPrintOperation, ev_print_operation, G_TYPE_OBJECT)
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)
{
return op->progress;
}
+#if GTK_CHECK_VERSION (2, 17, 1) | GTKUNIXPRINT_ENABLED
static void
ev_print_operation_update_status (EvPrintOperation *op,
gint page,
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())
typedef struct _EvPrintOperationExport EvPrintOperationExport;
typedef struct _EvPrintOperationExportClass EvPrintOperationExportClass;
-GType ev_print_operation_export_get_type (void) G_GNUC_CONST;
+static GType ev_print_operation_export_get_type (void) G_GNUC_CONST;
static void ev_print_operation_export_begin (EvPrintOperationExport *export);
static gboolean export_print_page (EvPrintOperationExport *export);
gint fd;
gchar *temp_file;
gchar *job_name;
-
+ gboolean embed_page_setup;
+
guint idle_id;
/* Context */
gint collated_copies;
gint uncollated, collated, total;
+ gint sheet, page_count;
+
gint range, n_ranges;
GtkPageRange *ranges;
GtkPageRange one_range;
}
}
-static void
+static gboolean
clamp_ranges (EvPrintOperationExport *export)
{
gint num_of_correct_ranges = 0;
gint n_pages_to_print = 0;
gint i;
+ gboolean null_flag = FALSE;
for (i = 0; i < export->n_ranges; i++) {
gint n_pages;
} else if (n_pages % 2 == 0) {
n_pages_to_print += n_pages / 2;
} else if (export->page_set == GTK_PAGE_SET_EVEN) {
- n_pages_to_print += export->ranges[i].start % 2 == 0 ?
+ if (n_pages==1 && export->ranges[i].start % 2 == 0)
+ null_flag = TRUE;
+ else
+ n_pages_to_print += export->ranges[i].start % 2 == 0 ?
n_pages / 2 : (n_pages / 2) + 1;
} else if (export->page_set == GTK_PAGE_SET_ODD) {
- n_pages_to_print += export->ranges[i].start % 2 == 0 ?
+ if (n_pages==1 && export->ranges[i].start % 2 != 0)
+ null_flag = TRUE;
+ else
+ n_pages_to_print += export->ranges[i].start % 2 == 0 ?
(n_pages / 2) + 1 : n_pages / 2;
}
}
- export->n_ranges = num_of_correct_ranges;
- export->n_pages_to_print = n_pages_to_print;
+ if (null_flag && !n_pages_to_print) {
+ return FALSE;
+ } else {
+ export->n_ranges = num_of_correct_ranges;
+ export->n_pages_to_print = n_pages_to_print;
+ return TRUE;
+ }
}
static void
{
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;
find_range (export);
export->page = export->start;
}
- } while ((export->page_set == GTK_PAGE_SET_EVEN && export->page % 2 == 0) ||
- (export->page_set == GTK_PAGE_SET_ODD && export->page % 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;
}
}
static void
-print_job_finished (GtkPrintJob *print_job,
- EvPrintOperationExport *export,
- GError *error)
+gtk_print_job_finished (GtkPrintJob *print_job,
+ EvPrintOperationExport *export,
+ GError *error)
{
EvPrintOperation *op = EV_PRINT_OPERATION (export);
EvPrintOperation *op = EV_PRINT_OPERATION (export);
GtkPrintSettings *settings;
EvFileExporterCapabilities capabilities;
+ GError *error = NULL;
g_assert (export->temp_file != NULL);
}
if (export->print_preview) {
- gchar *uri;
- gchar *print_settings_file = NULL;
-
- print_settings_file = ev_tmp_filename ("print-settings");
- gtk_print_settings_to_file (settings, print_settings_file, NULL);
-
- uri = g_filename_to_uri (export->temp_file, NULL, NULL);
- ev_application_open_uri_at_dest (EV_APP,
- uri,
- gtk_window_get_screen (export->parent_window),
- NULL,
- EV_WINDOW_MODE_PREVIEW,
- NULL,
- TRUE,
- print_settings_file,
- GDK_CURRENT_TIME);
- g_free (print_settings_file);
- g_free (uri);
+ GKeyFile *key_file;
+ gchar *data = NULL;
+ gsize data_len;
+ gchar *print_settings_file = NULL;
- g_signal_emit (op, signals[DONE], 0, GTK_PRINT_OPERATION_RESULT_APPLY);
- /* temp_file will be deleted by the previewer */
+ key_file = g_key_file_new ();
- ev_print_operation_export_run_next (export);
+ gtk_print_settings_to_key_file (settings, key_file, NULL);
+ gtk_page_setup_to_key_file (export->page_setup, key_file, NULL);
+ g_key_file_set_string (key_file, "Print Job", "title", export->job_name);
+
+ data = g_key_file_to_data (key_file, &data_len, &error);
+ if (data) {
+ gint fd;
+
+ fd = g_file_open_tmp ("print-settingsXXXXXX", &print_settings_file, &error);
+ if (!error)
+ g_file_set_contents (print_settings_file, data, data_len, &error);
+ close (fd);
+
+ g_free (data);
+ }
+
+ g_key_file_free (key_file);
+
+ if (!error) {
+ gint argc;
+ gchar **argv;
+ gchar *cmd;
+ gchar *quoted_filename;
+ gchar *quoted_settings_filename;
+
+ quoted_filename = g_shell_quote (export->temp_file);
+ quoted_settings_filename = g_shell_quote (print_settings_file);
+ cmd = g_strdup_printf ("evince-previewer --unlink-tempfile --print-settings %s %s",
+ quoted_settings_filename, quoted_filename);
+
+ g_shell_parse_argv (cmd, &argc, &argv, &error);
+
+ g_free (quoted_filename);
+ g_free (quoted_settings_filename);
+ g_free (cmd);
+
+ if (!error) {
+ gdk_spawn_on_screen (gtk_window_get_screen (export->parent_window),
+ NULL, argv, NULL,
+ G_SPAWN_SEARCH_PATH,
+ NULL, NULL, NULL,
+ &error);
+ }
+
+ g_strfreev (argv);
+ }
+
+ if (error) {
+ if (print_settings_file)
+ g_unlink (print_settings_file);
+ g_free (print_settings_file);
+ } else {
+ g_signal_emit (op, signals[DONE], 0, GTK_PRINT_OPERATION_RESULT_APPLY);
+ /* temp_file will be deleted by the previewer */
+
+ ev_print_operation_export_run_next (export);
+ }
} else {
GtkPrintJob *job;
- GError *error = NULL;
job = gtk_print_job_new (export->job_name,
export->printer,
settings,
export->page_setup);
gtk_print_job_set_source_file (job, export->temp_file, &error);
- if (error) {
- g_set_error_literal (&export->error,
- GTK_PRINT_ERROR,
- GTK_PRINT_ERROR_GENERAL,
- error->message);
- g_error_free (error);
- ev_print_operation_export_clear_temp_file (export);
- g_signal_emit (op, signals[DONE], 0, GTK_PRINT_OPERATION_RESULT_ERROR);
-
- ev_print_operation_export_run_next (export);
- } else {
+ if (!error){
gtk_print_job_send (job,
- (GtkPrintJobCompleteFunc)print_job_finished,
+ (GtkPrintJobCompleteFunc)gtk_print_job_finished,
g_object_ref (export),
(GDestroyNotify)g_object_unref);
}
}
g_object_unref (settings);
+
+ if (error) {
+ g_set_error_literal (&export->error,
+ GTK_PRINT_ERROR,
+ GTK_PRINT_ERROR_GENERAL,
+ error->message);
+ g_error_free (error);
+ ev_print_operation_export_clear_temp_file (export);
+ g_signal_emit (op, signals[DONE], 0, GTK_PRINT_OPERATION_RESULT_ERROR);
+
+ ev_print_operation_export_run_next (export);
+ }
}
static void
{
EvPrintOperation *op = EV_PRINT_OPERATION (export);
- if (export->pages_per_sheet == 1 || export->total % 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 ();
if (!export->temp_file)
return FALSE; /* cancelled */
-
+
export->total++;
export->collated++;
+ /* 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)) {
ev_document_doc_mutex_lock ();
- if (export->pages_per_sheet > 1 &&
- export->total - 1 % export->pages_per_sheet == 0)
- ev_file_exporter_end_page (EV_FILE_EXPORTER (op->document));
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;
}
}
- if (export->pages_per_sheet == 1 || export->total % 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",
return;
}
- ev_print_operation_update_status (op, -1, -1, 0.0);
-
export->print_preview = (response == GTK_RESPONSE_APPLY);
printer = gtk_print_unix_dialog_get_selected_printer (GTK_PRINT_UNIX_DIALOG (dialog));
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) {
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;
break;
}
- clamp_ranges (export);
+ if (export->n_ranges < 1 || !clamp_ranges (export)) {
+ GtkWidget *message_dialog;
+
+ message_dialog = gtk_message_dialog_new (GTK_WINDOW (dialog),
+ GTK_DIALOG_MODAL,
+ GTK_MESSAGE_WARNING,
+ GTK_BUTTONS_CLOSE,
+ "%s", _("Invalid page selection"));
+ gtk_window_set_title (GTK_WINDOW (message_dialog), _("Warning"));
+ gtk_message_dialog_format_secondary_text (GTK_MESSAGE_DIALOG (message_dialog),
+ "%s", _("Your print range selection does not include any page"));
+ g_signal_connect (message_dialog, "response",
+ G_CALLBACK (gtk_widget_destroy),
+ NULL);
+ gtk_widget_show (message_dialog);
+
+ return;
+ } else ev_print_operation_update_status (op, -1, -1, 0.0);
+
width = gtk_page_setup_get_paper_width (page_setup, GTK_UNIT_POINTS);
height = gtk_page_setup_get_paper_height (page_setup, GTK_UNIT_POINTS);
scale = gtk_print_settings_get_scale (print_settings) * 0.01;
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);
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);
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)
{
static void
ev_print_operation_export_init (EvPrintOperationExport *export)
{
+ /* sheets are counted from 1 to be physical */
+ export->sheet = 1;
}
static GObject *
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;
}
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())
+#define EV_PRINT_OPERATION_PRINT(object) (G_TYPE_CHECK_INSTANCE_CAST((object), EV_TYPE_PRINT_OPERATION_PRINT, EvPrintOperationPrint))
+#define EV_PRINT_OPERATION_PRINT_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST((klass), EV_TYPE_PRINT_OPERATION_PRINT, EvPrintOperationPrintClass))
+#define EV_IS_PRINT_OPERATION_PRINT(object) (G_TYPE_CHECK_INSTANCE_TYPE((object), EV_TYPE_PRINT_OPERATION_PRINT))
+
+typedef struct _EvPrintOperationPrint EvPrintOperationPrint;
+typedef struct _EvPrintOperationPrintClass EvPrintOperationPrintClass;
+
+static GType ev_print_operation_print_get_type (void) G_GNUC_CONST;
+
+struct _EvPrintOperationPrint {
+ EvPrintOperation parent;
+
+ GtkPrintOperation *op;
+ gint n_pages_to_print;
+ gint total;
+ EvJob *job_print;
+ gchar *job_name;
+};
+
+struct _EvPrintOperationPrintClass {
+ EvPrintOperationClass parent_class;
+};
+
+G_DEFINE_TYPE (EvPrintOperationPrint, ev_print_operation_print, EV_TYPE_PRINT_OPERATION)
+
+static void
+ev_print_operation_print_set_current_page (EvPrintOperation *op,
+ gint current_page)
+{
+ EvPrintOperationPrint *print = EV_PRINT_OPERATION_PRINT (op);
+
+ gtk_print_operation_set_current_page (print->op, current_page);
+}
+
+static void
+ev_print_operation_print_set_print_settings (EvPrintOperation *op,
+ GtkPrintSettings *print_settings)
+{
+ EvPrintOperationPrint *print = EV_PRINT_OPERATION_PRINT (op);
+
+ gtk_print_operation_set_print_settings (print->op, print_settings);
+}
+
+static GtkPrintSettings *
+ev_print_operation_print_get_print_settings (EvPrintOperation *op)
+{
+ EvPrintOperationPrint *print = EV_PRINT_OPERATION_PRINT (op);
+
+ return gtk_print_operation_get_print_settings (print->op);
+}
+
+static void
+ev_print_operation_print_set_default_page_setup (EvPrintOperation *op,
+ GtkPageSetup *page_setup)
+{
+ EvPrintOperationPrint *print = EV_PRINT_OPERATION_PRINT (op);
+
+ gtk_print_operation_set_default_page_setup (print->op, page_setup);
+}
+
+static GtkPageSetup *
+ev_print_operation_print_get_default_page_setup (EvPrintOperation *op)
+{
+ EvPrintOperationPrint *print = EV_PRINT_OPERATION_PRINT (op);
+
+ return gtk_print_operation_get_default_page_setup (print->op);
+}
+
+static void
+ev_print_operation_print_set_job_name (EvPrintOperation *op,
+ const gchar *job_name)
+{
+ EvPrintOperationPrint *print = EV_PRINT_OPERATION_PRINT (op);
+
+ g_free (print->job_name);
+ print->job_name = g_strdup (job_name);
+
+ gtk_print_operation_set_job_name (print->op, print->job_name);
+}
+
+static const gchar *
+ev_print_operation_print_get_job_name (EvPrintOperation *op)
+{
+ EvPrintOperationPrint *print = EV_PRINT_OPERATION_PRINT (op);
+
+ if (!print->job_name) {
+ gchar *name;
+
+ g_object_get (print->op, "job_name", &name, NULL);
+ print->job_name = name;
+ }
+
+ return print->job_name;
+}
+
+static void
+ev_print_operation_print_run (EvPrintOperation *op,
+ GtkWindow *parent)
+{
+ EvPrintOperationPrint *print = EV_PRINT_OPERATION_PRINT (op);
+
+ gtk_print_operation_run (print->op,
+ GTK_PRINT_OPERATION_ACTION_PRINT_DIALOG,
+ parent, NULL);
+}
+
+static void
+ev_print_operation_print_cancel (EvPrintOperation *op)
+{
+ EvPrintOperationPrint *print = EV_PRINT_OPERATION_PRINT (op);
+
+ gtk_print_operation_cancel (print->op);
+}
+
+static void
+ev_print_operation_print_get_error (EvPrintOperation *op,
+ GError **error)
+{
+ EvPrintOperationPrint *print = EV_PRINT_OPERATION_PRINT (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)
+{
+ EvPrintOperation *op = EV_PRINT_OPERATION (print);
+ gint n_pages;
+
+ n_pages = ev_document_get_n_pages (op->document);
+ gtk_print_operation_set_n_pages (print->op, n_pages);
+ ev_print_operation_update_status (op, -1, n_pages, 0);
+
+ g_signal_emit (op, signals[BEGIN_PRINT], 0);
+}
+
+static void
+ev_print_operation_print_done (EvPrintOperationPrint *print,
+ GtkPrintOperationResult result)
+{
+ EvPrintOperation *op = EV_PRINT_OPERATION (print);
+
+ 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);
+}
+
+static void
+print_job_cancelled (EvJobPrint *job,
+ EvPrintOperationPrint *print)
+{
+ 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,
+ gint page)
+{
+ EvPrintOperation *op = EV_PRINT_OPERATION (print);
+ cairo_t *cr;
+ gdouble cr_width, cr_height;
+ gdouble width, height, scale;
+
+ gtk_print_operation_set_defer_drawing (print->op);
+
+ if (!print->job_print) {
+ print->job_print = ev_job_print_new (op->document);
+ g_signal_connect (G_OBJECT (print->job_print), "finished",
+ G_CALLBACK (print_job_finished),
+ (gpointer)print);
+ g_signal_connect (G_OBJECT (print->job_print), "cancelled",
+ G_CALLBACK (print_job_cancelled),
+ (gpointer)print);
+ }
+
+ ev_job_print_set_page (EV_JOB_PRINT (print->job_print), page);
+
+ 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_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);
+}
+
+static void
+ev_print_operation_print_finalize (GObject *object)
+{
+ EvPrintOperationPrint *print = EV_PRINT_OPERATION_PRINT (object);
+
+ if (print->op) {
+ g_object_unref (print->op);
+ print->op = NULL;
+ }
+
+ if (print->job_name) {
+ g_free (print->job_name);
+ print->job_name = NULL;
+ }
+
+ if (print->job_print) {
+ if (!ev_job_is_finished (print->job_print))
+ ev_job_cancel (print->job_print);
+ g_signal_handlers_disconnect_by_func (print->job_print,
+ print_job_finished,
+ print);
+ g_signal_handlers_disconnect_by_func (print->job_print,
+ print_job_cancelled,
+ print);
+ g_object_unref (print->job_print);
+ print->job_print = NULL;
+ }
+
+ (* G_OBJECT_CLASS (ev_print_operation_print_parent_class)->finalize) (object);
+}
+
+static void
+ev_print_operation_print_init (EvPrintOperationPrint *print)
+{
+ print->op = gtk_print_operation_new ();
+ g_signal_connect_swapped (print->op, "begin_print",
+ G_CALLBACK (ev_print_operation_print_begin_print),
+ print);
+ g_signal_connect_swapped (print->op, "done",
+ G_CALLBACK (ev_print_operation_print_done),
+ 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);
+}
+
+static void
+ev_print_operation_print_class_init (EvPrintOperationPrintClass *klass)
+{
+ GObjectClass *g_object_class = G_OBJECT_CLASS (klass);
+ EvPrintOperationClass *ev_print_op_class = EV_PRINT_OPERATION_CLASS (klass);
+
+ ev_print_op_class->set_current_page = ev_print_operation_print_set_current_page;
+ ev_print_op_class->set_print_settings = ev_print_operation_print_set_print_settings;
+ ev_print_op_class->get_print_settings = ev_print_operation_print_get_print_settings;
+ ev_print_op_class->set_default_page_setup = ev_print_operation_print_set_default_page_setup;
+ ev_print_op_class->get_default_page_setup = ev_print_operation_print_get_default_page_setup;
+ ev_print_op_class->set_job_name = ev_print_operation_print_set_job_name;
+ ev_print_op_class->get_job_name = ev_print_operation_print_get_job_name;
+ 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;
+}
+#endif /* GTK_CHECK_VERSION (2, 17, 1) */
+
+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)
{
- /* TODO: EvPrintOperationPrint */
+ EvPrintOperation *op = NULL;
- return EV_PRINT_OPERATION (g_object_new (EV_TYPE_PRINT_OPERATION_EXPORT,
- "document", document, 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))
+ op = EV_PRINT_OPERATION (g_object_new (EV_TYPE_PRINT_OPERATION_PRINT,
+ "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;
}