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