]> git.sur5r.net Git - glabels/blob - glabels2/src/print-op.c
2007-04-02 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 "print.h"
36 #include "label.h"
37
38 #include "wdgt-print-copies.h"
39 #include "wdgt-print-merge.h"
40
41 #include "debug.h"
42
43 /*===========================================*/
44 /* Private data types                        */
45 /*===========================================*/
46
47 struct _glPrintOpPrivate {
48
49         glLabel   *label;
50
51         GtkWidget *simple_frame;
52         GtkWidget *copies_vbox;
53         GtkWidget *copies;
54
55         GtkWidget *merge_frame;
56         GtkWidget *prmerge_vbox;
57         GtkWidget *prmerge;
58
59         GtkWidget *outline_check;
60         GtkWidget *reverse_check;
61         GtkWidget *crop_marks_check;
62
63         gboolean   force_outline_flag;
64
65         gchar     *filename;
66
67         gboolean   outline_flag;
68         gboolean   reverse_flag;
69         gboolean   crop_marks_flag;
70         gboolean   merge_flag;
71         gboolean   collate_flag;
72
73         gint       first;
74         gint       last;
75         gint       n_sheets;
76         gint       n_copies;
77
78         glPrintState state;
79 };
80
81 struct _glPrintOpSettings
82 {
83
84         GtkPrintSettings *gtk_settings;
85
86         gboolean          outline_flag;
87         gboolean          reverse_flag;
88         gboolean          crop_marks_flag;
89         gboolean          collate_flag;
90
91         gint              first;
92         gint              last;
93         gint              n_sheets;
94         gint              n_copies;
95         
96 };
97
98
99 /*===========================================*/
100 /* Private globals                           */
101 /*===========================================*/
102
103 /*===========================================*/
104 /* Local function prototypes                 */
105 /*===========================================*/
106
107 static void     gl_print_op_finalize      (GObject            *object);
108
109 static void     gl_print_op_construct       (glPrintOp          *op,
110                                              glLabel            *label);
111
112 static void     gl_print_op_construct_batch (glPrintOp          *op,
113                                              glLabel            *label,
114                                              gchar              *filename,
115                                              gint                n_sheets,
116                                              gint                n_copies,
117                                              gint                first,
118                                              gboolean            outline_flag,
119                                              gboolean            reverse_flag,
120                                              gboolean            crop_marks_flag);
121
122
123 static GObject *create_custom_widget_cb       (GtkPrintOperation *operation,
124                                                gpointer           user_data);
125
126 static void     custom_widget_apply_cb        (GtkPrintOperation *operation,
127                                                GtkWidget         *widget,
128                                                gpointer           user_data);
129
130 static void     begin_print_cb                (GtkPrintOperation *operation,
131                                                GtkPrintContext   *context,
132                                                gpointer           user_data);
133
134 static void     draw_page_cb                  (GtkPrintOperation *operation,
135                                                GtkPrintContext   *context,
136                                                int                page_nr,
137                                                gpointer           user_data);
138
139
140
141 \f
142 /*****************************************************************************/
143 /* Boilerplate object stuff.                                                 */
144 /*****************************************************************************/
145 G_DEFINE_TYPE (glPrintOp, gl_print_op, GTK_TYPE_PRINT_OPERATION);
146
147 static void
148 gl_print_op_class_init (glPrintOpClass *class)
149 {
150         GObjectClass           *object_class = G_OBJECT_CLASS (class);
151
152         gl_debug (DEBUG_PRINT, "");
153         
154         gl_print_op_parent_class = g_type_class_peek_parent (class);
155
156         object_class->finalize = gl_print_op_finalize;
157 }
158
159 static void
160 gl_print_op_init (glPrintOp *op)
161 {
162         gl_debug (DEBUG_PRINT, "");
163
164         gtk_print_operation_set_use_full_page (GTK_PRINT_OPERATION (op), TRUE);
165
166         gtk_print_operation_set_unit (GTK_PRINT_OPERATION (op), GTK_UNIT_POINTS);
167
168         op->priv = g_new0 (glPrintOpPrivate, 1);
169
170 }
171
172 static void 
173 gl_print_op_finalize (GObject *object)
174 {
175         glPrintOp* op = GL_PRINT_OP (object);
176         
177         gl_debug (DEBUG_PRINT, "");
178
179         g_return_if_fail (object != NULL);
180         g_return_if_fail (GL_IS_PRINT_OP (op));
181         g_return_if_fail (op->priv != NULL);
182
183         if (op->priv->label) {
184                 g_object_unref (G_OBJECT(op->priv->label));
185         }
186         g_free (op->priv->filename);
187         g_free (op->priv);
188
189         G_OBJECT_CLASS (gl_print_op_parent_class)->finalize (object);
190
191         g_free (op->priv);
192 }
193
194 /*****************************************************************************/
195 /* NEW print op.                                                         */
196 /*****************************************************************************/
197 glPrintOp *
198 gl_print_op_new (glLabel      *label)
199 {
200         glPrintOp *op;
201
202         gl_debug (DEBUG_PRINT, "");
203
204         op = GL_PRINT_OP (g_object_new (GL_TYPE_PRINT_OP, NULL));
205
206         gl_print_op_construct (GL_PRINT_OP(op), label);
207
208         return op;
209 }
210
211 /*--------------------------------------------------------------------------*/
212 /* PRIVATE.  Construct op.                                              */
213 /*--------------------------------------------------------------------------*/
214 static void
215 gl_print_op_construct (glPrintOp      *op,
216                        glLabel        *label)
217 {
218         const glTemplateLabelType *label_type;
219
220         op->priv->label              = label;
221         op->priv->force_outline_flag = FALSE;
222
223         label_type = gl_template_get_first_label_type (label->template);
224
225         op->priv->n_sheets           = 1;
226         op->priv->first              = 1;
227         op->priv->last               = gl_template_get_n_labels (label_type);
228         op->priv->n_copies           = 1;
229
230         gtk_print_operation_set_custom_tab_label ( GTK_PRINT_OPERATION (op),
231                                                    _("Labels"));
232
233         g_signal_connect (G_OBJECT (op), "create-custom-widget",
234                           G_CALLBACK (create_custom_widget_cb), label);
235
236         g_signal_connect (G_OBJECT (op), "custom-widget-apply",
237                           G_CALLBACK (custom_widget_apply_cb), label);
238
239         g_signal_connect (G_OBJECT (op), "begin-print",
240                           G_CALLBACK (begin_print_cb), label);
241
242         g_signal_connect (G_OBJECT (op), "draw-page",
243                           G_CALLBACK (draw_page_cb), label);
244 }
245
246 /*****************************************************************************/
247 /* NEW batch print operation.                                                */
248 /*****************************************************************************/
249 glPrintOp *
250 gl_print_op_new_batch (glLabel       *label,
251                        gchar         *filename,
252                        gint           n_sheets,
253                        gint           n_copies,
254                        gint           first,
255                        gboolean       outline_flag,
256                        gboolean       reverse_flag,
257                        gboolean       crop_marks_flag)
258 {
259         glPrintOp *op;
260
261         gl_debug (DEBUG_PRINT, "");
262
263         op = GL_PRINT_OP (g_object_new (GL_TYPE_PRINT_OP, NULL));
264
265         gl_print_op_construct_batch (GL_PRINT_OP(op),
266                                          label,
267                                          filename,
268                                          n_sheets,
269                                          n_copies,
270                                          first,
271                                          outline_flag,
272                                          reverse_flag,
273                                          crop_marks_flag);
274
275         return op;
276 }
277
278 /*****************************************************************************/
279 /* Get print operation settings.                                             */
280 /*****************************************************************************/
281 glPrintOpSettings *
282 gl_print_op_get_settings (glPrintOp         *print_op)
283 {
284         glPrintOpSettings *settings;
285
286         settings = g_new0 (glPrintOpSettings, 1);
287
288         if ( settings )
289         {
290                 settings->gtk_settings =
291                         gtk_print_operation_get_print_settings (GTK_PRINT_OPERATION (print_op));
292
293                 settings->outline_flag     = print_op->priv->outline_flag;
294                 settings->reverse_flag     = print_op->priv->reverse_flag;
295                 settings->crop_marks_flag  = print_op->priv->crop_marks_flag;
296                 settings->collate_flag     = print_op->priv->collate_flag;
297
298                 settings->first            = print_op->priv->first;
299                 settings->last             = print_op->priv->last;
300                 settings->n_sheets         = print_op->priv->n_sheets;
301                 settings->n_copies         = print_op->priv->n_copies;
302         }
303
304         return settings;
305 }
306
307 /*****************************************************************************/
308 /* Set print operation settings.                                             */
309 /*****************************************************************************/
310 void
311 gl_print_op_set_settings (glPrintOp         *print_op,
312                           glPrintOpSettings *settings)
313 {
314
315         if ( settings )
316         {
317                 gtk_print_operation_set_print_settings (GTK_PRINT_OPERATION (print_op),
318                                                         settings->gtk_settings);
319
320                 print_op->priv->outline_flag     = settings->outline_flag;
321                 print_op->priv->reverse_flag     = settings->reverse_flag;
322                 print_op->priv->crop_marks_flag  = settings->crop_marks_flag;
323                 print_op->priv->collate_flag     = settings->collate_flag;
324
325                 print_op->priv->first            = settings->first;
326                 print_op->priv->last             = settings->last;
327                 print_op->priv->n_sheets         = settings->n_sheets;
328                 print_op->priv->n_copies         = settings->n_copies;
329         }
330
331  }
332
333 /*****************************************************************************/
334 /* Free print operation settings structure.                                  */
335 /*****************************************************************************/
336 void
337 gl_print_op_free_settings(glPrintOpSettings *settings)
338 {
339         
340         if ( settings )
341         {
342                 if ( settings->gtk_settings )
343                 {
344                         g_object_unref (settings->gtk_settings);
345                 }
346
347                 g_free (settings);
348         }
349 }
350
351 /*--------------------------------------------------------------------------*/
352 /* PRIVATE.  Construct op.                                              */
353 /*--------------------------------------------------------------------------*/
354 static void
355 gl_print_op_construct_batch (glPrintOp      *op,
356                              glLabel        *label,
357                              gchar          *filename,
358                              gint            n_sheets,
359                              gint            n_copies,
360                              gint            first,
361                              gboolean        outline_flag,
362                              gboolean        reverse_flag,
363                              gboolean        crop_marks_flag)
364
365 {
366         glMerge                   *merge = NULL;
367         const glTemplateLabelType *label_type = NULL;
368
369         op->priv->label              = label;
370         op->priv->force_outline_flag = FALSE;
371         op->priv->filename           = g_strdup (filename);
372         op->priv->n_sheets           = n_sheets;
373         op->priv->n_copies           = n_copies;
374         op->priv->first              = first;
375         op->priv->outline_flag       = outline_flag;
376         op->priv->reverse_flag       = reverse_flag;
377         op->priv->crop_marks_flag    = crop_marks_flag;
378
379         merge = gl_label_get_merge (label);
380
381         label_type = gl_template_get_first_label_type (label->template);
382         if (merge == NULL)
383         {
384                 op->priv->merge_flag = FALSE;
385
386                 op->priv->last = gl_template_get_n_labels (label_type);
387
388         }
389         else
390         {
391                 op->priv->merge_flag = TRUE;
392
393                 op->priv->n_sheets =
394                         ceil ((double)(first-1 + n_copies * gl_merge_get_record_count(merge))
395                               / gl_template_get_n_labels (label_type));;
396
397                 g_object_unref (G_OBJECT(merge));
398
399         }
400
401         gtk_print_operation_set_export_filename (GTK_PRINT_OPERATION (op),
402                                                  filename);
403
404         g_signal_connect (G_OBJECT (op), "begin-print",
405                           G_CALLBACK (begin_print_cb), label);
406
407         g_signal_connect (G_OBJECT (op), "draw-page",
408                           G_CALLBACK (draw_page_cb), label);
409 }
410
411 /*--------------------------------------------------------------------------*/
412 /* PRIVATE.  "Create custom widget" callback                                */
413 /*--------------------------------------------------------------------------*/
414 static GObject *
415 create_custom_widget_cb (GtkPrintOperation *operation,
416                          gpointer           user_data)
417 {
418         GladeXML      *gui;
419         glPrintOp     *op = GL_PRINT_OP (operation);
420         glLabel       *label  = GL_LABEL (user_data);
421         GtkWidget     *vbox;
422         glMerge       *merge = NULL;
423
424         gui = glade_xml_new (GLABELS_GLADE_DIR "print-custom-widget.glade",
425                              "print_custom_widget_vbox", NULL);
426
427         if (!gui) {
428                 g_warning ("Could not open print-op.glade, reinstall glabels!");
429                 return NULL;
430         }
431
432         vbox = glade_xml_get_widget (gui, "print_custom_widget_vbox");
433
434         /* ----- Simple print control ----- */
435         op->priv->simple_frame = glade_xml_get_widget (gui, "simple_frame");
436         op->priv->copies_vbox  = glade_xml_get_widget (gui, "copies_vbox");
437         op->priv->copies = gl_wdgt_print_copies_new (label);
438         gtk_box_pack_start (GTK_BOX(op->priv->copies_vbox),
439                             op->priv->copies, FALSE, FALSE, 0);
440
441         /* ----- Merge print control ----- */
442         op->priv->merge_frame  = glade_xml_get_widget (gui, "merge_frame");
443         op->priv->prmerge_vbox = glade_xml_get_widget (gui, "prmerge_vbox");
444         op->priv->prmerge = gl_wdgt_print_merge_new (label);
445         gtk_box_pack_start (GTK_BOX(op->priv->prmerge_vbox),
446                             op->priv->prmerge, FALSE, FALSE, 0);
447
448         /* ----- Options ----------------- */
449         op->priv->outline_check    = glade_xml_get_widget (gui, "outline_check");
450         op->priv->reverse_check    = glade_xml_get_widget (gui, "reverse_check");
451         op->priv->crop_marks_check = glade_xml_get_widget (gui, "crop_marks_check");
452
453         g_object_unref (gui);
454
455         /* ---- Activate either simple or merge print control widgets. ---- */
456         merge = gl_label_get_merge (op->priv->label);
457         if (merge == NULL) {
458
459                 gl_wdgt_print_copies_set_range (GL_WDGT_PRINT_COPIES (op->priv->copies),
460                                                 op->priv->n_sheets,
461                                                 op->priv->first,
462                                                 op->priv->last);
463
464                 gtk_widget_show_all (op->priv->simple_frame);
465                 gtk_widget_hide_all (op->priv->merge_frame);
466
467         } else {
468
469                 gint n_records = gl_merge_get_record_count( merge );
470                 gl_wdgt_print_merge_set_copies (GL_WDGT_PRINT_MERGE (op->priv->prmerge),
471                                                 op->priv->n_copies,
472                                                 op->priv->first,
473                                                 n_records,
474                                                 op->priv->collate_flag);
475                 g_object_unref (G_OBJECT(merge));
476
477                 gtk_widget_hide_all (op->priv->simple_frame);
478                 gtk_widget_show_all (op->priv->merge_frame);
479         }
480
481         /* --- Do we need to force the outline flag --- */
482         if (op->priv->force_outline_flag)
483         {
484                 gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON(op->priv->outline_check),
485                                               TRUE);
486
487                 gtk_widget_set_sensitive (op->priv->outline_check, FALSE);
488                 gtk_widget_set_sensitive (op->priv->reverse_check, FALSE);
489                 gtk_widget_set_sensitive (op->priv->crop_marks_check, FALSE);
490         }
491
492         /* --- Set options --- */
493         gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (op->priv->outline_check),
494                                       op->priv->outline_flag);
495         gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (op->priv->reverse_check),
496                                       op->priv->reverse_flag);
497         gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (op->priv->crop_marks_check),
498                                       op->priv->crop_marks_flag);
499
500         return G_OBJECT (vbox);
501 }
502
503 /*--------------------------------------------------------------------------*/
504 /* PRIVATE.  "Custom widget apply" callback                                 */
505 /*--------------------------------------------------------------------------*/
506 static void
507 custom_widget_apply_cb (GtkPrintOperation *operation,
508                         GtkWidget         *widget,
509                         gpointer           user_data)
510 {
511         glPrintOp *op = GL_PRINT_OP (operation);
512         glMerge       *merge = NULL;
513
514
515         op->priv->outline_flag =
516                 gtk_toggle_button_get_active (GTK_TOGGLE_BUTTON
517                                               (op->priv->outline_check));
518         op->priv->reverse_flag =
519                 gtk_toggle_button_get_active (GTK_TOGGLE_BUTTON
520                                               (op->priv->reverse_check));
521         op->priv->crop_marks_flag =
522                 gtk_toggle_button_get_active (GTK_TOGGLE_BUTTON
523                                               (op->priv->crop_marks_check));
524
525         merge = gl_label_get_merge (op->priv->label);
526
527         if (merge == NULL)
528         {
529
530                 op->priv->merge_flag = FALSE;
531                 gl_wdgt_print_copies_get_range (GL_WDGT_PRINT_COPIES (op->priv->copies),
532                                                 &op->priv->n_sheets,
533                                                 &op->priv->first,
534                                                 &op->priv->last);
535         }
536         else
537         {
538
539                 op->priv->merge_flag = TRUE;
540                 gl_wdgt_print_merge_get_copies (GL_WDGT_PRINT_MERGE (op->priv->prmerge),
541                                                 &op->priv->n_copies,
542                                                 &op->priv->first,
543                                                 &op->priv->collate_flag,
544                                                 &op->priv->n_sheets);
545                 g_object_unref (G_OBJECT(merge));
546         }
547
548 }
549
550 /*--------------------------------------------------------------------------*/
551 /* PRIVATE.  "Begin print" callback                                         */
552 /*--------------------------------------------------------------------------*/
553 static void
554 begin_print_cb (GtkPrintOperation *operation,
555                 GtkPrintContext   *context,
556                 gpointer           user_data)
557 {
558         glPrintOp *op = GL_PRINT_OP (operation);
559
560         gtk_print_operation_set_n_pages (operation, op->priv->n_sheets);
561
562 }
563
564 /*--------------------------------------------------------------------------*/
565 /* PRIVATE.  "Draw page" callback.                                          */
566 /*--------------------------------------------------------------------------*/
567 static void
568 draw_page_cb (GtkPrintOperation *operation,
569               GtkPrintContext   *context,
570               int                page_nr,
571               gpointer           user_data)
572 {
573         glPrintOp *op = GL_PRINT_OP (operation);
574         cairo_t       *cr;
575
576         cr = gtk_print_context_get_cairo_context (context);
577
578         if (!op->priv->merge_flag)
579         {
580                 gl_print_simple_sheet (op->priv->label,
581                                        cr,
582                                        page_nr,
583                                        op->priv->n_sheets,
584                                        op->priv->first,
585                                        op->priv->last,
586                                        op->priv->outline_flag,
587                                        op->priv->reverse_flag,
588                                        op->priv->crop_marks_flag);
589         }
590         else
591         {
592                 if (op->priv->collate_flag)
593                 {
594                         gl_print_collated_merge_sheet (op->priv->label,
595                                                        cr,
596                                                        page_nr,
597                                                        op->priv->n_copies,
598                                                        op->priv->first,
599                                                        op->priv->outline_flag,
600                                                        op->priv->reverse_flag,
601                                                        op->priv->crop_marks_flag,
602                                                        &op->priv->state);
603                 }
604                 else
605                 {
606                         gl_print_uncollated_merge_sheet (op->priv->label,
607                                                          cr,
608                                                          page_nr,
609                                                          op->priv->n_copies,
610                                                          op->priv->first,
611                                                          op->priv->outline_flag,
612                                                          op->priv->reverse_flag,
613                                                          op->priv->crop_marks_flag,
614                                                          &op->priv->state);
615                 }
616         }
617 }
618
619
620 /*****************************************************************************/
621 /* Set outline flag/checkbox.                                                */
622 /*****************************************************************************/
623 void
624 gl_print_op_force_outline_flag (glPrintOp *op)
625 {
626         op->priv->force_outline_flag = TRUE;
627 }
628
629