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 | |
124 | static void gtk_print_unix_dialog_constructed (GObject *object); |
125 | static void gtk_print_unix_dialog_dispose (GObject *object); |
126 | static void gtk_print_unix_dialog_finalize (GObject *object); |
127 | static void gtk_print_unix_dialog_set_property (GObject *object, |
128 | guint prop_id, |
129 | const GValue *value, |
130 | GParamSpec *pspec); |
131 | static void gtk_print_unix_dialog_get_property (GObject *object, |
132 | guint prop_id, |
133 | GValue *value, |
134 | GParamSpec *pspec); |
135 | static void unschedule_idle_mark_conflicts (GtkPrintUnixDialog *dialog); |
136 | static void selected_printer_changed (GtkPrintUnixDialog *dialog); |
137 | static void clear_per_printer_ui (GtkPrintUnixDialog *dialog); |
138 | static void printer_added_cb (GListModel *model, |
139 | guint position, |
140 | guint removed, |
141 | guint added, |
142 | GtkPrintUnixDialog *dialog); |
143 | static void printer_status_cb (GtkPrintBackend *backend, |
144 | GtkPrinter *printer, |
145 | GtkPrintUnixDialog *dialog); |
146 | static void update_collate_icon (GtkToggleButton *toggle_button, |
147 | GtkPrintUnixDialog *dialog); |
148 | static void error_dialogs (GtkPrintUnixDialog *print_dialog, |
149 | int print_dialog_response_id, |
150 | gpointer data); |
151 | static gboolean page_range_entry_focus_changed (GtkWidget *entry, |
152 | GParamSpec *pspec, |
153 | GtkPrintUnixDialog *dialog); |
154 | static void update_page_range_entry_sensitivity(GtkWidget *button, |
155 | GtkPrintUnixDialog *dialog); |
156 | static void update_print_at_entry_sensitivity (GtkWidget *button, |
157 | GtkPrintUnixDialog *dialog); |
158 | static void update_print_at_option (GtkPrintUnixDialog *dialog); |
159 | static void update_dialog_from_capabilities (GtkPrintUnixDialog *dialog); |
160 | static void draw_collate (GtkDrawingArea *da, |
161 | cairo_t *cr, |
162 | int width, |
163 | int height, |
164 | gpointer data); |
165 | static gboolean is_printer_active (gpointer item, |
166 | gpointer data); |
167 | static int default_printer_list_sort_func (gconstpointer a, |
168 | gconstpointer b, |
169 | gpointer user_data); |
170 | static void update_number_up_layout (GtkPrintUnixDialog *dialog); |
171 | static void draw_page (GtkDrawingArea *da, |
172 | cairo_t *cr, |
173 | int width, |
174 | int height, |
175 | gpointer data); |
176 | |
177 | |
178 | static gboolean dialog_get_collate (GtkPrintUnixDialog *dialog); |
179 | static gboolean dialog_get_reverse (GtkPrintUnixDialog *dialog); |
180 | static int dialog_get_n_copies (GtkPrintUnixDialog *dialog); |
181 | |
182 | static gboolean set_active_printer (GtkPrintUnixDialog *dialog, |
183 | const char *printer_name); |
184 | static void redraw_page_layout_preview (GtkPrintUnixDialog *dialog); |
185 | static GListModel *load_print_backends (GtkPrintUnixDialog *dialog); |
186 | |
187 | /* GtkBuildable */ |
188 | static void gtk_print_unix_dialog_buildable_init (GtkBuildableIface *iface); |
189 | static GObject *gtk_print_unix_dialog_buildable_get_internal_child (GtkBuildable *buildable, |
190 | GtkBuilder *builder, |
191 | const char *childname); |
192 | |
193 | static 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 */ |
209 | enum { |
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 */ |
216 | enum { |
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 | |
226 | enum { |
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 | |
238 | typedef struct _GtkPrintUnixDialogClass GtkPrintUnixDialogClass; |
239 | |
240 | struct _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 | |
342 | struct _GtkPrintUnixDialogClass |
343 | { |
344 | GtkDialogClass parent_class; |
345 | }; |
346 | |
347 | G_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 | |
351 | static GtkBuildableIface *parent_buildable_iface; |
352 | |
353 | static gboolean |
354 | is_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 | |
364 | static void |
365 | gtk_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 */ |
555 | static GtkWindow * |
556 | get_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 | |
567 | static void |
568 | set_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 | |
586 | typedef struct { |
587 | GMainLoop *loop; |
588 | int response; |
589 | } ConfirmationData; |
590 | |
591 | static void |
592 | on_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 | */ |
607 | static void |
608 | error_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 | |
711 | static char * |
712 | get_printer_key (GtkPrinter *printer) |
713 | { |
714 | return g_strconcat (string1: "" , gtk_printer_get_name (printer), " " , gtk_printer_get_location (printer), NULL); |
715 | } |
716 | |
717 | static void |
718 | setup_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 | |
728 | static void |
729 | bind_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 | |
763 | static void |
764 | bind_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 | |
776 | static void |
777 | gtk_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 | |
907 | static void |
908 | gtk_print_unix_dialog_constructed (GObject *object) |
909 | { |
910 | gboolean ; |
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 | |
930 | static void |
931 | gtk_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 | |
941 | static void |
942 | disconnect_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 | |
957 | static void |
958 | gtk_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 | |
996 | static void |
997 | gtk_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 | |
1004 | static GObject * |
1005 | gtk_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 | |
1017 | static void |
1018 | printer_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 | |
1037 | static void |
1038 | printer_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 | |
1071 | static GListModel * |
1072 | load_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 | |
1094 | static void |
1095 | gtk_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 | |
1132 | static void |
1133 | gtk_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 | |
1172 | static gboolean |
1173 | is_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 | |
1197 | static int |
1198 | default_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 | |
1234 | static GtkWidget * |
1235 | wrap_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 | |
1262 | static gboolean |
1263 | setup_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 | |
1275 | static void |
1276 | add_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 | |
1309 | static int |
1310 | grid_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 | |
1339 | static void |
1340 | add_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 | |
1373 | static void |
1374 | setup_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 | |
1392 | static void |
1393 | update_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 | |
1423 | static gboolean |
1424 | setup_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 | |
1467 | static void |
1468 | update_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 | |
1584 | static void |
1585 | update_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 | |
1617 | static gboolean |
1618 | page_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 | |
1630 | static gboolean |
1631 | page_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 | |
1638 | static gboolean |
1639 | set_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 | |
1687 | static void |
1688 | fill_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 | |
1694 | static void |
1695 | fill_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 | |
1729 | static void |
1730 | update_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 | |
1751 | static void |
1752 | mark_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 | |
1777 | static gboolean |
1778 | mark_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 | |
1789 | static void |
1790 | unschedule_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 | |
1799 | static void |
1800 | schedule_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 | |
1809 | static void |
1810 | options_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 | |
1818 | static void |
1819 | clear_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 | |
1838 | static void |
1839 | printer_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 | |
1849 | static void |
1850 | selected_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 | |
1949 | static void |
1950 | update_collate_icon (GtkToggleButton *toggle_button, |
1951 | GtkPrintUnixDialog *dialog) |
1952 | { |
1953 | gtk_widget_queue_draw (widget: dialog->collate_image); |
1954 | } |
1955 | |
1956 | static void |
1957 | paint_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 | |
1993 | static void |
1994 | draw_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 | |
2047 | static gboolean |
2048 | page_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 | |
2058 | static void |
2059 | update_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 | |
2070 | static void |
2071 | update_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 | |
2084 | static gboolean |
2085 | is_range_separator (char c) |
2086 | { |
2087 | return (c == ',' || c == ';' || c == ':'); |
2088 | } |
2089 | |
2090 | static GtkPageRange * |
2091 | dialog_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 | |
2170 | static void |
2171 | dialog_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 | |
2195 | static GtkPrintPages |
2196 | dialog_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 | |
2208 | static void |
2209 | dialog_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 | |
2222 | static double |
2223 | dialog_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 | |
2231 | static void |
2232 | dialog_set_scale (GtkPrintUnixDialog *dialog, |
2233 | double val) |
2234 | { |
2235 | gtk_spin_button_set_value (GTK_SPIN_BUTTON (dialog->scale_spin), value: val); |
2236 | } |
2237 | |
2238 | static GtkPageSet |
2239 | dialog_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 | |
2247 | static void |
2248 | dialog_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 | |
2254 | static int |
2255 | dialog_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 | |
2282 | static void |
2283 | dialog_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 | |
2289 | static gboolean |
2290 | dialog_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 | |
2297 | static void |
2298 | dialog_set_collate (GtkPrintUnixDialog *dialog, |
2299 | gboolean collate) |
2300 | { |
2301 | gtk_check_button_set_active (GTK_CHECK_BUTTON (dialog->collate_check), setting: collate); |
2302 | } |
2303 | |
2304 | static gboolean |
2305 | dialog_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 | |
2312 | static void |
2313 | dialog_set_reverse (GtkPrintUnixDialog *dialog, |
2314 | gboolean reverse) |
2315 | { |
2316 | gtk_check_button_set_active (GTK_CHECK_BUTTON (dialog->reverse_check), setting: reverse); |
2317 | } |
2318 | |
2319 | static int |
2320 | dialog_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 | |
2339 | static GtkNumberUpLayout |
2340 | dialog_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 | |
2379 | static void |
2380 | draw_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 | |
2782 | static void |
2783 | redraw_page_layout_preview (GtkPrintUnixDialog *dialog) |
2784 | { |
2785 | if (dialog->page_layout_preview) |
2786 | gtk_widget_queue_draw (widget: dialog->page_layout_preview); |
2787 | } |
2788 | |
2789 | static void |
2790 | update_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 | |
2934 | static void |
2935 | custom_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 | |
2968 | static void |
2969 | orientation_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 | |
2993 | static void |
2994 | paper_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 | */ |
3061 | GtkWidget * |
3062 | gtk_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 | */ |
3083 | GtkPrinter * |
3084 | gtk_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 | */ |
3098 | void |
3099 | gtk_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 | */ |
3124 | GtkPageSetup * |
3125 | gtk_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 | */ |
3140 | gboolean |
3141 | gtk_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 | */ |
3158 | void |
3159 | gtk_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 | */ |
3183 | int |
3184 | gtk_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 | |
3191 | static gboolean |
3192 | set_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 | */ |
3233 | void |
3234 | gtk_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 | */ |
3296 | GtkPrintSettings * |
3297 | gtk_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 | */ |
3360 | void |
3361 | gtk_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 | */ |
3384 | void |
3385 | gtk_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 | */ |
3411 | GtkPrintCapabilities |
3412 | gtk_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 | */ |
3426 | void |
3427 | gtk_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 | */ |
3463 | gboolean |
3464 | gtk_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 | */ |
3478 | void |
3479 | gtk_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 | */ |
3509 | gboolean |
3510 | gtk_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 | */ |
3524 | void |
3525 | gtk_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 | */ |
3569 | gboolean |
3570 | gtk_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 | |