Almost there to pass distcheck.
[mmediamanager.git] / libmmanager-gtk / mm-gtk-filter-builder.c
blobee3bfbb780c4d9637e62dfdc52cbf23e0ef137f7
1 /* MManager - a Desktop wide manager for multimedia applications.
3 * Copyright (C) 2008 Cosimo Cecchi <cosimoc@gnome.org>
5 * This library is free software; you can redistribute it and/or
6 * modify it under the terms of the GNU Lesser General Public
7 * License as published by the Free Software Foundation; either
8 * version 2 of the License, or (at your option) any later version.
10 * This library is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13 * Lesser General Public License for more details.
15 * You should have received a copy of the GNU Lesser General Public
16 * License along with this library; if not, write to the
17 * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
18 * Boston, MA 02111-1307, USA.
21 #include "mm-gtk-filter-builder.h"
22 #include "mm-gtk-attribute-store.h"
24 #include "libmmanager/mm-attribute-manager.h"
25 #include "libmmanager/mm-attribute-base-manager.h"
26 #include "libmmanager/mm-types.h"
27 #include "libmmanager/mm-string-utils.h"
28 #include "libmmanager/mm-filter-param.h"
29 #include "libmmanager/mm-attribute.h"
31 #include <gtk/gtk.h>
32 #include <glib.h>
33 #include <glib/gi18n.h>
35 G_DEFINE_TYPE (MMGtkFilterBuilder, mm_gtk_filter_builder, GTK_TYPE_VBOX);
37 #define MM_GTK_FILTER_BUILDER_GET_PRIVATE(o) \
38 (G_TYPE_INSTANCE_GET_PRIVATE ((o), MM_GTK_TYPE_FILTER_BUILDER, MMGtkFilterBuilderPrivate))
40 struct _MMGtkFilterBuilderPrivate {
41 GtkListStore *filter_store;
42 MMGtkAttributeStore *attribute_store;
43 GtkWidget *filter_view;
45 GHashTable *attr_managers;
47 GtkWidget *cat_combo;
48 GtkWidget *attr_combo;
49 GtkWidget *logic_combo;
50 GtkWidget *value_entry;
53 static const char * logic_strs [] = {
54 N_("equal"),
55 N_("greather than"),
56 N_("less than"),
57 N_("greater or equal than"),
58 N_("less or equal than"),
61 static void
62 mm_gtk_filter_builder_finalize (GObject *obj)
64 MMGtkFilterBuilder *self = MM_GTK_FILTER_BUILDER (obj);
65 g_hash_table_destroy (self->details->attr_managers);
67 G_OBJECT_CLASS (mm_gtk_filter_builder_parent_class)->finalize (obj);
70 static void
71 mm_gtk_filter_builder_class_init (MMGtkFilterBuilderClass *klass)
73 GObjectClass *oclass = G_OBJECT_CLASS (klass);
75 oclass->finalize = mm_gtk_filter_builder_finalize;
77 g_type_class_add_private (klass, sizeof (MMGtkFilterBuilderPrivate));
80 static void
81 populate_logic_combo (GtkWidget *combo)
83 int idx;
85 for (idx = 0; idx < G_N_ELEMENTS (logic_strs); idx++) {
86 gtk_combo_box_append_text (GTK_COMBO_BOX (combo), logic_strs[idx]);
89 gtk_combo_box_set_active (GTK_COMBO_BOX (combo), 0);
92 static MMComparisionOperator
93 logic_combo_get_selected (GtkComboBox *combo)
95 gint idx;
97 idx = gtk_combo_box_get_active (combo);
98 return (MMComparisionOperator) (idx + 1);
101 static const char *
102 comparision_op_to_string (MMComparisionOperator op)
104 return logic_strs[op - 1];
107 static void
108 cat_combo_changed_cb (GtkComboBox *combo,
109 MMGtkFilterBuilder *self)
111 gint idx;
112 MMAttributeManager *attr_manager;
114 idx = gtk_combo_box_get_active (combo);
115 attr_manager = g_hash_table_lookup (self->details->attr_managers,
116 &idx);
117 mm_gtk_attribute_store_set_from_attribute_manager (self->details->attribute_store,
118 attr_manager);
119 gtk_combo_box_set_model (GTK_COMBO_BOX (self->details->attr_combo),
120 GTK_TREE_MODEL (self->details->attribute_store));
121 gtk_combo_box_set_active (GTK_COMBO_BOX (self->details->attr_combo), 0);
124 static void
125 add_filter_button_clicked_cb (GtkButton *button,
126 MMGtkFilterBuilder *self)
128 MMFilterParam *fp;
129 MMAttribute *attribute;
130 MMComparisionOperator op;
131 GtkTreeIter attr_iter, fp_iter;
132 GValue val = { 0, };
133 const char * val_string;
134 gboolean res;
136 /* we need to build a filter-param object with the selected information */
137 gtk_combo_box_get_active_iter (GTK_COMBO_BOX (self->details->attr_combo),
138 &attr_iter);
139 gtk_tree_model_get (GTK_TREE_MODEL (self->details->attribute_store),
140 &attr_iter, MM_GTK_ATTR_STORE_ATTR_COL,
141 &attribute, -1);
142 op = logic_combo_get_selected (GTK_COMBO_BOX (self->details->logic_combo));
143 val_string = gtk_entry_get_text (GTK_ENTRY (self->details->value_entry));
144 res = mm_gvalue_from_string (val_string, mm_attribute_get_value_type (attribute),
145 &val);
146 /* TODO: the attribute manager should provide a method to validate values
147 * for the relevant attribute.
149 if (res) {
150 fp = mm_filter_param_new (attribute, &val, op);
151 gtk_list_store_append (self->details->filter_store, &fp_iter);
152 gtk_list_store_set (self->details->filter_store, &fp_iter,
153 0, fp, -1);
157 static void
158 filter_param_logic_cell_data_func (GtkTreeViewColumn *column,
159 GtkCellRenderer *cell,
160 GtkTreeModel *model,
161 GtkTreeIter *iter,
162 gpointer data)
164 MMFilterParam *fp;
165 const char *logic_name;
167 gtk_tree_model_get (model, iter, 0, &fp, -1);
168 logic_name = comparision_op_to_string (mm_filter_param_get_operator (fp));
169 g_object_set (cell, "text", logic_name, NULL);
171 g_object_unref (fp);
174 static void
175 filter_param_value_cell_data_func (GtkTreeViewColumn *column,
176 GtkCellRenderer *cell,
177 GtkTreeModel *model,
178 GtkTreeIter *iter,
179 gpointer data)
181 MMFilterParam *fp;
182 char *value_str;
183 GValue *val;
185 gtk_tree_model_get (model, iter, 0, &fp, -1);
186 val = mm_filter_param_get_value (fp);
187 value_str = mm_gvalue_to_string (val);
188 g_object_set (cell, "text", value_str, NULL);
190 g_free (value_str);
191 g_object_unref (fp);
194 static void
195 filter_param_attr_cell_data_func (GtkTreeViewColumn *column,
196 GtkCellRenderer *cell,
197 GtkTreeModel *model,
198 GtkTreeIter *iter,
199 gpointer data)
201 MMFilterParam *fp;
202 const char *attr_name;
204 gtk_tree_model_get (model, iter, 0, &fp, -1);
205 attr_name = mm_attribute_get_name (mm_filter_param_get_attribute (fp));
206 g_object_set (cell, "text", attr_name, NULL);
208 g_object_unref (fp);
211 static void
212 mm_gtk_filter_builder_init (MMGtkFilterBuilder *self)
214 MMGtkFilterBuilderPrivate *details = self->details =
215 MM_GTK_FILTER_BUILDER_GET_PRIVATE (self);
216 GtkWidget *filter_view;
217 GtkTreeViewColumn *column;
218 GtkCellRenderer *renderer;
219 GtkWidget *table;
220 GtkWidget *w;
222 details->attribute_store = mm_gtk_attribute_store_new ();
223 details->attr_managers = g_hash_table_new (g_int_hash, g_int_equal);
225 /* tree view */
226 details->filter_store = gtk_list_store_new (1, MM_TYPE_FILTER_PARAM);
227 filter_view = gtk_tree_view_new_with_model (GTK_TREE_MODEL (details->filter_store));
228 renderer = gtk_cell_renderer_text_new ();
229 column = gtk_tree_view_column_new ();
230 gtk_tree_view_column_set_title (column, _("Attribute"));
231 gtk_tree_view_column_pack_start (column, renderer, TRUE);
232 gtk_tree_view_column_set_cell_data_func (column, renderer,
233 filter_param_attr_cell_data_func,
234 NULL, NULL);
235 gtk_tree_view_append_column (GTK_TREE_VIEW (filter_view), column);
236 column = gtk_tree_view_column_new ();
237 gtk_tree_view_column_pack_start (column, renderer, TRUE);
238 gtk_tree_view_column_set_title (column, _("Logic"));
239 gtk_tree_view_column_set_cell_data_func (column, renderer,
240 filter_param_logic_cell_data_func,
241 NULL, NULL);
242 gtk_tree_view_append_column (GTK_TREE_VIEW (filter_view), column);
243 column = gtk_tree_view_column_new ();
244 gtk_tree_view_column_pack_start (column, renderer, TRUE);
245 gtk_tree_view_column_set_title (column, _("Value"));
246 gtk_tree_view_column_set_cell_data_func (column, renderer,
247 filter_param_value_cell_data_func,
248 NULL, NULL);
249 gtk_tree_view_append_column (GTK_TREE_VIEW (filter_view), column);
250 details->filter_view = filter_view;
251 gtk_box_pack_start (GTK_BOX (self), GTK_WIDGET (filter_view),
252 FALSE, FALSE, 12);
253 gtk_widget_show (filter_view);
255 /* table */
256 table = gtk_table_new (3, 4, FALSE);
258 /* attribute category */
259 w = gtk_label_new_with_mnemonic (_("Attribute _category:"));
260 gtk_table_attach (GTK_TABLE (table), w,
261 0, 1, 0, 1,
262 0, 0, 0, 0);
263 details->cat_combo = gtk_combo_box_new_text ();
264 g_signal_connect (details->cat_combo, "changed",
265 G_CALLBACK (cat_combo_changed_cb), self);
266 gtk_table_attach (GTK_TABLE (table), details->cat_combo,
267 1, 2, 0, 1,
268 0, 0, 0, 0);
270 /* attribute name */
271 w = gtk_label_new_with_mnemonic (_("Attribute _name:"));
272 gtk_table_attach (GTK_TABLE (table), w,
273 2, 3, 0, 1,
274 0, 0, 0, 0);
275 details->attr_combo = gtk_combo_box_new ();
276 renderer = gtk_cell_renderer_text_new ();
277 gtk_cell_layout_pack_start (GTK_CELL_LAYOUT (details->attr_combo),
278 renderer, TRUE);
279 gtk_cell_layout_add_attribute (GTK_CELL_LAYOUT (details->attr_combo),
280 renderer,
281 "text", MM_GTK_ATTR_STORE_NAME_COL);
282 gtk_table_attach (GTK_TABLE (table), details->attr_combo,
283 3, 4, 0, 1,
284 0, 0, 0, 0);
286 /* logic */
287 w = gtk_label_new_with_mnemonic (_("_Logic:"));
288 gtk_table_attach (GTK_TABLE (table), w,
289 0, 1, 1, 2,
290 0, 0, 0, 0);
291 details->logic_combo = gtk_combo_box_new_text ();
292 gtk_table_attach (GTK_TABLE (table), details->logic_combo,
293 1, 2, 1, 2,
294 0, 0, 0, 0);
296 /* value */
297 w = gtk_label_new_with_mnemonic (_("_Value:"));
298 gtk_table_attach (GTK_TABLE (table), w,
299 2, 3, 1, 2,
300 0, 0, 0, 0);
301 details->value_entry = gtk_entry_new ();
302 gtk_table_attach (GTK_TABLE (table), details->value_entry,
303 3, 4, 1, 2,
304 0, 0, 0, 0);
306 /* add filter button */
307 w = gtk_button_new_from_stock (GTK_STOCK_ADD);
308 g_signal_connect (w, "clicked",
309 G_CALLBACK (add_filter_button_clicked_cb), self);
310 gtk_table_attach (GTK_TABLE (table), w,
311 3, 4, 2, 3,
312 0, 0, 0, 0);
313 gtk_box_pack_start (GTK_BOX (self), table,
314 FALSE, FALSE, 12);
315 gtk_widget_show_all (table);
317 populate_logic_combo (details->logic_combo);
320 static void
321 populate_from_category (MMGtkFilterBuilder *self, MMCategory *cat)
323 MMApplicationType type;
324 MMAttributeManager *attr_manager;
325 gint key = 0;
327 /* TODO: we should take care in some way that applications may want to define
328 * a custom AttributeManager. The API here in libmmanager-gtk is already
329 * setup for that, but this needs an API addition in MMApplication.
332 g_return_if_fail (MM_GTK_IS_FILTER_BUILDER (self));
333 g_return_if_fail (MM_IS_CATEGORY (cat));
335 /* TODO: when I will create Photo, Video and Music attribute managers,
336 * here is the place for adding those custom attributes.
340 attr_manager = mm_attribute_base_manager_get ();
341 mm_gtk_attribute_store_set_from_attribute_manager (self->details->attribute_store,
342 attr_manager);
343 gtk_combo_box_append_text (GTK_COMBO_BOX (self->details->cat_combo),
344 _("Base attributes"));
345 g_hash_table_insert (self->details->attr_managers, &key, attr_manager);
347 /* this should trigger population in the attr combo box */
348 gtk_combo_box_set_active (GTK_COMBO_BOX (self->details->cat_combo), 0);
351 /* public methods */
354 * mm_gtk_filter_builder_new:
355 * @category: a #MMCategory.
357 * Builds a #GtkWidget that allows to create #MMFilter objects for attributes
358 * supported by @category.
360 * Return value: a new #MMGtkFilterBuilder.
363 MMGtkFilterBuilder *
364 mm_gtk_filter_builder_new (MMCategory *category)
366 MMGtkFilterBuilder *self;
368 self = MM_GTK_FILTER_BUILDER (g_object_new (MM_GTK_TYPE_FILTER_BUILDER, NULL));
369 populate_from_category (self, category);
371 return self;
375 * mm_gtk_filter_builder_get_filter:
376 * @self: a #MMGtkFilterBuilder.
378 * Gets the #MMFilter for all the conditions specified within @self.
380 * Return value: a new #MMFilter, which might be empty if no condition has
381 * been specified inside @self.
384 MMFilter *
385 mm_gtk_filter_builder_get_filter (MMGtkFilterBuilder *self)
387 MMFilter *filter;
388 GtkTreeIter iter;
389 gboolean next = TRUE;
390 MMFilterParam *fp;
391 gboolean res;
393 g_return_val_if_fail (MM_GTK_IS_FILTER_BUILDER (self), NULL);
395 filter = mm_filter_new ();
396 res = gtk_tree_model_get_iter_first (GTK_TREE_MODEL (self->details->filter_store),
397 &iter);
398 if (!res) {
399 goto out;
402 while (next) {
403 gtk_tree_model_get (GTK_TREE_MODEL (self->details->filter_store),
404 &iter, 0, &fp, -1);
405 mm_filter_add_filtering_param (filter, fp);
406 next = gtk_tree_model_iter_next (GTK_TREE_MODEL (self->details->filter_store),
407 &iter);
408 g_object_unref (fp);
411 out:
412 return filter;