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-cache.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;
72 /* Prevent recursion */
73 gboolean stop_signals;
81 typedef void (*glWdgtMediaSelectSignal) (GObject * object, gpointer data);
83 /*===========================================*/
85 /*===========================================*/
87 static gint wdgt_media_select_signals[LAST_SIGNAL] = { 0 };
89 /*===========================================*/
90 /* Local function prototypes */
91 /*===========================================*/
93 static void gl_wdgt_media_select_finalize (GObject *object);
95 static void gl_wdgt_media_select_construct (glWdgtMediaSelect *media_select);
97 static void filter_changed_cb (GtkComboBox *combo,
99 static void template_selection_changed_cb (GtkTreeSelection *selection,
102 static gchar *get_layout_desc (const glTemplate *template);
103 static gchar *get_label_size_desc (const glTemplate *template);
104 static void load_list (GtkListStore *store,
105 GtkTreeSelection *selection,
108 /****************************************************************************/
109 /* Boilerplate Object stuff. */
110 /****************************************************************************/
111 G_DEFINE_TYPE (glWdgtMediaSelect, gl_wdgt_media_select, GTK_TYPE_VBOX);
115 gl_wdgt_media_select_class_init (glWdgtMediaSelectClass *class)
117 GObjectClass *object_class = G_OBJECT_CLASS (class);
119 gl_debug (DEBUG_MEDIA_SELECT, "START");
121 gl_wdgt_media_select_parent_class = g_type_class_peek_parent (class);
123 object_class->finalize = gl_wdgt_media_select_finalize;
125 wdgt_media_select_signals[CHANGED] =
126 g_signal_new ("changed",
127 G_OBJECT_CLASS_TYPE(object_class),
129 G_STRUCT_OFFSET (glWdgtMediaSelectClass, changed),
131 gl_marshal_VOID__VOID,
134 gl_debug (DEBUG_MEDIA_SELECT, "END");
138 gl_wdgt_media_select_init (glWdgtMediaSelect *media_select)
140 gl_debug (DEBUG_MEDIA_SELECT, "START");
142 media_select->priv = g_new0 (glWdgtMediaSelectPrivate, 1);
144 gl_debug (DEBUG_MEDIA_SELECT, "END");
148 gl_wdgt_media_select_finalize (GObject *object)
150 glWdgtMediaSelect *media_select = GL_WDGT_MEDIA_SELECT (object);
152 gl_debug (DEBUG_MEDIA_SELECT, "START");
154 g_return_if_fail (object != NULL);
155 g_return_if_fail (GL_IS_WDGT_MEDIA_SELECT (object));
157 g_object_unref (media_select->priv->template_store);
158 g_free (media_select->priv);
160 G_OBJECT_CLASS (gl_wdgt_media_select_parent_class)->finalize (object);
162 gl_debug (DEBUG_MEDIA_SELECT, "END");
166 gl_wdgt_media_select_new (void)
168 glWdgtMediaSelect *media_select;
170 gl_debug (DEBUG_MEDIA_SELECT, "START");
172 media_select = g_object_new (gl_wdgt_media_select_get_type (), NULL);
174 gl_wdgt_media_select_construct (media_select);
176 gl_debug (DEBUG_MEDIA_SELECT, "END");
178 return GTK_WIDGET (media_select);
181 /*--------------------------------------------------------------------------*/
182 /* PRIVATE. Construct composite widget. */
183 /*--------------------------------------------------------------------------*/
185 gl_wdgt_media_select_construct (glWdgtMediaSelect *media_select)
189 GList *page_sizes = NULL;
190 GList *categories = NULL;
191 GList *template_names = NULL;
192 const gchar *page_size_id;
193 gchar *page_size_name;
194 GtkCellRenderer *renderer;
195 GtkTreeViewColumn *column;
196 GtkTreeSelection *selection;
198 gl_debug (DEBUG_MEDIA_SELECT, "START");
200 g_return_if_fail (GL_IS_WDGT_MEDIA_SELECT (media_select));
201 g_return_if_fail (media_select->priv != NULL);
203 gui = glade_xml_new (GLABELS_GLADE_DIR "wdgt-media-select.glade",
204 "wdgt_media_select_hbox", NULL);
207 g_critical ("Could not open wdgt-media-select.glade. gLabels may not be installed correctly!");
211 hbox = glade_xml_get_widget (gui, "wdgt_media_select_hbox");
212 gtk_container_add (GTK_CONTAINER (media_select), hbox);
214 media_select->priv->page_size_combo =
215 glade_xml_get_widget (gui, "page_size_combo");
216 media_select->priv->category_combo =
217 glade_xml_get_widget (gui, "category_combo");
218 media_select->priv->template_treeview =
219 glade_xml_get_widget (gui, "template_treeview");
221 g_object_unref (gui);
223 page_size_id = gl_prefs_get_page_size ();
224 page_size_name = gl_paper_lookup_name_from_id (page_size_id);
226 /* Page size selection control */
227 gl_util_combo_box_add_text_model (GTK_COMBO_BOX (media_select->priv->page_size_combo));
228 page_sizes = gl_paper_get_name_list ();
229 page_sizes = g_list_prepend (page_sizes, g_strdup (_("Any")));
230 gl_util_combo_box_set_strings (GTK_COMBO_BOX (media_select->priv->page_size_combo), page_sizes);
231 gl_paper_free_name_list (page_sizes);
232 gl_util_combo_box_set_active_text (GTK_COMBO_BOX (media_select->priv->page_size_combo),
235 /* Category selection control */
236 gl_util_combo_box_add_text_model (GTK_COMBO_BOX (media_select->priv->category_combo));
237 categories = gl_category_get_name_list ();
238 categories = g_list_prepend (categories, g_strdup (_("Any")));
239 gl_util_combo_box_set_strings (GTK_COMBO_BOX (media_select->priv->category_combo), categories);
240 gl_util_combo_box_set_active_text (GTK_COMBO_BOX (media_select->priv->category_combo),
242 gl_category_free_name_list (categories);
244 /* Actual selection control */
245 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);
246 gtk_tree_view_set_model (GTK_TREE_VIEW (media_select->priv->template_treeview),
247 GTK_TREE_MODEL (media_select->priv->template_store));
248 renderer = gtk_cell_renderer_pixbuf_new ();
249 column = gtk_tree_view_column_new_with_attributes ("", renderer,
250 "pixbuf", PREVIEW_COLUMN,
251 "stock-id", PREVIEW_COLUMN_STOCK,
252 "stock-size", PREVIEW_COLUMN_STOCK_SIZE,
254 gtk_tree_view_column_set_sizing (column, GTK_TREE_VIEW_COLUMN_AUTOSIZE);
255 gtk_tree_view_append_column (GTK_TREE_VIEW (media_select->priv->template_treeview), column);
256 renderer = gtk_cell_renderer_text_new ();
257 column = gtk_tree_view_column_new_with_attributes ("", renderer,
258 "markup", DESCRIPTION_COLUMN,
260 gtk_tree_view_column_set_sizing (column, GTK_TREE_VIEW_COLUMN_AUTOSIZE);
261 gtk_tree_view_append_column (GTK_TREE_VIEW (media_select->priv->template_treeview), column);
262 selection = gtk_tree_view_get_selection (GTK_TREE_VIEW (media_select->priv->template_treeview));
263 template_names = gl_template_get_name_list_all (page_size_id, NULL);
264 load_list (media_select->priv->template_store, selection, template_names);
265 gl_template_free_name_list (template_names);
267 /* Connect signals to controls */
268 g_signal_connect (G_OBJECT (media_select->priv->page_size_combo), "changed",
269 G_CALLBACK (filter_changed_cb),
271 g_signal_connect (G_OBJECT (media_select->priv->category_combo), "changed",
272 G_CALLBACK (filter_changed_cb),
274 g_signal_connect (G_OBJECT (selection), "changed",
275 G_CALLBACK (template_selection_changed_cb),
278 g_free (page_size_name);
280 gl_debug (DEBUG_MEDIA_SELECT, "END");
283 /*--------------------------------------------------------------------------*/
284 /* PRIVATE. modify widget due to change in selection */
285 /*--------------------------------------------------------------------------*/
287 filter_changed_cb (GtkComboBox *combo,
290 glWdgtMediaSelect *media_select = GL_WDGT_MEDIA_SELECT (user_data);
291 gchar *page_size_name, *page_size_id;
292 gchar *category_name, *category_id;
293 GList *template_names;
294 GtkTreeSelection *selection;
296 gl_debug (DEBUG_MEDIA_SELECT, "START");
299 media_select->priv->stop_signals = TRUE;
301 /* Update template selections for new page size */
302 page_size_name = gtk_combo_box_get_active_text (GTK_COMBO_BOX (media_select->priv->page_size_combo));
303 category_name = gtk_combo_box_get_active_text (GTK_COMBO_BOX (media_select->priv->category_combo));
304 if ( page_size_name && strlen(page_size_name) &&
305 category_name && strlen(category_name) )
307 gl_debug (DEBUG_MEDIA_SELECT, "page_size_name = \"%s\"", page_size_name);
308 gl_debug (DEBUG_MEDIA_SELECT, "category_name = \"%s\"", category_name);
309 page_size_id = gl_paper_lookup_id_from_name (page_size_name);
310 category_id = gl_category_lookup_id_from_name (category_name);
311 gl_debug (DEBUG_MEDIA_SELECT, "page_size_id = \"%s\"", page_size_id);
312 gl_debug (DEBUG_MEDIA_SELECT, "category_id = \"%s\"", category_id);
313 template_names = gl_template_get_name_list_all (page_size_id, category_id);
314 selection = gtk_tree_view_get_selection (GTK_TREE_VIEW (media_select->priv->template_treeview));
315 load_list (media_select->priv->template_store, selection, template_names);
316 gl_template_free_name_list (template_names);
317 g_free (page_size_id);
319 /* Emit our "changed" signal */
320 g_signal_emit (G_OBJECT (user_data),
321 wdgt_media_select_signals[CHANGED], 0);
323 g_free (page_size_name);
326 media_select->priv->stop_signals = FALSE;
328 gl_debug (DEBUG_MEDIA_SELECT, "END");
331 /*--------------------------------------------------------------------------*/
332 /* PRIVATE. modify widget due to change in selection */
333 /*--------------------------------------------------------------------------*/
335 template_selection_changed_cb (GtkTreeSelection *selection,
338 glWdgtMediaSelect *media_select = GL_WDGT_MEDIA_SELECT (user_data);
340 if (media_select->priv->stop_signals) return;
342 gl_debug (DEBUG_MEDIA_SELECT, "START");
344 /* Emit our "changed" signal */
345 g_signal_emit (G_OBJECT (user_data),
346 wdgt_media_select_signals[CHANGED], 0);
348 gl_debug (DEBUG_MEDIA_SELECT, "END");
351 /****************************************************************************/
352 /* query selected label template name. */
353 /****************************************************************************/
355 gl_wdgt_media_select_get_name (glWdgtMediaSelect *media_select)
357 GtkTreeSelection *selection;
362 gl_debug (DEBUG_MEDIA_SELECT, "START");
363 selection = gtk_tree_view_get_selection (GTK_TREE_VIEW (media_select->priv->template_treeview));
364 if (gtk_tree_selection_get_mode (selection) == GTK_SELECTION_NONE)
370 gtk_tree_selection_get_selected (selection, &model, &iter);
371 gtk_tree_model_get (model, &iter, NAME_COLUMN, &name, -1);
374 gl_debug (DEBUG_MEDIA_SELECT, "END");
378 /****************************************************************************/
379 /* set selected label template name. */
380 /****************************************************************************/
382 gl_wdgt_media_select_set_name (glWdgtMediaSelect *media_select,
385 GtkTreeSelection *selection;
392 gl_debug (DEBUG_MEDIA_SELECT, "START");
394 selection = gtk_tree_view_get_selection (GTK_TREE_VIEW (media_select->priv->template_treeview));
395 g_return_if_fail (GTK_IS_TREE_SELECTION (selection));
397 model = GTK_TREE_MODEL (media_select->priv->template_store);
399 for ( flag = gtk_tree_model_get_iter_first (model, &iter);
401 flag = gtk_tree_model_iter_next(model, &iter) )
403 gtk_tree_model_get (model, &iter, NAME_COLUMN, &name_i, -1);
404 if (strcasecmp(name, name_i) == 0)
406 gtk_tree_selection_select_iter (selection, &iter);
407 path = gtk_tree_model_get_path (model, &iter);
408 gtk_tree_view_scroll_to_cell (GTK_TREE_VIEW (media_select->priv->template_treeview),
412 gtk_tree_path_free (path);
417 gl_debug (DEBUG_MEDIA_SELECT, "END");
420 /****************************************************************************/
421 /* query current filter parameters. */
422 /****************************************************************************/
424 gl_wdgt_media_select_get_filter_parameters (glWdgtMediaSelect *media_select,
425 gchar **page_size_id,
428 gchar *page_size_name, *category_name;
430 gl_debug (DEBUG_MEDIA_SELECT, "");
432 g_free (*page_size_id);
433 g_free (*category_id);
436 gtk_combo_box_get_active_text (GTK_COMBO_BOX (media_select->priv->page_size_combo));
438 *page_size_id = gl_paper_lookup_id_from_name (page_size_name);
441 gtk_combo_box_get_active_text (GTK_COMBO_BOX (media_select->priv->category_combo));
443 *category_id = gl_category_lookup_id_from_name (category_name);
445 g_free (page_size_name);
446 g_free (category_name);
449 /****************************************************************************/
450 /* set filter parameters. */
451 /****************************************************************************/
453 gl_wdgt_media_select_set_filter_parameters (glWdgtMediaSelect *media_select,
454 const gchar *page_size_id,
455 const gchar *category_id)
457 gchar *page_size_name;
458 gchar *category_name;
460 gl_debug (DEBUG_MEDIA_SELECT, "START");
462 page_size_name = gl_paper_lookup_name_from_id (page_size_id);
463 if (page_size_name == NULL)
465 page_size_name = g_strdup (_("Any"));
468 gl_util_combo_box_set_active_text (GTK_COMBO_BOX (media_select->priv->page_size_combo),
471 category_name = gl_category_lookup_name_from_id (category_id);
472 if (category_name == NULL)
474 category_name = g_strdup (_("Any"));
477 gl_util_combo_box_set_active_text (GTK_COMBO_BOX (media_select->priv->category_combo),
479 g_free (page_size_name);
480 g_free (category_name);
482 gl_debug (DEBUG_MEDIA_SELECT, "END");
485 /*--------------------------------------------------------------------------*/
486 /* PRIVATE. Get a description of the layout and number of labels. */
487 /*--------------------------------------------------------------------------*/
489 get_layout_desc (const glTemplate *template)
491 const glTemplateLabelType *label_type;
495 label_type = gl_template_get_first_label_type (template);
497 n_labels = gl_template_get_n_labels (label_type);
499 string = g_strdup_printf (_("%d per sheet"), n_labels);
504 /*--------------------------------------------------------------------------*/
505 /* PRIVATE. Get label size description. */
506 /*--------------------------------------------------------------------------*/
508 get_label_size_desc (const glTemplate *template)
511 const gchar *units_string;
512 gdouble units_per_point;
513 const glTemplateLabelType *label_type;
514 gchar *string = NULL;
516 units = gl_prefs_get_units ();
517 units_string = gl_prefs_get_units_string ();
518 units_per_point = gl_prefs_get_units_per_point ();
520 label_type = gl_template_get_first_label_type (template);
522 switch (label_type->shape) {
523 case GL_TEMPLATE_SHAPE_RECT:
524 if ( units == GL_UNITS_INCH ) {
527 xstr = gl_util_fraction (label_type->size.rect.w*units_per_point);
528 ystr = gl_util_fraction (label_type->size.rect.h*units_per_point);
529 string = g_strdup_printf (_("%s x %s %s"),
530 xstr, ystr, units_string);
534 string = g_strdup_printf (_("%.5g x %.5g %s"),
535 label_type->size.rect.w*units_per_point,
536 label_type->size.rect.h*units_per_point,
540 case GL_TEMPLATE_SHAPE_ROUND:
541 if ( units == GL_UNITS_INCH ) {
544 dstr = gl_util_fraction (2.0*label_type->size.round.r*units_per_point);
545 string = g_strdup_printf (_("%s %s diameter"),
549 string = g_strdup_printf (_("%.5g %s diameter"),
550 2.0*label_type->size.round.r*units_per_point,
554 case GL_TEMPLATE_SHAPE_CD:
555 if ( units == GL_UNITS_INCH ) {
558 dstr = gl_util_fraction (2.0*label_type->size.cd.r1*units_per_point);
559 string = g_strdup_printf (_("%s %s diameter"),
563 string = g_strdup_printf (_("%.5g %s diameter"),
564 2.0*label_type->size.cd.r1*units_per_point,
575 /*--------------------------------------------------------------------------*/
576 /* PRIVATE. Load list store from template name list. */
577 /*--------------------------------------------------------------------------*/
579 load_list (GtkListStore *store,
580 GtkTreeSelection *selection,
585 glTemplate *template;
591 gl_debug (DEBUG_MEDIA_SELECT, "START");
593 gtk_list_store_clear (store);
598 for ( p=list; p!=NULL; p=p->next )
601 gl_debug (DEBUG_MEDIA_SELECT, "p->data = \"%s\"", p->data);
603 template = gl_template_from_name (p->data);
605 pixbuf = gl_mini_preview_pixbuf_cache_get_pixbuf (template->name);
607 size = get_label_size_desc (template);
608 layout = get_layout_desc (template);
609 description = g_strdup_printf ("<b>%s: %s</b>\n%s\n%s",
611 template->description,
617 gl_template_free (template);
619 gtk_list_store_append (store, &iter);
620 gtk_list_store_set (store, &iter,
621 NAME_COLUMN, p->data,
622 PREVIEW_COLUMN, pixbuf,
623 DESCRIPTION_COLUMN, description,
626 g_object_unref (G_OBJECT (pixbuf));
627 g_free (description);
630 gtk_tree_selection_set_mode (selection, GTK_SELECTION_BROWSE);
631 gtk_tree_model_get_iter_first (GTK_TREE_MODEL (store), &iter);
632 gtk_tree_selection_select_iter (selection, &iter);
637 gchar *text = g_strdup_printf ("<span weight=\"bold\" size=\"larger\">%s</span>\n%s",
639 _("Try selecting a different page size or category."));
640 gtk_list_store_append (store, &iter);
641 gtk_list_store_set (store, &iter,
642 NAME_COLUMN, "empty",
643 PREVIEW_COLUMN_STOCK, GTK_STOCK_DIALOG_WARNING,
644 PREVIEW_COLUMN_STOCK_SIZE, GTK_ICON_SIZE_DIALOG,
645 DESCRIPTION_COLUMN, text,
649 gtk_tree_selection_set_mode (selection, GTK_SELECTION_NONE);
653 gl_debug (DEBUG_MEDIA_SELECT, "END");