]> Pileus Git - ~andy/gtk/blob - gtk/gtkprintunixdialog.c
0ecebc8b922e556158052b3b203011194c6f95df
[~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   gboolean ltr = TRUE;
2541
2542   orientation = gtk_page_setup_get_orientation (priv->page_setup);
2543   landscape =
2544     (orientation == GTK_PAGE_ORIENTATION_LANDSCAPE) ||
2545     (orientation == GTK_PAGE_ORIENTATION_REVERSE_LANDSCAPE);
2546
2547   number_up_layout = dialog_get_number_up_layout (dialog);
2548
2549   cr = gdk_cairo_create (widget->window);
2550
2551   cairo_save (cr);
2552
2553   page_setup = gtk_print_unix_dialog_get_page_setup (dialog);  
2554
2555   if (page_setup != NULL)
2556     {
2557       if (!landscape)
2558         {
2559           paper_width = gtk_page_setup_get_paper_width (page_setup, GTK_UNIT_MM);
2560           paper_height = gtk_page_setup_get_paper_height (page_setup, GTK_UNIT_MM);
2561         }
2562       else
2563         {
2564           paper_width = gtk_page_setup_get_paper_height (page_setup, GTK_UNIT_MM);
2565           paper_height = gtk_page_setup_get_paper_width (page_setup, GTK_UNIT_MM);
2566         }
2567
2568       if (paper_width < paper_height)
2569         {
2570           h = EXAMPLE_PAGE_AREA_SIZE - 3;
2571           w = (paper_height != 0) ? h * paper_width / paper_height : 0;
2572         }
2573       else
2574         {
2575           w = EXAMPLE_PAGE_AREA_SIZE - 3;
2576           h = (paper_width != 0) ? w * paper_height / paper_width : 0;
2577         }
2578
2579       if (paper_width == 0)
2580         w = 0;
2581
2582       if (paper_height == 0)
2583         h = 0;
2584     }
2585   else
2586     {
2587       ratio = G_SQRT2;
2588       w = (EXAMPLE_PAGE_AREA_SIZE - 3) / ratio;
2589       h = EXAMPLE_PAGE_AREA_SIZE - 3;
2590     }
2591
2592   pages_per_sheet = dialog_get_pages_per_sheet (dialog);
2593   switch (pages_per_sheet)
2594     {
2595     default:
2596     case 1:
2597       pages_x = 1; pages_y = 1;
2598       break;
2599     case 2:
2600       landscape = !landscape;
2601       pages_x = 1; pages_y = 2;
2602       break;
2603     case 4:
2604       pages_x = 2; pages_y = 2;
2605       break;
2606     case 6:
2607       landscape = !landscape;
2608       pages_x = 2; pages_y = 3;
2609       break;
2610     case 9:
2611       pages_x = 3; pages_y = 3;
2612       break;
2613     case 16:
2614       pages_x = 4; pages_y = 4;
2615       break;
2616     }
2617
2618   if (landscape)
2619     {
2620       tmp = w;
2621       w = h;
2622       h = tmp;
2623
2624       tmp = pages_x;
2625       pages_x = pages_y;
2626       pages_y = tmp;
2627     }
2628
2629   pos_x = widget->allocation.x + (widget->allocation.width - w) / 2;
2630   pos_y = widget->allocation.y + (widget->allocation.height - h) / 2 - 10;
2631   color = &widget->style->text[GTK_STATE_NORMAL];
2632   cairo_translate (cr, pos_x, pos_y);
2633
2634   shadow_offset = 3;
2635
2636   color = &widget->style->text[GTK_STATE_NORMAL];
2637   cairo_set_source_rgba (cr, color->red / 65535., color->green / 65535., color->blue / 65535, 0.5);
2638   cairo_rectangle (cr, shadow_offset + 1, shadow_offset + 1, w, h);
2639   cairo_fill (cr);
2640
2641   gdk_cairo_set_source_color (cr, &widget->style->base[GTK_STATE_NORMAL]);
2642   cairo_rectangle (cr, 1, 1, w, h);
2643   cairo_fill (cr);
2644   cairo_set_line_width (cr, 1.0);
2645   cairo_rectangle (cr, 0.5, 0.5, w + 1, h + 1);
2646
2647   gdk_cairo_set_source_color (cr, &widget->style->text[GTK_STATE_NORMAL]);
2648   cairo_stroke (cr);
2649
2650   i = 1;
2651
2652   page_width = (double)w / pages_x;
2653   page_height = (double)h / pages_y;
2654
2655   layout  = pango_cairo_create_layout (cr);
2656
2657   font = pango_font_description_new ();
2658   pango_font_description_set_family (font, "sans");
2659
2660   if (page_height > 0)
2661     pango_font_description_set_absolute_size (font, page_height * 0.4 * PANGO_SCALE);
2662   else
2663     pango_font_description_set_absolute_size (font, 1);
2664
2665   pango_layout_set_font_description (layout, font);
2666   pango_font_description_free (font);
2667
2668   pango_layout_set_width (layout, page_width * PANGO_SCALE);
2669   pango_layout_set_alignment (layout, PANGO_ALIGN_CENTER);
2670
2671   switch (number_up_layout)
2672     {
2673       default:
2674       case GTK_NUMBER_UP_LAYOUT_LEFT_TO_RIGHT_TOP_TO_BOTTOM:
2675         start_x = 0;
2676         end_x = pages_x - 1;
2677         start_y = 0;
2678         end_y = pages_y - 1;
2679         dx = 1;
2680         dy = 1;
2681         horizontal = TRUE;
2682         break;
2683       case GTK_NUMBER_UP_LAYOUT_LEFT_TO_RIGHT_BOTTOM_TO_TOP:
2684         start_x = 0;
2685         end_x = pages_x - 1;
2686         start_y = pages_y - 1;
2687         end_y = 0;
2688         dx = 1;
2689         dy = - 1;
2690         horizontal = TRUE;
2691         break;
2692       case GTK_NUMBER_UP_LAYOUT_RIGHT_TO_LEFT_TOP_TO_BOTTOM:
2693         start_x = pages_x - 1;
2694         end_x = 0;
2695         start_y = 0;
2696         end_y = pages_y - 1;
2697         dx = - 1;
2698         dy = 1;
2699         horizontal = TRUE;
2700         break;
2701       case GTK_NUMBER_UP_LAYOUT_RIGHT_TO_LEFT_BOTTOM_TO_TOP:
2702         start_x = pages_x - 1;
2703         end_x = 0;
2704         start_y = pages_y - 1;
2705         end_y = 0;
2706         dx = - 1;
2707         dy = - 1;
2708         horizontal = TRUE;
2709         break;
2710       case GTK_NUMBER_UP_LAYOUT_TOP_TO_BOTTOM_LEFT_TO_RIGHT:
2711         start_x = 0;
2712         end_x = pages_x - 1;
2713         start_y = 0;
2714         end_y = pages_y - 1;
2715         dx = 1;
2716         dy = 1;
2717         horizontal = FALSE;
2718         break;
2719       case GTK_NUMBER_UP_LAYOUT_TOP_TO_BOTTOM_RIGHT_TO_LEFT:
2720         start_x = pages_x - 1;
2721         end_x = 0;
2722         start_y = 0;
2723         end_y = pages_y - 1;
2724         dx = - 1;
2725         dy = 1;
2726         horizontal = FALSE;
2727         break;
2728       case GTK_NUMBER_UP_LAYOUT_BOTTOM_TO_TOP_LEFT_TO_RIGHT:
2729         start_x = 0;
2730         end_x = pages_x - 1;
2731         start_y = pages_y - 1;
2732         end_y = 0;
2733         dx = 1;
2734         dy = - 1;
2735         horizontal = FALSE;
2736         break;
2737       case GTK_NUMBER_UP_LAYOUT_BOTTOM_TO_TOP_RIGHT_TO_LEFT:
2738         start_x = pages_x - 1;
2739         end_x = 0;
2740         start_y = pages_y - 1;
2741         end_y = 0;
2742         dx = - 1;
2743         dy = - 1;
2744         horizontal = FALSE;
2745         break;
2746     }
2747
2748   if (horizontal)
2749     for (y = start_y; y != end_y + dy; y += dy)
2750       {
2751         for (x = start_x; x != end_x + dx; x += dx)
2752           {
2753             text = g_strdup_printf ("%d", i++);
2754             pango_layout_set_text (layout, text, -1);
2755             g_free (text);
2756             pango_layout_get_size (layout, &layout_w, &layout_h);
2757             cairo_save (cr);
2758             cairo_translate (cr,
2759                              x * page_width,
2760                              y * page_height + (page_height - layout_h / 1024.0) / 2);
2761
2762             pango_cairo_show_layout (cr, layout);
2763             cairo_restore (cr);
2764           }
2765       }
2766   else
2767     for (x = start_x; x != end_x + dx; x += dx)
2768       {
2769         for (y = start_y; y != end_y + dy; y += dy)
2770           {
2771             text = g_strdup_printf ("%d", i++);
2772             pango_layout_set_text (layout, text, -1);
2773             g_free (text);
2774             pango_layout_get_size (layout, &layout_w, &layout_h);
2775             cairo_save (cr);
2776             cairo_translate (cr,
2777                              x * page_width,
2778                              y * page_height + (page_height - layout_h / 1024.0) / 2);
2779
2780             pango_cairo_show_layout (cr, layout);
2781             cairo_restore (cr);
2782           }
2783       }
2784
2785   g_object_unref (layout);
2786
2787   if (page_setup != NULL)
2788     {
2789       pos_x += 1;
2790       pos_y += 1;
2791
2792       if (pages_per_sheet == 2 || pages_per_sheet == 6)
2793         {
2794           paper_width = gtk_page_setup_get_paper_height (page_setup, _gtk_print_get_default_user_units ());
2795           paper_height = gtk_page_setup_get_paper_width (page_setup, _gtk_print_get_default_user_units ());
2796         }
2797       else
2798         {
2799           paper_width = gtk_page_setup_get_paper_width (page_setup, _gtk_print_get_default_user_units ());
2800           paper_height = gtk_page_setup_get_paper_height (page_setup, _gtk_print_get_default_user_units ());
2801         }
2802
2803       cairo_restore (cr);
2804       cairo_save (cr);
2805
2806       layout  = pango_cairo_create_layout (cr);
2807
2808       font = pango_font_description_new ();
2809       pango_font_description_set_family (font, "sans");
2810
2811       PangoContext *pango_c = NULL;
2812       PangoFontDescription *pango_f = NULL;
2813       gint font_size = 12 * PANGO_SCALE;
2814
2815       pango_c = gtk_widget_get_pango_context (widget);
2816       if (pango_c != NULL)
2817         {
2818           pango_f = pango_context_get_font_description (pango_c);
2819           if (pango_f != NULL)
2820             font_size = pango_font_description_get_size (pango_f);
2821         }
2822
2823       pango_font_description_set_size (font, font_size);
2824       pango_layout_set_font_description (layout, font);
2825       pango_font_description_free (font);
2826
2827       pango_layout_set_width (layout, -1);
2828       pango_layout_set_alignment (layout, PANGO_ALIGN_CENTER);
2829
2830       if (_gtk_print_get_default_user_units () == GTK_UNIT_MM)
2831         text = g_strdup_printf ("%.1f mm", paper_height);
2832       else
2833         text = g_strdup_printf ("%.2f inch", paper_height);
2834
2835       pango_layout_set_text (layout, text, -1);
2836       g_free (text);
2837       pango_layout_get_size (layout, &layout_w, &layout_h);
2838
2839       ltr = gtk_widget_get_direction (GTK_WIDGET (dialog)) == GTK_TEXT_DIR_LTR;
2840
2841       if (ltr)
2842         cairo_translate (cr, pos_x - layout_w / PANGO_SCALE - 2 * RULER_DISTANCE,
2843                              widget->allocation.y + (widget->allocation.height - layout_h / PANGO_SCALE) / 2);
2844       else
2845         cairo_translate (cr, pos_x + w + shadow_offset + 2 * RULER_DISTANCE,
2846                              widget->allocation.y + (widget->allocation.height - layout_h / PANGO_SCALE) / 2);
2847
2848       pango_cairo_show_layout (cr, layout);
2849
2850       cairo_restore (cr);
2851       cairo_save (cr);
2852
2853       if (_gtk_print_get_default_user_units () == GTK_UNIT_MM)
2854         text = g_strdup_printf ("%.1f mm", paper_width);
2855       else
2856         text = g_strdup_printf ("%.2f inch", paper_width);
2857
2858       pango_layout_set_text (layout, text, -1);
2859       g_free (text);
2860       pango_layout_get_size (layout, &layout_w, &layout_h);
2861
2862       cairo_translate (cr, widget->allocation.x + (widget->allocation.width - layout_w / PANGO_SCALE) / 2,
2863                            pos_y + h + shadow_offset + 2 * RULER_DISTANCE);
2864
2865       pango_cairo_show_layout (cr, layout);
2866
2867       g_object_unref (layout);
2868
2869       cairo_restore (cr);
2870
2871       cairo_set_line_width (cr, 1);
2872
2873       if (ltr)
2874         {
2875           cairo_move_to (cr, pos_x - RULER_DISTANCE, pos_y);
2876           cairo_line_to (cr, pos_x - RULER_DISTANCE, pos_y + h);
2877           cairo_stroke (cr);
2878
2879           cairo_move_to (cr, pos_x - RULER_DISTANCE - RULER_RADIUS, pos_y - 0.5);
2880           cairo_line_to (cr, pos_x - RULER_DISTANCE + RULER_RADIUS, pos_y - 0.5);
2881           cairo_stroke (cr);
2882
2883           cairo_move_to (cr, pos_x - RULER_DISTANCE - RULER_RADIUS, pos_y + h + 0.5);
2884           cairo_line_to (cr, pos_x - RULER_DISTANCE + RULER_RADIUS, pos_y + h + 0.5);
2885           cairo_stroke (cr);
2886         }
2887       else
2888         {
2889           cairo_move_to (cr, pos_x + w + shadow_offset + RULER_DISTANCE, pos_y);
2890           cairo_line_to (cr, pos_x + w + shadow_offset + RULER_DISTANCE, pos_y + h);
2891           cairo_stroke (cr);
2892
2893           cairo_move_to (cr, pos_x + w + shadow_offset + RULER_DISTANCE - RULER_RADIUS, pos_y - 0.5);
2894           cairo_line_to (cr, pos_x + w + shadow_offset + RULER_DISTANCE + RULER_RADIUS, pos_y - 0.5);
2895           cairo_stroke (cr);
2896
2897           cairo_move_to (cr, pos_x + w + shadow_offset + RULER_DISTANCE - RULER_RADIUS, pos_y + h + 0.5);
2898           cairo_line_to (cr, pos_x + w + shadow_offset + RULER_DISTANCE + RULER_RADIUS, pos_y + h + 0.5);
2899           cairo_stroke (cr);
2900         }
2901
2902       cairo_move_to (cr, pos_x, pos_y + h + shadow_offset + RULER_DISTANCE);
2903       cairo_line_to (cr, pos_x + w, pos_y + h + shadow_offset + RULER_DISTANCE);
2904       cairo_stroke (cr);
2905
2906       cairo_move_to (cr, pos_x - 0.5, pos_y + h + shadow_offset + RULER_DISTANCE - RULER_RADIUS);
2907       cairo_line_to (cr, pos_x - 0.5, pos_y + h + shadow_offset + RULER_DISTANCE + RULER_RADIUS);
2908       cairo_stroke (cr);
2909
2910       cairo_move_to (cr, pos_x + w + 0.5, pos_y + h + shadow_offset + RULER_DISTANCE - RULER_RADIUS);
2911       cairo_line_to (cr, pos_x + w + 0.5, pos_y + h + shadow_offset + RULER_DISTANCE + RULER_RADIUS);
2912       cairo_stroke (cr);
2913     }
2914
2915   cairo_destroy (cr);
2916
2917   return TRUE;
2918 }
2919
2920 static void
2921 redraw_page_layout_preview (GtkPrintUnixDialog *dialog)
2922 {
2923   GtkPrintUnixDialogPrivate *priv = dialog->priv;
2924
2925   if (priv->page_layout_preview)
2926     gtk_widget_queue_draw (priv->page_layout_preview);
2927 }
2928
2929 static void
2930 update_number_up_layout (GtkPrintUnixDialog *dialog)
2931 {
2932   GtkPrintUnixDialogPrivate *priv = dialog->priv;
2933   GtkPrintCapabilities       caps;
2934   GtkPrinterOptionSet       *set;
2935   GtkNumberUpLayout          layout;
2936   GtkPrinterOption          *option;
2937   GtkPrinterOption          *old_option;
2938   GtkPageOrientation         page_orientation;
2939
2940   set = priv->options;
2941
2942   caps = priv->manual_capabilities | priv->printer_capabilities;
2943
2944   if (caps & GTK_PRINT_CAPABILITY_NUMBER_UP_LAYOUT)
2945     {
2946       if (priv->number_up_layout_n_option == NULL)
2947         {
2948           priv->number_up_layout_n_option = gtk_printer_option_set_lookup (set, "gtk-n-up-layout");
2949           if (priv->number_up_layout_n_option == NULL)
2950             {
2951               char *n_up_layout[] = { "lrtb", "lrbt", "rltb", "rlbt", "tblr", "tbrl", "btlr", "btrl" };
2952                /* Translators: These strings name the possible arrangements of
2953                 * multiple pages on a sheet when printing (same as in gtkprintbackendcups.c)
2954                 */
2955               char *n_up_layout_display[] = { N_("Left to right, top to bottom"), N_("Left to right, bottom to top"),
2956                                               N_("Right to left, top to bottom"), N_("Right to left, bottom to top"),
2957                                               N_("Top to bottom, left to right"), N_("Top to bottom, right to left"),
2958                                               N_("Bottom to top, left to right"), N_("Bottom to top, right to left") };
2959               int i;
2960
2961               priv->number_up_layout_n_option = gtk_printer_option_new ("gtk-n-up-layout",
2962                                                                         _("Page Ordering"),
2963                                                                         GTK_PRINTER_OPTION_TYPE_PICKONE);
2964               gtk_printer_option_allocate_choices (priv->number_up_layout_n_option, 8);
2965
2966               for (i = 0; i < G_N_ELEMENTS (n_up_layout_display); i++)
2967                 {
2968                   priv->number_up_layout_n_option->choices[i] = g_strdup (n_up_layout[i]);
2969                   priv->number_up_layout_n_option->choices_display[i] = g_strdup (_(n_up_layout_display[i]));
2970                 }
2971             }
2972           g_object_ref (priv->number_up_layout_n_option);
2973
2974           priv->number_up_layout_2_option = gtk_printer_option_new ("gtk-n-up-layout",
2975                                                                     _("Page Ordering"),
2976                                                                     GTK_PRINTER_OPTION_TYPE_PICKONE);
2977           gtk_printer_option_allocate_choices (priv->number_up_layout_2_option, 2);
2978         }
2979
2980       page_orientation = gtk_page_setup_get_orientation (priv->page_setup);
2981       if (page_orientation == GTK_PAGE_ORIENTATION_PORTRAIT ||
2982           page_orientation == GTK_PAGE_ORIENTATION_REVERSE_PORTRAIT)
2983         {
2984           if (! (priv->number_up_layout_2_option->choices[0] == priv->number_up_layout_n_option->choices[0] &&
2985                  priv->number_up_layout_2_option->choices[1] == priv->number_up_layout_n_option->choices[2]))
2986             {
2987               g_free (priv->number_up_layout_2_option->choices_display[0]);
2988               g_free (priv->number_up_layout_2_option->choices_display[1]);
2989               priv->number_up_layout_2_option->choices[0] = priv->number_up_layout_n_option->choices[0];
2990               priv->number_up_layout_2_option->choices[1] = priv->number_up_layout_n_option->choices[2];
2991               priv->number_up_layout_2_option->choices_display[0] = g_strdup ( _("Left to right"));
2992               priv->number_up_layout_2_option->choices_display[1] = g_strdup ( _("Right to left"));
2993             }
2994         }
2995       else
2996         {
2997           if (! (priv->number_up_layout_2_option->choices[0] == priv->number_up_layout_n_option->choices[0] &&
2998                  priv->number_up_layout_2_option->choices[1] == priv->number_up_layout_n_option->choices[1]))
2999             {
3000               g_free (priv->number_up_layout_2_option->choices_display[0]);
3001               g_free (priv->number_up_layout_2_option->choices_display[1]);
3002               priv->number_up_layout_2_option->choices[0] = priv->number_up_layout_n_option->choices[0];
3003               priv->number_up_layout_2_option->choices[1] = priv->number_up_layout_n_option->choices[1];
3004               priv->number_up_layout_2_option->choices_display[0] = g_strdup ( _("Top to bottom"));
3005               priv->number_up_layout_2_option->choices_display[1] = g_strdup ( _("Bottom to top"));
3006             }
3007         }
3008
3009       layout = dialog_get_number_up_layout (dialog);
3010
3011       old_option = gtk_printer_option_set_lookup (set, "gtk-n-up-layout");
3012       if (old_option != NULL)
3013         gtk_printer_option_set_remove (set, old_option);
3014
3015       if (dialog_get_pages_per_sheet (dialog) != 1)
3016         {
3017           GEnumClass *enum_class;
3018           GEnumValue *enum_value;
3019           enum_class = g_type_class_ref (GTK_TYPE_NUMBER_UP_LAYOUT);
3020
3021           if (dialog_get_pages_per_sheet (dialog) == 2)
3022             {
3023               option = priv->number_up_layout_2_option;
3024
3025               if (layout == GTK_NUMBER_UP_LAYOUT_LEFT_TO_RIGHT_TOP_TO_BOTTOM ||
3026                   layout == GTK_NUMBER_UP_LAYOUT_TOP_TO_BOTTOM_LEFT_TO_RIGHT)
3027                 enum_value = g_enum_get_value (enum_class, GTK_NUMBER_UP_LAYOUT_LEFT_TO_RIGHT_TOP_TO_BOTTOM);
3028
3029               if (layout == GTK_NUMBER_UP_LAYOUT_LEFT_TO_RIGHT_BOTTOM_TO_TOP ||
3030                   layout == GTK_NUMBER_UP_LAYOUT_BOTTOM_TO_TOP_LEFT_TO_RIGHT)
3031                 enum_value = g_enum_get_value (enum_class, GTK_NUMBER_UP_LAYOUT_LEFT_TO_RIGHT_BOTTOM_TO_TOP);
3032
3033               if (layout == GTK_NUMBER_UP_LAYOUT_RIGHT_TO_LEFT_TOP_TO_BOTTOM ||
3034                   layout == GTK_NUMBER_UP_LAYOUT_TOP_TO_BOTTOM_RIGHT_TO_LEFT)
3035                 enum_value = g_enum_get_value (enum_class, GTK_NUMBER_UP_LAYOUT_RIGHT_TO_LEFT_TOP_TO_BOTTOM);
3036
3037               if (layout == GTK_NUMBER_UP_LAYOUT_RIGHT_TO_LEFT_BOTTOM_TO_TOP ||
3038                   layout == GTK_NUMBER_UP_LAYOUT_BOTTOM_TO_TOP_RIGHT_TO_LEFT)
3039                 enum_value = g_enum_get_value (enum_class, GTK_NUMBER_UP_LAYOUT_RIGHT_TO_LEFT_BOTTOM_TO_TOP);
3040             }
3041           else
3042             {
3043               option = priv->number_up_layout_n_option;
3044
3045               enum_value = g_enum_get_value (enum_class, layout);
3046             }
3047
3048           g_assert (enum_value != NULL);
3049           gtk_printer_option_set (option, enum_value->value_nick);
3050           g_type_class_unref (enum_class);
3051
3052           gtk_printer_option_set_add (set, option);
3053         }
3054     }
3055
3056   setup_option (dialog, "gtk-n-up-layout", priv->number_up_layout);
3057
3058   if (priv->number_up_layout != NULL)
3059     gtk_widget_set_sensitive (GTK_WIDGET (priv->number_up_layout),
3060                               (caps & GTK_PRINT_CAPABILITY_NUMBER_UP_LAYOUT) &&
3061                               (dialog_get_pages_per_sheet (dialog) > 1));
3062 }
3063
3064 static void
3065 custom_paper_dialog_response_cb (GtkDialog *custom_paper_dialog,
3066                                  gint       response_id,
3067                                  gpointer   user_data)
3068 {
3069   GtkPrintUnixDialog        *print_dialog = GTK_PRINT_UNIX_DIALOG (user_data);
3070   GtkPrintUnixDialogPrivate *priv = print_dialog->priv;
3071   GtkTreeModel              *model;
3072   GtkTreeIter                iter;
3073
3074   _gtk_print_load_custom_papers (priv->custom_paper_list);
3075
3076   priv->internal_page_setup_change = TRUE;
3077   update_paper_sizes (print_dialog);
3078   priv->internal_page_setup_change = FALSE;
3079
3080   if (priv->page_setup_set)
3081     {
3082       model = GTK_TREE_MODEL (priv->custom_paper_list);
3083       if (gtk_tree_model_get_iter_first (model, &iter))
3084         {
3085           do
3086             {
3087               GtkPageSetup *page_setup;
3088               gtk_tree_model_get (model, &iter, 0, &page_setup, -1);
3089
3090               if (page_setup &&
3091                   g_strcmp0 (gtk_paper_size_get_display_name (gtk_page_setup_get_paper_size (page_setup)),
3092                              gtk_paper_size_get_display_name (gtk_page_setup_get_paper_size (priv->page_setup))) == 0)
3093                 gtk_print_unix_dialog_set_page_setup (print_dialog, page_setup);
3094
3095               g_object_unref (page_setup);
3096             } while (gtk_tree_model_iter_next (model, &iter));
3097         }
3098     }
3099
3100   gtk_widget_destroy (GTK_WIDGET (custom_paper_dialog));
3101 }
3102
3103 static void
3104 orientation_changed (GtkComboBox        *combo_box,
3105                      GtkPrintUnixDialog *dialog)
3106 {
3107   GtkPrintUnixDialogPrivate *priv = dialog->priv;
3108   GtkPageOrientation         orientation;
3109   GtkPageSetup              *page_setup;
3110
3111   if (priv->internal_page_setup_change)
3112     return;
3113
3114   orientation = (GtkPageOrientation) gtk_combo_box_get_active (GTK_COMBO_BOX (priv->orientation_combo));
3115
3116   if (priv->page_setup)
3117     {
3118       page_setup = gtk_page_setup_copy (priv->page_setup);
3119       if (page_setup)
3120         gtk_page_setup_set_orientation (page_setup, orientation);
3121
3122       gtk_print_unix_dialog_set_page_setup (dialog, page_setup);
3123     }
3124
3125   redraw_page_layout_preview (dialog);
3126 }
3127
3128 static void
3129 paper_size_changed (GtkComboBox        *combo_box,
3130                     GtkPrintUnixDialog *dialog)
3131 {
3132   GtkPrintUnixDialogPrivate *priv = dialog->priv;
3133   GtkTreeIter iter;
3134   GtkPageSetup *page_setup, *last_page_setup;
3135   GtkPageOrientation orientation;
3136
3137   if (priv->internal_page_setup_change)
3138     return;
3139
3140   if (gtk_combo_box_get_active_iter (combo_box, &iter))
3141     {
3142       gtk_tree_model_get (gtk_combo_box_get_model (combo_box),
3143                           &iter, PAGE_SETUP_LIST_COL_PAGE_SETUP, &page_setup, -1);
3144
3145       if (page_setup == NULL)
3146         {
3147           GtkWidget *custom_paper_dialog;
3148
3149           /* Change from "manage" menu item to last value */
3150           if (priv->page_setup)
3151             last_page_setup = g_object_ref (priv->page_setup);
3152           else
3153             last_page_setup = gtk_page_setup_new (); /* "good" default */
3154
3155           if (!set_paper_size (dialog, last_page_setup, FALSE, FALSE))
3156             set_paper_size (dialog, last_page_setup, TRUE, TRUE);
3157           g_object_unref (last_page_setup);
3158
3159           /* And show the custom paper dialog */
3160           custom_paper_dialog = _gtk_custom_paper_unix_dialog_new (GTK_WINDOW (dialog), _("Manage Custom Sizes"));
3161           g_signal_connect (custom_paper_dialog, "response", G_CALLBACK (custom_paper_dialog_response_cb), dialog);
3162           gtk_window_present (GTK_WINDOW (custom_paper_dialog));
3163
3164           return;
3165         }
3166
3167       if (priv->page_setup)
3168         orientation = gtk_page_setup_get_orientation (priv->page_setup);
3169       else
3170         orientation = GTK_PAGE_ORIENTATION_PORTRAIT;
3171
3172       gtk_page_setup_set_orientation (page_setup, orientation);
3173       gtk_print_unix_dialog_set_page_setup (dialog, page_setup);
3174
3175       g_object_unref (page_setup);
3176     }
3177
3178   redraw_page_layout_preview (dialog);
3179 }
3180
3181 static gboolean
3182 paper_size_row_is_separator (GtkTreeModel *model,
3183                              GtkTreeIter  *iter,
3184                              gpointer      data)
3185 {
3186   gboolean separator;
3187
3188   gtk_tree_model_get (model, iter, PAGE_SETUP_LIST_COL_IS_SEPARATOR, &separator, -1);
3189   return separator;
3190 }
3191
3192 static void
3193 page_name_func (GtkCellLayout   *cell_layout,
3194                 GtkCellRenderer *cell,
3195                 GtkTreeModel    *tree_model,
3196                 GtkTreeIter     *iter,
3197                 gpointer         data)
3198 {
3199   GtkPageSetup *page_setup;
3200   GtkPaperSize *paper_size;
3201
3202   gtk_tree_model_get (tree_model, iter,
3203                       PAGE_SETUP_LIST_COL_PAGE_SETUP, &page_setup, -1);
3204   if (page_setup)
3205     {
3206       paper_size = gtk_page_setup_get_paper_size (page_setup);
3207       g_object_set (cell, "text",  gtk_paper_size_get_display_name (paper_size), NULL);
3208       g_object_unref (page_setup);
3209     }
3210   else
3211     g_object_set (cell, "text",  _("Manage Custom Sizes..."), NULL);
3212 }
3213
3214 static void
3215 create_page_setup_page (GtkPrintUnixDialog *dialog)
3216 {
3217   GtkPrintUnixDialogPrivate *priv = dialog->priv;
3218   GtkWidget *main_vbox, *label, *hbox, *hbox2;
3219   GtkWidget *frame, *table, *widget;
3220   GtkWidget *combo, *spinbutton, *draw;
3221   GtkCellRenderer *cell;
3222
3223   main_vbox = gtk_vbox_new (FALSE, 18);
3224   gtk_container_set_border_width (GTK_CONTAINER (main_vbox), 12);
3225   gtk_widget_show (main_vbox);
3226
3227   hbox = gtk_hbox_new (FALSE, 18);
3228   gtk_widget_show (hbox);
3229   gtk_box_pack_start (GTK_BOX (main_vbox), hbox, FALSE, FALSE, 0);
3230
3231   table = gtk_table_new (5, 2, FALSE);
3232   gtk_table_set_row_spacings (GTK_TABLE (table), 6);
3233   gtk_table_set_col_spacings (GTK_TABLE (table), 12);
3234   frame = wrap_in_frame (_("Layout"), table);
3235   gtk_box_pack_start (GTK_BOX (hbox), frame, TRUE, TRUE, 0);
3236   gtk_widget_show (table);
3237
3238   label = gtk_label_new_with_mnemonic (_("T_wo-sided:"));
3239   gtk_misc_set_alignment (GTK_MISC (label), 0.0, 0.5);
3240   gtk_widget_show (label);
3241   gtk_table_attach (GTK_TABLE (table), label,
3242                     0, 1, 0, 1,  GTK_FILL, 0,
3243                     0, 0);
3244
3245   widget = gtk_printer_option_widget_new (NULL);
3246   priv->duplex = GTK_PRINTER_OPTION_WIDGET (widget);
3247   gtk_widget_show (widget);
3248   gtk_table_attach (GTK_TABLE (table), widget,
3249                     1, 2, 0, 1,  GTK_FILL, 0,
3250                     0, 0);
3251   gtk_label_set_mnemonic_widget (GTK_LABEL (label), widget);
3252
3253   label = gtk_label_new_with_mnemonic (_("Pages per _side:"));
3254   gtk_misc_set_alignment (GTK_MISC (label), 0.0, 0.5);
3255   gtk_widget_show (label);
3256   gtk_table_attach (GTK_TABLE (table), label,
3257                     0, 1, 1, 2,  GTK_FILL, 0,
3258                     0, 0);
3259
3260   widget = gtk_printer_option_widget_new (NULL);
3261   g_signal_connect_swapped (widget, "changed", G_CALLBACK (redraw_page_layout_preview), dialog);
3262   g_signal_connect_swapped (widget, "changed", G_CALLBACK (update_number_up_layout), dialog);
3263   priv->pages_per_sheet = GTK_PRINTER_OPTION_WIDGET (widget);
3264   gtk_widget_show (widget);
3265   gtk_table_attach (GTK_TABLE (table), widget,
3266                     1, 2, 1, 2,  GTK_FILL, 0,
3267                     0, 0);
3268   gtk_label_set_mnemonic_widget (GTK_LABEL (label), widget);
3269
3270   label = gtk_label_new_with_mnemonic (_("Page or_dering:"));
3271   gtk_misc_set_alignment (GTK_MISC (label), 0.0, 0.5);
3272   gtk_widget_show (label);
3273   gtk_table_attach (GTK_TABLE (table), label,
3274                     0, 1, 2, 3,  GTK_FILL, 0,
3275                     0, 0);
3276
3277   widget = gtk_printer_option_widget_new (NULL);
3278   g_signal_connect_swapped (widget, "changed", G_CALLBACK (redraw_page_layout_preview), dialog);
3279   priv->number_up_layout = GTK_PRINTER_OPTION_WIDGET (widget);
3280   gtk_widget_show (widget);
3281   gtk_table_attach (GTK_TABLE (table), widget,
3282                     1, 2, 2, 3,  GTK_FILL, 0,
3283                     0, 0);
3284   gtk_label_set_mnemonic_widget (GTK_LABEL (label), widget);
3285
3286   label = gtk_label_new_with_mnemonic (_("_Only print:"));
3287   gtk_misc_set_alignment (GTK_MISC (label), 0.0, 0.5);
3288   gtk_widget_show (label);
3289   gtk_table_attach (GTK_TABLE (table), label,
3290                     0, 1, 3, 4,  GTK_FILL, 0,
3291                     0, 0);
3292
3293   combo = gtk_combo_box_new_text ();
3294   priv->page_set_combo = combo;
3295   gtk_widget_show (combo);
3296   gtk_table_attach (GTK_TABLE (table), combo,
3297                     1, 2, 3, 4,  GTK_FILL, 0,
3298                     0, 0);
3299   gtk_label_set_mnemonic_widget (GTK_LABEL (label), combo);
3300   /* In enum order */
3301   gtk_combo_box_append_text (GTK_COMBO_BOX (combo), _("All sheets"));
3302   gtk_combo_box_append_text (GTK_COMBO_BOX (combo), _("Even sheets"));
3303   gtk_combo_box_append_text (GTK_COMBO_BOX (combo), _("Odd sheets"));
3304   gtk_combo_box_set_active (GTK_COMBO_BOX (combo), 0);
3305
3306   label = gtk_label_new_with_mnemonic (_("Sc_ale:"));
3307   gtk_misc_set_alignment (GTK_MISC (label), 0.0, 0.5);
3308   gtk_widget_show (label);
3309   gtk_table_attach (GTK_TABLE (table), label,
3310                     0, 1, 4, 5,  GTK_FILL, 0,
3311                     0, 0);
3312
3313   hbox2 = gtk_hbox_new (FALSE, 6);
3314   gtk_widget_show (hbox2);
3315   gtk_table_attach (GTK_TABLE (table), hbox2,
3316                     1, 2, 4, 5,  GTK_FILL, 0,
3317                     0, 0);
3318
3319   spinbutton = gtk_spin_button_new_with_range (1.0, 1000.0, 1.0);
3320   priv->scale_spin = spinbutton;
3321   gtk_spin_button_set_digits (GTK_SPIN_BUTTON (spinbutton), 1);
3322   gtk_spin_button_set_value (GTK_SPIN_BUTTON (spinbutton), 100.0);
3323   gtk_box_pack_start (GTK_BOX (hbox2), spinbutton, FALSE, FALSE, 0);
3324   gtk_label_set_mnemonic_widget (GTK_LABEL (label), spinbutton);
3325   gtk_widget_show (spinbutton);
3326   label = gtk_label_new ("%"); /* FIXMEchpe does there exist any language where % needs to be translated? */
3327   gtk_widget_show (label);
3328   gtk_box_pack_start (GTK_BOX (hbox2), label, FALSE, FALSE, 0);
3329
3330   table = gtk_table_new (4, 2, FALSE);
3331   gtk_table_set_row_spacings (GTK_TABLE (table), 6);
3332   gtk_table_set_col_spacings (GTK_TABLE (table), 12);
3333   frame = wrap_in_frame (_("Paper"), table);
3334   gtk_box_pack_start (GTK_BOX (hbox), frame, TRUE, TRUE, 6);
3335   gtk_widget_show (table);
3336
3337   label = gtk_label_new_with_mnemonic (_("Paper _type:"));
3338   gtk_misc_set_alignment (GTK_MISC (label), 0.0, 0.5);
3339   gtk_widget_show (label);
3340   gtk_table_attach (GTK_TABLE (table), label,
3341                     0, 1, 0, 1,  GTK_FILL, 0,
3342                     0, 0);
3343
3344   widget = gtk_printer_option_widget_new (NULL);
3345   priv->paper_type = GTK_PRINTER_OPTION_WIDGET (widget);
3346   gtk_widget_show (widget);
3347   gtk_table_attach (GTK_TABLE (table), widget,
3348                     1, 2, 0, 1,  GTK_FILL, 0,
3349                     0, 0);
3350   gtk_label_set_mnemonic_widget (GTK_LABEL (label), widget);
3351
3352   label = gtk_label_new_with_mnemonic (_("Paper _source:"));
3353   gtk_misc_set_alignment (GTK_MISC (label), 0.0, 0.5);
3354   gtk_widget_show (label);
3355   gtk_table_attach (GTK_TABLE (table), label,
3356                     0, 1, 1, 2,  GTK_FILL, 0,
3357                     0, 0);
3358
3359   widget = gtk_printer_option_widget_new (NULL);
3360   priv->paper_source = GTK_PRINTER_OPTION_WIDGET (widget);
3361   gtk_widget_show (widget);
3362   gtk_table_attach (GTK_TABLE (table), widget,
3363                     1, 2, 1, 2,  GTK_FILL, 0,
3364                     0, 0);
3365   gtk_label_set_mnemonic_widget (GTK_LABEL (label), widget);
3366
3367   label = gtk_label_new_with_mnemonic (_("Output t_ray:"));
3368   gtk_misc_set_alignment (GTK_MISC (label), 0.0, 0.5);
3369   gtk_widget_show (label);
3370   gtk_table_attach (GTK_TABLE (table), label,
3371                     0, 1, 2, 3,  GTK_FILL, 0,
3372                     0, 0);
3373
3374   widget = gtk_printer_option_widget_new (NULL);
3375   priv->output_tray = GTK_PRINTER_OPTION_WIDGET (widget);
3376   gtk_widget_show (widget);
3377   gtk_table_attach (GTK_TABLE (table), widget,
3378                     1, 2, 2, 3,  GTK_FILL, 0,
3379                     0, 0);
3380   gtk_label_set_mnemonic_widget (GTK_LABEL (label), widget);
3381
3382
3383   label = gtk_label_new_with_mnemonic (_("_Paper size:"));
3384   priv->paper_size_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, 3, 4,  GTK_FILL, 0,
3389                     0, 0);
3390
3391   combo = gtk_combo_box_new_with_model (GTK_TREE_MODEL (priv->page_setup_list));
3392   priv->paper_size_combo = GTK_WIDGET (combo);
3393   gtk_combo_box_set_row_separator_func (GTK_COMBO_BOX (combo), 
3394                                         paper_size_row_is_separator, NULL, NULL);
3395   cell = gtk_cell_renderer_text_new ();
3396   gtk_cell_layout_pack_start (GTK_CELL_LAYOUT (combo), cell, TRUE);
3397   gtk_cell_layout_set_cell_data_func (GTK_CELL_LAYOUT (combo), cell,
3398                                       page_name_func, NULL, NULL);
3399   gtk_table_attach (GTK_TABLE (table), combo,
3400                     1, 2, 3, 4,  GTK_FILL, 0,
3401                     0, 0);
3402   gtk_label_set_mnemonic_widget (GTK_LABEL (label), combo);
3403   gtk_widget_set_sensitive (combo, FALSE);
3404   gtk_widget_show (combo);
3405
3406
3407   label = gtk_label_new_with_mnemonic (_("Or_ientation:"));
3408   priv->orientation_combo_label = GTK_WIDGET (label);
3409   gtk_misc_set_alignment (GTK_MISC (label), 0.0, 0.5);
3410   gtk_widget_show (label);
3411   gtk_table_attach (GTK_TABLE (table), label,
3412                     0, 1, 4, 5,
3413                     GTK_FILL, 0, 0, 0);
3414
3415   combo = gtk_combo_box_new_text ();
3416   priv->orientation_combo = GTK_WIDGET (combo);
3417   gtk_table_attach (GTK_TABLE (table), combo,
3418                     1, 2, 4, 5,  GTK_FILL, 0,
3419                     0, 0);
3420   gtk_label_set_mnemonic_widget (GTK_LABEL (label), combo);
3421   /* In enum order */
3422   gtk_combo_box_append_text (GTK_COMBO_BOX (combo), _("Portrait"));
3423   gtk_combo_box_append_text (GTK_COMBO_BOX (combo), _("Landscape"));
3424   gtk_combo_box_append_text (GTK_COMBO_BOX (combo), _("Reverse portrait"));
3425   gtk_combo_box_append_text (GTK_COMBO_BOX (combo), _("Reverse landscape"));
3426   gtk_combo_box_set_active (GTK_COMBO_BOX (combo), 0);
3427   gtk_widget_set_sensitive (combo, FALSE);
3428   gtk_widget_show (combo);
3429
3430
3431   /* Add the page layout preview */
3432   hbox2 = gtk_hbox_new (FALSE, 0);
3433   gtk_widget_show (hbox2);
3434   gtk_box_pack_start (GTK_BOX (main_vbox), hbox2, TRUE, TRUE, 0);
3435
3436   draw = gtk_drawing_area_new ();
3437   GTK_WIDGET_SET_FLAGS (draw, GTK_NO_WINDOW);
3438   priv->page_layout_preview = draw;
3439   gtk_widget_set_size_request (draw, 350, 200);
3440   g_signal_connect (draw, "expose-event", G_CALLBACK (draw_page_cb), dialog);
3441   gtk_widget_show (draw);
3442
3443   gtk_box_pack_start (GTK_BOX (hbox2), draw, TRUE, FALSE, 0);
3444
3445   label = gtk_label_new (_("Page Setup"));
3446   gtk_widget_show (label);
3447
3448   gtk_notebook_append_page (GTK_NOTEBOOK (priv->notebook),
3449                             main_vbox, label);
3450 }
3451
3452 static void
3453 create_job_page (GtkPrintUnixDialog *dialog)
3454 {
3455   GtkPrintUnixDialogPrivate *priv = dialog->priv;
3456   GtkWidget *main_table, *label;
3457   GtkWidget *frame, *table, *radio;
3458   GtkWidget *entry, *widget;
3459   const gchar *at_tooltip;
3460   const gchar *on_hold_tooltip;
3461
3462   main_table = gtk_table_new (2, 2, FALSE);
3463   gtk_container_set_border_width (GTK_CONTAINER (main_table), 12);
3464   gtk_table_set_row_spacings (GTK_TABLE (main_table), 18);
3465   gtk_table_set_col_spacings (GTK_TABLE (main_table), 18);
3466
3467   table = gtk_table_new (2, 2, FALSE);
3468   gtk_table_set_row_spacings (GTK_TABLE (table), 6);
3469   gtk_table_set_col_spacings (GTK_TABLE (table), 12);
3470   frame = wrap_in_frame (_("Job Details"), table);
3471   gtk_table_attach (GTK_TABLE (main_table), frame,
3472                     0, 1, 0, 1,  GTK_FILL, 0,
3473                     0, 0);
3474   gtk_widget_show (table);
3475
3476   label = gtk_label_new_with_mnemonic (_("Pri_ority:"));
3477   gtk_misc_set_alignment (GTK_MISC (label), 0.0, 0.5);
3478   gtk_widget_show (label);
3479   gtk_table_attach (GTK_TABLE (table), label,
3480                     0, 1, 0, 1,  GTK_FILL, 0,
3481                     0, 0);
3482
3483   widget = gtk_printer_option_widget_new (NULL);
3484   priv->job_prio = GTK_PRINTER_OPTION_WIDGET (widget);
3485   gtk_widget_show (widget);
3486   gtk_table_attach (GTK_TABLE (table), widget,
3487                     1, 2, 0, 1,  GTK_FILL, 0,
3488                     0, 0);
3489   gtk_label_set_mnemonic_widget (GTK_LABEL (label), widget);
3490
3491   label = gtk_label_new_with_mnemonic (_("_Billing info:"));
3492   gtk_misc_set_alignment (GTK_MISC (label), 0.0, 0.5);
3493   gtk_widget_show (label);
3494   gtk_table_attach (GTK_TABLE (table), label,
3495                     0, 1, 1, 2,  GTK_FILL, 0,
3496                     0, 0);
3497
3498   widget = gtk_printer_option_widget_new (NULL);
3499   priv->billing_info = GTK_PRINTER_OPTION_WIDGET (widget);
3500   gtk_widget_show (widget);
3501   gtk_table_attach (GTK_TABLE (table), widget,
3502                     1, 2, 1, 2,  GTK_FILL, 0,
3503                     0, 0);
3504   gtk_label_set_mnemonic_widget (GTK_LABEL (label), widget);
3505
3506   table = gtk_table_new (2, 2, FALSE);
3507   gtk_table_set_row_spacings (GTK_TABLE (table), 6);
3508   gtk_table_set_col_spacings (GTK_TABLE (table), 12);
3509   frame = wrap_in_frame (_("Print Document"), table);
3510   gtk_table_attach (GTK_TABLE (main_table), frame,
3511                     0, 1, 1, 2,  GTK_FILL, 0,
3512                     0, 0);
3513   gtk_widget_show (table);
3514
3515   /* Translators: this is one of the choices for the print at option
3516    * in the print dialog
3517    */
3518   radio = gtk_radio_button_new_with_mnemonic (NULL, _("_Now"));
3519   priv->print_now_radio = radio;
3520   gtk_widget_show (radio);
3521   gtk_table_attach (GTK_TABLE (table), radio,
3522                     0, 2, 0, 1,  GTK_FILL, 0,
3523                     0, 0);
3524   /* Translators: this is one of the choices for the print at option
3525    * in the print dialog. It also serves as the label for an entry that
3526    * allows the user to enter a time.
3527    */
3528   radio = gtk_radio_button_new_with_mnemonic (gtk_radio_button_get_group (GTK_RADIO_BUTTON (radio)),
3529                                               _("A_t:"));
3530
3531   /* Translators: Ability to parse the am/pm format depends on actual locale.
3532    * You can remove the am/pm values below for your locale if they are not
3533    * supported.
3534    */
3535   at_tooltip = _("Specify the time of print,\n e.g. 15:30, 2:35 pm, 14:15:20, 11:46:30 am, 4 pm");
3536   gtk_widget_set_tooltip_text (radio, at_tooltip);
3537   priv->print_at_radio = radio;
3538   gtk_widget_show (radio);
3539   gtk_table_attach (GTK_TABLE (table), radio,
3540                     0, 1, 1, 2,  GTK_FILL, 0,
3541                     0, 0);
3542
3543   entry = gtk_entry_new ();
3544   gtk_widget_set_tooltip_text (entry, at_tooltip);
3545   atk_object_set_name (gtk_widget_get_accessible (entry), _("Time of print"));
3546   atk_object_set_description (gtk_widget_get_accessible (entry), at_tooltip);
3547   priv->print_at_entry = entry;
3548   gtk_widget_show (entry);
3549   gtk_table_attach (GTK_TABLE (table), entry,
3550                     1, 2, 1, 2,  GTK_FILL, 0,
3551                     0, 0);
3552
3553   g_signal_connect (radio, "toggled", G_CALLBACK (update_entry_sensitivity), entry);
3554   update_entry_sensitivity (radio, entry);
3555
3556   /* Translators: this is one of the choices for the print at option
3557    * in the print dialog. It means that the print job will not be
3558    * printed until it explicitly gets 'released'.
3559    */
3560   radio = gtk_radio_button_new_with_mnemonic (gtk_radio_button_get_group (GTK_RADIO_BUTTON (radio)),
3561                                               _("On _hold"));
3562   on_hold_tooltip = _("Hold the job until it is explicitly released");
3563   gtk_widget_set_tooltip_text (radio, on_hold_tooltip);
3564   priv->print_hold_radio = radio;
3565   gtk_widget_show (radio);
3566   gtk_table_attach (GTK_TABLE (table), radio,
3567                     0, 2, 2, 3,  GTK_FILL, 0,
3568                     0, 0);
3569
3570   g_signal_connect_swapped (priv->print_now_radio, "toggled",
3571                             G_CALLBACK (update_print_at_option), dialog);
3572   g_signal_connect_swapped (priv->print_at_radio, "toggled",
3573                             G_CALLBACK (update_print_at_option), dialog);
3574   g_signal_connect_swapped (priv->print_at_entry, "changed",
3575                             G_CALLBACK (update_print_at_option), dialog);
3576   g_signal_connect_swapped (priv->print_hold_radio, "toggled",
3577                             G_CALLBACK (update_print_at_option), dialog);
3578
3579   table = gtk_table_new (2, 2, FALSE);
3580   gtk_table_set_row_spacings (GTK_TABLE (table), 6);
3581   gtk_table_set_col_spacings (GTK_TABLE (table), 12);
3582   frame = wrap_in_frame (_("Add Cover Page"), table);
3583   gtk_table_attach (GTK_TABLE (main_table), frame,
3584                     1, 2, 0, 1,  GTK_FILL, 0,
3585                     0, 0);
3586   gtk_widget_show (table);
3587
3588   /* Translators, this is the label used for the option in the print
3589    * dialog that controls the front cover page.
3590    */
3591   label = gtk_label_new_with_mnemonic (_("Be_fore:"));
3592   gtk_misc_set_alignment (GTK_MISC (label), 0.0, 0.5);
3593   gtk_widget_show (label);
3594   gtk_table_attach (GTK_TABLE (table), label,
3595                     0, 1, 0, 1,  GTK_FILL, 0,
3596                     0, 0);
3597
3598   widget = gtk_printer_option_widget_new (NULL);
3599   priv->cover_before = GTK_PRINTER_OPTION_WIDGET (widget);
3600   gtk_widget_show (widget);
3601   gtk_table_attach (GTK_TABLE (table), widget,
3602                     1, 2, 0, 1,  GTK_FILL, 0,
3603                     0, 0);
3604   gtk_label_set_mnemonic_widget (GTK_LABEL (label), widget);
3605
3606   /* Translators, this is the label used for the option in the print
3607    * dialog that controls the back cover page.
3608    */
3609   label = gtk_label_new_with_mnemonic (_("_After:"));
3610   gtk_misc_set_alignment (GTK_MISC (label), 0.0, 0.5);
3611   gtk_widget_show (label);
3612   gtk_table_attach (GTK_TABLE (table), label,
3613                     0, 1, 1, 2,  GTK_FILL, 0,
3614                     0, 0);
3615
3616   widget = gtk_printer_option_widget_new (NULL);
3617   priv->cover_after = GTK_PRINTER_OPTION_WIDGET (widget);
3618   gtk_widget_show (widget);
3619   gtk_table_attach (GTK_TABLE (table), widget,
3620                     1, 2, 1, 2,  GTK_FILL, 0,
3621                     0, 0);
3622   gtk_label_set_mnemonic_widget (GTK_LABEL (label), widget);
3623
3624   /* Translators: this is the tab label for the notebook tab containing
3625    * job-specific options in the print dialog
3626    */
3627   label = gtk_label_new (_("Job"));
3628   gtk_widget_show (label);
3629
3630   priv->job_page = main_table;
3631   gtk_notebook_append_page (GTK_NOTEBOOK (priv->notebook),
3632                             main_table, label);
3633 }
3634
3635 static void
3636 create_optional_page (GtkPrintUnixDialog  *dialog,
3637                       const gchar         *text,
3638                       GtkWidget          **table_out,
3639                       GtkWidget          **page_out)
3640 {
3641   GtkPrintUnixDialogPrivate *priv = dialog->priv;
3642   GtkWidget *table, *label, *scrolled;
3643
3644   scrolled = gtk_scrolled_window_new (NULL, NULL);
3645   gtk_scrolled_window_set_policy (GTK_SCROLLED_WINDOW (scrolled),
3646                                   GTK_POLICY_NEVER,
3647                                   GTK_POLICY_AUTOMATIC);
3648
3649   table = gtk_table_new (1, 2, FALSE);
3650   gtk_table_set_row_spacings (GTK_TABLE (table), 6);
3651   gtk_table_set_col_spacings (GTK_TABLE (table), 12);
3652   gtk_container_set_border_width (GTK_CONTAINER (table), 12);
3653   gtk_widget_show (table);
3654
3655   gtk_scrolled_window_add_with_viewport (GTK_SCROLLED_WINDOW (scrolled),
3656                                          table);
3657   gtk_viewport_set_shadow_type (GTK_VIEWPORT (GTK_BIN(scrolled)->child),
3658                                 GTK_SHADOW_NONE);
3659
3660   label = gtk_label_new (text);
3661   gtk_widget_show (label);
3662
3663   gtk_notebook_append_page (GTK_NOTEBOOK (priv->notebook),
3664                             scrolled, label);
3665
3666   *table_out = table;
3667   *page_out = scrolled;
3668 }
3669
3670 static void
3671 create_advanced_page (GtkPrintUnixDialog *dialog)
3672 {
3673   GtkPrintUnixDialogPrivate *priv = dialog->priv;
3674   GtkWidget *main_vbox, *label, *scrolled;
3675
3676   scrolled = gtk_scrolled_window_new (NULL, NULL);
3677   priv->advanced_page = scrolled;
3678   gtk_scrolled_window_set_policy (GTK_SCROLLED_WINDOW (scrolled),
3679                                   GTK_POLICY_NEVER,
3680                                   GTK_POLICY_AUTOMATIC);
3681
3682   main_vbox = gtk_vbox_new (FALSE, 18);
3683   gtk_container_set_border_width (GTK_CONTAINER (main_vbox), 12);
3684   gtk_widget_show (main_vbox);
3685
3686   gtk_scrolled_window_add_with_viewport (GTK_SCROLLED_WINDOW (scrolled),
3687                                          main_vbox);
3688   gtk_viewport_set_shadow_type (GTK_VIEWPORT (GTK_BIN(scrolled)->child),
3689                                 GTK_SHADOW_NONE);
3690
3691   priv->advanced_vbox = main_vbox;
3692
3693   label = gtk_label_new (_("Advanced"));
3694   gtk_widget_show (label);
3695
3696   gtk_notebook_append_page (GTK_NOTEBOOK (priv->notebook),
3697                             scrolled, label);
3698 }
3699
3700 static void
3701 populate_dialog (GtkPrintUnixDialog *print_dialog)
3702 {
3703   GtkPrintUnixDialogPrivate *priv = print_dialog->priv;
3704   GtkDialog *dialog = GTK_DIALOG (print_dialog);
3705   GtkWidget *vbox, *conflict_hbox, *image, *label;
3706
3707   gtk_dialog_set_has_separator (dialog, FALSE);
3708   gtk_container_set_border_width (GTK_CONTAINER (dialog), 5);
3709   gtk_box_set_spacing (GTK_BOX (dialog->vbox), 2); /* 2 * 5 + 2 = 12 */
3710   gtk_container_set_border_width (GTK_CONTAINER (dialog->action_area), 5);
3711   gtk_box_set_spacing (GTK_BOX (dialog->action_area), 6);
3712
3713   vbox = gtk_vbox_new (FALSE, 6);
3714   gtk_container_set_border_width (GTK_CONTAINER (vbox), 5);
3715   gtk_box_pack_start (GTK_BOX (dialog->vbox), vbox, TRUE, TRUE, 0);
3716   gtk_widget_show (vbox);
3717
3718   priv->notebook = gtk_notebook_new ();
3719   gtk_box_pack_start (GTK_BOX (vbox), priv->notebook, TRUE, TRUE, 0);
3720   gtk_widget_show (priv->notebook);
3721
3722   create_printer_list_model (print_dialog);
3723
3724   create_main_page (print_dialog);
3725   create_page_setup_page (print_dialog);
3726   create_job_page (print_dialog);
3727   create_optional_page (print_dialog, _("Image Quality"),
3728                         &priv->image_quality_table,
3729                         &priv->image_quality_page);
3730   create_optional_page (print_dialog, _("Color"),
3731                         &priv->color_table,
3732                         &priv->color_page);
3733   create_optional_page (print_dialog, _("Finishing"),
3734                         &priv->finishing_table,
3735                         &priv->finishing_page);
3736   create_advanced_page (print_dialog);
3737
3738   priv->conflicts_widget = conflict_hbox = gtk_hbox_new (FALSE, 12);
3739   gtk_box_pack_end (GTK_BOX (vbox), conflict_hbox, FALSE, FALSE, 0);
3740   image = gtk_image_new_from_stock (GTK_STOCK_DIALOG_WARNING, GTK_ICON_SIZE_MENU);
3741   gtk_widget_show (image);
3742   gtk_box_pack_start (GTK_BOX (conflict_hbox), image, FALSE, TRUE, 0);
3743   label = gtk_label_new (_("Some of the settings in the dialog conflict"));
3744   gtk_widget_show (label);
3745   gtk_box_pack_start (GTK_BOX (conflict_hbox), label, FALSE, TRUE, 0);
3746
3747   load_print_backends (print_dialog);
3748 }
3749
3750 /**
3751  * gtk_print_unix_dialog_new:
3752  * @title: Title of the dialog, or %NULL
3753  * @parent: Transient parent of the dialog, or %NULL
3754  *
3755  * Creates a new #GtkPrintUnixDialog.
3756  *
3757  * Return value: a new #GtkPrintUnixDialog
3758  *
3759  * Since: 2.10
3760  **/
3761 GtkWidget *
3762 gtk_print_unix_dialog_new (const gchar *title,
3763                            GtkWindow   *parent)
3764 {
3765   GtkWidget *result;
3766   const gchar *_title = _("Print");
3767
3768   if (title)
3769     _title = title;
3770
3771   result = g_object_new (GTK_TYPE_PRINT_UNIX_DIALOG,
3772                          "transient-for", parent,
3773                          "title", _title,
3774                          "has-separator", FALSE,
3775                          NULL);
3776
3777   return result;
3778 }
3779
3780 /**
3781  * gtk_print_unix_dialog_get_selected_printer:
3782  * @dialog: a #GtkPrintUnixDialog
3783  *
3784  * Gets the currently selected printer.
3785  *
3786  * Returns: the currently selected printer
3787  *
3788  * Since: 2.10
3789  */
3790 GtkPrinter *
3791 gtk_print_unix_dialog_get_selected_printer (GtkPrintUnixDialog *dialog)
3792 {
3793   g_return_val_if_fail (GTK_IS_PRINT_UNIX_DIALOG (dialog), NULL);
3794
3795   return dialog->priv->current_printer;
3796 }
3797
3798 /**
3799  * gtk_print_unix_dialog_set_page_setup:
3800  * @dialog: a #GtkPrintUnixDialog
3801  * @page_setup: a #GtkPageSetup
3802  *
3803  * Sets the page setup of the #GtkPrintUnixDialog.
3804  *
3805  * Since: 2.10
3806  */
3807 void
3808 gtk_print_unix_dialog_set_page_setup (GtkPrintUnixDialog *dialog,
3809                                       GtkPageSetup       *page_setup)
3810 {
3811   GtkPrintUnixDialogPrivate *priv;
3812
3813   g_return_if_fail (GTK_IS_PRINT_UNIX_DIALOG (dialog));
3814   g_return_if_fail (GTK_IS_PAGE_SETUP (page_setup));
3815
3816   priv = dialog->priv;
3817
3818   if (priv->page_setup != page_setup)
3819     {
3820       g_object_unref (priv->page_setup);
3821       priv->page_setup = g_object_ref (page_setup);
3822
3823       priv->page_setup_set = TRUE;
3824
3825       g_object_notify (G_OBJECT (dialog), "page-setup");
3826     }
3827 }
3828
3829 /**
3830  * gtk_print_unix_dialog_get_page_setup:
3831  * @dialog: a #GtkPrintUnixDialog
3832  *
3833  * Gets the page setup that is used by the #GtkPrintUnixDialog.
3834  *
3835  * Returns: the page setup of @dialog.
3836  *
3837  * Since: 2.10
3838  */
3839 GtkPageSetup *
3840 gtk_print_unix_dialog_get_page_setup (GtkPrintUnixDialog *dialog)
3841 {
3842   g_return_val_if_fail (GTK_IS_PRINT_UNIX_DIALOG (dialog), NULL);
3843
3844   return dialog->priv->page_setup;
3845 }
3846
3847 /**
3848  * gtk_print_unix_dialog_get_page_setup_set:
3849  * @dialog: a #GtkPrintUnixDialog
3850  *
3851  * Gets the page setup that is used by the #GtkPrintUnixDialog.
3852  *
3853  * Returns: whether a page setup was set by user.
3854  *
3855  * Since: 2.18
3856  */
3857 gboolean
3858 gtk_print_unix_dialog_get_page_setup_set (GtkPrintUnixDialog *dialog)
3859 {
3860   g_return_val_if_fail (GTK_IS_PRINT_UNIX_DIALOG (dialog), FALSE);
3861
3862   return dialog->priv->page_setup_set;
3863 }
3864
3865 /**
3866  * gtk_print_unix_dialog_set_current_page:
3867  * @dialog: a #GtkPrintUnixDialog
3868  * @current_page: the current page number.
3869  *
3870  * Sets the current page number. If @current_page is not -1, this enables
3871  * the current page choice for the range of pages to print.
3872  *
3873  * Since: 2.10
3874  */
3875 void
3876 gtk_print_unix_dialog_set_current_page (GtkPrintUnixDialog *dialog,
3877                                         gint                current_page)
3878 {
3879   GtkPrintUnixDialogPrivate *priv;
3880
3881   g_return_if_fail (GTK_IS_PRINT_UNIX_DIALOG (dialog));
3882
3883   priv = dialog->priv;
3884
3885   if (priv->current_page != current_page)
3886     {
3887       priv->current_page = current_page;
3888
3889       if (priv->current_page_radio)
3890         gtk_widget_set_sensitive (priv->current_page_radio, current_page != -1);
3891
3892       g_object_notify (G_OBJECT (dialog), "current-page");
3893     }
3894 }
3895
3896 /**
3897  * gtk_print_unix_dialog_get_current_page:
3898  * @dialog: a #GtkPrintUnixDialog
3899  *
3900  * Gets the current page of the #GtkPrintDialog.
3901  *
3902  * Returns: the current page of @dialog
3903  *
3904  * Since: 2.10
3905  */
3906 gint
3907 gtk_print_unix_dialog_get_current_page (GtkPrintUnixDialog *dialog)
3908 {
3909   g_return_val_if_fail (GTK_IS_PRINT_UNIX_DIALOG (dialog), -1);
3910
3911   return dialog->priv->current_page;
3912 }
3913
3914 static gboolean
3915 set_active_printer (GtkPrintUnixDialog *dialog,
3916                     const gchar        *printer_name)
3917 {
3918   GtkPrintUnixDialogPrivate *priv = dialog->priv;
3919   GtkTreeModel *model;
3920   GtkTreeIter iter, filter_iter;
3921   GtkTreeSelection *selection;
3922   GtkPrinter *printer;
3923
3924   model = GTK_TREE_MODEL (priv->printer_list);
3925
3926   if (gtk_tree_model_get_iter_first (model, &iter))
3927     {
3928       do
3929         {
3930           gtk_tree_model_get (GTK_TREE_MODEL (priv->printer_list), &iter,
3931                               PRINTER_LIST_COL_PRINTER_OBJ, &printer, -1);
3932           if (printer == NULL)
3933             continue;
3934
3935           if (strcmp (gtk_printer_get_name (printer), printer_name) == 0)
3936             {
3937               gtk_tree_model_filter_convert_child_iter_to_iter (priv->printer_list_filter,
3938                                                                 &filter_iter, &iter);
3939
3940               selection = gtk_tree_view_get_selection (GTK_TREE_VIEW (priv->printer_treeview));
3941               priv->internal_printer_change = TRUE;
3942               gtk_tree_selection_select_iter (selection, &filter_iter);
3943               priv->internal_printer_change = FALSE;
3944               g_free (priv->waiting_for_printer);
3945               priv->waiting_for_printer = NULL;
3946
3947               g_object_unref (printer);
3948               return TRUE;
3949             }
3950
3951           g_object_unref (printer);
3952
3953         } while (gtk_tree_model_iter_next (model, &iter));
3954     }
3955
3956   return FALSE;
3957 }
3958
3959 /**
3960  * gtk_print_unix_dialog_set_settings:
3961  * @dialog: a #GtkPrintUnixDialog
3962  * @settings: a #GtkPrintSettings, or %NULL
3963  *
3964  * Sets the #GtkPrintSettings for the #GtkPrintUnixDialog. Typically,
3965  * this is used to restore saved print settings from a previous print
3966  * operation before the print dialog is shown.
3967  *
3968  * Since: 2.10
3969  **/
3970 void
3971 gtk_print_unix_dialog_set_settings (GtkPrintUnixDialog *dialog,
3972                                     GtkPrintSettings   *settings)
3973 {
3974   GtkPrintUnixDialogPrivate *priv;
3975   const gchar *printer;
3976   GtkPageRange *ranges;
3977   gint num_ranges;
3978
3979   g_return_if_fail (GTK_IS_PRINT_UNIX_DIALOG (dialog));
3980   g_return_if_fail (settings == NULL || GTK_IS_PRINT_SETTINGS (settings));
3981
3982   priv = dialog->priv;
3983
3984   if (settings != NULL)
3985     {
3986       dialog_set_collate (dialog, gtk_print_settings_get_collate (settings));
3987       dialog_set_reverse (dialog, gtk_print_settings_get_reverse (settings));
3988       dialog_set_n_copies (dialog, gtk_print_settings_get_n_copies (settings));
3989       dialog_set_scale (dialog, gtk_print_settings_get_scale (settings));
3990       dialog_set_page_set (dialog, gtk_print_settings_get_page_set (settings));
3991       dialog_set_print_pages (dialog, gtk_print_settings_get_print_pages (settings));
3992       ranges = gtk_print_settings_get_page_ranges (settings, &num_ranges);
3993       if (ranges)
3994         {
3995           dialog_set_page_ranges (dialog, ranges, num_ranges);
3996           g_free (ranges);
3997         }
3998
3999       priv->format_for_printer =
4000         g_strdup (gtk_print_settings_get (settings, "format-for-printer"));
4001     }
4002
4003   if (priv->initial_settings)
4004     g_object_unref (priv->initial_settings);
4005
4006   priv->initial_settings = settings;
4007
4008   g_free (priv->waiting_for_printer);
4009   priv->waiting_for_printer = NULL;
4010
4011   if (settings)
4012     {
4013       g_object_ref (settings);
4014
4015       printer = gtk_print_settings_get_printer (settings);
4016
4017       if (printer && !set_active_printer (dialog, printer))
4018         priv->waiting_for_printer = g_strdup (printer);
4019     }
4020
4021   g_object_notify (G_OBJECT (dialog), "print-settings");
4022 }
4023
4024 /**
4025  * gtk_print_unix_dialog_get_settings:
4026  * @dialog: a #GtkPrintUnixDialog
4027  *
4028  * Gets a new #GtkPrintSettings object that represents the
4029  * current values in the print dialog. Note that this creates a
4030  * <emphasis>new object</emphasis>, and you need to unref it
4031  * if don't want to keep it.
4032  *
4033  * Returns: a new #GtkPrintSettings object with the values from @dialog
4034  *
4035  * Since: 2.10
4036  */
4037 GtkPrintSettings *
4038 gtk_print_unix_dialog_get_settings (GtkPrintUnixDialog *dialog)
4039 {
4040   GtkPrintUnixDialogPrivate *priv;
4041   GtkPrintSettings *settings;
4042   GtkPrintPages print_pages;
4043   GtkPageRange *ranges;
4044   gint n_ranges;
4045
4046   g_return_val_if_fail (GTK_IS_PRINT_UNIX_DIALOG (dialog), NULL);
4047
4048   priv = dialog->priv;
4049   settings = gtk_print_settings_new ();
4050
4051   if (priv->current_printer)
4052     gtk_print_settings_set_printer (settings,
4053                                     gtk_printer_get_name (priv->current_printer));
4054   else
4055     gtk_print_settings_set_printer (settings, "default");
4056
4057   gtk_print_settings_set (settings, "format-for-printer",
4058                           priv->format_for_printer);
4059
4060   gtk_print_settings_set_collate (settings,
4061                                   dialog_get_collate (dialog));
4062
4063   gtk_print_settings_set_reverse (settings,
4064                                   dialog_get_reverse (dialog));
4065
4066   gtk_print_settings_set_n_copies (settings,
4067                                    dialog_get_n_copies (dialog));
4068
4069   gtk_print_settings_set_scale (settings,
4070                                 dialog_get_scale (dialog));
4071
4072   gtk_print_settings_set_page_set (settings,
4073                                    dialog_get_page_set (dialog));
4074
4075   print_pages = dialog_get_print_pages (dialog);
4076   gtk_print_settings_set_print_pages (settings, print_pages);
4077
4078   ranges = dialog_get_page_ranges (dialog, &n_ranges);
4079   if (ranges)
4080     {
4081       gtk_print_settings_set_page_ranges  (settings, ranges, n_ranges);
4082       g_free (ranges);
4083     }
4084
4085   /* TODO: print when. How to handle? */
4086
4087   if (priv->current_printer)
4088     _gtk_printer_get_settings_from_options (priv->current_printer,
4089                                             priv->options,
4090                                             settings);
4091
4092   return settings;
4093 }
4094
4095 /**
4096  * gtk_print_unix_dialog_add_custom_tab:
4097  * @dialog: a #GtkPrintUnixDialog
4098  * @child: the widget to put in the custom tab
4099  * @tab_label: the widget to use as tab label
4100  *
4101  * Adds a custom tab to the print dialog.
4102  *
4103  * Since: 2.10
4104  */
4105 void
4106 gtk_print_unix_dialog_add_custom_tab (GtkPrintUnixDialog *dialog,
4107                                       GtkWidget          *child,
4108                                       GtkWidget          *tab_label)
4109 {
4110   gtk_notebook_insert_page (GTK_NOTEBOOK (dialog->priv->notebook),
4111                             child, tab_label, 2);
4112   gtk_widget_show (child);
4113   gtk_widget_show (tab_label);
4114 }
4115
4116 /**
4117  * gtk_print_unix_dialog_set_manual_capabilities:
4118  * @dialog: a #GtkPrintUnixDialog
4119  * @capabilities: the printing capabilities of your application
4120  *
4121  * This lets you specify the printing capabilities your application
4122  * supports. For instance, if you can handle scaling the output then
4123  * you pass #GTK_PRINT_CAPABILITY_SCALE. If you don't pass that, then
4124  * the dialog will only let you select the scale if the printing
4125  * system automatically handles scaling.
4126  *
4127  * Since: 2.10
4128  */
4129 void
4130 gtk_print_unix_dialog_set_manual_capabilities (GtkPrintUnixDialog   *dialog,
4131                                                GtkPrintCapabilities  capabilities)
4132 {
4133   GtkPrintUnixDialogPrivate *priv = dialog->priv;
4134
4135   if (priv->manual_capabilities != capabilities)
4136     {
4137       priv->manual_capabilities = capabilities;
4138       update_dialog_from_capabilities (dialog);
4139
4140       if (priv->current_printer)
4141         {
4142           GtkTreeSelection *selection;
4143
4144           selection = gtk_tree_view_get_selection (GTK_TREE_VIEW (priv->printer_treeview));
4145
4146           g_object_unref (priv->current_printer);
4147           priv->current_printer = NULL;
4148           priv->internal_printer_change = TRUE;
4149           selected_printer_changed (selection, dialog);
4150           priv->internal_printer_change = FALSE;
4151        }
4152
4153       g_object_notify (G_OBJECT (dialog), "manual-capabilities");
4154     }
4155 }
4156
4157 /**
4158  * gtk_print_unix_dialog_get_manual_capabilities:
4159  * @dialog: a #GtkPrintUnixDialog
4160  *
4161  * Gets the value of #GtkPrintUnixDialog::manual-capabilities property.
4162  *
4163  * Returns: the printing capabilities
4164  *
4165  * Since: 2.18
4166  */
4167 GtkPrintCapabilities
4168 gtk_print_unix_dialog_get_manual_capabilities (GtkPrintUnixDialog *dialog)
4169 {
4170   g_return_val_if_fail (GTK_IS_PRINT_UNIX_DIALOG (dialog), FALSE);
4171
4172   return dialog->priv->manual_capabilities;
4173 }
4174
4175 /**
4176  * gtk_print_unix_dialog_set_support_selection:
4177  * @dialog: a #GtkPrintUnixDialog
4178  * @support_selection: %TRUE to allow print selection
4179  *
4180  * Sets whether the print dialog allows user to print a selection.
4181  *
4182  * Since: 2.18
4183  */
4184 void
4185 gtk_print_unix_dialog_set_support_selection (GtkPrintUnixDialog *dialog,
4186                                              gboolean            support_selection)
4187 {
4188   GtkPrintUnixDialogPrivate *priv;
4189
4190   g_return_if_fail (GTK_IS_PRINT_UNIX_DIALOG (dialog));
4191
4192   priv = dialog->priv;
4193
4194   support_selection = support_selection != FALSE;
4195   if (priv->support_selection != support_selection)
4196     {
4197       priv->support_selection = support_selection;
4198
4199       if (priv->selection_radio)
4200         {
4201           if (support_selection)
4202             {
4203               gtk_widget_set_sensitive (priv->selection_radio, priv->has_selection);
4204               gtk_table_set_row_spacing (GTK_TABLE (priv->range_table),
4205                                          2,
4206                                          gtk_table_get_default_row_spacing (GTK_TABLE (priv->range_table)));
4207               gtk_widget_show (priv->selection_radio);
4208             }
4209           else
4210             {
4211               gtk_widget_set_sensitive (priv->selection_radio, FALSE);
4212               gtk_table_set_row_spacing (GTK_TABLE (priv->range_table), 2, 0);
4213               gtk_widget_hide (priv->selection_radio);
4214             }
4215         }
4216
4217       g_object_notify (G_OBJECT (dialog), "support-selection");
4218     }
4219 }
4220
4221 /**
4222  * gtk_print_unix_dialog_get_support_selection:
4223  * @dialog: a #GtkPrintUnixDialog
4224  *
4225  * Gets the value of #GtkPrintUnixDialog::support-selection property.
4226  *
4227  * Returns: whether the application supports print of selection
4228  *
4229  * Since: 2.18
4230  */
4231 gboolean
4232 gtk_print_unix_dialog_get_support_selection (GtkPrintUnixDialog *dialog)
4233 {
4234   g_return_val_if_fail (GTK_IS_PRINT_UNIX_DIALOG (dialog), FALSE);
4235
4236   return dialog->priv->support_selection;
4237 }
4238
4239 /**
4240  * gtk_print_unix_dialog_set_has_selection:
4241  * @dialog: a #GtkPrintUnixDialog
4242  * @has_selection: %TRUE indicates that a selection exists
4243  *
4244  * Sets whether a selection exists.
4245  *
4246  * Since: 2.18
4247  */
4248 void
4249 gtk_print_unix_dialog_set_has_selection (GtkPrintUnixDialog *dialog,
4250                                          gboolean            has_selection)
4251 {
4252   GtkPrintUnixDialogPrivate *priv;
4253
4254   g_return_if_fail (GTK_IS_PRINT_UNIX_DIALOG (dialog));
4255
4256   priv = dialog->priv;
4257
4258   has_selection = has_selection != FALSE;
4259   if (priv->has_selection != has_selection)
4260     {
4261       priv->has_selection = has_selection;
4262
4263       if (priv->selection_radio)
4264         {
4265           if (priv->support_selection)
4266             gtk_widget_set_sensitive (priv->selection_radio, has_selection);
4267           else
4268             gtk_widget_set_sensitive (priv->selection_radio, FALSE);
4269         }
4270
4271       g_object_notify (G_OBJECT (dialog), "has-selection");
4272     }
4273 }
4274
4275 /**
4276  * gtk_print_unix_dialog_get_has_selection:
4277  * @dialog: a #GtkPrintUnixDialog
4278  *
4279  * Gets the value of #GtkPrintUnixDialog::has-selection property.
4280  *
4281  * Returns: whether there is a selection
4282  *
4283  * Since: 2.18
4284  */
4285 gboolean
4286 gtk_print_unix_dialog_get_has_selection (GtkPrintUnixDialog *dialog)
4287 {
4288   g_return_val_if_fail (GTK_IS_PRINT_UNIX_DIALOG (dialog), FALSE);
4289
4290   return dialog->priv->has_selection;
4291 }
4292
4293 /**
4294  * gtk_print_unix_dialog_set_embed_page_setup
4295  * @dialog: a #GtkPrintUnixDialog
4296  * @embed: embed page setup selection
4297  *
4298  * Embed page size combo box and orientation combo box into page setup page.
4299  *
4300  * Since: 2.18
4301  */
4302 void
4303 gtk_print_unix_dialog_set_embed_page_setup (GtkPrintUnixDialog *dialog,
4304                                             gboolean            embed)
4305 {
4306   GtkPrintUnixDialogPrivate *priv;
4307
4308   g_return_if_fail (GTK_IS_PRINT_UNIX_DIALOG (dialog));
4309
4310   priv = dialog->priv;
4311
4312   embed = embed != FALSE;
4313   if (priv->embed_page_setup != embed)
4314     {
4315       priv->embed_page_setup = embed;
4316
4317       gtk_widget_set_sensitive (priv->paper_size_combo, priv->embed_page_setup);
4318       gtk_widget_set_sensitive (priv->orientation_combo, priv->embed_page_setup);
4319
4320       if (priv->embed_page_setup)
4321         {
4322           if (priv->paper_size_combo != NULL)
4323             g_signal_connect (priv->paper_size_combo, "changed", G_CALLBACK (paper_size_changed), dialog);
4324
4325           if (priv->orientation_combo)
4326             g_signal_connect (priv->orientation_combo, "changed", G_CALLBACK (orientation_changed), dialog);
4327         }
4328       else
4329         {
4330           if (priv->paper_size_combo != NULL)
4331             g_signal_handlers_disconnect_by_func (priv->paper_size_combo, G_CALLBACK (paper_size_changed), dialog);
4332
4333           if (priv->orientation_combo)
4334             g_signal_handlers_disconnect_by_func (priv->orientation_combo, G_CALLBACK (orientation_changed), dialog);
4335         }
4336
4337       priv->internal_page_setup_change = TRUE;
4338       update_paper_sizes (dialog);
4339       priv->internal_page_setup_change = FALSE;
4340     }
4341 }
4342
4343 /**
4344  * gtk_print_unix_dialog_get_embed_page_setup:
4345  * @dialog: a #GtkPrintUnixDialog
4346  *
4347  * Gets the value of #GtkPrintUnixDialog::embed-page-setup property.
4348  *
4349  * Returns: whether there is a selection
4350  *
4351  * Since: 2.18
4352  */
4353 gboolean
4354 gtk_print_unix_dialog_get_embed_page_setup (GtkPrintUnixDialog *dialog)
4355 {
4356   g_return_val_if_fail (GTK_IS_PRINT_UNIX_DIALOG (dialog), FALSE);
4357
4358   return dialog->priv->embed_page_setup;
4359 }
4360
4361 #define __GTK_PRINT_UNIX_DIALOG_C__
4362 #include "gtkaliasdef.c"