]> Pileus Git - ~andy/gtk/blob - gtk/gtkprintoperation-unix.c
Use a priv variable when accessing priv multiple times in the same
[~andy/gtk] / gtk / gtkprintoperation-unix.c
1 /* GTK - The GIMP Toolkit
2  * gtkprintoperation-unix.c: Print Operation Details for Unix and Unix like platforms
3  * Copyright (C) 2006, Red Hat, Inc.
4  *
5  * This library is free software; you can redistribute it and/or
6  * modify it under the terms of the GNU Lesser General Public
7  * License as published by the Free Software Foundation; either
8  * version 2 of the License, or (at your option) any later version.
9  *
10  * This library is distributed in the hope that it will be useful,
11  * but WITHOUT ANY WARRANTY; without even the implied warranty of
12  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
13  * Lesser General Public License for more details.
14  *
15  * You should have received a copy of the GNU Lesser General Public
16  * License along with this library; if not, write to the
17  * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
18  * Boston, MA 02111-1307, USA.
19  */
20
21 #include "config.h"
22 #ifdef HAVE_UNISTD_H
23 #include <unistd.h>
24 #endif
25 #include <sys/types.h>
26 #include <sys/stat.h>
27 #include <string.h>
28
29 #include "gtkprintoperation-private.h"
30 #include "gtkmarshal.h"
31 #include "gtkmessagedialog.h"
32
33 #include "gtkprintunixdialog.h"
34 #include "gtkpagesetupunixdialog.h"
35 #include "gtkprintbackend.h"
36 #include "gtkprinter.h"
37 #include "gtkprintjob.h"
38 #include "gtkalias.h"
39
40 typedef struct {
41   GtkPrintJob *job;         /* the job we are sending to the printer */
42   gulong job_status_changed_tag;
43   GtkWindow *parent;        /* just in case we need to throw error dialogs */
44 } GtkPrintOperationUnix;
45
46 static void
47 unix_start_page (GtkPrintOperation *op,
48                  GtkPrintContext   *print_context,
49                  GtkPageSetup      *page_setup)
50 {
51
52 }
53
54 static void
55 unix_end_page (GtkPrintOperation *op,
56                GtkPrintContext   *print_context)
57 {
58   cairo_t *cr;
59
60   cr = gtk_print_context_get_cairo (print_context);
61   cairo_show_page (cr);
62 }
63
64 static void
65 op_unix_free (GtkPrintOperationUnix *op_unix)
66 {
67   if (op_unix->job)
68     {
69       g_signal_handler_disconnect (op_unix->job,
70                                    op_unix->job_status_changed_tag);
71       g_object_unref (op_unix->job);
72     }
73
74   g_free (op_unix);
75 }
76
77 static void
78 unix_finish_send  (GtkPrintJob *job,
79                    void        *user_data, 
80                    GError      *error)
81 {
82   GtkPrintOperationUnix *op_unix;
83
84   op_unix = (GtkPrintOperationUnix *) user_data;
85
86   if (error != NULL)
87     {
88       GtkWidget *edialog;
89       edialog = gtk_message_dialog_new (op_unix->parent, 
90                                         GTK_DIALOG_DESTROY_WITH_PARENT,
91                                         GTK_MESSAGE_ERROR,
92                                         GTK_BUTTONS_CLOSE,
93                                         "Error printing: %s",
94                                         error->message);
95
96       gtk_dialog_run (GTK_DIALOG (edialog));
97       gtk_widget_destroy (edialog);
98     }
99 }
100
101 static void
102 unix_end_run (GtkPrintOperation *op)
103 {
104   GtkPrintOperationUnix *op_unix = op->priv->platform_data;
105  
106   /* TODO: Check for error */
107   gtk_print_job_send (op_unix->job,
108                       unix_finish_send, 
109                       op_unix, NULL,
110                       NULL);
111 }
112
113 static void
114 job_status_changed_cb (GtkPrintJob       *job, 
115                        GtkPrintOperation *op)
116 {
117   _gtk_print_operation_set_status (op, gtk_print_job_get_status (job), NULL);
118 }
119
120
121 static GtkWidget *
122 get_print_dialog (GtkPrintOperation *op,
123                   GtkWindow         *parent)
124 {
125   GtkPrintOperationPrivate *priv = op->priv;
126   GtkWidget *pd;
127   GtkPageSetup *page_setup;
128
129   pd = gtk_print_unix_dialog_new (NULL, parent);
130
131   if (priv->print_settings)
132     gtk_print_unix_dialog_set_settings (GTK_PRINT_UNIX_DIALOG (pd),
133                                         priv->print_settings);
134   if (priv->default_page_setup)
135     page_setup = gtk_page_setup_copy (priv->default_page_setup);
136   else
137     page_setup = gtk_page_setup_new ();
138
139   gtk_print_unix_dialog_set_page_setup (GTK_PRINT_UNIX_DIALOG (pd), 
140                                         page_setup);
141   g_object_unref (page_setup);
142
143   return pd;
144 }
145   
146 typedef struct {
147   GtkPrintOperation           *op;
148   gboolean                     do_print;
149   GError                     **error;
150   GtkPrintOperationResult      result;
151   GtkPrintOperationPrintFunc   print_cb;
152   GDestroyNotify               destroy;
153 } PrintResponseData;
154
155 static void
156 print_response_data_free (gpointer data)
157 {
158   PrintResponseData *rdata = data;
159
160   g_object_unref (rdata->op);
161   g_free (rdata);
162 }
163
164 static void
165 handle_print_response (GtkWidget *dialog,
166                        gint       response,
167                        gpointer   data)
168 {
169   GtkPrintUnixDialog *pd = GTK_PRINT_UNIX_DIALOG (dialog);
170   PrintResponseData *rdata = data;
171   GtkPrintOperation *op = rdata->op;
172   GtkPrintOperationPrivate *priv = op->priv;
173
174   if (response == GTK_RESPONSE_OK)
175     {
176       GtkPrintOperationUnix *op_unix;
177       GtkPrinter *printer;
178       GtkPrintSettings *settings;
179       GtkPageSetup *page_setup;
180
181       rdata->result = GTK_PRINT_OPERATION_RESULT_APPLY;
182
183       printer = gtk_print_unix_dialog_get_selected_printer (GTK_PRINT_UNIX_DIALOG (pd));
184       if (printer == NULL)
185         goto out;
186       
187       rdata->do_print = TRUE;
188
189       settings = gtk_print_unix_dialog_get_settings (GTK_PRINT_UNIX_DIALOG (pd));
190       page_setup = gtk_print_unix_dialog_get_page_setup (GTK_PRINT_UNIX_DIALOG (pd));
191
192       gtk_print_operation_set_print_settings (op, settings);
193
194       op_unix = g_new0 (GtkPrintOperationUnix, 1);
195       op_unix->job = gtk_print_job_new (priv->job_name,
196                                         printer,
197                                         settings,
198                                         page_setup);
199       g_object_unref (settings);
200   
201       rdata->op->priv->surface = gtk_print_job_get_surface (op_unix->job, rdata->error);
202       if (op->priv->surface == NULL)
203         {
204           rdata->do_print = FALSE;
205           op_unix_free (op_unix);
206           rdata->result = GTK_PRINT_OPERATION_RESULT_ERROR;
207           goto out;
208         }
209
210       _gtk_print_operation_set_status (op, gtk_print_job_get_status (op_unix->job), NULL);
211       op_unix->job_status_changed_tag =
212         g_signal_connect (op_unix->job, "status_changed",
213                           G_CALLBACK (job_status_changed_cb), op);
214       
215       op_unix->parent = gtk_window_get_transient_for (GTK_WINDOW (pd));
216
217       priv->dpi_x = 72;
218       priv->dpi_y = 72;
219  
220       priv->platform_data = op_unix;
221       priv->free_platform_data = (GDestroyNotify) op_unix_free;
222
223       priv->print_pages = op_unix->job->print_pages;
224       priv->page_ranges = op_unix->job->page_ranges;
225       priv->num_page_ranges = op_unix->job->num_page_ranges;
226   
227       priv->manual_num_copies = op_unix->job->num_copies;
228       priv->manual_collation = op_unix->job->collate;
229       priv->manual_reverse = op_unix->job->reverse;
230       priv->manual_page_set = op_unix->job->page_set;
231       priv->manual_scale = op_unix->job->scale;
232       priv->manual_orientation = op_unix->job->rotate_to_orientation;
233     } 
234
235   priv->start_page = unix_start_page;
236   priv->end_page = unix_end_page;
237   priv->end_run = unix_end_run;
238
239  out:  
240   gtk_widget_destroy (GTK_WIDGET (pd));
241
242   if (rdata->print_cb)
243     {
244       if (rdata->do_print)
245         rdata->print_cb (op); 
246       else
247        _gtk_print_operation_set_status (op, GTK_PRINT_STATUS_FINISHED_ABORTED, NULL); 
248     }
249
250   if (rdata->destroy)
251     rdata->destroy (rdata);
252 }
253
254 void
255 _gtk_print_operation_platform_backend_run_dialog_async (GtkPrintOperation          *op,
256                                                         GtkWindow                  *parent,
257                                                         GtkPrintOperationPrintFunc  print_cb)
258 {
259   GtkWidget *pd;
260   PrintResponseData *rdata;
261
262   rdata = g_new (PrintResponseData, 1);
263   rdata->op = g_object_ref (op);
264   rdata->do_print = FALSE;
265   rdata->result = GTK_PRINT_OPERATION_RESULT_CANCEL;
266   rdata->error = NULL;
267   rdata->print_cb = print_cb;
268   rdata->destroy = print_response_data_free;
269   
270   pd = get_print_dialog (op, parent);
271   gtk_window_set_modal (GTK_WINDOW (pd), TRUE);
272
273   g_signal_connect (pd, "response", 
274                     G_CALLBACK (handle_print_response), rdata);
275
276   gtk_window_present (GTK_WINDOW (pd));
277 }
278
279 GtkPrintOperationResult
280 _gtk_print_operation_platform_backend_run_dialog (GtkPrintOperation *op,
281                                                   GtkWindow         *parent,
282                                                   gboolean          *do_print,
283                                                   GError           **error)
284  {
285   GtkWidget *pd;
286   PrintResponseData rdata;
287   gint response;  
288    
289   rdata.op = op;
290   rdata.do_print = FALSE;
291   rdata.result = GTK_PRINT_OPERATION_RESULT_CANCEL;
292   rdata.error = error;
293   rdata.print_cb = NULL;
294   rdata.destroy = NULL;
295
296   pd = get_print_dialog (op, parent);
297
298   response = gtk_dialog_run (GTK_DIALOG (pd));
299   handle_print_response (pd, response, &rdata);
300
301   *do_print = rdata.do_print;
302
303   return rdata.result;
304 }
305
306
307 typedef struct {
308   GtkPageSetup  *page_setup;
309   GFunc          done_cb;
310   gpointer       data;
311   GDestroyNotify destroy;
312 } PageSetupResponseData;
313
314 static void
315 page_setup_data_free (gpointer data)
316 {
317   PageSetupResponseData *rdata = data;
318
319   g_object_unref (rdata->page_setup);
320   g_free (rdata);
321 }
322
323 static void
324 handle_page_setup_response (GtkWidget *dialog,
325                             gint       response,
326                             gpointer   data)
327 {
328   GtkPageSetupUnixDialog *psd;
329   PageSetupResponseData *rdata = data;
330
331   psd = GTK_PAGE_SETUP_UNIX_DIALOG (dialog);
332   if (response == GTK_RESPONSE_OK)
333     rdata->page_setup = gtk_page_setup_unix_dialog_get_page_setup (psd);
334
335   gtk_widget_destroy (dialog);
336
337   if (rdata->done_cb)
338     rdata->done_cb (rdata->page_setup, rdata->data);
339
340   if (rdata->destroy)
341     rdata->destroy (rdata);
342 }
343
344 static GtkWidget *
345 get_page_setup_dialog (GtkWindow        *parent,
346                        GtkPageSetup     *page_setup,
347                        GtkPrintSettings *settings)
348 {
349   GtkWidget *dialog;
350
351   dialog = gtk_page_setup_unix_dialog_new (NULL, parent);
352   if (page_setup)
353     gtk_page_setup_unix_dialog_set_page_setup (GTK_PAGE_SETUP_UNIX_DIALOG (dialog),
354                                                page_setup);
355   gtk_page_setup_unix_dialog_set_print_settings (GTK_PAGE_SETUP_UNIX_DIALOG (dialog),
356                                                  settings);
357
358   return dialog;
359 }
360
361 /**
362  * gtk_print_run_page_setup_dialog:
363  * @parent: transient parent, or %NULL
364  * @page_setup: an existing #GtkPageSetup, or %NULL
365  * @settings: a #GtkPrintSettings
366  * 
367  * Runs a page setup dialog, letting the user modify the values from 
368  * @page_setup. If the user cancels the dialog, the returned #GtkPageSetup 
369  * is identical to the passed in @page_setup, otherwise it contains the 
370  * modifications done in the dialog.
371  *
372  * Note that this function may use a recursive mainloop to show the page
373  * setup dialog. See gtk_print_run_page_setup_dialog_async() if this is 
374  * a problem.
375  * 
376  * Return value: a new #GtkPageSetup
377  *
378  * Since: 2.10
379  */
380 GtkPageSetup *
381 gtk_print_run_page_setup_dialog (GtkWindow        *parent,
382                                  GtkPageSetup     *page_setup,
383                                  GtkPrintSettings *settings)
384 {
385   GtkWidget *dialog;
386   gint response;
387   PageSetupResponseData rdata;  
388   
389   rdata.page_setup = NULL;
390   rdata.done_cb = NULL;
391   rdata.data = NULL;
392   rdata.destroy = NULL;
393
394   dialog = get_page_setup_dialog (parent, page_setup, settings);
395   response = gtk_dialog_run (GTK_DIALOG (dialog));
396   handle_page_setup_response (dialog, response, &rdata);
397  
398   if (rdata.page_setup)
399     return rdata.page_setup;
400   else if (page_setup)
401     return gtk_page_setup_copy (page_setup);
402   else
403     return gtk_page_setup_new ();
404 }
405
406 /**
407  * gtk_print_run_page_setup_dialog_async:
408  * @parent: transient parent, or %NULL
409  * @page_setup: an existing #GtkPageSetup, or %NULL
410  * @settings: a #GtkPrintSettings
411  * @done_cb: a function to call when the user saves the modified page setup
412  * @data: user data to pass to @done_cb
413  * 
414  * Runs a page setup dialog, letting the user modify the values from @page_setup. 
415  *
416  * In contrast to gtk_print_run_page_setup_dialog(), this function  returns after 
417  * showing the page setup dialog on platforms that support this, and calls @done_cb 
418  * from a signal handler for the ::response signal of the dialog.
419  *
420  * Since: 2.10
421  */
422 void
423 gtk_print_run_page_setup_dialog_async (GtkWindow            *parent,
424                                        GtkPageSetup         *page_setup,
425                                        GtkPrintSettings     *settings,
426                                        GtkPageSetupDoneFunc  done_cb,
427                                        gpointer              data)
428 {
429   GtkWidget *dialog;
430   PageSetupResponseData *rdata;
431   
432   dialog = get_page_setup_dialog (parent, page_setup, settings);
433   gtk_window_set_modal (GTK_WINDOW (dialog), TRUE);
434   
435   rdata = g_new (PageSetupResponseData, 1);
436   rdata->page_setup = NULL;
437   rdata->done_cb = done_cb;
438   rdata->data = data;
439   rdata->destroy = page_setup_data_free;
440
441   g_signal_connect (dialog, "response",
442                     G_CALLBACK (handle_page_setup_response), rdata);
443  
444   gtk_window_present (GTK_WINDOW (dialog));
445  }
446
447
448 #define __GTK_PRINT_OPERATION_UNIX_C__
449 #include "gtkaliasdef.c"