diff --git a/ChangeLog b/ChangeLog index 7bdd5f8c65..4c4c99d44d 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,44 @@ +2006-03-30 Alexander Larsson + + * gtk/gtk.symbols: + Update + + * gtk/gtkprintbackend.[ch]: + Add dnotify to gtk_print_backend_print_stream + + * gtk/gtkprinter-private.h: + Declare gtk_print_job_set_status + + * gtk/gtkprinter.[ch]: + Remove gtk_printer_prepare_job. + + * gtk/gtkprintjob.[ch]: + Now you create print job directly with gtk_print_job_new() and + they'll be prepared automatically. + Add status_changed signal and get_status. + Add gtk_print_job_set_source_file to allow sending a file. + + * gtk/gtkprintoperation-private.h: + Add destroy notify for platform_data. + Declare _gtk_print_operation_set_status. + + * gtk/gtkprintoperation-unix.c: + Hook up status change handling. + Use the new way to get a print job. + + * gtk/gtkprintoperation.[ch]: + Add status_changed signal and get_status/is_finished. + + + * modules/printbackends/cups/gtkprintbackendcups.c: + * modules/printbackends/lpr/gtkprintbackendlpr.c: + * modules/printbackends/pdf/gtkprintbackendpdf.c: + Update to use new APIs and set status on the job. + Cups polls for the status. + + * tests/print-editor.c: + Track the print operations in the status bar. + 2006-03-30 Alexander Larsson * gtk/Makefile.am: diff --git a/ChangeLog.pre-2-10 b/ChangeLog.pre-2-10 index 7bdd5f8c65..4c4c99d44d 100644 --- a/ChangeLog.pre-2-10 +++ b/ChangeLog.pre-2-10 @@ -1,3 +1,44 @@ +2006-03-30 Alexander Larsson + + * gtk/gtk.symbols: + Update + + * gtk/gtkprintbackend.[ch]: + Add dnotify to gtk_print_backend_print_stream + + * gtk/gtkprinter-private.h: + Declare gtk_print_job_set_status + + * gtk/gtkprinter.[ch]: + Remove gtk_printer_prepare_job. + + * gtk/gtkprintjob.[ch]: + Now you create print job directly with gtk_print_job_new() and + they'll be prepared automatically. + Add status_changed signal and get_status. + Add gtk_print_job_set_source_file to allow sending a file. + + * gtk/gtkprintoperation-private.h: + Add destroy notify for platform_data. + Declare _gtk_print_operation_set_status. + + * gtk/gtkprintoperation-unix.c: + Hook up status change handling. + Use the new way to get a print job. + + * gtk/gtkprintoperation.[ch]: + Add status_changed signal and get_status/is_finished. + + + * modules/printbackends/cups/gtkprintbackendcups.c: + * modules/printbackends/lpr/gtkprintbackendlpr.c: + * modules/printbackends/pdf/gtkprintbackendpdf.c: + Update to use new APIs and set status on the job. + Cups polls for the status. + + * tests/print-editor.c: + Track the print operations in the status bar. + 2006-03-30 Alexander Larsson * gtk/Makefile.am: diff --git a/TODO.printing b/TODO.printing index dc980a0ce8..adaa05b3a3 100644 --- a/TODO.printing +++ b/TODO.printing @@ -2,9 +2,8 @@ Temporary file with stuff left to do in the printing work: Highlevel API: * Add a way to make the cairo printing callbacks (optionally) happen in a thread -* Add API to EggPrintOperation to handle job status feedback while printing. - Needs something like "job_status_changed" and "job_finished" signals - Also during page generation. Should have progress bar? +* Do we want a progress bar during page generation? + At least a signal tracking the page generation progress. * Add API to allow the app to add a custom tab with gtk+ widgets to the print dialog. We can hopefully implement this on osx & win32. * Want a print preview API. @@ -13,6 +12,7 @@ Highlevel API: Lowlevel API: * Figure out the best way to configure module loading (textfile, gtkrc or just frob the modules directory) +* Maybe we want gtk_print_job_cancel? PDF backend: * Change to using a GtkFileChooserEntry to get file names when we move to @@ -41,7 +41,7 @@ General: * use filechooserentry => J5 * get the right DPI from the printer into cairo * gets errors on alex laptop -* general print to file (ps+pdf) +* general print to file module (ps+pdf) Page setting dialog: * insensitive margins-from-printer if list is empty diff --git a/gtk/gtk.symbols b/gtk/gtk.symbols index faf0c9cd79..c254a7ad6d 100644 --- a/gtk/gtk.symbols +++ b/gtk/gtk.symbols @@ -2558,7 +2558,6 @@ gtk_printer_get_icon_name gtk_printer_get_job_count gtk_printer_is_active gtk_printer_is_virtual -gtk_printer_prepare_job #endif #endif @@ -2605,9 +2604,11 @@ gtk_print_job_get_type G_GNUC_CONST gtk_print_job_new gtk_print_job_get_settings gtk_print_job_get_printer +gtk_print_job_get_title +gtk_print_job_get_status +gtk_print_job_set_source_file gtk_print_job_get_surface gtk_print_job_send -gtk_print_job_prepare #endif #endif @@ -2628,6 +2629,8 @@ gtk_print_operation_set_unit gtk_print_operation_set_show_dialog gtk_print_operation_set_pdf_target gtk_print_operation_run +gtk_print_operation_get_status +gtk_print_operation_is_finished #endif #endif diff --git a/gtk/gtkprintbackend.c b/gtk/gtkprintbackend.c index 320644f0e1..fae38ce957 100644 --- a/gtk/gtkprintbackend.c +++ b/gtk/gtkprintbackend.c @@ -358,19 +358,19 @@ gtk_print_backend_find_printer (GtkPrintBackend *print_backend, void gtk_print_backend_print_stream (GtkPrintBackend *print_backend, GtkPrintJob *job, - const gchar *title, gint data_fd, GtkPrintJobCompleteFunc callback, - gpointer user_data) + gpointer user_data, + GDestroyNotify dnotify) { g_return_if_fail (GTK_IS_PRINT_BACKEND (print_backend)); - return GTK_PRINT_BACKEND_GET_IFACE (print_backend)->print_stream (print_backend, - job, - title, - data_fd, - callback, - user_data); + GTK_PRINT_BACKEND_GET_IFACE (print_backend)->print_stream (print_backend, + job, + data_fd, + callback, + user_data, + dnotify); } #define __GTK_PRINT_BACKEND_C__ diff --git a/gtk/gtkprintbackend.h b/gtk/gtkprintbackend.h index 4cfcec5cc1..fb39a77518 100644 --- a/gtk/gtkprintbackend.h +++ b/gtk/gtkprintbackend.h @@ -67,10 +67,10 @@ struct _GtkPrintBackendIface const gchar *printer_name); void (*print_stream) (GtkPrintBackend *print_backend, GtkPrintJob *job, - const gchar *title, gint data_fd, GtkPrintJobCompleteFunc callback, - gpointer user_data); + gpointer user_data, + GDestroyNotify dnotify); /* Printer methods: */ void (*printer_request_details) (GtkPrinter *printer); @@ -112,10 +112,10 @@ GtkPrinter *gtk_print_backend_find_printer (GtkPrintBackend *print_b const gchar *printer_name); void gtk_print_backend_print_stream (GtkPrintBackend *print_backend, GtkPrintJob *job, - const gchar *title, gint data_fd, GtkPrintJobCompleteFunc callback, - gpointer user_data); + gpointer user_data, + GDestroyNotify dnotify); GList * gtk_print_backend_load_modules (void); diff --git a/gtk/gtkprinter-private.h b/gtk/gtkprinter-private.h index ca85ee83b4..674f4e793c 100644 --- a/gtk/gtkprinter-private.h +++ b/gtk/gtkprinter-private.h @@ -23,7 +23,7 @@ #include #include "gtkprinter.h" -#include "gtkprintsettings.h" +#include "gtkprintoperation.h" #include "gtkprinteroptionset.h" #include "gtkpagesetup.h" @@ -73,5 +73,10 @@ void _gtk_printer_get_hard_margins (GtkPrinter double *right); GHashTable * _gtk_printer_get_custom_widgets (GtkPrinter *printer); + +/* GtkPrintJob private methods: */ +void gtk_print_job_set_status (GtkPrintJob *job, + GtkPrintStatus status); + G_END_DECLS #endif /* __GTK_PRINT_OPERATION_PRIVATE_H__ */ diff --git a/gtk/gtkprinter.c b/gtk/gtkprinter.c index a60cbf38ba..8293328c3b 100644 --- a/gtk/gtkprinter.c +++ b/gtk/gtkprinter.c @@ -305,29 +305,6 @@ gtk_printer_is_virtual (GtkPrinter *printer) return printer->priv->is_virtual; } -GtkPrintJob * -gtk_printer_prepare_job (GtkPrinter *printer, - GtkPrintSettings *settings, - GtkPageSetup *page_setup, - const gchar *title, - GError **error) -{ - GtkPrintJob *job; - - job = gtk_print_job_new (title, - settings, - page_setup, - printer); - - if (!gtk_print_job_prepare (job, error)) - { - g_object_unref (G_OBJECT (job)); - job = NULL; - } - - return job; -} - void _gtk_printer_request_details (GtkPrinter *printer) { diff --git a/gtk/gtkprinter.h b/gtk/gtkprinter.h index bbcabbed65..c045ec62f2 100644 --- a/gtk/gtkprinter.h +++ b/gtk/gtkprinter.h @@ -21,8 +21,8 @@ #include #include -#include "gtkprintsettings.h" -#include "gtkpagesetup.h" +#include +#include G_BEGIN_DECLS @@ -78,12 +78,6 @@ gint gtk_printer_get_job_count (GtkPrinter *printer); gboolean gtk_printer_is_active (GtkPrinter *printer); gboolean gtk_printer_is_virtual (GtkPrinter *printer); -GtkPrintJob *gtk_printer_prepare_job (GtkPrinter *printer, - GtkPrintSettings *settings, - GtkPageSetup *page_setup, - const gchar *title, - GError **error); - G_END_DECLS #endif /* __GTK_PRINTER_H__ */ diff --git a/gtk/gtkprintjob.c b/gtk/gtkprintjob.c index efeb359a9f..3abffaa076 100644 --- a/gtk/gtkprintjob.c +++ b/gtk/gtkprintjob.c @@ -21,12 +21,15 @@ #include #include #include +#include +#include #ifdef HAVE_UNISTD_H #include #endif #include #include +#include #include "gtkintl.h" #include "gtkprivate.h" @@ -35,37 +38,49 @@ #include "gtkprintbackend.h" #include "gtkalias.h" +#ifndef O_BINARY +#define O_BINARY 0 +#endif + struct _GtkPrintJobPrivate { gchar *title; - gint cache_fd; + int spool_file_fd; cairo_surface_t *surface; - GtkPrintSettings *settings; - GtkPageSetup *page_setup; + GtkPrintStatus status; GtkPrintBackend *backend; GtkPrinter *printer; + GtkPrintSettings *settings; + GtkPageSetup *page_setup; gint printer_set : 1; gint page_setup_set : 1; gint settings_set : 1; - gint prepped : 1; }; #define GTK_PRINT_JOB_GET_PRIVATE(o) \ (G_TYPE_INSTANCE_GET_PRIVATE ((o), GTK_TYPE_PRINT_JOB, GtkPrintJobPrivate)) -static void gtk_print_job_finalize (GObject *object); -static void gtk_print_job_set_property (GObject *object, - guint prop_id, - const GValue *value, - GParamSpec *pspec); -static void gtk_print_job_get_property (GObject *object, - guint prop_id, - GValue *value, - GParamSpec *pspec); +static void gtk_print_job_finalize (GObject *object); +static void gtk_print_job_set_property (GObject *object, + guint prop_id, + const GValue *value, + GParamSpec *pspec); +static void gtk_print_job_get_property (GObject *object, + guint prop_id, + GValue *value, + GParamSpec *pspec); +static GObject* gtk_print_job_constructor (GType type, + guint n_construct_properties, + GObjectConstructParam *construct_params); + +enum { + STATUS_CHANGED, + LAST_SIGNAL +}; enum { PROP_0, @@ -75,6 +90,8 @@ enum { GTK_PRINT_JOB_PROP_SETTINGS }; +static guint signals[LAST_SIGNAL] = { 0 }; + G_DEFINE_TYPE (GtkPrintJob, gtk_print_job, G_TYPE_OBJECT); static void @@ -84,6 +101,7 @@ gtk_print_job_class_init (GtkPrintJobClass *class) object_class = (GObjectClass *) class; object_class->finalize = gtk_print_job_finalize; + object_class->constructor = gtk_print_job_constructor; object_class->set_property = gtk_print_job_set_property; object_class->get_property = gtk_print_job_get_property; @@ -95,7 +113,7 @@ gtk_print_job_class_init (GtkPrintJobClass *class) P_("Title"), P_("Title of the print job"), NULL, - GTK_PARAM_WRITABLE | + GTK_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY)); g_object_class_install_property (G_OBJECT_CLASS (class), @@ -124,15 +142,24 @@ gtk_print_job_class_init (GtkPrintJobClass *class) GTK_TYPE_PAGE_SETUP, GTK_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY)); + + signals[STATUS_CHANGED] = + g_signal_new ("status-changed", + G_TYPE_FROM_CLASS (class), + G_SIGNAL_RUN_LAST, + G_STRUCT_OFFSET (GtkPrintJobClass, status_changed), + NULL, NULL, + g_cclosure_marshal_VOID__VOID, + G_TYPE_NONE, 0); } static void gtk_print_job_init (GtkPrintJob *print_job) { print_job->priv = GTK_PRINT_JOB_GET_PRIVATE (print_job); - print_job->priv->cache_fd = 0; + print_job->priv->spool_file_fd = -1; - print_job->priv->title = NULL; + print_job->priv->title = g_strdup (""); print_job->priv->surface = NULL; print_job->priv->backend = NULL; print_job->priv->printer = NULL; @@ -140,7 +167,7 @@ gtk_print_job_init (GtkPrintJob *print_job) print_job->priv->printer_set = FALSE; print_job->priv->settings_set = FALSE; print_job->priv->page_setup_set = FALSE; - + print_job->priv->status = GTK_PRINT_STATUS_INITIAL; print_job->print_pages = GTK_PRINT_PAGES_ALL; print_job->page_ranges = NULL; @@ -153,15 +180,49 @@ gtk_print_job_init (GtkPrintJob *print_job) print_job->rotate_to_orientation = FALSE; } + +static GObject* +gtk_print_job_constructor (GType type, + guint n_construct_properties, + GObjectConstructParam *construct_params) +{ + GtkPrintJob *job; + GObject *object; + + object = + G_OBJECT_CLASS (gtk_print_job_parent_class)->constructor (type, + n_construct_properties, + construct_params); + + job = GTK_PRINT_JOB (object); + + g_assert (job->priv->printer_set && + job->priv->settings_set && + job->priv->page_setup_set); + + _gtk_printer_prepare_for_print (job->priv->printer, + job, + job->priv->settings, + job->priv->page_setup); + + return object; +} + + static void gtk_print_job_finalize (GObject *object) { + GtkPrintJob *print_job; + g_return_if_fail (object != NULL); - GtkPrintJob *print_job = GTK_PRINT_JOB (object); + print_job = GTK_PRINT_JOB (object); - if (print_job->priv->cache_fd != 0) - close (print_job->priv->cache_fd); + if (print_job->priv->spool_file_fd > 0) + { + close (print_job->priv->spool_file_fd); + print_job->priv->spool_file_fd = -1; + } if (print_job->priv->backend) g_object_unref (G_OBJECT (print_job->priv->backend)); @@ -181,6 +242,9 @@ gtk_print_job_finalize (GObject *object) g_free (print_job->page_ranges); print_job->page_ranges = NULL; + g_free (print_job->priv->title); + print_job->priv->title = NULL; + if (G_OBJECT_CLASS (gtk_print_job_parent_class)->finalize) G_OBJECT_CLASS (gtk_print_job_parent_class)->finalize (object); } @@ -196,30 +260,28 @@ gtk_print_job_finalize (GObject *object) **/ GtkPrintJob * gtk_print_job_new (const gchar *title, + GtkPrinter *printer, GtkPrintSettings *settings, - GtkPageSetup *page_setup, - GtkPrinter *printer) + GtkPageSetup *page_setup) { GObject *result; - result = g_object_new (GTK_TYPE_PRINT_JOB, "title", title, "printer", printer, "settings", settings, "page-setup", page_setup, NULL); - return (GtkPrintJob *) result; } GtkPrintSettings * gtk_print_job_get_settings (GtkPrintJob *print_job) { - g_assert (GTK_IS_PRINT_SETTINGS (print_job->priv->settings)); + g_return_val_if_fail (GTK_IS_PRINT_JOB (print_job), NULL); + return print_job->priv->settings; } - GtkPrinter * gtk_print_job_get_printer (GtkPrintJob *print_job) { @@ -228,53 +290,91 @@ gtk_print_job_get_printer (GtkPrintJob *print_job) return print_job->priv->printer; } - -cairo_surface_t * -gtk_print_job_get_surface (GtkPrintJob *print_job) +const char * +gtk_print_job_get_title (GtkPrintJob *print_job) { g_return_val_if_fail (GTK_IS_PRINT_JOB (print_job), NULL); - - return print_job->priv->surface; + + return print_job->priv->title; } -gboolean -gtk_print_job_prepare (GtkPrintJob *job, - GError **error) +GtkPrintStatus +gtk_print_job_get_status (GtkPrintJob *print_job) +{ + g_return_val_if_fail (GTK_IS_PRINT_JOB (print_job), GTK_PRINT_STATUS_FINISHED); + + return print_job->priv->status; +} + +void +gtk_print_job_set_status (GtkPrintJob *job, + GtkPrintStatus status) +{ + if (job->priv->status == status) + return; + + job->priv->status = status; + g_signal_emit (job, signals[STATUS_CHANGED], 0); +} + +gboolean +gtk_print_job_set_source_file (GtkPrintJob *job, + const char *filename, + GError **error) +{ + g_return_val_if_fail (GTK_IS_PRINT_JOB (job), FALSE); + + job->priv->spool_file_fd = g_open (filename, O_RDONLY|O_BINARY); + if (job->priv->spool_file_fd < 0) + { + gchar *display_filename = g_filename_display_name (filename); + int save_errno = errno; + + g_set_error (error, + G_FILE_ERROR, + g_file_error_from_errno (save_errno), + _("Failed to open file '%s': %s"), + display_filename, + g_strerror (save_errno)); + + g_free (display_filename); + + return FALSE; + } + return TRUE; +} + +cairo_surface_t * +gtk_print_job_get_surface (GtkPrintJob *job, + GError **error) { char *filename; double width, height; GtkPaperSize *paper_size; - /* TODO: populate GError */ - if (!(job->priv->printer_set && - job->priv->settings_set && - job->priv->page_setup_set)) - return FALSE; + g_return_val_if_fail (GTK_IS_PRINT_JOB (job), NULL); - job->priv->prepped = TRUE; - job->priv->cache_fd = g_file_open_tmp ("gtkprint_XXXXXX", - &filename, - error); - fchmod (job->priv->cache_fd, S_IRUSR | S_IWUSR); + if (job->priv->surface) + return job->priv->surface; + + job->priv->spool_file_fd = g_file_open_tmp ("gtkprint_XXXXXX", + &filename, + error); + if (job->priv->spool_file_fd == -1) + return NULL; + + fchmod (job->priv->spool_file_fd, S_IRUSR | S_IWUSR); unlink (filename); - if (error != NULL && *error != NULL) - return FALSE; - paper_size = gtk_page_setup_get_paper_size (job->priv->page_setup); width = gtk_paper_size_get_width (paper_size, GTK_UNIT_POINTS); height = gtk_paper_size_get_height (paper_size, GTK_UNIT_POINTS); job->priv->surface = _gtk_printer_create_cairo_surface (job->priv->printer, width, height, - job->priv->cache_fd); - - _gtk_printer_prepare_for_print (job->priv->printer, - job, - job->priv->settings, - job->priv->page_setup); - - return TRUE; + job->priv->spool_file_fd); + + return job->priv->surface; } static void @@ -285,6 +385,7 @@ gtk_print_job_set_property (GObject *object, { GtkPrintJob *job = GTK_PRINT_JOB (object); + GtkPrintSettings *settings; switch (prop_id) { @@ -304,7 +405,10 @@ gtk_print_job_set_property (GObject *object, break; case GTK_PRINT_JOB_PROP_SETTINGS: - job->priv->settings = GTK_PRINT_SETTINGS (g_value_dup_object (value)); + /* We save a copy of the settings since we modify + * if when preparing the printer job. */ + settings = GTK_PRINT_SETTINGS (g_value_get_object (value)); + job->priv->settings = gtk_print_settings_copy (settings); job->priv->settings_set = TRUE; break; @@ -324,6 +428,9 @@ gtk_print_job_get_property (GObject *object, switch (prop_id) { + case GTK_PRINT_JOB_PROP_TITLE: + g_value_set_string (value, job->priv->title); + break; case GTK_PRINT_JOB_PROP_PRINTER: g_value_set_object (value, job->priv->printer); break; @@ -343,23 +450,23 @@ gboolean gtk_print_job_send (GtkPrintJob *print_job, GtkPrintJobCompleteFunc callback, gpointer user_data, + GDestroyNotify dnotify, GError **error) { - /* TODO: set gerror */ - if (!print_job->priv->prepped) - return FALSE; + g_return_val_if_fail (GTK_IS_PRINT_JOB (print_job), FALSE); + g_return_val_if_fail (print_job->priv->spool_file_fd > 0, FALSE); - lseek (print_job->priv->cache_fd, 0, SEEK_SET); + gtk_print_job_set_status (print_job, GTK_PRINT_STATUS_SENDING_DATA); + lseek (print_job->priv->spool_file_fd, 0, SEEK_SET); gtk_print_backend_print_stream (print_job->priv->backend, print_job, - print_job->priv->title, - print_job->priv->cache_fd, + print_job->priv->spool_file_fd, callback, - user_data); + user_data, + dnotify); return TRUE; } - #define __GTK_PRINT_JOB_C__ #include "gtkaliasdef.c" diff --git a/gtk/gtkprintjob.h b/gtk/gtkprintjob.h index ef4cabb913..a5116c9995 100644 --- a/gtk/gtkprintjob.h +++ b/gtk/gtkprintjob.h @@ -22,8 +22,8 @@ #include #include -#include "gtkprinter.h" -#include "gtkprintsettings.h" +#include +#include G_BEGIN_DECLS @@ -40,7 +40,7 @@ typedef struct _GtkPrintJobPrivate GtkPrintJobPrivate; typedef void (*GtkPrintJobCompleteFunc) (GtkPrintJob *print_job, void *user_data, - GError **error); + GError *error); struct _GtkPrinter; @@ -50,7 +50,9 @@ struct _GtkPrintJob GtkPrintJobPrivate *priv; - /* These are read-only, set by prepare */ + /* Settings the client has to implement: + * (These are read-only, set at initialization) + */ GtkPrintPages print_pages; GtkPageRange *page_ranges; int num_page_ranges; @@ -66,6 +68,7 @@ struct _GtkPrintJobClass { GObjectClass parent_class; + void (*status_changed) (GtkPrintJob *job); /* Padding for future expansion */ void (*_gtk_reserved1) (void); @@ -79,20 +82,24 @@ struct _GtkPrintJobClass GType gtk_print_job_get_type (void) G_GNUC_CONST; GtkPrintJob *gtk_print_job_new (const gchar *title, + GtkPrinter *printer, GtkPrintSettings *settings, - GtkPageSetup *page_setup, - GtkPrinter *printer); + GtkPageSetup *page_setup); GtkPrintSettings *gtk_print_job_get_settings (GtkPrintJob *print_job); GtkPrinter *gtk_print_job_get_printer (GtkPrintJob *print_job); -cairo_surface_t *gtk_print_job_get_surface (GtkPrintJob *print_job); -gboolean gtk_print_job_send (GtkPrintJob *print_job, - GtkPrintJobCompleteFunc callback, - gpointer user_data, - GError **error); -gboolean gtk_print_job_prepare (GtkPrintJob *job, - GError **error); - +const char *gtk_print_job_get_title (GtkPrintJob *print_job); +GtkPrintStatus gtk_print_job_get_status (GtkPrintJob *print_job); +gboolean gtk_print_job_set_source_file (GtkPrintJob *print_job, + const char *filename, + GError **error); +cairo_surface_t *gtk_print_job_get_surface (GtkPrintJob *print_job, + GError **error); +gboolean gtk_print_job_send (GtkPrintJob *print_job, + GtkPrintJobCompleteFunc callback, + gpointer user_data, + GDestroyNotify dnotify, + GError **error); G_END_DECLS diff --git a/gtk/gtkprintoperation-private.h b/gtk/gtkprintoperation-private.h index 922e8ea051..0b09ac4e8f 100644 --- a/gtk/gtkprintoperation-private.h +++ b/gtk/gtkprintoperation-private.h @@ -27,6 +27,7 @@ G_BEGIN_DECLS struct _GtkPrintOperationPrivate { + GtkPrintStatus status; GtkPageSetup *default_page_setup; GtkPrintSettings *print_settings; char *job_name; @@ -60,6 +61,7 @@ struct _GtkPrintOperationPrivate void (*end_page) (GtkPrintOperation *operation, GtkPrintContext *print_context); void (*end_run) (GtkPrintOperation *operation); + GDestroyNotify free_platform_data; }; GtkPrintOperationResult _gtk_print_operation_platform_backend_run_dialog (GtkPrintOperation *operation, @@ -67,7 +69,8 @@ GtkPrintOperationResult _gtk_print_operation_platform_backend_run_dialog (GtkPri gboolean *do_print, GError **error); - +void _gtk_print_operation_set_status (GtkPrintOperation *op, + GtkPrintStatus status); /* GtkPrintContext private functions: */ diff --git a/gtk/gtkprintoperation-unix.c b/gtk/gtkprintoperation-unix.c index e51d1d984f..330a873196 100644 --- a/gtk/gtkprintoperation-unix.c +++ b/gtk/gtkprintoperation-unix.c @@ -39,6 +39,7 @@ typedef struct { GtkPrintJob *job; /* the job we are sending to the printer */ + gulong job_status_changed_tag; GtkWindow *parent; /* parent window just in case we need to throw error dialogs */ } GtkPrintOperationUnix; @@ -64,7 +65,11 @@ static void op_unix_free (GtkPrintOperationUnix *op_unix) { if (op_unix->job) - g_object_unref (G_OBJECT (op_unix->job)); + { + g_signal_handler_disconnect (op_unix->job, + op_unix->job_status_changed_tag); + g_object_unref (op_unix->job); + } g_free (op_unix); } @@ -72,7 +77,7 @@ op_unix_free (GtkPrintOperationUnix *op_unix) static void unix_finish_send (GtkPrintJob *job, void *user_data, - GError **error) + GError *error) { GtkPrintOperationUnix *op_unix; GtkWindow *parent; @@ -81,19 +86,15 @@ unix_finish_send (GtkPrintJob *job, parent = op_unix->parent; - op_unix_free (op_unix); - - if (error != NULL && *error != NULL) + if (error != NULL) { GtkWidget *edialog; - GError *err = *error; - edialog = gtk_message_dialog_new (parent, GTK_DIALOG_DESTROY_WITH_PARENT, GTK_MESSAGE_ERROR, GTK_BUTTONS_CLOSE, "Error printing: %s", - err->message); + error->message); gtk_dialog_run (GTK_DIALOG (edialog)); gtk_widget_destroy (edialog); @@ -106,11 +107,16 @@ unix_end_run (GtkPrintOperation *op) GtkPrintOperationUnix *op_unix = op->priv->platform_data; /* TODO: Check for error */ - gtk_print_job_send (g_object_ref (op_unix->job), + gtk_print_job_send (op_unix->job, unix_finish_send, - op_unix, NULL); + op_unix, NULL, + NULL); +} - op->priv->platform_data = NULL; +static void +job_status_changed_cb (GtkPrintJob *job, GtkPrintOperation *op) +{ + _gtk_print_operation_set_status (op, gtk_print_job_get_status (job)); } GtkPrintOperationResult @@ -143,7 +149,7 @@ _gtk_print_operation_platform_backend_run_dialog (GtkPrintOperation *op, { GtkPrintOperationUnix *op_unix; GtkPrinter *printer; - GtkPrintSettings *settings, *settings_copy; + GtkPrintSettings *settings; result = GTK_PRINT_OPERATION_RESULT_APPLY; @@ -154,22 +160,17 @@ _gtk_print_operation_platform_backend_run_dialog (GtkPrintOperation *op, *do_print = TRUE; settings = gtk_print_unix_dialog_get_settings (GTK_PRINT_UNIX_DIALOG (pd)); + gtk_print_operation_set_print_settings (op, settings); - /* We save a copy to return to the user to avoid exposing - the extra settings preparint the printer job adds. */ - settings_copy = gtk_print_settings_copy (settings); - gtk_print_operation_set_print_settings (op, settings_copy); - g_object_unref (settings_copy); - - op_unix = g_new (GtkPrintOperationUnix, 1); - op_unix->job = gtk_printer_prepare_job (printer, - settings, - page_setup, - "Title", - error); + op_unix = g_new0 (GtkPrintOperationUnix, 1); + op_unix->job = gtk_print_job_new (op->priv->job_name, + printer, + settings, + page_setup); g_object_unref (settings); - - if (error != NULL && *error != NULL) + + op->priv->surface = gtk_print_job_get_surface (op_unix->job, error); + if (op->priv->surface == NULL) { *do_print = FALSE; op_unix_free (op_unix); @@ -177,14 +178,18 @@ _gtk_print_operation_platform_backend_run_dialog (GtkPrintOperation *op, goto out; } + _gtk_print_operation_set_status (op, gtk_print_job_get_status (op_unix->job)); + op_unix->job_status_changed_tag = + g_signal_connect (op_unix->job, "status_changed", + G_CALLBACK (job_status_changed_cb), op); + op_unix->parent = parent; - op->priv->surface = gtk_print_job_get_surface (op_unix->job); - op->priv->dpi_x = 72; op->priv->dpi_y = 72; op->priv->platform_data = op_unix; + op->priv->free_platform_data = (GDestroyNotify) op_unix_free; op->priv->print_pages = op_unix->job->print_pages; op->priv->page_ranges = op_unix->job->page_ranges; diff --git a/gtk/gtkprintoperation.c b/gtk/gtkprintoperation.c index 1547d5e4b5..2060a78aab 100644 --- a/gtk/gtkprintoperation.c +++ b/gtk/gtkprintoperation.c @@ -31,6 +31,7 @@ enum { REQUEST_PAGE_SETUP, DRAW_PAGE, END_PRINT, + STATUS_CHANGED, LAST_SIGNAL }; @@ -53,6 +54,13 @@ gtk_print_operation_finalize (GObject *object) { GtkPrintOperation *print_operation = GTK_PRINT_OPERATION (object); + if (print_operation->priv->free_platform_data && + print_operation->priv->platform_data) + { + print_operation->priv->free_platform_data (print_operation->priv->platform_data); + print_operation->priv->free_platform_data = NULL; + } + if (print_operation->priv->default_page_setup) g_object_unref (print_operation->priv->default_page_setup); @@ -61,6 +69,7 @@ gtk_print_operation_finalize (GObject *object) g_free (print_operation->priv->pdf_target); g_free (print_operation->priv->job_name); + G_OBJECT_CLASS (gtk_print_operation_parent_class)->finalize (object); } @@ -71,6 +80,7 @@ gtk_print_operation_init (GtkPrintOperation *operation) operation->priv = GTK_PRINT_OPERATION_GET_PRIVATE (operation); + operation->priv->status = GTK_PRINT_STATUS_INITIAL; operation->priv->default_page_setup = NULL; operation->priv->print_settings = NULL; operation->priv->nr_of_pages = -1; @@ -132,6 +142,15 @@ gtk_print_operation_class_init (GtkPrintOperationClass *class) NULL, NULL, g_cclosure_marshal_VOID__OBJECT, G_TYPE_NONE, 1, GTK_TYPE_PRINT_CONTEXT); + + signals[STATUS_CHANGED] = + g_signal_new ("status-changed", + G_TYPE_FROM_CLASS (class), + G_SIGNAL_RUN_LAST, + G_STRUCT_OFFSET (GtkPrintOperationClass, status_changed), + NULL, NULL, + g_cclosure_marshal_VOID__VOID, + G_TYPE_NONE, 0); } GtkPrintOperation * @@ -238,6 +257,37 @@ gtk_print_operation_set_unit (GtkPrintOperation *op, op->priv->unit = unit; } +void +_gtk_print_operation_set_status (GtkPrintOperation *op, + GtkPrintStatus status) +{ + if (op->priv->status == status) + return; + + op->priv->status = status; + g_signal_emit (op, signals[STATUS_CHANGED], 0); +} + + +GtkPrintStatus +gtk_print_operation_get_status (GtkPrintOperation *op) +{ + g_return_val_if_fail (GTK_IS_PRINT_OPERATION (op), GTK_PRINT_STATUS_FINISHED_ABORTED); + + return op->priv->status; +} + +gboolean +gtk_print_operation_is_finished (GtkPrintOperation *op) +{ + g_return_val_if_fail (GTK_IS_PRINT_OPERATION (op), TRUE); + + return + op->priv->status == GTK_PRINT_STATUS_FINISHED_ABORTED || + op->priv->status == GTK_PRINT_STATUS_FINISHED; +} + + void gtk_print_operation_set_show_dialog (GtkPrintOperation *op, gboolean show_dialog) @@ -404,7 +454,10 @@ gtk_print_operation_run (GtkPrintOperation *op, result = run_print_dialog (op, parent, &do_print, error); if (!do_print) - return result; + { + _gtk_print_operation_set_status (op, GTK_PRINT_STATUS_FINISHED_ABORTED); + return result; + } if (op->priv->manual_collation) { @@ -422,6 +475,7 @@ gtk_print_operation_run (GtkPrintOperation *op, initial_page_setup = create_page_setup (op); _gtk_print_context_set_page_setup (print_context, initial_page_setup); + _gtk_print_operation_set_status (op, GTK_PRINT_STATUS_PREPARING); g_signal_emit (op, signals[BEGIN_PRINT], 0, print_context); g_return_val_if_fail (op->priv->nr_of_pages != -1, FALSE); @@ -447,6 +501,8 @@ gtk_print_operation_run (GtkPrintOperation *op, ranges[0].end = op->priv->nr_of_pages - 1; } + _gtk_print_operation_set_status (op, GTK_PRINT_STATUS_GENERATING_DATA); + for (i = 0; i < uncollated_copies; i++) { for (range = 0; range < num_ranges; range ++) diff --git a/gtk/gtkprintoperation.h b/gtk/gtkprintoperation.h index ba693d5f15..170444d343 100644 --- a/gtk/gtkprintoperation.h +++ b/gtk/gtkprintoperation.h @@ -23,6 +23,7 @@ #include #include +#include "gtkmain.h" #include "gtkenums.h" #include "gtkwindow.h" #include "gtkpagesetup.h" @@ -39,6 +40,17 @@ typedef struct _GtkPrintOperationClass GtkPrintOperationClass; typedef struct _GtkPrintOperationPrivate GtkPrintOperationPrivate; typedef struct _GtkPrintOperation GtkPrintOperation; +typedef enum { + GTK_PRINT_STATUS_INITIAL, + GTK_PRINT_STATUS_PREPARING, + GTK_PRINT_STATUS_GENERATING_DATA, + GTK_PRINT_STATUS_SENDING_DATA, + GTK_PRINT_STATUS_PENDING, + GTK_PRINT_STATUS_PROCESSING, + GTK_PRINT_STATUS_FINISHED, + GTK_PRINT_STATUS_FINISHED_ABORTED +} GtkPrintStatus; + struct _GtkPrintOperation { GObject parent_instance; @@ -61,6 +73,8 @@ struct _GtkPrintOperationClass void (*end_print) (GtkPrintOperation *operation, GtkPrintContext *context); + void (*status_changed) (GtkPrintOperation *operation); + /* Padding for future expansion */ void (*_gtk_reserved1) (void); void (*_gtk_reserved2) (void); @@ -113,6 +127,8 @@ void gtk_print_operation_set_pdf_target (GtkPrintOper GtkPrintOperationResult gtk_print_operation_run (GtkPrintOperation *op, GtkWindow *parent, GError **error); +GtkPrintStatus gtk_print_operation_get_status (GtkPrintOperation *op); +gboolean gtk_print_operation_is_finished (GtkPrintOperation *op); GtkPageSetup *gtk_print_run_page_setup_dialog (GtkWindow *parent, GtkPageSetup *page_setup, diff --git a/modules/printbackends/cups/gtkprintbackendcups.c b/modules/printbackends/cups/gtkprintbackendcups.c index 981b1dfe40..9e09eb097d 100644 --- a/modules/printbackends/cups/gtkprintbackendcups.c +++ b/modules/printbackends/cups/gtkprintbackendcups.c @@ -138,6 +138,10 @@ static void cups_printer_get_hard_margins (GtkPrinter double *right); static void set_option_from_settings (GtkPrinterOption *option, GtkPrintSettings *setting); +static void cups_begin_polling_info (GtkPrintBackendCups *print_backend, + GtkPrintJob *job, + int job_id); +static gboolean cups_job_info_poll_timeout (gpointer user_data); static void gtk_print_backend_cups_register_type (GTypeModule *module) @@ -281,7 +285,17 @@ typedef struct { GtkPrintJobCompleteFunc callback; GtkPrintJob *job; gpointer user_data; -} _PrintStreamData; + GDestroyNotify dnotify; +} CupsPrintStreamData; + +static void +cups_free_print_stream_data (CupsPrintStreamData *data) +{ + if (data->dnotify) + data->dnotify (data->user_data); + g_object_unref (data->job); + g_free (data); +} static void cups_print_cb (GtkPrintBackendCups *print_backend, @@ -289,8 +303,7 @@ cups_print_cb (GtkPrintBackendCups *print_backend, gpointer user_data) { GError *error = NULL; - - _PrintStreamData *ps = (_PrintStreamData *) user_data; + CupsPrintStreamData *ps = user_data; if (gtk_cups_result_is_error (result)) error = g_error_new_literal (gtk_print_error_quark (), @@ -298,9 +311,33 @@ cups_print_cb (GtkPrintBackendCups *print_backend, gtk_cups_result_get_error_string (result)); if (ps->callback) - ps->callback (ps->job, ps->user_data, &error); + ps->callback (ps->job, ps->user_data, error); - g_free (ps); + if (error == NULL) + { + int job_id = 0; + ipp_attribute_t *attr; /* IPP job-id attribute */ + ipp_t *response = gtk_cups_result_get_response (result); + + if ((attr = ippFindAttribute(response, "job-id", IPP_TAG_INTEGER)) != NULL) + job_id = attr->values[0].integer; + + + if (job_id == 0) + gtk_print_job_set_status (ps->job, GTK_PRINT_STATUS_FINISHED); + else + { + gtk_print_job_set_status (ps->job, GTK_PRINT_STATUS_PENDING); + cups_begin_polling_info (print_backend, ps->job, job_id); + } + } + else + gtk_print_job_set_status (ps->job, GTK_PRINT_STATUS_FINISHED_ABORTED); + + + if (error) + g_error_free (error); + } static void @@ -324,16 +361,17 @@ add_cups_options (const char *key, static void gtk_print_backend_cups_print_stream (GtkPrintBackend *print_backend, GtkPrintJob *job, - const gchar *title, gint data_fd, GtkPrintJobCompleteFunc callback, - gpointer user_data) + gpointer user_data, + GDestroyNotify dnotify) { GError *error; GtkPrinterCups *cups_printer; - _PrintStreamData *ps; + CupsPrintStreamData *ps; GtkCupsRequest *request; GtkPrintSettings *settings; + const gchar *title; cups_printer = GTK_PRINTER_CUPS (gtk_print_job_get_printer (job)); settings = gtk_print_job_get_settings (job); @@ -353,22 +391,24 @@ gtk_print_backend_cups_print_stream (GtkPrintBackend *print_backend, gtk_cups_request_ipp_add_string (request, IPP_TAG_OPERATION, IPP_TAG_NAME, "requesting-user-name", NULL, cupsUser()); + title = gtk_print_job_get_title (job); if (title) gtk_cups_request_ipp_add_string (request, IPP_TAG_OPERATION, IPP_TAG_NAME, "job-name", NULL, title); gtk_print_settings_foreach (settings, add_cups_options, request); - ps = g_new0 (_PrintStreamData, 1); + ps = g_new0 (CupsPrintStreamData, 1); ps->callback = callback; ps->user_data = user_data; - ps->job = job; + ps->dnotify = dnotify; + ps->job = g_object_ref (job); cups_request_execute (GTK_PRINT_BACKEND_CUPS (print_backend), request, (GtkPrintCupsResponseCallbackFunc) cups_print_cb, ps, - NULL, + (GDestroyNotify)cups_free_print_stream_data, &error); } @@ -634,6 +674,9 @@ cups_request_printer_info_cb (GtkPrintBackendCups *print_backend, cups_printer->device_uri = g_strdup_printf ("/printers/%s", printer_name); + state_msg = ""; + loc = ""; + desc = ""; for (attr = response->attrs; attr != NULL; attr = attr->next) { if (!attr->name) @@ -732,6 +775,167 @@ cups_request_printer_info (GtkPrintBackendCups *print_backend, } + +typedef struct { + GtkPrintBackendCups *print_backend; + GtkPrintJob *job; + int job_id; + int counter; +} CupsJobPollData; + +static void +job_object_died (gpointer user_data, + GObject *where_the_object_was) +{ + CupsJobPollData *data = user_data; + data->job = NULL; +} + +static void +cups_job_poll_data_free (CupsJobPollData *data) +{ + if (data->job) + g_object_weak_unref (G_OBJECT (data->job), job_object_died, data); + + g_free (data); +} + +static void +cups_request_job_info_cb (GtkPrintBackendCups *print_backend, + GtkCupsResult *result, + gpointer user_data) +{ + CupsJobPollData *data = user_data; + ipp_attribute_t *attr; + ipp_t *response; + int state; + gboolean done; + + if (data->job == NULL) + { + cups_job_poll_data_free (data); + return; + } + + data->counter++; + + response = gtk_cups_result_get_response (result); + + state = 0; + for (attr = response->attrs; attr != NULL; attr = attr->next) + { + if (!attr->name) + continue; + + _CUPS_MAP_ATTR_INT (attr, state, "job-state"); + } + + done = FALSE; + switch (state) + { + case IPP_JOB_PENDING: + case IPP_JOB_HELD: + case IPP_JOB_STOPPED: + gtk_print_job_set_status (data->job, + GTK_PRINT_STATUS_PENDING); + break; + case IPP_JOB_PROCESSING: + gtk_print_job_set_status (data->job, + GTK_PRINT_STATUS_PROCESSING); + break; + default: + case IPP_JOB_CANCELLED: + case IPP_JOB_ABORTED: + gtk_print_job_set_status (data->job, + GTK_PRINT_STATUS_FINISHED_ABORTED); + done = TRUE; + break; + case 0: + case IPP_JOB_COMPLETED: + gtk_print_job_set_status (data->job, + GTK_PRINT_STATUS_FINISHED); + done = TRUE; + break; + } + + if (!done && data->job != NULL) + { + guint32 timeout; + + if (data->counter < 5) + timeout = 100; + else if (data->counter < 10) + timeout = 500; + else + timeout = 1000; + + g_timeout_add (timeout, cups_job_info_poll_timeout, data); + } + else + cups_job_poll_data_free (data); +} + +static void +cups_request_job_info (CupsJobPollData *data) +{ + GError *error; + GtkCupsRequest *request; + gchar *printer_uri; + + + error = NULL; + request = gtk_cups_request_new (NULL, + GTK_CUPS_POST, + IPP_GET_JOB_ATTRIBUTES, + 0, + NULL, + NULL); + + printer_uri = g_strdup_printf ("ipp://localhost/jobs/%d", data->job_id); + gtk_cups_request_ipp_add_string (request, IPP_TAG_OPERATION, IPP_TAG_URI, + "job-uri", NULL, printer_uri); + g_free (printer_uri); + + cups_request_execute (data->print_backend, + request, + (GtkPrintCupsResponseCallbackFunc) cups_request_job_info_cb, + data, + NULL, + &error); +} + +static gboolean +cups_job_info_poll_timeout (gpointer user_data) +{ + CupsJobPollData *data = user_data; + + if (data->job == NULL) + cups_job_poll_data_free (data); + else + cups_request_job_info (data); + + return FALSE; +} + +static void +cups_begin_polling_info (GtkPrintBackendCups *print_backend, + GtkPrintJob *job, + int job_id) +{ + CupsJobPollData *data; + + data = g_new0 (CupsJobPollData, 1); + + data->print_backend = print_backend; + data->job = job; + data->job_id = job_id; + data->counter = 0; + + g_object_weak_ref (G_OBJECT (job), job_object_died, data); + + cups_request_job_info (data); +} + static gint printer_cmp (GtkPrinter *a, GtkPrinter *b) { diff --git a/modules/printbackends/lpr/gtkprintbackendlpr.c b/modules/printbackends/lpr/gtkprintbackendlpr.c index 9206fbf463..dcbbe4674c 100644 --- a/modules/printbackends/lpr/gtkprintbackendlpr.c +++ b/modules/printbackends/lpr/gtkprintbackendlpr.c @@ -241,6 +241,7 @@ typedef struct { GtkPrintJobCompleteFunc callback; GtkPrintJob *job; gpointer user_data; + GDestroyNotify dnotify; gint in; gint out; @@ -250,7 +251,7 @@ typedef struct { static void lpr_print_cb (GtkPrintBackendLpr *print_backend, - GError **error, + GError *error, gpointer user_data) { _PrintStreamData *ps = (_PrintStreamData *) user_data; @@ -267,6 +268,15 @@ lpr_print_cb (GtkPrintBackendLpr *print_backend, if (ps->callback) ps->callback (ps->job, ps->user_data, error); + if (ps->dnotify) + ps->dnotify (ps->user_data); + + gtk_print_job_set_status (ps->job, + (error != NULL)?GTK_PRINT_STATUS_FINISHED_ABORTED:GTK_PRINT_STATUS_FINISHED); + + if (ps->job) + g_object_unref (ps->job); + g_free (ps); } @@ -307,7 +317,7 @@ lpr_write (GIOChannel *source, if (bytes_read == 0 || error != NULL) { - lpr_print_cb (GTK_PRINT_BACKEND_LPR (ps->backend), &error, user_data); + lpr_print_cb (GTK_PRINT_BACKEND_LPR (ps->backend), error, user_data); return FALSE; } @@ -319,11 +329,11 @@ lpr_write (GIOChannel *source, static void gtk_print_backend_lpr_print_stream (GtkPrintBackend *print_backend, - GtkPrintJob *job, - const gchar *title, - gint data_fd, - GtkPrintJobCompleteFunc callback, - gpointer user_data) + GtkPrintJob *job, + gint data_fd, + GtkPrintJobCompleteFunc callback, + gpointer user_data, + GDestroyNotify dnotify) { GError *error; GtkPrinterLpr *lpr_printer; @@ -344,7 +354,8 @@ gtk_print_backend_lpr_print_stream (GtkPrintBackend *print_backend, ps = g_new0 (_PrintStreamData, 1); ps->callback = callback; ps->user_data = user_data; - ps->job = job; + ps->dnotify = dnotify; + ps->job = g_object_ref (job); ps->in = 0; ps->out = 0; ps->err = 0; @@ -360,8 +371,7 @@ gtk_print_backend_lpr_print_stream (GtkPrintBackend *print_backend, &error)) { lpr_print_cb (GTK_PRINT_BACKEND_LPR (print_backend), - &error, - ps); + error, ps); g_free (cmd_line); return; @@ -382,8 +392,7 @@ gtk_print_backend_lpr_print_stream (GtkPrintBackend *print_backend, &error)) { lpr_print_cb (GTK_PRINT_BACKEND_LPR (print_backend), - &error, - ps); + error, ps); goto out; diff --git a/modules/printbackends/pdf/gtkprintbackendpdf.c b/modules/printbackends/pdf/gtkprintbackendpdf.c index 5b3c3bbf5e..3fd4ed3bbd 100644 --- a/modules/printbackends/pdf/gtkprintbackendpdf.c +++ b/modules/printbackends/pdf/gtkprintbackendpdf.c @@ -242,11 +242,12 @@ typedef struct { GtkPrintJob *job; gint target_fd; gpointer user_data; + GDestroyNotify dnotify; } _PrintStreamData; static void pdf_print_cb (GtkPrintBackendPdf *print_backend, - GError **error, + GError *error, gpointer user_data) { _PrintStreamData *ps = (_PrintStreamData *) user_data; @@ -257,6 +258,15 @@ pdf_print_cb (GtkPrintBackendPdf *print_backend, if (ps->callback) ps->callback (ps->job, ps->user_data, error); + if (ps->dnotify) + ps->dnotify (ps->user_data); + + gtk_print_job_set_status (ps->job, + (error != NULL)?GTK_PRINT_STATUS_FINISHED_ABORTED:GTK_PRINT_STATUS_FINISHED); + + if (ps->job) + g_object_unref (ps->job); + g_free (ps); } @@ -299,7 +309,7 @@ pdf_write (GIOChannel *source, if (bytes_read == 0 || error != NULL) { - pdf_print_cb (GTK_PRINT_BACKEND_PDF (ps->backend), &error, user_data); + pdf_print_cb (GTK_PRINT_BACKEND_PDF (ps->backend), error, user_data); return FALSE; } @@ -309,11 +319,11 @@ pdf_write (GIOChannel *source, static void gtk_print_backend_pdf_print_stream (GtkPrintBackend *print_backend, - GtkPrintJob *job, - const gchar *title, - gint data_fd, - GtkPrintJobCompleteFunc callback, - gpointer user_data) + GtkPrintJob *job, + gint data_fd, + GtkPrintJobCompleteFunc callback, + gpointer user_data, + GDestroyNotify dnotify) { GError *error; GtkPrinterPdf *pdf_printer; @@ -335,7 +345,7 @@ gtk_print_backend_pdf_print_stream (GtkPrintBackend *print_backend, ps = g_new0 (_PrintStreamData, 1); ps->callback = callback; ps->user_data = user_data; - ps->job = job; + ps->job = g_object_ref (job); filename = pdf_printer->file_option->value; @@ -349,7 +359,7 @@ gtk_print_backend_pdf_print_stream (GtkPrintBackend *print_backend, g_strerror (errno)); pdf_print_cb (GTK_PRINT_BACKEND_PDF (print_backend), - &error, + error, ps); return; diff --git a/tests/print-editor.c b/tests/print-editor.c index d235e235e2..d065f48768 100644 --- a/tests/print-editor.c +++ b/tests/print-editor.c @@ -9,6 +9,7 @@ static GtkPrintSettings *settings = NULL; static gboolean file_changed = FALSE; static GtkTextBuffer *buffer; static GtkWidget *statusbar; +static int printing_count = 0; static void update_title (void) @@ -44,8 +45,10 @@ update_statusbar (void) row = gtk_text_iter_get_line (&iter); col = gtk_text_iter_get_line_offset (&iter); - msg = g_strdup_printf ("%d, %d%s", - row, col, file_changed?" - Modified":""); + msg = g_strdup_printf ("%d, %d%s%s", + row, col, + file_changed?" - Modified":"", + (printing_count > 0)?" printing...":""); gtk_statusbar_push (GTK_STATUSBAR (statusbar), 0, msg); @@ -368,6 +371,17 @@ do_page_setup (GtkAction *action) page_setup = new_page_setup; } +static void +status_changed_cb (GtkPrintOperation *op, + gpointer user_data) +{ + if (gtk_print_operation_is_finished (op)) + { + g_object_unref (op); + printing_count--; + update_statusbar (); + } +} static void do_print (GtkAction *action) @@ -382,6 +396,7 @@ do_print (GtkAction *action) print = gtk_print_operation_new (); + if (settings != NULL) gtk_print_operation_set_print_settings (print, settings); @@ -412,6 +427,19 @@ do_print (GtkAction *action) g_object_unref (settings); settings = g_object_ref (gtk_print_operation_get_print_settings (print)); } + + if (!gtk_print_operation_is_finished (print)) + { + printing_count++; + update_statusbar (); + + /* This ref is unref:ed when we get the final state change */ + g_object_ref (print); + g_signal_connect (print, "status_changed", + G_CALLBACK (status_changed_cb), NULL); + } + + g_object_unref (print); } static void