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