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 {
66 GtkWidget *page_size_combo;
67 GtkWidget *category_combo;
69 GtkWidget *template_treeview;
70 GtkListStore *template_store;
78 typedef void (*glWdgtMediaSelectSignal) (GObject * object, gpointer data);
80 /*===========================================*/
82 /*===========================================*/
84 static gint wdgt_media_select_signals[LAST_SIGNAL] = { 0 };
86 /*===========================================*/
87 /* Local function prototypes */
88 /*===========================================*/
90 static void gl_wdgt_media_select_finalize (GObject *object);
92 static void gl_wdgt_media_select_construct (glWdgtMediaSelect *media_select);
94 static void filter_changed_cb (GtkComboBox *combo,
96 static void template_selection_changed_cb (GtkTreeSelection *selection,
99 static gchar *get_layout_desc (const glTemplate *template);
100 static gchar *get_label_size_desc (const glTemplate *template);
101 static void load_list (GtkListStore *store,
102 GtkTreeSelection *selection,
105 /****************************************************************************/
106 /* Boilerplate Object stuff. */
107 /****************************************************************************/
108 G_DEFINE_TYPE (glWdgtMediaSelect, gl_wdgt_media_select, GTK_TYPE_VBOX);
112 gl_wdgt_media_select_class_init (glWdgtMediaSelectClass *class)
114 GObjectClass *object_class = G_OBJECT_CLASS (class);
116 gl_debug (DEBUG_MEDIA_SELECT, "START");
118 gl_wdgt_media_select_parent_class = g_type_class_peek_parent (class);
120 object_class->finalize = gl_wdgt_media_select_finalize;
122 wdgt_media_select_signals[CHANGED] =
123 g_signal_new ("changed",
124 G_OBJECT_CLASS_TYPE(object_class),
126 G_STRUCT_OFFSET (glWdgtMediaSelectClass, changed),
128 gl_marshal_VOID__VOID,
131 gl_debug (DEBUG_MEDIA_SELECT, "END");
135 gl_wdgt_media_select_init (glWdgtMediaSelect *media_select)
137 gl_debug (DEBUG_MEDIA_SELECT, "START");
139 media_select->priv = g_new0 (glWdgtMediaSelectPrivate, 1);
141 gl_debug (DEBUG_MEDIA_SELECT, "END");
145 gl_wdgt_media_select_finalize (GObject *object)
147 glWdgtMediaSelect *media_select = GL_WDGT_MEDIA_SELECT (object);
149 gl_debug (DEBUG_MEDIA_SELECT, "START");
151 g_return_if_fail (object != NULL);
152 g_return_if_fail (GL_IS_WDGT_MEDIA_SELECT (object));
154 g_object_unref (media_select->priv->template_store);
155 g_free (media_select->priv);
157 G_OBJECT_CLASS (gl_wdgt_media_select_parent_class)->finalize (object);
159 gl_debug (DEBUG_MEDIA_SELECT, "END");
163 gl_wdgt_media_select_new (void)
165 glWdgtMediaSelect *media_select;
167 gl_debug (DEBUG_MEDIA_SELECT, "START");
169 media_select = g_object_new (gl_wdgt_media_select_get_type (), NULL);
171 gl_wdgt_media_select_construct (media_select);
173 gl_debug (DEBUG_MEDIA_SELECT, "END");
175 return GTK_WIDGET (media_select);
178 /*--------------------------------------------------------------------------*/
179 /* PRIVATE. Construct composite widget. */
180 /*--------------------------------------------------------------------------*/
182 gl_wdgt_media_select_construct (glWdgtMediaSelect *media_select)
186 GList *page_sizes = NULL;
187 GList *categories = NULL;
188 GList *template_names = NULL;
189 const gchar *page_size_id;
190 gchar *page_size_name;
191 GtkCellRenderer *renderer;
192 GtkTreeViewColumn *column;
193 GtkTreeSelection *selection;
195 gl_debug (DEBUG_MEDIA_SELECT, "START");
197 g_return_if_fail (GL_IS_WDGT_MEDIA_SELECT (media_select));
198 g_return_if_fail (media_select->priv != NULL);
200 gui = glade_xml_new (GLABELS_GLADE_DIR "wdgt-media-select.glade",
201 "wdgt_media_select_hbox", NULL);
204 g_critical ("Could not open wdgt-media-select.glade. gLabels may not be installed correctly!");
208 hbox = glade_xml_get_widget (gui, "wdgt_media_select_hbox");
209 gtk_container_add (GTK_CONTAINER (media_select), hbox);
211 media_select->priv->page_size_combo =
212 glade_xml_get_widget (gui, "page_size_combo");
213 media_select->priv->category_combo =
214 glade_xml_get_widget (gui, "category_combo");
215 media_select->priv->template_treeview =
216 glade_xml_get_widget (gui, "template_treeview");
218 g_object_unref (gui);
220 page_size_id = gl_prefs_get_page_size ();
221 page_size_name = gl_paper_lookup_name_from_id (page_size_id);
223 /* Page size selection control */
224 gl_util_combo_box_add_text_model (GTK_COMBO_BOX (media_select->priv->page_size_combo));
225 page_sizes = gl_paper_get_name_list ();
226 page_sizes = g_list_prepend (page_sizes, g_strdup (_("Any")));
227 gl_util_combo_box_set_strings (GTK_COMBO_BOX (media_select->priv->page_size_combo), page_sizes);
228 gl_paper_free_name_list (page_sizes);
229 gl_util_combo_box_set_active_text (GTK_COMBO_BOX (media_select->priv->page_size_combo),
232 /* Category selection control */
233 gl_util_combo_box_add_text_model (GTK_COMBO_BOX (media_select->priv->category_combo));
234 categories = gl_category_get_name_list ();
235 categories = g_list_prepend (categories, g_strdup (_("Any")));
236 gl_util_combo_box_set_strings (GTK_COMBO_BOX (media_select->priv->category_combo), categories);
237 gl_util_combo_box_set_active_text (GTK_COMBO_BOX (media_select->priv->category_combo),
239 gl_category_free_name_list (categories);
241 /* Actual selection control */
242 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);
243 gtk_tree_view_set_model (GTK_TREE_VIEW (media_select->priv->template_treeview),
244 GTK_TREE_MODEL (media_select->priv->template_store));
245 renderer = gtk_cell_renderer_pixbuf_new ();
246 column = gtk_tree_view_column_new_with_attributes ("", renderer,
247 "pixbuf", PREVIEW_COLUMN,
248 "stock-id", PREVIEW_COLUMN_STOCK,
249 "stock-size", PREVIEW_COLUMN_STOCK_SIZE,
251 gtk_tree_view_column_set_sizing (column, GTK_TREE_VIEW_COLUMN_AUTOSIZE);
252 gtk_tree_view_append_column (GTK_TREE_VIEW (media_select->priv->template_treeview), column);
253 renderer = gtk_cell_renderer_text_new ();
254 column = gtk_tree_view_column_new_with_attributes ("", renderer,
255 "markup", DESCRIPTION_COLUMN,
257 gtk_tree_view_column_set_sizing (column, GTK_TREE_VIEW_COLUMN_AUTOSIZE);
258 gtk_tree_view_append_column (GTK_TREE_VIEW (media_select->priv->template_treeview), column);
259 selection = gtk_tree_view_get_selection (GTK_TREE_VIEW (media_select->priv->template_treeview));
260 template_names = gl_template_get_name_list (page_size_id, NULL);
261 load_list (media_select->priv->template_store, selection, template_names);
262 gl_template_free_name_list (template_names);
264 /* Connect signals to controls */
265 g_signal_connect (G_OBJECT (media_select->priv->page_size_combo), "changed",
266 G_CALLBACK (filter_changed_cb),
268 g_signal_connect (G_OBJECT (media_select->priv->category_combo), "changed",
269 G_CALLBACK (filter_changed_cb),
271 g_signal_connect (G_OBJECT (selection), "changed",
272 G_CALLBACK (template_selection_changed_cb),
275 g_free (page_size_name);
277 gl_debug (DEBUG_MEDIA_SELECT, "END");
280 /*--------------------------------------------------------------------------*/
281 /* PRIVATE. modify widget due to change in selection */
282 /*--------------------------------------------------------------------------*/
284 filter_changed_cb (GtkComboBox *combo,
287 glWdgtMediaSelect *media_select = GL_WDGT_MEDIA_SELECT (user_data);
288 gchar *page_size_name, *page_size_id;
289 gchar *category_name, *category_id;
290 GList *template_names;
291 GtkTreeSelection *selection;
293 gl_debug (DEBUG_MEDIA_SELECT, "START");
296 /* Update template selections for new page size */
297 page_size_name = gtk_combo_box_get_active_text (GTK_COMBO_BOX (media_select->priv->page_size_combo));
298 category_name = gtk_combo_box_get_active_text (GTK_COMBO_BOX (media_select->priv->category_combo));
299 if ( page_size_name && strlen(page_size_name) &&
300 category_name && strlen(category_name) )
302 gl_debug (DEBUG_MEDIA_SELECT, "page_size_name = \"%s\"", page_size_name);
303 gl_debug (DEBUG_MEDIA_SELECT, "category_name = \"%s\"", category_name);
304 page_size_id = gl_paper_lookup_id_from_name (page_size_name);
305 category_id = gl_category_lookup_id_from_name (category_name);
306 gl_debug (DEBUG_MEDIA_SELECT, "page_size_id = \"%s\"", page_size_id);
307 gl_debug (DEBUG_MEDIA_SELECT, "category_id = \"%s\"", category_id);
308 template_names = gl_template_get_name_list (page_size_id, category_id);
309 selection = gtk_tree_view_get_selection (GTK_TREE_VIEW (media_select->priv->template_treeview));
310 g_signal_handlers_block_by_func (G_OBJECT (selection),
311 template_selection_changed_cb,
313 load_list (media_select->priv->template_store, selection, template_names);
314 g_signal_handlers_unblock_by_func (G_OBJECT (selection),
315 template_selection_changed_cb,
317 gl_template_free_name_list (template_names);
318 g_free (page_size_id);
320 /* Emit our "changed" signal */
321 g_signal_emit (G_OBJECT (user_data),
322 wdgt_media_select_signals[CHANGED], 0);
324 g_free (page_size_name);
326 gl_debug (DEBUG_MEDIA_SELECT, "END");
329 /*--------------------------------------------------------------------------*/
330 /* PRIVATE. modify widget due to change in selection */
331 /*--------------------------------------------------------------------------*/
333 template_selection_changed_cb (GtkTreeSelection *selection,
336 gl_debug (DEBUG_MEDIA_SELECT, "START");
338 /* Emit our "changed" signal */
339 g_signal_emit (G_OBJECT (user_data),
340 wdgt_media_select_signals[CHANGED], 0);
342 gl_debug (DEBUG_MEDIA_SELECT, "END");
345 /****************************************************************************/
346 /* query selected label template name. */
347 /****************************************************************************/
349 gl_wdgt_media_select_get_name (glWdgtMediaSelect *media_select)
351 GtkTreeSelection *selection;
356 gl_debug (DEBUG_MEDIA_SELECT, "START");
357 selection = gtk_tree_view_get_selection (GTK_TREE_VIEW (media_select->priv->template_treeview));
358 if (gtk_tree_selection_get_mode (selection) == GTK_SELECTION_NONE)
364 gtk_tree_selection_get_selected (selection, &model, &iter);
365 gtk_tree_model_get (model, &iter, NAME_COLUMN, &name, -1);
368 gl_debug (DEBUG_MEDIA_SELECT, "END");
372 /****************************************************************************/
373 /* set selected label template name. */
374 /****************************************************************************/
376 gl_wdgt_media_select_set_name (glWdgtMediaSelect *media_select,
379 GtkTreeSelection *selection;
386 gl_debug (DEBUG_MEDIA_SELECT, "START");
388 selection = gtk_tree_view_get_selection (GTK_TREE_VIEW (media_select->priv->template_treeview));
389 g_return_if_fail (GTK_IS_TREE_SELECTION (selection));
391 model = GTK_TREE_MODEL (media_select->priv->template_store);
393 for ( flag = gtk_tree_model_get_iter_first (model, &iter);
395 flag = gtk_tree_model_iter_next(model, &iter) )
397 gtk_tree_model_get (model, &iter, NAME_COLUMN, &name_i, -1);
398 if (strcasecmp(name, name_i) == 0)
400 gtk_tree_selection_select_iter (selection, &iter);
401 path = gtk_tree_model_get_path (model, &iter);
402 gtk_tree_view_scroll_to_cell (GTK_TREE_VIEW (media_select->priv->template_treeview),
406 gtk_tree_path_free (path);
411 gl_debug (DEBUG_MEDIA_SELECT, "END");
414 /****************************************************************************/
415 /* query current filter parameters. */
416 /****************************************************************************/
418 gl_wdgt_media_select_get_filter_parameters (glWdgtMediaSelect *media_select,
419 gchar **page_size_id,
422 gchar *page_size_name, *category_name;
424 gl_debug (DEBUG_MEDIA_SELECT, "");
426 g_free (*page_size_id);
427 g_free (*category_id);
430 gtk_combo_box_get_active_text (GTK_COMBO_BOX (media_select->priv->page_size_combo));
432 *page_size_id = gl_paper_lookup_id_from_name (page_size_name);
435 gtk_combo_box_get_active_text (GTK_COMBO_BOX (media_select->priv->category_combo));
437 *category_id = gl_category_lookup_id_from_name (category_name);
439 g_free (page_size_name);
440 g_free (category_name);
443 /****************************************************************************/
444 /* set filter parameters. */
445 /****************************************************************************/
447 gl_wdgt_media_select_set_filter_parameters (glWdgtMediaSelect *media_select,
448 const gchar *page_size_id,
449 const gchar *category_id)
451 gchar *page_size_name;
452 gchar *category_name;
454 gl_debug (DEBUG_MEDIA_SELECT, "START");
456 page_size_name = gl_paper_lookup_name_from_id (page_size_id);
457 if (page_size_name == NULL)
459 page_size_name = g_strdup (_("Any"));
462 gl_util_combo_box_set_active_text (GTK_COMBO_BOX (media_select->priv->page_size_combo),
465 category_name = gl_category_lookup_name_from_id (category_id);
466 if (category_name == NULL)
468 category_name = g_strdup (_("Any"));
471 gl_util_combo_box_set_active_text (GTK_COMBO_BOX (media_select->priv->category_combo),
473 g_free (page_size_name);
474 g_free (category_name);
476 gl_debug (DEBUG_MEDIA_SELECT, "END");
479 /*--------------------------------------------------------------------------*/
480 /* PRIVATE. Get a description of the layout and number of labels. */
481 /*--------------------------------------------------------------------------*/
483 get_layout_desc (const glTemplate *template)
485 const glTemplateLabelType *label_type;
489 label_type = gl_template_get_first_label_type (template);
491 n_labels = gl_template_get_n_labels (label_type);
493 string = g_strdup_printf (_("%d per sheet"), n_labels);
498 /*--------------------------------------------------------------------------*/
499 /* PRIVATE. Get label size description. */
500 /*--------------------------------------------------------------------------*/
502 get_label_size_desc (const glTemplate *template)
505 const gchar *units_string;
506 gdouble units_per_point;
507 const glTemplateLabelType *label_type;
508 gchar *string = NULL;
510 units = gl_prefs_get_units ();
511 units_string = gl_prefs_get_units_string ();
512 units_per_point = gl_prefs_get_units_per_point ();
514 label_type = gl_template_get_first_label_type (template);
516 switch (label_type->shape) {
517 case GL_TEMPLATE_SHAPE_RECT:
518 if ( units == GL_UNITS_INCH ) {
521 xstr = gl_util_fraction (label_type->size.rect.w*units_per_point);
522 ystr = gl_util_fraction (label_type->size.rect.h*units_per_point);
523 string = g_strdup_printf (_("%s x %s %s"),
524 xstr, ystr, units_string);
528 string = g_strdup_printf (_("%.5g x %.5g %s"),
529 label_type->size.rect.w*units_per_point,
530 label_type->size.rect.h*units_per_point,
534 case GL_TEMPLATE_SHAPE_ROUND:
535 if ( units == GL_UNITS_INCH ) {
538 dstr = gl_util_fraction (2.0*label_type->size.round.r*units_per_point);
539 string = g_strdup_printf (_("%s %s diameter"),
543 string = g_strdup_printf (_("%.5g %s diameter"),
544 2.0*label_type->size.round.r*units_per_point,
548 case GL_TEMPLATE_SHAPE_CD:
549 if ( units == GL_UNITS_INCH ) {
552 dstr = gl_util_fraction (2.0*label_type->size.cd.r1*units_per_point);
553 string = g_strdup_printf (_("%s %s diameter"),
557 string = g_strdup_printf (_("%.5g %s diameter"),
558 2.0*label_type->size.cd.r1*units_per_point,
569 /*--------------------------------------------------------------------------*/
570 /* PRIVATE. Load list store from template name list. */
571 /*--------------------------------------------------------------------------*/
573 load_list (GtkListStore *store,
574 GtkTreeSelection *selection,
579 glTemplate *template;
585 gl_debug (DEBUG_MEDIA_SELECT, "START");
587 gtk_list_store_clear (store);
592 for ( p=list; p!=NULL; p=p->next )
595 gl_debug (DEBUG_MEDIA_SELECT, "p->data = \"%s\"", p->data);
597 template = gl_template_from_name (p->data);
599 pixbuf = gl_mini_preview_pixbuf_new (template, 72, 72);
601 size = get_label_size_desc (template);
602 layout = get_layout_desc (template);
603 description = g_strdup_printf ("<b>%s</b>\n%s\n%s",
610 gl_template_free (template);
612 gtk_list_store_append (store, &iter);
613 gtk_list_store_set (store, &iter,
614 NAME_COLUMN, p->data,
615 PREVIEW_COLUMN, pixbuf,
616 DESCRIPTION_COLUMN, description,
619 g_object_unref (G_OBJECT (pixbuf));
620 g_free (description);
623 gtk_tree_selection_set_mode (selection, GTK_SELECTION_BROWSE);
624 gtk_tree_model_get_iter_first (GTK_TREE_MODEL (store), &iter);
625 gtk_tree_selection_select_iter (selection, &iter);
630 gchar *text = g_strdup_printf ("<span weight=\"bold\" size=\"larger\">%s</span>\n%s",
632 _("Try selecting a different page size or category."));
633 gtk_list_store_append (store, &iter);
634 gtk_list_store_set (store, &iter,
635 NAME_COLUMN, "empty",
636 PREVIEW_COLUMN_STOCK, GTK_STOCK_DIALOG_WARNING,
637 PREVIEW_COLUMN_STOCK_SIZE, GTK_ICON_SIZE_DIALOG,
638 DESCRIPTION_COLUMN, text,
642 gtk_tree_selection_set_mode (selection, GTK_SELECTION_NONE);
646 gl_debug (DEBUG_MEDIA_SELECT, "END");