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