1
/* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 8 -*- */
4
* Copyright (C) 2007 David Zeuthen
6
* This library is free software; you can redistribute it and/or
7
* modify it under the terms of the GNU Lesser General Public License
8
* as published by the Free Software Foundation; either version 2 of
9
* the License, or (at your option) any later version.
11
* This library is distributed in the hope that it will be useful, but
12
* WITHOUT ANY WARRANTY; without even the implied warranty of
13
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14
* Lesser General Public License for more details.
16
* You should have received a copy of the GNU Lesser General Public
17
* License along with this library; if not, write to the Free Software
18
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
23
#include <glib/gi18n.h>
26
#include <gdu-gtk/gdu-gtk.h>
31
struct _GduDeviceTreePrivate
33
GduPresentable *presentable;
37
static GObjectClass *parent_class = NULL;
39
G_DEFINE_TYPE (GduDeviceTree, gdu_device_tree, GTK_TYPE_TREE_VIEW)
41
static void device_tree_presentable_added (GduPool *pool, GduPresentable *presentable, gpointer user_data);
42
static void device_tree_presentable_removed (GduPool *pool, GduPresentable *presentable, gpointer user_data);
43
static void device_tree_presentable_changed (GduPool *pool, GduPresentable *presentable, gpointer user_data);
44
static void add_presentable_to_tree (GduDeviceTree *device_tree, GduPresentable *presentable, GtkTreeIter *iter_out);
46
static gint sort_iter_compare_func (GtkTreeModel *model, GtkTreeIter *a, GtkTreeIter *b, gpointer userdata);
57
PRESENTABLE_OBJ_COLUMN,
63
update_pool (GduDeviceTree *device_tree)
68
presentables = gdu_pool_get_presentables (device_tree->priv->pool);
69
for (l = presentables; l != NULL; l = l->next) {
70
GduPresentable *presentable = GDU_PRESENTABLE (l->data);
71
add_presentable_to_tree (device_tree, presentable, NULL);
72
g_object_unref (presentable);
74
g_list_free (presentables);
76
/* add/remove/change rows when the pool reports presentable add/remove/change */
77
g_signal_connect (device_tree->priv->pool, "presentable-added",
78
(GCallback) device_tree_presentable_added, device_tree);
79
g_signal_connect (device_tree->priv->pool, "presentable-removed",
80
(GCallback) device_tree_presentable_removed, device_tree);
81
g_signal_connect (device_tree->priv->pool, "presentable-changed",
82
(GCallback) device_tree_presentable_changed, device_tree);
86
gdu_device_tree_set_property (GObject *object,
91
GduDeviceTree *device_tree = GDU_DEVICE_TREE (object);
96
if (device_tree->priv->pool != NULL)
97
g_object_unref (device_tree->priv->pool);
98
obj = g_value_get_object (value);
99
device_tree->priv->pool = (obj == NULL ? NULL : g_object_ref (obj));
100
update_pool (device_tree);
104
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
110
gdu_device_tree_get_property (GObject *object,
115
GduDeviceTree *device_tree = GDU_DEVICE_TREE (object);
119
g_value_set_object (value, device_tree->priv->pool);
123
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
129
gdu_device_tree_finalize (GduDeviceTree *device_tree)
131
g_signal_handlers_disconnect_by_func (device_tree->priv->pool, device_tree_presentable_added, device_tree);
132
g_signal_handlers_disconnect_by_func (device_tree->priv->pool, device_tree_presentable_removed, device_tree);
133
g_signal_handlers_disconnect_by_func (device_tree->priv->pool, device_tree_presentable_changed, device_tree);
135
if (device_tree->priv->pool != NULL)
136
g_object_unref (device_tree->priv->pool);
138
if (G_OBJECT_CLASS (parent_class)->finalize)
139
(* G_OBJECT_CLASS (parent_class)->finalize) (G_OBJECT (device_tree));
143
gdu_device_tree_class_init (GduDeviceTreeClass *klass)
145
GObjectClass *obj_class = (GObjectClass *) klass;
147
parent_class = g_type_class_peek_parent (klass);
149
obj_class->finalize = (GObjectFinalizeFunc) gdu_device_tree_finalize;
150
obj_class->set_property = gdu_device_tree_set_property;
151
obj_class->get_property = gdu_device_tree_get_property;
153
g_type_class_add_private (klass, sizeof (GduDeviceTreePrivate));
156
* GduDeviceTree:pool:
158
* The #GduPool instance we are getting information from
160
g_object_class_install_property (obj_class,
162
g_param_spec_object ("pool",
168
G_PARAM_CONSTRUCT_ONLY));
172
gdu_device_tree_init (GduDeviceTree *device_tree)
174
GtkCellRenderer *renderer;
175
GtkTreeViewColumn *column;
178
device_tree->priv = G_TYPE_INSTANCE_GET_PRIVATE (device_tree, GDU_TYPE_DEVICE_TREE, GduDeviceTreePrivate);
180
store = gtk_tree_store_new (N_COLUMNS,
183
GDU_TYPE_PRESENTABLE,
186
gtk_tree_sortable_set_sort_func (GTK_TREE_SORTABLE (store), SORTNAME_COLUMN, sort_iter_compare_func,
188
gtk_tree_sortable_set_sort_column_id (GTK_TREE_SORTABLE (store), SORTNAME_COLUMN, GTK_SORT_ASCENDING);
190
gtk_tree_view_set_model (GTK_TREE_VIEW (device_tree), GTK_TREE_MODEL (store));
191
/* TODO: when GTK 2.12 is available... we can do this */
192
/*gtk_tree_view_set_show_expanders (GTK_TREE_VIEW (tree), FALSE);*/
194
column = gtk_tree_view_column_new ();
195
gtk_tree_view_column_set_title (column, "Title");
196
renderer = gtk_cell_renderer_pixbuf_new ();
197
gtk_tree_view_column_pack_start (column, renderer, FALSE);
198
gtk_tree_view_column_set_attributes (column, renderer,
199
"pixbuf", ICON_COLUMN,
201
renderer = gtk_cell_renderer_text_new ();
202
gtk_tree_view_column_pack_start (column, renderer, TRUE);
203
gtk_tree_view_column_set_attributes (column, renderer,
204
"text", TITLE_COLUMN,
206
gtk_tree_view_append_column (GTK_TREE_VIEW (device_tree), column);
208
gtk_tree_view_set_headers_visible (GTK_TREE_VIEW (device_tree), FALSE);
210
gtk_tree_view_set_show_expanders (GTK_TREE_VIEW (device_tree), FALSE);
211
gtk_tree_view_set_level_indentation (GTK_TREE_VIEW (device_tree), 16);
216
sort_iter_compare_func (GtkTreeModel *model,
225
gtk_tree_model_get (model, a, SORTNAME_COLUMN, &s1, -1);
226
gtk_tree_model_get (model, b, SORTNAME_COLUMN, &s2, -1);
227
if (s1 == NULL || s2 == NULL)
230
result = g_ascii_strcasecmp (s1, s2);
239
GduPresentable *presentable;
245
find_iter_by_presentable_foreach (GtkTreeModel *model,
251
GduPresentable *presentable = NULL;
252
FIBDData *fibd_data = (FIBDData *) data;
255
gtk_tree_model_get (model, iter, PRESENTABLE_OBJ_COLUMN, &presentable, -1);
256
if (presentable == fibd_data->presentable) {
257
fibd_data->found = TRUE;
258
fibd_data->iter = *iter;
261
if (presentable != NULL)
262
g_object_unref (presentable);
269
find_iter_by_presentable (GtkTreeStore *store, GduPresentable *presentable, GtkTreeIter *iter)
274
fibd_data.presentable = presentable;
275
fibd_data.found = FALSE;
276
gtk_tree_model_foreach (GTK_TREE_MODEL (store), find_iter_by_presentable_foreach, &fibd_data);
277
if (fibd_data.found) {
279
*iter = fibd_data.iter;
289
device_tree_presentable_changed (GduPool *pool, GduPresentable *presentable, gpointer user_data)
291
GtkTreeView *tree_view = GTK_TREE_VIEW (user_data);
298
store = GTK_TREE_STORE (gtk_tree_view_get_model (tree_view));
300
/* update name and icon */
301
if (find_iter_by_presentable (store, presentable, &iter)) {
303
name = gdu_presentable_get_name (presentable);
304
device = gdu_presentable_get_device (presentable);
306
pixbuf = gdu_util_get_pixbuf_for_presentable (presentable, GTK_ICON_SIZE_MENU);
308
gtk_tree_store_set (store,
316
g_object_unref (pixbuf);
318
g_object_unref (device);
323
add_presentable_to_tree (GduDeviceTree *device_tree, GduPresentable *presentable, GtkTreeIter *iter_out)
327
GtkTreeIter *parent_iter;
332
GduPresentable *enclosing_presentable;
333
const char *object_path;
338
store = GTK_TREE_STORE (gtk_tree_view_get_model (GTK_TREE_VIEW (device_tree)));
340
/* check to see if presentable is already added */
341
if (find_iter_by_presentable (store, presentable, NULL))
344
/* set up parent relationship */
346
enclosing_presentable = gdu_presentable_get_enclosing_presentable (presentable);
347
if (enclosing_presentable != NULL) {
348
if (find_iter_by_presentable (store, enclosing_presentable, &iter2)) {
349
parent_iter = &iter2;
351
/* add parent if it's not already added */
352
/*g_debug ("we have no parent for %s (%p)", gdu_presentable_get_id (enclosing_presentable), enclosing_presentable);*/
353
add_presentable_to_tree (device_tree, enclosing_presentable, &iter2);
354
parent_iter = &iter2;
356
g_object_unref (enclosing_presentable);
359
device = gdu_presentable_get_device (presentable);
361
object_path = gdu_device_get_object_path (device);
365
/* compute the name */
366
name = gdu_presentable_get_name (presentable);
367
pixbuf = gdu_util_get_pixbuf_for_presentable (presentable, GTK_ICON_SIZE_MENU);
369
/* sort by offset so we get partitions in the right order */
370
sortname = g_strdup_printf ("%016" G_GINT64_FORMAT "_%s", gdu_presentable_get_offset (presentable), object_path);
372
/*g_debug ("adding %s (%p)", gdu_presentable_get_id (presentable), presentable);*/
374
gtk_tree_store_append (store, &iter, parent_iter);
375
gtk_tree_store_set (store, &iter,
378
PRESENTABLE_OBJ_COLUMN, presentable,
379
SORTNAME_COLUMN, sortname,
383
if (iter_out != NULL)
388
g_object_unref (pixbuf);
390
if (parent_iter != NULL) {
392
path = gtk_tree_model_get_path (GTK_TREE_MODEL (store), parent_iter);
394
gtk_tree_view_expand_row (GTK_TREE_VIEW (device_tree), path, TRUE);
395
gtk_tree_path_free (path);
401
g_object_unref (device);
405
device_tree_presentable_added (GduPool *pool, GduPresentable *presentable, gpointer user_data)
407
GduDeviceTree *device_tree = GDU_DEVICE_TREE (user_data);
408
add_presentable_to_tree (device_tree, presentable, NULL);
412
device_tree_presentable_removed (GduPool *pool, GduPresentable *presentable, gpointer user_data)
414
GduDeviceTree *device_tree = GDU_DEVICE_TREE (user_data);
418
store = GTK_TREE_STORE (gtk_tree_view_get_model (GTK_TREE_VIEW (device_tree)));
419
if (find_iter_by_presentable (store, presentable, &iter)) {
420
gtk_tree_store_remove (store, &iter);
425
gdu_device_tree_new (GduPool *pool)
427
return GTK_WIDGET (g_object_new (GDU_TYPE_DEVICE_TREE, "pool", pool, NULL));
431
gdu_device_tree_get_selected_presentable (GtkTreeView *tree_view)
433
GduPresentable *presentable;
435
GtkTreeModel *presentable_tree_model;
439
presentable_tree_model = gtk_tree_view_get_model (tree_view);
440
gtk_tree_view_get_cursor (tree_view, &path, NULL);
444
if (gtk_tree_model_get_iter (presentable_tree_model, &iter, path)) {
446
gtk_tree_model_get (presentable_tree_model, &iter,
447
PRESENTABLE_OBJ_COLUMN,
451
if (presentable != NULL)
452
g_object_unref (presentable);
455
gtk_tree_path_free (path);
462
gdu_device_tree_select_presentable (GtkTreeView *tree_view, GduPresentable *presentable)
465
GtkTreeModel *tree_model;
468
if (presentable == NULL)
471
tree_model = gtk_tree_view_get_model (tree_view);
472
if (!find_iter_by_presentable (GTK_TREE_STORE (tree_model), presentable, &iter))
475
path = gtk_tree_model_get_path (tree_model, &iter);
479
gtk_tree_view_set_cursor (tree_view, path, NULL, FALSE);
480
gtk_tree_path_free (path);
486
gdu_device_tree_select_first_presentable (GtkTreeView *tree_view)
489
GtkTreeModel *tree_model;
492
tree_model = gtk_tree_view_get_model (tree_view);
494
if (gtk_tree_model_get_iter_first (tree_model, &iter)) {
495
path = gtk_tree_model_get_path (tree_model, &iter);
499
gtk_tree_view_set_cursor (tree_view, path, NULL, FALSE);
500
gtk_tree_path_free (path);