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