]> Pileus Git - ~andy/gtk/blob - gtk/gtkprintunixdialog.c
Added new symbols
[~andy/gtk] / gtk / gtkprintunixdialog.c
1 /* GtkPrintUnixDialog
2  * Copyright (C) 2006 John (J5) Palmieri  <johnp@redhat.com>
3  * Copyright (C) 2006 Alexander Larsson <alexl@redhat.com>
4  *
5  * This library is free software; you can redistribute it and/or
6  * modify it under the terms of the GNU Lesser General Public
7  * License as published by the Free Software Foundation; either
8  * version 2 of the License, or (at your option) any later version.
9  *
10  * This library is distributed in the hope that it will be useful,
11  * but WITHOUT ANY WARRANTY; without even the implied warranty of
12  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
13  * Lesser General Public License for more details.
14  *
15  * You should have received a copy of the GNU Lesser General Public
16  * License along with this library; if not, write to the
17  * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
18  * Boston, MA 02111-1307, USA.
19  */
20
21 #include "config.h"
22 #include <stdlib.h>
23 #include <string.h>
24 #include <stdio.h>
25 #include <math.h>
26
27 #include "gtkintl.h"
28 #include "gtkprivate.h"
29
30 #include "gtkspinbutton.h"
31 #include "gtkcellrendererpixbuf.h"
32 #include "gtkcellrenderertext.h"
33 #include "gtkstock.h"
34 #include "gtkiconfactory.h"
35 #include "gtkimage.h"
36 #include "gtktreeselection.h"
37 #include "gtknotebook.h"
38 #include "gtkscrolledwindow.h"
39 #include "gtkcombobox.h"
40 #include "gtktogglebutton.h"
41 #include "gtkradiobutton.h"
42 #include "gtkdrawingarea.h"
43 #include "gtkvbox.h"
44 #include "gtktable.h"
45 #include "gtkframe.h"
46 #include "gtkalignment.h"
47 #include "gtklabel.h"
48
49 #include "gtkprintbackend.h"
50 #include "gtkprintunixdialog.h"
51 #include "gtkprinteroptionwidget.h"
52 #include "gtkalias.h"
53
54 #define EXAMPLE_PAGE_AREA_SIZE 140
55
56 #define GTK_PRINT_UNIX_DIALOG_GET_PRIVATE(o)  \
57    (G_TYPE_INSTANCE_GET_PRIVATE ((o), GTK_TYPE_PRINT_UNIX_DIALOG, GtkPrintUnixDialogPrivate))
58
59 static void gtk_print_unix_dialog_destroy      (GtkPrintUnixDialog *dialog);
60 static void gtk_print_unix_dialog_finalize     (GObject            *object);
61 static void gtk_print_unix_dialog_set_property (GObject            *object,
62                                                 guint               prop_id,
63                                                 const GValue       *value,
64                                                 GParamSpec         *pspec);
65 static void gtk_print_unix_dialog_get_property (GObject            *object,
66                                                 guint               prop_id,
67                                                 GValue             *value,
68                                                 GParamSpec         *pspec);
69 static void gtk_print_unix_dialog_style_set    (GtkWidget          *widget,
70                                                 GtkStyle           *previous_style);
71 static void populate_dialog                    (GtkPrintUnixDialog *dialog);
72 static void unschedule_idle_mark_conflicts     (GtkPrintUnixDialog *dialog);
73 static void selected_printer_changed           (GtkTreeSelection   *selection,
74                                                 GtkPrintUnixDialog *dialog);
75 static void clear_per_printer_ui               (GtkPrintUnixDialog *dialog);
76 static void printer_added_cb                   (GtkPrintBackend    *backend,
77                                                 GtkPrinter         *printer,
78                                                 GtkPrintUnixDialog *dialog);
79 static void printer_removed_cb                 (GtkPrintBackend    *backend,
80                                                 GtkPrinter         *printer,
81                                                 GtkPrintUnixDialog *dialog);
82 static void printer_status_cb                  (GtkPrintBackend    *backend,
83                                                 GtkPrinter         *printer,
84                                                 GtkPrintUnixDialog *dialog);
85
86 enum {
87   PROP_0,
88   PROP_PAGE_SETUP,
89   PROP_CURRENT_PAGE,
90   PROP_PRINT_SETTINGS,
91   PROP_SELECTED_PRINTER
92 };
93
94 enum {
95   PRINTER_LIST_COL_ICON,
96   PRINTER_LIST_COL_NAME,
97   PRINTER_LIST_COL_STATE,
98   PRINTER_LIST_COL_JOBS,
99   PRINTER_LIST_COL_LOCATION,
100   PRINTER_LIST_COL_PRINTER_OBJ,
101   PRINTER_LIST_N_COLS
102 };
103
104 #define _EXTENTION_POINT_MAIN_PAGE_CUSTOM_INPUT "gtk-main-page-custom-input"
105
106 struct GtkPrintUnixDialogPrivate
107 {
108   GtkWidget *notebook;
109
110   GtkWidget *printer_treeview;
111   
112   GtkTreeModel *printer_list;
113   GtkTreeModelFilter *printer_list_filter;
114
115   GtkPageSetup *page_setup;
116
117   GtkWidget *all_pages_radio;
118   GtkWidget *current_page_radio;
119   GtkWidget *page_range_radio;
120   GtkWidget *page_range_entry;
121   
122   GtkWidget *copies_spin;
123   GtkWidget *collate_check;
124   GtkWidget *reverse_check;
125   GtkWidget *collate_image;
126   GtkWidget *page_layout_preview;
127   GtkWidget *scale_spin;
128   GtkWidget *page_set_combo;
129   GtkWidget *print_now_radio;
130   GtkWidget *print_at_radio;
131   GtkWidget *print_at_entry;
132   GtkWidget *print_hold_radio;
133   gboolean updating_print_at;
134   GtkPrinterOptionWidget *pages_per_sheet;
135   GtkPrinterOptionWidget *duplex;
136   GtkPrinterOptionWidget *paper_type;
137   GtkPrinterOptionWidget *paper_source;
138   GtkPrinterOptionWidget *output_tray;
139   GtkPrinterOptionWidget *job_prio;
140   GtkPrinterOptionWidget *billing_info;
141   GtkPrinterOptionWidget *cover_before;
142   GtkPrinterOptionWidget *cover_after;
143
144   GtkWidget *conflicts_widget;
145
146   GtkWidget *job_page;
147   GtkWidget *finishing_table;
148   GtkWidget *finishing_page;
149   GtkWidget *image_quality_table;
150   GtkWidget *image_quality_page;
151   GtkWidget *color_table;
152   GtkWidget *color_page;
153
154   GtkWidget *advanced_vbox;
155   GtkWidget *advanced_page;
156
157   GHashTable *extension_points;  
158
159   /* These are set initially on selected printer (either default printer, printer
160    * taken from set settings, or user-selected), but when any setting is changed
161    * by the user it is cleared */
162   GtkPrintSettings *initial_settings;
163   
164   /* This is the initial printer set by set_settings. We look for it in the
165    * added printers. We clear this whenever the user manually changes
166    * to another printer, when the user changes a setting or when we find
167    * this printer */
168   char *waiting_for_printer;
169   gboolean internal_printer_change;
170   
171   GList *print_backends;
172   
173   GtkPrinter *current_printer;
174   guint request_details_tag;
175   GtkPrinterOptionSet *options;
176   gulong options_changed_handler;
177   gulong mark_conflicts_id;
178
179   char *format_for_printer;
180   
181   gint current_page;
182 };
183
184 G_DEFINE_TYPE (GtkPrintUnixDialog, gtk_print_unix_dialog, GTK_TYPE_DIALOG);
185
186 static gboolean
187 is_default_printer (GtkPrintUnixDialog *dialog,
188                     GtkPrinter *printer)
189 {
190   GtkPrintUnixDialogPrivate *priv = dialog->priv;
191
192   if (priv->format_for_printer)
193     return strcmp (priv->format_for_printer,
194                    gtk_printer_get_name (printer)) == 0;
195  else
196    return gtk_printer_is_default (printer);
197 }
198
199 static void
200 gtk_print_unix_dialog_class_init (GtkPrintUnixDialogClass *class)
201 {
202   GObjectClass *object_class;
203   GtkWidgetClass *widget_class;
204
205   object_class = (GObjectClass *) class;
206   widget_class = (GtkWidgetClass *) class;
207
208   object_class->finalize = gtk_print_unix_dialog_finalize;
209   object_class->set_property = gtk_print_unix_dialog_set_property;
210   object_class->get_property = gtk_print_unix_dialog_get_property;
211
212   widget_class->style_set = gtk_print_unix_dialog_style_set;
213
214   g_object_class_install_property (object_class,
215                                    PROP_PAGE_SETUP,
216                                    g_param_spec_object ("page-setup",
217                                                         P_("Page Setup"),
218                                                         P_("The GtkPageSetup to use"),
219                                                         GTK_TYPE_PAGE_SETUP,
220                                                         GTK_PARAM_READWRITE));
221
222   g_object_class_install_property (object_class,
223                                    PROP_CURRENT_PAGE,
224                                    g_param_spec_int ("current-page",
225                                                      P_("Current Page"),
226                                                      P_("The current page in the document"),
227                                                      -1,
228                                                      G_MAXINT,
229                                                      -1,
230                                                      GTK_PARAM_READWRITE));
231
232   g_object_class_install_property (object_class,
233                                    PROP_PRINT_SETTINGS,
234                                    g_param_spec_object ("print-settings",
235                                                         P_("Print Settings"),
236                                                         P_("The GtkPrintSettings used for initializing the dialog"),
237                                                         GTK_TYPE_PRINT_SETTINGS,
238                                                         GTK_PARAM_READWRITE));
239
240   g_object_class_install_property (object_class,
241                                    PROP_SELECTED_PRINTER,
242                                    g_param_spec_object ("selected-printer",
243                                                         P_("Selected Printer"),
244                                                         P_("The GtkPrinter which which is selected"),
245                                                         GTK_TYPE_PRINTER,
246                                                         GTK_PARAM_READABLE));
247   
248   g_type_class_add_private (class, sizeof (GtkPrintUnixDialogPrivate));  
249 }
250
251 static void
252 gtk_print_unix_dialog_init (GtkPrintUnixDialog *dialog)
253 {
254   GtkPrintUnixDialogPrivate *priv = dialog->priv;
255
256   priv = dialog->priv = GTK_PRINT_UNIX_DIALOG_GET_PRIVATE (dialog); 
257   priv->print_backends = NULL;
258   priv->current_page = -1;
259
260   priv->extension_points = g_hash_table_new (g_str_hash,
261                                              g_str_equal);
262
263   priv->page_setup = gtk_page_setup_new ();
264
265   populate_dialog (dialog);
266
267   g_signal_connect (dialog, 
268                     "destroy", 
269                     (GCallback) gtk_print_unix_dialog_destroy, 
270                     NULL);
271
272   gtk_dialog_add_buttons (GTK_DIALOG (dialog), 
273                           GTK_STOCK_CANCEL, GTK_RESPONSE_CANCEL,
274                           GTK_STOCK_PRINT, GTK_RESPONSE_OK,
275                           NULL);
276
277   gtk_dialog_set_default_response (GTK_DIALOG (dialog), GTK_RESPONSE_OK);
278   gtk_dialog_set_response_sensitive (GTK_DIALOG (dialog), GTK_RESPONSE_OK, FALSE);
279 }
280
281 static void
282 gtk_print_unix_dialog_destroy (GtkPrintUnixDialog *dialog)
283 {
284   /* Make sure we don't destroy custom widgets owned by the backends */
285   clear_per_printer_ui (dialog);  
286 }
287
288 static void
289 gtk_print_unix_dialog_finalize (GObject *object)
290 {
291   GtkPrintUnixDialog *dialog = GTK_PRINT_UNIX_DIALOG (object);
292   GtkPrintUnixDialogPrivate *priv = dialog->priv;
293   GtkPrintBackend *backend;
294   GList *node;
295
296   unschedule_idle_mark_conflicts (dialog);
297
298   if (priv->request_details_tag)
299     {
300       g_source_remove (priv->request_details_tag);
301       priv->request_details_tag = 0;
302     }
303   
304   if (priv->current_printer)
305     {
306       g_object_unref (priv->current_printer);
307       priv->current_printer = NULL;
308     }
309
310   if (priv->printer_list)
311     {
312       g_object_unref (priv->printer_list);
313       priv->printer_list = NULL;
314     }
315  
316   if (priv->printer_list_filter)
317     {
318       g_object_unref (priv->printer_list_filter);
319       priv->printer_list_filter = NULL;
320     }
321
322  
323   if (priv->options)
324     {
325       g_object_unref (priv->options);
326       priv->options = NULL;
327     }
328  
329   if (priv->extension_points)
330     {
331       g_hash_table_unref (priv->extension_points);
332       priv->extension_points = NULL;
333     }
334  
335   if (priv->page_setup)
336     {
337       g_object_unref (priv->page_setup);
338       priv->page_setup = NULL;
339     }
340
341   if (priv->initial_settings)
342     {
343       g_object_unref (priv->initial_settings);
344       priv->initial_settings = NULL;
345     }
346
347   g_free (priv->waiting_for_printer);
348   priv->waiting_for_printer = NULL;
349   
350   g_free (priv->format_for_printer);
351   priv->format_for_printer = NULL;
352
353   for (node = priv->print_backends; node != NULL; node = node->next)
354     {
355       backend = GTK_PRINT_BACKEND (node->data);
356
357       g_signal_handlers_disconnect_by_func (backend, printer_added_cb, dialog);
358       g_signal_handlers_disconnect_by_func (backend, printer_removed_cb, dialog);
359       g_signal_handlers_disconnect_by_func (backend, printer_status_cb, dialog);
360
361       gtk_print_backend_destroy (backend);
362       g_object_unref (backend);
363     }
364   
365   g_list_free (priv->print_backends);
366   priv->print_backends = NULL;
367   
368   G_OBJECT_CLASS (gtk_print_unix_dialog_parent_class)->finalize (object);
369 }
370
371 static void
372 printer_removed_cb (GtkPrintBackend    *backend, 
373                     GtkPrinter         *printer, 
374                     GtkPrintUnixDialog *dialog)
375 {
376   GtkPrintUnixDialogPrivate *priv = dialog->priv;
377   GtkTreeIter *iter;
378
379   iter = g_object_get_data (G_OBJECT (printer), "gtk-print-tree-iter");
380   gtk_list_store_remove (GTK_LIST_STORE (priv->printer_list), iter);
381 }
382
383 static void
384 printer_status_cb (GtkPrintBackend    *backend, 
385                    GtkPrinter         *printer, 
386                    GtkPrintUnixDialog *dialog)
387 {
388   GtkPrintUnixDialogPrivate *priv = dialog->priv;
389   GtkTreeIter *iter;
390
391   iter = g_object_get_data (G_OBJECT (printer), "gtk-print-tree-iter");
392
393   gtk_list_store_set (GTK_LIST_STORE (priv->printer_list), iter,
394                       PRINTER_LIST_COL_ICON, gtk_printer_get_icon_name (printer),
395                       PRINTER_LIST_COL_STATE, gtk_printer_get_state_message (printer),
396                       PRINTER_LIST_COL_JOBS, gtk_printer_get_job_count (printer),
397                       PRINTER_LIST_COL_LOCATION, gtk_printer_get_location (printer),
398                       -1);
399
400 }
401
402 static void
403 printer_added_cb (GtkPrintBackend    *backend, 
404                   GtkPrinter         *printer, 
405                   GtkPrintUnixDialog *dialog)
406 {
407   GtkPrintUnixDialogPrivate *priv = dialog->priv;
408   GtkTreeIter iter, filter_iter;
409   GtkTreeSelection *selection;
410
411   gtk_list_store_append (GTK_LIST_STORE (priv->printer_list), &iter);
412   
413   g_object_set_data_full (G_OBJECT (printer), 
414                          "gtk-print-tree-iter", 
415                           gtk_tree_iter_copy (&iter),
416                           (GDestroyNotify) gtk_tree_iter_free);
417
418   gtk_list_store_set (GTK_LIST_STORE (priv->printer_list), &iter,
419                       PRINTER_LIST_COL_ICON, gtk_printer_get_icon_name (printer),
420                       PRINTER_LIST_COL_NAME, gtk_printer_get_name (printer),
421                       PRINTER_LIST_COL_STATE, gtk_printer_get_state_message (printer),
422                       PRINTER_LIST_COL_JOBS, gtk_printer_get_job_count (printer),
423                       PRINTER_LIST_COL_LOCATION, gtk_printer_get_location (printer),
424                       PRINTER_LIST_COL_PRINTER_OBJ, printer,
425                       -1);
426
427   gtk_tree_model_filter_convert_child_iter_to_iter (priv->printer_list_filter,
428                                                     &filter_iter, &iter);
429   
430   selection = gtk_tree_view_get_selection (GTK_TREE_VIEW (priv->printer_treeview));
431   
432   if (priv->waiting_for_printer != NULL &&
433       strcmp (gtk_printer_get_name (printer),
434               priv->waiting_for_printer) == 0)
435     {
436       priv->internal_printer_change = TRUE;
437       gtk_tree_selection_select_iter (selection, &filter_iter);
438       priv->internal_printer_change = FALSE;
439       g_free (priv->waiting_for_printer);
440       priv->waiting_for_printer = NULL;
441     }
442   else if (is_default_printer (dialog, printer) &&
443            gtk_tree_selection_count_selected_rows (selection) == 0)
444     {
445       priv->internal_printer_change = TRUE;
446       gtk_tree_selection_select_iter (selection, &filter_iter);
447       priv->internal_printer_change = FALSE;
448     }
449 }
450
451 static void
452 printer_list_initialize (GtkPrintUnixDialog *dialog,
453                          GtkPrintBackend    *print_backend)
454 {
455   GList *list;
456   GList *node;
457
458   g_return_if_fail (print_backend != NULL);
459
460   g_signal_connect_object (print_backend, 
461                            "printer-added", 
462                            (GCallback) printer_added_cb, 
463                            G_OBJECT (dialog), 0);
464
465   g_signal_connect_object (print_backend, 
466                            "printer-removed", 
467                            (GCallback) printer_removed_cb, 
468                            G_OBJECT (dialog), 0);
469
470   g_signal_connect_object (print_backend, 
471                            "printer-status-changed", 
472                            (GCallback) printer_status_cb, 
473                            G_OBJECT (dialog), 0);
474
475   list = gtk_print_backend_get_printer_list (print_backend);
476
477   node = list;
478   while (node != NULL)
479     {
480       printer_added_cb (print_backend, node->data, dialog);
481       node = node->next;
482     }
483
484   g_list_free (list);
485 }
486
487 static void
488 load_print_backends (GtkPrintUnixDialog *dialog)
489 {
490   GtkPrintUnixDialogPrivate *priv = dialog->priv;
491   GList *node;
492
493   if (g_module_supported ())
494     priv->print_backends = gtk_print_backend_load_modules ();
495
496   for (node = priv->print_backends; node != NULL; node = node->next)
497     printer_list_initialize (dialog, GTK_PRINT_BACKEND (node->data));
498 }
499
500 static void
501 gtk_print_unix_dialog_set_property (GObject      *object,
502                                     guint         prop_id,
503                                     const GValue *value,
504                                     GParamSpec   *pspec)
505
506 {
507   GtkPrintUnixDialog *dialog = GTK_PRINT_UNIX_DIALOG (object);
508
509   switch (prop_id)
510     {
511     case PROP_PAGE_SETUP:
512       gtk_print_unix_dialog_set_page_setup (dialog, g_value_get_object (value));
513       break;
514     case PROP_CURRENT_PAGE:
515       gtk_print_unix_dialog_set_current_page (dialog, g_value_get_int (value));
516       break;
517     case PROP_PRINT_SETTINGS:
518       gtk_print_unix_dialog_set_settings (dialog, g_value_get_object (value));
519       break;
520     default:
521       G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
522       break;
523     }
524 }
525
526 static void
527 gtk_print_unix_dialog_get_property (GObject    *object,
528                                     guint       prop_id,
529                                     GValue     *value,
530                                     GParamSpec *pspec)
531 {
532   GtkPrintUnixDialog *dialog = GTK_PRINT_UNIX_DIALOG (object);
533   GtkPrintUnixDialogPrivate *priv = dialog->priv;
534
535   switch (prop_id)
536     {
537     case PROP_PAGE_SETUP:
538       g_value_set_object (value, priv->page_setup);
539       break;
540     case PROP_CURRENT_PAGE:
541       g_value_set_int (value, priv->current_page);
542       break;
543     case PROP_PRINT_SETTINGS:
544       g_value_set_object (value, gtk_print_unix_dialog_get_settings (dialog));
545       break;
546     case PROP_SELECTED_PRINTER:
547       g_value_set_object (value, priv->current_printer);
548       break;
549     default:
550       G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
551       break;
552     }
553 }
554
555 static gboolean
556 is_printer_active (GtkTreeModel       *model,
557                    GtkTreeIter        *iter,
558                    GtkPrintUnixDialog *dialog)
559 {
560   gboolean result;
561   GtkPrinter *printer;
562
563   gtk_tree_model_get (model,
564                       iter,
565                       PRINTER_LIST_COL_PRINTER_OBJ,
566                       &printer,
567                       -1);
568   
569   if (printer == NULL)
570     return FALSE;
571
572   result = gtk_printer_is_active (printer);
573
574   g_object_unref (printer);
575
576   return result;
577 }
578
579 static gint
580 default_printer_list_sort_func (GtkTreeModel *model,
581                                 GtkTreeIter  *a,
582                                 GtkTreeIter  *b,
583                                 gpointer      user_data)
584 {
585   gchar *a_name;
586   gchar *b_name;
587   GtkPrinter *a_printer;
588   GtkPrinter *b_printer;
589   gint result;
590
591   gtk_tree_model_get (model, a, 
592                       PRINTER_LIST_COL_NAME, &a_name, 
593                       PRINTER_LIST_COL_PRINTER_OBJ, &a_printer,
594                       -1);
595   gtk_tree_model_get (model, b, 
596                       PRINTER_LIST_COL_NAME, &b_name,
597                       PRINTER_LIST_COL_PRINTER_OBJ, &b_printer,
598                       -1);
599
600   if (a_printer == NULL && b_printer == NULL)
601     result = 0;
602   else if (a_printer == NULL)
603    result = G_MAXINT;
604   else if (b_printer == NULL)
605    result = G_MININT;
606   else if (gtk_printer_is_virtual (a_printer) && gtk_printer_is_virtual (b_printer))
607     result = 0;
608   else if (gtk_printer_is_virtual (a_printer) && !gtk_printer_is_virtual (b_printer))
609     result = G_MININT;
610   else if (!gtk_printer_is_virtual (a_printer) && gtk_printer_is_virtual (b_printer))
611     result = G_MAXINT;
612   else if (a_name == NULL && b_name == NULL)
613     result = 0;
614   else if (a_name == NULL && b_name != NULL)
615     result = 1;
616   else if (a_name != NULL && b_name == NULL)
617     result = -1;
618   else
619     result = g_ascii_strcasecmp (a_name, b_name);
620
621   g_free (a_name);
622   g_free (b_name);
623   g_object_unref (a_printer);
624   g_object_unref (b_printer);
625
626   return result;
627 }
628
629
630 static void
631 create_printer_list_model (GtkPrintUnixDialog *dialog)
632 {
633   GtkPrintUnixDialogPrivate *priv = dialog->priv;
634   GtkListStore *model;
635   GtkTreeSortable *sort;
636
637   model = gtk_list_store_new (PRINTER_LIST_N_COLS,
638                               G_TYPE_STRING,
639                               G_TYPE_STRING, 
640                               G_TYPE_STRING, 
641                               G_TYPE_INT, 
642                               G_TYPE_STRING,
643                               G_TYPE_OBJECT);
644
645   priv->printer_list = (GtkTreeModel *)model;
646   priv->printer_list_filter = (GtkTreeModelFilter *) gtk_tree_model_filter_new ((GtkTreeModel *)model,
647                                                                                         NULL);
648
649   gtk_tree_model_filter_set_visible_func (priv->printer_list_filter,
650                                           (GtkTreeModelFilterVisibleFunc) is_printer_active,
651                                           dialog,
652                                           NULL);
653
654   sort = GTK_TREE_SORTABLE (model);
655   gtk_tree_sortable_set_default_sort_func (sort,
656                                            default_printer_list_sort_func,
657                                            NULL,
658                                            NULL);
659  
660   gtk_tree_sortable_set_sort_column_id (sort,
661                                         GTK_TREE_SORTABLE_DEFAULT_SORT_COLUMN_ID,
662                                         GTK_SORT_ASCENDING);
663
664 }
665
666
667 static GtkWidget *
668 wrap_in_frame (const gchar *label, 
669                GtkWidget   *child)
670 {
671   GtkWidget *frame, *alignment, *label_widget;
672   char *bold_text;
673
674   label_widget = gtk_label_new ("");
675   gtk_misc_set_alignment (GTK_MISC (label_widget), 0.0, 0.5);
676   gtk_widget_show (label_widget);
677   
678   bold_text = g_markup_printf_escaped ("<b>%s</b>", label);
679   gtk_label_set_markup (GTK_LABEL (label_widget), bold_text);
680   g_free (bold_text);
681   
682   frame = gtk_vbox_new (FALSE, 6);
683   gtk_box_pack_start (GTK_BOX (frame), label_widget, FALSE, FALSE, 0);
684   
685   alignment = gtk_alignment_new (0.0, 0.0, 1.0, 1.0);
686   gtk_alignment_set_padding (GTK_ALIGNMENT (alignment),
687                              0, 0, 12, 0);
688   gtk_box_pack_start (GTK_BOX (frame), alignment, FALSE, FALSE, 0);
689
690   gtk_container_add (GTK_CONTAINER (alignment), child);
691
692   gtk_widget_show (frame);
693   gtk_widget_show (alignment);
694   
695   return frame;
696 }
697
698 static gboolean
699 setup_option (GtkPrintUnixDialog     *dialog,
700               const gchar            *option_name,
701               GtkPrinterOptionWidget *widget)
702 {
703   GtkPrintUnixDialogPrivate *priv = dialog->priv;
704   GtkPrinterOption *option;
705
706   option = gtk_printer_option_set_lookup (priv->options, option_name);
707   gtk_printer_option_widget_set_source (widget, option);
708
709   return option != NULL;
710 }
711
712 static void
713 add_option_to_extension_point (GtkPrinterOption *option,
714                                gpointer          user_data)
715 {
716   GHashTable *extension_points = (GHashTable *) user_data;
717   GtkWidget *widget, *extension_hbox;
718
719   extension_hbox = g_hash_table_lookup (extension_points, option->name);
720
721   if (extension_hbox)
722     {
723
724       widget = gtk_printer_option_widget_new (option);
725       gtk_widget_show (widget);
726    
727       if (gtk_printer_option_widget_has_external_label (GTK_PRINTER_OPTION_WIDGET (widget)))
728         {
729           GtkWidget *label, *hbox;
730
731           label = gtk_printer_option_widget_get_external_label (GTK_PRINTER_OPTION_WIDGET (widget));
732           gtk_widget_show (label);
733           gtk_misc_set_alignment (GTK_MISC (label), 0.0, 0.5);
734           gtk_label_set_mnemonic_widget (GTK_LABEL (label), widget);
735
736           hbox = gtk_hbox_new (FALSE, 12);
737           gtk_box_pack_start (GTK_BOX (hbox), label, FALSE, FALSE, 0);
738           gtk_box_pack_start (GTK_BOX (hbox), widget, FALSE, FALSE, 0);
739           gtk_widget_show (hbox);
740
741           gtk_box_pack_start (GTK_BOX (extension_hbox), hbox, FALSE, FALSE, 0);
742         }
743       else
744         gtk_box_pack_start (GTK_BOX (extension_hbox), widget, FALSE, FALSE, 0);
745     }
746   else
747     g_warning ("Extension point %s requested but not found.", option->name);
748 }
749
750 static void
751 add_option_to_table (GtkPrinterOption *option,
752                      gpointer          user_data)
753 {
754   GtkTable *table;
755   GtkWidget *label, *widget;
756   int row;
757
758   table = GTK_TABLE (user_data);
759   
760   if (g_str_has_prefix (option->name, "gtk-"))
761     return;
762   
763   widget = gtk_printer_option_widget_new (option);
764   gtk_widget_show (widget);
765
766   row = table->nrows;
767   gtk_table_resize (table, table->nrows + 1, table->ncols + 1);
768   
769   if (gtk_printer_option_widget_has_external_label (GTK_PRINTER_OPTION_WIDGET (widget)))
770     {
771       label = gtk_printer_option_widget_get_external_label (GTK_PRINTER_OPTION_WIDGET (widget));
772       gtk_widget_show (label);
773
774       gtk_misc_set_alignment (GTK_MISC (label), 0.0, 0.5);
775       gtk_label_set_mnemonic_widget (GTK_LABEL (label), widget);
776
777       gtk_table_attach (table, label,
778                         0, 1, row - 1 , row,  GTK_FILL, 0, 0, 0);
779       
780       gtk_table_attach (table, widget,
781                         1, 2, row - 1, row,  GTK_FILL, 0, 0, 0);
782     }
783   else
784     gtk_table_attach (table, widget,
785                       0, 2, row - 1, row,  GTK_FILL, 0, 0, 0);
786 }
787
788
789 static void
790 setup_page_table (GtkPrinterOptionSet *options,
791                   const gchar         *group,
792                   GtkWidget           *table,
793                   GtkWidget           *page)
794 {
795   gtk_printer_option_set_foreach_in_group (options, group,
796                                            add_option_to_table,
797                                            table);
798   if (GTK_TABLE (table)->nrows == 1)
799     gtk_widget_hide (page);
800   else
801     gtk_widget_show (page);
802 }
803
804 static void
805 update_print_at_option (GtkPrintUnixDialog *dialog)
806 {
807   GtkPrintUnixDialogPrivate *priv = dialog->priv;
808   GtkPrinterOption *option;
809   
810   option = gtk_printer_option_set_lookup (priv->options, "gtk-print-time");
811
812   if (option == NULL)
813     return;
814   
815   if (priv->updating_print_at)
816     return;
817   
818   if (gtk_toggle_button_get_active (GTK_TOGGLE_BUTTON (priv->print_at_radio)))
819     gtk_printer_option_set (option, "at");
820   else if (gtk_toggle_button_get_active (GTK_TOGGLE_BUTTON (priv->print_hold_radio)))
821     gtk_printer_option_set (option, "on-hold");
822   else
823     gtk_printer_option_set (option, "now");
824   
825   option = gtk_printer_option_set_lookup (priv->options, "gtk-print-time-text");
826   if (option != NULL)
827     {
828       const char *text = gtk_entry_get_text (GTK_ENTRY (priv->print_at_entry));
829       gtk_printer_option_set (option,text);
830     }
831 }
832
833
834 static gboolean
835 setup_print_at (GtkPrintUnixDialog *dialog)
836 {
837   GtkPrintUnixDialogPrivate *priv = dialog->priv;
838   GtkPrinterOption *option;
839   
840   option = gtk_printer_option_set_lookup (priv->options, "gtk-print-time");
841  
842   if (option == NULL)
843     {
844       gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (priv->print_now_radio),
845                                     TRUE);
846       gtk_widget_set_sensitive (priv->print_at_radio, FALSE);
847       gtk_widget_set_sensitive (priv->print_at_entry, FALSE);
848       gtk_widget_set_sensitive (priv->print_hold_radio, FALSE);
849       gtk_entry_set_text (GTK_ENTRY (priv->print_at_entry), "");
850       return FALSE;
851     }
852
853   priv->updating_print_at = TRUE;
854   
855   if (gtk_printer_option_has_choice (option, "at"))
856     {
857       gtk_widget_set_sensitive (priv->print_at_radio, TRUE);
858       gtk_widget_set_sensitive (priv->print_at_entry, TRUE);
859     }
860   else
861     {
862       gtk_widget_set_sensitive (priv->print_at_radio, FALSE);
863       gtk_widget_set_sensitive (priv->print_at_entry, FALSE);
864     }
865   
866   gtk_widget_set_sensitive (priv->print_hold_radio,
867                             gtk_printer_option_has_choice (option, "on-hold"));
868
869   update_print_at_option (dialog);
870
871   if (strcmp (option->value, "at") == 0)
872     gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (priv->print_at_radio),
873                                   TRUE);
874   else if (strcmp (option->value, "on-hold") == 0)
875     gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (priv->print_hold_radio),
876                                   TRUE);
877   else
878     gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (priv->print_now_radio),
879                                   TRUE);
880
881   option = gtk_printer_option_set_lookup (priv->options, "gtk-print-time-text");
882   if (option != NULL)
883     gtk_entry_set_text (GTK_ENTRY (priv->print_at_entry),
884                         option->value);
885   
886
887   priv->updating_print_at = FALSE;
888
889   return TRUE;
890 }
891              
892 static void
893 update_dialog_from_settings (GtkPrintUnixDialog *dialog)
894 {
895   GtkPrintUnixDialogPrivate *priv = dialog->priv;
896   GList *groups, *l;
897   char *group;
898   GtkWidget *table, *frame;
899   gboolean has_advanced, has_job;
900  
901   if (priv->current_printer == NULL)
902     {
903        clear_per_printer_ui (dialog);
904        gtk_widget_hide (priv->job_page);
905        gtk_widget_hide (priv->advanced_page);
906        gtk_widget_hide (priv->image_quality_page);
907        gtk_widget_hide (priv->finishing_page);
908        gtk_widget_hide (priv->color_page);
909        gtk_dialog_set_response_sensitive (GTK_DIALOG (dialog), GTK_RESPONSE_OK, FALSE);
910
911        return;
912     }
913  
914   setup_option (dialog, "gtk-n-up", priv->pages_per_sheet);
915   setup_option (dialog, "gtk-duplex", priv->duplex);
916   setup_option (dialog, "gtk-paper-type", priv->paper_type);
917   setup_option (dialog, "gtk-paper-source", priv->paper_source);
918   setup_option (dialog, "gtk-output-tray", priv->output_tray);
919
920   has_job = FALSE;
921   has_job |= setup_option (dialog, "gtk-job-prio", priv->job_prio);
922   has_job |= setup_option (dialog, "gtk-billing-info", priv->billing_info);
923   has_job |= setup_option (dialog, "gtk-cover-before", priv->cover_before);
924   has_job |= setup_option (dialog, "gtk-cover-after", priv->cover_after);
925   has_job |= setup_print_at (dialog);
926   
927   if (has_job)
928     gtk_widget_show (priv->job_page);
929   else
930     gtk_widget_hide (priv->job_page);
931
932   
933   setup_page_table (priv->options,
934                     "ImageQualityPage",
935                     priv->image_quality_table,
936                     priv->image_quality_page);
937   
938   setup_page_table (priv->options,
939                     "FinishingPage",
940                     priv->finishing_table,
941                     priv->finishing_page);
942
943   setup_page_table (priv->options,
944                     "ColorPage",
945                     priv->color_table,
946                     priv->color_page);
947
948   /* Put the rest of the groups in the advanced page */
949   groups = gtk_printer_option_set_get_groups (priv->options);
950
951   has_advanced = FALSE;
952   for (l = groups; l != NULL; l = l->next)
953     {
954       group = l->data;
955
956       if (group == NULL)
957         continue;
958       
959       if (strcmp (group, "ImageQualityPage") == 0 ||
960           strcmp (group, "ColorPage") == 0 ||
961           strcmp (group, "FinishingPage") == 0)
962         continue;
963
964       if (strcmp (group, "GtkPrintDialogExtention") == 0)
965         {
966           gtk_printer_option_set_foreach_in_group (priv->options,
967                                                    group,
968                                                    add_option_to_extension_point,
969                                                    priv->extension_points);
970           continue;
971         }
972
973       table = gtk_table_new (1, 2, FALSE);
974       gtk_table_set_row_spacings (GTK_TABLE (table), 6);
975       gtk_table_set_col_spacings (GTK_TABLE (table), 12);
976       
977       gtk_printer_option_set_foreach_in_group (priv->options,
978                                                group,
979                                                add_option_to_table,
980                                                table);
981       if (GTK_TABLE (table)->nrows == 1)
982         gtk_widget_destroy (table);
983       else
984         {
985           has_advanced = TRUE;
986           frame = wrap_in_frame (group, table);
987           gtk_widget_show (table);
988           gtk_widget_show (frame);
989           
990           gtk_box_pack_start (GTK_BOX (priv->advanced_vbox),
991                               frame, FALSE, FALSE, 0);
992         }
993     }
994
995   if (has_advanced)
996     gtk_widget_show (priv->advanced_page);
997   else
998     gtk_widget_hide (priv->advanced_page);
999
1000   
1001   g_list_foreach (groups, (GFunc) g_free, NULL);
1002   g_list_free (groups);
1003 }
1004
1005 static void
1006 mark_conflicts (GtkPrintUnixDialog *dialog)
1007 {
1008   GtkPrintUnixDialogPrivate *priv = dialog->priv;
1009   GtkPrinter *printer;
1010   gboolean have_conflict;
1011
1012   have_conflict = FALSE;
1013
1014   printer = priv->current_printer;
1015
1016   if (printer)
1017     {
1018
1019       g_signal_handler_block (priv->options,
1020                               priv->options_changed_handler);
1021       
1022       gtk_printer_option_set_clear_conflicts (priv->options);
1023       
1024       have_conflict = _gtk_printer_mark_conflicts (printer,
1025                                                    priv->options);
1026       
1027       g_signal_handler_unblock (priv->options,
1028                                 priv->options_changed_handler);
1029     }
1030
1031   if (have_conflict)
1032     gtk_widget_show (priv->conflicts_widget);
1033   else
1034     gtk_widget_hide (priv->conflicts_widget);
1035 }
1036
1037 static gboolean
1038 mark_conflicts_callback (gpointer data)
1039 {
1040   GtkPrintUnixDialog *dialog = data;
1041   GtkPrintUnixDialogPrivate *priv = dialog->priv;
1042
1043   priv->mark_conflicts_id = 0;
1044
1045   mark_conflicts (dialog);
1046
1047   return FALSE;
1048 }
1049
1050 static void
1051 unschedule_idle_mark_conflicts (GtkPrintUnixDialog *dialog)
1052 {
1053   GtkPrintUnixDialogPrivate *priv = dialog->priv;
1054
1055   if (priv->mark_conflicts_id != 0)
1056     {
1057       g_source_remove (priv->mark_conflicts_id);
1058       priv->mark_conflicts_id = 0;
1059     }
1060 }
1061
1062 static void
1063 schedule_idle_mark_conflicts (GtkPrintUnixDialog *dialog)
1064 {
1065   GtkPrintUnixDialogPrivate *priv = dialog->priv;
1066
1067   if (priv->mark_conflicts_id != 0)
1068     return;
1069
1070   priv->mark_conflicts_id = g_idle_add (mark_conflicts_callback,
1071                                                 dialog);
1072 }
1073
1074 static void
1075 options_changed_cb (GtkPrintUnixDialog *dialog)
1076 {
1077   GtkPrintUnixDialogPrivate *priv = dialog->priv;
1078
1079   schedule_idle_mark_conflicts (dialog);
1080
1081   if (priv->initial_settings)
1082     {
1083       g_object_unref (priv->initial_settings);
1084       priv->initial_settings = NULL;
1085     }
1086
1087   g_free (priv->waiting_for_printer);
1088   priv->waiting_for_printer = NULL;
1089 }
1090
1091 static void
1092 remove_custom_widget (GtkWidget    *widget,
1093                       GtkContainer *container)
1094 {
1095   gtk_container_remove (container, widget);
1096 }
1097
1098 static void
1099 extension_point_clear_children (const gchar  *key,
1100                                 GtkContainer *container,
1101                                 gpointer      data)
1102 {
1103   gtk_container_foreach (container,
1104                          (GtkCallback)remove_custom_widget,
1105                          container);
1106 }
1107
1108 static void
1109 clear_per_printer_ui (GtkPrintUnixDialog *dialog)
1110 {
1111   GtkPrintUnixDialogPrivate *priv = dialog->priv;
1112
1113   gtk_container_foreach (GTK_CONTAINER (priv->finishing_table),
1114                          (GtkCallback)gtk_widget_destroy,
1115                          NULL);
1116   gtk_table_resize (GTK_TABLE (priv->finishing_table), 1, 2);
1117   gtk_container_foreach (GTK_CONTAINER (priv->image_quality_table),
1118                          (GtkCallback)gtk_widget_destroy,
1119                          NULL);
1120   gtk_table_resize (GTK_TABLE (priv->image_quality_table), 1, 2);
1121   gtk_container_foreach (GTK_CONTAINER (priv->color_table),
1122                          (GtkCallback)gtk_widget_destroy,
1123                          NULL);
1124   gtk_table_resize (GTK_TABLE (priv->color_table), 1, 2);
1125   gtk_container_foreach (GTK_CONTAINER (priv->advanced_vbox),
1126                          (GtkCallback)gtk_widget_destroy,
1127                          NULL);
1128   g_hash_table_foreach (priv->extension_points, 
1129                         (GHFunc) extension_point_clear_children, 
1130                         NULL);
1131 }
1132
1133 static void
1134 printer_details_acquired (GtkPrinter         *printer,
1135                           gboolean            success,
1136                           GtkPrintUnixDialog *dialog)
1137 {
1138   GtkPrintUnixDialogPrivate *priv = dialog->priv;
1139
1140   priv->request_details_tag = 0;
1141   
1142   if (success)
1143     {
1144       GtkTreeSelection *selection;
1145       selection = gtk_tree_view_get_selection (GTK_TREE_VIEW (priv->printer_treeview));
1146       
1147       selected_printer_changed (selection, dialog);
1148     }
1149 }
1150
1151 static void
1152 selected_printer_changed (GtkTreeSelection   *selection,
1153                           GtkPrintUnixDialog *dialog)
1154 {
1155   GtkPrintUnixDialogPrivate *priv = dialog->priv;
1156   GtkPrinter *printer;
1157   GtkTreeIter iter, filter_iter;
1158
1159   /* Whenever the user selects a printer we stop looking for
1160      the printer specified in the initial settings */
1161   if (priv->waiting_for_printer &&
1162       !priv->internal_printer_change)
1163     {
1164       g_free (priv->waiting_for_printer);
1165       priv->waiting_for_printer = NULL;
1166     }
1167   
1168   if (priv->request_details_tag)
1169     {
1170       g_source_remove (priv->request_details_tag);
1171       priv->request_details_tag = 0;
1172     }
1173   
1174   printer = NULL;
1175   if (gtk_tree_selection_get_selected (selection, NULL, &filter_iter))
1176     {
1177       gtk_tree_model_filter_convert_iter_to_child_iter (priv->printer_list_filter,
1178                                                         &iter,
1179                                                         &filter_iter);
1180
1181       gtk_tree_model_get (priv->printer_list, &iter,
1182                           PRINTER_LIST_COL_PRINTER_OBJ, &printer,
1183                           -1);
1184     }
1185   
1186   if (printer != NULL && !_gtk_printer_has_details (printer))
1187     {
1188       gtk_dialog_set_response_sensitive (GTK_DIALOG (dialog), GTK_RESPONSE_OK, FALSE);
1189       priv->request_details_tag =
1190         g_signal_connect (printer, "details-acquired",
1191                           G_CALLBACK (printer_details_acquired), dialog);
1192       _gtk_printer_request_details (printer);
1193       g_object_unref (printer);
1194       return;
1195     }
1196   
1197   if (printer == priv->current_printer)
1198     {
1199       if (printer)
1200         g_object_unref (printer);
1201       return;
1202     }
1203
1204   if (priv->options)
1205     {
1206       g_object_unref (priv->options);
1207       priv->options = NULL;  
1208
1209       clear_per_printer_ui (dialog);
1210     }
1211
1212   if (priv->current_printer)
1213     {
1214       g_object_unref (priv->current_printer);
1215     }
1216
1217   gtk_dialog_set_response_sensitive (GTK_DIALOG (dialog), GTK_RESPONSE_OK, TRUE);
1218   priv->current_printer = printer;
1219
1220   if (printer != NULL)
1221     {
1222       priv->options = _gtk_printer_get_options (printer, priv->initial_settings,
1223                                                         priv->page_setup);
1224   
1225       priv->options_changed_handler = 
1226         g_signal_connect_swapped (priv->options, "changed", G_CALLBACK (options_changed_cb), dialog);
1227     }
1228
1229   update_dialog_from_settings (dialog);
1230 }
1231 static void
1232 update_collate_icon (GtkToggleButton    *toggle_button,
1233                      GtkPrintUnixDialog *dialog)
1234 {
1235   GtkPrintUnixDialogPrivate *priv = dialog->priv;
1236
1237   gtk_widget_queue_draw (priv->collate_image);
1238 }
1239
1240 static void
1241 paint_page (GtkWidget *widget,
1242             cairo_t   *cr, 
1243             gfloat     scale,
1244             gint       x_offset, 
1245             gint       y_offset,
1246             gchar     *text)
1247 {
1248   gint x, y, width, height;
1249   gint linewidth = 2;
1250
1251   x = x_offset * scale;
1252   y = y_offset * scale;
1253   width = 20 * scale;
1254   height = 26 * scale;
1255
1256   gdk_cairo_set_source_color (cr, &widget->style->base[GTK_STATE_NORMAL]);
1257   cairo_rectangle (cr, x, y, width, height);
1258   cairo_fill (cr);
1259
1260   gdk_cairo_set_source_color (cr, &widget->style->text[GTK_STATE_NORMAL]);
1261   cairo_set_line_width (cr, linewidth);
1262   cairo_rectangle (cr, x + linewidth/2.0, y + linewidth/2.0, width - linewidth, height - linewidth);
1263   cairo_stroke (cr);
1264
1265   cairo_select_font_face (cr, "Sans", 
1266                           CAIRO_FONT_SLANT_NORMAL,
1267                           CAIRO_FONT_WEIGHT_NORMAL);
1268   cairo_set_font_size (cr, (gint)(9 * scale));
1269   cairo_move_to (cr, x + (gint)(11 * scale), y + (gint)(21 * scale));
1270   cairo_show_text (cr, text);
1271 }
1272
1273
1274 static gboolean
1275 draw_collate_cb (GtkWidget          *widget,
1276                  GdkEventExpose     *event,
1277                  GtkPrintUnixDialog *dialog)
1278 {
1279   GtkPrintUnixDialogPrivate *priv = dialog->priv;
1280   GtkSettings *settings;
1281   cairo_t *cr;
1282   gint size;
1283   gfloat scale;
1284   gboolean collate, reverse;
1285
1286   collate = gtk_toggle_button_get_active (GTK_TOGGLE_BUTTON (priv->collate_check));
1287   reverse = gtk_toggle_button_get_active (GTK_TOGGLE_BUTTON (priv->reverse_check));
1288
1289   settings = gtk_widget_get_settings (widget);
1290   gtk_icon_size_lookup_for_settings (settings,
1291                                      GTK_ICON_SIZE_DIALOG,
1292                                      &size,
1293                                      NULL);
1294   scale = size / 48.0;
1295
1296   cr = gdk_cairo_create (widget->window);
1297
1298   paint_page (widget, cr, scale, 15, 5, collate == reverse ? "1" : "2");
1299   paint_page (widget, cr, scale, 5, 15, reverse ? "2" : "1");
1300
1301   paint_page (widget, cr, scale, 50, 5, reverse ? "1" : "2");
1302   paint_page (widget, cr, scale, 40, 15, collate == reverse ? "2" : "1");
1303   
1304   cairo_destroy (cr);
1305
1306   return TRUE;
1307 }
1308
1309 static void
1310 gtk_print_unix_dialog_style_set (GtkWidget *widget,
1311                                  GtkStyle  *previous_style)
1312 {
1313   if (GTK_WIDGET_CLASS (gtk_print_unix_dialog_parent_class)->style_set)
1314     GTK_WIDGET_CLASS (gtk_print_unix_dialog_parent_class)->style_set (widget, previous_style);
1315
1316   if (gtk_widget_has_screen (widget))
1317     {
1318       GtkPrintUnixDialog *dialog = (GtkPrintUnixDialog *)widget;
1319       GtkPrintUnixDialogPrivate *priv = dialog->priv;
1320       GtkSettings *settings;
1321       gint size;
1322       gfloat scale;
1323       
1324       settings = gtk_widget_get_settings (widget);
1325       gtk_icon_size_lookup_for_settings (settings,
1326                                          GTK_ICON_SIZE_DIALOG,
1327                                          &size,
1328                                          NULL);
1329       scale = size / 48.0;
1330       
1331       gtk_widget_set_size_request (priv->collate_image, 
1332                                    (50 + 20) * scale,
1333                                    (15 + 26) * scale);
1334     }
1335 }
1336
1337 static void
1338 create_main_page (GtkPrintUnixDialog *dialog)
1339 {
1340   GtkPrintUnixDialogPrivate *priv = dialog->priv;
1341   GtkWidget *main_vbox, *label, *vbox, *hbox;
1342   GtkWidget *scrolled, *treeview, *frame, *table;
1343   GtkWidget *entry, *spinbutton;
1344   GtkWidget *radio, *check, *image;
1345   GtkCellRenderer *renderer;
1346   GtkTreeViewColumn *column;
1347   GtkTreeSelection *selection;
1348   GtkWidget *custom_input;
1349
1350   main_vbox = gtk_vbox_new (FALSE, 18);
1351   gtk_container_set_border_width (GTK_CONTAINER (main_vbox), 12);
1352   gtk_widget_show (main_vbox);
1353
1354   vbox = gtk_vbox_new (FALSE, 6);
1355   gtk_box_pack_start (GTK_BOX (main_vbox), vbox, TRUE, TRUE, 0);
1356   gtk_widget_show (vbox);
1357
1358   scrolled = gtk_scrolled_window_new (NULL, NULL);
1359   gtk_scrolled_window_set_policy (GTK_SCROLLED_WINDOW (scrolled),
1360                                   GTK_POLICY_AUTOMATIC,
1361                                   GTK_POLICY_AUTOMATIC);
1362   gtk_scrolled_window_set_shadow_type (GTK_SCROLLED_WINDOW (scrolled),
1363                                        GTK_SHADOW_IN);
1364   gtk_widget_show (scrolled);
1365   gtk_box_pack_start (GTK_BOX (vbox), scrolled, TRUE, TRUE, 0);
1366
1367   treeview = gtk_tree_view_new_with_model ((GtkTreeModel *) priv->printer_list_filter);
1368   priv->printer_treeview = treeview;
1369   gtk_tree_view_set_headers_visible (GTK_TREE_VIEW (treeview), TRUE);
1370   gtk_tree_view_set_search_column (GTK_TREE_VIEW (treeview), PRINTER_LIST_COL_NAME);
1371   gtk_tree_view_set_enable_search (GTK_TREE_VIEW (treeview), TRUE);
1372   selection = gtk_tree_view_get_selection (GTK_TREE_VIEW (treeview));
1373   gtk_tree_selection_set_mode (selection, GTK_SELECTION_BROWSE);
1374   g_signal_connect (selection, "changed", G_CALLBACK (selected_printer_changed), dialog);
1375  
1376   renderer = gtk_cell_renderer_pixbuf_new ();
1377   column = gtk_tree_view_column_new_with_attributes ("",
1378                                                      renderer,
1379                                                      "icon-name",
1380                                                      PRINTER_LIST_COL_ICON,
1381                                                      NULL);
1382   gtk_tree_view_append_column (GTK_TREE_VIEW (treeview), column);
1383
1384   renderer = gtk_cell_renderer_text_new ();
1385   column = gtk_tree_view_column_new_with_attributes (_("Printer"),
1386                                                      renderer,
1387                                                      "text",
1388                                                      PRINTER_LIST_COL_NAME,
1389                                                      NULL);
1390   gtk_tree_view_append_column (GTK_TREE_VIEW (treeview), column);
1391   
1392   renderer = gtk_cell_renderer_text_new ();
1393   column = gtk_tree_view_column_new_with_attributes (_("Location"),
1394                                                      renderer,
1395                                                      "text",
1396                                                      PRINTER_LIST_COL_LOCATION,
1397                                                      NULL);
1398   gtk_tree_view_append_column (GTK_TREE_VIEW (treeview), column);
1399
1400   renderer = gtk_cell_renderer_text_new ();
1401   g_object_set (renderer, "ellipsize", PANGO_ELLIPSIZE_END, NULL);
1402   column = gtk_tree_view_column_new_with_attributes (_("Status"),
1403                                                      renderer,
1404                                                      "text",
1405                                                      PRINTER_LIST_COL_STATE,
1406                                                      NULL);
1407   gtk_tree_view_append_column (GTK_TREE_VIEW (treeview), column);
1408   
1409   gtk_widget_show (treeview);
1410   gtk_container_add (GTK_CONTAINER (scrolled), treeview);
1411
1412   custom_input = gtk_hbox_new (FALSE, 18);
1413   gtk_widget_show (custom_input);
1414   gtk_box_pack_start (GTK_BOX (vbox), custom_input, FALSE, FALSE, 0);
1415   g_hash_table_insert (priv->extension_points, 
1416                        _EXTENTION_POINT_MAIN_PAGE_CUSTOM_INPUT,
1417                        custom_input);
1418
1419   hbox = gtk_hbox_new (FALSE, 18);
1420   gtk_widget_show (hbox);
1421   gtk_box_pack_start (GTK_BOX (main_vbox), hbox, FALSE, FALSE, 0);
1422
1423   table = gtk_table_new (3, 2, FALSE);
1424   gtk_table_set_row_spacings (GTK_TABLE (table), 6);
1425   gtk_table_set_col_spacings (GTK_TABLE (table), 12);
1426   frame = wrap_in_frame (_("Print Pages"), table);
1427   gtk_box_pack_start (GTK_BOX (hbox), frame, TRUE, TRUE, 0);
1428   gtk_widget_show (table);
1429
1430   radio = gtk_radio_button_new_with_mnemonic (NULL, _("_All"));
1431   priv->all_pages_radio = radio;
1432   gtk_widget_show (radio);
1433   gtk_table_attach (GTK_TABLE (table), radio,
1434                     0, 2, 0, 1,  GTK_FILL, 0,
1435                     0, 0);
1436   radio = gtk_radio_button_new_with_mnemonic (gtk_radio_button_get_group (GTK_RADIO_BUTTON (radio)),
1437                                               _("C_urrent"));
1438   if (priv->current_page == -1)
1439     gtk_widget_set_sensitive (radio, FALSE);    
1440   priv->current_page_radio = radio;
1441   gtk_widget_show (radio);
1442   gtk_table_attach (GTK_TABLE (table), radio,
1443                     0, 2, 1, 2,  GTK_FILL, 0,
1444                     0, 0);
1445   radio = gtk_radio_button_new_with_mnemonic (gtk_radio_button_get_group (GTK_RADIO_BUTTON (radio)),
1446                                               _("Ra_nge: "));
1447   priv->page_range_radio = radio;
1448   gtk_widget_show (radio);
1449   gtk_table_attach (GTK_TABLE (table), radio,
1450                     0, 1, 2, 3,  GTK_FILL, 0,
1451                     0, 0);
1452   entry = gtk_entry_new ();
1453   priv->page_range_entry = entry;
1454   gtk_widget_show (entry);
1455   gtk_table_attach (GTK_TABLE (table), entry,
1456                     1, 2, 2, 3,  GTK_FILL, 0,
1457                     0, 0);
1458
1459   table = gtk_table_new (3, 2, FALSE);
1460   gtk_table_set_row_spacings (GTK_TABLE (table), 6);
1461   gtk_table_set_col_spacings (GTK_TABLE (table), 12);
1462   frame = wrap_in_frame (_("Copies"), table);
1463   gtk_box_pack_start (GTK_BOX (hbox), frame, TRUE, TRUE, 0);
1464   gtk_widget_show (table);
1465
1466   /* FIXMEchpe: too much space between Copies and spinbutton, put those 2 in a hbox and make it span 2 columns */
1467   label = gtk_label_new_with_mnemonic (_("Copie_s:"));
1468   gtk_misc_set_alignment (GTK_MISC (label), 0.0, 0.5);
1469   gtk_widget_show (label);
1470   gtk_table_attach (GTK_TABLE (table), label,
1471                     0, 1, 0, 1,  GTK_FILL, 0,
1472                     0, 0);
1473   spinbutton = gtk_spin_button_new_with_range (1.0, 100.0, 1.0);
1474   priv->copies_spin = spinbutton;
1475   gtk_widget_show (spinbutton);
1476   gtk_table_attach (GTK_TABLE (table), spinbutton,
1477                     1, 2, 0, 1,  GTK_FILL, 0,
1478                     0, 0);
1479   gtk_label_set_mnemonic_widget (GTK_LABEL (label), spinbutton);
1480
1481   check = gtk_check_button_new_with_mnemonic (_("C_ollate"));
1482   priv->collate_check = check;
1483   g_signal_connect (check, "toggled", G_CALLBACK (update_collate_icon), dialog);
1484   gtk_widget_show (check);
1485   gtk_table_attach (GTK_TABLE (table), check,
1486                     0, 1, 1, 2,  GTK_FILL, 0,
1487                     0, 0);
1488   check = gtk_check_button_new_with_mnemonic (_("_Reverse"));
1489   g_signal_connect (check, "toggled", G_CALLBACK (update_collate_icon), dialog);
1490   priv->reverse_check = check;
1491   gtk_widget_show (check);
1492   gtk_table_attach (GTK_TABLE (table), check,
1493                     0, 1, 2, 3,  GTK_FILL, 0,
1494                     0, 0);
1495
1496   image = gtk_drawing_area_new ();
1497   priv->collate_image = image;
1498   gtk_widget_show (image);
1499   gtk_widget_set_size_request (image, 70, 90);
1500   gtk_table_attach (GTK_TABLE (table), image,
1501                     1, 2, 1, 3, GTK_FILL, 0,
1502                     0, 0);
1503   g_signal_connect (image, "expose_event", G_CALLBACK (draw_collate_cb), dialog);
1504
1505   label = gtk_label_new (_("General"));
1506   gtk_widget_show (label);
1507   
1508   gtk_notebook_append_page (GTK_NOTEBOOK (priv->notebook),
1509                             main_vbox, label);
1510 }
1511
1512 static gboolean
1513 is_range_separator (gchar c)
1514 {
1515   return (c == ',' || c == ';' || c == ':');
1516 }
1517
1518 static GtkPageRange *
1519 dialog_get_page_ranges (GtkPrintUnixDialog *dialog,
1520                         gint               *n_ranges_out)
1521 {
1522   GtkPrintUnixDialogPrivate *priv = dialog->priv;
1523   int i, n_ranges;
1524   const char *text, *p;
1525   char *next;
1526   GtkPageRange *ranges;
1527   int start, end;
1528   
1529   text = gtk_entry_get_text (GTK_ENTRY (priv->page_range_entry));
1530
1531   if (*text == 0)
1532     {
1533       *n_ranges_out = 0;
1534       return NULL;
1535     }
1536   
1537   n_ranges = 1;
1538   p = text;
1539   while (*p)
1540     {
1541       if (is_range_separator (*p))
1542         n_ranges++;
1543       p++;
1544     }
1545
1546   ranges = g_new0 (GtkPageRange, n_ranges);
1547   
1548   i = 0;
1549   p = text;
1550   while (*p)
1551     {
1552       start = (int)strtol (p, &next, 10);
1553       if (start < 1)
1554         start = 1;
1555       end = start;
1556
1557       if (next != p)
1558         {
1559           p = next;
1560
1561           if (*p == '-')
1562             {
1563               p++;
1564               end = (int)strtol (p, NULL, 10);
1565               if (end < start)
1566                 end = start;
1567             }
1568         }
1569
1570       ranges[i].start = start - 1;
1571       ranges[i].end = end - 1;
1572       i++;
1573
1574       /* Skip until end or separator */
1575       while (*p && !is_range_separator (*p))
1576         p++;
1577
1578       /* if not at end, skip separator */
1579       if (*p)
1580         p++;
1581     }
1582
1583   *n_ranges_out = i;
1584   
1585   return ranges;
1586 }
1587
1588 static void
1589 dialog_set_page_ranges (GtkPrintUnixDialog *dialog,
1590                         GtkPageRange       *ranges,
1591                         gint                n_ranges)
1592 {
1593   GtkPrintUnixDialogPrivate *priv = dialog->priv;
1594   int i;
1595   GString *s = g_string_new ("");
1596
1597   for (i = 0; i < n_ranges; i++)
1598     {
1599       g_string_append_printf (s, "%d", ranges[i].start + 1);
1600       if (ranges[i].end > ranges[i].start)
1601         g_string_append_printf (s, "-%d", ranges[i].end + 1);
1602       
1603       if (i != n_ranges - 1)
1604         g_string_append (s, ",");
1605     }
1606
1607   gtk_entry_set_text (GTK_ENTRY (priv->page_range_entry),
1608                       s->str);
1609   
1610   g_string_free (s, TRUE);
1611 }
1612
1613
1614 static GtkPrintPages
1615 dialog_get_print_pages (GtkPrintUnixDialog *dialog)
1616 {
1617   GtkPrintUnixDialogPrivate *priv = dialog->priv;
1618   
1619   if (gtk_toggle_button_get_active (GTK_TOGGLE_BUTTON (priv->all_pages_radio)))
1620     return GTK_PRINT_PAGES_ALL;
1621   else if (gtk_toggle_button_get_active (GTK_TOGGLE_BUTTON (priv->current_page_radio)))
1622     return GTK_PRINT_PAGES_CURRENT;
1623   else
1624     return GTK_PRINT_PAGES_RANGES;
1625 }
1626
1627 static void
1628 dialog_set_print_pages (GtkPrintUnixDialog *dialog, GtkPrintPages pages)
1629 {
1630   GtkPrintUnixDialogPrivate *priv = dialog->priv;
1631
1632   if (pages == GTK_PRINT_PAGES_RANGES)
1633     gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (priv->page_range_radio), TRUE);
1634   else if (pages == GTK_PRINT_PAGES_CURRENT)
1635     gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (priv->current_page_radio), TRUE);
1636   else
1637     gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (priv->all_pages_radio), TRUE);
1638 }
1639
1640 static gdouble
1641 dialog_get_scale (GtkPrintUnixDialog *dialog)
1642 {
1643   return gtk_spin_button_get_value (GTK_SPIN_BUTTON (dialog->priv->scale_spin));
1644 }
1645
1646 static void
1647 dialog_set_scale (GtkPrintUnixDialog *dialog, 
1648                   gdouble             val)
1649 {
1650   return gtk_spin_button_set_value (GTK_SPIN_BUTTON (dialog->priv->scale_spin),
1651                                     val);
1652 }
1653
1654 static GtkPageSet
1655 dialog_get_page_set (GtkPrintUnixDialog *dialog)
1656 {
1657   return (GtkPageSet)gtk_combo_box_get_active (GTK_COMBO_BOX (dialog->priv->page_set_combo));
1658 }
1659
1660 static void
1661 dialog_set_page_set (GtkPrintUnixDialog *dialog, 
1662                      GtkPageSet          val)
1663 {
1664   gtk_combo_box_set_active (GTK_COMBO_BOX (dialog->priv->page_set_combo),
1665                             (int)val);
1666 }
1667
1668 static gint
1669 dialog_get_n_copies (GtkPrintUnixDialog *dialog)
1670 {
1671   return gtk_spin_button_get_value_as_int (GTK_SPIN_BUTTON (dialog->priv->copies_spin));
1672 }
1673
1674 static void
1675 dialog_set_n_copies (GtkPrintUnixDialog *dialog, 
1676                      gint                n_copies)
1677 {
1678   gtk_spin_button_set_value (GTK_SPIN_BUTTON (dialog->priv->copies_spin),
1679                              n_copies);
1680 }
1681
1682 static gboolean
1683 dialog_get_collate (GtkPrintUnixDialog *dialog)
1684 {
1685   return gtk_toggle_button_get_active (GTK_TOGGLE_BUTTON (dialog->priv->collate_check));
1686 }
1687
1688 static void
1689 dialog_set_collate (GtkPrintUnixDialog *dialog, 
1690                     gboolean            collate)
1691 {
1692   gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (dialog->priv->collate_check),
1693                                 collate);
1694 }
1695
1696 static gboolean
1697 dialog_get_reverse (GtkPrintUnixDialog *dialog)
1698 {
1699   return gtk_toggle_button_get_active (GTK_TOGGLE_BUTTON (dialog->priv->reverse_check));
1700 }
1701
1702 static void
1703 dialog_set_reverse (GtkPrintUnixDialog *dialog, 
1704                     gboolean            reverse)
1705 {
1706   gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (dialog->priv->reverse_check),
1707                                 reverse);
1708 }
1709
1710 static gint 
1711 dialog_get_pages_per_sheet (GtkPrintUnixDialog *dialog)
1712 {
1713   GtkPrintUnixDialogPrivate *priv = dialog->priv;
1714   const char *val;
1715   int num;
1716
1717   val = gtk_printer_option_widget_get_value (priv->pages_per_sheet);
1718
1719   num = 1;
1720   
1721   if (val)
1722     {
1723       num = atoi(val);
1724       if (num < 1)
1725         num = 1;
1726     }
1727   
1728   return num;
1729 }
1730
1731
1732 static gboolean
1733 draw_page_cb (GtkWidget          *widget,
1734               GdkEventExpose     *event,
1735               GtkPrintUnixDialog *dialog)
1736 {
1737   GtkPrintUnixDialogPrivate *priv = dialog->priv;
1738   cairo_t *cr;
1739   double ratio;
1740   int w, h, tmp, shadow_offset;
1741   int pages_x, pages_y, i, x, y, layout_w, layout_h;
1742   double page_width, page_height;
1743   GtkPageOrientation orientation;
1744   gboolean landscape;
1745   PangoLayout *layout;
1746   PangoFontDescription *font;
1747   char *text;
1748   
1749   orientation = gtk_page_setup_get_orientation (priv->page_setup);
1750   landscape =
1751     (orientation == GTK_PAGE_ORIENTATION_LANDSCAPE) ||
1752     (orientation == GTK_PAGE_ORIENTATION_REVERSE_LANDSCAPE);
1753   
1754   cr = gdk_cairo_create (widget->window);
1755   
1756   ratio = G_SQRT2;
1757
1758   w = (EXAMPLE_PAGE_AREA_SIZE - 3) / ratio;
1759   h = w * ratio;
1760
1761   switch (dialog_get_pages_per_sheet (dialog))
1762     {
1763     default:
1764     case 1:
1765       pages_x = 1; pages_y = 1;
1766       break;
1767     case 2:
1768       landscape = !landscape;
1769       pages_x = 1; pages_y = 2;
1770       break;
1771     case 4:
1772       pages_x = 2; pages_y = 2;
1773       break;
1774     case 6:
1775       landscape = !landscape;
1776       pages_x = 2; pages_y = 3;
1777       break;
1778     case 9:
1779       pages_x = 3; pages_y = 3;
1780       break;
1781     case 16:
1782       pages_x = 4; pages_y = 4;
1783       break;
1784     }
1785
1786   if (landscape)
1787     {
1788       tmp = w;
1789       w = h;
1790       h = tmp;
1791
1792       tmp = pages_x;
1793       pages_x = pages_y;
1794       pages_y = tmp;
1795     }
1796   
1797   shadow_offset = 3;
1798   
1799   cairo_set_source_rgba (cr, 0.0, 0.0, 0.0, 0.5);
1800   cairo_rectangle (cr, shadow_offset + 1, shadow_offset + 1, w, h);
1801   cairo_fill (cr);
1802   
1803   cairo_set_source_rgb (cr, 1.0, 1.0, 1.0);
1804   cairo_rectangle (cr, 1, 1, w, h);
1805   cairo_fill (cr);
1806   cairo_set_line_width (cr, 1.0);
1807   cairo_rectangle (cr, 0.5, 0.5, w+1, h+1);
1808   
1809   cairo_set_source_rgb (cr, 0.0, 0.0, 0.0);
1810   cairo_stroke (cr);
1811
1812   i = 1;
1813
1814   page_width = (double)w / pages_x;
1815   page_height = (double)h / pages_y;
1816
1817   layout  = pango_cairo_create_layout (cr);
1818
1819   font = pango_font_description_new ();
1820   pango_font_description_set_family (font, "sans");
1821   pango_font_description_set_absolute_size (font, page_height * 0.4 * PANGO_SCALE);
1822   pango_layout_set_font_description (layout, font);
1823   pango_font_description_free (font);
1824
1825   pango_layout_set_width (layout, page_width * PANGO_SCALE);
1826   pango_layout_set_alignment (layout, PANGO_ALIGN_CENTER);
1827   
1828   for (y = 0; y < pages_y; y++)
1829     {
1830       for (x = 0; x < pages_x; x++)
1831         {
1832           text = g_strdup_printf ("%d", i++);
1833           pango_layout_set_text (layout, text, -1);
1834           g_free (text);
1835           pango_layout_get_size (layout, &layout_w, &layout_h);
1836           cairo_save (cr);
1837           cairo_translate (cr,
1838                            x * page_width,
1839                            y * page_height + (page_height - layout_h / 1024.0) / 2
1840                            );
1841           
1842           pango_cairo_show_layout (cr, layout);
1843           cairo_restore (cr);
1844         }
1845     }
1846     
1847   cairo_destroy (cr);
1848
1849   return TRUE;
1850 }
1851
1852 static void
1853 redraw_page_layout_preview (GtkPrintUnixDialog *dialog)
1854 {
1855   GtkPrintUnixDialogPrivate *priv = dialog->priv;
1856
1857   if (priv->page_layout_preview)
1858     gtk_widget_queue_draw (priv->page_layout_preview);
1859 }
1860
1861 static void
1862 create_page_setup_page (GtkPrintUnixDialog *dialog)
1863 {
1864   GtkPrintUnixDialogPrivate *priv = dialog->priv;
1865   GtkWidget *main_vbox, *label, *hbox, *hbox2;
1866   GtkWidget *frame, *table, *widget;
1867   GtkWidget *combo, *spinbutton, *draw;
1868
1869   main_vbox = gtk_vbox_new (FALSE, 18);
1870   gtk_container_set_border_width (GTK_CONTAINER (main_vbox), 12);
1871   gtk_widget_show (main_vbox);
1872
1873   hbox = gtk_hbox_new (FALSE, 18);
1874   gtk_widget_show (hbox);
1875   gtk_box_pack_start (GTK_BOX (main_vbox), hbox, FALSE, FALSE, 0);
1876
1877   table = gtk_table_new (5, 2, FALSE);
1878   gtk_table_set_row_spacings (GTK_TABLE (table), 6);
1879   gtk_table_set_col_spacings (GTK_TABLE (table), 12);
1880   frame = wrap_in_frame (_("Layout"), table);
1881   gtk_box_pack_start (GTK_BOX (hbox), frame, TRUE, TRUE, 0);
1882   gtk_widget_show (table);
1883
1884   label = gtk_label_new_with_mnemonic (_("Pages per _sheet:"));
1885   gtk_misc_set_alignment (GTK_MISC (label), 0.0, 0.5);
1886   gtk_widget_show (label);
1887   gtk_table_attach (GTK_TABLE (table), label,
1888                     0, 1, 0, 1,  GTK_FILL, 0,
1889                     0, 0);
1890
1891   widget = gtk_printer_option_widget_new (NULL);
1892   g_signal_connect_swapped (widget, "changed", G_CALLBACK (redraw_page_layout_preview), dialog);
1893   priv->pages_per_sheet = GTK_PRINTER_OPTION_WIDGET (widget);
1894   gtk_widget_show (widget);
1895   gtk_table_attach (GTK_TABLE (table), widget,
1896                     1, 2, 0, 1,  GTK_FILL, 0,
1897                     0, 0);
1898   gtk_label_set_mnemonic_widget (GTK_LABEL (label), widget);
1899
1900   label = gtk_label_new_with_mnemonic (_("T_wo-sided:"));
1901   gtk_misc_set_alignment (GTK_MISC (label), 0.0, 0.5);
1902   gtk_widget_show (label);
1903   gtk_table_attach (GTK_TABLE (table), label,
1904                     0, 1, 1, 2,  GTK_FILL, 0,
1905                     0, 0);
1906
1907   widget = gtk_printer_option_widget_new (NULL);
1908   priv->duplex = GTK_PRINTER_OPTION_WIDGET (widget);
1909   gtk_widget_show (widget);
1910   gtk_table_attach (GTK_TABLE (table), widget,
1911                     1, 2, 1, 2,  GTK_FILL, 0,
1912                     0, 0);
1913   gtk_label_set_mnemonic_widget (GTK_LABEL (label), widget);
1914
1915   label = gtk_label_new_with_mnemonic (_("_Only Print:"));
1916   gtk_misc_set_alignment (GTK_MISC (label), 0.0, 0.5);
1917   gtk_widget_show (label);
1918   gtk_table_attach (GTK_TABLE (table), label,
1919                     0, 1, 2, 3,  GTK_FILL, 0,
1920                     0, 0);
1921
1922   combo = gtk_combo_box_new_text ();
1923   priv->page_set_combo = combo;
1924   gtk_widget_show (combo);
1925   gtk_table_attach (GTK_TABLE (table), combo,
1926                     1, 2, 2, 3,  GTK_FILL, 0,
1927                     0, 0);
1928   gtk_label_set_mnemonic_widget (GTK_LABEL (label), combo);
1929   /* In enum order */
1930   gtk_combo_box_append_text (GTK_COMBO_BOX (combo), _("All sheets"));  
1931   gtk_combo_box_append_text (GTK_COMBO_BOX (combo), _("Even sheets"));  
1932   gtk_combo_box_append_text (GTK_COMBO_BOX (combo), _("Odd sheets"));  
1933   gtk_combo_box_set_active (GTK_COMBO_BOX (combo), 0);
1934
1935   label = gtk_label_new_with_mnemonic (_("Sc_ale:"));
1936   gtk_misc_set_alignment (GTK_MISC (label), 0.0, 0.5);
1937   gtk_widget_show (label);
1938   gtk_table_attach (GTK_TABLE (table), label,
1939                     0, 1, 3, 4,  GTK_FILL, 0,
1940                     0, 0);
1941
1942   hbox2 = gtk_hbox_new (FALSE, 6);
1943   gtk_widget_show (hbox2);
1944   gtk_table_attach (GTK_TABLE (table), hbox2,
1945                     1, 2, 3, 4,  GTK_FILL, 0,
1946                     0, 0);
1947   
1948   spinbutton = gtk_spin_button_new_with_range (1.0, 1000.0, 1.0);
1949   priv->scale_spin = spinbutton;
1950   gtk_spin_button_set_digits (GTK_SPIN_BUTTON (spinbutton), 1);
1951   gtk_spin_button_set_value (GTK_SPIN_BUTTON (spinbutton), 100.0);
1952   gtk_box_pack_start (GTK_BOX (hbox2), spinbutton, FALSE, FALSE, 0);
1953   gtk_label_set_mnemonic_widget (GTK_LABEL (label), spinbutton);
1954   gtk_widget_show (spinbutton);
1955   label = gtk_label_new ("%"); /* FIXMEchpe does there exist any language where % needs to be translated? */
1956   gtk_widget_show (label);
1957   gtk_box_pack_start (GTK_BOX (hbox2), label, FALSE, FALSE, 0);
1958
1959   table = gtk_table_new (4, 2, FALSE);
1960   gtk_table_set_row_spacings (GTK_TABLE (table), 6);
1961   gtk_table_set_col_spacings (GTK_TABLE (table), 12);
1962   frame = wrap_in_frame (_("Paper"), table);
1963   gtk_box_pack_start (GTK_BOX (hbox), frame, TRUE, TRUE, 6);
1964   gtk_widget_show (table);
1965
1966   label = gtk_label_new_with_mnemonic (_("Paper _Type:"));
1967   gtk_misc_set_alignment (GTK_MISC (label), 0.0, 0.5);
1968   gtk_widget_show (label);
1969   gtk_table_attach (GTK_TABLE (table), label,
1970                     0, 1, 0, 1,  GTK_FILL, 0,
1971                     0, 0);
1972
1973   widget = gtk_printer_option_widget_new (NULL);
1974   priv->paper_type = GTK_PRINTER_OPTION_WIDGET (widget);
1975   gtk_widget_show (widget);
1976   gtk_table_attach (GTK_TABLE (table), widget,
1977                     1, 2, 0, 1,  GTK_FILL, 0,
1978                     0, 0);
1979   gtk_label_set_mnemonic_widget (GTK_LABEL (label), widget);
1980
1981   label = gtk_label_new_with_mnemonic (_("Paper _Source:"));
1982   gtk_misc_set_alignment (GTK_MISC (label), 0.0, 0.5);
1983   gtk_widget_show (label);
1984   gtk_table_attach (GTK_TABLE (table), label,
1985                     0, 1, 1, 2,  GTK_FILL, 0,
1986                     0, 0);
1987
1988   widget = gtk_printer_option_widget_new (NULL);
1989   priv->paper_source = GTK_PRINTER_OPTION_WIDGET (widget);
1990   gtk_widget_show (widget);
1991   gtk_table_attach (GTK_TABLE (table), widget,
1992                     1, 2, 1, 2,  GTK_FILL, 0,
1993                     0, 0);
1994   gtk_label_set_mnemonic_widget (GTK_LABEL (label), widget);
1995
1996   label = gtk_label_new_with_mnemonic (_("Output T_ray:"));
1997   gtk_misc_set_alignment (GTK_MISC (label), 0.0, 0.5);
1998   gtk_widget_show (label);
1999   gtk_table_attach (GTK_TABLE (table), label,
2000                     0, 1, 2, 3,  GTK_FILL, 0,
2001                     0, 0);
2002
2003   widget = gtk_printer_option_widget_new (NULL);
2004   priv->output_tray = GTK_PRINTER_OPTION_WIDGET (widget);
2005   gtk_widget_show (widget);
2006   gtk_table_attach (GTK_TABLE (table), widget,
2007                     1, 2, 2, 3,  GTK_FILL, 0,
2008                     0, 0);
2009   gtk_label_set_mnemonic_widget (GTK_LABEL (label), widget);
2010
2011   /* Add the page layout preview */
2012   hbox2 = gtk_hbox_new (FALSE, 0);
2013   gtk_widget_show (hbox2);
2014   gtk_box_pack_start (GTK_BOX (main_vbox), hbox2, TRUE, TRUE, 0);
2015
2016   draw = gtk_drawing_area_new ();
2017   priv->page_layout_preview = draw;
2018   gtk_widget_set_size_request (draw, 200, 200);
2019   g_signal_connect (draw, "expose_event", G_CALLBACK (draw_page_cb), dialog);
2020   gtk_widget_show (draw);
2021
2022   gtk_box_pack_start (GTK_BOX (hbox2), draw, TRUE, FALSE, 0);
2023   
2024   label = gtk_label_new (_("Page Setup"));
2025   gtk_widget_show (label);
2026   
2027   gtk_notebook_append_page (GTK_NOTEBOOK (priv->notebook),
2028                             main_vbox, label);
2029 }
2030
2031 static void
2032 create_job_page (GtkPrintUnixDialog *dialog)
2033 {
2034   GtkPrintUnixDialogPrivate *priv = dialog->priv;
2035   GtkWidget *main_table, *label;
2036   GtkWidget *frame, *table, *radio;
2037   GtkWidget *entry, *widget;
2038
2039   main_table = gtk_table_new (2, 2, FALSE);
2040   gtk_container_set_border_width (GTK_CONTAINER (main_table), 12);
2041   gtk_table_set_row_spacings (GTK_TABLE (main_table), 18);
2042   gtk_table_set_col_spacings (GTK_TABLE (main_table), 18);
2043
2044   table = gtk_table_new (2, 2, FALSE);
2045   gtk_table_set_row_spacings (GTK_TABLE (table), 6);
2046   gtk_table_set_col_spacings (GTK_TABLE (table), 12);
2047   frame = wrap_in_frame (_("Job Details"), table);
2048   gtk_table_attach (GTK_TABLE (main_table), frame,
2049                     0, 1, 0, 1,  GTK_FILL, 0,
2050                     0, 0);
2051   gtk_widget_show (table);
2052
2053   label = gtk_label_new_with_mnemonic (_("Pri_ority:"));
2054   gtk_misc_set_alignment (GTK_MISC (label), 0.0, 0.5);
2055   gtk_widget_show (label);
2056   gtk_table_attach (GTK_TABLE (table), label,
2057                     0, 1, 0, 1,  GTK_FILL, 0,
2058                     0, 0);
2059
2060   widget = gtk_printer_option_widget_new (NULL);
2061   priv->job_prio = GTK_PRINTER_OPTION_WIDGET (widget);
2062   gtk_widget_show (widget);
2063   gtk_table_attach (GTK_TABLE (table), widget,
2064                     1, 2, 0, 1,  GTK_FILL, 0,
2065                     0, 0);
2066   gtk_label_set_mnemonic_widget (GTK_LABEL (label), widget);
2067
2068   label = gtk_label_new_with_mnemonic (_("_Billing info:"));
2069   gtk_misc_set_alignment (GTK_MISC (label), 0.0, 0.5);
2070   gtk_widget_show (label);
2071   gtk_table_attach (GTK_TABLE (table), label,
2072                     0, 1, 1, 2,  GTK_FILL, 0,
2073                     0, 0);
2074
2075   widget = gtk_printer_option_widget_new (NULL);
2076   priv->billing_info = GTK_PRINTER_OPTION_WIDGET (widget);
2077   gtk_widget_show (widget);
2078   gtk_table_attach (GTK_TABLE (table), widget,
2079                     1, 2, 1, 2,  GTK_FILL, 0,
2080                     0, 0);
2081   gtk_label_set_mnemonic_widget (GTK_LABEL (label), widget);
2082
2083   table = gtk_table_new (2, 2, FALSE);
2084   gtk_table_set_row_spacings (GTK_TABLE (table), 6);
2085   gtk_table_set_col_spacings (GTK_TABLE (table), 12);
2086   frame = wrap_in_frame (_("Print Document"), table);
2087   gtk_table_attach (GTK_TABLE (main_table), frame,
2088                     0, 1, 1, 2,  GTK_FILL, 0,
2089                     0, 0);
2090   gtk_widget_show (table);
2091
2092   radio = gtk_radio_button_new_with_mnemonic (NULL, _("_Now"));
2093   priv->print_now_radio = radio;
2094   gtk_widget_show (radio);
2095   gtk_table_attach (GTK_TABLE (table), radio,
2096                     0, 2, 0, 1,  GTK_FILL, 0,
2097                     0, 0);
2098   radio = gtk_radio_button_new_with_mnemonic (gtk_radio_button_get_group (GTK_RADIO_BUTTON (radio)),
2099                                               _("A_t:"));
2100   priv->print_at_radio = radio;
2101   gtk_widget_show (radio);
2102   gtk_table_attach (GTK_TABLE (table), radio,
2103                     0, 1, 1, 2,  GTK_FILL, 0,
2104                     0, 0);
2105
2106   entry = gtk_entry_new ();
2107   priv->print_at_entry = entry;
2108   gtk_widget_show (entry);
2109   gtk_table_attach (GTK_TABLE (table), entry,
2110                     1, 2, 1, 2,  GTK_FILL, 0,
2111                     0, 0);
2112
2113   radio = gtk_radio_button_new_with_mnemonic (gtk_radio_button_get_group (GTK_RADIO_BUTTON (radio)),
2114                                               _("On _Hold"));
2115   priv->print_hold_radio = radio;
2116   gtk_widget_show (radio);
2117   gtk_table_attach (GTK_TABLE (table), radio,
2118                     0, 2, 2, 3,  GTK_FILL, 0,
2119                     0, 0);
2120
2121   g_signal_connect_swapped (priv->print_now_radio, "toggled",
2122                             G_CALLBACK (update_print_at_option), dialog);
2123   g_signal_connect_swapped (priv->print_at_radio, "toggled",
2124                             G_CALLBACK (update_print_at_option), dialog);
2125   g_signal_connect_swapped (priv->print_at_entry, "changed",
2126                             G_CALLBACK (update_print_at_option), dialog);
2127   g_signal_connect_swapped (priv->print_hold_radio, "toggled",
2128                             G_CALLBACK (update_print_at_option), dialog);
2129
2130   table = gtk_table_new (2, 2, FALSE);
2131   gtk_table_set_row_spacings (GTK_TABLE (table), 6);
2132   gtk_table_set_col_spacings (GTK_TABLE (table), 12);
2133   frame = wrap_in_frame (_("Add Cover Page"), table);
2134   gtk_table_attach (GTK_TABLE (main_table), frame,
2135                     1, 2, 0, 1,  GTK_FILL, 0,
2136                     0, 0);
2137   gtk_widget_show (table);
2138
2139   label = gtk_label_new_with_mnemonic (_("Be_fore:"));
2140   gtk_misc_set_alignment (GTK_MISC (label), 0.0, 0.5);
2141   gtk_widget_show (label);
2142   gtk_table_attach (GTK_TABLE (table), label,
2143                     0, 1, 0, 1,  GTK_FILL, 0,
2144                     0, 0);
2145
2146   widget = gtk_printer_option_widget_new (NULL);
2147   priv->cover_before = GTK_PRINTER_OPTION_WIDGET (widget);
2148   gtk_widget_show (widget);
2149   gtk_table_attach (GTK_TABLE (table), widget,
2150                     1, 2, 0, 1,  GTK_FILL, 0,
2151                     0, 0);
2152   gtk_label_set_mnemonic_widget (GTK_LABEL (label), widget);
2153
2154   label = gtk_label_new_with_mnemonic (_("_After:"));
2155   gtk_misc_set_alignment (GTK_MISC (label), 0.0, 0.5);
2156   gtk_widget_show (label);
2157   gtk_table_attach (GTK_TABLE (table), label,
2158                     0, 1, 1, 2,  GTK_FILL, 0,
2159                     0, 0);
2160
2161   widget = gtk_printer_option_widget_new (NULL);
2162   priv->cover_after = GTK_PRINTER_OPTION_WIDGET (widget);
2163   gtk_widget_show (widget);
2164   gtk_table_attach (GTK_TABLE (table), widget,
2165                     1, 2, 1, 2,  GTK_FILL, 0,
2166                     0, 0);
2167   gtk_label_set_mnemonic_widget (GTK_LABEL (label), widget);
2168
2169   label = gtk_label_new (_("Job"));
2170   gtk_widget_show (label);
2171
2172   priv->job_page = main_table;
2173   gtk_notebook_append_page (GTK_NOTEBOOK (priv->notebook),
2174                             main_table, label);
2175 }
2176
2177 static void 
2178 create_optional_page (GtkPrintUnixDialog  *dialog,
2179                       const gchar         *text,
2180                       GtkWidget          **table_out,
2181                       GtkWidget          **page_out)
2182 {
2183   GtkPrintUnixDialogPrivate *priv = dialog->priv;
2184   GtkWidget *table, *label, *scrolled;
2185
2186   scrolled = gtk_scrolled_window_new (NULL, NULL);
2187   gtk_scrolled_window_set_policy (GTK_SCROLLED_WINDOW (scrolled),
2188                                   GTK_POLICY_NEVER,
2189                                   GTK_POLICY_AUTOMATIC);
2190   
2191   table = gtk_table_new (1, 2, FALSE);
2192   gtk_table_set_row_spacings (GTK_TABLE (table), 6);
2193   gtk_table_set_col_spacings (GTK_TABLE (table), 12);
2194   gtk_container_set_border_width (GTK_CONTAINER (table), 12);
2195   gtk_widget_show (table);
2196
2197   gtk_scrolled_window_add_with_viewport (GTK_SCROLLED_WINDOW (scrolled),
2198                                          table);
2199   gtk_viewport_set_shadow_type (GTK_VIEWPORT (GTK_BIN(scrolled)->child),
2200                                 GTK_SHADOW_NONE);
2201   
2202   label = gtk_label_new (text);
2203   gtk_widget_show (label);
2204   
2205   gtk_notebook_append_page (GTK_NOTEBOOK (priv->notebook),
2206                             scrolled, label);
2207
2208   *table_out = table;
2209   *page_out = scrolled;
2210 }
2211
2212 static void
2213 create_advanced_page (GtkPrintUnixDialog *dialog)
2214 {
2215   GtkPrintUnixDialogPrivate *priv = dialog->priv;
2216   GtkWidget *main_vbox, *label, *scrolled;
2217
2218   scrolled = gtk_scrolled_window_new (NULL, NULL);
2219   priv->advanced_page = scrolled;
2220   gtk_scrolled_window_set_policy (GTK_SCROLLED_WINDOW (scrolled),
2221                                   GTK_POLICY_NEVER,
2222                                   GTK_POLICY_AUTOMATIC);
2223
2224   main_vbox = gtk_vbox_new (FALSE, 18);
2225   gtk_container_set_border_width (GTK_CONTAINER (main_vbox), 12);
2226   gtk_widget_show (main_vbox);
2227
2228   gtk_scrolled_window_add_with_viewport (GTK_SCROLLED_WINDOW (scrolled),
2229                                          main_vbox);
2230   gtk_viewport_set_shadow_type (GTK_VIEWPORT (GTK_BIN(scrolled)->child),
2231                                 GTK_SHADOW_NONE);
2232   
2233   priv->advanced_vbox = main_vbox;
2234   
2235   label = gtk_label_new (_("Advanced"));
2236   gtk_widget_show (label);
2237   
2238   gtk_notebook_append_page (GTK_NOTEBOOK (priv->notebook),
2239                             scrolled, label);
2240 }
2241
2242
2243 static void
2244 populate_dialog (GtkPrintUnixDialog *print_dialog)
2245 {
2246   GtkPrintUnixDialogPrivate *priv = print_dialog->priv;
2247   GtkDialog *dialog = GTK_DIALOG (print_dialog);
2248   GtkWidget *hbox, *conflict_hbox, *image, *label;
2249
2250   gtk_dialog_set_has_separator (dialog, FALSE);
2251   gtk_container_set_border_width (GTK_CONTAINER (dialog), 5);
2252   gtk_box_set_spacing (GTK_BOX (dialog->vbox), 2); /* 2 * 5 + 2 = 12 */
2253   gtk_container_set_border_width (GTK_CONTAINER (dialog->action_area), 5);
2254   gtk_box_set_spacing (GTK_BOX (dialog->action_area), 6);
2255
2256   priv->notebook = gtk_notebook_new ();
2257   gtk_container_set_border_width (GTK_CONTAINER (priv->notebook), 5);
2258   gtk_box_pack_start (GTK_BOX (dialog->vbox), priv->notebook, TRUE, TRUE, 0);
2259
2260   create_printer_list_model (print_dialog);
2261
2262   create_main_page (print_dialog);
2263   create_page_setup_page (print_dialog);
2264   create_job_page (print_dialog);
2265   create_optional_page (print_dialog, _("Image Quality"),
2266                         &priv->image_quality_table,
2267                         &priv->image_quality_page);
2268   create_optional_page (print_dialog, _("Color"),
2269                         &priv->color_table,
2270                         &priv->color_page);
2271   create_optional_page (print_dialog, _("Finishing"),
2272                         &priv->finishing_table,
2273                         &priv->finishing_page);
2274   create_advanced_page (print_dialog);
2275
2276   hbox = gtk_hbox_new (FALSE, 0);
2277   gtk_widget_show (hbox);
2278   gtk_box_pack_end (GTK_BOX (dialog->vbox), hbox, FALSE, TRUE, 0);
2279   
2280   conflict_hbox = gtk_hbox_new (FALSE, 0);
2281   image = gtk_image_new_from_stock (GTK_STOCK_DIALOG_WARNING, GTK_ICON_SIZE_MENU);
2282   gtk_widget_show (image);
2283   gtk_box_pack_start (GTK_BOX (conflict_hbox), image, FALSE, TRUE, 0);
2284   label = gtk_label_new (_("Some of the settings in the dialog conflict"));
2285   gtk_widget_show (label);
2286   gtk_box_pack_start (GTK_BOX (conflict_hbox), label, FALSE, TRUE, 0);
2287   priv->conflicts_widget = conflict_hbox;
2288
2289   gtk_box_pack_start (GTK_BOX (hbox), conflict_hbox,
2290                       FALSE, FALSE, 0);
2291
2292   /* Reparent the action area into the hbox. This is so we can have the
2293    * conflict warning on the same row, but not make the buttons the same
2294    * width as the warning (which the buttonbox does).
2295    */
2296   g_object_ref (dialog->action_area);
2297   gtk_container_remove (GTK_CONTAINER (dialog->vbox),
2298                         dialog->action_area);
2299   gtk_box_pack_end (GTK_BOX (hbox), dialog->action_area,
2300                     FALSE, FALSE, 0);
2301   g_object_unref (dialog->action_area);
2302   
2303   gtk_widget_show (priv->notebook);
2304
2305   load_print_backends (print_dialog);
2306 }
2307
2308 /**
2309  * gtk_print_unix_dialog_new:
2310  * @title: Title of the dialog, or %NULL
2311  * @parent: Transient parent of the dialog, or %NULL
2312  *
2313  * Creates a new #GtkPrintUnixDialog.
2314  *
2315  * Return value: a new #GtkPrintUnixDialog
2316  *
2317  * Since: 2.10
2318  **/
2319 GtkWidget *
2320 gtk_print_unix_dialog_new (const gchar *title,
2321                            GtkWindow   *parent)
2322 {
2323   GtkWidget *result;
2324   const gchar *_title = _("Print");
2325
2326   if (title)
2327     _title = title;
2328   
2329   result = g_object_new (GTK_TYPE_PRINT_UNIX_DIALOG,
2330                          "title", _title,
2331                          "has-separator", FALSE,
2332                          NULL);
2333
2334   if (parent)
2335     gtk_window_set_transient_for (GTK_WINDOW (result), parent);
2336
2337   return result;
2338 }
2339
2340 /**
2341  * gtk_print_unix_dialog_get_selected_printer:
2342  * @dialog: a #GtkPrintUnixDialog
2343  * 
2344  * Gets the currently selected printer.
2345  * 
2346  * Returns: the currently selected printer
2347  * 
2348  * Since: 2.10
2349  */
2350 GtkPrinter *
2351 gtk_print_unix_dialog_get_selected_printer (GtkPrintUnixDialog *dialog)
2352 {
2353   g_return_val_if_fail (GTK_IS_PRINT_UNIX_DIALOG (dialog), NULL);
2354
2355   return dialog->priv->current_printer;
2356 }
2357
2358 /**
2359  * gtk_print_unix_dialog_set_page_setup:
2360  * @dialog: a #GtkPrintUnixDialog
2361  * @page_setup: a #GtkPageSetup
2362  * 
2363  * Sets the page setup of the #GtkPrintUnixDialog.
2364  *
2365  * Since: 2.10
2366  */
2367 void
2368 gtk_print_unix_dialog_set_page_setup (GtkPrintUnixDialog *dialog,
2369                                       GtkPageSetup       *page_setup)
2370 {
2371   GtkPrintUnixDialogPrivate *priv;
2372
2373   g_return_if_fail (GTK_IS_PRINT_UNIX_DIALOG (dialog));
2374   g_return_if_fail (GTK_IS_PAGE_SETUP (page_setup));
2375
2376   priv = dialog->priv;
2377
2378   if (priv->page_setup != page_setup)
2379     {
2380       g_object_unref (priv->page_setup);
2381       priv->page_setup = g_object_ref (page_setup);
2382
2383       g_object_notify (G_OBJECT (dialog), "page-setup");
2384     }
2385 }
2386
2387 /**
2388  * gtk_print_unix_dialog_get_page_setup:
2389  * @dialog: a #GtkPrintUnixDialog
2390  * 
2391  * Gets the page setup that is used by the #GtkPrintUnixDialog.
2392  * 
2393  * Returns: the page setup of @dialog.
2394  *
2395  * Since: 2.10
2396  */
2397 GtkPageSetup *
2398 gtk_print_unix_dialog_get_page_setup (GtkPrintUnixDialog *dialog)
2399 {
2400   g_return_val_if_fail (GTK_IS_PRINT_UNIX_DIALOG (dialog), NULL);
2401
2402   return dialog->priv->page_setup;
2403 }
2404
2405 /**
2406  * gtk_print_unix_dialog_set_current_page:
2407  * @dialog: a #GtkPrintUnixDialog
2408  * @current_page: the current page number.
2409  * 
2410  * Sets the current page number. If @current_page is not -1, this enables
2411  * the current page choice for the range of pages to print.
2412  *
2413  * Since: 2.10
2414  */
2415 void
2416 gtk_print_unix_dialog_set_current_page (GtkPrintUnixDialog *dialog,
2417                                         gint                current_page)
2418 {
2419   GtkPrintUnixDialogPrivate *priv;
2420
2421   g_return_if_fail (GTK_IS_PRINT_UNIX_DIALOG (dialog));
2422
2423   priv = dialog->priv;
2424
2425   if (priv->current_page != current_page)
2426     {
2427       priv->current_page = current_page;
2428
2429       if (priv->current_page_radio)
2430         gtk_widget_set_sensitive (priv->current_page_radio, current_page != -1);
2431
2432       g_object_notify (G_OBJECT (dialog), "current-page");
2433     }
2434 }
2435
2436 /**
2437  * gtk_print_unix_dialog_get_current_page:
2438  * @dialog: a #GtkPrintUnixDialog
2439  * 
2440  * Gets the current page of the #GtkPrintDialog.
2441  * 
2442  * Returns: the current page of @dialog
2443  * 
2444  * Since: 2.10
2445  */
2446 gint
2447 gtk_print_unix_dialog_get_current_page (GtkPrintUnixDialog *dialog)
2448 {
2449   g_return_val_if_fail (GTK_IS_PRINT_UNIX_DIALOG (dialog), -1);
2450
2451   return dialog->priv->current_page;
2452 }
2453
2454 static gboolean
2455 set_active_printer (GtkPrintUnixDialog *dialog,
2456                     const gchar        *printer_name)
2457 {
2458   GtkPrintUnixDialogPrivate *priv = dialog->priv;
2459   GtkTreeModel *model;
2460   GtkTreeIter iter, filter_iter;
2461   GtkTreeSelection *selection;
2462   GtkPrinter *printer;
2463
2464   model = GTK_TREE_MODEL (priv->printer_list);
2465
2466   if (gtk_tree_model_get_iter_first (model, &iter))
2467     {
2468       do
2469         {
2470           gtk_tree_model_get (GTK_TREE_MODEL (priv->printer_list), &iter,
2471                               PRINTER_LIST_COL_PRINTER_OBJ, &printer, -1);
2472           if (printer == NULL)
2473             continue;
2474           
2475           if (strcmp (gtk_printer_get_name (printer), printer_name) == 0)
2476             {
2477               gtk_tree_model_filter_convert_child_iter_to_iter (priv->printer_list_filter,
2478                                                                 &filter_iter, &iter);
2479               
2480               selection = gtk_tree_view_get_selection (GTK_TREE_VIEW (priv->printer_treeview));
2481               priv->internal_printer_change = TRUE;
2482               gtk_tree_selection_select_iter (selection, &filter_iter);
2483               priv->internal_printer_change = FALSE;
2484               g_free (priv->waiting_for_printer);
2485               priv->waiting_for_printer = NULL;
2486               
2487               g_object_unref (printer);
2488               return TRUE;
2489             }
2490               
2491           g_object_unref (printer);
2492           
2493         } while (gtk_tree_model_iter_next (model, &iter));
2494     }
2495   
2496   return FALSE;
2497 }
2498
2499 /**
2500  * gtk_print_unix_dialog_set_settings:
2501  * @dialog: a #GtkPrintUnixDialog
2502  * @settings: a #GtkPrintSettings, or %NULL
2503  * 
2504  * Sets the #GtkPrintSettings for the #GtkPrintUnixDialog. Typically,
2505  * this is used to restore saved print settings from a previous print
2506  * operation before the print dialog is shown.
2507  * 
2508  * Since: 2.10
2509  **/
2510 void
2511 gtk_print_unix_dialog_set_settings (GtkPrintUnixDialog *dialog,
2512                                     GtkPrintSettings   *settings)
2513 {
2514   GtkPrintUnixDialogPrivate *priv;
2515   const char *printer;
2516   GtkPageRange *ranges;
2517   int num_ranges;
2518   
2519   g_return_if_fail (GTK_IS_PRINT_UNIX_DIALOG (dialog));
2520   g_return_if_fail (settings == NULL || GTK_IS_PRINT_SETTINGS (settings));
2521
2522   priv = dialog->priv;
2523
2524   if (settings != NULL)
2525     {
2526       dialog_set_collate (dialog, gtk_print_settings_get_collate (settings));
2527       dialog_set_reverse (dialog, gtk_print_settings_get_reverse (settings));
2528       dialog_set_n_copies (dialog, gtk_print_settings_get_num_copies (settings));
2529       dialog_set_scale (dialog, gtk_print_settings_get_scale (settings));
2530       dialog_set_page_set (dialog, gtk_print_settings_get_page_set (settings));
2531       dialog_set_print_pages (dialog, gtk_print_settings_get_print_pages (settings));
2532       ranges = gtk_print_settings_get_page_ranges (settings, &num_ranges);
2533       if (ranges)
2534         dialog_set_page_ranges (dialog, ranges, num_ranges);
2535
2536       priv->format_for_printer =
2537         g_strdup (gtk_print_settings_get (settings, "format-for-printer"));
2538     }
2539
2540   if (priv->initial_settings)
2541     g_object_unref (priv->initial_settings);
2542
2543   priv->initial_settings = settings;
2544
2545   g_free (priv->waiting_for_printer);
2546   priv->waiting_for_printer = NULL;
2547   
2548   if (settings)
2549     {
2550       g_object_ref (settings);
2551
2552       printer = gtk_print_settings_get_printer (settings);
2553       
2554       if (printer && !set_active_printer (dialog, printer))
2555         priv->waiting_for_printer = g_strdup (printer); 
2556     }
2557
2558   g_object_notify (G_OBJECT (dialog), "print-settings");
2559 }
2560
2561 /**
2562  * gtk_print_unix_dialog_get_settings:
2563  * @dialog: a #GtkPrintUnixDialog
2564  * 
2565  * Gets a new #GtkPrintSettings object that represents the
2566  * current values in the print dialog. Note that this creates a
2567  * <emphasis>new object</emphasis>, and you need to unref it
2568  * if don't want to keep it.
2569  * 
2570  * Returns: a new #GtkPrintSettings object with the values from @dialog
2571  *
2572  * Since: 2.10
2573  */
2574 GtkPrintSettings *
2575 gtk_print_unix_dialog_get_settings (GtkPrintUnixDialog *dialog)
2576 {
2577   GtkPrintUnixDialogPrivate *priv;
2578   GtkPrintSettings *settings;
2579   GtkPrintPages print_pages;
2580   GtkPageRange *ranges;
2581   int n_ranges;
2582
2583   g_return_val_if_fail (GTK_IS_PRINT_UNIX_DIALOG (dialog), NULL);
2584
2585   priv = dialog->priv;
2586   settings = gtk_print_settings_new ();
2587
2588   if (priv->current_printer)
2589     gtk_print_settings_set_printer (settings,
2590                                     gtk_printer_get_name (priv->current_printer));
2591   else
2592     gtk_print_settings_set_printer (settings, "default");
2593   
2594   gtk_print_settings_set (settings, "format-for-printer",
2595                           priv->format_for_printer);
2596
2597   
2598   gtk_print_settings_set_collate (settings,
2599                                   dialog_get_collate (dialog));
2600   
2601   gtk_print_settings_set_reverse (settings,
2602                                   dialog_get_reverse (dialog));
2603   
2604   gtk_print_settings_set_num_copies (settings,
2605                                      dialog_get_n_copies (dialog));
2606
2607   gtk_print_settings_set_scale (settings,
2608                                 dialog_get_scale (dialog));
2609   
2610   gtk_print_settings_set_page_set (settings,
2611                                    dialog_get_page_set (dialog));
2612   
2613   print_pages = dialog_get_print_pages (dialog);
2614   gtk_print_settings_set_print_pages (settings, print_pages);
2615
2616   ranges = dialog_get_page_ranges (dialog, &n_ranges);
2617   if (ranges)
2618     {
2619       gtk_print_settings_set_page_ranges  (settings, ranges, n_ranges);
2620       g_free (ranges);
2621     }
2622
2623   /* TODO: print when. How to handle? */
2624
2625   if (priv->current_printer)
2626     _gtk_printer_get_settings_from_options (priv->current_printer,
2627                                             priv->options,
2628                                             settings);
2629   
2630   return settings;
2631 }
2632
2633
2634 #define __GTK_PRINT_UNIX_DIALOG_C__
2635 #include "gtkaliasdef.c"