Add doc files to dist and fix version number in NEWS.
[mmediamanager.git] / libmmanager-gtk / mm-gtk-application-store.c
blob0bcc370be7a623dbe297ca1ddaee9562e7f5a272
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-application-store.h"
23 #include "libmmanager/mm-type-builtins.h"
24 #include "libmmanager/mm-types.h"
25 #include "libmmanager/mm-application.h"
26 #include "libmmanager/mm-manager.h"
27 #include "libmmanager/mm-category.h"
28 #include <gtk/gtk.h>
29 #include <glib/gi18n.h>
31 /* our parent's model iface */
32 static GtkTreeModelIface parent_iface = { 0, };
33 static void mm_gtk_application_store_tree_model_iface_init (GtkTreeModelIface *iface);
34 static void value_set_gicon_from_mm_type (GValue *val, MMApplicationType type);
36 G_DEFINE_TYPE_EXTENDED (MMGtkApplicationStore, mm_gtk_application_store,
37 GTK_TYPE_TREE_STORE, 0,
38 G_IMPLEMENT_INTERFACE (GTK_TYPE_TREE_MODEL,
39 mm_gtk_application_store_tree_model_iface_init));
41 static void
42 mm_gtk_application_store_finalize (GObject *object)
44 if (G_OBJECT_CLASS (mm_gtk_application_store_parent_class)->finalize)
45 G_OBJECT_CLASS (mm_gtk_application_store_parent_class)->finalize (object);
48 static void
49 mm_gtk_application_store_class_init (MMGtkApplicationStoreClass *klass)
51 GObjectClass *object_class = G_OBJECT_CLASS (klass);
53 object_class->finalize = mm_gtk_application_store_finalize;
56 static void
57 insert_categories_for_app (MMGtkApplicationStore *self,
58 GtkTreeIter iter,
59 MMApplication *app)
61 GList *categories, *l;
62 GError *error = NULL;
63 GtkTreeIter child;
65 /* at the third level of the tree we insert all the categories */
66 categories = mm_application_get_categories (app, &error);
67 if (error) {
68 g_critical ("MM-GTK: failed to build the ApplicationStore: %s",
69 error->message);
70 return;
72 for (l = categories; l; l = l->next) {
73 gtk_tree_store_append (GTK_TREE_STORE (self), &child, &iter);
74 gtk_tree_store_set (GTK_TREE_STORE (self), &child, MM_GTK_APP_STORE_CAT_COLUMN,
75 l->data, -1);
79 static void
80 insert_applications_for_type (MMGtkApplicationStore *self,
81 GtkTreeIter iter,
82 MMManager *manager,
83 MMApplicationType type)
85 GList *applications, *l;
86 GtkTreeIter child;
88 /* at the second level of the tree we insert all the applications */
89 applications = mm_manager_get_application_list_for_type (manager, type);
90 for (l = applications; l; l = l->next) {
91 gtk_tree_store_append (GTK_TREE_STORE (self), &child, &iter);
92 gtk_tree_store_set (GTK_TREE_STORE (self), &child, MM_GTK_APP_STORE_APP_COLUMN,
93 l->data, -1);
94 insert_categories_for_app (self, child, l->data);
98 static void
99 populate_store (MMGtkApplicationStore *self)
101 MMManager *manager;
102 GtkTreeIter iter;
103 MMApplicationType app_types[3] = {
104 MM_APPLICATION_MUSIC,
105 MM_APPLICATION_PHOTO,
106 MM_APPLICATION_VIDEO
108 int idx;
110 manager = mm_manager_get ();
111 /* at the first level, we insert all the types */
112 for (idx = 0; idx < 3; idx++) {
113 gtk_tree_store_append (GTK_TREE_STORE (self), &iter, NULL);
114 gtk_tree_store_set (GTK_TREE_STORE (self), &iter,
115 MM_GTK_APP_STORE_TYPE_COLUMN, app_types[idx],
116 -1);
117 insert_applications_for_type (self, iter, manager, app_types[idx]);
121 static void
122 mm_gtk_application_store_init (MMGtkApplicationStore *self)
124 GType types [] = { MM_TYPE_MAPPLICATION_TYPE,
125 MM_TYPE_APPLICATION,
126 MM_TYPE_CATEGORY
129 gtk_tree_store_set_column_types (GTK_TREE_STORE (self), 3, types);
130 populate_store (self);
133 /* retreive an object from our parent's data storage,
134 * unset the value when done. */
135 static GValue *
136 mm_gtk_application_store_get_object (MMGtkApplicationStore *self, GtkTreeIter *iter,
137 gint column)
139 GValue *value = g_new0 (GValue, 1);
141 /* validate our parameters */
142 g_return_val_if_fail (MM_GTK_IS_APPLICATION_STORE (self), NULL);
143 g_return_val_if_fail (iter != NULL, NULL);
145 /* retreive the object using our parent's interface */
146 parent_iface.get_value (GTK_TREE_MODEL (self), iter, column, value);
148 return value;
151 static GType
152 impl_get_column_type (GtkTreeModel *self, gint column)
154 GType types [] = {
155 MM_TYPE_MAPPLICATION_TYPE,
156 MM_TYPE_APPLICATION,
157 MM_TYPE_CATEGORY,
158 G_TYPE_ICON,
159 G_TYPE_STRING
162 g_return_val_if_fail (MM_GTK_IS_APPLICATION_STORE (self), G_TYPE_INVALID);
163 g_return_val_if_fail (column >= 0 && column < MM_GTK_APP_STORE_N_COLUMNS, G_TYPE_INVALID);
165 return types[column];
168 static void
169 value_set_gicon_from_cat (GValue *val,
170 MMCategory *cat)
172 GIcon *icon;
174 icon = mm_category_get_icon (cat);
175 if (!icon || !G_IS_ICON (icon)) {
176 /* fallback to a generic mimetype icon */
178 MMApplicationType type;
179 MMApplication *application;
181 application = mm_category_get_application (cat);
182 g_object_get (application, "supported-type", &type, NULL);
183 value_set_gicon_from_mm_type (val, type);
184 g_object_unref (application);
185 } else {
186 g_value_take_object (val, icon);
190 static void
191 get_value_for_category (GtkTreeModel *self, GtkTreeIter *iter,
192 gint column, GValue *value)
194 MMCategory *cat;
195 GValue *obj;
196 GIcon *icon;
198 obj = mm_gtk_application_store_get_object (MM_GTK_APPLICATION_STORE (self),
199 iter, MM_GTK_APP_STORE_CAT_COLUMN);
200 cat = MM_CATEGORY (g_value_dup_object (obj));
201 g_value_unset (obj);
203 switch (column) {
204 case MM_GTK_APP_STORE_CAT_COLUMN:
205 /* return the object itself */
206 g_value_set_object (value, cat);
207 break;
208 case MM_GTK_APP_STORE_APP_COLUMN:
209 g_value_take_object (value, mm_category_get_application (cat));
210 break;
211 case MM_GTK_APP_STORE_GICON_COLUMN:
212 value_set_gicon_from_cat (value, cat);
213 break;
214 case MM_GTK_APP_STORE_NAME_COLUMN:
215 g_value_set_string (value, mm_category_get_name (cat));
216 break;
217 case MM_GTK_APP_STORE_TYPE_COLUMN:
218 g_critical ("MM-GTK: impossible to get this kind of value, something in the"
219 "view is wrong!");
220 break;
221 default:
222 g_assert_not_reached ();
223 break;
226 g_object_unref (cat);
229 static void
230 value_set_gicon_from_app (GValue *val, MMApplication *app)
232 GAppInfo *app_info;
233 GIcon *icon;
235 app_info = mm_application_get_app_info (app);
236 icon = g_app_info_get_icon (app_info);
237 if (!icon || !G_IS_ICON (icon)) {
238 /* fallback to a default app icon */
239 icon = g_themed_icon_new ("application-default-icon");
242 g_value_take_object (val, icon);
244 g_object_unref (app_info);
247 static void
248 value_set_name_from_app (GValue *value, MMApplication *app)
250 GAppInfo *app_info;
252 app_info = mm_application_get_app_info (app);
253 g_value_set_string (value, g_app_info_get_name (app_info));
255 g_object_unref (app_info);
258 static void
259 value_set_supp_type_from_app (GValue *val, MMApplication *app)
261 MMApplicationType supp_type;
263 g_object_get (app, "supported-type", &supp_type, NULL);
265 g_value_set_enum (val, supp_type);
268 static void
269 get_value_for_application (GtkTreeModel *self, GtkTreeIter *iter,
270 gint column, GValue *value)
272 MMApplication *app;
273 GValue *obj;
275 obj = mm_gtk_application_store_get_object (MM_GTK_APPLICATION_STORE (self),
276 iter, MM_GTK_APP_STORE_APP_COLUMN);
277 app = MM_APPLICATION (g_value_dup_object (obj));
278 g_value_unset (obj);
280 switch (column) {
281 case MM_GTK_APP_STORE_APP_COLUMN:
282 /* return the object itself */
283 g_value_set_object (value, app);
284 break;
285 case MM_GTK_APP_STORE_GICON_COLUMN:
286 value_set_gicon_from_app (value, app);
287 break;
288 case MM_GTK_APP_STORE_NAME_COLUMN:
289 value_set_name_from_app (value, app);
290 break;
291 case MM_GTK_APP_STORE_TYPE_COLUMN:
292 value_set_supp_type_from_app (value, app);
293 break;
294 case MM_GTK_APP_STORE_CAT_COLUMN:
295 g_critical ("MM-GTK: impossible to get this kind of value, something in the"
296 "view is wrong!");
297 default:
298 g_assert_not_reached ();
299 break;
302 g_object_unref (app);
305 static void
306 value_set_name_from_mm_type (GValue *val,
307 MMApplicationType type)
309 static const char *messages[] = {
310 N_("Photos"),
311 N_("Music"),
312 N_("Videos")
315 g_value_set_string (val, messages[type-1]);
318 static void
319 value_set_gicon_from_mm_type (GValue *val,
320 MMApplicationType type)
322 GIcon *icon;
324 switch (type) {
325 case MM_APPLICATION_MUSIC:
326 icon = g_themed_icon_new ("audio-x-generic");
327 break;
328 case MM_APPLICATION_VIDEO:
329 icon = g_themed_icon_new ("video-x-generic");
330 break;
331 case MM_APPLICATION_PHOTO:
332 icon = g_themed_icon_new ("image-x-generic");
333 break;
334 default:
335 g_assert_not_reached ();
336 break;
339 g_value_take_object (val, icon);
342 static void
343 get_value_for_mm_type (GtkTreeModel *self, GtkTreeIter *iter,
344 gint column, GValue *value)
346 MMApplicationType type;
347 GValue *obj;
349 obj = mm_gtk_application_store_get_object (MM_GTK_APPLICATION_STORE (self),
350 iter, MM_GTK_APP_STORE_TYPE_COLUMN);
351 type = g_value_get_enum (obj);
353 switch (column) {
354 case MM_GTK_APP_STORE_TYPE_COLUMN:
355 /* return the value itself */
356 g_value_copy (obj, value);
357 break;
358 case MM_GTK_APP_STORE_GICON_COLUMN:
359 value_set_gicon_from_mm_type (value, type);
360 break;
361 case MM_GTK_APP_STORE_NAME_COLUMN:
362 value_set_name_from_mm_type (value, type);
363 break;
364 case MM_GTK_APP_STORE_CAT_COLUMN:
365 case MM_GTK_APP_STORE_APP_COLUMN:
366 g_critical ("MM-GTK: impossible to get this kind of value, something in the"
367 "view is wrong!");
368 break;
369 default:
370 g_assert_not_reached ();
371 break;
374 g_value_unset (obj);
377 static void
378 impl_get_value (GtkTreeModel *self, GtkTreeIter *iter,
379 gint column, GValue *value)
381 int depth;
383 g_return_if_fail (MM_GTK_IS_APPLICATION_STORE (self));
384 g_return_if_fail (iter != NULL);
385 g_return_if_fail (column >= 0 && column < MM_GTK_APP_STORE_N_COLUMNS);
386 g_return_if_fail (value != NULL);
388 value = g_value_init (value, impl_get_column_type (self, column));
389 depth = gtk_tree_store_iter_depth (GTK_TREE_STORE (self), iter);
390 if (depth == 0) {
391 get_value_for_mm_type (self, iter, column, value);
392 } else if (depth == 1) {
393 get_value_for_application (self, iter, column, value);
394 } else if (depth == 2) {
395 get_value_for_category (self, iter, column, value);
396 } else {
397 g_assert_not_reached ();
401 static int
402 impl_get_n_columns (GtkTreeModel *self)
404 g_return_val_if_fail (MM_GTK_IS_APPLICATION_STORE (self), 0);
406 /* we have four columns:
407 * - media type
408 * - application
409 * - category
410 * - gicon
411 * - name
413 return MM_GTK_APP_STORE_N_COLUMNS;
416 static void
417 mm_gtk_application_store_tree_model_iface_init (GtkTreeModelIface *iface)
419 /* save a copy of our parent's iface */
420 parent_iface = *iface;
422 /* override the iface methods */
423 iface->get_n_columns = impl_get_n_columns;
424 iface->get_column_type = impl_get_column_type;
425 iface->get_value = impl_get_value;
428 /* public methods */
431 * mm_gtk_application_store_new:
433 * Builds a #GtkTreeStore that hierarchically groups all the #MMApplicationType,
434 * #MMApplication and #MMCategory objects in a #GtkTreeModel fashion.
436 * Return value: an already populated #MMGtkApplicationStore.
439 MMGtkApplicationStore*
440 mm_gtk_application_store_new (void)
442 return g_object_new (MM_GTK_TYPE_APPLICATION_STORE, NULL);