]> Pileus Git - ~andy/gtk/blob - gtk/gtkpagesetupunixdialog.c
Make the labels left-aligned, and remove an obsolete event box. Bug
[~andy/gtk] / gtk / gtkpagesetupunixdialog.c
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 #ifdef HAVE__NL_MEASUREMENT_MEASUREMENT
27 #include <langinfo.h>
28 #endif
29
30 #include "gtkintl.h"
31 #include "gtkprivate.h"
32
33 #include "gtkliststore.h"
34 #include "gtkstock.h"
35 #include "gtktreeviewcolumn.h"
36 #include "gtktreeselection.h"
37 #include "gtktreemodel.h"
38 #include "gtkbutton.h"
39 #include "gtkscrolledwindow.h"
40 #include "gtkvbox.h"
41 #include "gtkhbox.h"
42 #include "gtkframe.h"
43 #include "gtkeventbox.h"
44 #include "gtkcombobox.h"
45 #include "gtktogglebutton.h"
46 #include "gtkradiobutton.h"
47 #include "gtklabel.h"
48 #include "gtktable.h"
49 #include "gtkcelllayout.h"
50 #include "gtkcellrenderertext.h"
51 #include "gtkalignment.h"
52 #include "gtkspinbutton.h"
53 #include "gtkbbox.h"
54 #include "gtkhbbox.h"
55
56 #include "gtkpagesetupunixdialog.h"
57 #include "gtkprintbackend.h"
58 #include "gtkprinter-private.h"
59 #include "gtkpapersize.h"
60 #include "gtkprintutils.h"
61 #include "gtkalias.h"
62
63 #define CUSTOM_PAPER_FILENAME ".gtk-custom-papers"
64
65
66 struct GtkPageSetupUnixDialogPrivate
67 {
68   GtkListStore *printer_list;
69   GtkListStore *page_setup_list;
70   GtkListStore *custom_paper_list;
71   
72   GList *print_backends;
73
74   GtkWidget *printer_combo;
75   GtkWidget *paper_size_combo;
76   GtkWidget *paper_size_label;
77
78   GtkWidget *portrait_radio;
79   GtkWidget *reverse_portrait_radio;
80   GtkWidget *landscape_radio;
81   GtkWidget *reverse_landscape_radio;
82
83   guint request_details_tag;
84   GtkPrinter *request_details_printer;
85   
86   GtkPrintSettings *print_settings;
87
88   /* Save last setup so we can re-set it after selecting manage custom sizes */
89   GtkPageSetup *last_setup;
90
91   gchar *waiting_for_printer;
92 };
93
94 enum {
95   PRINTER_LIST_COL_NAME,
96   PRINTER_LIST_COL_PRINTER,
97   PRINTER_LIST_N_COLS
98 };
99
100 enum {
101   PAGE_SETUP_LIST_COL_PAGE_SETUP,
102   PAGE_SETUP_LIST_COL_IS_SEPARATOR,
103   PAGE_SETUP_LIST_N_COLS
104 };
105
106 G_DEFINE_TYPE (GtkPageSetupUnixDialog, gtk_page_setup_unix_dialog, GTK_TYPE_DIALOG)
107
108 #define GTK_PAGE_SETUP_UNIX_DIALOG_GET_PRIVATE(o)  \
109    (G_TYPE_INSTANCE_GET_PRIVATE ((o), GTK_TYPE_PAGE_SETUP_UNIX_DIALOG, GtkPageSetupUnixDialogPrivate))
110
111 static void gtk_page_setup_unix_dialog_finalize  (GObject                *object);
112 static void populate_dialog                      (GtkPageSetupUnixDialog *dialog);
113 static void fill_paper_sizes_from_printer        (GtkPageSetupUnixDialog *dialog,
114                                                   GtkPrinter             *printer);
115 static void show_custom_paper_dialog             (GtkPageSetupUnixDialog *dialog);
116 static void printer_added_cb                     (GtkPrintBackend        *backend,
117                                                   GtkPrinter             *printer,
118                                                   GtkPageSetupUnixDialog *dialog);
119 static void printer_removed_cb                   (GtkPrintBackend        *backend,
120                                                   GtkPrinter             *printer,
121                                                   GtkPageSetupUnixDialog *dialog);
122 static void printer_status_cb                    (GtkPrintBackend        *backend,
123                                                   GtkPrinter             *printer,
124                                                   GtkPageSetupUnixDialog *dialog);
125
126
127
128 static const gchar const common_paper_sizes[][16] = {
129   "na_letter",
130   "na_legal",
131   "iso_a4",
132   "iso_a5",
133   "roc_16k",
134   "iso_b5",
135   "jis_b5",
136   "na_number-10",
137   "iso_dl",
138   "jpn_chou3",
139   "na_ledger",
140   "iso_a3",
141 };
142
143 static GtkUnit
144 get_default_user_units (void)
145 {
146   /* Translate to the default units to use for presenting
147    * lengths to the user. Translate to default:inch if you
148    * want inches, otherwise translate to default:mm.
149    * Do *not* translate it to "predefinito:mm", if it
150    * it isn't default:mm or default:inch it will not work 
151    */
152   gchar *e = _("default:mm");
153   
154 #ifdef HAVE__NL_MEASUREMENT_MEASUREMENT
155   gchar *imperial = NULL;
156   
157   imperial = nl_langinfo (_NL_MEASUREMENT_MEASUREMENT);
158   if (imperial && imperial[0] == 2 )
159     return GTK_UNIT_INCH;  /* imperial */
160   if (imperial && imperial[0] == 1 )
161     return GTK_UNIT_MM;  /* metric */
162 #endif
163   
164   if (strcmp (e, "default:inch")==0)
165     return GTK_UNIT_INCH;
166   else if (strcmp (e, "default:mm"))
167     g_warning ("Whoever translated default:mm did so wrongly.\n");
168   return GTK_UNIT_MM;
169 }
170
171 static char *
172 custom_paper_get_filename (void)
173 {
174   gchar *filename;
175
176   filename = g_build_filename (g_get_home_dir (), 
177                                CUSTOM_PAPER_FILENAME, NULL);
178   g_assert (filename != NULL);
179   return filename;
180 }
181
182 GList *
183 _gtk_load_custom_papers (void)
184 {
185   GKeyFile *keyfile;
186   gchar *filename;
187   gchar **groups;
188   gsize n_groups, i;
189   gboolean load_ok;
190   GList *result = NULL;
191
192   filename = custom_paper_get_filename ();
193
194   keyfile = g_key_file_new ();
195   load_ok = g_key_file_load_from_file (keyfile, filename, 0, NULL);
196   g_free (filename);
197   if (!load_ok)
198     {
199       g_key_file_free (keyfile);
200       return NULL;
201     }
202
203   groups = g_key_file_get_groups (keyfile, &n_groups);
204   for (i = 0; i < n_groups; ++i)
205     {
206       GtkPageSetup *page_setup;
207
208       page_setup = gtk_page_setup_new_from_key_file (keyfile, groups[i], NULL);
209       if (!page_setup)
210         continue;
211
212       result = g_list_prepend (result, page_setup);
213     }
214  
215   g_strfreev (groups);
216   g_key_file_free (keyfile);
217
218   return g_list_reverse (result);
219 }
220
221 static void
222 load_custom_papers (GtkListStore *store)
223 {
224   GtkTreeIter iter;
225   GList *papers, *p;
226   GtkPageSetup *page_setup;
227   
228   papers = _gtk_load_custom_papers ();
229   for (p = papers; p; p = p->next)
230     {
231       page_setup = p->data;
232       gtk_list_store_append (store, &iter);
233       gtk_list_store_set (store, &iter,
234                           0, page_setup, 
235                           -1);
236       g_object_unref (page_setup);
237     }
238
239   g_list_free (papers); 
240 }
241
242 static void
243 save_custom_papers (GtkListStore *store)
244 {
245   GtkTreeModel *model = GTK_TREE_MODEL (store);
246   GtkTreeIter iter;
247   GKeyFile *keyfile;
248   gchar *filename, *data;
249   gsize len;
250   gint i = 0;
251
252   keyfile = g_key_file_new ();
253   
254   if (gtk_tree_model_get_iter_first (model, &iter))
255     {
256       do
257         {
258           GtkPageSetup *page_setup;
259           gchar group[32];
260
261           g_snprintf (group, sizeof (group), "Paper%u", i);
262
263           gtk_tree_model_get (model, &iter, 0, &page_setup, -1);
264
265           gtk_page_setup_to_key_file (page_setup, keyfile, group);
266           
267           ++i;
268         } while (gtk_tree_model_iter_next (model, &iter));
269     }
270
271   filename = custom_paper_get_filename ();
272   data = g_key_file_to_data (keyfile, &len, NULL);
273   g_file_set_contents (filename, data, len, NULL);
274   g_free (data);
275   g_free (filename);
276 }
277
278 static void
279 gtk_page_setup_unix_dialog_class_init (GtkPageSetupUnixDialogClass *class)
280 {
281   GObjectClass *object_class;
282   GtkWidgetClass *widget_class;
283
284   object_class = (GObjectClass *) class;
285   widget_class = (GtkWidgetClass *) class;
286
287   object_class->finalize = gtk_page_setup_unix_dialog_finalize;
288
289   g_type_class_add_private (class, sizeof (GtkPageSetupUnixDialogPrivate));  
290 }
291
292 static void
293 gtk_page_setup_unix_dialog_init (GtkPageSetupUnixDialog *dialog)
294 {
295   GtkPageSetupUnixDialogPrivate *priv;
296   GtkTreeIter iter;
297
298   priv = dialog->priv = GTK_PAGE_SETUP_UNIX_DIALOG_GET_PRIVATE (dialog);
299
300   priv->print_backends = NULL;
301
302   priv->printer_list = gtk_list_store_new (PRINTER_LIST_N_COLS,
303                                                    G_TYPE_STRING, 
304                                                    G_TYPE_OBJECT);
305
306   gtk_list_store_append (priv->printer_list, &iter);
307   gtk_list_store_set (priv->printer_list, &iter,
308                       PRINTER_LIST_COL_NAME, _("<b>Any Printer</b>\nFor portable documents"),
309                       PRINTER_LIST_COL_PRINTER, NULL,
310                       -1);
311   
312   priv->page_setup_list = gtk_list_store_new (PAGE_SETUP_LIST_N_COLS,
313                                                       G_TYPE_OBJECT,
314                                                       G_TYPE_BOOLEAN);
315
316   priv->custom_paper_list = gtk_list_store_new (1, G_TYPE_OBJECT);
317   load_custom_papers (priv->custom_paper_list);
318
319   populate_dialog (dialog);
320   
321   gtk_dialog_add_buttons (GTK_DIALOG (dialog), 
322                           GTK_STOCK_CANCEL, GTK_RESPONSE_CANCEL,
323                           GTK_STOCK_APPLY, GTK_RESPONSE_OK,
324                           NULL);
325   gtk_dialog_set_alternative_button_order (GTK_DIALOG (dialog),
326                                            GTK_RESPONSE_OK,
327                                            GTK_RESPONSE_CANCEL,
328                                            -1);
329
330   gtk_dialog_set_default_response (GTK_DIALOG (dialog), GTK_RESPONSE_OK);
331 }
332
333 static void
334 gtk_page_setup_unix_dialog_finalize (GObject *object)
335 {
336   GtkPageSetupUnixDialog *dialog = GTK_PAGE_SETUP_UNIX_DIALOG (object);
337   GtkPageSetupUnixDialogPrivate *priv = dialog->priv;
338   GtkPrintBackend *backend;
339   GList *node;
340   
341   if (priv->request_details_tag)
342     {
343       g_signal_handler_disconnect (priv->request_details_printer,
344                                    priv->request_details_tag);
345       g_object_unref (priv->request_details_printer);
346       priv->request_details_printer = NULL;
347       priv->request_details_tag = 0;
348     }
349   
350   if (priv->printer_list)
351     {
352       g_object_unref (priv->printer_list);
353       priv->printer_list = NULL;
354     }
355
356   if (priv->page_setup_list)
357     {
358       g_object_unref (priv->page_setup_list);
359       priv->page_setup_list = NULL;
360     }
361
362   if (priv->custom_paper_list)
363     {
364       g_object_unref (priv->custom_paper_list);
365       priv->custom_paper_list = NULL;
366     }
367
368   if (priv->print_settings)
369     {
370       g_object_unref (priv->print_settings);
371       priv->print_settings = NULL;
372     }
373
374   g_free (priv->waiting_for_printer);
375   priv->waiting_for_printer = NULL;
376
377   for (node = priv->print_backends; node != NULL; node = node->next)
378     {
379       backend = GTK_PRINT_BACKEND (node->data);
380
381       g_signal_handlers_disconnect_by_func (backend, printer_added_cb, dialog);
382       g_signal_handlers_disconnect_by_func (backend, printer_removed_cb, dialog);
383       g_signal_handlers_disconnect_by_func (backend, printer_status_cb, dialog);
384
385       gtk_print_backend_destroy (backend);
386       g_object_unref (backend);
387     }
388   
389   g_list_free (priv->print_backends);
390   priv->print_backends = NULL;
391
392   G_OBJECT_CLASS (gtk_page_setup_unix_dialog_parent_class)->finalize (object);
393 }
394
395 static void
396 printer_added_cb (GtkPrintBackend        *backend, 
397                   GtkPrinter             *printer, 
398                   GtkPageSetupUnixDialog *dialog)
399 {
400   GtkPageSetupUnixDialogPrivate *priv = dialog->priv;
401   GtkTreeIter iter;
402   gchar *str;
403   const gchar *location;;
404
405   if (gtk_printer_is_virtual (printer))
406     return;
407
408   location = gtk_printer_get_location (printer);
409   if (location == NULL)
410     location = "";
411   str = g_strdup_printf ("<b>%s</b>\n%s",
412                          gtk_printer_get_name (printer),
413                          location);
414   
415   gtk_list_store_append (priv->printer_list, &iter);
416   gtk_list_store_set (priv->printer_list, &iter,
417                       PRINTER_LIST_COL_NAME, str,
418                       PRINTER_LIST_COL_PRINTER, printer,
419                       -1);
420
421   g_object_set_data_full (G_OBJECT (printer), 
422                           "gtk-print-tree-iter", 
423                           gtk_tree_iter_copy (&iter),
424                           (GDestroyNotify) gtk_tree_iter_free);
425   
426   g_free (str);
427
428   if (priv->waiting_for_printer != NULL &&
429       strcmp (priv->waiting_for_printer,
430               gtk_printer_get_name (printer)) == 0)
431     {
432       gtk_combo_box_set_active_iter (GTK_COMBO_BOX (priv->printer_combo),
433                                      &iter);
434       priv->waiting_for_printer = NULL;
435     }
436 }
437
438 static void
439 printer_removed_cb (GtkPrintBackend        *backend, 
440                     GtkPrinter             *printer, 
441                     GtkPageSetupUnixDialog *dialog)
442 {
443   GtkPageSetupUnixDialogPrivate *priv = dialog->priv;
444   GtkTreeIter *iter;
445
446   iter = g_object_get_data (G_OBJECT (printer), "gtk-print-tree-iter");
447   gtk_list_store_remove (GTK_LIST_STORE (priv->printer_list), iter);
448 }
449
450
451 static void
452 printer_status_cb (GtkPrintBackend        *backend, 
453                    GtkPrinter             *printer, 
454                    GtkPageSetupUnixDialog *dialog)
455 {
456   GtkPageSetupUnixDialogPrivate *priv = dialog->priv;
457   GtkTreeIter *iter;
458   gchar *str;
459   const gchar *location;;
460   
461   iter = g_object_get_data (G_OBJECT (printer), "gtk-print-tree-iter");
462
463   location = gtk_printer_get_location (printer);
464   if (location == NULL)
465     location = "";
466   str = g_strdup_printf ("<b>%s</b>\n%s",
467                          gtk_printer_get_name (printer),
468                          location);
469   gtk_list_store_set (priv->printer_list, iter,
470                       PRINTER_LIST_COL_NAME, str,
471                       -1);
472   g_free (str);
473 }
474
475 static void
476 printer_list_initialize (GtkPageSetupUnixDialog *dialog,
477                          GtkPrintBackend        *print_backend)
478 {
479   GList *list, *node;
480   
481   g_return_if_fail (print_backend != NULL);
482
483   g_signal_connect_object (print_backend, 
484                            "printer-added", 
485                            (GCallback) printer_added_cb, 
486                            G_OBJECT (dialog), 0);
487
488   g_signal_connect_object (print_backend, 
489                            "printer-removed", 
490                            (GCallback) printer_removed_cb, 
491                            G_OBJECT (dialog), 0);
492
493   g_signal_connect_object (print_backend, 
494                            "printer-status-changed", 
495                            (GCallback) printer_status_cb, 
496                            G_OBJECT (dialog), 0);
497
498   list = gtk_print_backend_get_printer_list (print_backend);
499
500   node = list;
501   while (node != NULL)
502     {
503       printer_added_cb (print_backend, node->data, dialog);
504       node = node->next;
505     }
506
507   g_list_free (list);
508   
509 }
510
511 static void
512 load_print_backends (GtkPageSetupUnixDialog *dialog)
513 {
514   GtkPageSetupUnixDialogPrivate *priv = dialog->priv;
515   GList *node;
516
517   if (g_module_supported ())
518     priv->print_backends = gtk_print_backend_load_modules ();
519
520   for (node = priv->print_backends; node != NULL; node = node->next)
521     printer_list_initialize (dialog, GTK_PRINT_BACKEND (node->data));
522 }
523
524 static gboolean
525 paper_size_row_is_separator (GtkTreeModel *model,
526                              GtkTreeIter  *iter,
527                              gpointer      data)
528 {
529   gboolean separator;
530
531   gtk_tree_model_get (model, iter, PAGE_SETUP_LIST_COL_IS_SEPARATOR, &separator, -1);
532   return separator;
533 }
534
535 static GtkPageSetup *
536 get_current_page_setup (GtkPageSetupUnixDialog *dialog)
537 {
538   GtkPageSetupUnixDialogPrivate *priv = dialog->priv;
539   GtkPageSetup *current_page_setup;
540   GtkComboBox *combo_box;
541   GtkTreeIter iter;
542
543   current_page_setup = NULL;
544   
545   combo_box = GTK_COMBO_BOX (priv->paper_size_combo);
546   if (gtk_combo_box_get_active_iter (combo_box, &iter))
547     gtk_tree_model_get (GTK_TREE_MODEL (priv->page_setup_list), &iter,
548                         PAGE_SETUP_LIST_COL_PAGE_SETUP, &current_page_setup, -1);
549
550   if (current_page_setup)
551     return current_page_setup;
552
553   /* No selected page size, return the default one.
554    * This is used to set the first page setup when the dialog is created
555    * as there is no selection on the first printer_changed.
556    */ 
557   return gtk_page_setup_new ();
558 }
559
560 static gboolean
561 page_setup_is_equal (GtkPageSetup *a, 
562                      GtkPageSetup *b)
563 {
564   return
565     gtk_paper_size_is_equal (gtk_page_setup_get_paper_size (a),
566                              gtk_page_setup_get_paper_size (b)) &&
567     gtk_page_setup_get_top_margin (a, GTK_UNIT_MM) == gtk_page_setup_get_top_margin (b, GTK_UNIT_MM) &&
568     gtk_page_setup_get_bottom_margin (a, GTK_UNIT_MM) == gtk_page_setup_get_bottom_margin (b, GTK_UNIT_MM) &&
569     gtk_page_setup_get_left_margin (a, GTK_UNIT_MM) == gtk_page_setup_get_left_margin (b, GTK_UNIT_MM) &&
570     gtk_page_setup_get_right_margin (a, GTK_UNIT_MM) == gtk_page_setup_get_right_margin (b, GTK_UNIT_MM);
571 }
572
573 static gboolean
574 page_setup_is_same_size (GtkPageSetup *a,
575                          GtkPageSetup *b)
576 {
577   return gtk_paper_size_is_equal (gtk_page_setup_get_paper_size (a),
578                                   gtk_page_setup_get_paper_size (b));
579 }
580
581 static gboolean
582 set_paper_size (GtkPageSetupUnixDialog *dialog,
583                 GtkPageSetup           *page_setup,
584                 gboolean                size_only,
585                 gboolean                add_item)
586 {
587   GtkPageSetupUnixDialogPrivate *priv = dialog->priv;
588   GtkTreeModel *model;
589   GtkTreeIter iter;
590   GtkPageSetup *list_page_setup;
591
592   model = GTK_TREE_MODEL (priv->page_setup_list);
593
594   if (gtk_tree_model_get_iter_first (model, &iter))
595     {
596       do
597         {
598           gtk_tree_model_get (GTK_TREE_MODEL (priv->page_setup_list), &iter,
599                               PAGE_SETUP_LIST_COL_PAGE_SETUP, &list_page_setup, -1);
600           if (list_page_setup == NULL)
601             continue;
602           
603           if ((size_only && page_setup_is_same_size (page_setup, list_page_setup)) ||
604               (!size_only && page_setup_is_equal (page_setup, list_page_setup)))
605             {
606               gtk_combo_box_set_active_iter (GTK_COMBO_BOX (priv->paper_size_combo),
607                                              &iter);
608               g_object_unref (list_page_setup);
609               return TRUE;
610             }
611               
612           g_object_unref (list_page_setup);
613           
614         } while (gtk_tree_model_iter_next (model, &iter));
615     }
616
617   if (add_item)
618     {
619       gtk_list_store_append (priv->page_setup_list, &iter);
620       gtk_list_store_set (priv->page_setup_list, &iter,
621                           PAGE_SETUP_LIST_COL_IS_SEPARATOR, TRUE,
622                           -1);
623       gtk_list_store_append (priv->page_setup_list, &iter);
624       gtk_list_store_set (priv->page_setup_list, &iter,
625                           PAGE_SETUP_LIST_COL_PAGE_SETUP, page_setup,
626                           -1);
627       gtk_combo_box_set_active_iter (GTK_COMBO_BOX (priv->paper_size_combo),
628                                      &iter);
629       return TRUE;
630     }
631
632   return FALSE;
633 }
634
635 static void
636 fill_custom_paper_sizes (GtkPageSetupUnixDialog *dialog)
637 {
638   GtkPageSetupUnixDialogPrivate *priv = dialog->priv;
639   GtkTreeIter iter, paper_iter;
640   GtkTreeModel *model;
641
642   model = GTK_TREE_MODEL (priv->custom_paper_list);
643   if (gtk_tree_model_get_iter_first (model, &iter))
644     {
645       gtk_list_store_append (priv->page_setup_list, &paper_iter);
646       gtk_list_store_set (priv->page_setup_list, &paper_iter,
647                           PAGE_SETUP_LIST_COL_IS_SEPARATOR, TRUE,
648                           -1);
649       do
650         {
651           GtkPageSetup *page_setup;
652           gtk_tree_model_get (model, &iter, 0, &page_setup, -1);
653
654           gtk_list_store_append (priv->page_setup_list, &paper_iter);
655           gtk_list_store_set (priv->page_setup_list, &paper_iter,
656                               PAGE_SETUP_LIST_COL_PAGE_SETUP, page_setup,
657                               -1);
658
659           g_object_unref (page_setup);
660         } while (gtk_tree_model_iter_next (model, &iter));
661     }
662   
663   gtk_list_store_append (priv->page_setup_list, &paper_iter);
664   gtk_list_store_set (priv->page_setup_list, &paper_iter,
665                       PAGE_SETUP_LIST_COL_IS_SEPARATOR, TRUE,
666                       -1);
667   gtk_list_store_append (priv->page_setup_list, &paper_iter);
668   gtk_list_store_set (priv->page_setup_list, &paper_iter,
669                       PAGE_SETUP_LIST_COL_PAGE_SETUP, NULL,
670                       -1);
671 }
672
673 static void
674 fill_paper_sizes_from_printer (GtkPageSetupUnixDialog *dialog,
675                                GtkPrinter             *printer)
676 {
677   GtkPageSetupUnixDialogPrivate *priv = dialog->priv;
678   GList *list, *l;
679   GtkPageSetup *current_page_setup, *page_setup;
680   GtkPaperSize *paper_size;
681   GtkTreeIter iter;
682   gint i;
683
684   current_page_setup = get_current_page_setup (dialog);
685   
686   gtk_list_store_clear (priv->page_setup_list);
687
688   if (printer == NULL)
689     {
690       for (i = 0; i < G_N_ELEMENTS (common_paper_sizes); i++)
691         {
692           page_setup = gtk_page_setup_new ();
693           paper_size = gtk_paper_size_new (common_paper_sizes[i]);
694           gtk_page_setup_set_paper_size_and_default_margins (page_setup, paper_size);
695           gtk_paper_size_free (paper_size);
696           
697           gtk_list_store_append (priv->page_setup_list, &iter);
698           gtk_list_store_set (priv->page_setup_list, &iter,
699                               PAGE_SETUP_LIST_COL_PAGE_SETUP, page_setup,
700                               -1);
701           g_object_unref (page_setup);
702         }
703     }
704   else
705     {
706       list = gtk_printer_list_papers (printer);
707       /* TODO: We should really sort this list so interesting size
708          are at the top */
709       for (l = list; l != NULL; l = l->next)
710         {
711           page_setup = l->data;
712           gtk_list_store_append (priv->page_setup_list, &iter);
713           gtk_list_store_set (priv->page_setup_list, &iter,
714                               PAGE_SETUP_LIST_COL_PAGE_SETUP, page_setup,
715                               -1);
716           g_object_unref (page_setup);
717         }
718       g_list_free (list);
719     }
720
721   fill_custom_paper_sizes (dialog);
722   
723   if (!set_paper_size (dialog, current_page_setup, FALSE, FALSE))
724     set_paper_size (dialog, current_page_setup, TRUE, TRUE);
725   
726   if (current_page_setup)
727     g_object_unref (current_page_setup);
728 }
729
730 static void
731 printer_changed_finished_callback (GtkPrinter             *printer,
732                                    gboolean                success,
733                                    GtkPageSetupUnixDialog *dialog)
734 {
735   GtkPageSetupUnixDialogPrivate *priv = dialog->priv;
736
737   g_signal_handler_disconnect (priv->request_details_printer,
738                                priv->request_details_tag);
739   g_object_unref (priv->request_details_printer);
740   priv->request_details_tag = 0;
741   priv->request_details_printer = NULL;
742   
743   if (success)
744     fill_paper_sizes_from_printer (dialog, printer);
745
746 }
747
748 static void
749 printer_changed_callback (GtkComboBox            *combo_box,
750                           GtkPageSetupUnixDialog *dialog)
751 {
752   GtkPageSetupUnixDialogPrivate *priv = dialog->priv;
753   GtkPrinter *printer;
754   GtkTreeIter iter;
755
756   /* If we're waiting for a specific printer but the user changed
757    * to another printer, cancel that wait. 
758    */
759   if (priv->waiting_for_printer)
760     {
761       g_free (priv->waiting_for_printer);
762       priv->waiting_for_printer = NULL;
763     }
764   
765   if (priv->request_details_tag)
766     {
767       g_signal_handler_disconnect (priv->request_details_printer,
768                                    priv->request_details_tag);
769       g_object_unref (priv->request_details_printer);
770       priv->request_details_printer = NULL;
771       priv->request_details_tag = 0;
772     }
773   
774   if (gtk_combo_box_get_active_iter (combo_box, &iter))
775     {
776       gtk_tree_model_get (gtk_combo_box_get_model (combo_box), &iter,
777                           PRINTER_LIST_COL_PRINTER, &printer, -1);
778
779       if (printer == NULL || gtk_printer_has_details (printer))
780         fill_paper_sizes_from_printer (dialog, printer);
781       else
782         {
783           priv->request_details_printer = g_object_ref (printer);
784           priv->request_details_tag =
785             g_signal_connect (printer, "details-acquired",
786                               G_CALLBACK (printer_changed_finished_callback), dialog);
787           gtk_printer_request_details (printer);
788
789         }
790
791       if (printer)
792         g_object_unref (printer);
793
794       if (priv->print_settings)
795         {
796           const char *name = NULL;
797
798           if (printer)
799             name = gtk_printer_get_name (printer);
800           
801           gtk_print_settings_set (priv->print_settings,
802                                   "format-for-printer", name);
803         }
804     }
805 }
806
807 /* We do this munging because we don't want to show zero digits
808    after the decimal point, and not to many such digits if they
809    are nonzero. I wish printf let you specify max precision for %f... */
810 static gchar *
811 double_to_string (gdouble d, 
812                   GtkUnit unit)
813 {
814   gchar *val, *p;
815   struct lconv *locale_data;
816   const gchar *decimal_point;
817   gint decimal_point_len;
818
819   locale_data = localeconv ();
820   decimal_point = locale_data->decimal_point;
821   decimal_point_len = strlen (decimal_point);
822   
823   /* Max two decimal digits for inch, max one for mm */
824   if (unit == GTK_UNIT_INCH)
825     val = g_strdup_printf ("%.2f", d);
826   else
827     val = g_strdup_printf ("%.1f", d);
828
829   if (strstr (val, decimal_point))
830     {
831       p = val + strlen (val) - 1;
832       while (*p == '0')
833         p--;
834       if (p - val + 1 >= decimal_point_len &&
835           strncmp (p - (decimal_point_len - 1), decimal_point, decimal_point_len) == 0)
836         p -= decimal_point_len;
837       p[1] = '\0';
838     }
839
840   return val;
841 }
842
843 static void
844 paper_size_changed (GtkComboBox            *combo_box,
845                     GtkPageSetupUnixDialog *dialog)
846 {
847   GtkPageSetupUnixDialogPrivate *priv = dialog->priv;
848   GtkTreeIter iter;
849   GtkPageSetup *page_setup, *last_page_setup;
850   GtkUnit unit;
851   gchar *str, *w, *h;
852   gchar *top, *bottom, *left, *right;
853   GtkLabel *label;
854   const gchar *unit_str;
855
856   label = GTK_LABEL (priv->paper_size_label);
857    
858   if (gtk_combo_box_get_active_iter (combo_box, &iter))
859     {
860       gtk_tree_model_get (gtk_combo_box_get_model (combo_box),
861                           &iter, PAGE_SETUP_LIST_COL_PAGE_SETUP, &page_setup, -1);
862
863       if (page_setup == NULL)
864         {
865           /* Change from "manage" menu item to last value */
866           if (priv->last_setup)
867             last_page_setup = g_object_ref (priv->last_setup);
868           else
869             last_page_setup = gtk_page_setup_new (); /* "good" default */
870           set_paper_size (dialog, last_page_setup, FALSE, TRUE);
871           g_object_unref (last_page_setup);
872
873           /* And show the custom paper dialog */
874           show_custom_paper_dialog (dialog);
875
876           return;
877         }
878
879       if (priv->last_setup)
880         g_object_unref (priv->last_setup);
881
882       priv->last_setup = g_object_ref (page_setup);
883       
884       unit = get_default_user_units ();
885
886       if (unit == GTK_UNIT_MM)
887         unit_str = _("mm");
888       else
889         unit_str = _("inch");
890         
891
892       w = double_to_string (gtk_page_setup_get_paper_width (page_setup, unit),
893                             unit);
894       h = double_to_string (gtk_page_setup_get_paper_height (page_setup, unit),
895                             unit);
896       str = g_strdup_printf ("%s x %s %s", w, h, unit_str);
897       g_free (w);
898       g_free (h);
899       
900       gtk_label_set_text (label, str);
901       g_free (str);
902
903       top = double_to_string (gtk_page_setup_get_top_margin (page_setup, unit), unit);
904       bottom = double_to_string (gtk_page_setup_get_bottom_margin (page_setup, unit), unit);
905       left = double_to_string (gtk_page_setup_get_left_margin (page_setup, unit), unit);
906       right = double_to_string (gtk_page_setup_get_right_margin (page_setup, unit), unit);
907
908       str = g_strdup_printf (_("Margins:\n"
909                                " Left: %s %s\n"
910                                " Right: %s %s\n"
911                                " Top: %s %s\n"
912                                " Bottom: %s %s"
913                                ),
914                              left, unit_str,
915                              right, unit_str,
916                              top, unit_str,
917                              bottom, unit_str);
918       g_free (top);
919       g_free (bottom);
920       g_free (left);
921       g_free (right);
922       
923       gtk_widget_set_tooltip_text (priv->paper_size_label, str);
924       g_free (str);
925       
926       g_object_unref (page_setup);
927     }
928   else
929     {
930       gtk_label_set_text (label, "");
931       gtk_widget_set_tooltip_text (priv->paper_size_label, NULL);
932       if (priv->last_setup)
933         g_object_unref (priv->last_setup);
934       priv->last_setup = NULL;
935     }
936 }
937
938 static void
939 page_name_func (GtkCellLayout   *cell_layout,
940                 GtkCellRenderer *cell,
941                 GtkTreeModel    *tree_model,
942                 GtkTreeIter     *iter,
943                 gpointer         data)
944 {
945   GtkPageSetup *page_setup;
946   GtkPaperSize *paper_size;
947   
948   gtk_tree_model_get (tree_model, iter,
949                       PAGE_SETUP_LIST_COL_PAGE_SETUP, &page_setup, -1);
950   if (page_setup)
951     {
952       paper_size = gtk_page_setup_get_paper_size (page_setup);
953       g_object_set (cell, "text",  gtk_paper_size_get_display_name (paper_size), NULL);
954       g_object_unref (page_setup);
955     }
956   else
957     g_object_set (cell, "text",  _("Manage Custom Sizes..."), NULL);
958       
959 }
960
961 static GtkWidget *
962 create_radio_button (GSList      *group,
963                      const gchar *stock_id)
964 {
965   GtkWidget *radio_button, *image, *label, *hbox;
966   GtkStockItem item;
967
968   radio_button = gtk_radio_button_new (group);
969   image = gtk_image_new_from_stock (stock_id, GTK_ICON_SIZE_LARGE_TOOLBAR);
970   gtk_stock_lookup (stock_id, &item);
971   label = gtk_label_new (item.label);
972   hbox = gtk_hbox_new (0, 6);
973   gtk_container_add (GTK_CONTAINER (radio_button), hbox);
974   gtk_container_add (GTK_CONTAINER (hbox), image);
975   gtk_container_add (GTK_CONTAINER (hbox), label);
976
977   gtk_widget_show_all (radio_button);
978
979   return radio_button;
980 }
981
982 static void
983 populate_dialog (GtkPageSetupUnixDialog *ps_dialog)
984 {
985   GtkPageSetupUnixDialogPrivate *priv = ps_dialog->priv;
986   GtkDialog *dialog = GTK_DIALOG (ps_dialog);
987   GtkWidget *table, *label, *combo, *radio_button;
988   GtkCellRenderer *cell;
989
990   gtk_window_set_resizable (GTK_WINDOW (dialog), FALSE);
991
992   gtk_dialog_set_has_separator (dialog, FALSE);
993   gtk_container_set_border_width (GTK_CONTAINER (dialog), 5);
994   gtk_box_set_spacing (GTK_BOX (dialog->vbox), 2); /* 2 * 5 + 2 = 12 */
995   gtk_container_set_border_width (GTK_CONTAINER (dialog->action_area), 5);
996   gtk_box_set_spacing (GTK_BOX (dialog->action_area), 6);
997
998   table = gtk_table_new (5, 4, FALSE);
999   gtk_table_set_row_spacings (GTK_TABLE (table), 6);
1000   gtk_table_set_col_spacings (GTK_TABLE (table), 12);
1001   gtk_container_set_border_width (GTK_CONTAINER (table), 5);
1002   gtk_box_pack_start (GTK_BOX (dialog->vbox), table, TRUE, TRUE, 0);
1003   gtk_widget_show (table);
1004
1005   label = gtk_label_new_with_mnemonic (_("_Format for:"));
1006   gtk_misc_set_alignment (GTK_MISC (label), 0.0, 0.5);
1007   gtk_table_attach (GTK_TABLE (table), label,
1008                     0, 1, 0, 1,
1009                     GTK_FILL, 0, 0, 0);
1010   gtk_widget_show (label);
1011
1012   combo = gtk_combo_box_new_with_model (GTK_TREE_MODEL (priv->printer_list));
1013   priv->printer_combo = combo;
1014
1015   cell = gtk_cell_renderer_text_new ();
1016   gtk_cell_layout_pack_start (GTK_CELL_LAYOUT (combo), cell, TRUE);
1017   gtk_cell_layout_set_attributes (GTK_CELL_LAYOUT (combo), cell,
1018                                   "markup", PRINTER_LIST_COL_NAME,
1019                                   NULL);
1020
1021   gtk_table_attach (GTK_TABLE (table), combo,
1022                     1, 4, 0, 1,
1023                     GTK_FILL | GTK_EXPAND, 0, 0, 0);
1024   gtk_widget_show (combo);
1025   gtk_label_set_mnemonic_widget (GTK_LABEL (label), combo);
1026
1027   label = gtk_label_new_with_mnemonic (_("_Paper size:"));
1028   gtk_misc_set_alignment (GTK_MISC (label), 0.0, 0.5);
1029   gtk_table_attach (GTK_TABLE (table), label,
1030                     0, 1, 1, 2,
1031                     GTK_FILL, 0, 0, 0);
1032   gtk_widget_show (label);
1033
1034   combo = gtk_combo_box_new_with_model (GTK_TREE_MODEL (priv->page_setup_list));
1035   priv->paper_size_combo = combo;
1036   gtk_combo_box_set_row_separator_func (GTK_COMBO_BOX (combo), 
1037                                         paper_size_row_is_separator, NULL, NULL);
1038   
1039   cell = gtk_cell_renderer_text_new ();
1040   gtk_cell_layout_pack_start (GTK_CELL_LAYOUT (combo), cell, TRUE);
1041   gtk_cell_layout_set_cell_data_func (GTK_CELL_LAYOUT (combo), cell,
1042                                       page_name_func, NULL, NULL);
1043
1044   gtk_table_attach (GTK_TABLE (table), combo,
1045                     1, 4, 1, 2,
1046                     GTK_FILL | GTK_EXPAND, 0, 0, 0);
1047   gtk_widget_show (combo);
1048   gtk_label_set_mnemonic_widget (GTK_LABEL (label), combo);
1049
1050   label = gtk_label_new (NULL);
1051   priv->paper_size_label = label;
1052   gtk_misc_set_alignment (GTK_MISC (label), 0.0, 0.5);
1053   gtk_table_attach (GTK_TABLE (table), label,
1054                     1, 4, 2, 3,
1055                     GTK_FILL, 0, 0, 0);
1056   gtk_widget_show (label);
1057
1058   label = gtk_label_new_with_mnemonic (_("_Orientation:"));
1059   gtk_misc_set_alignment (GTK_MISC (label), 0.0, 0.5);
1060   gtk_table_attach (GTK_TABLE (table), label,
1061                     0, 1, 3, 4,
1062                     GTK_FILL, 0, 0, 0);
1063   gtk_widget_show (label);
1064
1065   radio_button = create_radio_button (NULL, GTK_STOCK_ORIENTATION_PORTRAIT);
1066   priv->portrait_radio = radio_button;
1067   gtk_table_attach (GTK_TABLE (table), radio_button,
1068                     1, 2, 3, 4,
1069                     GTK_EXPAND|GTK_FILL, 0, 0, 0);
1070   gtk_label_set_mnemonic_widget (GTK_LABEL (label), radio_button);
1071
1072   radio_button = create_radio_button (gtk_radio_button_get_group (GTK_RADIO_BUTTON (radio_button)),
1073                                       GTK_STOCK_ORIENTATION_REVERSE_PORTRAIT);
1074   priv->reverse_portrait_radio = radio_button;
1075   gtk_table_attach (GTK_TABLE (table), radio_button,
1076                     2, 3, 3, 4,
1077                     GTK_EXPAND|GTK_FILL, 0, 0, 0);
1078
1079   radio_button = create_radio_button (gtk_radio_button_get_group (GTK_RADIO_BUTTON (radio_button)),
1080                                       GTK_STOCK_ORIENTATION_LANDSCAPE);
1081   priv->landscape_radio = radio_button;
1082   gtk_table_attach (GTK_TABLE (table), radio_button,
1083                     1, 2, 4, 5,
1084                     GTK_EXPAND|GTK_FILL, 0, 0, 0);
1085   gtk_widget_show (radio_button);
1086
1087   gtk_table_set_row_spacing (GTK_TABLE (table), 3, 0);
1088   
1089   radio_button = create_radio_button (gtk_radio_button_get_group (GTK_RADIO_BUTTON (radio_button)),
1090                                       GTK_STOCK_ORIENTATION_REVERSE_LANDSCAPE);
1091   priv->reverse_landscape_radio = radio_button;
1092   gtk_table_attach (GTK_TABLE (table), radio_button,
1093                     2, 3, 4, 5,
1094                     GTK_EXPAND|GTK_FILL, 0, 0, 0);
1095
1096
1097   g_signal_connect (priv->paper_size_combo, "changed", G_CALLBACK (paper_size_changed), ps_dialog);
1098   g_signal_connect (priv->printer_combo, "changed", G_CALLBACK (printer_changed_callback), ps_dialog);
1099   gtk_combo_box_set_active (GTK_COMBO_BOX (priv->printer_combo), 0);
1100
1101   load_print_backends (ps_dialog);
1102 }
1103
1104 /**
1105  * gtk_page_setup_unix_dialog_new:
1106  * @title: the title of the dialog, or %NULL
1107  * @parent: transient parent of the dialog, or %NULL
1108  *
1109  * Creates a new page setup dialog.
1110  *
1111  * Returns: the new #GtkPageSetupUnixDialog
1112  *
1113  * Since: 2.10
1114  */
1115 GtkWidget *
1116 gtk_page_setup_unix_dialog_new (const gchar *title,
1117                                 GtkWindow   *parent)
1118 {
1119   GtkWidget *result;
1120
1121   if (title == NULL)
1122     title = _("Page Setup");
1123   
1124   result = g_object_new (GTK_TYPE_PAGE_SETUP_UNIX_DIALOG,
1125                          "title", title,
1126                          NULL);
1127
1128   if (parent)
1129     gtk_window_set_transient_for (GTK_WINDOW (result), parent);
1130
1131   return result;
1132 }
1133
1134 static GtkPageOrientation
1135 get_orientation (GtkPageSetupUnixDialog *dialog)
1136 {
1137   GtkPageSetupUnixDialogPrivate *priv = dialog->priv;
1138
1139   if (gtk_toggle_button_get_active (GTK_TOGGLE_BUTTON (priv->portrait_radio)))
1140     return GTK_PAGE_ORIENTATION_PORTRAIT;
1141   if (gtk_toggle_button_get_active (GTK_TOGGLE_BUTTON (priv->landscape_radio)))
1142     return GTK_PAGE_ORIENTATION_LANDSCAPE;
1143   if (gtk_toggle_button_get_active (GTK_TOGGLE_BUTTON (priv->reverse_landscape_radio)))
1144     return GTK_PAGE_ORIENTATION_REVERSE_LANDSCAPE;
1145   return GTK_PAGE_ORIENTATION_REVERSE_PORTRAIT;
1146 }
1147
1148 static void
1149 set_orientation (GtkPageSetupUnixDialog *dialog, 
1150                  GtkPageOrientation      orientation)
1151 {
1152   GtkPageSetupUnixDialogPrivate *priv = dialog->priv;
1153
1154   switch (orientation)
1155     {
1156     case GTK_PAGE_ORIENTATION_REVERSE_PORTRAIT:
1157       gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (priv->reverse_portrait_radio), TRUE);
1158       break;
1159     case GTK_PAGE_ORIENTATION_PORTRAIT:
1160       gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (priv->portrait_radio), TRUE);
1161       break;
1162     case GTK_PAGE_ORIENTATION_LANDSCAPE:
1163       gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (priv->landscape_radio), TRUE);
1164       break;
1165     case GTK_PAGE_ORIENTATION_REVERSE_LANDSCAPE:
1166       gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (priv->reverse_landscape_radio), TRUE);
1167       break;
1168     }
1169 }
1170
1171 /**
1172  * gtk_page_setup_unix_dialog_set_page_setup:
1173  * @dialog: a #GtkPageSetupUnixDialog
1174  * @page_setup: a #GtkPageSetup
1175  * 
1176  * Sets the #GtkPageSetup from which the page setup
1177  * dialog takes its values.
1178  *
1179  * Since: 2.10
1180  **/
1181 void
1182 gtk_page_setup_unix_dialog_set_page_setup (GtkPageSetupUnixDialog *dialog,
1183                                            GtkPageSetup           *page_setup)
1184 {
1185   if (page_setup)
1186     {
1187       set_paper_size (dialog, page_setup, FALSE, TRUE);
1188       set_orientation (dialog, gtk_page_setup_get_orientation (page_setup));
1189     }
1190 }
1191
1192 /**
1193  * gtk_page_setup_unix_dialog_get_page_setup:
1194  * @dialog: a #GtkPageSetupUnixDialog
1195  * 
1196  * Gets the currently selected page setup from the dialog. 
1197  * 
1198  * Returns: the current page setup 
1199  *
1200  * Since: 2.10
1201  **/
1202 GtkPageSetup *
1203 gtk_page_setup_unix_dialog_get_page_setup (GtkPageSetupUnixDialog *dialog)
1204 {
1205   GtkPageSetup *page_setup;
1206   
1207   page_setup = get_current_page_setup (dialog);
1208
1209   gtk_page_setup_set_orientation (page_setup, get_orientation (dialog));
1210
1211   return page_setup;
1212 }
1213
1214 static gboolean
1215 set_active_printer (GtkPageSetupUnixDialog *dialog,
1216                     const gchar            *printer_name)
1217 {
1218   GtkPageSetupUnixDialogPrivate *priv = dialog->priv;
1219   GtkTreeModel *model;
1220   GtkTreeIter iter;
1221   GtkPrinter *printer;
1222
1223   model = GTK_TREE_MODEL (priv->printer_list);
1224
1225   if (gtk_tree_model_get_iter_first (model, &iter))
1226     {
1227       do
1228         {
1229           gtk_tree_model_get (GTK_TREE_MODEL (priv->printer_list), &iter,
1230                               PRINTER_LIST_COL_PRINTER, &printer, -1);
1231           if (printer == NULL)
1232             continue;
1233           
1234           if (strcmp (gtk_printer_get_name (printer), printer_name) == 0)
1235             {
1236               gtk_combo_box_set_active_iter (GTK_COMBO_BOX (priv->printer_combo),
1237                                              &iter);
1238               g_object_unref (printer);
1239               return TRUE;
1240             }
1241               
1242           g_object_unref (printer);
1243           
1244         } while (gtk_tree_model_iter_next (model, &iter));
1245     }
1246   
1247   return FALSE;
1248 }
1249
1250 /**
1251  * gtk_page_setup_unix_dialog_set_print_settings:
1252  * @dialog: a #GtkPageSetupUnixDialog
1253  * @print_settings: a #GtkPrintSettings
1254  * 
1255  * Sets the #GtkPrintSettings from which the page setup dialog
1256  * takes its values.
1257  * 
1258  * Since: 2.10
1259  **/
1260 void
1261 gtk_page_setup_unix_dialog_set_print_settings (GtkPageSetupUnixDialog *dialog,
1262                                                GtkPrintSettings       *print_settings)
1263 {
1264   GtkPageSetupUnixDialogPrivate *priv = dialog->priv;
1265   const gchar *format_for_printer;
1266
1267   if (priv->print_settings == print_settings) return;
1268
1269   if (priv->print_settings)
1270     g_object_unref (priv->print_settings);
1271
1272   priv->print_settings = print_settings;
1273
1274   if (print_settings)
1275     {
1276       g_object_ref (print_settings);
1277
1278       format_for_printer = gtk_print_settings_get (print_settings, "format-for-printer");
1279
1280       /* Set printer if in list, otherwise set when 
1281        * that printer is added 
1282        */
1283       if (format_for_printer &&
1284           !set_active_printer (dialog, format_for_printer))
1285         priv->waiting_for_printer = g_strdup (format_for_printer); 
1286     }
1287 }
1288
1289 /**
1290  * gtk_page_setup_unix_dialog_get_print_settings:
1291  * @dialog: a #GtkPageSetupUnixDialog
1292  * 
1293  * Gets the current print settings from the dialog.
1294  * 
1295  * Returns: the current print settings
1296  *
1297  * Since: 2.10
1298  **/
1299 GtkPrintSettings *
1300 gtk_page_setup_unix_dialog_get_print_settings (GtkPageSetupUnixDialog *dialog)
1301 {
1302   GtkPageSetupUnixDialogPrivate *priv = dialog->priv;
1303
1304   return priv->print_settings;
1305 }
1306
1307 static GtkWidget *
1308 wrap_in_frame (const gchar *label, 
1309                GtkWidget   *child)
1310 {
1311   GtkWidget *frame, *alignment, *label_widget;
1312   gchar *bold_text;
1313
1314   label_widget = gtk_label_new (NULL);
1315   gtk_misc_set_alignment (GTK_MISC (label_widget), 0.0, 0.5);
1316   gtk_widget_show (label_widget);
1317   
1318   bold_text = g_markup_printf_escaped ("<b>%s</b>", label);
1319   gtk_label_set_markup (GTK_LABEL (label_widget), bold_text);
1320   g_free (bold_text);
1321   
1322   frame = gtk_vbox_new (FALSE, 6);
1323   gtk_box_pack_start (GTK_BOX (frame), label_widget, FALSE, FALSE, 0);
1324   
1325   alignment = gtk_alignment_new (0.0, 0.0, 1.0, 1.0);
1326   gtk_alignment_set_padding (GTK_ALIGNMENT (alignment),
1327                              0, 0, 12, 0);
1328   gtk_box_pack_start (GTK_BOX (frame), alignment, FALSE, FALSE, 0);
1329
1330   gtk_container_add (GTK_CONTAINER (alignment), child);
1331
1332   gtk_widget_show (frame);
1333   gtk_widget_show (alignment);
1334   
1335   return frame;
1336 }
1337
1338 typedef struct 
1339 {
1340   GtkUnit display_unit;
1341   GtkWidget *spin_button;
1342 } UnitWidget;
1343
1344 typedef struct 
1345 {
1346   GtkPageSetupUnixDialog *dialog;
1347   GtkWidget *treeview;
1348   GtkTreeViewColumn *text_column;
1349   GtkWidget *values_box;
1350   GtkWidget *printer_combo;
1351   GtkWidget *width_widget;
1352   GtkWidget *height_widget;
1353   GtkWidget *top_widget;
1354   GtkWidget *bottom_widget;
1355   GtkWidget *left_widget;
1356   GtkWidget *right_widget;
1357   gulong printer_inserted_tag;
1358   gulong printer_removed_tag;
1359   guint request_details_tag;
1360   GtkPrinter *request_details_printer;
1361   guint non_user_change : 1;
1362 } CustomPaperDialog;
1363
1364 static void unit_widget_changed (CustomPaperDialog *data);
1365
1366 static GtkWidget *
1367 new_unit_widget (CustomPaperDialog *dialog, 
1368                  GtkUnit            unit, 
1369                  GtkWidget         *mnemonic_label)
1370 {
1371   GtkWidget *hbox, *button, *label;
1372   UnitWidget *data;
1373
1374   data = g_new0 (UnitWidget, 1);
1375   data->display_unit = unit;
1376   
1377   hbox = gtk_hbox_new (FALSE, 6);
1378
1379   button = gtk_spin_button_new_with_range (0.0, 9999.0, 1);
1380   if (unit == GTK_UNIT_INCH)
1381     gtk_spin_button_set_digits (GTK_SPIN_BUTTON (button), 2);
1382   else
1383     gtk_spin_button_set_digits (GTK_SPIN_BUTTON (button), 1);
1384
1385   gtk_box_pack_start (GTK_BOX (hbox), button, TRUE, TRUE, 0);
1386   gtk_widget_show (button);
1387
1388   data->spin_button = button;
1389
1390   g_signal_connect_swapped (button, "value-changed",
1391                             G_CALLBACK (unit_widget_changed), dialog);
1392   
1393   if (unit == GTK_UNIT_INCH)
1394     label = gtk_label_new (_("inch"));
1395   else
1396     label = gtk_label_new (_("mm"));
1397
1398   gtk_box_pack_start (GTK_BOX (hbox), label, FALSE, FALSE, 0);
1399   gtk_widget_show (label);
1400   gtk_label_set_mnemonic_widget (GTK_LABEL (mnemonic_label), button);
1401
1402   g_object_set_data_full (G_OBJECT (hbox), "unit-data", data, g_free);
1403   
1404   return hbox;
1405 }
1406
1407 static double
1408 unit_widget_get (GtkWidget *unit_widget)
1409 {
1410   UnitWidget *data = g_object_get_data (G_OBJECT (unit_widget), "unit-data");
1411   return _gtk_print_convert_to_mm (gtk_spin_button_get_value (GTK_SPIN_BUTTON (data->spin_button)),
1412                                    data->display_unit);
1413 }
1414
1415 static void
1416 unit_widget_set (GtkWidget *unit_widget, 
1417                  gdouble    value)
1418 {
1419   UnitWidget *data;
1420
1421   data = g_object_get_data (G_OBJECT (unit_widget), "unit-data");
1422   gtk_spin_button_set_value (GTK_SPIN_BUTTON (data->spin_button),
1423                              _gtk_print_convert_from_mm (value, data->display_unit));
1424 }
1425
1426 static void
1427 custom_paper_printer_data_func (GtkCellLayout   *cell_layout,
1428                                 GtkCellRenderer *cell,
1429                                 GtkTreeModel    *tree_model,
1430                                 GtkTreeIter     *iter,
1431                                 gpointer         data)
1432 {
1433   GtkPrinter *printer;
1434
1435   gtk_tree_model_get (tree_model, iter,
1436                       PRINTER_LIST_COL_PRINTER, &printer, -1);
1437
1438   if (printer)
1439     g_object_set (cell, "text",  gtk_printer_get_name (printer), NULL);
1440   else
1441     g_object_set (cell, "text",  _("Margins from Printer..."), NULL);
1442   
1443   if (printer)
1444     g_object_unref (printer);
1445 }
1446
1447 static void
1448 update_combo_sensitivity_from_printers (CustomPaperDialog *data)
1449 {
1450   GtkTreeIter iter;
1451   gboolean sensitive;
1452   GtkTreeSelection *selection;
1453   GtkTreeModel *model;
1454
1455   sensitive = FALSE;
1456   model = GTK_TREE_MODEL (data->dialog->priv->printer_list);
1457   selection = gtk_tree_view_get_selection (GTK_TREE_VIEW (data->treeview));
1458   if (gtk_tree_model_get_iter_first (model, &iter) &&
1459       gtk_tree_model_iter_next (model, &iter) &&
1460       gtk_tree_selection_get_selected (selection, NULL, &iter))
1461     sensitive = TRUE;
1462
1463   gtk_widget_set_sensitive (data->printer_combo, sensitive);
1464 }
1465
1466 static void
1467 update_custom_widgets_from_list (CustomPaperDialog *data)
1468 {
1469   GtkTreeSelection *selection;
1470   GtkTreeModel *model;
1471   GtkTreeIter iter;
1472   GtkPageSetup *page_setup;
1473   
1474   model = gtk_tree_view_get_model (GTK_TREE_VIEW (data->treeview));
1475   selection = gtk_tree_view_get_selection (GTK_TREE_VIEW (data->treeview));
1476
1477   data->non_user_change = TRUE;
1478   if (gtk_tree_selection_get_selected (selection, NULL, &iter))
1479     {
1480       gtk_tree_model_get (model, &iter, 0, &page_setup, -1);
1481       
1482       unit_widget_set (data->width_widget,
1483                        gtk_page_setup_get_paper_width (page_setup, GTK_UNIT_MM));
1484       unit_widget_set (data->height_widget, 
1485                        gtk_page_setup_get_paper_height (page_setup, GTK_UNIT_MM));
1486       unit_widget_set (data->top_widget,
1487                        gtk_page_setup_get_top_margin (page_setup, GTK_UNIT_MM));
1488       unit_widget_set (data->bottom_widget, 
1489                        gtk_page_setup_get_bottom_margin (page_setup, GTK_UNIT_MM));
1490       unit_widget_set (data->left_widget,
1491                        gtk_page_setup_get_left_margin (page_setup, GTK_UNIT_MM));
1492       unit_widget_set (data->right_widget,
1493                        gtk_page_setup_get_right_margin (page_setup, GTK_UNIT_MM));
1494
1495       gtk_widget_set_sensitive (data->values_box, TRUE);
1496     }
1497   else
1498     {
1499       gtk_widget_set_sensitive (data->values_box, FALSE);
1500     }
1501
1502   update_combo_sensitivity_from_printers (data);
1503   data->non_user_change = FALSE;
1504 }
1505
1506 static void
1507 selected_custom_paper_changed (GtkTreeSelection  *selection,
1508                                CustomPaperDialog *data)
1509 {
1510   update_custom_widgets_from_list (data);
1511 }
1512
1513 static void
1514 unit_widget_changed (CustomPaperDialog *data)
1515 {
1516   gdouble w, h, top, bottom, left, right;
1517   GtkTreeSelection *selection;
1518   GtkTreeIter iter;
1519   GtkPageSetup *page_setup;
1520   GtkPaperSize *paper_size;
1521
1522   if (data->non_user_change)
1523     return;
1524   
1525   selection = gtk_tree_view_get_selection (GTK_TREE_VIEW (data->treeview));
1526
1527   if (gtk_tree_selection_get_selected (selection, NULL, &iter))
1528     {
1529       gtk_tree_model_get (GTK_TREE_MODEL (data->dialog->priv->custom_paper_list), &iter, 0, &page_setup, -1);
1530
1531       w = unit_widget_get (data->width_widget);
1532       h = unit_widget_get (data->height_widget);
1533
1534       paper_size = gtk_page_setup_get_paper_size (page_setup);
1535       gtk_paper_size_set_size (paper_size, w, h, GTK_UNIT_MM);
1536       
1537       top = unit_widget_get (data->top_widget);
1538       bottom = unit_widget_get (data->bottom_widget);
1539       left = unit_widget_get (data->left_widget);
1540       right = unit_widget_get (data->right_widget);
1541
1542       gtk_page_setup_set_top_margin (page_setup, top, GTK_UNIT_MM);
1543       gtk_page_setup_set_bottom_margin (page_setup, bottom, GTK_UNIT_MM);
1544       gtk_page_setup_set_left_margin (page_setup, left, GTK_UNIT_MM);
1545       gtk_page_setup_set_right_margin (page_setup, right, GTK_UNIT_MM);
1546       
1547       g_object_unref (page_setup);
1548     }
1549 }
1550
1551 static gboolean
1552 custom_paper_name_used (CustomPaperDialog *data, 
1553                         const gchar       *name)
1554 {
1555   GtkTreeModel *model;
1556   GtkTreeIter iter;
1557   GtkPageSetup *page_setup;
1558   GtkPaperSize *paper_size;
1559   
1560   model = gtk_tree_view_get_model (GTK_TREE_VIEW (data->treeview));
1561           
1562   if (gtk_tree_model_get_iter_first (model, &iter))
1563     {
1564       do
1565         {
1566           gtk_tree_model_get (model, &iter, 0, &page_setup, -1);
1567           paper_size = gtk_page_setup_get_paper_size (page_setup);
1568           if (strcmp (name,
1569                       gtk_paper_size_get_name (paper_size)) == 0)
1570             {
1571               g_object_unref (page_setup);
1572               return TRUE;
1573             }
1574           g_object_unref (page_setup);
1575         } while (gtk_tree_model_iter_next (model, &iter));
1576     }
1577   
1578   return FALSE;
1579 }
1580
1581 static void
1582 add_custom_paper (CustomPaperDialog *data)
1583 {
1584   GtkListStore *store;
1585   GtkPageSetup *page_setup;
1586   GtkPaperSize *paper_size;
1587   GtkTreeSelection *selection;
1588   GtkTreePath *path;
1589   GtkTreeIter iter;
1590   gchar *name;
1591   gint i;
1592   
1593   selection = gtk_tree_view_get_selection (GTK_TREE_VIEW (data->treeview));
1594   store = data->dialog->priv->custom_paper_list;
1595
1596   i = 1;
1597   name = NULL;
1598   do
1599     {
1600       g_free (name);
1601       name = g_strdup_printf (_("Custom Size %d"), i);
1602       i++;
1603     } while (custom_paper_name_used (data, name));
1604
1605   page_setup = gtk_page_setup_new ();
1606   paper_size = gtk_paper_size_new_custom (name, name,
1607                                           gtk_page_setup_get_paper_width (page_setup, GTK_UNIT_MM),
1608                                           gtk_page_setup_get_paper_height (page_setup, GTK_UNIT_MM),
1609                                           GTK_UNIT_MM);
1610   gtk_page_setup_set_paper_size (page_setup, paper_size);
1611   gtk_paper_size_free (paper_size);
1612
1613   gtk_list_store_append (store, &iter);
1614   gtk_list_store_set (store, &iter, 0, page_setup, -1);
1615   g_object_unref (page_setup);
1616
1617   gtk_tree_selection_select_iter (selection, &iter);
1618   path = gtk_tree_model_get_path (GTK_TREE_MODEL (store), &iter);
1619   gtk_widget_grab_focus (data->treeview);
1620   gtk_tree_view_set_cursor (GTK_TREE_VIEW (data->treeview), path,
1621                             data->text_column, TRUE);
1622   gtk_tree_path_free (path);
1623   g_free (name);
1624 }
1625
1626 static void
1627 remove_custom_paper (CustomPaperDialog *data)
1628 {
1629   GtkTreeSelection *selection;
1630   GtkTreeIter iter;
1631   GtkListStore *store;
1632   
1633   selection = gtk_tree_view_get_selection (GTK_TREE_VIEW (data->treeview));
1634   store = data->dialog->priv->custom_paper_list;
1635
1636   if (gtk_tree_selection_get_selected (selection, NULL, &iter))
1637     {
1638       GtkTreePath *path = gtk_tree_model_get_path (GTK_TREE_MODEL (store), &iter);
1639       gtk_list_store_remove (store, &iter);
1640       
1641       if (gtk_tree_model_get_iter (GTK_TREE_MODEL (store), &iter, path))
1642         gtk_tree_selection_select_iter (selection, &iter);
1643       else if (gtk_tree_path_prev (path) && gtk_tree_model_get_iter (GTK_TREE_MODEL (store), &iter, path))
1644         gtk_tree_selection_select_iter (selection, &iter);
1645       
1646       gtk_tree_path_free (path);
1647     }
1648 }
1649
1650 static void
1651 set_margins_from_printer (CustomPaperDialog *data,
1652                           GtkPrinter        *printer)
1653 {
1654   gdouble top, bottom, left, right;
1655
1656   top = bottom = left = right = 0;
1657   _gtk_printer_get_hard_margins (printer, &top, &bottom, &left, &right);
1658   
1659   data->non_user_change = TRUE;
1660   unit_widget_set (data->top_widget, _gtk_print_convert_to_mm (top, GTK_UNIT_POINTS));
1661   unit_widget_set (data->bottom_widget, _gtk_print_convert_to_mm (bottom, GTK_UNIT_POINTS));
1662   unit_widget_set (data->left_widget, _gtk_print_convert_to_mm (left, GTK_UNIT_POINTS));
1663   unit_widget_set (data->right_widget, _gtk_print_convert_to_mm (right, GTK_UNIT_POINTS));
1664   data->non_user_change = FALSE;
1665
1666   /* Only send one change */
1667   unit_widget_changed (data);
1668 }
1669
1670 static void
1671 get_margins_finished_callback (GtkPrinter        *printer,
1672                                gboolean           success,
1673                                CustomPaperDialog *data)
1674 {
1675   g_signal_handler_disconnect (data->request_details_printer,
1676                                data->request_details_tag);
1677   g_object_unref (data->request_details_printer);
1678   data->request_details_tag = 0;
1679   data->request_details_printer = NULL;
1680   
1681   if (success)
1682     set_margins_from_printer (data, printer);
1683
1684   gtk_combo_box_set_active (GTK_COMBO_BOX (data->printer_combo), 0);
1685 }
1686
1687 static void
1688 margins_from_printer_changed (CustomPaperDialog *data)
1689 {
1690   GtkTreeIter iter;
1691   GtkComboBox *combo;
1692   GtkPrinter *printer;
1693
1694   combo = GTK_COMBO_BOX (data->printer_combo);
1695
1696   if (data->request_details_tag)
1697     {
1698       g_signal_handler_disconnect (data->request_details_printer,
1699                                    data->request_details_tag);
1700       g_object_unref (data->request_details_printer);
1701       data->request_details_printer = NULL;
1702       data->request_details_tag = 0;
1703     }
1704   
1705   if (gtk_combo_box_get_active_iter  (combo, &iter))
1706     {
1707       gtk_tree_model_get (gtk_combo_box_get_model (combo), &iter,
1708                           PRINTER_LIST_COL_PRINTER, &printer, -1);
1709
1710       if (printer)
1711         {
1712           if (gtk_printer_has_details (printer))
1713             {
1714               set_margins_from_printer (data, printer);
1715               gtk_combo_box_set_active (combo, 0);
1716             }
1717           else
1718             {
1719               data->request_details_printer = g_object_ref (printer);
1720               data->request_details_tag =
1721                 g_signal_connect (printer, "details-acquired",
1722                                   G_CALLBACK (get_margins_finished_callback), data);
1723               gtk_printer_request_details (printer);
1724             }
1725
1726           g_object_unref (printer);
1727         }
1728     }
1729 }
1730
1731
1732 static void
1733 custom_paper_dialog_free (gpointer p)
1734 {
1735   CustomPaperDialog *data = p;
1736   GtkPageSetupUnixDialogPrivate *priv = data->dialog->priv;
1737
1738   g_signal_handler_disconnect (priv->printer_list, data->printer_inserted_tag);
1739   g_signal_handler_disconnect (priv->printer_list, data->printer_removed_tag);
1740
1741   if (data->request_details_tag)
1742     {
1743       g_signal_handler_disconnect (data->request_details_printer,
1744                                    data->request_details_tag);
1745       g_object_unref (data->request_details_printer);
1746       data->request_details_printer = NULL;
1747       data->request_details_tag = 0;
1748     }
1749   
1750   g_free (data);
1751 }
1752
1753 static void
1754 custom_size_name_edited (GtkCellRenderer   *cell,
1755                          gchar             *path_string,
1756                          gchar             *new_text,
1757                          CustomPaperDialog *data)
1758 {
1759   GtkTreePath *path;
1760   GtkTreeIter iter;
1761   GtkListStore *store;
1762   GtkPageSetup *page_setup;
1763   GtkPaperSize *paper_size;
1764
1765   store = data->dialog->priv->custom_paper_list;
1766   path = gtk_tree_path_new_from_string (path_string);
1767   gtk_tree_model_get_iter (GTK_TREE_MODEL (store), &iter, path);
1768   gtk_tree_model_get (GTK_TREE_MODEL (store), &iter, 0, &page_setup, -1);
1769   gtk_tree_path_free (path);
1770
1771   paper_size = gtk_paper_size_new_custom (new_text, new_text,
1772                                           gtk_page_setup_get_paper_width (page_setup, GTK_UNIT_MM),
1773                                           gtk_page_setup_get_paper_height (page_setup, GTK_UNIT_MM),
1774                                           GTK_UNIT_MM);
1775   gtk_page_setup_set_paper_size (page_setup, paper_size);
1776   gtk_paper_size_free (paper_size);
1777   
1778   g_object_unref (page_setup);
1779 }
1780
1781 static void
1782 custom_name_func (GtkTreeViewColumn *tree_column,
1783                   GtkCellRenderer   *cell,
1784                   GtkTreeModel      *tree_model,
1785                   GtkTreeIter       *iter,
1786                   gpointer           data)
1787 {
1788   GtkPageSetup *page_setup;
1789   GtkPaperSize *paper_size;
1790
1791   gtk_tree_model_get (tree_model, iter, 0, &page_setup, -1);
1792   if (page_setup)
1793     {
1794       paper_size = gtk_page_setup_get_paper_size (page_setup);
1795       g_object_set (cell, "text",  gtk_paper_size_get_display_name (paper_size), NULL);
1796       g_object_unref (page_setup);
1797     }
1798 }
1799
1800 static void
1801 custom_paper_dialog_response_cb (GtkWidget         *custom_dialog,
1802                                  gint               response,
1803                                  CustomPaperDialog *data)
1804 {
1805   GtkPageSetupUnixDialog *dialog = data->dialog;
1806   GtkPageSetupUnixDialogPrivate *priv = dialog->priv;
1807
1808   save_custom_papers (priv->custom_paper_list);
1809
1810   /* Update printer page list */
1811   printer_changed_callback (GTK_COMBO_BOX (priv->printer_combo), dialog);
1812
1813   gtk_widget_destroy (custom_dialog);
1814 }
1815
1816 static void
1817 show_custom_paper_dialog (GtkPageSetupUnixDialog *ps_dialog)
1818 {
1819   GtkPageSetupUnixDialogPrivate *priv = ps_dialog->priv;
1820   GtkWidget *custom_dialog, *image, *table, *label, *widget, *frame, *combo;
1821   GtkWidget *hbox, *vbox, *treeview, *scrolled, *button_box, *button;
1822   GtkDialog *dialog;
1823   GtkCellRenderer *cell;
1824   GtkTreeViewColumn *column;
1825   GtkTreeIter iter;
1826   GtkTreeSelection *selection;
1827   CustomPaperDialog *data;
1828   GtkUnit user_units;
1829   
1830   custom_dialog = gtk_dialog_new_with_buttons (_("Manage Custom Sizes"),
1831                                                GTK_WINDOW (ps_dialog),
1832                                                GTK_DIALOG_MODAL | GTK_DIALOG_DESTROY_WITH_PARENT | GTK_DIALOG_NO_SEPARATOR,
1833                                                GTK_STOCK_CLOSE, GTK_RESPONSE_CLOSE,
1834                                                NULL);
1835
1836   dialog = GTK_DIALOG (custom_dialog);
1837
1838   data = g_new0 (CustomPaperDialog, 1);
1839   data->dialog = ps_dialog;
1840   g_object_set_data_full (G_OBJECT (custom_dialog), "custom-dialog", data,
1841                           custom_paper_dialog_free);
1842   g_signal_connect (dialog, "response",
1843                     G_CALLBACK (custom_paper_dialog_response_cb), data);
1844
1845   gtk_dialog_set_has_separator (dialog, FALSE);
1846   gtk_container_set_border_width (GTK_CONTAINER (dialog), 5);
1847   gtk_box_set_spacing (GTK_BOX (dialog->vbox), 2); /* 2 * 5 + 2 = 12 */
1848   gtk_container_set_border_width (GTK_CONTAINER (dialog->action_area), 5);
1849   gtk_box_set_spacing (GTK_BOX (dialog->action_area), 6);
1850
1851   hbox = gtk_hbox_new (FALSE, 18);
1852   gtk_container_set_border_width (GTK_CONTAINER (hbox), 5);
1853   gtk_box_pack_start (GTK_BOX (dialog->vbox), hbox, TRUE, TRUE, 0);
1854   gtk_widget_show (hbox);
1855
1856   vbox = gtk_vbox_new (FALSE, 6);
1857   gtk_box_pack_start (GTK_BOX (hbox), vbox, TRUE, TRUE, 0);
1858   gtk_widget_show (vbox);
1859   
1860   scrolled = gtk_scrolled_window_new (NULL, NULL);
1861   gtk_scrolled_window_set_policy (GTK_SCROLLED_WINDOW (scrolled),
1862                                   GTK_POLICY_AUTOMATIC,
1863                                   GTK_POLICY_AUTOMATIC);
1864   gtk_scrolled_window_set_shadow_type (GTK_SCROLLED_WINDOW (scrolled),
1865                                        GTK_SHADOW_IN);
1866   gtk_box_pack_start (GTK_BOX (vbox), scrolled, TRUE, TRUE, 0);
1867   gtk_widget_show (scrolled);
1868
1869   treeview = gtk_tree_view_new_with_model (GTK_TREE_MODEL (priv->custom_paper_list));
1870   data->treeview = treeview;
1871   gtk_tree_view_set_headers_visible (GTK_TREE_VIEW (treeview), FALSE);
1872   gtk_widget_set_size_request (treeview, 140, -1);
1873   
1874   selection = gtk_tree_view_get_selection (GTK_TREE_VIEW (treeview));
1875   gtk_tree_selection_set_mode (selection, GTK_SELECTION_BROWSE);
1876   g_signal_connect (selection, "changed", G_CALLBACK (selected_custom_paper_changed), data);
1877
1878   cell = gtk_cell_renderer_text_new ();
1879   g_object_set (cell, "editable", TRUE, NULL);
1880   g_signal_connect (cell, "edited", 
1881                     G_CALLBACK (custom_size_name_edited), data);
1882   data->text_column = column =
1883     gtk_tree_view_column_new_with_attributes ("paper", cell,
1884                                               NULL);
1885   gtk_tree_view_column_set_cell_data_func  (column, cell, custom_name_func, NULL, NULL);
1886   
1887   gtk_tree_view_append_column (GTK_TREE_VIEW (treeview), column);
1888
1889   gtk_container_add (GTK_CONTAINER (scrolled), treeview);
1890   gtk_widget_show (treeview);
1891
1892   button_box = gtk_hbox_new (FALSE, 6);
1893   gtk_box_pack_start (GTK_BOX (vbox), button_box, FALSE, FALSE, 0);
1894   gtk_widget_show (button_box);
1895
1896   button = gtk_button_new ();
1897   image = gtk_image_new_from_stock (GTK_STOCK_ADD, GTK_ICON_SIZE_BUTTON);
1898   gtk_widget_show (image);
1899   gtk_container_add (GTK_CONTAINER (button), image);
1900   gtk_box_pack_start (GTK_BOX (button_box), button, FALSE, FALSE, 0);
1901   gtk_widget_show (button);
1902
1903   g_signal_connect_swapped (button, "clicked", G_CALLBACK (add_custom_paper), data);
1904   
1905   button = gtk_button_new ();
1906   image = gtk_image_new_from_stock (GTK_STOCK_REMOVE, GTK_ICON_SIZE_BUTTON);
1907   gtk_widget_show (image);
1908   gtk_container_add (GTK_CONTAINER (button), image);
1909   gtk_box_pack_start (GTK_BOX (button_box), button, FALSE, FALSE, 0);
1910   gtk_widget_show (button);
1911
1912   g_signal_connect_swapped (button, "clicked", G_CALLBACK (remove_custom_paper), data);
1913
1914   user_units = get_default_user_units ();
1915   
1916   vbox = gtk_vbox_new (FALSE, 18);
1917   data->values_box = vbox;
1918   gtk_box_pack_start (GTK_BOX (hbox), vbox, TRUE, TRUE, 0);
1919   gtk_widget_show (vbox);
1920   
1921   table = gtk_table_new (2, 2, FALSE);
1922   
1923   gtk_table_set_row_spacings (GTK_TABLE (table), 6);
1924   gtk_table_set_col_spacings (GTK_TABLE (table), 12);
1925
1926   label = gtk_label_new_with_mnemonic (_("_Width:"));
1927   gtk_misc_set_alignment (GTK_MISC (label), 0.0, 0.5);
1928   gtk_widget_show (label);
1929   gtk_table_attach (GTK_TABLE (table), label,
1930                     0, 1, 0, 1, GTK_FILL, 0, 0, 0);
1931   
1932   widget = new_unit_widget (data, user_units, label);
1933   data->width_widget = widget;
1934   gtk_table_attach (GTK_TABLE (table), widget,
1935                     1, 2, 0, 1, GTK_FILL, 0, 0, 0);
1936   gtk_widget_show (widget);
1937
1938   label = gtk_label_new_with_mnemonic (_("_Height:"));
1939   gtk_misc_set_alignment (GTK_MISC (label), 0.0, 0.5);
1940   gtk_widget_show (label);
1941   gtk_table_attach (GTK_TABLE (table), label,
1942                     0, 1, 1, 2, GTK_FILL, 0, 0, 0);
1943   
1944   widget = new_unit_widget (data, user_units, label);
1945   data->height_widget = widget;
1946   gtk_table_attach (GTK_TABLE (table), widget,
1947                     1, 2, 1, 2, GTK_FILL, 0, 0, 0);
1948   gtk_widget_show (widget);
1949
1950   frame = wrap_in_frame (_("Paper Size"), table);
1951   gtk_widget_show (table);
1952   gtk_box_pack_start (GTK_BOX (vbox), frame, FALSE, FALSE, 0);
1953   gtk_widget_show (frame);
1954   
1955
1956   table = gtk_table_new (5, 2, FALSE);
1957   gtk_table_set_row_spacings (GTK_TABLE (table), 6);
1958   gtk_table_set_col_spacings (GTK_TABLE (table), 12);
1959
1960   label = gtk_label_new_with_mnemonic (_("_Top:"));
1961   gtk_misc_set_alignment (GTK_MISC (label), 0.0, 0.5);
1962   gtk_table_attach (GTK_TABLE (table), label,
1963                     0, 1, 0, 1, GTK_FILL, 0, 0, 0);
1964   gtk_widget_show (label);
1965
1966   widget = new_unit_widget (data, user_units, label);
1967   data->top_widget = widget;
1968   gtk_table_attach (GTK_TABLE (table), widget,
1969                     1, 2, 0, 1, GTK_FILL, 0, 0, 0);
1970   gtk_widget_show (widget);
1971   
1972   label = gtk_label_new_with_mnemonic (_("_Bottom:"));
1973   gtk_misc_set_alignment (GTK_MISC (label), 0.0, 0.5);
1974   gtk_table_attach (GTK_TABLE (table), label,
1975                     0, 1 , 1, 2, GTK_FILL, 0, 0, 0);
1976   gtk_widget_show (label);
1977
1978   widget = new_unit_widget (data, user_units, label);
1979   data->bottom_widget = widget;
1980   gtk_table_attach (GTK_TABLE (table), widget,
1981                     1, 2, 1, 2, GTK_FILL, 0, 0, 0);
1982   gtk_widget_show (widget);
1983
1984   label = gtk_label_new_with_mnemonic (_("_Left:"));
1985   gtk_misc_set_alignment (GTK_MISC (label), 0.0, 0.5);
1986   gtk_table_attach (GTK_TABLE (table), label,
1987                     0, 1, 2, 3, GTK_FILL, 0, 0, 0);
1988   gtk_widget_show (label);
1989   
1990   widget = new_unit_widget (data, user_units, label);
1991   data->left_widget = widget;
1992   gtk_table_attach (GTK_TABLE (table), widget,
1993                     1, 2, 2, 3, GTK_FILL, 0, 0, 0);
1994   gtk_widget_show (widget);
1995
1996   label = gtk_label_new_with_mnemonic (_("_Right:"));
1997   gtk_misc_set_alignment (GTK_MISC (label), 0.0, 0.5);
1998   gtk_table_attach (GTK_TABLE (table), label,
1999                     0, 1, 3, 4, GTK_FILL, 0, 0, 0);
2000   gtk_widget_show (label);
2001
2002   widget = new_unit_widget (data, user_units, label);
2003   data->right_widget = widget;
2004   gtk_table_attach (GTK_TABLE (table), widget,
2005                     1, 2, 3, 4, GTK_FILL, 0, 0, 0);
2006   gtk_widget_show (widget);
2007
2008   hbox = gtk_hbox_new (FALSE, 0);
2009   gtk_table_attach (GTK_TABLE (table), hbox,
2010                     0, 2, 4, 5, GTK_FILL | GTK_EXPAND, 0, 0, 0);
2011   gtk_widget_show (hbox);
2012   
2013   combo = gtk_combo_box_new_with_model (GTK_TREE_MODEL (priv->printer_list));
2014   data->printer_combo = combo;
2015
2016   data->printer_inserted_tag =
2017     g_signal_connect_swapped (priv->printer_list, "row-inserted",
2018                               G_CALLBACK (update_combo_sensitivity_from_printers), data);
2019   data->printer_removed_tag =
2020     g_signal_connect_swapped (priv->printer_list, "row-deleted",
2021                               G_CALLBACK (update_combo_sensitivity_from_printers), data);
2022   update_combo_sensitivity_from_printers (data);
2023   
2024   cell = gtk_cell_renderer_text_new ();
2025   gtk_cell_layout_pack_start (GTK_CELL_LAYOUT (combo), cell, TRUE);
2026   gtk_cell_layout_set_cell_data_func (GTK_CELL_LAYOUT (combo), cell,
2027                                       custom_paper_printer_data_func,
2028                                       NULL, NULL);
2029
2030   gtk_combo_box_set_active (GTK_COMBO_BOX (combo), 0);
2031   gtk_box_pack_start (GTK_BOX (hbox), combo, FALSE, FALSE, 0);
2032   gtk_widget_show (combo);
2033
2034   g_signal_connect_swapped (combo, "changed",
2035                             G_CALLBACK (margins_from_printer_changed), data);
2036   
2037   frame = wrap_in_frame (_("Paper Margins"), table);
2038   gtk_widget_show (table);
2039   gtk_box_pack_start (GTK_BOX (vbox), frame, FALSE, FALSE, 0);
2040   gtk_widget_show (frame);
2041
2042   update_custom_widgets_from_list (data);
2043
2044   /* If no custom sizes, add one */
2045   if (!gtk_tree_model_get_iter_first (GTK_TREE_MODEL (priv->custom_paper_list),
2046                                       &iter))
2047     {
2048       /* Need to realize treeview so we can start the rename */
2049       gtk_widget_realize (treeview);
2050       add_custom_paper (data);
2051     }
2052
2053   gtk_window_present (GTK_WINDOW (dialog));
2054 }
2055
2056
2057 #define __GTK_PAGE_SETUP_UNIX_DIALOG_C__
2058 #include "gtkaliasdef.c"