1 /* GIMP - The GNU Image Manipulation Program
2 * Copyright (C) 1995 Spencer Kimball and Peter Mattis
3 *
4 * This program is free software: you can redistribute it and/or modify
5 * it under the terms of the GNU General Public License as published by
6 * the Free Software Foundation; either version 3 of the License, or
7 * (at your option) any later version.
8 *
9 * This program is distributed in the hope that it will be useful,
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 * GNU General Public License for more details.
13 *
14 * You should have received a copy of the GNU General Public License
15 * along with this program. If not, see <https://www.gnu.org/licenses/>.
16 */
17
18 #include "config.h"
19
20 #include <string.h>
21
22 #include <libgimp/gimp.h>
23 #include <libgimp/gimpui.h>
24
25 #include "print.h"
26 #include "print-settings.h"
27 #include "print-page-layout.h"
28 #include "print-page-setup.h"
29 #include "print-draw-page.h"
30
31 #include "libgimp/stdplugins-intl.h"
32
33
34 #define PLUG_IN_BINARY "print"
35 #define PLUG_IN_ROLE "gimp-print"
36 #define PRINT_PROC_NAME "file-print-gtk"
37
38 #ifndef EMBED_PAGE_SETUP
39 #define PAGE_SETUP_PROC_NAME "file-print-gtk-page-setup"
40 #define PRINT_TEMP_PROC_NAME "file-print-gtk-page-setup-notify-temp"
41 #endif
42
43 G_DEFINE_QUARK (gimp-plugin-print-error-quark, gimp_plugin_print_error)
44
45 static void query (void);
46 static void run (const gchar *name,
47 gint nparams,
48 const GimpParam *param,
49 gint *nreturn_vals,
50 GimpParam **return_vals);
51
52 static GimpPDBStatusType print_image (gint32 image_ID,
53 gboolean interactive,
54 GError **error);
55 #ifndef EMBED_PAGE_SETUP
56 static GimpPDBStatusType page_setup (gint32 image_ID);
57 #endif
58
59 static void print_show_error (const gchar *message);
60 static void print_operation_set_name (GtkPrintOperation *operation,
61 gint image_ID);
62
63 static void begin_print (GtkPrintOperation *operation,
64 GtkPrintContext *context,
65 PrintData *data);
66 static void end_print (GtkPrintOperation *operation,
67 GtkPrintContext *context,
68 gint32 *layer_ID);
69 static void draw_page (GtkPrintOperation *print,
70 GtkPrintContext *context,
71 gint page_nr,
72 PrintData *data);
73
74 static GtkWidget * create_custom_widget (GtkPrintOperation *operation,
75 PrintData *data);
76
77 #ifndef EMBED_PAGE_SETUP
78 static gchar * print_temp_proc_name (gint32 image_ID);
79 static gchar * print_temp_proc_install (gint32 image_ID);
80
81 /* Keep a reference to the current GtkPrintOperation
82 * for access by the temporary procedure.
83 */
84 static GtkPrintOperation *print_operation = NULL;
85 #endif
86
87
88 const GimpPlugInInfo PLUG_IN_INFO =
89 {
90 NULL, /* init_proc */
91 NULL, /* quit_proc */
92 query, /* query_proc */
93 run, /* run_proc */
94 };
95
MAIN()96 MAIN ()
97
98 static void
99 query (void)
100 {
101 static const GimpParamDef print_args[] =
102 {
103 { GIMP_PDB_INT32, "run-mode", "The run mode { RUN-INTERACTIVE (0) }" },
104 { GIMP_PDB_IMAGE, "image", "Image to print" }
105 };
106
107 gimp_install_procedure (PRINT_PROC_NAME,
108 N_("Print the image"),
109 "Print the image using the GTK+ Print API.",
110 "Bill Skaggs, Sven Neumann, Stefan Röllin",
111 "Bill Skaggs <weskaggs@primate.ucdavis.edu>",
112 "2006 - 2008",
113 N_("_Print..."),
114 "*",
115 GIMP_PLUGIN,
116 G_N_ELEMENTS (print_args), 0,
117 print_args, NULL);
118
119 gimp_plugin_menu_register (PRINT_PROC_NAME, "<Image>/File/Send");
120 gimp_plugin_icon_register (PRINT_PROC_NAME, GIMP_ICON_TYPE_ICON_NAME,
121 (const guint8 *) GIMP_ICON_DOCUMENT_PRINT);
122
123 #ifndef EMBED_PAGE_SETUP
124 gimp_install_procedure (PAGE_SETUP_PROC_NAME,
125 N_("Adjust page size and orientation for printing"),
126 "Adjust page size and orientation for printing the "
127 "image using the GTK+ Print API.",
128 "Bill Skaggs, Sven Neumann, Stefan Röllin",
129 "Sven Neumann <sven@gimp.org>",
130 "2008",
131 N_("Page Set_up..."),
132 "*",
133 GIMP_PLUGIN,
134 G_N_ELEMENTS (print_args), 0,
135 print_args, NULL);
136
137 gimp_plugin_menu_register (PAGE_SETUP_PROC_NAME, "<Image>/File/Send");
138 gimp_plugin_icon_register (PAGE_SETUP_PROC_NAME, GIMP_ICON_TYPE_ICON_NAME,
139 (const guint8 *) GIMP_ICON_DOCUMENT_PAGE_SETUP);
140 #endif
141 }
142
143 static void
run(const gchar * name,gint nparams,const GimpParam * param,gint * nreturn_vals,GimpParam ** return_vals)144 run (const gchar *name,
145 gint nparams,
146 const GimpParam *param,
147 gint *nreturn_vals,
148 GimpParam **return_vals)
149 {
150 static GimpParam values[2];
151 GimpRunMode run_mode;
152 GimpPDBStatusType status;
153 gint32 image_ID;
154 GError *error = NULL;
155
156 INIT_I18N ();
157 gegl_init (NULL, NULL);
158
159 run_mode = param[0].data.d_int32;
160
161 *nreturn_vals = 1;
162 *return_vals = values;
163
164 values[0].type = GIMP_PDB_STATUS;
165 values[0].data.d_status = GIMP_PDB_EXECUTION_ERROR;
166
167 image_ID = param[1].data.d_int32;
168
169 if (strcmp (name, PRINT_PROC_NAME) == 0)
170 {
171 status = print_image (image_ID, run_mode == GIMP_RUN_INTERACTIVE, &error);
172
173 if (error && run_mode == GIMP_RUN_INTERACTIVE)
174 {
175 print_show_error (error->message);
176 }
177 }
178 #ifndef EMBED_PAGE_SETUP
179 else if (strcmp (name, PAGE_SETUP_PROC_NAME) == 0)
180 {
181 if (run_mode == GIMP_RUN_INTERACTIVE)
182 {
183 status = page_setup (image_ID);
184 }
185 else
186 {
187 status = GIMP_PDB_CALLING_ERROR;
188 }
189 }
190 #endif
191 else
192 {
193 status = GIMP_PDB_CALLING_ERROR;
194 }
195
196 if (status != GIMP_PDB_SUCCESS && error)
197 {
198 *nreturn_vals = 2;
199 values[1].type = GIMP_PDB_STRING;
200 values[1].data.d_string = error->message;
201 }
202
203 values[0].data.d_status = status;
204 }
205
206 static GimpPDBStatusType
print_image(gint32 image_ID,gboolean interactive,GError ** error)207 print_image (gint32 image_ID,
208 gboolean interactive,
209 GError **error)
210 {
211 GtkPrintOperation *operation;
212 GtkPrintOperationResult result;
213 gint32 layer;
214 PrintData data;
215 #ifndef EMBED_PAGE_SETUP
216 gchar *temp_proc;
217 #endif
218
219 /* create a print layer from the projection */
220 layer = gimp_layer_new_from_visible (image_ID, image_ID, PRINT_PROC_NAME);
221
222 operation = gtk_print_operation_new ();
223
224 gtk_print_operation_set_n_pages (operation, 1);
225 print_operation_set_name (operation, image_ID);
226
227 print_page_setup_load (operation, image_ID);
228
229 /* fill in the PrintData struct */
230 data.image_id = image_ID;
231 data.drawable_id = layer;
232 data.unit = gimp_get_default_unit ();
233 data.image_unit = gimp_image_get_unit (image_ID);
234 data.offset_x = 0;
235 data.offset_y = 0;
236 data.center = CENTER_BOTH;
237 data.use_full_page = FALSE;
238 data.draw_crop_marks = FALSE;
239 data.operation = operation;
240
241 gimp_image_get_resolution (image_ID, &data.xres, &data.yres);
242
243 print_settings_load (&data);
244
245 gtk_print_operation_set_unit (operation, GTK_UNIT_PIXEL);
246
247 g_signal_connect (operation, "begin-print",
248 G_CALLBACK (begin_print),
249 &data);
250 g_signal_connect (operation, "draw-page",
251 G_CALLBACK (draw_page),
252 &data);
253 g_signal_connect (operation, "end-print",
254 G_CALLBACK (end_print),
255 &layer);
256
257 #ifndef EMBED_PAGE_SETUP
258 print_operation = operation;
259 temp_proc = print_temp_proc_install (image_ID);
260 gimp_extension_enable ();
261 #endif
262
263 if (interactive)
264 {
265 gimp_ui_init (PLUG_IN_BINARY, FALSE);
266
267 g_signal_connect_swapped (operation, "end-print",
268 G_CALLBACK (print_settings_save),
269 &data);
270
271 g_signal_connect (operation, "create-custom-widget",
272 G_CALLBACK (create_custom_widget),
273 &data);
274
275 gtk_print_operation_set_custom_tab_label (operation, _("Image Settings"));
276
277 #ifdef EMBED_PAGE_SETUP
278 gtk_print_operation_set_embed_page_setup (operation, TRUE);
279 #endif
280
281 result = gtk_print_operation_run (operation,
282 GTK_PRINT_OPERATION_ACTION_PRINT_DIALOG,
283 NULL, error);
284
285 if (result == GTK_PRINT_OPERATION_RESULT_APPLY ||
286 result == GTK_PRINT_OPERATION_RESULT_IN_PROGRESS)
287 {
288 print_page_setup_save (operation, image_ID);
289 }
290 }
291 else
292 {
293 result = gtk_print_operation_run (operation,
294 GTK_PRINT_OPERATION_ACTION_PRINT,
295 NULL, error);
296 }
297
298 #ifndef EMBED_PAGE_SETUP
299 gimp_uninstall_temp_proc (temp_proc);
300 g_free (temp_proc);
301 print_operation = NULL;
302 #endif
303
304 g_object_unref (operation);
305
306 if (gimp_item_is_valid (layer))
307 gimp_item_delete (layer);
308
309 switch (result)
310 {
311 case GTK_PRINT_OPERATION_RESULT_APPLY:
312 case GTK_PRINT_OPERATION_RESULT_IN_PROGRESS:
313 return GIMP_PDB_SUCCESS;
314
315 case GTK_PRINT_OPERATION_RESULT_CANCEL:
316 return GIMP_PDB_CANCEL;
317
318 case GTK_PRINT_OPERATION_RESULT_ERROR:
319 return GIMP_PDB_EXECUTION_ERROR;
320 }
321
322 return GIMP_PDB_EXECUTION_ERROR;
323 }
324
325 #ifndef EMBED_PAGE_SETUP
326 static GimpPDBStatusType
page_setup(gint32 image_ID)327 page_setup (gint32 image_ID)
328 {
329 GtkPrintOperation *operation;
330 GimpParam *return_vals;
331 gchar *name;
332 gint n_return_vals;
333
334 gimp_ui_init (PLUG_IN_BINARY, FALSE);
335
336 operation = gtk_print_operation_new ();
337
338 print_page_setup_load (operation, image_ID);
339 print_page_setup_dialog (operation);
340 print_page_setup_save (operation, image_ID);
341
342 g_object_unref (operation);
343
344 /* now notify a running print procedure about this change */
345 name = print_temp_proc_name (image_ID);
346
347 /* we don't want the core to show an error message if the
348 * temporary procedure does not exist
349 */
350 gimp_plugin_set_pdb_error_handler (GIMP_PDB_ERROR_HANDLER_PLUGIN);
351
352 return_vals = gimp_run_procedure (name,
353 &n_return_vals,
354 GIMP_PDB_IMAGE, image_ID,
355 GIMP_PDB_END);
356 gimp_destroy_params (return_vals, n_return_vals);
357
358 g_free (name);
359
360 return GIMP_PDB_SUCCESS;
361 }
362 #endif
363
364 static void
print_show_error(const gchar * message)365 print_show_error (const gchar *message)
366 {
367 GtkWidget *dialog;
368
369 dialog = gtk_message_dialog_new (NULL, 0,
370 GTK_MESSAGE_ERROR,
371 GTK_BUTTONS_OK,
372 "%s",
373 _("An error occurred while trying to print:"));
374
375 gtk_message_dialog_format_secondary_text (GTK_MESSAGE_DIALOG (dialog),
376 "%s", message);
377
378 gtk_dialog_run (GTK_DIALOG (dialog));
379 gtk_widget_destroy (dialog);
380 }
381
382 static void
print_operation_set_name(GtkPrintOperation * operation,gint image_ID)383 print_operation_set_name (GtkPrintOperation *operation,
384 gint image_ID)
385 {
386 gchar *name = gimp_image_get_name (image_ID);
387
388 gtk_print_operation_set_job_name (operation, name);
389
390 g_free (name);
391 }
392
393 static void
begin_print(GtkPrintOperation * operation,GtkPrintContext * context,PrintData * data)394 begin_print (GtkPrintOperation *operation,
395 GtkPrintContext *context,
396 PrintData *data)
397 {
398 gtk_print_operation_set_use_full_page (operation, data->use_full_page);
399
400 gimp_progress_init (_("Printing"));
401 }
402
403 static void
end_print(GtkPrintOperation * operation,GtkPrintContext * context,gint32 * layer_ID)404 end_print (GtkPrintOperation *operation,
405 GtkPrintContext *context,
406 gint32 *layer_ID)
407 {
408 /* we don't need the print layer any longer, delete it */
409 if (gimp_item_is_valid (*layer_ID))
410 {
411 gimp_item_delete (*layer_ID);
412 *layer_ID = -1;
413 }
414
415 gimp_progress_end ();
416
417 /* generate events to solve the problems described in bug #466928 */
418 g_timeout_add_seconds (1, (GSourceFunc) gtk_true, NULL);
419 }
420
421 static void
draw_page(GtkPrintOperation * operation,GtkPrintContext * context,gint page_nr,PrintData * data)422 draw_page (GtkPrintOperation *operation,
423 GtkPrintContext *context,
424 gint page_nr,
425 PrintData *data)
426 {
427 GError *error = NULL;
428
429 if (print_draw_page (context, data, &error))
430 {
431 gimp_progress_update (1.0);
432 }
433 else
434 {
435 print_show_error (error->message);
436 g_error_free (error);
437 }
438 }
439
440
441 /*
442 * This callback creates a "custom" widget that gets inserted into the
443 * print operation dialog.
444 */
445 static GtkWidget *
create_custom_widget(GtkPrintOperation * operation,PrintData * data)446 create_custom_widget (GtkPrintOperation *operation,
447 PrintData *data)
448 {
449 return print_page_layout_gui (data, PRINT_PROC_NAME);
450 }
451
452 #ifndef EMBED_PAGE_SETUP
453 static void
print_temp_proc_run(const gchar * name,gint nparams,const GimpParam * param,gint * nreturn_vals,GimpParam ** return_vals)454 print_temp_proc_run (const gchar *name,
455 gint nparams,
456 const GimpParam *param,
457 gint *nreturn_vals,
458 GimpParam **return_vals)
459 {
460 static GimpParam values[1];
461
462 values[0].type = GIMP_PDB_STATUS;
463 values[0].data.d_status = GIMP_PDB_SUCCESS;
464
465 *nreturn_vals = 1;
466 *return_vals = values;
467
468 if (print_operation && nparams == 1)
469 print_page_setup_load (print_operation, param[0].data.d_int32);
470 }
471
472 static gchar *
print_temp_proc_name(gint32 image_ID)473 print_temp_proc_name (gint32 image_ID)
474 {
475 return g_strdup_printf (PRINT_TEMP_PROC_NAME "-%d", image_ID);
476 }
477
478 static gchar *
print_temp_proc_install(gint32 image_ID)479 print_temp_proc_install (gint32 image_ID)
480 {
481 static const GimpParamDef args[] =
482 {
483 { GIMP_PDB_IMAGE, "image", "Image to print" }
484 };
485
486 gchar *name = print_temp_proc_name (image_ID);
487
488 gimp_install_temp_proc (name,
489 "DON'T USE THIS ONE",
490 "Temporary procedure to notify the Print plug-in "
491 "about changes to the Page Setup.",
492 "Sven Neumann",
493 "Sven Neumann",
494 "2008",
495 NULL,
496 "",
497 GIMP_TEMPORARY,
498 G_N_ELEMENTS (args), 0, args, NULL,
499 print_temp_proc_run);
500
501 return name;
502 }
503 #endif
504