]> git.sur5r.net Git - glabels/blob - glabels2/src/print-op.c
2008-01-29 Jim Evins <evins@snaught.com>
[glabels] / glabels2 / 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         gchar        *name;
429
430         name = lgl_db_lookup_paper_name_from_id (label->template->paper_id);
431
432         if (lgl_db_is_paper_id_other (label->template->paper_id))
433         {
434                 psize = gtk_paper_size_new_custom (label->template->paper_id,
435                                                    name,
436                                                    label->template->page_width,
437                                                    label->template->page_height,
438                                                    GTK_UNIT_POINTS);
439         }
440         else
441         {
442                 /* Use default size. */
443                 return;
444         }
445         g_free (name);
446
447         su = gtk_page_setup_new ();
448         gtk_page_setup_set_paper_size (su, psize);
449         gtk_print_operation_set_default_page_setup (GTK_PRINT_OPERATION (op), su);
450         g_object_unref (su);
451
452         gtk_paper_size_free (psize);
453 }
454
455 /*--------------------------------------------------------------------------*/
456 /* PRIVATE.  "Create custom widget" callback                                */
457 /*--------------------------------------------------------------------------*/
458 static GObject *
459 create_custom_widget_cb (GtkPrintOperation *operation,
460                          gpointer           user_data)
461 {
462         GladeXML      *gui;
463         glPrintOp     *op = GL_PRINT_OP (operation);
464         glLabel       *label  = GL_LABEL (user_data);
465         GtkWidget     *vbox;
466         glMerge       *merge = NULL;
467
468         gui = glade_xml_new (GLABELS_GLADE_DIR "print-custom-widget.glade",
469                              "print_custom_widget_vbox", NULL);
470
471         if (!gui) {
472                 g_warning ("Could not open print-op.glade, reinstall glabels!");
473                 return NULL;
474         }
475
476         vbox = glade_xml_get_widget (gui, "print_custom_widget_vbox");
477
478         /* ----- Simple print control ----- */
479         op->priv->simple_frame = glade_xml_get_widget (gui, "simple_frame");
480         op->priv->copies_vbox  = glade_xml_get_widget (gui, "copies_vbox");
481         op->priv->copies = gl_wdgt_print_copies_new (label);
482         gtk_box_pack_start (GTK_BOX(op->priv->copies_vbox),
483                             op->priv->copies, FALSE, FALSE, 0);
484
485         /* ----- Merge print control ----- */
486         op->priv->merge_frame  = glade_xml_get_widget (gui, "merge_frame");
487         op->priv->prmerge_vbox = glade_xml_get_widget (gui, "prmerge_vbox");
488         op->priv->prmerge = gl_wdgt_print_merge_new (label);
489         gtk_box_pack_start (GTK_BOX(op->priv->prmerge_vbox),
490                             op->priv->prmerge, FALSE, FALSE, 0);
491
492         /* ----- Options ----------------- */
493         op->priv->outline_check    = glade_xml_get_widget (gui, "outline_check");
494         op->priv->reverse_check    = glade_xml_get_widget (gui, "reverse_check");
495         op->priv->crop_marks_check = glade_xml_get_widget (gui, "crop_marks_check");
496
497         g_object_unref (gui);
498
499         /* ---- Activate either simple or merge print control widgets. ---- */
500         merge = gl_label_get_merge (op->priv->label);
501         if (merge == NULL) {
502
503                 gl_wdgt_print_copies_set_range (GL_WDGT_PRINT_COPIES (op->priv->copies),
504                                                 op->priv->n_sheets,
505                                                 op->priv->first,
506                                                 op->priv->last);
507
508                 gtk_widget_show_all (op->priv->simple_frame);
509                 gtk_widget_hide_all (op->priv->merge_frame);
510
511         } else {
512
513                 gint n_records = gl_merge_get_record_count( merge );
514                 gl_wdgt_print_merge_set_copies (GL_WDGT_PRINT_MERGE (op->priv->prmerge),
515                                                 op->priv->n_copies,
516                                                 op->priv->first,
517                                                 n_records,
518                                                 op->priv->collate_flag);
519                 g_object_unref (G_OBJECT(merge));
520
521                 gtk_widget_hide_all (op->priv->simple_frame);
522                 gtk_widget_show_all (op->priv->merge_frame);
523         }
524
525         /* --- Set options --- */
526         gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (op->priv->outline_check),
527                                       op->priv->outline_flag);
528         gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (op->priv->reverse_check),
529                                       op->priv->reverse_flag);
530         gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (op->priv->crop_marks_check),
531                                       op->priv->crop_marks_flag);
532
533         /* --- Do we need to force the outline flag --- */
534         if (op->priv->force_outline_flag)
535         {
536                 gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON(op->priv->outline_check),
537                                               TRUE);
538
539                 gtk_widget_set_sensitive (op->priv->outline_check, FALSE);
540                 gtk_widget_set_sensitive (op->priv->reverse_check, FALSE);
541                 gtk_widget_set_sensitive (op->priv->crop_marks_check, FALSE);
542         }
543
544         return G_OBJECT (vbox);
545 }
546
547 /*--------------------------------------------------------------------------*/
548 /* PRIVATE.  "Custom widget apply" callback                                 */
549 /*--------------------------------------------------------------------------*/
550 static void
551 custom_widget_apply_cb (GtkPrintOperation *operation,
552                         GtkWidget         *widget,
553                         gpointer           user_data)
554 {
555         glPrintOp *op = GL_PRINT_OP (operation);
556         glMerge       *merge = NULL;
557
558
559         op->priv->outline_flag =
560                 gtk_toggle_button_get_active (GTK_TOGGLE_BUTTON
561                                               (op->priv->outline_check));
562         op->priv->reverse_flag =
563                 gtk_toggle_button_get_active (GTK_TOGGLE_BUTTON
564                                               (op->priv->reverse_check));
565         op->priv->crop_marks_flag =
566                 gtk_toggle_button_get_active (GTK_TOGGLE_BUTTON
567                                               (op->priv->crop_marks_check));
568
569         merge = gl_label_get_merge (op->priv->label);
570
571         if (merge == NULL)
572         {
573
574                 op->priv->merge_flag = FALSE;
575                 gl_wdgt_print_copies_get_range (GL_WDGT_PRINT_COPIES (op->priv->copies),
576                                                 &op->priv->n_sheets,
577                                                 &op->priv->first,
578                                                 &op->priv->last);
579         }
580         else
581         {
582
583                 op->priv->merge_flag = TRUE;
584                 gl_wdgt_print_merge_get_copies (GL_WDGT_PRINT_MERGE (op->priv->prmerge),
585                                                 &op->priv->n_copies,
586                                                 &op->priv->first,
587                                                 &op->priv->collate_flag,
588                                                 &op->priv->n_sheets);
589                 g_object_unref (G_OBJECT(merge));
590         }
591
592 }
593
594 /*--------------------------------------------------------------------------*/
595 /* PRIVATE.  "Begin print" callback                                         */
596 /*--------------------------------------------------------------------------*/
597 static void
598 begin_print_cb (GtkPrintOperation *operation,
599                 GtkPrintContext   *context,
600                 gpointer           user_data)
601 {
602         glPrintOp *op = GL_PRINT_OP (operation);
603
604         gtk_print_operation_set_n_pages (operation, op->priv->n_sheets);
605
606 }
607
608 /*--------------------------------------------------------------------------*/
609 /* PRIVATE.  "Draw page" callback.                                          */
610 /*--------------------------------------------------------------------------*/
611 static void
612 draw_page_cb (GtkPrintOperation *operation,
613               GtkPrintContext   *context,
614               int                page_nr,
615               gpointer           user_data)
616 {
617         glPrintOp *op = GL_PRINT_OP (operation);
618         cairo_t       *cr;
619
620         cr = gtk_print_context_get_cairo_context (context);
621
622         if (!op->priv->merge_flag)
623         {
624                 gl_print_simple_sheet (op->priv->label,
625                                        cr,
626                                        page_nr,
627                                        op->priv->n_sheets,
628                                        op->priv->first,
629                                        op->priv->last,
630                                        op->priv->outline_flag,
631                                        op->priv->reverse_flag,
632                                        op->priv->crop_marks_flag);
633         }
634         else
635         {
636                 if (op->priv->collate_flag)
637                 {
638                         gl_print_collated_merge_sheet (op->priv->label,
639                                                        cr,
640                                                        page_nr,
641                                                        op->priv->n_copies,
642                                                        op->priv->first,
643                                                        op->priv->outline_flag,
644                                                        op->priv->reverse_flag,
645                                                        op->priv->crop_marks_flag,
646                                                        &op->priv->state);
647                 }
648                 else
649                 {
650                         gl_print_uncollated_merge_sheet (op->priv->label,
651                                                          cr,
652                                                          page_nr,
653                                                          op->priv->n_copies,
654                                                          op->priv->first,
655                                                          op->priv->outline_flag,
656                                                          op->priv->reverse_flag,
657                                                          op->priv->crop_marks_flag,
658                                                          &op->priv->state);
659                 }
660         }
661 }
662
663
664 /*****************************************************************************/
665 /* Set outline flag/checkbox.                                                */
666 /*****************************************************************************/
667 void
668 gl_print_op_force_outline_flag (glPrintOp *op)
669 {
670         op->priv->force_outline_flag = TRUE;
671 }
672
673