]> git.sur5r.net Git - glabels/blob - src/new-label-dialog.c
Imported Upstream version 3.2.0
[glabels] / src / new-label-dialog.c
1 /*
2  *  new-label-dialog.c
3  *  Copyright (C) 2006-2009  Jim Evins <evins@snaught.com>.
4  *
5  *  This file is part of gLabels.
6  *
7  *  gLabels is free software: you can redistribute it and/or modify
8  *  it under the terms of the GNU General Public License as published by
9  *  the Free Software Foundation, either version 3 of the License, or
10  *  (at your option) any later version.
11  *
12  *  gLabels is distributed in the hope that it will be useful,
13  *  but WITHOUT ANY WARRANTY; without even the implied warranty of
14  *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
15  *  GNU General Public License for more details.
16  *
17  *  You should have received a copy of the GNU General Public License
18  *  along with gLabels.  If not, see <http://www.gnu.org/licenses/>.
19  */
20
21 #include <config.h>
22
23 #include "new-label-dialog.h"
24
25 #include <glib/gi18n.h>
26 #include <gtk/gtk.h>
27
28 #include "marshal.h"
29 #include "builder-util.h"
30 #include "prefs.h"
31 #include "media-select.h"
32 #include "mini-label-preview.h"
33 #include "mini-preview.h"
34
35 #include "debug.h"
36
37
38 #define LABEL_PREVIEW_WIDTH  96
39 #define LABEL_PREVIEW_HEIGHT 96
40
41 #define MINI_PREVIEW_MIN_WIDTH  300
42 #define MINI_PREVIEW_MIN_HEIGHT 360
43
44
45 /*===========================================*/
46 /* Private data types                        */
47 /*===========================================*/
48
49 struct _glNewLabelDialogPrivate {
50
51         GtkBuilder *builder;
52
53         GtkWidget  *template_page_vbox;
54         GtkWidget  *combo_hbox;
55         GtkWidget  *combo;
56
57         GtkWidget  *rotate_page_vbox;
58         GtkWidget  *normal_radio;
59         GtkWidget  *rotated_radio;
60         GtkWidget  *normal_preview_hbox;
61         GtkWidget  *rotated_preview_hbox;
62         GtkWidget  *normal_preview;
63         GtkWidget  *rotated_preview;
64
65         GtkWidget  *confirm_page_vbox;
66         GtkWidget  *preview_vbox;
67         GtkWidget  *preview;
68         GtkWidget  *desc_label;
69         GtkWidget  *page_size_label;
70         GtkWidget  *label_size_label;
71         GtkWidget  *layout_label;
72         GtkWidget  *vendor_label;
73         GtkWidget  *part_label;
74         GtkWidget  *similar_label;
75 };
76
77 /* Page numbers for traversing GtkAssistant */
78 enum {
79         TEMPLATE_PAGE_NUM = 0,
80         ROTATE_PAGE_NUM,
81         CONFIRM_PAGE_NUM
82 };
83
84 enum {
85         COMPLETE,
86         LAST_SIGNAL
87 };
88
89
90 /*===========================================*/
91 /* Private globals                           */
92 /*===========================================*/
93
94 static gint signals[LAST_SIGNAL] = { 0 };
95
96
97 /*===========================================*/
98 /* Local function prototypes                 */
99 /*===========================================*/
100
101 static void       gl_new_label_dialog_finalize        (GObject           *object);
102
103 static void       cancel_cb                           (glNewLabelDialog  *this);
104 static void       apply_cb                            (glNewLabelDialog  *this);
105 static void       close_cb                            (glNewLabelDialog  *this);
106
107 static gint       forward_page_function               (gint               current_page,
108                                                        glNewLabelDialog  *this);
109
110 static void       combo_changed_cb                    (glNewLabelDialog  *this);
111 static void       rotate_toggled_cb                   (glNewLabelDialog  *this);
112
113 static void       set_info                            (glNewLabelDialog  *this,
114                                                        const gchar       *name);
115
116
117 /*****************************************************************************/
118 /* Boilerplate object stuff.                                                 */
119 /*****************************************************************************/
120 G_DEFINE_TYPE (glNewLabelDialog, gl_new_label_dialog, GTK_TYPE_ASSISTANT)
121
122
123 /*****************************************************************************/
124 /* Class Init Function.                                                      */
125 /*****************************************************************************/
126 static void
127 gl_new_label_dialog_class_init (glNewLabelDialogClass *class)
128 {
129         GObjectClass *object_class = G_OBJECT_CLASS (class);
130
131         gl_debug (DEBUG_FILE, "");
132
133         gl_new_label_dialog_parent_class = g_type_class_peek_parent (class);
134
135         object_class->finalize = gl_new_label_dialog_finalize;
136
137         signals[COMPLETE] =
138             g_signal_new ("complete",
139                           G_OBJECT_CLASS_TYPE(object_class),
140                           G_SIGNAL_RUN_LAST,
141                           G_STRUCT_OFFSET (glNewLabelDialogClass, complete),
142                           NULL, NULL,
143                           gl_marshal_VOID__VOID,
144                           G_TYPE_NONE, 0);
145
146 }
147
148
149 /*****************************************************************************/
150 /* Object Instance Init Function.                                            */
151 /*****************************************************************************/
152 static void
153 gl_new_label_dialog_init (glNewLabelDialog *this)
154 {
155         GdkRGBA       banner_color = { 0, 0.5, 1.0, 1.0 };
156         GtkWidget    *page_1_banner_eventbox, *page_2_banner_eventbox, *page_3_banner_eventbox;
157         GtkWidget    *page_1_image, *page_2_image, *page_3_image;
158         gchar        *logo_filename;
159         GdkPixbuf    *logo;
160         GtkBuilder   *builder;
161         gchar        *builder_filename;
162         static gchar *object_ids[] = { "template_page_vbox",
163                                        "rotate_page_vbox",
164                                        "confirm_page_vbox",
165                                        NULL };
166         GError       *error = NULL;
167
168         gl_debug (DEBUG_FILE, "START");
169
170         g_return_if_fail (GL_IS_NEW_LABEL_DIALOG (this));
171
172         this->priv = g_new0 (glNewLabelDialogPrivate, 1);
173
174         builder = gtk_builder_new ();
175         builder_filename = g_build_filename (GLABELS_DATA_DIR, "ui", "new-label-dialog.ui", NULL);
176         gtk_builder_add_objects_from_file (builder, builder_filename, object_ids, &error);
177         g_free (builder_filename);
178         if (error) {
179                 g_critical ("%s\n\ngLabels may not be installed correctly!", error->message);
180                 g_error_free (error);
181                 return;
182         }
183
184         gl_builder_util_get_widgets (builder,
185                                      "page_1_banner_eventbox", &page_1_banner_eventbox,
186                                      "page_2_banner_eventbox", &page_2_banner_eventbox,
187                                      "page_3_banner_eventbox", &page_3_banner_eventbox,
188                                      "page_1_image",           &page_1_image,
189                                      "page_2_image",           &page_2_image,
190                                      "page_3_image",           &page_3_image,
191                                      "template_page_vbox",     &this->priv->template_page_vbox,
192                                      "combo_hbox",             &this->priv->combo_hbox,
193                                      "rotate_page_vbox",       &this->priv->rotate_page_vbox,
194                                      "normal_radio",           &this->priv->normal_radio,
195                                      "rotated_radio",          &this->priv->rotated_radio,
196                                      "normal_preview_hbox",    &this->priv->normal_preview_hbox,
197                                      "rotated_preview_hbox",   &this->priv->rotated_preview_hbox,
198                                      "confirm_page_vbox",      &this->priv->confirm_page_vbox,
199                                      "preview_vbox",           &this->priv->preview_vbox,
200                                      "desc_label",             &this->priv->desc_label,
201                                      "page_size_label",        &this->priv->page_size_label,
202                                      "label_size_label",       &this->priv->label_size_label,
203                                      "layout_label",           &this->priv->layout_label,
204                                      "vendor_label",           &this->priv->vendor_label,
205                                      "part_label",             &this->priv->part_label,
206                                      "similar_label",          &this->priv->similar_label,
207                                      NULL);
208
209         this->priv->builder = builder;
210
211         gtk_assistant_append_page (GTK_ASSISTANT (this), this->priv->template_page_vbox);
212         gtk_assistant_set_page_title (GTK_ASSISTANT (this), this->priv->template_page_vbox, _("Select Product"));
213         gtk_assistant_set_page_type (GTK_ASSISTANT (this), this->priv->template_page_vbox, GTK_ASSISTANT_PAGE_INTRO);
214         gtk_widget_override_background_color (page_1_banner_eventbox, GTK_STATE_NORMAL, &banner_color);
215         logo_filename = g_build_filename (GLABELS_DATA_DIR, "pixmaps", "new-select.png", NULL);
216         logo = gdk_pixbuf_new_from_file (logo_filename, NULL);
217         gtk_image_set_from_pixbuf (GTK_IMAGE (page_1_image), logo);
218         g_free (logo_filename);
219         g_object_unref (logo);
220
221         this->priv->combo = gl_media_select_new ();
222         gtk_container_add (GTK_CONTAINER (this->priv->combo_hbox), this->priv->combo);
223
224         gtk_assistant_append_page (GTK_ASSISTANT (this), this->priv->rotate_page_vbox);
225         gtk_assistant_set_page_title (GTK_ASSISTANT (this), this->priv->rotate_page_vbox, _("Choose Orientation"));
226         gtk_assistant_set_page_complete (GTK_ASSISTANT (this), this->priv->rotate_page_vbox, TRUE);
227         gtk_widget_override_background_color (page_2_banner_eventbox, GTK_STATE_NORMAL, &banner_color);
228         logo_filename = g_build_filename (GLABELS_DATA_DIR, "pixmaps", "new-rotate.png", NULL);
229         logo = gdk_pixbuf_new_from_file (logo_filename, NULL);
230         gtk_image_set_from_pixbuf (GTK_IMAGE (page_2_image), logo);
231         g_free (logo_filename);
232         g_object_unref (logo);
233
234         this->priv->normal_preview = gl_mini_label_preview_new (LABEL_PREVIEW_WIDTH, LABEL_PREVIEW_HEIGHT);
235         gtk_container_add (GTK_CONTAINER (this->priv->normal_preview_hbox), this->priv->normal_preview);
236         this->priv->rotated_preview = gl_mini_label_preview_new (LABEL_PREVIEW_WIDTH, LABEL_PREVIEW_HEIGHT);
237         gtk_container_add (GTK_CONTAINER (this->priv->rotated_preview_hbox), this->priv->rotated_preview);
238
239         gtk_assistant_append_page (GTK_ASSISTANT (this), this->priv->confirm_page_vbox);
240         gtk_assistant_set_page_title (GTK_ASSISTANT (this), this->priv->confirm_page_vbox, _("Review"));
241         gtk_assistant_set_page_type (GTK_ASSISTANT (this), this->priv->confirm_page_vbox, GTK_ASSISTANT_PAGE_CONFIRM);
242         gtk_assistant_set_page_complete (GTK_ASSISTANT (this), this->priv->confirm_page_vbox, TRUE);
243         gtk_widget_override_background_color (page_3_banner_eventbox, GTK_STATE_NORMAL, &banner_color);
244         logo_filename = g_build_filename (GLABELS_DATA_DIR, "pixmaps", "new-confirm.png", NULL);
245         logo = gdk_pixbuf_new_from_file (logo_filename, NULL);
246         gtk_image_set_from_pixbuf (GTK_IMAGE (page_3_image), logo);
247         g_free (logo_filename);
248         g_object_unref (logo);
249
250         this->priv->preview = gl_mini_preview_new (MINI_PREVIEW_MIN_HEIGHT, MINI_PREVIEW_MIN_WIDTH);
251         gl_mini_preview_set_draw_arrow (GL_MINI_PREVIEW (this->priv->preview), TRUE);
252         gl_mini_preview_set_rotate (GL_MINI_PREVIEW (this->priv->preview), FALSE);
253         gtk_container_add (GTK_CONTAINER (this->priv->preview_vbox), this->priv->preview);
254
255         gtk_assistant_set_forward_page_func (GTK_ASSISTANT (this), (GtkAssistantPageFunc)forward_page_function, this, NULL);
256
257         g_signal_connect_swapped (G_OBJECT(this), "cancel", G_CALLBACK(cancel_cb), this);
258         g_signal_connect_swapped (G_OBJECT(this), "apply",  G_CALLBACK(apply_cb),  this);
259         g_signal_connect_swapped (G_OBJECT(this), "close",  G_CALLBACK(close_cb),  this);
260
261         g_signal_connect_swapped (G_OBJECT (this->priv->combo),         "changed", G_CALLBACK (combo_changed_cb),  this);
262         g_signal_connect_swapped (G_OBJECT (this->priv->normal_radio),  "toggled", G_CALLBACK (rotate_toggled_cb), this);
263         g_signal_connect_swapped (G_OBJECT (this->priv->rotated_radio), "toggled", G_CALLBACK (rotate_toggled_cb), this);
264
265         combo_changed_cb (this);
266
267         gl_debug (DEBUG_FILE, "END");
268 }
269
270
271 /*****************************************************************************/
272 /* Finalize Function.                                                        */
273 /*****************************************************************************/
274 static void 
275 gl_new_label_dialog_finalize (GObject *object)
276 {
277         glNewLabelDialog* this = GL_NEW_LABEL_DIALOG (object);;
278
279         gl_debug (DEBUG_FILE, "START");
280
281         g_return_if_fail (object != NULL);
282         g_return_if_fail (GL_IS_NEW_LABEL_DIALOG (this));
283         g_return_if_fail (this->priv != NULL);
284
285         g_object_unref (G_OBJECT (this->priv->builder));
286         g_free (this->priv);
287
288         G_OBJECT_CLASS (gl_new_label_dialog_parent_class)->finalize (object);
289
290         gl_debug (DEBUG_FILE, "END");
291
292 }
293
294
295 /*****************************************************************************/
296 /* NEW object properties dialog.                                             */
297 /*****************************************************************************/
298 GtkWidget *
299 gl_new_label_dialog_new (GtkWindow    *win)
300 {
301         GtkWidget *this;
302
303         gl_debug (DEBUG_FILE, "");
304
305         this = GTK_WIDGET (g_object_new (GL_TYPE_NEW_LABEL_DIALOG, NULL));
306
307         gtk_window_set_transient_for (GTK_WINDOW (this), win);
308
309         return this;
310 }
311
312
313 /*--------------------------------------------------------------------------*/
314 /* PRIVATE.  Handle non-linear forward traversal.                           */
315 /*--------------------------------------------------------------------------*/
316 static gint
317 forward_page_function (gint              current_page,
318                        glNewLabelDialog *this)
319 {
320         gchar                     *name;
321         lglTemplate               *template;
322         const lglTemplateFrame    *frame;
323         gdouble                    w, h;
324
325         switch (current_page)
326         {
327         case TEMPLATE_PAGE_NUM:
328                 name = gl_media_select_get_name (GL_MEDIA_SELECT (this->priv->combo));
329                 if ( name != NULL )
330                 {
331                         template = lgl_db_lookup_template_from_name (name);
332                         frame    = (lglTemplateFrame *)template->frames->data;
333                         lgl_template_frame_get_size (frame, &w, &h);
334
335                         if ( w == h )
336                         {
337                                 /* Skip rotate page for square and circular labels. */
338                                 return CONFIRM_PAGE_NUM;
339                         }
340                 }
341                 return ROTATE_PAGE_NUM;
342
343         case ROTATE_PAGE_NUM:
344                 return CONFIRM_PAGE_NUM;
345
346         case CONFIRM_PAGE_NUM:
347         default:
348                 return -1;
349         }
350
351         return -1;
352 }
353
354
355 /*--------------------------------------------------------------------------*/
356 /* PRIVATE.  cancel callback.                                               */
357 /*--------------------------------------------------------------------------*/
358 static void
359 cancel_cb (glNewLabelDialog *this)
360 {
361                                                                                
362         gtk_widget_destroy (GTK_WIDGET(this));
363
364 }
365
366
367 /*--------------------------------------------------------------------------*/
368 /* PRIVATE.  apply callback                                                 */
369 /*--------------------------------------------------------------------------*/
370 static void
371 apply_cb (glNewLabelDialog *this)
372 {
373
374         g_signal_emit (G_OBJECT (this), signals[COMPLETE], 0);
375
376 }
377
378                          
379 /*--------------------------------------------------------------------------*/
380 /* PRIVATE.  close callback                                                 */
381 /*--------------------------------------------------------------------------*/
382 static void
383 close_cb (glNewLabelDialog *this)
384 {
385                                                                                
386         gtk_widget_destroy (GTK_WIDGET(this));
387
388 }
389
390                          
391 /*---------------------------------------------------------------------------*/
392 /* PRIVATE.  Template changed callback.                                      */
393 /*---------------------------------------------------------------------------*/
394 static void
395 combo_changed_cb (glNewLabelDialog  *this)
396 {
397         gchar             *name;
398
399         gl_debug (DEBUG_FILE, "START");
400
401         name = gl_media_select_get_name (GL_MEDIA_SELECT (this->priv->combo));
402
403         gl_mini_label_preview_set_by_name (GL_MINI_LABEL_PREVIEW (this->priv->normal_preview),  name, FALSE);
404         gl_mini_label_preview_set_by_name (GL_MINI_LABEL_PREVIEW (this->priv->rotated_preview), name, TRUE);
405         gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (this->priv->normal_radio), TRUE);
406
407         gl_mini_preview_set_by_name (GL_MINI_PREVIEW (this->priv->preview), name);
408         set_info (this, name);
409
410         gtk_assistant_set_page_complete (GTK_ASSISTANT (this), this->priv->template_page_vbox, (name != NULL));
411
412         g_free (name);
413
414         gl_debug (DEBUG_FILE, "END");
415 }
416
417
418 /*---------------------------------------------------------------------------*/
419 /* PRIVATE.  Rotate toggled callback.                                        */
420 /*---------------------------------------------------------------------------*/
421 static void
422 rotate_toggled_cb (glNewLabelDialog  *this)
423 {
424         gboolean state;
425
426         gl_debug (DEBUG_FILE, "START");
427
428         state = gtk_toggle_button_get_active (GTK_TOGGLE_BUTTON (this->priv->rotated_radio));
429         gl_mini_preview_set_rotate (GL_MINI_PREVIEW (this->priv->preview), state);
430
431         gl_debug (DEBUG_FILE, "END");
432 }
433
434
435 /*---------------------------------------------------------------------------*/
436 /* PRIVATE.  Set information labels.                                         */
437 /*---------------------------------------------------------------------------*/
438 static void
439 set_info (glNewLabelDialog  *this,
440           const gchar       *name)
441 {
442         lglTemplate          *template;
443         lglTemplateFrame     *frame;
444         lglVendor            *vendor;
445         lglUnits              units;
446         gchar                *page_size_string;
447         gchar                *label_size_string;
448         gchar                *layout_string;
449         GList                *list, *p;
450         GString              *list_string;
451
452         template = lgl_db_lookup_template_from_name (name);
453         frame    = template->frames->data;
454         vendor   = lgl_db_lookup_vendor_from_name (template->brand);
455
456         units    = gl_prefs_model_get_units (gl_prefs);
457
458         page_size_string  = lgl_db_lookup_paper_name_from_id (template->paper_id);
459         label_size_string = lgl_template_frame_get_size_description (frame, units);
460         layout_string     = lgl_template_frame_get_layout_description (frame);
461
462         gtk_label_set_text (GTK_LABEL (this->priv->desc_label),       template->description);
463         gtk_label_set_text (GTK_LABEL (this->priv->page_size_label),  page_size_string);
464         gtk_label_set_text (GTK_LABEL (this->priv->label_size_label), label_size_string);
465         gtk_label_set_text (GTK_LABEL (this->priv->layout_label),     layout_string);
466
467         if ( vendor && vendor->url )
468         {
469                 gchar *escaped_url;
470                 gchar *markup;
471
472                 escaped_url = g_markup_escape_text (vendor->url, -1);
473                 markup = g_strdup_printf ("<a href='%s'>%s</a>", escaped_url, vendor->name);
474                 gtk_label_set_markup (GTK_LABEL (this->priv->vendor_label), markup);
475                 gtk_widget_set_tooltip_text (this->priv->vendor_label, escaped_url);
476                 g_free (escaped_url);
477                 g_free (markup);
478         }
479         else
480         {
481                 /* FIXME: Using set_markup instead of set_text to clear out previous link. */
482                 gtk_label_set_markup (GTK_LABEL (this->priv->vendor_label), template->brand);
483                 gtk_widget_set_has_tooltip (this->priv->vendor_label, FALSE);
484         }
485
486         if ( template->product_url )
487         {
488                 gchar *escaped_url;
489                 gchar *markup;
490
491                 escaped_url = g_markup_escape_text (template->product_url, -1);
492                 markup = g_strdup_printf ("<a href='%s'>%s</a>", escaped_url, template->part);
493                 gtk_label_set_markup (GTK_LABEL (this->priv->part_label), markup);
494                 gtk_widget_set_tooltip_text (this->priv->part_label, escaped_url);
495                 g_free (escaped_url);
496                 g_free (markup);
497         }
498         else
499         {
500                 /* FIXME: Using set_markup instead of set_text to clear out previous link. */
501                 gtk_label_set_markup (GTK_LABEL (this->priv->part_label), template->part);
502                 gtk_widget_set_has_tooltip (this->priv->part_label, FALSE);
503         }
504
505         list = lgl_db_get_similar_template_name_list (name);
506         list_string = g_string_new ("");
507         for ( p = list; p; p = p->next )
508         {
509                 g_string_append (list_string, (char *)p->data);
510                 if ( p->next )
511                 {
512                         g_string_append (list_string, "\n");
513                 }
514         }
515         gtk_label_set_text (GTK_LABEL (this->priv->similar_label), list_string->str);
516
517         lgl_db_free_template_name_list (list);
518         g_string_free (list_string, TRUE);
519
520         g_free (page_size_string);
521         g_free (label_size_string);
522         g_free (layout_string);
523 }
524
525
526 /*****************************************************************************/
527 /* Get template name.                                                        */
528 /*****************************************************************************/
529 gchar *
530 gl_new_label_dialog_get_template_name (glNewLabelDialog *this)
531 {
532         gchar *name;
533
534         name = gl_media_select_get_name (GL_MEDIA_SELECT (this->priv->combo));
535
536         return name;
537 }
538
539
540 /*****************************************************************************/
541 /* Set template name.                                                        */
542 /*****************************************************************************/
543 void
544 gl_new_label_dialog_set_template_name (glNewLabelDialog *this,
545                                        gchar            *name)
546 {
547         gl_mini_preview_set_by_name (GL_MINI_PREVIEW (this->priv->preview), name);
548         gl_media_select_set_name (GL_MEDIA_SELECT (this->priv->combo), name);
549         set_info (this, name);
550 }
551
552
553 /*****************************************************************************/
554 /* Get current filter parameters.                                            */
555 /*****************************************************************************/
556 void
557 gl_new_label_dialog_get_filter_parameters (glNewLabelDialog  *this,
558                                            gchar            **page_size_id,
559                                            gchar            **category_id)
560 {
561 }
562
563
564 /*****************************************************************************/
565 /* Set current filter parameters.                                            */
566 /*****************************************************************************/
567 void
568 gl_new_label_dialog_set_filter_parameters (glNewLabelDialog *this,
569                                            const gchar      *page_size_id,
570                                            const gchar      *category_id)
571 {
572 }
573
574
575 /*****************************************************************************/
576 /* Get rotate state.                                                         */
577 /*****************************************************************************/
578 gboolean
579 gl_new_label_dialog_get_rotate_state (glNewLabelDialog *this)
580 {
581         return gtk_toggle_button_get_active (GTK_TOGGLE_BUTTON (this->priv->rotated_radio));
582 }
583
584
585 /*****************************************************************************/
586 /* Set rotate state.                                                         */
587 /*****************************************************************************/
588 void
589 gl_new_label_dialog_set_rotate_state (glNewLabelDialog *this,
590                                       gboolean          state)
591 {
592         gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (this->priv->rotated_radio), state);
593         gl_mini_preview_set_rotate (GL_MINI_PREVIEW (this->priv->preview), state);
594 }
595
596
597
598 /*
599  * Local Variables:       -- emacs
600  * mode: C                -- emacs
601  * c-basic-offset: 8      -- emacs
602  * tab-width: 8           -- emacs
603  * indent-tabs-mode: nil  -- emacs
604  * End:                   -- emacs
605  */