]> Pileus Git - ~andy/gtk/blob - gtk/gtkprintjob.c
Added gtk_print_job_set/get_track_print_status
[~andy/gtk] / gtk / gtkprintjob.c
1 /* GtkPrintJob
2  * Copyright (C) 2006 John (J5) Palmieri  <johnp@redhat.com>
3  *
4  * This library is free software; you can redistribute it and/or
5  * modify it under the terms of the GNU Lesser General Public
6  * License as published by the Free Software Foundation; either
7  * version 2 of the License, or (at your option) any later version.
8  *
9  * This library is distributed in the hope that it will be useful,
10  * but WITHOUT ANY WARRANTY; without even the implied warranty of
11  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
12  * Lesser General Public License for more details.
13  *
14  * You should have received a copy of the GNU Lesser General Public
15  * License along with this library; if not, write to the
16  * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
17  * Boston, MA 02111-1307, USA.
18  */
19
20 #include "config.h"
21 #include <stdlib.h>
22 #include <string.h>
23 #include <stdio.h>
24 #include <fcntl.h>
25 #include <errno.h>
26 #ifdef HAVE_UNISTD_H
27 #include <unistd.h>
28 #endif
29 #include <sys/types.h>
30 #include <sys/stat.h>
31
32 #include <glib/gstdio.h>
33 #include "gtkintl.h"
34 #include "gtkprivate.h"
35
36 #include "gtkprintjob.h"
37 #include "gtkprinter.h"
38 #include "gtkprintbackend.h"
39 #include "gtkalias.h"
40
41 #ifndef O_BINARY
42 #define O_BINARY 0
43 #endif
44
45 struct _GtkPrintJobPrivate
46 {
47   gchar *title;
48
49   int spool_file_fd;
50   cairo_surface_t *surface;
51
52   GtkPrintStatus status;
53   GtkPrintBackend *backend;  
54   GtkPrinter *printer;
55   GtkPrintSettings *settings;
56   GtkPageSetup *page_setup;
57
58   guint printer_set : 1;
59   guint page_setup_set : 1;
60   guint settings_set  : 1;
61   guint track_print_status : 1;
62 };
63
64
65 #define GTK_PRINT_JOB_GET_PRIVATE(o)  \
66    (G_TYPE_INSTANCE_GET_PRIVATE ((o), GTK_TYPE_PRINT_JOB, GtkPrintJobPrivate))
67
68 static void     gtk_print_job_finalize     (GObject               *object);
69 static void     gtk_print_job_set_property (GObject               *object,
70                                             guint                  prop_id,
71                                             const GValue          *value,
72                                             GParamSpec            *pspec);
73 static void     gtk_print_job_get_property (GObject               *object,
74                                             guint                  prop_id,
75                                             GValue                *value,
76                                             GParamSpec            *pspec);
77 static GObject* gtk_print_job_constructor  (GType                  type,
78                                             guint                  n_construct_properties,
79                                             GObjectConstructParam *construct_params);
80
81 enum {
82   STATUS_CHANGED,
83   LAST_SIGNAL
84 };
85
86 enum {
87   PROP_0,
88   GTK_PRINT_JOB_PROP_TITLE,
89   GTK_PRINT_JOB_PROP_PRINTER,
90   GTK_PRINT_JOB_PROP_PAGE_SETUP,
91   GTK_PRINT_JOB_PROP_SETTINGS
92 };
93
94 static guint signals[LAST_SIGNAL] = { 0 };
95
96 G_DEFINE_TYPE (GtkPrintJob, gtk_print_job, G_TYPE_OBJECT)
97
98 static void
99 gtk_print_job_class_init (GtkPrintJobClass *class)
100 {
101   GObjectClass *object_class;
102   object_class = (GObjectClass *) class;
103
104   object_class->finalize = gtk_print_job_finalize;
105   object_class->constructor = gtk_print_job_constructor;
106   object_class->set_property = gtk_print_job_set_property;
107   object_class->get_property = gtk_print_job_get_property;
108
109   g_type_class_add_private (class, sizeof (GtkPrintJobPrivate));
110
111   g_object_class_install_property (G_OBJECT_CLASS (class),
112                                    GTK_PRINT_JOB_PROP_TITLE,
113                                    g_param_spec_string ("title",
114                                                         P_("Title"),
115                                                         P_("Title of the print job"),
116                                                         NULL,
117                                                         GTK_PARAM_READWRITE |
118                                                         G_PARAM_CONSTRUCT_ONLY));
119
120   g_object_class_install_property (G_OBJECT_CLASS (class),
121                                    GTK_PRINT_JOB_PROP_PRINTER,
122                                    g_param_spec_object ("printer",
123                                                         P_("Printer"),
124                                                         P_("Printer to print the job to"),
125                                                         GTK_TYPE_PRINTER,
126                                                         GTK_PARAM_READWRITE |
127                                                         G_PARAM_CONSTRUCT_ONLY));
128
129   g_object_class_install_property (G_OBJECT_CLASS (class),
130                                    GTK_PRINT_JOB_PROP_SETTINGS,
131                                    g_param_spec_object ("settings",
132                                                         P_("Settings"),
133                                                         P_("Printer settings"),
134                                                         GTK_TYPE_PRINT_SETTINGS,
135                                                         GTK_PARAM_READWRITE |
136                                                         G_PARAM_CONSTRUCT_ONLY));
137
138   g_object_class_install_property (G_OBJECT_CLASS (class),
139                                    GTK_PRINT_JOB_PROP_PAGE_SETUP,
140                                    g_param_spec_object ("page-setup",
141                                                         P_("Page Setup"),
142                                                         P_("Page Setup"),
143                                                         GTK_TYPE_PAGE_SETUP,
144                                                         GTK_PARAM_READWRITE |
145                                                         G_PARAM_CONSTRUCT_ONLY));
146
147   /**
148    * GtkPrintJob::status-changed:
149    * @job: the #GtkPrintJob object on which the signal was emitted
150    *
151    * Gets emitted when the status of a job changes. The signal handler
152    * can use gtk_print_job_get_status() to obtain the new status.
153    *
154    * Since: 2.10
155    */
156   signals[STATUS_CHANGED] =
157    g_signal_new ("status-changed",
158                  G_TYPE_FROM_CLASS (class),
159                  G_SIGNAL_RUN_LAST,
160                  G_STRUCT_OFFSET (GtkPrintJobClass, status_changed),
161                  NULL, NULL,
162                  g_cclosure_marshal_VOID__VOID,
163                  G_TYPE_NONE, 0);
164 }
165
166 static void
167 gtk_print_job_init (GtkPrintJob *job)
168 {
169   GtkPrintJobPrivate *priv;
170
171   priv = job->priv = GTK_PRINT_JOB_GET_PRIVATE (job); 
172
173   priv->spool_file_fd = -1;
174
175   priv->title = g_strdup ("");
176   priv->surface = NULL;
177   priv->backend = NULL;
178   priv->printer = NULL;
179
180   priv->printer_set = FALSE;
181   priv->settings_set = FALSE;
182   priv->page_setup_set = FALSE;
183   priv->status = GTK_PRINT_STATUS_INITIAL;
184   priv->track_print_status = FALSE;
185   
186   job->print_pages = GTK_PRINT_PAGES_ALL;
187   job->page_ranges = NULL;
188   job->num_page_ranges = 0;
189   job->collate = FALSE;
190   job->reverse = FALSE;
191   job->num_copies = 1;
192   job->scale = 1.0;
193   job->page_set = GTK_PAGE_SET_ALL;
194   job->rotate_to_orientation = FALSE;
195 }
196
197
198 static GObject*
199 gtk_print_job_constructor (GType                  type,
200                            guint                  n_construct_properties,
201                            GObjectConstructParam *construct_params)
202 {
203   GtkPrintJob *job;
204   GtkPrintJobPrivate *priv;
205   GObject *object;
206
207   object =
208     G_OBJECT_CLASS (gtk_print_job_parent_class)->constructor (type,
209                                                               n_construct_properties,
210                                                               construct_params);
211
212   job = GTK_PRINT_JOB (object);
213
214   priv = job->priv;
215   g_assert (priv->printer_set &&
216             priv->settings_set &&
217             priv->page_setup_set);
218   
219   _gtk_printer_prepare_for_print (priv->printer,
220                                   job,
221                                   priv->settings,
222                                   priv->page_setup);
223
224   return object;
225 }
226
227
228 static void
229 gtk_print_job_finalize (GObject *object)
230 {
231   GtkPrintJob *job = GTK_PRINT_JOB (object);
232   GtkPrintJobPrivate *priv = job->priv;
233
234   if (priv->spool_file_fd >= 0)
235     {
236       close (priv->spool_file_fd);
237       priv->spool_file_fd = -1;
238     }
239   
240   if (priv->backend)
241     g_object_unref (priv->backend);
242
243   if (priv->printer)
244     g_object_unref (priv->printer);
245
246   if (priv->surface)
247     cairo_surface_destroy (priv->surface);
248
249   if (priv->settings)
250     g_object_unref (priv->settings);
251   
252   if (priv->page_setup)
253     g_object_unref (priv->page_setup);
254
255   g_free (job->page_ranges);
256   job->page_ranges = NULL;
257   
258   g_free (priv->title);
259   priv->title = NULL;
260
261   G_OBJECT_CLASS (gtk_print_job_parent_class)->finalize (object);
262 }
263
264 /**
265  * gtk_print_job_new:
266  * @title: the job title
267  * @printer: a #GtkPrinter
268  * @settings: a #GtkPrintSettings
269  * @page_setup: a #GtkPageSetup
270  *
271  * Creates a new #GtkPrintJob.
272  *
273  * Return value: a new #GtkPrintJob
274  *
275  * Since: 2.10
276  **/
277 GtkPrintJob *
278 gtk_print_job_new (const gchar      *title,
279                    GtkPrinter       *printer,
280                    GtkPrintSettings *settings,
281                    GtkPageSetup     *page_setup)
282 {
283   GObject *result;
284   result = g_object_new (GTK_TYPE_PRINT_JOB,
285                          "title", title,
286                          "printer", printer,
287                          "settings", settings,
288                          "page-setup", page_setup,
289                          NULL);
290   return (GtkPrintJob *) result;
291 }
292
293 /**
294  * gtk_print_job_get_settings:
295  * @job: a #GtkPrintJob
296  * 
297  * Gets the #GtkPrintSettings of the print job.
298  * 
299  * Return value: the settings of @job
300  *
301  * Since: 2.10
302  */
303 GtkPrintSettings *
304 gtk_print_job_get_settings (GtkPrintJob *job)
305 {
306   g_return_val_if_fail (GTK_IS_PRINT_JOB (job), NULL);
307   
308   return job->priv->settings;
309 }
310
311 /**
312  * gtk_print_job_get_printer:
313  * @job: a #GtkPrintJob
314  * 
315  * Gets the #GtkPrinter of the print job.
316  * 
317  * Return value: the printer of @job
318  *
319  * Since: 2.10
320  */
321 GtkPrinter *
322 gtk_print_job_get_printer (GtkPrintJob *job)
323 {
324   g_return_val_if_fail (GTK_IS_PRINT_JOB (job), NULL);
325   
326   return job->priv->printer;
327 }
328
329 /**
330  * gtk_print_job_get_title:
331  * @job: a #GtkPrintJob
332  * 
333  * Gets the job title.
334  * 
335  * Return value: the title of @job
336  *
337  * Since: 2.10
338  */
339 G_CONST_RETURN gchar *
340 gtk_print_job_get_title (GtkPrintJob *job)
341 {
342   g_return_val_if_fail (GTK_IS_PRINT_JOB (job), NULL);
343   
344   return job->priv->title;
345 }
346
347 /**
348  * gtk_print_job_get_status:
349  * @job: a #GtkPrintJob
350  * 
351  * Gets the status of the print job.
352  * 
353  * Return value: the status of @job
354  *
355  * Since: 2.10
356  */
357 GtkPrintStatus
358 gtk_print_job_get_status (GtkPrintJob *job)
359 {
360   g_return_val_if_fail (GTK_IS_PRINT_JOB (job), GTK_PRINT_STATUS_FINISHED);
361   
362   return job->priv->status;
363 }
364
365 void
366 gtk_print_job_set_status (GtkPrintJob   *job,
367                           GtkPrintStatus status)
368 {
369   GtkPrintJobPrivate *priv;
370
371   g_return_if_fail (GTK_IS_PRINT_JOB (job));
372
373   priv = job->priv;
374
375   if (priv->status == status)
376     return;
377
378   priv->status = status;
379   g_signal_emit (job, signals[STATUS_CHANGED], 0);
380 }
381
382 /**
383  * gtk_print_job_set_source_file:
384  * @job: a #GtkPrintJob
385  * @filename: the file to be printed
386  * @error: return location for errors
387  * 
388  * Make the #GtkPrintJob send an existing document to the 
389  * printing system. The file can be in any format understood
390  * by the platforms printing system (typically PostScript,
391  * but on many platforms PDF may work too).
392  * 
393  * Returns: %FALSE if an error occurred
394  *
395  * Since: 2.10
396  **/
397 gboolean
398 gtk_print_job_set_source_file (GtkPrintJob *job,
399                                const gchar *filename,
400                                GError     **error)
401 {
402   GtkPrintJobPrivate *priv;
403
404   g_return_val_if_fail (GTK_IS_PRINT_JOB (job), FALSE);
405
406   priv = job->priv;
407
408   priv->spool_file_fd = g_open (filename, O_RDONLY|O_BINARY);
409   if (priv->spool_file_fd < 0)
410     {
411       gchar *display_filename = g_filename_display_name (filename);
412       int save_errno = errno;
413       
414       g_set_error (error,
415                    G_FILE_ERROR,
416                    g_file_error_from_errno (save_errno),
417                    _("Failed to open file '%s': %s"),
418                    display_filename, 
419                    g_strerror (save_errno));
420       
421       g_free (display_filename);
422
423       return FALSE;
424     }
425     return TRUE;
426 }
427
428 /**
429  * gtk_print_job_get_surface:
430  * @job: a #GtkPrintJob
431  * @error: return location for errors, or %NULL
432  * 
433  * Gets a cairo surface onto which the pages of
434  * the print job should be rendered.
435  * 
436  * Return value: the cairo surface of @job
437  *
438  * Since: 2.10
439  **/
440 cairo_surface_t *
441 gtk_print_job_get_surface (GtkPrintJob  *job,
442                            GError      **error)
443 {
444   GtkPrintJobPrivate *priv;
445   gchar *filename;
446   gdouble width, height;
447   GtkPaperSize *paper_size;
448   
449   g_return_val_if_fail (GTK_IS_PRINT_JOB (job), NULL);
450
451   priv = job->priv;
452
453   if (priv->surface)
454     return priv->surface;
455  
456   g_return_val_if_fail (priv->spool_file_fd == -1, NULL);
457  
458   priv->spool_file_fd = g_file_open_tmp ("gtkprint_XXXXXX", 
459                                                     &filename, 
460                                                     error);
461   if (priv->spool_file_fd == -1)
462     return NULL;
463
464   fchmod (priv->spool_file_fd, S_IRUSR | S_IWUSR);
465   unlink (filename);
466
467   paper_size = gtk_page_setup_get_paper_size (priv->page_setup);
468   width = gtk_paper_size_get_width (paper_size, GTK_UNIT_POINTS);
469   height = gtk_paper_size_get_height (paper_size, GTK_UNIT_POINTS);
470   
471   priv->surface = _gtk_printer_create_cairo_surface (priv->printer,
472                                                           width, height,
473                                                           priv->spool_file_fd);
474  
475   return priv->surface;
476 }
477
478 /**
479  * gtk_print_job_set_track_print_status:
480  * @job: a #GtkPrintJob
481  * @track_status: %TRUE to track status after printing
482  * 
483  * If track_status is %TRUE, the print job will try to continue report
484  * on the status of the print job in the printer queues and printer. This
485  * can allow your application to show things like "out of paper" issues,
486  * and when the print job actually reaches the printer.
487  * 
488  * This function is often implemented using some form of polling, so it should
489  * not be enabled unless needed.
490  *
491  * Since: 2.10
492  */
493 void
494 gtk_print_job_set_track_print_status (GtkPrintJob *job,
495                                       gboolean track_status)
496 {
497   GtkPrintJobPrivate *priv;
498
499   g_return_if_fail (GTK_IS_PRINT_JOB (job));
500
501   priv = job->priv;
502
503   priv->track_print_status = track_status;
504 }
505
506 /**
507  * gtk_print_job_get_track_print_status:
508  * @job: a #GtkPrintJob
509  *
510  * Returns wheter jobs will be tracked after printing.
511  * For details, see gtk_print_job_set_track_print_status().
512  *
513  * Return value: %TRUE if print job status will be reported after printing
514  *
515  * Since: 2.10
516  */
517 gboolean
518 gtk_print_job_get_track_print_status (GtkPrintJob *job)
519 {
520   GtkPrintJobPrivate *priv;
521
522   g_return_val_if_fail (GTK_IS_PRINT_JOB (job), FALSE);
523
524   priv = job->priv;
525   
526   return priv->track_print_status;
527 }
528
529 static void
530 gtk_print_job_set_property (GObject      *object,
531                             guint         prop_id,
532                             const GValue *value,
533                             GParamSpec   *pspec)
534
535 {
536   GtkPrintJob *job = GTK_PRINT_JOB (object);
537   GtkPrintJobPrivate *priv = job->priv;
538   GtkPrintSettings *settings;
539
540   switch (prop_id)
541     {
542     case GTK_PRINT_JOB_PROP_TITLE:
543       priv->title = g_value_dup_string (value);
544       break;
545     
546     case GTK_PRINT_JOB_PROP_PRINTER:
547       priv->printer = GTK_PRINTER (g_value_dup_object (value));
548       priv->printer_set = TRUE;
549       priv->backend = g_object_ref (gtk_printer_get_backend (priv->printer));
550       break;
551
552     case GTK_PRINT_JOB_PROP_PAGE_SETUP:
553       priv->page_setup = GTK_PAGE_SETUP (g_value_dup_object (value));
554       priv->page_setup_set = TRUE;
555       break;
556       
557     case GTK_PRINT_JOB_PROP_SETTINGS:
558       /* We save a copy of the settings since we modify
559        * if when preparing the printer job. */
560       settings = GTK_PRINT_SETTINGS (g_value_get_object (value));
561       priv->settings = gtk_print_settings_copy (settings);
562       priv->settings_set = TRUE;
563       break;
564
565     default:
566       G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
567       break;
568     }
569 }
570
571 static void
572 gtk_print_job_get_property (GObject    *object,
573                             guint       prop_id,
574                             GValue     *value,
575                             GParamSpec *pspec)
576 {
577   GtkPrintJob *job = GTK_PRINT_JOB (object);
578   GtkPrintJobPrivate *priv = job->priv;
579
580   switch (prop_id)
581     {
582     case GTK_PRINT_JOB_PROP_TITLE:
583       g_value_set_string (value, priv->title);
584       break;
585     case GTK_PRINT_JOB_PROP_PRINTER:
586       g_value_set_object (value, priv->printer);
587       break;
588     case GTK_PRINT_JOB_PROP_SETTINGS:
589       g_value_set_object (value, priv->settings);
590       break;
591     case GTK_PRINT_JOB_PROP_PAGE_SETUP:
592       g_value_set_object (value, priv->page_setup);
593       break;
594     default:
595       G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
596       break;
597     }
598 }
599
600 /**
601  * gtk_print_job_send:
602  * @job: a GtkPrintJob
603  * @callback: function to call when the job completes
604  * @user_data: user data that gets passed to @callback
605  * @dnotify: destroy notify for @user_data
606  * @error: return location for errors, or %NULL
607  * 
608  * Sends the print job off to the printer.  
609  * 
610  * Return value: %FALSE if an error occurred
611  *
612  * Since: 2.10
613  **/
614 gboolean
615 gtk_print_job_send (GtkPrintJob             *job,
616                     GtkPrintJobCompleteFunc  callback,
617                     gpointer                 user_data,
618                     GDestroyNotify           dnotify,
619                     GError                 **error)
620 {
621   GtkPrintJobPrivate *priv;
622
623   g_return_val_if_fail (GTK_IS_PRINT_JOB (job), FALSE);
624
625   priv = job->priv;
626   g_return_val_if_fail (priv->spool_file_fd > 0, FALSE);
627   
628   gtk_print_job_set_status (job, GTK_PRINT_STATUS_SENDING_DATA);
629   lseek (priv->spool_file_fd, 0, SEEK_SET);
630   gtk_print_backend_print_stream (priv->backend,
631                                   job,
632                                   priv->spool_file_fd,
633                                   callback,
634                                   user_data,
635                                   dnotify);
636
637   return TRUE;
638 }
639
640 #define __GTK_PRINT_JOB_C__
641 #include "gtkaliasdef.c"