1 /* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 8 -*- */
4 * (GLABELS) Label and Business Card Creation program for GNOME
6 * wdgt_media_select.c: media selection widget module
8 * Copyright (C) 2001-2006 Jim Evins <evins@snaught.com>.
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.
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.
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
27 #include "wdgt-media-select.h"
29 #include <glib/gi18n.h>
30 #include <glade/glade-xml.h>
31 #include <gtk/gtkcombobox.h>
32 #include <gtk/gtktreeview.h>
33 #include <gtk/gtktreeselection.h>
34 #include <gtk/gtkliststore.h>
35 #include <gtk/gtkcellrenderertext.h>
36 #include <gtk/gtkcellrendererpixbuf.h>
37 #include <gtk/gtkstock.h>
40 #include "mini-preview-pixbuf.h"
45 #include <libglabels/paper.h>
46 #include <libglabels/category.h>
47 #include <libglabels/template.h>
51 /*===========================================*/
53 /*===========================================*/
59 PREVIEW_COLUMN_STOCK_SIZE,
64 struct _glWdgtMediaSelectPrivate {
68 GtkWidget *page_size_combo;
69 GtkWidget *category_combo;
71 GtkWidget *template_treeview;
72 GtkListStore *template_store;
80 typedef void (*glWdgtMediaSelectSignal) (GObject * object, gpointer data);
82 /*===========================================*/
84 /*===========================================*/
86 static GObjectClass *parent_class;
88 static gint wdgt_media_select_signals[LAST_SIGNAL] = { 0 };
90 /*===========================================*/
91 /* Local function prototypes */
92 /*===========================================*/
94 static void gl_wdgt_media_select_class_init (glWdgtMediaSelectClass *class);
95 static void gl_wdgt_media_select_instance_init (glWdgtMediaSelect *media_select);
96 static void gl_wdgt_media_select_finalize (GObject *object);
98 static void gl_wdgt_media_select_construct (glWdgtMediaSelect *media_select);
100 static void filter_changed_cb (GtkComboBox *combo,
102 static void template_selection_changed_cb (GtkTreeSelection *selection,
105 static void details_update (glWdgtMediaSelect *media_select,
108 static gchar *get_layout_desc (const glTemplate *template);
109 static gchar *get_label_size_desc (const glTemplate *template);
110 static void load_list (GtkListStore *store,
111 GtkTreeSelection *selection,
114 /****************************************************************************/
115 /* Boilerplate Object stuff. */
116 /****************************************************************************/
118 gl_wdgt_media_select_get_type (void)
120 static GType type = 0;
123 static const GTypeInfo info = {
124 sizeof (glWdgtMediaSelectClass),
127 (GClassInitFunc) gl_wdgt_media_select_class_init,
130 sizeof (glWdgtMediaSelect),
132 (GInstanceInitFunc) gl_wdgt_media_select_instance_init,
136 type = g_type_register_static (GTK_TYPE_VBOX,
137 "glWdgtMediaSelect", &info, 0);
144 gl_wdgt_media_select_class_init (glWdgtMediaSelectClass *class)
146 GObjectClass *object_class;
148 gl_debug (DEBUG_MEDIA_SELECT, "START");
150 object_class = (GObjectClass *) class;
152 parent_class = g_type_class_peek_parent (class);
154 object_class->finalize = gl_wdgt_media_select_finalize;
156 wdgt_media_select_signals[CHANGED] =
157 g_signal_new ("changed",
158 G_OBJECT_CLASS_TYPE(object_class),
160 G_STRUCT_OFFSET (glWdgtMediaSelectClass, changed),
162 gl_marshal_VOID__VOID,
165 gl_debug (DEBUG_MEDIA_SELECT, "END");
169 gl_wdgt_media_select_instance_init (glWdgtMediaSelect *media_select)
171 gl_debug (DEBUG_MEDIA_SELECT, "START");
173 media_select->priv = g_new0 (glWdgtMediaSelectPrivate, 1);
175 media_select->priv->gui = glade_xml_new (GLABELS_GLADE_DIR "wdgt-media-select.glade",
176 "wdgt_media_select_hbox",
179 if (!media_select->priv->gui) {
180 g_critical ("Could not open wdgt-media-select.glade. gLabels may not be installed correctly!");
184 gl_debug (DEBUG_MEDIA_SELECT, "END");
188 gl_wdgt_media_select_finalize (GObject *object)
190 glWdgtMediaSelect *media_select;
191 glWdgtMediaSelectClass *class;
193 gl_debug (DEBUG_MEDIA_SELECT, "START");
195 g_return_if_fail (object != NULL);
196 g_return_if_fail (GL_IS_WDGT_MEDIA_SELECT (object));
198 media_select = GL_WDGT_MEDIA_SELECT (object);
200 G_OBJECT_CLASS (parent_class)->finalize (object);
202 g_free (media_select->priv);
204 gl_debug (DEBUG_MEDIA_SELECT, "END");
208 gl_wdgt_media_select_new (void)
210 glWdgtMediaSelect *media_select;
212 gl_debug (DEBUG_MEDIA_SELECT, "START");
214 media_select = g_object_new (gl_wdgt_media_select_get_type (), NULL);
216 gl_wdgt_media_select_construct (media_select);
218 gl_debug (DEBUG_MEDIA_SELECT, "END");
220 return GTK_WIDGET (media_select);
223 /*--------------------------------------------------------------------------*/
224 /* PRIVATE. Construct composite widget. */
225 /*--------------------------------------------------------------------------*/
227 gl_wdgt_media_select_construct (glWdgtMediaSelect *media_select)
230 GtkWidget *preview_vbox;
231 GList *page_sizes = NULL;
232 GList *categories = NULL;
233 GList *template_names = NULL;
234 const gchar *page_size_id;
235 gchar *page_size_name;
237 GtkCellRenderer *renderer;
238 GtkTreeViewColumn *column;
239 GtkTreeSelection *selection;
243 gl_debug (DEBUG_MEDIA_SELECT, "START");
245 g_return_if_fail (GL_IS_WDGT_MEDIA_SELECT (media_select));
246 g_return_if_fail (media_select->priv != NULL);
248 hbox = glade_xml_get_widget (media_select->priv->gui,
249 "wdgt_media_select_hbox");
250 gtk_container_add (GTK_CONTAINER (media_select), hbox);
252 media_select->priv->page_size_combo =
253 glade_xml_get_widget (media_select->priv->gui, "page_size_combo");
254 media_select->priv->category_combo =
255 glade_xml_get_widget (media_select->priv->gui, "category_combo");
256 media_select->priv->template_treeview =
257 glade_xml_get_widget (media_select->priv->gui, "template_treeview");
259 page_size_id = gl_prefs_get_page_size ();
260 page_size_name = gl_paper_lookup_name_from_id (page_size_id);
262 /* Page size selection control */
263 gl_util_combo_box_add_text_model (GTK_COMBO_BOX (media_select->priv->page_size_combo));
264 page_sizes = gl_paper_get_name_list ();
265 page_sizes = g_list_prepend (page_sizes, g_strdup (_("Any")));
266 gl_util_combo_box_set_strings (GTK_COMBO_BOX (media_select->priv->page_size_combo), page_sizes);
267 gl_paper_free_name_list (page_sizes);
268 gl_util_combo_box_set_active_text (GTK_COMBO_BOX (media_select->priv->page_size_combo),
271 /* Category selection control */
272 gl_util_combo_box_add_text_model (GTK_COMBO_BOX (media_select->priv->category_combo));
273 categories = gl_category_get_name_list ();
274 categories = g_list_prepend (categories, g_strdup (_("Any")));
275 gl_util_combo_box_set_strings (GTK_COMBO_BOX (media_select->priv->category_combo), categories);
276 gl_util_combo_box_set_active_text (GTK_COMBO_BOX (media_select->priv->category_combo),
278 gl_category_free_name_list (categories);
280 /* Actual selection control */
281 media_select->priv->template_store = gtk_list_store_new (N_COLUMNS, G_TYPE_STRING, GDK_TYPE_PIXBUF, G_TYPE_STRING, G_TYPE_UINT, G_TYPE_STRING);
282 gtk_tree_view_set_model (GTK_TREE_VIEW (media_select->priv->template_treeview),
283 GTK_TREE_MODEL (media_select->priv->template_store));
284 renderer = gtk_cell_renderer_pixbuf_new ();
285 column = gtk_tree_view_column_new_with_attributes ("", renderer,
286 "pixbuf", PREVIEW_COLUMN,
287 "stock-id", PREVIEW_COLUMN_STOCK,
288 "stock-size", PREVIEW_COLUMN_STOCK_SIZE,
290 gtk_tree_view_column_set_sizing (column, GTK_TREE_VIEW_COLUMN_AUTOSIZE);
291 gtk_tree_view_append_column (GTK_TREE_VIEW (media_select->priv->template_treeview), column);
292 renderer = gtk_cell_renderer_text_new ();
293 column = gtk_tree_view_column_new_with_attributes ("", renderer,
294 "markup", DESCRIPTION_COLUMN,
296 gtk_tree_view_column_set_sizing (column, GTK_TREE_VIEW_COLUMN_AUTOSIZE);
297 gtk_tree_view_append_column (GTK_TREE_VIEW (media_select->priv->template_treeview), column);
298 selection = gtk_tree_view_get_selection (GTK_TREE_VIEW (media_select->priv->template_treeview));
299 template_names = gl_template_get_name_list (page_size_id, NULL);
300 load_list (media_select->priv->template_store, selection, template_names);
301 gl_template_free_name_list (template_names);
303 /* Connect signals to controls */
304 g_signal_connect (G_OBJECT (media_select->priv->page_size_combo), "changed",
305 G_CALLBACK (filter_changed_cb),
307 g_signal_connect (G_OBJECT (media_select->priv->category_combo), "changed",
308 G_CALLBACK (filter_changed_cb),
310 g_signal_connect (G_OBJECT (selection), "changed",
311 G_CALLBACK (template_selection_changed_cb),
314 g_free (page_size_name);
316 gl_debug (DEBUG_MEDIA_SELECT, "END");
319 /*--------------------------------------------------------------------------*/
320 /* PRIVATE. modify widget due to change in selection */
321 /*--------------------------------------------------------------------------*/
323 filter_changed_cb (GtkComboBox *combo,
326 glWdgtMediaSelect *media_select = GL_WDGT_MEDIA_SELECT (user_data);
327 gchar *page_size_name, *page_size_id;
328 gchar *category_name, *category_id;
329 GList *template_names;
330 GtkTreeSelection *selection;
334 gl_debug (DEBUG_MEDIA_SELECT, "START");
337 /* Update template selections for new page size */
338 page_size_name = gtk_combo_box_get_active_text (GTK_COMBO_BOX (media_select->priv->page_size_combo));
339 category_name = gtk_combo_box_get_active_text (GTK_COMBO_BOX (media_select->priv->category_combo));
340 if ( page_size_name && strlen(page_size_name) &&
341 category_name && strlen(category_name) )
343 gl_debug (DEBUG_MEDIA_SELECT, "page_size_name = \"%s\"", page_size_name);
344 gl_debug (DEBUG_MEDIA_SELECT, "category_name = \"%s\"", category_name);
345 page_size_id = gl_paper_lookup_id_from_name (page_size_name);
346 category_id = gl_category_lookup_id_from_name (category_name);
347 gl_debug (DEBUG_MEDIA_SELECT, "page_size_id = \"%s\"", page_size_id);
348 gl_debug (DEBUG_MEDIA_SELECT, "category_id = \"%s\"", category_id);
349 template_names = gl_template_get_name_list (page_size_id, category_id);
350 selection = gtk_tree_view_get_selection (GTK_TREE_VIEW (media_select->priv->template_treeview));
351 g_signal_handlers_block_by_func (G_OBJECT (selection),
352 template_selection_changed_cb,
354 load_list (media_select->priv->template_store, selection, template_names);
355 g_signal_handlers_unblock_by_func (G_OBJECT (selection),
356 template_selection_changed_cb,
358 gl_template_free_name_list (template_names);
359 g_free (page_size_id);
361 /* Emit our "changed" signal */
362 g_signal_emit (G_OBJECT (user_data),
363 wdgt_media_select_signals[CHANGED], 0);
365 g_free (page_size_name);
367 gl_debug (DEBUG_MEDIA_SELECT, "END");
370 /*--------------------------------------------------------------------------*/
371 /* PRIVATE. modify widget due to change in selection */
372 /*--------------------------------------------------------------------------*/
374 template_selection_changed_cb (GtkTreeSelection *selection,
377 glWdgtMediaSelect *media_select = GL_WDGT_MEDIA_SELECT (user_data);
379 gl_debug (DEBUG_MEDIA_SELECT, "START");
381 /* Emit our "changed" signal */
382 g_signal_emit (G_OBJECT (user_data),
383 wdgt_media_select_signals[CHANGED], 0);
385 gl_debug (DEBUG_MEDIA_SELECT, "END");
388 /****************************************************************************/
389 /* query selected label template name. */
390 /****************************************************************************/
392 gl_wdgt_media_select_get_name (glWdgtMediaSelect *media_select)
394 GtkTreeSelection *selection;
399 gl_debug (DEBUG_MEDIA_SELECT, "START");
400 selection = gtk_tree_view_get_selection (GTK_TREE_VIEW (media_select->priv->template_treeview));
401 if (gtk_tree_selection_get_mode (selection) == GTK_SELECTION_NONE)
407 gtk_tree_selection_get_selected (selection, &model, &iter);
408 gtk_tree_model_get (model, &iter, NAME_COLUMN, &name, -1);
411 gl_debug (DEBUG_MEDIA_SELECT, "END");
415 /****************************************************************************/
416 /* set selected label template name. */
417 /****************************************************************************/
419 gl_wdgt_media_select_set_name (glWdgtMediaSelect *media_select,
422 GtkTreeSelection *selection;
429 gl_debug (DEBUG_MEDIA_SELECT, "START");
431 selection = gtk_tree_view_get_selection (GTK_TREE_VIEW (media_select->priv->template_treeview));
432 g_return_if_fail (GTK_IS_TREE_SELECTION (selection));
434 model = GTK_TREE_MODEL (media_select->priv->template_store);
436 for ( flag = gtk_tree_model_get_iter_first (model, &iter);
438 flag = gtk_tree_model_iter_next(model, &iter) )
440 gtk_tree_model_get (model, &iter, NAME_COLUMN, &name_i, -1);
441 if (strcasecmp(name, name_i) == 0)
443 gtk_tree_selection_select_iter (selection, &iter);
444 path = gtk_tree_model_get_path (model, &iter);
445 gtk_tree_view_scroll_to_cell (GTK_TREE_VIEW (media_select->priv->template_treeview),
449 gtk_tree_path_free (path);
454 gl_debug (DEBUG_MEDIA_SELECT, "END");
457 /****************************************************************************/
458 /* query current filter parameters. */
459 /****************************************************************************/
461 gl_wdgt_media_select_get_filter_parameters (glWdgtMediaSelect *media_select,
462 gchar **page_size_id,
465 gchar *page_size_name, *category_name;
467 gl_debug (DEBUG_MEDIA_SELECT, "");
469 g_free (*page_size_id);
470 g_free (*category_id);
473 gtk_combo_box_get_active_text (GTK_COMBO_BOX (media_select->priv->page_size_combo));
475 *page_size_id = gl_paper_lookup_id_from_name (page_size_name);
478 gtk_combo_box_get_active_text (GTK_COMBO_BOX (media_select->priv->category_combo));
480 *category_id = gl_category_lookup_id_from_name (category_name);
482 g_free (page_size_name);
483 g_free (category_name);
486 /****************************************************************************/
487 /* set filter parameters. */
488 /****************************************************************************/
490 gl_wdgt_media_select_set_filter_parameters (glWdgtMediaSelect *media_select,
491 const gchar *page_size_id,
492 const gchar *category_id)
494 gchar *page_size_name;
495 gchar *category_name;
497 gl_debug (DEBUG_MEDIA_SELECT, "START");
499 page_size_name = gl_paper_lookup_name_from_id (page_size_id);
500 if (page_size_name == NULL)
502 page_size_name = g_strdup (_("Any"));
505 gl_util_combo_box_set_active_text (GTK_COMBO_BOX (media_select->priv->page_size_combo),
508 category_name = gl_category_lookup_name_from_id (category_id);
509 if (category_name == NULL)
511 category_name = g_strdup (_("Any"));
514 gl_util_combo_box_set_active_text (GTK_COMBO_BOX (media_select->priv->category_combo),
516 g_free (page_size_name);
517 g_free (category_name);
519 gl_debug (DEBUG_MEDIA_SELECT, "END");
522 /*--------------------------------------------------------------------------*/
523 /* PRIVATE. Get a description of the layout and number of labels. */
524 /*--------------------------------------------------------------------------*/
526 get_layout_desc (const glTemplate *template)
528 const glTemplateLabelType *label_type;
530 glTemplateLayout *layout;
533 label_type = gl_template_get_first_label_type (template);
535 n_labels = gl_template_get_n_labels (label_type);
537 string = g_strdup_printf (_("%d per sheet"), n_labels);
542 /*--------------------------------------------------------------------------*/
543 /* PRIVATE. Get label size description. */
544 /*--------------------------------------------------------------------------*/
546 get_label_size_desc (const glTemplate *template)
549 const gchar *units_string;
550 gdouble units_per_point;
551 const glTemplateLabelType *label_type;
552 gchar *string = NULL;
554 units = gl_prefs_get_units ();
555 units_string = gl_prefs_get_units_string ();
556 units_per_point = gl_prefs_get_units_per_point ();
558 label_type = gl_template_get_first_label_type (template);
560 switch (label_type->shape) {
561 case GL_TEMPLATE_SHAPE_RECT:
562 if ( units == GL_UNITS_INCH ) {
565 xstr = gl_util_fraction (label_type->size.rect.w*units_per_point);
566 ystr = gl_util_fraction (label_type->size.rect.h*units_per_point);
567 string = g_strdup_printf (_("%s x %s %s"),
568 xstr, ystr, units_string);
572 string = g_strdup_printf (_("%.5g x %.5g %s"),
573 label_type->size.rect.w*units_per_point,
574 label_type->size.rect.h*units_per_point,
578 case GL_TEMPLATE_SHAPE_ROUND:
579 if ( units == GL_UNITS_INCH ) {
582 dstr = gl_util_fraction (2.0*label_type->size.round.r*units_per_point);
583 string = g_strdup_printf (_("%s %s diameter"),
587 string = g_strdup_printf (_("%.5g %s diameter"),
588 2.0*label_type->size.round.r*units_per_point,
592 case GL_TEMPLATE_SHAPE_CD:
593 if ( units == GL_UNITS_INCH ) {
596 dstr = gl_util_fraction (2.0*label_type->size.cd.r1*units_per_point);
597 string = g_strdup_printf (_("%s %s diameter"),
601 string = g_strdup_printf (_("%.5g %s diameter"),
602 2.0*label_type->size.cd.r1*units_per_point,
613 /*--------------------------------------------------------------------------*/
614 /* PRIVATE. Load list store from template name list. */
615 /*--------------------------------------------------------------------------*/
617 load_list (GtkListStore *store,
618 GtkTreeSelection *selection,
623 glTemplate *template;
629 gl_debug (DEBUG_MEDIA_SELECT, "START");
631 gtk_list_store_clear (store);
636 for ( p=list; p!=NULL; p=p->next )
639 gl_debug (DEBUG_MEDIA_SELECT, "p->data = \"%s\"", p->data);
641 template = gl_template_from_name (p->data);
643 pixbuf = gl_mini_preview_pixbuf_new (template, 64, 64);
645 size = get_label_size_desc (template);
646 layout = get_layout_desc (template);
647 description = g_strdup_printf ("<b>%s</b>\n%s\n%s",
654 gl_template_free (template);
656 gtk_list_store_append (store, &iter);
657 gtk_list_store_set (store, &iter,
658 NAME_COLUMN, p->data,
659 PREVIEW_COLUMN, pixbuf,
660 DESCRIPTION_COLUMN, description,
663 g_object_unref (G_OBJECT (pixbuf));
664 g_free (description);
667 gtk_tree_selection_set_mode (selection, GTK_SELECTION_BROWSE);
668 gtk_tree_model_get_iter_first (GTK_TREE_MODEL (store), &iter);
669 gtk_tree_selection_select_iter (selection, &iter);
674 gchar *text = g_strdup_printf ("<span weight=\"bold\" size=\"larger\">%s</span>\n%s",
676 _("Try selecting a different page size or category."));
677 gtk_list_store_append (store, &iter);
678 gtk_list_store_set (store, &iter,
679 NAME_COLUMN, "empty",
680 PREVIEW_COLUMN_STOCK, GTK_STOCK_DIALOG_WARNING,
681 PREVIEW_COLUMN_STOCK_SIZE, GTK_ICON_SIZE_DIALOG,
682 DESCRIPTION_COLUMN, text,
686 gtk_tree_selection_set_mode (selection, GTK_SELECTION_NONE);
690 gl_debug (DEBUG_MEDIA_SELECT, "END");