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, see <http://www.gnu.org/licenses/>.
18 */
19
20#include "config.h"
21
22#include <stdlib.h>
23#include <string.h>
24#include <ctype.h>
25#include <stdio.h>
26#include <math.h>
27
28#include "gtkprintunixdialog.h"
29
30#include "gtkcustompaperunixdialog.h"
31#include "gtkprintbackendprivate.h"
32#include "gtkprinterprivate.h"
33#include "gtkprinteroptionwidget.h"
34#include "gtkprintutils.h"
35
36#include "gtkspinbutton.h"
37#include "gtkimage.h"
38#include "gtknotebook.h"
39#include "gtkscrolledwindow.h"
40#include "gtktogglebutton.h"
41#include "gtkdrawingarea.h"
42#include "gtkbox.h"
43#include "gtkgrid.h"
44#include "gtkframe.h"
45#include "gtklabel.h"
46#include "gtkbuildable.h"
47#include "gtkmessagedialog.h"
48#include "gtkbutton.h"
49#include "gtkintl.h"
50#include "gtkprivate.h"
51#include "gtktypebuiltins.h"
52#include "gtkdialogprivate.h"
53#include "gtkstylecontextprivate.h"
54#include "gtkwidgetprivate.h"
55
56
57/**
58 * GtkPrintUnixDialog:
59 *
60 * `GtkPrintUnixDialog` implements a print dialog for platforms
61 * which don’t provide a native print dialog, like Unix.
62 *
63 * ![An example GtkPrintUnixDialog](printdialog.png)
64 *
65 * It can be used very much like any other GTK dialog, at the cost of
66 * the portability offered by the high-level printing API with
67 * [class@Gtk.PrintOperation].
68 *
69 * In order to print something with `GtkPrintUnixDialog`, you need to
70 * use [method@Gtk.PrintUnixDialog.get_selected_printer] to obtain a
71 * [class@Gtk.Printer] object and use it to construct a [class@Gtk.PrintJob]
72 * using [ctor@Gtk.PrintJob.new].
73 *
74 * `GtkPrintUnixDialog` uses the following response values:
75 *
76 * - %GTK_RESPONSE_OK: for the “Print” button
77 * - %GTK_RESPONSE_APPLY: for the “Preview” button
78 * - %GTK_RESPONSE_CANCEL: for the “Cancel” button
79 *
80 * # GtkPrintUnixDialog as GtkBuildable
81 *
82 * The `GtkPrintUnixDialog` implementation of the `GtkBuildable` interface
83 * exposes its @notebook internal children with the name “notebook”.
84 *
85 * An example of a `GtkPrintUnixDialog` UI definition fragment:
86 *
87 * ```xml
88 * <object class="GtkPrintUnixDialog" id="dialog1">
89 * <child internal-child="notebook">
90 * <object class="GtkNotebook" id="notebook">
91 * <child>
92 * <object type="GtkNotebookPage">
93 * <property name="tab_expand">False</property>
94 * <property name="tab_fill">False</property>
95 * <property name="tab">
96 * <object class="GtkLabel" id="tablabel">
97 * <property name="label">Tab label</property>
98 * </object>
99 * </property>
100 * <property name="child">
101 * <object class="GtkLabel" id="tabcontent">
102 * <property name="label">Content on notebook tab</property>
103 * </object>
104 * </property>
105 * </object>
106 * </child>
107 * </object>
108 * </child>
109 * </object>
110 * ```
111 *
112 * # CSS nodes
113 *
114 * `GtkPrintUnixDialog` has a single CSS node with name window. The style classes
115 * dialog and print are added.
116 */
117
118
119#define EXAMPLE_PAGE_AREA_SIZE 110
120#define RULER_DISTANCE 7.5
121#define RULER_RADIUS 2
122
123
124static void gtk_print_unix_dialog_constructed (GObject *object);
125static void gtk_print_unix_dialog_dispose (GObject *object);
126static void gtk_print_unix_dialog_finalize (GObject *object);
127static void gtk_print_unix_dialog_set_property (GObject *object,
128 guint prop_id,
129 const GValue *value,
130 GParamSpec *pspec);
131static void gtk_print_unix_dialog_get_property (GObject *object,
132 guint prop_id,
133 GValue *value,
134 GParamSpec *pspec);
135static void unschedule_idle_mark_conflicts (GtkPrintUnixDialog *dialog);
136static void selected_printer_changed (GtkPrintUnixDialog *dialog);
137static void clear_per_printer_ui (GtkPrintUnixDialog *dialog);
138static void printer_added_cb (GListModel *model,
139 guint position,
140 guint removed,
141 guint added,
142 GtkPrintUnixDialog *dialog);
143static void printer_status_cb (GtkPrintBackend *backend,
144 GtkPrinter *printer,
145 GtkPrintUnixDialog *dialog);
146static void update_collate_icon (GtkToggleButton *toggle_button,
147 GtkPrintUnixDialog *dialog);
148static void error_dialogs (GtkPrintUnixDialog *print_dialog,
149 int print_dialog_response_id,
150 gpointer data);
151static gboolean page_range_entry_focus_changed (GtkWidget *entry,
152 GParamSpec *pspec,
153 GtkPrintUnixDialog *dialog);
154static void update_page_range_entry_sensitivity(GtkWidget *button,
155 GtkPrintUnixDialog *dialog);
156static void update_print_at_entry_sensitivity (GtkWidget *button,
157 GtkPrintUnixDialog *dialog);
158static void update_print_at_option (GtkPrintUnixDialog *dialog);
159static void update_dialog_from_capabilities (GtkPrintUnixDialog *dialog);
160static void draw_collate (GtkDrawingArea *da,
161 cairo_t *cr,
162 int width,
163 int height,
164 gpointer data);
165static gboolean is_printer_active (gpointer item,
166 gpointer data);
167static int default_printer_list_sort_func (gconstpointer a,
168 gconstpointer b,
169 gpointer user_data);
170static void update_number_up_layout (GtkPrintUnixDialog *dialog);
171static void draw_page (GtkDrawingArea *da,
172 cairo_t *cr,
173 int width,
174 int height,
175 gpointer data);
176
177
178static gboolean dialog_get_collate (GtkPrintUnixDialog *dialog);
179static gboolean dialog_get_reverse (GtkPrintUnixDialog *dialog);
180static int dialog_get_n_copies (GtkPrintUnixDialog *dialog);
181
182static gboolean set_active_printer (GtkPrintUnixDialog *dialog,
183 const char *printer_name);
184static void redraw_page_layout_preview (GtkPrintUnixDialog *dialog);
185static GListModel *load_print_backends (GtkPrintUnixDialog *dialog);
186
187/* GtkBuildable */
188static void gtk_print_unix_dialog_buildable_init (GtkBuildableIface *iface);
189static GObject *gtk_print_unix_dialog_buildable_get_internal_child (GtkBuildable *buildable,
190 GtkBuilder *builder,
191 const char *childname);
192
193static const char common_paper_sizes[][16] = {
194 "na_letter",
195 "na_legal",
196 "iso_a4",
197 "iso_a5",
198 "roc_16k",
199 "iso_b5",
200 "jis_b5",
201 "na_number-10",
202 "iso_dl",
203 "jpn_chou3",
204 "na_ledger",
205 "iso_a3",
206};
207
208/* Keep in line with liststore defined in gtkprintunixdialog.ui */
209enum {
210 PAGE_SETUP_LIST_COL_PAGE_SETUP,
211 PAGE_SETUP_LIST_COL_IS_SEPARATOR,
212 PAGE_SETUP_LIST_N_COLS
213};
214
215/* Keep in line with liststore defined in gtkprintunixdialog.ui */
216enum {
217 PRINTER_LIST_COL_ICON,
218 PRINTER_LIST_COL_NAME,
219 PRINTER_LIST_COL_STATE,
220 PRINTER_LIST_COL_JOBS,
221 PRINTER_LIST_COL_LOCATION,
222 PRINTER_LIST_COL_PRINTER_OBJ,
223 PRINTER_LIST_N_COLS
224};
225
226enum {
227 PROP_0,
228 PROP_PAGE_SETUP,
229 PROP_CURRENT_PAGE,
230 PROP_PRINT_SETTINGS,
231 PROP_SELECTED_PRINTER,
232 PROP_MANUAL_CAPABILITIES,
233 PROP_SUPPORT_SELECTION,
234 PROP_HAS_SELECTION,
235 PROP_EMBED_PAGE_SETUP
236};
237
238typedef struct _GtkPrintUnixDialogClass GtkPrintUnixDialogClass;
239
240struct _GtkPrintUnixDialog
241{
242 GtkDialog parent_instance;
243
244 GtkWidget *notebook;
245
246 GtkWidget *printer_list;
247
248 GtkPrintCapabilities manual_capabilities;
249 GtkPrintCapabilities printer_capabilities;
250
251 GtkPageSetup *page_setup;
252 gboolean page_setup_set;
253 gboolean embed_page_setup;
254 GListStore *page_setup_list;
255 GListStore *custom_paper_list;
256 GListStore *manage_papers_list;
257
258 gboolean support_selection;
259 gboolean has_selection;
260
261 GtkWidget *all_pages_radio;
262 GtkWidget *current_page_radio;
263 GtkWidget *selection_radio;
264 GtkWidget *range_table;
265 GtkWidget *page_range_radio;
266 GtkWidget *page_range_entry;
267
268 GtkWidget *copies_spin;
269 GtkWidget *collate_check;
270 GtkWidget *reverse_check;
271 GtkWidget *collate_image;
272 GtkWidget *page_layout_preview;
273 GtkWidget *scale_spin;
274 GtkWidget *page_set_combo;
275 GtkWidget *print_now_radio;
276 GtkWidget *print_at_radio;
277 GtkWidget *print_at_entry;
278 GtkWidget *print_hold_radio;
279 GtkWidget *paper_size_combo;
280 GtkWidget *orientation_combo;
281 gboolean internal_page_setup_change;
282 gboolean updating_print_at;
283 GtkPrinterOptionWidget *pages_per_sheet;
284 GtkPrinterOptionWidget *duplex;
285 GtkPrinterOptionWidget *paper_type;
286 GtkPrinterOptionWidget *paper_source;
287 GtkPrinterOptionWidget *output_tray;
288 GtkPrinterOptionWidget *job_prio;
289 GtkPrinterOptionWidget *billing_info;
290 GtkPrinterOptionWidget *cover_before;
291 GtkPrinterOptionWidget *cover_after;
292 GtkPrinterOptionWidget *number_up_layout;
293
294 GtkWidget *conflicts_widget;
295
296 GtkWidget *job_page;
297 GtkWidget *finishing_table;
298 GtkWidget *finishing_page;
299 GtkWidget *image_quality_table;
300 GtkWidget *image_quality_page;
301 GtkWidget *color_table;
302 GtkWidget *color_page;
303
304 GtkWidget *advanced_vbox;
305 GtkWidget *advanced_page;
306
307 GtkWidget *extension_point;
308
309 /* These are set initially on selected printer (either default printer,
310 * printer taken from set settings, or user-selected), but when any
311 * setting is changed by the user it is cleared.
312 */
313 GtkPrintSettings *initial_settings;
314
315 GtkPrinterOption *number_up_layout_n_option;
316 GtkPrinterOption *number_up_layout_2_option;
317
318 /* This is the initial printer set by set_settings. We look for it in
319 * the added printers. We clear this whenever the user manually changes
320 * to another printer, when the user changes a setting or when we find
321 * this printer.
322 */
323 char *waiting_for_printer;
324 gboolean internal_printer_change;
325
326 GList *print_backends;
327
328 GtkPrinter *current_printer;
329 GtkPrinter *request_details_printer;
330 gulong request_details_tag;
331 GtkPrinterOptionSet *options;
332 gulong options_changed_handler;
333 gulong mark_conflicts_id;
334
335 char *format_for_printer;
336
337 int current_page;
338 GtkCssNode *collate_paper_node;
339 GtkCssNode *page_layout_paper_node;
340};
341
342struct _GtkPrintUnixDialogClass
343{
344 GtkDialogClass parent_class;
345};
346
347G_DEFINE_TYPE_WITH_CODE (GtkPrintUnixDialog, gtk_print_unix_dialog, GTK_TYPE_DIALOG,
348 G_IMPLEMENT_INTERFACE (GTK_TYPE_BUILDABLE,
349 gtk_print_unix_dialog_buildable_init))
350
351static GtkBuildableIface *parent_buildable_iface;
352
353static gboolean
354is_default_printer (GtkPrintUnixDialog *dialog,
355 GtkPrinter *printer)
356{
357 if (dialog->format_for_printer)
358 return strcmp (s1: dialog->format_for_printer,
359 s2: gtk_printer_get_name (printer)) == 0;
360 else
361 return gtk_printer_is_default (printer);
362}
363
364static void
365gtk_print_unix_dialog_class_init (GtkPrintUnixDialogClass *class)
366{
367 GObjectClass *object_class;
368 GtkWidgetClass *widget_class;
369
370 object_class = (GObjectClass *) class;
371 widget_class = (GtkWidgetClass *) class;
372
373 object_class->constructed = gtk_print_unix_dialog_constructed;
374 object_class->finalize = gtk_print_unix_dialog_finalize;
375 object_class->dispose = gtk_print_unix_dialog_dispose;
376 object_class->set_property = gtk_print_unix_dialog_set_property;
377 object_class->get_property = gtk_print_unix_dialog_get_property;
378
379 /**
380 * GtkPrintUnixDialog:page-setup: (attributes org.gtk.Property.get=gtk_print_unix_dialog_get_page_setup org.gtk.Property.set=gtk_print_unix_dialog_set_page_setup)
381 *
382 * The `GtkPageSetup` object to use.
383 */
384 g_object_class_install_property (oclass: object_class,
385 property_id: PROP_PAGE_SETUP,
386 pspec: g_param_spec_object (name: "page-setup",
387 P_("Page Setup"),
388 P_("The GtkPageSetup to use"),
389 GTK_TYPE_PAGE_SETUP,
390 GTK_PARAM_READWRITE));
391
392 /**
393 * GtkPrintUnixDialog:current-page: (attributes org.gtk.Property.get=gtk_print_unix_dialog_get_current_page org.gtk.Property.set=gtk_print_unix_dialog_set_current_page)
394 *
395 * The current page in the document.
396 */
397 g_object_class_install_property (oclass: object_class,
398 property_id: PROP_CURRENT_PAGE,
399 pspec: g_param_spec_int (name: "current-page",
400 P_("Current Page"),
401 P_("The current page in the document"),
402 minimum: -1,
403 G_MAXINT,
404 default_value: -1,
405 GTK_PARAM_READWRITE));
406
407 /**
408 * GtkPrintUnixDialog:print-settings: (attributes org.gtk.Property.get=gtk_print_unix_dialog_get_settings org.gtk.Property.set=gtk_print_unix_dialog_set_settings)
409 *
410 * The `GtkPrintSettings` object used for this dialog.
411 */
412 g_object_class_install_property (oclass: object_class,
413 property_id: PROP_PRINT_SETTINGS,
414 pspec: g_param_spec_object (name: "print-settings",
415 P_("Print Settings"),
416 P_("The GtkPrintSettings used for initializing the dialog"),
417 GTK_TYPE_PRINT_SETTINGS,
418 GTK_PARAM_READWRITE));
419
420 /**
421 * GtkPrintUnixDialog:selected-printer: (attributes org.gtk.Property.get=gtk_print_unix_dialog_get_selected_printer)
422 *
423 * The `GtkPrinter` which is selected.
424 */
425 g_object_class_install_property (oclass: object_class,
426 property_id: PROP_SELECTED_PRINTER,
427 pspec: g_param_spec_object (name: "selected-printer",
428 P_("Selected Printer"),
429 P_("The GtkPrinter which is selected"),
430 GTK_TYPE_PRINTER,
431 GTK_PARAM_READABLE));
432
433 /**
434 * GtkPrintUnixDialog:manual-capabilities: (attributes org.gtk.Property.get=gtk_print_unix_dialog_get_manual_capabilities org.gtk.Property.set=gtk_print_unix_dialog_set_manual_capabilities)
435 *
436 * Capabilities the application can handle.
437 */
438 g_object_class_install_property (oclass: object_class,
439 property_id: PROP_MANUAL_CAPABILITIES,
440 pspec: g_param_spec_flags (name: "manual-capabilities",
441 P_("Manual Capabilities"),
442 P_("Capabilities the application can handle"),
443 GTK_TYPE_PRINT_CAPABILITIES,
444 default_value: 0,
445 GTK_PARAM_READWRITE));
446
447 /**
448 * GtkPrintUnixDialog:support-selection: (attributes org.gtk.Property.get=gtk_print_unix_dialog_get_support_selection org.gtk.Property.set=gtk_print_unix_dialog_set_support_selection)
449 *
450 * Whether the dialog supports selection.
451 */
452 g_object_class_install_property (oclass: object_class,
453 property_id: PROP_SUPPORT_SELECTION,
454 pspec: g_param_spec_boolean (name: "support-selection",
455 P_("Support Selection"),
456 P_("Whether the dialog supports selection"),
457 FALSE,
458 GTK_PARAM_READWRITE));
459
460 /**
461 * GtkPrintUnixDialog:has-selection: (attributes org.gtk.Property.get=gtk_print_unix_dialog_get_has_selection org.gtk.Property.set=gtk_print_unix_dialog_set_has_selection)
462 *
463 * Whether the application has a selection.
464 */
465 g_object_class_install_property (oclass: object_class,
466 property_id: PROP_HAS_SELECTION,
467 pspec: g_param_spec_boolean (name: "has-selection",
468 P_("Has Selection"),
469 P_("Whether the application has a selection"),
470 FALSE,
471 GTK_PARAM_READWRITE));
472
473 /**
474 * GtkPrintUnixDialog:embed-page-setup: (attributes org.gtk.Property.get=gtk_print_unix_dialog_get_embed_page_setup org.gtk.Property.set=gtk_print_unix_dialog_set_embed_page_setup)
475 *
476 * %TRUE if the page setup controls are embedded.
477 */
478 g_object_class_install_property (oclass: object_class,
479 property_id: PROP_EMBED_PAGE_SETUP,
480 pspec: g_param_spec_boolean (name: "embed-page-setup",
481 P_("Embed Page Setup"),
482 P_("TRUE if page setup combos are embedded in GtkPrintUnixDialog"),
483 FALSE,
484 GTK_PARAM_READWRITE));
485
486 /* Bind class to template
487 */
488 gtk_widget_class_set_template_from_resource (widget_class,
489 resource_name: "/org/gtk/libgtk/ui/gtkprintunixdialog.ui");
490
491 /* GtkTreeView / GtkTreeModel */
492 gtk_widget_class_bind_template_child (widget_class, GtkPrintUnixDialog, printer_list);
493
494 /* General Widgetry */
495 gtk_widget_class_bind_template_child (widget_class, GtkPrintUnixDialog, notebook);
496 gtk_widget_class_bind_template_child (widget_class, GtkPrintUnixDialog, all_pages_radio);
497 gtk_widget_class_bind_template_child (widget_class, GtkPrintUnixDialog, all_pages_radio);
498 gtk_widget_class_bind_template_child (widget_class, GtkPrintUnixDialog, current_page_radio);
499 gtk_widget_class_bind_template_child (widget_class, GtkPrintUnixDialog, selection_radio);
500 gtk_widget_class_bind_template_child (widget_class, GtkPrintUnixDialog, range_table);
501 gtk_widget_class_bind_template_child (widget_class, GtkPrintUnixDialog, page_range_radio);
502 gtk_widget_class_bind_template_child (widget_class, GtkPrintUnixDialog, page_range_entry);
503 gtk_widget_class_bind_template_child (widget_class, GtkPrintUnixDialog, copies_spin);
504 gtk_widget_class_bind_template_child (widget_class, GtkPrintUnixDialog, collate_check);
505 gtk_widget_class_bind_template_child (widget_class, GtkPrintUnixDialog, reverse_check);
506 gtk_widget_class_bind_template_child (widget_class, GtkPrintUnixDialog, collate_image);
507 gtk_widget_class_bind_template_child (widget_class, GtkPrintUnixDialog, page_layout_preview);
508 gtk_widget_class_bind_template_child (widget_class, GtkPrintUnixDialog, scale_spin);
509 gtk_widget_class_bind_template_child (widget_class, GtkPrintUnixDialog, page_set_combo);
510 gtk_widget_class_bind_template_child (widget_class, GtkPrintUnixDialog, print_now_radio);
511 gtk_widget_class_bind_template_child (widget_class, GtkPrintUnixDialog, print_at_radio);
512 gtk_widget_class_bind_template_child (widget_class, GtkPrintUnixDialog, print_at_entry);
513 gtk_widget_class_bind_template_child (widget_class, GtkPrintUnixDialog, print_hold_radio);
514 gtk_widget_class_bind_template_child (widget_class, GtkPrintUnixDialog, paper_size_combo);
515 gtk_widget_class_bind_template_child (widget_class, GtkPrintUnixDialog, orientation_combo);
516 gtk_widget_class_bind_template_child (widget_class, GtkPrintUnixDialog, conflicts_widget);
517 gtk_widget_class_bind_template_child (widget_class, GtkPrintUnixDialog, job_page);
518 gtk_widget_class_bind_template_child (widget_class, GtkPrintUnixDialog, finishing_table);
519 gtk_widget_class_bind_template_child (widget_class, GtkPrintUnixDialog, finishing_page);
520 gtk_widget_class_bind_template_child (widget_class, GtkPrintUnixDialog, image_quality_table);
521 gtk_widget_class_bind_template_child (widget_class, GtkPrintUnixDialog, image_quality_page);
522 gtk_widget_class_bind_template_child (widget_class, GtkPrintUnixDialog, color_table);
523 gtk_widget_class_bind_template_child (widget_class, GtkPrintUnixDialog, color_page);
524 gtk_widget_class_bind_template_child (widget_class, GtkPrintUnixDialog, advanced_vbox);
525 gtk_widget_class_bind_template_child (widget_class, GtkPrintUnixDialog, advanced_page);
526 gtk_widget_class_bind_template_child (widget_class, GtkPrintUnixDialog, extension_point);
527
528 /* GtkPrinterOptionWidgets... */
529 gtk_widget_class_bind_template_child (widget_class, GtkPrintUnixDialog, pages_per_sheet);
530 gtk_widget_class_bind_template_child (widget_class, GtkPrintUnixDialog, duplex);
531 gtk_widget_class_bind_template_child (widget_class, GtkPrintUnixDialog, paper_type);
532 gtk_widget_class_bind_template_child (widget_class, GtkPrintUnixDialog, paper_source);
533 gtk_widget_class_bind_template_child (widget_class, GtkPrintUnixDialog, output_tray);
534 gtk_widget_class_bind_template_child (widget_class, GtkPrintUnixDialog, job_prio);
535 gtk_widget_class_bind_template_child (widget_class, GtkPrintUnixDialog, billing_info);
536 gtk_widget_class_bind_template_child (widget_class, GtkPrintUnixDialog, cover_before);
537 gtk_widget_class_bind_template_child (widget_class, GtkPrintUnixDialog, cover_after);
538 gtk_widget_class_bind_template_child (widget_class, GtkPrintUnixDialog, number_up_layout);
539
540 /* Callbacks handled in the UI */
541 gtk_widget_class_bind_template_callback (widget_class, redraw_page_layout_preview);
542 gtk_widget_class_bind_template_callback (widget_class, error_dialogs);
543 gtk_widget_class_bind_template_callback (widget_class, page_range_entry_focus_changed);
544 gtk_widget_class_bind_template_callback (widget_class, update_page_range_entry_sensitivity);
545 gtk_widget_class_bind_template_callback (widget_class, update_print_at_entry_sensitivity);
546 gtk_widget_class_bind_template_callback (widget_class, update_print_at_option);
547 gtk_widget_class_bind_template_callback (widget_class, update_dialog_from_capabilities);
548 gtk_widget_class_bind_template_callback (widget_class, update_collate_icon);
549 gtk_widget_class_bind_template_callback (widget_class, redraw_page_layout_preview);
550 gtk_widget_class_bind_template_callback (widget_class, update_number_up_layout);
551 gtk_widget_class_bind_template_callback (widget_class, redraw_page_layout_preview);
552}
553
554/* Returns a toplevel GtkWindow, or NULL if none */
555static GtkWindow *
556get_toplevel (GtkWidget *widget)
557{
558 GtkWidget *toplevel = NULL;
559
560 toplevel = GTK_WIDGET (gtk_widget_get_root (widget));
561 if (GTK_IS_WINDOW (toplevel))
562 return GTK_WINDOW (toplevel);
563 else
564 return NULL;
565}
566
567static void
568set_busy_cursor (GtkPrintUnixDialog *dialog,
569 gboolean busy)
570{
571 GtkWidget *widget;
572 GtkWindow *toplevel;
573
574 toplevel = get_toplevel (GTK_WIDGET (dialog));
575 widget = GTK_WIDGET (toplevel);
576
577 if (!toplevel || !gtk_widget_get_realized (widget))
578 return;
579
580 if (busy)
581 gtk_widget_set_cursor_from_name (widget, name: "progress");
582 else
583 gtk_widget_set_cursor (widget, NULL);
584}
585
586typedef struct {
587 GMainLoop *loop;
588 int response;
589} ConfirmationData;
590
591static void
592on_confirmation_dialog_response (GtkWidget *dialog,
593 int response,
594 gpointer user_data)
595{
596 ConfirmationData *data = user_data;
597
598 data->response = response;
599
600 g_main_loop_quit (loop: data->loop);
601
602 gtk_window_destroy (GTK_WINDOW (dialog));
603}
604
605/* This function handles error messages before printing.
606 */
607static void
608error_dialogs (GtkPrintUnixDialog *dialog,
609 int dialog_response_id,
610 gpointer data)
611{
612 if (dialog != NULL && dialog_response_id == GTK_RESPONSE_OK)
613 {
614 GtkPrinter *printer = gtk_print_unix_dialog_get_selected_printer (dialog);
615
616 if (printer != NULL)
617 {
618 if (dialog->request_details_tag || !gtk_printer_is_accepting_jobs (printer))
619 {
620 g_signal_stop_emission_by_name (instance: dialog, detailed_signal: "response");
621 return;
622 }
623
624 /* Shows overwrite confirmation dialog in the case of printing
625 * to file which already exists.
626 */
627 if (gtk_printer_is_virtual (printer))
628 {
629 GtkPrinterOption *option =
630 gtk_printer_option_set_lookup (set: dialog->options,
631 name: "gtk-main-page-custom-input");
632
633 if (option != NULL &&
634 option->type == GTK_PRINTER_OPTION_TYPE_FILESAVE)
635 {
636 GFile *file = g_file_new_for_uri (uri: option->value);
637
638 if (g_file_query_exists (file, NULL))
639 {
640 GtkWidget *message_dialog;
641 GtkWindow *toplevel;
642 char *basename;
643 char *dirname;
644 GFile *parent;
645
646 toplevel = get_toplevel (GTK_WIDGET (dialog));
647
648 basename = g_file_get_basename (file);
649 parent = g_file_get_parent (file);
650 dirname = g_file_get_parse_name (file: parent);
651 g_object_unref (object: parent);
652
653 message_dialog = gtk_message_dialog_new (parent: toplevel,
654 flags: GTK_DIALOG_MODAL |
655 GTK_DIALOG_DESTROY_WITH_PARENT,
656 type: GTK_MESSAGE_QUESTION,
657 buttons: GTK_BUTTONS_NONE,
658 _("A file named “%s” already exists. Do you want to replace it?"),
659 basename);
660
661 gtk_message_dialog_format_secondary_text (GTK_MESSAGE_DIALOG (message_dialog),
662 _("The file already exists in “%s”. Replacing it will "
663 "overwrite its contents."),
664 dirname);
665
666 gtk_dialog_add_button (GTK_DIALOG (message_dialog),
667 _("_Cancel"),
668 response_id: GTK_RESPONSE_CANCEL);
669 gtk_dialog_add_button (GTK_DIALOG (message_dialog),
670 _("_Replace"),
671 response_id: GTK_RESPONSE_ACCEPT);
672 gtk_dialog_set_default_response (GTK_DIALOG (message_dialog),
673 response_id: GTK_RESPONSE_ACCEPT);
674
675 if (gtk_window_has_group (window: toplevel))
676 gtk_window_group_add_window (window_group: gtk_window_get_group (window: toplevel),
677 GTK_WINDOW (message_dialog));
678
679 gtk_window_present (GTK_WINDOW (message_dialog));
680
681 /* Block on the confirmation dialog until we have a response,
682 * so that we can stop the "response" signal emission on the
683 * print dialog
684 */
685 ConfirmationData cdata;
686
687 cdata.loop = g_main_loop_new (NULL, FALSE);
688 cdata.response = 0;
689
690 g_signal_connect (message_dialog, "response",
691 G_CALLBACK (on_confirmation_dialog_response),
692 &cdata);
693
694 g_main_loop_run (loop: cdata.loop);
695 g_main_loop_unref (loop: cdata.loop);
696
697 g_free (mem: dirname);
698 g_free (mem: basename);
699
700 if (cdata.response != GTK_RESPONSE_ACCEPT)
701 g_signal_stop_emission_by_name (instance: dialog, detailed_signal: "response");
702 }
703
704 g_object_unref (object: file);
705 }
706 }
707 }
708 }
709}
710
711static char *
712get_printer_key (GtkPrinter *printer)
713{
714 return g_strconcat (string1: "", gtk_printer_get_name (printer), " ", gtk_printer_get_location (printer), NULL);
715}
716
717static void
718setup_paper_size_item (GtkSignalListItemFactory *factory,
719 GtkListItem *item)
720{
721 GtkWidget *label;
722
723 label = gtk_label_new (str: "");
724 gtk_widget_set_halign (widget: label, align: GTK_ALIGN_START);
725 gtk_list_item_set_child (self: item, child: label);
726}
727
728static void
729bind_paper_size_list_item (GtkSignalListItemFactory *factory,
730 GtkListItem *item,
731 GtkPrintUnixDialog *self)
732{
733 GtkPageSetup *page_setup;
734 GtkWidget *label;
735 guint pos;
736 GListModel *papers;
737 GListModel *model;
738 gpointer first;
739
740 page_setup = gtk_list_item_get_item (self: item);
741 label = gtk_list_item_get_child (self: item);
742
743 pos = gtk_list_item_get_position (self: item);
744 papers = gtk_drop_down_get_model (self: GTK_DROP_DOWN (ptr: self->paper_size_combo));
745 model = gtk_flatten_list_model_get_model_for_item (self: GTK_FLATTEN_LIST_MODEL (ptr: papers), position: pos);
746 if (model != G_LIST_MODEL (ptr: self->manage_papers_list))
747 {
748 GtkPaperSize *paper_size = gtk_page_setup_get_paper_size (setup: page_setup);
749 gtk_label_set_text (GTK_LABEL (label), str: gtk_paper_size_get_display_name (size: paper_size));
750 }
751 else
752 gtk_label_set_text (GTK_LABEL (label), _("Manage Custom Sizes…"));
753
754 first = g_list_model_get_item (list: model, position: 0);
755 g_object_unref (object: first);
756 if (pos != 0 &&
757 page_setup == GTK_PAGE_SETUP (first))
758 gtk_widget_add_css_class (widget: gtk_widget_get_parent (widget: label), css_class: "separator");
759 else
760 gtk_widget_remove_css_class (widget: gtk_widget_get_parent (widget: label), css_class: "separator");
761}
762
763static void
764bind_paper_size_item (GtkSignalListItemFactory *factory,
765 GtkListItem *item,
766 GtkPrintUnixDialog *self)
767{
768 GtkWidget *label;
769
770 bind_paper_size_list_item (factory, item, self);
771
772 label = gtk_list_item_get_child (self: item);
773 gtk_widget_remove_css_class (widget: label, css_class: "separator-before");
774}
775
776static void
777gtk_print_unix_dialog_init (GtkPrintUnixDialog *dialog)
778{
779 GtkWidget *widget;
780 GListModel *model;
781 GListModel *sorted;
782 GListModel *filtered;
783 GListModel *selection;
784 GtkSorter *sorter;
785 GtkFilter *filter;
786 GtkStringFilter *filter1;
787 GtkCustomFilter *filter2;
788 GtkListItemFactory *factory;
789 GListStore *store;
790 GListModel *paper_size_list;
791 GtkPageSetup *page_setup;
792
793 dialog->print_backends = NULL;
794 dialog->current_page = -1;
795 dialog->number_up_layout_n_option = NULL;
796 dialog->number_up_layout_2_option = NULL;
797
798 dialog->page_setup = gtk_page_setup_new ();
799 dialog->page_setup_set = FALSE;
800 dialog->embed_page_setup = FALSE;
801 dialog->internal_page_setup_change = FALSE;
802 dialog->page_setup_list = g_list_store_new (GTK_TYPE_PAGE_SETUP);
803 dialog->custom_paper_list = g_list_store_new (GTK_TYPE_PAGE_SETUP);
804 dialog->manage_papers_list = g_list_store_new (GTK_TYPE_PAGE_SETUP);
805 page_setup = gtk_page_setup_new ();
806 g_list_store_append (store: dialog->manage_papers_list, item: page_setup);
807 g_object_unref (object: page_setup);
808
809 dialog->support_selection = FALSE;
810 dialog->has_selection = FALSE;
811
812 g_type_ensure (GTK_TYPE_PRINTER);
813 g_type_ensure (GTK_TYPE_PRINTER_OPTION);
814 g_type_ensure (GTK_TYPE_PRINTER_OPTION_SET);
815 g_type_ensure (GTK_TYPE_PRINTER_OPTION_WIDGET);
816
817 gtk_widget_init_template (GTK_WIDGET (dialog));
818 gtk_widget_add_css_class (GTK_WIDGET (dialog), css_class: "print");
819
820 gtk_dialog_set_use_header_bar_from_setting (GTK_DIALOG (dialog));
821 gtk_dialog_add_buttons (GTK_DIALOG (dialog),
822 _("Pre_view"), GTK_RESPONSE_APPLY,
823 _("_Cancel"), GTK_RESPONSE_CANCEL,
824 _("_Print"), GTK_RESPONSE_OK,
825 NULL);
826 gtk_dialog_set_default_response (GTK_DIALOG (dialog), response_id: GTK_RESPONSE_OK);
827 widget = gtk_dialog_get_widget_for_response (GTK_DIALOG (dialog), response_id: GTK_RESPONSE_OK);
828 gtk_widget_set_sensitive (widget, FALSE);
829
830 gtk_widget_set_visible (widget: dialog->selection_radio, FALSE);
831 gtk_widget_set_visible (widget: dialog->conflicts_widget, FALSE);
832
833 factory = gtk_signal_list_item_factory_new ();
834 g_signal_connect (factory, "setup", G_CALLBACK (setup_paper_size_item), dialog);
835 g_signal_connect (factory, "bind", G_CALLBACK (bind_paper_size_item), dialog);
836 gtk_drop_down_set_factory (self: GTK_DROP_DOWN (ptr: dialog->paper_size_combo), factory);
837 g_object_unref (object: factory);
838
839 factory = gtk_signal_list_item_factory_new ();
840 g_signal_connect (factory, "setup", G_CALLBACK (setup_paper_size_item), dialog);
841 g_signal_connect (factory, "bind", G_CALLBACK (bind_paper_size_list_item), dialog);
842 gtk_drop_down_set_list_factory (self: GTK_DROP_DOWN (ptr: dialog->paper_size_combo), factory);
843 g_object_unref (object: factory);
844
845 store = g_list_store_new (G_TYPE_LIST_MODEL);
846 g_list_store_append (store, item: dialog->page_setup_list);
847 g_list_store_append (store, item: dialog->custom_paper_list);
848 g_list_store_append (store, item: dialog->manage_papers_list);
849 paper_size_list = G_LIST_MODEL (ptr: gtk_flatten_list_model_new (model: G_LIST_MODEL (ptr: store)));
850 gtk_drop_down_set_model (self: GTK_DROP_DOWN (ptr: dialog->paper_size_combo), model: paper_size_list);
851 g_object_unref (object: paper_size_list);
852
853 /* Load backends */
854 model = load_print_backends (dialog);
855 sorter = GTK_SORTER (ptr: gtk_custom_sorter_new (sort_func: default_printer_list_sort_func, NULL, NULL));
856 sorted = G_LIST_MODEL (ptr: gtk_sort_list_model_new (model, sorter));
857
858 filter = GTK_FILTER (ptr: gtk_every_filter_new ());
859
860 filter1 = gtk_string_filter_new (
861 expression: gtk_cclosure_expression_new (G_TYPE_STRING,
862 NULL, n_params: 0, NULL,
863 G_CALLBACK (get_printer_key),
864 NULL, NULL));
865 gtk_string_filter_set_match_mode (self: filter1, mode: GTK_STRING_FILTER_MATCH_MODE_SUBSTRING);
866 gtk_string_filter_set_ignore_case (self: filter1, TRUE);
867 gtk_multi_filter_append (self: GTK_MULTI_FILTER (ptr: filter), filter: GTK_FILTER (ptr: filter1));
868
869 filter2 = gtk_custom_filter_new (match_func: is_printer_active, user_data: dialog, NULL);
870 gtk_multi_filter_append (self: GTK_MULTI_FILTER (ptr: filter), filter: GTK_FILTER (ptr: filter2));
871
872 filtered = G_LIST_MODEL (ptr: gtk_filter_list_model_new (model: sorted, filter));
873
874 selection = G_LIST_MODEL (ptr: gtk_single_selection_new (model: filtered));
875 gtk_single_selection_set_autoselect (self: GTK_SINGLE_SELECTION (ptr: selection), FALSE);
876 gtk_single_selection_set_selected (self: GTK_SINGLE_SELECTION (ptr: selection), GTK_INVALID_LIST_POSITION);
877 gtk_column_view_set_model (GTK_COLUMN_VIEW (dialog->printer_list), model: GTK_SELECTION_MODEL (ptr: selection));
878 g_signal_connect (selection, "items-changed", G_CALLBACK (printer_added_cb), dialog);
879 g_signal_connect_swapped (selection, "notify::selected", G_CALLBACK (selected_printer_changed), dialog);
880 g_object_unref (object: selection);
881
882 gtk_print_load_custom_papers (store: dialog->custom_paper_list);
883
884 gtk_drawing_area_set_draw_func (GTK_DRAWING_AREA (dialog->collate_image),
885 draw_func: draw_collate,
886 user_data: dialog, NULL);
887 gtk_drawing_area_set_draw_func (GTK_DRAWING_AREA (dialog->page_layout_preview),
888 draw_func: draw_page,
889 user_data: dialog, NULL);
890
891 gtk_css_node_set_name (cssnode: gtk_widget_get_css_node (widget: dialog->collate_image), name: g_quark_from_static_string (string: "drawing"));
892 gtk_css_node_set_name (cssnode: gtk_widget_get_css_node (widget: dialog->page_layout_preview), name: g_quark_from_static_string (string: "drawing"));
893
894 dialog->collate_paper_node = gtk_css_node_new();
895 gtk_css_node_set_name (cssnode: dialog->collate_paper_node, name: g_quark_from_static_string (string: "paper"));
896 gtk_css_node_set_parent (cssnode: dialog->collate_paper_node,
897 parent: gtk_widget_get_css_node (widget: dialog->collate_image));
898 g_object_unref (object: dialog->collate_paper_node);
899
900 dialog->page_layout_paper_node = gtk_css_node_new();
901 gtk_css_node_set_name (cssnode: dialog->page_layout_paper_node, name: g_quark_from_static_string (string: "paper"));
902 gtk_css_node_set_parent (cssnode: dialog->page_layout_paper_node,
903 parent: gtk_widget_get_css_node (widget: dialog->page_layout_preview));
904 g_object_unref (object: dialog->page_layout_paper_node);
905}
906
907static void
908gtk_print_unix_dialog_constructed (GObject *object)
909{
910 gboolean use_header;
911
912 G_OBJECT_CLASS (gtk_print_unix_dialog_parent_class)->constructed (object);
913
914 g_object_get (object, first_property_name: "use-header-bar", &use_header, NULL);
915 if (use_header)
916 {
917 /* Reorder the preview button */
918 GtkWidget *button, *parent;
919 button = gtk_dialog_get_widget_for_response (GTK_DIALOG (object), response_id: GTK_RESPONSE_APPLY);
920 g_object_ref (button);
921 parent = gtk_widget_get_ancestor (widget: button, GTK_TYPE_HEADER_BAR);
922 gtk_box_remove (GTK_BOX (gtk_widget_get_parent (button)), child: button);
923 gtk_header_bar_pack_end (GTK_HEADER_BAR (parent), child: button);
924 g_object_unref (object: button);
925 }
926
927 update_dialog_from_capabilities (GTK_PRINT_UNIX_DIALOG (object));
928}
929
930static void
931gtk_print_unix_dialog_dispose (GObject *object)
932{
933 GtkPrintUnixDialog *dialog = GTK_PRINT_UNIX_DIALOG (object);
934
935 /* Make sure we don't destroy custom widgets owned by the backends */
936 clear_per_printer_ui (dialog);
937
938 G_OBJECT_CLASS (gtk_print_unix_dialog_parent_class)->dispose (object);
939}
940
941static void
942disconnect_printer_details_request (GtkPrintUnixDialog *dialog,
943 gboolean details_failed)
944{
945 if (dialog->request_details_tag)
946 {
947 g_signal_handler_disconnect (instance: dialog->request_details_printer,
948 handler_id: dialog->request_details_tag);
949 dialog->request_details_tag = 0;
950 set_busy_cursor (dialog, FALSE);
951 if (details_failed)
952 gtk_printer_set_state_message (printer: dialog->request_details_printer, _("Getting printer information failed"));
953 g_clear_object (&dialog->request_details_printer);
954 }
955}
956
957static void
958gtk_print_unix_dialog_finalize (GObject *object)
959{
960 GtkPrintUnixDialog *dialog = GTK_PRINT_UNIX_DIALOG (object);
961
962 unschedule_idle_mark_conflicts (dialog);
963 disconnect_printer_details_request (dialog, FALSE);
964
965 g_clear_object (&dialog->current_printer);
966 g_clear_object (&dialog->options);
967
968 if (dialog->number_up_layout_2_option)
969 {
970 dialog->number_up_layout_2_option->choices[0] = NULL;
971 dialog->number_up_layout_2_option->choices[1] = NULL;
972 g_free (mem: dialog->number_up_layout_2_option->choices_display[0]);
973 g_free (mem: dialog->number_up_layout_2_option->choices_display[1]);
974 dialog->number_up_layout_2_option->choices_display[0] = NULL;
975 dialog->number_up_layout_2_option->choices_display[1] = NULL;
976 g_object_unref (object: dialog->number_up_layout_2_option);
977 dialog->number_up_layout_2_option = NULL;
978 }
979
980 g_clear_object (&dialog->number_up_layout_n_option);
981 g_clear_object (&dialog->page_setup);
982 g_clear_object (&dialog->initial_settings);
983 g_clear_pointer (&dialog->waiting_for_printer, (GDestroyNotify)g_free);
984 g_clear_pointer (&dialog->format_for_printer, (GDestroyNotify)g_free);
985
986 g_list_free (list: dialog->print_backends);
987 dialog->print_backends = NULL;
988
989 g_clear_object (&dialog->page_setup_list);
990 g_clear_object (&dialog->custom_paper_list);
991 g_clear_object (&dialog->manage_papers_list);
992
993 G_OBJECT_CLASS (gtk_print_unix_dialog_parent_class)->finalize (object);
994}
995
996static void
997gtk_print_unix_dialog_buildable_init (GtkBuildableIface *iface)
998{
999 parent_buildable_iface = g_type_interface_peek_parent (g_iface: iface);
1000
1001 iface->get_internal_child = gtk_print_unix_dialog_buildable_get_internal_child;
1002}
1003
1004static GObject *
1005gtk_print_unix_dialog_buildable_get_internal_child (GtkBuildable *buildable,
1006 GtkBuilder *builder,
1007 const char *childname)
1008{
1009 GtkPrintUnixDialog *dialog = GTK_PRINT_UNIX_DIALOG (buildable);
1010
1011 if (strcmp (s1: childname, s2: "notebook") == 0)
1012 return G_OBJECT (dialog->notebook);
1013
1014 return parent_buildable_iface->get_internal_child (buildable, builder, childname);
1015}
1016
1017static void
1018printer_status_cb (GtkPrintBackend *backend,
1019 GtkPrinter *printer,
1020 GtkPrintUnixDialog *dialog)
1021{
1022 GListModel *model;
1023
1024 /* When the pause state change then we need to update sensitive property
1025 * of GTK_RESPONSE_OK button inside of selected_printer_changed function.
1026 */
1027 selected_printer_changed (dialog);
1028
1029 model = G_LIST_MODEL (ptr: gtk_column_view_get_model (GTK_COLUMN_VIEW (dialog->printer_list)));
1030
1031 if (gtk_print_backend_printer_list_is_done (print_backend: backend) &&
1032 gtk_printer_is_default (printer) &&
1033 gtk_single_selection_get_selected (self: GTK_SINGLE_SELECTION (ptr: model)) == GTK_INVALID_LIST_POSITION)
1034 set_active_printer (dialog, printer_name: gtk_printer_get_name (printer));
1035}
1036
1037static void
1038printer_added_cb (GListModel *model,
1039 guint position,
1040 guint removed,
1041 guint added,
1042 GtkPrintUnixDialog *dialog)
1043{
1044 guint i;
1045
1046 for (i = position; i < position + added; i++)
1047 {
1048 GtkPrinter *printer = g_list_model_get_item (list: model, position: i);
1049
1050 if (dialog->waiting_for_printer != NULL &&
1051 strcmp (s1: gtk_printer_get_name (printer), s2: dialog->waiting_for_printer) == 0)
1052 {
1053 gtk_single_selection_set_selected (self: GTK_SINGLE_SELECTION (ptr: model), position: i);
1054 g_free (mem: dialog->waiting_for_printer);
1055 dialog->waiting_for_printer = NULL;
1056 g_object_unref (object: printer);
1057 return;
1058 }
1059 else if (is_default_printer (dialog, printer) &&
1060 gtk_single_selection_get_selected (self: GTK_SINGLE_SELECTION (ptr: model)) == GTK_INVALID_LIST_POSITION)
1061 {
1062 gtk_single_selection_set_selected (self: GTK_SINGLE_SELECTION (ptr: model), position: i);
1063 g_object_unref (object: printer);
1064 return;
1065 }
1066
1067 g_object_unref (object: printer);
1068 }
1069}
1070
1071static GListModel *
1072load_print_backends (GtkPrintUnixDialog *dialog)
1073{
1074 GList *node;
1075 GListStore *lists;
1076
1077 lists = g_list_store_new (G_TYPE_LIST_MODEL);
1078
1079 if (g_module_supported ())
1080 dialog->print_backends = gtk_print_backend_load_modules ();
1081
1082 for (node = dialog->print_backends; node != NULL; node = node->next)
1083 {
1084 GtkPrintBackend *backend = node->data;
1085
1086 g_signal_connect_object (instance: backend, detailed_signal: "printer-status-changed",
1087 G_CALLBACK (printer_status_cb), G_OBJECT (dialog), connect_flags: 0);
1088 g_list_store_append (store: lists, item: gtk_print_backend_get_printers (print_backend: backend));
1089 }
1090
1091 return G_LIST_MODEL (ptr: gtk_flatten_list_model_new (model: G_LIST_MODEL (ptr: lists)));
1092}
1093
1094static void
1095gtk_print_unix_dialog_set_property (GObject *object,
1096 guint prop_id,
1097 const GValue *value,
1098 GParamSpec *pspec)
1099
1100{
1101 GtkPrintUnixDialog *dialog = GTK_PRINT_UNIX_DIALOG (object);
1102
1103 switch (prop_id)
1104 {
1105 case PROP_PAGE_SETUP:
1106 gtk_print_unix_dialog_set_page_setup (dialog, page_setup: g_value_get_object (value));
1107 break;
1108 case PROP_CURRENT_PAGE:
1109 gtk_print_unix_dialog_set_current_page (dialog, current_page: g_value_get_int (value));
1110 break;
1111 case PROP_PRINT_SETTINGS:
1112 gtk_print_unix_dialog_set_settings (dialog, settings: g_value_get_object (value));
1113 break;
1114 case PROP_MANUAL_CAPABILITIES:
1115 gtk_print_unix_dialog_set_manual_capabilities (dialog, capabilities: g_value_get_flags (value));
1116 break;
1117 case PROP_SUPPORT_SELECTION:
1118 gtk_print_unix_dialog_set_support_selection (dialog, support_selection: g_value_get_boolean (value));
1119 break;
1120 case PROP_HAS_SELECTION:
1121 gtk_print_unix_dialog_set_has_selection (dialog, has_selection: g_value_get_boolean (value));
1122 break;
1123 case PROP_EMBED_PAGE_SETUP:
1124 gtk_print_unix_dialog_set_embed_page_setup (dialog, embed: g_value_get_boolean (value));
1125 break;
1126 default:
1127 G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
1128 break;
1129 }
1130}
1131
1132static void
1133gtk_print_unix_dialog_get_property (GObject *object,
1134 guint prop_id,
1135 GValue *value,
1136 GParamSpec *pspec)
1137{
1138 GtkPrintUnixDialog *dialog = GTK_PRINT_UNIX_DIALOG (object);
1139
1140 switch (prop_id)
1141 {
1142 case PROP_PAGE_SETUP:
1143 g_value_set_object (value, v_object: dialog->page_setup);
1144 break;
1145 case PROP_CURRENT_PAGE:
1146 g_value_set_int (value, v_int: dialog->current_page);
1147 break;
1148 case PROP_PRINT_SETTINGS:
1149 g_value_take_object (value, v_object: gtk_print_unix_dialog_get_settings (dialog));
1150 break;
1151 case PROP_SELECTED_PRINTER:
1152 g_value_set_object (value, v_object: dialog->current_printer);
1153 break;
1154 case PROP_MANUAL_CAPABILITIES:
1155 g_value_set_flags (value, v_flags: dialog->manual_capabilities);
1156 break;
1157 case PROP_SUPPORT_SELECTION:
1158 g_value_set_boolean (value, v_boolean: dialog->support_selection);
1159 break;
1160 case PROP_HAS_SELECTION:
1161 g_value_set_boolean (value, v_boolean: dialog->has_selection);
1162 break;
1163 case PROP_EMBED_PAGE_SETUP:
1164 g_value_set_boolean (value, v_boolean: dialog->embed_page_setup);
1165 break;
1166 default:
1167 G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
1168 break;
1169 }
1170}
1171
1172static gboolean
1173is_printer_active (gpointer item, gpointer data)
1174{
1175 GtkPrinter *printer = item;
1176 GtkPrintUnixDialog *dialog = data;
1177 gboolean result;
1178
1179 result = gtk_printer_is_active (printer);
1180
1181 if (result &&
1182 dialog->manual_capabilities & (GTK_PRINT_CAPABILITY_GENERATE_PDF |
1183 GTK_PRINT_CAPABILITY_GENERATE_PS))
1184 {
1185 /* Check that the printer can handle at least one of the data
1186 * formats that the application supports.
1187 */
1188 result = ((dialog->manual_capabilities & GTK_PRINT_CAPABILITY_GENERATE_PDF) &&
1189 gtk_printer_accepts_pdf (printer)) ||
1190 ((dialog->manual_capabilities & GTK_PRINT_CAPABILITY_GENERATE_PS) &&
1191 gtk_printer_accepts_ps (printer));
1192 }
1193
1194 return result;
1195}
1196
1197static int
1198default_printer_list_sort_func (gconstpointer a,
1199 gconstpointer b,
1200 gpointer user_data)
1201{
1202 GtkPrinter *a_printer = (gpointer)a;
1203 GtkPrinter *b_printer = (gpointer)b;
1204 const char *a_name;
1205 const char *b_name;
1206
1207 if (a_printer == NULL && b_printer == NULL)
1208 return 0;
1209 else if (a_printer == NULL)
1210 return 1;
1211 else if (b_printer == NULL)
1212 return -1;
1213
1214 if (gtk_printer_is_virtual (printer: a_printer) && gtk_printer_is_virtual (printer: b_printer))
1215 return 0;
1216 else if (gtk_printer_is_virtual (printer: a_printer) && !gtk_printer_is_virtual (printer: b_printer))
1217 return -1;
1218 else if (!gtk_printer_is_virtual (printer: a_printer) && gtk_printer_is_virtual (printer: b_printer))
1219 return 1;
1220
1221 a_name = gtk_printer_get_name (printer: a_printer);
1222 b_name = gtk_printer_get_name (printer: b_printer);
1223
1224 if (a_name == NULL && b_name == NULL)
1225 return 0;
1226 else if (a_name == NULL && b_name != NULL)
1227 return 1;
1228 else if (a_name != NULL && b_name == NULL)
1229 return -1;
1230
1231 return g_ascii_strcasecmp (s1: a_name, s2: b_name);
1232}
1233
1234static GtkWidget *
1235wrap_in_frame (const char *label,
1236 GtkWidget *child)
1237{
1238 GtkWidget *box, *label_widget;
1239 char *bold_text;
1240
1241 label_widget = gtk_label_new (NULL);
1242 gtk_widget_set_halign (widget: label_widget, align: GTK_ALIGN_START);
1243 gtk_widget_set_valign (widget: label_widget, align: GTK_ALIGN_CENTER);
1244 gtk_widget_show (widget: label_widget);
1245
1246 bold_text = g_markup_printf_escaped (format: "<b>%s</b>", label);
1247 gtk_label_set_markup (GTK_LABEL (label_widget), str: bold_text);
1248 g_free (mem: bold_text);
1249
1250 box = gtk_box_new (orientation: GTK_ORIENTATION_VERTICAL, spacing: 6);
1251 gtk_box_append (GTK_BOX (box), child: label_widget);
1252
1253 gtk_widget_set_margin_start (widget: child, margin: 12);
1254 gtk_widget_set_halign (widget: child, align: GTK_ALIGN_FILL);
1255 gtk_widget_set_valign (widget: child, align: GTK_ALIGN_FILL);
1256
1257 gtk_box_append (GTK_BOX (box), child);
1258
1259 return box;
1260}
1261
1262static gboolean
1263setup_option (GtkPrintUnixDialog *dialog,
1264 const char *option_name,
1265 GtkPrinterOptionWidget *widget)
1266{
1267 GtkPrinterOption *option;
1268
1269 option = gtk_printer_option_set_lookup (set: dialog->options, name: option_name);
1270 gtk_printer_option_widget_set_source (setting: widget, source: option);
1271
1272 return option != NULL;
1273}
1274
1275static void
1276add_option_to_extension_point (GtkPrinterOption *option,
1277 gpointer data)
1278{
1279 GtkWidget *extension_point = data;
1280 GtkWidget *widget;
1281
1282 widget = gtk_printer_option_widget_new (source: option);
1283 gtk_widget_show (widget);
1284
1285 if (gtk_printer_option_widget_has_external_label (GTK_PRINTER_OPTION_WIDGET (widget)))
1286 {
1287 GtkWidget *label, *hbox;
1288
1289 gtk_widget_set_valign (widget, align: GTK_ALIGN_BASELINE);
1290
1291 label = gtk_printer_option_widget_get_external_label (GTK_PRINTER_OPTION_WIDGET (widget));
1292 gtk_widget_show (widget: label);
1293 gtk_widget_set_halign (widget: label, align: GTK_ALIGN_START);
1294 gtk_widget_set_valign (widget: label, align: GTK_ALIGN_BASELINE);
1295 gtk_label_set_mnemonic_widget (GTK_LABEL (label), widget);
1296
1297 hbox = gtk_box_new (orientation: GTK_ORIENTATION_HORIZONTAL, spacing: 12);
1298 gtk_widget_set_valign (widget: hbox, align: GTK_ALIGN_BASELINE);
1299 gtk_box_append (GTK_BOX (hbox), child: label);
1300 gtk_box_append (GTK_BOX (hbox), child: widget);
1301 gtk_widget_show (widget: hbox);
1302
1303 gtk_box_append (GTK_BOX (extension_point), child: hbox);
1304 }
1305 else
1306 gtk_box_append (GTK_BOX (extension_point), child: widget);
1307}
1308
1309static int
1310grid_rows (GtkGrid *table)
1311{
1312 int t0, t1, l, t, w, h;
1313 GtkWidget *c;
1314 gboolean first;
1315
1316 t0 = t1 = 0;
1317 for (c = gtk_widget_get_first_child (GTK_WIDGET (table)), first = TRUE;
1318 c != NULL;
1319 c = gtk_widget_get_next_sibling (GTK_WIDGET (c)), first = FALSE)
1320 {
1321 gtk_grid_query_child (grid: table, child: c, column: &l, row: &t, width: &w, height: &h);
1322 if (first)
1323 {
1324 t0 = t;
1325 t1 = t + h;
1326 }
1327 else
1328 {
1329 if (t < t0)
1330 t0 = t;
1331 if (t + h > t1)
1332 t1 = t + h;
1333 }
1334 }
1335
1336 return t1 - t0;
1337}
1338
1339static void
1340add_option_to_table (GtkPrinterOption *option,
1341 gpointer user_data)
1342{
1343 GtkGrid *table;
1344 GtkWidget *label, *widget;
1345 guint row;
1346
1347 table = GTK_GRID (user_data);
1348
1349 if (g_str_has_prefix (str: option->name, prefix: "gtk-"))
1350 return;
1351
1352 row = grid_rows (table);
1353
1354 widget = gtk_printer_option_widget_new (source: option);
1355 gtk_widget_show (widget);
1356
1357 if (gtk_printer_option_widget_has_external_label (GTK_PRINTER_OPTION_WIDGET (widget)))
1358 {
1359 label = gtk_printer_option_widget_get_external_label (GTK_PRINTER_OPTION_WIDGET (widget));
1360 gtk_widget_show (widget: label);
1361
1362 gtk_widget_set_halign (widget: label, align: GTK_ALIGN_START);
1363 gtk_widget_set_valign (widget: label, align: GTK_ALIGN_CENTER);
1364 gtk_label_set_mnemonic_widget (GTK_LABEL (label), widget);
1365
1366 gtk_grid_attach (grid: table, child: label, column: 0, row: row - 1, width: 1, height: 1);
1367 gtk_grid_attach (grid: table, child: widget, column: 1, row: row - 1, width: 1, height: 1);
1368 }
1369 else
1370 gtk_grid_attach (grid: table, child: widget, column: 0, row: row - 1, width: 2, height: 1);
1371}
1372
1373static void
1374setup_page_table (GtkPrinterOptionSet *options,
1375 const char *group,
1376 GtkWidget *table,
1377 GtkWidget *page)
1378{
1379 int nrows;
1380
1381 gtk_printer_option_set_foreach_in_group (set: options, group,
1382 func: add_option_to_table,
1383 user_data: table);
1384
1385 nrows = grid_rows (GTK_GRID (table));
1386 if (nrows == 0)
1387 gtk_widget_hide (widget: page);
1388 else
1389 gtk_widget_show (widget: page);
1390}
1391
1392static void
1393update_print_at_option (GtkPrintUnixDialog *dialog)
1394{
1395 GtkPrinterOption *option;
1396
1397 option = gtk_printer_option_set_lookup (set: dialog->options, name: "gtk-print-time");
1398
1399 if (option == NULL)
1400 return;
1401
1402 if (dialog->updating_print_at)
1403 return;
1404
1405 if (gtk_check_button_get_active (GTK_CHECK_BUTTON (dialog->print_at_radio)))
1406 gtk_printer_option_set (option, value: "at");
1407 else if (gtk_check_button_get_active (GTK_CHECK_BUTTON (dialog->print_hold_radio)))
1408 gtk_printer_option_set (option, value: "on-hold");
1409 else
1410 gtk_printer_option_set (option, value: "now");
1411
1412 option = gtk_printer_option_set_lookup (set: dialog->options, name: "gtk-print-time-text");
1413 if (option != NULL)
1414 {
1415 const char *text;
1416
1417 text = gtk_editable_get_text (GTK_EDITABLE (dialog->print_at_entry));
1418 gtk_printer_option_set (option, value: text);
1419 }
1420}
1421
1422
1423static gboolean
1424setup_print_at (GtkPrintUnixDialog *dialog)
1425{
1426 GtkPrinterOption *option;
1427
1428 option = gtk_printer_option_set_lookup (set: dialog->options, name: "gtk-print-time");
1429
1430 if (option == NULL)
1431 {
1432 gtk_check_button_set_active (GTK_CHECK_BUTTON (dialog->print_now_radio), TRUE);
1433 gtk_widget_set_sensitive (widget: dialog->print_at_radio, FALSE);
1434 gtk_widget_set_sensitive (widget: dialog->print_at_entry, FALSE);
1435 gtk_widget_set_sensitive (widget: dialog->print_hold_radio, FALSE);
1436 gtk_editable_set_text (GTK_EDITABLE (dialog->print_at_entry), text: "");
1437 return FALSE;
1438 }
1439
1440 dialog->updating_print_at = TRUE;
1441
1442 gtk_widget_set_sensitive (widget: dialog->print_at_entry, FALSE);
1443 gtk_widget_set_sensitive (widget: dialog->print_at_radio,
1444 sensitive: gtk_printer_option_has_choice (option, choice: "at"));
1445
1446 gtk_widget_set_sensitive (widget: dialog->print_hold_radio,
1447 sensitive: gtk_printer_option_has_choice (option, choice: "on-hold"));
1448
1449 update_print_at_option (dialog);
1450
1451 if (strcmp (s1: option->value, s2: "at") == 0)
1452 gtk_check_button_set_active (GTK_CHECK_BUTTON (dialog->print_at_radio), TRUE);
1453 else if (strcmp (s1: option->value, s2: "on-hold") == 0)
1454 gtk_check_button_set_active (GTK_CHECK_BUTTON (dialog->print_hold_radio), TRUE);
1455 else
1456 gtk_check_button_set_active (GTK_CHECK_BUTTON (dialog->print_now_radio), TRUE);
1457
1458 option = gtk_printer_option_set_lookup (set: dialog->options, name: "gtk-print-time-text");
1459 if (option != NULL)
1460 gtk_editable_set_text (GTK_EDITABLE (dialog->print_at_entry), text: option->value);
1461
1462 dialog->updating_print_at = FALSE;
1463
1464 return TRUE;
1465}
1466
1467static void
1468update_dialog_from_settings (GtkPrintUnixDialog *dialog)
1469{
1470 GList *groups, *l;
1471 char *group;
1472 GtkWidget *table, *frame;
1473 gboolean has_advanced, has_job;
1474 guint nrows;
1475 GtkWidget *child;
1476
1477 if (dialog->current_printer == NULL)
1478 {
1479 clear_per_printer_ui (dialog);
1480 gtk_widget_hide (widget: dialog->job_page);
1481 gtk_widget_hide (widget: dialog->advanced_page);
1482 gtk_widget_hide (widget: dialog->image_quality_page);
1483 gtk_widget_hide (widget: dialog->finishing_page);
1484 gtk_widget_hide (widget: dialog->color_page);
1485 gtk_dialog_set_response_sensitive (GTK_DIALOG (dialog), response_id: GTK_RESPONSE_OK, FALSE);
1486
1487 return;
1488 }
1489
1490 setup_option (dialog, option_name: "gtk-n-up", widget: dialog->pages_per_sheet);
1491 setup_option (dialog, option_name: "gtk-n-up-layout", widget: dialog->number_up_layout);
1492 setup_option (dialog, option_name: "gtk-duplex", widget: dialog->duplex);
1493 setup_option (dialog, option_name: "gtk-paper-type", widget: dialog->paper_type);
1494 setup_option (dialog, option_name: "gtk-paper-source", widget: dialog->paper_source);
1495 setup_option (dialog, option_name: "gtk-output-tray", widget: dialog->output_tray);
1496
1497 has_job = FALSE;
1498 has_job |= setup_option (dialog, option_name: "gtk-job-prio", widget: dialog->job_prio);
1499 has_job |= setup_option (dialog, option_name: "gtk-billing-info", widget: dialog->billing_info);
1500 has_job |= setup_option (dialog, option_name: "gtk-cover-before", widget: dialog->cover_before);
1501 has_job |= setup_option (dialog, option_name: "gtk-cover-after", widget: dialog->cover_after);
1502 has_job |= setup_print_at (dialog);
1503
1504 if (has_job)
1505 gtk_widget_show (widget: dialog->job_page);
1506 else
1507 gtk_widget_hide (widget: dialog->job_page);
1508
1509 setup_page_table (options: dialog->options,
1510 group: "ImageQualityPage",
1511 table: dialog->image_quality_table,
1512 page: dialog->image_quality_page);
1513
1514 setup_page_table (options: dialog->options,
1515 group: "FinishingPage",
1516 table: dialog->finishing_table,
1517 page: dialog->finishing_page);
1518
1519 setup_page_table (options: dialog->options,
1520 group: "ColorPage",
1521 table: dialog->color_table,
1522 page: dialog->color_page);
1523
1524 gtk_printer_option_set_foreach_in_group (set: dialog->options,
1525 group: "GtkPrintDialogExtension",
1526 func: add_option_to_extension_point,
1527 user_data: dialog->extension_point);
1528
1529 /* A bit of a hack, keep the last option flush right.
1530 * This keeps the file format radios from moving as the
1531 * filename changes.
1532 */
1533 child = gtk_widget_get_last_child (widget: dialog->extension_point);
1534 if (child && child != gtk_widget_get_first_child (widget: dialog->extension_point))
1535 gtk_widget_set_halign (widget: child, align: GTK_ALIGN_END);
1536
1537 /* Put the rest of the groups in the advanced page */
1538 groups = gtk_printer_option_set_get_groups (set: dialog->options);
1539
1540 has_advanced = FALSE;
1541 for (l = groups; l != NULL; l = l->next)
1542 {
1543 group = l->data;
1544
1545 if (group == NULL)
1546 continue;
1547
1548 if (strcmp (s1: group, s2: "ImageQualityPage") == 0 ||
1549 strcmp (s1: group, s2: "ColorPage") == 0 ||
1550 strcmp (s1: group, s2: "FinishingPage") == 0 ||
1551 strcmp (s1: group, s2: "GtkPrintDialogExtension") == 0)
1552 continue;
1553
1554 table = gtk_grid_new ();
1555 gtk_grid_set_row_spacing (GTK_GRID (table), spacing: 6);
1556 gtk_grid_set_column_spacing (GTK_GRID (table), spacing: 12);
1557
1558 gtk_printer_option_set_foreach_in_group (set: dialog->options,
1559 group,
1560 func: add_option_to_table,
1561 user_data: table);
1562
1563 nrows = grid_rows (GTK_GRID (table));
1564 if (nrows == 0)
1565 {
1566 g_object_unref (g_object_ref_sink (table));
1567 }
1568 else
1569 {
1570 has_advanced = TRUE;
1571 frame = wrap_in_frame (label: group, child: table);
1572 gtk_box_append (GTK_BOX (dialog->advanced_vbox), child: frame);
1573 }
1574 }
1575
1576 if (has_advanced)
1577 gtk_widget_show (widget: dialog->advanced_page);
1578 else
1579 gtk_widget_hide (widget: dialog->advanced_page);
1580
1581 g_list_free_full (list: groups, free_func: g_free);
1582}
1583
1584static void
1585update_dialog_from_capabilities (GtkPrintUnixDialog *dialog)
1586{
1587 GtkPrintCapabilities caps;
1588 gboolean can_collate;
1589 const char *copies;
1590 GtkWidget *button;
1591
1592 copies = gtk_editable_get_text (GTK_EDITABLE (dialog->copies_spin));
1593 can_collate = (*copies != '\0' && atoi (nptr: copies) > 1);
1594
1595 caps = dialog->manual_capabilities | dialog->printer_capabilities;
1596
1597 gtk_widget_set_sensitive (widget: dialog->page_set_combo,
1598 sensitive: caps & GTK_PRINT_CAPABILITY_PAGE_SET);
1599 gtk_widget_set_sensitive (widget: dialog->copies_spin,
1600 sensitive: caps & GTK_PRINT_CAPABILITY_COPIES);
1601 gtk_widget_set_sensitive (widget: dialog->collate_check,
1602 sensitive: can_collate &&
1603 (caps & GTK_PRINT_CAPABILITY_COLLATE));
1604 gtk_widget_set_sensitive (widget: dialog->reverse_check,
1605 sensitive: caps & GTK_PRINT_CAPABILITY_REVERSE);
1606 gtk_widget_set_sensitive (widget: dialog->scale_spin,
1607 sensitive: caps & GTK_PRINT_CAPABILITY_SCALE);
1608 gtk_widget_set_sensitive (GTK_WIDGET (dialog->pages_per_sheet),
1609 sensitive: caps & GTK_PRINT_CAPABILITY_NUMBER_UP);
1610
1611 button = gtk_dialog_get_widget_for_response (GTK_DIALOG (dialog), response_id: GTK_RESPONSE_APPLY);
1612 gtk_widget_set_visible (widget: button, visible: (caps & GTK_PRINT_CAPABILITY_PREVIEW) != 0);
1613
1614 update_collate_icon (NULL, dialog);
1615}
1616
1617static gboolean
1618page_setup_is_equal (GtkPageSetup *a,
1619 GtkPageSetup *b)
1620{
1621 return
1622 gtk_paper_size_is_equal (size1: gtk_page_setup_get_paper_size (setup: a),
1623 size2: gtk_page_setup_get_paper_size (setup: b)) &&
1624 gtk_page_setup_get_top_margin (setup: a, unit: GTK_UNIT_MM) == gtk_page_setup_get_top_margin (setup: b, unit: GTK_UNIT_MM) &&
1625 gtk_page_setup_get_bottom_margin (setup: a, unit: GTK_UNIT_MM) == gtk_page_setup_get_bottom_margin (setup: b, unit: GTK_UNIT_MM) &&
1626 gtk_page_setup_get_left_margin (setup: a, unit: GTK_UNIT_MM) == gtk_page_setup_get_left_margin (setup: b, unit: GTK_UNIT_MM) &&
1627 gtk_page_setup_get_right_margin (setup: a, unit: GTK_UNIT_MM) == gtk_page_setup_get_right_margin (setup: b, unit: GTK_UNIT_MM);
1628}
1629
1630static gboolean
1631page_setup_is_same_size (GtkPageSetup *a,
1632 GtkPageSetup *b)
1633{
1634 return gtk_paper_size_is_equal (size1: gtk_page_setup_get_paper_size (setup: a),
1635 size2: gtk_page_setup_get_paper_size (setup: b));
1636}
1637
1638static gboolean
1639set_paper_size (GtkPrintUnixDialog *dialog,
1640 GtkPageSetup *page_setup,
1641 gboolean size_only,
1642 gboolean add_item)
1643{
1644 GListModel *model;
1645 GtkPageSetup *list_page_setup;
1646 guint i;
1647
1648 if (!dialog->internal_page_setup_change)
1649 return TRUE;
1650
1651 if (page_setup == NULL)
1652 return FALSE;
1653
1654 model = gtk_drop_down_get_model (self: GTK_DROP_DOWN (ptr: dialog->paper_size_combo));
1655 for (i = 0; i < g_list_model_get_n_items (list: model); i++)
1656 {
1657 list_page_setup = g_list_model_get_item (list: model, position: i);
1658 if (list_page_setup == NULL)
1659 continue;
1660
1661 if ((size_only && page_setup_is_same_size (a: page_setup, b: list_page_setup)) ||
1662 (!size_only && page_setup_is_equal (a: page_setup, b: list_page_setup)))
1663 {
1664 gtk_drop_down_set_selected (self: GTK_DROP_DOWN (ptr: dialog->paper_size_combo), position: i);
1665 gtk_drop_down_set_selected (self: GTK_DROP_DOWN (ptr: dialog->orientation_combo),
1666 position: gtk_page_setup_get_orientation (setup: page_setup));
1667 g_object_unref (object: list_page_setup);
1668 return TRUE;
1669 }
1670
1671 g_object_unref (object: list_page_setup);
1672 }
1673
1674 if (add_item)
1675 {
1676 i = g_list_model_get_n_items (list: model);
1677 g_list_store_append (store: dialog->page_setup_list, item: page_setup);
1678 gtk_drop_down_set_selected (self: GTK_DROP_DOWN (ptr: dialog->paper_size_combo), position: i);
1679 gtk_drop_down_set_selected (self: GTK_DROP_DOWN (ptr: dialog->orientation_combo),
1680 position: gtk_page_setup_get_orientation (setup: page_setup));
1681 return TRUE;
1682 }
1683
1684 return FALSE;
1685}
1686
1687static void
1688fill_custom_paper_sizes (GtkPrintUnixDialog *dialog)
1689{
1690 g_list_store_remove_all (store: dialog->custom_paper_list);
1691 gtk_print_load_custom_papers (store: dialog->custom_paper_list);
1692}
1693
1694static void
1695fill_paper_sizes (GtkPrintUnixDialog *dialog,
1696 GtkPrinter *printer)
1697{
1698 GList *list, *l;
1699 GtkPageSetup *page_setup;
1700 GtkPaperSize *paper_size;
1701 int i;
1702
1703 g_list_store_remove_all (store: dialog->page_setup_list);
1704
1705 if (printer == NULL || (list = gtk_printer_list_papers (printer)) == NULL)
1706 {
1707 for (i = 0; i < G_N_ELEMENTS (common_paper_sizes); i++)
1708 {
1709 page_setup = gtk_page_setup_new ();
1710 paper_size = gtk_paper_size_new (name: common_paper_sizes[i]);
1711 gtk_page_setup_set_paper_size_and_default_margins (setup: page_setup, size: paper_size);
1712 gtk_paper_size_free (size: paper_size);
1713 g_list_store_append (store: dialog->page_setup_list, item: page_setup);
1714 g_object_unref (object: page_setup);
1715 }
1716 }
1717 else
1718 {
1719 for (l = list; l != NULL; l = l->next)
1720 {
1721 page_setup = l->data;
1722 g_list_store_append (store: dialog->page_setup_list, item: page_setup);
1723 g_object_unref (object: page_setup);
1724 }
1725 g_list_free (list);
1726 }
1727}
1728
1729static void
1730update_paper_sizes (GtkPrintUnixDialog *dialog)
1731{
1732 GtkPageSetup *current_page_setup = NULL;
1733 GtkPrinter *printer;
1734
1735 printer = gtk_print_unix_dialog_get_selected_printer (dialog);
1736
1737 fill_paper_sizes (dialog, printer);
1738 fill_custom_paper_sizes (dialog);
1739
1740 current_page_setup = gtk_page_setup_copy (other: gtk_print_unix_dialog_get_page_setup (dialog));
1741
1742 if (current_page_setup)
1743 {
1744 if (!set_paper_size (dialog, page_setup: current_page_setup, FALSE, FALSE))
1745 set_paper_size (dialog, page_setup: current_page_setup, TRUE, TRUE);
1746
1747 g_object_unref (object: current_page_setup);
1748 }
1749}
1750
1751static void
1752mark_conflicts (GtkPrintUnixDialog *dialog)
1753{
1754 GtkPrinter *printer;
1755 gboolean have_conflict;
1756
1757 have_conflict = FALSE;
1758
1759 printer = dialog->current_printer;
1760
1761 if (printer)
1762 {
1763 g_signal_handler_block (instance: dialog->options, handler_id: dialog->options_changed_handler);
1764
1765 gtk_printer_option_set_clear_conflicts (set: dialog->options);
1766 have_conflict = _gtk_printer_mark_conflicts (printer, options: dialog->options);
1767
1768 g_signal_handler_unblock (instance: dialog->options, handler_id: dialog->options_changed_handler);
1769 }
1770
1771 if (have_conflict)
1772 gtk_widget_show (widget: dialog->conflicts_widget);
1773 else
1774 gtk_widget_hide (widget: dialog->conflicts_widget);
1775}
1776
1777static gboolean
1778mark_conflicts_callback (gpointer data)
1779{
1780 GtkPrintUnixDialog *dialog = data;
1781
1782 dialog->mark_conflicts_id = 0;
1783
1784 mark_conflicts (dialog);
1785
1786 return FALSE;
1787}
1788
1789static void
1790unschedule_idle_mark_conflicts (GtkPrintUnixDialog *dialog)
1791{
1792 if (dialog->mark_conflicts_id != 0)
1793 {
1794 g_source_remove (tag: dialog->mark_conflicts_id);
1795 dialog->mark_conflicts_id = 0;
1796 }
1797}
1798
1799static void
1800schedule_idle_mark_conflicts (GtkPrintUnixDialog *dialog)
1801{
1802 if (dialog->mark_conflicts_id != 0)
1803 return;
1804
1805 dialog->mark_conflicts_id = g_idle_add (function: mark_conflicts_callback, data: dialog);
1806 gdk_source_set_static_name_by_id (tag: dialog->mark_conflicts_id, name: "[gtk] mark_conflicts_callback");
1807}
1808
1809static void
1810options_changed_cb (GtkPrintUnixDialog *dialog)
1811{
1812 schedule_idle_mark_conflicts (dialog);
1813
1814 g_free (mem: dialog->waiting_for_printer);
1815 dialog->waiting_for_printer = NULL;
1816}
1817
1818static void
1819clear_per_printer_ui (GtkPrintUnixDialog *dialog)
1820{
1821 GtkWidget *child;
1822
1823 if (dialog->finishing_table == NULL)
1824 return;
1825
1826 while ((child = gtk_widget_get_first_child (widget: dialog->finishing_table)))
1827 gtk_grid_remove (GTK_GRID (dialog->finishing_table), child);
1828 while ((child = gtk_widget_get_first_child (widget: dialog->image_quality_table)))
1829 gtk_grid_remove (GTK_GRID (dialog->image_quality_table), child);
1830 while ((child = gtk_widget_get_first_child (widget: dialog->color_table)))
1831 gtk_grid_remove (GTK_GRID (dialog->color_table), child);
1832 while ((child = gtk_widget_get_first_child (widget: dialog->advanced_vbox)))
1833 gtk_box_remove (GTK_BOX (dialog->advanced_vbox), child);
1834 while ((child = gtk_widget_get_first_child (widget: dialog->extension_point)))
1835 gtk_box_remove (GTK_BOX (dialog->extension_point), child);
1836}
1837
1838static void
1839printer_details_acquired (GtkPrinter *printer,
1840 gboolean success,
1841 GtkPrintUnixDialog *dialog)
1842{
1843 disconnect_printer_details_request (dialog, details_failed: !success);
1844
1845 if (success)
1846 selected_printer_changed (dialog);
1847}
1848
1849static void
1850selected_printer_changed (GtkPrintUnixDialog *dialog)
1851{
1852 GListModel *model = G_LIST_MODEL (ptr: gtk_column_view_get_model (GTK_COLUMN_VIEW (dialog->printer_list)));
1853 GtkPrinter *printer;
1854
1855 /* Whenever the user selects a printer we stop looking for
1856 * the printer specified in the initial settings
1857 */
1858 if (dialog->waiting_for_printer &&
1859 !dialog->internal_printer_change)
1860 {
1861 g_free (mem: dialog->waiting_for_printer);
1862 dialog->waiting_for_printer = NULL;
1863 }
1864
1865 disconnect_printer_details_request (dialog, FALSE);
1866
1867 printer = gtk_single_selection_get_selected_item (self: GTK_SINGLE_SELECTION (ptr: model));
1868
1869 /* sets GTK_RESPONSE_OK button sensitivity depending on whether the printer
1870 * accepts/rejects jobs
1871 */
1872 if (printer != NULL)
1873 {
1874 if (!gtk_printer_is_accepting_jobs (printer))
1875 gtk_dialog_set_response_sensitive (GTK_DIALOG (dialog), response_id: GTK_RESPONSE_OK, FALSE);
1876 else if (dialog->current_printer == printer && gtk_printer_has_details (printer))
1877 gtk_dialog_set_response_sensitive (GTK_DIALOG (dialog), response_id: GTK_RESPONSE_OK, TRUE);
1878 }
1879
1880 if (printer != NULL && !gtk_printer_has_details (printer))
1881 {
1882 gtk_dialog_set_response_sensitive (GTK_DIALOG (dialog), response_id: GTK_RESPONSE_OK, FALSE);
1883 dialog->request_details_tag = g_signal_connect (printer, "details-acquired",
1884 G_CALLBACK (printer_details_acquired), dialog);
1885
1886 dialog->request_details_printer = g_object_ref (printer);
1887 set_busy_cursor (dialog, TRUE);
1888 gtk_printer_set_state_message (printer, _("Getting printer information…"));
1889 gtk_printer_request_details (printer);
1890 return;
1891 }
1892
1893 if (printer == dialog->current_printer)
1894 return;
1895
1896 if (dialog->options)
1897 {
1898 g_clear_object (&dialog->options);
1899 clear_per_printer_ui (dialog);
1900 }
1901
1902 g_clear_object (&dialog->current_printer);
1903 dialog->printer_capabilities = 0;
1904
1905 if (printer != NULL && gtk_printer_is_accepting_jobs (printer))
1906 gtk_dialog_set_response_sensitive (GTK_DIALOG (dialog), response_id: GTK_RESPONSE_OK, TRUE);
1907 dialog->current_printer = g_object_ref (printer);
1908
1909 if (printer != NULL)
1910 {
1911 if (!dialog->page_setup_set)
1912 {
1913 /* if no explicit page setup has been set, use the printer default */
1914 GtkPageSetup *page_setup;
1915
1916 page_setup = gtk_printer_get_default_page_size (printer);
1917
1918 if (!page_setup)
1919 page_setup = gtk_page_setup_new ();
1920
1921 if (page_setup && dialog->page_setup)
1922 gtk_page_setup_set_orientation (setup: page_setup, orientation: gtk_page_setup_get_orientation (setup: dialog->page_setup));
1923
1924 g_clear_object (&dialog->page_setup);
1925 dialog->page_setup = page_setup; /* transfer ownership */
1926 }
1927
1928 dialog->printer_capabilities = gtk_printer_get_capabilities (printer);
1929 dialog->options = _gtk_printer_get_options (printer,
1930 settings: dialog->initial_settings,
1931 page_setup: dialog->page_setup,
1932 capabilities: dialog->manual_capabilities);
1933
1934 dialog->options_changed_handler =
1935 g_signal_connect_swapped (dialog->options, "changed", G_CALLBACK (options_changed_cb), dialog);
1936 schedule_idle_mark_conflicts (dialog);
1937 }
1938
1939 update_dialog_from_settings (dialog);
1940 update_dialog_from_capabilities (dialog);
1941
1942 dialog->internal_page_setup_change = TRUE;
1943 update_paper_sizes (dialog);
1944 dialog->internal_page_setup_change = FALSE;
1945
1946 g_object_notify (G_OBJECT (dialog), property_name: "selected-printer");
1947}
1948
1949static void
1950update_collate_icon (GtkToggleButton *toggle_button,
1951 GtkPrintUnixDialog *dialog)
1952{
1953 gtk_widget_queue_draw (widget: dialog->collate_image);
1954}
1955
1956static void
1957paint_page (GtkPrintUnixDialog *dialog,
1958 GtkWidget *widget,
1959 cairo_t *cr,
1960 int x,
1961 int y,
1962 const char *text,
1963 int text_x)
1964{
1965 GtkStyleContext *context;
1966 int width, height;
1967 int text_y;
1968 GdkRGBA color;
1969
1970 width = 20;
1971 height = 26;
1972 text_y = 21;
1973
1974 context = gtk_widget_get_style_context (widget);
1975 gtk_style_context_save_to_node (context, node: dialog->collate_paper_node);
1976
1977 gtk_render_background (context, cr, x, y, width, height);
1978 gtk_render_frame (context, cr, x, y, width, height);
1979
1980 gtk_style_context_get_color (context, color: &color);
1981 cairo_set_source_rgba (cr, red: color.red, green: color.green, blue: color.blue, alpha: color.alpha);
1982
1983 cairo_select_font_face (cr, family: "Sans",
1984 slant: CAIRO_FONT_SLANT_NORMAL,
1985 weight: CAIRO_FONT_WEIGHT_NORMAL);
1986 cairo_set_font_size (cr, size: 9);
1987 cairo_move_to (cr, x: x + text_x, y: y + text_y);
1988 cairo_show_text (cr, utf8: text);
1989
1990 gtk_style_context_restore (context);
1991}
1992
1993static void
1994draw_collate (GtkDrawingArea *da,
1995 cairo_t *cr,
1996 int width,
1997 int height,
1998 gpointer data)
1999{
2000 GtkPrintUnixDialog *dialog = GTK_PRINT_UNIX_DIALOG (data);
2001 GtkWidget *widget = GTK_WIDGET (da);
2002 gboolean collate, reverse, rtl;
2003 int copies;
2004 int text_x;
2005 int x, y, x1, x2, p1, p2;
2006
2007 collate = dialog_get_collate (dialog);
2008 reverse = dialog_get_reverse (dialog);
2009 copies = dialog_get_n_copies (dialog);
2010
2011 rtl = (gtk_widget_get_direction (widget) == GTK_TEXT_DIR_RTL);
2012
2013 x = (width - 30) / 2;
2014 y = (height - 36) / 2;
2015 if (rtl)
2016 {
2017 x1 = x;
2018 x2 = x - 36;
2019 p1 = 0;
2020 p2 = 10;
2021 text_x = 4;
2022 }
2023 else
2024 {
2025 x1 = x;
2026 x2 = x + 36;
2027 p1 = 10;
2028 p2 = 0;
2029 text_x = 11;
2030 }
2031
2032 if (copies == 1)
2033 {
2034 paint_page (dialog, widget, cr, x: x1 + p1, y, text: reverse ? "1" : "2", text_x);
2035 paint_page (dialog, widget, cr, x: x1 + p2, y: y + 10, text: reverse ? "2" : "1", text_x);
2036 }
2037 else
2038 {
2039 paint_page (dialog, widget, cr, x: x1 + p1, y, text: collate == reverse ? "1" : "2", text_x);
2040 paint_page (dialog, widget, cr, x: x1 + p2, y: y + 10, text: reverse ? "2" : "1", text_x);
2041
2042 paint_page (dialog, widget, cr, x: x2 + p1, y, text: reverse ? "1" : "2", text_x);
2043 paint_page (dialog, widget, cr, x: x2 + p2, y: y + 10, text: collate == reverse ? "2" : "1", text_x);
2044 }
2045}
2046
2047static gboolean
2048page_range_entry_focus_changed (GtkWidget *entry,
2049 GParamSpec *pspec,
2050 GtkPrintUnixDialog *dialog)
2051{
2052 if (gtk_widget_has_focus (widget: entry))
2053 gtk_check_button_set_active (GTK_CHECK_BUTTON (dialog->page_range_radio), TRUE);
2054
2055 return FALSE;
2056}
2057
2058static void
2059update_page_range_entry_sensitivity (GtkWidget *button,
2060 GtkPrintUnixDialog *dialog)
2061{
2062 gboolean active;
2063
2064 active = gtk_check_button_get_active (GTK_CHECK_BUTTON (button));
2065
2066 if (active)
2067 gtk_widget_grab_focus (widget: dialog->page_range_entry);
2068}
2069
2070static void
2071update_print_at_entry_sensitivity (GtkWidget *button,
2072 GtkPrintUnixDialog *dialog)
2073{
2074 gboolean active;
2075
2076 active = gtk_check_button_get_active (GTK_CHECK_BUTTON (button));
2077
2078 gtk_widget_set_sensitive (widget: dialog->print_at_entry, sensitive: active);
2079
2080 if (active)
2081 gtk_widget_grab_focus (widget: dialog->print_at_entry);
2082}
2083
2084static gboolean
2085is_range_separator (char c)
2086{
2087 return (c == ',' || c == ';' || c == ':');
2088}
2089
2090static GtkPageRange *
2091dialog_get_page_ranges (GtkPrintUnixDialog *dialog,
2092 int *n_ranges_out)
2093{
2094 int i, n_ranges;
2095 const char *text, *p;
2096 char *next;
2097 GtkPageRange *ranges;
2098 int start, end;
2099
2100 text = gtk_editable_get_text (GTK_EDITABLE (dialog->page_range_entry));
2101
2102 if (*text == 0)
2103 {
2104 *n_ranges_out = 0;
2105 return NULL;
2106 }
2107
2108 n_ranges = 1;
2109 p = text;
2110 while (*p)
2111 {
2112 if (is_range_separator (c: *p))
2113 n_ranges++;
2114 p++;
2115 }
2116
2117 ranges = g_new0 (GtkPageRange, n_ranges);
2118
2119 i = 0;
2120 p = text;
2121 while (*p)
2122 {
2123 while (isspace (*p)) p++;
2124
2125 if (*p == '-')
2126 {
2127 /* a half-open range like -2 */
2128 start = 1;
2129 }
2130 else
2131 {
2132 start = (int)strtol (nptr: p, endptr: &next, base: 10);
2133 if (start < 1)
2134 start = 1;
2135 p = next;
2136 }
2137
2138 end = start;
2139
2140 while (isspace (*p)) p++;
2141
2142 if (*p == '-')
2143 {
2144 p++;
2145 end = (int)strtol (nptr: p, endptr: &next, base: 10);
2146 if (next == p) /* a half-open range like 2- */
2147 end = 0;
2148 else if (end < start)
2149 end = start;
2150 }
2151
2152 ranges[i].start = start - 1;
2153 ranges[i].end = end - 1;
2154 i++;
2155
2156 /* Skip until end or separator */
2157 while (*p && !is_range_separator (c: *p))
2158 p++;
2159
2160 /* if not at end, skip separator */
2161 if (*p)
2162 p++;
2163 }
2164
2165 *n_ranges_out = i;
2166
2167 return ranges;
2168}
2169
2170static void
2171dialog_set_page_ranges (GtkPrintUnixDialog *dialog,
2172 GtkPageRange *ranges,
2173 int n_ranges)
2174{
2175 int i;
2176 GString *s = g_string_new (NULL);
2177
2178 for (i = 0; i < n_ranges; i++)
2179 {
2180 g_string_append_printf (string: s, format: "%d", ranges[i].start + 1);
2181 if (ranges[i].end > ranges[i].start)
2182 g_string_append_printf (string: s, format: "-%d", ranges[i].end + 1);
2183 else if (ranges[i].end == -1)
2184 g_string_append (string: s, val: "-");
2185
2186 if (i != n_ranges - 1)
2187 g_string_append (string: s, val: ",");
2188 }
2189
2190 gtk_editable_set_text (GTK_EDITABLE (dialog->page_range_entry), text: s->str);
2191
2192 g_string_free (string: s, TRUE);
2193}
2194
2195static GtkPrintPages
2196dialog_get_print_pages (GtkPrintUnixDialog *dialog)
2197{
2198 if (gtk_check_button_get_active (GTK_CHECK_BUTTON (dialog->all_pages_radio)))
2199 return GTK_PRINT_PAGES_ALL;
2200 else if (gtk_check_button_get_active (GTK_CHECK_BUTTON (dialog->current_page_radio)))
2201 return GTK_PRINT_PAGES_CURRENT;
2202 else if (gtk_check_button_get_active (GTK_CHECK_BUTTON (dialog->selection_radio)))
2203 return GTK_PRINT_PAGES_SELECTION;
2204 else
2205 return GTK_PRINT_PAGES_RANGES;
2206}
2207
2208static void
2209dialog_set_print_pages (GtkPrintUnixDialog *dialog,
2210 GtkPrintPages pages)
2211{
2212 if (pages == GTK_PRINT_PAGES_RANGES)
2213 gtk_check_button_set_active (GTK_CHECK_BUTTON (dialog->page_range_radio), TRUE);
2214 else if (pages == GTK_PRINT_PAGES_CURRENT)
2215 gtk_check_button_set_active (GTK_CHECK_BUTTON (dialog->current_page_radio), TRUE);
2216 else if (pages == GTK_PRINT_PAGES_SELECTION)
2217 gtk_check_button_set_active (GTK_CHECK_BUTTON (dialog->selection_radio), TRUE);
2218 else
2219 gtk_check_button_set_active (GTK_CHECK_BUTTON (dialog->all_pages_radio), TRUE);
2220}
2221
2222static double
2223dialog_get_scale (GtkPrintUnixDialog *dialog)
2224{
2225 if (gtk_widget_is_sensitive (widget: dialog->scale_spin))
2226 return gtk_spin_button_get_value (GTK_SPIN_BUTTON (dialog->scale_spin));
2227 else
2228 return 100.0;
2229}
2230
2231static void
2232dialog_set_scale (GtkPrintUnixDialog *dialog,
2233 double val)
2234{
2235 gtk_spin_button_set_value (GTK_SPIN_BUTTON (dialog->scale_spin), value: val);
2236}
2237
2238static GtkPageSet
2239dialog_get_page_set (GtkPrintUnixDialog *dialog)
2240{
2241 if (gtk_widget_is_sensitive (widget: dialog->page_set_combo))
2242 return (GtkPageSet)gtk_drop_down_get_selected (self: GTK_DROP_DOWN (ptr: dialog->page_set_combo));
2243 else
2244 return GTK_PAGE_SET_ALL;
2245}
2246
2247static void
2248dialog_set_page_set (GtkPrintUnixDialog *dialog,
2249 GtkPageSet val)
2250{
2251 gtk_drop_down_set_selected (self: GTK_DROP_DOWN (ptr: dialog->page_set_combo), position: (guint)val);
2252}
2253
2254static int
2255dialog_get_n_copies (GtkPrintUnixDialog *dialog)
2256{
2257 GtkAdjustment *adjustment;
2258 const char *text;
2259 char *endptr = NULL;
2260 int n_copies;
2261
2262 adjustment = gtk_spin_button_get_adjustment (GTK_SPIN_BUTTON (dialog->copies_spin));
2263
2264 text = gtk_editable_get_text (GTK_EDITABLE (dialog->copies_spin));
2265 n_copies = g_ascii_strtoull (nptr: text, endptr: &endptr, base: 0);
2266
2267 if (gtk_widget_is_sensitive (widget: dialog->copies_spin))
2268 {
2269 if (n_copies != 0 && endptr != text && (endptr != NULL && endptr[0] == '\0') &&
2270 n_copies >= gtk_adjustment_get_lower (adjustment) &&
2271 n_copies <= gtk_adjustment_get_upper (adjustment))
2272 {
2273 return n_copies;
2274 }
2275
2276 return gtk_spin_button_get_value_as_int (GTK_SPIN_BUTTON (dialog->copies_spin));
2277 }
2278
2279 return 1;
2280}
2281
2282static void
2283dialog_set_n_copies (GtkPrintUnixDialog *dialog,
2284 int n_copies)
2285{
2286 gtk_spin_button_set_value (GTK_SPIN_BUTTON (dialog->copies_spin), value: n_copies);
2287}
2288
2289static gboolean
2290dialog_get_collate (GtkPrintUnixDialog *dialog)
2291{
2292 if (gtk_widget_is_sensitive (widget: dialog->collate_check))
2293 return gtk_check_button_get_active (GTK_CHECK_BUTTON (dialog->collate_check));
2294 return FALSE;
2295}
2296
2297static void
2298dialog_set_collate (GtkPrintUnixDialog *dialog,
2299 gboolean collate)
2300{
2301 gtk_check_button_set_active (GTK_CHECK_BUTTON (dialog->collate_check), setting: collate);
2302}
2303
2304static gboolean
2305dialog_get_reverse (GtkPrintUnixDialog *dialog)
2306{
2307 if (gtk_widget_is_sensitive (widget: dialog->reverse_check))
2308 return gtk_check_button_get_active (GTK_CHECK_BUTTON (dialog->reverse_check));
2309 return FALSE;
2310}
2311
2312static void
2313dialog_set_reverse (GtkPrintUnixDialog *dialog,
2314 gboolean reverse)
2315{
2316 gtk_check_button_set_active (GTK_CHECK_BUTTON (dialog->reverse_check), setting: reverse);
2317}
2318
2319static int
2320dialog_get_pages_per_sheet (GtkPrintUnixDialog *dialog)
2321{
2322 const char *val;
2323 int num;
2324
2325 val = gtk_printer_option_widget_get_value (setting: dialog->pages_per_sheet);
2326
2327 num = 1;
2328
2329 if (val)
2330 {
2331 num = atoi(nptr: val);
2332 if (num < 1)
2333 num = 1;
2334 }
2335
2336 return num;
2337}
2338
2339static GtkNumberUpLayout
2340dialog_get_number_up_layout (GtkPrintUnixDialog *dialog)
2341{
2342 GtkPrintCapabilities caps;
2343 GtkNumberUpLayout layout;
2344 const char *val;
2345 GEnumClass *enum_class;
2346 GEnumValue *enum_value;
2347
2348 val = gtk_printer_option_widget_get_value (setting: dialog->number_up_layout);
2349
2350 caps = dialog->manual_capabilities | dialog->printer_capabilities;
2351
2352 if ((caps & GTK_PRINT_CAPABILITY_NUMBER_UP_LAYOUT) == 0)
2353 return GTK_NUMBER_UP_LAYOUT_LEFT_TO_RIGHT_TOP_TO_BOTTOM;
2354
2355 if (gtk_widget_get_direction (GTK_WIDGET (dialog)) == GTK_TEXT_DIR_LTR)
2356 layout = GTK_NUMBER_UP_LAYOUT_LEFT_TO_RIGHT_TOP_TO_BOTTOM;
2357 else
2358 layout = GTK_NUMBER_UP_LAYOUT_RIGHT_TO_LEFT_TOP_TO_BOTTOM;
2359
2360 if (val == NULL)
2361 return layout;
2362
2363 if (val[0] == '\0' && dialog->options)
2364 {
2365 GtkPrinterOption *option = gtk_printer_option_set_lookup (set: dialog->options, name: "gtk-n-up-layout");
2366 if (option)
2367 val = option->value;
2368 }
2369
2370 enum_class = g_type_class_ref (type: GTK_TYPE_NUMBER_UP_LAYOUT);
2371 enum_value = g_enum_get_value_by_nick (enum_class, nick: val);
2372 if (enum_value)
2373 layout = enum_value->value;
2374 g_type_class_unref (g_class: enum_class);
2375
2376 return layout;
2377}
2378
2379static void
2380draw_page (GtkDrawingArea *da,
2381 cairo_t *cr,
2382 int width,
2383 int height,
2384 gpointer data)
2385{
2386 GtkWidget *widget = GTK_WIDGET (da);
2387 GtkPrintUnixDialog *dialog = GTK_PRINT_UNIX_DIALOG (data);
2388 GtkStyleContext *context;
2389 double ratio;
2390 int w, h, tmp;
2391 int pages_x, pages_y, i, x, y, layout_w, layout_h;
2392 double page_width, page_height;
2393 GtkPageOrientation orientation;
2394 gboolean landscape;
2395 PangoLayout *layout;
2396 PangoFontDescription *font;
2397 char *text;
2398 GdkRGBA color;
2399 GtkNumberUpLayout number_up_layout;
2400 int start_x, end_x, start_y, end_y;
2401 int dx, dy;
2402 gboolean horizontal;
2403 GtkPageSetup *page_setup;
2404 double paper_width, paper_height;
2405 double pos_x, pos_y;
2406 int pages_per_sheet;
2407 gboolean ltr = TRUE;
2408
2409 orientation = gtk_page_setup_get_orientation (setup: dialog->page_setup);
2410 landscape =
2411 (orientation == GTK_PAGE_ORIENTATION_LANDSCAPE) ||
2412 (orientation == GTK_PAGE_ORIENTATION_REVERSE_LANDSCAPE);
2413
2414 number_up_layout = dialog_get_number_up_layout (dialog);
2415
2416 cairo_save (cr);
2417
2418 page_setup = gtk_print_unix_dialog_get_page_setup (dialog);
2419
2420 if (page_setup != NULL)
2421 {
2422 if (!landscape)
2423 {
2424 paper_width = gtk_page_setup_get_paper_width (setup: page_setup, unit: GTK_UNIT_MM);
2425 paper_height = gtk_page_setup_get_paper_height (setup: page_setup, unit: GTK_UNIT_MM);
2426 }
2427 else
2428 {
2429 paper_width = gtk_page_setup_get_paper_height (setup: page_setup, unit: GTK_UNIT_MM);
2430 paper_height = gtk_page_setup_get_paper_width (setup: page_setup, unit: GTK_UNIT_MM);
2431 }
2432
2433 if (paper_width < paper_height)
2434 {
2435 h = EXAMPLE_PAGE_AREA_SIZE - 3;
2436 w = (paper_height != 0) ? h * paper_width / paper_height : 0;
2437 }
2438 else
2439 {
2440 w = EXAMPLE_PAGE_AREA_SIZE - 3;
2441 h = (paper_width != 0) ? w * paper_height / paper_width : 0;
2442 }
2443
2444 if (paper_width == 0)
2445 w = 0;
2446
2447 if (paper_height == 0)
2448 h = 0;
2449 }
2450 else
2451 {
2452 ratio = G_SQRT2;
2453 w = (EXAMPLE_PAGE_AREA_SIZE - 3) / ratio;
2454 h = EXAMPLE_PAGE_AREA_SIZE - 3;
2455 }
2456
2457 pages_per_sheet = dialog_get_pages_per_sheet (dialog);
2458 switch (pages_per_sheet)
2459 {
2460 default:
2461 case 1:
2462 pages_x = 1; pages_y = 1;
2463 break;
2464 case 2:
2465 landscape = !landscape;
2466 pages_x = 1; pages_y = 2;
2467 break;
2468 case 4:
2469 pages_x = 2; pages_y = 2;
2470 break;
2471 case 6:
2472 landscape = !landscape;
2473 pages_x = 2; pages_y = 3;
2474 break;
2475 case 9:
2476 pages_x = 3; pages_y = 3;
2477 break;
2478 case 16:
2479 pages_x = 4; pages_y = 4;
2480 break;
2481 }
2482
2483 if (landscape)
2484 {
2485 tmp = w;
2486 w = h;
2487 h = tmp;
2488
2489 tmp = pages_x;
2490 pages_x = pages_y;
2491 pages_y = tmp;
2492 }
2493
2494 context = gtk_widget_get_style_context (widget);
2495 gtk_style_context_save_to_node (context, node: dialog->page_layout_paper_node);
2496 gtk_style_context_get_color (context, color: &color);
2497
2498 pos_x = (width - w) / 2;
2499 pos_y = (height - h) / 2 - 10;
2500 cairo_translate (cr, tx: pos_x, ty: pos_y);
2501
2502 gtk_render_background (context, cr, x: 1, y: 1, width: w, height: h);
2503 gtk_render_frame (context, cr, x: 1, y: 1, width: w, height: h);
2504
2505 cairo_set_line_width (cr, width: 1.0);
2506
2507 i = 1;
2508
2509 page_width = (double)w / pages_x;
2510 page_height = (double)h / pages_y;
2511
2512 layout = pango_cairo_create_layout (cr);
2513
2514 font = pango_font_description_new ();
2515 pango_font_description_set_family (desc: font, family: "sans");
2516
2517 if (page_height > 0)
2518 pango_font_description_set_absolute_size (desc: font, size: page_height * 0.4 * PANGO_SCALE);
2519 else
2520 pango_font_description_set_absolute_size (desc: font, size: 1);
2521
2522 pango_layout_set_font_description (layout, desc: font);
2523 pango_font_description_free (desc: font);
2524
2525 pango_layout_set_width (layout, width: page_width * PANGO_SCALE);
2526 pango_layout_set_alignment (layout, alignment: PANGO_ALIGN_CENTER);
2527
2528 switch (number_up_layout)
2529 {
2530 default:
2531 case GTK_NUMBER_UP_LAYOUT_LEFT_TO_RIGHT_TOP_TO_BOTTOM:
2532 start_x = 0;
2533 end_x = pages_x - 1;
2534 start_y = 0;
2535 end_y = pages_y - 1;
2536 dx = 1;
2537 dy = 1;
2538 horizontal = TRUE;
2539 break;
2540 case GTK_NUMBER_UP_LAYOUT_LEFT_TO_RIGHT_BOTTOM_TO_TOP:
2541 start_x = 0;
2542 end_x = pages_x - 1;
2543 start_y = pages_y - 1;
2544 end_y = 0;
2545 dx = 1;
2546 dy = - 1;
2547 horizontal = TRUE;
2548 break;
2549 case GTK_NUMBER_UP_LAYOUT_RIGHT_TO_LEFT_TOP_TO_BOTTOM:
2550 start_x = pages_x - 1;
2551 end_x = 0;
2552 start_y = 0;
2553 end_y = pages_y - 1;
2554 dx = - 1;
2555 dy = 1;
2556 horizontal = TRUE;
2557 break;
2558 case GTK_NUMBER_UP_LAYOUT_RIGHT_TO_LEFT_BOTTOM_TO_TOP:
2559 start_x = pages_x - 1;
2560 end_x = 0;
2561 start_y = pages_y - 1;
2562 end_y = 0;
2563 dx = - 1;
2564 dy = - 1;
2565 horizontal = TRUE;
2566 break;
2567 case GTK_NUMBER_UP_LAYOUT_TOP_TO_BOTTOM_LEFT_TO_RIGHT:
2568 start_x = 0;
2569 end_x = pages_x - 1;
2570 start_y = 0;
2571 end_y = pages_y - 1;
2572 dx = 1;
2573 dy = 1;
2574 horizontal = FALSE;
2575 break;
2576 case GTK_NUMBER_UP_LAYOUT_TOP_TO_BOTTOM_RIGHT_TO_LEFT:
2577 start_x = pages_x - 1;
2578 end_x = 0;
2579 start_y = 0;
2580 end_y = pages_y - 1;
2581 dx = - 1;
2582 dy = 1;
2583 horizontal = FALSE;
2584 break;
2585 case GTK_NUMBER_UP_LAYOUT_BOTTOM_TO_TOP_LEFT_TO_RIGHT:
2586 start_x = 0;
2587 end_x = pages_x - 1;
2588 start_y = pages_y - 1;
2589 end_y = 0;
2590 dx = 1;
2591 dy = - 1;
2592 horizontal = FALSE;
2593 break;
2594 case GTK_NUMBER_UP_LAYOUT_BOTTOM_TO_TOP_RIGHT_TO_LEFT:
2595 start_x = pages_x - 1;
2596 end_x = 0;
2597 start_y = pages_y - 1;
2598 end_y = 0;
2599 dx = - 1;
2600 dy = - 1;
2601 horizontal = FALSE;
2602 break;
2603 }
2604
2605 cairo_set_source_rgba (cr, red: color.red, green: color.green, blue: color.blue, alpha: color.alpha);
2606 if (horizontal)
2607 for (y = start_y; y != end_y + dy; y += dy)
2608 {
2609 for (x = start_x; x != end_x + dx; x += dx)
2610 {
2611 text = g_strdup_printf (format: "%d", i++);
2612 pango_layout_set_text (layout, text, length: -1);
2613 g_free (mem: text);
2614 pango_layout_get_size (layout, width: &layout_w, height: &layout_h);
2615 cairo_save (cr);
2616 cairo_translate (cr,
2617 tx: x * page_width,
2618 ty: y * page_height + (page_height - layout_h / 1024.0) / 2);
2619
2620 pango_cairo_show_layout (cr, layout);
2621 cairo_restore (cr);
2622 }
2623 }
2624 else
2625 for (x = start_x; x != end_x + dx; x += dx)
2626 {
2627 for (y = start_y; y != end_y + dy; y += dy)
2628 {
2629 text = g_strdup_printf (format: "%d", i++);
2630 pango_layout_set_text (layout, text, length: -1);
2631 g_free (mem: text);
2632 pango_layout_get_size (layout, width: &layout_w, height: &layout_h);
2633 cairo_save (cr);
2634 cairo_translate (cr,
2635 tx: x * page_width,
2636 ty: y * page_height + (page_height - layout_h / 1024.0) / 2);
2637
2638 pango_cairo_show_layout (cr, layout);
2639 cairo_restore (cr);
2640 }
2641 }
2642
2643 g_object_unref (object: layout);
2644
2645 gtk_style_context_restore (context);
2646
2647 gtk_style_context_get_color (context, color: &color);
2648
2649 if (page_setup != NULL)
2650 {
2651 PangoContext *pango_c = NULL;
2652 PangoFontDescription *pango_f = NULL;
2653 int font_size = 12 * PANGO_SCALE;
2654
2655 pos_x += 1;
2656 pos_y += 1;
2657
2658 if (pages_per_sheet == 2 || pages_per_sheet == 6)
2659 {
2660 paper_width = gtk_page_setup_get_paper_height (setup: page_setup, unit: _gtk_print_get_default_user_units ());
2661 paper_height = gtk_page_setup_get_paper_width (setup: page_setup, unit: _gtk_print_get_default_user_units ());
2662 }
2663 else
2664 {
2665 paper_width = gtk_page_setup_get_paper_width (setup: page_setup, unit: _gtk_print_get_default_user_units ());
2666 paper_height = gtk_page_setup_get_paper_height (setup: page_setup, unit: _gtk_print_get_default_user_units ());
2667 }
2668
2669 cairo_restore (cr);
2670 cairo_save (cr);
2671
2672 layout = pango_cairo_create_layout (cr);
2673
2674 font = pango_font_description_new ();
2675 pango_font_description_set_family (desc: font, family: "sans");
2676
2677 pango_c = gtk_widget_get_pango_context (widget);
2678 if (pango_c != NULL)
2679 {
2680 pango_f = pango_context_get_font_description (context: pango_c);
2681 if (pango_f != NULL)
2682 font_size = pango_font_description_get_size (desc: pango_f);
2683 }
2684
2685 pango_font_description_set_size (desc: font, size: font_size);
2686 pango_layout_set_font_description (layout, desc: font);
2687 pango_font_description_free (desc: font);
2688
2689 pango_layout_set_width (layout, width: -1);
2690 pango_layout_set_alignment (layout, alignment: PANGO_ALIGN_CENTER);
2691
2692 if (_gtk_print_get_default_user_units () == GTK_UNIT_MM)
2693 text = g_strdup_printf (format: "%.1f mm", paper_height);
2694 else
2695 text = g_strdup_printf (format: "%.2f inch", paper_height);
2696
2697 pango_layout_set_text (layout, text, length: -1);
2698 g_free (mem: text);
2699 pango_layout_get_size (layout, width: &layout_w, height: &layout_h);
2700
2701 ltr = gtk_widget_get_direction (GTK_WIDGET (dialog)) == GTK_TEXT_DIR_LTR;
2702
2703 if (ltr)
2704 cairo_translate (cr, tx: pos_x - layout_w / PANGO_SCALE - 2 * RULER_DISTANCE,
2705 ty: (height - layout_h / PANGO_SCALE) / 2);
2706 else
2707 cairo_translate (cr, tx: pos_x + w + 2 * RULER_DISTANCE,
2708 ty: (height - layout_h / PANGO_SCALE) / 2);
2709
2710 gdk_cairo_set_source_rgba (cr, rgba: &color);
2711 pango_cairo_show_layout (cr, layout);
2712
2713 cairo_restore (cr);
2714 cairo_save (cr);
2715
2716 if (_gtk_print_get_default_user_units () == GTK_UNIT_MM)
2717 text = g_strdup_printf (format: "%.1f mm", paper_width);
2718 else
2719 text = g_strdup_printf (format: "%.2f inch", paper_width);
2720
2721 pango_layout_set_text (layout, text, length: -1);
2722 g_free (mem: text);
2723 pango_layout_get_size (layout, width: &layout_w, height: &layout_h);
2724
2725 cairo_translate (cr, tx: (width - layout_w / PANGO_SCALE) / 2,
2726 ty: pos_y + h + 2 * RULER_DISTANCE);
2727
2728 gdk_cairo_set_source_rgba (cr, rgba: &color);
2729 pango_cairo_show_layout (cr, layout);
2730
2731 g_object_unref (object: layout);
2732
2733 cairo_restore (cr);
2734
2735 cairo_set_line_width (cr, width: 1);
2736
2737 gdk_cairo_set_source_rgba (cr, rgba: &color);
2738
2739 if (ltr)
2740 {
2741 cairo_move_to (cr, x: pos_x - RULER_DISTANCE, y: pos_y);
2742 cairo_line_to (cr, x: pos_x - RULER_DISTANCE, y: pos_y + h);
2743 cairo_stroke (cr);
2744
2745 cairo_move_to (cr, x: pos_x - RULER_DISTANCE - RULER_RADIUS, y: pos_y - 0.5);
2746 cairo_line_to (cr, x: pos_x - RULER_DISTANCE + RULER_RADIUS, y: pos_y - 0.5);
2747 cairo_stroke (cr);
2748
2749 cairo_move_to (cr, x: pos_x - RULER_DISTANCE - RULER_RADIUS, y: pos_y + h + 0.5);
2750 cairo_line_to (cr, x: pos_x - RULER_DISTANCE + RULER_RADIUS, y: pos_y + h + 0.5);
2751 cairo_stroke (cr);
2752 }
2753 else
2754 {
2755 cairo_move_to (cr, x: pos_x + w + RULER_DISTANCE, y: pos_y);
2756 cairo_line_to (cr, x: pos_x + w + RULER_DISTANCE, y: pos_y + h);
2757 cairo_stroke (cr);
2758
2759 cairo_move_to (cr, x: pos_x + w + RULER_DISTANCE - RULER_RADIUS, y: pos_y - 0.5);
2760 cairo_line_to (cr, x: pos_x + w + RULER_DISTANCE + RULER_RADIUS, y: pos_y - 0.5);
2761 cairo_stroke (cr);
2762
2763 cairo_move_to (cr, x: pos_x + w + RULER_DISTANCE - RULER_RADIUS, y: pos_y + h + 0.5);
2764 cairo_line_to (cr, x: pos_x + w + RULER_DISTANCE + RULER_RADIUS, y: pos_y + h + 0.5);
2765 cairo_stroke (cr);
2766 }
2767
2768 cairo_move_to (cr, x: pos_x, y: pos_y + h + RULER_DISTANCE);
2769 cairo_line_to (cr, x: pos_x + w, y: pos_y + h + RULER_DISTANCE);
2770 cairo_stroke (cr);
2771
2772 cairo_move_to (cr, x: pos_x - 0.5, y: pos_y + h + RULER_DISTANCE - RULER_RADIUS);
2773 cairo_line_to (cr, x: pos_x - 0.5, y: pos_y + h + RULER_DISTANCE + RULER_RADIUS);
2774 cairo_stroke (cr);
2775
2776 cairo_move_to (cr, x: pos_x + w + 0.5, y: pos_y + h + RULER_DISTANCE - RULER_RADIUS);
2777 cairo_line_to (cr, x: pos_x + w + 0.5, y: pos_y + h + RULER_DISTANCE + RULER_RADIUS);
2778 cairo_stroke (cr);
2779 }
2780}
2781
2782static void
2783redraw_page_layout_preview (GtkPrintUnixDialog *dialog)
2784{
2785 if (dialog->page_layout_preview)
2786 gtk_widget_queue_draw (widget: dialog->page_layout_preview);
2787}
2788
2789static void
2790update_number_up_layout (GtkPrintUnixDialog *dialog)
2791{
2792 GtkPrintCapabilities caps;
2793 GtkPrinterOptionSet *set;
2794 GtkNumberUpLayout layout;
2795 GtkPrinterOption *option;
2796 GtkPrinterOption *old_option;
2797 GtkPageOrientation page_orientation;
2798
2799 set = dialog->options;
2800
2801 caps = dialog->manual_capabilities | dialog->printer_capabilities;
2802
2803 if (caps & GTK_PRINT_CAPABILITY_NUMBER_UP_LAYOUT)
2804 {
2805 if (dialog->number_up_layout_n_option == NULL)
2806 {
2807 dialog->number_up_layout_n_option = gtk_printer_option_set_lookup (set, name: "gtk-n-up-layout");
2808 if (dialog->number_up_layout_n_option == NULL)
2809 {
2810 const char *n_up_layout[] = { "lrtb", "lrbt", "rltb", "rlbt", "tblr", "tbrl", "btlr", "btrl" };
2811 /* Translators: These strings name the possible arrangements of
2812 * multiple pages on a sheet when printing (same as in gtkprintbackendcups.c)
2813 */
2814 const char *n_up_layout_display[] = { N_("Left to right, top to bottom"), N_("Left to right, bottom to top"),
2815 N_("Right to left, top to bottom"), N_("Right to left, bottom to top"),
2816 N_("Top to bottom, left to right"), N_("Top to bottom, right to left"),
2817 N_("Bottom to top, left to right"), N_("Bottom to top, right to left") };
2818 int i;
2819
2820 dialog->number_up_layout_n_option = gtk_printer_option_new (name: "gtk-n-up-layout",
2821 _("Page Ordering"),
2822 type: GTK_PRINTER_OPTION_TYPE_PICKONE);
2823 gtk_printer_option_allocate_choices (option: dialog->number_up_layout_n_option, num: 8);
2824
2825 for (i = 0; i < G_N_ELEMENTS (n_up_layout_display); i++)
2826 {
2827 dialog->number_up_layout_n_option->choices[i] = g_strdup (str: n_up_layout[i]);
2828 dialog->number_up_layout_n_option->choices_display[i] = g_strdup (_(n_up_layout_display[i]));
2829 }
2830 }
2831 g_object_ref (dialog->number_up_layout_n_option);
2832
2833 dialog->number_up_layout_2_option = gtk_printer_option_new (name: "gtk-n-up-layout",
2834 _("Page Ordering"),
2835 type: GTK_PRINTER_OPTION_TYPE_PICKONE);
2836 gtk_printer_option_allocate_choices (option: dialog->number_up_layout_2_option, num: 2);
2837 }
2838
2839 page_orientation = gtk_page_setup_get_orientation (setup: dialog->page_setup);
2840 if (page_orientation == GTK_PAGE_ORIENTATION_PORTRAIT ||
2841 page_orientation == GTK_PAGE_ORIENTATION_REVERSE_PORTRAIT)
2842 {
2843 if (! (dialog->number_up_layout_2_option->choices[0] == dialog->number_up_layout_n_option->choices[0] &&
2844 dialog->number_up_layout_2_option->choices[1] == dialog->number_up_layout_n_option->choices[2]))
2845 {
2846 g_free (mem: dialog->number_up_layout_2_option->choices_display[0]);
2847 g_free (mem: dialog->number_up_layout_2_option->choices_display[1]);
2848 dialog->number_up_layout_2_option->choices[0] = dialog->number_up_layout_n_option->choices[0];
2849 dialog->number_up_layout_2_option->choices[1] = dialog->number_up_layout_n_option->choices[2];
2850 dialog->number_up_layout_2_option->choices_display[0] = g_strdup ( _("Left to right"));
2851 dialog->number_up_layout_2_option->choices_display[1] = g_strdup ( _("Right to left"));
2852 }
2853 }
2854 else
2855 {
2856 if (! (dialog->number_up_layout_2_option->choices[0] == dialog->number_up_layout_n_option->choices[0] &&
2857 dialog->number_up_layout_2_option->choices[1] == dialog->number_up_layout_n_option->choices[1]))
2858 {
2859 g_free (mem: dialog->number_up_layout_2_option->choices_display[0]);
2860 g_free (mem: dialog->number_up_layout_2_option->choices_display[1]);
2861 dialog->number_up_layout_2_option->choices[0] = dialog->number_up_layout_n_option->choices[0];
2862 dialog->number_up_layout_2_option->choices[1] = dialog->number_up_layout_n_option->choices[1];
2863 dialog->number_up_layout_2_option->choices_display[0] = g_strdup ( _("Top to bottom"));
2864 dialog->number_up_layout_2_option->choices_display[1] = g_strdup ( _("Bottom to top"));
2865 }
2866 }
2867
2868 layout = dialog_get_number_up_layout (dialog);
2869
2870 old_option = gtk_printer_option_set_lookup (set, name: "gtk-n-up-layout");
2871 if (old_option != NULL)
2872 gtk_printer_option_set_remove (set, option: old_option);
2873
2874 if (dialog_get_pages_per_sheet (dialog) != 1)
2875 {
2876 GEnumClass *enum_class;
2877 GEnumValue *enum_value;
2878 enum_class = g_type_class_ref (type: GTK_TYPE_NUMBER_UP_LAYOUT);
2879
2880 if (dialog_get_pages_per_sheet (dialog) == 2)
2881 {
2882 option = dialog->number_up_layout_2_option;
2883
2884 switch (layout)
2885 {
2886 case GTK_NUMBER_UP_LAYOUT_LEFT_TO_RIGHT_TOP_TO_BOTTOM:
2887 case GTK_NUMBER_UP_LAYOUT_TOP_TO_BOTTOM_LEFT_TO_RIGHT:
2888 enum_value = g_enum_get_value (enum_class, value: GTK_NUMBER_UP_LAYOUT_LEFT_TO_RIGHT_TOP_TO_BOTTOM);
2889 break;
2890
2891 case GTK_NUMBER_UP_LAYOUT_LEFT_TO_RIGHT_BOTTOM_TO_TOP:
2892 case GTK_NUMBER_UP_LAYOUT_BOTTOM_TO_TOP_LEFT_TO_RIGHT:
2893 enum_value = g_enum_get_value (enum_class, value: GTK_NUMBER_UP_LAYOUT_LEFT_TO_RIGHT_BOTTOM_TO_TOP);
2894 break;
2895
2896 case GTK_NUMBER_UP_LAYOUT_RIGHT_TO_LEFT_TOP_TO_BOTTOM:
2897 case GTK_NUMBER_UP_LAYOUT_TOP_TO_BOTTOM_RIGHT_TO_LEFT:
2898 enum_value = g_enum_get_value (enum_class, value: GTK_NUMBER_UP_LAYOUT_RIGHT_TO_LEFT_TOP_TO_BOTTOM);
2899 break;
2900
2901 case GTK_NUMBER_UP_LAYOUT_RIGHT_TO_LEFT_BOTTOM_TO_TOP:
2902 case GTK_NUMBER_UP_LAYOUT_BOTTOM_TO_TOP_RIGHT_TO_LEFT:
2903 enum_value = g_enum_get_value (enum_class, value: GTK_NUMBER_UP_LAYOUT_RIGHT_TO_LEFT_BOTTOM_TO_TOP);
2904 break;
2905
2906 default:
2907 g_assert_not_reached();
2908 enum_value = NULL;
2909 }
2910 }
2911 else
2912 {
2913 option = dialog->number_up_layout_n_option;
2914
2915 enum_value = g_enum_get_value (enum_class, value: layout);
2916 }
2917
2918 g_assert (enum_value != NULL);
2919 gtk_printer_option_set (option, value: enum_value->value_nick);
2920 g_type_class_unref (g_class: enum_class);
2921
2922 gtk_printer_option_set_add (set, option);
2923 }
2924 }
2925
2926 setup_option (dialog, option_name: "gtk-n-up-layout", widget: dialog->number_up_layout);
2927
2928 if (dialog->number_up_layout != NULL)
2929 gtk_widget_set_sensitive (GTK_WIDGET (dialog->number_up_layout),
2930 sensitive: (caps & GTK_PRINT_CAPABILITY_NUMBER_UP_LAYOUT) &&
2931 (dialog_get_pages_per_sheet (dialog) > 1));
2932}
2933
2934static void
2935custom_paper_dialog_response_cb (GtkDialog *custom_paper_dialog,
2936 int response_id,
2937 gpointer user_data)
2938{
2939 GtkPrintUnixDialog *dialog = GTK_PRINT_UNIX_DIALOG (user_data);
2940
2941 dialog->internal_page_setup_change = TRUE;
2942 gtk_print_load_custom_papers (store: dialog->custom_paper_list);
2943 update_paper_sizes (dialog);
2944 dialog->internal_page_setup_change = FALSE;
2945
2946 if (dialog->page_setup_set)
2947 {
2948 GListModel *model;
2949 guint n, i;
2950
2951 model = G_LIST_MODEL (ptr: dialog->custom_paper_list);
2952 n = g_list_model_get_n_items (list: model);
2953 for (i = 0; i < n; i++)
2954 {
2955 GtkPageSetup *page_setup = g_list_model_get_item (list: model, position: i);
2956
2957 if (g_strcmp0 (str1: gtk_paper_size_get_display_name (size: gtk_page_setup_get_paper_size (setup: page_setup)),
2958 str2: gtk_paper_size_get_display_name (size: gtk_page_setup_get_paper_size (setup: dialog->page_setup))) == 0)
2959 gtk_print_unix_dialog_set_page_setup (dialog, page_setup);
2960
2961 g_clear_object (&page_setup);
2962 }
2963 }
2964
2965 gtk_window_destroy (GTK_WINDOW (custom_paper_dialog));
2966}
2967
2968static void
2969orientation_changed (GObject *object,
2970 GParamSpec *pspec,
2971 GtkPrintUnixDialog *dialog)
2972{
2973 GtkPageOrientation orientation;
2974 GtkPageSetup *page_setup;
2975
2976 if (dialog->internal_page_setup_change)
2977 return;
2978
2979 orientation = (GtkPageOrientation) gtk_drop_down_get_selected (self: GTK_DROP_DOWN (ptr: dialog->orientation_combo));
2980
2981 if (dialog->page_setup)
2982 {
2983 page_setup = gtk_page_setup_copy (other: dialog->page_setup);
2984 if (page_setup)
2985 gtk_page_setup_set_orientation (setup: page_setup, orientation);
2986
2987 gtk_print_unix_dialog_set_page_setup (dialog, page_setup);
2988 }
2989
2990 redraw_page_layout_preview (dialog);
2991}
2992
2993static void
2994paper_size_changed (GtkDropDown *combo_box,
2995 GParamSpec *pspec,
2996 GtkPrintUnixDialog *dialog)
2997{
2998 GtkPageSetup *page_setup, *last_page_setup;
2999 GtkPageOrientation orientation;
3000 guint selected;
3001
3002 if (dialog->internal_page_setup_change)
3003 return;
3004
3005 selected = gtk_drop_down_get_selected (self: GTK_DROP_DOWN (ptr: combo_box));
3006 if (selected != GTK_INVALID_LIST_POSITION)
3007 {
3008 GListModel *papers, *model;
3009
3010 papers = gtk_drop_down_get_model (self: GTK_DROP_DOWN (ptr: dialog->paper_size_combo));
3011 page_setup = g_list_model_get_item (list: papers, position: selected);
3012 model = gtk_flatten_list_model_get_model_for_item (self: GTK_FLATTEN_LIST_MODEL (ptr: papers), position: selected);
3013
3014 if (model == G_LIST_MODEL (ptr: dialog->manage_papers_list))
3015 {
3016 GtkWidget *custom_paper_dialog;
3017
3018 /* Change from "manage" menu item to last value */
3019 if (dialog->page_setup)
3020 last_page_setup = g_object_ref (dialog->page_setup);
3021 else
3022 last_page_setup = gtk_page_setup_new (); /* "good" default */
3023
3024 if (!set_paper_size (dialog, page_setup: last_page_setup, FALSE, FALSE))
3025 set_paper_size (dialog, page_setup: last_page_setup, TRUE, TRUE);
3026 g_object_unref (object: last_page_setup);
3027
3028 /* And show the custom paper dialog */
3029 custom_paper_dialog = _gtk_custom_paper_unix_dialog_new (GTK_WINDOW (dialog), _("Manage Custom Sizes"));
3030 g_signal_connect (custom_paper_dialog, "response", G_CALLBACK (custom_paper_dialog_response_cb), dialog);
3031 gtk_window_present (GTK_WINDOW (custom_paper_dialog));
3032
3033 g_object_unref (object: page_setup);
3034
3035 return;
3036 }
3037
3038 if (dialog->page_setup)
3039 orientation = gtk_page_setup_get_orientation (setup: dialog->page_setup);
3040 else
3041 orientation = GTK_PAGE_ORIENTATION_PORTRAIT;
3042
3043 gtk_page_setup_set_orientation (setup: page_setup, orientation);
3044 gtk_print_unix_dialog_set_page_setup (dialog, page_setup);
3045
3046 g_object_unref (object: page_setup);
3047 }
3048
3049 redraw_page_layout_preview (dialog);
3050}
3051
3052/**
3053 * gtk_print_unix_dialog_new:
3054 * @title: (nullable): Title of the dialog
3055 * @parent: (nullable): Transient parent of the dialog
3056 *
3057 * Creates a new `GtkPrintUnixDialog`.
3058 *
3059 * Returns: a new `GtkPrintUnixDialog`
3060 */
3061GtkWidget *
3062gtk_print_unix_dialog_new (const char *title,
3063 GtkWindow *parent)
3064{
3065 GtkWidget *result;
3066
3067 result = g_object_new (GTK_TYPE_PRINT_UNIX_DIALOG,
3068 first_property_name: "transient-for", parent,
3069 "title", title ? title : _("Print"),
3070 NULL);
3071
3072 return result;
3073}
3074
3075/**
3076 * gtk_print_unix_dialog_get_selected_printer: (attributes org.gtk.Method.get_property=selected-printer)
3077 * @dialog: a `GtkPrintUnixDialog`
3078 *
3079 * Gets the currently selected printer.
3080 *
3081 * Returns: (transfer none) (nullable): the currently selected printer
3082 */
3083GtkPrinter *
3084gtk_print_unix_dialog_get_selected_printer (GtkPrintUnixDialog *dialog)
3085{
3086 g_return_val_if_fail (GTK_IS_PRINT_UNIX_DIALOG (dialog), NULL);
3087
3088 return dialog->current_printer;
3089}
3090
3091/**
3092 * gtk_print_unix_dialog_set_page_setup: (attributes org.gtk.Method.set_property=page-setup)
3093 * @dialog: a `GtkPrintUnixDialog`
3094 * @page_setup: a `GtkPageSetup`
3095 *
3096 * Sets the page setup of the `GtkPrintUnixDialog`.
3097 */
3098void
3099gtk_print_unix_dialog_set_page_setup (GtkPrintUnixDialog *dialog,
3100 GtkPageSetup *page_setup)
3101{
3102 g_return_if_fail (GTK_IS_PRINT_UNIX_DIALOG (dialog));
3103 g_return_if_fail (GTK_IS_PAGE_SETUP (page_setup));
3104
3105 if (dialog->page_setup != page_setup)
3106 {
3107 g_clear_object (&dialog->page_setup);
3108 dialog->page_setup = g_object_ref (page_setup);
3109
3110 dialog->page_setup_set = TRUE;
3111
3112 g_object_notify (G_OBJECT (dialog), property_name: "page-setup");
3113 }
3114}
3115
3116/**
3117 * gtk_print_unix_dialog_get_page_setup: (attributes org.gtk.Method.get_property=page-setup)
3118 * @dialog: a `GtkPrintUnixDialog`
3119 *
3120 * Gets the page setup that is used by the `GtkPrintUnixDialog`.
3121 *
3122 * Returns: (transfer none): the page setup of @dialog.
3123 */
3124GtkPageSetup *
3125gtk_print_unix_dialog_get_page_setup (GtkPrintUnixDialog *dialog)
3126{
3127 g_return_val_if_fail (GTK_IS_PRINT_UNIX_DIALOG (dialog), NULL);
3128
3129 return dialog->page_setup;
3130}
3131
3132/**
3133 * gtk_print_unix_dialog_get_page_setup_set:
3134 * @dialog: a `GtkPrintUnixDialog`
3135 *
3136 * Gets whether a page setup was set by the user.
3137 *
3138 * Returns: whether a page setup was set by user.
3139 */
3140gboolean
3141gtk_print_unix_dialog_get_page_setup_set (GtkPrintUnixDialog *dialog)
3142{
3143 g_return_val_if_fail (GTK_IS_PRINT_UNIX_DIALOG (dialog), FALSE);
3144
3145 return dialog->page_setup_set;
3146}
3147
3148/**
3149 * gtk_print_unix_dialog_set_current_page: (attributes org.gtk.Method.set_property=current-page)
3150 * @dialog: a `GtkPrintUnixDialog`
3151 * @current_page: the current page number.
3152 *
3153 * Sets the current page number.
3154 *
3155 * If @current_page is not -1, this enables the current page choice
3156 * for the range of pages to print.
3157 */
3158void
3159gtk_print_unix_dialog_set_current_page (GtkPrintUnixDialog *dialog,
3160 int current_page)
3161{
3162 g_return_if_fail (GTK_IS_PRINT_UNIX_DIALOG (dialog));
3163
3164 if (dialog->current_page != current_page)
3165 {
3166 dialog->current_page = current_page;
3167
3168 if (dialog->current_page_radio)
3169 gtk_widget_set_sensitive (widget: dialog->current_page_radio, sensitive: current_page != -1);
3170
3171 g_object_notify (G_OBJECT (dialog), property_name: "current-page");
3172 }
3173}
3174
3175/**
3176 * gtk_print_unix_dialog_get_current_page: (attributes org.gtk.Method.get_property=current-page)
3177 * @dialog: a `GtkPrintUnixDialog`
3178 *
3179 * Gets the current page of the `GtkPrintUnixDialog`.
3180 *
3181 * Returns: the current page of @dialog
3182 */
3183int
3184gtk_print_unix_dialog_get_current_page (GtkPrintUnixDialog *dialog)
3185{
3186 g_return_val_if_fail (GTK_IS_PRINT_UNIX_DIALOG (dialog), -1);
3187
3188 return dialog->current_page;
3189}
3190
3191static gboolean
3192set_active_printer (GtkPrintUnixDialog *dialog,
3193 const char *printer_name)
3194{
3195 GListModel *model;
3196 GtkPrinter *printer;
3197 guint i;
3198
3199 model = G_LIST_MODEL (ptr: gtk_column_view_get_model (GTK_COLUMN_VIEW (dialog->printer_list)));
3200
3201 for (i = 0; i < g_list_model_get_n_items (list: model); i++)
3202 {
3203 printer = g_list_model_get_item (list: model, position: i);
3204
3205 if (strcmp (s1: gtk_printer_get_name (printer), s2: printer_name) == 0)
3206 {
3207 gtk_single_selection_set_selected (self: GTK_SINGLE_SELECTION (ptr: model), position: i);
3208
3209 g_free (mem: dialog->waiting_for_printer);
3210 dialog->waiting_for_printer = NULL;
3211
3212 g_object_unref (object: printer);
3213 return TRUE;
3214 }
3215
3216 g_object_unref (object: printer);
3217 }
3218
3219 return FALSE;
3220}
3221
3222/**
3223 * gtk_print_unix_dialog_set_settings: (attributes org.gtk.Method.set_property=print-settings)
3224 * @dialog: a `GtkPrintUnixDialog`
3225 * @settings: (nullable): a `GtkPrintSettings`
3226 *
3227 * Sets the `GtkPrintSettings` for the `GtkPrintUnixDialog`.
3228 *
3229 * Typically, this is used to restore saved print settings
3230 * from a previous print operation before the print dialog
3231 * is shown.
3232 */
3233void
3234gtk_print_unix_dialog_set_settings (GtkPrintUnixDialog *dialog,
3235 GtkPrintSettings *settings)
3236{
3237 const char *printer;
3238 GtkPageRange *ranges;
3239 int num_ranges;
3240
3241 g_return_if_fail (GTK_IS_PRINT_UNIX_DIALOG (dialog));
3242 g_return_if_fail (settings == NULL || GTK_IS_PRINT_SETTINGS (settings));
3243
3244 if (settings != NULL)
3245 {
3246 dialog_set_collate (dialog, collate: gtk_print_settings_get_collate (settings));
3247 dialog_set_reverse (dialog, reverse: gtk_print_settings_get_reverse (settings));
3248 dialog_set_n_copies (dialog, n_copies: gtk_print_settings_get_n_copies (settings));
3249 dialog_set_scale (dialog, val: gtk_print_settings_get_scale (settings));
3250 dialog_set_page_set (dialog, val: gtk_print_settings_get_page_set (settings));
3251 dialog_set_print_pages (dialog, pages: gtk_print_settings_get_print_pages (settings));
3252 ranges = gtk_print_settings_get_page_ranges (settings, num_ranges: &num_ranges);
3253 if (ranges)
3254 {
3255 dialog_set_page_ranges (dialog, ranges, n_ranges: num_ranges);
3256 g_free (mem: ranges);
3257 }
3258
3259 dialog->format_for_printer =
3260 g_strdup (str: gtk_print_settings_get (settings, key: "format-for-printer"));
3261 }
3262
3263 if (dialog->initial_settings)
3264 g_object_unref (object: dialog->initial_settings);
3265
3266 dialog->initial_settings = settings;
3267
3268 g_free (mem: dialog->waiting_for_printer);
3269 dialog->waiting_for_printer = NULL;
3270
3271 if (settings)
3272 {
3273 g_object_ref (settings);
3274
3275 printer = gtk_print_settings_get_printer (settings);
3276
3277 if (printer && !set_active_printer (dialog, printer_name: printer))
3278 dialog->waiting_for_printer = g_strdup (str: printer);
3279 }
3280
3281 g_object_notify (G_OBJECT (dialog), property_name: "print-settings");
3282}
3283
3284/**
3285 * gtk_print_unix_dialog_get_settings: (attributes org.gtk.Method.set_property=print-settings)
3286 * @dialog: a `GtkPrintUnixDialog`
3287 *
3288 * Gets a new `GtkPrintSettings` object that represents the
3289 * current values in the print dialog.
3290 *
3291 * Note that this creates a new object, and you need to unref
3292 * it if don’t want to keep it.
3293 *
3294 * Returns: (transfer full): a new `GtkPrintSettings` object with the values from @dialog
3295 */
3296GtkPrintSettings *
3297gtk_print_unix_dialog_get_settings (GtkPrintUnixDialog *dialog)
3298{
3299 GtkPrintSettings *settings;
3300 GtkPrintPages print_pages;
3301 GtkPageRange *ranges;
3302 int n_ranges;
3303
3304 g_return_val_if_fail (GTK_IS_PRINT_UNIX_DIALOG (dialog), NULL);
3305
3306 settings = gtk_print_settings_new ();
3307
3308 if (dialog->current_printer)
3309 gtk_print_settings_set_printer (settings,
3310 printer: gtk_printer_get_name (printer: dialog->current_printer));
3311 else
3312 gtk_print_settings_set_printer (settings, printer: "default");
3313
3314 gtk_print_settings_set (settings, key: "format-for-printer",
3315 value: dialog->format_for_printer);
3316
3317 gtk_print_settings_set_collate (settings,
3318 collate: dialog_get_collate (dialog));
3319
3320 gtk_print_settings_set_reverse (settings,
3321 reverse: dialog_get_reverse (dialog));
3322
3323 gtk_print_settings_set_n_copies (settings,
3324 num_copies: dialog_get_n_copies (dialog));
3325
3326 gtk_print_settings_set_scale (settings,
3327 scale: dialog_get_scale (dialog));
3328
3329 gtk_print_settings_set_page_set (settings,
3330 page_set: dialog_get_page_set (dialog));
3331
3332 print_pages = dialog_get_print_pages (dialog);
3333 gtk_print_settings_set_print_pages (settings, pages: print_pages);
3334
3335 ranges = dialog_get_page_ranges (dialog, n_ranges_out: &n_ranges);
3336 if (ranges)
3337 {
3338 gtk_print_settings_set_page_ranges (settings, page_ranges: ranges, num_ranges: n_ranges);
3339 g_free (mem: ranges);
3340 }
3341
3342 /* TODO: print when. How to handle? */
3343
3344 if (dialog->current_printer)
3345 _gtk_printer_get_settings_from_options (printer: dialog->current_printer,
3346 options: dialog->options,
3347 settings);
3348
3349 return settings;
3350}
3351
3352/**
3353 * gtk_print_unix_dialog_add_custom_tab:
3354 * @dialog: a `GtkPrintUnixDialog`
3355 * @child: the widget to put in the custom tab
3356 * @tab_label: the widget to use as tab label
3357 *
3358 * Adds a custom tab to the print dialog.
3359 */
3360void
3361gtk_print_unix_dialog_add_custom_tab (GtkPrintUnixDialog *dialog,
3362 GtkWidget *child,
3363 GtkWidget *tab_label)
3364{
3365 gtk_notebook_insert_page (GTK_NOTEBOOK (dialog->notebook),
3366 child, tab_label, position: 2);
3367 gtk_widget_show (widget: child);
3368 gtk_widget_show (widget: tab_label);
3369}
3370
3371/**
3372 * gtk_print_unix_dialog_set_manual_capabilities: (attributes org.gtk.Method.set_property=manual-capabilities)
3373 * @dialog: a `GtkPrintUnixDialog`
3374 * @capabilities: the printing capabilities of your application
3375 *
3376 * This lets you specify the printing capabilities your application
3377 * supports.
3378 *
3379 * For instance, if you can handle scaling the output then you pass
3380 * %GTK_PRINT_CAPABILITY_SCALE. If you don’t pass that, then the dialog
3381 * will only let you select the scale if the printing system automatically
3382 * handles scaling.
3383 */
3384void
3385gtk_print_unix_dialog_set_manual_capabilities (GtkPrintUnixDialog *dialog,
3386 GtkPrintCapabilities capabilities)
3387{
3388 if (dialog->manual_capabilities != capabilities)
3389 {
3390 dialog->manual_capabilities = capabilities;
3391 update_dialog_from_capabilities (dialog);
3392
3393 if (dialog->current_printer)
3394 {
3395 g_clear_object (&dialog->current_printer);
3396 selected_printer_changed (dialog);
3397 }
3398
3399 g_object_notify (G_OBJECT (dialog), property_name: "manual-capabilities");
3400 }
3401}
3402
3403/**
3404 * gtk_print_unix_dialog_get_manual_capabilities: (attributes org.gtk.Method.get_property=manual-capabilities)
3405 * @dialog: a `GtkPrintUnixDialog`
3406 *
3407 * Gets the capabilities that have been set on this `GtkPrintUnixDialog`.
3408 *
3409 * Returns: the printing capabilities
3410 */
3411GtkPrintCapabilities
3412gtk_print_unix_dialog_get_manual_capabilities (GtkPrintUnixDialog *dialog)
3413{
3414 g_return_val_if_fail (GTK_IS_PRINT_UNIX_DIALOG (dialog), FALSE);
3415
3416 return dialog->manual_capabilities;
3417}
3418
3419/**
3420 * gtk_print_unix_dialog_set_support_selection: (attributes org.gtk.Method.set_property=support-selection)
3421 * @dialog: a `GtkPrintUnixDialog`
3422 * @support_selection: %TRUE to allow print selection
3423 *
3424 * Sets whether the print dialog allows user to print a selection.
3425 */
3426void
3427gtk_print_unix_dialog_set_support_selection (GtkPrintUnixDialog *dialog,
3428 gboolean support_selection)
3429{
3430 g_return_if_fail (GTK_IS_PRINT_UNIX_DIALOG (dialog));
3431
3432 support_selection = support_selection != FALSE;
3433 if (dialog->support_selection != support_selection)
3434 {
3435 dialog->support_selection = support_selection;
3436
3437 if (dialog->selection_radio)
3438 {
3439 if (support_selection)
3440 {
3441 gtk_widget_set_sensitive (widget: dialog->selection_radio, sensitive: dialog->has_selection);
3442 gtk_widget_show (widget: dialog->selection_radio);
3443 }
3444 else
3445 {
3446 gtk_widget_set_sensitive (widget: dialog->selection_radio, FALSE);
3447 gtk_widget_hide (widget: dialog->selection_radio);
3448 }
3449 }
3450
3451 g_object_notify (G_OBJECT (dialog), property_name: "support-selection");
3452 }
3453}
3454
3455/**
3456 * gtk_print_unix_dialog_get_support_selection: (attributes org.gtk.Method.get_property=support-selection)
3457 * @dialog: a `GtkPrintUnixDialog`
3458 *
3459 * Gets whether the print dialog allows user to print a selection.
3460 *
3461 * Returns: whether the application supports print of selection
3462 */
3463gboolean
3464gtk_print_unix_dialog_get_support_selection (GtkPrintUnixDialog *dialog)
3465{
3466 g_return_val_if_fail (GTK_IS_PRINT_UNIX_DIALOG (dialog), FALSE);
3467
3468 return dialog->support_selection;
3469}
3470
3471/**
3472 * gtk_print_unix_dialog_set_has_selection: (attributes org.gtk.Method.set_property=has-selection)
3473 * @dialog: a `GtkPrintUnixDialog`
3474 * @has_selection: %TRUE indicates that a selection exists
3475 *
3476 * Sets whether a selection exists.
3477 */
3478void
3479gtk_print_unix_dialog_set_has_selection (GtkPrintUnixDialog *dialog,
3480 gboolean has_selection)
3481{
3482 g_return_if_fail (GTK_IS_PRINT_UNIX_DIALOG (dialog));
3483
3484 has_selection = has_selection != FALSE;
3485 if (dialog->has_selection != has_selection)
3486 {
3487 dialog->has_selection = has_selection;
3488
3489 if (dialog->selection_radio)
3490 {
3491 if (dialog->support_selection)
3492 gtk_widget_set_sensitive (widget: dialog->selection_radio, sensitive: has_selection);
3493 else
3494 gtk_widget_set_sensitive (widget: dialog->selection_radio, FALSE);
3495 }
3496
3497 g_object_notify (G_OBJECT (dialog), property_name: "has-selection");
3498 }
3499}
3500
3501/**
3502 * gtk_print_unix_dialog_get_has_selection: (attributes org.gtk.Method.get_property=has-selection)
3503 * @dialog: a `GtkPrintUnixDialog`
3504 *
3505 * Gets whether there is a selection.
3506 *
3507 * Returns: whether there is a selection
3508 */
3509gboolean
3510gtk_print_unix_dialog_get_has_selection (GtkPrintUnixDialog *dialog)
3511{
3512 g_return_val_if_fail (GTK_IS_PRINT_UNIX_DIALOG (dialog), FALSE);
3513
3514 return dialog->has_selection;
3515}
3516
3517/**
3518 * gtk_print_unix_dialog_set_embed_page_setup: (attributes org.gtk.Method.set_property=embed-page-setup)
3519 * @dialog: a `GtkPrintUnixDialog`
3520 * @embed: embed page setup selection
3521 *
3522 * Embed page size combo box and orientation combo box into page setup page.
3523 */
3524void
3525gtk_print_unix_dialog_set_embed_page_setup (GtkPrintUnixDialog *dialog,
3526 gboolean embed)
3527{
3528 g_return_if_fail (GTK_IS_PRINT_UNIX_DIALOG (dialog));
3529
3530 embed = embed != FALSE;
3531 if (dialog->embed_page_setup != embed)
3532 {
3533 dialog->embed_page_setup = embed;
3534
3535 gtk_widget_set_sensitive (widget: dialog->paper_size_combo, sensitive: dialog->embed_page_setup);
3536 gtk_widget_set_sensitive (widget: dialog->orientation_combo, sensitive: dialog->embed_page_setup);
3537
3538 if (dialog->embed_page_setup)
3539 {
3540 if (dialog->paper_size_combo != NULL)
3541 g_signal_connect (dialog->paper_size_combo, "notify::selected", G_CALLBACK (paper_size_changed), dialog);
3542
3543 if (dialog->orientation_combo)
3544 g_signal_connect (dialog->orientation_combo, "notify::selected", G_CALLBACK (orientation_changed), dialog);
3545 }
3546 else
3547 {
3548 if (dialog->paper_size_combo != NULL)
3549 g_signal_handlers_disconnect_by_func (dialog->paper_size_combo, G_CALLBACK (paper_size_changed), dialog);
3550
3551 if (dialog->orientation_combo)
3552 g_signal_handlers_disconnect_by_func (dialog->orientation_combo, G_CALLBACK (orientation_changed), dialog);
3553 }
3554
3555 dialog->internal_page_setup_change = TRUE;
3556 update_paper_sizes (dialog);
3557 dialog->internal_page_setup_change = FALSE;
3558 }
3559}
3560
3561/**
3562 * gtk_print_unix_dialog_get_embed_page_setup: (attributes org.gtk.Method.get_property=embed-page-setup)
3563 * @dialog: a `GtkPrintUnixDialog`
3564 *
3565 * Gets whether to embed the page setup.
3566 *
3567 * Returns: whether to embed the page setup
3568 */
3569gboolean
3570gtk_print_unix_dialog_get_embed_page_setup (GtkPrintUnixDialog *dialog)
3571{
3572 g_return_val_if_fail (GTK_IS_PRINT_UNIX_DIALOG (dialog), FALSE);
3573
3574 return dialog->embed_page_setup;
3575}
3576

source code of gtk/gtk/gtkprintunixdialog.c