diff options
author | Havoc Pennington <hp@redhat.com> | 2001-01-10 23:44:22 +0000 |
---|---|---|
committer | Havoc Pennington <hp@src.gnome.org> | 2001-01-10 23:44:22 +0000 |
commit | 740ee8ef9467725b5cac7c145c4d1c5d065e8f74 (patch) | |
tree | 41d2b89f5e052b309db8950b4f5a45018bb87190 | |
parent | 85267e9224f8ffec7aeafb8ccbed583d60e7bf4c (diff) | |
download | gtk+-740ee8ef9467725b5cac7c145c4d1c5d065e8f74.tar.gz |
handle case where sibling == iter (gtk_tree_store_insert_after): handle
2001-01-10 Havoc Pennington <hp@redhat.com>
* gtk/gtktreestore.c (gtk_tree_store_insert_before): handle case
where sibling == iter
(gtk_tree_store_insert_after): handle sibling == iter
(gtk_tree_store_prepend): remove stamp checks
(gtk_tree_store_insert_before): ditto
(gtk_tree_store_append): ditto
(gtk_tree_store_get_path): ditto
(gtk_tree_store_get_value): ditto
(gtk_tree_store_iter_has_child): ditto
(gtk_tree_store_iter_n_children): ditto
(gtk_tree_store_iter_nth_child): ditto
(gtk_tree_store_insert_after): ditto
(gtk_tree_store_is_ancestor): ditto
(gtk_tree_store_iter_depth): ditto
(gtk_tree_store_insert_before): assert that sibling's parent is
the same as the passed-in parent
(gtk_tree_store_insert_after): assert that sibling's parent is
the same as the passed-in parent
* gtk/gtktreemodel.c (gtk_tree_model_get_first): new convenience
function to get the first iterator in a model
* gtk/gtktreestore.c (gtk_tree_store_get_root_iter): remove,
conventionally the "root" in this sense is just NULL afaict.
* gtk/gtkliststore.c (gtk_list_store_insert_before): handle case
where sibling == iter
(gtk_list_store_insert_after): handle case where sibling == iter
* tests/testtreeview.c (run_automated_tests): fairly lame basic
automated tests for ListStore, TreeStore
* gtk/gtkliststore.c (gtk_list_store_remove): update tail pointer
(gtk_list_store_insert): update tail pointer, and fix it to work
(gtk_list_store_insert_before): update tail pointer, and fix it to work
(gtk_list_store_append): use tail to be faster
(gtk_list_store_prepend): fix it, update tail pointer
(gtk_list_store_insert_after): fix it, update tail pointer
* gtk/gtkliststore.h (struct _GtkListStore): add tail pointer for
the list
-rw-r--r-- | ChangeLog | 45 | ||||
-rw-r--r-- | ChangeLog.pre-2-0 | 45 | ||||
-rw-r--r-- | ChangeLog.pre-2-10 | 45 | ||||
-rw-r--r-- | ChangeLog.pre-2-2 | 45 | ||||
-rw-r--r-- | ChangeLog.pre-2-4 | 45 | ||||
-rw-r--r-- | ChangeLog.pre-2-6 | 45 | ||||
-rw-r--r-- | ChangeLog.pre-2-8 | 45 | ||||
-rw-r--r-- | gtk/gtkliststore.c | 156 | ||||
-rw-r--r-- | gtk/gtkliststore.h | 1 | ||||
-rw-r--r-- | gtk/gtktreemodel.c | 30 | ||||
-rw-r--r-- | gtk/gtktreemodel.h | 2 | ||||
-rw-r--r-- | gtk/gtktreestore.c | 105 | ||||
-rw-r--r-- | gtk/gtktreestore.h | 2 | ||||
-rw-r--r-- | tests/testtreeview.c | 178 |
14 files changed, 692 insertions, 97 deletions
@@ -1,3 +1,48 @@ +2001-01-10 Havoc Pennington <hp@redhat.com> + + * gtk/gtktreestore.c (gtk_tree_store_insert_before): handle case + where sibling == iter + (gtk_tree_store_insert_after): handle sibling == iter + (gtk_tree_store_prepend): remove stamp checks + (gtk_tree_store_insert_before): ditto + (gtk_tree_store_append): ditto + (gtk_tree_store_get_path): ditto + (gtk_tree_store_get_value): ditto + (gtk_tree_store_iter_has_child): ditto + (gtk_tree_store_iter_n_children): ditto + (gtk_tree_store_iter_nth_child): ditto + (gtk_tree_store_insert_after): ditto + (gtk_tree_store_is_ancestor): ditto + (gtk_tree_store_iter_depth): ditto + (gtk_tree_store_insert_before): assert that sibling's parent is + the same as the passed-in parent + (gtk_tree_store_insert_after): assert that sibling's parent is + the same as the passed-in parent + + + * gtk/gtktreemodel.c (gtk_tree_model_get_first): new convenience + function to get the first iterator in a model + + * gtk/gtktreestore.c (gtk_tree_store_get_root_iter): remove, + conventionally the "root" in this sense is just NULL afaict. + + * gtk/gtkliststore.c (gtk_list_store_insert_before): handle case + where sibling == iter + (gtk_list_store_insert_after): handle case where sibling == iter + + * tests/testtreeview.c (run_automated_tests): fairly lame basic + automated tests for ListStore, TreeStore + + * gtk/gtkliststore.c (gtk_list_store_remove): update tail pointer + (gtk_list_store_insert): update tail pointer, and fix it to work + (gtk_list_store_insert_before): update tail pointer, and fix it to work + (gtk_list_store_append): use tail to be faster + (gtk_list_store_prepend): fix it, update tail pointer + (gtk_list_store_insert_after): fix it, update tail pointer + + * gtk/gtkliststore.h (struct _GtkListStore): add tail pointer for + the list + 2001-01-09 Havoc Pennington <hp@redhat.com> * gtk/gtklabel.c (gtk_label_expose): don't draw if label->layout diff --git a/ChangeLog.pre-2-0 b/ChangeLog.pre-2-0 index 39ee2fb828..8e480dd1dc 100644 --- a/ChangeLog.pre-2-0 +++ b/ChangeLog.pre-2-0 @@ -1,3 +1,48 @@ +2001-01-10 Havoc Pennington <hp@redhat.com> + + * gtk/gtktreestore.c (gtk_tree_store_insert_before): handle case + where sibling == iter + (gtk_tree_store_insert_after): handle sibling == iter + (gtk_tree_store_prepend): remove stamp checks + (gtk_tree_store_insert_before): ditto + (gtk_tree_store_append): ditto + (gtk_tree_store_get_path): ditto + (gtk_tree_store_get_value): ditto + (gtk_tree_store_iter_has_child): ditto + (gtk_tree_store_iter_n_children): ditto + (gtk_tree_store_iter_nth_child): ditto + (gtk_tree_store_insert_after): ditto + (gtk_tree_store_is_ancestor): ditto + (gtk_tree_store_iter_depth): ditto + (gtk_tree_store_insert_before): assert that sibling's parent is + the same as the passed-in parent + (gtk_tree_store_insert_after): assert that sibling's parent is + the same as the passed-in parent + + + * gtk/gtktreemodel.c (gtk_tree_model_get_first): new convenience + function to get the first iterator in a model + + * gtk/gtktreestore.c (gtk_tree_store_get_root_iter): remove, + conventionally the "root" in this sense is just NULL afaict. + + * gtk/gtkliststore.c (gtk_list_store_insert_before): handle case + where sibling == iter + (gtk_list_store_insert_after): handle case where sibling == iter + + * tests/testtreeview.c (run_automated_tests): fairly lame basic + automated tests for ListStore, TreeStore + + * gtk/gtkliststore.c (gtk_list_store_remove): update tail pointer + (gtk_list_store_insert): update tail pointer, and fix it to work + (gtk_list_store_insert_before): update tail pointer, and fix it to work + (gtk_list_store_append): use tail to be faster + (gtk_list_store_prepend): fix it, update tail pointer + (gtk_list_store_insert_after): fix it, update tail pointer + + * gtk/gtkliststore.h (struct _GtkListStore): add tail pointer for + the list + 2001-01-09 Havoc Pennington <hp@redhat.com> * gtk/gtklabel.c (gtk_label_expose): don't draw if label->layout diff --git a/ChangeLog.pre-2-10 b/ChangeLog.pre-2-10 index 39ee2fb828..8e480dd1dc 100644 --- a/ChangeLog.pre-2-10 +++ b/ChangeLog.pre-2-10 @@ -1,3 +1,48 @@ +2001-01-10 Havoc Pennington <hp@redhat.com> + + * gtk/gtktreestore.c (gtk_tree_store_insert_before): handle case + where sibling == iter + (gtk_tree_store_insert_after): handle sibling == iter + (gtk_tree_store_prepend): remove stamp checks + (gtk_tree_store_insert_before): ditto + (gtk_tree_store_append): ditto + (gtk_tree_store_get_path): ditto + (gtk_tree_store_get_value): ditto + (gtk_tree_store_iter_has_child): ditto + (gtk_tree_store_iter_n_children): ditto + (gtk_tree_store_iter_nth_child): ditto + (gtk_tree_store_insert_after): ditto + (gtk_tree_store_is_ancestor): ditto + (gtk_tree_store_iter_depth): ditto + (gtk_tree_store_insert_before): assert that sibling's parent is + the same as the passed-in parent + (gtk_tree_store_insert_after): assert that sibling's parent is + the same as the passed-in parent + + + * gtk/gtktreemodel.c (gtk_tree_model_get_first): new convenience + function to get the first iterator in a model + + * gtk/gtktreestore.c (gtk_tree_store_get_root_iter): remove, + conventionally the "root" in this sense is just NULL afaict. + + * gtk/gtkliststore.c (gtk_list_store_insert_before): handle case + where sibling == iter + (gtk_list_store_insert_after): handle case where sibling == iter + + * tests/testtreeview.c (run_automated_tests): fairly lame basic + automated tests for ListStore, TreeStore + + * gtk/gtkliststore.c (gtk_list_store_remove): update tail pointer + (gtk_list_store_insert): update tail pointer, and fix it to work + (gtk_list_store_insert_before): update tail pointer, and fix it to work + (gtk_list_store_append): use tail to be faster + (gtk_list_store_prepend): fix it, update tail pointer + (gtk_list_store_insert_after): fix it, update tail pointer + + * gtk/gtkliststore.h (struct _GtkListStore): add tail pointer for + the list + 2001-01-09 Havoc Pennington <hp@redhat.com> * gtk/gtklabel.c (gtk_label_expose): don't draw if label->layout diff --git a/ChangeLog.pre-2-2 b/ChangeLog.pre-2-2 index 39ee2fb828..8e480dd1dc 100644 --- a/ChangeLog.pre-2-2 +++ b/ChangeLog.pre-2-2 @@ -1,3 +1,48 @@ +2001-01-10 Havoc Pennington <hp@redhat.com> + + * gtk/gtktreestore.c (gtk_tree_store_insert_before): handle case + where sibling == iter + (gtk_tree_store_insert_after): handle sibling == iter + (gtk_tree_store_prepend): remove stamp checks + (gtk_tree_store_insert_before): ditto + (gtk_tree_store_append): ditto + (gtk_tree_store_get_path): ditto + (gtk_tree_store_get_value): ditto + (gtk_tree_store_iter_has_child): ditto + (gtk_tree_store_iter_n_children): ditto + (gtk_tree_store_iter_nth_child): ditto + (gtk_tree_store_insert_after): ditto + (gtk_tree_store_is_ancestor): ditto + (gtk_tree_store_iter_depth): ditto + (gtk_tree_store_insert_before): assert that sibling's parent is + the same as the passed-in parent + (gtk_tree_store_insert_after): assert that sibling's parent is + the same as the passed-in parent + + + * gtk/gtktreemodel.c (gtk_tree_model_get_first): new convenience + function to get the first iterator in a model + + * gtk/gtktreestore.c (gtk_tree_store_get_root_iter): remove, + conventionally the "root" in this sense is just NULL afaict. + + * gtk/gtkliststore.c (gtk_list_store_insert_before): handle case + where sibling == iter + (gtk_list_store_insert_after): handle case where sibling == iter + + * tests/testtreeview.c (run_automated_tests): fairly lame basic + automated tests for ListStore, TreeStore + + * gtk/gtkliststore.c (gtk_list_store_remove): update tail pointer + (gtk_list_store_insert): update tail pointer, and fix it to work + (gtk_list_store_insert_before): update tail pointer, and fix it to work + (gtk_list_store_append): use tail to be faster + (gtk_list_store_prepend): fix it, update tail pointer + (gtk_list_store_insert_after): fix it, update tail pointer + + * gtk/gtkliststore.h (struct _GtkListStore): add tail pointer for + the list + 2001-01-09 Havoc Pennington <hp@redhat.com> * gtk/gtklabel.c (gtk_label_expose): don't draw if label->layout diff --git a/ChangeLog.pre-2-4 b/ChangeLog.pre-2-4 index 39ee2fb828..8e480dd1dc 100644 --- a/ChangeLog.pre-2-4 +++ b/ChangeLog.pre-2-4 @@ -1,3 +1,48 @@ +2001-01-10 Havoc Pennington <hp@redhat.com> + + * gtk/gtktreestore.c (gtk_tree_store_insert_before): handle case + where sibling == iter + (gtk_tree_store_insert_after): handle sibling == iter + (gtk_tree_store_prepend): remove stamp checks + (gtk_tree_store_insert_before): ditto + (gtk_tree_store_append): ditto + (gtk_tree_store_get_path): ditto + (gtk_tree_store_get_value): ditto + (gtk_tree_store_iter_has_child): ditto + (gtk_tree_store_iter_n_children): ditto + (gtk_tree_store_iter_nth_child): ditto + (gtk_tree_store_insert_after): ditto + (gtk_tree_store_is_ancestor): ditto + (gtk_tree_store_iter_depth): ditto + (gtk_tree_store_insert_before): assert that sibling's parent is + the same as the passed-in parent + (gtk_tree_store_insert_after): assert that sibling's parent is + the same as the passed-in parent + + + * gtk/gtktreemodel.c (gtk_tree_model_get_first): new convenience + function to get the first iterator in a model + + * gtk/gtktreestore.c (gtk_tree_store_get_root_iter): remove, + conventionally the "root" in this sense is just NULL afaict. + + * gtk/gtkliststore.c (gtk_list_store_insert_before): handle case + where sibling == iter + (gtk_list_store_insert_after): handle case where sibling == iter + + * tests/testtreeview.c (run_automated_tests): fairly lame basic + automated tests for ListStore, TreeStore + + * gtk/gtkliststore.c (gtk_list_store_remove): update tail pointer + (gtk_list_store_insert): update tail pointer, and fix it to work + (gtk_list_store_insert_before): update tail pointer, and fix it to work + (gtk_list_store_append): use tail to be faster + (gtk_list_store_prepend): fix it, update tail pointer + (gtk_list_store_insert_after): fix it, update tail pointer + + * gtk/gtkliststore.h (struct _GtkListStore): add tail pointer for + the list + 2001-01-09 Havoc Pennington <hp@redhat.com> * gtk/gtklabel.c (gtk_label_expose): don't draw if label->layout diff --git a/ChangeLog.pre-2-6 b/ChangeLog.pre-2-6 index 39ee2fb828..8e480dd1dc 100644 --- a/ChangeLog.pre-2-6 +++ b/ChangeLog.pre-2-6 @@ -1,3 +1,48 @@ +2001-01-10 Havoc Pennington <hp@redhat.com> + + * gtk/gtktreestore.c (gtk_tree_store_insert_before): handle case + where sibling == iter + (gtk_tree_store_insert_after): handle sibling == iter + (gtk_tree_store_prepend): remove stamp checks + (gtk_tree_store_insert_before): ditto + (gtk_tree_store_append): ditto + (gtk_tree_store_get_path): ditto + (gtk_tree_store_get_value): ditto + (gtk_tree_store_iter_has_child): ditto + (gtk_tree_store_iter_n_children): ditto + (gtk_tree_store_iter_nth_child): ditto + (gtk_tree_store_insert_after): ditto + (gtk_tree_store_is_ancestor): ditto + (gtk_tree_store_iter_depth): ditto + (gtk_tree_store_insert_before): assert that sibling's parent is + the same as the passed-in parent + (gtk_tree_store_insert_after): assert that sibling's parent is + the same as the passed-in parent + + + * gtk/gtktreemodel.c (gtk_tree_model_get_first): new convenience + function to get the first iterator in a model + + * gtk/gtktreestore.c (gtk_tree_store_get_root_iter): remove, + conventionally the "root" in this sense is just NULL afaict. + + * gtk/gtkliststore.c (gtk_list_store_insert_before): handle case + where sibling == iter + (gtk_list_store_insert_after): handle case where sibling == iter + + * tests/testtreeview.c (run_automated_tests): fairly lame basic + automated tests for ListStore, TreeStore + + * gtk/gtkliststore.c (gtk_list_store_remove): update tail pointer + (gtk_list_store_insert): update tail pointer, and fix it to work + (gtk_list_store_insert_before): update tail pointer, and fix it to work + (gtk_list_store_append): use tail to be faster + (gtk_list_store_prepend): fix it, update tail pointer + (gtk_list_store_insert_after): fix it, update tail pointer + + * gtk/gtkliststore.h (struct _GtkListStore): add tail pointer for + the list + 2001-01-09 Havoc Pennington <hp@redhat.com> * gtk/gtklabel.c (gtk_label_expose): don't draw if label->layout diff --git a/ChangeLog.pre-2-8 b/ChangeLog.pre-2-8 index 39ee2fb828..8e480dd1dc 100644 --- a/ChangeLog.pre-2-8 +++ b/ChangeLog.pre-2-8 @@ -1,3 +1,48 @@ +2001-01-10 Havoc Pennington <hp@redhat.com> + + * gtk/gtktreestore.c (gtk_tree_store_insert_before): handle case + where sibling == iter + (gtk_tree_store_insert_after): handle sibling == iter + (gtk_tree_store_prepend): remove stamp checks + (gtk_tree_store_insert_before): ditto + (gtk_tree_store_append): ditto + (gtk_tree_store_get_path): ditto + (gtk_tree_store_get_value): ditto + (gtk_tree_store_iter_has_child): ditto + (gtk_tree_store_iter_n_children): ditto + (gtk_tree_store_iter_nth_child): ditto + (gtk_tree_store_insert_after): ditto + (gtk_tree_store_is_ancestor): ditto + (gtk_tree_store_iter_depth): ditto + (gtk_tree_store_insert_before): assert that sibling's parent is + the same as the passed-in parent + (gtk_tree_store_insert_after): assert that sibling's parent is + the same as the passed-in parent + + + * gtk/gtktreemodel.c (gtk_tree_model_get_first): new convenience + function to get the first iterator in a model + + * gtk/gtktreestore.c (gtk_tree_store_get_root_iter): remove, + conventionally the "root" in this sense is just NULL afaict. + + * gtk/gtkliststore.c (gtk_list_store_insert_before): handle case + where sibling == iter + (gtk_list_store_insert_after): handle case where sibling == iter + + * tests/testtreeview.c (run_automated_tests): fairly lame basic + automated tests for ListStore, TreeStore + + * gtk/gtkliststore.c (gtk_list_store_remove): update tail pointer + (gtk_list_store_insert): update tail pointer, and fix it to work + (gtk_list_store_insert_before): update tail pointer, and fix it to work + (gtk_list_store_append): use tail to be faster + (gtk_list_store_prepend): fix it, update tail pointer + (gtk_list_store_insert_after): fix it, update tail pointer + + * gtk/gtkliststore.h (struct _GtkListStore): add tail pointer for + the list + 2001-01-09 Havoc Pennington <hp@redhat.com> * gtk/gtklabel.c (gtk_label_expose): don't draw if label->layout diff --git a/gtk/gtkliststore.c b/gtk/gtkliststore.c index 8c6b4cff16..b045f2e60d 100644 --- a/gtk/gtkliststore.c +++ b/gtk/gtkliststore.c @@ -171,6 +171,7 @@ static void gtk_list_store_init (GtkListStore *list_store) { list_store->root = NULL; + list_store->tail = NULL; list_store->stamp = g_random_int (); } @@ -612,6 +613,39 @@ gtk_list_store_get (GtkListStore *list_store, va_end (var_args); } +static GSList* +remove_link_saving_prev (GSList *list, + GSList *link, + GSList **prevp) +{ + GSList *tmp; + GSList *prev; + + prev = NULL; + tmp = list; + + while (tmp) + { + if (tmp == link) + { + if (prev) + prev->next = tmp->next; + if (list == tmp) + list = list->next; + + tmp->next = NULL; + break; + } + + prev = tmp; + tmp = tmp->next; + } + + *prevp = prev; + + return list; +} + void gtk_list_store_remove (GtkListStore *list_store, GtkTreeIter *iter) @@ -620,14 +654,25 @@ gtk_list_store_remove (GtkListStore *list_store, g_return_if_fail (list_store != NULL); g_return_if_fail (GTK_IS_LIST_STORE (list_store)); - + g_return_if_fail (iter->user_data != NULL); + if (G_SLIST (iter->user_data)->data) _gtk_tree_data_list_free ((GtkTreeDataList *) G_SLIST (iter->user_data)->data, list_store->column_headers); path = gtk_list_store_get_path (GTK_TREE_MODEL (list_store), iter); - list_store->root = g_slist_remove_link (G_SLIST (list_store->root), - G_SLIST (iter->user_data)); + + { + GSList *prev = NULL; + + list_store->root = remove_link_saving_prev (G_SLIST (list_store->root), + G_SLIST (iter->user_data), + &prev); + + if (iter->user_data == list_store->tail) + list_store->tail = prev; + } + list_store->stamp ++; gtk_signal_emit_by_name (GTK_OBJECT (list_store), "deleted", @@ -635,6 +680,23 @@ gtk_list_store_remove (GtkListStore *list_store, gtk_tree_path_free (path); } +static void +insert_after (GtkListStore *list_store, + GSList *sibling, + GSList *new_list) +{ + g_return_if_fail (sibling != NULL); + g_return_if_fail (new_list != NULL); + + /* insert new node after list */ + new_list->next = sibling->next; + sibling->next = new_list; + + /* if list was the tail, the new node is the new tail */ + if (sibling == list_store->tail) + list_store->tail = new_list; +} + void gtk_list_store_insert (GtkListStore *list_store, GtkTreeIter *iter, @@ -642,11 +704,12 @@ gtk_list_store_insert (GtkListStore *list_store, { GSList *list; GtkTreePath *path; - + GSList *new_list; + g_return_if_fail (list_store != NULL); g_return_if_fail (GTK_IS_LIST_STORE (list_store)); g_return_if_fail (iter != NULL); - g_return_if_fail (position < 0); + g_return_if_fail (position >= 0); if (position == 0) { @@ -654,15 +717,21 @@ gtk_list_store_insert (GtkListStore *list_store, return; } - iter->stamp = list_store->stamp; - iter->user_data = g_slist_alloc (); + new_list = g_slist_alloc (); list = g_slist_nth (G_SLIST (list_store->root), position - 1); - if (list) + + if (list == NULL) { - G_SLIST (iter->user_data)->next = list->next; - list->next = G_SLIST (iter->user_data)->next; + g_warning ("%s: position %d is off the end of the list\n", G_STRLOC, position); + return; } + + insert_after (list_store, list, new_list); + + iter->stamp = list_store->stamp; + iter->user_data = new_list; + path = gtk_tree_path_new (); gtk_tree_path_append_index (path, position); gtk_signal_emit_by_name (GTK_OBJECT (list_store), @@ -677,22 +746,20 @@ gtk_list_store_insert_before (GtkListStore *list_store, GtkTreeIter *sibling) { GtkTreePath *path; - GSList *list, *prev; + GSList *list, *prev, *new_list; gint i = 0; g_return_if_fail (list_store != NULL); g_return_if_fail (GTK_IS_LIST_STORE (list_store)); g_return_if_fail (iter != NULL); - g_return_if_fail (G_SLIST (iter)->next == NULL); if (sibling == NULL) { gtk_list_store_append (list_store, iter); return; } - - iter->stamp = list_store->stamp; - iter->user_data = g_slist_alloc (); + + new_list = g_slist_alloc (); prev = list = list_store->root; while (list && list != sibling->user_data) @@ -701,17 +768,35 @@ gtk_list_store_insert_before (GtkListStore *list_store, list = list->next; i++; } + + if (list != sibling->user_data) + { + g_warning ("%s: sibling iterator invalid? not found in the list", G_STRLOC); + return; + } + + /* if there are no nodes, we become the list tail, otherwise we + * are inserting before any existing nodes so we can't change + * the tail + */ + + if (list_store->root == NULL) + list_store->tail = new_list; if (prev) { - prev->next = iter->user_data; + new_list->next = prev->next; + prev->next = new_list; } else { - G_SLIST (iter->user_data)->next = list_store->root; - list_store->root = iter->user_data; + new_list->next = list_store->root; + list_store->root = new_list; } + iter->stamp = list_store->stamp; + iter->user_data = new_list; + path = gtk_tree_path_new (); gtk_tree_path_append_index (path, i); gtk_signal_emit_by_name (GTK_OBJECT (list_store), @@ -726,12 +811,12 @@ gtk_list_store_insert_after (GtkListStore *list_store, GtkTreeIter *sibling) { GtkTreePath *path; - GSList *list; + GSList *list, *new_list; gint i = 0; g_return_if_fail (list_store != NULL); g_return_if_fail (GTK_IS_LIST_STORE (list_store)); - g_return_if_fail (iter == NULL); + g_return_if_fail (iter != NULL); if (sibling) g_return_if_fail (sibling->stamp == list_store->stamp); @@ -744,14 +829,15 @@ gtk_list_store_insert_after (GtkListStore *list_store, for (list = list_store->root; list && list != sibling->user_data; list = list->next) i++; - g_return_if_fail (list != NULL); + g_return_if_fail (list == sibling->user_data); - iter->stamp = list_store->stamp; - iter->user_data = g_slist_alloc (); - - G_SLIST (iter->user_data)->next = G_SLIST (sibling->user_data)->next; - G_SLIST (sibling)->next = G_SLIST (iter); + new_list = g_slist_alloc (); + insert_after (list_store, list, new_list); + + iter->stamp = list_store->stamp; + iter->user_data = new_list; + path = gtk_tree_path_new (); gtk_tree_path_append_index (path, i); gtk_signal_emit_by_name (GTK_OBJECT (list_store), @@ -773,6 +859,9 @@ gtk_list_store_prepend (GtkListStore *list_store, iter->stamp = list_store->stamp; iter->user_data = g_slist_alloc (); + if (list_store->root == NULL) + list_store->tail = iter->user_data; + G_SLIST (iter->user_data)->next = G_SLIST (list_store->root); list_store->root = iter->user_data; @@ -789,7 +878,6 @@ gtk_list_store_append (GtkListStore *list_store, GtkTreeIter *iter) { GtkTreePath *path; - GSList *list, *prev; gint i = 0; g_return_if_fail (list_store != NULL); @@ -799,19 +887,13 @@ gtk_list_store_append (GtkListStore *list_store, iter->stamp = list_store->stamp; iter->user_data = g_slist_alloc (); - prev = list = list_store->root; - while (list) - { - prev = list; - list = list->next; - i++; - } - - if (prev) - prev->next = iter->user_data; + if (list_store->tail) + list_store->tail->next = iter->user_data; else list_store->root = iter->user_data; + list_store->tail = iter->user_data; + path = gtk_tree_path_new (); gtk_tree_path_append_index (path, i); gtk_signal_emit_by_name (GTK_OBJECT (list_store), diff --git a/gtk/gtkliststore.h b/gtk/gtkliststore.h index ff01ea37fc..55ad276a01 100644 --- a/gtk/gtkliststore.h +++ b/gtk/gtkliststore.h @@ -42,6 +42,7 @@ struct _GtkListStore /*< private >*/ gint stamp; gpointer root; + GSList *tail; gint n_columns; GType *column_headers; }; diff --git a/gtk/gtktreemodel.c b/gtk/gtktreemodel.c index b3bbaca07d..c1afaa3e51 100644 --- a/gtk/gtktreemodel.c +++ b/gtk/gtktreemodel.c @@ -543,6 +543,36 @@ gtk_tree_model_get_iter (GtkTreeModel *tree_model, } /** + * gtk_tree_model_get_first: + * @tree_model: a #GtkTreeModel + * @iter: iterator to initialize + * + * Initialized @iter with the first iterator in the tree (the one at the + * root path) and returns %TRUE, or returns %FALSE if there are no + * iterable locations in the model (i.e. the tree is empty). + * + * Return value: %TRUE if @iter was initialized + **/ +gboolean +gtk_tree_model_get_first (GtkTreeModel *tree_model, + GtkTreeIter *iter) +{ + gboolean retval; + GtkTreePath *path; + + g_return_val_if_fail (GTK_IS_TREE_MODEL (tree_model), FALSE); + g_return_val_if_fail (iter != NULL, FALSE); + + path = gtk_tree_path_new_root (); + + retval = gtk_tree_model_get_iter (tree_model, iter, path); + + gtk_tree_path_free (path); + + return retval; +} + +/** * gtk_tree_model_get_path: * @tree_model: A #GtkTreeModel. * @iter: The #GtkTreeIter. diff --git a/gtk/gtktreemodel.h b/gtk/gtktreemodel.h index c91a7b60f5..74fd34da7e 100644 --- a/gtk/gtktreemodel.h +++ b/gtk/gtktreemodel.h @@ -152,6 +152,8 @@ GType gtk_tree_model_get_column_type (GtkTreeModel *tree_model, gboolean gtk_tree_model_get_iter (GtkTreeModel *tree_model, GtkTreeIter *iter, GtkTreePath *path); +gboolean gtk_tree_model_get_first (GtkTreeModel *tree_model, + GtkTreeIter *iter); GtkTreePath *gtk_tree_model_get_path (GtkTreeModel *tree_model, GtkTreeIter *iter); void gtk_tree_model_get_value (GtkTreeModel *tree_model, diff --git a/gtk/gtktreestore.c b/gtk/gtktreestore.c index 0c4bc516df..aa8c658368 100644 --- a/gtk/gtktreestore.c +++ b/gtk/gtktreestore.c @@ -285,10 +285,12 @@ gtk_tree_store_get_path (GtkTreeModel *tree_model, g_return_val_if_fail (tree_model != NULL, NULL); g_return_val_if_fail (GTK_IS_TREE_STORE (tree_model), NULL); g_return_val_if_fail (iter != NULL, NULL); - g_return_val_if_fail (GTK_TREE_STORE (tree_model)->stamp == iter->stamp, NULL); + if (iter->user_data == NULL) return NULL; + g_assert (G_NODE (iter->user_data)->parent != NULL); + if (G_NODE (iter->user_data)->parent == G_NODE (GTK_TREE_STORE (tree_model)->root)) { retval = gtk_tree_path_new (); @@ -346,7 +348,6 @@ gtk_tree_store_get_value (GtkTreeModel *tree_model, g_return_if_fail (tree_model != NULL); g_return_if_fail (GTK_IS_TREE_STORE (tree_model)); g_return_if_fail (iter != NULL); - g_return_if_fail (iter->stamp == GTK_TREE_STORE (tree_model)->stamp); g_return_if_fail (column < GTK_TREE_STORE (tree_model)->n_columns); list = G_NODE (iter->user_data)->data; @@ -400,7 +401,6 @@ gtk_tree_store_iter_has_child (GtkTreeModel *tree_model, g_return_val_if_fail (tree_model != NULL, FALSE); g_return_val_if_fail (GTK_IS_TREE_STORE (tree_model), FALSE); g_return_val_if_fail (iter != NULL, FALSE); - g_return_val_if_fail (iter->stamp == GTK_TREE_STORE (tree_model)->stamp, FALSE); return G_NODE (iter->user_data)->children != NULL; } @@ -414,8 +414,6 @@ gtk_tree_store_iter_n_children (GtkTreeModel *tree_model, g_return_val_if_fail (tree_model != NULL, 0); g_return_val_if_fail (GTK_IS_TREE_STORE (tree_model), 0); - if (iter) - g_return_val_if_fail (iter->stamp == GTK_TREE_STORE (tree_model)->stamp, 0); if (iter == NULL) node = G_NODE (GTK_TREE_STORE (tree_model)->root)->children; @@ -441,8 +439,6 @@ gtk_tree_store_iter_nth_child (GtkTreeModel *tree_model, g_return_val_if_fail (tree_model != NULL, FALSE); g_return_val_if_fail (GTK_IS_TREE_STORE (tree_model), FALSE); g_return_val_if_fail (iter != NULL, FALSE); - if (parent) - g_return_val_if_fail (parent->stamp == GTK_TREE_STORE (tree_model)->stamp, FALSE); if (parent == NULL) parent_node = GTK_TREE_STORE (tree_model)->root; @@ -464,12 +460,15 @@ gtk_tree_store_iter_parent (GtkTreeModel *tree_model, GtkTreeIter *iter, GtkTreeIter *child) { + g_assert (G_NODE (child->user_data)->parent != NULL); + iter->stamp = GTK_TREE_STORE (tree_model)->stamp; iter->user_data = G_NODE (child->user_data)->parent; if (iter->user_data == GTK_TREE_STORE (tree_model)->root) { iter->stamp = 0; + iter->user_data = NULL; return FALSE; } @@ -677,6 +676,8 @@ gtk_tree_store_remove (GtkTreeStore *model, parent = G_NODE (iter->user_data)->parent; + g_assert (parent != NULL); + if (G_NODE (iter->user_data)->data) _gtk_tree_data_list_free ((GtkTreeDataList *) G_NODE (iter->user_data)->data, model->column_headers); @@ -691,6 +692,7 @@ gtk_tree_store_remove (GtkTreeStore *model, if (parent != G_NODE (model->root) && parent->children == NULL) { gtk_tree_path_up (path); + gtk_signal_emit_by_name (GTK_OBJECT (model), "child_toggled", path, @@ -706,7 +708,7 @@ gtk_tree_store_insert (GtkTreeStore *model, gint position) { GtkTreePath *path; - + g_return_if_fail (model != NULL); g_return_if_fail (GTK_IS_TREE_STORE (model)); @@ -731,30 +733,35 @@ gtk_tree_store_insert_before (GtkTreeStore *model, GtkTreeIter *sibling) { GtkTreePath *path; - GNode *parent_node = NULL; - + GNode *parent_node = NULL; + GNode *new_node; + g_return_if_fail (model != NULL); g_return_if_fail (GTK_IS_TREE_STORE (model)); g_return_if_fail (iter != NULL); - if (parent != NULL) - g_return_if_fail (parent->stamp == model->stamp); - if (sibling != NULL) - g_return_if_fail (sibling->stamp == model->stamp); - iter->stamp = model->stamp; - iter->user_data = g_node_new (NULL); + new_node = g_node_new (NULL); if (parent == NULL && sibling == NULL) parent_node = model->root; else if (parent == NULL) parent_node = G_NODE (sibling->user_data)->parent; - else + else if (sibling == NULL) parent_node = G_NODE (parent->user_data); + else + { + g_return_if_fail (G_NODE (sibling->user_data)->parent == + G_NODE (parent->user_data)); + parent_node = G_NODE (parent->user_data); + } g_node_insert_before (parent_node, sibling ? G_NODE (sibling->user_data) : NULL, - G_NODE (iter->user_data)); + new_node); + iter->stamp = model->stamp; + iter->user_data = new_node; + path = gtk_tree_store_get_path (GTK_TREE_MODEL (model), iter); gtk_signal_emit_by_name (GTK_OBJECT (model), "inserted", @@ -770,29 +777,35 @@ gtk_tree_store_insert_after (GtkTreeStore *model, { GtkTreePath *path; GNode *parent_node; - + GNode *new_node; + g_return_if_fail (model != NULL); g_return_if_fail (GTK_IS_TREE_STORE (model)); g_return_if_fail (iter != NULL); - if (parent != NULL) - g_return_if_fail (parent->stamp == model->stamp); - if (sibling != NULL) - g_return_if_fail (sibling->stamp == model->stamp); - iter->stamp = model->stamp; - iter->user_data = g_node_new (NULL); + new_node = g_node_new (NULL); if (parent == NULL && sibling == NULL) parent_node = model->root; else if (parent == NULL) parent_node = G_NODE (sibling->user_data)->parent; - else + else if (sibling == NULL) parent_node = G_NODE (parent->user_data); + else + { + g_return_if_fail (G_NODE (sibling->user_data)->parent == + G_NODE (parent->user_data)); + parent_node = G_NODE (parent->user_data); + } + g_node_insert_after (parent_node, sibling ? G_NODE (sibling->user_data) : NULL, - G_NODE (iter->user_data)); - + new_node); + + iter->stamp = model->stamp; + iter->user_data = new_node; + path = gtk_tree_store_get_path (GTK_TREE_MODEL (model), iter); gtk_signal_emit_by_name (GTK_OBJECT (model), "inserted", @@ -806,27 +819,25 @@ gtk_tree_store_prepend (GtkTreeStore *model, GtkTreeIter *parent) { GNode *parent_node; - + g_return_if_fail (model != NULL); g_return_if_fail (GTK_IS_TREE_STORE (model)); g_return_if_fail (iter != NULL); - if (parent != NULL) - g_return_if_fail (parent->stamp == model->stamp); if (parent == NULL) parent_node = model->root; else parent_node = parent->user_data; - - iter->stamp = model->stamp; - iter->user_data = g_node_new (NULL); - + if (parent_node->children == NULL) { GtkTreePath *path; - - g_node_prepend (parent_node, G_NODE (iter->user_data)); - + + iter->stamp = model->stamp; + iter->user_data = g_node_new (NULL); + + g_node_prepend (parent_node, iter->user_data); + if (parent_node != model->root) { path = gtk_tree_store_get_path (GTK_TREE_MODEL (model), parent); @@ -862,8 +873,6 @@ gtk_tree_store_append (GtkTreeStore *model, g_return_if_fail (model != NULL); g_return_if_fail (GTK_IS_TREE_STORE (model)); g_return_if_fail (iter != NULL); - if (parent != NULL) - g_return_if_fail (parent->stamp == model->stamp); if (parent == NULL) parent_node = model->root; @@ -904,19 +913,6 @@ gtk_tree_store_append (GtkTreeStore *model, } } -void -gtk_tree_store_get_root_iter (GtkTreeStore *model, - GtkTreeIter *iter) -{ - g_return_if_fail (model != NULL); - g_return_if_fail (GTK_IS_TREE_STORE (model)); - g_return_if_fail (iter != NULL); - - iter->stamp = model->stamp; - iter->user_data = G_NODE (model->root)->children; -} - - gboolean gtk_tree_store_is_ancestor (GtkTreeStore *model, GtkTreeIter *iter, @@ -926,8 +922,6 @@ gtk_tree_store_is_ancestor (GtkTreeStore *model, g_return_val_if_fail (GTK_IS_TREE_STORE (model), FALSE); g_return_val_if_fail (iter != NULL, FALSE); g_return_val_if_fail (descendant != NULL, FALSE); - g_return_val_if_fail (iter->stamp == model->stamp, FALSE); - g_return_val_if_fail (descendant->stamp == model->stamp, FALSE); return g_node_is_ancestor (G_NODE (iter->user_data), G_NODE (descendant->user_data)); @@ -941,7 +935,6 @@ gtk_tree_store_iter_depth (GtkTreeStore *model, g_return_val_if_fail (model != NULL, 0); g_return_val_if_fail (GTK_IS_TREE_STORE (model), 0); g_return_val_if_fail (iter != NULL, 0); - g_return_val_if_fail (iter->stamp == model->stamp, 0); return g_node_depth (G_NODE (iter->user_data)) - 1; } diff --git a/gtk/gtktreestore.h b/gtk/gtktreestore.h index ab6abefa1d..b56c3f8ce4 100644 --- a/gtk/gtktreestore.h +++ b/gtk/gtktreestore.h @@ -113,8 +113,6 @@ void gtk_tree_store_prepend (GtkTreeStore *tree_store, void gtk_tree_store_append (GtkTreeStore *tree_store, GtkTreeIter *iter, GtkTreeIter *parent); -void gtk_tree_store_get_root_iter (GtkTreeStore *tree_store, - GtkTreeIter *iter); gboolean gtk_tree_store_is_ancestor (GtkTreeStore *tree_store, GtkTreeIter *iter, GtkTreeIter *descendant); diff --git a/tests/testtreeview.c b/tests/testtreeview.c index 3ddaf6e897..dae6baab84 100644 --- a/tests/testtreeview.c +++ b/tests/testtreeview.c @@ -1372,10 +1372,184 @@ create_prop_editor (GObject *object) */ static void +treestore_torture_recurse (GtkTreeStore *store, + GtkTreeIter *root, + gint depth) +{ + GtkTreeModel *model; + gint i; + GtkTreeIter iter; + + model = GTK_TREE_MODEL (store); + + if (depth > 2) + return; + + ++depth; + + gtk_tree_store_append (store, &iter, root); + + gtk_tree_model_iter_children (model, &iter, root); + + i = 0; + while (i < 100) + { + gtk_tree_store_append (store, &iter, root); + ++i; + } + + while (gtk_tree_model_iter_children (model, &iter, root)) + gtk_tree_store_remove (store, &iter); + + gtk_tree_store_append (store, &iter, root); + + /* inserts before last node in tree */ + i = 0; + while (i < 100) + { + gtk_tree_store_insert_before (store, &iter, root, &iter); + ++i; + } + + /* inserts after the node before the last node */ + i = 0; + while (i < 100) + { + gtk_tree_store_insert_after (store, &iter, root, &iter); + ++i; + } + + /* inserts after the last node */ + gtk_tree_store_append (store, &iter, root); + + i = 0; + while (i < 100) + { + gtk_tree_store_insert_after (store, &iter, root, &iter); + ++i; + } + + /* remove everything again */ + while (gtk_tree_model_iter_children (model, &iter, root)) + gtk_tree_store_remove (store, &iter); + + + /* Prepends */ + gtk_tree_store_prepend (store, &iter, root); + + i = 0; + while (i < 100) + { + gtk_tree_store_prepend (store, &iter, root); + ++i; + } + + /* remove everything again */ + while (gtk_tree_model_iter_children (model, &iter, root)) + gtk_tree_store_remove (store, &iter); + + gtk_tree_store_append (store, &iter, root); + gtk_tree_store_append (store, &iter, root); + gtk_tree_store_append (store, &iter, root); + gtk_tree_store_append (store, &iter, root); + + while (gtk_tree_model_iter_children (model, &iter, root)) + { + treestore_torture_recurse (store, &iter, depth); + gtk_tree_store_remove (store, &iter); + } +} + +static void run_automated_tests (void) { + g_print ("Running automated tests...\n"); + /* FIXME TreePath basic verification */ - /* FIXME consistency checks on the models */ - + /* FIXME generic consistency checks on the models */ + + { + /* Make sure list store mutations don't crash anything */ + GtkListStore *store; + GtkTreeModel *model; + gint i; + GtkTreeIter iter; + + store = gtk_list_store_new_with_types (1, G_TYPE_INT); + + model = GTK_TREE_MODEL (store); + + i = 0; + while (i < 100) + { + gtk_list_store_append (store, &iter); + ++i; + } + + while (gtk_tree_model_get_first (model, &iter)) + gtk_list_store_remove (store, &iter); + + gtk_list_store_append (store, &iter); + + /* inserts before last node in list */ + i = 0; + while (i < 100) + { + gtk_list_store_insert_before (store, &iter, &iter); + ++i; + } + + /* inserts after the node before the last node */ + i = 0; + while (i < 100) + { + gtk_list_store_insert_after (store, &iter, &iter); + ++i; + } + + /* inserts after the last node */ + gtk_list_store_append (store, &iter); + + i = 0; + while (i < 100) + { + gtk_list_store_insert_after (store, &iter, &iter); + ++i; + } + + /* remove everything again */ + while (gtk_tree_model_get_first (model, &iter)) + gtk_list_store_remove (store, &iter); + + + /* Prepends */ + gtk_list_store_prepend (store, &iter); + + i = 0; + while (i < 100) + { + gtk_list_store_prepend (store, &iter); + ++i; + } + + /* remove everything again */ + while (gtk_tree_model_get_first (model, &iter)) + gtk_list_store_remove (store, &iter); + + g_object_unref (G_OBJECT (store)); + } + + { + /* Make sure tree store mutations don't crash anything */ + GtkTreeStore *store; + + store = gtk_tree_store_new_with_types (1, G_TYPE_INT); + + treestore_torture_recurse (store, NULL, 0); + + g_object_unref (G_OBJECT (store)); + } + + g_print ("Passed.\n"); } |