2 * Copyright (C) 2000 Red Hat, Inc., Jonathan Blandford <jrb@redhat.com>
4 * This library is free software; you can redistribute it and/or
5 * modify it under the terms of the GNU Library General Public
6 * License as published by the Free Software Foundation; either
7 * version 2 of the License, or (at your option) any later version.
9 * This library 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 * Library General Public License for more details.
14 * You should have received a copy of the GNU Library General Public
15 * License along with this library; if not, write to the
16 * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
17 * Boston, MA 02111-1307, USA.
20 #include "gtktreemodel.h"
21 #include "gtktreestore.h"
22 #include "gtktreedatalist.h"
23 #include "gtksignal.h"
26 #define G_NODE(node) ((GNode *)node)
36 static guint tree_store_signals[LAST_SIGNAL] = { 0 };
38 static void gtk_tree_store_init (GtkTreeStore *tree_store);
39 static void gtk_tree_store_class_init (GtkTreeStoreClass *tree_store_class);
40 static void gtk_tree_store_tree_model_init (GtkTreeModelIface *iface);
41 static gint gtk_tree_store_get_n_columns (GtkTreeModel *tree_model);
42 static GtkTreeNode gtk_tree_store_get_node (GtkTreeModel *tree_model,
44 static GtkTreePath *gtk_tree_store_get_path (GtkTreeModel *tree_model,
46 static void gtk_tree_store_node_get_value (GtkTreeModel *tree_model,
50 static gboolean gtk_tree_store_node_next (GtkTreeModel *tree_model,
52 static GtkTreeNode gtk_tree_store_node_children (GtkTreeModel *tree_model,
54 static gboolean gtk_tree_store_node_has_child (GtkTreeModel *tree_model,
56 static gint gtk_tree_store_node_n_children (GtkTreeModel *tree_model,
58 static GtkTreeNode gtk_tree_store_node_nth_child (GtkTreeModel *tree_model,
61 static GtkTreeNode gtk_tree_store_node_parent (GtkTreeModel *tree_model,
67 gtk_tree_store_get_type (void)
69 static GtkType tree_store_type = 0;
73 static const GTypeInfo tree_store_info =
75 sizeof (GtkTreeStoreClass),
77 NULL, /* base_finalize */
78 (GClassInitFunc) gtk_tree_store_class_init,
79 NULL, /* class_finalize */
80 NULL, /* class_data */
81 sizeof (GtkTreeStore),
83 (GInstanceInitFunc) gtk_tree_store_init
86 static const GInterfaceInfo tree_model_info =
88 (GInterfaceInitFunc) gtk_tree_store_tree_model_init,
93 tree_store_type = g_type_register_static (GTK_TYPE_OBJECT, "GtkTreeStore", &tree_store_info);
94 g_type_add_interface_static (tree_store_type,
99 return tree_store_type;
103 gtk_tree_store_class_init (GtkTreeStoreClass *tree_store_class)
105 GtkObjectClass *object_class;
107 object_class = (GtkObjectClass *) tree_store_class;
109 tree_store_signals[NODE_CHANGED] =
110 gtk_signal_new ("node_changed",
112 GTK_CLASS_TYPE (object_class),
113 GTK_SIGNAL_OFFSET (GtkTreeStoreClass, node_changed),
114 gtk_marshal_NONE__POINTER_POINTER,
118 tree_store_signals[NODE_INSERTED] =
119 gtk_signal_new ("node_inserted",
121 GTK_CLASS_TYPE (object_class),
122 GTK_SIGNAL_OFFSET (GtkTreeStoreClass, node_inserted),
123 gtk_marshal_NONE__POINTER_POINTER,
127 tree_store_signals[NODE_CHILD_TOGGLED] =
128 gtk_signal_new ("node_child_toggled",
130 GTK_CLASS_TYPE (object_class),
131 GTK_SIGNAL_OFFSET (GtkTreeStoreClass, node_child_toggled),
132 gtk_marshal_NONE__POINTER_POINTER,
136 tree_store_signals[NODE_DELETED] =
137 gtk_signal_new ("node_deleted",
139 GTK_CLASS_TYPE (object_class),
140 GTK_SIGNAL_OFFSET (GtkTreeStoreClass, node_deleted),
141 gtk_marshal_NONE__POINTER,
145 gtk_object_class_add_signals (object_class, tree_store_signals, LAST_SIGNAL);
149 gtk_tree_store_tree_model_init (GtkTreeModelIface *iface)
151 iface->get_n_columns = gtk_tree_store_get_n_columns;
152 iface->get_node = gtk_tree_store_get_node;
153 iface->get_path = gtk_tree_store_get_path;
154 iface->node_get_value = gtk_tree_store_node_get_value;
155 iface->node_next = gtk_tree_store_node_next;
156 iface->node_children = gtk_tree_store_node_children;
157 iface->node_has_child = gtk_tree_store_node_has_child;
158 iface->node_n_children = gtk_tree_store_node_n_children;
159 iface->node_nth_child = gtk_tree_store_node_nth_child;
160 iface->node_parent = gtk_tree_store_node_parent;
164 gtk_tree_store_init (GtkTreeStore *tree_store)
166 tree_store->root = gtk_tree_store_node_new ();
170 gtk_tree_store_new (void)
172 return GTK_OBJECT (gtk_type_new (gtk_tree_store_get_type ()));
176 gtk_tree_store_new_with_values (gint n_columns,
183 g_return_val_if_fail (n_columns > 0, NULL);
185 retval = gtk_tree_store_new ();
186 gtk_tree_store_set_n_columns (GTK_TREE_STORE (retval),
189 va_start (args, n_columns);
190 for (i = 0; i < n_columns; i++)
191 gtk_tree_store_set_column_type (GTK_TREE_STORE (retval),
192 i, va_arg (args, GType));
200 gtk_tree_store_set_n_columns (GtkTreeStore *tree_store,
205 g_return_if_fail (tree_store != NULL);
206 g_return_if_fail (GTK_IS_TREE_STORE (tree_store));
208 if (tree_store->n_columns == n_columns)
211 new_columns = g_new0 (GType, n_columns);
212 if (tree_store->column_headers)
214 /* copy the old header orders over */
215 if (n_columns >= tree_store->n_columns)
216 memcpy (new_columns, tree_store->column_headers, tree_store->n_columns * sizeof (gchar *));
218 memcpy (new_columns, tree_store->column_headers, n_columns * sizeof (GType));
220 g_free (tree_store->column_headers);
223 tree_store->column_headers = new_columns;
224 tree_store->n_columns = n_columns;
228 gtk_tree_store_set_column_type (GtkTreeStore *tree_store,
232 g_return_if_fail (tree_store != NULL);
233 g_return_if_fail (GTK_IS_TREE_STORE (tree_store));
234 g_return_if_fail (column >=0 && column < tree_store->n_columns);
236 tree_store->column_headers[column] = type;
239 /* fulfill the GtkTreeModel requirements */
240 /* NOTE: GtkTreeStore::root is a GNode, that acts as the parent node. However,
241 * it is not visible to the tree or to the user., and the path "1" refers to the
242 * first child of GtkTreeStore::root.
245 gtk_tree_store_get_n_columns (GtkTreeModel *tree_model)
247 g_return_val_if_fail (tree_model != NULL, 0);
248 g_return_val_if_fail (GTK_IS_TREE_STORE (tree_model), 0);
250 return GTK_TREE_STORE (tree_model)->n_columns;
254 gtk_tree_store_get_node (GtkTreeModel *tree_model,
259 gint *indices = gtk_tree_path_get_indices (path);
261 node = GTK_TREE_STORE (tree_model)->root;
263 for (i = 0; i < gtk_tree_path_get_depth (path); i ++)
265 node = (GtkTreeNode) gtk_tree_store_node_nth_child (tree_model,
271 return (GtkTreeNode) node;
275 gtk_tree_store_get_path (GtkTreeModel *tree_model,
282 g_return_val_if_fail (tree_model != NULL, NULL);
286 if (node == G_NODE (GTK_TREE_STORE (tree_model)->root))
289 if (G_NODE (node)->parent == G_NODE (GTK_TREE_STORE (tree_model)->root))
291 retval = gtk_tree_path_new ();
292 tmp_node = G_NODE (GTK_TREE_STORE (tree_model)->root)->children;
296 retval = gtk_tree_store_get_path (tree_model,
297 G_NODE (node)->parent);
298 tmp_node = G_NODE (node)->parent->children;
303 if (tmp_node == NULL)
305 gtk_tree_path_free (retval);
309 for (; tmp_node; tmp_node = tmp_node->next)
311 if (tmp_node == G_NODE (node))
315 if (tmp_node == NULL)
317 /* We couldn't find node, meaning it's prolly not ours */
318 gtk_tree_path_free (retval);
322 gtk_tree_path_append_index (retval, i);
329 gtk_tree_store_node_get_value (GtkTreeModel *tree_model,
334 GtkTreeDataList *list;
335 gint tmp_column = column;
337 g_return_if_fail (tree_model != NULL);
338 g_return_if_fail (GTK_IS_TREE_STORE (tree_model));
339 g_return_if_fail (node != NULL);
340 g_return_if_fail (column < GTK_TREE_STORE (tree_model)->n_columns);
342 list = G_NODE (node)->data;
344 while (tmp_column-- > 0 && list)
347 g_return_if_fail (list != NULL);
349 gtk_tree_data_list_node_to_value (list,
350 GTK_TREE_STORE (tree_model)->column_headers[column],
355 gtk_tree_store_node_next (GtkTreeModel *tree_model,
358 if (node == NULL || *node == NULL)
361 *node = (GtkTreeNode) G_NODE (*node)->next;
362 return (*node != NULL);
366 gtk_tree_store_node_children (GtkTreeModel *tree_model,
369 return (GtkTreeNode) G_NODE (node)->children;
373 gtk_tree_store_node_has_child (GtkTreeModel *tree_model,
376 return G_NODE (node)->children != NULL;
380 gtk_tree_store_node_n_children (GtkTreeModel *tree_model,
385 node = (GtkTreeNode) G_NODE (node)->children;
389 node = (GtkTreeNode) G_NODE (node)->next;
396 gtk_tree_store_node_nth_child (GtkTreeModel *tree_model,
400 g_return_val_if_fail (node != NULL, NULL);
402 return (GtkTreeNode) g_node_nth_child (G_NODE (node), n);
406 gtk_tree_store_node_parent (GtkTreeModel *tree_model,
409 return (GtkTreeNode) G_NODE (node)->parent;
412 /* Public accessors */
414 gtk_tree_store_node_new (void)
418 retval = (GtkTreeNode) g_node_new (NULL);
423 * This is a somewhat inelegant function that does a lot of list
424 * manipulations on it's own.
427 gtk_tree_store_node_set_cell (GtkTreeStore *tree_store,
432 GtkTreeDataList *list;
433 GtkTreeDataList *prev;
435 g_return_if_fail (tree_store != NULL);
436 g_return_if_fail (GTK_IS_TREE_STORE (tree_store));
437 g_return_if_fail (node != NULL);
438 g_return_if_fail (column >= 0 && column < tree_store->n_columns);
440 prev = list = G_NODE (node)->data;
446 gtk_tree_data_list_value_to_node (list, value);
455 if (G_NODE (node)->data == NULL)
457 G_NODE (node)->data = list = gtk_tree_data_list_alloc ();
462 list = prev->next = gtk_tree_data_list_alloc ();
468 list->next = gtk_tree_data_list_alloc ();
473 gtk_tree_data_list_value_to_node (list, value);
477 gtk_tree_store_node_remove (GtkTreeStore *model,
483 g_return_if_fail (model != NULL);
484 g_return_if_fail (GTK_IS_TREE_STORE (model));
485 g_return_if_fail (node != NULL);
486 /* FIXME: if node is NULL, do I want to free the tree? */
488 parent = G_NODE (node)->parent;
490 path = gtk_tree_store_get_path (GTK_TREE_MODEL (model), node);
491 g_node_destroy (G_NODE (node));
492 gtk_signal_emit_by_name (GTK_OBJECT (model),
495 if (parent != G_NODE (model->root) && parent->children == NULL)
497 gtk_tree_path_up (path);
498 gtk_signal_emit_by_name (GTK_OBJECT (model),
499 "node_child_toggled",
503 gtk_tree_path_free (path);
507 gtk_tree_store_node_insert (GtkTreeStore *model,
514 g_return_val_if_fail (model != NULL, node);
515 g_return_val_if_fail (GTK_IS_TREE_STORE (model), node);
516 g_return_val_if_fail (node != NULL, node);
519 parent = model->root;
521 g_node_insert (G_NODE (parent), position, G_NODE (node));
523 path = gtk_tree_store_get_path (GTK_TREE_MODEL (model), node);
524 gtk_signal_emit_by_name (GTK_OBJECT (model),
527 gtk_tree_path_free (path);
533 gtk_tree_store_node_insert_before (GtkTreeStore *model,
540 g_return_val_if_fail (model != NULL, node);
541 g_return_val_if_fail (GTK_IS_TREE_STORE (model), node);
542 g_return_val_if_fail (node != NULL, node);
544 if (parent == NULL && sibling == NULL)
545 parent = model->root;
548 parent = (GtkTreeNode) G_NODE (sibling)->parent;
550 g_node_insert_before (G_NODE (parent), G_NODE (sibling), G_NODE (node));
552 path = gtk_tree_store_get_path (GTK_TREE_MODEL (model), node);
553 gtk_signal_emit_by_name (GTK_OBJECT (model),
556 gtk_tree_path_free (path);
562 gtk_tree_store_node_insert_after (GtkTreeStore *model,
569 g_return_val_if_fail (model != NULL, node);
570 g_return_val_if_fail (GTK_IS_TREE_STORE (model), node);
571 g_return_val_if_fail (node != NULL, node);
573 if (parent == NULL && sibling == NULL)
574 parent = model->root;
577 parent = (GtkTreeNode) G_NODE (sibling)->parent;
579 g_node_insert_after (G_NODE (parent), G_NODE (sibling), G_NODE (node));
581 path = gtk_tree_store_get_path (GTK_TREE_MODEL (model), node);
582 gtk_signal_emit_by_name (GTK_OBJECT (model),
585 gtk_tree_path_free (path);
590 gtk_tree_store_node_prepend (GtkTreeStore *model,
594 g_return_val_if_fail (model != NULL, node);
595 g_return_val_if_fail (GTK_IS_TREE_STORE (model), node);
596 g_return_val_if_fail (node != NULL, node);
599 parent = model->root;
601 if (G_NODE (parent)->children == NULL)
604 g_node_prepend (G_NODE (parent), G_NODE (node));
605 if (parent != model->root)
607 path = gtk_tree_store_get_path (GTK_TREE_MODEL (model), parent);
608 gtk_signal_emit_by_name (GTK_OBJECT (model),
609 "node_child_toggled",
612 gtk_tree_path_append_index (path, 1);
616 path = gtk_tree_store_get_path (GTK_TREE_MODEL (model), G_NODE (parent)->children);
618 gtk_signal_emit_by_name (GTK_OBJECT (model),
621 G_NODE (parent)->children);
622 gtk_tree_path_free (path);
626 gtk_tree_store_node_insert_after (model,
627 parent == model->root?NULL:parent,
635 gtk_tree_store_node_append (GtkTreeStore *model,
639 g_return_val_if_fail (model != NULL, node);
640 g_return_val_if_fail (GTK_IS_TREE_STORE (model), node);
641 g_return_val_if_fail (node != NULL, node);
644 parent = model->root;
646 if (G_NODE (parent)->children == NULL)
649 g_node_append (G_NODE (parent), G_NODE (node));
650 if (parent != model->root)
652 path = gtk_tree_store_get_path (GTK_TREE_MODEL (model), parent);
653 gtk_signal_emit_by_name (GTK_OBJECT (model),
654 "node_child_toggled",
657 gtk_tree_path_append_index (path, 1);
661 path = gtk_tree_store_get_path (GTK_TREE_MODEL (model), G_NODE (parent)->children);
663 gtk_signal_emit_by_name (GTK_OBJECT (model),
666 G_NODE (parent)->children);
667 gtk_tree_path_free (path);
671 gtk_tree_store_node_insert_before (model,
672 parent == model->root?NULL:parent,
680 gtk_tree_store_node_get_root (GtkTreeStore *model)
682 g_return_val_if_fail (model != NULL, NULL);
683 g_return_val_if_fail (GTK_IS_TREE_STORE (model), NULL);
685 return (GtkTreeNode) model->root;
690 gtk_tree_store_node_is_ancestor (GtkTreeStore *model,
692 GtkTreeNode descendant)
694 g_return_val_if_fail (model != NULL, FALSE);
695 g_return_val_if_fail (GTK_IS_TREE_STORE (model), FALSE);
696 g_return_val_if_fail (node != NULL, FALSE);
697 g_return_val_if_fail (descendant != NULL, FALSE);
699 return g_node_is_ancestor (G_NODE (node), G_NODE (descendant));
704 gtk_tree_store_node_depth (GtkTreeStore *model,
707 g_return_val_if_fail (model != NULL, 0);
708 g_return_val_if_fail (GTK_IS_TREE_STORE (model), 0);
709 g_return_val_if_fail (node != NULL, 0);
711 return g_node_depth (G_NODE (node));