]> git.sur5r.net Git - glabels/blob - src/new-label-dialog.c
Fix incomplete library dependencies.
[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         gchar        *logo_filename;
156         GdkPixbuf    *logo;
157         GtkBuilder   *builder;
158         gchar        *builder_filename;
159         static gchar *object_ids[] = { "template_page_vbox",
160                                        "rotate_page_vbox",
161                                        "confirm_page_vbox",
162                                        NULL };
163         GError       *error = NULL;
164
165         gl_debug (DEBUG_FILE, "START");
166
167         g_return_if_fail (GL_IS_NEW_LABEL_DIALOG (this));
168
169         this->priv = g_new0 (glNewLabelDialogPrivate, 1);
170
171         builder = gtk_builder_new ();
172         builder_filename = g_build_filename (GLABELS_DATA_DIR, "ui", "new-label-dialog.ui", NULL);
173         gtk_builder_add_objects_from_file (builder, builder_filename, object_ids, &error);
174         g_free (builder_filename);
175         if (error) {
176                 g_critical ("%s\n\ngLabels may not be installed correctly!", error->message);
177                 g_error_free (error);
178                 return;
179         }
180
181         gl_builder_util_get_widgets (builder,
182                                      "template_page_vbox",     &this->priv->template_page_vbox,
183                                      "combo_hbox",             &this->priv->combo_hbox,
184                                      "rotate_page_vbox",       &this->priv->rotate_page_vbox,
185                                      "normal_radio",           &this->priv->normal_radio,
186                                      "rotated_radio",          &this->priv->rotated_radio,
187                                      "normal_preview_hbox",    &this->priv->normal_preview_hbox,
188                                      "rotated_preview_hbox",   &this->priv->rotated_preview_hbox,
189                                      "confirm_page_vbox",      &this->priv->confirm_page_vbox,
190                                      "preview_vbox",           &this->priv->preview_vbox,
191                                      "desc_label",             &this->priv->desc_label,
192                                      "page_size_label",        &this->priv->page_size_label,
193                                      "label_size_label",       &this->priv->label_size_label,
194                                      "layout_label",           &this->priv->layout_label,
195                                      "vendor_label",           &this->priv->vendor_label,
196                                      "part_label",             &this->priv->part_label,
197                                      "similar_label",          &this->priv->similar_label,
198                                      NULL);
199
200         this->priv->builder = builder;
201
202         gtk_assistant_append_page (GTK_ASSISTANT (this), this->priv->template_page_vbox);
203         gtk_assistant_set_page_title (GTK_ASSISTANT (this), this->priv->template_page_vbox, _("Select Product"));
204         gtk_assistant_set_page_type (GTK_ASSISTANT (this), this->priv->template_page_vbox, GTK_ASSISTANT_PAGE_INTRO);
205         logo_filename = g_build_filename (GLABELS_DATA_DIR, "pixmaps", "new-select.png", NULL);
206         logo = gdk_pixbuf_new_from_file (logo_filename, NULL);
207         gtk_assistant_set_page_header_image (GTK_ASSISTANT (this), this->priv->template_page_vbox, logo);
208         g_free (logo_filename);
209         g_object_unref (logo);
210
211         this->priv->combo = gl_media_select_new ();
212         gtk_container_add (GTK_CONTAINER (this->priv->combo_hbox), this->priv->combo);
213
214         gtk_assistant_append_page (GTK_ASSISTANT (this), this->priv->rotate_page_vbox);
215         gtk_assistant_set_page_title (GTK_ASSISTANT (this), this->priv->rotate_page_vbox, _("Choose Orientation"));
216         gtk_assistant_set_page_complete (GTK_ASSISTANT (this), this->priv->rotate_page_vbox, TRUE);
217         logo_filename = g_build_filename (GLABELS_DATA_DIR, "pixmaps", "new-rotate.png", NULL);
218         logo = gdk_pixbuf_new_from_file (logo_filename, NULL);
219         gtk_assistant_set_page_header_image (GTK_ASSISTANT (this), this->priv->rotate_page_vbox, logo);
220         g_free (logo_filename);
221         g_object_unref (logo);
222
223         this->priv->normal_preview = gl_mini_label_preview_new (LABEL_PREVIEW_WIDTH, LABEL_PREVIEW_HEIGHT);
224         gtk_container_add (GTK_CONTAINER (this->priv->normal_preview_hbox), this->priv->normal_preview);
225         this->priv->rotated_preview = gl_mini_label_preview_new (LABEL_PREVIEW_WIDTH, LABEL_PREVIEW_HEIGHT);
226         gtk_container_add (GTK_CONTAINER (this->priv->rotated_preview_hbox), this->priv->rotated_preview);
227
228         gtk_assistant_append_page (GTK_ASSISTANT (this), this->priv->confirm_page_vbox);
229         gtk_assistant_set_page_title (GTK_ASSISTANT (this), this->priv->confirm_page_vbox, _("Review"));
230         gtk_assistant_set_page_type (GTK_ASSISTANT (this), this->priv->confirm_page_vbox, GTK_ASSISTANT_PAGE_CONFIRM);
231         gtk_assistant_set_page_complete (GTK_ASSISTANT (this), this->priv->confirm_page_vbox, TRUE);
232         logo_filename = g_build_filename (GLABELS_DATA_DIR, "pixmaps", "new-confirm.png", NULL);
233         logo = gdk_pixbuf_new_from_file (logo_filename, NULL);
234         gtk_assistant_set_page_header_image (GTK_ASSISTANT (this), this->priv->confirm_page_vbox, logo);
235         g_free (logo_filename);
236         g_object_unref (logo);
237
238         this->priv->preview = gl_mini_preview_new (MINI_PREVIEW_MIN_HEIGHT, MINI_PREVIEW_MIN_WIDTH);
239         gl_mini_preview_set_draw_arrow (GL_MINI_PREVIEW (this->priv->preview), TRUE);
240         gl_mini_preview_set_rotate (GL_MINI_PREVIEW (this->priv->preview), FALSE);
241         gtk_container_add (GTK_CONTAINER (this->priv->preview_vbox), this->priv->preview);
242
243         gtk_assistant_set_forward_page_func (GTK_ASSISTANT (this), (GtkAssistantPageFunc)forward_page_function, this, NULL);
244
245         g_signal_connect_swapped (G_OBJECT(this), "cancel", G_CALLBACK(cancel_cb), this);
246         g_signal_connect_swapped (G_OBJECT(this), "apply",  G_CALLBACK(apply_cb),  this);
247         g_signal_connect_swapped (G_OBJECT(this), "close",  G_CALLBACK(close_cb),  this);
248
249         g_signal_connect_swapped (G_OBJECT (this->priv->combo),         "changed", G_CALLBACK (combo_changed_cb),  this);
250         g_signal_connect_swapped (G_OBJECT (this->priv->normal_radio),  "toggled", G_CALLBACK (rotate_toggled_cb), this);
251         g_signal_connect_swapped (G_OBJECT (this->priv->rotated_radio), "toggled", G_CALLBACK (rotate_toggled_cb), this);
252
253         combo_changed_cb (this);
254
255         gl_debug (DEBUG_FILE, "END");
256 }
257
258
259 /*****************************************************************************/
260 /* Finalize Function.                                                        */
261 /*****************************************************************************/
262 static void 
263 gl_new_label_dialog_finalize (GObject *object)
264 {
265         glNewLabelDialog* this = GL_NEW_LABEL_DIALOG (object);;
266
267         gl_debug (DEBUG_FILE, "START");
268
269         g_return_if_fail (object != NULL);
270         g_return_if_fail (GL_IS_NEW_LABEL_DIALOG (this));
271         g_return_if_fail (this->priv != NULL);
272
273         g_object_unref (G_OBJECT (this->priv->builder));
274         g_free (this->priv);
275
276         G_OBJECT_CLASS (gl_new_label_dialog_parent_class)->finalize (object);
277
278         gl_debug (DEBUG_FILE, "END");
279
280 }
281
282
283 /*****************************************************************************/
284 /* NEW object properties dialog.                                             */
285 /*****************************************************************************/
286 GtkWidget *
287 gl_new_label_dialog_new (GtkWindow    *win)
288 {
289         GtkWidget *this;
290
291         gl_debug (DEBUG_FILE, "");
292
293         this = GTK_WIDGET (g_object_new (GL_TYPE_NEW_LABEL_DIALOG, NULL));
294
295         gtk_window_set_transient_for (GTK_WINDOW (this), win);
296
297         return this;
298 }
299
300
301 /*--------------------------------------------------------------------------*/
302 /* PRIVATE.  Handle non-linear forward traversal.                           */
303 /*--------------------------------------------------------------------------*/
304 static gint
305 forward_page_function (gint              current_page,
306                        glNewLabelDialog *this)
307 {
308         gchar                     *name;
309         lglTemplate               *template;
310         const lglTemplateFrame    *frame;
311         gdouble                    w, h;
312
313         switch (current_page)
314         {
315         case TEMPLATE_PAGE_NUM:
316                 name = gl_media_select_get_name (GL_MEDIA_SELECT (this->priv->combo));
317                 if ( name != NULL )
318                 {
319                         template = lgl_db_lookup_template_from_name (name);
320                         frame    = (lglTemplateFrame *)template->frames->data;
321                         lgl_template_frame_get_size (frame, &w, &h);
322
323                         if ( w == h )
324                         {
325                                 /* Skip rotate page for square and circular labels. */
326                                 return CONFIRM_PAGE_NUM;
327                         }
328                 }
329                 return ROTATE_PAGE_NUM;
330
331         case ROTATE_PAGE_NUM:
332                 return CONFIRM_PAGE_NUM;
333
334         case CONFIRM_PAGE_NUM:
335         default:
336                 return -1;
337         }
338
339         return -1;
340 }
341
342
343 /*--------------------------------------------------------------------------*/
344 /* PRIVATE.  cancel callback.                                               */
345 /*--------------------------------------------------------------------------*/
346 static void
347 cancel_cb (glNewLabelDialog *this)
348 {
349                                                                                
350         gtk_widget_destroy (GTK_WIDGET(this));
351
352 }
353
354
355 /*--------------------------------------------------------------------------*/
356 /* PRIVATE.  apply callback                                                 */
357 /*--------------------------------------------------------------------------*/
358 static void
359 apply_cb (glNewLabelDialog *this)
360 {
361
362         g_signal_emit (G_OBJECT (this), signals[COMPLETE], 0);
363
364 }
365
366                          
367 /*--------------------------------------------------------------------------*/
368 /* PRIVATE.  close callback                                                 */
369 /*--------------------------------------------------------------------------*/
370 static void
371 close_cb (glNewLabelDialog *this)
372 {
373                                                                                
374         gtk_widget_destroy (GTK_WIDGET(this));
375
376 }
377
378                          
379 /*---------------------------------------------------------------------------*/
380 /* PRIVATE.  Template changed callback.                                      */
381 /*---------------------------------------------------------------------------*/
382 static void
383 combo_changed_cb (glNewLabelDialog  *this)
384 {
385         gchar             *name;
386
387         gl_debug (DEBUG_FILE, "START");
388
389         name = gl_media_select_get_name (GL_MEDIA_SELECT (this->priv->combo));
390
391         gl_mini_label_preview_set_by_name (GL_MINI_LABEL_PREVIEW (this->priv->normal_preview),  name, FALSE);
392         gl_mini_label_preview_set_by_name (GL_MINI_LABEL_PREVIEW (this->priv->rotated_preview), name, TRUE);
393         gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (this->priv->normal_radio), TRUE);
394
395         gl_mini_preview_set_by_name (GL_MINI_PREVIEW (this->priv->preview), name);
396         set_info (this, name);
397
398         gtk_assistant_set_page_complete (GTK_ASSISTANT (this), this->priv->template_page_vbox, (name != NULL));
399
400         g_free (name);
401
402         gl_debug (DEBUG_FILE, "END");
403 }
404
405
406 /*---------------------------------------------------------------------------*/
407 /* PRIVATE.  Rotate toggled callback.                                        */
408 /*---------------------------------------------------------------------------*/
409 static void
410 rotate_toggled_cb (glNewLabelDialog  *this)
411 {
412         gboolean state;
413
414         gl_debug (DEBUG_FILE, "START");
415
416         state = gtk_toggle_button_get_active (GTK_TOGGLE_BUTTON (this->priv->rotated_radio));
417         gl_mini_preview_set_rotate (GL_MINI_PREVIEW (this->priv->preview), state);
418
419         gl_debug (DEBUG_FILE, "END");
420 }
421
422
423 /*---------------------------------------------------------------------------*/
424 /* PRIVATE.  Set information labels.                                         */
425 /*---------------------------------------------------------------------------*/
426 static void
427 set_info (glNewLabelDialog  *this,
428           const gchar       *name)
429 {
430         lglTemplate          *template;
431         lglTemplateFrame     *frame;
432         lglVendor            *vendor;
433         lglUnits              units;
434         gchar                *page_size_string;
435         gchar                *label_size_string;
436         gchar                *layout_string;
437         GList                *list, *p;
438         GString              *list_string;
439
440         template = lgl_db_lookup_template_from_name (name);
441         frame    = template->frames->data;
442         vendor   = lgl_db_lookup_vendor_from_name (template->brand);
443
444         units    = gl_prefs_model_get_units (gl_prefs);
445
446         page_size_string  = lgl_db_lookup_paper_name_from_id (template->paper_id);
447         label_size_string = lgl_template_frame_get_size_description (frame, units);
448         layout_string     = lgl_template_frame_get_layout_description (frame);
449
450         gtk_label_set_text (GTK_LABEL (this->priv->desc_label),       template->description);
451         gtk_label_set_text (GTK_LABEL (this->priv->page_size_label),  page_size_string);
452         gtk_label_set_text (GTK_LABEL (this->priv->label_size_label), label_size_string);
453         gtk_label_set_text (GTK_LABEL (this->priv->layout_label),     layout_string);
454
455         if ( vendor && vendor->url )
456         {
457                 gchar *escaped_url;
458                 gchar *markup;
459
460                 escaped_url = g_markup_escape_text (vendor->url, -1);
461                 markup = g_strdup_printf ("<a href='%s'>%s</a>", escaped_url, vendor->name);
462                 gtk_label_set_markup (GTK_LABEL (this->priv->vendor_label), markup);
463                 gtk_widget_set_tooltip_text (this->priv->vendor_label, escaped_url);
464                 g_free (escaped_url);
465                 g_free (markup);
466         }
467         else
468         {
469                 /* FIXME: Using set_markup instead of set_text to clear out previous link. */
470                 gtk_label_set_markup (GTK_LABEL (this->priv->vendor_label), template->brand);
471                 gtk_widget_set_has_tooltip (this->priv->vendor_label, FALSE);
472         }
473
474         if ( template->product_url )
475         {
476                 gchar *escaped_url;
477                 gchar *markup;
478
479                 escaped_url = g_markup_escape_text (template->product_url, -1);
480                 markup = g_strdup_printf ("<a href='%s'>%s</a>", escaped_url, template->part);
481                 gtk_label_set_markup (GTK_LABEL (this->priv->part_label), markup);
482                 gtk_widget_set_tooltip_text (this->priv->part_label, escaped_url);
483                 g_free (escaped_url);
484                 g_free (markup);
485         }
486         else
487         {
488                 /* FIXME: Using set_markup instead of set_text to clear out previous link. */
489                 gtk_label_set_markup (GTK_LABEL (this->priv->part_label), template->part);
490                 gtk_widget_set_has_tooltip (this->priv->part_label, FALSE);
491         }
492
493         list = lgl_db_get_similar_template_name_list (name);
494         list_string = g_string_new ("");
495         for ( p = list; p; p = p->next )
496         {
497                 g_string_append (list_string, (char *)p->data);
498                 if ( p->next )
499                 {
500                         g_string_append (list_string, "\n");
501                 }
502         }
503         gtk_label_set_text (GTK_LABEL (this->priv->similar_label), list_string->str);
504
505         lgl_db_free_template_name_list (list);
506         g_string_free (list_string, TRUE);
507
508         g_free (page_size_string);
509         g_free (label_size_string);
510         g_free (layout_string);
511 }
512
513
514 /*****************************************************************************/
515 /* Get template name.                                                        */
516 /*****************************************************************************/
517 gchar *
518 gl_new_label_dialog_get_template_name (glNewLabelDialog *this)
519 {
520         gchar *name;
521
522         name = gl_media_select_get_name (GL_MEDIA_SELECT (this->priv->combo));
523
524         return name;
525 }
526
527
528 /*****************************************************************************/
529 /* Set template name.                                                        */
530 /*****************************************************************************/
531 void
532 gl_new_label_dialog_set_template_name (glNewLabelDialog *this,
533                                        gchar            *name)
534 {
535         gl_mini_preview_set_by_name (GL_MINI_PREVIEW (this->priv->preview), name);
536         gl_media_select_set_name (GL_MEDIA_SELECT (this->priv->combo), name);
537         set_info (this, name);
538 }
539
540
541 /*****************************************************************************/
542 /* Get current filter parameters.                                            */
543 /*****************************************************************************/
544 void
545 gl_new_label_dialog_get_filter_parameters (glNewLabelDialog  *this,
546                                            gchar            **page_size_id,
547                                            gchar            **category_id)
548 {
549 }
550
551
552 /*****************************************************************************/
553 /* Set current filter parameters.                                            */
554 /*****************************************************************************/
555 void
556 gl_new_label_dialog_set_filter_parameters (glNewLabelDialog *this,
557                                            const gchar      *page_size_id,
558                                            const gchar      *category_id)
559 {
560 }
561
562
563 /*****************************************************************************/
564 /* Get rotate state.                                                         */
565 /*****************************************************************************/
566 gboolean
567 gl_new_label_dialog_get_rotate_state (glNewLabelDialog *this)
568 {
569         return gtk_toggle_button_get_active (GTK_TOGGLE_BUTTON (this->priv->rotated_radio));
570 }
571
572
573 /*****************************************************************************/
574 /* Set rotate state.                                                         */
575 /*****************************************************************************/
576 void
577 gl_new_label_dialog_set_rotate_state (glNewLabelDialog *this,
578                                       gboolean          state)
579 {
580         gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (this->priv->rotated_radio), state);
581         gl_mini_preview_set_rotate (GL_MINI_PREVIEW (this->priv->preview), state);
582 }
583
584
585
586 /*
587  * Local Variables:       -- emacs
588  * mode: C                -- emacs
589  * c-basic-offset: 8      -- emacs
590  * tab-width: 8           -- emacs
591  * indent-tabs-mode: nil  -- emacs
592  * End:                   -- emacs
593  */