]> Pileus Git - ~andy/gtk/blob - gtk/gtkprintjob.c
More of the same
[~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   gint printer_set : 1;
59   gint page_setup_set : 1;
60   gint settings_set  : 1;
61 };
62
63
64 #define GTK_PRINT_JOB_GET_PRIVATE(o)  \
65    (G_TYPE_INSTANCE_GET_PRIVATE ((o), GTK_TYPE_PRINT_JOB, GtkPrintJobPrivate))
66
67 static void     gtk_print_job_finalize     (GObject               *object);
68 static void     gtk_print_job_set_property (GObject               *object,
69                                             guint                  prop_id,
70                                             const GValue          *value,
71                                             GParamSpec            *pspec);
72 static void     gtk_print_job_get_property (GObject               *object,
73                                             guint                  prop_id,
74                                             GValue                *value,
75                                             GParamSpec            *pspec);
76 static GObject* gtk_print_job_constructor  (GType                  type,
77                                             guint                  n_construct_properties,
78                                             GObjectConstructParam *construct_params);
79
80 enum {
81   STATUS_CHANGED,
82   LAST_SIGNAL
83 };
84
85 enum {
86   PROP_0,
87   GTK_PRINT_JOB_PROP_TITLE,
88   GTK_PRINT_JOB_PROP_PRINTER,
89   GTK_PRINT_JOB_PROP_PAGE_SETUP,
90   GTK_PRINT_JOB_PROP_SETTINGS
91 };
92
93 static guint signals[LAST_SIGNAL] = { 0 };
94
95 G_DEFINE_TYPE (GtkPrintJob, gtk_print_job, G_TYPE_OBJECT)
96
97 static void
98 gtk_print_job_class_init (GtkPrintJobClass *class)
99 {
100   GObjectClass *object_class;
101   object_class = (GObjectClass *) class;
102
103   object_class->finalize = gtk_print_job_finalize;
104   object_class->constructor = gtk_print_job_constructor;
105   object_class->set_property = gtk_print_job_set_property;
106   object_class->get_property = gtk_print_job_get_property;
107
108   g_type_class_add_private (class, sizeof (GtkPrintJobPrivate));
109
110   g_object_class_install_property (G_OBJECT_CLASS (class),
111                                    GTK_PRINT_JOB_PROP_TITLE,
112                                    g_param_spec_string ("title",
113                                                         P_("Title"),
114                                                         P_("Title of the print job"),
115                                                         NULL,
116                                                         GTK_PARAM_READWRITE |
117                                                         G_PARAM_CONSTRUCT_ONLY));
118
119   g_object_class_install_property (G_OBJECT_CLASS (class),
120                                    GTK_PRINT_JOB_PROP_PRINTER,
121                                    g_param_spec_object ("printer",
122                                                         P_("Printer"),
123                                                         P_("Printer to print the job to"),
124                                                         GTK_TYPE_PRINTER,
125                                                         GTK_PARAM_READWRITE |
126                                                         G_PARAM_CONSTRUCT_ONLY));
127
128   g_object_class_install_property (G_OBJECT_CLASS (class),
129                                    GTK_PRINT_JOB_PROP_SETTINGS,
130                                    g_param_spec_object ("settings",
131                                                         P_("Settings"),
132                                                         P_("Printer settings"),
133                                                         GTK_TYPE_PRINT_SETTINGS,
134                                                         GTK_PARAM_READWRITE |
135                                                         G_PARAM_CONSTRUCT_ONLY));
136
137   g_object_class_install_property (G_OBJECT_CLASS (class),
138                                    GTK_PRINT_JOB_PROP_PAGE_SETUP,
139                                    g_param_spec_object ("page-setup",
140                                                         P_("Page Setup"),
141                                                         P_("Page Setup"),
142                                                         GTK_TYPE_PAGE_SETUP,
143                                                         GTK_PARAM_READWRITE |
144                                                         G_PARAM_CONSTRUCT_ONLY));
145
146   /**
147    * GtkPrintJob::status-changed:
148    * @job: the #GtkPrintJob object on which the signal was emitted
149    *
150    * Gets emitted when the status of a job changes. The signal handler
151    * can use gtk_print_job_get_status() to obtain the new status.
152    *
153    * Since: 2.10
154    */
155   signals[STATUS_CHANGED] =
156    g_signal_new ("status-changed",
157                  G_TYPE_FROM_CLASS (class),
158                  G_SIGNAL_RUN_LAST,
159                  G_STRUCT_OFFSET (GtkPrintJobClass, status_changed),
160                  NULL, NULL,
161                  g_cclosure_marshal_VOID__VOID,
162                  G_TYPE_NONE, 0);
163 }
164
165 static void
166 gtk_print_job_init (GtkPrintJob *job)
167 {
168   GtkPrintJobPrivate *priv;
169
170   priv = job->priv = GTK_PRINT_JOB_GET_PRIVATE (job); 
171
172   priv->spool_file_fd = -1;
173
174   priv->title = g_strdup ("");
175   priv->surface = NULL;
176   priv->backend = NULL;
177   priv->printer = NULL;
178
179   priv->printer_set = FALSE;
180   priv->settings_set = FALSE;
181   priv->page_setup_set = FALSE;
182   priv->status = GTK_PRINT_STATUS_INITIAL;
183
184   job->print_pages = GTK_PRINT_PAGES_ALL;
185   job->page_ranges = NULL;
186   job->num_page_ranges = 0;
187   job->collate = FALSE;
188   job->reverse = FALSE;
189   job->num_copies = 1;
190   job->scale = 1.0;
191   job->page_set = GTK_PAGE_SET_ALL;
192   job->rotate_to_orientation = FALSE;
193 }
194
195
196 static GObject*
197 gtk_print_job_constructor (GType                  type,
198                            guint                  n_construct_properties,
199                            GObjectConstructParam *construct_params)
200 {
201   GtkPrintJob *job;
202   GtkPrintJobPrivate *priv;
203   GObject *object;
204
205   object =
206     G_OBJECT_CLASS (gtk_print_job_parent_class)->constructor (type,
207                                                               n_construct_properties,
208                                                               construct_params);
209
210   job = GTK_PRINT_JOB (object);
211
212   priv = job->priv;
213   g_assert (priv->printer_set &&
214             priv->settings_set &&
215             priv->page_setup_set);
216   
217   _gtk_printer_prepare_for_print (priv->printer,
218                                   job,
219                                   priv->settings,
220                                   priv->page_setup);
221
222   return object;
223 }
224
225
226 static void
227 gtk_print_job_finalize (GObject *object)
228 {
229   GtkPrintJob *job = GTK_PRINT_JOB (object);
230   GtkPrintJobPrivate *priv = job->priv;
231
232   if (priv->spool_file_fd >= 0)
233     {
234       close (priv->spool_file_fd);
235       priv->spool_file_fd = -1;
236     }
237   
238   if (priv->backend)
239     g_object_unref (priv->backend);
240
241   if (priv->printer)
242     g_object_unref (priv->printer);
243
244   if (priv->surface)
245     cairo_surface_destroy (priv->surface);
246
247   if (priv->settings)
248     g_object_unref (priv->settings);
249   
250   if (priv->page_setup)
251     g_object_unref (priv->page_setup);
252
253   g_free (job->page_ranges);
254   job->page_ranges = NULL;
255   
256   g_free (priv->title);
257   priv->title = NULL;
258
259   G_OBJECT_CLASS (gtk_print_job_parent_class)->finalize (object);
260 }
261
262 /**
263  * gtk_print_job_new:
264  * @title: the job title
265  * @printer: a #GtkPrinter
266  * @settings: a #GtkPrintSettings
267  * @page_setup: a #GtkPageSetup
268  *
269  * Creates a new #GtkPrintJob.
270  *
271  * Return value: a new #GtkPrintJob
272  *
273  * Since: 2.10
274  **/
275 GtkPrintJob *
276 gtk_print_job_new (const gchar      *title,
277                    GtkPrinter       *printer,
278                    GtkPrintSettings *settings,
279                    GtkPageSetup     *page_setup)
280 {
281   GObject *result;
282   result = g_object_new (GTK_TYPE_PRINT_JOB,
283                          "title", title,
284                          "printer", printer,
285                          "settings", settings,
286                          "page-setup", page_setup,
287                          NULL);
288   return (GtkPrintJob *) result;
289 }
290
291 /**
292  * gtk_print_job_get_settings:
293  * @job: a #GtkPrintJob
294  * 
295  * Gets the #GtkPrintSettings of the print job.
296  * 
297  * Return value: the settings of @job
298  *
299  * Since: 2.10
300  */
301 GtkPrintSettings *
302 gtk_print_job_get_settings (GtkPrintJob *job)
303 {
304   g_return_val_if_fail (GTK_IS_PRINT_JOB (job), NULL);
305   
306   return job->priv->settings;
307 }
308
309 /**
310  * gtk_print_job_get_printer:
311  * @job: a #GtkPrintJob
312  * 
313  * Gets the #GtkPrinter of the print job.
314  * 
315  * Return value: the printer of @job
316  *
317  * Since: 2.10
318  */
319 GtkPrinter *
320 gtk_print_job_get_printer (GtkPrintJob *job)
321 {
322   g_return_val_if_fail (GTK_IS_PRINT_JOB (job), NULL);
323   
324   return job->priv->printer;
325 }
326
327 /**
328  * gtk_print_job_get_title:
329  * @job: a #GtkPrintJob
330  * 
331  * Gets the job title.
332  * 
333  * Return value: the title of @job
334  *
335  * Since: 2.10
336  */
337 G_CONST_RETURN gchar *
338 gtk_print_job_get_title (GtkPrintJob *job)
339 {
340   g_return_val_if_fail (GTK_IS_PRINT_JOB (job), NULL);
341   
342   return job->priv->title;
343 }
344
345 /**
346  * gtk_print_job_get_status:
347  * @job: a #GtkPrintJob
348  * 
349  * Gets the status of the print job.
350  * 
351  * Return value: the status of @job
352  *
353  * Since: 2.10
354  */
355 GtkPrintStatus
356 gtk_print_job_get_status (GtkPrintJob *job)
357 {
358   g_return_val_if_fail (GTK_IS_PRINT_JOB (job), GTK_PRINT_STATUS_FINISHED);
359   
360   return job->priv->status;
361 }
362
363 void
364 gtk_print_job_set_status (GtkPrintJob   *job,
365                           GtkPrintStatus status)
366 {
367   GtkPrintJobPrivate *priv;
368
369   g_return_if_fail (GTK_IS_PRINT_JOB (job));
370
371   priv = job->priv;
372
373   if (priv->status == status)
374     return;
375
376   priv->status = status;
377   g_signal_emit (job, signals[STATUS_CHANGED], 0);
378 }
379
380 /**
381  * gtk_print_job_set_source_file:
382  * @job: a #GtkPrintJob
383  * @filename: the file to be printed
384  * @error: return location for errors
385  * 
386  * Make the #GtkPrintJob send an existing document to the 
387  * printing system. The file can be in any format understood
388  * by the platforms printing system (typically PostScript,
389  * but on many platforms PDF may work too).
390  * 
391  * Returns: %FALSE if an error occurred
392  *
393  * Since: 2.10
394  **/
395 gboolean
396 gtk_print_job_set_source_file (GtkPrintJob *job,
397                                const gchar *filename,
398                                GError     **error)
399 {
400   GtkPrintJobPrivate *priv;
401
402   g_return_val_if_fail (GTK_IS_PRINT_JOB (job), FALSE);
403
404   priv = job->priv;
405
406   priv->spool_file_fd = g_open (filename, O_RDONLY|O_BINARY);
407   if (priv->spool_file_fd < 0)
408     {
409       gchar *display_filename = g_filename_display_name (filename);
410       int save_errno = errno;
411       
412       g_set_error (error,
413                    G_FILE_ERROR,
414                    g_file_error_from_errno (save_errno),
415                    _("Failed to open file '%s': %s"),
416                    display_filename, 
417                    g_strerror (save_errno));
418       
419       g_free (display_filename);
420
421       return FALSE;
422     }
423     return TRUE;
424 }
425
426 /**
427  * gtk_print_job_get_surface:
428  * @job: a #GtkPrintJob
429  * @error: return location for errors, or %NULL
430  * 
431  * Gets a cairo surface onto which the pages of
432  * the print job should be rendered.
433  * 
434  * Return value: the cairo surface of @job
435  *
436  * Since: 2.10
437  **/
438 cairo_surface_t *
439 gtk_print_job_get_surface (GtkPrintJob  *job,
440                            GError      **error)
441 {
442   GtkPrintJobPrivate *priv;
443   gchar *filename;
444   gdouble width, height;
445   GtkPaperSize *paper_size;
446   
447   g_return_val_if_fail (GTK_IS_PRINT_JOB (job), NULL);
448
449   priv = job->priv;
450
451   if (priv->surface)
452     return priv->surface;
453  
454   g_return_val_if_fail (priv->spool_file_fd == -1, NULL);
455  
456   priv->spool_file_fd = g_file_open_tmp ("gtkprint_XXXXXX", 
457                                                     &filename, 
458                                                     error);
459   if (priv->spool_file_fd == -1)
460     return NULL;
461
462   fchmod (priv->spool_file_fd, S_IRUSR | S_IWUSR);
463   unlink (filename);
464
465   paper_size = gtk_page_setup_get_paper_size (priv->page_setup);
466   width = gtk_paper_size_get_width (paper_size, GTK_UNIT_POINTS);
467   height = gtk_paper_size_get_height (paper_size, GTK_UNIT_POINTS);
468   
469   priv->surface = _gtk_printer_create_cairo_surface (priv->printer,
470                                                           width, height,
471                                                           priv->spool_file_fd);
472  
473   return priv->surface;
474 }
475
476 static void
477 gtk_print_job_set_property (GObject      *object,
478                             guint         prop_id,
479                             const GValue *value,
480                             GParamSpec   *pspec)
481
482 {
483   GtkPrintJob *job = GTK_PRINT_JOB (object);
484   GtkPrintJobPrivate *priv = job->priv;
485   GtkPrintSettings *settings;
486
487   switch (prop_id)
488     {
489     case GTK_PRINT_JOB_PROP_TITLE:
490       priv->title = g_value_dup_string (value);
491       break;
492     
493     case GTK_PRINT_JOB_PROP_PRINTER:
494       priv->printer = GTK_PRINTER (g_value_dup_object (value));
495       priv->printer_set = TRUE;
496       priv->backend = g_object_ref (gtk_printer_get_backend (priv->printer));
497       break;
498
499     case GTK_PRINT_JOB_PROP_PAGE_SETUP:
500       priv->page_setup = GTK_PAGE_SETUP (g_value_dup_object (value));
501       priv->page_setup_set = TRUE;
502       break;
503       
504     case GTK_PRINT_JOB_PROP_SETTINGS:
505       /* We save a copy of the settings since we modify
506        * if when preparing the printer job. */
507       settings = GTK_PRINT_SETTINGS (g_value_get_object (value));
508       priv->settings = gtk_print_settings_copy (settings);
509       priv->settings_set = TRUE;
510       break;
511
512     default:
513       G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
514       break;
515     }
516 }
517
518 static void
519 gtk_print_job_get_property (GObject    *object,
520                             guint       prop_id,
521                             GValue     *value,
522                             GParamSpec *pspec)
523 {
524   GtkPrintJob *job = GTK_PRINT_JOB (object);
525   GtkPrintJobPrivate *priv = job->priv;
526
527   switch (prop_id)
528     {
529     case GTK_PRINT_JOB_PROP_TITLE:
530       g_value_set_string (value, priv->title);
531       break;
532     case GTK_PRINT_JOB_PROP_PRINTER:
533       g_value_set_object (value, priv->printer);
534       break;
535     case GTK_PRINT_JOB_PROP_SETTINGS:
536       g_value_set_object (value, priv->settings);
537       break;
538     case GTK_PRINT_JOB_PROP_PAGE_SETUP:
539       g_value_set_object (value, priv->page_setup);
540       break;
541     default:
542       G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
543       break;
544     }
545 }
546
547 /**
548  * gtk_print_job_send:
549  * @job: a GtkPrintJob
550  * @callback: function to call when the job completes
551  * @user_data: user data that gets passed to @callback
552  * @dnotify: destroy notify for @user_data
553  * @error: return location for errors, or %NULL
554  * 
555  * Sends the print job off to the printer.  
556  * 
557  * Return value: %FALSE if an error occurred
558  *
559  * Since: 2.10
560  **/
561 gboolean
562 gtk_print_job_send (GtkPrintJob             *job,
563                     GtkPrintJobCompleteFunc  callback,
564                     gpointer                 user_data,
565                     GDestroyNotify           dnotify,
566                     GError                 **error)
567 {
568   GtkPrintJobPrivate *priv;
569
570   g_return_val_if_fail (GTK_IS_PRINT_JOB (job), FALSE);
571
572   priv = job->priv;
573   g_return_val_if_fail (priv->spool_file_fd > 0, FALSE);
574   
575   gtk_print_job_set_status (job, GTK_PRINT_STATUS_SENDING_DATA);
576   lseek (priv->spool_file_fd, 0, SEEK_SET);
577   gtk_print_backend_print_stream (priv->backend,
578                                   job,
579                                   priv->spool_file_fd,
580                                   callback,
581                                   user_data,
582                                   dnotify);
583
584   return TRUE;
585 }
586
587 #define __GTK_PRINT_JOB_C__
588 #include "gtkaliasdef.c"