]> Pileus Git - ~andy/gtk/commitdiff
modify and free tmp instead of path ... (patch from #97927).
authorKristian Rietveld <kris@gtk.org>
Mon, 18 Nov 2002 19:33:28 +0000 (19:33 +0000)
committerKristian Rietveld <kristian@src.gnome.org>
Mon, 18 Nov 2002 19:33:28 +0000 (19:33 +0000)
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.

13 files changed:
ChangeLog
ChangeLog.pre-2-10
ChangeLog.pre-2-2
ChangeLog.pre-2-4
ChangeLog.pre-2-6
ChangeLog.pre-2-8
gtk/gtkcellrenderertext.c
gtk/gtkliststore.c
gtk/gtkliststore.h
gtk/gtktreeselection.c
gtk/gtktreestore.c
gtk/gtktreestore.h
gtk/gtktreeview.c

index 4e862a8b4b88fcd6d2f9b440c635c4bdcb1e713d..4605dcba0005385143ca9262914c9bdbeed137ce 100644 (file)
--- a/ChangeLog
+++ b/ChangeLog
@@ -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 
index 4e862a8b4b88fcd6d2f9b440c635c4bdcb1e713d..4605dcba0005385143ca9262914c9bdbeed137ce 100644 (file)
@@ -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 
index 4e862a8b4b88fcd6d2f9b440c635c4bdcb1e713d..4605dcba0005385143ca9262914c9bdbeed137ce 100644 (file)
@@ -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 
index 4e862a8b4b88fcd6d2f9b440c635c4bdcb1e713d..4605dcba0005385143ca9262914c9bdbeed137ce 100644 (file)
@@ -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 
index 4e862a8b4b88fcd6d2f9b440c635c4bdcb1e713d..4605dcba0005385143ca9262914c9bdbeed137ce 100644 (file)
@@ -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 
index 4e862a8b4b88fcd6d2f9b440c635c4bdcb1e713d..4605dcba0005385143ca9262914c9bdbeed137ce 100644 (file)
@@ -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 
index 8fa5b41cefc87ef92b7b5c52b595da86709dda48..a7490317a0fe8e23a5564ed363a19085b2d9d50f 100644 (file)
@@ -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);
index 6ea0c9f8e7ab714c733a0d53bdbbbc48eff54152..538cbe67c283581a533a508817ff140ee7ca327a 100644 (file)
@@ -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 */
index 25787e2bae020861afeb2c8690ed2faa06f9230c..bb17678aa0bb5f488ce6a55ce05ca0b5b98341b8 100644 (file)
@@ -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
index d0239b5891c14bba36847053857c619688af2fd0..38d943ebfcac5137beeaaa506ee49a5386e5377a 100644 (file)
@@ -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);
index e2304e965dc53b68483f20bbb858e3421cadf8a2..a3f56cd64fa876eaf26054ce01844b1108cc9007 100644 (file)
@@ -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 */
index d8a5f9d297dd3373cc1f98995dd21be381ef2ab4..ed6b50263ec1a19a9624fe9a96979afc55158c0f 100644 (file)
@@ -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
index 831bf705cb2bd17c0cdadac016f58f489de1ae70..8ebf772f1988d876841cdc40fc629831415a3fde 100644 (file)
@@ -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