1 /*
2  * gedit-print-job.c
3  * This file is part of gedit
4  *
5  * Copyright (C) 2000-2001 Chema Celorio, Paolo Maggi
6  * Copyright (C) 2002-2008 Paolo Maggi
7  * Copyright (C) 2015 Sébastien Wilmet
8  *
9  * This program is free software; you can redistribute it and/or modify
10  * it under the terms of the GNU General Public License as published by
11  * the Free Software Foundation; either version 2 of the License, or
12  * (at your option) any later version.
13  *
14  * This program is distributed in the hope that it will be useful,
15  * but WITHOUT ANY WARRANTY; without even the implied warranty of
16  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
17  * GNU General Public License for more details.
18  *
19  * You should have received a copy of the GNU General Public License
20  * along with this program; if not, see <http://www.gnu.org/licenses/>.
21  */
22 
23 #include "gedit-print-job.h"
24 
25 #include <glib/gi18n.h>
26 #include <tepl/tepl.h>
27 
28 #include "gedit-debug.h"
29 #include "gedit-document-private.h"
30 #include "gedit-print-preview.h"
31 #include "gedit-utils.h"
32 #include "gedit-dirs.h"
33 #include "gedit-settings.h"
34 
35 struct _GeditPrintJob
36 {
37 	GObject parent_instance;
38 
39 	GSettings *gsettings;
40 
41 	GeditView *view;
42 
43 	GtkPrintOperation *operation;
44 	GtkSourcePrintCompositor *compositor;
45 
46 	GtkWidget *preview;
47 
48 	gchar *status_string;
49 	gdouble progress;
50 
51 	/* Widgets part of the custom print preferences widget.
52 	 * These pointers are valid just when the dialog is displayed.
53 	 */
54 	GtkToggleButton *syntax_checkbutton;
55 	GtkToggleButton *page_header_checkbutton;
56 	GtkToggleButton *line_numbers_checkbutton;
57 	GtkSpinButton *line_numbers_spinbutton;
58 	GtkToggleButton *text_wrapping_checkbutton;
59 	GtkToggleButton *do_not_split_checkbutton;
60 	GtkFontButton *body_fontbutton;
61 	GtkFontButton *headers_fontbutton;
62 	GtkFontButton *numbers_fontbutton;
63 
64 	guint is_preview : 1;
65 };
66 
67 enum
68 {
69 	PROP_0,
70 	PROP_VIEW,
71 	LAST_PROP
72 };
73 
74 static GParamSpec *properties[LAST_PROP];
75 
76 enum
77 {
78 	PRINTING,
79 	SHOW_PREVIEW,
80 	DONE,
81 	LAST_SIGNAL
82 };
83 
84 static guint signals[LAST_SIGNAL];
85 
G_DEFINE_TYPE(GeditPrintJob,gedit_print_job,G_TYPE_OBJECT)86 G_DEFINE_TYPE (GeditPrintJob, gedit_print_job, G_TYPE_OBJECT)
87 
88 static void
89 gedit_print_job_get_property (GObject    *object,
90 			      guint       prop_id,
91 			      GValue     *value,
92 			      GParamSpec *pspec)
93 {
94 	GeditPrintJob *job = GEDIT_PRINT_JOB (object);
95 
96 	switch (prop_id)
97 	{
98 		case PROP_VIEW:
99 			g_value_set_object (value, job->view);
100 			break;
101 
102 		default:
103 			G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
104 			break;
105 	}
106 }
107 
108 static void
gedit_print_job_set_property(GObject * object,guint prop_id,const GValue * value,GParamSpec * pspec)109 gedit_print_job_set_property (GObject      *object,
110 			      guint         prop_id,
111 			      const GValue *value,
112 			      GParamSpec   *pspec)
113 {
114 	GeditPrintJob *job = GEDIT_PRINT_JOB (object);
115 
116 	switch (prop_id)
117 	{
118 		case PROP_VIEW:
119 			job->view = g_value_get_object (value);
120 			break;
121 
122 		default:
123 			G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
124 			break;
125 	}
126 }
127 
128 static void
gedit_print_job_dispose(GObject * object)129 gedit_print_job_dispose (GObject *object)
130 {
131 	GeditPrintJob *job = GEDIT_PRINT_JOB (object);
132 
133 	g_clear_object (&job->gsettings);
134 	g_clear_object (&job->operation);
135 	g_clear_object (&job->compositor);
136 	g_clear_object (&job->preview);
137 
138 	G_OBJECT_CLASS (gedit_print_job_parent_class)->dispose (object);
139 }
140 
141 static void
gedit_print_job_finalize(GObject * object)142 gedit_print_job_finalize (GObject *object)
143 {
144 	GeditPrintJob *job = GEDIT_PRINT_JOB (object);
145 
146 	g_free (job->status_string);
147 
148 	G_OBJECT_CLASS (gedit_print_job_parent_class)->finalize (object);
149 }
150 
151 static void
gedit_print_job_printing(GeditPrintJob * job,GeditPrintJobStatus status)152 gedit_print_job_printing (GeditPrintJob       *job,
153                           GeditPrintJobStatus  status)
154 {
155 }
156 
157 static void
gedit_print_job_show_preview(GeditPrintJob * job,GtkWidget * preview)158 gedit_print_job_show_preview (GeditPrintJob *job,
159                               GtkWidget     *preview)
160 {
161 }
162 
163 static void
gedit_print_job_done(GeditPrintJob * job,GeditPrintJobResult result,const GError * error)164 gedit_print_job_done (GeditPrintJob       *job,
165                       GeditPrintJobResult  result,
166                       const GError        *error)
167 {
168 }
169 
170 static void
gedit_print_job_class_init(GeditPrintJobClass * klass)171 gedit_print_job_class_init (GeditPrintJobClass *klass)
172 {
173 	GObjectClass *object_class;
174 
175 	object_class = G_OBJECT_CLASS (klass);
176 
177 	object_class->get_property = gedit_print_job_get_property;
178 	object_class->set_property = gedit_print_job_set_property;
179 	object_class->dispose = gedit_print_job_dispose;
180 	object_class->finalize = gedit_print_job_finalize;
181 
182 	properties[PROP_VIEW] =
183 		g_param_spec_object ("view",
184 		                     "Gedit View",
185 		                     "Gedit View to print",
186 		                     GEDIT_TYPE_VIEW,
187 		                     G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS | G_PARAM_CONSTRUCT_ONLY);
188 
189 	g_object_class_install_properties (object_class, LAST_PROP, properties);
190 
191 	signals[PRINTING] =
192 		g_signal_new_class_handler ("printing",
193 		                            G_TYPE_FROM_CLASS (klass),
194 		                            G_SIGNAL_RUN_LAST,
195 		                            G_CALLBACK (gedit_print_job_printing),
196 		                            NULL, NULL, NULL,
197 		                            G_TYPE_NONE,
198 		                            1,
199 		                            G_TYPE_UINT);
200 
201 	signals[SHOW_PREVIEW] =
202 		g_signal_new_class_handler ("show-preview",
203 		                            G_TYPE_FROM_CLASS (klass),
204 		                            G_SIGNAL_RUN_LAST,
205 		                            G_CALLBACK (gedit_print_job_show_preview),
206 		                            NULL, NULL, NULL,
207 		                            G_TYPE_NONE,
208 		                            1,
209 		                            GTK_TYPE_WIDGET);
210 
211 	signals[DONE] =
212 		g_signal_new_class_handler ("done",
213 		                            G_TYPE_FROM_CLASS (klass),
214 		                            G_SIGNAL_RUN_LAST,
215 		                            G_CALLBACK (gedit_print_job_done),
216 		                            NULL, NULL, NULL,
217 		                            G_TYPE_NONE,
218 		                            2,
219 		                            G_TYPE_UINT,
220 		                            G_TYPE_POINTER);
221 }
222 
223 static void
gedit_print_job_init(GeditPrintJob * job)224 gedit_print_job_init (GeditPrintJob *job)
225 {
226 	job->gsettings = g_settings_new ("org.gnome.gedit.preferences.print");
227 
228 	job->status_string = g_strdup (_("Preparing…"));
229 }
230 
231 static void
restore_button_clicked(GtkButton * button,GeditPrintJob * job)232 restore_button_clicked (GtkButton     *button,
233 			GeditPrintJob *job)
234 
235 {
236 	g_settings_reset (job->gsettings, GEDIT_SETTINGS_PRINT_FONT_BODY_PANGO);
237 	g_settings_reset (job->gsettings, GEDIT_SETTINGS_PRINT_FONT_HEADER_PANGO);
238 	g_settings_reset (job->gsettings, GEDIT_SETTINGS_PRINT_FONT_NUMBERS_PANGO);
239 }
240 
241 static GObject *
create_custom_widget_cb(GtkPrintOperation * operation,GeditPrintJob * job)242 create_custom_widget_cb (GtkPrintOperation *operation,
243 			 GeditPrintJob     *job)
244 {
245 	GtkBuilder *builder;
246 	GtkWidget *contents;
247 	GtkWidget *line_numbers_hbox;
248 	GtkWidget *restore_button;
249 	guint line_numbers;
250 	GtkWrapMode wrap_mode;
251 
252 	gchar *root_objects[] = {
253 		"adjustment1",
254 		"contents",
255 		NULL
256 	};
257 
258 	builder = gtk_builder_new ();
259 	gtk_builder_add_objects_from_resource (builder, "/org/gnome/gedit/ui/gedit-print-preferences.ui",
260 	                                       root_objects, NULL);
261 	contents = GTK_WIDGET (gtk_builder_get_object (builder, "contents"));
262 	g_object_ref (contents);
263 	job->syntax_checkbutton = GTK_TOGGLE_BUTTON (gtk_builder_get_object (builder, "syntax_checkbutton"));
264 	job->line_numbers_checkbutton = GTK_TOGGLE_BUTTON (gtk_builder_get_object (builder, "line_numbers_checkbutton"));
265 	line_numbers_hbox = GTK_WIDGET (gtk_builder_get_object (builder, "line_numbers_hbox"));
266 	job->line_numbers_spinbutton = GTK_SPIN_BUTTON (gtk_builder_get_object (builder, "line_numbers_spinbutton"));
267 	job->page_header_checkbutton = GTK_TOGGLE_BUTTON (gtk_builder_get_object (builder, "page_header_checkbutton"));
268 	job->text_wrapping_checkbutton = GTK_TOGGLE_BUTTON (gtk_builder_get_object (builder, "text_wrapping_checkbutton"));
269 	job->do_not_split_checkbutton = GTK_TOGGLE_BUTTON (gtk_builder_get_object (builder, "do_not_split_checkbutton"));
270 	job->body_fontbutton = GTK_FONT_BUTTON (gtk_builder_get_object (builder, "body_fontbutton"));
271 	job->headers_fontbutton = GTK_FONT_BUTTON (gtk_builder_get_object (builder, "headers_fontbutton"));
272 	job->numbers_fontbutton = GTK_FONT_BUTTON (gtk_builder_get_object (builder, "numbers_fontbutton"));
273 	restore_button = GTK_WIDGET (gtk_builder_get_object (builder, "restore_button"));
274 	g_object_unref (builder);
275 
276 	/* Syntax highlighting */
277 	g_settings_bind (job->gsettings, GEDIT_SETTINGS_PRINT_SYNTAX_HIGHLIGHTING,
278 			 job->syntax_checkbutton, "active",
279 			 G_SETTINGS_BIND_GET);
280 
281 	/* Print header */
282 	g_settings_bind (job->gsettings, GEDIT_SETTINGS_PRINT_HEADER,
283 			 job->page_header_checkbutton, "active",
284 			 G_SETTINGS_BIND_GET);
285 
286 	/* Line numbers */
287 	g_settings_get (job->gsettings, GEDIT_SETTINGS_PRINT_LINE_NUMBERS,
288 			"u", &line_numbers);
289 
290 	if (line_numbers > 0)
291 	{
292 		gtk_spin_button_set_value (job->line_numbers_spinbutton, line_numbers);
293 	}
294 	else
295 	{
296 		gtk_spin_button_set_value (job->line_numbers_spinbutton, 1);
297 	}
298 
299 	gtk_toggle_button_set_active (job->line_numbers_checkbutton,
300 				      line_numbers > 0);
301 
302 	g_object_bind_property (job->line_numbers_checkbutton, "active",
303 				line_numbers_hbox, "sensitive",
304 				G_BINDING_SYNC_CREATE);
305 
306 	/* Fonts */
307 	g_settings_bind (job->gsettings, GEDIT_SETTINGS_PRINT_FONT_BODY_PANGO,
308 			 job->body_fontbutton, "font-name",
309 			 G_SETTINGS_BIND_GET);
310 
311 	g_settings_bind (job->gsettings, GEDIT_SETTINGS_PRINT_FONT_HEADER_PANGO,
312 			 job->headers_fontbutton, "font-name",
313 			 G_SETTINGS_BIND_GET);
314 
315 	g_settings_bind (job->gsettings, GEDIT_SETTINGS_PRINT_FONT_NUMBERS_PANGO,
316 			 job->numbers_fontbutton, "font-name",
317 			 G_SETTINGS_BIND_GET);
318 
319 	/* Wrap mode */
320 	wrap_mode = g_settings_get_enum (job->gsettings, GEDIT_SETTINGS_PRINT_WRAP_MODE);
321 
322 	switch (wrap_mode)
323 	{
324 		case GTK_WRAP_WORD:
325 			gtk_toggle_button_set_active (job->text_wrapping_checkbutton, TRUE);
326 			gtk_toggle_button_set_active (job->do_not_split_checkbutton, TRUE);
327 			break;
328 
329 		case GTK_WRAP_CHAR:
330 			gtk_toggle_button_set_active (job->text_wrapping_checkbutton, TRUE);
331 			gtk_toggle_button_set_active (job->do_not_split_checkbutton, FALSE);
332 			break;
333 
334 		default:
335 			gtk_toggle_button_set_active (job->text_wrapping_checkbutton, FALSE);
336 			break;
337 	}
338 
339 	g_object_bind_property (job->text_wrapping_checkbutton, "active",
340 				job->do_not_split_checkbutton, "sensitive",
341 				G_BINDING_SYNC_CREATE);
342 
343 	g_object_bind_property (job->text_wrapping_checkbutton, "active",
344 				job->do_not_split_checkbutton, "inconsistent",
345 				G_BINDING_INVERT_BOOLEAN | G_BINDING_SYNC_CREATE);
346 
347 	/* Restore */
348 	g_signal_connect (restore_button,
349 			  "clicked",
350 			  G_CALLBACK (restore_button_clicked),
351 			  job);
352 
353 	return G_OBJECT (contents);
354 }
355 
356 static void
custom_widget_apply_cb(GtkPrintOperation * operation,GtkWidget * widget,GeditPrintJob * job)357 custom_widget_apply_cb (GtkPrintOperation *operation,
358 			GtkWidget         *widget,
359 			GeditPrintJob     *job)
360 {
361 	gboolean syntax;
362 	gboolean page_header;
363 	const gchar *body_font;
364 	const gchar *header_font;
365 	const gchar *numbers_font;
366 	GtkWrapMode wrap_mode;
367 
368 	syntax = gtk_toggle_button_get_active (job->syntax_checkbutton);
369 	page_header = gtk_toggle_button_get_active (job->page_header_checkbutton);
370 	body_font = gtk_font_chooser_get_font (GTK_FONT_CHOOSER (job->body_fontbutton));
371 	header_font = gtk_font_chooser_get_font (GTK_FONT_CHOOSER (job->headers_fontbutton));
372 	numbers_font = gtk_font_chooser_get_font (GTK_FONT_CHOOSER (job->numbers_fontbutton));
373 
374 	g_settings_set_boolean (job->gsettings,
375 				GEDIT_SETTINGS_PRINT_SYNTAX_HIGHLIGHTING,
376 				syntax);
377 
378 	g_settings_set_boolean (job->gsettings,
379 				GEDIT_SETTINGS_PRINT_HEADER,
380 				page_header);
381 
382 	g_settings_set_string (job->gsettings,
383 			       GEDIT_SETTINGS_PRINT_FONT_BODY_PANGO,
384 			       body_font);
385 
386 	g_settings_set_string (job->gsettings,
387 			       GEDIT_SETTINGS_PRINT_FONT_HEADER_PANGO,
388 			       header_font);
389 
390 	g_settings_set_string (job->gsettings,
391 			       GEDIT_SETTINGS_PRINT_FONT_NUMBERS_PANGO,
392 			       numbers_font);
393 
394 	if (gtk_toggle_button_get_active (job->line_numbers_checkbutton))
395 	{
396 		gint num;
397 
398 		num = gtk_spin_button_get_value_as_int (job->line_numbers_spinbutton);
399 
400 		g_settings_set (job->gsettings,
401 				GEDIT_SETTINGS_PRINT_LINE_NUMBERS,
402 				"u", MAX (1, num));
403 	}
404 	else
405 	{
406 		g_settings_set (job->gsettings,
407 				GEDIT_SETTINGS_PRINT_LINE_NUMBERS,
408 				"u", 0);
409 	}
410 
411 	if (gtk_toggle_button_get_active (job->text_wrapping_checkbutton))
412 	{
413 		if (gtk_toggle_button_get_active (job->do_not_split_checkbutton))
414 		{
415 			wrap_mode = GTK_WRAP_WORD;
416 		}
417 		else
418 		{
419 			wrap_mode = GTK_WRAP_CHAR;
420 		}
421 	}
422 	else
423 	{
424 		wrap_mode = GTK_WRAP_NONE;
425 	}
426 
427 	g_settings_set_enum (job->gsettings,
428 			     GEDIT_SETTINGS_PRINT_WRAP_MODE,
429 			     wrap_mode);
430 }
431 
432 static void
preview_ready(GtkPrintOperationPreview * gtk_preview,GtkPrintContext * context,GeditPrintJob * job)433 preview_ready (GtkPrintOperationPreview *gtk_preview,
434 	       GtkPrintContext          *context,
435 	       GeditPrintJob            *job)
436 {
437 	job->is_preview = TRUE;
438 
439 	g_signal_emit (job, signals[SHOW_PREVIEW], 0, job->preview);
440 
441 	g_clear_object (&job->preview);
442 }
443 
444 static gboolean
preview_cb(GtkPrintOperation * op,GtkPrintOperationPreview * gtk_preview,GtkPrintContext * context,GtkWindow * parent,GeditPrintJob * job)445 preview_cb (GtkPrintOperation        *op,
446 	    GtkPrintOperationPreview *gtk_preview,
447 	    GtkPrintContext          *context,
448 	    GtkWindow                *parent,
449 	    GeditPrintJob            *job)
450 {
451 	g_clear_object (&job->preview);
452 	job->preview = gedit_print_preview_new (op, gtk_preview, context);
453 	g_object_ref_sink (job->preview);
454 
455 	g_signal_connect_after (gtk_preview,
456 			        "ready",
457 				G_CALLBACK (preview_ready),
458 				job);
459 
460 	return TRUE;
461 }
462 
463 static void
create_compositor(GeditPrintJob * job)464 create_compositor (GeditPrintJob *job)
465 {
466 	GtkSourceBuffer *buf;
467 	gchar *print_font_body;
468 	gchar *print_font_header;
469 	gchar *print_font_numbers;
470 	gboolean syntax_hl;
471 	GtkWrapMode wrap_mode;
472 	guint print_line_numbers;
473 	gboolean print_header;
474 	guint tab_width;
475 	gdouble margin;
476 
477 	buf = GTK_SOURCE_BUFFER (gtk_text_view_get_buffer (GTK_TEXT_VIEW (job->view)));
478 
479 	print_font_body = g_settings_get_string (job->gsettings,
480 	                                         GEDIT_SETTINGS_PRINT_FONT_BODY_PANGO);
481 
482 	print_font_header = g_settings_get_string (job->gsettings,
483 	                                          GEDIT_SETTINGS_PRINT_FONT_HEADER_PANGO);
484 
485 	print_font_numbers = g_settings_get_string (job->gsettings,
486 	                                            GEDIT_SETTINGS_PRINT_FONT_NUMBERS_PANGO);
487 
488 	g_settings_get (job->gsettings,
489 	                GEDIT_SETTINGS_PRINT_LINE_NUMBERS,
490 	                "u", &print_line_numbers);
491 
492 	print_header = g_settings_get_boolean (job->gsettings,
493 	                                       GEDIT_SETTINGS_PRINT_HEADER);
494 
495 	wrap_mode = g_settings_get_enum (job->gsettings,
496 	                                 GEDIT_SETTINGS_PRINT_WRAP_MODE);
497 
498 	syntax_hl = g_settings_get_boolean (job->gsettings,
499 	                                    GEDIT_SETTINGS_PRINT_SYNTAX_HIGHLIGHTING);
500 
501 	syntax_hl &= gtk_source_buffer_get_highlight_syntax (buf);
502 
503 	tab_width = gtk_source_view_get_tab_width (GTK_SOURCE_VIEW (job->view));
504 
505 	job->compositor = GTK_SOURCE_PRINT_COMPOSITOR (
506 		g_object_new (GTK_SOURCE_TYPE_PRINT_COMPOSITOR,
507 			      "buffer", buf,
508 			      "tab-width", tab_width,
509 			      "highlight-syntax", syntax_hl,
510 			      "wrap-mode", wrap_mode,
511 			      "print-line-numbers", print_line_numbers,
512 			      "print-header", print_header,
513 			      "print-footer", FALSE,
514 			      "body-font-name", print_font_body,
515 			      "line-numbers-font-name", print_font_numbers,
516 			      "header-font-name", print_font_header,
517 			      NULL));
518 
519 	margin = g_settings_get_double (job->gsettings, GEDIT_SETTINGS_PRINT_MARGIN_LEFT);
520 	gtk_source_print_compositor_set_left_margin (job->compositor, margin, GTK_UNIT_MM);
521 
522 	margin = g_settings_get_double (job->gsettings, GEDIT_SETTINGS_PRINT_MARGIN_TOP);
523 	gtk_source_print_compositor_set_top_margin (job->compositor, margin, GTK_UNIT_MM);
524 
525 	margin = g_settings_get_double (job->gsettings, GEDIT_SETTINGS_PRINT_MARGIN_RIGHT);
526 	gtk_source_print_compositor_set_right_margin (job->compositor, margin, GTK_UNIT_MM);
527 
528 	margin = g_settings_get_double (job->gsettings, GEDIT_SETTINGS_PRINT_MARGIN_BOTTOM);
529 	gtk_source_print_compositor_set_bottom_margin (job->compositor, margin, GTK_UNIT_MM);
530 
531 	if (print_header)
532 	{
533 		gchar *doc_name;
534 		gchar *name_to_display;
535 		gchar *left;
536 
537 		doc_name = _gedit_document_get_uri_for_display (GEDIT_DOCUMENT (buf));
538 		name_to_display = tepl_utils_str_middle_truncate (doc_name, 60);
539 
540 		left = g_strdup_printf (_("File: %s"), name_to_display);
541 
542 		gtk_source_print_compositor_set_header_format (job->compositor,
543 							       TRUE,
544 							       left,
545 							       NULL,
546 							       /* Translators: %N is the current page number, %Q is the total
547 							        * number of pages (ex. Page 2 of 10)
548 							        */
549 							       _("Page %N of %Q"));
550 
551 		g_free (doc_name);
552 		g_free (name_to_display);
553 		g_free (left);
554 	}
555 
556 	g_free (print_font_body);
557 	g_free (print_font_header);
558 	g_free (print_font_numbers);
559 }
560 
561 static void
begin_print_cb(GtkPrintOperation * operation,GtkPrintContext * context,GeditPrintJob * job)562 begin_print_cb (GtkPrintOperation *operation,
563 	        GtkPrintContext   *context,
564 	        GeditPrintJob     *job)
565 {
566 	create_compositor (job);
567 
568 	job->progress = 0.0;
569 
570 	g_signal_emit (job,
571 		       signals[PRINTING],
572 		       0,
573 		       GEDIT_PRINT_JOB_STATUS_PAGINATING);
574 }
575 
576 static gboolean
paginate_cb(GtkPrintOperation * operation,GtkPrintContext * context,GeditPrintJob * job)577 paginate_cb (GtkPrintOperation *operation,
578 	     GtkPrintContext   *context,
579 	     GeditPrintJob     *job)
580 {
581 	gboolean finished;
582 
583 	finished = gtk_source_print_compositor_paginate (job->compositor, context);
584 
585 	if (finished)
586 	{
587 		gint n_pages;
588 
589 		n_pages = gtk_source_print_compositor_get_n_pages (job->compositor);
590 		gtk_print_operation_set_n_pages (job->operation, n_pages);
591 	}
592 
593 	job->progress = gtk_source_print_compositor_get_pagination_progress (job->compositor);
594 
595 	/* When previewing, the progress is just for pagination, when printing
596 	 * it's split between pagination and rendering.
597 	 */
598 	if (!job->is_preview)
599 	{
600 		job->progress /= 2.0;
601 	}
602 
603 	g_signal_emit (job,
604 		       signals[PRINTING],
605 		       0,
606 		       GEDIT_PRINT_JOB_STATUS_PAGINATING);
607 
608 	return finished;
609 }
610 
611 static void
draw_page_cb(GtkPrintOperation * operation,GtkPrintContext * context,gint page_nr,GeditPrintJob * job)612 draw_page_cb (GtkPrintOperation *operation,
613 	      GtkPrintContext   *context,
614 	      gint               page_nr,
615 	      GeditPrintJob     *job)
616 {
617 	/* In preview, pages are drawn on the fly, so rendering is
618 	 * not part of the progress.
619 	 */
620 	if (!job->is_preview)
621 	{
622 		gint n_pages;
623 
624 		n_pages = gtk_source_print_compositor_get_n_pages (job->compositor);
625 
626 		g_free (job->status_string);
627 		job->status_string = g_strdup_printf (_("Rendering page %d of %d…"), page_nr + 1, n_pages);
628 
629 		job->progress = page_nr / (2.0 * n_pages) + 0.5;
630 
631 		g_signal_emit (job,
632 			       signals[PRINTING],
633 			       0,
634 			       GEDIT_PRINT_JOB_STATUS_DRAWING);
635 	}
636 
637 	gtk_source_print_compositor_draw_page (job->compositor, context, page_nr);
638 }
639 
640 static void
end_print_cb(GtkPrintOperation * operation,GtkPrintContext * context,GeditPrintJob * job)641 end_print_cb (GtkPrintOperation *operation,
642 	      GtkPrintContext   *context,
643 	      GeditPrintJob     *job)
644 {
645 	g_clear_object (&job->compositor);
646 }
647 
648 static void
done_cb(GtkPrintOperation * operation,GtkPrintOperationResult result,GeditPrintJob * job)649 done_cb (GtkPrintOperation       *operation,
650 	 GtkPrintOperationResult  result,
651 	 GeditPrintJob           *job)
652 {
653 	GError *error = NULL;
654 	GeditPrintJobResult print_result;
655 
656 	switch (result)
657 	{
658 		case GTK_PRINT_OPERATION_RESULT_CANCEL:
659 			print_result = GEDIT_PRINT_JOB_RESULT_CANCEL;
660 			break;
661 
662 		case GTK_PRINT_OPERATION_RESULT_APPLY:
663 			print_result = GEDIT_PRINT_JOB_RESULT_OK;
664 			break;
665 
666 		case GTK_PRINT_OPERATION_RESULT_ERROR:
667 			print_result = GEDIT_PRINT_JOB_RESULT_ERROR;
668 			gtk_print_operation_get_error (operation, &error);
669 			break;
670 
671 		default:
672 			g_return_if_reached ();
673 	}
674 
675 	/* Avoid that job is destroyed in the handler of the "done" message. */
676 	g_object_ref (job);
677 	g_signal_emit (job, signals[DONE], 0, print_result, error);
678 	g_object_unref (job);
679 }
680 
681 GeditPrintJob *
gedit_print_job_new(GeditView * view)682 gedit_print_job_new (GeditView *view)
683 {
684 	g_return_val_if_fail (GEDIT_IS_VIEW (view), NULL);
685 
686 	return g_object_new (GEDIT_TYPE_PRINT_JOB,
687 			     "view", view,
688 			     NULL);
689 }
690 
691 /* Note that gedit_print_job_print() can only be called once on a given
692  * GeditPrintJob.
693  */
694 GtkPrintOperationResult
gedit_print_job_print(GeditPrintJob * job,GtkPrintOperationAction action,GtkPageSetup * page_setup,GtkPrintSettings * settings,GtkWindow * parent,GError ** error)695 gedit_print_job_print (GeditPrintJob            *job,
696 		       GtkPrintOperationAction   action,
697 		       GtkPageSetup             *page_setup,
698 		       GtkPrintSettings         *settings,
699 		       GtkWindow                *parent,
700 		       GError                  **error)
701 {
702 	GeditDocument *doc;
703 	gchar *job_name;
704 
705 	g_return_val_if_fail (job->operation == NULL, GTK_PRINT_OPERATION_RESULT_ERROR);
706 	g_return_val_if_fail (job->compositor == NULL, GTK_PRINT_OPERATION_RESULT_ERROR);
707 
708 	job->operation = gtk_print_operation_new ();
709 
710 	job->is_preview = action == GTK_PRINT_OPERATION_ACTION_PREVIEW;
711 
712 	if (settings != NULL)
713 	{
714 		gtk_print_operation_set_print_settings (job->operation,
715 							settings);
716 	}
717 
718 	if (page_setup != NULL)
719 	{
720 		gtk_print_operation_set_default_page_setup (job->operation,
721 							    page_setup);
722 	}
723 
724 	doc = GEDIT_DOCUMENT (gtk_text_view_get_buffer (GTK_TEXT_VIEW (job->view)));
725 	job_name = gedit_document_get_short_name_for_display (doc);
726 	gtk_print_operation_set_job_name (job->operation, job_name);
727 	g_free (job_name);
728 
729 	gtk_print_operation_set_embed_page_setup (job->operation, TRUE);
730 
731 	gtk_print_operation_set_custom_tab_label (job->operation, _("Text Editor"));
732 
733 	gtk_print_operation_set_allow_async (job->operation, TRUE);
734 
735 	g_signal_connect (job->operation,
736 			  "create-custom-widget",
737 			  G_CALLBACK (create_custom_widget_cb),
738 			  job);
739 
740 	g_signal_connect (job->operation,
741 			  "custom-widget-apply",
742 			  G_CALLBACK (custom_widget_apply_cb),
743 			  job);
744 
745 	g_signal_connect (job->operation,
746 			  "preview",
747 			  G_CALLBACK (preview_cb),
748 			  job);
749 
750 	g_signal_connect (job->operation,
751 			  "begin-print",
752 			  G_CALLBACK (begin_print_cb),
753 			  job);
754 
755 	g_signal_connect (job->operation,
756 			  "paginate",
757 			  G_CALLBACK (paginate_cb),
758 			  job);
759 
760 	g_signal_connect (job->operation,
761 			  "draw-page",
762 			  G_CALLBACK (draw_page_cb),
763 			  job);
764 
765 	g_signal_connect_object (job->operation,
766 				 "end-print",
767 				 G_CALLBACK (end_print_cb),
768 				 job,
769 				 0);
770 
771 	g_signal_connect_object (job->operation,
772 				 "done",
773 				 G_CALLBACK (done_cb),
774 				 job,
775 				 0);
776 
777 	return gtk_print_operation_run (job->operation,
778 					action,
779 					parent,
780 					error);
781 }
782 
783 void
gedit_print_job_cancel(GeditPrintJob * job)784 gedit_print_job_cancel (GeditPrintJob *job)
785 {
786 	g_return_if_fail (GEDIT_IS_PRINT_JOB (job));
787 
788 	gtk_print_operation_cancel (job->operation);
789 }
790 
791 const gchar *
gedit_print_job_get_status_string(GeditPrintJob * job)792 gedit_print_job_get_status_string (GeditPrintJob *job)
793 {
794 	g_return_val_if_fail (GEDIT_IS_PRINT_JOB (job), NULL);
795 	g_return_val_if_fail (job->status_string != NULL, NULL);
796 
797 	return job->status_string;
798 }
799 
800 gdouble
gedit_print_job_get_progress(GeditPrintJob * job)801 gedit_print_job_get_progress (GeditPrintJob *job)
802 {
803 	g_return_val_if_fail (GEDIT_IS_PRINT_JOB (job), 0.0);
804 
805 	return job->progress;
806 }
807 
808 GtkPrintSettings *
gedit_print_job_get_print_settings(GeditPrintJob * job)809 gedit_print_job_get_print_settings (GeditPrintJob *job)
810 {
811 	g_return_val_if_fail (GEDIT_IS_PRINT_JOB (job), NULL);
812 
813 	return gtk_print_operation_get_print_settings (job->operation);
814 }
815 
816 GtkPageSetup *
gedit_print_job_get_page_setup(GeditPrintJob * job)817 gedit_print_job_get_page_setup (GeditPrintJob *job)
818 {
819 	g_return_val_if_fail (GEDIT_IS_PRINT_JOB (job), NULL);
820 
821 	return gtk_print_operation_get_default_page_setup (job->operation);
822 }
823 
824 /* ex:set ts=8 noet: */
825