1 /* GtkPageSetupUnixDialog
2 * Copyright (C) 2006 Alexander Larsson <alexl@redhat.com>
3 * Copyright © 2006, 2007, 2008 Christian Persch
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
22 #include "config.h"
23 #include <string.h>
24 #include <locale.h>
25
26 #include "gtkintl.h"
27 #include "gtkprivate.h"
28
29 #include "gtkliststore.h"
30 #include "gtkstock.h"
31 #include "gtktreeviewcolumn.h"
32 #include "gtktreeselection.h"
33 #include "gtktreemodel.h"
34 #include "gtkbutton.h"
35 #include "gtkscrolledwindow.h"
36 #include "gtkvbox.h"
37 #include "gtkhbox.h"
38 #include "gtkframe.h"
39 #include "gtkeventbox.h"
40 #include "gtkcombobox.h"
41 #include "gtktogglebutton.h"
42 #include "gtkradiobutton.h"
43 #include "gtklabel.h"
44 #include "gtktable.h"
45 #include "gtkcelllayout.h"
46 #include "gtkcellrenderertext.h"
47 #include "gtkalignment.h"
48 #include "gtkspinbutton.h"
49 #include "gtkbbox.h"
50 #include "gtkhbbox.h"
51
52 #include "gtkpagesetupunixdialog.h"
53 #include "gtkcustompaperunixdialog.h"
54 #include "gtkprintbackend.h"
55 #include "gtkpapersize.h"
56 #include "gtkprintutils.h"
57 #include "gtkalias.h"
58
59
60 struct GtkPageSetupUnixDialogPrivate
61 {
62 GtkListStore *printer_list;
63 GtkListStore *page_setup_list;
64 GtkListStore *custom_paper_list;
65
66 GList *print_backends;
67
68 GtkWidget *printer_combo;
69 GtkWidget *paper_size_combo;
70 GtkWidget *paper_size_label;
71
72 GtkWidget *portrait_radio;
73 GtkWidget *reverse_portrait_radio;
74 GtkWidget *landscape_radio;
75 GtkWidget *reverse_landscape_radio;
76
77 guint request_details_tag;
78 GtkPrinter *request_details_printer;
79
80 GtkPrintSettings *print_settings;
81
82 /* Save last setup so we can re-set it after selecting manage custom sizes */
83 GtkPageSetup *last_setup;
84
85 gchar *waiting_for_printer;
86 };
87
88 enum {
89 PRINTER_LIST_COL_NAME,
90 PRINTER_LIST_COL_PRINTER,
91 PRINTER_LIST_N_COLS
92 };
93
94 enum {
95 PAGE_SETUP_LIST_COL_PAGE_SETUP,
96 PAGE_SETUP_LIST_COL_IS_SEPARATOR,
97 PAGE_SETUP_LIST_N_COLS
98 };
99
100 G_DEFINE_TYPE (GtkPageSetupUnixDialog, gtk_page_setup_unix_dialog, GTK_TYPE_DIALOG)
101
102 #define GTK_PAGE_SETUP_UNIX_DIALOG_GET_PRIVATE(o) \
103 (G_TYPE_INSTANCE_GET_PRIVATE ((o), GTK_TYPE_PAGE_SETUP_UNIX_DIALOG, GtkPageSetupUnixDialogPrivate))
104
105 static void gtk_page_setup_unix_dialog_finalize (GObject *object);
106 static void populate_dialog (GtkPageSetupUnixDialog *dialog);
107 static void fill_paper_sizes_from_printer (GtkPageSetupUnixDialog *dialog,
108 GtkPrinter *printer);
109 static void printer_added_cb (GtkPrintBackend *backend,
110 GtkPrinter *printer,
111 GtkPageSetupUnixDialog *dialog);
112 static void printer_removed_cb (GtkPrintBackend *backend,
113 GtkPrinter *printer,
114 GtkPageSetupUnixDialog *dialog);
115 static void printer_status_cb (GtkPrintBackend *backend,
116 GtkPrinter *printer,
117 GtkPageSetupUnixDialog *dialog);
118
119
120
121 static const gchar const common_paper_sizes[][16] = {
122 "na_letter",
123 "na_legal",
124 "iso_a4",
125 "iso_a5",
126 "roc_16k",
127 "iso_b5",
128 "jis_b5",
129 "na_number-10",
130 "iso_dl",
131 "jpn_chou3",
132 "na_ledger",
133 "iso_a3",
134 };
135
136
137 static void
gtk_page_setup_unix_dialog_class_init(GtkPageSetupUnixDialogClass * class)138 gtk_page_setup_unix_dialog_class_init (GtkPageSetupUnixDialogClass *class)
139 {
140 GObjectClass *object_class;
141 GtkWidgetClass *widget_class;
142
143 object_class = (GObjectClass *) class;
144 widget_class = (GtkWidgetClass *) class;
145
146 object_class->finalize = gtk_page_setup_unix_dialog_finalize;
147
148 g_type_class_add_private (class, sizeof (GtkPageSetupUnixDialogPrivate));
149 }
150
151 static void
gtk_page_setup_unix_dialog_init(GtkPageSetupUnixDialog * dialog)152 gtk_page_setup_unix_dialog_init (GtkPageSetupUnixDialog *dialog)
153 {
154 GtkPageSetupUnixDialogPrivate *priv;
155 GtkTreeIter iter;
156 gchar *tmp;
157
158 priv = dialog->priv = GTK_PAGE_SETUP_UNIX_DIALOG_GET_PRIVATE (dialog);
159
160 priv->print_backends = NULL;
161
162 priv->printer_list = gtk_list_store_new (PRINTER_LIST_N_COLS,
163 G_TYPE_STRING,
164 G_TYPE_OBJECT);
165
166 gtk_list_store_append (priv->printer_list, &iter);
167 tmp = g_strdup_printf ("<b>%s</b>\n%s", _("Any Printer"), _("For portable documents"));
168 gtk_list_store_set (priv->printer_list, &iter,
169 PRINTER_LIST_COL_NAME, tmp,
170 PRINTER_LIST_COL_PRINTER, NULL,
171 -1);
172 g_free (tmp);
173
174 priv->page_setup_list = gtk_list_store_new (PAGE_SETUP_LIST_N_COLS,
175 G_TYPE_OBJECT,
176 G_TYPE_BOOLEAN);
177
178 priv->custom_paper_list = gtk_list_store_new (1, G_TYPE_OBJECT);
179 _gtk_print_load_custom_papers (priv->custom_paper_list);
180
181 populate_dialog (dialog);
182
183 gtk_dialog_add_buttons (GTK_DIALOG (dialog),
184 GTK_STOCK_CANCEL, GTK_RESPONSE_CANCEL,
185 GTK_STOCK_APPLY, GTK_RESPONSE_OK,
186 NULL);
187 gtk_dialog_set_alternative_button_order (GTK_DIALOG (dialog),
188 GTK_RESPONSE_OK,
189 GTK_RESPONSE_CANCEL,
190 -1);
191
192 gtk_dialog_set_default_response (GTK_DIALOG (dialog), GTK_RESPONSE_OK);
193 }
194
195 static void
gtk_page_setup_unix_dialog_finalize(GObject * object)196 gtk_page_setup_unix_dialog_finalize (GObject *object)
197 {
198 GtkPageSetupUnixDialog *dialog = GTK_PAGE_SETUP_UNIX_DIALOG (object);
199 GtkPageSetupUnixDialogPrivate *priv = dialog->priv;
200 GtkPrintBackend *backend;
201 GList *node;
202
203 if (priv->request_details_tag)
204 {
205 g_signal_handler_disconnect (priv->request_details_printer,
206 priv->request_details_tag);
207 g_object_unref (priv->request_details_printer);
208 priv->request_details_printer = NULL;
209 priv->request_details_tag = 0;
210 }
211
212 if (priv->printer_list)
213 {
214 g_object_unref (priv->printer_list);
215 priv->printer_list = NULL;
216 }
217
218 if (priv->page_setup_list)
219 {
220 g_object_unref (priv->page_setup_list);
221 priv->page_setup_list = NULL;
222 }
223
224 if (priv->custom_paper_list)
225 {
226 g_object_unref (priv->custom_paper_list);
227 priv->custom_paper_list = NULL;
228 }
229
230 if (priv->print_settings)
231 {
232 g_object_unref (priv->print_settings);
233 priv->print_settings = NULL;
234 }
235
236 g_free (priv->waiting_for_printer);
237 priv->waiting_for_printer = NULL;
238
239 for (node = priv->print_backends; node != NULL; node = node->next)
240 {
241 backend = GTK_PRINT_BACKEND (node->data);
242
243 g_signal_handlers_disconnect_by_func (backend, printer_added_cb, dialog);
244 g_signal_handlers_disconnect_by_func (backend, printer_removed_cb, dialog);
245 g_signal_handlers_disconnect_by_func (backend, printer_status_cb, dialog);
246
247 gtk_print_backend_destroy (backend);
248 g_object_unref (backend);
249 }
250
251 g_list_free (priv->print_backends);
252 priv->print_backends = NULL;
253
254 G_OBJECT_CLASS (gtk_page_setup_unix_dialog_parent_class)->finalize (object);
255 }
256
257 static void
printer_added_cb(GtkPrintBackend * backend,GtkPrinter * printer,GtkPageSetupUnixDialog * dialog)258 printer_added_cb (GtkPrintBackend *backend,
259 GtkPrinter *printer,
260 GtkPageSetupUnixDialog *dialog)
261 {
262 GtkPageSetupUnixDialogPrivate *priv = dialog->priv;
263 GtkTreeIter iter;
264 gchar *str;
265 const gchar *location;
266
267 if (gtk_printer_is_virtual (printer))
268 return;
269
270 location = gtk_printer_get_location (printer);
271 if (location == NULL)
272 location = "";
273 str = g_strdup_printf ("<b>%s</b>\n%s",
274 gtk_printer_get_name (printer),
275 location);
276
277 gtk_list_store_append (priv->printer_list, &iter);
278 gtk_list_store_set (priv->printer_list, &iter,
279 PRINTER_LIST_COL_NAME, str,
280 PRINTER_LIST_COL_PRINTER, printer,
281 -1);
282
283 g_object_set_data_full (G_OBJECT (printer),
284 "gtk-print-tree-iter",
285 gtk_tree_iter_copy (&iter),
286 (GDestroyNotify) gtk_tree_iter_free);
287 g_free (str);
288
289 if (priv->waiting_for_printer != NULL &&
290 strcmp (priv->waiting_for_printer,
291 gtk_printer_get_name (printer)) == 0)
292 {
293 gtk_combo_box_set_active_iter (GTK_COMBO_BOX (priv->printer_combo),
294 &iter);
295 priv->waiting_for_printer = NULL;
296 }
297 }
298
299 static void
printer_removed_cb(GtkPrintBackend * backend,GtkPrinter * printer,GtkPageSetupUnixDialog * dialog)300 printer_removed_cb (GtkPrintBackend *backend,
301 GtkPrinter *printer,
302 GtkPageSetupUnixDialog *dialog)
303 {
304 GtkPageSetupUnixDialogPrivate *priv = dialog->priv;
305 GtkTreeIter *iter;
306
307 iter = g_object_get_data (G_OBJECT (printer), "gtk-print-tree-iter");
308 gtk_list_store_remove (GTK_LIST_STORE (priv->printer_list), iter);
309 }
310
311
312 static void
printer_status_cb(GtkPrintBackend * backend,GtkPrinter * printer,GtkPageSetupUnixDialog * dialog)313 printer_status_cb (GtkPrintBackend *backend,
314 GtkPrinter *printer,
315 GtkPageSetupUnixDialog *dialog)
316 {
317 GtkPageSetupUnixDialogPrivate *priv = dialog->priv;
318 GtkTreeIter *iter;
319 gchar *str;
320 const gchar *location;
321
322 iter = g_object_get_data (G_OBJECT (printer), "gtk-print-tree-iter");
323
324 location = gtk_printer_get_location (printer);
325 if (location == NULL)
326 location = "";
327 str = g_strdup_printf ("<b>%s</b>\n%s",
328 gtk_printer_get_name (printer),
329 location);
330 gtk_list_store_set (priv->printer_list, iter,
331 PRINTER_LIST_COL_NAME, str,
332 -1);
333 g_free (str);
334 }
335
336 static void
printer_list_initialize(GtkPageSetupUnixDialog * dialog,GtkPrintBackend * print_backend)337 printer_list_initialize (GtkPageSetupUnixDialog *dialog,
338 GtkPrintBackend *print_backend)
339 {
340 GList *list, *node;
341
342 g_return_if_fail (print_backend != NULL);
343
344 g_signal_connect_object (print_backend,
345 "printer-added",
346 (GCallback) printer_added_cb,
347 G_OBJECT (dialog), 0);
348
349 g_signal_connect_object (print_backend,
350 "printer-removed",
351 (GCallback) printer_removed_cb,
352 G_OBJECT (dialog), 0);
353
354 g_signal_connect_object (print_backend,
355 "printer-status-changed",
356 (GCallback) printer_status_cb,
357 G_OBJECT (dialog), 0);
358
359 list = gtk_print_backend_get_printer_list (print_backend);
360
361 node = list;
362 while (node != NULL)
363 {
364 printer_added_cb (print_backend, node->data, dialog);
365 node = node->next;
366 }
367
368 g_list_free (list);
369
370 }
371
372 static void
load_print_backends(GtkPageSetupUnixDialog * dialog)373 load_print_backends (GtkPageSetupUnixDialog *dialog)
374 {
375 GtkPageSetupUnixDialogPrivate *priv = dialog->priv;
376 GList *node;
377
378 if (g_module_supported ())
379 priv->print_backends = gtk_print_backend_load_modules ();
380
381 for (node = priv->print_backends; node != NULL; node = node->next)
382 printer_list_initialize (dialog, GTK_PRINT_BACKEND (node->data));
383 }
384
385 static gboolean
paper_size_row_is_separator(GtkTreeModel * model,GtkTreeIter * iter,gpointer data)386 paper_size_row_is_separator (GtkTreeModel *model,
387 GtkTreeIter *iter,
388 gpointer data)
389 {
390 gboolean separator;
391
392 gtk_tree_model_get (model, iter, PAGE_SETUP_LIST_COL_IS_SEPARATOR, &separator, -1);
393 return separator;
394 }
395
396 static GtkPageSetup *
get_current_page_setup(GtkPageSetupUnixDialog * dialog)397 get_current_page_setup (GtkPageSetupUnixDialog *dialog)
398 {
399 GtkPageSetupUnixDialogPrivate *priv = dialog->priv;
400 GtkPageSetup *current_page_setup;
401 GtkComboBox *combo_box;
402 GtkTreeIter iter;
403
404 current_page_setup = NULL;
405
406 combo_box = GTK_COMBO_BOX (priv->paper_size_combo);
407 if (gtk_combo_box_get_active_iter (combo_box, &iter))
408 gtk_tree_model_get (GTK_TREE_MODEL (priv->page_setup_list), &iter,
409 PAGE_SETUP_LIST_COL_PAGE_SETUP, ¤t_page_setup, -1);
410
411 if (current_page_setup)
412 return current_page_setup;
413
414 /* No selected page size, return the default one.
415 * This is used to set the first page setup when the dialog is created
416 * as there is no selection on the first printer_changed.
417 */
418 return gtk_page_setup_new ();
419 }
420
421 static gboolean
page_setup_is_equal(GtkPageSetup * a,GtkPageSetup * b)422 page_setup_is_equal (GtkPageSetup *a,
423 GtkPageSetup *b)
424 {
425 return
426 gtk_paper_size_is_equal (gtk_page_setup_get_paper_size (a),
427 gtk_page_setup_get_paper_size (b)) &&
428 gtk_page_setup_get_top_margin (a, GTK_UNIT_MM) == gtk_page_setup_get_top_margin (b, GTK_UNIT_MM) &&
429 gtk_page_setup_get_bottom_margin (a, GTK_UNIT_MM) == gtk_page_setup_get_bottom_margin (b, GTK_UNIT_MM) &&
430 gtk_page_setup_get_left_margin (a, GTK_UNIT_MM) == gtk_page_setup_get_left_margin (b, GTK_UNIT_MM) &&
431 gtk_page_setup_get_right_margin (a, GTK_UNIT_MM) == gtk_page_setup_get_right_margin (b, GTK_UNIT_MM);
432 }
433
434 static gboolean
page_setup_is_same_size(GtkPageSetup * a,GtkPageSetup * b)435 page_setup_is_same_size (GtkPageSetup *a,
436 GtkPageSetup *b)
437 {
438 return gtk_paper_size_is_equal (gtk_page_setup_get_paper_size (a),
439 gtk_page_setup_get_paper_size (b));
440 }
441
442 static gboolean
set_paper_size(GtkPageSetupUnixDialog * dialog,GtkPageSetup * page_setup,gboolean size_only,gboolean add_item)443 set_paper_size (GtkPageSetupUnixDialog *dialog,
444 GtkPageSetup *page_setup,
445 gboolean size_only,
446 gboolean add_item)
447 {
448 GtkPageSetupUnixDialogPrivate *priv = dialog->priv;
449 GtkTreeModel *model;
450 GtkTreeIter iter;
451 GtkPageSetup *list_page_setup;
452
453 model = GTK_TREE_MODEL (priv->page_setup_list);
454
455 if (gtk_tree_model_get_iter_first (model, &iter))
456 {
457 do
458 {
459 gtk_tree_model_get (GTK_TREE_MODEL (priv->page_setup_list), &iter,
460 PAGE_SETUP_LIST_COL_PAGE_SETUP, &list_page_setup, -1);
461 if (list_page_setup == NULL)
462 continue;
463
464 if ((size_only && page_setup_is_same_size (page_setup, list_page_setup)) ||
465 (!size_only && page_setup_is_equal (page_setup, list_page_setup)))
466 {
467 gtk_combo_box_set_active_iter (GTK_COMBO_BOX (priv->paper_size_combo),
468 &iter);
469 g_object_unref (list_page_setup);
470 return TRUE;
471 }
472
473 g_object_unref (list_page_setup);
474
475 } while (gtk_tree_model_iter_next (model, &iter));
476 }
477
478 if (add_item)
479 {
480 gtk_list_store_append (priv->page_setup_list, &iter);
481 gtk_list_store_set (priv->page_setup_list, &iter,
482 PAGE_SETUP_LIST_COL_IS_SEPARATOR, TRUE,
483 -1);
484 gtk_list_store_append (priv->page_setup_list, &iter);
485 gtk_list_store_set (priv->page_setup_list, &iter,
486 PAGE_SETUP_LIST_COL_PAGE_SETUP, page_setup,
487 -1);
488 gtk_combo_box_set_active_iter (GTK_COMBO_BOX (priv->paper_size_combo),
489 &iter);
490 return TRUE;
491 }
492
493 return FALSE;
494 }
495
496 static void
fill_custom_paper_sizes(GtkPageSetupUnixDialog * dialog)497 fill_custom_paper_sizes (GtkPageSetupUnixDialog *dialog)
498 {
499 GtkPageSetupUnixDialogPrivate *priv = dialog->priv;
500 GtkTreeIter iter, paper_iter;
501 GtkTreeModel *model;
502
503 model = GTK_TREE_MODEL (priv->custom_paper_list);
504 if (gtk_tree_model_get_iter_first (model, &iter))
505 {
506 gtk_list_store_append (priv->page_setup_list, &paper_iter);
507 gtk_list_store_set (priv->page_setup_list, &paper_iter,
508 PAGE_SETUP_LIST_COL_IS_SEPARATOR, TRUE,
509 -1);
510 do
511 {
512 GtkPageSetup *page_setup;
513 gtk_tree_model_get (model, &iter, 0, &page_setup, -1);
514
515 gtk_list_store_append (priv->page_setup_list, &paper_iter);
516 gtk_list_store_set (priv->page_setup_list, &paper_iter,
517 PAGE_SETUP_LIST_COL_PAGE_SETUP, page_setup,
518 -1);
519
520 g_object_unref (page_setup);
521 } while (gtk_tree_model_iter_next (model, &iter));
522 }
523
524 gtk_list_store_append (priv->page_setup_list, &paper_iter);
525 gtk_list_store_set (priv->page_setup_list, &paper_iter,
526 PAGE_SETUP_LIST_COL_IS_SEPARATOR, TRUE,
527 -1);
528 gtk_list_store_append (priv->page_setup_list, &paper_iter);
529 gtk_list_store_set (priv->page_setup_list, &paper_iter,
530 PAGE_SETUP_LIST_COL_PAGE_SETUP, NULL,
531 -1);
532 }
533
534 static void
fill_paper_sizes_from_printer(GtkPageSetupUnixDialog * dialog,GtkPrinter * printer)535 fill_paper_sizes_from_printer (GtkPageSetupUnixDialog *dialog,
536 GtkPrinter *printer)
537 {
538 GtkPageSetupUnixDialogPrivate *priv = dialog->priv;
539 GList *list, *l;
540 GtkPageSetup *current_page_setup, *page_setup;
541 GtkPaperSize *paper_size;
542 GtkTreeIter iter;
543 gint i;
544
545 gtk_list_store_clear (priv->page_setup_list);
546
547 if (printer == NULL)
548 {
549 for (i = 0; i < G_N_ELEMENTS (common_paper_sizes); i++)
550 {
551 page_setup = gtk_page_setup_new ();
552 paper_size = gtk_paper_size_new (common_paper_sizes[i]);
553 gtk_page_setup_set_paper_size_and_default_margins (page_setup, paper_size);
554 gtk_paper_size_free (paper_size);
555
556 gtk_list_store_append (priv->page_setup_list, &iter);
557 gtk_list_store_set (priv->page_setup_list, &iter,
558 PAGE_SETUP_LIST_COL_PAGE_SETUP, page_setup,
559 -1);
560 g_object_unref (page_setup);
561 }
562 }
563 else
564 {
565 list = gtk_printer_list_papers (printer);
566 /* TODO: We should really sort this list so interesting size
567 are at the top */
568 for (l = list; l != NULL; l = l->next)
569 {
570 page_setup = l->data;
571 gtk_list_store_append (priv->page_setup_list, &iter);
572 gtk_list_store_set (priv->page_setup_list, &iter,
573 PAGE_SETUP_LIST_COL_PAGE_SETUP, page_setup,
574 -1);
575 g_object_unref (page_setup);
576 }
577 g_list_free (list);
578 }
579
580 fill_custom_paper_sizes (dialog);
581
582 current_page_setup = NULL;
583
584 /* When selecting a different printer, select its default paper size */
585 if (printer != NULL)
586 current_page_setup = gtk_printer_get_default_page_size (printer);
587
588 if (current_page_setup == NULL)
589 current_page_setup = get_current_page_setup (dialog);
590
591 if (!set_paper_size (dialog, current_page_setup, FALSE, FALSE))
592 set_paper_size (dialog, current_page_setup, TRUE, TRUE);
593
594 if (current_page_setup)
595 g_object_unref (current_page_setup);
596 }
597
598 static void
printer_changed_finished_callback(GtkPrinter * printer,gboolean success,GtkPageSetupUnixDialog * dialog)599 printer_changed_finished_callback (GtkPrinter *printer,
600 gboolean success,
601 GtkPageSetupUnixDialog *dialog)
602 {
603 GtkPageSetupUnixDialogPrivate *priv = dialog->priv;
604
605 g_signal_handler_disconnect (priv->request_details_printer,
606 priv->request_details_tag);
607 g_object_unref (priv->request_details_printer);
608 priv->request_details_tag = 0;
609 priv->request_details_printer = NULL;
610
611 if (success)
612 fill_paper_sizes_from_printer (dialog, printer);
613
614 }
615
616 static void
printer_changed_callback(GtkComboBox * combo_box,GtkPageSetupUnixDialog * dialog)617 printer_changed_callback (GtkComboBox *combo_box,
618 GtkPageSetupUnixDialog *dialog)
619 {
620 GtkPageSetupUnixDialogPrivate *priv = dialog->priv;
621 GtkPrinter *printer;
622 GtkTreeIter iter;
623
624 /* If we're waiting for a specific printer but the user changed
625 * to another printer, cancel that wait.
626 */
627 if (priv->waiting_for_printer)
628 {
629 g_free (priv->waiting_for_printer);
630 priv->waiting_for_printer = NULL;
631 }
632
633 if (priv->request_details_tag)
634 {
635 g_signal_handler_disconnect (priv->request_details_printer,
636 priv->request_details_tag);
637 g_object_unref (priv->request_details_printer);
638 priv->request_details_printer = NULL;
639 priv->request_details_tag = 0;
640 }
641
642 if (gtk_combo_box_get_active_iter (combo_box, &iter))
643 {
644 gtk_tree_model_get (gtk_combo_box_get_model (combo_box), &iter,
645 PRINTER_LIST_COL_PRINTER, &printer, -1);
646
647 if (printer == NULL || gtk_printer_has_details (printer))
648 fill_paper_sizes_from_printer (dialog, printer);
649 else
650 {
651 priv->request_details_printer = g_object_ref (printer);
652 priv->request_details_tag =
653 g_signal_connect (printer, "details-acquired",
654 G_CALLBACK (printer_changed_finished_callback), dialog);
655 gtk_printer_request_details (printer);
656
657 }
658
659 if (printer)
660 g_object_unref (printer);
661
662 if (priv->print_settings)
663 {
664 const char *name = NULL;
665
666 if (printer)
667 name = gtk_printer_get_name (printer);
668
669 gtk_print_settings_set (priv->print_settings,
670 "format-for-printer", name);
671 }
672 }
673 }
674
675 /* We do this munging because we don't want to show zero digits
676 after the decimal point, and not to many such digits if they
677 are nonzero. I wish printf let you specify max precision for %f... */
678 static gchar *
double_to_string(gdouble d,GtkUnit unit)679 double_to_string (gdouble d,
680 GtkUnit unit)
681 {
682 gchar *val, *p;
683 struct lconv *locale_data;
684 const gchar *decimal_point;
685 gint decimal_point_len;
686
687 locale_data = localeconv ();
688 decimal_point = locale_data->decimal_point;
689 decimal_point_len = strlen (decimal_point);
690
691 /* Max two decimal digits for inch, max one for mm */
692 if (unit == GTK_UNIT_INCH)
693 val = g_strdup_printf ("%.2f", d);
694 else
695 val = g_strdup_printf ("%.1f", d);
696
697 if (strstr (val, decimal_point))
698 {
699 p = val + strlen (val) - 1;
700 while (*p == '0')
701 p--;
702 if (p - val + 1 >= decimal_point_len &&
703 strncmp (p - (decimal_point_len - 1), decimal_point, decimal_point_len) == 0)
704 p -= decimal_point_len;
705 p[1] = '\0';
706 }
707
708 return val;
709 }
710
711
712 static void
custom_paper_dialog_response_cb(GtkDialog * custom_paper_dialog,gint response_id,gpointer user_data)713 custom_paper_dialog_response_cb (GtkDialog *custom_paper_dialog,
714 gint response_id,
715 gpointer user_data)
716 {
717 GtkPageSetupUnixDialog *page_setup_dialog = GTK_PAGE_SETUP_UNIX_DIALOG (user_data);
718 GtkPageSetupUnixDialogPrivate *priv = page_setup_dialog->priv;
719
720 _gtk_print_load_custom_papers (priv->custom_paper_list);
721
722 /* Update printer page list */
723 printer_changed_callback (GTK_COMBO_BOX (priv->printer_combo), page_setup_dialog);
724
725 gtk_widget_destroy (GTK_WIDGET (custom_paper_dialog));
726 }
727
728 static void
paper_size_changed(GtkComboBox * combo_box,GtkPageSetupUnixDialog * dialog)729 paper_size_changed (GtkComboBox *combo_box,
730 GtkPageSetupUnixDialog *dialog)
731 {
732 GtkPageSetupUnixDialogPrivate *priv = dialog->priv;
733 GtkTreeIter iter;
734 GtkPageSetup *page_setup, *last_page_setup;
735 GtkUnit unit;
736 gchar *str, *w, *h;
737 gchar *top, *bottom, *left, *right;
738 GtkLabel *label;
739 const gchar *unit_str;
740
741 label = GTK_LABEL (priv->paper_size_label);
742
743 if (gtk_combo_box_get_active_iter (combo_box, &iter))
744 {
745 gtk_tree_model_get (gtk_combo_box_get_model (combo_box),
746 &iter, PAGE_SETUP_LIST_COL_PAGE_SETUP, &page_setup, -1);
747
748 if (page_setup == NULL)
749 {
750 GtkWidget *custom_paper_dialog;
751
752 /* Change from "manage" menu item to last value */
753 if (priv->last_setup)
754 last_page_setup = g_object_ref (priv->last_setup);
755 else
756 last_page_setup = gtk_page_setup_new (); /* "good" default */
757 set_paper_size (dialog, last_page_setup, FALSE, TRUE);
758 g_object_unref (last_page_setup);
759
760 /* And show the custom paper dialog */
761 custom_paper_dialog = _gtk_custom_paper_unix_dialog_new (GTK_WINDOW (dialog), NULL);
762 g_signal_connect (custom_paper_dialog, "response", G_CALLBACK (custom_paper_dialog_response_cb), dialog);
763 gtk_window_present (GTK_WINDOW (custom_paper_dialog));
764
765 return;
766 }
767
768 if (priv->last_setup)
769 g_object_unref (priv->last_setup);
770
771 priv->last_setup = g_object_ref (page_setup);
772
773 unit = _gtk_print_get_default_user_units ();
774
775 if (unit == GTK_UNIT_MM)
776 unit_str = _("mm");
777 else
778 unit_str = _("inch");
779
780
781 w = double_to_string (gtk_page_setup_get_paper_width (page_setup, unit),
782 unit);
783 h = double_to_string (gtk_page_setup_get_paper_height (page_setup, unit),
784 unit);
785 str = g_strdup_printf ("%s x %s %s", w, h, unit_str);
786 g_free (w);
787 g_free (h);
788
789 gtk_label_set_text (label, str);
790 g_free (str);
791
792 top = double_to_string (gtk_page_setup_get_top_margin (page_setup, unit), unit);
793 bottom = double_to_string (gtk_page_setup_get_bottom_margin (page_setup, unit), unit);
794 left = double_to_string (gtk_page_setup_get_left_margin (page_setup, unit), unit);
795 right = double_to_string (gtk_page_setup_get_right_margin (page_setup, unit), unit);
796
797 str = g_strdup_printf (_("Margins:\n"
798 " Left: %s %s\n"
799 " Right: %s %s\n"
800 " Top: %s %s\n"
801 " Bottom: %s %s"
802 ),
803 left, unit_str,
804 right, unit_str,
805 top, unit_str,
806 bottom, unit_str);
807 g_free (top);
808 g_free (bottom);
809 g_free (left);
810 g_free (right);
811
812 gtk_widget_set_tooltip_text (priv->paper_size_label, str);
813 g_free (str);
814
815 g_object_unref (page_setup);
816 }
817 else
818 {
819 gtk_label_set_text (label, "");
820 gtk_widget_set_tooltip_text (priv->paper_size_label, NULL);
821 if (priv->last_setup)
822 g_object_unref (priv->last_setup);
823 priv->last_setup = NULL;
824 }
825 }
826
827 static void
page_name_func(GtkCellLayout * cell_layout,GtkCellRenderer * cell,GtkTreeModel * tree_model,GtkTreeIter * iter,gpointer data)828 page_name_func (GtkCellLayout *cell_layout,
829 GtkCellRenderer *cell,
830 GtkTreeModel *tree_model,
831 GtkTreeIter *iter,
832 gpointer data)
833 {
834 GtkPageSetup *page_setup;
835 GtkPaperSize *paper_size;
836
837 gtk_tree_model_get (tree_model, iter,
838 PAGE_SETUP_LIST_COL_PAGE_SETUP, &page_setup, -1);
839 if (page_setup)
840 {
841 paper_size = gtk_page_setup_get_paper_size (page_setup);
842 g_object_set (cell, "text", gtk_paper_size_get_display_name (paper_size), NULL);
843 g_object_unref (page_setup);
844 }
845 else
846 g_object_set (cell, "text", _("Manage Custom Sizes..."), NULL);
847
848 }
849
850 static GtkWidget *
create_radio_button(GSList * group,const gchar * stock_id)851 create_radio_button (GSList *group,
852 const gchar *stock_id)
853 {
854 GtkWidget *radio_button, *image, *label, *hbox;
855 GtkStockItem item;
856
857 radio_button = gtk_radio_button_new (group);
858 image = gtk_image_new_from_stock (stock_id, GTK_ICON_SIZE_LARGE_TOOLBAR);
859 gtk_stock_lookup (stock_id, &item);
860 label = gtk_label_new (item.label);
861 hbox = gtk_hbox_new (0, 6);
862 gtk_container_add (GTK_CONTAINER (radio_button), hbox);
863 gtk_container_add (GTK_CONTAINER (hbox), image);
864 gtk_container_add (GTK_CONTAINER (hbox), label);
865
866 gtk_widget_show_all (radio_button);
867
868 return radio_button;
869 }
870
871 static void
populate_dialog(GtkPageSetupUnixDialog * ps_dialog)872 populate_dialog (GtkPageSetupUnixDialog *ps_dialog)
873 {
874 GtkPageSetupUnixDialogPrivate *priv = ps_dialog->priv;
875 GtkDialog *dialog = GTK_DIALOG (ps_dialog);
876 GtkWidget *table, *label, *combo, *radio_button;
877 GtkCellRenderer *cell;
878
879 gtk_window_set_resizable (GTK_WINDOW (dialog), FALSE);
880
881 gtk_dialog_set_has_separator (dialog, FALSE);
882 gtk_container_set_border_width (GTK_CONTAINER (dialog), 5);
883 gtk_box_set_spacing (GTK_BOX (dialog->vbox), 2); /* 2 * 5 + 2 = 12 */
884 gtk_container_set_border_width (GTK_CONTAINER (dialog->action_area), 5);
885 gtk_box_set_spacing (GTK_BOX (dialog->action_area), 6);
886
887 table = gtk_table_new (5, 4, FALSE);
888 gtk_table_set_row_spacings (GTK_TABLE (table), 6);
889 gtk_table_set_col_spacings (GTK_TABLE (table), 12);
890 gtk_container_set_border_width (GTK_CONTAINER (table), 5);
891 gtk_box_pack_start (GTK_BOX (dialog->vbox), table, TRUE, TRUE, 0);
892 gtk_widget_show (table);
893
894 label = gtk_label_new_with_mnemonic (_("_Format for:"));
895 gtk_misc_set_alignment (GTK_MISC (label), 0.0, 0.5);
896 gtk_table_attach (GTK_TABLE (table), label,
897 0, 1, 0, 1,
898 GTK_FILL, 0, 0, 0);
899 gtk_widget_show (label);
900
901 combo = gtk_combo_box_new_with_model (GTK_TREE_MODEL (priv->printer_list));
902 priv->printer_combo = combo;
903
904 cell = gtk_cell_renderer_text_new ();
905 gtk_cell_layout_pack_start (GTK_CELL_LAYOUT (combo), cell, TRUE);
906 gtk_cell_layout_set_attributes (GTK_CELL_LAYOUT (combo), cell,
907 "markup", PRINTER_LIST_COL_NAME,
908 NULL);
909
910 gtk_table_attach (GTK_TABLE (table), combo,
911 1, 4, 0, 1,
912 GTK_FILL | GTK_EXPAND, 0, 0, 0);
913 gtk_widget_show (combo);
914 gtk_label_set_mnemonic_widget (GTK_LABEL (label), combo);
915
916 label = gtk_label_new_with_mnemonic (_("_Paper size:"));
917 gtk_misc_set_alignment (GTK_MISC (label), 0.0, 0.5);
918 gtk_table_attach (GTK_TABLE (table), label,
919 0, 1, 1, 2,
920 GTK_FILL, 0, 0, 0);
921 gtk_widget_show (label);
922
923 combo = gtk_combo_box_new_with_model (GTK_TREE_MODEL (priv->page_setup_list));
924 priv->paper_size_combo = combo;
925 gtk_combo_box_set_row_separator_func (GTK_COMBO_BOX (combo),
926 paper_size_row_is_separator, NULL, NULL);
927
928 cell = gtk_cell_renderer_text_new ();
929 gtk_cell_layout_pack_start (GTK_CELL_LAYOUT (combo), cell, TRUE);
930 gtk_cell_layout_set_cell_data_func (GTK_CELL_LAYOUT (combo), cell,
931 page_name_func, NULL, NULL);
932
933 gtk_table_attach (GTK_TABLE (table), combo,
934 1, 4, 1, 2,
935 GTK_FILL | GTK_EXPAND, 0, 0, 0);
936 gtk_widget_show (combo);
937 gtk_label_set_mnemonic_widget (GTK_LABEL (label), combo);
938
939 label = gtk_label_new (NULL);
940 priv->paper_size_label = label;
941 gtk_misc_set_alignment (GTK_MISC (label), 0.0, 0.5);
942 gtk_table_attach (GTK_TABLE (table), label,
943 1, 4, 2, 3,
944 GTK_FILL, 0, 0, 0);
945 gtk_widget_show (label);
946
947 label = gtk_label_new_with_mnemonic (_("_Orientation:"));
948 gtk_misc_set_alignment (GTK_MISC (label), 0.0, 0.5);
949 gtk_table_attach (GTK_TABLE (table), label,
950 0, 1, 3, 4,
951 GTK_FILL, 0, 0, 0);
952 gtk_widget_show (label);
953
954 radio_button = create_radio_button (NULL, GTK_STOCK_ORIENTATION_PORTRAIT);
955 priv->portrait_radio = radio_button;
956 gtk_table_attach (GTK_TABLE (table), radio_button,
957 1, 2, 3, 4,
958 GTK_EXPAND|GTK_FILL, 0, 0, 0);
959 gtk_label_set_mnemonic_widget (GTK_LABEL (label), radio_button);
960
961 radio_button = create_radio_button (gtk_radio_button_get_group (GTK_RADIO_BUTTON (radio_button)),
962 GTK_STOCK_ORIENTATION_REVERSE_PORTRAIT);
963 priv->reverse_portrait_radio = radio_button;
964 gtk_table_attach (GTK_TABLE (table), radio_button,
965 2, 3, 3, 4,
966 GTK_EXPAND|GTK_FILL, 0, 0, 0);
967
968 radio_button = create_radio_button (gtk_radio_button_get_group (GTK_RADIO_BUTTON (radio_button)),
969 GTK_STOCK_ORIENTATION_LANDSCAPE);
970 priv->landscape_radio = radio_button;
971 gtk_table_attach (GTK_TABLE (table), radio_button,
972 1, 2, 4, 5,
973 GTK_EXPAND|GTK_FILL, 0, 0, 0);
974 gtk_widget_show (radio_button);
975
976 gtk_table_set_row_spacing (GTK_TABLE (table), 3, 0);
977
978 radio_button = create_radio_button (gtk_radio_button_get_group (GTK_RADIO_BUTTON (radio_button)),
979 GTK_STOCK_ORIENTATION_REVERSE_LANDSCAPE);
980 priv->reverse_landscape_radio = radio_button;
981 gtk_table_attach (GTK_TABLE (table), radio_button,
982 2, 3, 4, 5,
983 GTK_EXPAND|GTK_FILL, 0, 0, 0);
984
985
986 g_signal_connect (priv->paper_size_combo, "changed", G_CALLBACK (paper_size_changed), ps_dialog);
987 g_signal_connect (priv->printer_combo, "changed", G_CALLBACK (printer_changed_callback), ps_dialog);
988 gtk_combo_box_set_active (GTK_COMBO_BOX (priv->printer_combo), 0);
989
990 load_print_backends (ps_dialog);
991 }
992
993 /**
994 * gtk_page_setup_unix_dialog_new:
995 * @title: (allow-none): the title of the dialog, or %NULL
996 * @parent: (allow-none): transient parent of the dialog, or %NULL
997 *
998 * Creates a new page setup dialog.
999 *
1000 * Returns: the new #GtkPageSetupUnixDialog
1001 *
1002 * Since: 2.10
1003 */
1004 GtkWidget *
gtk_page_setup_unix_dialog_new(const gchar * title,GtkWindow * parent)1005 gtk_page_setup_unix_dialog_new (const gchar *title,
1006 GtkWindow *parent)
1007 {
1008 GtkWidget *result;
1009
1010 if (title == NULL)
1011 title = _("Page Setup");
1012
1013 result = g_object_new (GTK_TYPE_PAGE_SETUP_UNIX_DIALOG,
1014 "title", title,
1015 NULL);
1016
1017 if (parent)
1018 gtk_window_set_transient_for (GTK_WINDOW (result), parent);
1019
1020 return result;
1021 }
1022
1023 static GtkPageOrientation
get_orientation(GtkPageSetupUnixDialog * dialog)1024 get_orientation (GtkPageSetupUnixDialog *dialog)
1025 {
1026 GtkPageSetupUnixDialogPrivate *priv = dialog->priv;
1027
1028 if (gtk_toggle_button_get_active (GTK_TOGGLE_BUTTON (priv->portrait_radio)))
1029 return GTK_PAGE_ORIENTATION_PORTRAIT;
1030 if (gtk_toggle_button_get_active (GTK_TOGGLE_BUTTON (priv->landscape_radio)))
1031 return GTK_PAGE_ORIENTATION_LANDSCAPE;
1032 if (gtk_toggle_button_get_active (GTK_TOGGLE_BUTTON (priv->reverse_landscape_radio)))
1033 return GTK_PAGE_ORIENTATION_REVERSE_LANDSCAPE;
1034 return GTK_PAGE_ORIENTATION_REVERSE_PORTRAIT;
1035 }
1036
1037 static void
set_orientation(GtkPageSetupUnixDialog * dialog,GtkPageOrientation orientation)1038 set_orientation (GtkPageSetupUnixDialog *dialog,
1039 GtkPageOrientation orientation)
1040 {
1041 GtkPageSetupUnixDialogPrivate *priv = dialog->priv;
1042
1043 switch (orientation)
1044 {
1045 case GTK_PAGE_ORIENTATION_REVERSE_PORTRAIT:
1046 gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (priv->reverse_portrait_radio), TRUE);
1047 break;
1048 case GTK_PAGE_ORIENTATION_PORTRAIT:
1049 gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (priv->portrait_radio), TRUE);
1050 break;
1051 case GTK_PAGE_ORIENTATION_LANDSCAPE:
1052 gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (priv->landscape_radio), TRUE);
1053 break;
1054 case GTK_PAGE_ORIENTATION_REVERSE_LANDSCAPE:
1055 gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (priv->reverse_landscape_radio), TRUE);
1056 break;
1057 }
1058 }
1059
1060 /**
1061 * gtk_page_setup_unix_dialog_set_page_setup:
1062 * @dialog: a #GtkPageSetupUnixDialog
1063 * @page_setup: a #GtkPageSetup
1064 *
1065 * Sets the #GtkPageSetup from which the page setup
1066 * dialog takes its values.
1067 *
1068 * Since: 2.10
1069 **/
1070 void
gtk_page_setup_unix_dialog_set_page_setup(GtkPageSetupUnixDialog * dialog,GtkPageSetup * page_setup)1071 gtk_page_setup_unix_dialog_set_page_setup (GtkPageSetupUnixDialog *dialog,
1072 GtkPageSetup *page_setup)
1073 {
1074 if (page_setup)
1075 {
1076 set_paper_size (dialog, page_setup, FALSE, TRUE);
1077 set_orientation (dialog, gtk_page_setup_get_orientation (page_setup));
1078 }
1079 }
1080
1081 /**
1082 * gtk_page_setup_unix_dialog_get_page_setup:
1083 * @dialog: a #GtkPageSetupUnixDialog
1084 *
1085 * Gets the currently selected page setup from the dialog.
1086 *
1087 * Returns: (transfer none): the current page setup
1088 *
1089 * Since: 2.10
1090 **/
1091 GtkPageSetup *
gtk_page_setup_unix_dialog_get_page_setup(GtkPageSetupUnixDialog * dialog)1092 gtk_page_setup_unix_dialog_get_page_setup (GtkPageSetupUnixDialog *dialog)
1093 {
1094 GtkPageSetup *page_setup;
1095
1096 page_setup = get_current_page_setup (dialog);
1097
1098 gtk_page_setup_set_orientation (page_setup, get_orientation (dialog));
1099
1100 return page_setup;
1101 }
1102
1103 static gboolean
set_active_printer(GtkPageSetupUnixDialog * dialog,const gchar * printer_name)1104 set_active_printer (GtkPageSetupUnixDialog *dialog,
1105 const gchar *printer_name)
1106 {
1107 GtkPageSetupUnixDialogPrivate *priv = dialog->priv;
1108 GtkTreeModel *model;
1109 GtkTreeIter iter;
1110 GtkPrinter *printer;
1111
1112 model = GTK_TREE_MODEL (priv->printer_list);
1113
1114 if (gtk_tree_model_get_iter_first (model, &iter))
1115 {
1116 do
1117 {
1118 gtk_tree_model_get (GTK_TREE_MODEL (priv->printer_list), &iter,
1119 PRINTER_LIST_COL_PRINTER, &printer, -1);
1120 if (printer == NULL)
1121 continue;
1122
1123 if (strcmp (gtk_printer_get_name (printer), printer_name) == 0)
1124 {
1125 gtk_combo_box_set_active_iter (GTK_COMBO_BOX (priv->printer_combo),
1126 &iter);
1127 g_object_unref (printer);
1128 return TRUE;
1129 }
1130
1131 g_object_unref (printer);
1132
1133 } while (gtk_tree_model_iter_next (model, &iter));
1134 }
1135
1136 return FALSE;
1137 }
1138
1139 /**
1140 * gtk_page_setup_unix_dialog_set_print_settings:
1141 * @dialog: a #GtkPageSetupUnixDialog
1142 * @print_settings: a #GtkPrintSettings
1143 *
1144 * Sets the #GtkPrintSettings from which the page setup dialog
1145 * takes its values.
1146 *
1147 * Since: 2.10
1148 **/
1149 void
gtk_page_setup_unix_dialog_set_print_settings(GtkPageSetupUnixDialog * dialog,GtkPrintSettings * print_settings)1150 gtk_page_setup_unix_dialog_set_print_settings (GtkPageSetupUnixDialog *dialog,
1151 GtkPrintSettings *print_settings)
1152 {
1153 GtkPageSetupUnixDialogPrivate *priv = dialog->priv;
1154 const gchar *format_for_printer;
1155
1156 if (priv->print_settings == print_settings) return;
1157
1158 if (priv->print_settings)
1159 g_object_unref (priv->print_settings);
1160
1161 priv->print_settings = print_settings;
1162
1163 if (print_settings)
1164 {
1165 g_object_ref (print_settings);
1166
1167 format_for_printer = gtk_print_settings_get (print_settings, "format-for-printer");
1168
1169 /* Set printer if in list, otherwise set when
1170 * that printer is added
1171 */
1172 if (format_for_printer &&
1173 !set_active_printer (dialog, format_for_printer))
1174 priv->waiting_for_printer = g_strdup (format_for_printer);
1175 }
1176 }
1177
1178 /**
1179 * gtk_page_setup_unix_dialog_get_print_settings:
1180 * @dialog: a #GtkPageSetupUnixDialog
1181 *
1182 * Gets the current print settings from the dialog.
1183 *
1184 * Returns: (transfer none): the current print settings
1185 *
1186 * Since: 2.10
1187 **/
1188 GtkPrintSettings *
gtk_page_setup_unix_dialog_get_print_settings(GtkPageSetupUnixDialog * dialog)1189 gtk_page_setup_unix_dialog_get_print_settings (GtkPageSetupUnixDialog *dialog)
1190 {
1191 GtkPageSetupUnixDialogPrivate *priv = dialog->priv;
1192
1193 return priv->print_settings;
1194 }
1195
1196 #define __GTK_PAGE_SETUP_UNIX_DIALOG_C__
1197 #include "gtkaliasdef.c"
1198