]> Pileus Git - ~andy/gtk/blob - gtk/gtkprintunixdialog.c
Add paper size combo and orientation combo to print dialog
[~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  * Copyright © 2006, 2007 Christian Persch
5  *
6  * This library is free software; you can redistribute it and/or
7  * modify it under the terms of the GNU Lesser General Public
8  * License as published by the Free Software Foundation; either
9  * version 2 of the License, or (at your option) any later version.
10  *
11  * This library is distributed in the hope that it will be useful,
12  * but WITHOUT ANY WARRANTY; without even the implied warranty of
13  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
14  * Lesser General Public License for more details.
15  *
16  * You should have received a copy of the GNU Lesser General Public
17  * License along with this library; if not, write to the
18  * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
19  * Boston, MA 02111-1307, USA.
20  */
21
22 #include "config.h"
23 #include <stdlib.h>
24 #include <string.h>
25 #include <ctype.h>
26 #include <stdio.h>
27 #include <math.h>
28
29 #include "gtkintl.h"
30 #include "gtkprivate.h"
31
32 #include "gtkspinbutton.h"
33 #include "gtkcellrendererpixbuf.h"
34 #include "gtkcellrenderertext.h"
35 #include "gtkstock.h"
36 #include "gtkiconfactory.h"
37 #include "gtkimage.h"
38 #include "gtktreeselection.h"
39 #include "gtknotebook.h"
40 #include "gtkscrolledwindow.h"
41 #include "gtkcombobox.h"
42 #include "gtktogglebutton.h"
43 #include "gtkradiobutton.h"
44 #include "gtkdrawingarea.h"
45 #include "gtkvbox.h"
46 #include "gtktable.h"
47 #include "gtkframe.h"
48 #include "gtkalignment.h"
49 #include "gtklabel.h"
50 #include "gtkeventbox.h"
51 #include "gtkbuildable.h"
52
53 #include "gtkcustompaperunixdialog.h"
54 #include "gtkprintbackend.h"
55 #include "gtkprinter-private.h"
56 #include "gtkprintunixdialog.h"
57 #include "gtkprinteroptionwidget.h"
58 #include "gtkprintutils.h"
59 #include "gtkalias.h"
60
61 #include "gtkmessagedialog.h"
62 #include "gtkbutton.h"
63
64 #define EXAMPLE_PAGE_AREA_SIZE 140
65 #define RULER_DISTANCE 7.5
66 #define RULER_RADIUS 2
67
68
69 #define GTK_PRINT_UNIX_DIALOG_GET_PRIVATE(o)  \
70    (G_TYPE_INSTANCE_GET_PRIVATE ((o), GTK_TYPE_PRINT_UNIX_DIALOG, GtkPrintUnixDialogPrivate))
71
72 static void     gtk_print_unix_dialog_destroy      (GtkPrintUnixDialog *dialog);
73 static void     gtk_print_unix_dialog_finalize     (GObject            *object);
74 static void     gtk_print_unix_dialog_set_property (GObject            *object,
75                                                     guint               prop_id,
76                                                     const GValue       *value,
77                                                     GParamSpec         *pspec);
78 static void     gtk_print_unix_dialog_get_property (GObject            *object,
79                                                     guint               prop_id,
80                                                     GValue             *value,
81                                                     GParamSpec         *pspec);
82 static void     gtk_print_unix_dialog_style_set    (GtkWidget          *widget,
83                                                     GtkStyle           *previous_style);
84 static void     populate_dialog                    (GtkPrintUnixDialog *dialog);
85 static void     unschedule_idle_mark_conflicts     (GtkPrintUnixDialog *dialog);
86 static void     selected_printer_changed           (GtkTreeSelection   *selection,
87                                                     GtkPrintUnixDialog *dialog);
88 static void     clear_per_printer_ui               (GtkPrintUnixDialog *dialog);
89 static void     printer_added_cb                   (GtkPrintBackend    *backend,
90                                                     GtkPrinter         *printer,
91                                                     GtkPrintUnixDialog *dialog);
92 static void     printer_removed_cb                 (GtkPrintBackend    *backend,
93                                                     GtkPrinter         *printer,
94                                                     GtkPrintUnixDialog *dialog);
95 static void     printer_status_cb                  (GtkPrintBackend    *backend,
96                                                     GtkPrinter         *printer,
97                                                     GtkPrintUnixDialog *dialog);
98 static void     update_collate_icon                (GtkToggleButton    *toggle_button,
99                                                     GtkPrintUnixDialog *dialog);
100 static gboolean dialog_get_collate                 (GtkPrintUnixDialog *dialog);
101 static gboolean dialog_get_reverse                 (GtkPrintUnixDialog *dialog);
102 static gint     dialog_get_n_copies                (GtkPrintUnixDialog *dialog);
103
104 static void     set_cell_sensitivity_func          (GtkTreeViewColumn *tree_column,
105                                                     GtkCellRenderer   *cell,
106                                                     GtkTreeModel      *model,
107                                                     GtkTreeIter       *iter,
108                                                     gpointer           data);
109 static gboolean set_active_printer                 (GtkPrintUnixDialog *dialog,
110                                                     const gchar        *printer_name);
111 static void redraw_page_layout_preview             (GtkPrintUnixDialog *dialog);
112
113 /* GtkBuildable */
114 static void gtk_print_unix_dialog_buildable_init                    (GtkBuildableIface *iface);
115 static GObject *gtk_print_unix_dialog_buildable_get_internal_child  (GtkBuildable *buildable,
116                                                                      GtkBuilder   *builder,
117                                                                      const gchar  *childname);
118
119 static const gchar const common_paper_sizes[][16] = {
120   "na_letter",
121   "na_legal",
122   "iso_a4",
123   "iso_a5",
124   "roc_16k",
125   "iso_b5",
126   "jis_b5",
127   "na_number-10",
128   "iso_dl",
129   "jpn_chou3",
130   "na_ledger",
131   "iso_a3",
132 };
133
134 enum {
135   PAGE_SETUP_LIST_COL_PAGE_SETUP,
136   PAGE_SETUP_LIST_COL_IS_SEPARATOR,
137   PAGE_SETUP_LIST_N_COLS
138 };
139
140 enum {
141   PROP_0,
142   PROP_PAGE_SETUP,
143   PROP_CURRENT_PAGE,
144   PROP_PRINT_SETTINGS,
145   PROP_SELECTED_PRINTER,
146   PROP_MANUAL_CAPABILITIES,
147   PROP_SUPPORT_SELECTION,
148   PROP_HAS_SELECTION,
149   PROP_EMBED_PAGE_SETUP
150 };
151
152 enum {
153   PRINTER_LIST_COL_ICON,
154   PRINTER_LIST_COL_NAME,
155   PRINTER_LIST_COL_STATE,
156   PRINTER_LIST_COL_JOBS,
157   PRINTER_LIST_COL_LOCATION,
158   PRINTER_LIST_COL_PRINTER_OBJ,
159   PRINTER_LIST_N_COLS
160 };
161
162 struct GtkPrintUnixDialogPrivate
163 {
164   GtkWidget *notebook;
165
166   GtkWidget *printer_treeview;
167
168   GtkPrintCapabilities manual_capabilities;
169   GtkPrintCapabilities printer_capabilities;
170
171   GtkTreeModel *printer_list;
172   GtkTreeModelFilter *printer_list_filter;
173
174   GtkPageSetup *page_setup;
175   gboolean page_setup_set;
176   gboolean embed_page_setup;
177   GtkListStore *page_setup_list;
178   GtkListStore *custom_paper_list;
179
180   gboolean support_selection;
181   gboolean has_selection;
182
183   GtkWidget *all_pages_radio;
184   GtkWidget *current_page_radio;
185   GtkWidget *selection_radio;
186   GtkWidget *range_table;
187   GtkWidget *page_range_radio;
188   GtkWidget *page_range_entry;
189
190   GtkWidget *copies_spin;
191   GtkWidget *collate_check;
192   GtkWidget *reverse_check;
193   GtkWidget *collate_image;
194   GtkWidget *page_layout_preview;
195   GtkWidget *scale_spin;
196   GtkWidget *page_set_combo;
197   GtkWidget *print_now_radio;
198   GtkWidget *print_at_radio;
199   GtkWidget *print_at_entry;
200   GtkWidget *print_hold_radio;
201   GtkWidget *preview_button;
202   GtkWidget *paper_size_combo;
203   GtkWidget *paper_size_combo_label;
204   GtkWidget *orientation_combo;
205   GtkWidget *orientation_combo_label;
206   gboolean internal_page_setup_change;
207   gboolean updating_print_at;
208   GtkPrinterOptionWidget *pages_per_sheet;
209   GtkPrinterOptionWidget *duplex;
210   GtkPrinterOptionWidget *paper_type;
211   GtkPrinterOptionWidget *paper_source;
212   GtkPrinterOptionWidget *output_tray;
213   GtkPrinterOptionWidget *job_prio;
214   GtkPrinterOptionWidget *billing_info;
215   GtkPrinterOptionWidget *cover_before;
216   GtkPrinterOptionWidget *cover_after;
217   GtkPrinterOptionWidget *number_up_layout;
218
219   GtkWidget *conflicts_widget;
220
221   GtkWidget *job_page;
222   GtkWidget *finishing_table;
223   GtkWidget *finishing_page;
224   GtkWidget *image_quality_table;
225   GtkWidget *image_quality_page;
226   GtkWidget *color_table;
227   GtkWidget *color_page;
228
229   GtkWidget *advanced_vbox;
230   GtkWidget *advanced_page;
231
232   GtkWidget *extension_point;
233
234   /* These are set initially on selected printer (either default printer,
235    * printer taken from set settings, or user-selected), but when any
236    * setting is changed by the user it is cleared.
237    */
238   GtkPrintSettings *initial_settings;
239
240   GtkPrinterOption *number_up_layout_n_option;
241   GtkPrinterOption *number_up_layout_2_option;
242
243   /* This is the initial printer set by set_settings. We look for it in
244    * the added printers. We clear this whenever the user manually changes
245    * to another printer, when the user changes a setting or when we find
246    * this printer.
247    */
248   char *waiting_for_printer;
249   gboolean internal_printer_change;
250
251   GList *print_backends;
252
253   GtkPrinter *current_printer;
254   GtkPrinter *request_details_printer;
255   guint request_details_tag;
256   GtkPrinterOptionSet *options;
257   gulong options_changed_handler;
258   gulong mark_conflicts_id;
259
260   gchar *format_for_printer;
261
262   gint current_page;
263 };
264
265 G_DEFINE_TYPE_WITH_CODE (GtkPrintUnixDialog, gtk_print_unix_dialog, GTK_TYPE_DIALOG,
266                          G_IMPLEMENT_INTERFACE (GTK_TYPE_BUILDABLE,
267                                                 gtk_print_unix_dialog_buildable_init))
268
269 static GtkBuildableIface *parent_buildable_iface;
270
271 static gboolean
272 is_default_printer (GtkPrintUnixDialog *dialog,
273                     GtkPrinter         *printer)
274 {
275   GtkPrintUnixDialogPrivate *priv = dialog->priv;
276
277   if (priv->format_for_printer)
278     return strcmp (priv->format_for_printer,
279                    gtk_printer_get_name (printer)) == 0;
280  else
281    return gtk_printer_is_default (printer);
282 }
283
284 static void
285 gtk_print_unix_dialog_class_init (GtkPrintUnixDialogClass *class)
286 {
287   GObjectClass *object_class;
288   GtkWidgetClass *widget_class;
289
290   object_class = (GObjectClass *) class;
291   widget_class = (GtkWidgetClass *) class;
292
293   object_class->finalize = gtk_print_unix_dialog_finalize;
294   object_class->set_property = gtk_print_unix_dialog_set_property;
295   object_class->get_property = gtk_print_unix_dialog_get_property;
296
297   widget_class->style_set = gtk_print_unix_dialog_style_set;
298
299   g_object_class_install_property (object_class,
300                                    PROP_PAGE_SETUP,
301                                    g_param_spec_object ("page-setup",
302                                                         P_("Page Setup"),
303                                                         P_("The GtkPageSetup to use"),
304                                                         GTK_TYPE_PAGE_SETUP,
305                                                         GTK_PARAM_READWRITE));
306
307   g_object_class_install_property (object_class,
308                                    PROP_CURRENT_PAGE,
309                                    g_param_spec_int ("current-page",
310                                                      P_("Current Page"),
311                                                      P_("The current page in the document"),
312                                                      -1,
313                                                      G_MAXINT,
314                                                      -1,
315                                                      GTK_PARAM_READWRITE));
316
317   g_object_class_install_property (object_class,
318                                    PROP_PRINT_SETTINGS,
319                                    g_param_spec_object ("print-settings",
320                                                         P_("Print Settings"),
321                                                         P_("The GtkPrintSettings used for initializing the dialog"),
322                                                         GTK_TYPE_PRINT_SETTINGS,
323                                                         GTK_PARAM_READWRITE));
324
325   g_object_class_install_property (object_class,
326                                    PROP_SELECTED_PRINTER,
327                                    g_param_spec_object ("selected-printer",
328                                                         P_("Selected Printer"),
329                                                         P_("The GtkPrinter which is selected"),
330                                                         GTK_TYPE_PRINTER,
331                                                         GTK_PARAM_READABLE));
332
333   g_object_class_install_property (object_class,
334                                    PROP_MANUAL_CAPABILITIES,
335                                    g_param_spec_flags ("manual-capabilities",
336                                                        P_("Manual Capabilites"),
337                                                        P_("Capabilities the application can handle"),
338                                                        GTK_TYPE_PRINT_CAPABILITIES,
339                                                        0,
340                                                        GTK_PARAM_READWRITE));
341
342   g_object_class_install_property (object_class,
343                                    PROP_SUPPORT_SELECTION,
344                                    g_param_spec_boolean ("support-selection",
345                                                          P_("Support Selection"),
346                                                          P_("Whether the dialog supports selection"),
347                                                          FALSE,
348                                                          GTK_PARAM_READWRITE));
349
350   g_object_class_install_property (object_class,
351                                    PROP_HAS_SELECTION,
352                                    g_param_spec_boolean ("has-selection",
353                                                          P_("Has Selection"),
354                                                          P_("Whether the application has a selection"),
355                                                          FALSE,
356                                                          GTK_PARAM_READWRITE));
357
358    g_object_class_install_property (object_class,
359                                    PROP_EMBED_PAGE_SETUP,
360                                    g_param_spec_boolean ("embed-page-setup",
361                                                          P_("Embed Page Setup"),
362                                                          P_("TRUE if page setup combos are embedded in GtkPrintUnixDialog"),
363                                                          FALSE,
364                                                          GTK_PARAM_READWRITE));
365
366   g_type_class_add_private (class, sizeof (GtkPrintUnixDialogPrivate));
367 }
368
369 /* Returns a toplevel GtkWindow, or NULL if none */
370 static GtkWindow *
371 get_toplevel (GtkWidget *widget)
372 {
373   GtkWidget *toplevel = NULL;
374
375   toplevel = gtk_widget_get_toplevel (widget);
376   if (!GTK_WIDGET_TOPLEVEL (toplevel))
377     return NULL;
378   else
379     return GTK_WINDOW (toplevel);
380 }
381
382 static void
383 add_custom_button_to_dialog (GtkDialog   *dialog,
384                              const gchar *mnemonic_label,
385                              const gchar *stock_id,
386                              gint         response_id)
387 {
388   GtkWidget *button = NULL;
389
390   button = gtk_button_new_with_mnemonic (mnemonic_label);
391   GTK_WIDGET_SET_FLAGS (button, GTK_CAN_DEFAULT);
392   gtk_button_set_image (GTK_BUTTON (button),
393                         gtk_image_new_from_stock (stock_id,
394                                                   GTK_ICON_SIZE_BUTTON));
395   gtk_widget_show (button);
396
397   gtk_dialog_add_action_widget (GTK_DIALOG (dialog), button, response_id);
398 }
399
400 /* This function handles error messages before printing.
401  */
402 static gboolean
403 error_dialogs (GtkPrintUnixDialog *print_dialog,
404                gint                print_dialog_response_id,
405                gpointer            data)
406 {
407   GtkPrintUnixDialogPrivate *priv = print_dialog->priv;
408   GtkPrinterOption          *option = NULL;
409   GtkPrinter                *printer = NULL;
410   GtkWindow                 *toplevel = NULL;
411   GtkWidget                 *dialog = NULL;
412   GFile                     *file = NULL;
413   gchar                     *basename = NULL;
414   gchar                     *dirname = NULL;
415   int                        response;
416
417   if (print_dialog != NULL && print_dialog_response_id == GTK_RESPONSE_OK)
418     {
419       printer = gtk_print_unix_dialog_get_selected_printer (print_dialog);
420
421       /* Shows overwrite confirmation dialog in the case of printing to file which
422        * already exists. */
423       if (printer != NULL && gtk_printer_is_virtual (printer))
424         {
425           option = gtk_printer_option_set_lookup (priv->options,
426                                                   "gtk-main-page-custom-input");
427
428           if (option != NULL &&
429               option->type == GTK_PRINTER_OPTION_TYPE_FILESAVE)
430             {
431               file = g_file_new_for_uri (option->value);
432
433               if (file != NULL &&
434                   g_file_query_exists (file, NULL))
435                 {
436                   toplevel = get_toplevel (GTK_WIDGET (print_dialog));
437
438                   basename = g_file_get_basename (file);
439                   dirname = g_file_get_parse_name (g_file_get_parent (file));
440
441                   dialog = gtk_message_dialog_new (toplevel,
442                                                    GTK_DIALOG_MODAL |
443                                                    GTK_DIALOG_DESTROY_WITH_PARENT,
444                                                    GTK_MESSAGE_QUESTION,
445                                                    GTK_BUTTONS_NONE,
446                                                    _("A file named \"%s\" already exists.  Do you want to replace it?"),
447                                                    basename);
448
449                   gtk_message_dialog_format_secondary_text (GTK_MESSAGE_DIALOG (dialog),
450                                                             _("The file already exists in \"%s\".  Replacing it will "
451                                                             "overwrite its contents."),
452                                                             dirname);
453
454                   gtk_dialog_add_button (GTK_DIALOG (dialog),
455                                          GTK_STOCK_CANCEL, GTK_RESPONSE_CANCEL);
456                   add_custom_button_to_dialog (GTK_DIALOG (dialog),
457                                                _("_Replace"),
458                                                GTK_STOCK_PRINT,
459                                                GTK_RESPONSE_ACCEPT);
460                   gtk_dialog_set_alternative_button_order (GTK_DIALOG (dialog),
461                                                            GTK_RESPONSE_ACCEPT,
462                                                            GTK_RESPONSE_CANCEL,
463                                                            -1);
464                   gtk_dialog_set_default_response (GTK_DIALOG (dialog),
465                                                    GTK_RESPONSE_ACCEPT);
466
467                   if (toplevel->group)
468                     gtk_window_group_add_window (toplevel->group,
469                                                  GTK_WINDOW (dialog));
470
471                   response = gtk_dialog_run (GTK_DIALOG (dialog));
472
473                   gtk_widget_destroy (dialog);
474
475                   g_free (dirname);
476                   g_free (basename);
477
478                   if (response != GTK_RESPONSE_ACCEPT)
479                     {
480                       g_signal_stop_emission_by_name (print_dialog, "response");
481                       g_object_unref (file);
482                       return TRUE;
483                     }
484                 }
485
486               g_object_unref (file);
487             }
488         }
489     }
490   return FALSE;
491 }
492
493 static void
494 gtk_print_unix_dialog_init (GtkPrintUnixDialog *dialog)
495 {
496   GtkPrintUnixDialogPrivate *priv = dialog->priv;
497
498   priv = dialog->priv = GTK_PRINT_UNIX_DIALOG_GET_PRIVATE (dialog);
499   priv->print_backends = NULL;
500   priv->current_page = -1;
501   priv->number_up_layout_n_option = NULL;
502   priv->number_up_layout_2_option = NULL;
503
504   priv->page_setup = gtk_page_setup_new ();
505   priv->page_setup_set = FALSE;
506   priv->embed_page_setup = FALSE;
507   priv->internal_page_setup_change = FALSE;
508
509   priv->support_selection = FALSE;
510   priv->has_selection = FALSE;
511
512   g_signal_connect (dialog,
513                     "destroy",
514                     (GCallback) gtk_print_unix_dialog_destroy,
515                     NULL);
516
517   g_signal_connect (dialog,
518                     "response",
519                     (GCallback) error_dialogs,
520                     NULL);
521
522   g_signal_connect (dialog,
523                     "notify::page-setup",
524                     (GCallback) redraw_page_layout_preview,
525                     NULL);
526
527   priv->preview_button = gtk_button_new_from_stock (GTK_STOCK_PRINT_PREVIEW);
528   gtk_widget_show (priv->preview_button);
529
530   gtk_dialog_add_action_widget (GTK_DIALOG (dialog),
531                                 priv->preview_button,
532                                 GTK_RESPONSE_APPLY);
533   gtk_dialog_add_buttons (GTK_DIALOG (dialog),
534                           GTK_STOCK_CANCEL, GTK_RESPONSE_CANCEL,
535                           GTK_STOCK_PRINT, GTK_RESPONSE_OK,
536                           NULL);
537   gtk_dialog_set_alternative_button_order (GTK_DIALOG (dialog),
538                                            GTK_RESPONSE_APPLY,
539                                            GTK_RESPONSE_OK,
540                                            GTK_RESPONSE_CANCEL,
541                                            -1);
542
543   gtk_dialog_set_default_response (GTK_DIALOG (dialog), GTK_RESPONSE_OK);
544   gtk_dialog_set_response_sensitive (GTK_DIALOG (dialog), GTK_RESPONSE_OK, FALSE);
545
546   priv->page_setup_list = gtk_list_store_new (PAGE_SETUP_LIST_N_COLS,
547                                               G_TYPE_OBJECT,
548                                               G_TYPE_BOOLEAN);
549
550   priv->custom_paper_list = gtk_list_store_new (1, G_TYPE_OBJECT);
551   _gtk_print_load_custom_papers (priv->custom_paper_list);
552
553   populate_dialog (dialog);
554 }
555
556 static void
557 gtk_print_unix_dialog_destroy (GtkPrintUnixDialog *dialog)
558 {
559   /* Make sure we don't destroy custom widgets owned by the backends */
560   clear_per_printer_ui (dialog);
561 }
562
563 static void
564 disconnect_printer_details_request (GtkPrintUnixDialog *dialog)
565 {
566   GtkPrintUnixDialogPrivate *priv = dialog->priv;
567
568   if (priv->request_details_tag)
569     {
570       g_signal_handler_disconnect (priv->request_details_printer,
571                                    priv->request_details_tag);
572       priv->request_details_tag = 0;
573       g_object_unref (priv->request_details_printer);
574       priv->request_details_printer = NULL;
575     }
576 }
577
578 static void
579 gtk_print_unix_dialog_finalize (GObject *object)
580 {
581   GtkPrintUnixDialog *dialog = GTK_PRINT_UNIX_DIALOG (object);
582   GtkPrintUnixDialogPrivate *priv = dialog->priv;
583   GtkPrintBackend *backend;
584   GList *node;
585
586   unschedule_idle_mark_conflicts (dialog);
587   disconnect_printer_details_request (dialog);
588
589   if (priv->current_printer)
590     {
591       g_object_unref (priv->current_printer);
592       priv->current_printer = NULL;
593     }
594
595   if (priv->printer_list)
596     {
597       g_object_unref (priv->printer_list);
598       priv->printer_list = NULL;
599     }
600
601   if (priv->custom_paper_list)
602     {
603       g_object_unref (priv->custom_paper_list);
604       priv->custom_paper_list = NULL;
605     }
606
607   if (priv->printer_list_filter)
608     {
609       g_object_unref (priv->printer_list_filter);
610       priv->printer_list_filter = NULL;
611     }
612
613   if (priv->options)
614     {
615       g_object_unref (priv->options);
616       priv->options = NULL;
617     }
618
619   if (priv->number_up_layout_2_option)
620     {
621       priv->number_up_layout_2_option->choices[0] = NULL;
622       priv->number_up_layout_2_option->choices[1] = NULL;
623       g_free (priv->number_up_layout_2_option->choices_display[0]);
624       g_free (priv->number_up_layout_2_option->choices_display[1]);
625       priv->number_up_layout_2_option->choices_display[0] = NULL;
626       priv->number_up_layout_2_option->choices_display[1] = NULL;
627       g_object_unref (priv->number_up_layout_2_option);
628       priv->number_up_layout_2_option = NULL;
629     }
630
631   if (priv->number_up_layout_n_option)
632     {
633       g_object_unref (priv->number_up_layout_n_option);
634       priv->number_up_layout_n_option = NULL;
635     }
636
637  if (priv->page_setup)
638     {
639       g_object_unref (priv->page_setup);
640       priv->page_setup = NULL;
641     }
642
643   if (priv->initial_settings)
644     {
645       g_object_unref (priv->initial_settings);
646       priv->initial_settings = NULL;
647     }
648
649   g_free (priv->waiting_for_printer);
650   priv->waiting_for_printer = NULL;
651
652   g_free (priv->format_for_printer);
653   priv->format_for_printer = NULL;
654
655   for (node = priv->print_backends; node != NULL; node = node->next)
656     {
657       backend = GTK_PRINT_BACKEND (node->data);
658
659       g_signal_handlers_disconnect_by_func (backend, printer_added_cb, dialog);
660       g_signal_handlers_disconnect_by_func (backend, printer_removed_cb, dialog);
661       g_signal_handlers_disconnect_by_func (backend, printer_status_cb, dialog);
662
663       gtk_print_backend_destroy (backend);
664       g_object_unref (backend);
665     }
666
667   g_list_free (priv->print_backends);
668   priv->print_backends = NULL;
669
670   if (priv->page_setup_list)
671     {
672       g_object_unref (priv->page_setup_list);
673       priv->page_setup_list = NULL;
674     }
675
676   G_OBJECT_CLASS (gtk_print_unix_dialog_parent_class)->finalize (object);
677 }
678
679 static void
680 printer_removed_cb (GtkPrintBackend    *backend,
681                     GtkPrinter         *printer,
682                     GtkPrintUnixDialog *dialog)
683 {
684   GtkPrintUnixDialogPrivate *priv = dialog->priv;
685   GtkTreeIter *iter;
686
687   iter = g_object_get_data (G_OBJECT (printer), "gtk-print-tree-iter");
688   gtk_list_store_remove (GTK_LIST_STORE (priv->printer_list), iter);
689 }
690
691 static void
692 gtk_print_unix_dialog_buildable_init (GtkBuildableIface *iface)
693 {
694   parent_buildable_iface = g_type_interface_peek_parent (iface);
695
696   iface->get_internal_child = gtk_print_unix_dialog_buildable_get_internal_child;
697 }
698
699 static GObject *
700 gtk_print_unix_dialog_buildable_get_internal_child (GtkBuildable *buildable,
701                                                     GtkBuilder   *builder,
702                                                     const gchar  *childname)
703 {
704   if (strcmp (childname, "notebook") == 0)
705     return G_OBJECT (GTK_PRINT_UNIX_DIALOG (buildable)->priv->notebook);
706
707   return parent_buildable_iface->get_internal_child (buildable, builder, childname);
708 }
709
710 /* This function controls "sensitive" property of GtkCellRenderer based on pause
711  * state of printers. */
712 void set_cell_sensitivity_func (GtkTreeViewColumn *tree_column,
713                                 GtkCellRenderer   *cell,
714                                 GtkTreeModel      *tree_model,
715                                 GtkTreeIter       *iter,
716                                 gpointer           data)
717 {
718   GtkPrinter *printer;
719
720   gtk_tree_model_get (tree_model, iter, PRINTER_LIST_COL_PRINTER_OBJ, &printer, -1);
721
722   if (printer != NULL && !gtk_printer_is_accepting_jobs (printer))
723     g_object_set (cell,
724                   "sensitive", FALSE,
725                   NULL);
726   else
727     g_object_set (cell,
728                   "sensitive", TRUE,
729                   NULL);
730 }
731
732 static void
733 printer_status_cb (GtkPrintBackend    *backend,
734                    GtkPrinter         *printer,
735                    GtkPrintUnixDialog *dialog)
736 {
737   GtkPrintUnixDialogPrivate *priv = dialog->priv;
738   GtkTreeIter *iter;
739   GtkTreeSelection *selection;
740
741   iter = g_object_get_data (G_OBJECT (printer), "gtk-print-tree-iter");
742
743   gtk_list_store_set (GTK_LIST_STORE (priv->printer_list), iter,
744                       PRINTER_LIST_COL_ICON, gtk_printer_get_icon_name (printer),
745                       PRINTER_LIST_COL_STATE, gtk_printer_get_state_message (printer),
746                       PRINTER_LIST_COL_JOBS, gtk_printer_get_job_count (printer),
747                       PRINTER_LIST_COL_LOCATION, gtk_printer_get_location (printer),
748                       -1);
749
750   /* When the pause state change then we need to update sensitive property
751    * of GTK_RESPONSE_OK button inside of selected_printer_changed function. */
752   selection = gtk_tree_view_get_selection (GTK_TREE_VIEW (priv->printer_treeview));
753   selected_printer_changed (selection, dialog);
754
755   if (gtk_print_backend_printer_list_is_done (backend) &&
756       gtk_printer_is_default (printer) &&
757       (gtk_tree_selection_count_selected_rows (selection) == 0))
758     set_active_printer (dialog, gtk_printer_get_name (printer));
759 }
760
761 static void
762 printer_added_cb (GtkPrintBackend    *backend,
763                   GtkPrinter         *printer,
764                   GtkPrintUnixDialog *dialog)
765 {
766   GtkPrintUnixDialogPrivate *priv = dialog->priv;
767   GtkTreeIter iter, filter_iter;
768   GtkTreeSelection *selection;
769   GtkTreePath *path;
770
771   gtk_list_store_append (GTK_LIST_STORE (priv->printer_list), &iter);
772
773   g_object_set_data_full (G_OBJECT (printer),
774                          "gtk-print-tree-iter",
775                           gtk_tree_iter_copy (&iter),
776                           (GDestroyNotify) gtk_tree_iter_free);
777
778   gtk_list_store_set (GTK_LIST_STORE (priv->printer_list), &iter,
779                       PRINTER_LIST_COL_ICON, gtk_printer_get_icon_name (printer),
780                       PRINTER_LIST_COL_NAME, gtk_printer_get_name (printer),
781                       PRINTER_LIST_COL_STATE, gtk_printer_get_state_message (printer),
782                       PRINTER_LIST_COL_JOBS, gtk_printer_get_job_count (printer),
783                       PRINTER_LIST_COL_LOCATION, gtk_printer_get_location (printer),
784                       PRINTER_LIST_COL_PRINTER_OBJ, printer,
785                       -1);
786
787   gtk_tree_model_filter_convert_child_iter_to_iter (priv->printer_list_filter,
788                                                     &filter_iter, &iter);
789   path = gtk_tree_model_get_path (GTK_TREE_MODEL (priv->printer_list_filter), &filter_iter);
790
791   selection = gtk_tree_view_get_selection (GTK_TREE_VIEW (priv->printer_treeview));
792
793   if (priv->waiting_for_printer != NULL &&
794       strcmp (gtk_printer_get_name (printer),
795               priv->waiting_for_printer) == 0)
796     {
797       priv->internal_printer_change = TRUE;
798       gtk_tree_selection_select_iter (selection, &filter_iter);
799       gtk_tree_view_scroll_to_cell (GTK_TREE_VIEW (priv->printer_treeview),
800                                     path, NULL, TRUE, 0.5, 0.0);
801       priv->internal_printer_change = FALSE;
802       g_free (priv->waiting_for_printer);
803       priv->waiting_for_printer = NULL;
804     }
805   else if (is_default_printer (dialog, printer) &&
806            gtk_tree_selection_count_selected_rows (selection) == 0)
807     {
808       priv->internal_printer_change = TRUE;
809       gtk_tree_selection_select_iter (selection, &filter_iter);
810       gtk_tree_view_scroll_to_cell (GTK_TREE_VIEW (priv->printer_treeview),
811                                     path, NULL, TRUE, 0.5, 0.0);
812       priv->internal_printer_change = FALSE;
813     }
814
815   gtk_tree_path_free (path);
816 }
817
818 static void
819 printer_list_initialize (GtkPrintUnixDialog *dialog,
820                          GtkPrintBackend    *print_backend)
821 {
822   GList *list;
823   GList *node;
824
825   g_return_if_fail (print_backend != NULL);
826
827   g_signal_connect_object (print_backend,
828                            "printer-added",
829                            (GCallback) printer_added_cb,
830                            G_OBJECT (dialog), 0);
831
832   g_signal_connect_object (print_backend,
833                            "printer-removed",
834                            (GCallback) printer_removed_cb,
835                            G_OBJECT (dialog), 0);
836
837   g_signal_connect_object (print_backend,
838                            "printer-status-changed",
839                            (GCallback) printer_status_cb,
840                            G_OBJECT (dialog), 0);
841
842   list = gtk_print_backend_get_printer_list (print_backend);
843
844   node = list;
845   while (node != NULL)
846     {
847       printer_added_cb (print_backend, node->data, dialog);
848       node = node->next;
849     }
850
851   g_list_free (list);
852 }
853
854 static void
855 load_print_backends (GtkPrintUnixDialog *dialog)
856 {
857   GtkPrintUnixDialogPrivate *priv = dialog->priv;
858   GList *node;
859
860   if (g_module_supported ())
861     priv->print_backends = gtk_print_backend_load_modules ();
862
863   for (node = priv->print_backends; node != NULL; node = node->next)
864     {
865       GtkPrintBackend *backend = node->data;
866       printer_list_initialize (dialog, backend);
867     }
868 }
869
870 static void
871 gtk_print_unix_dialog_set_property (GObject      *object,
872                                     guint         prop_id,
873                                     const GValue *value,
874                                     GParamSpec   *pspec)
875
876 {
877   GtkPrintUnixDialog *dialog = GTK_PRINT_UNIX_DIALOG (object);
878
879   switch (prop_id)
880     {
881     case PROP_PAGE_SETUP:
882       gtk_print_unix_dialog_set_page_setup (dialog, g_value_get_object (value));
883       break;
884     case PROP_CURRENT_PAGE:
885       gtk_print_unix_dialog_set_current_page (dialog, g_value_get_int (value));
886       break;
887     case PROP_PRINT_SETTINGS:
888       gtk_print_unix_dialog_set_settings (dialog, g_value_get_object (value));
889       break;
890     case PROP_MANUAL_CAPABILITIES:
891       gtk_print_unix_dialog_set_manual_capabilities (dialog, g_value_get_flags (value));
892       break;
893     case PROP_SUPPORT_SELECTION:
894       gtk_print_unix_dialog_set_support_selection (dialog, g_value_get_boolean (value));
895       break;
896     case PROP_HAS_SELECTION:
897       gtk_print_unix_dialog_set_has_selection (dialog, g_value_get_boolean (value));
898       break;
899     case PROP_EMBED_PAGE_SETUP:
900       gtk_print_unix_dialog_set_embed_page_setup (dialog, g_value_get_boolean (value));
901       break;
902     default:
903       G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
904       break;
905     }
906 }
907
908 static void
909 gtk_print_unix_dialog_get_property (GObject    *object,
910                                     guint       prop_id,
911                                     GValue     *value,
912                                     GParamSpec *pspec)
913 {
914   GtkPrintUnixDialog *dialog = GTK_PRINT_UNIX_DIALOG (object);
915   GtkPrintUnixDialogPrivate *priv = dialog->priv;
916
917   switch (prop_id)
918     {
919     case PROP_PAGE_SETUP:
920       g_value_set_object (value, priv->page_setup);
921       break;
922     case PROP_CURRENT_PAGE:
923       g_value_set_int (value, priv->current_page);
924       break;
925     case PROP_PRINT_SETTINGS:
926       g_value_take_object (value, gtk_print_unix_dialog_get_settings (dialog));
927       break;
928     case PROP_SELECTED_PRINTER:
929       g_value_set_object (value, priv->current_printer);
930       break;
931     case PROP_MANUAL_CAPABILITIES:
932       g_value_set_flags (value, priv->manual_capabilities);
933       break;
934     case PROP_SUPPORT_SELECTION:
935       g_value_set_boolean (value, priv->support_selection);
936       break;
937     case PROP_HAS_SELECTION:
938       g_value_set_boolean (value, priv->has_selection);
939       break;
940     case PROP_EMBED_PAGE_SETUP:
941       g_value_set_boolean (value, priv->embed_page_setup);
942       break;
943     default:
944       G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
945       break;
946     }
947 }
948
949 static gboolean
950 is_printer_active (GtkTreeModel       *model,
951                    GtkTreeIter        *iter,
952                    GtkPrintUnixDialog *dialog)
953 {
954   gboolean result;
955   GtkPrinter *printer;
956   GtkPrintUnixDialogPrivate *priv = dialog->priv;
957
958   gtk_tree_model_get (model,
959                       iter,
960                       PRINTER_LIST_COL_PRINTER_OBJ,
961                       &printer,
962                       -1);
963
964   if (printer == NULL)
965     return FALSE;
966
967   result = gtk_printer_is_active (printer);
968
969   if (result &&
970       priv->manual_capabilities & (GTK_PRINT_CAPABILITY_GENERATE_PDF |
971                                    GTK_PRINT_CAPABILITY_GENERATE_PS))
972     {
973        /* Check that the printer can handle at least one of the data
974         * formats that the application supports.
975         */
976        result = ((priv->manual_capabilities & GTK_PRINT_CAPABILITY_GENERATE_PDF) &&
977                  gtk_printer_accepts_pdf (printer)) ||
978                 ((priv->manual_capabilities & GTK_PRINT_CAPABILITY_GENERATE_PS) &&
979                  gtk_printer_accepts_ps (printer));
980     }
981
982   g_object_unref (printer);
983
984   return result;
985 }
986
987 static gint
988 default_printer_list_sort_func (GtkTreeModel *model,
989                                 GtkTreeIter  *a,
990                                 GtkTreeIter  *b,
991                                 gpointer      user_data)
992 {
993   gchar *a_name;
994   gchar *b_name;
995   GtkPrinter *a_printer;
996   GtkPrinter *b_printer;
997   gint result;
998
999   gtk_tree_model_get (model, a,
1000                       PRINTER_LIST_COL_NAME, &a_name,
1001                       PRINTER_LIST_COL_PRINTER_OBJ, &a_printer,
1002                       -1);
1003   gtk_tree_model_get (model, b,
1004                       PRINTER_LIST_COL_NAME, &b_name,
1005                       PRINTER_LIST_COL_PRINTER_OBJ, &b_printer,
1006                       -1);
1007
1008   if (a_printer == NULL && b_printer == NULL)
1009     result = 0;
1010   else if (a_printer == NULL)
1011    result = G_MAXINT;
1012   else if (b_printer == NULL)
1013    result = G_MININT;
1014   else if (gtk_printer_is_virtual (a_printer) && gtk_printer_is_virtual (b_printer))
1015     result = 0;
1016   else if (gtk_printer_is_virtual (a_printer) && !gtk_printer_is_virtual (b_printer))
1017     result = G_MININT;
1018   else if (!gtk_printer_is_virtual (a_printer) && gtk_printer_is_virtual (b_printer))
1019     result = G_MAXINT;
1020   else if (a_name == NULL && b_name == NULL)
1021     result = 0;
1022   else if (a_name == NULL && b_name != NULL)
1023     result = 1;
1024   else if (a_name != NULL && b_name == NULL)
1025     result = -1;
1026   else
1027     result = g_ascii_strcasecmp (a_name, b_name);
1028
1029   g_free (a_name);
1030   g_free (b_name);
1031   g_object_unref (a_printer);
1032   g_object_unref (b_printer);
1033
1034   return result;
1035 }
1036
1037 static void
1038 create_printer_list_model (GtkPrintUnixDialog *dialog)
1039 {
1040   GtkPrintUnixDialogPrivate *priv = dialog->priv;
1041   GtkListStore *model;
1042   GtkTreeSortable *sort;
1043
1044   model = gtk_list_store_new (PRINTER_LIST_N_COLS,
1045                               G_TYPE_STRING,
1046                               G_TYPE_STRING,
1047                               G_TYPE_STRING,
1048                               G_TYPE_INT,
1049                               G_TYPE_STRING,
1050                               G_TYPE_OBJECT);
1051
1052   priv->printer_list = (GtkTreeModel *)model;
1053   priv->printer_list_filter = (GtkTreeModelFilter *) gtk_tree_model_filter_new ((GtkTreeModel *)model,
1054                                                                                         NULL);
1055
1056   gtk_tree_model_filter_set_visible_func (priv->printer_list_filter,
1057                                           (GtkTreeModelFilterVisibleFunc) is_printer_active,
1058                                           dialog,
1059                                           NULL);
1060
1061   sort = GTK_TREE_SORTABLE (model);
1062   gtk_tree_sortable_set_default_sort_func (sort,
1063                                            default_printer_list_sort_func,
1064                                            NULL,
1065                                            NULL);
1066
1067   gtk_tree_sortable_set_sort_column_id (sort,
1068                                         GTK_TREE_SORTABLE_DEFAULT_SORT_COLUMN_ID,
1069                                         GTK_SORT_ASCENDING);
1070
1071 }
1072
1073
1074 static GtkWidget *
1075 wrap_in_frame (const gchar *label,
1076                GtkWidget   *child)
1077 {
1078   GtkWidget *frame, *alignment, *label_widget;
1079   gchar *bold_text;
1080
1081   label_widget = gtk_label_new (NULL);
1082   gtk_misc_set_alignment (GTK_MISC (label_widget), 0.0, 0.5);
1083   gtk_widget_show (label_widget);
1084
1085   bold_text = g_markup_printf_escaped ("<b>%s</b>", label);
1086   gtk_label_set_markup (GTK_LABEL (label_widget), bold_text);
1087   g_free (bold_text);
1088
1089   frame = gtk_vbox_new (FALSE, 6);
1090   gtk_box_pack_start (GTK_BOX (frame), label_widget, FALSE, FALSE, 0);
1091
1092   alignment = gtk_alignment_new (0.0, 0.0, 1.0, 1.0);
1093   gtk_alignment_set_padding (GTK_ALIGNMENT (alignment),
1094                              0, 0, 12, 0);
1095   gtk_box_pack_start (GTK_BOX (frame), alignment, FALSE, FALSE, 0);
1096
1097   gtk_container_add (GTK_CONTAINER (alignment), child);
1098
1099   gtk_widget_show (frame);
1100   gtk_widget_show (alignment);
1101
1102   return frame;
1103 }
1104
1105 static gboolean
1106 setup_option (GtkPrintUnixDialog     *dialog,
1107               const gchar            *option_name,
1108               GtkPrinterOptionWidget *widget)
1109 {
1110   GtkPrintUnixDialogPrivate *priv = dialog->priv;
1111   GtkPrinterOption *option;
1112
1113   option = gtk_printer_option_set_lookup (priv->options, option_name);
1114   gtk_printer_option_widget_set_source (widget, option);
1115
1116   return option != NULL;
1117 }
1118
1119 static void
1120 add_option_to_extension_point (GtkPrinterOption *option,
1121                                gpointer          data)
1122 {
1123   GtkWidget *extension_point = data;
1124   GtkWidget *widget;
1125
1126   widget = gtk_printer_option_widget_new (option);
1127   gtk_widget_show (widget);
1128
1129   if (gtk_printer_option_widget_has_external_label (GTK_PRINTER_OPTION_WIDGET (widget)))
1130     {
1131       GtkWidget *label, *hbox;
1132
1133       label = gtk_printer_option_widget_get_external_label (GTK_PRINTER_OPTION_WIDGET (widget));
1134       gtk_widget_show (label);
1135       gtk_misc_set_alignment (GTK_MISC (label), 0.0, 0.5);
1136       gtk_label_set_mnemonic_widget (GTK_LABEL (label), widget);
1137
1138       hbox = gtk_hbox_new (FALSE, 12);
1139       gtk_box_pack_start (GTK_BOX (hbox), label, FALSE, FALSE, 0);
1140       gtk_box_pack_start (GTK_BOX (hbox), widget, FALSE, FALSE, 0);
1141       gtk_widget_show (hbox);
1142
1143       gtk_box_pack_start (GTK_BOX (extension_point), hbox, FALSE, FALSE, 0);
1144     }
1145   else
1146     gtk_box_pack_start (GTK_BOX (extension_point), widget, FALSE, FALSE, 0);
1147 }
1148
1149 static void
1150 add_option_to_table (GtkPrinterOption *option,
1151                      gpointer          user_data)
1152 {
1153   GtkTable *table;
1154   GtkWidget *label, *widget;
1155   gint row;
1156
1157   table = GTK_TABLE (user_data);
1158
1159   if (g_str_has_prefix (option->name, "gtk-"))
1160     return;
1161
1162   widget = gtk_printer_option_widget_new (option);
1163   gtk_widget_show (widget);
1164
1165   row = table->nrows;
1166   gtk_table_resize (table, table->nrows + 1, 2);
1167
1168   if (gtk_printer_option_widget_has_external_label (GTK_PRINTER_OPTION_WIDGET (widget)))
1169     {
1170       label = gtk_printer_option_widget_get_external_label (GTK_PRINTER_OPTION_WIDGET (widget));
1171       gtk_widget_show (label);
1172
1173       gtk_misc_set_alignment (GTK_MISC (label), 0.0, 0.5);
1174       gtk_label_set_mnemonic_widget (GTK_LABEL (label), widget);
1175
1176       gtk_table_attach (table, label,
1177                         0, 1, row - 1 , row,  GTK_FILL, 0, 0, 0);
1178
1179       gtk_table_attach (table, widget,
1180                         1, 2, row - 1, row,  GTK_FILL, 0, 0, 0);
1181     }
1182   else
1183     gtk_table_attach (table, widget,
1184                       0, 2, row - 1, row,  GTK_FILL, 0, 0, 0);
1185 }
1186
1187 static void
1188 setup_page_table (GtkPrinterOptionSet *options,
1189                   const gchar         *group,
1190                   GtkWidget           *table,
1191                   GtkWidget           *page)
1192 {
1193   gtk_printer_option_set_foreach_in_group (options, group,
1194                                            add_option_to_table,
1195                                            table);
1196   if (GTK_TABLE (table)->nrows == 1)
1197     gtk_widget_hide (page);
1198   else
1199     gtk_widget_show (page);
1200 }
1201
1202 static void
1203 update_print_at_option (GtkPrintUnixDialog *dialog)
1204 {
1205   GtkPrintUnixDialogPrivate *priv = dialog->priv;
1206   GtkPrinterOption *option;
1207
1208   option = gtk_printer_option_set_lookup (priv->options, "gtk-print-time");
1209
1210   if (option == NULL)
1211     return;
1212
1213   if (priv->updating_print_at)
1214     return;
1215
1216   if (gtk_toggle_button_get_active (GTK_TOGGLE_BUTTON (priv->print_at_radio)))
1217     gtk_printer_option_set (option, "at");
1218   else if (gtk_toggle_button_get_active (GTK_TOGGLE_BUTTON (priv->print_hold_radio)))
1219     gtk_printer_option_set (option, "on-hold");
1220   else
1221     gtk_printer_option_set (option, "now");
1222
1223   option = gtk_printer_option_set_lookup (priv->options, "gtk-print-time-text");
1224   if (option != NULL)
1225     {
1226       const char *text = gtk_entry_get_text (GTK_ENTRY (priv->print_at_entry));
1227       gtk_printer_option_set (option, text);
1228     }
1229 }
1230
1231
1232 static gboolean
1233 setup_print_at (GtkPrintUnixDialog *dialog)
1234 {
1235   GtkPrintUnixDialogPrivate *priv = dialog->priv;
1236   GtkPrinterOption *option;
1237
1238   option = gtk_printer_option_set_lookup (priv->options, "gtk-print-time");
1239
1240   if (option == NULL)
1241     {
1242       gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (priv->print_now_radio),
1243                                     TRUE);
1244       gtk_widget_set_sensitive (priv->print_at_radio, FALSE);
1245       gtk_widget_set_sensitive (priv->print_at_entry, FALSE);
1246       gtk_widget_set_sensitive (priv->print_hold_radio, FALSE);
1247       gtk_entry_set_text (GTK_ENTRY (priv->print_at_entry), "");
1248       return FALSE;
1249     }
1250
1251   priv->updating_print_at = TRUE;
1252
1253   gtk_widget_set_sensitive (priv->print_at_entry, FALSE);
1254   gtk_widget_set_sensitive (priv->print_at_radio,
1255                             gtk_printer_option_has_choice (option, "at"));
1256
1257   gtk_widget_set_sensitive (priv->print_hold_radio,
1258                             gtk_printer_option_has_choice (option, "on-hold"));
1259
1260   update_print_at_option (dialog);
1261
1262   if (strcmp (option->value, "at") == 0)
1263     gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (priv->print_at_radio),
1264                                   TRUE);
1265   else if (strcmp (option->value, "on-hold") == 0)
1266     gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (priv->print_hold_radio),
1267                                   TRUE);
1268   else
1269     gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (priv->print_now_radio),
1270                                   TRUE);
1271
1272   option = gtk_printer_option_set_lookup (priv->options, "gtk-print-time-text");
1273   if (option != NULL)
1274     gtk_entry_set_text (GTK_ENTRY (priv->print_at_entry), option->value);
1275
1276   priv->updating_print_at = FALSE;
1277
1278   return TRUE;
1279 }
1280
1281 static void
1282 update_dialog_from_settings (GtkPrintUnixDialog *dialog)
1283 {
1284   GtkPrintUnixDialogPrivate *priv = dialog->priv;
1285   GList *groups, *l;
1286   gchar *group;
1287   GtkWidget *table, *frame;
1288   gboolean has_advanced, has_job;
1289
1290   if (priv->current_printer == NULL)
1291     {
1292        clear_per_printer_ui (dialog);
1293        gtk_widget_hide (priv->job_page);
1294        gtk_widget_hide (priv->advanced_page);
1295        gtk_widget_hide (priv->image_quality_page);
1296        gtk_widget_hide (priv->finishing_page);
1297        gtk_widget_hide (priv->color_page);
1298        gtk_dialog_set_response_sensitive (GTK_DIALOG (dialog), GTK_RESPONSE_OK, FALSE);
1299
1300        return;
1301     }
1302
1303   setup_option (dialog, "gtk-n-up", priv->pages_per_sheet);
1304   setup_option (dialog, "gtk-n-up-layout", priv->number_up_layout);
1305   setup_option (dialog, "gtk-duplex", priv->duplex);
1306   setup_option (dialog, "gtk-paper-type", priv->paper_type);
1307   setup_option (dialog, "gtk-paper-source", priv->paper_source);
1308   setup_option (dialog, "gtk-output-tray", priv->output_tray);
1309
1310   has_job = FALSE;
1311   has_job |= setup_option (dialog, "gtk-job-prio", priv->job_prio);
1312   has_job |= setup_option (dialog, "gtk-billing-info", priv->billing_info);
1313   has_job |= setup_option (dialog, "gtk-cover-before", priv->cover_before);
1314   has_job |= setup_option (dialog, "gtk-cover-after", priv->cover_after);
1315   has_job |= setup_print_at (dialog);
1316
1317   if (has_job)
1318     gtk_widget_show (priv->job_page);
1319   else
1320     gtk_widget_hide (priv->job_page);
1321
1322   setup_page_table (priv->options,
1323                     "ImageQualityPage",
1324                     priv->image_quality_table,
1325                     priv->image_quality_page);
1326
1327   setup_page_table (priv->options,
1328                     "FinishingPage",
1329                     priv->finishing_table,
1330                     priv->finishing_page);
1331
1332   setup_page_table (priv->options,
1333                     "ColorPage",
1334                     priv->color_table,
1335                     priv->color_page);
1336
1337   gtk_printer_option_set_foreach_in_group (priv->options,
1338                                            "GtkPrintDialogExtension",
1339                                            add_option_to_extension_point,
1340                                            priv->extension_point);
1341
1342   /* Put the rest of the groups in the advanced page */
1343   groups = gtk_printer_option_set_get_groups (priv->options);
1344
1345   has_advanced = FALSE;
1346   for (l = groups; l != NULL; l = l->next)
1347     {
1348       group = l->data;
1349
1350       if (group == NULL)
1351         continue;
1352
1353       if (strcmp (group, "ImageQualityPage") == 0 ||
1354           strcmp (group, "ColorPage") == 0 ||
1355           strcmp (group, "FinishingPage") == 0 ||
1356           strcmp (group, "GtkPrintDialogExtension") == 0)
1357         continue;
1358
1359       table = gtk_table_new (1, 2, FALSE);
1360       gtk_table_set_row_spacings (GTK_TABLE (table), 6);
1361       gtk_table_set_col_spacings (GTK_TABLE (table), 12);
1362
1363       gtk_printer_option_set_foreach_in_group (priv->options,
1364                                                group,
1365                                                add_option_to_table,
1366                                                table);
1367       if (GTK_TABLE (table)->nrows == 1)
1368         gtk_widget_destroy (table);
1369       else
1370         {
1371           has_advanced = TRUE;
1372           frame = wrap_in_frame (group, table);
1373           gtk_widget_show (table);
1374           gtk_widget_show (frame);
1375
1376           gtk_box_pack_start (GTK_BOX (priv->advanced_vbox),
1377                               frame, FALSE, FALSE, 0);
1378         }
1379     }
1380
1381   if (has_advanced)
1382     gtk_widget_show (priv->advanced_page);
1383   else
1384     gtk_widget_hide (priv->advanced_page);
1385
1386   g_list_foreach (groups, (GFunc) g_free, NULL);
1387   g_list_free (groups);
1388 }
1389
1390 static void
1391 update_dialog_from_capabilities (GtkPrintUnixDialog *dialog)
1392 {
1393   GtkPrintCapabilities caps;
1394   GtkPrintUnixDialogPrivate *priv = dialog->priv;
1395   gboolean can_collate;
1396   const gchar *copies;
1397
1398   copies = gtk_entry_get_text (GTK_ENTRY (priv->copies_spin));
1399   can_collate = (*copies != '\0' && atoi (copies) > 1);
1400
1401   caps = priv->manual_capabilities | priv->printer_capabilities;
1402
1403   gtk_widget_set_sensitive (priv->page_set_combo,
1404                             caps & GTK_PRINT_CAPABILITY_PAGE_SET);
1405   gtk_widget_set_sensitive (priv->copies_spin,
1406                             caps & GTK_PRINT_CAPABILITY_COPIES);
1407   gtk_widget_set_sensitive (priv->collate_check,
1408                             can_collate &&
1409                             (caps & GTK_PRINT_CAPABILITY_COLLATE));
1410   gtk_widget_set_sensitive (priv->reverse_check,
1411                             caps & GTK_PRINT_CAPABILITY_REVERSE);
1412   gtk_widget_set_sensitive (priv->scale_spin,
1413                             caps & GTK_PRINT_CAPABILITY_SCALE);
1414   gtk_widget_set_sensitive (GTK_WIDGET (priv->pages_per_sheet),
1415                             caps & GTK_PRINT_CAPABILITY_NUMBER_UP);
1416
1417   if (caps & GTK_PRINT_CAPABILITY_PREVIEW)
1418     gtk_widget_show (priv->preview_button);
1419   else
1420     gtk_widget_hide (priv->preview_button);
1421
1422   update_collate_icon (NULL, dialog);
1423
1424   gtk_tree_model_filter_refilter (priv->printer_list_filter);
1425 }
1426
1427 static gboolean
1428 page_setup_is_equal (GtkPageSetup *a, 
1429                      GtkPageSetup *b)
1430 {
1431   return
1432     gtk_paper_size_is_equal (gtk_page_setup_get_paper_size (a),
1433                              gtk_page_setup_get_paper_size (b)) &&
1434     gtk_page_setup_get_top_margin (a, GTK_UNIT_MM) == gtk_page_setup_get_top_margin (b, GTK_UNIT_MM) &&
1435     gtk_page_setup_get_bottom_margin (a, GTK_UNIT_MM) == gtk_page_setup_get_bottom_margin (b, GTK_UNIT_MM) &&
1436     gtk_page_setup_get_left_margin (a, GTK_UNIT_MM) == gtk_page_setup_get_left_margin (b, GTK_UNIT_MM) &&
1437     gtk_page_setup_get_right_margin (a, GTK_UNIT_MM) == gtk_page_setup_get_right_margin (b, GTK_UNIT_MM);
1438 }
1439
1440 static gboolean
1441 page_setup_is_same_size (GtkPageSetup *a,
1442                          GtkPageSetup *b)
1443 {
1444   return gtk_paper_size_is_equal (gtk_page_setup_get_paper_size (a),
1445                                   gtk_page_setup_get_paper_size (b));
1446 }
1447
1448 static gboolean
1449 set_paper_size (GtkPrintUnixDialog *dialog,
1450                 GtkPageSetup       *page_setup,
1451                 gboolean            size_only,
1452                 gboolean            add_item)
1453 {
1454   GtkPrintUnixDialogPrivate *priv = dialog->priv;
1455   GtkTreeModel *model;
1456   GtkTreeIter iter;
1457   GtkPageSetup *list_page_setup;
1458
1459   if (!priv->internal_page_setup_change)
1460     return TRUE;
1461
1462   if (page_setup == NULL)
1463     return FALSE;
1464
1465   model = GTK_TREE_MODEL (priv->page_setup_list);
1466
1467   if (gtk_tree_model_get_iter_first (model, &iter))
1468     {
1469       do
1470         {
1471           gtk_tree_model_get (GTK_TREE_MODEL (priv->page_setup_list), &iter,
1472                               PAGE_SETUP_LIST_COL_PAGE_SETUP, &list_page_setup, -1);
1473           if (list_page_setup == NULL)
1474             continue;
1475           
1476           if ((size_only && page_setup_is_same_size (page_setup, list_page_setup)) ||
1477               (!size_only && page_setup_is_equal (page_setup, list_page_setup)))
1478             {
1479               gtk_combo_box_set_active_iter (GTK_COMBO_BOX (priv->paper_size_combo),
1480                                              &iter);
1481               gtk_combo_box_set_active (GTK_COMBO_BOX (priv->orientation_combo),
1482                                         gtk_page_setup_get_orientation (page_setup));
1483               g_object_unref (list_page_setup);
1484               return TRUE;
1485             }
1486               
1487           g_object_unref (list_page_setup);
1488           
1489         } while (gtk_tree_model_iter_next (model, &iter));
1490     }
1491
1492   if (add_item)
1493     {
1494       gtk_list_store_append (priv->page_setup_list, &iter);
1495       gtk_list_store_set (priv->page_setup_list, &iter,
1496                           PAGE_SETUP_LIST_COL_IS_SEPARATOR, TRUE,
1497                           -1);
1498       gtk_list_store_append (priv->page_setup_list, &iter);
1499       gtk_list_store_set (priv->page_setup_list, &iter,
1500                           PAGE_SETUP_LIST_COL_PAGE_SETUP, page_setup,
1501                           -1);
1502       gtk_combo_box_set_active_iter (GTK_COMBO_BOX (priv->paper_size_combo),
1503                                      &iter);
1504       gtk_combo_box_set_active (GTK_COMBO_BOX (priv->orientation_combo),
1505                                 gtk_page_setup_get_orientation (page_setup));
1506       return TRUE;
1507     }
1508
1509   return FALSE;
1510 }
1511
1512 static void
1513 fill_custom_paper_sizes (GtkPrintUnixDialog *dialog)
1514 {
1515   GtkPrintUnixDialogPrivate *priv = dialog->priv;
1516   GtkTreeIter iter, paper_iter;
1517   GtkTreeModel *model;
1518
1519   model = GTK_TREE_MODEL (priv->custom_paper_list);
1520   if (gtk_tree_model_get_iter_first (model, &iter))
1521     {
1522       gtk_list_store_append (priv->page_setup_list, &paper_iter);
1523       gtk_list_store_set (priv->page_setup_list, &paper_iter,
1524                           PAGE_SETUP_LIST_COL_IS_SEPARATOR, TRUE,
1525                           -1);
1526       do
1527         {
1528           GtkPageSetup *page_setup;
1529           gtk_tree_model_get (model, &iter, 0, &page_setup, -1);
1530
1531           gtk_list_store_append (priv->page_setup_list, &paper_iter);
1532           gtk_list_store_set (priv->page_setup_list, &paper_iter,
1533                               PAGE_SETUP_LIST_COL_PAGE_SETUP, page_setup,
1534                               -1);
1535
1536           g_object_unref (page_setup);
1537         } while (gtk_tree_model_iter_next (model, &iter));
1538     }
1539   
1540   gtk_list_store_append (priv->page_setup_list, &paper_iter);
1541   gtk_list_store_set (priv->page_setup_list, &paper_iter,
1542                       PAGE_SETUP_LIST_COL_IS_SEPARATOR, TRUE,
1543                       -1);
1544   gtk_list_store_append (priv->page_setup_list, &paper_iter);
1545   gtk_list_store_set (priv->page_setup_list, &paper_iter,
1546                       PAGE_SETUP_LIST_COL_PAGE_SETUP, NULL,
1547                       -1);
1548 }
1549
1550 static void
1551 fill_paper_sizes (GtkPrintUnixDialog *dialog,
1552                   GtkPrinter         *printer)
1553 {
1554   GtkPrintUnixDialogPrivate *priv = dialog->priv;
1555   GList *list, *l;
1556   GtkPageSetup *page_setup;
1557   GtkPaperSize *paper_size;
1558   GtkTreeIter iter;
1559   gint i;
1560
1561   gtk_list_store_clear (priv->page_setup_list);
1562
1563   if (printer == NULL || (list = gtk_printer_list_papers (printer)) == NULL)
1564     {
1565       for (i = 0; i < G_N_ELEMENTS (common_paper_sizes); i++)
1566         {
1567           page_setup = gtk_page_setup_new ();
1568           paper_size = gtk_paper_size_new (common_paper_sizes[i]);
1569           gtk_page_setup_set_paper_size_and_default_margins (page_setup, paper_size);
1570           gtk_paper_size_free (paper_size);
1571
1572           gtk_list_store_append (priv->page_setup_list, &iter);
1573           gtk_list_store_set (priv->page_setup_list, &iter,
1574                               PAGE_SETUP_LIST_COL_PAGE_SETUP, page_setup,
1575                               -1);
1576           g_object_unref (page_setup);
1577         }
1578     }
1579   else
1580     {
1581       for (l = list; l != NULL; l = l->next)
1582         {
1583           page_setup = l->data;
1584           gtk_list_store_append (priv->page_setup_list, &iter);
1585           gtk_list_store_set (priv->page_setup_list, &iter,
1586                               PAGE_SETUP_LIST_COL_PAGE_SETUP, page_setup,
1587                               -1);
1588           g_object_unref (page_setup);
1589         }
1590       g_list_free (list);
1591     }
1592
1593   fill_custom_paper_sizes (dialog);
1594 }
1595
1596 static void
1597 update_paper_sizes (GtkPrintUnixDialog *dialog)
1598 {
1599   GtkPageSetup *current_page_setup = NULL;
1600   GtkPrinter   *printer;
1601
1602   printer = gtk_print_unix_dialog_get_selected_printer (dialog);
1603
1604   fill_paper_sizes (dialog, printer);
1605
1606   current_page_setup = gtk_page_setup_copy (gtk_print_unix_dialog_get_page_setup (dialog));
1607
1608   if (current_page_setup)
1609     {
1610       if (!set_paper_size (dialog, current_page_setup, FALSE, FALSE))
1611         set_paper_size (dialog, current_page_setup, TRUE, TRUE);
1612
1613       g_object_unref (current_page_setup);
1614     }
1615 }
1616
1617 static void
1618 mark_conflicts (GtkPrintUnixDialog *dialog)
1619 {
1620   GtkPrintUnixDialogPrivate *priv = dialog->priv;
1621   GtkPrinter *printer;
1622   gboolean have_conflict;
1623
1624   have_conflict = FALSE;
1625
1626   printer = priv->current_printer;
1627
1628   if (printer)
1629     {
1630
1631       g_signal_handler_block (priv->options,
1632                               priv->options_changed_handler);
1633
1634       gtk_printer_option_set_clear_conflicts (priv->options);
1635
1636       have_conflict = _gtk_printer_mark_conflicts (printer,
1637                                                    priv->options);
1638
1639       g_signal_handler_unblock (priv->options,
1640                                 priv->options_changed_handler);
1641     }
1642
1643   if (have_conflict)
1644     gtk_widget_show (priv->conflicts_widget);
1645   else
1646     gtk_widget_hide (priv->conflicts_widget);
1647 }
1648
1649 static gboolean
1650 mark_conflicts_callback (gpointer data)
1651 {
1652   GtkPrintUnixDialog *dialog = data;
1653   GtkPrintUnixDialogPrivate *priv = dialog->priv;
1654
1655   priv->mark_conflicts_id = 0;
1656
1657   mark_conflicts (dialog);
1658
1659   return FALSE;
1660 }
1661
1662 static void
1663 unschedule_idle_mark_conflicts (GtkPrintUnixDialog *dialog)
1664 {
1665   GtkPrintUnixDialogPrivate *priv = dialog->priv;
1666
1667   if (priv->mark_conflicts_id != 0)
1668     {
1669       g_source_remove (priv->mark_conflicts_id);
1670       priv->mark_conflicts_id = 0;
1671     }
1672 }
1673
1674 static void
1675 schedule_idle_mark_conflicts (GtkPrintUnixDialog *dialog)
1676 {
1677   GtkPrintUnixDialogPrivate *priv = dialog->priv;
1678
1679   if (priv->mark_conflicts_id != 0)
1680     return;
1681
1682   priv->mark_conflicts_id = gdk_threads_add_idle (mark_conflicts_callback,
1683                                         dialog);
1684 }
1685
1686 static void
1687 options_changed_cb (GtkPrintUnixDialog *dialog)
1688 {
1689   GtkPrintUnixDialogPrivate *priv = dialog->priv;
1690
1691   schedule_idle_mark_conflicts (dialog);
1692
1693   g_free (priv->waiting_for_printer);
1694   priv->waiting_for_printer = NULL;
1695 }
1696
1697 static void
1698 remove_custom_widget (GtkWidget    *widget,
1699                       GtkContainer *container)
1700 {
1701   gtk_container_remove (container, widget);
1702 }
1703
1704 static void
1705 extension_point_clear_children (GtkContainer *container)
1706 {
1707   gtk_container_foreach (container,
1708                          (GtkCallback)remove_custom_widget,
1709                          container);
1710 }
1711
1712 static void
1713 clear_per_printer_ui (GtkPrintUnixDialog *dialog)
1714 {
1715   GtkPrintUnixDialogPrivate *priv = dialog->priv;
1716
1717   gtk_container_foreach (GTK_CONTAINER (priv->finishing_table),
1718                          (GtkCallback)gtk_widget_destroy,
1719                          NULL);
1720   gtk_table_resize (GTK_TABLE (priv->finishing_table), 1, 2);
1721   gtk_container_foreach (GTK_CONTAINER (priv->image_quality_table),
1722                          (GtkCallback)gtk_widget_destroy,
1723                          NULL);
1724   gtk_table_resize (GTK_TABLE (priv->image_quality_table), 1, 2);
1725   gtk_container_foreach (GTK_CONTAINER (priv->color_table),
1726                          (GtkCallback)gtk_widget_destroy,
1727                          NULL);
1728   gtk_table_resize (GTK_TABLE (priv->color_table), 1, 2);
1729   gtk_container_foreach (GTK_CONTAINER (priv->advanced_vbox),
1730                          (GtkCallback)gtk_widget_destroy,
1731                          NULL);
1732   extension_point_clear_children (GTK_CONTAINER (priv->extension_point));
1733 }
1734
1735 static void
1736 printer_details_acquired (GtkPrinter         *printer,
1737                           gboolean            success,
1738                           GtkPrintUnixDialog *dialog)
1739 {
1740   GtkPrintUnixDialogPrivate *priv = dialog->priv;
1741
1742   disconnect_printer_details_request (dialog);
1743
1744   if (success)
1745     {
1746       GtkTreeSelection *selection;
1747       selection = gtk_tree_view_get_selection (GTK_TREE_VIEW (priv->printer_treeview));
1748
1749       selected_printer_changed (selection, dialog);
1750     }
1751 }
1752
1753 static void
1754 selected_printer_changed (GtkTreeSelection   *selection,
1755                           GtkPrintUnixDialog *dialog)
1756 {
1757   GtkPrintUnixDialogPrivate *priv = dialog->priv;
1758   GtkPrinter *printer;
1759   GtkTreeIter iter, filter_iter;
1760
1761   /* Whenever the user selects a printer we stop looking for
1762      the printer specified in the initial settings */
1763   if (priv->waiting_for_printer &&
1764       !priv->internal_printer_change)
1765     {
1766       g_free (priv->waiting_for_printer);
1767       priv->waiting_for_printer = NULL;
1768     }
1769
1770   disconnect_printer_details_request (dialog);
1771
1772   printer = NULL;
1773   if (gtk_tree_selection_get_selected (selection, NULL, &filter_iter))
1774     {
1775       gtk_tree_model_filter_convert_iter_to_child_iter (priv->printer_list_filter,
1776                                                         &iter,
1777                                                         &filter_iter);
1778
1779       gtk_tree_model_get (priv->printer_list, &iter,
1780                           PRINTER_LIST_COL_PRINTER_OBJ, &printer,
1781                           -1);
1782     }
1783
1784   /* sets GTK_RESPONSE_OK button sensitivity depending on whether the printer
1785    * accepts/rejects jobs
1786    */
1787   if (printer != NULL)
1788     {
1789       if (!gtk_printer_is_accepting_jobs (printer))
1790         {
1791           gtk_dialog_set_response_sensitive (GTK_DIALOG (dialog), GTK_RESPONSE_OK, FALSE);
1792         }
1793       else
1794         {
1795           if (priv->current_printer == printer && gtk_printer_has_details (printer))
1796             gtk_dialog_set_response_sensitive (GTK_DIALOG (dialog), GTK_RESPONSE_OK, TRUE);
1797         }
1798     }
1799
1800   if (printer != NULL && !gtk_printer_has_details (printer))
1801     {
1802       gtk_dialog_set_response_sensitive (GTK_DIALOG (dialog), GTK_RESPONSE_OK, FALSE);
1803       priv->request_details_tag =
1804         g_signal_connect (printer, "details-acquired",
1805                           G_CALLBACK (printer_details_acquired), dialog);
1806       /* take the reference */
1807       priv->request_details_printer = printer;
1808       gtk_printer_request_details (printer);
1809       return;
1810     }
1811
1812   if (printer == priv->current_printer)
1813     {
1814       if (printer)
1815         g_object_unref (printer);
1816       return;
1817     }
1818
1819   if (priv->options)
1820     {
1821       g_object_unref (priv->options);
1822       priv->options = NULL;
1823
1824       clear_per_printer_ui (dialog);
1825     }
1826
1827   if (priv->current_printer)
1828     {
1829       g_object_unref (priv->current_printer);
1830     }
1831
1832   priv->printer_capabilities = 0;
1833
1834   if (gtk_printer_is_accepting_jobs (printer))
1835     gtk_dialog_set_response_sensitive (GTK_DIALOG (dialog), GTK_RESPONSE_OK, TRUE);
1836   priv->current_printer = printer;
1837
1838   if (printer != NULL)
1839     {
1840       if (!priv->page_setup_set)
1841         {
1842           /* if no explicit page setup has been set, use the printer default */
1843           GtkPageSetup *page_setup;
1844
1845           page_setup = gtk_printer_get_default_page_size (printer);
1846
1847           if (!page_setup)
1848             page_setup = gtk_page_setup_new ();
1849
1850           if (page_setup && priv->page_setup)
1851             gtk_page_setup_set_orientation (page_setup, gtk_page_setup_get_orientation (priv->page_setup));
1852
1853           g_object_unref (priv->page_setup);
1854           priv->page_setup = page_setup;
1855         }
1856
1857       priv->printer_capabilities = gtk_printer_get_capabilities (printer);
1858       priv->options = _gtk_printer_get_options (printer,
1859                                                 priv->initial_settings,
1860                                                 priv->page_setup,
1861                                                 priv->manual_capabilities);
1862
1863       priv->options_changed_handler =
1864         g_signal_connect_swapped (priv->options, "changed", G_CALLBACK (options_changed_cb), dialog);
1865     }
1866
1867   update_dialog_from_settings (dialog);
1868   update_dialog_from_capabilities (dialog);
1869
1870   priv->internal_page_setup_change = TRUE;
1871   update_paper_sizes (dialog);
1872   priv->internal_page_setup_change = FALSE;
1873
1874   g_object_notify ( G_OBJECT(dialog), "selected-printer");
1875 }
1876
1877 static void
1878 update_collate_icon (GtkToggleButton    *toggle_button,
1879                      GtkPrintUnixDialog *dialog)
1880 {
1881   GtkPrintUnixDialogPrivate *priv = dialog->priv;
1882
1883   gtk_widget_queue_draw (priv->collate_image);
1884 }
1885
1886 static void
1887 paint_page (GtkWidget *widget,
1888             cairo_t   *cr,
1889             gfloat     scale,
1890             gint       x_offset,
1891             gint       y_offset,
1892             gchar     *text,
1893             gint       text_x)
1894 {
1895   gint x, y, width, height;
1896   gint text_y, linewidth;
1897
1898   x = x_offset * scale;
1899   y = y_offset * scale;
1900   width = 20 * scale;
1901   height = 26 * scale;
1902
1903   linewidth = 2;
1904   text_y = 21;
1905
1906   gdk_cairo_set_source_color (cr, &widget->style->base[GTK_STATE_NORMAL]);
1907   cairo_rectangle (cr, x, y, width, height);
1908   cairo_fill (cr);
1909
1910   gdk_cairo_set_source_color (cr, &widget->style->text[GTK_STATE_NORMAL]);
1911   cairo_set_line_width (cr, linewidth);
1912   cairo_rectangle (cr, x + linewidth/2.0, y + linewidth/2.0, width - linewidth, height - linewidth);
1913   cairo_stroke (cr);
1914
1915   cairo_select_font_face (cr, "Sans",
1916                           CAIRO_FONT_SLANT_NORMAL,
1917                           CAIRO_FONT_WEIGHT_NORMAL);
1918   cairo_set_font_size (cr, (gint)(9 * scale));
1919   cairo_move_to (cr, x + (gint)(text_x * scale), y + (gint)(text_y * scale));
1920   cairo_show_text (cr, text);
1921 }
1922
1923 static gboolean
1924 draw_collate_cb (GtkWidget          *widget,
1925                  GdkEventExpose     *event,
1926                  GtkPrintUnixDialog *dialog)
1927 {
1928   GtkSettings *settings;
1929   cairo_t *cr;
1930   gint size;
1931   gfloat scale;
1932   gboolean collate, reverse, rtl;
1933   gint copies;
1934   gint text_x;
1935
1936   collate = dialog_get_collate (dialog);
1937   reverse = dialog_get_reverse (dialog);
1938   copies = dialog_get_n_copies (dialog);
1939
1940   rtl = (gtk_widget_get_direction (GTK_WIDGET (widget)) == GTK_TEXT_DIR_RTL);
1941
1942   settings = gtk_widget_get_settings (widget);
1943   gtk_icon_size_lookup_for_settings (settings,
1944                                      GTK_ICON_SIZE_DIALOG,
1945                                      &size,
1946                                      NULL);
1947   scale = size / 48.0;
1948   text_x = rtl ? 4 : 11;
1949
1950   cr = gdk_cairo_create (widget->window);
1951
1952   cairo_translate (cr, widget->allocation.x, widget->allocation.y);
1953
1954   if (copies == 1)
1955     {
1956       paint_page (widget, cr, scale, rtl ? 40: 15, 5, reverse ? "1" : "2", text_x);
1957       paint_page (widget, cr, scale, rtl ? 50: 5, 15, reverse ? "2" : "1", text_x);
1958     }
1959   else
1960     {
1961       paint_page (widget, cr, scale, rtl ? 40: 15, 5, collate == reverse ? "1" : "2", text_x);
1962       paint_page (widget, cr, scale, rtl ? 50: 5, 15, reverse ? "2" : "1", text_x);
1963
1964       paint_page (widget, cr, scale, rtl ? 5 : 50, 5, reverse ? "1" : "2", text_x);
1965       paint_page (widget, cr, scale, rtl ? 15 : 40, 15, collate == reverse ? "2" : "1", text_x);
1966     }
1967
1968   cairo_destroy (cr);
1969
1970   return TRUE;
1971 }
1972
1973 static void
1974 gtk_print_unix_dialog_style_set (GtkWidget *widget,
1975                                  GtkStyle  *previous_style)
1976 {
1977   GTK_WIDGET_CLASS (gtk_print_unix_dialog_parent_class)->style_set (widget, previous_style);
1978
1979   if (gtk_widget_has_screen (widget))
1980     {
1981       GtkPrintUnixDialog *dialog = (GtkPrintUnixDialog *)widget;
1982       GtkPrintUnixDialogPrivate *priv = dialog->priv;
1983       GtkSettings *settings;
1984       gint size;
1985       gfloat scale;
1986
1987       settings = gtk_widget_get_settings (widget);
1988       gtk_icon_size_lookup_for_settings (settings,
1989                                          GTK_ICON_SIZE_DIALOG,
1990                                          &size,
1991                                          NULL);
1992       scale = size / 48.0;
1993
1994       gtk_widget_set_size_request (priv->collate_image,
1995                                    (50 + 20) * scale,
1996                                    (15 + 26) * scale);
1997     }
1998 }
1999
2000 static void
2001 update_entry_sensitivity (GtkWidget *button,
2002                           GtkWidget *range)
2003 {
2004   gboolean active;
2005
2006   active = gtk_toggle_button_get_active (GTK_TOGGLE_BUTTON (button));
2007
2008   gtk_widget_set_sensitive (range, active);
2009
2010   if (active)
2011     gtk_widget_grab_focus (range);
2012 }
2013
2014 static void
2015 emit_ok_response (GtkTreeView       *tree_view,
2016                   GtkTreePath       *path,
2017                   GtkTreeViewColumn *column,
2018                   gpointer          *user_data)
2019 {
2020   GtkPrintUnixDialog *print_dialog;
2021
2022   print_dialog = (GtkPrintUnixDialog *) user_data;
2023
2024   gtk_dialog_response (GTK_DIALOG (print_dialog), GTK_RESPONSE_OK);
2025 }
2026
2027 static void
2028 create_main_page (GtkPrintUnixDialog *dialog)
2029 {
2030   GtkPrintUnixDialogPrivate *priv = dialog->priv;
2031   GtkWidget *main_vbox, *label, *vbox, *hbox;
2032   GtkWidget *scrolled, *treeview, *frame, *table;
2033   GtkWidget *entry, *spinbutton;
2034   GtkWidget *radio, *check, *image;
2035   GtkCellRenderer *renderer;
2036   GtkTreeViewColumn *column;
2037   GtkTreeSelection *selection;
2038   GtkWidget *custom_input;
2039   const gchar *range_tooltip;
2040
2041   main_vbox = gtk_vbox_new (FALSE, 18);
2042   gtk_container_set_border_width (GTK_CONTAINER (main_vbox), 12);
2043   gtk_widget_show (main_vbox);
2044
2045   vbox = gtk_vbox_new (FALSE, 6);
2046   gtk_box_pack_start (GTK_BOX (main_vbox), vbox, TRUE, TRUE, 0);
2047   gtk_widget_show (vbox);
2048
2049   scrolled = gtk_scrolled_window_new (NULL, NULL);
2050   gtk_scrolled_window_set_policy (GTK_SCROLLED_WINDOW (scrolled),
2051                                   GTK_POLICY_AUTOMATIC,
2052                                   GTK_POLICY_AUTOMATIC);
2053   gtk_scrolled_window_set_shadow_type (GTK_SCROLLED_WINDOW (scrolled),
2054                                        GTK_SHADOW_IN);
2055   gtk_widget_show (scrolled);
2056   gtk_box_pack_start (GTK_BOX (vbox), scrolled, TRUE, TRUE, 0);
2057
2058   treeview = gtk_tree_view_new_with_model ((GtkTreeModel *) priv->printer_list_filter);
2059   priv->printer_treeview = treeview;
2060   gtk_tree_view_set_headers_visible (GTK_TREE_VIEW (treeview), TRUE);
2061   gtk_tree_view_set_search_column (GTK_TREE_VIEW (treeview), PRINTER_LIST_COL_NAME);
2062   gtk_tree_view_set_enable_search (GTK_TREE_VIEW (treeview), TRUE);
2063   selection = gtk_tree_view_get_selection (GTK_TREE_VIEW (treeview));
2064   gtk_tree_selection_set_mode (selection, GTK_SELECTION_BROWSE);
2065   g_signal_connect (selection, "changed", G_CALLBACK (selected_printer_changed), dialog);
2066
2067   renderer = gtk_cell_renderer_pixbuf_new ();
2068   column = gtk_tree_view_column_new_with_attributes ("",
2069                                                      renderer,
2070                                                      "icon-name",
2071                                                      PRINTER_LIST_COL_ICON,
2072                                                      NULL);
2073   gtk_tree_view_column_set_cell_data_func (column, renderer, set_cell_sensitivity_func, NULL, NULL);
2074   gtk_tree_view_append_column (GTK_TREE_VIEW (treeview), column);
2075
2076   renderer = gtk_cell_renderer_text_new ();
2077   column = gtk_tree_view_column_new_with_attributes (_("Printer"),
2078                                                      renderer,
2079                                                      "text",
2080                                                      PRINTER_LIST_COL_NAME,
2081                                                      NULL);
2082   gtk_tree_view_column_set_cell_data_func (column, renderer, set_cell_sensitivity_func, NULL, NULL);
2083   gtk_tree_view_append_column (GTK_TREE_VIEW (treeview), column);
2084
2085   renderer = gtk_cell_renderer_text_new ();
2086   /* Translators: this is the header for the location column in the print dialog */
2087   column = gtk_tree_view_column_new_with_attributes (_("Location"),
2088                                                      renderer,
2089                                                      "text",
2090                                                      PRINTER_LIST_COL_LOCATION,
2091                                                      NULL);
2092   gtk_tree_view_column_set_cell_data_func (column, renderer, set_cell_sensitivity_func, NULL, NULL);
2093   gtk_tree_view_append_column (GTK_TREE_VIEW (treeview), column);
2094
2095   renderer = gtk_cell_renderer_text_new ();
2096   g_object_set (renderer, "ellipsize", PANGO_ELLIPSIZE_END, NULL);
2097   /* Translators: this is the header for the printer status column in the print dialog */
2098   column = gtk_tree_view_column_new_with_attributes (_("Status"),
2099                                                      renderer,
2100                                                      "text",
2101                                                      PRINTER_LIST_COL_STATE,
2102                                                      NULL);
2103   gtk_tree_view_column_set_cell_data_func (column, renderer, set_cell_sensitivity_func, NULL, NULL);
2104   gtk_tree_view_append_column (GTK_TREE_VIEW (treeview), column);
2105
2106   g_signal_connect (GTK_TREE_VIEW (treeview), "row-activated", G_CALLBACK (emit_ok_response), dialog);
2107
2108   gtk_widget_show (treeview);
2109   gtk_container_add (GTK_CONTAINER (scrolled), treeview);
2110
2111   custom_input = gtk_hbox_new (FALSE, 18);
2112   gtk_widget_show (custom_input);
2113   gtk_box_pack_start (GTK_BOX (vbox), custom_input, FALSE, FALSE, 0);
2114   priv->extension_point = custom_input;
2115
2116   hbox = gtk_hbox_new (FALSE, 18);
2117   gtk_widget_show (hbox);
2118   gtk_box_pack_start (GTK_BOX (main_vbox), hbox, FALSE, FALSE, 0);
2119
2120   table = gtk_table_new (4, 2, FALSE);
2121   priv->range_table = table;
2122   gtk_table_set_row_spacings (GTK_TABLE (table), 6);
2123   gtk_table_set_col_spacings (GTK_TABLE (table), 12);
2124   frame = wrap_in_frame (_("Range"), table);
2125   gtk_box_pack_start (GTK_BOX (hbox), frame, TRUE, TRUE, 0);
2126   gtk_widget_show (table);
2127
2128   radio = gtk_radio_button_new_with_mnemonic (NULL, _("_All Pages"));
2129   priv->all_pages_radio = radio;
2130   gtk_widget_show (radio);
2131   gtk_table_attach (GTK_TABLE (table), radio,
2132                     0, 2, 0, 1,  GTK_FILL, 0,
2133                     0, 0);
2134   radio = gtk_radio_button_new_with_mnemonic (gtk_radio_button_get_group (GTK_RADIO_BUTTON (radio)),
2135                                               _("C_urrent Page"));
2136   if (priv->current_page == -1)
2137     gtk_widget_set_sensitive (radio, FALSE);
2138   priv->current_page_radio = radio;
2139   gtk_widget_show (radio);
2140   gtk_table_attach (GTK_TABLE (table), radio,
2141                     0, 2, 1, 2,  GTK_FILL, 0,
2142                     0, 0);
2143
2144   radio = gtk_radio_button_new_with_mnemonic (gtk_radio_button_get_group (GTK_RADIO_BUTTON (radio)),
2145                                               _("Se_lection"));
2146
2147   gtk_widget_set_sensitive (radio, priv->has_selection);
2148   priv->selection_radio = radio;
2149   gtk_table_attach (GTK_TABLE (table), radio,
2150                     0, 2, 2, 3,  GTK_FILL, 0,
2151                     0, 0);
2152   gtk_table_set_row_spacing (GTK_TABLE (table), 2, 0);
2153
2154   radio = gtk_radio_button_new_with_mnemonic (gtk_radio_button_get_group (GTK_RADIO_BUTTON (radio)), _("Pag_es:"));
2155   range_tooltip = _("Specify one or more page ranges,\n e.g. 1-3,7,11");
2156   gtk_widget_set_tooltip_text (radio, range_tooltip);
2157
2158   priv->page_range_radio = radio;
2159   gtk_widget_show (radio);
2160   gtk_table_attach (GTK_TABLE (table), radio,
2161                     0, 1, 3, 4,  GTK_FILL, 0,
2162                     0, 0);
2163   entry = gtk_entry_new ();
2164   gtk_widget_set_tooltip_text (entry, range_tooltip);
2165   atk_object_set_name (gtk_widget_get_accessible (entry), _("Pages"));
2166   atk_object_set_description (gtk_widget_get_accessible (entry), range_tooltip);
2167   priv->page_range_entry = entry;
2168   gtk_widget_show (entry);
2169   gtk_table_attach (GTK_TABLE (table), entry,
2170                     1, 2, 3, 4,  GTK_FILL, 0,
2171                     0, 0);
2172   g_signal_connect (radio, "toggled", G_CALLBACK (update_entry_sensitivity), entry);
2173   update_entry_sensitivity (radio, entry);
2174
2175   table = gtk_table_new (3, 2, FALSE);
2176   gtk_table_set_row_spacings (GTK_TABLE (table), 6);
2177   gtk_table_set_col_spacings (GTK_TABLE (table), 12);
2178   frame = wrap_in_frame (_("Copies"), table);
2179   gtk_box_pack_start (GTK_BOX (hbox), frame, TRUE, TRUE, 0);
2180   gtk_widget_show (table);
2181
2182   /* FIXME chpe: too much space between Copies and spinbutton, put those 2 in a hbox and make it span 2 columns */
2183   label = gtk_label_new_with_mnemonic (_("Copie_s:"));
2184   gtk_misc_set_alignment (GTK_MISC (label), 0.0, 0.5);
2185   gtk_widget_show (label);
2186   gtk_table_attach (GTK_TABLE (table), label,
2187                     0, 1, 0, 1,  GTK_FILL, 0,
2188                     0, 0);
2189   spinbutton = gtk_spin_button_new_with_range (1.0, 100.0, 1.0);
2190   priv->copies_spin = spinbutton;
2191   gtk_widget_show (spinbutton);
2192   gtk_table_attach (GTK_TABLE (table), spinbutton,
2193                     1, 2, 0, 1,  GTK_FILL, 0,
2194                     0, 0);
2195   gtk_label_set_mnemonic_widget (GTK_LABEL (label), spinbutton);
2196   g_signal_connect_swapped (spinbutton, "value-changed",
2197                             G_CALLBACK (update_dialog_from_capabilities), dialog);
2198   g_signal_connect_swapped (spinbutton, "changed",
2199                             G_CALLBACK (update_dialog_from_capabilities), dialog);
2200
2201   check = gtk_check_button_new_with_mnemonic (_("C_ollate"));
2202   priv->collate_check = check;
2203   g_signal_connect (check, "toggled", G_CALLBACK (update_collate_icon), dialog);
2204   gtk_widget_show (check);
2205   gtk_table_attach (GTK_TABLE (table), check,
2206                     0, 1, 1, 2,  GTK_FILL, 0,
2207                     0, 0);
2208
2209   check = gtk_check_button_new_with_mnemonic (_("_Reverse"));
2210   g_signal_connect (check, "toggled", G_CALLBACK (update_collate_icon), dialog);
2211   priv->reverse_check = check;
2212   gtk_widget_show (check);
2213   gtk_table_attach (GTK_TABLE (table), check,
2214                     0, 1, 2, 3,  GTK_FILL, 0,
2215                     0, 0);
2216
2217   image = gtk_drawing_area_new ();
2218   GTK_WIDGET_SET_FLAGS (image, GTK_NO_WINDOW);
2219
2220   priv->collate_image = image;
2221   gtk_widget_show (image);
2222   gtk_widget_set_size_request (image, 70, 90);
2223   gtk_table_attach (GTK_TABLE (table), image,
2224                     1, 2, 1, 3, GTK_FILL, 0,
2225                     0, 0);
2226   g_signal_connect (image, "expose-event",
2227                     G_CALLBACK (draw_collate_cb), dialog);
2228
2229   label = gtk_label_new (_("General"));
2230   gtk_widget_show (label);
2231
2232   gtk_notebook_append_page (GTK_NOTEBOOK (priv->notebook), main_vbox, label);
2233 }
2234
2235 static gboolean
2236 is_range_separator (gchar c)
2237 {
2238   return (c == ',' || c == ';' || c == ':');
2239 }
2240
2241 static GtkPageRange *
2242 dialog_get_page_ranges (GtkPrintUnixDialog *dialog,
2243                         gint               *n_ranges_out)
2244 {
2245   GtkPrintUnixDialogPrivate *priv = dialog->priv;
2246   gint i, n_ranges;
2247   const gchar *text, *p;
2248   gchar *next;
2249   GtkPageRange *ranges;
2250   gint start, end;
2251
2252   text = gtk_entry_get_text (GTK_ENTRY (priv->page_range_entry));
2253
2254   if (*text == 0)
2255     {
2256       *n_ranges_out = 0;
2257       return NULL;
2258     }
2259
2260   n_ranges = 1;
2261   p = text;
2262   while (*p)
2263     {
2264       if (is_range_separator (*p))
2265         n_ranges++;
2266       p++;
2267     }
2268
2269   ranges = g_new0 (GtkPageRange, n_ranges);
2270
2271   i = 0;
2272   p = text;
2273   while (*p)
2274     {
2275       while (isspace (*p)) p++;
2276
2277       if (*p == '-')
2278         {
2279           /* a half-open range like -2 */
2280           start = 1;
2281         }
2282       else
2283         {
2284           start = (int)strtol (p, &next, 10);
2285           if (start < 1)
2286             start = 1;
2287           p = next;
2288         }
2289
2290       end = start;
2291
2292       while (isspace (*p)) p++;
2293
2294       if (*p == '-')
2295         {
2296           p++;
2297           end = (int)strtol (p, &next, 10);
2298           if (next == p) /* a half-open range like 2- */
2299             end = 0;
2300           else if (end < start)
2301             end = start;
2302         }
2303
2304       ranges[i].start = start - 1;
2305       ranges[i].end = end - 1;
2306       i++;
2307
2308       /* Skip until end or separator */
2309       while (*p && !is_range_separator (*p))
2310         p++;
2311
2312       /* if not at end, skip separator */
2313       if (*p)
2314         p++;
2315     }
2316
2317   *n_ranges_out = i;
2318
2319   return ranges;
2320 }
2321
2322 static void
2323 dialog_set_page_ranges (GtkPrintUnixDialog *dialog,
2324                         GtkPageRange       *ranges,
2325                         gint                n_ranges)
2326 {
2327   GtkPrintUnixDialogPrivate *priv = dialog->priv;
2328   gint i;
2329   GString *s = g_string_new (NULL);
2330
2331   for (i = 0; i < n_ranges; i++)
2332     {
2333       g_string_append_printf (s, "%d", ranges[i].start + 1);
2334       if (ranges[i].end > ranges[i].start)
2335         g_string_append_printf (s, "-%d", ranges[i].end + 1);
2336       else if (ranges[i].end == -1)
2337         g_string_append (s, "-");
2338
2339       if (i != n_ranges - 1)
2340         g_string_append (s, ",");
2341     }
2342
2343   gtk_entry_set_text (GTK_ENTRY (priv->page_range_entry), s->str);
2344
2345   g_string_free (s, TRUE);
2346 }
2347
2348 static GtkPrintPages
2349 dialog_get_print_pages (GtkPrintUnixDialog *dialog)
2350 {
2351   GtkPrintUnixDialogPrivate *priv = dialog->priv;
2352
2353   if (gtk_toggle_button_get_active (GTK_TOGGLE_BUTTON (priv->all_pages_radio)))
2354     return GTK_PRINT_PAGES_ALL;
2355   else if (gtk_toggle_button_get_active (GTK_TOGGLE_BUTTON (priv->current_page_radio)))
2356     return GTK_PRINT_PAGES_CURRENT;
2357   else if (gtk_toggle_button_get_active (GTK_TOGGLE_BUTTON (priv->selection_radio)))
2358     return GTK_PRINT_PAGES_SELECTION;
2359   else
2360     return GTK_PRINT_PAGES_RANGES;
2361 }
2362
2363 static void
2364 dialog_set_print_pages (GtkPrintUnixDialog *dialog,
2365                         GtkPrintPages       pages)
2366 {
2367   GtkPrintUnixDialogPrivate *priv = dialog->priv;
2368
2369   if (pages == GTK_PRINT_PAGES_RANGES)
2370     gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (priv->page_range_radio), TRUE);
2371   else if (pages == GTK_PRINT_PAGES_CURRENT)
2372     gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (priv->current_page_radio), TRUE);
2373   else if (pages == GTK_PRINT_PAGES_SELECTION)
2374     gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (priv->selection_radio), TRUE);
2375   else
2376     gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (priv->all_pages_radio), TRUE);
2377 }
2378
2379 static gdouble
2380 dialog_get_scale (GtkPrintUnixDialog *dialog)
2381 {
2382   if (GTK_WIDGET_IS_SENSITIVE (dialog->priv->scale_spin))
2383     return gtk_spin_button_get_value (GTK_SPIN_BUTTON (dialog->priv->scale_spin));
2384   else
2385     return 100.0;
2386 }
2387
2388 static void
2389 dialog_set_scale (GtkPrintUnixDialog *dialog,
2390                   gdouble             val)
2391 {
2392   gtk_spin_button_set_value (GTK_SPIN_BUTTON (dialog->priv->scale_spin), val);
2393 }
2394
2395 static GtkPageSet
2396 dialog_get_page_set (GtkPrintUnixDialog *dialog)
2397 {
2398   if (GTK_WIDGET_IS_SENSITIVE (dialog->priv->page_set_combo))
2399     return (GtkPageSet)gtk_combo_box_get_active (GTK_COMBO_BOX (dialog->priv->page_set_combo));
2400   else
2401     return GTK_PAGE_SET_ALL;
2402 }
2403
2404 static void
2405 dialog_set_page_set (GtkPrintUnixDialog *dialog,
2406                      GtkPageSet          val)
2407 {
2408   gtk_combo_box_set_active (GTK_COMBO_BOX (dialog->priv->page_set_combo),
2409                             (int)val);
2410 }
2411
2412 static gint
2413 dialog_get_n_copies (GtkPrintUnixDialog *dialog)
2414 {
2415   if (GTK_WIDGET_IS_SENSITIVE (dialog->priv->copies_spin))
2416     return gtk_spin_button_get_value_as_int (GTK_SPIN_BUTTON (dialog->priv->copies_spin));
2417   return 1;
2418 }
2419
2420 static void
2421 dialog_set_n_copies (GtkPrintUnixDialog *dialog,
2422                      gint                n_copies)
2423 {
2424   gtk_spin_button_set_value (GTK_SPIN_BUTTON (dialog->priv->copies_spin),
2425                              n_copies);
2426 }
2427
2428 static gboolean
2429 dialog_get_collate (GtkPrintUnixDialog *dialog)
2430 {
2431   if (GTK_WIDGET_IS_SENSITIVE (dialog->priv->collate_check))
2432     return gtk_toggle_button_get_active (GTK_TOGGLE_BUTTON (dialog->priv->collate_check));
2433   return FALSE;
2434 }
2435
2436 static void
2437 dialog_set_collate (GtkPrintUnixDialog *dialog,
2438                     gboolean            collate)
2439 {
2440   gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (dialog->priv->collate_check),
2441                                 collate);
2442 }
2443
2444 static gboolean
2445 dialog_get_reverse (GtkPrintUnixDialog *dialog)
2446 {
2447   if (GTK_WIDGET_IS_SENSITIVE (dialog->priv->reverse_check))
2448     return gtk_toggle_button_get_active (GTK_TOGGLE_BUTTON (dialog->priv->reverse_check));
2449   return FALSE;
2450 }
2451
2452 static void
2453 dialog_set_reverse (GtkPrintUnixDialog *dialog,
2454                     gboolean            reverse)
2455 {
2456   gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (dialog->priv->reverse_check),
2457                                 reverse);
2458 }
2459
2460 static gint
2461 dialog_get_pages_per_sheet (GtkPrintUnixDialog *dialog)
2462 {
2463   GtkPrintUnixDialogPrivate *priv = dialog->priv;
2464   const gchar *val;
2465   gint num;
2466
2467   val = gtk_printer_option_widget_get_value (priv->pages_per_sheet);
2468
2469   num = 1;
2470
2471   if (val)
2472     {
2473       num = atoi(val);
2474       if (num < 1)
2475         num = 1;
2476     }
2477
2478   return num;
2479 }
2480
2481 static GtkNumberUpLayout
2482 dialog_get_number_up_layout (GtkPrintUnixDialog *dialog)
2483 {
2484   GtkPrintUnixDialogPrivate *priv = dialog->priv;
2485   GtkPrintCapabilities       caps;
2486   GtkNumberUpLayout          layout;
2487   const gchar               *val;
2488   GEnumClass                *enum_class;
2489   GEnumValue                *enum_value;
2490
2491   val = gtk_printer_option_widget_get_value (priv->number_up_layout);
2492
2493   caps = priv->manual_capabilities | priv->printer_capabilities;
2494
2495   if ((caps & GTK_PRINT_CAPABILITY_NUMBER_UP_LAYOUT) == 0)
2496     return GTK_NUMBER_UP_LAYOUT_LEFT_TO_RIGHT_TOP_TO_BOTTOM;
2497
2498   if (gtk_widget_get_direction (GTK_WIDGET (dialog)) == GTK_TEXT_DIR_LTR)
2499     layout = GTK_NUMBER_UP_LAYOUT_LEFT_TO_RIGHT_TOP_TO_BOTTOM;
2500   else
2501     layout = GTK_NUMBER_UP_LAYOUT_RIGHT_TO_LEFT_TOP_TO_BOTTOM;
2502
2503   if (val == NULL)
2504     return layout;
2505
2506   enum_class = g_type_class_ref (GTK_TYPE_NUMBER_UP_LAYOUT);
2507   enum_value = g_enum_get_value_by_nick (enum_class, val);
2508   if (enum_value)
2509     layout = enum_value->value;
2510   g_type_class_unref (enum_class);
2511
2512   return layout;
2513 }
2514
2515 static gboolean
2516 draw_page_cb (GtkWidget          *widget,
2517               GdkEventExpose     *event,
2518               GtkPrintUnixDialog *dialog)
2519 {
2520   GtkPrintUnixDialogPrivate *priv = dialog->priv;
2521   cairo_t *cr;
2522   gdouble ratio;
2523   gint w, h, tmp, shadow_offset;
2524   gint pages_x, pages_y, i, x, y, layout_w, layout_h;
2525   gdouble page_width, page_height;
2526   GtkPageOrientation orientation;
2527   gboolean landscape;
2528   PangoLayout *layout;
2529   PangoFontDescription *font;
2530   gchar *text;
2531   GdkColor *color;
2532   GtkNumberUpLayout number_up_layout;
2533   gint start_x, end_x, start_y, end_y;
2534   gint dx, dy;
2535   gboolean horizontal;
2536   GtkPageSetup *page_setup;
2537   gdouble paper_width, paper_height;
2538   gdouble pos_x, pos_y;
2539   gint pages_per_sheet;
2540
2541   orientation = gtk_page_setup_get_orientation (priv->page_setup);
2542   landscape =
2543     (orientation == GTK_PAGE_ORIENTATION_LANDSCAPE) ||
2544     (orientation == GTK_PAGE_ORIENTATION_REVERSE_LANDSCAPE);
2545
2546   number_up_layout = dialog_get_number_up_layout (dialog);
2547
2548   cr = gdk_cairo_create (widget->window);
2549
2550   cairo_save (cr);
2551
2552   page_setup = gtk_print_unix_dialog_get_page_setup (dialog);  
2553
2554   if (page_setup != NULL)
2555     {
2556       if (!landscape)
2557         {
2558           paper_width = gtk_page_setup_get_paper_width (page_setup, GTK_UNIT_MM);
2559           paper_height = gtk_page_setup_get_paper_height (page_setup, GTK_UNIT_MM);
2560         }
2561       else
2562         {
2563           paper_width = gtk_page_setup_get_paper_height (page_setup, GTK_UNIT_MM);
2564           paper_height = gtk_page_setup_get_paper_width (page_setup, GTK_UNIT_MM);
2565         }
2566
2567       if (paper_width < paper_height)
2568         {
2569           h = EXAMPLE_PAGE_AREA_SIZE - 3;
2570           w = (paper_height != 0) ? h * paper_width / paper_height : 0;
2571         }
2572       else
2573         {
2574           w = EXAMPLE_PAGE_AREA_SIZE - 3;
2575           h = (paper_width != 0) ? w * paper_height / paper_width : 0;
2576         }
2577
2578       if (paper_width == 0)
2579         w = 0;
2580
2581       if (paper_height == 0)
2582         h = 0;
2583     }
2584   else
2585     {
2586       ratio = G_SQRT2;
2587       w = (EXAMPLE_PAGE_AREA_SIZE - 3) / ratio;
2588       h = EXAMPLE_PAGE_AREA_SIZE - 3;
2589     }
2590
2591   pages_per_sheet = dialog_get_pages_per_sheet (dialog);
2592   switch (pages_per_sheet)
2593     {
2594     default:
2595     case 1:
2596       pages_x = 1; pages_y = 1;
2597       break;
2598     case 2:
2599       landscape = !landscape;
2600       pages_x = 1; pages_y = 2;
2601       break;
2602     case 4:
2603       pages_x = 2; pages_y = 2;
2604       break;
2605     case 6:
2606       landscape = !landscape;
2607       pages_x = 2; pages_y = 3;
2608       break;
2609     case 9:
2610       pages_x = 3; pages_y = 3;
2611       break;
2612     case 16:
2613       pages_x = 4; pages_y = 4;
2614       break;
2615     }
2616
2617   if (landscape)
2618     {
2619       tmp = w;
2620       w = h;
2621       h = tmp;
2622
2623       tmp = pages_x;
2624       pages_x = pages_y;
2625       pages_y = tmp;
2626     }
2627
2628   pos_x = widget->allocation.x + (widget->allocation.width - w) / 2;
2629   pos_y = widget->allocation.y + (widget->allocation.height - h) / 2 - 10;
2630   color = &widget->style->text[GTK_STATE_NORMAL];
2631   cairo_translate (cr, pos_x, pos_y);
2632
2633   shadow_offset = 3;
2634
2635   color = &widget->style->text[GTK_STATE_NORMAL];
2636   cairo_set_source_rgba (cr, color->red / 65535., color->green / 65535., color->blue / 65535, 0.5);
2637   cairo_rectangle (cr, shadow_offset + 1, shadow_offset + 1, w, h);
2638   cairo_fill (cr);
2639
2640   gdk_cairo_set_source_color (cr, &widget->style->base[GTK_STATE_NORMAL]);
2641   cairo_rectangle (cr, 1, 1, w, h);
2642   cairo_fill (cr);
2643   cairo_set_line_width (cr, 1.0);
2644   cairo_rectangle (cr, 0.5, 0.5, w + 1, h + 1);
2645
2646   gdk_cairo_set_source_color (cr, &widget->style->text[GTK_STATE_NORMAL]);
2647   cairo_stroke (cr);
2648
2649   i = 1;
2650
2651   page_width = (double)w / pages_x;
2652   page_height = (double)h / pages_y;
2653
2654   layout  = pango_cairo_create_layout (cr);
2655
2656   font = pango_font_description_new ();
2657   pango_font_description_set_family (font, "sans");
2658
2659   if (page_height > 0)
2660     pango_font_description_set_absolute_size (font, page_height * 0.4 * PANGO_SCALE);
2661   else
2662     pango_font_description_set_absolute_size (font, 1);
2663
2664   pango_layout_set_font_description (layout, font);
2665   pango_font_description_free (font);
2666
2667   pango_layout_set_width (layout, page_width * PANGO_SCALE);
2668   pango_layout_set_alignment (layout, PANGO_ALIGN_CENTER);
2669
2670   switch (number_up_layout)
2671     {
2672       default:
2673       case GTK_NUMBER_UP_LAYOUT_LEFT_TO_RIGHT_TOP_TO_BOTTOM:
2674         start_x = 0;
2675         end_x = pages_x - 1;
2676         start_y = 0;
2677         end_y = pages_y - 1;
2678         dx = 1;
2679         dy = 1;
2680         horizontal = TRUE;
2681         break;
2682       case GTK_NUMBER_UP_LAYOUT_LEFT_TO_RIGHT_BOTTOM_TO_TOP:
2683         start_x = 0;
2684         end_x = pages_x - 1;
2685         start_y = pages_y - 1;
2686         end_y = 0;
2687         dx = 1;
2688         dy = - 1;
2689         horizontal = TRUE;
2690         break;
2691       case GTK_NUMBER_UP_LAYOUT_RIGHT_TO_LEFT_TOP_TO_BOTTOM:
2692         start_x = pages_x - 1;
2693         end_x = 0;
2694         start_y = 0;
2695         end_y = pages_y - 1;
2696         dx = - 1;
2697         dy = 1;
2698         horizontal = TRUE;
2699         break;
2700       case GTK_NUMBER_UP_LAYOUT_RIGHT_TO_LEFT_BOTTOM_TO_TOP:
2701         start_x = pages_x - 1;
2702         end_x = 0;
2703         start_y = pages_y - 1;
2704         end_y = 0;
2705         dx = - 1;
2706         dy = - 1;
2707         horizontal = TRUE;
2708         break;
2709       case GTK_NUMBER_UP_LAYOUT_TOP_TO_BOTTOM_LEFT_TO_RIGHT:
2710         start_x = 0;
2711         end_x = pages_x - 1;
2712         start_y = 0;
2713         end_y = pages_y - 1;
2714         dx = 1;
2715         dy = 1;
2716         horizontal = FALSE;
2717         break;
2718       case GTK_NUMBER_UP_LAYOUT_TOP_TO_BOTTOM_RIGHT_TO_LEFT:
2719         start_x = pages_x - 1;
2720         end_x = 0;
2721         start_y = 0;
2722         end_y = pages_y - 1;
2723         dx = - 1;
2724         dy = 1;
2725         horizontal = FALSE;
2726         break;
2727       case GTK_NUMBER_UP_LAYOUT_BOTTOM_TO_TOP_LEFT_TO_RIGHT:
2728         start_x = 0;
2729         end_x = pages_x - 1;
2730         start_y = pages_y - 1;
2731         end_y = 0;
2732         dx = 1;
2733         dy = - 1;
2734         horizontal = FALSE;
2735         break;
2736       case GTK_NUMBER_UP_LAYOUT_BOTTOM_TO_TOP_RIGHT_TO_LEFT:
2737         start_x = pages_x - 1;
2738         end_x = 0;
2739         start_y = pages_y - 1;
2740         end_y = 0;
2741         dx = - 1;
2742         dy = - 1;
2743         horizontal = FALSE;
2744         break;
2745     }
2746
2747   if (horizontal)
2748     for (y = start_y; y != end_y + dy; y += dy)
2749       {
2750         for (x = start_x; x != end_x + dx; x += dx)
2751           {
2752             text = g_strdup_printf ("%d", i++);
2753             pango_layout_set_text (layout, text, -1);
2754             g_free (text);
2755             pango_layout_get_size (layout, &layout_w, &layout_h);
2756             cairo_save (cr);
2757             cairo_translate (cr,
2758                              x * page_width,
2759                              y * page_height + (page_height - layout_h / 1024.0) / 2);
2760
2761             pango_cairo_show_layout (cr, layout);
2762             cairo_restore (cr);
2763           }
2764       }
2765   else
2766     for (x = start_x; x != end_x + dx; x += dx)
2767       {
2768         for (y = start_y; y != end_y + dy; y += dy)
2769           {
2770             text = g_strdup_printf ("%d", i++);
2771             pango_layout_set_text (layout, text, -1);
2772             g_free (text);
2773             pango_layout_get_size (layout, &layout_w, &layout_h);
2774             cairo_save (cr);
2775             cairo_translate (cr,
2776                              x * page_width,
2777                              y * page_height + (page_height - layout_h / 1024.0) / 2);
2778
2779             pango_cairo_show_layout (cr, layout);
2780             cairo_restore (cr);
2781           }
2782       }
2783
2784   g_object_unref (layout);
2785
2786   if (page_setup != NULL)
2787     {
2788       pos_x += 1;
2789       pos_y += 1;
2790
2791       if (pages_per_sheet == 2 || pages_per_sheet == 6)
2792         {
2793           paper_width = gtk_page_setup_get_paper_height (page_setup, _gtk_print_get_default_user_units ());
2794           paper_height = gtk_page_setup_get_paper_width (page_setup, _gtk_print_get_default_user_units ());
2795         }
2796       else
2797         {
2798           paper_width = gtk_page_setup_get_paper_width (page_setup, _gtk_print_get_default_user_units ());
2799           paper_height = gtk_page_setup_get_paper_height (page_setup, _gtk_print_get_default_user_units ());
2800         }
2801
2802       cairo_restore (cr);
2803       cairo_save (cr);
2804
2805       layout  = pango_cairo_create_layout (cr);
2806
2807       font = pango_font_description_new ();
2808       pango_font_description_set_family (font, "sans");
2809
2810       PangoContext *pango_c = NULL;
2811       PangoFontDescription *pango_f = NULL;
2812       gint font_size = 12 * PANGO_SCALE;
2813
2814       pango_c = gtk_widget_get_pango_context (widget);
2815       if (pango_c != NULL)
2816         {
2817           pango_f = pango_context_get_font_description (pango_c);
2818           if (pango_f != NULL)
2819             font_size = pango_font_description_get_size (pango_f);
2820         }
2821
2822       pango_font_description_set_size (font, font_size);
2823       pango_layout_set_font_description (layout, font);
2824       pango_font_description_free (font);
2825
2826       pango_layout_set_width (layout, -1);
2827       pango_layout_set_alignment (layout, PANGO_ALIGN_CENTER);
2828
2829       if (_gtk_print_get_default_user_units () == GTK_UNIT_MM)
2830         text = g_strdup_printf ("%.1f mm", paper_height);
2831       else
2832         text = g_strdup_printf ("%.2f inch", paper_height);
2833
2834       pango_layout_set_text (layout, text, -1);
2835       g_free (text);
2836       pango_layout_get_size (layout, &layout_w, &layout_h);
2837
2838       cairo_translate (cr, pos_x - layout_w / PANGO_SCALE - 2 * RULER_DISTANCE,
2839                            widget->allocation.y + (widget->allocation.height - layout_h / PANGO_SCALE) / 2);
2840
2841       pango_cairo_show_layout (cr, layout);
2842
2843       cairo_restore (cr);
2844       cairo_save (cr);
2845
2846       if (_gtk_print_get_default_user_units () == GTK_UNIT_MM)
2847         text = g_strdup_printf ("%.1f mm", paper_width);
2848       else
2849         text = g_strdup_printf ("%.2f inch", paper_width);
2850
2851       pango_layout_set_text (layout, text, -1);
2852       g_free (text);
2853       pango_layout_get_size (layout, &layout_w, &layout_h);
2854
2855       cairo_translate (cr, widget->allocation.x + (widget->allocation.width - layout_w / PANGO_SCALE) / 2,
2856                            pos_y + h + shadow_offset + 2 * RULER_DISTANCE);
2857
2858       pango_cairo_show_layout (cr, layout);
2859
2860       g_object_unref (layout);
2861
2862       cairo_restore (cr);
2863
2864       cairo_set_line_width (cr, 1);
2865
2866       cairo_move_to (cr, pos_x - RULER_DISTANCE, pos_y);
2867       cairo_line_to (cr, pos_x - RULER_DISTANCE, pos_y + h);
2868       cairo_stroke (cr);
2869
2870       cairo_move_to (cr, pos_x - RULER_DISTANCE - RULER_RADIUS, pos_y - 0.5);
2871       cairo_line_to (cr, pos_x - RULER_DISTANCE + RULER_RADIUS, pos_y - 0.5);
2872       cairo_stroke (cr);
2873
2874       cairo_move_to (cr, pos_x - RULER_DISTANCE - RULER_RADIUS, pos_y + h + 0.5);
2875       cairo_line_to (cr, pos_x - RULER_DISTANCE + RULER_RADIUS, pos_y + h + 0.5);
2876       cairo_stroke (cr);
2877
2878       cairo_move_to (cr, pos_x, pos_y + h + shadow_offset + RULER_DISTANCE);
2879       cairo_line_to (cr, pos_x + w, pos_y + h + shadow_offset + RULER_DISTANCE);
2880       cairo_stroke (cr);
2881
2882       cairo_move_to (cr, pos_x - 0.5, pos_y + h + shadow_offset + RULER_DISTANCE - RULER_RADIUS);
2883       cairo_line_to (cr, pos_x - 0.5, pos_y + h + shadow_offset + RULER_DISTANCE + RULER_RADIUS);
2884       cairo_stroke (cr);
2885
2886       cairo_move_to (cr, pos_x + w + 0.5, pos_y + h + shadow_offset + RULER_DISTANCE - RULER_RADIUS);
2887       cairo_line_to (cr, pos_x + w + 0.5, pos_y + h + shadow_offset + RULER_DISTANCE + RULER_RADIUS);
2888       cairo_stroke (cr);
2889     }
2890
2891   cairo_destroy (cr);
2892
2893   return TRUE;
2894 }
2895
2896 static void
2897 redraw_page_layout_preview (GtkPrintUnixDialog *dialog)
2898 {
2899   GtkPrintUnixDialogPrivate *priv = dialog->priv;
2900
2901   if (priv->page_layout_preview)
2902     gtk_widget_queue_draw (priv->page_layout_preview);
2903 }
2904
2905 static void
2906 update_number_up_layout (GtkPrintUnixDialog *dialog)
2907 {
2908   GtkPrintUnixDialogPrivate *priv = dialog->priv;
2909   GtkPrintCapabilities       caps;
2910   GtkPrinterOptionSet       *set;
2911   GtkNumberUpLayout          layout;
2912   GtkPrinterOption          *option;
2913   GtkPrinterOption          *old_option;
2914   GtkPageOrientation         page_orientation;
2915
2916   set = priv->options;
2917
2918   caps = priv->manual_capabilities | priv->printer_capabilities;
2919
2920   if (caps & GTK_PRINT_CAPABILITY_NUMBER_UP_LAYOUT)
2921     {
2922       if (priv->number_up_layout_n_option == NULL)
2923         {
2924           priv->number_up_layout_n_option = gtk_printer_option_set_lookup (set, "gtk-n-up-layout");
2925           if (priv->number_up_layout_n_option == NULL)
2926             {
2927               char *n_up_layout[] = { "lrtb", "lrbt", "rltb", "rlbt", "tblr", "tbrl", "btlr", "btrl" };
2928                /* Translators: These strings name the possible arrangements of
2929                 * multiple pages on a sheet when printing (same as in gtkprintbackendcups.c)
2930                 */
2931               char *n_up_layout_display[] = { N_("Left to right, top to bottom"), N_("Left to right, bottom to top"),
2932                                               N_("Right to left, top to bottom"), N_("Right to left, bottom to top"),
2933                                               N_("Top to bottom, left to right"), N_("Top to bottom, right to left"),
2934                                               N_("Bottom to top, left to right"), N_("Bottom to top, right to left") };
2935               int i;
2936
2937               priv->number_up_layout_n_option = gtk_printer_option_new ("gtk-n-up-layout",
2938                                                                         _("Page Ordering"),
2939                                                                         GTK_PRINTER_OPTION_TYPE_PICKONE);
2940               gtk_printer_option_allocate_choices (priv->number_up_layout_n_option, 8);
2941
2942               for (i = 0; i < G_N_ELEMENTS (n_up_layout_display); i++)
2943                 {
2944                   priv->number_up_layout_n_option->choices[i] = g_strdup (n_up_layout[i]);
2945                   priv->number_up_layout_n_option->choices_display[i] = g_strdup (_(n_up_layout_display[i]));
2946                 }
2947             }
2948           g_object_ref (priv->number_up_layout_n_option);
2949
2950           priv->number_up_layout_2_option = gtk_printer_option_new ("gtk-n-up-layout",
2951                                                                     _("Page Ordering"),
2952                                                                     GTK_PRINTER_OPTION_TYPE_PICKONE);
2953           gtk_printer_option_allocate_choices (priv->number_up_layout_2_option, 2);
2954         }
2955
2956       page_orientation = gtk_page_setup_get_orientation (priv->page_setup);
2957       if (page_orientation == GTK_PAGE_ORIENTATION_PORTRAIT ||
2958           page_orientation == GTK_PAGE_ORIENTATION_REVERSE_PORTRAIT)
2959         {
2960           if (! (priv->number_up_layout_2_option->choices[0] == priv->number_up_layout_n_option->choices[0] &&
2961                  priv->number_up_layout_2_option->choices[1] == priv->number_up_layout_n_option->choices[2]))
2962             {
2963               g_free (priv->number_up_layout_2_option->choices_display[0]);
2964               g_free (priv->number_up_layout_2_option->choices_display[1]);
2965               priv->number_up_layout_2_option->choices[0] = priv->number_up_layout_n_option->choices[0];
2966               priv->number_up_layout_2_option->choices[1] = priv->number_up_layout_n_option->choices[2];
2967               priv->number_up_layout_2_option->choices_display[0] = g_strdup ( _("Left to right"));
2968               priv->number_up_layout_2_option->choices_display[1] = g_strdup ( _("Right to left"));
2969             }
2970         }
2971       else
2972         {
2973           if (! (priv->number_up_layout_2_option->choices[0] == priv->number_up_layout_n_option->choices[0] &&
2974                  priv->number_up_layout_2_option->choices[1] == priv->number_up_layout_n_option->choices[1]))
2975             {
2976               g_free (priv->number_up_layout_2_option->choices_display[0]);
2977               g_free (priv->number_up_layout_2_option->choices_display[1]);
2978               priv->number_up_layout_2_option->choices[0] = priv->number_up_layout_n_option->choices[0];
2979               priv->number_up_layout_2_option->choices[1] = priv->number_up_layout_n_option->choices[1];
2980               priv->number_up_layout_2_option->choices_display[0] = g_strdup ( _("Top to bottom"));
2981               priv->number_up_layout_2_option->choices_display[1] = g_strdup ( _("Bottom to top"));
2982             }
2983         }
2984
2985       layout = dialog_get_number_up_layout (dialog);
2986
2987       old_option = gtk_printer_option_set_lookup (set, "gtk-n-up-layout");
2988       if (old_option != NULL)
2989         gtk_printer_option_set_remove (set, old_option);
2990
2991       if (dialog_get_pages_per_sheet (dialog) != 1)
2992         {
2993           GEnumClass *enum_class;
2994           GEnumValue *enum_value;
2995           enum_class = g_type_class_ref (GTK_TYPE_NUMBER_UP_LAYOUT);
2996
2997           if (dialog_get_pages_per_sheet (dialog) == 2)
2998             {
2999               option = priv->number_up_layout_2_option;
3000
3001               if (layout == GTK_NUMBER_UP_LAYOUT_LEFT_TO_RIGHT_TOP_TO_BOTTOM ||
3002                   layout == GTK_NUMBER_UP_LAYOUT_TOP_TO_BOTTOM_LEFT_TO_RIGHT)
3003                 enum_value = g_enum_get_value (enum_class, GTK_NUMBER_UP_LAYOUT_LEFT_TO_RIGHT_TOP_TO_BOTTOM);
3004
3005               if (layout == GTK_NUMBER_UP_LAYOUT_LEFT_TO_RIGHT_BOTTOM_TO_TOP ||
3006                   layout == GTK_NUMBER_UP_LAYOUT_BOTTOM_TO_TOP_LEFT_TO_RIGHT)
3007                 enum_value = g_enum_get_value (enum_class, GTK_NUMBER_UP_LAYOUT_LEFT_TO_RIGHT_BOTTOM_TO_TOP);
3008
3009               if (layout == GTK_NUMBER_UP_LAYOUT_RIGHT_TO_LEFT_TOP_TO_BOTTOM ||
3010                   layout == GTK_NUMBER_UP_LAYOUT_TOP_TO_BOTTOM_RIGHT_TO_LEFT)
3011                 enum_value = g_enum_get_value (enum_class, GTK_NUMBER_UP_LAYOUT_RIGHT_TO_LEFT_TOP_TO_BOTTOM);
3012
3013               if (layout == GTK_NUMBER_UP_LAYOUT_RIGHT_TO_LEFT_BOTTOM_TO_TOP ||
3014                   layout == GTK_NUMBER_UP_LAYOUT_BOTTOM_TO_TOP_RIGHT_TO_LEFT)
3015                 enum_value = g_enum_get_value (enum_class, GTK_NUMBER_UP_LAYOUT_RIGHT_TO_LEFT_BOTTOM_TO_TOP);
3016             }
3017           else
3018             {
3019               option = priv->number_up_layout_n_option;
3020
3021               enum_value = g_enum_get_value (enum_class, layout);
3022             }
3023
3024           g_assert (enum_value != NULL);
3025           gtk_printer_option_set (option, enum_value->value_nick);
3026           g_type_class_unref (enum_class);
3027
3028           gtk_printer_option_set_add (set, option);
3029         }
3030     }
3031
3032   setup_option (dialog, "gtk-n-up-layout", priv->number_up_layout);
3033
3034   if (priv->number_up_layout != NULL)
3035     gtk_widget_set_sensitive (GTK_WIDGET (priv->number_up_layout),
3036                               (caps & GTK_PRINT_CAPABILITY_NUMBER_UP_LAYOUT) &&
3037                               (dialog_get_pages_per_sheet (dialog) > 1));
3038 }
3039
3040 static void
3041 custom_paper_dialog_response_cb (GtkDialog *custom_paper_dialog,
3042                                  gint       response_id,
3043                                  gpointer   user_data)
3044 {
3045   GtkPrintUnixDialog        *print_dialog = GTK_PRINT_UNIX_DIALOG (user_data);
3046   GtkPrintUnixDialogPrivate *priv = print_dialog->priv;
3047   GtkTreeModel              *model;
3048   GtkTreeIter                iter;
3049
3050   _gtk_print_load_custom_papers (priv->custom_paper_list);
3051
3052   priv->internal_page_setup_change = TRUE;
3053   update_paper_sizes (print_dialog);
3054   priv->internal_page_setup_change = FALSE;
3055
3056   if (priv->page_setup_set)
3057     {
3058       model = GTK_TREE_MODEL (priv->custom_paper_list);
3059       if (gtk_tree_model_get_iter_first (model, &iter))
3060         {
3061           do
3062             {
3063               GtkPageSetup *page_setup;
3064               gtk_tree_model_get (model, &iter, 0, &page_setup, -1);
3065
3066               if (page_setup &&
3067                   g_strcmp0 (gtk_paper_size_get_display_name (gtk_page_setup_get_paper_size (page_setup)),
3068                              gtk_paper_size_get_display_name (gtk_page_setup_get_paper_size (priv->page_setup))) == 0)
3069                 gtk_print_unix_dialog_set_page_setup (print_dialog, page_setup);
3070
3071               g_object_unref (page_setup);
3072             } while (gtk_tree_model_iter_next (model, &iter));
3073         }
3074     }
3075
3076   gtk_widget_destroy (GTK_WIDGET (custom_paper_dialog));
3077 }
3078
3079 static void
3080 orientation_changed (GtkComboBox        *combo_box,
3081                      GtkPrintUnixDialog *dialog)
3082 {
3083   GtkPrintUnixDialogPrivate *priv = dialog->priv;
3084   GtkPageOrientation         orientation;
3085   GtkPageSetup              *page_setup;
3086
3087   if (priv->internal_page_setup_change)
3088     return;
3089
3090   orientation = (GtkPageOrientation) gtk_combo_box_get_active (GTK_COMBO_BOX (priv->orientation_combo));
3091
3092   if (priv->page_setup)
3093     {
3094       page_setup = gtk_page_setup_copy (priv->page_setup);
3095       if (page_setup)
3096         gtk_page_setup_set_orientation (page_setup, orientation);
3097
3098       gtk_print_unix_dialog_set_page_setup (dialog, page_setup);
3099     }
3100
3101   redraw_page_layout_preview (dialog);
3102 }
3103
3104 static void
3105 paper_size_changed (GtkComboBox        *combo_box,
3106                     GtkPrintUnixDialog *dialog)
3107 {
3108   GtkPrintUnixDialogPrivate *priv = dialog->priv;
3109   GtkTreeIter iter;
3110   GtkPageSetup *page_setup, *last_page_setup;
3111   GtkPageOrientation orientation;
3112
3113   if (priv->internal_page_setup_change)
3114     return;
3115
3116   if (gtk_combo_box_get_active_iter (combo_box, &iter))
3117     {
3118       gtk_tree_model_get (gtk_combo_box_get_model (combo_box),
3119                           &iter, PAGE_SETUP_LIST_COL_PAGE_SETUP, &page_setup, -1);
3120
3121       if (page_setup == NULL)
3122         {
3123           GtkWidget *custom_paper_dialog;
3124
3125           /* Change from "manage" menu item to last value */
3126           if (priv->page_setup)
3127             last_page_setup = g_object_ref (priv->page_setup);
3128           else
3129             last_page_setup = gtk_page_setup_new (); /* "good" default */
3130
3131           if (!set_paper_size (dialog, last_page_setup, FALSE, FALSE))
3132             set_paper_size (dialog, last_page_setup, TRUE, TRUE);
3133           g_object_unref (last_page_setup);
3134
3135           /* And show the custom paper dialog */
3136           custom_paper_dialog = _gtk_custom_paper_unix_dialog_new (GTK_WINDOW (dialog), _("Manage Custom Sizes"));
3137           g_signal_connect (custom_paper_dialog, "response", G_CALLBACK (custom_paper_dialog_response_cb), dialog);
3138           gtk_window_present (GTK_WINDOW (custom_paper_dialog));
3139
3140           return;
3141         }
3142
3143       if (priv->page_setup)
3144         orientation = gtk_page_setup_get_orientation (priv->page_setup);
3145       else
3146         orientation = GTK_PAGE_ORIENTATION_PORTRAIT;
3147
3148       gtk_page_setup_set_orientation (page_setup, orientation);
3149       gtk_print_unix_dialog_set_page_setup (dialog, page_setup);
3150
3151       g_object_unref (page_setup);
3152     }
3153
3154   redraw_page_layout_preview (dialog);
3155 }
3156
3157 static gboolean
3158 paper_size_row_is_separator (GtkTreeModel *model,
3159                              GtkTreeIter  *iter,
3160                              gpointer      data)
3161 {
3162   gboolean separator;
3163
3164   gtk_tree_model_get (model, iter, PAGE_SETUP_LIST_COL_IS_SEPARATOR, &separator, -1);
3165   return separator;
3166 }
3167
3168 static void
3169 page_name_func (GtkCellLayout   *cell_layout,
3170                 GtkCellRenderer *cell,
3171                 GtkTreeModel    *tree_model,
3172                 GtkTreeIter     *iter,
3173                 gpointer         data)
3174 {
3175   GtkPageSetup *page_setup;
3176   GtkPaperSize *paper_size;
3177
3178   gtk_tree_model_get (tree_model, iter,
3179                       PAGE_SETUP_LIST_COL_PAGE_SETUP, &page_setup, -1);
3180   if (page_setup)
3181     {
3182       paper_size = gtk_page_setup_get_paper_size (page_setup);
3183       g_object_set (cell, "text",  gtk_paper_size_get_display_name (paper_size), NULL);
3184       g_object_unref (page_setup);
3185     }
3186   else
3187     g_object_set (cell, "text",  _("Manage Custom Sizes..."), NULL);
3188 }
3189
3190 static void
3191 create_page_setup_page (GtkPrintUnixDialog *dialog)
3192 {
3193   GtkPrintUnixDialogPrivate *priv = dialog->priv;
3194   GtkWidget *main_vbox, *label, *hbox, *hbox2;
3195   GtkWidget *frame, *table, *widget;
3196   GtkWidget *combo, *spinbutton, *draw;
3197   GtkCellRenderer *cell;
3198
3199   main_vbox = gtk_vbox_new (FALSE, 18);
3200   gtk_container_set_border_width (GTK_CONTAINER (main_vbox), 12);
3201   gtk_widget_show (main_vbox);
3202
3203   hbox = gtk_hbox_new (FALSE, 18);
3204   gtk_widget_show (hbox);
3205   gtk_box_pack_start (GTK_BOX (main_vbox), hbox, FALSE, FALSE, 0);
3206
3207   table = gtk_table_new (5, 2, FALSE);
3208   gtk_table_set_row_spacings (GTK_TABLE (table), 6);
3209   gtk_table_set_col_spacings (GTK_TABLE (table), 12);
3210   frame = wrap_in_frame (_("Layout"), table);
3211   gtk_box_pack_start (GTK_BOX (hbox), frame, TRUE, TRUE, 0);
3212   gtk_widget_show (table);
3213
3214   label = gtk_label_new_with_mnemonic (_("T_wo-sided:"));
3215   gtk_misc_set_alignment (GTK_MISC (label), 0.0, 0.5);
3216   gtk_widget_show (label);
3217   gtk_table_attach (GTK_TABLE (table), label,
3218                     0, 1, 0, 1,  GTK_FILL, 0,
3219                     0, 0);
3220
3221   widget = gtk_printer_option_widget_new (NULL);
3222   priv->duplex = GTK_PRINTER_OPTION_WIDGET (widget);
3223   gtk_widget_show (widget);
3224   gtk_table_attach (GTK_TABLE (table), widget,
3225                     1, 2, 0, 1,  GTK_FILL, 0,
3226                     0, 0);
3227   gtk_label_set_mnemonic_widget (GTK_LABEL (label), widget);
3228
3229   label = gtk_label_new_with_mnemonic (_("Pages per _side:"));
3230   gtk_misc_set_alignment (GTK_MISC (label), 0.0, 0.5);
3231   gtk_widget_show (label);
3232   gtk_table_attach (GTK_TABLE (table), label,
3233                     0, 1, 1, 2,  GTK_FILL, 0,
3234                     0, 0);
3235
3236   widget = gtk_printer_option_widget_new (NULL);
3237   g_signal_connect_swapped (widget, "changed", G_CALLBACK (redraw_page_layout_preview), dialog);
3238   g_signal_connect_swapped (widget, "changed", G_CALLBACK (update_number_up_layout), dialog);
3239   priv->pages_per_sheet = GTK_PRINTER_OPTION_WIDGET (widget);
3240   gtk_widget_show (widget);
3241   gtk_table_attach (GTK_TABLE (table), widget,
3242                     1, 2, 1, 2,  GTK_FILL, 0,
3243                     0, 0);
3244   gtk_label_set_mnemonic_widget (GTK_LABEL (label), widget);
3245
3246   label = gtk_label_new_with_mnemonic (_("Page or_dering:"));
3247   gtk_misc_set_alignment (GTK_MISC (label), 0.0, 0.5);
3248   gtk_widget_show (label);
3249   gtk_table_attach (GTK_TABLE (table), label,
3250                     0, 1, 2, 3,  GTK_FILL, 0,
3251                     0, 0);
3252
3253   widget = gtk_printer_option_widget_new (NULL);
3254   g_signal_connect_swapped (widget, "changed", G_CALLBACK (redraw_page_layout_preview), dialog);
3255   priv->number_up_layout = GTK_PRINTER_OPTION_WIDGET (widget);
3256   gtk_widget_show (widget);
3257   gtk_table_attach (GTK_TABLE (table), widget,
3258                     1, 2, 2, 3,  GTK_FILL, 0,
3259                     0, 0);
3260   gtk_label_set_mnemonic_widget (GTK_LABEL (label), widget);
3261
3262   label = gtk_label_new_with_mnemonic (_("_Only print:"));
3263   gtk_misc_set_alignment (GTK_MISC (label), 0.0, 0.5);
3264   gtk_widget_show (label);
3265   gtk_table_attach (GTK_TABLE (table), label,
3266                     0, 1, 3, 4,  GTK_FILL, 0,
3267                     0, 0);
3268
3269   combo = gtk_combo_box_new_text ();
3270   priv->page_set_combo = combo;
3271   gtk_widget_show (combo);
3272   gtk_table_attach (GTK_TABLE (table), combo,
3273                     1, 2, 3, 4,  GTK_FILL, 0,
3274                     0, 0);
3275   gtk_label_set_mnemonic_widget (GTK_LABEL (label), combo);
3276   /* In enum order */
3277   gtk_combo_box_append_text (GTK_COMBO_BOX (combo), _("All sheets"));
3278   gtk_combo_box_append_text (GTK_COMBO_BOX (combo), _("Even sheets"));
3279   gtk_combo_box_append_text (GTK_COMBO_BOX (combo), _("Odd sheets"));
3280   gtk_combo_box_set_active (GTK_COMBO_BOX (combo), 0);
3281
3282   label = gtk_label_new_with_mnemonic (_("Sc_ale:"));
3283   gtk_misc_set_alignment (GTK_MISC (label), 0.0, 0.5);
3284   gtk_widget_show (label);
3285   gtk_table_attach (GTK_TABLE (table), label,
3286                     0, 1, 4, 5,  GTK_FILL, 0,
3287                     0, 0);
3288
3289   hbox2 = gtk_hbox_new (FALSE, 6);
3290   gtk_widget_show (hbox2);
3291   gtk_table_attach (GTK_TABLE (table), hbox2,
3292                     1, 2, 4, 5,  GTK_FILL, 0,
3293                     0, 0);
3294
3295   spinbutton = gtk_spin_button_new_with_range (1.0, 1000.0, 1.0);
3296   priv->scale_spin = spinbutton;
3297   gtk_spin_button_set_digits (GTK_SPIN_BUTTON (spinbutton), 1);
3298   gtk_spin_button_set_value (GTK_SPIN_BUTTON (spinbutton), 100.0);
3299   gtk_box_pack_start (GTK_BOX (hbox2), spinbutton, FALSE, FALSE, 0);
3300   gtk_label_set_mnemonic_widget (GTK_LABEL (label), spinbutton);
3301   gtk_widget_show (spinbutton);
3302   label = gtk_label_new ("%"); /* FIXMEchpe does there exist any language where % needs to be translated? */
3303   gtk_widget_show (label);
3304   gtk_box_pack_start (GTK_BOX (hbox2), label, FALSE, FALSE, 0);
3305
3306   table = gtk_table_new (4, 2, FALSE);
3307   gtk_table_set_row_spacings (GTK_TABLE (table), 6);
3308   gtk_table_set_col_spacings (GTK_TABLE (table), 12);
3309   frame = wrap_in_frame (_("Paper"), table);
3310   gtk_box_pack_start (GTK_BOX (hbox), frame, TRUE, TRUE, 6);
3311   gtk_widget_show (table);
3312
3313   label = gtk_label_new_with_mnemonic (_("Paper _type:"));
3314   gtk_misc_set_alignment (GTK_MISC (label), 0.0, 0.5);
3315   gtk_widget_show (label);
3316   gtk_table_attach (GTK_TABLE (table), label,
3317                     0, 1, 0, 1,  GTK_FILL, 0,
3318                     0, 0);
3319
3320   widget = gtk_printer_option_widget_new (NULL);
3321   priv->paper_type = GTK_PRINTER_OPTION_WIDGET (widget);
3322   gtk_widget_show (widget);
3323   gtk_table_attach (GTK_TABLE (table), widget,
3324                     1, 2, 0, 1,  GTK_FILL, 0,
3325                     0, 0);
3326   gtk_label_set_mnemonic_widget (GTK_LABEL (label), widget);
3327
3328   label = gtk_label_new_with_mnemonic (_("Paper _source:"));
3329   gtk_misc_set_alignment (GTK_MISC (label), 0.0, 0.5);
3330   gtk_widget_show (label);
3331   gtk_table_attach (GTK_TABLE (table), label,
3332                     0, 1, 1, 2,  GTK_FILL, 0,
3333                     0, 0);
3334
3335   widget = gtk_printer_option_widget_new (NULL);
3336   priv->paper_source = GTK_PRINTER_OPTION_WIDGET (widget);
3337   gtk_widget_show (widget);
3338   gtk_table_attach (GTK_TABLE (table), widget,
3339                     1, 2, 1, 2,  GTK_FILL, 0,
3340                     0, 0);
3341   gtk_label_set_mnemonic_widget (GTK_LABEL (label), widget);
3342
3343   label = gtk_label_new_with_mnemonic (_("Output t_ray:"));
3344   gtk_misc_set_alignment (GTK_MISC (label), 0.0, 0.5);
3345   gtk_widget_show (label);
3346   gtk_table_attach (GTK_TABLE (table), label,
3347                     0, 1, 2, 3,  GTK_FILL, 0,
3348                     0, 0);
3349
3350   widget = gtk_printer_option_widget_new (NULL);
3351   priv->output_tray = GTK_PRINTER_OPTION_WIDGET (widget);
3352   gtk_widget_show (widget);
3353   gtk_table_attach (GTK_TABLE (table), widget,
3354                     1, 2, 2, 3,  GTK_FILL, 0,
3355                     0, 0);
3356   gtk_label_set_mnemonic_widget (GTK_LABEL (label), widget);
3357
3358
3359   label = gtk_label_new_with_mnemonic (_("_Paper size:"));
3360   priv->paper_size_combo_label = GTK_WIDGET (label);
3361   gtk_misc_set_alignment (GTK_MISC (label), 0.0, 0.5);
3362   gtk_widget_show (label);
3363   gtk_table_attach (GTK_TABLE (table), label,
3364                     0, 1, 3, 4,  GTK_FILL, 0,
3365                     0, 0);
3366
3367   combo = gtk_combo_box_new_with_model (GTK_TREE_MODEL (priv->page_setup_list));
3368   priv->paper_size_combo = GTK_WIDGET (combo);
3369   gtk_combo_box_set_row_separator_func (GTK_COMBO_BOX (combo), 
3370                                         paper_size_row_is_separator, NULL, NULL);
3371   cell = gtk_cell_renderer_text_new ();
3372   gtk_cell_layout_pack_start (GTK_CELL_LAYOUT (combo), cell, TRUE);
3373   gtk_cell_layout_set_cell_data_func (GTK_CELL_LAYOUT (combo), cell,
3374                                       page_name_func, NULL, NULL);
3375   gtk_table_attach (GTK_TABLE (table), combo,
3376                     1, 2, 3, 4,  GTK_FILL, 0,
3377                     0, 0);
3378   gtk_label_set_mnemonic_widget (GTK_LABEL (label), combo);
3379   gtk_widget_set_sensitive (combo, FALSE);
3380   gtk_widget_show (combo);
3381
3382
3383   label = gtk_label_new_with_mnemonic (_("Or_ientation:"));
3384   priv->orientation_combo_label = GTK_WIDGET (label);
3385   gtk_misc_set_alignment (GTK_MISC (label), 0.0, 0.5);
3386   gtk_widget_show (label);
3387   gtk_table_attach (GTK_TABLE (table), label,
3388                     0, 1, 4, 5,
3389                     GTK_FILL, 0, 0, 0);
3390
3391   combo = gtk_combo_box_new_text ();
3392   priv->orientation_combo = GTK_WIDGET (combo);
3393   gtk_table_attach (GTK_TABLE (table), combo,
3394                     1, 2, 4, 5,  GTK_FILL, 0,
3395                     0, 0);
3396   gtk_label_set_mnemonic_widget (GTK_LABEL (label), combo);
3397   /* In enum order */
3398   gtk_combo_box_append_text (GTK_COMBO_BOX (combo), _("Portrait"));
3399   gtk_combo_box_append_text (GTK_COMBO_BOX (combo), _("Landscape"));
3400   gtk_combo_box_append_text (GTK_COMBO_BOX (combo), _("Reverse portrait"));
3401   gtk_combo_box_append_text (GTK_COMBO_BOX (combo), _("Reverse landscape"));
3402   gtk_combo_box_set_active (GTK_COMBO_BOX (combo), 0);
3403   gtk_widget_set_sensitive (combo, FALSE);
3404   gtk_widget_show (combo);
3405
3406
3407   /* Add the page layout preview */
3408   hbox2 = gtk_hbox_new (FALSE, 0);
3409   gtk_widget_show (hbox2);
3410   gtk_box_pack_start (GTK_BOX (main_vbox), hbox2, TRUE, TRUE, 0);
3411
3412   draw = gtk_drawing_area_new ();
3413   GTK_WIDGET_SET_FLAGS (draw, GTK_NO_WINDOW);
3414   priv->page_layout_preview = draw;
3415   gtk_widget_set_size_request (draw, 350, 200);
3416   g_signal_connect (draw, "expose-event", G_CALLBACK (draw_page_cb), dialog);
3417   gtk_widget_show (draw);
3418
3419   gtk_box_pack_start (GTK_BOX (hbox2), draw, TRUE, FALSE, 0);
3420
3421   label = gtk_label_new (_("Page Setup"));
3422   gtk_widget_show (label);
3423
3424   gtk_notebook_append_page (GTK_NOTEBOOK (priv->notebook),
3425                             main_vbox, label);
3426 }
3427
3428 static void
3429 create_job_page (GtkPrintUnixDialog *dialog)
3430 {
3431   GtkPrintUnixDialogPrivate *priv = dialog->priv;
3432   GtkWidget *main_table, *label;
3433   GtkWidget *frame, *table, *radio;
3434   GtkWidget *entry, *widget;
3435   const gchar *at_tooltip;
3436   const gchar *on_hold_tooltip;
3437
3438   main_table = gtk_table_new (2, 2, FALSE);
3439   gtk_container_set_border_width (GTK_CONTAINER (main_table), 12);
3440   gtk_table_set_row_spacings (GTK_TABLE (main_table), 18);
3441   gtk_table_set_col_spacings (GTK_TABLE (main_table), 18);
3442
3443   table = gtk_table_new (2, 2, FALSE);
3444   gtk_table_set_row_spacings (GTK_TABLE (table), 6);
3445   gtk_table_set_col_spacings (GTK_TABLE (table), 12);
3446   frame = wrap_in_frame (_("Job Details"), table);
3447   gtk_table_attach (GTK_TABLE (main_table), frame,
3448                     0, 1, 0, 1,  GTK_FILL, 0,
3449                     0, 0);
3450   gtk_widget_show (table);
3451
3452   label = gtk_label_new_with_mnemonic (_("Pri_ority:"));
3453   gtk_misc_set_alignment (GTK_MISC (label), 0.0, 0.5);
3454   gtk_widget_show (label);
3455   gtk_table_attach (GTK_TABLE (table), label,
3456                     0, 1, 0, 1,  GTK_FILL, 0,
3457                     0, 0);
3458
3459   widget = gtk_printer_option_widget_new (NULL);
3460   priv->job_prio = GTK_PRINTER_OPTION_WIDGET (widget);
3461   gtk_widget_show (widget);
3462   gtk_table_attach (GTK_TABLE (table), widget,
3463                     1, 2, 0, 1,  GTK_FILL, 0,
3464                     0, 0);
3465   gtk_label_set_mnemonic_widget (GTK_LABEL (label), widget);
3466
3467   label = gtk_label_new_with_mnemonic (_("_Billing info:"));
3468   gtk_misc_set_alignment (GTK_MISC (label), 0.0, 0.5);
3469   gtk_widget_show (label);
3470   gtk_table_attach (GTK_TABLE (table), label,
3471                     0, 1, 1, 2,  GTK_FILL, 0,
3472                     0, 0);
3473
3474   widget = gtk_printer_option_widget_new (NULL);
3475   priv->billing_info = GTK_PRINTER_OPTION_WIDGET (widget);
3476   gtk_widget_show (widget);
3477   gtk_table_attach (GTK_TABLE (table), widget,
3478                     1, 2, 1, 2,  GTK_FILL, 0,
3479                     0, 0);
3480   gtk_label_set_mnemonic_widget (GTK_LABEL (label), widget);
3481
3482   table = gtk_table_new (2, 2, FALSE);
3483   gtk_table_set_row_spacings (GTK_TABLE (table), 6);
3484   gtk_table_set_col_spacings (GTK_TABLE (table), 12);
3485   frame = wrap_in_frame (_("Print Document"), table);
3486   gtk_table_attach (GTK_TABLE (main_table), frame,
3487                     0, 1, 1, 2,  GTK_FILL, 0,
3488                     0, 0);
3489   gtk_widget_show (table);
3490
3491   /* Translators: this is one of the choices for the print at option
3492    * in the print dialog
3493    */
3494   radio = gtk_radio_button_new_with_mnemonic (NULL, _("_Now"));
3495   priv->print_now_radio = radio;
3496   gtk_widget_show (radio);
3497   gtk_table_attach (GTK_TABLE (table), radio,
3498                     0, 2, 0, 1,  GTK_FILL, 0,
3499                     0, 0);
3500   /* Translators: this is one of the choices for the print at option
3501    * in the print dialog. It also serves as the label for an entry that
3502    * allows the user to enter a time.
3503    */
3504   radio = gtk_radio_button_new_with_mnemonic (gtk_radio_button_get_group (GTK_RADIO_BUTTON (radio)),
3505                                               _("A_t:"));
3506
3507   /* Translators: Ability to parse the am/pm format depends on actual locale.
3508    * You can remove the am/pm values below for your locale if they are not
3509    * supported.
3510    */
3511   at_tooltip = _("Specify the time of print,\n e.g. 15:30, 2:35 pm, 14:15:20, 11:46:30 am, 4 pm");
3512   gtk_widget_set_tooltip_text (radio, at_tooltip);
3513   priv->print_at_radio = radio;
3514   gtk_widget_show (radio);
3515   gtk_table_attach (GTK_TABLE (table), radio,
3516                     0, 1, 1, 2,  GTK_FILL, 0,
3517                     0, 0);
3518
3519   entry = gtk_entry_new ();
3520   gtk_widget_set_tooltip_text (entry, at_tooltip);
3521   atk_object_set_name (gtk_widget_get_accessible (entry), _("Time of print"));
3522   atk_object_set_description (gtk_widget_get_accessible (entry), at_tooltip);
3523   priv->print_at_entry = entry;
3524   gtk_widget_show (entry);
3525   gtk_table_attach (GTK_TABLE (table), entry,
3526                     1, 2, 1, 2,  GTK_FILL, 0,
3527                     0, 0);
3528
3529   g_signal_connect (radio, "toggled", G_CALLBACK (update_entry_sensitivity), entry);
3530   update_entry_sensitivity (radio, entry);
3531
3532   /* Translators: this is one of the choices for the print at option
3533    * in the print dialog. It means that the print job will not be
3534    * printed until it explicitly gets 'released'.
3535    */
3536   radio = gtk_radio_button_new_with_mnemonic (gtk_radio_button_get_group (GTK_RADIO_BUTTON (radio)),
3537                                               _("On _hold"));
3538   on_hold_tooltip = _("Hold the job until it is explicitly released");
3539   gtk_widget_set_tooltip_text (radio, on_hold_tooltip);
3540   priv->print_hold_radio = radio;
3541   gtk_widget_show (radio);
3542   gtk_table_attach (GTK_TABLE (table), radio,
3543                     0, 2, 2, 3,  GTK_FILL, 0,
3544                     0, 0);
3545
3546   g_signal_connect_swapped (priv->print_now_radio, "toggled",
3547                             G_CALLBACK (update_print_at_option), dialog);
3548   g_signal_connect_swapped (priv->print_at_radio, "toggled",
3549                             G_CALLBACK (update_print_at_option), dialog);
3550   g_signal_connect_swapped (priv->print_at_entry, "changed",
3551                             G_CALLBACK (update_print_at_option), dialog);
3552   g_signal_connect_swapped (priv->print_hold_radio, "toggled",
3553                             G_CALLBACK (update_print_at_option), dialog);
3554
3555   table = gtk_table_new (2, 2, FALSE);
3556   gtk_table_set_row_spacings (GTK_TABLE (table), 6);
3557   gtk_table_set_col_spacings (GTK_TABLE (table), 12);
3558   frame = wrap_in_frame (_("Add Cover Page"), table);
3559   gtk_table_attach (GTK_TABLE (main_table), frame,
3560                     1, 2, 0, 1,  GTK_FILL, 0,
3561                     0, 0);
3562   gtk_widget_show (table);
3563
3564   /* Translators, this is the label used for the option in the print
3565    * dialog that controls the front cover page.
3566    */
3567   label = gtk_label_new_with_mnemonic (_("Be_fore:"));
3568   gtk_misc_set_alignment (GTK_MISC (label), 0.0, 0.5);
3569   gtk_widget_show (label);
3570   gtk_table_attach (GTK_TABLE (table), label,
3571                     0, 1, 0, 1,  GTK_FILL, 0,
3572                     0, 0);
3573
3574   widget = gtk_printer_option_widget_new (NULL);
3575   priv->cover_before = GTK_PRINTER_OPTION_WIDGET (widget);
3576   gtk_widget_show (widget);
3577   gtk_table_attach (GTK_TABLE (table), widget,
3578                     1, 2, 0, 1,  GTK_FILL, 0,
3579                     0, 0);
3580   gtk_label_set_mnemonic_widget (GTK_LABEL (label), widget);
3581
3582   /* Translators, this is the label used for the option in the print
3583    * dialog that controls the back cover page.
3584    */
3585   label = gtk_label_new_with_mnemonic (_("_After:"));
3586   gtk_misc_set_alignment (GTK_MISC (label), 0.0, 0.5);
3587   gtk_widget_show (label);
3588   gtk_table_attach (GTK_TABLE (table), label,
3589                     0, 1, 1, 2,  GTK_FILL, 0,
3590                     0, 0);
3591
3592   widget = gtk_printer_option_widget_new (NULL);
3593   priv->cover_after = GTK_PRINTER_OPTION_WIDGET (widget);
3594   gtk_widget_show (widget);
3595   gtk_table_attach (GTK_TABLE (table), widget,
3596                     1, 2, 1, 2,  GTK_FILL, 0,
3597                     0, 0);
3598   gtk_label_set_mnemonic_widget (GTK_LABEL (label), widget);
3599
3600   /* Translators: this is the tab label for the notebook tab containing
3601    * job-specific options in the print dialog
3602    */
3603   label = gtk_label_new (_("Job"));
3604   gtk_widget_show (label);
3605
3606   priv->job_page = main_table;
3607   gtk_notebook_append_page (GTK_NOTEBOOK (priv->notebook),
3608                             main_table, label);
3609 }
3610
3611 static void
3612 create_optional_page (GtkPrintUnixDialog  *dialog,
3613                       const gchar         *text,
3614                       GtkWidget          **table_out,
3615                       GtkWidget          **page_out)
3616 {
3617   GtkPrintUnixDialogPrivate *priv = dialog->priv;
3618   GtkWidget *table, *label, *scrolled;
3619
3620   scrolled = gtk_scrolled_window_new (NULL, NULL);
3621   gtk_scrolled_window_set_policy (GTK_SCROLLED_WINDOW (scrolled),
3622                                   GTK_POLICY_NEVER,
3623                                   GTK_POLICY_AUTOMATIC);
3624
3625   table = gtk_table_new (1, 2, FALSE);
3626   gtk_table_set_row_spacings (GTK_TABLE (table), 6);
3627   gtk_table_set_col_spacings (GTK_TABLE (table), 12);
3628   gtk_container_set_border_width (GTK_CONTAINER (table), 12);
3629   gtk_widget_show (table);
3630
3631   gtk_scrolled_window_add_with_viewport (GTK_SCROLLED_WINDOW (scrolled),
3632                                          table);
3633   gtk_viewport_set_shadow_type (GTK_VIEWPORT (GTK_BIN(scrolled)->child),
3634                                 GTK_SHADOW_NONE);
3635
3636   label = gtk_label_new (text);
3637   gtk_widget_show (label);
3638
3639   gtk_notebook_append_page (GTK_NOTEBOOK (priv->notebook),
3640                             scrolled, label);
3641
3642   *table_out = table;
3643   *page_out = scrolled;
3644 }
3645
3646 static void
3647 create_advanced_page (GtkPrintUnixDialog *dialog)
3648 {
3649   GtkPrintUnixDialogPrivate *priv = dialog->priv;
3650   GtkWidget *main_vbox, *label, *scrolled;
3651
3652   scrolled = gtk_scrolled_window_new (NULL, NULL);
3653   priv->advanced_page = scrolled;
3654   gtk_scrolled_window_set_policy (GTK_SCROLLED_WINDOW (scrolled),
3655                                   GTK_POLICY_NEVER,
3656                                   GTK_POLICY_AUTOMATIC);
3657
3658   main_vbox = gtk_vbox_new (FALSE, 18);
3659   gtk_container_set_border_width (GTK_CONTAINER (main_vbox), 12);
3660   gtk_widget_show (main_vbox);
3661
3662   gtk_scrolled_window_add_with_viewport (GTK_SCROLLED_WINDOW (scrolled),
3663                                          main_vbox);
3664   gtk_viewport_set_shadow_type (GTK_VIEWPORT (GTK_BIN(scrolled)->child),
3665                                 GTK_SHADOW_NONE);
3666
3667   priv->advanced_vbox = main_vbox;
3668
3669   label = gtk_label_new (_("Advanced"));
3670   gtk_widget_show (label);
3671
3672   gtk_notebook_append_page (GTK_NOTEBOOK (priv->notebook),
3673                             scrolled, label);
3674 }
3675
3676 static void
3677 populate_dialog (GtkPrintUnixDialog *print_dialog)
3678 {
3679   GtkPrintUnixDialogPrivate *priv = print_dialog->priv;
3680   GtkDialog *dialog = GTK_DIALOG (print_dialog);
3681   GtkWidget *vbox, *conflict_hbox, *image, *label;
3682
3683   gtk_dialog_set_has_separator (dialog, FALSE);
3684   gtk_container_set_border_width (GTK_CONTAINER (dialog), 5);
3685   gtk_box_set_spacing (GTK_BOX (dialog->vbox), 2); /* 2 * 5 + 2 = 12 */
3686   gtk_container_set_border_width (GTK_CONTAINER (dialog->action_area), 5);
3687   gtk_box_set_spacing (GTK_BOX (dialog->action_area), 6);
3688
3689   vbox = gtk_vbox_new (FALSE, 6);
3690   gtk_container_set_border_width (GTK_CONTAINER (vbox), 5);
3691   gtk_box_pack_start (GTK_BOX (dialog->vbox), vbox, TRUE, TRUE, 0);
3692   gtk_widget_show (vbox);
3693
3694   priv->notebook = gtk_notebook_new ();
3695   gtk_box_pack_start (GTK_BOX (vbox), priv->notebook, TRUE, TRUE, 0);
3696   gtk_widget_show (priv->notebook);
3697
3698   create_printer_list_model (print_dialog);
3699
3700   create_main_page (print_dialog);
3701   create_page_setup_page (print_dialog);
3702   create_job_page (print_dialog);
3703   create_optional_page (print_dialog, _("Image Quality"),
3704                         &priv->image_quality_table,
3705                         &priv->image_quality_page);
3706   create_optional_page (print_dialog, _("Color"),
3707                         &priv->color_table,
3708                         &priv->color_page);
3709   create_optional_page (print_dialog, _("Finishing"),
3710                         &priv->finishing_table,
3711                         &priv->finishing_page);
3712   create_advanced_page (print_dialog);
3713
3714   priv->conflicts_widget = conflict_hbox = gtk_hbox_new (FALSE, 12);
3715   gtk_box_pack_end (GTK_BOX (vbox), conflict_hbox, FALSE, FALSE, 0);
3716   image = gtk_image_new_from_stock (GTK_STOCK_DIALOG_WARNING, GTK_ICON_SIZE_MENU);
3717   gtk_widget_show (image);
3718   gtk_box_pack_start (GTK_BOX (conflict_hbox), image, FALSE, TRUE, 0);
3719   label = gtk_label_new (_("Some of the settings in the dialog conflict"));
3720   gtk_widget_show (label);
3721   gtk_box_pack_start (GTK_BOX (conflict_hbox), label, FALSE, TRUE, 0);
3722
3723   load_print_backends (print_dialog);
3724 }
3725
3726 /**
3727  * gtk_print_unix_dialog_new:
3728  * @title: Title of the dialog, or %NULL
3729  * @parent: Transient parent of the dialog, or %NULL
3730  *
3731  * Creates a new #GtkPrintUnixDialog.
3732  *
3733  * Return value: a new #GtkPrintUnixDialog
3734  *
3735  * Since: 2.10
3736  **/
3737 GtkWidget *
3738 gtk_print_unix_dialog_new (const gchar *title,
3739                            GtkWindow   *parent)
3740 {
3741   GtkWidget *result;
3742   const gchar *_title = _("Print");
3743
3744   if (title)
3745     _title = title;
3746
3747   result = g_object_new (GTK_TYPE_PRINT_UNIX_DIALOG,
3748                          "transient-for", parent,
3749                          "title", _title,
3750                          "has-separator", FALSE,
3751                          NULL);
3752
3753   return result;
3754 }
3755
3756 /**
3757  * gtk_print_unix_dialog_get_selected_printer:
3758  * @dialog: a #GtkPrintUnixDialog
3759  *
3760  * Gets the currently selected printer.
3761  *
3762  * Returns: the currently selected printer
3763  *
3764  * Since: 2.10
3765  */
3766 GtkPrinter *
3767 gtk_print_unix_dialog_get_selected_printer (GtkPrintUnixDialog *dialog)
3768 {
3769   g_return_val_if_fail (GTK_IS_PRINT_UNIX_DIALOG (dialog), NULL);
3770
3771   return dialog->priv->current_printer;
3772 }
3773
3774 /**
3775  * gtk_print_unix_dialog_set_page_setup:
3776  * @dialog: a #GtkPrintUnixDialog
3777  * @page_setup: a #GtkPageSetup
3778  *
3779  * Sets the page setup of the #GtkPrintUnixDialog.
3780  *
3781  * Since: 2.10
3782  */
3783 void
3784 gtk_print_unix_dialog_set_page_setup (GtkPrintUnixDialog *dialog,
3785                                       GtkPageSetup       *page_setup)
3786 {
3787   GtkPrintUnixDialogPrivate *priv;
3788
3789   g_return_if_fail (GTK_IS_PRINT_UNIX_DIALOG (dialog));
3790   g_return_if_fail (GTK_IS_PAGE_SETUP (page_setup));
3791
3792   priv = dialog->priv;
3793
3794   if (priv->page_setup != page_setup)
3795     {
3796       g_object_unref (priv->page_setup);
3797       priv->page_setup = g_object_ref (page_setup);
3798
3799       priv->page_setup_set = TRUE;
3800
3801       g_object_notify (G_OBJECT (dialog), "page-setup");
3802     }
3803 }
3804
3805 /**
3806  * gtk_print_unix_dialog_get_page_setup:
3807  * @dialog: a #GtkPrintUnixDialog
3808  *
3809  * Gets the page setup that is used by the #GtkPrintUnixDialog.
3810  *
3811  * Returns: the page setup of @dialog.
3812  *
3813  * Since: 2.10
3814  */
3815 GtkPageSetup *
3816 gtk_print_unix_dialog_get_page_setup (GtkPrintUnixDialog *dialog)
3817 {
3818   g_return_val_if_fail (GTK_IS_PRINT_UNIX_DIALOG (dialog), NULL);
3819
3820   return dialog->priv->page_setup;
3821 }
3822
3823 /**
3824  * gtk_print_unix_dialog_get_page_setup_set:
3825  * @dialog: a #GtkPrintUnixDialog
3826  *
3827  * Gets the page setup that is used by the #GtkPrintUnixDialog.
3828  *
3829  * Returns: whether a page setup was set by user.
3830  *
3831  * Since: 2.18
3832  */
3833 gboolean
3834 gtk_print_unix_dialog_get_page_setup_set (GtkPrintUnixDialog *dialog)
3835 {
3836   g_return_val_if_fail (GTK_IS_PRINT_UNIX_DIALOG (dialog), FALSE);
3837
3838   return dialog->priv->page_setup_set;
3839 }
3840
3841 /**
3842  * gtk_print_unix_dialog_set_current_page:
3843  * @dialog: a #GtkPrintUnixDialog
3844  * @current_page: the current page number.
3845  *
3846  * Sets the current page number. If @current_page is not -1, this enables
3847  * the current page choice for the range of pages to print.
3848  *
3849  * Since: 2.10
3850  */
3851 void
3852 gtk_print_unix_dialog_set_current_page (GtkPrintUnixDialog *dialog,
3853                                         gint                current_page)
3854 {
3855   GtkPrintUnixDialogPrivate *priv;
3856
3857   g_return_if_fail (GTK_IS_PRINT_UNIX_DIALOG (dialog));
3858
3859   priv = dialog->priv;
3860
3861   if (priv->current_page != current_page)
3862     {
3863       priv->current_page = current_page;
3864
3865       if (priv->current_page_radio)
3866         gtk_widget_set_sensitive (priv->current_page_radio, current_page != -1);
3867
3868       g_object_notify (G_OBJECT (dialog), "current-page");
3869     }
3870 }
3871
3872 /**
3873  * gtk_print_unix_dialog_get_current_page:
3874  * @dialog: a #GtkPrintUnixDialog
3875  *
3876  * Gets the current page of the #GtkPrintDialog.
3877  *
3878  * Returns: the current page of @dialog
3879  *
3880  * Since: 2.10
3881  */
3882 gint
3883 gtk_print_unix_dialog_get_current_page (GtkPrintUnixDialog *dialog)
3884 {
3885   g_return_val_if_fail (GTK_IS_PRINT_UNIX_DIALOG (dialog), -1);
3886
3887   return dialog->priv->current_page;
3888 }
3889
3890 static gboolean
3891 set_active_printer (GtkPrintUnixDialog *dialog,
3892                     const gchar        *printer_name)
3893 {
3894   GtkPrintUnixDialogPrivate *priv = dialog->priv;
3895   GtkTreeModel *model;
3896   GtkTreeIter iter, filter_iter;
3897   GtkTreeSelection *selection;
3898   GtkPrinter *printer;
3899
3900   model = GTK_TREE_MODEL (priv->printer_list);
3901
3902   if (gtk_tree_model_get_iter_first (model, &iter))
3903     {
3904       do
3905         {
3906           gtk_tree_model_get (GTK_TREE_MODEL (priv->printer_list), &iter,
3907                               PRINTER_LIST_COL_PRINTER_OBJ, &printer, -1);
3908           if (printer == NULL)
3909             continue;
3910
3911           if (strcmp (gtk_printer_get_name (printer), printer_name) == 0)
3912             {
3913               gtk_tree_model_filter_convert_child_iter_to_iter (priv->printer_list_filter,
3914                                                                 &filter_iter, &iter);
3915
3916               selection = gtk_tree_view_get_selection (GTK_TREE_VIEW (priv->printer_treeview));
3917               priv->internal_printer_change = TRUE;
3918               gtk_tree_selection_select_iter (selection, &filter_iter);
3919               priv->internal_printer_change = FALSE;
3920               g_free (priv->waiting_for_printer);
3921               priv->waiting_for_printer = NULL;
3922
3923               g_object_unref (printer);
3924               return TRUE;
3925             }
3926
3927           g_object_unref (printer);
3928
3929         } while (gtk_tree_model_iter_next (model, &iter));
3930     }
3931
3932   return FALSE;
3933 }
3934
3935 /**
3936  * gtk_print_unix_dialog_set_settings:
3937  * @dialog: a #GtkPrintUnixDialog
3938  * @settings: a #GtkPrintSettings, or %NULL
3939  *
3940  * Sets the #GtkPrintSettings for the #GtkPrintUnixDialog. Typically,
3941  * this is used to restore saved print settings from a previous print
3942  * operation before the print dialog is shown.
3943  *
3944  * Since: 2.10
3945  **/
3946 void
3947 gtk_print_unix_dialog_set_settings (GtkPrintUnixDialog *dialog,
3948                                     GtkPrintSettings   *settings)
3949 {
3950   GtkPrintUnixDialogPrivate *priv;
3951   const gchar *printer;
3952   GtkPageRange *ranges;
3953   gint num_ranges;
3954
3955   g_return_if_fail (GTK_IS_PRINT_UNIX_DIALOG (dialog));
3956   g_return_if_fail (settings == NULL || GTK_IS_PRINT_SETTINGS (settings));
3957
3958   priv = dialog->priv;
3959
3960   if (settings != NULL)
3961     {
3962       dialog_set_collate (dialog, gtk_print_settings_get_collate (settings));
3963       dialog_set_reverse (dialog, gtk_print_settings_get_reverse (settings));
3964       dialog_set_n_copies (dialog, gtk_print_settings_get_n_copies (settings));
3965       dialog_set_scale (dialog, gtk_print_settings_get_scale (settings));
3966       dialog_set_page_set (dialog, gtk_print_settings_get_page_set (settings));
3967       dialog_set_print_pages (dialog, gtk_print_settings_get_print_pages (settings));
3968       ranges = gtk_print_settings_get_page_ranges (settings, &num_ranges);
3969       if (ranges)
3970         {
3971           dialog_set_page_ranges (dialog, ranges, num_ranges);
3972           g_free (ranges);
3973         }
3974
3975       priv->format_for_printer =
3976         g_strdup (gtk_print_settings_get (settings, "format-for-printer"));
3977     }
3978
3979   if (priv->initial_settings)
3980     g_object_unref (priv->initial_settings);
3981
3982   priv->initial_settings = settings;
3983
3984   g_free (priv->waiting_for_printer);
3985   priv->waiting_for_printer = NULL;
3986
3987   if (settings)
3988     {
3989       g_object_ref (settings);
3990
3991       printer = gtk_print_settings_get_printer (settings);
3992
3993       if (printer && !set_active_printer (dialog, printer))
3994         priv->waiting_for_printer = g_strdup (printer);
3995     }
3996
3997   g_object_notify (G_OBJECT (dialog), "print-settings");
3998 }
3999
4000 /**
4001  * gtk_print_unix_dialog_get_settings:
4002  * @dialog: a #GtkPrintUnixDialog
4003  *
4004  * Gets a new #GtkPrintSettings object that represents the
4005  * current values in the print dialog. Note that this creates a
4006  * <emphasis>new object</emphasis>, and you need to unref it
4007  * if don't want to keep it.
4008  *
4009  * Returns: a new #GtkPrintSettings object with the values from @dialog
4010  *
4011  * Since: 2.10
4012  */
4013 GtkPrintSettings *
4014 gtk_print_unix_dialog_get_settings (GtkPrintUnixDialog *dialog)
4015 {
4016   GtkPrintUnixDialogPrivate *priv;
4017   GtkPrintSettings *settings;
4018   GtkPrintPages print_pages;
4019   GtkPageRange *ranges;
4020   gint n_ranges;
4021
4022   g_return_val_if_fail (GTK_IS_PRINT_UNIX_DIALOG (dialog), NULL);
4023
4024   priv = dialog->priv;
4025   settings = gtk_print_settings_new ();
4026
4027   if (priv->current_printer)
4028     gtk_print_settings_set_printer (settings,
4029                                     gtk_printer_get_name (priv->current_printer));
4030   else
4031     gtk_print_settings_set_printer (settings, "default");
4032
4033   gtk_print_settings_set (settings, "format-for-printer",
4034                           priv->format_for_printer);
4035
4036   gtk_print_settings_set_collate (settings,
4037                                   dialog_get_collate (dialog));
4038
4039   gtk_print_settings_set_reverse (settings,
4040                                   dialog_get_reverse (dialog));
4041
4042   gtk_print_settings_set_n_copies (settings,
4043                                    dialog_get_n_copies (dialog));
4044
4045   gtk_print_settings_set_scale (settings,
4046                                 dialog_get_scale (dialog));
4047
4048   gtk_print_settings_set_page_set (settings,
4049                                    dialog_get_page_set (dialog));
4050
4051   print_pages = dialog_get_print_pages (dialog);
4052   gtk_print_settings_set_print_pages (settings, print_pages);
4053
4054   ranges = dialog_get_page_ranges (dialog, &n_ranges);
4055   if (ranges)
4056     {
4057       gtk_print_settings_set_page_ranges  (settings, ranges, n_ranges);
4058       g_free (ranges);
4059     }
4060
4061   /* TODO: print when. How to handle? */
4062
4063   if (priv->current_printer)
4064     _gtk_printer_get_settings_from_options (priv->current_printer,
4065                                             priv->options,
4066                                             settings);
4067
4068   return settings;
4069 }
4070
4071 /**
4072  * gtk_print_unix_dialog_add_custom_tab:
4073  * @dialog: a #GtkPrintUnixDialog
4074  * @child: the widget to put in the custom tab
4075  * @tab_label: the widget to use as tab label
4076  *
4077  * Adds a custom tab to the print dialog.
4078  *
4079  * Since: 2.10
4080  */
4081 void
4082 gtk_print_unix_dialog_add_custom_tab (GtkPrintUnixDialog *dialog,
4083                                       GtkWidget          *child,
4084                                       GtkWidget          *tab_label)
4085 {
4086   gtk_notebook_insert_page (GTK_NOTEBOOK (dialog->priv->notebook),
4087                             child, tab_label, 2);
4088   gtk_widget_show (child);
4089   gtk_widget_show (tab_label);
4090 }
4091
4092 /**
4093  * gtk_print_unix_dialog_set_manual_capabilities:
4094  * @dialog: a #GtkPrintUnixDialog
4095  * @capabilities: the printing capabilities of your application
4096  *
4097  * This lets you specify the printing capabilities your application
4098  * supports. For instance, if you can handle scaling the output then
4099  * you pass #GTK_PRINT_CAPABILITY_SCALE. If you don't pass that, then
4100  * the dialog will only let you select the scale if the printing
4101  * system automatically handles scaling.
4102  *
4103  * Since: 2.10
4104  */
4105 void
4106 gtk_print_unix_dialog_set_manual_capabilities (GtkPrintUnixDialog   *dialog,
4107                                                GtkPrintCapabilities  capabilities)
4108 {
4109   GtkPrintUnixDialogPrivate *priv = dialog->priv;
4110
4111   if (priv->manual_capabilities != capabilities)
4112     {
4113       priv->manual_capabilities = capabilities;
4114       update_dialog_from_capabilities (dialog);
4115
4116       if (priv->current_printer)
4117         {
4118           GtkTreeSelection *selection;
4119
4120           selection = gtk_tree_view_get_selection (GTK_TREE_VIEW (priv->printer_treeview));
4121
4122           g_object_unref (priv->current_printer);
4123           priv->current_printer = NULL;
4124           priv->internal_printer_change = TRUE;
4125           selected_printer_changed (selection, dialog);
4126           priv->internal_printer_change = FALSE;
4127        }
4128
4129       g_object_notify (G_OBJECT (dialog), "manual-capabilities");
4130     }
4131 }
4132
4133 /**
4134  * gtk_print_unix_dialog_get_manual_capabilities:
4135  * @dialog: a #GtkPrintUnixDialog
4136  *
4137  * Gets the value of #GtkPrintUnixDialog::manual-capabilities property.
4138  *
4139  * Returns: the printing capabilities
4140  *
4141  * Since: 2.18
4142  */
4143 GtkPrintCapabilities
4144 gtk_print_unix_dialog_get_manual_capabilities (GtkPrintUnixDialog *dialog)
4145 {
4146   g_return_val_if_fail (GTK_IS_PRINT_UNIX_DIALOG (dialog), FALSE);
4147
4148   return dialog->priv->manual_capabilities;
4149 }
4150
4151 /**
4152  * gtk_print_unix_dialog_set_support_selection:
4153  * @dialog: a #GtkPrintUnixDialog
4154  * @support_selection: %TRUE to allow print selection
4155  *
4156  * Sets whether the print dialog allows user to print a selection.
4157  *
4158  * Since: 2.18
4159  */
4160 void
4161 gtk_print_unix_dialog_set_support_selection (GtkPrintUnixDialog *dialog,
4162                                              gboolean            support_selection)
4163 {
4164   GtkPrintUnixDialogPrivate *priv;
4165
4166   g_return_if_fail (GTK_IS_PRINT_UNIX_DIALOG (dialog));
4167
4168   priv = dialog->priv;
4169
4170   support_selection = support_selection != FALSE;
4171   if (priv->support_selection != support_selection)
4172     {
4173       priv->support_selection = support_selection;
4174
4175       if (priv->selection_radio)
4176         {
4177           if (support_selection)
4178             {
4179               gtk_widget_set_sensitive (priv->selection_radio, priv->has_selection);
4180               gtk_table_set_row_spacing (GTK_TABLE (priv->range_table),
4181                                          2,
4182                                          gtk_table_get_default_row_spacing (GTK_TABLE (priv->range_table)));
4183               gtk_widget_show (priv->selection_radio);
4184             }
4185           else
4186             {
4187               gtk_widget_set_sensitive (priv->selection_radio, FALSE);
4188               gtk_table_set_row_spacing (GTK_TABLE (priv->range_table), 2, 0);
4189               gtk_widget_hide (priv->selection_radio);
4190             }
4191         }
4192
4193       g_object_notify (G_OBJECT (dialog), "support-selection");
4194     }
4195 }
4196
4197 /**
4198  * gtk_print_unix_dialog_get_support_selection:
4199  * @dialog: a #GtkPrintUnixDialog
4200  *
4201  * Gets the value of #GtkPrintUnixDialog::support-selection property.
4202  *
4203  * Returns: whether the application supports print of selection
4204  *
4205  * Since: 2.18
4206  */
4207 gboolean
4208 gtk_print_unix_dialog_get_support_selection (GtkPrintUnixDialog *dialog)
4209 {
4210   g_return_val_if_fail (GTK_IS_PRINT_UNIX_DIALOG (dialog), FALSE);
4211
4212   return dialog->priv->support_selection;
4213 }
4214
4215 /**
4216  * gtk_print_unix_dialog_set_has_selection:
4217  * @dialog: a #GtkPrintUnixDialog
4218  * @has_selection: %TRUE indicates that a selection exists
4219  *
4220  * Sets whether a selection exists.
4221  *
4222  * Since: 2.18
4223  */
4224 void
4225 gtk_print_unix_dialog_set_has_selection (GtkPrintUnixDialog *dialog,
4226                                          gboolean            has_selection)
4227 {
4228   GtkPrintUnixDialogPrivate *priv;
4229
4230   g_return_if_fail (GTK_IS_PRINT_UNIX_DIALOG (dialog));
4231
4232   priv = dialog->priv;
4233
4234   has_selection = has_selection != FALSE;
4235   if (priv->has_selection != has_selection)
4236     {
4237       priv->has_selection = has_selection;
4238
4239       if (priv->selection_radio)
4240         {
4241           if (priv->support_selection)
4242             gtk_widget_set_sensitive (priv->selection_radio, has_selection);
4243           else
4244             gtk_widget_set_sensitive (priv->selection_radio, FALSE);
4245         }
4246
4247       g_object_notify (G_OBJECT (dialog), "has-selection");
4248     }
4249 }
4250
4251 /**
4252  * gtk_print_unix_dialog_get_has_selection:
4253  * @dialog: a #GtkPrintUnixDialog
4254  *
4255  * Gets the value of #GtkPrintUnixDialog::has-selection property.
4256  *
4257  * Returns: whether there is a selection
4258  *
4259  * Since: 2.18
4260  */
4261 gboolean
4262 gtk_print_unix_dialog_get_has_selection (GtkPrintUnixDialog *dialog)
4263 {
4264   g_return_val_if_fail (GTK_IS_PRINT_UNIX_DIALOG (dialog), FALSE);
4265
4266   return dialog->priv->has_selection;
4267 }
4268
4269 /**
4270  * gtk_print_unix_dialog_set_embed_page_setup
4271  * @dialog: a #GtkPrintUnixDialog
4272  * @embed: embed page setup selection
4273  *
4274  * Embed page size combo box and orientation combo box into page setup page.
4275  *
4276  * Since: 2.18
4277  */
4278 void
4279 gtk_print_unix_dialog_set_embed_page_setup (GtkPrintUnixDialog *dialog,
4280                                             gboolean            embed)
4281 {
4282   GtkPrintUnixDialogPrivate *priv;
4283
4284   g_return_if_fail (GTK_IS_PRINT_UNIX_DIALOG (dialog));
4285
4286   priv = dialog->priv;
4287
4288   embed = embed != FALSE;
4289   if (priv->embed_page_setup != embed)
4290     {
4291       priv->embed_page_setup = embed;
4292
4293       gtk_widget_set_sensitive (priv->paper_size_combo, priv->embed_page_setup);
4294       gtk_widget_set_sensitive (priv->orientation_combo, priv->embed_page_setup);
4295
4296       if (priv->embed_page_setup)
4297         {
4298           if (priv->paper_size_combo != NULL)
4299             g_signal_connect (priv->paper_size_combo, "changed", G_CALLBACK (paper_size_changed), dialog);
4300
4301           if (priv->orientation_combo)
4302             g_signal_connect (priv->orientation_combo, "changed", G_CALLBACK (orientation_changed), dialog);
4303         }
4304       else
4305         {
4306           if (priv->paper_size_combo != NULL)
4307             g_signal_handlers_disconnect_by_func (priv->paper_size_combo, G_CALLBACK (paper_size_changed), dialog);
4308
4309           if (priv->orientation_combo)
4310             g_signal_handlers_disconnect_by_func (priv->orientation_combo, G_CALLBACK (orientation_changed), dialog);
4311         }
4312
4313       priv->internal_page_setup_change = TRUE;
4314       update_paper_sizes (dialog);
4315       priv->internal_page_setup_change = FALSE;
4316     }
4317 }
4318
4319 /**
4320  * gtk_print_unix_dialog_get_embed_page_setup:
4321  * @dialog: a #GtkPrintUnixDialog
4322  *
4323  * Gets the value of #GtkPrintUnixDialog::embed-page-setup property.
4324  *
4325  * Returns: whether there is a selection
4326  *
4327  * Since: 2.18
4328  */
4329 gboolean
4330 gtk_print_unix_dialog_get_embed_page_setup (GtkPrintUnixDialog *dialog)
4331 {
4332   g_return_val_if_fail (GTK_IS_PRINT_UNIX_DIALOG (dialog), FALSE);
4333
4334   return dialog->priv->embed_page_setup;
4335 }
4336
4337 #define __GTK_PRINT_UNIX_DIALOG_C__
4338 #include "gtkaliasdef.c"