]> git.sur5r.net Git - glabels/blob - src/print-op.c
Imported Upstream version 2.2.8
[glabels] / src / print-op.c
1 /* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 8 -*- */
2
3 /*
4  *  (GLABELS) Label and Business Card Creation program for GNOME
5  *
6  *  print-op.c:  Print operation module
7  *
8  *  Copyright (C) 2001-2007  Jim Evins <evins@snaught.com>.
9  *
10  *  This program is free software; you can redistribute it and/or modify
11  *  it under the terms of the GNU General Public License as published by
12  *  the Free Software Foundation; either version 2 of the License, or
13  *  (at your option) any later version.
14  *
15  *  This program is distributed in the hope that it will be useful,
16  *  but WITHOUT ANY WARRANTY; without even the implied warranty of
17  *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
18  *  GNU General Public License for more details.
19  *
20  *  You should have received a copy of the GNU General Public License
21  *  along with this program; if not, write to the Free Software
22  *  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307 USA
23  */
24 #include <config.h>
25
26 #include "print-op.h"
27
28 #include <glib/gi18n.h>
29 #include <glade/glade-xml.h>
30 #include <math.h>
31 #include <time.h>
32 #include <ctype.h>
33 #include <gtk/gtktogglebutton.h>
34
35 #include <libglabels/db.h>
36 #include "print.h"
37 #include "label.h"
38
39 #include "wdgt-print-copies.h"
40 #include "wdgt-print-merge.h"
41
42 #include "debug.h"
43
44 /*===========================================*/
45 /* Private data types                        */
46 /*===========================================*/
47
48 struct _glPrintOpPrivate {
49
50         glLabel   *label;
51
52         GtkWidget *simple_frame;
53         GtkWidget *copies_vbox;
54         GtkWidget *copies;
55
56         GtkWidget *merge_frame;
57         GtkWidget *prmerge_vbox;
58         GtkWidget *prmerge;
59
60         GtkWidget *outline_check;
61         GtkWidget *reverse_check;
62         GtkWidget *crop_marks_check;
63
64         gboolean   force_outline_flag;
65
66         gchar     *filename;
67
68         gboolean   outline_flag;
69         gboolean   reverse_flag;
70         gboolean   crop_marks_flag;
71         gboolean   merge_flag;
72         gboolean   collate_flag;
73
74         gint       first;
75         gint       last;
76         gint       n_sheets;
77         gint       n_copies;
78
79         glPrintState state;
80 };
81
82 struct _glPrintOpSettings
83 {
84
85         GtkPrintSettings *gtk_settings;
86
87         gboolean          outline_flag;
88         gboolean          reverse_flag;
89         gboolean          crop_marks_flag;
90         gboolean          collate_flag;
91
92         gint              first;
93         gint              last;
94         gint              n_sheets;
95         gint              n_copies;
96         
97 };
98
99
100 /*===========================================*/
101 /* Private globals                           */
102 /*===========================================*/
103
104 /*===========================================*/
105 /* Local function prototypes                 */
106 /*===========================================*/
107
108 static void     gl_print_op_finalize      (GObject            *object);
109
110 static void     gl_print_op_construct       (glPrintOp          *op,
111                                              glLabel            *label);
112
113 static void     gl_print_op_construct_batch (glPrintOp          *op,
114                                              glLabel            *label,
115                                              gchar              *filename,
116                                              gint                n_sheets,
117                                              gint                n_copies,
118                                              gint                first,
119                                              gboolean            outline_flag,
120                                              gboolean            reverse_flag,
121                                              gboolean            crop_marks_flag);
122
123
124 static void     set_page_size                 (glPrintOp         *op,
125                                                glLabel           *label);
126
127 static GObject *create_custom_widget_cb       (GtkPrintOperation *operation,
128                                                gpointer           user_data);
129
130 static void     custom_widget_apply_cb        (GtkPrintOperation *operation,
131                                                GtkWidget         *widget,
132                                                gpointer           user_data);
133
134 static void     begin_print_cb                (GtkPrintOperation *operation,
135                                                GtkPrintContext   *context,
136                                                gpointer           user_data);
137
138 static void     draw_page_cb                  (GtkPrintOperation *operation,
139                                                GtkPrintContext   *context,
140                                                int                page_nr,
141                                                gpointer           user_data);
142
143
144
145 \f
146 /*****************************************************************************/
147 /* Boilerplate object stuff.                                                 */
148 /*****************************************************************************/
149 G_DEFINE_TYPE (glPrintOp, gl_print_op, GTK_TYPE_PRINT_OPERATION);
150
151 static void
152 gl_print_op_class_init (glPrintOpClass *class)
153 {
154         GObjectClass           *object_class = G_OBJECT_CLASS (class);
155
156         gl_debug (DEBUG_PRINT, "");
157         
158         gl_print_op_parent_class = g_type_class_peek_parent (class);
159
160         object_class->finalize = gl_print_op_finalize;
161 }
162
163 static void
164 gl_print_op_init (glPrintOp *op)
165 {
166         gl_debug (DEBUG_PRINT, "");
167
168         gtk_print_operation_set_use_full_page (GTK_PRINT_OPERATION (op), TRUE);
169
170         gtk_print_operation_set_unit (GTK_PRINT_OPERATION (op), GTK_UNIT_POINTS);
171
172         op->priv = g_new0 (glPrintOpPrivate, 1);
173
174 }
175
176 static void 
177 gl_print_op_finalize (GObject *object)
178 {
179         glPrintOp* op = GL_PRINT_OP (object);
180         
181         gl_debug (DEBUG_PRINT, "");
182
183         g_return_if_fail (object != NULL);
184         g_return_if_fail (GL_IS_PRINT_OP (op));
185         g_return_if_fail (op->priv != NULL);
186
187         if (op->priv->label) {
188                 g_object_unref (G_OBJECT(op->priv->label));
189         }
190         g_free (op->priv->filename);
191         g_free (op->priv);
192
193         G_OBJECT_CLASS (gl_print_op_parent_class)->finalize (object);
194
195         g_free (op->priv);
196 }
197
198 /*****************************************************************************/
199 /* NEW print op.                                                         */
200 /*****************************************************************************/
201 glPrintOp *
202 gl_print_op_new (glLabel      *label)
203 {
204         glPrintOp *op;
205
206         gl_debug (DEBUG_PRINT, "");
207
208         op = GL_PRINT_OP (g_object_new (GL_TYPE_PRINT_OP, NULL));
209
210         gl_print_op_construct (GL_PRINT_OP(op), label);
211
212         return op;
213 }
214
215 /*--------------------------------------------------------------------------*/
216 /* PRIVATE.  Construct op.                                              */
217 /*--------------------------------------------------------------------------*/
218 static void
219 gl_print_op_construct (glPrintOp      *op,
220                        glLabel        *label)
221 {
222         const lglTemplateFrame *frame;
223
224         op->priv->label              = label;
225         op->priv->force_outline_flag = FALSE;
226
227         frame = (lglTemplateFrame *)label->template->frames->data;
228
229         op->priv->n_sheets           = 1;
230         op->priv->first              = 1;
231         op->priv->last               = lgl_template_frame_get_n_labels (frame);
232         op->priv->n_copies           = 1;
233
234         set_page_size (op, label);
235
236         gtk_print_operation_set_custom_tab_label ( GTK_PRINT_OPERATION (op),
237                                                    _("Labels"));
238
239         g_signal_connect (G_OBJECT (op), "create-custom-widget",
240                           G_CALLBACK (create_custom_widget_cb), label);
241
242         g_signal_connect (G_OBJECT (op), "custom-widget-apply",
243                           G_CALLBACK (custom_widget_apply_cb), label);
244
245         g_signal_connect (G_OBJECT (op), "begin-print",
246                           G_CALLBACK (begin_print_cb), label);
247
248         g_signal_connect (G_OBJECT (op), "draw-page",
249                           G_CALLBACK (draw_page_cb), label);
250 }
251
252 /*****************************************************************************/
253 /* NEW batch print operation.                                                */
254 /*****************************************************************************/
255 glPrintOp *
256 gl_print_op_new_batch (glLabel       *label,
257                        gchar         *filename,
258                        gint           n_sheets,
259                        gint           n_copies,
260                        gint           first,
261                        gboolean       outline_flag,
262                        gboolean       reverse_flag,
263                        gboolean       crop_marks_flag)
264 {
265         glPrintOp *op;
266
267         gl_debug (DEBUG_PRINT, "");
268
269         op = GL_PRINT_OP (g_object_new (GL_TYPE_PRINT_OP, NULL));
270
271         gl_print_op_construct_batch (GL_PRINT_OP(op),
272                                          label,
273                                          filename,
274                                          n_sheets,
275                                          n_copies,
276                                          first,
277                                          outline_flag,
278                                          reverse_flag,
279                                          crop_marks_flag);
280
281         return op;
282 }
283
284 /*****************************************************************************/
285 /* Get print operation settings.                                             */
286 /*****************************************************************************/
287 glPrintOpSettings *
288 gl_print_op_get_settings (glPrintOp         *print_op)
289 {
290         glPrintOpSettings *settings;
291
292         settings = g_new0 (glPrintOpSettings, 1);
293
294         if ( settings )
295         {
296                 settings->gtk_settings =
297                         gtk_print_operation_get_print_settings (GTK_PRINT_OPERATION (print_op));
298
299                 settings->outline_flag     = print_op->priv->outline_flag;
300                 settings->reverse_flag     = print_op->priv->reverse_flag;
301                 settings->crop_marks_flag  = print_op->priv->crop_marks_flag;
302                 settings->collate_flag     = print_op->priv->collate_flag;
303
304                 settings->first            = print_op->priv->first;
305                 settings->last             = print_op->priv->last;
306                 settings->n_sheets         = print_op->priv->n_sheets;
307                 settings->n_copies         = print_op->priv->n_copies;
308         }
309
310         return settings;
311 }
312
313 /*****************************************************************************/
314 /* Set print operation settings.                                             */
315 /*****************************************************************************/
316 void
317 gl_print_op_set_settings (glPrintOp         *print_op,
318                           glPrintOpSettings *settings)
319 {
320
321         if ( settings )
322         {
323                 gtk_print_operation_set_print_settings (GTK_PRINT_OPERATION (print_op),
324                                                         settings->gtk_settings);
325
326                 print_op->priv->outline_flag     = settings->outline_flag;
327                 print_op->priv->reverse_flag     = settings->reverse_flag;
328                 print_op->priv->crop_marks_flag  = settings->crop_marks_flag;
329                 print_op->priv->collate_flag     = settings->collate_flag;
330
331                 print_op->priv->first            = settings->first;
332                 print_op->priv->last             = settings->last;
333                 print_op->priv->n_sheets         = settings->n_sheets;
334                 print_op->priv->n_copies         = settings->n_copies;
335         }
336
337  }
338
339 /*****************************************************************************/
340 /* Free print operation settings structure.                                  */
341 /*****************************************************************************/
342 void
343 gl_print_op_free_settings(glPrintOpSettings *settings)
344 {
345         
346         if ( settings )
347         {
348                 if ( settings->gtk_settings )
349                 {
350                         g_object_unref (settings->gtk_settings);
351                 }
352
353                 g_free (settings);
354         }
355 }
356
357 /*--------------------------------------------------------------------------*/
358 /* PRIVATE.  Construct op.                                                  */
359 /*--------------------------------------------------------------------------*/
360 static void
361 gl_print_op_construct_batch (glPrintOp      *op,
362                              glLabel        *label,
363                              gchar          *filename,
364                              gint            n_sheets,
365                              gint            n_copies,
366                              gint            first,
367                              gboolean        outline_flag,
368                              gboolean        reverse_flag,
369                              gboolean        crop_marks_flag)
370
371 {
372         glMerge                *merge = NULL;
373         const lglTemplateFrame *frame = NULL;
374
375         op->priv->label              = label;
376         op->priv->force_outline_flag = FALSE;
377         op->priv->filename           = g_strdup (filename);
378         op->priv->n_sheets           = n_sheets;
379         op->priv->n_copies           = n_copies;
380         op->priv->first              = first;
381         op->priv->outline_flag       = outline_flag;
382         op->priv->reverse_flag       = reverse_flag;
383         op->priv->crop_marks_flag    = crop_marks_flag;
384
385         merge = gl_label_get_merge (label);
386
387         frame = (lglTemplateFrame *)label->template->frames->data;
388         if (merge == NULL)
389         {
390                 op->priv->merge_flag = FALSE;
391
392                 op->priv->last = lgl_template_frame_get_n_labels (frame);
393
394         }
395         else
396         {
397                 op->priv->merge_flag = TRUE;
398
399                 op->priv->n_sheets =
400                         ceil ((double)(first-1 + n_copies * gl_merge_get_record_count(merge))
401                               / lgl_template_frame_get_n_labels (frame));;
402
403                 g_object_unref (G_OBJECT(merge));
404
405         }
406
407         set_page_size (op, label);
408
409         gtk_print_operation_set_export_filename (GTK_PRINT_OPERATION (op),
410                                                  filename);
411
412         g_signal_connect (G_OBJECT (op), "begin-print",
413                           G_CALLBACK (begin_print_cb), label);
414
415         g_signal_connect (G_OBJECT (op), "draw-page",
416                           G_CALLBACK (draw_page_cb), label);
417 }
418
419 /*--------------------------------------------------------------------------*/
420 /* PRIVATE.  Set page size.                                                 */
421 /*--------------------------------------------------------------------------*/
422 static void
423 set_page_size (glPrintOp  *op,
424                glLabel    *label)
425 {
426         GtkPaperSize *psize;
427         GtkPageSetup *su;
428         lglPaper     *paper;
429
430         gl_debug (DEBUG_PRINT, "begin");
431
432         paper = lgl_db_lookup_paper_from_id (label->template->paper_id);
433
434         if (!paper)
435         {
436                 const gchar *name;
437
438                 name = gtk_paper_size_get_default ();
439                 psize = gtk_paper_size_new (name);
440
441                 gl_debug (DEBUG_PRINT, "Using default size = \"%s\"", name);
442         }
443         else if (lgl_db_is_paper_id_other (paper->id))
444         {
445                 psize = gtk_paper_size_new_custom (paper->id,
446                                                    paper->name,
447                                                    label->template->page_width,
448                                                    label->template->page_height,
449                                                    GTK_UNIT_POINTS);
450                 gl_debug (DEBUG_PRINT, "Using custom size = %g x %g points",
451                           label->template->page_width,
452                           label->template->page_height);
453
454         }
455         else
456         {
457                 psize = gtk_paper_size_new (paper->pwg_size);
458                 gl_debug (DEBUG_PRINT, "Using PWG size \"%s\"", paper->pwg_size);
459         }
460         lgl_paper_free (paper);
461
462         su = gtk_page_setup_new ();
463         gtk_page_setup_set_paper_size (su, psize);
464         gtk_print_operation_set_default_page_setup (GTK_PRINT_OPERATION (op), su);
465         g_object_unref (su);
466
467         gtk_paper_size_free (psize);
468
469         gl_debug (DEBUG_PRINT, "end");
470 }
471
472 /*--------------------------------------------------------------------------*/
473 /* PRIVATE.  "Create custom widget" callback                                */
474 /*--------------------------------------------------------------------------*/
475 static GObject *
476 create_custom_widget_cb (GtkPrintOperation *operation,
477                          gpointer           user_data)
478 {
479         GladeXML      *gui;
480         glPrintOp     *op = GL_PRINT_OP (operation);
481         glLabel       *label  = GL_LABEL (user_data);
482         GtkWidget     *vbox;
483         glMerge       *merge = NULL;
484
485         gui = glade_xml_new (GLABELS_GLADE_DIR "print-custom-widget.glade",
486                              "print_custom_widget_vbox", NULL);
487
488         if (!gui) {
489                 g_warning ("Could not open print-op.glade, reinstall glabels!");
490                 return NULL;
491         }
492
493         vbox = glade_xml_get_widget (gui, "print_custom_widget_vbox");
494
495         /* ----- Simple print control ----- */
496         op->priv->simple_frame = glade_xml_get_widget (gui, "simple_frame");
497         op->priv->copies_vbox  = glade_xml_get_widget (gui, "copies_vbox");
498         op->priv->copies = gl_wdgt_print_copies_new (label);
499         gtk_box_pack_start (GTK_BOX(op->priv->copies_vbox),
500                             op->priv->copies, FALSE, FALSE, 0);
501
502         /* ----- Merge print control ----- */
503         op->priv->merge_frame  = glade_xml_get_widget (gui, "merge_frame");
504         op->priv->prmerge_vbox = glade_xml_get_widget (gui, "prmerge_vbox");
505         op->priv->prmerge = gl_wdgt_print_merge_new (label);
506         gtk_box_pack_start (GTK_BOX(op->priv->prmerge_vbox),
507                             op->priv->prmerge, FALSE, FALSE, 0);
508
509         /* ----- Options ----------------- */
510         op->priv->outline_check    = glade_xml_get_widget (gui, "outline_check");
511         op->priv->reverse_check    = glade_xml_get_widget (gui, "reverse_check");
512         op->priv->crop_marks_check = glade_xml_get_widget (gui, "crop_marks_check");
513
514         g_object_unref (gui);
515
516         /* ---- Activate either simple or merge print control widgets. ---- */
517         merge = gl_label_get_merge (op->priv->label);
518         if (merge == NULL) {
519
520                 gl_wdgt_print_copies_set_range (GL_WDGT_PRINT_COPIES (op->priv->copies),
521                                                 op->priv->n_sheets,
522                                                 op->priv->first,
523                                                 op->priv->last);
524
525                 gtk_widget_show_all (op->priv->simple_frame);
526                 gtk_widget_hide_all (op->priv->merge_frame);
527
528         } else {
529
530                 gint n_records = gl_merge_get_record_count( merge );
531                 gl_wdgt_print_merge_set_copies (GL_WDGT_PRINT_MERGE (op->priv->prmerge),
532                                                 op->priv->n_copies,
533                                                 op->priv->first,
534                                                 n_records,
535                                                 op->priv->collate_flag);
536                 g_object_unref (G_OBJECT(merge));
537
538                 gtk_widget_hide_all (op->priv->simple_frame);
539                 gtk_widget_show_all (op->priv->merge_frame);
540         }
541
542         /* --- Set options --- */
543         gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (op->priv->outline_check),
544                                       op->priv->outline_flag);
545         gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (op->priv->reverse_check),
546                                       op->priv->reverse_flag);
547         gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (op->priv->crop_marks_check),
548                                       op->priv->crop_marks_flag);
549
550         /* --- Do we need to force the outline flag --- */
551         if (op->priv->force_outline_flag)
552         {
553                 gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON(op->priv->outline_check),
554                                               TRUE);
555
556                 gtk_widget_set_sensitive (op->priv->outline_check, FALSE);
557                 gtk_widget_set_sensitive (op->priv->reverse_check, FALSE);
558                 gtk_widget_set_sensitive (op->priv->crop_marks_check, FALSE);
559         }
560
561         return G_OBJECT (vbox);
562 }
563
564 /*--------------------------------------------------------------------------*/
565 /* PRIVATE.  "Custom widget apply" callback                                 */
566 /*--------------------------------------------------------------------------*/
567 static void
568 custom_widget_apply_cb (GtkPrintOperation *operation,
569                         GtkWidget         *widget,
570                         gpointer           user_data)
571 {
572         glPrintOp *op = GL_PRINT_OP (operation);
573         glMerge       *merge = NULL;
574
575
576         op->priv->outline_flag =
577                 gtk_toggle_button_get_active (GTK_TOGGLE_BUTTON
578                                               (op->priv->outline_check));
579         op->priv->reverse_flag =
580                 gtk_toggle_button_get_active (GTK_TOGGLE_BUTTON
581                                               (op->priv->reverse_check));
582         op->priv->crop_marks_flag =
583                 gtk_toggle_button_get_active (GTK_TOGGLE_BUTTON
584                                               (op->priv->crop_marks_check));
585
586         merge = gl_label_get_merge (op->priv->label);
587
588         if (merge == NULL)
589         {
590
591                 op->priv->merge_flag = FALSE;
592                 gl_wdgt_print_copies_get_range (GL_WDGT_PRINT_COPIES (op->priv->copies),
593                                                 &op->priv->n_sheets,
594                                                 &op->priv->first,
595                                                 &op->priv->last);
596         }
597         else
598         {
599
600                 op->priv->merge_flag = TRUE;
601                 gl_wdgt_print_merge_get_copies (GL_WDGT_PRINT_MERGE (op->priv->prmerge),
602                                                 &op->priv->n_copies,
603                                                 &op->priv->first,
604                                                 &op->priv->collate_flag,
605                                                 &op->priv->n_sheets);
606                 g_object_unref (G_OBJECT(merge));
607         }
608
609 }
610
611 /*--------------------------------------------------------------------------*/
612 /* PRIVATE.  "Begin print" callback                                         */
613 /*--------------------------------------------------------------------------*/
614 static void
615 begin_print_cb (GtkPrintOperation *operation,
616                 GtkPrintContext   *context,
617                 gpointer           user_data)
618 {
619         glPrintOp *op = GL_PRINT_OP (operation);
620
621         gtk_print_operation_set_n_pages (operation, op->priv->n_sheets);
622
623 }
624
625 /*--------------------------------------------------------------------------*/
626 /* PRIVATE.  "Draw page" callback.                                          */
627 /*--------------------------------------------------------------------------*/
628 static void
629 draw_page_cb (GtkPrintOperation *operation,
630               GtkPrintContext   *context,
631               int                page_nr,
632               gpointer           user_data)
633 {
634         glPrintOp *op = GL_PRINT_OP (operation);
635         cairo_t       *cr;
636
637         cr = gtk_print_context_get_cairo_context (context);
638
639         if (!op->priv->merge_flag)
640         {
641                 gl_print_simple_sheet (op->priv->label,
642                                        cr,
643                                        page_nr,
644                                        op->priv->n_sheets,
645                                        op->priv->first,
646                                        op->priv->last,
647                                        op->priv->outline_flag,
648                                        op->priv->reverse_flag,
649                                        op->priv->crop_marks_flag);
650         }
651         else
652         {
653                 if (op->priv->collate_flag)
654                 {
655                         gl_print_collated_merge_sheet (op->priv->label,
656                                                        cr,
657                                                        page_nr,
658                                                        op->priv->n_copies,
659                                                        op->priv->first,
660                                                        op->priv->outline_flag,
661                                                        op->priv->reverse_flag,
662                                                        op->priv->crop_marks_flag,
663                                                        &op->priv->state);
664                 }
665                 else
666                 {
667                         gl_print_uncollated_merge_sheet (op->priv->label,
668                                                          cr,
669                                                          page_nr,
670                                                          op->priv->n_copies,
671                                                          op->priv->first,
672                                                          op->priv->outline_flag,
673                                                          op->priv->reverse_flag,
674                                                          op->priv->crop_marks_flag,
675                                                          &op->priv->state);
676                 }
677         }
678 }
679
680
681 /*****************************************************************************/
682 /* Set outline flag/checkbox.                                                */
683 /*****************************************************************************/
684 void
685 gl_print_op_force_outline_flag (glPrintOp *op)
686 {
687         op->priv->force_outline_flag = TRUE;
688 }
689
690