1/* GTK - The GIMP Toolkit
2 * gtkprintoperation.c: Print Operation
3 * Copyright (C) 2006, Red Hat, Inc.
4 *
5 * This library is free software; you can redistribute it and/or
6 * modify it under the terms of the GNU Lesser General Public
7 * License as published by the Free Software Foundation; either
8 * version 2 of the License, or (at your option) any later version.
9 *
10 * This library is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13 * Lesser General Public License for more details.
14 *
15 * You should have received a copy of the GNU Lesser General Public
16 * License along with this library. If not, see <http://www.gnu.org/licenses/>.
17 */
18
19#include "config.h"
20
21#include <errno.h>
22#include <stdlib.h>
23#include <math.h>
24#include <string.h>
25
26#include <cairo-pdf.h>
27
28#include "gtkprintoperation-private.h"
29#include "gtkmarshalers.h"
30#include "gtkintl.h"
31#include "gtkprivate.h"
32#include "gtkmessagedialog.h"
33#include "gtkwindowgroup.h"
34#include "gtktypebuiltins.h"
35
36/**
37 * GtkPrintOperation:
38 *
39 * `GtkPrintOperation` is the high-level, portable printing API.
40 *
41 * It looks a bit different than other GTK dialogs such as the
42 * `GtkFileChooser`, since some platforms don’t expose enough
43 * infrastructure to implement a good print dialog. On such
44 * platforms, `GtkPrintOperation` uses the native print dialog.
45 * On platforms which do not provide a native print dialog, GTK
46 * uses its own, see [class@Gtk.PrintUnixDialog].
47 *
48 * The typical way to use the high-level printing API is to create
49 * a `GtkPrintOperation` object with [ctor@Gtk.PrintOperation.new]
50 * when the user selects to print. Then you set some properties on it,
51 * e.g. the page size, any [class@Gtk.PrintSettings] from previous print
52 * operations, the number of pages, the current page, etc.
53 *
54 * Then you start the print operation by calling [method@Gtk.PrintOperation.run].
55 * It will then show a dialog, let the user select a printer and options.
56 * When the user finished the dialog, various signals will be emitted on
57 * the `GtkPrintOperation`, the main one being
58 * [signal@Gtk.PrintOperation::draw-page], which you are supposed to handle
59 * and render the page on the provided [class@Gtk.PrintContext] using Cairo.
60 *
61 * # The high-level printing API
62 *
63 * ```c
64 * static GtkPrintSettings *settings = NULL;
65 *
66 * static void
67 * do_print (void)
68 * {
69 * GtkPrintOperation *print;
70 * GtkPrintOperationResult res;
71 *
72 * print = gtk_print_operation_new ();
73 *
74 * if (settings != NULL)
75 * gtk_print_operation_set_print_settings (print, settings);
76 *
77 * g_signal_connect (print, "begin_print", G_CALLBACK (begin_print), NULL);
78 * g_signal_connect (print, "draw_page", G_CALLBACK (draw_page), NULL);
79 *
80 * res = gtk_print_operation_run (print, GTK_PRINT_OPERATION_ACTION_PRINT_DIALOG,
81 * GTK_WINDOW (main_window), NULL);
82 *
83 * if (res == GTK_PRINT_OPERATION_RESULT_APPLY)
84 * {
85 * if (settings != NULL)
86 * g_object_unref (settings);
87 * settings = g_object_ref (gtk_print_operation_get_print_settings (print));
88 * }
89 *
90 * g_object_unref (print);
91 * }
92 * ```
93 *
94 * By default `GtkPrintOperation` uses an external application to do
95 * print preview. To implement a custom print preview, an application
96 * must connect to the preview signal. The functions
97 * [method@Gtk.PrintOperationPreview.render_page],
98 * [method@Gtk.PrintOperationPreview.end_preview] and
99 * [method@Gtk.PrintOperationPreview.is_selected]
100 * are useful when implementing a print preview.
101 */
102
103#define SHOW_PROGRESS_TIME 1200
104
105
106enum
107{
108 DONE,
109 BEGIN_PRINT,
110 PAGINATE,
111 REQUEST_PAGE_SETUP,
112 DRAW_PAGE,
113 END_PRINT,
114 STATUS_CHANGED,
115 CREATE_CUSTOM_WIDGET,
116 CUSTOM_WIDGET_APPLY,
117 PREVIEW,
118 UPDATE_CUSTOM_WIDGET,
119 LAST_SIGNAL
120};
121
122enum
123{
124 PROP_0,
125 PROP_DEFAULT_PAGE_SETUP,
126 PROP_PRINT_SETTINGS,
127 PROP_JOB_NAME,
128 PROP_N_PAGES,
129 PROP_CURRENT_PAGE,
130 PROP_USE_FULL_PAGE,
131 PROP_TRACK_PRINT_STATUS,
132 PROP_UNIT,
133 PROP_SHOW_PROGRESS,
134 PROP_ALLOW_ASYNC,
135 PROP_EXPORT_FILENAME,
136 PROP_STATUS,
137 PROP_STATUS_STRING,
138 PROP_CUSTOM_TAB_LABEL,
139 PROP_EMBED_PAGE_SETUP,
140 PROP_HAS_SELECTION,
141 PROP_SUPPORT_SELECTION,
142 PROP_N_PAGES_TO_PRINT
143};
144
145static guint signals[LAST_SIGNAL] = { 0 };
146static int job_nr = 0;
147typedef struct _PrintPagesData PrintPagesData;
148
149static void preview_iface_init (GtkPrintOperationPreviewIface *iface);
150static GtkPageSetup *create_page_setup (GtkPrintOperation *op);
151static void common_render_page (GtkPrintOperation *op,
152 int page_nr);
153static void increment_page_sequence (PrintPagesData *data);
154static void prepare_data (PrintPagesData *data);
155static void clamp_page_ranges (PrintPagesData *data);
156
157
158G_DEFINE_TYPE_WITH_CODE (GtkPrintOperation, gtk_print_operation, G_TYPE_OBJECT,
159 G_ADD_PRIVATE (GtkPrintOperation)
160 G_IMPLEMENT_INTERFACE (GTK_TYPE_PRINT_OPERATION_PREVIEW,
161 preview_iface_init))
162
163/**
164 * gtk_print_error_quark:
165 *
166 * Registers an error quark for `GtkPrintOperation` if necessary.
167 *
168 * Returns: The error quark used for `GtkPrintOperation` errors.
169 **/
170GQuark
171gtk_print_error_quark (void)
172{
173 static GQuark quark = 0;
174 if (quark == 0)
175 quark = g_quark_from_static_string (string: "gtk-print-error-quark");
176 return quark;
177}
178
179static void
180gtk_print_operation_finalize (GObject *object)
181{
182 GtkPrintOperation *op = GTK_PRINT_OPERATION (object);
183 GtkPrintOperationPrivate *priv = gtk_print_operation_get_instance_private (self: op);
184
185 if (priv->free_platform_data &&
186 priv->platform_data)
187 {
188 priv->free_platform_data (priv->platform_data);
189 priv->free_platform_data = NULL;
190 }
191
192 if (priv->default_page_setup)
193 g_object_unref (object: priv->default_page_setup);
194
195 if (priv->print_settings)
196 g_object_unref (object: priv->print_settings);
197
198 if (priv->print_context)
199 g_object_unref (object: priv->print_context);
200
201 g_free (mem: priv->export_filename);
202 g_free (mem: priv->job_name);
203 g_free (mem: priv->custom_tab_label);
204 g_free (mem: priv->status_string);
205
206 if (priv->print_pages_idle_id > 0)
207 g_source_remove (tag: priv->print_pages_idle_id);
208
209 if (priv->show_progress_timeout_id > 0)
210 g_source_remove (tag: priv->show_progress_timeout_id);
211
212 if (priv->error)
213 g_error_free (error: priv->error);
214
215 G_OBJECT_CLASS (gtk_print_operation_parent_class)->finalize (object);
216}
217
218static void
219gtk_print_operation_init (GtkPrintOperation *operation)
220{
221 GtkPrintOperationPrivate *priv = gtk_print_operation_get_instance_private (self: operation);
222 const char *appname;
223
224 priv->status = GTK_PRINT_STATUS_INITIAL;
225 priv->status_string = g_strdup (str: "");
226 priv->default_page_setup = NULL;
227 priv->print_settings = NULL;
228 priv->nr_of_pages = -1;
229 priv->nr_of_pages_to_print = -1;
230 priv->page_position = -1;
231 priv->current_page = -1;
232 priv->use_full_page = FALSE;
233 priv->show_progress = FALSE;
234 priv->export_filename = NULL;
235 priv->track_print_status = FALSE;
236 priv->is_sync = FALSE;
237 priv->support_selection = FALSE;
238 priv->has_selection = FALSE;
239 priv->embed_page_setup = FALSE;
240
241 priv->page_drawing_state = GTK_PAGE_DRAWING_STATE_READY;
242
243 priv->rloop = NULL;
244 priv->unit = GTK_UNIT_NONE;
245
246 appname = g_get_application_name ();
247 if (appname == NULL)
248 appname = "";
249 /* translators: this string is the default job title for print
250 * jobs. %s gets replaced by the application name, %d gets replaced
251 * by the job number.
252 */
253 priv->job_name = g_strdup_printf (_("%s job #%d"), appname, ++job_nr);
254 operation->priv = priv;
255}
256
257static void
258preview_iface_render_page (GtkPrintOperationPreview *preview,
259 int page_nr)
260{
261
262 GtkPrintOperation *op;
263
264 op = GTK_PRINT_OPERATION (preview);
265 common_render_page (op, page_nr);
266}
267
268static void
269preview_iface_end_preview (GtkPrintOperationPreview *preview)
270{
271 GtkPrintOperation *op;
272 GtkPrintOperationResult result;
273
274 op = GTK_PRINT_OPERATION (preview);
275
276 g_signal_emit (instance: op, signal_id: signals[END_PRINT], detail: 0, op->priv->print_context);
277
278 if (op->priv->rloop)
279 g_main_loop_quit (loop: op->priv->rloop);
280
281 if (op->priv->end_run)
282 op->priv->end_run (op, op->priv->is_sync, TRUE);
283
284 _gtk_print_operation_set_status (op, status: GTK_PRINT_STATUS_FINISHED, NULL);
285
286 if (op->priv->error)
287 result = GTK_PRINT_OPERATION_RESULT_ERROR;
288 else if (op->priv->cancelled)
289 result = GTK_PRINT_OPERATION_RESULT_CANCEL;
290 else
291 result = GTK_PRINT_OPERATION_RESULT_APPLY;
292
293 g_signal_emit (instance: op, signal_id: signals[DONE], detail: 0, result);
294}
295
296static gboolean
297preview_iface_is_selected (GtkPrintOperationPreview *preview,
298 int page_nr)
299{
300 GtkPrintOperation *op = GTK_PRINT_OPERATION (preview);
301 GtkPrintOperationPrivate *priv = gtk_print_operation_get_instance_private (self: op);
302 int i;
303
304 switch (priv->print_pages)
305 {
306 case GTK_PRINT_PAGES_SELECTION:
307 case GTK_PRINT_PAGES_ALL:
308 return (page_nr >= 0) && (page_nr < priv->nr_of_pages);
309 case GTK_PRINT_PAGES_CURRENT:
310 return page_nr == priv->current_page;
311 case GTK_PRINT_PAGES_RANGES:
312 for (i = 0; i < priv->num_page_ranges; i++)
313 {
314 if (page_nr >= priv->page_ranges[i].start &&
315 (page_nr <= priv->page_ranges[i].end || priv->page_ranges[i].end == -1))
316 return TRUE;
317 }
318 return FALSE;
319 default:
320 return FALSE;
321 }
322}
323
324static void
325preview_iface_init (GtkPrintOperationPreviewIface *iface)
326{
327 iface->render_page = preview_iface_render_page;
328 iface->end_preview = preview_iface_end_preview;
329 iface->is_selected = preview_iface_is_selected;
330}
331
332static void
333preview_start_page (GtkPrintOperation *op,
334 GtkPrintContext *print_context,
335 GtkPageSetup *page_setup)
336{
337 if ((op->priv->manual_number_up < 2) ||
338 (op->priv->page_position % op->priv->manual_number_up == 0))
339 g_signal_emit_by_name (instance: op, detailed_signal: "got-page-size", print_context, page_setup);
340}
341
342static void
343preview_end_page (GtkPrintOperation *op,
344 GtkPrintContext *print_context)
345{
346 cairo_t *cr;
347
348 cr = gtk_print_context_get_cairo_context (context: print_context);
349
350 if ((op->priv->manual_number_up < 2) ||
351 ((op->priv->page_position + 1) % op->priv->manual_number_up == 0) ||
352 (op->priv->page_position == op->priv->nr_of_pages_to_print - 1))
353 cairo_show_page (cr);
354}
355
356static void
357preview_end_run (GtkPrintOperation *op,
358 gboolean wait,
359 gboolean cancelled)
360{
361 g_free (mem: op->priv->page_ranges);
362 op->priv->page_ranges = NULL;
363}
364
365
366static void
367gtk_print_operation_set_property (GObject *object,
368 guint prop_id,
369 const GValue *value,
370 GParamSpec *pspec)
371{
372 GtkPrintOperation *op = GTK_PRINT_OPERATION (object);
373
374 switch (prop_id)
375 {
376 case PROP_DEFAULT_PAGE_SETUP:
377 gtk_print_operation_set_default_page_setup (op, default_page_setup: g_value_get_object (value));
378 break;
379 case PROP_PRINT_SETTINGS:
380 gtk_print_operation_set_print_settings (op, print_settings: g_value_get_object (value));
381 break;
382 case PROP_JOB_NAME:
383 gtk_print_operation_set_job_name (op, job_name: g_value_get_string (value));
384 break;
385 case PROP_N_PAGES:
386 gtk_print_operation_set_n_pages (op, n_pages: g_value_get_int (value));
387 break;
388 case PROP_CURRENT_PAGE:
389 gtk_print_operation_set_current_page (op, current_page: g_value_get_int (value));
390 break;
391 case PROP_USE_FULL_PAGE:
392 gtk_print_operation_set_use_full_page (op, full_page: g_value_get_boolean (value));
393 break;
394 case PROP_TRACK_PRINT_STATUS:
395 gtk_print_operation_set_track_print_status (op, track_status: g_value_get_boolean (value));
396 break;
397 case PROP_UNIT:
398 gtk_print_operation_set_unit (op, unit: g_value_get_enum (value));
399 break;
400 case PROP_ALLOW_ASYNC:
401 gtk_print_operation_set_allow_async (op, allow_async: g_value_get_boolean (value));
402 break;
403 case PROP_SHOW_PROGRESS:
404 gtk_print_operation_set_show_progress (op, show_progress: g_value_get_boolean (value));
405 break;
406 case PROP_EXPORT_FILENAME:
407 gtk_print_operation_set_export_filename (op, filename: g_value_get_string (value));
408 break;
409 case PROP_CUSTOM_TAB_LABEL:
410 gtk_print_operation_set_custom_tab_label (op, label: g_value_get_string (value));
411 break;
412 case PROP_EMBED_PAGE_SETUP:
413 gtk_print_operation_set_embed_page_setup (op, embed: g_value_get_boolean (value));
414 break;
415 case PROP_HAS_SELECTION:
416 gtk_print_operation_set_has_selection (op, has_selection: g_value_get_boolean (value));
417 break;
418 case PROP_SUPPORT_SELECTION:
419 gtk_print_operation_set_support_selection (op, support_selection: g_value_get_boolean (value));
420 break;
421 default:
422 G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
423 break;
424 }
425}
426
427static void
428gtk_print_operation_get_property (GObject *object,
429 guint prop_id,
430 GValue *value,
431 GParamSpec *pspec)
432{
433 GtkPrintOperation *op = GTK_PRINT_OPERATION (object);
434 GtkPrintOperationPrivate *priv = gtk_print_operation_get_instance_private (self: op);
435
436 switch (prop_id)
437 {
438 case PROP_DEFAULT_PAGE_SETUP:
439 g_value_set_object (value, v_object: priv->default_page_setup);
440 break;
441 case PROP_PRINT_SETTINGS:
442 g_value_set_object (value, v_object: priv->print_settings);
443 break;
444 case PROP_JOB_NAME:
445 g_value_set_string (value, v_string: priv->job_name);
446 break;
447 case PROP_N_PAGES:
448 g_value_set_int (value, v_int: priv->nr_of_pages);
449 break;
450 case PROP_CURRENT_PAGE:
451 g_value_set_int (value, v_int: priv->current_page);
452 break;
453 case PROP_USE_FULL_PAGE:
454 g_value_set_boolean (value, v_boolean: priv->use_full_page);
455 break;
456 case PROP_TRACK_PRINT_STATUS:
457 g_value_set_boolean (value, v_boolean: priv->track_print_status);
458 break;
459 case PROP_UNIT:
460 g_value_set_enum (value, v_enum: priv->unit);
461 break;
462 case PROP_ALLOW_ASYNC:
463 g_value_set_boolean (value, v_boolean: priv->allow_async);
464 break;
465 case PROP_SHOW_PROGRESS:
466 g_value_set_boolean (value, v_boolean: priv->show_progress);
467 break;
468 case PROP_EXPORT_FILENAME:
469 g_value_set_string (value, v_string: priv->export_filename);
470 break;
471 case PROP_STATUS:
472 g_value_set_enum (value, v_enum: priv->status);
473 break;
474 case PROP_STATUS_STRING:
475 g_value_set_string (value, v_string: priv->status_string);
476 break;
477 case PROP_CUSTOM_TAB_LABEL:
478 g_value_set_string (value, v_string: priv->custom_tab_label);
479 break;
480 case PROP_EMBED_PAGE_SETUP:
481 g_value_set_boolean (value, v_boolean: priv->embed_page_setup);
482 break;
483 case PROP_HAS_SELECTION:
484 g_value_set_boolean (value, v_boolean: priv->has_selection);
485 break;
486 case PROP_SUPPORT_SELECTION:
487 g_value_set_boolean (value, v_boolean: priv->support_selection);
488 break;
489 case PROP_N_PAGES_TO_PRINT:
490 g_value_set_int (value, v_int: priv->nr_of_pages_to_print);
491 break;
492 default:
493 G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
494 break;
495 }
496}
497
498struct _PrintPagesData
499{
500 GtkPrintOperation *op;
501 int uncollated_copies;
502 int collated_copies;
503 int uncollated, collated, total;
504
505 int range, num_ranges;
506 GtkPageRange *ranges;
507 GtkPageRange one_range;
508
509 int page;
510 int sheet;
511 int first_position, last_position;
512 int first_sheet;
513 int num_of_sheets;
514 int *pages;
515
516 GtkWidget *progress;
517
518 gboolean initialized;
519 gboolean is_preview;
520 gboolean done;
521};
522
523typedef struct
524{
525 GtkPrintOperationPreview *preview;
526 GtkPrintContext *print_context;
527 GtkWindow *parent;
528 cairo_surface_t *surface;
529 char *filename;
530 gboolean wait;
531 PrintPagesData *pages_data;
532} PreviewOp;
533
534static void
535preview_print_idle_done (gpointer data)
536{
537 GtkPrintOperation *op;
538 PreviewOp *pop = (PreviewOp *) data;
539
540 op = GTK_PRINT_OPERATION (pop->preview);
541
542 cairo_surface_finish (surface: pop->surface);
543
544 if (op->priv->status == GTK_PRINT_STATUS_FINISHED_ABORTED)
545 {
546 cairo_surface_destroy (surface: pop->surface);
547 }
548 else
549 {
550 /* Surface is destroyed in launch_preview */
551 _gtk_print_operation_platform_backend_launch_preview (op,
552 surface: pop->surface,
553 parent: pop->parent,
554 filename: pop->filename);
555 }
556
557 g_free (mem: pop->filename);
558
559 gtk_print_operation_preview_end_preview (preview: pop->preview);
560
561 g_object_unref (object: pop->pages_data->op);
562 g_free (mem: pop->pages_data->pages);
563 g_free (mem: pop->pages_data);
564
565 g_object_unref (object: op);
566 g_free (mem: pop);
567}
568
569static gboolean
570preview_print_idle (gpointer data)
571{
572 PreviewOp *pop = (PreviewOp *) data;
573 GtkPrintOperation *op = GTK_PRINT_OPERATION (pop->preview);
574 GtkPrintOperationPrivate *priv = gtk_print_operation_get_instance_private (self: op);
575 gboolean done = FALSE;
576
577 if (priv->page_drawing_state == GTK_PAGE_DRAWING_STATE_READY)
578 {
579 if (priv->cancelled)
580 {
581 done = TRUE;
582 _gtk_print_operation_set_status (op, status: GTK_PRINT_STATUS_FINISHED_ABORTED, NULL);
583 }
584 else if (!pop->pages_data->initialized)
585 {
586 pop->pages_data->initialized = TRUE;
587 prepare_data (data: pop->pages_data);
588 }
589 else
590 {
591 increment_page_sequence (data: pop->pages_data);
592
593 if (!pop->pages_data->done)
594 gtk_print_operation_preview_render_page (preview: pop->preview, page_nr: pop->pages_data->page);
595 else
596 done = priv->page_drawing_state == GTK_PAGE_DRAWING_STATE_READY;
597 }
598 }
599
600 return !done;
601}
602
603static void
604preview_got_page_size (GtkPrintOperationPreview *preview,
605 GtkPrintContext *context,
606 GtkPageSetup *page_setup,
607 PreviewOp *pop)
608{
609 GtkPrintOperation *op = GTK_PRINT_OPERATION (preview);
610 cairo_t *cr;
611
612 _gtk_print_operation_platform_backend_resize_preview_surface (op, page_setup, surface: pop->surface);
613
614 cr = gtk_print_context_get_cairo_context (context: pop->print_context);
615 _gtk_print_operation_platform_backend_preview_start_page (op, surface: pop->surface, cr);
616
617}
618
619static void
620preview_ready (GtkPrintOperationPreview *preview,
621 GtkPrintContext *context,
622 PreviewOp *pop)
623{
624 guint id;
625
626 pop->print_context = context;
627
628 g_object_ref (preview);
629
630 id = g_idle_add_full (G_PRIORITY_DEFAULT_IDLE + 10,
631 function: preview_print_idle,
632 data: pop,
633 notify: preview_print_idle_done);
634 gdk_source_set_static_name_by_id (tag: id, name: "[gtk] preview_print_idle");
635}
636
637
638static gboolean
639gtk_print_operation_preview_handler (GtkPrintOperation *op,
640 GtkPrintOperationPreview *preview,
641 GtkPrintContext *context,
642 GtkWindow *parent)
643{
644 double dpi_x, dpi_y;
645 PreviewOp *pop;
646 GtkPageSetup *page_setup;
647 cairo_t *cr;
648
649 pop = g_new0 (PreviewOp, 1);
650 pop->filename = NULL;
651 pop->preview = preview;
652 pop->parent = parent;
653 pop->pages_data = g_new0 (PrintPagesData, 1);
654 pop->pages_data->op = g_object_ref (GTK_PRINT_OPERATION (preview));
655 pop->pages_data->is_preview = TRUE;
656
657 page_setup = gtk_print_context_get_page_setup (context);
658
659 pop->surface =
660 _gtk_print_operation_platform_backend_create_preview_surface (op,
661 page_setup,
662 dpi_x: &dpi_x, dpi_y: &dpi_y,
663 target: &pop->filename);
664
665 if (pop->surface == NULL)
666 {
667 g_free (mem: pop);
668 return FALSE;
669 }
670
671 cr = cairo_create (target: pop->surface);
672 gtk_print_context_set_cairo_context (context: op->priv->print_context, cr,
673 dpi_x, dpi_y);
674 cairo_destroy (cr);
675
676 g_signal_connect (preview, "ready", (GCallback) preview_ready, pop);
677 g_signal_connect (preview, "got-page-size", (GCallback) preview_got_page_size, pop);
678
679 return TRUE;
680}
681
682static GtkWidget *
683gtk_print_operation_create_custom_widget (GtkPrintOperation *operation)
684{
685 return NULL;
686}
687
688static gboolean
689gtk_print_operation_paginate (GtkPrintOperation *operation,
690 GtkPrintContext *context)
691{
692 /* assume the number of pages is already set and pagination is not needed */
693 return TRUE;
694}
695
696static void
697gtk_print_operation_done (GtkPrintOperation *operation,
698 GtkPrintOperationResult result)
699{
700 GtkPrintOperationPrivate *priv = gtk_print_operation_get_instance_private (self: operation);
701
702 if (priv->print_context)
703 {
704 g_object_unref (object: priv->print_context);
705 priv->print_context = NULL;
706 }
707}
708
709static gboolean
710custom_widget_accumulator (GSignalInvocationHint *ihint,
711 GValue *return_accu,
712 const GValue *handler_return,
713 gpointer dummy)
714{
715 gboolean continue_emission;
716 GtkWidget *widget;
717
718 widget = g_value_get_object (value: handler_return);
719 if (widget != NULL)
720 g_value_set_object (value: return_accu, v_object: widget);
721 continue_emission = (widget == NULL);
722
723 return continue_emission;
724}
725
726static gboolean
727paginate_accumulator (GSignalInvocationHint *ihint,
728 GValue *return_accu,
729 const GValue *handler_return,
730 gpointer dummy)
731{
732 *return_accu = *handler_return;
733
734 /* Stop signal emission on first invocation, so if it's a callback then
735 * the default handler won't run. */
736 return FALSE;
737}
738
739static void
740gtk_print_operation_class_init (GtkPrintOperationClass *class)
741{
742 GObjectClass *gobject_class = (GObjectClass *)class;
743
744 gobject_class->set_property = gtk_print_operation_set_property;
745 gobject_class->get_property = gtk_print_operation_get_property;
746 gobject_class->finalize = gtk_print_operation_finalize;
747
748 class->preview = gtk_print_operation_preview_handler;
749 class->create_custom_widget = gtk_print_operation_create_custom_widget;
750 class->paginate = gtk_print_operation_paginate;
751 class->done = gtk_print_operation_done;
752
753 /**
754 * GtkPrintOperation::done:
755 * @operation: the `GtkPrintOperation` on which the signal was emitted
756 * @result: the result of the print operation
757 *
758 * Emitted when the print operation run has finished doing
759 * everything required for printing.
760 *
761 * @result gives you information about what happened during the run.
762 * If @result is %GTK_PRINT_OPERATION_RESULT_ERROR then you can call
763 * [method@Gtk.PrintOperation.get_error] for more information.
764 *
765 * If you enabled print status tracking then
766 * [method@Gtk.PrintOperation.is_finished] may still return %FALSE
767 * after the ::done signal was emitted.
768 */
769 signals[DONE] =
770 g_signal_new (I_("done"),
771 G_TYPE_FROM_CLASS (gobject_class),
772 signal_flags: G_SIGNAL_RUN_LAST,
773 G_STRUCT_OFFSET (GtkPrintOperationClass, done),
774 NULL, NULL,
775 NULL,
776 G_TYPE_NONE, n_params: 1, GTK_TYPE_PRINT_OPERATION_RESULT);
777
778 /**
779 * GtkPrintOperation::begin-print:
780 * @operation: the `GtkPrintOperation` on which the signal was emitted
781 * @context: the `GtkPrintContext` for the current operation
782 *
783 * Emitted after the user has finished changing print settings
784 * in the dialog, before the actual rendering starts.
785 *
786 * A typical use for ::begin-print is to use the parameters from the
787 * [class@Gtk.PrintContext] and paginate the document accordingly,
788 * and then set the number of pages with
789 * [method@Gtk.PrintOperation.set_n_pages].
790 */
791 signals[BEGIN_PRINT] =
792 g_signal_new (I_("begin-print"),
793 G_TYPE_FROM_CLASS (gobject_class),
794 signal_flags: G_SIGNAL_RUN_LAST,
795 G_STRUCT_OFFSET (GtkPrintOperationClass, begin_print),
796 NULL, NULL,
797 NULL,
798 G_TYPE_NONE, n_params: 1, GTK_TYPE_PRINT_CONTEXT);
799
800 /**
801 * GtkPrintOperation::paginate:
802 * @operation: the `GtkPrintOperation` on which the signal was emitted
803 * @context: the `GtkPrintContext` for the current operation
804 *
805 * Emitted after the ::begin-print signal, but before the actual rendering
806 * starts.
807 *
808 * It keeps getting emitted until a connected signal handler returns %TRUE.
809 *
810 * The ::paginate signal is intended to be used for paginating a document
811 * in small chunks, to avoid blocking the user interface for a long
812 * time. The signal handler should update the number of pages using
813 * [method@Gtk.PrintOperation.set_n_pages], and return %TRUE if the document
814 * has been completely paginated.
815 *
816 * If you don't need to do pagination in chunks, you can simply do
817 * it all in the ::begin-print handler, and set the number of pages
818 * from there.
819 *
820 * Returns: %TRUE if pagination is complete
821 */
822 signals[PAGINATE] =
823 g_signal_new (I_("paginate"),
824 G_TYPE_FROM_CLASS (gobject_class),
825 signal_flags: G_SIGNAL_RUN_LAST,
826 G_STRUCT_OFFSET (GtkPrintOperationClass, paginate),
827 accumulator: paginate_accumulator, NULL,
828 c_marshaller: _gtk_marshal_BOOLEAN__OBJECT,
829 G_TYPE_BOOLEAN, n_params: 1, GTK_TYPE_PRINT_CONTEXT);
830
831
832 /**
833 * GtkPrintOperation::request-page-setup:
834 * @operation: the `GtkPrintOperation` on which the signal was emitted
835 * @context: the `GtkPrintContext` for the current operation
836 * @page_nr: the number of the currently printed page (0-based)
837 * @setup: the `GtkPageSetup`
838 *
839 * Emitted once for every page that is printed.
840 *
841 * This gives the application a chance to modify the page setup.
842 * Any changes done to @setup will be in force only for printing
843 * this page.
844 */
845 signals[REQUEST_PAGE_SETUP] =
846 g_signal_new (I_("request-page-setup"),
847 G_TYPE_FROM_CLASS (gobject_class),
848 signal_flags: G_SIGNAL_RUN_LAST,
849 G_STRUCT_OFFSET (GtkPrintOperationClass, request_page_setup),
850 NULL, NULL,
851 c_marshaller: _gtk_marshal_VOID__OBJECT_INT_OBJECT,
852 G_TYPE_NONE, n_params: 3,
853 GTK_TYPE_PRINT_CONTEXT,
854 G_TYPE_INT,
855 GTK_TYPE_PAGE_SETUP);
856
857 /**
858 * GtkPrintOperation::draw-page:
859 * @operation: the `GtkPrintOperation` on which the signal was emitted
860 * @context: the `GtkPrintContext` for the current operation
861 * @page_nr: the number of the currently printed page (0-based)
862 *
863 * Emitted for every page that is printed.
864 *
865 * The signal handler must render the @page_nr's page onto the cairo
866 * context obtained from @context using
867 * [method@Gtk.PrintContext.get_cairo_context].
868 *
869 * ```c
870 * static void
871 * draw_page (GtkPrintOperation *operation,
872 * GtkPrintContext *context,
873 * int page_nr,
874 * gpointer user_data)
875 * {
876 * cairo_t *cr;
877 * PangoLayout *layout;
878 * double width, text_height;
879 * int layout_height;
880 * PangoFontDescription *desc;
881 *
882 * cr = gtk_print_context_get_cairo_context (context);
883 * width = gtk_print_context_get_width (context);
884 *
885 * cairo_rectangle (cr, 0, 0, width, HEADER_HEIGHT);
886 *
887 * cairo_set_source_rgb (cr, 0.8, 0.8, 0.8);
888 * cairo_fill (cr);
889 *
890 * layout = gtk_print_context_create_pango_layout (context);
891 *
892 * desc = pango_font_description_from_string ("sans 14");
893 * pango_layout_set_font_description (layout, desc);
894 * pango_font_description_free (desc);
895 *
896 * pango_layout_set_text (layout, "some text", -1);
897 * pango_layout_set_width (layout, width * PANGO_SCALE);
898 * pango_layout_set_alignment (layout, PANGO_ALIGN_CENTER);
899 *
900 * pango_layout_get_size (layout, NULL, &layout_height);
901 * text_height = (double)layout_height / PANGO_SCALE;
902 *
903 * cairo_move_to (cr, width / 2, (HEADER_HEIGHT - text_height) / 2);
904 * pango_cairo_show_layout (cr, layout);
905 *
906 * g_object_unref (layout);
907 * }
908 * ```
909 *
910 * Use [method@Gtk.PrintOperation.set_use_full_page] and
911 * [method@Gtk.PrintOperation.set_unit] before starting the print
912 * operation to set up the transformation of the cairo context
913 * according to your needs.
914 */
915 signals[DRAW_PAGE] =
916 g_signal_new (I_("draw-page"),
917 G_TYPE_FROM_CLASS (gobject_class),
918 signal_flags: G_SIGNAL_RUN_LAST,
919 G_STRUCT_OFFSET (GtkPrintOperationClass, draw_page),
920 NULL, NULL,
921 c_marshaller: _gtk_marshal_VOID__OBJECT_INT,
922 G_TYPE_NONE, n_params: 2,
923 GTK_TYPE_PRINT_CONTEXT,
924 G_TYPE_INT);
925
926 /**
927 * GtkPrintOperation::end-print:
928 * @operation: the `GtkPrintOperation` on which the signal was emitted
929 * @context: the `GtkPrintContext` for the current operation
930 *
931 * Emitted after all pages have been rendered.
932 *
933 * A handler for this signal can clean up any resources that have
934 * been allocated in the [signal@Gtk.PrintOperation::begin-print] handler.
935 */
936 signals[END_PRINT] =
937 g_signal_new (I_("end-print"),
938 G_TYPE_FROM_CLASS (gobject_class),
939 signal_flags: G_SIGNAL_RUN_LAST,
940 G_STRUCT_OFFSET (GtkPrintOperationClass, end_print),
941 NULL, NULL,
942 NULL,
943 G_TYPE_NONE, n_params: 1, GTK_TYPE_PRINT_CONTEXT);
944
945 /**
946 * GtkPrintOperation::status-changed:
947 * @operation: the `GtkPrintOperation` on which the signal was emitted
948 *
949 * Emitted at between the various phases of the print operation.
950 *
951 * See [enum@Gtk.PrintStatus] for the phases that are being discriminated.
952 * Use [method@Gtk.PrintOperation.get_status] to find out the current
953 * status.
954 */
955 signals[STATUS_CHANGED] =
956 g_signal_new (I_("status-changed"),
957 G_TYPE_FROM_CLASS (class),
958 signal_flags: G_SIGNAL_RUN_LAST,
959 G_STRUCT_OFFSET (GtkPrintOperationClass, status_changed),
960 NULL, NULL,
961 NULL,
962 G_TYPE_NONE, n_params: 0);
963
964
965 /**
966 * GtkPrintOperation::create-custom-widget:
967 * @operation: the `GtkPrintOperation` on which the signal was emitted
968 *
969 * Emitted when displaying the print dialog.
970 *
971 * If you return a widget in a handler for this signal it will be
972 * added to a custom tab in the print dialog. You typically return a
973 * container widget with multiple widgets in it.
974 *
975 * The print dialog owns the returned widget, and its lifetime is not
976 * controlled by the application. However, the widget is guaranteed
977 * to stay around until the [signal@Gtk.PrintOperation::custom-widget-apply]
978 * signal is emitted on the operation. Then you can read out any
979 * information you need from the widgets.
980 *
981 * Returns: (nullable) (transfer none): A custom widget that gets embedded in
982 * the print dialog
983 */
984 signals[CREATE_CUSTOM_WIDGET] =
985 g_signal_new (I_("create-custom-widget"),
986 G_TYPE_FROM_CLASS (class),
987 signal_flags: G_SIGNAL_RUN_LAST,
988 G_STRUCT_OFFSET (GtkPrintOperationClass, create_custom_widget),
989 accumulator: custom_widget_accumulator, NULL,
990 c_marshaller: _gtk_marshal_OBJECT__VOID,
991 G_TYPE_OBJECT, n_params: 0);
992
993 /**
994 * GtkPrintOperation::update-custom-widget:
995 * @operation: the `GtkPrintOperation` on which the signal was emitted
996 * @widget: the custom widget added in ::create-custom-widget
997 * @setup: actual page setup
998 * @settings: actual print settings
999 *
1000 * Emitted after change of selected printer.
1001 *
1002 * The actual page setup and print settings are passed to the custom
1003 * widget, which can actualize itself according to this change.
1004 */
1005 signals[UPDATE_CUSTOM_WIDGET] =
1006 g_signal_new (I_("update-custom-widget"),
1007 G_TYPE_FROM_CLASS (class),
1008 signal_flags: G_SIGNAL_RUN_LAST,
1009 G_STRUCT_OFFSET (GtkPrintOperationClass, update_custom_widget),
1010 NULL, NULL,
1011 c_marshaller: _gtk_marshal_VOID__OBJECT_OBJECT_OBJECT,
1012 G_TYPE_NONE, n_params: 3, GTK_TYPE_WIDGET, GTK_TYPE_PAGE_SETUP, GTK_TYPE_PRINT_SETTINGS);
1013
1014 /**
1015 * GtkPrintOperation::custom-widget-apply:
1016 * @operation: the `GtkPrintOperation` on which the signal was emitted
1017 * @widget: the custom widget added in ::create-custom-widget
1018 *
1019 * Emitted right before ::begin-print if you added
1020 * a custom widget in the ::create-custom-widget handler.
1021 *
1022 * When you get this signal you should read the information from the
1023 * custom widgets, as the widgets are not guaranteed to be around at a
1024 * later time.
1025 */
1026 signals[CUSTOM_WIDGET_APPLY] =
1027 g_signal_new (I_("custom-widget-apply"),
1028 G_TYPE_FROM_CLASS (class),
1029 signal_flags: G_SIGNAL_RUN_LAST,
1030 G_STRUCT_OFFSET (GtkPrintOperationClass, custom_widget_apply),
1031 NULL, NULL,
1032 NULL,
1033 G_TYPE_NONE, n_params: 1, GTK_TYPE_WIDGET);
1034
1035 /**
1036 * GtkPrintOperation::preview:
1037 * @operation: the `GtkPrintOperation` on which the signal was emitted
1038 * @preview: the `GtkPrintOperationPreview` for the current operation
1039 * @context: the `GtkPrintContext` that will be used
1040 * @parent: (nullable): the `GtkWindow` to use as window parent
1041 *
1042 * Gets emitted when a preview is requested from the native dialog.
1043 *
1044 * The default handler for this signal uses an external viewer
1045 * application to preview.
1046 *
1047 * To implement a custom print preview, an application must return
1048 * %TRUE from its handler for this signal. In order to use the
1049 * provided @context for the preview implementation, it must be
1050 * given a suitable cairo context with
1051 * [method@Gtk.PrintContext.set_cairo_context].
1052 *
1053 * The custom preview implementation can use
1054 * [method@Gtk.PrintOperationPreview.is_selected] and
1055 * [method@Gtk.PrintOperationPreview.render_page] to find pages which
1056 * are selected for print and render them. The preview must be
1057 * finished by calling [method@Gtk.PrintOperationPreview.end_preview]
1058 * (typically in response to the user clicking a close button).
1059 *
1060 * Returns: %TRUE if the listener wants to take over control of the preview
1061 */
1062 signals[PREVIEW] =
1063 g_signal_new (I_("preview"),
1064 G_TYPE_FROM_CLASS (gobject_class),
1065 signal_flags: G_SIGNAL_RUN_LAST,
1066 G_STRUCT_OFFSET (GtkPrintOperationClass, preview),
1067 accumulator: _gtk_boolean_handled_accumulator, NULL,
1068 c_marshaller: _gtk_marshal_BOOLEAN__OBJECT_OBJECT_OBJECT,
1069 G_TYPE_BOOLEAN, n_params: 3,
1070 GTK_TYPE_PRINT_OPERATION_PREVIEW,
1071 GTK_TYPE_PRINT_CONTEXT,
1072 GTK_TYPE_WINDOW);
1073
1074 /**
1075 * GtkPrintOperation:default-page-setup: (attributes org.gtk.Property.get=gtk_print_operation_get_default_page_setup org.gtk.Property.set=gtk_print_operation_set_default_page_setup)
1076 *
1077 * The `GtkPageSetup` used by default.
1078 *
1079 * This page setup will be used by [method@Gtk.PrintOperation.run],
1080 * but it can be overridden on a per-page basis by connecting
1081 * to the [signal@Gtk.PrintOperation::request-page-setup] signal.
1082 */
1083 g_object_class_install_property (oclass: gobject_class,
1084 property_id: PROP_DEFAULT_PAGE_SETUP,
1085 pspec: g_param_spec_object (name: "default-page-setup",
1086 P_("Default Page Setup"),
1087 P_("The GtkPageSetup used by default"),
1088 GTK_TYPE_PAGE_SETUP,
1089 GTK_PARAM_READWRITE));
1090
1091 /**
1092 * GtkPrintOperation:print-settings: (attributes org.gtk.Property.get=gtk_print_operation_get_print_settings org.gtk.Property.set=gtk_print_operation_set_print_settings)
1093 *
1094 * The `GtkPrintSettings` used for initializing the dialog.
1095 *
1096 * Setting this property is typically used to re-establish
1097 * print settings from a previous print operation, see
1098 * [method@Gtk.PrintOperation.run].
1099 */
1100 g_object_class_install_property (oclass: gobject_class,
1101 property_id: PROP_PRINT_SETTINGS,
1102 pspec: g_param_spec_object (name: "print-settings",
1103 P_("Print Settings"),
1104 P_("The GtkPrintSettings used for initializing the dialog"),
1105 GTK_TYPE_PRINT_SETTINGS,
1106 GTK_PARAM_READWRITE));
1107
1108 /**
1109 * GtkPrintOperation:job-name: (attributes org.gtk.Property.set=gtk_print_operation_set_job_name)
1110 *
1111 * A string used to identify the job (e.g. in monitoring
1112 * applications like eggcups).
1113 *
1114 * If you don't set a job name, GTK picks a default one
1115 * by numbering successive print jobs.
1116 */
1117 g_object_class_install_property (oclass: gobject_class,
1118 property_id: PROP_JOB_NAME,
1119 pspec: g_param_spec_string (name: "job-name",
1120 P_("Job Name"),
1121 P_("A string used for identifying the print job."),
1122 default_value: "",
1123 GTK_PARAM_READWRITE));
1124
1125 /**
1126 * GtkPrintOperation:n-pages: (attributes org.gtk.Property.set=gtk_print_operation_set_n_pages)
1127 *
1128 * The number of pages in the document.
1129 *
1130 * This must be set to a positive number before the rendering
1131 * starts. It may be set in a [signal@Gtk.PrintOperation::begin-print]
1132 * signal handler.
1133 *
1134 * Note that the page numbers passed to the
1135 * [signal@Gtk.PrintOperation::request-page-setup] and
1136 * [signal@Gtk.PrintOperation::draw-page] signals are 0-based, i.e.
1137 * if the user chooses to print all pages, the last ::draw-page signal
1138 * will be for page @n_pages - 1.
1139 */
1140 g_object_class_install_property (oclass: gobject_class,
1141 property_id: PROP_N_PAGES,
1142 pspec: g_param_spec_int (name: "n-pages",
1143 P_("Number of Pages"),
1144 P_("The number of pages in the document."),
1145 minimum: -1,
1146 G_MAXINT,
1147 default_value: -1,
1148 GTK_PARAM_READWRITE|G_PARAM_EXPLICIT_NOTIFY));
1149
1150 /**
1151 * GtkPrintOperation:current-page: (attributes org.gtk.Property.set=gtk_print_operation_set_current_page)
1152 *
1153 * The current page in the document.
1154 *
1155 * If this is set before [method@Gtk.PrintOperation.run],
1156 * the user will be able to select to print only the current page.
1157 *
1158 * Note that this only makes sense for pre-paginated documents.
1159 */
1160 g_object_class_install_property (oclass: gobject_class,
1161 property_id: PROP_CURRENT_PAGE,
1162 pspec: g_param_spec_int (name: "current-page",
1163 P_("Current Page"),
1164 P_("The current page in the document"),
1165 minimum: -1,
1166 G_MAXINT,
1167 default_value: -1,
1168 GTK_PARAM_READWRITE|G_PARAM_EXPLICIT_NOTIFY));
1169
1170 /**
1171 * GtkPrintOperation:use-full-page: (attributes org.gtk.Property.set=gtk_print_operation_set_use_full_page)
1172 *
1173 * If %TRUE, the transformation for the cairo context obtained
1174 * from `GtkPrintContext` puts the origin at the top left corner
1175 * of the page.
1176 *
1177 * This may not be the top left corner of the sheet, depending on
1178 * page orientation and the number of pages per sheet. Otherwise,
1179 * the origin is at the top left corner of the imageable area (i.e.
1180 * inside the margins).
1181 */
1182 g_object_class_install_property (oclass: gobject_class,
1183 property_id: PROP_USE_FULL_PAGE,
1184 pspec: g_param_spec_boolean (name: "use-full-page",
1185 P_("Use full page"),
1186 P_("TRUE if the origin of the context should be at the corner of the page and not the corner of the imageable area"),
1187 FALSE,
1188 GTK_PARAM_READWRITE|G_PARAM_EXPLICIT_NOTIFY));
1189
1190 /**
1191 * GtkPrintOperation:track-print-status: (attributes org.gtk.Property.set=gtk_print_operation_set_track_print_status)
1192 *
1193 * If %TRUE, the print operation will try to continue report on
1194 * the status of the print job in the printer queues and printer.
1195 *
1196 * This can allow your application to show things like “out of paper”
1197 * issues, and when the print job actually reaches the printer.
1198 * However, this is often implemented using polling, and should
1199 * not be enabled unless needed.
1200 */
1201 g_object_class_install_property (oclass: gobject_class,
1202 property_id: PROP_TRACK_PRINT_STATUS,
1203 pspec: g_param_spec_boolean (name: "track-print-status",
1204 P_("Track Print Status"),
1205 P_("TRUE if the print operation will continue to report on the print job status after the print data has been sent to the printer or print server."),
1206 FALSE,
1207 GTK_PARAM_READWRITE|G_PARAM_EXPLICIT_NOTIFY));
1208
1209 /**
1210 * GtkPrintOperation:unit: (attributes org.gtk.Property.set=gtk_print_operation_set_unit)
1211 *
1212 * The transformation for the cairo context obtained from
1213 * `GtkPrintContext` is set up in such a way that distances
1214 * are measured in units of @unit.
1215 */
1216 g_object_class_install_property (oclass: gobject_class,
1217 property_id: PROP_UNIT,
1218 pspec: g_param_spec_enum (name: "unit",
1219 P_("Unit"),
1220 P_("The unit in which distances can be measured in the context"),
1221 enum_type: GTK_TYPE_UNIT,
1222 default_value: GTK_UNIT_NONE,
1223 GTK_PARAM_READWRITE|G_PARAM_EXPLICIT_NOTIFY));
1224
1225 /**
1226 * GtkPrintOperation:show-progress: (attributes org.gtk.Property.set=gtk_print_operation_set_show_progress)
1227 *
1228 * Determines whether to show a progress dialog during the
1229 * print operation.
1230 */
1231 g_object_class_install_property (oclass: gobject_class,
1232 property_id: PROP_SHOW_PROGRESS,
1233 pspec: g_param_spec_boolean (name: "show-progress",
1234 P_("Show Dialog"),
1235 P_("TRUE if a progress dialog is shown while printing."),
1236 FALSE,
1237 GTK_PARAM_READWRITE|G_PARAM_EXPLICIT_NOTIFY));
1238
1239 /**
1240 * GtkPrintOperation:allow-async: (attributes org.gtk.Property.set=gtk_print_operation_set_allow_async)
1241 *
1242 * Determines whether the print operation may run asynchronously or not.
1243 *
1244 * Some systems don't support asynchronous printing, but those that do
1245 * will return %GTK_PRINT_OPERATION_RESULT_IN_PROGRESS as the status, and
1246 * emit the [signal@Gtk.PrintOperation::done] signal when the operation
1247 * is actually done.
1248 *
1249 * The Windows port does not support asynchronous operation at all (this
1250 * is unlikely to change). On other platforms, all actions except for
1251 * %GTK_PRINT_OPERATION_ACTION_EXPORT support asynchronous operation.
1252 */
1253 g_object_class_install_property (oclass: gobject_class,
1254 property_id: PROP_ALLOW_ASYNC,
1255 pspec: g_param_spec_boolean (name: "allow-async",
1256 P_("Allow Async"),
1257 P_("TRUE if print process may run asynchronous."),
1258 FALSE,
1259 GTK_PARAM_READWRITE|G_PARAM_EXPLICIT_NOTIFY));
1260
1261 /**
1262 * GtkPrintOperation:export-filename: (attributes org.gtk.Property.set=gtk_print_operation_set_export_filename)
1263 *
1264 * The name of a file to generate instead of showing the print dialog.
1265 *
1266 * Currently, PDF is the only supported format.
1267 *
1268 * The intended use of this property is for implementing
1269 * “Export to PDF” actions.
1270 *
1271 * “Print to PDF” support is independent of this and is done
1272 * by letting the user pick the “Print to PDF” item from the
1273 * list of printers in the print dialog.
1274 */
1275 g_object_class_install_property (oclass: gobject_class,
1276 property_id: PROP_EXPORT_FILENAME,
1277 pspec: g_param_spec_string (name: "export-filename",
1278 P_("Export filename"),
1279 P_("Export filename"),
1280 NULL,
1281 GTK_PARAM_READWRITE));
1282
1283 /**
1284 * GtkPrintOperation:status: (attributes org.gtk.Property.get=gtk_print_operation_get_status)
1285 *
1286 * The status of the print operation.
1287 */
1288 g_object_class_install_property (oclass: gobject_class,
1289 property_id: PROP_STATUS,
1290 pspec: g_param_spec_enum (name: "status",
1291 P_("Status"),
1292 P_("The status of the print operation"),
1293 enum_type: GTK_TYPE_PRINT_STATUS,
1294 default_value: GTK_PRINT_STATUS_INITIAL,
1295 GTK_PARAM_READABLE|G_PARAM_EXPLICIT_NOTIFY));
1296
1297 /**
1298 * GtkPrintOperation:status-string: (attributes org.gtk.Property.get=gtk_print_operation_get_status_string)
1299 *
1300 * A string representation of the status of the print operation.
1301 *
1302 * The string is translated and suitable for displaying the print
1303 * status e.g. in a `GtkStatusbar`.
1304 *
1305 * See the [property@Gtk.PrintOperation:status] property for a status
1306 * value that is suitable for programmatic use.
1307 */
1308 g_object_class_install_property (oclass: gobject_class,
1309 property_id: PROP_STATUS_STRING,
1310 pspec: g_param_spec_string (name: "status-string",
1311 P_("Status String"),
1312 P_("A human-readable description of the status"),
1313 default_value: "",
1314 GTK_PARAM_READABLE));
1315
1316
1317 /**
1318 * GtkPrintOperation:custom-tab-label: (attributes org.gtk.Property.set=gtk_print_operation_set_custom_tab_label)
1319 *
1320 * Used as the label of the tab containing custom widgets.
1321 *
1322 * Note that this property may be ignored on some platforms.
1323 *
1324 * If this is %NULL, GTK uses a default label.
1325 */
1326 g_object_class_install_property (oclass: gobject_class,
1327 property_id: PROP_CUSTOM_TAB_LABEL,
1328 pspec: g_param_spec_string (name: "custom-tab-label",
1329 P_("Custom tab label"),
1330 P_("Label for the tab containing custom widgets."),
1331 NULL,
1332 GTK_PARAM_READWRITE));
1333
1334 /**
1335 * GtkPrintOperation:support-selection: (attributes org.gtk.Property.get=gtk_print_operation_get_support_selection org.gtk.Property.set=gtk_print_operation_set_support_selection)
1336 *
1337 * If %TRUE, the print operation will support print of selection.
1338 *
1339 * This allows the print dialog to show a "Selection" button.
1340 */
1341 g_object_class_install_property (oclass: gobject_class,
1342 property_id: PROP_SUPPORT_SELECTION,
1343 pspec: g_param_spec_boolean (name: "support-selection",
1344 P_("Support Selection"),
1345 P_("TRUE if the print operation will support print of selection."),
1346 FALSE,
1347 GTK_PARAM_READWRITE|G_PARAM_EXPLICIT_NOTIFY));
1348
1349 /**
1350 * GtkPrintOperation:has-selection: (attributes org.gtk.Property.get=gtk_print_operation_get_has_selection org.gtk.Property.set=gtk_print_operation_set_has_selection)
1351 *
1352 * Determines whether there is a selection in your application.
1353 *
1354 * This can allow your application to print the selection.
1355 * This is typically used to make a "Selection" button sensitive.
1356 */
1357 g_object_class_install_property (oclass: gobject_class,
1358 property_id: PROP_HAS_SELECTION,
1359 pspec: g_param_spec_boolean (name: "has-selection",
1360 P_("Has Selection"),
1361 P_("TRUE if a selection exists."),
1362 FALSE,
1363 GTK_PARAM_READWRITE|G_PARAM_EXPLICIT_NOTIFY));
1364
1365
1366 /**
1367 * GtkPrintOperation:embed-page-setup: (attributes org.gtk.Property.get=gtk_print_operation_get_embed_page_setup org.gtk.Property.set=gtk_print_operation_set_embed_page_setup)
1368 *
1369 * If %TRUE, page size combo box and orientation combo box
1370 * are embedded into page setup page.
1371 */
1372 g_object_class_install_property (oclass: gobject_class,
1373 property_id: PROP_EMBED_PAGE_SETUP,
1374 pspec: g_param_spec_boolean (name: "embed-page-setup",
1375 P_("Embed Page Setup"),
1376 P_("TRUE if page setup combos are embedded in GtkPrintUnixDialog"),
1377 FALSE,
1378 GTK_PARAM_READWRITE|G_PARAM_EXPLICIT_NOTIFY));
1379
1380 /**
1381 * GtkPrintOperation:n-pages-to-print: (attributes org.gtk.Property.get=gtk_print_operation_get_n_pages_to_print)
1382 *
1383 * The number of pages that will be printed.
1384 *
1385 * Note that this value is set during print preparation phase
1386 * (%GTK_PRINT_STATUS_PREPARING), so this value should never be
1387 * get before the data generation phase (%GTK_PRINT_STATUS_GENERATING_DATA).
1388 * You can connect to the [signal@Gtk.PrintOperation::status-changed] signal
1389 * and call [method@Gtk.PrintOperation.get_n_pages_to_print] when
1390 * print status is %GTK_PRINT_STATUS_GENERATING_DATA.
1391 *
1392 * This is typically used to track the progress of print operation.
1393 */
1394 g_object_class_install_property (oclass: gobject_class,
1395 property_id: PROP_N_PAGES_TO_PRINT,
1396 pspec: g_param_spec_int (name: "n-pages-to-print",
1397 P_("Number of Pages To Print"),
1398 P_("The number of pages that will be printed."),
1399 minimum: -1,
1400 G_MAXINT,
1401 default_value: -1,
1402 GTK_PARAM_READABLE|G_PARAM_EXPLICIT_NOTIFY));
1403}
1404
1405/**
1406 * gtk_print_operation_new:
1407 *
1408 * Creates a new `GtkPrintOperation`.
1409 *
1410 * Returns: a new `GtkPrintOperation`
1411 */
1412GtkPrintOperation *
1413gtk_print_operation_new (void)
1414{
1415 GtkPrintOperation *print_operation;
1416
1417 print_operation = g_object_new (GTK_TYPE_PRINT_OPERATION, NULL);
1418
1419 return print_operation;
1420}
1421
1422/**
1423 * gtk_print_operation_set_default_page_setup: (attributes org.gtk.Method.set_property=default-page-setup)
1424 * @op: a `GtkPrintOperation`
1425 * @default_page_setup: (nullable): a `GtkPageSetup`
1426 *
1427 * Makes @default_page_setup the default page setup for @op.
1428 *
1429 * This page setup will be used by [method@Gtk.PrintOperation.run],
1430 * but it can be overridden on a per-page basis by connecting
1431 * to the [signal@Gtk.PrintOperation::request-page-setup] signal.
1432 **/
1433void
1434gtk_print_operation_set_default_page_setup (GtkPrintOperation *op,
1435 GtkPageSetup *default_page_setup)
1436{
1437 GtkPrintOperationPrivate *priv = gtk_print_operation_get_instance_private (self: op);
1438
1439 g_return_if_fail (GTK_IS_PRINT_OPERATION (op));
1440 g_return_if_fail (default_page_setup == NULL ||
1441 GTK_IS_PAGE_SETUP (default_page_setup));
1442
1443 if (default_page_setup != priv->default_page_setup)
1444 {
1445 if (default_page_setup)
1446 g_object_ref (default_page_setup);
1447
1448 if (priv->default_page_setup)
1449 g_object_unref (object: priv->default_page_setup);
1450
1451 priv->default_page_setup = default_page_setup;
1452
1453 g_object_notify (G_OBJECT (op), property_name: "default-page-setup");
1454 }
1455}
1456
1457/**
1458 * gtk_print_operation_get_default_page_setup: (attributes org.gtk.Method.get_property=default-page-setup)
1459 * @op: a `GtkPrintOperation`
1460 *
1461 * Returns the default page setup.
1462 *
1463 * Returns: (transfer none): the default page setup
1464 */
1465GtkPageSetup *
1466gtk_print_operation_get_default_page_setup (GtkPrintOperation *op)
1467{
1468 g_return_val_if_fail (GTK_IS_PRINT_OPERATION (op), NULL);
1469
1470 return op->priv->default_page_setup;
1471}
1472
1473
1474/**
1475 * gtk_print_operation_set_print_settings: (attributes org.gtk.Method.set_property=print-settings)
1476 * @op: a `GtkPrintOperation`
1477 * @print_settings: (nullable): `GtkPrintSettings`
1478 *
1479 * Sets the print settings for @op.
1480 *
1481 * This is typically used to re-establish print settings
1482 * from a previous print operation, see [method@Gtk.PrintOperation.run].
1483 */
1484void
1485gtk_print_operation_set_print_settings (GtkPrintOperation *op,
1486 GtkPrintSettings *print_settings)
1487{
1488 GtkPrintOperationPrivate *priv = gtk_print_operation_get_instance_private (self: op);
1489
1490 g_return_if_fail (GTK_IS_PRINT_OPERATION (op));
1491 g_return_if_fail (print_settings == NULL ||
1492 GTK_IS_PRINT_SETTINGS (print_settings));
1493
1494 if (print_settings != priv->print_settings)
1495 {
1496 if (print_settings)
1497 g_object_ref (print_settings);
1498
1499 if (priv->print_settings)
1500 g_object_unref (object: priv->print_settings);
1501
1502 priv->print_settings = print_settings;
1503
1504 g_object_notify (G_OBJECT (op), property_name: "print-settings");
1505 }
1506}
1507
1508/**
1509 * gtk_print_operation_get_print_settings: (attributes org.gtk.Method.get_property=print-settings)
1510 * @op: a `GtkPrintOperation`
1511 *
1512 * Returns the current print settings.
1513 *
1514 * Note that the return value is %NULL until either
1515 * [method@Gtk.PrintOperation.set_print_settings] or
1516 * [method@Gtk.PrintOperation.run] have been called.
1517 *
1518 * Returns: (transfer none) (nullable): the current print settings of @op.
1519 **/
1520GtkPrintSettings *
1521gtk_print_operation_get_print_settings (GtkPrintOperation *op)
1522{
1523 g_return_val_if_fail (GTK_IS_PRINT_OPERATION (op), NULL);
1524
1525 return op->priv->print_settings;
1526}
1527
1528/**
1529 * gtk_print_operation_set_job_name: (attributes org.gtk.Method.set_property=job-name)
1530 * @op: a `GtkPrintOperation`
1531 * @job_name: a string that identifies the print job
1532 *
1533 * Sets the name of the print job.
1534 *
1535 * The name is used to identify the job (e.g. in monitoring
1536 * applications like eggcups).
1537 *
1538 * If you don’t set a job name, GTK picks a default one by
1539 * numbering successive print jobs.
1540 */
1541void
1542gtk_print_operation_set_job_name (GtkPrintOperation *op,
1543 const char *job_name)
1544{
1545 GtkPrintOperationPrivate *priv = gtk_print_operation_get_instance_private (self: op);
1546
1547 g_return_if_fail (GTK_IS_PRINT_OPERATION (op));
1548 g_return_if_fail (job_name != NULL);
1549
1550 if (g_strcmp0 (str1: priv->job_name, str2: job_name) == 0)
1551 return;
1552
1553 g_free (mem: priv->job_name);
1554 priv->job_name = g_strdup (str: job_name);
1555
1556 g_object_notify (G_OBJECT (op), property_name: "job-name");
1557}
1558
1559/**
1560 * gtk_print_operation_set_n_pages: (attributes org.gtk.Method.set_property=n-pages)
1561 * @op: a `GtkPrintOperation`
1562 * @n_pages: the number of pages
1563 *
1564 * Sets the number of pages in the document.
1565 *
1566 * This must be set to a positive number before the rendering
1567 * starts. It may be set in a [signal@Gtk.PrintOperation::begin-print]
1568 * signal handler.
1569 *
1570 * Note that the page numbers passed to the
1571 * [signal@Gtk.PrintOperation::request-page-setup]
1572 * and [signal@Gtk.PrintOperation::draw-page] signals are 0-based, i.e.
1573 * if the user chooses to print all pages, the last ::draw-page signal
1574 * will be for page @n_pages - 1.
1575 */
1576void
1577gtk_print_operation_set_n_pages (GtkPrintOperation *op,
1578 int n_pages)
1579{
1580 GtkPrintOperationPrivate *priv = gtk_print_operation_get_instance_private (self: op);
1581
1582 g_return_if_fail (GTK_IS_PRINT_OPERATION (op));
1583 g_return_if_fail (n_pages > 0);
1584 g_return_if_fail (priv->current_page == -1 ||
1585 priv->current_page < n_pages);
1586
1587 if (priv->nr_of_pages != n_pages)
1588 {
1589 priv->nr_of_pages = n_pages;
1590
1591 g_object_notify (G_OBJECT (op), property_name: "n-pages");
1592 }
1593}
1594
1595/**
1596 * gtk_print_operation_set_current_page: (attributes org.gtk.Method.set_property=current-page)
1597 * @op: a `GtkPrintOperation`
1598 * @current_page: the current page, 0-based
1599 *
1600 * Sets the current page.
1601 *
1602 * If this is called before [method@Gtk.PrintOperation.run],
1603 * the user will be able to select to print only the current page.
1604 *
1605 * Note that this only makes sense for pre-paginated documents.
1606 */
1607void
1608gtk_print_operation_set_current_page (GtkPrintOperation *op,
1609 int current_page)
1610{
1611 GtkPrintOperationPrivate *priv = gtk_print_operation_get_instance_private (self: op);
1612
1613 g_return_if_fail (GTK_IS_PRINT_OPERATION (op));
1614 g_return_if_fail (current_page >= 0);
1615 g_return_if_fail (priv->nr_of_pages == -1 ||
1616 current_page < priv->nr_of_pages);
1617
1618 if (priv->current_page != current_page)
1619 {
1620 priv->current_page = current_page;
1621
1622 g_object_notify (G_OBJECT (op), property_name: "current-page");
1623 }
1624}
1625
1626/**
1627 * gtk_print_operation_set_use_full_page: (attributes org.gtk.Method.set_property=use-full-page)
1628 * @op: a `GtkPrintOperation`
1629 * @full_page: %TRUE to set up the `GtkPrintContext` for the full page
1630 *
1631 * If @full_page is %TRUE, the transformation for the cairo context
1632 * obtained from `GtkPrintContext` puts the origin at the top left
1633 * corner of the page.
1634 *
1635 * This may not be the top left corner of the sheet, depending on page
1636 * orientation and the number of pages per sheet). Otherwise, the origin
1637 * is at the top left corner of the imageable area (i.e. inside the margins).
1638 */
1639void
1640gtk_print_operation_set_use_full_page (GtkPrintOperation *op,
1641 gboolean full_page)
1642{
1643 GtkPrintOperationPrivate *priv = gtk_print_operation_get_instance_private (self: op);
1644
1645 g_return_if_fail (GTK_IS_PRINT_OPERATION (op));
1646
1647 full_page = full_page != FALSE;
1648
1649 if (priv->use_full_page != full_page)
1650 {
1651 priv->use_full_page = full_page;
1652
1653 g_object_notify (G_OBJECT (op), property_name: "use-full-page");
1654 }
1655}
1656
1657/**
1658 * gtk_print_operation_set_unit: (attributes org.gtk.Method.set_property=unit)
1659 * @op: a `GtkPrintOperation`
1660 * @unit: the unit to use
1661 *
1662 * Sets up the transformation for the cairo context obtained from
1663 * `GtkPrintContext` in such a way that distances are measured in
1664 * units of @unit.
1665 */
1666void
1667gtk_print_operation_set_unit (GtkPrintOperation *op,
1668 GtkUnit unit)
1669{
1670 GtkPrintOperationPrivate *priv = gtk_print_operation_get_instance_private (self: op);
1671
1672 g_return_if_fail (GTK_IS_PRINT_OPERATION (op));
1673
1674 if (priv->unit != unit)
1675 {
1676 priv->unit = unit;
1677
1678 g_object_notify (G_OBJECT (op), property_name: "unit");
1679 }
1680}
1681
1682/**
1683 * gtk_print_operation_set_track_print_status: (attributes org.gtk.Method.set_property=track-print-status)
1684 * @op: a `GtkPrintOperation`
1685 * @track_status: %TRUE to track status after printing
1686 *
1687 * If track_status is %TRUE, the print operation will try to continue
1688 * report on the status of the print job in the printer queues and printer.
1689 *
1690 * This can allow your application to show things like “out of paper”
1691 * issues, and when the print job actually reaches the printer.
1692 *
1693 * This function is often implemented using some form of polling,
1694 * so it should not be enabled unless needed.
1695 */
1696void
1697gtk_print_operation_set_track_print_status (GtkPrintOperation *op,
1698 gboolean track_status)
1699{
1700 GtkPrintOperationPrivate *priv = gtk_print_operation_get_instance_private (self: op);
1701
1702 g_return_if_fail (GTK_IS_PRINT_OPERATION (op));
1703
1704 if (priv->track_print_status != track_status)
1705 {
1706 priv->track_print_status = track_status;
1707
1708 g_object_notify (G_OBJECT (op), property_name: "track-print-status");
1709 }
1710}
1711
1712void
1713_gtk_print_operation_set_status (GtkPrintOperation *op,
1714 GtkPrintStatus status,
1715 const char *string)
1716{
1717 GtkPrintOperationPrivate *priv = gtk_print_operation_get_instance_private (self: op);
1718 static const char *status_strs[] = {
1719 NC_("print operation status", "Initial state"),
1720 NC_("print operation status", "Preparing to print"),
1721 NC_("print operation status", "Generating data"),
1722 NC_("print operation status", "Sending data"),
1723 NC_("print operation status", "Waiting"),
1724 NC_("print operation status", "Blocking on issue"),
1725 NC_("print operation status", "Printing"),
1726 NC_("print operation status", "Finished"),
1727 NC_("print operation status", "Finished with error")
1728 };
1729
1730 if (status > GTK_PRINT_STATUS_FINISHED_ABORTED)
1731 status = GTK_PRINT_STATUS_FINISHED_ABORTED;
1732
1733 if (string == NULL)
1734 string = g_dpgettext2 (GETTEXT_PACKAGE, context: "print operation status", msgid: status_strs[status]);
1735
1736 if (priv->status == status &&
1737 strcmp (s1: string, s2: priv->status_string) == 0)
1738 return;
1739
1740 g_free (mem: priv->status_string);
1741 priv->status_string = g_strdup (str: string);
1742 priv->status = status;
1743
1744 g_object_notify (G_OBJECT (op), property_name: "status");
1745 g_object_notify (G_OBJECT (op), property_name: "status-string");
1746
1747 g_signal_emit (instance: op, signal_id: signals[STATUS_CHANGED], detail: 0);
1748}
1749
1750
1751/**
1752 * gtk_print_operation_get_status: (attributes org.gtk.Method.get_property=status)
1753 * @op: a `GtkPrintOperation`
1754 *
1755 * Returns the status of the print operation.
1756 *
1757 * Also see [method@Gtk.PrintOperation.get_status_string].
1758 *
1759 * Returns: the status of the print operation
1760 */
1761GtkPrintStatus
1762gtk_print_operation_get_status (GtkPrintOperation *op)
1763{
1764 g_return_val_if_fail (GTK_IS_PRINT_OPERATION (op),
1765 GTK_PRINT_STATUS_FINISHED_ABORTED);
1766
1767 return op->priv->status;
1768}
1769
1770/**
1771 * gtk_print_operation_get_status_string: (attributes org.gtk.Method.get_property=status-string)
1772 * @op: a `GtkPrintOperation`
1773 *
1774 * Returns a string representation of the status of the
1775 * print operation.
1776 *
1777 * The string is translated and suitable for displaying
1778 * the print status e.g. in a `GtkStatusbar`.
1779 *
1780 * Use [method@Gtk.PrintOperation.get_status] to obtain
1781 * a status value that is suitable for programmatic use.
1782 *
1783 * Returns: a string representation of the status
1784 * of the print operation
1785 */
1786const char *
1787gtk_print_operation_get_status_string (GtkPrintOperation *op)
1788{
1789 g_return_val_if_fail (GTK_IS_PRINT_OPERATION (op), "");
1790
1791 return op->priv->status_string;
1792}
1793
1794/**
1795 * gtk_print_operation_is_finished:
1796 * @op: a `GtkPrintOperation`
1797 *
1798 * A convenience function to find out if the print operation
1799 * is finished.
1800 *
1801 * a print operation is finished if its status is either
1802 * %GTK_PRINT_STATUS_FINISHED or %GTK_PRINT_STATUS_FINISHED_ABORTED.
1803 *
1804 * Note: when you enable print status tracking the print operation
1805 * can be in a non-finished state even after done has been called, as
1806 * the operation status then tracks the print job status on the printer.
1807 *
1808 * Returns: %TRUE, if the print operation is finished.
1809 */
1810gboolean
1811gtk_print_operation_is_finished (GtkPrintOperation *op)
1812{
1813 GtkPrintOperationPrivate *priv = gtk_print_operation_get_instance_private (self: op);
1814
1815 g_return_val_if_fail (GTK_IS_PRINT_OPERATION (op), TRUE);
1816
1817 return
1818 priv->status == GTK_PRINT_STATUS_FINISHED_ABORTED ||
1819 priv->status == GTK_PRINT_STATUS_FINISHED;
1820}
1821
1822/**
1823 * gtk_print_operation_set_show_progress: (attributes org.gtk.Method.set_property=show-progress)
1824 * @op: a `GtkPrintOperation`
1825 * @show_progress: %TRUE to show a progress dialog
1826 *
1827 * If @show_progress is %TRUE, the print operation will show
1828 * a progress dialog during the print operation.
1829 */
1830void
1831gtk_print_operation_set_show_progress (GtkPrintOperation *op,
1832 gboolean show_progress)
1833{
1834 GtkPrintOperationPrivate *priv = gtk_print_operation_get_instance_private (self: op);
1835
1836 g_return_if_fail (GTK_IS_PRINT_OPERATION (op));
1837
1838 show_progress = show_progress != FALSE;
1839
1840 if (priv->show_progress != show_progress)
1841 {
1842 priv->show_progress = show_progress;
1843
1844 g_object_notify (G_OBJECT (op), property_name: "show-progress");
1845 }
1846}
1847
1848/**
1849 * gtk_print_operation_set_allow_async: (attributes org.gtk.Method.set_property=allow-async)
1850 * @op: a `GtkPrintOperation`
1851 * @allow_async: %TRUE to allow asynchronous operation
1852 *
1853 * Sets whether gtk_print_operation_run() may return
1854 * before the print operation is completed.
1855 *
1856 * Note that some platforms may not allow asynchronous
1857 * operation.
1858 */
1859void
1860gtk_print_operation_set_allow_async (GtkPrintOperation *op,
1861 gboolean allow_async)
1862{
1863 GtkPrintOperationPrivate *priv = gtk_print_operation_get_instance_private (self: op);
1864
1865 g_return_if_fail (GTK_IS_PRINT_OPERATION (op));
1866
1867 allow_async = allow_async != FALSE;
1868
1869 if (priv->allow_async != allow_async)
1870 {
1871 priv->allow_async = allow_async;
1872
1873 g_object_notify (G_OBJECT (op), property_name: "allow-async");
1874 }
1875}
1876
1877
1878/**
1879 * gtk_print_operation_set_custom_tab_label: (attributes org.gtk.Method.set_property=custom-tab-label)
1880 * @op: a `GtkPrintOperation`
1881 * @label: (nullable): the label to use, or %NULL to use the default label
1882 *
1883 * Sets the label for the tab holding custom widgets.
1884 */
1885void
1886gtk_print_operation_set_custom_tab_label (GtkPrintOperation *op,
1887 const char *label)
1888{
1889 GtkPrintOperationPrivate *priv = gtk_print_operation_get_instance_private (self: op);
1890
1891 g_return_if_fail (GTK_IS_PRINT_OPERATION (op));
1892
1893 g_free (mem: priv->custom_tab_label);
1894 priv->custom_tab_label = g_strdup (str: label);
1895
1896 g_object_notify (G_OBJECT (op), property_name: "custom-tab-label");
1897}
1898
1899
1900/**
1901 * gtk_print_operation_set_export_filename: (attributes org.gtk.Method.set_property=export-filename)
1902 * @op: a `GtkPrintOperation`
1903 * @filename: (type filename): the filename for the exported file
1904 *
1905 * Sets up the `GtkPrintOperation` to generate a file instead
1906 * of showing the print dialog.
1907 *
1908 * The intended use of this function is for implementing
1909 * “Export to PDF” actions. Currently, PDF is the only supported
1910 * format.
1911 *
1912 * “Print to PDF” support is independent of this and is done
1913 * by letting the user pick the “Print to PDF” item from the list
1914 * of printers in the print dialog.
1915 */
1916void
1917gtk_print_operation_set_export_filename (GtkPrintOperation *op,
1918 const char *filename)
1919{
1920 GtkPrintOperationPrivate *priv = gtk_print_operation_get_instance_private (self: op);
1921
1922 g_return_if_fail (GTK_IS_PRINT_OPERATION (op));
1923
1924 g_free (mem: priv->export_filename);
1925 priv->export_filename = g_strdup (str: filename);
1926
1927 g_object_notify (G_OBJECT (op), property_name: "export-filename");
1928}
1929
1930/* Creates the initial page setup used for printing unless the
1931 * app overrides this on a per-page basis using request_page_setup.
1932 *
1933 * Data is taken from, in order, if existing:
1934 *
1935 * PrintSettings returned from the print dialog
1936 * (initial dialog values are set from default_page_setup
1937 * if unset in app specified print_settings)
1938 * default_page_setup
1939 * per-locale default setup
1940 */
1941static GtkPageSetup *
1942create_page_setup (GtkPrintOperation *op)
1943{
1944 GtkPrintOperationPrivate *priv = gtk_print_operation_get_instance_private (self: op);
1945 GtkPageSetup *page_setup;
1946 GtkPrintSettings *settings;
1947
1948 if (priv->default_page_setup)
1949 page_setup = gtk_page_setup_copy (other: priv->default_page_setup);
1950 else
1951 page_setup = gtk_page_setup_new ();
1952
1953 settings = priv->print_settings;
1954 if (settings)
1955 {
1956 GtkPaperSize *paper_size;
1957
1958 if (gtk_print_settings_has_key (settings, GTK_PRINT_SETTINGS_ORIENTATION))
1959 gtk_page_setup_set_orientation (setup: page_setup,
1960 orientation: gtk_print_settings_get_orientation (settings));
1961
1962
1963 paper_size = gtk_print_settings_get_paper_size (settings);
1964 if (paper_size)
1965 {
1966 gtk_page_setup_set_paper_size (setup: page_setup, size: paper_size);
1967 gtk_paper_size_free (size: paper_size);
1968 }
1969
1970 /* TODO: Margins? */
1971 }
1972
1973 return page_setup;
1974}
1975
1976static void
1977pdf_start_page (GtkPrintOperation *op,
1978 GtkPrintContext *print_context,
1979 GtkPageSetup *page_setup)
1980{
1981 cairo_surface_t *surface = op->priv->platform_data;
1982 double w, h;
1983
1984 w = gtk_page_setup_get_paper_width (setup: page_setup, unit: GTK_UNIT_POINTS);
1985 h = gtk_page_setup_get_paper_height (setup: page_setup, unit: GTK_UNIT_POINTS);
1986
1987 cairo_pdf_surface_set_size (surface, width_in_points: w, height_in_points: h);
1988}
1989
1990static void
1991pdf_end_page (GtkPrintOperation *op,
1992 GtkPrintContext *print_context)
1993{
1994 cairo_t *cr;
1995
1996 cr = gtk_print_context_get_cairo_context (context: print_context);
1997
1998 if ((op->priv->manual_number_up < 2) ||
1999 ((op->priv->page_position + 1) % op->priv->manual_number_up == 0) ||
2000 (op->priv->page_position == op->priv->nr_of_pages_to_print - 1))
2001 cairo_show_page (cr);
2002}
2003
2004static void
2005pdf_end_run (GtkPrintOperation *op,
2006 gboolean wait,
2007 gboolean cancelled)
2008{
2009 GtkPrintOperationPrivate *priv = gtk_print_operation_get_instance_private (self: op);
2010 cairo_surface_t *surface = priv->platform_data;
2011
2012 cairo_surface_finish (surface);
2013 cairo_surface_destroy (surface);
2014
2015 priv->platform_data = NULL;
2016 priv->free_platform_data = NULL;
2017}
2018
2019static GtkPrintOperationResult
2020run_pdf (GtkPrintOperation *op,
2021 GtkWindow *parent,
2022 gboolean *do_print)
2023{
2024 GtkPrintOperationPrivate *priv = gtk_print_operation_get_instance_private (self: op);
2025 GtkPageSetup *page_setup;
2026 cairo_surface_t *surface;
2027 cairo_t *cr;
2028 double width, height;
2029
2030 priv->print_context = _gtk_print_context_new (op);
2031
2032 page_setup = create_page_setup (op);
2033 _gtk_print_context_set_page_setup (context: priv->print_context, page_setup);
2034
2035 /* This will be overwritten later by the non-default size, but
2036 we need to pass some size: */
2037 width = gtk_page_setup_get_paper_width (setup: page_setup, unit: GTK_UNIT_POINTS);
2038 height = gtk_page_setup_get_paper_height (setup: page_setup, unit: GTK_UNIT_POINTS);
2039 g_object_unref (object: page_setup);
2040
2041 surface = cairo_pdf_surface_create (filename: priv->export_filename,
2042 width_in_points: width, height_in_points: height);
2043 if (cairo_surface_status (surface) != CAIRO_STATUS_SUCCESS)
2044 {
2045 g_set_error_literal (err: &priv->error,
2046 GTK_PRINT_ERROR,
2047 code: GTK_PRINT_ERROR_GENERAL,
2048 message: cairo_status_to_string (status: cairo_surface_status (surface)));
2049 *do_print = FALSE;
2050 return GTK_PRINT_OPERATION_RESULT_ERROR;
2051 }
2052
2053 /* this would crash on a nil surface */
2054 cairo_surface_set_fallback_resolution (surface, x_pixels_per_inch: 300, y_pixels_per_inch: 300);
2055
2056 priv->platform_data = surface;
2057 priv->free_platform_data = (GDestroyNotify) cairo_surface_destroy;
2058
2059 cr = cairo_create (target: surface);
2060 gtk_print_context_set_cairo_context (context: op->priv->print_context,
2061 cr, dpi_x: 72, dpi_y: 72);
2062 cairo_destroy (cr);
2063
2064
2065 priv->print_pages = GTK_PRINT_PAGES_ALL;
2066 priv->page_ranges = NULL;
2067 priv->num_page_ranges = 0;
2068
2069 priv->manual_num_copies = 1;
2070 priv->manual_collation = FALSE;
2071 priv->manual_reverse = FALSE;
2072 priv->manual_page_set = GTK_PAGE_SET_ALL;
2073 priv->manual_scale = 1.0;
2074 priv->manual_orientation = FALSE;
2075 priv->manual_number_up = 1;
2076 priv->manual_number_up_layout = GTK_NUMBER_UP_LAYOUT_LEFT_TO_RIGHT_TOP_TO_BOTTOM;
2077
2078 *do_print = TRUE;
2079
2080 priv->start_page = pdf_start_page;
2081 priv->end_page = pdf_end_page;
2082 priv->end_run = pdf_end_run;
2083
2084 return GTK_PRINT_OPERATION_RESULT_APPLY;
2085}
2086
2087
2088static void
2089clamp_page_ranges (PrintPagesData *data)
2090{
2091 GtkPrintOperationPrivate *priv = gtk_print_operation_get_instance_private (self: data->op);
2092 int num_of_correct_ranges;
2093 int i;
2094
2095 num_of_correct_ranges = 0;
2096
2097 for (i = 0; i < data->num_ranges; i++)
2098 if ((data->ranges[i].start >= 0) &&
2099 (data->ranges[i].start < priv->nr_of_pages) &&
2100 (data->ranges[i].end >= 0) &&
2101 (data->ranges[i].end < priv->nr_of_pages))
2102 {
2103 data->ranges[num_of_correct_ranges] = data->ranges[i];
2104 num_of_correct_ranges++;
2105 }
2106 else if ((data->ranges[i].start >= 0) &&
2107 (data->ranges[i].start < priv->nr_of_pages) &&
2108 (data->ranges[i].end >= priv->nr_of_pages))
2109 {
2110 data->ranges[i].end = priv->nr_of_pages - 1;
2111 data->ranges[num_of_correct_ranges] = data->ranges[i];
2112 num_of_correct_ranges++;
2113 }
2114 else if ((data->ranges[i].end >= 0) &&
2115 (data->ranges[i].end < priv->nr_of_pages) &&
2116 (data->ranges[i].start < 0))
2117 {
2118 data->ranges[i].start = 0;
2119 data->ranges[num_of_correct_ranges] = data->ranges[i];
2120 num_of_correct_ranges++;
2121 }
2122
2123 data->num_ranges = num_of_correct_ranges;
2124}
2125
2126static void
2127increment_page_sequence (PrintPagesData *data)
2128{
2129 GtkPrintOperationPrivate *priv = gtk_print_operation_get_instance_private (self: data->op);
2130 int inc;
2131
2132 if (data->total == -1)
2133 {
2134 data->total = 0;
2135 return;
2136 }
2137
2138 /* check whether we reached last position */
2139 if (priv->page_position == data->last_position &&
2140 !(data->collated_copies > 1 && data->collated < (data->collated_copies - 1)))
2141 {
2142 if (data->uncollated_copies > 1 && data->uncollated < (data->uncollated_copies - 1))
2143 {
2144 priv->page_position = data->first_position;
2145 data->sheet = data->first_sheet;
2146 data->uncollated++;
2147 }
2148 else
2149 {
2150 data->done = TRUE;
2151 return;
2152 }
2153 }
2154 else
2155 {
2156 if (priv->manual_reverse)
2157 inc = -1;
2158 else
2159 inc = 1;
2160
2161 /* changing sheet */
2162 if (priv->manual_number_up < 2 ||
2163 (priv->page_position + 1) % priv->manual_number_up == 0 ||
2164 priv->page_position == data->last_position ||
2165 priv->page_position == priv->nr_of_pages_to_print - 1)
2166 {
2167 /* check whether to print the same sheet again */
2168 if (data->collated_copies > 1)
2169 {
2170 if (data->collated < (data->collated_copies - 1))
2171 {
2172 data->collated++;
2173 data->total++;
2174 priv->page_position = data->sheet * priv->manual_number_up;
2175
2176 if (priv->page_position < 0 ||
2177 priv->page_position >= priv->nr_of_pages_to_print ||
2178 data->sheet < 0 ||
2179 data->sheet >= data->num_of_sheets)
2180 {
2181 data->done = TRUE;
2182 return;
2183 }
2184 else
2185 data->page = data->pages[priv->page_position];
2186
2187 return;
2188 }
2189 else
2190 data->collated = 0;
2191 }
2192
2193 if (priv->manual_page_set == GTK_PAGE_SET_ODD ||
2194 priv->manual_page_set == GTK_PAGE_SET_EVEN)
2195 data->sheet += 2 * inc;
2196 else
2197 data->sheet += inc;
2198
2199 priv->page_position = data->sheet * priv->manual_number_up;
2200 }
2201 else
2202 priv->page_position += 1;
2203 }
2204
2205 /* general check */
2206 if (priv->page_position < 0 ||
2207 priv->page_position >= priv->nr_of_pages_to_print ||
2208 data->sheet < 0 ||
2209 data->sheet >= data->num_of_sheets)
2210 {
2211 data->done = TRUE;
2212 return;
2213 }
2214 else
2215 data->page = data->pages[priv->page_position];
2216
2217 data->total++;
2218}
2219
2220static void
2221print_pages_idle_done (gpointer user_data)
2222{
2223 PrintPagesData *data = (PrintPagesData*)user_data;
2224 GtkPrintOperationPrivate *priv = gtk_print_operation_get_instance_private (self: data->op);
2225
2226 priv->print_pages_idle_id = 0;
2227
2228 if (priv->show_progress_timeout_id > 0)
2229 {
2230 g_source_remove (tag: priv->show_progress_timeout_id);
2231 priv->show_progress_timeout_id = 0;
2232 }
2233
2234 if (data->progress)
2235 gtk_window_destroy (GTK_WINDOW (data->progress));
2236
2237 if (priv->rloop && !data->is_preview)
2238 g_main_loop_quit (loop: priv->rloop);
2239
2240 if (!data->is_preview)
2241 {
2242 GtkPrintOperationResult result;
2243
2244 if (priv->error)
2245 result = GTK_PRINT_OPERATION_RESULT_ERROR;
2246 else if (priv->cancelled)
2247 result = GTK_PRINT_OPERATION_RESULT_CANCEL;
2248 else
2249 result = GTK_PRINT_OPERATION_RESULT_APPLY;
2250
2251 g_signal_emit (instance: data->op, signal_id: signals[DONE], detail: 0, result);
2252 }
2253
2254 g_object_unref (object: data->op);
2255 g_free (mem: data->pages);
2256 g_free (mem: data);
2257}
2258
2259static void
2260update_progress (PrintPagesData *data)
2261{
2262 GtkPrintOperationPrivate *priv = gtk_print_operation_get_instance_private (self: data->op);
2263 char *text = NULL;
2264
2265 if (data->progress)
2266 {
2267 if (priv->status == GTK_PRINT_STATUS_PREPARING)
2268 {
2269 if (priv->nr_of_pages_to_print > 0)
2270 text = g_strdup_printf (_("Preparing %d"), priv->nr_of_pages_to_print);
2271 else
2272 text = g_strdup (_("Preparing"));
2273 }
2274 else if (priv->status == GTK_PRINT_STATUS_GENERATING_DATA)
2275 text = g_strdup_printf (_("Printing %d"), data->total);
2276
2277 if (text)
2278 {
2279 g_object_set (object: data->progress, first_property_name: "text", text, NULL);
2280 g_free (mem: text);
2281 }
2282 }
2283 }
2284
2285/**
2286 * gtk_print_operation_set_defer_drawing:
2287 * @op: a `GtkPrintOperation`
2288 *
2289 * Sets up the `GtkPrintOperation` to wait for calling of
2290 * [method@Gtk.PrintOperation.draw_page_finish from application.
2291 *
2292 * This can be used for drawing page in another thread.
2293 *
2294 * This function must be called in the callback of the
2295 * [signal@Gtk.PrintOperation::draw-page] signal.
2296 */
2297void
2298gtk_print_operation_set_defer_drawing (GtkPrintOperation *op)
2299{
2300 GtkPrintOperationPrivate *priv = gtk_print_operation_get_instance_private (self: op);
2301
2302 g_return_if_fail (priv->page_drawing_state == GTK_PAGE_DRAWING_STATE_DRAWING);
2303
2304 priv->page_drawing_state = GTK_PAGE_DRAWING_STATE_DEFERRED_DRAWING;
2305}
2306
2307/**
2308 * gtk_print_operation_set_embed_page_setup: (attributes org.gtk.Method.set_property=embed-page-setup)
2309 * @op: a `GtkPrintOperation`
2310 * @embed: %TRUE to embed page setup selection in the `GtkPrintUnixDialog`
2311 *
2312 * Embed page size combo box and orientation combo box into page setup page.
2313 *
2314 * Selected page setup is stored as default page setup in `GtkPrintOperation`.
2315 */
2316void
2317gtk_print_operation_set_embed_page_setup (GtkPrintOperation *op,
2318 gboolean embed)
2319{
2320 GtkPrintOperationPrivate *priv = gtk_print_operation_get_instance_private (self: op);
2321
2322 g_return_if_fail (GTK_IS_PRINT_OPERATION (op));
2323
2324 embed = embed != FALSE;
2325 if (priv->embed_page_setup != embed)
2326 {
2327 priv->embed_page_setup = embed;
2328 g_object_notify (G_OBJECT (op), property_name: "embed-page-setup");
2329 }
2330}
2331
2332/**
2333 * gtk_print_operation_get_embed_page_setup: (attributes org.gtk.Method.get_property=embed-page-setup)
2334 * @op: a `GtkPrintOperation`
2335 *
2336 * Gets whether page setup selection combos are embedded
2337 *
2338 * Returns: whether page setup selection combos are embedded
2339 */
2340gboolean
2341gtk_print_operation_get_embed_page_setup (GtkPrintOperation *op)
2342{
2343 GtkPrintOperationPrivate *priv = gtk_print_operation_get_instance_private (self: op);
2344
2345 g_return_val_if_fail (GTK_IS_PRINT_OPERATION (op), FALSE);
2346
2347 return priv->embed_page_setup;
2348}
2349
2350/**
2351 * gtk_print_operation_draw_page_finish:
2352 * @op: a `GtkPrintOperation`
2353 *
2354 * Signal that drawing of particular page is complete.
2355 *
2356 * It is called after completion of page drawing (e.g. drawing
2357 * in another thread). If [method@Gtk.PrintOperation.set_defer_drawing]
2358 * was called before, then this function has to be called by application.
2359 * Otherwise it is called by GTK itself.
2360 */
2361void
2362gtk_print_operation_draw_page_finish (GtkPrintOperation *op)
2363{
2364 GtkPrintOperationPrivate *priv = gtk_print_operation_get_instance_private (self: op);
2365 GtkPageSetup *page_setup;
2366 GtkPrintContext *print_context;
2367 cairo_t *cr;
2368
2369 print_context = priv->print_context;
2370 page_setup = gtk_print_context_get_page_setup (context: print_context);
2371
2372 cr = gtk_print_context_get_cairo_context (context: print_context);
2373
2374 priv->end_page (op, print_context);
2375
2376 cairo_restore (cr);
2377
2378 g_object_unref (object: page_setup);
2379
2380 priv->page_drawing_state = GTK_PAGE_DRAWING_STATE_READY;
2381}
2382
2383static void
2384common_render_page (GtkPrintOperation *op,
2385 int page_nr)
2386{
2387 GtkPrintOperationPrivate *priv = gtk_print_operation_get_instance_private (self: op);
2388 GtkPageSetup *page_setup;
2389 GtkPrintContext *print_context;
2390 cairo_t *cr;
2391
2392 print_context = priv->print_context;
2393
2394 page_setup = create_page_setup (op);
2395
2396 g_signal_emit (instance: op, signal_id: signals[REQUEST_PAGE_SETUP], detail: 0,
2397 print_context, page_nr, page_setup);
2398
2399 _gtk_print_context_set_page_setup (context: print_context, page_setup);
2400
2401 priv->start_page (op, print_context, page_setup);
2402
2403 cr = gtk_print_context_get_cairo_context (context: print_context);
2404
2405 cairo_save (cr);
2406
2407 if (priv->manual_orientation)
2408 _gtk_print_context_rotate_according_to_orientation (context: print_context);
2409 else
2410 _gtk_print_context_reverse_according_to_orientation (context: print_context);
2411
2412 if (priv->manual_number_up <= 1)
2413 {
2414 if (!priv->use_full_page)
2415 _gtk_print_context_translate_into_margin (context: print_context);
2416 if (priv->manual_scale != 1.0)
2417 cairo_scale (cr,
2418 sx: priv->manual_scale,
2419 sy: priv->manual_scale);
2420 }
2421 else
2422 {
2423 GtkPageOrientation orientation;
2424 double paper_width, paper_height;
2425 double page_width, page_height;
2426 double context_width, context_height;
2427 double bottom_margin, top_margin, left_margin, right_margin;
2428 double x_step, y_step;
2429 double x_scale, y_scale, scale;
2430 double horizontal_offset = 0.0, vertical_offset = 0.0;
2431 int columns, rows, x, y, tmp_length;
2432
2433 page_setup = gtk_print_context_get_page_setup (context: print_context);
2434 orientation = gtk_page_setup_get_orientation (setup: page_setup);
2435
2436 top_margin = gtk_page_setup_get_top_margin (setup: page_setup, unit: GTK_UNIT_POINTS);
2437 bottom_margin = gtk_page_setup_get_bottom_margin (setup: page_setup, unit: GTK_UNIT_POINTS);
2438 left_margin = gtk_page_setup_get_left_margin (setup: page_setup, unit: GTK_UNIT_POINTS);
2439 right_margin = gtk_page_setup_get_right_margin (setup: page_setup, unit: GTK_UNIT_POINTS);
2440
2441 paper_width = gtk_page_setup_get_paper_width (setup: page_setup, unit: GTK_UNIT_POINTS);
2442 paper_height = gtk_page_setup_get_paper_height (setup: page_setup, unit: GTK_UNIT_POINTS);
2443
2444 context_width = gtk_print_context_get_width (context: print_context);
2445 context_height = gtk_print_context_get_height (context: print_context);
2446
2447 if (orientation == GTK_PAGE_ORIENTATION_PORTRAIT ||
2448 orientation == GTK_PAGE_ORIENTATION_REVERSE_PORTRAIT)
2449 {
2450 page_width = paper_width - (left_margin + right_margin);
2451 page_height = paper_height - (top_margin + bottom_margin);
2452 }
2453 else
2454 {
2455 page_width = paper_width - (top_margin + bottom_margin);
2456 page_height = paper_height - (left_margin + right_margin);
2457 }
2458
2459 if (orientation == GTK_PAGE_ORIENTATION_PORTRAIT ||
2460 orientation == GTK_PAGE_ORIENTATION_REVERSE_PORTRAIT)
2461 cairo_translate (cr, tx: left_margin, ty: top_margin);
2462 else
2463 cairo_translate (cr, tx: top_margin, ty: left_margin);
2464
2465 switch (priv->manual_number_up)
2466 {
2467 default:
2468 columns = 1;
2469 rows = 1;
2470 break;
2471 case 2:
2472 columns = 2;
2473 rows = 1;
2474 break;
2475 case 4:
2476 columns = 2;
2477 rows = 2;
2478 break;
2479 case 6:
2480 columns = 3;
2481 rows = 2;
2482 break;
2483 case 9:
2484 columns = 3;
2485 rows = 3;
2486 break;
2487 case 16:
2488 columns = 4;
2489 rows = 4;
2490 break;
2491 }
2492
2493 if (orientation == GTK_PAGE_ORIENTATION_LANDSCAPE ||
2494 orientation == GTK_PAGE_ORIENTATION_REVERSE_LANDSCAPE)
2495 {
2496 tmp_length = columns;
2497 columns = rows;
2498 rows = tmp_length;
2499 }
2500
2501 switch (priv->manual_number_up_layout)
2502 {
2503 case GTK_NUMBER_UP_LAYOUT_LEFT_TO_RIGHT_TOP_TO_BOTTOM:
2504 x = priv->page_position % columns;
2505 y = (priv->page_position / columns) % rows;
2506 break;
2507 case GTK_NUMBER_UP_LAYOUT_LEFT_TO_RIGHT_BOTTOM_TO_TOP:
2508 x = priv->page_position % columns;
2509 y = rows - 1 - (priv->page_position / columns) % rows;
2510 break;
2511 case GTK_NUMBER_UP_LAYOUT_RIGHT_TO_LEFT_TOP_TO_BOTTOM:
2512 x = columns - 1 - priv->page_position % columns;
2513 y = (priv->page_position / columns) % rows;
2514 break;
2515 case GTK_NUMBER_UP_LAYOUT_RIGHT_TO_LEFT_BOTTOM_TO_TOP:
2516 x = columns - 1 - priv->page_position % columns;
2517 y = rows - 1 - (priv->page_position / columns) % rows;
2518 break;
2519 case GTK_NUMBER_UP_LAYOUT_TOP_TO_BOTTOM_LEFT_TO_RIGHT:
2520 x = (priv->page_position / rows) % columns;
2521 y = priv->page_position % rows;
2522 break;
2523 case GTK_NUMBER_UP_LAYOUT_TOP_TO_BOTTOM_RIGHT_TO_LEFT:
2524 x = columns - 1 - (priv->page_position / rows) % columns;
2525 y = priv->page_position % rows;
2526 break;
2527 case GTK_NUMBER_UP_LAYOUT_BOTTOM_TO_TOP_LEFT_TO_RIGHT:
2528 x = (priv->page_position / rows) % columns;
2529 y = rows - 1 - priv->page_position % rows;
2530 break;
2531 case GTK_NUMBER_UP_LAYOUT_BOTTOM_TO_TOP_RIGHT_TO_LEFT:
2532 x = columns - 1 - (priv->page_position / rows) % columns;
2533 y = rows - 1 - priv->page_position % rows;
2534 break;
2535 default:
2536 g_assert_not_reached();
2537 x = 0;
2538 y = 0;
2539 }
2540
2541 if (priv->manual_number_up == 4 || priv->manual_number_up == 9 || priv->manual_number_up == 16)
2542 {
2543 x_scale = page_width / (columns * paper_width);
2544 y_scale = page_height / (rows * paper_height);
2545
2546 scale = x_scale < y_scale ? x_scale : y_scale;
2547
2548 x_step = paper_width * (x_scale / scale);
2549 y_step = paper_height * (y_scale / scale);
2550
2551 if ((left_margin + right_margin) > 0)
2552 {
2553 horizontal_offset = left_margin * (x_step - context_width) / (left_margin + right_margin);
2554 vertical_offset = top_margin * (y_step - context_height) / (top_margin + bottom_margin);
2555 }
2556 else
2557 {
2558 horizontal_offset = (x_step - context_width) / 2.0;
2559 vertical_offset = (y_step - context_height) / 2.0;
2560 }
2561
2562 cairo_scale (cr, sx: scale, sy: scale);
2563
2564 cairo_translate (cr,
2565 tx: x * x_step + horizontal_offset,
2566 ty: y * y_step + vertical_offset);
2567
2568 if (priv->manual_scale != 1.0)
2569 cairo_scale (cr, sx: priv->manual_scale, sy: priv->manual_scale);
2570 }
2571
2572 if (priv->manual_number_up == 2 || priv->manual_number_up == 6)
2573 {
2574 x_scale = page_height / (columns * paper_width);
2575 y_scale = page_width / (rows * paper_height);
2576
2577 scale = x_scale < y_scale ? x_scale : y_scale;
2578
2579 horizontal_offset = (paper_width * (x_scale / scale) - paper_width) / 2.0 * columns;
2580 vertical_offset = (paper_height * (y_scale / scale) - paper_height) / 2.0 * rows;
2581
2582 if (!priv->use_full_page)
2583 {
2584 horizontal_offset -= right_margin;
2585 vertical_offset += top_margin;
2586 }
2587
2588 cairo_scale (cr, sx: scale, sy: scale);
2589
2590 cairo_translate (cr,
2591 tx: y * paper_height + vertical_offset,
2592 ty: (columns - x) * paper_width + horizontal_offset);
2593
2594 if (priv->manual_scale != 1.0)
2595 cairo_scale (cr, sx: priv->manual_scale, sy: priv->manual_scale);
2596
2597 cairo_rotate (cr, angle: - G_PI / 2);
2598 }
2599 }
2600
2601 priv->page_drawing_state = GTK_PAGE_DRAWING_STATE_DRAWING;
2602
2603 g_signal_emit (instance: op, signal_id: signals[DRAW_PAGE], detail: 0,
2604 print_context, page_nr);
2605
2606 if (priv->page_drawing_state == GTK_PAGE_DRAWING_STATE_DRAWING)
2607 gtk_print_operation_draw_page_finish (op);
2608}
2609
2610static void
2611prepare_data (PrintPagesData *data)
2612{
2613 GtkPrintOperationPrivate *priv = gtk_print_operation_get_instance_private (self: data->op);
2614 GtkPageSetup *page_setup;
2615 gboolean paginated = FALSE;
2616 int i, j, counter;
2617
2618 if (priv->manual_collation)
2619 {
2620 data->uncollated_copies = priv->manual_num_copies;
2621 data->collated_copies = 1;
2622 }
2623 else
2624 {
2625 data->uncollated_copies = 1;
2626 data->collated_copies = priv->manual_num_copies;
2627 }
2628
2629 if (!data->initialized)
2630 {
2631 data->initialized = TRUE;
2632 page_setup = create_page_setup (op: data->op);
2633 _gtk_print_context_set_page_setup (context: priv->print_context,
2634 page_setup);
2635 g_object_unref (object: page_setup);
2636
2637 g_signal_emit (instance: data->op, signal_id: signals[BEGIN_PRINT], detail: 0, priv->print_context);
2638
2639 return;
2640 }
2641
2642 g_signal_emit (instance: data->op, signal_id: signals[PAGINATE], detail: 0, priv->print_context, &paginated);
2643 if (!paginated)
2644 return;
2645
2646 /* Initialize parts of PrintPagesData that depend on nr_of_pages
2647 */
2648 if (priv->print_pages == GTK_PRINT_PAGES_RANGES)
2649 {
2650 if (priv->page_ranges == NULL)
2651 {
2652 g_warning ("no pages to print");
2653 priv->cancelled = TRUE;
2654 return;
2655 }
2656 data->ranges = priv->page_ranges;
2657 data->num_ranges = priv->num_page_ranges;
2658 for (i = 0; i < data->num_ranges; i++)
2659 if (data->ranges[i].end == -1 ||
2660 data->ranges[i].end >= priv->nr_of_pages)
2661 data->ranges[i].end = priv->nr_of_pages - 1;
2662 }
2663 else if (priv->print_pages == GTK_PRINT_PAGES_CURRENT &&
2664 priv->current_page != -1)
2665 {
2666 data->ranges = &data->one_range;
2667 data->num_ranges = 1;
2668 data->ranges[0].start = priv->current_page;
2669 data->ranges[0].end = priv->current_page;
2670 }
2671 else
2672 {
2673 data->ranges = &data->one_range;
2674 data->num_ranges = 1;
2675 data->ranges[0].start = 0;
2676 data->ranges[0].end = priv->nr_of_pages - 1;
2677 }
2678
2679 clamp_page_ranges (data);
2680
2681 if (data->num_ranges < 1)
2682 {
2683 priv->cancelled = TRUE;
2684 return;
2685 }
2686
2687 priv->nr_of_pages_to_print = 0;
2688 for (i = 0; i < data->num_ranges; i++)
2689 priv->nr_of_pages_to_print += data->ranges[i].end - data->ranges[i].start + 1;
2690
2691 data->pages = g_new (int, priv->nr_of_pages_to_print);
2692 counter = 0;
2693 for (i = 0; i < data->num_ranges; i++)
2694 for (j = data->ranges[i].start; j <= data->ranges[i].end; j++)
2695 {
2696 data->pages[counter] = j;
2697 counter++;
2698 }
2699
2700 data->total = -1;
2701 data->collated = 0;
2702 data->uncollated = 0;
2703
2704 if (priv->manual_number_up > 1)
2705 {
2706 if (priv->nr_of_pages_to_print % priv->manual_number_up == 0)
2707 data->num_of_sheets = priv->nr_of_pages_to_print / priv->manual_number_up;
2708 else
2709 data->num_of_sheets = priv->nr_of_pages_to_print / priv->manual_number_up + 1;
2710 }
2711 else
2712 data->num_of_sheets = priv->nr_of_pages_to_print;
2713
2714 if (priv->manual_reverse)
2715 {
2716 /* data->sheet is 0-based */
2717 if (priv->manual_page_set == GTK_PAGE_SET_ODD)
2718 data->sheet = (data->num_of_sheets - 1) - (data->num_of_sheets - 1) % 2;
2719 else if (priv->manual_page_set == GTK_PAGE_SET_EVEN)
2720 data->sheet = (data->num_of_sheets - 1) - (1 - (data->num_of_sheets - 1) % 2);
2721 else
2722 data->sheet = data->num_of_sheets - 1;
2723 }
2724 else
2725 {
2726 /* data->sheet is 0-based */
2727 if (priv->manual_page_set == GTK_PAGE_SET_ODD)
2728 data->sheet = 0;
2729 else if (priv->manual_page_set == GTK_PAGE_SET_EVEN)
2730 {
2731 if (data->num_of_sheets > 1)
2732 data->sheet = 1;
2733 else
2734 data->sheet = -1;
2735 }
2736 else
2737 data->sheet = 0;
2738 }
2739
2740 priv->page_position = data->sheet * priv->manual_number_up;
2741
2742 if (priv->page_position < 0 || priv->page_position >= priv->nr_of_pages_to_print)
2743 {
2744 priv->cancelled = TRUE;
2745 return;
2746 }
2747
2748 data->page = data->pages[priv->page_position];
2749 data->first_position = priv->page_position;
2750 data->first_sheet = data->sheet;
2751
2752 if (priv->manual_reverse)
2753 {
2754 if (priv->manual_page_set == GTK_PAGE_SET_ODD)
2755 data->last_position = MIN (priv->manual_number_up - 1, priv->nr_of_pages_to_print - 1);
2756 else if (priv->manual_page_set == GTK_PAGE_SET_EVEN)
2757 data->last_position = MIN (2 * priv->manual_number_up - 1, priv->nr_of_pages_to_print - 1);
2758 else
2759 data->last_position = MIN (priv->manual_number_up - 1, priv->nr_of_pages_to_print - 1);
2760 }
2761 else
2762 {
2763 if (priv->manual_page_set == GTK_PAGE_SET_ODD)
2764 data->last_position = MIN (((data->num_of_sheets - 1) - ((data->num_of_sheets - 1) % 2)) * priv->manual_number_up - 1, priv->nr_of_pages_to_print - 1);
2765 else if (priv->manual_page_set == GTK_PAGE_SET_EVEN)
2766 data->last_position = MIN (((data->num_of_sheets - 1) - (1 - (data->num_of_sheets - 1) % 2)) * priv->manual_number_up - 1, priv->nr_of_pages_to_print - 1);
2767 else
2768 data->last_position = priv->nr_of_pages_to_print - 1;
2769 }
2770
2771
2772 _gtk_print_operation_set_status (op: data->op,
2773 status: GTK_PRINT_STATUS_GENERATING_DATA,
2774 NULL);
2775}
2776
2777static gboolean
2778print_pages_idle (gpointer user_data)
2779{
2780 PrintPagesData *data = (PrintPagesData*)user_data;
2781 GtkPrintOperationPrivate *priv = gtk_print_operation_get_instance_private (self: data->op);
2782 gboolean done = FALSE;
2783
2784 if (priv->page_drawing_state == GTK_PAGE_DRAWING_STATE_READY)
2785 {
2786 if (priv->status == GTK_PRINT_STATUS_PREPARING)
2787 {
2788 prepare_data (data);
2789 goto out;
2790 }
2791
2792 if (data->is_preview && !priv->cancelled)
2793 {
2794 done = TRUE;
2795
2796 g_signal_emit_by_name (instance: data->op, detailed_signal: "ready", priv->print_context);
2797 goto out;
2798 }
2799
2800 increment_page_sequence (data);
2801
2802 if (!data->done)
2803 common_render_page (op: data->op, page_nr: data->page);
2804 else
2805 done = priv->page_drawing_state == GTK_PAGE_DRAWING_STATE_READY;
2806
2807 out:
2808
2809 if (priv->cancelled)
2810 {
2811 _gtk_print_operation_set_status (op: data->op, status: GTK_PRINT_STATUS_FINISHED_ABORTED, NULL);
2812
2813 data->is_preview = FALSE;
2814 done = TRUE;
2815 }
2816
2817 if (done && !data->is_preview)
2818 {
2819 g_signal_emit (instance: data->op, signal_id: signals[END_PRINT], detail: 0, priv->print_context);
2820 priv->end_run (data->op, priv->is_sync, priv->cancelled);
2821 }
2822
2823 update_progress (data);
2824 }
2825
2826 return !done;
2827}
2828
2829static void
2830handle_progress_response (GtkWidget *dialog,
2831 int response,
2832 gpointer data)
2833{
2834 GtkPrintOperation *op = (GtkPrintOperation *)data;
2835
2836 gtk_widget_hide (widget: dialog);
2837 gtk_print_operation_cancel (op);
2838}
2839
2840static gboolean
2841show_progress_timeout (PrintPagesData *data)
2842{
2843 gtk_window_present (GTK_WINDOW (data->progress));
2844
2845 data->op->priv->show_progress_timeout_id = 0;
2846
2847 return FALSE;
2848}
2849
2850static void
2851print_pages (GtkPrintOperation *op,
2852 GtkWindow *parent,
2853 gboolean do_print,
2854 GtkPrintOperationResult result)
2855{
2856 GtkPrintOperationPrivate *priv = gtk_print_operation_get_instance_private (self: op);
2857 PrintPagesData *data;
2858
2859 if (!do_print)
2860 {
2861 GtkPrintOperationResult tmp_result;
2862
2863 _gtk_print_operation_set_status (op, status: GTK_PRINT_STATUS_FINISHED_ABORTED, NULL);
2864
2865 if (priv->error)
2866 tmp_result = GTK_PRINT_OPERATION_RESULT_ERROR;
2867 else if (priv->cancelled)
2868 tmp_result = GTK_PRINT_OPERATION_RESULT_CANCEL;
2869 else
2870 tmp_result = result;
2871
2872 g_signal_emit (instance: op, signal_id: signals[DONE], detail: 0, tmp_result);
2873
2874 return;
2875 }
2876
2877 _gtk_print_operation_set_status (op, status: GTK_PRINT_STATUS_PREPARING, NULL);
2878
2879 data = g_new0 (PrintPagesData, 1);
2880 data->op = g_object_ref (op);
2881 data->is_preview = (priv->action == GTK_PRINT_OPERATION_ACTION_PREVIEW);
2882
2883 if (priv->show_progress)
2884 {
2885 GtkWidget *progress;
2886
2887 progress = gtk_message_dialog_new (parent, flags: 0,
2888 type: GTK_MESSAGE_OTHER,
2889 buttons: GTK_BUTTONS_CANCEL,
2890 _("Preparing"));
2891 g_signal_connect (progress, "response",
2892 G_CALLBACK (handle_progress_response), op);
2893
2894 priv->show_progress_timeout_id =
2895 g_timeout_add (SHOW_PROGRESS_TIME,
2896 function: (GSourceFunc) show_progress_timeout,
2897 data);
2898 gdk_source_set_static_name_by_id (tag: priv->show_progress_timeout_id, name: "[gtk] show_progress_timeout");
2899
2900 data->progress = progress;
2901 }
2902
2903 if (data->is_preview)
2904 {
2905 gboolean handled;
2906
2907 g_signal_emit_by_name (instance: op, detailed_signal: "preview",
2908 GTK_PRINT_OPERATION_PREVIEW (op),
2909 priv->print_context,
2910 parent,
2911 &handled);
2912
2913 if (!handled)
2914 {
2915 GtkWidget *error_dialog;
2916
2917 error_dialog = gtk_message_dialog_new (parent,
2918 flags: GTK_DIALOG_MODAL | GTK_DIALOG_DESTROY_WITH_PARENT,
2919 type: GTK_MESSAGE_ERROR,
2920 buttons: GTK_BUTTONS_OK,
2921 _("Error creating print preview"));
2922
2923 gtk_message_dialog_format_secondary_text (GTK_MESSAGE_DIALOG (error_dialog),
2924 _("The most probable reason is that a temporary file could not be created."));
2925
2926 if (parent && gtk_window_has_group (window: parent))
2927 gtk_window_group_add_window (window_group: gtk_window_get_group (window: parent),
2928 GTK_WINDOW (error_dialog));
2929
2930 g_signal_connect (error_dialog, "response",
2931 G_CALLBACK (gtk_window_destroy), NULL);
2932
2933 gtk_widget_show (widget: error_dialog);
2934
2935 print_pages_idle_done (user_data: data);
2936
2937 return;
2938 }
2939
2940 if (gtk_print_context_get_cairo_context (context: priv->print_context) == NULL)
2941 {
2942 /* Programmer error */
2943 g_error ("You must set a cairo context on the print context");
2944 }
2945
2946 priv->start_page = preview_start_page;
2947 priv->end_page = preview_end_page;
2948 priv->end_run = preview_end_run;
2949
2950 priv->print_pages = gtk_print_settings_get_print_pages (settings: priv->print_settings);
2951 priv->page_ranges = gtk_print_settings_get_page_ranges (settings: priv->print_settings,
2952 num_ranges: &priv->num_page_ranges);
2953 priv->manual_num_copies = 1;
2954 priv->manual_collation = FALSE;
2955 priv->manual_reverse = gtk_print_settings_get_reverse (settings: priv->print_settings);
2956 priv->manual_page_set = gtk_print_settings_get_page_set (settings: priv->print_settings);
2957 priv->manual_scale = gtk_print_settings_get_scale (settings: priv->print_settings) / 100.0;
2958 priv->manual_orientation = FALSE;
2959 priv->manual_number_up = gtk_print_settings_get_number_up (settings: priv->print_settings);
2960 priv->manual_number_up_layout = gtk_print_settings_get_number_up_layout (settings: priv->print_settings);
2961 }
2962
2963 priv->print_pages_idle_id = g_idle_add_full (G_PRIORITY_DEFAULT_IDLE + 10,
2964 function: print_pages_idle,
2965 data,
2966 notify: print_pages_idle_done);
2967 gdk_source_set_static_name_by_id (tag: priv->print_pages_idle_id, name: "[gtk] print_pages_idle");
2968
2969 /* Recursive main loop to make sure we don't exit on sync operations */
2970 if (priv->is_sync)
2971 {
2972 priv->rloop = g_main_loop_new (NULL, FALSE);
2973
2974 g_object_ref (op);
2975
2976 g_main_loop_run (loop: priv->rloop);
2977 g_main_loop_unref (loop: priv->rloop);
2978 priv->rloop = NULL;
2979
2980 g_object_unref (object: op);
2981 }
2982}
2983
2984/**
2985 * gtk_print_operation_get_error:
2986 * @op: a `GtkPrintOperation`
2987 * @error: return location for the error
2988 *
2989 * Call this when the result of a print operation is
2990 * %GTK_PRINT_OPERATION_RESULT_ERROR.
2991 *
2992 * It can be called either after [method@Gtk.PrintOperation.run]
2993 * returns, or in the [signal@Gtk.PrintOperation::done] signal
2994 * handler.
2995 *
2996 * The returned `GError` will contain more details on what went wrong.
2997 */
2998void
2999gtk_print_operation_get_error (GtkPrintOperation *op,
3000 GError **error)
3001{
3002 g_return_if_fail (GTK_IS_PRINT_OPERATION (op));
3003
3004 g_propagate_error (dest: error, src: op->priv->error);
3005
3006 op->priv->error = NULL;
3007}
3008
3009
3010/**
3011 * gtk_print_operation_run:
3012 * @op: a `GtkPrintOperation`
3013 * @action: the action to start
3014 * @parent: (nullable): Transient parent of the dialog
3015 * @error: (nullable): Return location for errors
3016 *
3017 * Runs the print operation.
3018 *
3019 * Normally that this function does not return until the rendering
3020 * of all pages is complete. You can connect to the
3021 * [signal@Gtk.PrintOperation::status-changed] signal on @op to obtain
3022 * some information about the progress of the print operation.
3023 *
3024 * Furthermore, it may use a recursive mainloop to show the print dialog.
3025 *
3026 * If you set the [Gtk.PrintOperation:allow-async] property, the operation
3027 * will run asynchronously if this is supported on the platform. The
3028 * [signal@Gtk.PrintOperation::done] signal will be emitted with the result
3029 * of the operation when the it is done (i.e. when the dialog is canceled,
3030 * or when the print succeeds or fails).
3031 *
3032 * ```c
3033 * if (settings != NULL)
3034 * gtk_print_operation_set_print_settings (print, settings);
3035 *
3036 * if (page_setup != NULL)
3037 * gtk_print_operation_set_default_page_setup (print, page_setup);
3038 *
3039 * g_signal_connect (print, "begin-print",
3040 * G_CALLBACK (begin_print), &data);
3041 * g_signal_connect (print, "draw-page",
3042 * G_CALLBACK (draw_page), &data);
3043 *
3044 * res = gtk_print_operation_run (print,
3045 * GTK_PRINT_OPERATION_ACTION_PRINT_DIALOG,
3046 * parent,
3047 * &error);
3048 *
3049 * if (res == GTK_PRINT_OPERATION_RESULT_ERROR)
3050 * {
3051 * error_dialog = gtk_message_dialog_new (GTK_WINDOW (parent),
3052 * GTK_DIALOG_DESTROY_WITH_PARENT,
3053 * GTK_MESSAGE_ERROR,
3054 * GTK_BUTTONS_CLOSE,
3055 * "Error printing file:\n%s",
3056 * error->message);
3057 * g_signal_connect (error_dialog, "response",
3058 * G_CALLBACK (gtk_window_destroy), NULL);
3059 * gtk_widget_show (error_dialog);
3060 * g_error_free (error);
3061 * }
3062 * else if (res == GTK_PRINT_OPERATION_RESULT_APPLY)
3063 * {
3064 * if (settings != NULL)
3065 * g_object_unref (settings);
3066 * settings = g_object_ref (gtk_print_operation_get_print_settings (print));
3067 * }
3068 * ```
3069 *
3070 * Note that gtk_print_operation_run() can only be called once on a
3071 * given `GtkPrintOperation`.
3072 *
3073 * Returns: the result of the print operation. A return value of
3074 * %GTK_PRINT_OPERATION_RESULT_APPLY indicates that the printing was
3075 * completed successfully. In this case, it is a good idea to obtain
3076 * the used print settings with
3077 * [method@Gtk.PrintOperation.get_print_settings]
3078 * and store them for reuse with the next print operation. A value of
3079 * %GTK_PRINT_OPERATION_RESULT_IN_PROGRESS means the operation is running
3080 * asynchronously, and will emit the [signal@Gtk.PrintOperation::done]
3081 * signal when done.
3082 */
3083GtkPrintOperationResult
3084gtk_print_operation_run (GtkPrintOperation *op,
3085 GtkPrintOperationAction action,
3086 GtkWindow *parent,
3087 GError **error)
3088{
3089 GtkPrintOperationPrivate *priv = gtk_print_operation_get_instance_private (self: op);
3090 GtkPrintOperationResult result;
3091 GtkPageSetup *page_setup;
3092 gboolean do_print;
3093 gboolean run_print_pages;
3094
3095 g_return_val_if_fail (GTK_IS_PRINT_OPERATION (op),
3096 GTK_PRINT_OPERATION_RESULT_ERROR);
3097 g_return_val_if_fail (op->priv->status == GTK_PRINT_STATUS_INITIAL,
3098 GTK_PRINT_OPERATION_RESULT_ERROR);
3099
3100 run_print_pages = TRUE;
3101 do_print = FALSE;
3102 priv->error = NULL;
3103 priv->action = action;
3104
3105 if (priv->print_settings == NULL)
3106 priv->print_settings = gtk_print_settings_new ();
3107
3108 if (action == GTK_PRINT_OPERATION_ACTION_EXPORT)
3109 {
3110 /* note: if you implement async EXPORT, update the docs
3111 * docs for the allow-async property.
3112 */
3113 priv->is_sync = TRUE;
3114 g_return_val_if_fail (priv->export_filename != NULL, GTK_PRINT_OPERATION_RESULT_ERROR);
3115 result = run_pdf (op, parent, do_print: &do_print);
3116 }
3117 else if (action == GTK_PRINT_OPERATION_ACTION_PREVIEW)
3118 {
3119 priv->is_sync = !priv->allow_async;
3120 priv->print_context = _gtk_print_context_new (op);
3121 page_setup = create_page_setup (op);
3122 _gtk_print_context_set_page_setup (context: priv->print_context, page_setup);
3123 g_object_unref (object: page_setup);
3124 do_print = TRUE;
3125 result = priv->is_sync ? GTK_PRINT_OPERATION_RESULT_APPLY : GTK_PRINT_OPERATION_RESULT_IN_PROGRESS;
3126 }
3127#ifndef G_OS_WIN32
3128 else if (priv->allow_async)
3129 {
3130 priv->is_sync = FALSE;
3131 _gtk_print_operation_platform_backend_run_dialog_async (op,
3132 show_dialog: action == GTK_PRINT_OPERATION_ACTION_PRINT_DIALOG,
3133 parent,
3134 print_cb: print_pages);
3135 result = GTK_PRINT_OPERATION_RESULT_IN_PROGRESS;
3136 run_print_pages = FALSE; /* print_pages is called asynchronously from dialog */
3137 }
3138#endif
3139 else
3140 {
3141 priv->is_sync = TRUE;
3142 result = _gtk_print_operation_platform_backend_run_dialog (operation: op,
3143 show_dialog: action == GTK_PRINT_OPERATION_ACTION_PRINT_DIALOG,
3144 parent,
3145 do_print: &do_print);
3146 }
3147
3148 /* To ensure that priv is still valid after print_pages () */
3149 g_object_ref (op);
3150
3151 if (run_print_pages)
3152 print_pages (op, parent, do_print, result);
3153
3154 if (priv->error)
3155 {
3156 if (error)
3157 *error = g_error_copy (error: priv->error);
3158 result = GTK_PRINT_OPERATION_RESULT_ERROR;
3159 }
3160 else if (priv->cancelled)
3161 result = GTK_PRINT_OPERATION_RESULT_CANCEL;
3162
3163 g_object_unref (object: op);
3164 return result;
3165}
3166
3167/**
3168 * gtk_print_operation_cancel:
3169 * @op: a `GtkPrintOperation`
3170 *
3171 * Cancels a running print operation.
3172 *
3173 * This function may be called from a [signal@Gtk.PrintOperation::begin-print],
3174 * [signal@Gtk.PrintOperation::paginate] or [signal@Gtk.PrintOperation::draw-page]
3175 * signal handler to stop the currently running print operation.
3176 */
3177void
3178gtk_print_operation_cancel (GtkPrintOperation *op)
3179{
3180 g_return_if_fail (GTK_IS_PRINT_OPERATION (op));
3181
3182 op->priv->cancelled = TRUE;
3183}
3184
3185/**
3186 * gtk_print_operation_set_support_selection: (attributes org.gtk.Method.set_property=support-selection)
3187 * @op: a `GtkPrintOperation`
3188 * @support_selection: %TRUE to support selection
3189 *
3190 * Sets whether selection is supported by `GtkPrintOperation`.
3191 */
3192void
3193gtk_print_operation_set_support_selection (GtkPrintOperation *op,
3194 gboolean support_selection)
3195{
3196 GtkPrintOperationPrivate *priv = gtk_print_operation_get_instance_private (self: op);
3197
3198 g_return_if_fail (GTK_IS_PRINT_OPERATION (op));
3199
3200 support_selection = support_selection != FALSE;
3201 if (priv->support_selection != support_selection)
3202 {
3203 priv->support_selection = support_selection;
3204 g_object_notify (G_OBJECT (op), property_name: "support-selection");
3205 }
3206}
3207
3208/**
3209 * gtk_print_operation_get_support_selection: (attributes org.gtk.Method.get_property=support-selection)
3210 * @op: a `GtkPrintOperation`
3211 *
3212 * Gets whether the application supports print of selection
3213 *
3214 * Returns: whether the application supports print of selection
3215 */
3216gboolean
3217gtk_print_operation_get_support_selection (GtkPrintOperation *op)
3218{
3219 GtkPrintOperationPrivate *priv = gtk_print_operation_get_instance_private (self: op);
3220
3221 g_return_val_if_fail (GTK_IS_PRINT_OPERATION (op), FALSE);
3222
3223 return priv->support_selection;
3224}
3225
3226/**
3227 * gtk_print_operation_set_has_selection: (attributes org.gtk.Method.set_property=has-selection)
3228 * @op: a `GtkPrintOperation`
3229 * @has_selection: %TRUE indicates that a selection exists
3230 *
3231 * Sets whether there is a selection to print.
3232 *
3233 * Application has to set number of pages to which the selection
3234 * will draw by [method@Gtk.PrintOperation.set_n_pages] in a handler
3235 * for the [signal@Gtk.PrintOperation::begin-print] signal.
3236 */
3237void
3238gtk_print_operation_set_has_selection (GtkPrintOperation *op,
3239 gboolean has_selection)
3240{
3241 GtkPrintOperationPrivate *priv = gtk_print_operation_get_instance_private (self: op);
3242
3243 g_return_if_fail (GTK_IS_PRINT_OPERATION (op));
3244
3245 has_selection = has_selection != FALSE;
3246 if (priv->has_selection != has_selection)
3247 {
3248 priv->has_selection = has_selection;
3249 g_object_notify (G_OBJECT (op), property_name: "has-selection");
3250 }
3251}
3252
3253/**
3254 * gtk_print_operation_get_has_selection: (attributes org.gtk.Method.get_property=has-selection)
3255 * @op: a `GtkPrintOperation`
3256 *
3257 * Gets whether there is a selection.
3258 *
3259 * Returns: whether there is a selection
3260 */
3261gboolean
3262gtk_print_operation_get_has_selection (GtkPrintOperation *op)
3263{
3264 GtkPrintOperationPrivate *priv = gtk_print_operation_get_instance_private (self: op);
3265
3266 g_return_val_if_fail (GTK_IS_PRINT_OPERATION (op), FALSE);
3267
3268 return priv->has_selection;
3269}
3270
3271/**
3272 * gtk_print_operation_get_n_pages_to_print: (attributes org.gtk.Method.get_property=n-pages-to-print)
3273 * @op: a `GtkPrintOperation`
3274 *
3275 * Returns the number of pages that will be printed.
3276 *
3277 * Note that this value is set during print preparation phase
3278 * (%GTK_PRINT_STATUS_PREPARING), so this function should never be
3279 * called before the data generation phase (%GTK_PRINT_STATUS_GENERATING_DATA).
3280 * You can connect to the [signal@Gtk.PrintOperation::status-changed]
3281 * signal and call gtk_print_operation_get_n_pages_to_print() when
3282 * print status is %GTK_PRINT_STATUS_GENERATING_DATA.
3283 *
3284 * This is typically used to track the progress of print operation.
3285 *
3286 * Returns: the number of pages that will be printed
3287 */
3288int
3289gtk_print_operation_get_n_pages_to_print (GtkPrintOperation *op)
3290{
3291 GtkPrintOperationPrivate *priv = gtk_print_operation_get_instance_private (self: op);
3292
3293 g_return_val_if_fail (GTK_IS_PRINT_OPERATION (op), -1);
3294
3295 return priv->nr_of_pages_to_print;
3296}
3297

source code of gtk/gtk/gtkprintoperation.c