]> Pileus Git - ~andy/gtk/blobdiff - gtk/gtktreeview.c
Bug fix to make trees work again when not sorted.
[~andy/gtk] / gtk / gtktreeview.c
index 761ab3b641160faf4f85b6cc612d89e72f2127fd..e8a14ed3a6a1db7c7fbd7af8e104786e93c9b96c 100644 (file)
@@ -62,6 +62,8 @@ struct _GtkTreeViewChild
 enum
 {
   ROW_ACTIVATED,
+  EXPAND_ROW,
+  COLLAPSE_ROW,
   LAST_SIGNAL
 };
 
@@ -171,9 +173,11 @@ static void     gtk_tree_view_drag_data_received (GtkWidget        *widget,
 static void     gtk_tree_view_set_adjustments      (GtkTreeView      *tree_view,
                                                    GtkAdjustment    *hadj,
                                                    GtkAdjustment    *vadj);
-static void     gtk_tree_view_changed              (GtkTreeModel     *model,
+static void     gtk_tree_view_range_changed        (GtkTreeModel     *model,
                                                    GtkTreePath      *path,
                                                    GtkTreeIter      *iter,
+                                                   GtkTreePath      *end_path,
+                                                   GtkTreeIter      *end_iter,
                                                    gpointer          data);
 static void     gtk_tree_view_inserted             (GtkTreeModel     *model,
                                                    GtkTreePath      *path,
@@ -188,7 +192,9 @@ static void     gtk_tree_view_deleted              (GtkTreeModel     *model,
                                                    gpointer          data);
 static void     gtk_tree_view_reordered            (GtkTreeModel     *model,
                                                    GtkTreePath      *parent,
-                                                   gint             *new_order);
+                                                   GtkTreeIter      *iter,
+                                                   gint             *new_order,
+                                                   gpointer          data);
 /* Internal functions */
 static void     gtk_tree_view_unref_tree           (GtkTreeView      *tree_view,
                                                    GtkRBTree        *tree);
@@ -397,15 +403,35 @@ gtk_tree_view_class_init (GtkTreeViewClass *class)
                    GTK_TYPE_NONE, 2,
                    GTK_TYPE_ADJUSTMENT, GTK_TYPE_ADJUSTMENT);
 
-  tree_view_signals[ROW_ACTIVATED] = gtk_signal_new ("row_activated",
-                                                    GTK_RUN_LAST | GTK_RUN_ACTION,
-                                                    GTK_CLASS_TYPE (object_class),
-                                                    GTK_SIGNAL_OFFSET (GtkTreeViewClass, row_activated),
-                                                    gtk_marshal_VOID__BOXED_OBJECT,
-                                                    GTK_TYPE_NONE, 2,
-                                                    GTK_TYPE_TREE_PATH,
-                                                    GTK_TYPE_TREE_VIEW_COLUMN);
-
+  tree_view_signals[ROW_ACTIVATED] =
+    gtk_signal_new ("row_activated",
+                   GTK_RUN_LAST | GTK_RUN_ACTION,
+                   GTK_CLASS_TYPE (object_class),
+                   GTK_SIGNAL_OFFSET (GtkTreeViewClass, row_activated),
+                   gtk_marshal_VOID__BOXED_OBJECT,
+                   GTK_TYPE_NONE, 2,
+                   GTK_TYPE_TREE_PATH,
+                   GTK_TYPE_TREE_VIEW_COLUMN);
+  tree_view_signals[EXPAND_ROW] =
+    g_signal_newc ("expand_row",
+                  G_TYPE_FROM_CLASS (object_class),
+                  G_SIGNAL_RUN_LAST,
+                  G_STRUCT_OFFSET (GtkTreeViewClass, expand_row),
+                  _gtk_boolean_handled_accumulator, NULL,
+                   gtk_marshal_BOOLEAN__BOXED_BOXED,
+                  G_TYPE_BOOLEAN, 2,
+                  GTK_TYPE_TREE_ITER,
+                  GTK_TYPE_TREE_PATH);
+  tree_view_signals[COLLAPSE_ROW] =
+    g_signal_newc ("collapse_row",
+                  G_TYPE_FROM_CLASS (object_class),
+                  G_SIGNAL_RUN_LAST,
+                  G_STRUCT_OFFSET (GtkTreeViewClass, collapse_row),
+                  _gtk_boolean_handled_accumulator, NULL,
+                   gtk_marshal_BOOLEAN__BOXED_BOXED,
+                  G_TYPE_BOOLEAN, 2,
+                  GTK_TYPE_TREE_ITER,
+                  GTK_TYPE_TREE_PATH);
 }
 
 static void
@@ -1988,47 +2014,67 @@ gtk_tree_view_button_release (GtkWidget      *widget,
       if (tree_view->priv->button_pressed_node == tree_view->priv->prelight_node &&
           GTK_TREE_VIEW_FLAG_SET (tree_view, GTK_TREE_VIEW_ARROW_PRELIT))
        {
-         GtkTreePath *path;
+         GtkTreePath *path = NULL;
          GtkTreeIter iter;
 
          /* Actually activate the node */
          if (tree_view->priv->button_pressed_node->children == NULL)
            {
              GtkTreeIter child;
-             path = _gtk_tree_view_find_path (GTK_TREE_VIEW (widget),
+             path = _gtk_tree_view_find_path (tree_view,
                                               tree_view->priv->button_pressed_tree,
                                               tree_view->priv->button_pressed_node);
-             tree_view->priv->button_pressed_node->children = _gtk_rbtree_new ();
-             tree_view->priv->button_pressed_node->children->parent_tree = tree_view->priv->button_pressed_tree;
-             tree_view->priv->button_pressed_node->children->parent_node = tree_view->priv->button_pressed_node;
              gtk_tree_model_get_iter (tree_view->priv->model, &iter, path);
 
              if (gtk_tree_model_iter_children (tree_view->priv->model, &child, &iter))
-                gtk_tree_view_build_tree (tree_view,
-                                          tree_view->priv->button_pressed_node->children,
-                                          &child,
-                                          gtk_tree_path_get_depth (path) + 1,
-                                          FALSE,
-                                          GTK_WIDGET_REALIZED (widget));
+               {
+                 gboolean expand;
+                 g_signal_emit (G_OBJECT (tree_view), tree_view_signals[EXPAND_ROW], 0, &iter, path, &expand);
+                 if (! expand)
+                   {
+                     tree_view->priv->button_pressed_node->children = _gtk_rbtree_new ();
+                     tree_view->priv->button_pressed_node->children->parent_tree = tree_view->priv->button_pressed_tree;
+                     tree_view->priv->button_pressed_node->children->parent_node = tree_view->priv->button_pressed_node;
+                     gtk_tree_view_build_tree (tree_view,
+                                               tree_view->priv->button_pressed_node->children,
+                                               &child,
+                                               gtk_tree_path_get_depth (path) + 1,
+                                               FALSE,
+                                               GTK_WIDGET_REALIZED (widget));
+
+                   }
+               }
            }
          else
            {
+             gboolean collapse;
+
              path = _gtk_tree_view_find_path (GTK_TREE_VIEW (widget),
-                                              tree_view->priv->button_pressed_node->children,
-                                              tree_view->priv->button_pressed_node->children->root);
+                                              tree_view->priv->button_pressed_tree,
+                                              tree_view->priv->button_pressed_node);
              gtk_tree_model_get_iter (tree_view->priv->model,
                                       &iter,
                                       path);
+             g_signal_emit (G_OBJECT (tree_view), tree_view_signals[COLLAPSE_ROW], 0, &iter, path, &collapse);
 
-             gtk_tree_view_discover_dirty (GTK_TREE_VIEW (widget),
-                                           tree_view->priv->button_pressed_node->children,
-                                           &iter,
-                                           gtk_tree_path_get_depth (path));
-             gtk_tree_view_unref_tree (GTK_TREE_VIEW (widget),
-                                       tree_view->priv->button_pressed_node->children);
-             _gtk_rbtree_remove (tree_view->priv->button_pressed_node->children);
+             if (! collapse)
+               {
+                 GtkTreeIter child_iter;
+                 gtk_tree_path_append_index (path, 0);
+                 gtk_tree_model_iter_children (tree_view->priv->model,
+                                               &child_iter,
+                                               &iter);
+                 gtk_tree_view_discover_dirty (GTK_TREE_VIEW (widget),
+                                               tree_view->priv->button_pressed_node->children,
+                                               &child_iter,
+                                               gtk_tree_path_get_depth (path));
+                 gtk_tree_view_unref_tree (GTK_TREE_VIEW (widget),
+                                           tree_view->priv->button_pressed_node->children);
+                 _gtk_rbtree_remove (tree_view->priv->button_pressed_node->children);
+               }
            }
-         gtk_tree_path_free (path);
+         if (path)
+           gtk_tree_path_free (path);
 
          _gtk_tree_view_update_size (GTK_TREE_VIEW (widget));
        }
@@ -2707,10 +2753,12 @@ gtk_tree_view_row_activated (GtkTreeView       *tree_view,
  */
 
 static void
-gtk_tree_view_changed (GtkTreeModel *model,
-                      GtkTreePath  *path,
-                      GtkTreeIter  *iter,
-                      gpointer      data)
+gtk_tree_view_range_changed (GtkTreeModel *model,
+                            GtkTreePath  *path,
+                            GtkTreeIter  *iter,
+                            GtkTreePath  *end_path,
+                            GtkTreeIter  *end_iter,
+                            gpointer      data)
 {
   GtkTreeView *tree_view = (GtkTreeView *)data;
   GtkRBTree *tree;
@@ -3009,9 +3057,44 @@ gtk_tree_view_deleted (GtkTreeModel *model,
 static void
 gtk_tree_view_reordered (GtkTreeModel *model,
                         GtkTreePath  *parent,
-                        gint         *new_order)
+                        GtkTreeIter  *iter,
+                        gint         *new_order,
+                        gpointer      data)
 {
-  
+  GtkTreeView *tree_view = GTK_TREE_VIEW (data);
+  GtkRBTree *tree;
+  GtkRBNode *node;
+  gint len;
+
+  len = gtk_tree_model_iter_n_children (model, iter);
+
+  if (len < 2)
+    return;
+
+  gtk_tree_row_reference_reordered (G_OBJECT (data),
+                                   parent,
+                                   iter,
+                                   new_order);
+
+  if (_gtk_tree_view_find_node (tree_view,
+                               parent,
+                               &tree,
+                               &node))
+    return;
+
+  /* We need to special case the parent path */
+  if (tree == NULL)
+    tree = tree_view->priv->tree;
+  else
+    tree = node->children;
+
+  if (tree == NULL)
+    return;
+
+  /* FIXME: we need to unprelight our tree, if it's prelit. */
+  _gtk_rbtree_reorder (tree, new_order, len);
+
+  gtk_widget_queue_draw (GTK_WIDGET (tree_view));
 }
 
 /* Internal tree functions */
@@ -3159,7 +3242,9 @@ gtk_tree_view_calc_size (GtkTreeView *tree_view,
          else
             gtk_tree_view_column_set_width (column, MAX (column->width, width));
        }
+
       _gtk_rbtree_node_set_height (tree, temp, max_height);
+
       if (temp->children != NULL &&
          gtk_tree_model_iter_children (tree_view->priv->model, &child, iter))
        gtk_tree_view_calc_size (tree_view, temp->children, &child, depth + 1);
@@ -3178,7 +3263,7 @@ gtk_tree_view_discover_dirty_iter (GtkTreeView *tree_view,
   GtkTreeViewColumn *column;
   GList *list;
   gint i;
-  gint retval = FALSE;
+  gboolean retval = FALSE;
   gint tmpheight;
 
   if (height)
@@ -3459,9 +3544,7 @@ _gtk_tree_view_find_path (GtkTreeView *tree_view,
   return path;
 }
 
-/* Returns TRUE if we ran out of tree before finding the node,
- * so the returned node is the last node we saw and the returned
- * tree is NULL
+/* Returns TRUE if we ran out of tree before finding the path.
  */
 gboolean
 _gtk_tree_view_find_node (GtkTreeView  *tree_view,
@@ -3478,6 +3561,8 @@ _gtk_tree_view_find_node (GtkTreeView  *tree_view,
   *node = NULL;
   *tree = NULL;
 
+  if (depth == 0)
+    return FALSE;
   do
     {
       if (tmptree == NULL)
@@ -3858,8 +3943,8 @@ gtk_tree_view_setup_model (GtkTreeView *tree_view)
   tree_view->priv->tree = NULL;
 
   g_signal_connectc (tree_view->priv->model,
-                    "changed",
-                    gtk_tree_view_changed,
+                    "range_changed",
+                    gtk_tree_view_range_changed,
                     tree_view,
                     FALSE);
   g_signal_connectc (tree_view->priv->model,
@@ -3916,6 +4001,9 @@ gtk_tree_view_set_model (GtkTreeView  *tree_view,
 {
   g_return_if_fail (GTK_IS_TREE_VIEW (tree_view));
 
+  if (model == tree_view->priv->model)
+    return;
+
   if (model != NULL)
     g_object_ref (model);
 
@@ -3924,25 +4012,25 @@ gtk_tree_view_set_model (GtkTreeView  *tree_view,
       if (GTK_TREE_VIEW_FLAG_SET (tree_view, GTK_TREE_VIEW_MODEL_SETUP))
        {
          g_signal_handlers_disconnect_matched (G_OBJECT (tree_view->priv->model),
-                                               G_SIGNAL_MATCH_FUNC,
+                                               G_SIGNAL_MATCH_DATA,
                                                0, 0, NULL,
-                                               gtk_tree_view_changed, NULL);
+                                               NULL, tree_view);
          g_signal_handlers_disconnect_matched (G_OBJECT (tree_view->priv->model),
-                                               G_SIGNAL_MATCH_FUNC,
+                                               G_SIGNAL_MATCH_DATA,
                                                0, 0, NULL,
-                                               gtk_tree_view_inserted, NULL);
+                                               NULL, tree_view);
          g_signal_handlers_disconnect_matched (G_OBJECT (tree_view->priv->model),
-                                               G_SIGNAL_MATCH_FUNC,
+                                               G_SIGNAL_MATCH_DATA,
                                                0, 0, NULL,
-                                               gtk_tree_view_has_child_toggled, NULL);
+                                               NULL, tree_view);
          g_signal_handlers_disconnect_matched (G_OBJECT (tree_view->priv->model),
-                                               G_SIGNAL_MATCH_FUNC,
+                                               G_SIGNAL_MATCH_DATA,
                                                0, 0, NULL,
-                                               gtk_tree_view_deleted, NULL);
+                                               NULL, tree_view);
          g_signal_handlers_disconnect_matched (G_OBJECT (tree_view->priv->model),
-                                               G_SIGNAL_MATCH_FUNC,
+                                               G_SIGNAL_MATCH_DATA,
                                                0, 0, NULL,
-                                               gtk_tree_view_reordered, NULL);
+                                               NULL, tree_view);
          _gtk_rbtree_free (tree_view->priv->tree);
        }
 
@@ -3960,7 +4048,6 @@ gtk_tree_view_set_model (GtkTreeView  *tree_view,
       tree_view->priv->tree = NULL;
       if (GTK_WIDGET_REALIZED (tree_view))
        _gtk_tree_view_update_size (tree_view);
-      return;
     }
   else if (GTK_WIDGET_REALIZED (tree_view))
     {
@@ -5136,6 +5223,7 @@ gtk_tree_view_expand_row (GtkTreeView *tree_view,
   GtkTreeIter child;
   GtkRBTree *tree;
   GtkRBNode *node;
+  gboolean expand;
 
   g_return_val_if_fail (GTK_IS_TREE_VIEW (tree_view), FALSE);
   g_return_val_if_fail (tree_view->priv->model != NULL, FALSE);
@@ -5154,6 +5242,11 @@ gtk_tree_view_expand_row (GtkTreeView *tree_view,
   if (! gtk_tree_model_iter_has_child (tree_view->priv->model, &iter))
     return FALSE;
 
+  g_signal_emit (G_OBJECT (tree_view), tree_view_signals[EXPAND_ROW], 0, &iter, path, &expand);
+
+  if (expand)
+    return FALSE;
+
   node->children = _gtk_rbtree_new ();
   node->children->parent_tree = tree;
   node->children->parent_node = node;
@@ -5177,9 +5270,9 @@ gtk_tree_view_expand_row (GtkTreeView *tree_view,
  * @tree_view: a #GtkTreeView
  * @path: path to a row in the @tree_view
  *
- * Collapses a row (hides its child rows).
+ * Collapses a row (hides its child rows, if they exist.)
  *
- * Return value: %TRUE if the row was expanded
+ * Return value: %TRUE if the row was collapsed.
  **/
 gboolean
 gtk_tree_view_collapse_row (GtkTreeView *tree_view,
@@ -5188,6 +5281,7 @@ gtk_tree_view_collapse_row (GtkTreeView *tree_view,
   GtkRBTree *tree;
   GtkRBNode *node;
   GtkTreeIter iter;
+  gboolean collapse;
 
   g_return_val_if_fail (GTK_IS_TREE_VIEW (tree_view), FALSE);
   g_return_val_if_fail (tree_view->priv->tree != NULL, FALSE);
@@ -5203,6 +5297,12 @@ gtk_tree_view_collapse_row (GtkTreeView *tree_view,
     return FALSE;
 
   gtk_tree_model_get_iter (tree_view->priv->model, &iter, path);
+
+  g_signal_emit (G_OBJECT (tree_view), tree_view_signals[COLLAPSE_ROW], 0, &iter, path, &collapse);
+  
+  if (collapse)
+    return FALSE;
+
   gtk_tree_view_discover_dirty (tree_view,
                                node->children,
                                &iter,
@@ -6088,9 +6188,7 @@ open_row_timeout (gpointer data)
       (pos == GTK_TREE_VIEW_DROP_INTO_OR_AFTER ||
        pos == GTK_TREE_VIEW_DROP_INTO_OR_BEFORE))
     {
-      gtk_tree_view_expand_row (tree_view,
-                                dest_path,
-                                FALSE);
+      gtk_tree_view_expand_row (tree_view, dest_path, FALSE);
       tree_view->priv->open_dest_timeout = 0;
 
       gtk_tree_path_free (dest_path);