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.
21 #include "gtktreemodel.h"
22 #include "gtkliststore.h"
23 #include "gtktreedatalist.h"
24 #include "gtksignal.h"
26 #define G_SLIST(x) ((GSList *) x)
36 static guint list_store_signals[LAST_SIGNAL] = { 0 };
38 static void gtk_list_store_init (GtkListStore *list_store);
39 static void gtk_list_store_class_init (GtkListStoreClass *class);
40 static void gtk_list_store_tree_model_init (GtkTreeModelIface *iface);
41 static gint gtk_list_store_get_n_columns (GtkTreeModel *tree_model);
42 static GtkTreeIter *gtk_list_store_get_iter (GtkTreeModel *tree_model,
44 static GtkTreePath *gtk_list_store_get_path (GtkTreeModel *tree_model,
46 static void gtk_list_store_iter_get_value (GtkTreeModel *tree_model,
50 static gboolean gtk_list_store_iter_next (GtkTreeModel *tree_model,
52 static GtkTreeIter *gtk_list_store_iter_children (GtkTreeModel *tree_model,
54 static gboolean gtk_list_store_iter_has_child (GtkTreeModel *tree_model,
56 static gint gtk_list_store_iter_n_children (GtkTreeModel *tree_model,
58 static GtkTreeIter *gtk_list_store_iter_nth_child (GtkTreeModel *tree_model,
61 static GtkTreeIter *gtk_list_store_iter_parent (GtkTreeModel *tree_model,
66 gtk_list_store_get_type (void)
68 static GtkType list_store_type = 0;
72 static const GTypeInfo list_store_info =
74 sizeof (GtkListStoreClass),
76 NULL, /* base_finalize */
77 (GClassInitFunc) gtk_list_store_class_init,
78 NULL, /* class_finalize */
79 NULL, /* class_data */
80 sizeof (GtkListStore),
82 (GInstanceInitFunc) gtk_list_store_init,
85 static const GInterfaceInfo tree_model_info =
87 (GInterfaceInitFunc) gtk_list_store_tree_model_init,
92 list_store_type = g_type_register_static (GTK_TYPE_OBJECT, "GtkListStore", &list_store_info, 0);
93 g_type_add_interface_static (list_store_type,
98 return list_store_type;
102 gtk_list_store_class_init (GtkListStoreClass *class)
104 GtkObjectClass *object_class;
106 object_class = (GtkObjectClass*) class;
108 list_store_signals[CHANGED] =
109 gtk_signal_new ("changed",
111 GTK_CLASS_TYPE (object_class),
112 GTK_SIGNAL_OFFSET (GtkListStoreClass, changed),
113 gtk_marshal_VOID__POINTER_POINTER,
117 list_store_signals[INSERTED] =
118 gtk_signal_new ("inserted",
120 GTK_CLASS_TYPE (object_class),
121 GTK_SIGNAL_OFFSET (GtkListStoreClass, inserted),
122 gtk_marshal_VOID__POINTER_POINTER,
126 list_store_signals[CHILD_TOGGLED] =
127 gtk_signal_new ("child_toggled",
129 GTK_CLASS_TYPE (object_class),
130 GTK_SIGNAL_OFFSET (GtkListStoreClass, child_toggled),
131 gtk_marshal_VOID__POINTER_POINTER,
135 list_store_signals[DELETED] =
136 gtk_signal_new ("deleted",
138 GTK_CLASS_TYPE (object_class),
139 GTK_SIGNAL_OFFSET (GtkListStoreClass, deleted),
140 gtk_marshal_VOID__POINTER,
145 gtk_object_class_add_signals (object_class, list_store_signals, LAST_SIGNAL);
149 gtk_list_store_tree_model_init (GtkTreeModelIface *iface)
151 iface->get_n_columns = gtk_list_store_get_n_columns;
152 iface->get_iter = gtk_list_store_get_iter;
153 iface->get_path = gtk_list_store_get_path;
154 iface->iter_get_value = gtk_list_store_iter_get_value;
155 iface->iter_next = gtk_list_store_iter_next;
156 iface->iter_children = gtk_list_store_iter_children;
157 iface->iter_has_child = gtk_list_store_iter_has_child;
158 iface->iter_n_children = gtk_list_store_iter_n_children;
159 iface->iter_nth_child = gtk_list_store_iter_nth_child;
160 iface->iter_parent = gtk_list_store_iter_parent;
164 gtk_list_store_init (GtkListStore *list_store)
166 list_store->root = NULL;
170 gtk_list_store_new (void)
172 return GTK_OBJECT (gtk_type_new (gtk_list_store_get_type ()));
176 gtk_list_store_new_with_types (gint n_columns,
183 g_return_val_if_fail (n_columns > 0, NULL);
185 retval = gtk_list_store_new ();
186 gtk_list_store_set_n_columns (GTK_LIST_STORE (retval),
189 va_start (args, n_columns);
190 for (i = 0; i < n_columns; i++)
191 gtk_list_store_set_column_type (GTK_LIST_STORE (retval),
192 i, va_arg (args, GType));
200 gtk_list_store_set_n_columns (GtkListStore *list_store,
205 g_return_if_fail (list_store != NULL);
206 g_return_if_fail (GTK_IS_LIST_STORE (list_store));
208 if (list_store->n_columns == n_columns)
211 new_columns = g_new0 (GType, n_columns);
212 if (list_store->column_headers)
214 /* copy the old header orders over */
215 if (n_columns >= list_store->n_columns)
216 memcpy (new_columns, list_store->column_headers, list_store->n_columns * sizeof (gchar *));
218 memcpy (new_columns, list_store->column_headers, n_columns * sizeof (GType));
220 g_free (list_store->column_headers);
223 list_store->column_headers = new_columns;
224 list_store->n_columns = n_columns;
228 gtk_list_store_set_column_type (GtkListStore *list_store,
232 g_return_if_fail (list_store != NULL);
233 g_return_if_fail (GTK_IS_LIST_STORE (list_store));
234 g_return_if_fail (column >=0 && column < list_store->n_columns);
236 list_store->column_headers[column] = type;
239 /* Fulfill the GtkTreeModel requirements */
241 gtk_list_store_get_n_columns (GtkTreeModel *tree_model)
243 g_return_val_if_fail (tree_model != NULL, 0);
244 g_return_val_if_fail (GTK_IS_LIST_STORE (tree_model), 0);
246 return GTK_LIST_STORE (tree_model)->n_columns;
250 gtk_list_store_get_iter (GtkTreeModel *tree_model,
253 g_return_val_if_fail (gtk_tree_path_get_depth (path) > 0, NULL);
255 return (GtkTreeIter) g_slist_nth (G_SLIST (GTK_LIST_STORE (tree_model)->root),
256 gtk_tree_path_get_indices (path)[0]);
260 gtk_list_store_get_path (GtkTreeModel *tree_model,
267 g_return_val_if_fail (GTK_IS_LIST_STORE (tree_model), NULL);
269 for (list = G_SLIST (GTK_LIST_STORE (tree_model)->root); list; list = list->next)
272 if (list == G_SLIST (iter))
278 retval = gtk_tree_path_new ();
279 gtk_tree_path_append_index (retval, i);
285 gtk_list_store_iter_get_value (GtkTreeModel *tree_model,
290 GtkTreeDataList *list;
291 gint tmp_column = column;
293 g_return_if_fail (tree_model != NULL);
294 g_return_if_fail (GTK_IS_LIST_STORE (tree_model));
295 g_return_if_fail (iter != NULL);
296 g_return_if_fail (column < GTK_LIST_STORE (tree_model)->n_columns);
298 list = G_SLIST (iter)->data;
300 while (tmp_column-- > 0 && list)
303 g_return_if_fail (list != NULL);
305 gtk_tree_data_list_iter_to_value (list,
306 GTK_LIST_STORE (tree_model)->column_headers[column],
311 gtk_list_store_iter_next (GtkTreeModel *tree_model,
314 if (iter == NULL || *iter == NULL)
317 *iter = (GtkTreeIter) G_SLIST (*iter)->next;
319 return (*iter != NULL);
323 gtk_list_store_iter_children (GtkTreeModel *tree_model,
330 gtk_list_store_iter_has_child (GtkTreeModel *tree_model,
337 gtk_list_store_iter_n_children (GtkTreeModel *tree_model,
344 gtk_list_store_iter_nth_child (GtkTreeModel *tree_model,
352 gtk_list_store_iter_parent (GtkTreeModel *tree_model,
358 /* Public accessors */
360 gtk_list_store_iter_new (void)
362 GtkTreeIter retval = (GtkTreeIter) g_slist_alloc ();
367 /* This is a somewhat inelegant function that does a lot of list
368 * manipulations on it's own.
371 gtk_list_store_iter_set_cell (GtkListStore *list_store,
376 GtkTreeDataList *list;
377 GtkTreeDataList *prev;
379 g_return_if_fail (list_store != NULL);
380 g_return_if_fail (GTK_IS_LIST_STORE (list_store));
381 g_return_if_fail (iter != NULL);
382 g_return_if_fail (column >= 0 && column < list_store->n_columns);
384 prev = list = G_SLIST (iter)->data;
390 gtk_tree_data_list_value_to_iter (list, value);
399 if (G_SLIST (iter)->data == NULL)
401 G_SLIST (iter)->data = list = gtk_tree_data_list_alloc ();
406 list = prev->next = gtk_tree_data_list_alloc ();
412 list->next = gtk_tree_data_list_alloc ();
417 gtk_tree_data_list_value_to_iter (list, value);
421 gtk_list_store_iter_remove (GtkListStore *list_store,
424 /* FIXME: implement */
425 g_warning ("Remember to implement this function\n");
429 gtk_list_store_iter_insert (GtkListStore *list_store,
435 g_return_val_if_fail (list_store != NULL, iter);
436 g_return_val_if_fail (GTK_IS_LIST_STORE (list_store), iter);
437 g_return_val_if_fail (iter != NULL, iter);
438 g_return_val_if_fail (position < 0, iter);
439 g_return_val_if_fail (G_SLIST (iter)->next == NULL, iter);
443 gtk_list_store_iter_prepend (list_store, iter);
447 list = g_slist_nth (G_SLIST (list_store->root), position);
450 G_SLIST (iter)->next = list->next;
451 list->next = G_SLIST (iter)->next;
459 gtk_list_store_iter_insert_before (GtkListStore *list_store,
463 g_return_val_if_fail (list_store != NULL, iter);
464 g_return_val_if_fail (GTK_IS_LIST_STORE (list_store), iter);
465 g_return_val_if_fail (iter != NULL, iter);
467 /* FIXME: This is all wrong. This is actually insert_after */
469 return gtk_list_store_iter_prepend (list_store, iter);
471 G_SLIST (iter)->next = G_SLIST (sibling)->next;
472 G_SLIST (sibling)->next = G_SLIST (iter);
477 gtk_list_store_iter_prepend (GtkListStore *list_store,
480 g_return_val_if_fail (list_store != NULL, iter);
481 g_return_val_if_fail (GTK_IS_LIST_STORE (list_store), iter);
482 g_return_val_if_fail (iter != NULL, iter);
484 G_SLIST (iter)->next = G_SLIST (list_store->root);
485 list_store->root = iter;
491 gtk_list_store_iter_append (GtkListStore *list_store,
496 g_return_val_if_fail (list_store != NULL, iter);
497 g_return_val_if_fail (GTK_IS_LIST_STORE (list_store), iter);
498 g_return_val_if_fail (iter != NULL, iter);
499 g_return_val_if_fail (G_SLIST (iter)->next == NULL, iter);
501 list = g_slist_last (G_SLIST (list_store->root));
503 list_store->root = iter;
505 list->next = G_SLIST (iter);
511 gtk_list_store_iter_get_root (GtkListStore *list_store)
513 g_return_val_if_fail (list_store != NULL, NULL);
514 g_return_val_if_fail (GTK_IS_LIST_STORE (list_store), NULL);
516 return (GtkTreeIter *) list_store->root;