]> Pileus Git - ~andy/gtk/blobdiff - gtk/gtktreemodelfilter.c
Remove ambiguities pointed out by gcc.
[~andy/gtk] / gtk / gtktreemodelfilter.c
index 15aca9ae214bc40736c8995a0c9ced0c803a410b..85a89b77b5a5cf798a8b73a582584fb35bf37732 100644 (file)
  * Boston, MA 02111-1307, USA.
  */
 
+#include <config.h>
 #include "gtktreemodelfilter.h"
 #include "gtkintl.h"
+#include "gtktreednd.h"
+#include "gtkalias.h"
+#include "gtkprivate.h"
 #include <string.h>
 
 /* ITER FORMAT:
@@ -110,6 +114,7 @@ enum
 static void         gtk_tree_model_filter_init                            (GtkTreeModelFilter      *filter);
 static void         gtk_tree_model_filter_class_init                      (GtkTreeModelFilterClass *filter_class);
 static void         gtk_tree_model_filter_tree_model_init                 (GtkTreeModelIface       *iface);
+static void         gtk_tree_model_filter_drag_source_init                (GtkTreeDragSourceIface  *iface);
 static void         gtk_tree_model_filter_finalize                        (GObject                 *object);
 static void         gtk_tree_model_filter_set_property                    (GObject                 *object,
                                                                            guint                    prop_id,
@@ -143,7 +148,7 @@ static void         gtk_tree_model_filter_rows_reordered                  (GtkTr
                                                                            gpointer                data);
 
 /* GtkTreeModel interface */
-static guint        gtk_tree_model_filter_get_flags                       (GtkTreeModel           *model);
+static GtkTreeModelFlags gtk_tree_model_filter_get_flags                       (GtkTreeModel           *model);
 static gint         gtk_tree_model_filter_get_n_columns                   (GtkTreeModel           *model);
 static GType        gtk_tree_model_filter_get_column_type                 (GtkTreeModel           *model,
                                                                            gint                    index);
@@ -177,6 +182,14 @@ static void         gtk_tree_model_filter_ref_node                        (GtkTr
 static void         gtk_tree_model_filter_unref_node                      (GtkTreeModel           *model,
                                                                            GtkTreeIter            *iter);
 
+/* TreeDragSource interface */
+static gboolean    gtk_tree_model_filter_row_draggable                    (GtkTreeDragSource      *drag_source,
+                                                                           GtkTreePath            *path);
+static gboolean    gtk_tree_model_filter_drag_data_get                    (GtkTreeDragSource      *drag_source,
+                                                                           GtkTreePath            *path,
+                                                                           GtkSelectionData       *selection_data);
+static gboolean    gtk_tree_model_filter_drag_data_delete                 (GtkTreeDragSource      *drag_source,
+                                                                           GtkTreePath            *path);
 
 /* private functions */
 static void        gtk_tree_model_filter_build_level                      (GtkTreeModelFilter     *filter,
@@ -213,7 +226,7 @@ static void         gtk_tree_model_filter_set_root                        (GtkTr
 static GtkTreePath *gtk_real_tree_model_filter_convert_child_path_to_path (GtkTreeModelFilter     *filter,
                                                                            GtkTreePath            *child_path,
                                                                            gboolean                build_levels,
-                                                                           gboolean                fetch_childs);
+                                                                           gboolean                fetch_children);
 
 static FilterElt   *gtk_tree_model_filter_fetch_child                     (GtkTreeModelFilter     *filter,
                                                                            FilterLevel            *level,
@@ -222,7 +235,7 @@ static FilterElt   *gtk_tree_model_filter_fetch_child                     (GtkTr
 static void         gtk_tree_model_filter_remove_node                     (GtkTreeModelFilter     *filter,
                                                                            GtkTreeIter            *iter,
                                                                            gboolean                emit_signal);
-static void         gtk_tree_model_filter_update_childs                   (GtkTreeModelFilter     *filter,
+static void         gtk_tree_model_filter_update_children                 (GtkTreeModelFilter     *filter,
                                                                            FilterLevel            *level,
                                                                            FilterElt              *elt);
 static FilterElt   *bsearch_elt_with_offset                               (GArray                 *array,
@@ -259,6 +272,13 @@ gtk_tree_model_filter_get_type (void)
           NULL
         };
 
+      static const GInterfaceInfo drag_source_info =
+        {
+          (GInterfaceInitFunc) gtk_tree_model_filter_drag_source_init,
+          NULL,
+          NULL
+        };
+
       tree_model_filter_type = g_type_register_static (G_TYPE_OBJECT,
                                                        "GtkTreeModelFilter",
                                                        &tree_model_filter_info, 0);
@@ -266,6 +286,10 @@ gtk_tree_model_filter_get_type (void)
       g_type_add_interface_static (tree_model_filter_type,
                                    GTK_TYPE_TREE_MODEL,
                                    &tree_model_info);
+
+      g_type_add_interface_static (tree_model_filter_type,
+                                   GTK_TYPE_TREE_DRAG_SOURCE,
+                                   &drag_source_info);
     }
 
   return tree_model_filter_type;
@@ -300,19 +324,19 @@ gtk_tree_model_filter_class_init (GtkTreeModelFilterClass *filter_class)
    */
   g_object_class_install_property (object_class,
                                    PROP_CHILD_MODEL,
-                                   g_param_spec_object ("child_model",
+                                   g_param_spec_object ("child-model",
                                                         ("The child model"),
                                                         ("The model for the filtermodel to filter"),
                                                         GTK_TYPE_TREE_MODEL,
-                                                        G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY));
+                                                        GTK_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY));
 
   g_object_class_install_property (object_class,
                                    PROP_VIRTUAL_ROOT,
-                                   g_param_spec_boxed ("virtual_root",
+                                   g_param_spec_boxed ("virtual-root",
                                                        ("The virtual root"),
                                                        ("The virtual root (relative to the child model) for this filtermodel"),
                                                        GTK_TYPE_TREE_PATH,
-                                                       G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY));
+                                                       GTK_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY));
 
   g_type_class_add_private (object_class, sizeof (GtkTreeModelFilterPrivate));
 }
@@ -336,6 +360,14 @@ gtk_tree_model_filter_tree_model_init (GtkTreeModelIface *iface)
   iface->unref_node = gtk_tree_model_filter_unref_node;
 }
 
+static void
+gtk_tree_model_filter_drag_source_init (GtkTreeDragSourceIface *iface)
+{
+  iface->row_draggable = gtk_tree_model_filter_row_draggable;
+  iface->drag_data_delete = gtk_tree_model_filter_drag_data_delete;
+  iface->drag_data_get = gtk_tree_model_filter_drag_data_get;
+}
+
 
 static void
 gtk_tree_model_filter_finalize (GObject *object)
@@ -795,7 +827,10 @@ gtk_tree_model_filter_fetch_child (GtkTreeModelFilter *filter,
   g_array_insert_val (level->array, i, elt);
   *index = i;
 
-  for (i = MAX (--i, 0); i < level->array->len; i++)
+  if (i > 0)
+    i--;
+
+  for ( ; i < level->array->len; i++)
     {
       FilterElt *e = &(g_array_index (level->array, FilterElt, i));
       if (e->children)
@@ -871,7 +906,8 @@ gtk_tree_model_filter_remove_node (GtkTreeModelFilter *filter,
         {
           g_array_remove_index (level->array, i);
 
-          for (i = MAX (--i, 0); i < level->array->len; i++)
+         i--;
+          for (i = MAX (i, 0); i < level->array->len; i++)
             {
               /* NOTE: here we do *not* decrease offsets, because the node was
                * not removed from the child model
@@ -908,9 +944,9 @@ emit_has_child_toggled:
 }
 
 static void
-gtk_tree_model_filter_update_childs (GtkTreeModelFilter *filter,
-                                     FilterLevel        *level,
-                                     FilterElt          *elt)
+gtk_tree_model_filter_update_children (GtkTreeModelFilter *filter,
+                                      FilterLevel        *level,
+                                      FilterElt          *elt)
 {
   GtkTreeIter c_iter;
   GtkTreeIter iter;
@@ -963,7 +999,7 @@ bsearch_elt_with_offset (GArray *array,
         return NULL;
     }
 
-  while (start != end)
+  do
     {
       middle = (start + end) / 2;
 
@@ -976,6 +1012,7 @@ bsearch_elt_with_offset (GArray *array,
       else
         break;
     }
+  while (start != end);
 
   if (elt->offset == offset)
     {
@@ -995,7 +1032,7 @@ gtk_tree_model_filter_row_changed (GtkTreeModel *c_model,
 {
   GtkTreeModelFilter *filter = GTK_TREE_MODEL_FILTER (data);
   GtkTreeIter iter;
-  GtkTreeIter childs;
+  GtkTreeIter children;
   GtkTreeIter real_c_iter;
   GtkTreePath *path = NULL;
 
@@ -1050,13 +1087,14 @@ gtk_tree_model_filter_row_changed (GtkTreeModel *c_model,
     {
       /* get rid of this node */
       gtk_tree_model_get_iter (GTK_TREE_MODEL (filter), &iter, path);
-      gtk_tree_model_filter_remove_node (filter, &iter, TRUE);
 
       level = FILTER_LEVEL (iter.user_data);
 
       if (!level->parent_level)
         filter->priv->root_level_visible--;
 
+      gtk_tree_model_filter_remove_node (filter, &iter, TRUE);
+
       goto done;
     }
 
@@ -1069,9 +1107,9 @@ gtk_tree_model_filter_row_changed (GtkTreeModel *c_model,
       level = FILTER_LEVEL (iter.user_data);
       elt = FILTER_ELT (iter.user_data2);
 
-      /* and update the childs */
-      if (gtk_tree_model_iter_children (c_model, &childs, &real_c_iter))
-        gtk_tree_model_filter_update_childs (filter, level, elt);
+      /* and update the children */
+      if (gtk_tree_model_iter_children (c_model, &children, &real_c_iter))
+        gtk_tree_model_filter_update_children (filter, level, elt);
 
       goto done;
     }
@@ -1099,15 +1137,18 @@ gtk_tree_model_filter_row_changed (GtkTreeModel *c_model,
         }
     }
 
+  gtk_tree_model_filter_increment_stamp (filter);
+
   if (!path)
     path = gtk_real_tree_model_filter_convert_child_path_to_path (filter,
                                                                   c_path,
                                                                   TRUE,
                                                                   TRUE);
 
-  g_return_if_fail (path != NULL);
+  if (!path)
+    /* parent is probably being filtered out */
+    goto done;
 
-  gtk_tree_model_filter_increment_stamp (filter);
   gtk_tree_model_get_iter (GTK_TREE_MODEL (filter), &iter, path);
 
   level = FILTER_LEVEL (iter.user_data);
@@ -1121,8 +1162,8 @@ gtk_tree_model_filter_row_changed (GtkTreeModel *c_model,
   /* update stamp */
   gtk_tree_model_row_inserted (GTK_TREE_MODEL (filter), path, &iter);
 
-  if (gtk_tree_model_iter_children (c_model, &childs, c_iter))
-    gtk_tree_model_filter_update_childs (filter, level, elt);
+  if (gtk_tree_model_iter_children (c_model, &children, c_iter))
+    gtk_tree_model_filter_update_children (filter, level, elt);
 
 done:
   if (path)
@@ -1298,7 +1339,7 @@ gtk_tree_model_filter_row_inserted (GtkTreeModel *c_model,
         filter->priv->root_level_visible++;
     }
 
-  /* another iteration to update the references of childs to parents. */
+  /* another iteration to update the references of children to parents. */
   for (i = 0; i < level->array->len; i++)
     {
       FilterElt *e = &g_array_index (level->array, FilterElt, i);
@@ -1554,7 +1595,8 @@ gtk_tree_model_filter_row_deleted (GtkTreeModel *c_model,
       offset = tmp->offset;
       g_array_remove_index (level->array, i);
 
-      for (i = MAX (--i, 0); i < level->array->len; i++)
+      i--;
+      for (i = MAX (i, 0); i < level->array->len; i++)
         {
           elt = &g_array_index (level->array, FilterElt, i);
           if (elt->offset > offset)
@@ -1690,7 +1732,10 @@ gtk_tree_model_filter_rows_reordered (GtkTreeModel *c_model,
     }
 
   if (level->array->len < 1)
-    return;
+    {
+      gtk_tree_path_free (path);
+      return;
+    }
 
   /* NOTE: we do not bail out here if level->array->len < 2 like
    * GtkTreeModelSort does. This because we do some special tricky
@@ -1749,10 +1794,18 @@ gtk_tree_model_filter_rows_reordered (GtkTreeModel *c_model,
 }
 
 /* TreeModelIface implementation */
-static guint
+static GtkTreeModelFlags
 gtk_tree_model_filter_get_flags (GtkTreeModel *model)
 {
+  GtkTreeModelFlags flags;
+
   g_return_val_if_fail (GTK_IS_TREE_MODEL_FILTER (model), 0);
+  g_return_val_if_fail (GTK_TREE_MODEL_FILTER (model)->priv->child_model != NULL, 0);
+
+  flags = gtk_tree_model_get_flags (GTK_TREE_MODEL_FILTER (model)->priv->child_model);
+
+  if ((flags & GTK_TREE_MODEL_LIST_ONLY) == GTK_TREE_MODEL_LIST_ONLY)
+    return GTK_TREE_MODEL_LIST_ONLY;
 
   return 0;
 }
@@ -2222,6 +2275,62 @@ gtk_tree_model_filter_real_unref_node (GtkTreeModel *model,
     }
 }
 
+/* TreeDragSource interface implementation */
+static gboolean
+gtk_tree_model_filter_row_draggable (GtkTreeDragSource *drag_source,
+                                     GtkTreePath       *path)
+{
+  GtkTreeModelFilter *tree_model_filter = (GtkTreeModelFilter *)drag_source;
+  GtkTreePath *child_path;
+  gboolean draggable;
+
+  g_return_val_if_fail (GTK_IS_TREE_MODEL_FILTER (drag_source), FALSE);
+  g_return_val_if_fail (path != NULL, FALSE);
+
+  child_path = gtk_tree_model_filter_convert_path_to_child_path (tree_model_filter, path);
+  draggable = gtk_tree_drag_source_row_draggable (GTK_TREE_DRAG_SOURCE (tree_model_filter->priv->child_model), child_path);
+  gtk_tree_path_free (child_path);
+
+  return draggable;
+}
+
+static gboolean
+gtk_tree_model_filter_drag_data_get (GtkTreeDragSource *drag_source,
+                                     GtkTreePath       *path,
+                                     GtkSelectionData  *selection_data)
+{
+  GtkTreeModelFilter *tree_model_filter = (GtkTreeModelFilter *)drag_source;
+  GtkTreePath *child_path;
+  gboolean gotten;
+
+  g_return_val_if_fail (GTK_IS_TREE_MODEL_FILTER (drag_source), FALSE);
+  g_return_val_if_fail (path != NULL, FALSE);
+
+  child_path = gtk_tree_model_filter_convert_path_to_child_path (tree_model_filter, path);
+  gotten = gtk_tree_drag_source_drag_data_get (GTK_TREE_DRAG_SOURCE (tree_model_filter->priv->child_model), child_path, selection_data);
+  gtk_tree_path_free (child_path);
+
+  return gotten;
+}
+
+static gboolean
+gtk_tree_model_filter_drag_data_delete (GtkTreeDragSource *drag_source,
+                                        GtkTreePath       *path)
+{
+  GtkTreeModelFilter *tree_model_filter = (GtkTreeModelFilter *)drag_source;
+  GtkTreePath *child_path;
+  gboolean deleted;
+
+  g_return_val_if_fail (GTK_IS_TREE_MODEL_FILTER (drag_source), FALSE);
+  g_return_val_if_fail (path != NULL, FALSE);
+
+  child_path = gtk_tree_model_filter_convert_path_to_child_path (tree_model_filter, path);
+  deleted = gtk_tree_drag_source_drag_data_delete (GTK_TREE_DRAG_SOURCE (tree_model_filter->priv->child_model), child_path);
+  gtk_tree_path_free (child_path);
+
+  return deleted;
+}
+
 /* bits and pieces */
 static void
 gtk_tree_model_filter_set_model (GtkTreeModelFilter *filter,
@@ -2231,15 +2340,15 @@ gtk_tree_model_filter_set_model (GtkTreeModelFilter *filter,
 
   if (filter->priv->child_model)
     {
-      g_signal_handler_disconnect (G_OBJECT (filter->priv->child_model),
+      g_signal_handler_disconnect (filter->priv->child_model,
                                    filter->priv->changed_id);
-      g_signal_handler_disconnect (G_OBJECT (filter->priv->child_model),
+      g_signal_handler_disconnect (filter->priv->child_model,
                                    filter->priv->inserted_id);
-      g_signal_handler_disconnect (G_OBJECT (filter->priv->child_model),
+      g_signal_handler_disconnect (filter->priv->child_model,
                                    filter->priv->has_child_toggled_id);
-      g_signal_handler_disconnect (G_OBJECT (filter->priv->child_model),
+      g_signal_handler_disconnect (filter->priv->child_model,
                                    filter->priv->deleted_id);
-      g_signal_handler_disconnect (G_OBJECT (filter->priv->child_model),
+      g_signal_handler_disconnect (filter->priv->child_model,
                                    filter->priv->reordered_id);
 
       /* reset our state */
@@ -2247,7 +2356,7 @@ gtk_tree_model_filter_set_model (GtkTreeModelFilter *filter,
         gtk_tree_model_filter_free_level (filter, filter->priv->root);
 
       filter->priv->root = NULL;
-      g_object_unref (G_OBJECT (filter->priv->child_model));
+      g_object_unref (filter->priv->child_model);
       filter->priv->visible_column = -1;
       /* FIXME: destroy more crack here? the funcs? */
     }
@@ -2256,7 +2365,7 @@ gtk_tree_model_filter_set_model (GtkTreeModelFilter *filter,
 
   if (child_model)
     {
-      g_object_ref (G_OBJECT (filter->priv->child_model));
+      g_object_ref (filter->priv->child_model);
       filter->priv->changed_id =
         g_signal_connect (child_model, "row_changed",
                           G_CALLBACK (gtk_tree_model_filter_row_changed),
@@ -2317,11 +2426,10 @@ gtk_tree_model_filter_new (GtkTreeModel *child_model,
 
   g_return_val_if_fail (GTK_IS_TREE_MODEL (child_model), NULL);
 
-  retval = GTK_TREE_MODEL (g_object_new (gtk_tree_model_filter_get_type (), NULL));
-
-  gtk_tree_model_filter_set_model (GTK_TREE_MODEL_FILTER (retval),
-                                   child_model);
-  gtk_tree_model_filter_set_root (GTK_TREE_MODEL_FILTER (retval), root);
+  retval = g_object_new (GTK_TYPE_TREE_MODEL_FILTER, 
+                        "child-model", child_model,
+                        "virtual-root", root,
+                        NULL);
 
   return retval;
 }
@@ -2355,6 +2463,11 @@ gtk_tree_model_filter_get_model (GtkTreeModelFilter *filter)
  * function should return %TRUE if the given row should be visible and
  * %FALSE otherwise.
  *
+ * If the condition calculated by the function changes over time (e.g. because
+ * it depends on some global parameters), you must call 
+ * gtk_tree_model_filter_refilter() to keep the visibility information of 
+ * the model uptodate.
+ *
  * Since: 2.4
  */
 void
@@ -2387,12 +2500,17 @@ gtk_tree_model_filter_set_visible_func (GtkTreeModelFilter            *filter,
  * @filter: A #GtkTreeModelFilter.
  * @n_columns: The number of columns in the filter model.
  * @types: The #GType<!-- -->s of the columns.
- * @func: A #GtkTreeModelFilterModifyFunc, or %NULL.
+ * @func: A #GtkTreeModelFilterModifyFunc
  * @data: User data to pass to the modify function, or %NULL.
  * @destroy: Destroy notifier of @data, or %NULL.
  *
- * Sets the @filter to have @n_columns columns with @types. If @func
- * is not %NULL, it will set @func to be the modify function of @filter.
+ * With the @n_columns and @types parameters, you give an array of column
+ * types for this model (which will be exposed to the parent model/view).
+ * The @func, @data and @destroy parameters are for specifying the modify
+ * function. The modify function will get called for <emphasis>each</emphasis>
+ * data access, the goal of the modify function is to return the data which 
+ * should be displayed at the location specified using the parameters of the 
+ * modify function.
  *
  * Since: 2.4
  */
@@ -2531,7 +2649,7 @@ static GtkTreePath *
 gtk_real_tree_model_filter_convert_child_path_to_path (GtkTreeModelFilter *filter,
                                                        GtkTreePath        *child_path,
                                                        gboolean            build_levels,
-                                                       gboolean            fetch_childs)
+                                                       gboolean            fetch_children)
 {
   gint *child_indices;
   GtkTreePath *retval;
@@ -2582,7 +2700,7 @@ gtk_real_tree_model_filter_convert_child_path_to_path (GtkTreeModelFilter *filte
           found_child = TRUE;
         }
 
-      if (!found_child && fetch_childs)
+      if (!found_child && fetch_children)
         {
           tmp = gtk_tree_model_filter_fetch_child (filter, level,
                                                    child_indices[i],
@@ -2603,7 +2721,7 @@ gtk_real_tree_model_filter_convert_child_path_to_path (GtkTreeModelFilter *filte
           level = tmp->children;
           found_child = TRUE;
         }
-      else if (!found_child && !fetch_childs)
+      else if (!found_child && !fetch_children)
         {
           /* no path */
           gtk_tree_path_free (real_path);
@@ -2768,3 +2886,6 @@ gtk_tree_model_filter_clear_cache (GtkTreeModelFilter *filter)
     gtk_tree_model_filter_clear_cache_helper (filter,
                                               FILTER_LEVEL (filter->priv->root));
 }
+
+#define __GTK_TREE_MODEL_FILTER_C__
+#include "gtkaliasdef.c"