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