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