2 * Copyright (C) 2001, 2002 Anders Carlsson <andersca@gnu.org>
4 * This program is free software; you can redistribute it and/or
5 * modify it under the terms of the GNU General Public License as
6 * published by the Free Software Foundation; either version 2 of the
7 * License, or (at your option) any later version.
9 * This program is distributed in the hope that it will be useful,
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
12 * General Public License for more details.
14 * You should have received a copy of the GNU General Public License
15 * along with this program; if not, write to the Free Software
16 * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
21 #include "gconf-list-model.h"
24 #include "gconf-util.h"
26 #define G_SLIST(x) ((GSList *) x)
28 static const char *gconf_value_icon_names[] = {
39 static void gconf_list_model_class_init (GConfListModelClass *klass);
40 static void gconf_list_model_init (GConfListModel *model);
41 static void gconf_list_model_tree_model_init (GtkTreeModelIface *iface);
43 G_DEFINE_TYPE_WITH_CODE (GConfListModel, gconf_list_model, G_TYPE_OBJECT,
44 G_IMPLEMENT_INTERFACE (GTK_TYPE_TREE_MODEL, gconf_list_model_tree_model_init));
47 gconf_list_model_notify_func (GConfClient* client, guint cnxn_id, GConfEntry *entry, gpointer user_data)
52 GConfListModel *list_model = user_data;
56 key = gconf_entry_get_key (entry);
58 path_str = g_path_get_dirname (key);
60 if (strcmp (path_str, list_model->root_path) != 0)
68 if (strncmp (key, list_model->root_path, strlen (list_model->root_path)) != 0)
71 if (gconf_client_dir_exists (client, key, NULL))
72 /* this is a directory -- ignore */
75 list = g_hash_table_lookup (list_model->key_hash, key);
78 /* Create a new entry */
79 entry = gconf_entry_new (gconf_entry_get_key (entry),
80 gconf_entry_get_value (entry));
82 list = g_slist_append (list, entry);
83 list_model->values = g_slist_concat (list_model->values, list);
84 g_hash_table_insert (list_model->key_hash, g_strdup (key), list);
88 iter.stamp = list_model->stamp;
89 iter.user_data = list;
93 path = gtk_tree_model_get_path (GTK_TREE_MODEL (list_model), &iter);
94 gtk_tree_model_row_inserted (GTK_TREE_MODEL (list_model), path, &iter);
95 gtk_tree_path_free (path);
100 iter.stamp = list_model->stamp;
101 iter.user_data = list;
103 path = gtk_tree_model_get_path (GTK_TREE_MODEL (list_model), &iter);
105 gconf_entry_free (list->data);
107 if (gconf_entry_get_value (entry) != NULL) {
108 list->data = gconf_entry_new (gconf_entry_get_key (entry),
109 gconf_entry_get_value (entry));
110 gtk_tree_model_row_changed (GTK_TREE_MODEL (list_model), path, &iter);
113 gtk_tree_model_row_deleted (GTK_TREE_MODEL (list_model), path);
114 list_model->values = g_slist_remove (list_model->values, list->data);
115 list_model->length--;
116 g_hash_table_remove (list_model->key_hash, key);
119 gtk_tree_path_free (path);
124 gconf_list_model_set_root_path (GConfListModel *model, const gchar *root_path)
131 path = gtk_tree_path_new ();
132 gtk_tree_path_append_index (path, 0);
134 if (model->root_path != NULL) {
135 for (list = model->values; list; list = list->next) {
136 GConfEntry *entry = list->data;
138 g_hash_table_remove (model->key_hash, gconf_entry_get_key (entry));
140 gtk_tree_model_row_deleted (GTK_TREE_MODEL (model), path);
142 gconf_entry_free (entry);
145 gconf_client_notify_remove (model->client, model->notify_id);
147 gconf_client_remove_dir (model->client,
148 model->root_path, NULL);
150 g_free (model->root_path);
151 g_slist_free (model->values);
152 model->values = NULL;
154 gtk_tree_path_free (path);
156 gconf_client_add_dir (model->client,
158 GCONF_CLIENT_PRELOAD_ONELEVEL,
161 model->notify_id = gconf_client_notify_add (model->client, root_path,
162 gconf_list_model_notify_func,
165 model->root_path = g_strdup (root_path);
166 values = gconf_client_all_entries (model->client, root_path, NULL);
169 for (list = values; list; list = list->next) {
170 GConfEntry *entry = list->data;
172 model->values = g_slist_append (model->values, list->data);
177 iter.stamp = model->stamp;
178 iter.user_data = g_slist_last (model->values);
180 g_hash_table_insert (model->key_hash, g_strdup (gconf_entry_get_key (entry)), iter.user_data);
182 path = gtk_tree_model_get_path (GTK_TREE_MODEL (model), &iter);
183 gtk_tree_model_row_inserted (GTK_TREE_MODEL (model), path, &iter);
185 gtk_tree_path_free (path);
189 g_slist_free (values);
192 static GtkTreeModelFlags
193 gconf_list_model_get_flags (GtkTreeModel *tree_model)
199 gconf_list_model_get_n_columns (GtkTreeModel *tree_model)
201 return GCONF_LIST_MODEL_NUM_COLUMNS;
205 gconf_list_model_get_column_type (GtkTreeModel *tree_model, gint index)
208 case GCONF_LIST_MODEL_ICON_NAME_COLUMN:
209 case GCONF_LIST_MODEL_KEY_PATH_COLUMN:
210 case GCONF_LIST_MODEL_KEY_NAME_COLUMN:
211 return G_TYPE_STRING;
212 case GCONF_LIST_MODEL_VALUE_COLUMN:
213 return GCONF_TYPE_VALUE;
215 return G_TYPE_INVALID;
220 gconf_list_model_get_iter (GtkTreeModel *tree_model, GtkTreeIter *iter, GtkTreePath *path)
222 GConfListModel *list_model = (GConfListModel *)tree_model;
226 g_return_val_if_fail (gtk_tree_path_get_depth (path) > 0, FALSE);
228 i = gtk_tree_path_get_indices (path)[0];
230 if (i >= list_model->length)
233 list = g_slist_nth (list_model->values, i);
235 iter->stamp = list_model->stamp;
236 iter->user_data = list;
242 gconf_list_model_get_path (GtkTreeModel *tree_model, GtkTreeIter *iter)
245 GtkTreePath *tree_path;
248 g_return_val_if_fail (iter->stamp == GCONF_LIST_MODEL (tree_model)->stamp, NULL);
250 for (list = G_SLIST (GCONF_LIST_MODEL (tree_model)->values); list; list = list->next) {
251 if (list == G_SLIST (iter->user_data))
258 tree_path = gtk_tree_path_new ();
259 gtk_tree_path_append_index (tree_path, i);
265 gconf_list_model_get_value (GtkTreeModel *tree_model, GtkTreeIter *iter, gint column, GValue *value)
269 g_return_if_fail (iter->stamp == GCONF_LIST_MODEL (tree_model)->stamp);
271 entry = G_SLIST (iter->user_data)->data;
274 case GCONF_LIST_MODEL_KEY_PATH_COLUMN:
275 g_value_init (value, G_TYPE_STRING);
276 g_value_set_string (value, gconf_entry_get_key (entry));
279 case GCONF_LIST_MODEL_KEY_NAME_COLUMN:
280 g_value_init (value, G_TYPE_STRING);
281 g_value_take_string (value, gconf_get_key_name_from_path (gconf_entry_get_key (entry)));
284 case GCONF_LIST_MODEL_ICON_NAME_COLUMN: {
285 GConfValue *gconf_value;
286 GConfValueType value_type;
288 gconf_value = gconf_entry_get_value (entry);
290 value_type = gconf_value->type;
292 value_type = GCONF_VALUE_INVALID;
295 g_value_init (value, G_TYPE_STRING);
296 g_value_set_static_string (value, gconf_value_icon_names[value_type]);
301 case GCONF_LIST_MODEL_VALUE_COLUMN:
302 g_value_init (value, GCONF_TYPE_VALUE);
303 g_value_set_boxed (value, gconf_entry_get_value (entry));
312 gconf_list_model_iter_next (GtkTreeModel *tree_model, GtkTreeIter *iter)
314 g_return_val_if_fail (iter->stamp == GCONF_LIST_MODEL (tree_model)->stamp, FALSE);
316 iter->user_data = G_SLIST (iter->user_data)->next;
318 return (iter->user_data != NULL);
322 gconf_list_model_iter_has_child (GtkTreeModel *tree_model, GtkTreeIter *iter)
328 gconf_list_model_iter_n_children (GtkTreeModel *tree_model, GtkTreeIter *iter)
330 /* it should ask for the root node, because we're a list */
332 return g_slist_length (GCONF_LIST_MODEL (tree_model)->values);
338 gconf_list_model_iter_nth_child (GtkTreeModel *tree_model, GtkTreeIter *iter, GtkTreeIter *parent, gint n)
345 child = g_slist_nth (GCONF_LIST_MODEL (tree_model)->values, n);
348 iter->stamp = GCONF_LIST_MODEL (tree_model)->stamp;
349 iter->user_data = child;
357 gconf_list_model_tree_model_init (GtkTreeModelIface *iface)
359 iface->get_flags = gconf_list_model_get_flags;
360 iface->get_n_columns = gconf_list_model_get_n_columns;
361 iface->get_column_type = gconf_list_model_get_column_type;
362 iface->get_iter = gconf_list_model_get_iter;
363 iface->get_path = gconf_list_model_get_path;
364 iface->get_value = gconf_list_model_get_value;
365 iface->iter_next = gconf_list_model_iter_next;
366 iface->iter_has_child = gconf_list_model_iter_has_child;
367 iface->iter_n_children = gconf_list_model_iter_n_children;
368 iface->iter_nth_child = gconf_list_model_iter_nth_child;
372 gconf_list_model_finalize (GObject *object)
374 GConfListModel *list_model;
376 list_model = (GConfListModel *)object;
378 g_hash_table_destroy (list_model->key_hash);
380 if (list_model->client && list_model->notify_id > 0) {
381 gconf_client_notify_remove (list_model->client, list_model->notify_id);
384 if (list_model->client && list_model->root_path) {
385 gconf_client_remove_dir (list_model->client,
386 list_model->root_path, NULL);
389 if (list_model->client) {
390 g_object_unref (list_model->client);
391 list_model->client = NULL;
394 if (list_model->values) {
395 g_slist_foreach (list_model->values, (GFunc) gconf_entry_free, NULL);
396 g_slist_free (list_model->values);
397 list_model->values = NULL;
400 g_free (list_model->root_path);
402 G_OBJECT_CLASS (gconf_list_model_parent_class)->finalize (object);
406 gconf_list_model_class_init (GConfListModelClass *klass)
408 GObjectClass *object_class = G_OBJECT_CLASS (klass);
410 object_class->finalize = gconf_list_model_finalize;
414 gconf_list_model_init (GConfListModel *model)
416 model->stamp = g_random_int ();
417 model->key_hash = g_hash_table_new_full (g_str_hash, g_str_equal,
419 model->client = gconf_client_get_default ();
423 gconf_list_model_set_client (GConfListModel *model, GConfClient *client)
425 if (model->client != NULL) {
426 g_object_unref (model->client);
429 model->client = g_object_ref (client);
433 gconf_list_model_new (void)
435 return GTK_TREE_MODEL (g_object_new (GCONF_TYPE_LIST_MODEL, NULL));