diff options
author | Kristian Rietveld <kris@gtk.org> | 2002-11-18 19:33:28 +0000 |
---|---|---|
committer | Kristian Rietveld <kristian@src.gnome.org> | 2002-11-18 19:33:28 +0000 |
commit | b977d5af8fe25c58120abe4ab5a966fcd53b4d6f (patch) | |
tree | 04ec9ff675317ef6bdbc14dc39701670f3f78b58 | |
parent | d95f3da34d041fcdc5ad540814c34e22bf50d573 (diff) | |
download | gtk+-b977d5af8fe25c58120abe4ab5a966fcd53b4d6f.tar.gz |
modify and free tmp instead of path ... (patch from #97927).
Mon Nov 18 20:42:27 2002 Kristian Rietveld <kris@gtk.org>
* gtk/gtktreeview.c (gtk_tree_view_expand_to_path): modify and
free tmp instead of path ... (patch from #97927).
Mon Nov 18 20:31:20 2002 Kristian Rietveld <kris@gtk.org>
* gtk/gtkcellrenderertext.c (gtk_cell_renderer_text_start_editing):
only _set_text if celltext->text is not NULL. (#97815, reported
and testcase provided by Vitaly Tishkov).
Mon Nov 18 20:28:28 2002 Kristian Rietveld <kris@gtk.org>
* gtk/gtktreeselection.c (gtk_tree_selection_real_modify_range):
also update the anchor_path, makes behaviour consistent with the
other selection modification functions. (#96801, reported and
testcase provided by Vitaly Tishkov).
Mon Nov 18 20:17:56 2002 Kristian Rietveld <kris@gtk.org>
Hrm, this fixes up lots of mistakes in my swap/move code ... Some
of these mistakes where pointed out by Vitaly Tishkov in bugs
#97403, #97404, #97412, #97618.
* gtktreestore.[ch]: gtk_tree_store_move is now private, use
gtk_tree_store_move_{before,after} instead now. Lots of fixes
(more like a rewrite :) in the _move and _swap functions.
* gtkliststore.[ch]: likewise.
-rw-r--r-- | ChangeLog | 30 | ||||
-rw-r--r-- | ChangeLog.pre-2-10 | 30 | ||||
-rw-r--r-- | ChangeLog.pre-2-2 | 30 | ||||
-rw-r--r-- | ChangeLog.pre-2-4 | 30 | ||||
-rw-r--r-- | ChangeLog.pre-2-6 | 30 | ||||
-rw-r--r-- | ChangeLog.pre-2-8 | 30 | ||||
-rw-r--r-- | gtk/gtkcellrenderertext.c | 3 | ||||
-rw-r--r-- | gtk/gtkliststore.c | 216 | ||||
-rw-r--r-- | gtk/gtkliststore.h | 7 | ||||
-rw-r--r-- | gtk/gtktreeselection.c | 15 | ||||
-rw-r--r-- | gtk/gtktreestore.c | 414 | ||||
-rw-r--r-- | gtk/gtktreestore.h | 7 | ||||
-rw-r--r-- | gtk/gtktreeview.c | 6 |
13 files changed, 712 insertions, 136 deletions
@@ -1,3 +1,33 @@ +Mon Nov 18 20:42:27 2002 Kristian Rietveld <kris@gtk.org> + + * gtk/gtktreeview.c (gtk_tree_view_expand_to_path): modify and + free tmp instead of path ... (patch from #97927). + +Mon Nov 18 20:31:20 2002 Kristian Rietveld <kris@gtk.org> + + * gtk/gtkcellrenderertext.c (gtk_cell_renderer_text_start_editing): + only _set_text if celltext->text is not NULL. (#97815, reported + and testcase provided by Vitaly Tishkov). + +Mon Nov 18 20:28:28 2002 Kristian Rietveld <kris@gtk.org> + + * gtk/gtktreeselection.c (gtk_tree_selection_real_modify_range): + also update the anchor_path, makes behaviour consistent with the + other selection modification functions. (#96801, reported and + testcase provided by Vitaly Tishkov). + +Mon Nov 18 20:17:56 2002 Kristian Rietveld <kris@gtk.org> + + Hrm, this fixes up lots of mistakes in my swap/move code ... Some + of these mistakes where pointed out by Vitaly Tishkov in bugs + #97403, #97404, #97412, #97618. + + * gtktreestore.[ch]: gtk_tree_store_move is now private, use + gtk_tree_store_move_{before,after} instead now. Lots of fixes + (more like a rewrite :) in the _move and _swap functions. + + * gtkliststore.[ch]: likewise. + 2002-11-18 Abigail Brady <morwen@evilmagic.org> * gtk/gtkimmodule.c: (_gtk_im_module_list): Sort the list of Input diff --git a/ChangeLog.pre-2-10 b/ChangeLog.pre-2-10 index 4e862a8b4b..4605dcba00 100644 --- a/ChangeLog.pre-2-10 +++ b/ChangeLog.pre-2-10 @@ -1,3 +1,33 @@ +Mon Nov 18 20:42:27 2002 Kristian Rietveld <kris@gtk.org> + + * gtk/gtktreeview.c (gtk_tree_view_expand_to_path): modify and + free tmp instead of path ... (patch from #97927). + +Mon Nov 18 20:31:20 2002 Kristian Rietveld <kris@gtk.org> + + * gtk/gtkcellrenderertext.c (gtk_cell_renderer_text_start_editing): + only _set_text if celltext->text is not NULL. (#97815, reported + and testcase provided by Vitaly Tishkov). + +Mon Nov 18 20:28:28 2002 Kristian Rietveld <kris@gtk.org> + + * gtk/gtktreeselection.c (gtk_tree_selection_real_modify_range): + also update the anchor_path, makes behaviour consistent with the + other selection modification functions. (#96801, reported and + testcase provided by Vitaly Tishkov). + +Mon Nov 18 20:17:56 2002 Kristian Rietveld <kris@gtk.org> + + Hrm, this fixes up lots of mistakes in my swap/move code ... Some + of these mistakes where pointed out by Vitaly Tishkov in bugs + #97403, #97404, #97412, #97618. + + * gtktreestore.[ch]: gtk_tree_store_move is now private, use + gtk_tree_store_move_{before,after} instead now. Lots of fixes + (more like a rewrite :) in the _move and _swap functions. + + * gtkliststore.[ch]: likewise. + 2002-11-18 Abigail Brady <morwen@evilmagic.org> * gtk/gtkimmodule.c: (_gtk_im_module_list): Sort the list of Input diff --git a/ChangeLog.pre-2-2 b/ChangeLog.pre-2-2 index 4e862a8b4b..4605dcba00 100644 --- a/ChangeLog.pre-2-2 +++ b/ChangeLog.pre-2-2 @@ -1,3 +1,33 @@ +Mon Nov 18 20:42:27 2002 Kristian Rietveld <kris@gtk.org> + + * gtk/gtktreeview.c (gtk_tree_view_expand_to_path): modify and + free tmp instead of path ... (patch from #97927). + +Mon Nov 18 20:31:20 2002 Kristian Rietveld <kris@gtk.org> + + * gtk/gtkcellrenderertext.c (gtk_cell_renderer_text_start_editing): + only _set_text if celltext->text is not NULL. (#97815, reported + and testcase provided by Vitaly Tishkov). + +Mon Nov 18 20:28:28 2002 Kristian Rietveld <kris@gtk.org> + + * gtk/gtktreeselection.c (gtk_tree_selection_real_modify_range): + also update the anchor_path, makes behaviour consistent with the + other selection modification functions. (#96801, reported and + testcase provided by Vitaly Tishkov). + +Mon Nov 18 20:17:56 2002 Kristian Rietveld <kris@gtk.org> + + Hrm, this fixes up lots of mistakes in my swap/move code ... Some + of these mistakes where pointed out by Vitaly Tishkov in bugs + #97403, #97404, #97412, #97618. + + * gtktreestore.[ch]: gtk_tree_store_move is now private, use + gtk_tree_store_move_{before,after} instead now. Lots of fixes + (more like a rewrite :) in the _move and _swap functions. + + * gtkliststore.[ch]: likewise. + 2002-11-18 Abigail Brady <morwen@evilmagic.org> * gtk/gtkimmodule.c: (_gtk_im_module_list): Sort the list of Input diff --git a/ChangeLog.pre-2-4 b/ChangeLog.pre-2-4 index 4e862a8b4b..4605dcba00 100644 --- a/ChangeLog.pre-2-4 +++ b/ChangeLog.pre-2-4 @@ -1,3 +1,33 @@ +Mon Nov 18 20:42:27 2002 Kristian Rietveld <kris@gtk.org> + + * gtk/gtktreeview.c (gtk_tree_view_expand_to_path): modify and + free tmp instead of path ... (patch from #97927). + +Mon Nov 18 20:31:20 2002 Kristian Rietveld <kris@gtk.org> + + * gtk/gtkcellrenderertext.c (gtk_cell_renderer_text_start_editing): + only _set_text if celltext->text is not NULL. (#97815, reported + and testcase provided by Vitaly Tishkov). + +Mon Nov 18 20:28:28 2002 Kristian Rietveld <kris@gtk.org> + + * gtk/gtktreeselection.c (gtk_tree_selection_real_modify_range): + also update the anchor_path, makes behaviour consistent with the + other selection modification functions. (#96801, reported and + testcase provided by Vitaly Tishkov). + +Mon Nov 18 20:17:56 2002 Kristian Rietveld <kris@gtk.org> + + Hrm, this fixes up lots of mistakes in my swap/move code ... Some + of these mistakes where pointed out by Vitaly Tishkov in bugs + #97403, #97404, #97412, #97618. + + * gtktreestore.[ch]: gtk_tree_store_move is now private, use + gtk_tree_store_move_{before,after} instead now. Lots of fixes + (more like a rewrite :) in the _move and _swap functions. + + * gtkliststore.[ch]: likewise. + 2002-11-18 Abigail Brady <morwen@evilmagic.org> * gtk/gtkimmodule.c: (_gtk_im_module_list): Sort the list of Input diff --git a/ChangeLog.pre-2-6 b/ChangeLog.pre-2-6 index 4e862a8b4b..4605dcba00 100644 --- a/ChangeLog.pre-2-6 +++ b/ChangeLog.pre-2-6 @@ -1,3 +1,33 @@ +Mon Nov 18 20:42:27 2002 Kristian Rietveld <kris@gtk.org> + + * gtk/gtktreeview.c (gtk_tree_view_expand_to_path): modify and + free tmp instead of path ... (patch from #97927). + +Mon Nov 18 20:31:20 2002 Kristian Rietveld <kris@gtk.org> + + * gtk/gtkcellrenderertext.c (gtk_cell_renderer_text_start_editing): + only _set_text if celltext->text is not NULL. (#97815, reported + and testcase provided by Vitaly Tishkov). + +Mon Nov 18 20:28:28 2002 Kristian Rietveld <kris@gtk.org> + + * gtk/gtktreeselection.c (gtk_tree_selection_real_modify_range): + also update the anchor_path, makes behaviour consistent with the + other selection modification functions. (#96801, reported and + testcase provided by Vitaly Tishkov). + +Mon Nov 18 20:17:56 2002 Kristian Rietveld <kris@gtk.org> + + Hrm, this fixes up lots of mistakes in my swap/move code ... Some + of these mistakes where pointed out by Vitaly Tishkov in bugs + #97403, #97404, #97412, #97618. + + * gtktreestore.[ch]: gtk_tree_store_move is now private, use + gtk_tree_store_move_{before,after} instead now. Lots of fixes + (more like a rewrite :) in the _move and _swap functions. + + * gtkliststore.[ch]: likewise. + 2002-11-18 Abigail Brady <morwen@evilmagic.org> * gtk/gtkimmodule.c: (_gtk_im_module_list): Sort the list of Input diff --git a/ChangeLog.pre-2-8 b/ChangeLog.pre-2-8 index 4e862a8b4b..4605dcba00 100644 --- a/ChangeLog.pre-2-8 +++ b/ChangeLog.pre-2-8 @@ -1,3 +1,33 @@ +Mon Nov 18 20:42:27 2002 Kristian Rietveld <kris@gtk.org> + + * gtk/gtktreeview.c (gtk_tree_view_expand_to_path): modify and + free tmp instead of path ... (patch from #97927). + +Mon Nov 18 20:31:20 2002 Kristian Rietveld <kris@gtk.org> + + * gtk/gtkcellrenderertext.c (gtk_cell_renderer_text_start_editing): + only _set_text if celltext->text is not NULL. (#97815, reported + and testcase provided by Vitaly Tishkov). + +Mon Nov 18 20:28:28 2002 Kristian Rietveld <kris@gtk.org> + + * gtk/gtktreeselection.c (gtk_tree_selection_real_modify_range): + also update the anchor_path, makes behaviour consistent with the + other selection modification functions. (#96801, reported and + testcase provided by Vitaly Tishkov). + +Mon Nov 18 20:17:56 2002 Kristian Rietveld <kris@gtk.org> + + Hrm, this fixes up lots of mistakes in my swap/move code ... Some + of these mistakes where pointed out by Vitaly Tishkov in bugs + #97403, #97404, #97412, #97618. + + * gtktreestore.[ch]: gtk_tree_store_move is now private, use + gtk_tree_store_move_{before,after} instead now. Lots of fixes + (more like a rewrite :) in the _move and _swap functions. + + * gtkliststore.[ch]: likewise. + 2002-11-18 Abigail Brady <morwen@evilmagic.org> * gtk/gtkimmodule.c: (_gtk_im_module_list): Sort the list of Input diff --git a/gtk/gtkcellrenderertext.c b/gtk/gtkcellrenderertext.c index 8fa5b41cef..a7490317a0 100644 --- a/gtk/gtkcellrenderertext.c +++ b/gtk/gtkcellrenderertext.c @@ -1371,7 +1371,8 @@ gtk_cell_renderer_text_start_editing (GtkCellRenderer *cell, "has_frame", FALSE, NULL); - gtk_entry_set_text (GTK_ENTRY (entry), celltext->text); + if (celltext->text) + gtk_entry_set_text (GTK_ENTRY (entry), celltext->text); g_object_set_data_full (G_OBJECT (entry), GTK_CELL_RENDERER_TEXT_PATH, g_strdup (path), g_free); gtk_editable_select_region (GTK_EDITABLE (entry), 0, -1); diff --git a/gtk/gtkliststore.c b/gtk/gtkliststore.c index 6ea0c9f8e7..538cbe67c2 100644 --- a/gtk/gtkliststore.c +++ b/gtk/gtkliststore.c @@ -109,6 +109,11 @@ static void gtk_list_store_set_default_sort_func (GtkTreeSortable *so GtkDestroyNotify destroy); static gboolean gtk_list_store_has_default_sort_func (GtkTreeSortable *sortable); +static void gtk_list_store_move (GtkListStore *store, + GtkTreeIter *iter, + GtkTreeIter *path, + gboolean before); + static GObjectClass *parent_class = NULL; @@ -1717,7 +1722,7 @@ gtk_list_store_swap (GtkListStore *store, a_count++; } - if (a->user_data == store->root) + if (b->user_data == store->root) prev_b = NULL; else { @@ -1765,32 +1770,77 @@ gtk_list_store_swap (GtkListStore *store, g_free (order); } -/** - * gtk_list_store_move: - * @store: A #GtkTreeStore. - * @iter: A #GtkTreeIter. - * @position: A #GtkTreePath. - * - * Moves @iter in @store to the position before @position. Note that this - * function only works with unsorted stores. - **/ -void +static void gtk_list_store_move (GtkListStore *store, GtkTreeIter *iter, - GtkTreePath *position) + GtkTreeIter *position, + gboolean before) { - GSList *i, *prev = NULL, *new_prev = NULL; - gint old_pos = 0, j = 0, *order; - GtkTreePath *path; + GtkTreeIter dst_a; + GSList *i, *a, *prev = NULL, *tmp; + gint new_pos = 0, old_pos = 0, j = 0, *order; + GtkTreePath *path, *pos_path = NULL; g_return_if_fail (GTK_IS_LIST_STORE (store)); g_return_if_fail (!GTK_LIST_STORE_IS_SORTED (store)); g_return_if_fail (VALID_ITER (iter, store)); - g_return_if_fail (position != NULL); + if (position) + g_return_if_fail (VALID_ITER (position, store)); - if (gtk_tree_path_get_depth (position) != 1) - return; + /* lots of sanity checks */ + if (position) + { + path = gtk_tree_model_get_path (GTK_TREE_MODEL (store), iter); + pos_path = gtk_tree_model_get_path (GTK_TREE_MODEL (store), position); + + if (gtk_tree_path_get_depth (pos_path) != 1) + goto free_paths_and_out; + + /* if before: + * moving the iter before path or "path + 1" doesn't make sense + * else + * moving the iter before path or "path - 1" doesn't make sense + */ + if (!gtk_tree_path_compare (path, pos_path)) + goto free_paths_and_out; + + if (before) + gtk_tree_path_next (path); + else + gtk_tree_path_prev (path); + + if (!gtk_tree_path_compare (path, pos_path)) + goto free_paths_and_out; + + gtk_tree_path_free (path); + } + /* getting destination iters */ + if (before && position) + { + if (gtk_tree_path_get_indices (pos_path)[0] > 0) + { + gtk_tree_path_prev (pos_path); + if (gtk_tree_model_get_iter (GTK_TREE_MODEL (store), &dst_a, pos_path)) + a = G_SLIST (dst_a.user_data); + else + a = NULL; + gtk_tree_path_next (pos_path); + } + else + a = NULL; + } + else if (before && !position) + a = NULL; + else /* !before */ + { + if (position) + a = G_SLIST (position->user_data); + else + a = NULL; + } + + /* getting the old prev node */ if (iter->user_data == store->root) prev = NULL; else @@ -1805,54 +1855,126 @@ gtk_list_store_move (GtkListStore *store, old_pos++; } - if (old_pos == gtk_tree_path_get_indices (position)[0]) - return; - - if (gtk_tree_path_get_indices (position)[0] == 0) - new_prev = NULL; - else - { - for (i = store->root; i; i = i->next, j++) - if (j == gtk_tree_path_get_indices (position)[0] - 1) - { - new_prev = i; - break; - } - } - + /* remove node */ if (!prev) store->root = G_SLIST (iter->user_data)->next; else prev->next = G_SLIST (iter->user_data)->next; - if (!new_prev) + /* and reinsert it */ + if (a) { - G_SLIST (iter->user_data)->next = store->root; + tmp = a->next; + + a->next = G_SLIST (iter->user_data); + a->next->next = tmp; + } + else if (!a && !before) + { + tmp = G_SLIST (store->root); + store->root = G_SLIST (iter->user_data); + G_SLIST (store->root)->next = tmp; } - else + else if (!a && before) { - G_SLIST (iter->user_data)->next = new_prev->next; - new_prev->next = G_SLIST (iter->user_data); + G_SLIST (store->tail)->next = G_SLIST (iter->user_data); + G_SLIST (iter->user_data)->next = NULL; + store->tail = iter->user_data; } /* emit signal */ + if (position) + new_pos = gtk_tree_path_get_indices (pos_path)[0]; + else if (before) + new_pos = gtk_tree_model_iter_n_children (GTK_TREE_MODEL (store), NULL) - 1; + else + new_pos = 0; + + if (new_pos > old_pos) + { + if (before) + new_pos--; + } + else + { + if (!before) + new_pos++; + } + order = g_new (gint, store->length); - for (j = 0; j < store->length; j++) - if (j < old_pos) - order[j] = j; - else if (j >= old_pos && j < gtk_tree_path_get_indices (position)[0]) - order[j] = j + 1; - else if (j == gtk_tree_path_get_indices (position)[0]) - order[j] = old_pos; - else - order[j] = j; + if (new_pos > old_pos) + { + for (j = 0; j < store->length; j++) + if (j < old_pos) + order[j] = j; + else if (j >= old_pos && j < new_pos) + order[j] = j + 1; + else if (j == new_pos) + order[j] = old_pos; + else + order[j] = j; + } + else + { + for (j = 0; j < store->length; j++) + if (j == new_pos) + order[j] = old_pos; + else if (j > new_pos && j <= old_pos) + order[j] = j - 1; + else + order[j] = j; + } path = gtk_tree_path_new (); gtk_tree_model_rows_reordered (GTK_TREE_MODEL (store), path, NULL, order); gtk_tree_path_free (path); + if (position) + gtk_tree_path_free (pos_path); g_free (order); + + return; + +free_paths_and_out: + gtk_tree_path_free (path); + gtk_tree_path_free (pos_path); +} + +/** + * gtk_list_store_move_before: + * @store: A #GtkListStore. + * @iter: A #GtkTreeIter. + * @position: A #GtkTreeIter, or %NULL. + * + * Moves @iter in @store to the position before @position. Note that this + * function only works with unsorted stores. If @position is %NULL, @iter + * will be moved to the end of the list. + **/ +void +gtk_list_store_move_before (GtkListStore *store, + GtkTreeIter *iter, + GtkTreeIter *position) +{ + gtk_list_store_move (store, iter, position, TRUE); +} + +/** + * gtk_list_store_move_after: + * @store: A #GtkListStore. + * @iter: A #GtkTreeIter. + * @position: A #GtkTreeIter, or %NULL. + * + * Moves @iter in @store to the position after @position. Note that this + * function only works with unsorted stores. If @position is %NULL, @iter + * will be moved to the start of the list. + **/ +void +gtk_list_store_move_after (GtkListStore *store, + GtkTreeIter *iter, + GtkTreeIter *position) +{ + gtk_list_store_move (store, iter, position, FALSE); } /* Sorting */ diff --git a/gtk/gtkliststore.h b/gtk/gtkliststore.h index 25787e2bae..bb17678aa0 100644 --- a/gtk/gtkliststore.h +++ b/gtk/gtkliststore.h @@ -113,9 +113,12 @@ void gtk_list_store_reorder (GtkListStore *store, void gtk_list_store_swap (GtkListStore *store, GtkTreeIter *a, GtkTreeIter *b); -void gtk_list_store_move (GtkListStore *store, +void gtk_list_store_move_after (GtkListStore *store, GtkTreeIter *iter, - GtkTreePath *position); + GtkTreeIter *position); +void gtk_list_store_move_before (GtkListStore *store, + GtkTreeIter *iter, + GtkTreeIter *position); #ifdef __cplusplus diff --git a/gtk/gtktreeselection.c b/gtk/gtktreeselection.c index d0239b5891..38d943ebfc 100644 --- a/gtk/gtktreeselection.c +++ b/gtk/gtktreeselection.c @@ -1147,6 +1147,7 @@ gtk_tree_selection_real_modify_range (GtkTreeSelection *selection, { GtkRBNode *start_node, *end_node; GtkRBTree *start_tree, *end_tree; + GtkTreePath *anchor_path; gboolean dirty = FALSE; switch (gtk_tree_path_compare (start_path, end_path)) @@ -1160,6 +1161,7 @@ gtk_tree_selection_real_modify_range (GtkTreeSelection *selection, start_path, &end_tree, &end_node); + anchor_path = end_path; break; case 0: _gtk_tree_view_find_node (selection->tree_view, @@ -1168,6 +1170,7 @@ gtk_tree_selection_real_modify_range (GtkTreeSelection *selection, &start_node); end_tree = start_tree; end_node = start_node; + anchor_path = start_path; break; case -1: _gtk_tree_view_find_node (selection->tree_view, @@ -1178,12 +1181,24 @@ gtk_tree_selection_real_modify_range (GtkTreeSelection *selection, end_path, &end_tree, &end_node); + anchor_path = start_path; break; } g_return_val_if_fail (start_node != NULL, FALSE); g_return_val_if_fail (end_node != NULL, FALSE); + if (anchor_path) + { + if (selection->tree_view->priv->anchor) + gtk_tree_row_reference_free (selection->tree_view->priv->anchor); + + selection->tree_view->priv->anchor = + gtk_tree_row_reference_new_proxy (G_OBJECT (selection->tree_view), + selection->tree_view->priv->model, + anchor_path); + } + do { dirty |= gtk_tree_selection_real_select_node (selection, start_tree, start_node, (mode == RANGE_SELECT)?TRUE:FALSE); diff --git a/gtk/gtktreestore.c b/gtk/gtktreestore.c index e2304e965d..a3f56cd64f 100644 --- a/gtk/gtktreestore.c +++ b/gtk/gtktreestore.c @@ -111,6 +111,11 @@ static gboolean gtk_tree_store_has_default_sort_func (GtkTreeSortable * static void validate_gnode (GNode *node); +static void gtk_tree_store_move (GtkTreeStore *tree_store, + GtkTreeIter *iter, + GtkTreeIter *position, + gboolean before); + static GObjectClass *parent_class = NULL; @@ -1978,6 +1983,7 @@ gtk_tree_store_swap (GtkTreeStore *tree_store, GtkTreeIter *b) { GNode *tmp, *node_a, *node_b, *parent_node; + GNode *a_prev, *a_next, *b_prev, *b_next; gint i, a_count, b_count, length, *order; GtkTreePath *path_a, *path_b; GtkTreeIter parent; @@ -2015,8 +2021,26 @@ gtk_tree_store_swap (GtkTreeStore *tree_store, gtk_tree_path_free (path_b); + /* old links which we have to keep around */ + a_prev = node_a->prev; + a_next = node_a->next; + + b_prev = node_b->prev; + b_next = node_b->next; + + /* fix up links if the nodes are next to eachother */ + if (a_prev == node_b) + a_prev = node_a; + if (a_next == node_b) + a_next = node_a; + + if (b_prev == node_a) + b_prev = node_b; + if (b_next == node_a) + b_next = node_b; + /* counting nodes */ - tmp = parent_node; + tmp = parent_node->children; i = a_count = b_count = 0; while (tmp) { @@ -2031,29 +2055,27 @@ gtk_tree_store_swap (GtkTreeStore *tree_store, length = i; /* hacking the tree */ - if (!node_a->prev) + if (!a_prev) parent_node->children = node_b; else - node_a->prev->next = node_b; + a_prev->next = node_b; - if (!node_b->prev) + if (a_next) + a_next->prev = node_b; + + if (!b_prev) parent_node->children = node_a; else - node_b->prev->next = node_a; - - if (node_a->next) - node_a->next->prev = node_b; + b_prev->next = node_a; - if (node_b->next) - node_b->next->prev = node_a; + if (b_next) + b_next->prev = node_a; - tmp = node_a->next; - node_a->next = node_b->next; - node_b->next = tmp; + node_a->prev = b_prev; + node_a->next = b_next; - tmp = node_a->prev; - node_a->prev = node_b->prev; - node_b->prev = tmp; + node_b->prev = a_prev; + node_b->next = a_next; /* emit signal */ order = g_new (gint, length); @@ -2071,74 +2093,168 @@ gtk_tree_store_swap (GtkTreeStore *tree_store, g_free (order); } -/** - * gtk_tree_store_move: - * @tree_store: A #GtkTreeStore. - * @iter: A #GtkTreeIter. - * @position: A #GtkTreePath. - * - * Moves @iter in @tree_store to the position before @position. @iter and - * @position should be in the same level. Note that this function only - * works with unsorted stores. - **/ -void +/* WARNING: this function is *incredibly* fragily. Please smashtest after + * making changes here. + * -Kris + */ +static void gtk_tree_store_move (GtkTreeStore *tree_store, - GtkTreeIter *iter, - GtkTreePath *position) + GtkTreeIter *iter, + GtkTreeIter *position, + gboolean before) { - GNode *tmp, *new_prev, *new_next, *old_prev, *old_next; + GNode *parent, *node, *a, *b, *tmp, *tmp_a, *tmp_b; gint old_pos, new_pos, length, i, *order; - GtkTreePath *path, *tmppath; - GtkTreeIter parent, new_iter; + GtkTreePath *path = NULL, *tmppath, *pos_path = NULL; + GtkTreeIter parent_iter, dst_a, dst_b; + gint depth = 0; + gboolean handle_b = TRUE; g_return_if_fail (GTK_IS_TREE_STORE (tree_store)); g_return_if_fail (!GTK_TREE_STORE_IS_SORTED (tree_store)); g_return_if_fail (VALID_ITER (iter, tree_store)); - g_return_if_fail (position != NULL); + if (position) + g_return_if_fail (VALID_ITER (position, tree_store)); + + a = b = NULL; /* sanity checks */ - path = gtk_tree_model_get_path (GTK_TREE_MODEL (tree_store), iter); + if (position) + { + path = gtk_tree_model_get_path (GTK_TREE_MODEL (tree_store), iter); + pos_path = gtk_tree_model_get_path (GTK_TREE_MODEL (tree_store), + position); + + /* if before: + * moving the iter before path or "path + 1" doesn't make sense + * else + * moving the iter before path or "path - 1" doesn't make sense + */ + if (!gtk_tree_path_compare (path, pos_path)) + goto free_paths_and_out; + + if (before) + gtk_tree_path_next (path); + else + gtk_tree_path_prev (path); + + if (!gtk_tree_path_compare (path, pos_path)) + goto free_paths_and_out; + + if (before) + gtk_tree_path_prev (path); + else + gtk_tree_path_next (path); + + if (gtk_tree_path_get_depth (path) != gtk_tree_path_get_depth (pos_path)) + { + g_warning ("Given childs are not in the same level\n"); + + goto free_paths_and_out; + } + + tmppath = gtk_tree_path_copy (pos_path); + gtk_tree_path_up (path); + gtk_tree_path_up (tmppath); + + if (gtk_tree_path_get_depth (path) > 0 && + gtk_tree_path_compare (path, tmppath)) + { + g_warning ("Given childs are not in the same level\n"); + + gtk_tree_path_free (tmppath); + goto free_paths_and_out; + } - if (!gtk_tree_path_compare (path, position)) + gtk_tree_path_free (tmppath); + } + + if (!path) { - gtk_tree_path_free (path); - return; + path = gtk_tree_model_get_path (GTK_TREE_MODEL (tree_store), iter); + gtk_tree_path_up (path); } - if (gtk_tree_path_get_depth (path) != gtk_tree_path_get_depth (position)) + depth = gtk_tree_path_get_depth (path); + + if (depth) { + gtk_tree_model_get_iter (GTK_TREE_MODEL (tree_store), &parent_iter, path); gtk_tree_path_free (path); - g_warning ("Given childs are not in the same level\n"); - return; + parent = G_NODE (parent_iter.user_data); } + else + parent = G_NODE (tree_store->root); - tmppath = gtk_tree_path_copy (position); - gtk_tree_path_up (path); - gtk_tree_path_up (tmppath); + /* yes, I know that this can be done shorter, but I'm doing it this way + * so the code is also maintainable + */ - if (gtk_tree_path_compare (path, tmppath)) + if (before && position) { - gtk_tree_path_free (path); - gtk_tree_path_free (tmppath); + b = G_NODE (position->user_data); - g_warning ("Given childs are not in the same level\n"); - return; - } + if (gtk_tree_path_get_indices (pos_path)[gtk_tree_path_get_depth (pos_path) - 1] > 0) + { + gtk_tree_path_prev (pos_path); + if (gtk_tree_model_get_iter (GTK_TREE_MODEL (tree_store), &dst_a, pos_path)) + a = G_NODE (dst_a.user_data); + else + a = NULL; + gtk_tree_path_next (pos_path); + } - gtk_tree_path_free (tmppath); - gtk_tree_model_get_iter (GTK_TREE_MODEL (tree_store), &parent, path); + /* if b is NULL, a is NULL too -- we are at the beginning of the list + * yes and we leak memory here ... + */ + g_return_if_fail (b); + } + else if (before && !position) + { + /* move before without position is appending */ + a = NULL; + b = NULL; + } + else /* !before */ + { + if (position) + a = G_NODE (position->user_data); + else + a = NULL; - gtk_tree_model_get_iter (GTK_TREE_MODEL (tree_store), &new_iter, position); + if (position) + { + gtk_tree_path_next (pos_path); + if (gtk_tree_model_get_iter (GTK_TREE_MODEL (tree_store), &dst_b, pos_path)) + b = G_NODE (dst_b.user_data); + else + b = NULL; + gtk_tree_path_prev (pos_path); + } + else + { + /* move after without position is prepending */ + if (depth) + gtk_tree_model_iter_children (GTK_TREE_MODEL (tree_store), &dst_b, + &parent_iter); + else + gtk_tree_model_iter_children (GTK_TREE_MODEL (tree_store), &dst_b, + NULL); - new_prev = G_NODE (new_iter.user_data)->prev; - new_next = G_NODE (new_iter.user_data); + b = G_NODE (dst_b.user_data); + } - old_prev = G_NODE (iter->user_data)->prev; - old_next = G_NODE (iter->user_data)->next; + /* if a is NULL, a is NULL too -- we are at the end of the list + * yes and we leak memory here ... + */ + if (position) + g_return_if_fail (a); + } /* counting nodes */ - tmp = G_NODE (parent.user_data); + tmp = parent->children; + length = old_pos = 0; while (tmp) { @@ -2149,44 +2265,180 @@ gtk_tree_store_move (GtkTreeStore *tree_store, length++; } - /* hacking the tree */ - if (!old_prev) - G_NODE (parent.user_data)->children = old_next; + /* remove node from list */ + node = G_NODE (iter->user_data); + tmp_a = node->prev; + tmp_b = node->next; + + if (tmp_a) + tmp_a->next = tmp_b; else - old_prev->next = old_next; + parent->children = tmp_b; - if (old_next) - old_next->prev = old_prev; + if (tmp_b) + tmp_b->prev = tmp_a; - if (!new_prev) - G_NODE (parent.user_data)->children = iter->user_data; - else - new_prev->next = iter->user_data; + /* and reinsert the node */ + if (a) + { + tmp = a->next; + + a->next = node; + node->next = tmp; + node->prev = a; + } + else if (!a && !before) + { + tmp = parent->children; + + node->prev = NULL; + parent->children = node; + + node->next = tmp; + tmp->prev = node; + + handle_b = FALSE; + } + else if (!a && before) + { + if (!position) + { + node->parent = NULL; + node->next = node->prev = NULL; - if (new_next) - new_next->prev = iter->user_data; + /* before with sibling = NULL appends */ + g_node_insert_before (parent, NULL, node); + } + else + { + node->parent = NULL; + node->next = node->prev = NULL; - G_NODE (iter->user_data)->prev = new_prev; - G_NODE (iter->user_data)->next = new_next; + /* after with sibling = NULL prepends */ + g_node_insert_after (parent, NULL, node); + } + } + + if (handle_b) + { + if (b) + { + tmp = b->prev; + + b->prev = node; + node->prev = tmp; + node->next = b; + } + else if (!(!a && before)) /* !a && before is completely handled above */ + node->next = NULL; + } /* emit signal */ - new_pos = gtk_tree_path_get_indices (position)[gtk_tree_path_get_depth (position)-1]; + if (position) + new_pos = gtk_tree_path_get_indices (pos_path)[gtk_tree_path_get_depth (pos_path)-1]; + else if (before) + { + if (depth) + new_pos = gtk_tree_model_iter_n_children (GTK_TREE_MODEL (tree_store), + &parent_iter) - 1; + else + new_pos = gtk_tree_model_iter_n_children (GTK_TREE_MODEL (tree_store), + NULL) - 1; + } + else + new_pos = 0; + + if (new_pos > old_pos) + { + if (before && position) + new_pos--; + } + else + { + if (!before && position) + new_pos++; + } + order = g_new (gint, length); - for (i = 0; i < length; i++) - if (i < old_pos) - order[i] = i; - else if (i >= old_pos && i < new_pos) - order[i] = i + 1; - else if (i == new_pos) - order[i] = old_pos; - else - order[i] = i; + if (new_pos > old_pos) + { + for (i = 0; i < length; i++) + if (i < old_pos) + order[i] = i; + else if (i >= old_pos && i < new_pos) + order[i] = i + 1; + else if (i == new_pos) + order[i] = old_pos; + else + order[i] = i; + } + else + { + for (i = 0; i < length; i++) + if (i == new_pos) + order[i] = old_pos; + else if (i > new_pos && i <= old_pos) + order[i] = i - 1; + else + order[i] = i; + } path = gtk_tree_path_new (); gtk_tree_model_rows_reordered (GTK_TREE_MODEL (tree_store), path, NULL, order); + + for (i = 0; i < length; i++) + g_print ("%2d ", order[i]); + g_print ("\n"); + gtk_tree_path_free (path); + if (position) + gtk_tree_path_free (pos_path); g_free (order); + + return; + +free_paths_and_out: + gtk_tree_path_free (path); + gtk_tree_path_free (pos_path); +} + +/** + * gtk_tree_store_move_before: + * @tree_store: A #GtkTreeStore. + * @iter: A #GtkTreeIter. + * @position: A #GtkTreeIter or %NULL. + * + * Moves @iter in @tree_store to the position before @position. @iter and + * @position should be in the same level. Note that this function only + * works with unsorted stores. If @position is %NULL, @iter will be + * moved to the end of the level. + **/ +void +gtk_tree_store_move_before (GtkTreeStore *tree_store, + GtkTreeIter *iter, + GtkTreeIter *position) +{ + gtk_tree_store_move (tree_store, iter, position, TRUE); +} + +/** + * gtk_tree_store_move_after: + * @tree_store: A #GtkTreeStore. + * @iter: A #GtkTreeIter. + * @position: A #GtkTreeIter. + * + * Moves @iter in @tree_store to the position after @position. @iter and + * @position should be in the same level. Note that this function only + * works with unsorted stores. If @position is %NULL, @iter will be moved + * to the start of the level. + **/ +void +gtk_tree_store_move_after (GtkTreeStore *tree_store, + GtkTreeIter *iter, + GtkTreeIter *position) +{ + gtk_tree_store_move (tree_store, iter, position, FALSE); } /* Sorting */ diff --git a/gtk/gtktreestore.h b/gtk/gtktreestore.h index d8a5f9d297..ed6b50263e 100644 --- a/gtk/gtktreestore.h +++ b/gtk/gtktreestore.h @@ -123,9 +123,12 @@ void gtk_tree_store_reorder (GtkTreeStore *tree_store, void gtk_tree_store_swap (GtkTreeStore *tree_store, GtkTreeIter *a, GtkTreeIter *b); -void gtk_tree_store_move (GtkTreeStore *tree_store, +void gtk_tree_store_move_before (GtkTreeStore *tree_store, GtkTreeIter *iter, - GtkTreePath *position); + GtkTreeIter *position); +void gtk_tree_store_move_after (GtkTreeStore *tree_store, + GtkTreeIter *iter, + GtkTreeIter *position); #ifdef __cplusplus diff --git a/gtk/gtktreeview.c b/gtk/gtktreeview.c index 831bf705cb..8ebf772f19 100644 --- a/gtk/gtktreeview.c +++ b/gtk/gtktreeview.c @@ -8946,11 +8946,11 @@ gtk_tree_view_expand_to_path (GtkTreeView *tree_view, for (i = 0; i < depth; i++) { - gtk_tree_path_append_index (path, indices[i]); - gtk_tree_view_expand_row (tree_view, path, FALSE); + gtk_tree_path_append_index (tmp, indices[i]); + gtk_tree_view_expand_row (tree_view, tmp, FALSE); } - gtk_tree_path_free (path); + gtk_tree_path_free (tmp); } /* FIXME the bool return values for expand_row and collapse_row are |