summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorHavoc Pennington <hp@redhat.com>2001-01-10 23:44:22 +0000
committerHavoc Pennington <hp@src.gnome.org>2001-01-10 23:44:22 +0000
commit740ee8ef9467725b5cac7c145c4d1c5d065e8f74 (patch)
tree41d2b89f5e052b309db8950b4f5a45018bb87190
parent85267e9224f8ffec7aeafb8ccbed583d60e7bf4c (diff)
downloadgtk+-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--ChangeLog45
-rw-r--r--ChangeLog.pre-2-045
-rw-r--r--ChangeLog.pre-2-1045
-rw-r--r--ChangeLog.pre-2-245
-rw-r--r--ChangeLog.pre-2-445
-rw-r--r--ChangeLog.pre-2-645
-rw-r--r--ChangeLog.pre-2-845
-rw-r--r--gtk/gtkliststore.c156
-rw-r--r--gtk/gtkliststore.h1
-rw-r--r--gtk/gtktreemodel.c30
-rw-r--r--gtk/gtktreemodel.h2
-rw-r--r--gtk/gtktreestore.c105
-rw-r--r--gtk/gtktreestore.h2
-rw-r--r--tests/testtreeview.c178
14 files changed, 692 insertions, 97 deletions
diff --git a/ChangeLog b/ChangeLog
index 39ee2fb828..8e480dd1dc 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -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");
}