X-Git-Url: http://pileus.org/git/?a=blobdiff_plain;f=gtk%2Fgtkprintoperation-unix.c;h=6b24217987798535f9636196d08673ac633f97e6;hb=0ba92bc26d1b716f2f9c0543593f13cd5a92c521;hp=cf57ec62901c98d08a92e292e01b48aa9c10bdd0;hpb=09f4906d21ce35b8f30aa2b1339413bd230ef0c0;p=~andy%2Fgtk diff --git a/gtk/gtkprintoperation-unix.c b/gtk/gtkprintoperation-unix.c index cf57ec629..6b2421798 100644 --- a/gtk/gtkprintoperation-unix.c +++ b/gtk/gtkprintoperation-unix.c @@ -1,5 +1,6 @@ /* GTK - The GIMP Toolkit - * gtkprintoperation-unix.c: Print Operation Details for Unix and Unix like platforms + * gtkprintoperation-unix.c: Print Operation Details for Unix + * and Unix-like platforms * Copyright (C) 2006, Red Hat, Inc. * * This library is free software; you can redistribute it and/or @@ -13,9 +14,7 @@ * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public - * License along with this library; if not, write to the - * Free Software Foundation, Inc., 59 Temple Place - Suite 330, - * Boston, MA 02111-1307, USA. + * License along with this library. If not, see . */ #include "config.h" @@ -25,35 +24,44 @@ #include #include #include +#include +#include +#include +#include #include "gtkprintoperation-private.h" -#include "gtkmarshal.h" #include "gtkmessagedialog.h" #include #include +#include "gtkprivate.h" #include "gtkprintunixdialog.h" #include "gtkpagesetupunixdialog.h" #include "gtkprintbackend.h" #include "gtkprinter.h" #include "gtkprintjob.h" #include "gtklabel.h" -#include "gtkalias.h" #include "gtkintl.h" -typedef struct { - GtkPrintJob *job; /* the job we are sending to the printer */ - gulong job_status_changed_tag; +typedef struct +{ GtkWindow *parent; /* just in case we need to throw error dialogs */ GMainLoop *loop; gboolean data_sent; + + /* Real printing (not preview) */ + GtkPrintJob *job; /* the job we are sending to the printer */ + cairo_surface_t *surface; + gulong job_status_changed_tag; + + } GtkPrintOperationUnix; typedef struct _PrinterFinder PrinterFinder; static void printer_finder_free (PrinterFinder *finder); -static void find_printer (const char *printer, +static void find_printer (const gchar *printer, GFunc func, gpointer data); @@ -62,21 +70,50 @@ unix_start_page (GtkPrintOperation *op, GtkPrintContext *print_context, GtkPageSetup *page_setup) { + GtkPrintOperationUnix *op_unix; GtkPaperSize *paper_size; cairo_surface_type_t type; - double w, h; + gdouble w, h; + op_unix = op->priv->platform_data; + paper_size = gtk_page_setup_get_paper_size (page_setup); w = gtk_paper_size_get_width (paper_size, GTK_UNIT_POINTS); h = gtk_paper_size_get_height (paper_size, GTK_UNIT_POINTS); - type = cairo_surface_get_type (op->priv->surface); + type = cairo_surface_get_type (op_unix->surface); - if (type == CAIRO_SURFACE_TYPE_PS) - cairo_ps_surface_set_size (op->priv->surface, w, h); - else if (type == CAIRO_SURFACE_TYPE_PDF) - cairo_pdf_surface_set_size (op->priv->surface, w, h); + if ((op->priv->manual_number_up < 2) || + (op->priv->page_position % op->priv->manual_number_up == 0)) + { + if (type == CAIRO_SURFACE_TYPE_PS) + { + cairo_ps_surface_set_size (op_unix->surface, w, h); + cairo_ps_surface_dsc_begin_page_setup (op_unix->surface); + switch (gtk_page_setup_get_orientation (page_setup)) + { + case GTK_PAGE_ORIENTATION_PORTRAIT: + case GTK_PAGE_ORIENTATION_REVERSE_PORTRAIT: + cairo_ps_surface_dsc_comment (op_unix->surface, "%%PageOrientation: Portrait"); + break; + + case GTK_PAGE_ORIENTATION_LANDSCAPE: + case GTK_PAGE_ORIENTATION_REVERSE_LANDSCAPE: + cairo_ps_surface_dsc_comment (op_unix->surface, "%%PageOrientation: Landscape"); + break; + } + } + else if (type == CAIRO_SURFACE_TYPE_PDF) + { + if (!op->priv->manual_orientation) + { + w = gtk_page_setup_get_paper_width (page_setup, GTK_UNIT_POINTS); + h = gtk_page_setup_get_paper_height (page_setup, GTK_UNIT_POINTS); + } + cairo_pdf_surface_set_size (op_unix->surface, w, h); + } + } } static void @@ -86,7 +123,11 @@ unix_end_page (GtkPrintOperation *op, cairo_t *cr; cr = gtk_print_context_get_cairo_context (print_context); - cairo_show_page (cr); + + if ((op->priv->manual_number_up < 2) || + ((op->priv->page_position + 1) % op->priv->manual_number_up == 0) || + (op->priv->page_position == op->priv->nr_of_pages_to_print - 1)) + cairo_show_page (cr); } static void @@ -102,35 +143,220 @@ op_unix_free (GtkPrintOperationUnix *op_unix) g_free (op_unix); } -static void -unix_finish_send (GtkPrintJob *job, - void *user_data, - GError *error) +static gchar * +shell_command_substitute_file (const gchar *cmd, + const gchar *pdf_filename, + const gchar *settings_filename, + gboolean *pdf_filename_replaced, + gboolean *settings_filename_replaced) +{ + const gchar *inptr, *start; + GString *final; + + g_return_val_if_fail (cmd != NULL, NULL); + g_return_val_if_fail (pdf_filename != NULL, NULL); + g_return_val_if_fail (settings_filename != NULL, NULL); + + final = g_string_new (NULL); + + *pdf_filename_replaced = FALSE; + *settings_filename_replaced = FALSE; + + start = inptr = cmd; + while ((inptr = strchr (inptr, '%')) != NULL) + { + g_string_append_len (final, start, inptr - start); + inptr++; + switch (*inptr) + { + case 'f': + g_string_append (final, pdf_filename); + *pdf_filename_replaced = TRUE; + break; + + case 's': + g_string_append (final, settings_filename); + *settings_filename_replaced = TRUE; + break; + + case '%': + g_string_append_c (final, '%'); + break; + + default: + g_string_append_c (final, '%'); + if (*inptr) + g_string_append_c (final, *inptr); + break; + } + if (*inptr) + inptr++; + start = inptr; + } + g_string_append (final, start); + + return g_string_free (final, FALSE); +} + +void +_gtk_print_operation_platform_backend_launch_preview (GtkPrintOperation *op, + cairo_surface_t *surface, + GtkWindow *parent, + const gchar *filename) { - GtkPrintOperationUnix *op_unix; + GAppInfo *appinfo; + GdkAppLaunchContext *context; + gchar *cmd; + gchar *preview_cmd; + GtkSettings *settings; + GtkPrintSettings *print_settings = NULL; + GtkPageSetup *page_setup; + GKeyFile *key_file = NULL; + gchar *data = NULL; + gsize data_len; + gchar *settings_filename = NULL; + gchar *quoted_filename; + gchar *quoted_settings_filename; + gboolean filename_used = FALSE; + gboolean settings_used = FALSE; + GdkScreen *screen; + GError *error = NULL; + gint fd; + gboolean retval; + + cairo_surface_destroy (surface); + + if (parent) + screen = gtk_window_get_screen (parent); + else + screen = gdk_screen_get_default (); + + fd = g_file_open_tmp ("settingsXXXXXX.ini", &settings_filename, &error); + if (fd < 0) + goto out; + + key_file = g_key_file_new (); + + print_settings = gtk_print_settings_copy (gtk_print_operation_get_print_settings (op)); + + if (print_settings != NULL) + { + gtk_print_settings_set_reverse (print_settings, FALSE); + gtk_print_settings_set_page_set (print_settings, GTK_PAGE_SET_ALL); + gtk_print_settings_set_scale (print_settings, 1.0); + gtk_print_settings_set_number_up (print_settings, 1); + gtk_print_settings_set_number_up_layout (print_settings, GTK_NUMBER_UP_LAYOUT_LEFT_TO_RIGHT_TOP_TO_BOTTOM); + + /* These removals are neccessary because cups-* settings have higher priority + * than normal settings. + */ + gtk_print_settings_unset (print_settings, "cups-reverse"); + gtk_print_settings_unset (print_settings, "cups-page-set"); + gtk_print_settings_unset (print_settings, "cups-scale"); + gtk_print_settings_unset (print_settings, "cups-number-up"); + gtk_print_settings_unset (print_settings, "cups-number-up-layout"); + + gtk_print_settings_to_key_file (print_settings, key_file, NULL); + g_object_unref (print_settings); + } + + page_setup = gtk_print_context_get_page_setup (op->priv->print_context); + gtk_page_setup_to_key_file (page_setup, key_file, NULL); + + g_key_file_set_string (key_file, "Print Job", "title", op->priv->job_name); + + data = g_key_file_to_data (key_file, &data_len, &error); + if (!data) + goto out; + + retval = g_file_set_contents (settings_filename, data, data_len, &error); + if (!retval) + goto out; + + settings = gtk_settings_get_for_screen (screen); + g_object_get (settings, "gtk-print-preview-command", &preview_cmd, NULL); + + quoted_filename = g_shell_quote (filename); + quoted_settings_filename = g_shell_quote (settings_filename); + cmd = shell_command_substitute_file (preview_cmd, quoted_filename, quoted_settings_filename, &filename_used, &settings_used); + + appinfo = g_app_info_create_from_commandline (cmd, + "Print Preview", + G_APP_INFO_CREATE_NONE, + &error); - op_unix = (GtkPrintOperationUnix *) user_data; + g_free (preview_cmd); + g_free (quoted_filename); + g_free (quoted_settings_filename); + g_free (cmd); + + if (error != NULL) + goto out; + + context = gdk_display_get_app_launch_context (gdk_screen_get_display (screen)); + gdk_app_launch_context_set_screen (context, screen); + g_app_info_launch (appinfo, NULL, G_APP_LAUNCH_CONTEXT (context), &error); + + g_object_unref (context); + g_object_unref (appinfo); if (error != NULL) { - GtkWidget *edialog; - edialog = gtk_message_dialog_new (op_unix->parent, - GTK_DIALOG_DESTROY_WITH_PARENT, - GTK_MESSAGE_ERROR, - GTK_BUTTONS_CLOSE, - _("Error printing") /* FIXME better text */); - gtk_message_dialog_format_secondary_text (GTK_MESSAGE_DIALOG (edialog), - "%s", error->message); - gtk_window_set_modal (GTK_WINDOW (edialog), TRUE); - g_signal_connect (edialog, "response", - G_CALLBACK (gtk_widget_destroy), NULL); - - gtk_window_present (GTK_WINDOW (edialog)); + gchar* uri; + + g_warning ("%s %s", _("Error launching preview"), error->message); + + g_error_free (error); + error = NULL; + uri = g_filename_to_uri (filename, NULL, NULL); + gtk_show_uri (screen, uri, GDK_CURRENT_TIME, &error); + g_free (uri); } + out: + if (error != NULL) + { + if (op->priv->error == NULL) + op->priv->error = error; + else + g_error_free (error); + + filename_used = FALSE; + settings_used = FALSE; + } + + if (!filename_used) + g_unlink (filename); + + if (!settings_used) + g_unlink (settings_filename); + + if (fd > 0) + close (fd); + + if (key_file) + g_key_file_free (key_file); + g_free (data); + g_free (settings_filename); +} + +static void +unix_finish_send (GtkPrintJob *job, + gpointer user_data, + const GError *error) +{ + GtkPrintOperation *op = (GtkPrintOperation *) user_data; + GtkPrintOperationUnix *op_unix = op->priv->platform_data; + + if (error != NULL && op->priv->error == NULL) + op->priv->error = g_error_copy (error); + op_unix->data_sent = TRUE; + if (op_unix->loop) g_main_loop_quit (op_unix->loop); + + g_object_unref (op); } static void @@ -140,6 +366,8 @@ unix_end_run (GtkPrintOperation *op, { GtkPrintOperationUnix *op_unix = op->priv->platform_data; + cairo_surface_finish (op_unix->surface); + if (cancelled) return; @@ -147,20 +375,26 @@ unix_end_run (GtkPrintOperation *op, op_unix->loop = g_main_loop_new (NULL, FALSE); /* TODO: Check for error */ - gtk_print_job_send (op_unix->job, - unix_finish_send, - op_unix, NULL, - NULL); + if (op_unix->job != NULL) + { + g_object_ref (op); + gtk_print_job_send (op_unix->job, + unix_finish_send, + op, NULL); + } if (wait) { + g_object_ref (op); if (!op_unix->data_sent) { - GDK_THREADS_LEAVE (); + gdk_threads_leave (); g_main_loop_run (op_unix->loop); - GDK_THREADS_ENTER (); + gdk_threads_enter (); } g_main_loop_unref (op_unix->loop); + op_unix->loop = NULL; + g_object_unref (op); } } @@ -172,13 +406,32 @@ job_status_changed_cb (GtkPrintJob *job, } +static void +print_setup_changed_cb (GtkPrintUnixDialog *print_dialog, + GParamSpec *pspec, + gpointer user_data) +{ + GtkPageSetup *page_setup; + GtkPrintSettings *print_settings; + GtkPrintOperation *op = user_data; + GtkPrintOperationPrivate *priv = op->priv; + + page_setup = gtk_print_unix_dialog_get_page_setup (print_dialog); + print_settings = gtk_print_unix_dialog_get_settings (print_dialog); + + g_signal_emit_by_name (op, + "update-custom-widget", + priv->custom_widget, + page_setup, + print_settings); +} + static GtkWidget * get_print_dialog (GtkPrintOperation *op, GtkWindow *parent) { GtkPrintOperationPrivate *priv = op->priv; GtkWidget *pd, *label; - GtkPageSetup *page_setup; const gchar *custom_tab_label; pd = gtk_print_unix_dialog_new (NULL, parent); @@ -188,19 +441,30 @@ get_print_dialog (GtkPrintOperation *op, GTK_PRINT_CAPABILITY_COPIES | GTK_PRINT_CAPABILITY_COLLATE | GTK_PRINT_CAPABILITY_REVERSE | - GTK_PRINT_CAPABILITY_SCALE); + GTK_PRINT_CAPABILITY_SCALE | + GTK_PRINT_CAPABILITY_PREVIEW | + GTK_PRINT_CAPABILITY_NUMBER_UP | + GTK_PRINT_CAPABILITY_NUMBER_UP_LAYOUT); if (priv->print_settings) gtk_print_unix_dialog_set_settings (GTK_PRINT_UNIX_DIALOG (pd), priv->print_settings); + if (priv->default_page_setup) - page_setup = gtk_page_setup_copy (priv->default_page_setup); - else - page_setup = gtk_page_setup_new (); + gtk_print_unix_dialog_set_page_setup (GTK_PRINT_UNIX_DIALOG (pd), + priv->default_page_setup); + + gtk_print_unix_dialog_set_embed_page_setup (GTK_PRINT_UNIX_DIALOG (pd), + priv->embed_page_setup); + + gtk_print_unix_dialog_set_current_page (GTK_PRINT_UNIX_DIALOG (pd), + priv->current_page); + + gtk_print_unix_dialog_set_support_selection (GTK_PRINT_UNIX_DIALOG (pd), + priv->support_selection); - gtk_print_unix_dialog_set_page_setup (GTK_PRINT_UNIX_DIALOG (pd), - page_setup); - g_object_unref (page_setup); + gtk_print_unix_dialog_set_has_selection (GTK_PRINT_UNIX_DIALOG (pd), + priv->has_selection); g_signal_emit_by_name (op, "create-custom-widget", &priv->custom_widget); @@ -219,16 +483,20 @@ get_print_dialog (GtkPrintOperation *op, label = gtk_label_new (custom_tab_label); gtk_print_unix_dialog_add_custom_tab (GTK_PRINT_UNIX_DIALOG (pd), - op->priv->custom_widget, label); + priv->custom_widget, label); + + g_signal_connect (pd, "notify::selected-printer", (GCallback) print_setup_changed_cb, op); + g_signal_connect (pd, "notify::page-setup", (GCallback) print_setup_changed_cb, op); } return pd; } -typedef struct { +typedef struct +{ GtkPrintOperation *op; gboolean do_print; - GError **error; + gboolean do_preview; GtkPrintOperationResult result; GtkPrintOperationPrintFunc print_cb; GDestroyNotify destroy; @@ -247,79 +515,99 @@ print_response_data_free (gpointer data) static void finish_print (PrintResponseData *rdata, - GtkPrinter *printer, - GtkPageSetup *page_setup, - GtkPrintSettings *settings) + GtkPrinter *printer, + GtkPageSetup *page_setup, + GtkPrintSettings *settings, + gboolean page_setup_set) { GtkPrintOperation *op = rdata->op; GtkPrintOperationPrivate *priv = op->priv; - - priv->start_page = unix_start_page; - priv->end_page = unix_end_page; - priv->end_run = unix_end_run; + GtkPrintJob *job; + gdouble top, bottom, left, right; if (rdata->do_print) { - GtkPrintOperationUnix *op_unix; - gtk_print_operation_set_print_settings (op, settings); - - op_unix = g_new0 (GtkPrintOperationUnix, 1); - op_unix->job = gtk_print_job_new (priv->job_name, - printer, - settings, - page_setup); + priv->print_context = _gtk_print_context_new (op); - gtk_print_job_set_track_print_status (op_unix->job, priv->track_print_status); - - rdata->op->priv->surface = gtk_print_job_get_surface (op_unix->job, rdata->error); - if (op->priv->surface == NULL) + if (gtk_print_settings_get_number_up (settings) < 2) + { + if (printer && gtk_printer_get_hard_margins (printer, &top, &bottom, &left, &right)) + _gtk_print_context_set_hard_margins (priv->print_context, top, bottom, left, right); + } + else { - rdata->do_print = FALSE; - op_unix_free (op_unix); - rdata->result = GTK_PRINT_OPERATION_RESULT_ERROR; - goto out; + /* Pages do not have any unprintable area when printing n-up as each page on the + * sheet has been scaled down and translated to a position within the printable + * area of the sheet. + */ + _gtk_print_context_set_hard_margins (priv->print_context, 0, 0, 0, 0); } - _gtk_print_operation_set_status (op, gtk_print_job_get_status (op_unix->job), NULL); - op_unix->job_status_changed_tag = - g_signal_connect (op_unix->job, "status-changed", - G_CALLBACK (job_status_changed_cb), op); - - op_unix->parent = rdata->parent; + if (page_setup != NULL && + (gtk_print_operation_get_default_page_setup (op) == NULL || + page_setup_set)) + gtk_print_operation_set_default_page_setup (op, page_setup); - priv->dpi_x = 72; - priv->dpi_y = 72; - - priv->platform_data = op_unix; - priv->free_platform_data = (GDestroyNotify) op_unix_free; - - priv->print_pages = op_unix->job->print_pages; - priv->page_ranges = op_unix->job->page_ranges; - priv->num_page_ranges = op_unix->job->num_page_ranges; - - priv->manual_num_copies = op_unix->job->num_copies; - priv->manual_collation = op_unix->job->collate; - priv->manual_reverse = op_unix->job->reverse; - priv->manual_page_set = op_unix->job->page_set; - priv->manual_scale = op_unix->job->scale; - priv->manual_orientation = op_unix->job->rotate_to_orientation; - } + _gtk_print_context_set_page_setup (priv->print_context, page_setup); - out: + if (!rdata->do_preview) + { + GtkPrintOperationUnix *op_unix; + cairo_t *cr; + + op_unix = g_new0 (GtkPrintOperationUnix, 1); + priv->platform_data = op_unix; + priv->free_platform_data = (GDestroyNotify) op_unix_free; + op_unix->parent = rdata->parent; + + priv->start_page = unix_start_page; + priv->end_page = unix_end_page; + priv->end_run = unix_end_run; + + job = gtk_print_job_new (priv->job_name, printer, settings, page_setup); + op_unix->job = job; + gtk_print_job_set_track_print_status (job, priv->track_print_status); + + op_unix->surface = gtk_print_job_get_surface (job, &priv->error); + if (op_unix->surface == NULL) + { + rdata->result = GTK_PRINT_OPERATION_RESULT_ERROR; + rdata->do_print = FALSE; + goto out; + } + + cr = cairo_create (op_unix->surface); + gtk_print_context_set_cairo_context (priv->print_context, cr, 72, 72); + cairo_destroy (cr); + + _gtk_print_operation_set_status (op, gtk_print_job_get_status (job), NULL); + + op_unix->job_status_changed_tag = + g_signal_connect (job, "status-changed", + G_CALLBACK (job_status_changed_cb), op); + + priv->print_pages = gtk_print_job_get_pages (job); + priv->page_ranges = gtk_print_job_get_page_ranges (job, &priv->num_page_ranges); + priv->manual_num_copies = gtk_print_job_get_num_copies (job); + priv->manual_collation = gtk_print_job_get_collate (job); + priv->manual_reverse = gtk_print_job_get_reverse (job); + priv->manual_page_set = gtk_print_job_get_page_set (job); + priv->manual_scale = gtk_print_job_get_scale (job); + priv->manual_orientation = gtk_print_job_get_rotate (job); + priv->manual_number_up = gtk_print_job_get_n_up (job); + priv->manual_number_up_layout = gtk_print_job_get_n_up_layout (job); + } + } + out: if (rdata->print_cb) - { - if (rdata->do_print) - rdata->print_cb (op, rdata->parent); - else - _gtk_print_operation_set_status (op, GTK_PRINT_STATUS_FINISHED_ABORTED, NULL); - } + rdata->print_cb (op, rdata->parent, rdata->do_print, rdata->result); if (rdata->destroy) rdata->destroy (rdata); } -static void +static void handle_print_response (GtkWidget *dialog, gint response, gpointer data) @@ -329,35 +617,52 @@ handle_print_response (GtkWidget *dialog, GtkPrintSettings *settings = NULL; GtkPageSetup *page_setup = NULL; GtkPrinter *printer = NULL; + gboolean page_setup_set = FALSE; if (response == GTK_RESPONSE_OK) { - rdata->result = GTK_PRINT_OPERATION_RESULT_APPLY; - printer = gtk_print_unix_dialog_get_selected_printer (GTK_PRINT_UNIX_DIALOG (pd)); - if (printer == NULL) - goto out; - + + rdata->result = GTK_PRINT_OPERATION_RESULT_APPLY; + rdata->do_preview = FALSE; + if (printer != NULL) + rdata->do_print = TRUE; + } + else if (response == GTK_RESPONSE_APPLY) + { + /* print preview */ + rdata->result = GTK_PRINT_OPERATION_RESULT_APPLY; + rdata->do_preview = TRUE; rdata->do_print = TRUE; + rdata->op->priv->action = GTK_PRINT_OPERATION_ACTION_PREVIEW; + } + + if (rdata->do_print) + { settings = gtk_print_unix_dialog_get_settings (GTK_PRINT_UNIX_DIALOG (pd)); page_setup = gtk_print_unix_dialog_get_page_setup (GTK_PRINT_UNIX_DIALOG (pd)); + page_setup_set = gtk_print_unix_dialog_get_page_setup_set (GTK_PRINT_UNIX_DIALOG (pd)); + /* Set new print settings now so that custom-widget options + * can be added to the settings in the callback + */ + gtk_print_operation_set_print_settings (rdata->op, settings); g_signal_emit_by_name (rdata->op, "custom-widget-apply", rdata->op->priv->custom_widget); - } - - out: - finish_print (rdata, printer, page_setup, settings); + } + + finish_print (rdata, printer, page_setup, settings, page_setup_set); if (settings) g_object_unref (settings); - + gtk_widget_destroy (GTK_WIDGET (pd)); + } static void -found_printer (GtkPrinter *printer, +found_printer (GtkPrinter *printer, PrintResponseData *rdata) { GtkPrintOperation *op = rdata->op; @@ -368,7 +673,8 @@ found_printer (GtkPrinter *printer, if (rdata->loop) g_main_loop_quit (rdata->loop); - if (printer != NULL) { + if (printer != NULL) + { rdata->result = GTK_PRINT_OPERATION_RESULT_APPLY; rdata->do_print = TRUE; @@ -387,7 +693,7 @@ found_printer (GtkPrinter *printer, page_setup = gtk_page_setup_new (); } - finish_print (rdata, printer, page_setup, settings); + finish_print (rdata, printer, page_setup, settings, FALSE); if (settings) g_object_unref (settings); @@ -398,24 +704,25 @@ found_printer (GtkPrinter *printer, void _gtk_print_operation_platform_backend_run_dialog_async (GtkPrintOperation *op, + gboolean show_dialog, GtkWindow *parent, GtkPrintOperationPrintFunc print_cb) { GtkWidget *pd; PrintResponseData *rdata; - const char *printer_name; + const gchar *printer_name; rdata = g_new (PrintResponseData, 1); rdata->op = g_object_ref (op); rdata->do_print = FALSE; + rdata->do_preview = FALSE; rdata->result = GTK_PRINT_OPERATION_RESULT_CANCEL; - rdata->error = NULL; rdata->print_cb = print_cb; rdata->parent = parent; rdata->loop = NULL; rdata->destroy = print_response_data_free; - if (op->priv->show_dialog) + if (show_dialog) { pd = get_print_dialog (op, parent); gtk_window_set_modal (GTK_WINDOW (pd), TRUE); @@ -431,34 +738,134 @@ _gtk_print_operation_platform_backend_run_dialog_async (GtkPrintOperation if (op->priv->print_settings) printer_name = gtk_print_settings_get_printer (op->priv->print_settings); - find_printer (printer_name, - (GFunc) found_printer, rdata); + find_printer (printer_name, (GFunc) found_printer, rdata); + } +} + +static cairo_status_t +write_preview (void *closure, + const unsigned char *data, + unsigned int length) +{ + gint fd = GPOINTER_TO_INT (closure); + gssize written; + + while (length > 0) + { + written = write (fd, data, length); + + if (written == -1) + { + if (errno == EAGAIN || errno == EINTR) + continue; + + return CAIRO_STATUS_WRITE_ERROR; + } + + data += written; + length -= written; + } + + return CAIRO_STATUS_SUCCESS; +} + +static void +close_preview (void *data) +{ + gint fd = GPOINTER_TO_INT (data); + + close (fd); +} + +cairo_surface_t * +_gtk_print_operation_platform_backend_create_preview_surface (GtkPrintOperation *op, + GtkPageSetup *page_setup, + gdouble *dpi_x, + gdouble *dpi_y, + gchar **target) +{ + gchar *filename; + gint fd; + GtkPaperSize *paper_size; + gdouble w, h; + cairo_surface_t *surface; + static cairo_user_data_key_t key; + + filename = g_build_filename (g_get_tmp_dir (), "previewXXXXXX.pdf", NULL); + fd = g_mkstemp (filename); + + if (fd < 0) + { + g_free (filename); + return NULL; } + + *target = filename; + + paper_size = gtk_page_setup_get_paper_size (page_setup); + w = gtk_paper_size_get_width (paper_size, GTK_UNIT_POINTS); + h = gtk_paper_size_get_height (paper_size, GTK_UNIT_POINTS); + + *dpi_x = *dpi_y = 72; + surface = cairo_pdf_surface_create_for_stream (write_preview, GINT_TO_POINTER (fd), w, h); + + cairo_surface_set_user_data (surface, &key, GINT_TO_POINTER (fd), close_preview); + + return surface; +} + +void +_gtk_print_operation_platform_backend_preview_start_page (GtkPrintOperation *op, + cairo_surface_t *surface, + cairo_t *cr) +{ +} + +void +_gtk_print_operation_platform_backend_preview_end_page (GtkPrintOperation *op, + cairo_surface_t *surface, + cairo_t *cr) +{ + cairo_show_page (cr); +} + +void +_gtk_print_operation_platform_backend_resize_preview_surface (GtkPrintOperation *op, + GtkPageSetup *page_setup, + cairo_surface_t *surface) +{ + gdouble w, h; + + w = gtk_page_setup_get_paper_width (page_setup, GTK_UNIT_POINTS); + h = gtk_page_setup_get_paper_height (page_setup, GTK_UNIT_POINTS); + cairo_pdf_surface_set_size (surface, w, h); } + GtkPrintOperationResult _gtk_print_operation_platform_backend_run_dialog (GtkPrintOperation *op, + gboolean show_dialog, GtkWindow *parent, - gboolean *do_print, - GError **error) + gboolean *do_print) { GtkWidget *pd; PrintResponseData rdata; gint response; - const char *printer_name; + const gchar *printer_name; rdata.op = op; rdata.do_print = FALSE; + rdata.do_preview = FALSE; rdata.result = GTK_PRINT_OPERATION_RESULT_CANCEL; - rdata.error = error; rdata.print_cb = NULL; rdata.destroy = NULL; rdata.parent = parent; rdata.loop = NULL; - if (op->priv->show_dialog) + if (show_dialog) { pd = get_print_dialog (op, parent); + response = gtk_dialog_run (GTK_DIALOG (pd)); handle_print_response (pd, response, &rdata); } @@ -472,11 +879,12 @@ _gtk_print_operation_platform_backend_run_dialog (GtkPrintOperation *op, find_printer (printer_name, (GFunc) found_printer, &rdata); - GDK_THREADS_LEAVE (); + gdk_threads_leave (); g_main_loop_run (rdata.loop); - GDK_THREADS_ENTER (); + gdk_threads_enter (); g_main_loop_unref (rdata.loop); + rdata.loop = NULL; } *do_print = rdata.do_print; @@ -485,7 +893,8 @@ _gtk_print_operation_platform_backend_run_dialog (GtkPrintOperation *op, } -typedef struct { +typedef struct +{ GtkPageSetup *page_setup; GtkPageSetupDoneFunc done_cb; gpointer data; @@ -497,7 +906,9 @@ page_setup_data_free (gpointer data) { PageSetupResponseData *rdata = data; - g_object_unref (rdata->page_setup); + if (rdata->page_setup) + g_object_unref (rdata->page_setup); + g_free (rdata); } @@ -541,12 +952,12 @@ get_page_setup_dialog (GtkWindow *parent, /** * gtk_print_run_page_setup_dialog: - * @parent: transient parent, or %NULL - * @page_setup: an existing #GtkPageSetup, or %NULL + * @parent: (allow-none): transient parent + * @page_setup: (allow-none): an existing #GtkPageSetup * @settings: a #GtkPrintSettings - * - * Runs a page setup dialog, letting the user modify the values from - * @page_setup. If the user cancels the dialog, the returned #GtkPageSetup + * + * Runs a page setup dialog, letting the user modify the values from + * @page_setup. If the user cancels the dialog, the returned #GtkPageSetup * is identical to the passed in @page_setup, otherwise it contains the * modifications done in the dialog. * @@ -554,7 +965,7 @@ get_page_setup_dialog (GtkWindow *parent, * setup dialog. See gtk_print_run_page_setup_dialog_async() if this is * a problem. * - * Return value: a new #GtkPageSetup + * Return value: (transfer full): a new #GtkPageSetup * * Since: 2.10 */ @@ -586,10 +997,11 @@ gtk_print_run_page_setup_dialog (GtkWindow *parent, /** * gtk_print_run_page_setup_dialog_async: - * @parent: transient parent, or %NULL - * @page_setup: an existing #GtkPageSetup, or %NULL + * @parent: (allow-none): transient parent, or %NULL + * @page_setup: (allow-none): an existing #GtkPageSetup, or %NULL * @settings: a #GtkPrintSettings - * @done_cb: a function to call when the user saves the modified page setup + * @done_cb: (scope async): a function to call when the user saves + * the modified page setup * @data: user data to pass to @done_cb * * Runs a page setup dialog, letting the user modify the values from @page_setup. @@ -625,11 +1037,12 @@ gtk_print_run_page_setup_dialog_async (GtkWindow *parent, gtk_window_present (GTK_WINDOW (dialog)); } -struct _PrinterFinder { +struct _PrinterFinder +{ gboolean found_printer; GFunc func; gpointer data; - char *printer_name; + gchar *printer_name; GList *backends; guint timeout_tag; GtkPrinter *printer; @@ -656,7 +1069,7 @@ find_printer_idle (gpointer data) printer_finder_free (finder); - return FALSE; + return G_SOURCE_REMOVE; } static void @@ -664,8 +1077,11 @@ printer_added_cb (GtkPrintBackend *backend, GtkPrinter *printer, PrinterFinder *finder) { - if (gtk_printer_is_virtual (printer) || - finder->found_printer) + if (finder->found_printer) + return; + + /* FIXME this skips "Print to PDF" - is this intentional ? */ + if (gtk_printer_is_virtual (printer)) return; if (finder->printer_name != NULL && @@ -706,7 +1122,7 @@ printer_list_done_cb (GtkPrintBackend *backend, } static void -find_printer_init (PrinterFinder *finder, +find_printer_init (PrinterFinder *finder, GtkPrintBackend *backend) { GList *list; @@ -734,12 +1150,10 @@ find_printer_init (PrinterFinder *finder, } else { - g_signal_connect (backend, - "printer-added", + g_signal_connect (backend, "printer-added", (GCallback) printer_added_cb, finder); - g_signal_connect (backend, - "printer-list-done", + g_signal_connect (backend, "printer-list-done", (GCallback) printer_list_done_cb, finder); } @@ -777,9 +1191,9 @@ printer_finder_free (PrinterFinder *finder) } static void -find_printer (const char *printer, - GFunc func, - gpointer data) +find_printer (const gchar *printer, + GFunc func, + gpointer data) { GList *node, *next; PrinterFinder *finder; @@ -803,6 +1217,3 @@ find_printer (const char *printer, if (finder->backends == NULL && !finder->found_printer) g_idle_add (find_printer_idle, finder); } - -#define __GTK_PRINT_OPERATION_UNIX_C__ -#include "gtkaliasdef.c"