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