]> git.sur5r.net Git - glabels/blob - glabels2/src/print-dialog.c
2004-01-06 Jim Evins <evins@snaught.com>
[glabels] / glabels2 / src / print-dialog.c
1 /*
2  *  (GLABELS) Label and Business Card Creation program for GNOME
3  *
4  *  print-dialog.c:  Print dialog module
5  *
6  *  Copyright (C) 2001-2003  Jim Evins <evins@snaught.com>.
7  *
8  *  This program is free software; you can redistribute it and/or modify
9  *  it under the terms of the GNU General Public License as published by
10  *  the Free Software Foundation; either version 2 of the License, or
11  *  (at your option) any later version.
12  *
13  *  This program is distributed in the hope that it will be useful,
14  *  but WITHOUT ANY WARRANTY; without even the implied warranty of
15  *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
16  *  GNU General Public License for more details.
17  *
18  *  You should have received a copy of the GNU General Public License
19  *  along with this program; if not, write to the Free Software
20  *  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307 USA
21  */
22 #include <config.h>
23
24 #include <math.h>
25 #include <time.h>
26 #include <ctype.h>
27 #include <gtk/gtk.h>
28 #include <libgnomeprintui/gnome-print-dialog.h>
29 #include <libgnomeprint/gnome-print-job.h>
30 #include <libgnomeprintui/gnome-print-job-preview.h>
31
32 #include "print-dialog.h"
33 #include "print.h"
34 #include "label.h"
35
36 #include "wdgt-print-copies.h"
37 #include "wdgt-print-merge.h"
38
39 #include "debug.h"
40
41 /***************************************************************************/
42 /* FIXME: GnomePrinterSelector is not public in libgnomeprintui-2.2.       */
43 /*                                                                         */
44 /* I know that I'm asking for trouble, but here are standin prototypes:    */
45 GtkWidget          *gnome_printer_selector_new (GnomePrintConfig *config);
46 GnomePrintConfig   *gnome_printer_selector_get_config (GtkWidget *psel);
47 #define GNOME_PRINTER_SELECTOR(x) (x)
48 /***************************************************************************/
49
50 /*===========================================*/
51 /* Private data types                        */
52 /*===========================================*/
53
54 struct _glPrintDialogPrivate {
55
56         glLabel   *label;
57
58         GtkWidget *simple_frame;
59         GtkWidget *copies;
60
61         GtkWidget *merge_frame;
62         GtkWidget *prmerge;
63
64         GtkWidget *outline_check;
65         GtkWidget *reverse_check;
66         GtkWidget *crop_marks_check;
67
68         GtkWidget *printer_select;
69 };
70
71
72 /*===========================================*/
73 /* Private globals                           */
74 /*===========================================*/
75
76 static glHigDialogClass* parent_class = NULL;
77
78 /*===========================================*/
79 /* Local function prototypes                 */
80 /*===========================================*/
81
82 static void       gl_print_dialog_class_init      (glPrintDialogClass *klass);
83 static void       gl_print_dialog_init            (glPrintDialog      *dlg);
84 static void       gl_print_dialog_finalize        (GObject            *object);
85
86 static void       gl_print_dialog_construct       (glPrintDialog      *dialog,
87                                                    glLabel            *label,
88                                                    BonoboWindow       *win);
89
90 static GtkWidget *job_page_new                    (glPrintDialog      *dialog,
91                                                    glLabel            *label);
92
93 static GtkWidget *printer_page_new                (glPrintDialog      *dialog,
94                                                    glLabel            *label);
95
96 static void       merge_changed_cb                (glLabel            *label,
97                                                    glPrintDialog      *dialog);
98
99 static void       size_changed_cb                 (glLabel            *label,
100                                                    glPrintDialog      *dialog);
101
102 static void       delete_event_cb                 (glPrintDialog      *dialog,
103                                                    gpointer            user_data);
104
105 static void       print_response_cb               (glPrintDialog      *dialog,
106                                                    gint                response,
107                                                    glLabel            *label);
108
109 static void       print_sheets                    (GnomePrintConfig   *config,
110                                                    glLabel            *label,
111                                                    gboolean            preview_flag,
112                                                    gint                n_sheets,
113                                                    gint                first,
114                                                    gint                last,
115                                                    gboolean            outline_flag,
116                                                    gboolean            reverse_flag,
117                                                    gboolean            crop_marks_flag);
118
119 static void      print_sheets_merge               (GnomePrintConfig   *config,
120                                                    glLabel            *label,
121                                                    gboolean            preview_flag,
122                                                    gint                n_copies,
123                                                    gint                first,
124                                                    gboolean            collate_flag,
125                                                    gboolean            outline_flag,
126                                                    gboolean            reverse_flag,
127                                                    gboolean            crop_marks_flag);
128
129
130
131 \f
132 /*****************************************************************************/
133 /* Boilerplate object stuff.                                                 */
134 /*****************************************************************************/
135 GType
136 gl_print_dialog_get_type (void)
137 {
138         static GType dialog_type = 0;
139
140         if (!dialog_type)
141         {
142                 static const GTypeInfo dialog_info =
143                 {
144                         sizeof (glPrintDialogClass),
145                         NULL,           /* base_init */
146                         NULL,           /* base_finalize */
147                         (GClassInitFunc) gl_print_dialog_class_init,
148                         NULL,           /* class_finalize */
149                         NULL,           /* class_data */
150                         sizeof (glPrintDialog),
151                         0,              /* n_preallocs */
152                         (GInstanceInitFunc) gl_print_dialog_init
153                 };
154
155                 dialog_type = g_type_register_static (GL_TYPE_HIG_DIALOG,
156                                                       "glPrintDialog",
157                                                       &dialog_info, 
158                                                       0);
159         }
160
161         return dialog_type;
162 }
163
164 static void
165 gl_print_dialog_class_init (glPrintDialogClass *klass)
166 {
167         GObjectClass *object_class = G_OBJECT_CLASS (klass);
168
169         gl_debug (DEBUG_PRINT, "");
170         
171         parent_class = g_type_class_peek_parent (klass);
172
173         object_class->finalize = gl_print_dialog_finalize;      
174 }
175
176 static void
177 gl_print_dialog_init (glPrintDialog *dialog)
178 {
179         GtkWidget *pp_button;
180
181         gl_debug (DEBUG_PRINT, "");
182
183         dialog->priv = g_new0 (glPrintDialogPrivate, 1);
184
185         gtk_dialog_add_buttons (GTK_DIALOG(dialog),
186                                 GTK_STOCK_CANCEL, GTK_RESPONSE_CANCEL,
187                                 GTK_STOCK_PRINT,  GNOME_PRINT_DIALOG_RESPONSE_PRINT,
188                                 NULL);
189
190         pp_button =
191                 gtk_dialog_add_button (GTK_DIALOG (dialog),
192                                        GTK_STOCK_PRINT_PREVIEW, GNOME_PRINT_DIALOG_RESPONSE_PREVIEW);
193         gtk_button_box_set_child_secondary (GTK_BUTTON_BOX (GTK_DIALOG (dialog)->action_area), 
194                                             pp_button, TRUE);
195         gtk_dialog_set_default_response (GTK_DIALOG (dialog),
196                                          GNOME_PRINT_DIALOG_RESPONSE_PRINT);
197
198         gtk_window_set_resizable (GTK_WINDOW (dialog), FALSE);
199
200         g_signal_connect (G_OBJECT(dialog),
201                           "delete_event",
202                           G_CALLBACK (delete_event_cb),
203                           NULL);
204                                                                                 
205 }
206
207 static void 
208 gl_print_dialog_finalize (GObject *object)
209 {
210         glPrintDialog* dialog;
211         
212         gl_debug (DEBUG_PRINT, "");
213
214         g_return_if_fail (object != NULL);
215         
216         dialog = GL_PRINT_DIALOG (object);
217
218         g_return_if_fail (GL_IS_PRINT_DIALOG (dialog));
219         g_return_if_fail (dialog->priv != NULL);
220
221         if (dialog->priv->label) {
222                 g_object_unref (G_OBJECT(dialog->priv->label));
223         }
224         g_free (dialog->priv);
225
226         G_OBJECT_CLASS (parent_class)->finalize (object);
227
228         g_free (dialog->priv);
229 }
230
231 /*****************************************************************************/
232 /* NEW object properties dialog.                                              */
233 /*****************************************************************************/
234 GtkWidget *
235 gl_print_dialog_new (glLabel      *label,
236                      BonoboWindow *win)
237 {
238         GtkWidget *dialog;
239
240         gl_debug (DEBUG_PRINT, "");
241
242         dialog = GTK_WIDGET (g_object_new (GL_TYPE_PRINT_DIALOG, NULL));
243
244         gl_print_dialog_construct (GL_PRINT_DIALOG(dialog), label, win);
245
246         return dialog;
247 }
248
249 /*--------------------------------------------------------------------------*/
250 /* PRIVATE.  Construct dialog.                                              */
251 /*--------------------------------------------------------------------------*/
252 static void
253 gl_print_dialog_construct (glPrintDialog      *dialog,
254                            glLabel            *label,
255                            BonoboWindow       *win)
256 {
257         GtkWidget *notebook, *page;
258         gchar     *name, *title;
259
260         gl_debug (DEBUG_PRINT, "START");
261
262         g_return_if_fail (label && GL_IS_LABEL(label));
263
264         dialog->priv->label = GL_LABEL(g_object_ref (G_OBJECT(label)));
265
266         name = gl_label_get_short_name (label);
267         title = g_strdup_printf ("%s \"%s\"", _("Print"), name);
268         g_free (name);
269
270         gtk_window_set_title (GTK_WINDOW(dialog), title);
271         if (win) {
272                 gtk_window_set_transient_for (GTK_WINDOW(dialog), GTK_WINDOW(win));
273                 gtk_window_set_destroy_with_parent (GTK_WINDOW(dialog), TRUE);
274         }
275
276         notebook = gtk_notebook_new ();
277         gl_hig_dialog_add_widget (GL_HIG_DIALOG(dialog), notebook);
278
279         /* ----- Create Job notebook page ----- */
280         page = job_page_new (dialog, label);
281         gtk_notebook_append_page (GTK_NOTEBOOK(notebook), page,
282                                   gtk_label_new_with_mnemonic (_("_Job")));
283
284         /* ----- Create Printer notebook page ----- */
285         page = printer_page_new (dialog, label);
286         gtk_notebook_append_page (GTK_NOTEBOOK(notebook), page,
287                                   gtk_label_new_with_mnemonic (_("P_rinter")));
288
289         g_signal_connect (G_OBJECT(dialog), "response",
290                           G_CALLBACK (print_response_cb), label);
291
292         gtk_widget_show_all (GTK_WIDGET (dialog));
293
294         merge_changed_cb (GL_LABEL(label), dialog);
295
296         g_free (title);
297
298
299         gl_debug (DEBUG_PRINT, "END");
300 }
301
302 /*---------------------------------------------------------------------------*/
303 /* PRIVATE.  Create "Job" page.                                              */
304 /*---------------------------------------------------------------------------*/
305 static GtkWidget *
306 job_page_new (glPrintDialog *dialog,
307               glLabel       *label)
308 {
309         GtkWidget *vbox;
310         GtkWidget *wframe;
311
312         vbox = gl_hig_vbox_new (GL_HIG_VBOX_OUTER);
313
314         /* ----------- Add simple-copies widget ------------ */
315         dialog->priv->simple_frame = gl_hig_category_new (_("Copies"));
316         gl_hig_vbox_add_widget (GL_HIG_VBOX(vbox), dialog->priv->simple_frame);
317
318         dialog->priv->copies = gl_wdgt_print_copies_new (label);
319         gl_hig_category_add_widget (GL_HIG_CATEGORY(dialog->priv->simple_frame),
320                                     dialog->priv->copies);
321
322         /* ------- Add merge control widget ------------ */
323         dialog->priv->merge_frame = gl_hig_category_new (_("Document merge control"));
324         gl_hig_vbox_add_widget (GL_HIG_VBOX(vbox), dialog->priv->merge_frame);
325
326         dialog->priv->prmerge = gl_wdgt_print_merge_new (label);
327         gl_hig_category_add_widget (GL_HIG_CATEGORY(dialog->priv->merge_frame),
328                                     dialog->priv->prmerge);
329
330         /* ----------- Add custom print options area ------------ */
331         wframe = gl_hig_category_new (_("Options"));
332         gl_hig_vbox_add_widget (GL_HIG_VBOX(vbox), wframe);
333
334         /* add Outline check button */
335         dialog->priv->outline_check =
336             gtk_check_button_new_with_label (
337                     _("print outlines (to test printer alignment)"));
338         gl_hig_category_add_widget (GL_HIG_CATEGORY(wframe), dialog->priv->outline_check);
339         gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (dialog->priv->outline_check),
340                                       FALSE);
341
342         /* add Reverse check button */
343         dialog->priv->reverse_check =
344             gtk_check_button_new_with_label (
345                     _("print in reverse (i.e. a mirror image)"));
346         gl_hig_category_add_widget (GL_HIG_CATEGORY(wframe), dialog->priv->reverse_check);
347         gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (dialog->priv->reverse_check),
348                                       FALSE);
349
350         /* add Crop marks check button */
351         dialog->priv->crop_marks_check =
352             gtk_check_button_new_with_label (_("print crop marks"));
353         gl_hig_category_add_widget (GL_HIG_CATEGORY(wframe), dialog->priv->crop_marks_check);
354         gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (dialog->priv->crop_marks_check),
355                                       FALSE);
356
357         g_signal_connect (G_OBJECT(label), "merge_changed",
358                           G_CALLBACK (merge_changed_cb), dialog);
359
360         g_signal_connect (G_OBJECT(label), "size_changed",
361                           G_CALLBACK (size_changed_cb), dialog);
362
363         return vbox;
364 }
365
366 /*---------------------------------------------------------------------------*/
367 /* PRIVATE.  Create "Printer" page.                                          */
368 /*---------------------------------------------------------------------------*/
369 static GtkWidget *
370 printer_page_new (glPrintDialog *dialog,
371                   glLabel       *label)
372 {
373         GtkWidget *vbox;
374         GtkWidget *printer_select;
375
376         vbox = gl_hig_vbox_new (GL_HIG_VBOX_OUTER);
377
378         /* FIXME: GnomePrinterSelector is not public in libgnomeprintui-2.2 */
379         dialog->priv->printer_select =
380                 gnome_printer_selector_new (gnome_print_config_default ());
381         gtk_widget_show (dialog->priv->printer_select);
382         gl_hig_vbox_add_widget (GL_HIG_VBOX(vbox), dialog->priv->printer_select);
383
384         return vbox;
385 }
386
387 /*--------------------------------------------------------------------------*/
388 /* PRIVATE.  "merge_changed" callback.                                      */
389 /*--------------------------------------------------------------------------*/
390 static void
391 merge_changed_cb (glLabel            *label,
392                   glPrintDialog      *dialog)
393 {
394         glMerge   *merge;
395         gint       n_records;
396
397         gl_debug (DEBUG_PRINT, "START");
398
399         merge = gl_label_get_merge (label);
400         if (merge == NULL) {
401
402                 gtk_widget_show_all (dialog->priv->simple_frame);
403                 gtk_widget_hide_all (dialog->priv->merge_frame);
404
405         } else {
406
407                 n_records = gl_merge_get_record_count( merge );
408                 gl_wdgt_print_merge_set_copies (GL_WDGT_PRINT_MERGE(dialog->priv->prmerge),
409                                                 1, 1, n_records, FALSE);
410                 g_object_unref (G_OBJECT(merge));
411
412                 gtk_widget_hide_all (dialog->priv->simple_frame);
413                 gtk_widget_show_all (dialog->priv->merge_frame);
414         }
415
416         gl_debug (DEBUG_PRINT, "END");
417 }
418
419 /*--------------------------------------------------------------------------*/
420 /* PRIVATE.  "size_changed" (template changed) callback.                    */
421 /*--------------------------------------------------------------------------*/
422 static void
423 size_changed_cb (glLabel            *label,
424                  glPrintDialog      *dialog)
425 {
426         gl_debug (DEBUG_PRINT, "START");
427
428         /* Remove and unref original widgets. */
429         gtk_container_remove (GTK_CONTAINER(GL_HIG_CATEGORY(dialog->priv->simple_frame)->vbox),
430                               dialog->priv->copies);
431         gtk_container_remove (GTK_CONTAINER(GL_HIG_CATEGORY(dialog->priv->merge_frame)->vbox),
432                               dialog->priv->prmerge);
433
434         /* Create new widgets based on updated label and install */
435         dialog->priv->copies = gl_wdgt_print_copies_new (label);
436         gl_hig_category_add_widget (GL_HIG_CATEGORY(dialog->priv->simple_frame),
437                                     dialog->priv->copies);
438         dialog->priv->prmerge = gl_wdgt_print_merge_new (label);
439         gl_hig_category_add_widget (GL_HIG_CATEGORY(dialog->priv->merge_frame),
440                                     dialog->priv->prmerge);
441
442         /* Update these widgets. */
443         merge_changed_cb (label, dialog);
444
445         gl_debug (DEBUG_PRINT, "END");
446 }
447
448 /*--------------------------------------------------------------------------*/
449 /* PRIVATE.  delete event callback.                                         */
450 /*--------------------------------------------------------------------------*/
451 static void
452 delete_event_cb (glPrintDialog *dialog,
453                   gpointer       user_data)
454 {
455         gl_debug (DEBUG_PRINT, "START");
456
457         gtk_widget_hide (GTK_WIDGET(dialog));
458
459         gl_debug (DEBUG_PRINT, "END");
460 }
461
462 /*---------------------------------------------------------------------------*/
463 /* PRIVATE.  Print "response" callback.                                      */
464 /*---------------------------------------------------------------------------*/
465 static void
466 print_response_cb (glPrintDialog *dialog,
467                    gint           response,
468                    glLabel       *label)
469 {
470         GnomePrintConfig *config;
471         glMerge          *merge;
472         gboolean          outline_flag, reverse_flag, crop_marks_flag, collate_flag;
473         gint              first, last, n_sheets, n_copies;
474
475         switch (response) {
476
477         case GNOME_PRINT_DIALOG_RESPONSE_PRINT:
478         case GNOME_PRINT_DIALOG_RESPONSE_PREVIEW:
479
480                 /* FIXME: GnomePrinterSelector is not public in libgnomeprintui-2.2. */
481                 config = gnome_printer_selector_get_config (GNOME_PRINTER_SELECTOR(dialog->priv->printer_select));
482
483                 outline_flag =
484                         gtk_toggle_button_get_active (GTK_TOGGLE_BUTTON
485                                                       (dialog->priv->outline_check));
486                 reverse_flag =
487                         gtk_toggle_button_get_active (GTK_TOGGLE_BUTTON
488                                                       (dialog->priv->reverse_check));
489                 crop_marks_flag =
490                         gtk_toggle_button_get_active (GTK_TOGGLE_BUTTON
491                                                       (dialog->priv->crop_marks_check));
492
493                 merge = gl_label_get_merge (label);
494
495                 if (merge == NULL) {
496
497                         gl_wdgt_print_copies_get_range (GL_WDGT_PRINT_COPIES (dialog->priv->copies),
498                                                         &n_sheets, &first, &last);
499                         print_sheets (config, label,
500                                       (response == GNOME_PRINT_DIALOG_RESPONSE_PREVIEW),
501                                       n_sheets, first, last,
502                                       outline_flag, reverse_flag, crop_marks_flag);
503
504                 } else {
505
506                         gl_wdgt_print_merge_get_copies (GL_WDGT_PRINT_MERGE (dialog->priv->prmerge),
507                                                         &n_copies, &first,
508                                                         &collate_flag);
509                         print_sheets_merge (config, label,
510                                             (response == GNOME_PRINT_DIALOG_RESPONSE_PREVIEW),
511                                             n_copies, first,
512                                             collate_flag,
513                                             outline_flag,
514                                             reverse_flag,
515                                             crop_marks_flag);
516                         g_object_unref (G_OBJECT(merge));
517                 }
518                 break;
519
520         default:
521                 break;
522
523         }
524
525         gtk_widget_hide (GTK_WIDGET(dialog));
526 }
527
528 /*---------------------------------------------------------------------------*/
529 /* PRIVATE.  print the sheets                                                */
530 /*---------------------------------------------------------------------------*/
531 static void
532 print_sheets (GnomePrintConfig *config,
533               glLabel          *label,
534               gboolean          preview_flag,
535               gint              n_sheets,
536               gint              first,
537               gint              last,
538               gboolean          outline_flag,
539               gboolean          reverse_flag,
540               gboolean          crop_marks_flag)
541 {
542         GnomePrintJob *job;
543         glPrintFlags   flags;
544
545         job = gnome_print_job_new (config);
546         flags.outline = outline_flag;
547         flags.reverse = reverse_flag;
548         flags.crop_marks = crop_marks_flag;
549         gl_print_simple (job, label, n_sheets, first, last, &flags);
550         gnome_print_job_close (job);
551
552         if (preview_flag) {
553                 GtkWidget *preview_widget =
554                     gnome_print_job_preview_new (job, _("Print preview"));
555                 gtk_widget_show (GTK_WIDGET (preview_widget));
556         } else {
557                 gnome_print_job_print (job);
558         }
559
560         g_object_unref (G_OBJECT (job));
561 }
562
563 /*---------------------------------------------------------------------------*/
564 /* PRIVATE.  print the sheets with merge data                                */
565 /*---------------------------------------------------------------------------*/
566 static void
567 print_sheets_merge (GnomePrintConfig *config,
568                     glLabel          *label,
569                     gboolean          preview_flag,
570                     gint              n_copies,
571                     gint              first,
572                     gboolean          collate_flag,
573                     gboolean          outline_flag,
574                     gboolean          reverse_flag,
575                     gboolean          crop_marks_flag)
576 {
577         GnomePrintJob *job;
578         glPrintFlags   flags;
579
580         job = gnome_print_job_new (config);
581         flags.outline = outline_flag;
582         flags.reverse = reverse_flag;
583         flags.crop_marks = crop_marks_flag;
584         if ( collate_flag ) {
585                 gl_print_merge_collated (job, label, n_copies, first, &flags);
586         } else {
587                 gl_print_merge_uncollated (job, label, n_copies, first, &flags);
588         }
589         gnome_print_job_close (job);
590
591         if (preview_flag) {
592                 GtkWidget *preview_widget =
593                     gnome_print_job_preview_new (job, _("Print preview"));
594                 gtk_widget_show (GTK_WIDGET (preview_widget));
595         } else {
596                 gnome_print_job_print (job);
597         }
598
599         g_object_unref (G_OBJECT (job));
600 }
601
602 /*****************************************************************************/
603 /* Set outline flag/checkbox.                                                */
604 /*****************************************************************************/
605 void
606 gl_print_dialog_force_outline_flag (glPrintDialog *dialog)
607 {
608         gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON(dialog->priv->outline_check),
609                                       TRUE);
610
611         gtk_widget_set_sensitive (dialog->priv->outline_check, FALSE);
612         gtk_widget_set_sensitive (dialog->priv->reverse_check, FALSE);
613         gtk_widget_set_sensitive (dialog->priv->crop_marks_check, FALSE);
614 }
615
616