#include "gtktreemodel.h"
#include "gtktreeview.h"
#include "gtktreeprivate.h"
-#include "gtksignal.h"
+#include "gtkmarshalers.h"
+
+
+#define INITIALIZE_TREE_ITER(Iter) \
+ G_STMT_START{ \
+ (Iter)->stamp = 0; \
+ (Iter)->user_data = NULL; \
+ (Iter)->user_data2 = NULL; \
+ (Iter)->user_data3 = NULL; \
+ }G_STMT_END
+
+
+enum {
+ ROW_CHANGED,
+ ROW_INSERTED,
+ ROW_HAS_CHILD_TOGGLED,
+ ROW_DELETED,
+ ROWS_REORDERED,
+ LAST_SIGNAL
+};
+
+static guint tree_model_signals[LAST_SIGNAL] = { 0 };
struct _GtkTreePath
static void gtk_tree_model_base_init (gpointer g_class);
-GtkType
+GType
gtk_tree_model_get_type (void)
{
- static GtkType tree_model_type = 0;
+ static GType tree_model_type = 0;
if (! tree_model_type)
{
NULL
};
- tree_model_type = g_type_register_static (G_TYPE_INTERFACE, "GtkTreeModel", &tree_model_info, 0);
+ tree_model_type =
+ g_type_register_static (G_TYPE_INTERFACE, "GtkTreeModel",
+ &tree_model_info, 0);
+
g_type_interface_add_prerequisite (tree_model_type, G_TYPE_OBJECT);
}
if (! initialized)
{
- g_signal_new ("range_changed",
- GTK_TYPE_TREE_MODEL,
- G_SIGNAL_RUN_LAST,
- G_STRUCT_OFFSET (GtkTreeModelIface, range_changed),
- NULL, NULL,
- gtk_marshal_VOID__BOXED_BOXED_BOXED_BOXED,
- G_TYPE_NONE, 4,
- GTK_TYPE_TREE_PATH,
- GTK_TYPE_TREE_ITER,
- GTK_TYPE_TREE_PATH,
- GTK_TYPE_TREE_ITER);
- g_signal_new ("inserted",
- GTK_TYPE_TREE_MODEL,
- G_SIGNAL_RUN_LAST,
- G_STRUCT_OFFSET (GtkTreeModelIface, inserted),
- NULL, NULL,
- gtk_marshal_VOID__BOXED_BOXED,
- G_TYPE_NONE, 2,
- GTK_TYPE_TREE_PATH,
- GTK_TYPE_TREE_ITER);
- g_signal_new ("has_child_toggled",
- GTK_TYPE_TREE_MODEL,
- G_SIGNAL_RUN_LAST,
- G_STRUCT_OFFSET (GtkTreeModelIface, has_child_toggled),
- NULL, NULL,
- gtk_marshal_VOID__BOXED_BOXED,
- G_TYPE_NONE, 2,
- GTK_TYPE_TREE_PATH,
- GTK_TYPE_TREE_ITER);
- g_signal_new ("deleted",
- GTK_TYPE_TREE_MODEL,
- G_SIGNAL_RUN_LAST,
- G_STRUCT_OFFSET (GtkTreeModelIface, deleted),
- NULL, NULL,
- gtk_marshal_VOID__BOXED,
- G_TYPE_NONE, 1,
- GTK_TYPE_TREE_PATH);
- g_signal_new ("reordered",
- GTK_TYPE_TREE_MODEL,
- G_SIGNAL_RUN_LAST,
- G_STRUCT_OFFSET (GtkTreeModelIface, reordered),
- NULL, NULL,
- gtk_marshal_VOID__BOXED_BOXED_POINTER,
- G_TYPE_NONE, 3,
- GTK_TYPE_TREE_PATH,
- GTK_TYPE_TREE_ITER,
- G_TYPE_POINTER);
+ tree_model_signals[ROW_CHANGED] =
+ g_signal_new ("row_changed",
+ GTK_TYPE_TREE_MODEL,
+ G_SIGNAL_RUN_LAST,
+ G_STRUCT_OFFSET (GtkTreeModelIface, row_changed),
+ NULL, NULL,
+ _gtk_marshal_VOID__BOXED_BOXED,
+ G_TYPE_NONE, 2,
+ GTK_TYPE_TREE_PATH,
+ GTK_TYPE_TREE_ITER);
+ tree_model_signals[ROW_INSERTED] =
+ g_signal_new ("row_inserted",
+ GTK_TYPE_TREE_MODEL,
+ G_SIGNAL_RUN_LAST,
+ G_STRUCT_OFFSET (GtkTreeModelIface, row_inserted),
+ NULL, NULL,
+ _gtk_marshal_VOID__BOXED_BOXED,
+ G_TYPE_NONE, 2,
+ GTK_TYPE_TREE_PATH,
+ GTK_TYPE_TREE_ITER);
+ tree_model_signals[ROW_HAS_CHILD_TOGGLED] =
+ g_signal_new ("row_has_child_toggled",
+ GTK_TYPE_TREE_MODEL,
+ G_SIGNAL_RUN_LAST,
+ G_STRUCT_OFFSET (GtkTreeModelIface, row_has_child_toggled),
+ NULL, NULL,
+ _gtk_marshal_VOID__BOXED_BOXED,
+ G_TYPE_NONE, 2,
+ GTK_TYPE_TREE_PATH,
+ GTK_TYPE_TREE_ITER);
+ tree_model_signals[ROW_DELETED] =
+ g_signal_new ("row_deleted",
+ GTK_TYPE_TREE_MODEL,
+ G_SIGNAL_RUN_LAST,
+ G_STRUCT_OFFSET (GtkTreeModelIface, row_deleted),
+ NULL, NULL,
+ _gtk_marshal_VOID__BOXED,
+ G_TYPE_NONE, 1,
+ GTK_TYPE_TREE_PATH);
+ tree_model_signals[ROWS_REORDERED] =
+ g_signal_new ("rows_reordered",
+ GTK_TYPE_TREE_MODEL,
+ G_SIGNAL_RUN_LAST,
+ G_STRUCT_OFFSET (GtkTreeModelIface, rows_reordered),
+ NULL, NULL,
+ _gtk_marshal_VOID__BOXED_BOXED_POINTER,
+ G_TYPE_NONE, 3,
+ GTK_TYPE_TREE_PATH,
+ GTK_TYPE_TREE_ITER,
+ G_TYPE_POINTER);
initialized = TRUE;
}
}
/**
* gtk_tree_path_new:
*
- * Creates a new #GtkTreePath.
+ * Creates a new #GtkTreePath. This structure refers to a row.
*
* Return value: A newly created #GtkTreePath.
**/
* colon separated list of numbers. For example, the string "10:4:0" would
* create a path of depth 3 pointing to the 11th child of the root node, the 5th
* child of that 11th child, and the 1st child of that 5th child. If an invalid
- * path is past in, NULL is returned.
+ * path string is passed in, %NULL is returned.
*
- * Return value: A newly created #GtkTreePath, or NULL
+ * Return value: A newly-created #GtkTreePath, or %NULL
**/
GtkTreePath *
-gtk_tree_path_new_from_string (gchar *path)
+gtk_tree_path_new_from_string (const gchar *path)
{
GtkTreePath *retval;
- gchar *orig_path = path;
+ const gchar *orig_path = path;
gchar *ptr;
gint i;
if (i < 0)
{
- g_warning (G_STRLOC"Negative numbers in path %s passed to gtk_tree_path_new_from_string", orig_path);
+ g_warning (G_STRLOC ": Negative numbers in path %s passed to gtk_tree_path_new_from_string", orig_path);
gtk_tree_path_free (retval);
return NULL;
}
break;
if (ptr == path || *ptr != ':')
{
- g_warning (G_STRLOC"Invalid path %s passed to gtk_tree_path_new_from_string", orig_path);
+ g_warning (G_STRLOC ": Invalid path %s passed to gtk_tree_path_new_from_string", orig_path);
gtk_tree_path_free (retval);
return NULL;
}
return retval;
}
+/**
+ * gtk_tree_path_new_from_indices:
+ * @first_index: first integer
+ * @varargs: list of integers terminated by -1
+ *
+ * Creates a new path with @first_index and @varargs as indices.
+ *
+ * Return value: A newly created GtkTreePath.
+ *
+ * Since: 2.2
+ **/
+GtkTreePath *
+gtk_tree_path_new_from_indices (gint first_index,
+ ...)
+{
+ int arg;
+ va_list args;
+ GtkTreePath *path;
+
+ path = gtk_tree_path_new ();
+
+ va_start (args, first_index);
+ arg = first_index;
+
+ while (arg != -1)
+ {
+ gtk_tree_path_append_index (path, arg);
+ arg = va_arg (args, gint);
+ }
+
+ va_end (args);
+
+ return path;
+}
+
/**
* gtk_tree_path_to_string:
* @path: A #GtkTreePath
* Generates a string representation of the path. This string is a ':'
* separated list of numbers. For example, "4:10:0:3" would be an acceptable return value for this string.
*
- * Return value: A newly allocated string. Must be freed with #g_free.
+ * Return value: A newly-allocated string. Must be freed with g_free().
**/
gchar *
gtk_tree_path_to_string (GtkTreePath *path)
}
/**
- * gtk_tree_path_new_root:
+ * gtk_tree_path_new_first:
*
- * Creates a new root #GtkTreePath. The string representation of this path is
- * "0"
+ * Creates a new #GtkTreePath. The string representation of this path is "0"
*
* Return value: A new #GtkTreePath.
**/
GtkTreePath *
-gtk_tree_path_new_root (void)
+gtk_tree_path_new_first (void)
{
GtkTreePath *retval;
/**
* gtk_tree_path_append_index:
* @path: A #GtkTreePath.
- * @index: The index.
+ * @index_: The index.
*
* Appends a new index to a path. As a result, the depth of the path is
* increased.
/**
* gtk_tree_path_prepend_index:
* @path: A #GtkTreePath.
- * @index: The index.
+ * @index_: The index.
*
* Prepends a new index to a path. As a result, the depth of the path is
* increased.
gtk_tree_path_prepend_index (GtkTreePath *path,
gint index)
{
- gint *new_indices = g_new (gint, ++path->depth);
+ gint *new_indices;
+
+ (path->depth)++;
+ new_indices = g_new (gint, path->depth);
+
if (path->indices == NULL)
{
path->indices = new_indices;
* @path: A #GtkTreePath.
*
* Returns the current indices of @path. This is an array of integers, each
- * representing a node in a tree.
+ * representing a node in a tree. This value should not be freed.
*
- * Return value: The current indices, or NULL.
+ * Return value: The current indices, or %NULL.
**/
gint *
gtk_tree_path_get_indices (GtkTreePath *path)
* Return value: A new #GtkTreePath.
**/
GtkTreePath *
-gtk_tree_path_copy (GtkTreePath *path)
+gtk_tree_path_copy (const GtkTreePath *path)
{
GtkTreePath *retval;
return retval;
}
+GType
+gtk_tree_path_get_type (void)
+{
+ static GType our_type = 0;
+
+ if (our_type == 0)
+ our_type = g_boxed_type_register_static ("GtkTreePath",
+ (GBoxedCopyFunc) gtk_tree_path_copy,
+ (GBoxedFreeFunc) gtk_tree_path_free);
+
+ return our_type;
+}
+
/**
* gtk_tree_path_compare:
* @a: A #GtkTreePath.
* @b: A #GtkTreePath to compare with.
*
- * Compares two paths. If @a appears before @b in a tree, then -1, is returned.
+ * Compares two paths. If @a appears before @b in a tree, then -1 is returned.
* If @b appears before @a, then 1 is returned. If the two nodes are equal,
* then 0 is returned.
*
* @path: a #GtkTreePath
* @descendant: another #GtkTreePath
*
- *
+ * Returns %TRUE if @descendant is a descendant of @path.
*
* Return value: %TRUE if @descendant is contained inside @path
**/
* @path: a #GtkTreePath
* @ancestor: another #GtkTreePath
*
- *
+ * Returns %TRUE if @path is a descendant of @ancestor.
*
* Return value: %TRUE if @ancestor contains @path somewhere below it
**/
*
* Moves the @path to point to the previous node at the current depth, if it exists.
*
- * Return value: TRUE if @path has a previous node, and the move was made.
+ * Return value: %TRUE if @path has a previous node, and the move was made.
**/
gboolean
gtk_tree_path_prev (GtkTreePath *path)
*
* Moves the @path to point to it's parent node, if it has a parent.
*
- * Return value: TRUE if @path has a parent, and the move was made.
+ * Return value: %TRUE if @path has a parent, and the move was made.
**/
gboolean
gtk_tree_path_up (GtkTreePath *path)
{
g_return_val_if_fail (path != NULL, FALSE);
- if (path->depth == 1)
+ if (path->depth == 0)
return FALSE;
path->depth--;
*
* Creates a dynamically allocated tree iterator as a copy of @iter. This
* function is not intended for use in applications, because you can just copy
- * the structs by value (GtkTreeIter new_iter = iter;). You
+ * the structs by value (<literal>GtkTreeIter new_iter = iter;</literal>). You
* must free this iter with gtk_tree_iter_free ().
*
- * Return value: a newly allocated copy of @iter.
+ * Return value: a newly-allocated copy of @iter.
**/
GtkTreeIter *
gtk_tree_iter_copy (GtkTreeIter *iter)
* gtk_tree_iter_free:
* @iter: A dynamically allocated tree iterator.
*
- * Free an iterator that has been allocated on the heap. This function is
+ * Frees an iterator that has been allocated on the heap. This function is
* mainly used for language bindings.
**/
void
g_free (iter);
}
+GType
+gtk_tree_iter_get_type (void)
+{
+ static GType our_type = 0;
+
+ if (our_type == 0)
+ our_type = g_boxed_type_register_static ("GtkTreeIter",
+ (GBoxedCopyFunc) gtk_tree_iter_copy,
+ (GBoxedFreeFunc) gtk_tree_iter_free);
+
+ return our_type;
+}
+
/**
* gtk_tree_model_get_flags:
* @tree_model: A #GtkTreeModel.
* gtk_tree_model_get_n_columns:
* @tree_model: A #GtkTreeModel.
*
- * Returns the number of columns supported by the #tree_model
+ * Returns the number of columns supported by @tree_model.
*
* Return value: The number of columns.
**/
/**
* gtk_tree_model_get_column_type:
* @tree_model: A #GtkTreeModel.
- * @index: The column index.
+ * @index_: The column index.
*
* Returns the type of the column.
*
*
* Sets @iter to a valid iterator pointing to @path.
*
- * Return value: TRUE, if @iter was set.
+ * Return value: %TRUE, if @iter was set.
**/
gboolean
gtk_tree_model_get_iter (GtkTreeModel *tree_model,
g_return_val_if_fail (GTK_TREE_MODEL_GET_IFACE (tree_model)->get_iter != NULL, FALSE);
g_return_val_if_fail (path->depth > 0, FALSE);
+ INITIALIZE_TREE_ITER (iter);
+
return (* GTK_TREE_MODEL_GET_IFACE (tree_model)->get_iter) (tree_model, iter, path);
}
+/**
+ * gtk_tree_model_get_iter_from_string:
+ * @tree_model: A #GtkTreeModel.
+ * @iter: An uninitialized #GtkTreeIter.
+ * @path_string: A string representation of a #GtkTreePath.
+ *
+ * Sets @iter to a valid iterator pointing to @path_string, if it
+ * exists. Otherwise, @iter is left invalid and %FALSE is returned.
+ *
+ * Return value: %TRUE, if @iter was set.
+ **/
+gboolean
+gtk_tree_model_get_iter_from_string (GtkTreeModel *tree_model,
+ GtkTreeIter *iter,
+ const gchar *path_string)
+{
+ gboolean retval;
+ GtkTreePath *path;
+
+ g_return_val_if_fail (GTK_IS_TREE_MODEL (tree_model), FALSE);
+ g_return_val_if_fail (iter != NULL, FALSE);
+ g_return_val_if_fail (path_string != NULL, FALSE);
+
+ path = gtk_tree_path_new_from_string (path_string);
+
+ g_return_val_if_fail (path != NULL, FALSE);
+
+ retval = gtk_tree_model_get_iter (tree_model, iter, path);
+ gtk_tree_path_free (path);
+
+ return retval;
+}
+
+/**
+ * gtk_tree_model_get_string_from_iter:
+ * @tree_model: A #GtkTreeModel.
+ * @iter: An #GtkTreeIter.
+ *
+ * Generates a string representation of the iter. This string is a ':'
+ * separated list of numbers. For example, "4:10:0:3" would be an
+ * acceptable return value for this string.
+ *
+ * Return value: A newly-allocated string. Must be freed with g_free().
+ *
+ * Since: 2.2
+ **/
+gchar *
+gtk_tree_model_get_string_from_iter (GtkTreeModel *tree_model,
+ GtkTreeIter *iter)
+{
+ GtkTreePath *path;
+ gchar *ret;
+
+ g_return_val_if_fail (GTK_IS_TREE_MODEL (tree_model), NULL);
+ g_return_val_if_fail (iter != NULL, NULL);
+
+ path = gtk_tree_model_get_path (tree_model, iter);
+
+ g_return_val_if_fail (path != NULL, NULL);
+
+ ret = gtk_tree_path_to_string (path);
+ gtk_tree_path_free (path);
+
+ return ret;
+}
/**
- * gtk_tree_model_get_iter_root:
+ * gtk_tree_model_get_iter_first:
* @tree_model: A #GtkTreeModel.
* @iter: The uninitialized #GtkTreeIter.
*
- * Initialized @iter with the root iterator in the tree (the one at the root
- * path) and returns %TRUE. Returns %FALSE if the tree is empty.
+ * Initializes @iter with the first iterator in the tree (the one at the path
+ * "0") and returns %TRUE. Returns %FALSE if the tree is empty.
*
- * Return value: TRUE, if @iter was set.
+ * Return value: %TRUE, if @iter was set.
**/
gboolean
-gtk_tree_model_get_iter_root (GtkTreeModel *tree_model,
- GtkTreeIter *iter)
+gtk_tree_model_get_iter_first (GtkTreeModel *tree_model,
+ GtkTreeIter *iter)
{
GtkTreePath *path;
gboolean retval;
g_return_val_if_fail (GTK_IS_TREE_MODEL (tree_model), FALSE);
g_return_val_if_fail (iter != NULL, FALSE);
- path = gtk_tree_path_new_root ();
+ path = gtk_tree_path_new_first ();
retval = gtk_tree_model_get_iter (tree_model, iter, path);
gtk_tree_path_free (path);
* @tree_model: A #GtkTreeModel.
* @iter: The #GtkTreeIter.
*
- * Returns a newly created #GtkTreePath referenced by @iter. This path should
- * be freed with #gtk_tree_path_free.
+ * Returns a newly-created #GtkTreePath referenced by @iter. This path should
+ * be freed with gtk_tree_path_free().
*
- * Return value: a newly created #GtkTreePath.
+ * Return value: a newly-created #GtkTreePath.
**/
GtkTreePath *
gtk_tree_model_get_path (GtkTreeModel *tree_model,
* @value: An empty #GValue to set.
*
* Sets initializes and sets @value to that at @column. When done with @value,
- * #g_value_unset needs to be called to free any allocated memory.
+ * g_value_unset() needs to be called to free any allocated memory.
**/
void
gtk_tree_model_get_value (GtkTreeModel *tree_model,
* @iter: The #GtkTreeIter.
*
* Sets @iter to point to the node following it at the current level. If there
- * is no next @iter, FALSE is returned and @iter is set to be invalid.
+ * is no next @iter, %FALSE is returned and @iter is set to be invalid.
*
- * Return value: TRUE if @iter has been changed to the next node.
+ * Return value: %TRUE if @iter has been changed to the next node.
**/
gboolean
gtk_tree_model_iter_next (GtkTreeModel *tree_model,
* gtk_tree_model_iter_children:
* @tree_model: A #GtkTreeModel.
* @iter: The new #GtkTreeIter to be set to the child.
- * @parent: The #GtkTreeIter.
+ * @parent: The #GtkTreeIter, or %NULL
*
* Sets @iter to point to the first child of @parent. If @parent has no children,
- * FALSE is returned and @iter is set to be invalid. @parent will remain a valid
+ * %FALSE is returned and @iter is set to be invalid. @parent will remain a valid
* node after this function has been called.
*
- * Return value: TRUE, if @child has been set to the first child.
+ * If @parent is %NULL returns the first node, equivalent to
+ * <literal>gtk_tree_model_get_iter_first (tree_model, iter);</literal>
+ *
+ * Return value: %TRUE, if @child has been set to the first child.
**/
gboolean
gtk_tree_model_iter_children (GtkTreeModel *tree_model,
g_return_val_if_fail (iter != NULL, FALSE);
g_return_val_if_fail (GTK_TREE_MODEL_GET_IFACE (tree_model)->iter_children != NULL, FALSE);
+ INITIALIZE_TREE_ITER (iter);
+
return (* GTK_TREE_MODEL_GET_IFACE (tree_model)->iter_children) (tree_model, iter, parent);
}
* @tree_model: A #GtkTreeModel.
* @iter: The #GtkTreeIter to test for children.
*
- * Returns TRUE if @iter has children, FALSE otherwise.
+ * Returns %TRUE if @iter has children, %FALSE otherwise.
*
- * Return value: TRUE if @iter has children.
+ * Return value: %TRUE if @iter has children.
**/
gboolean
gtk_tree_model_iter_has_child (GtkTreeModel *tree_model,
/**
* gtk_tree_model_iter_n_children:
* @tree_model: A #GtkTreeModel.
- * @iter: The #GtkTreeIter, or NULL.
+ * @iter: The #GtkTreeIter, or %NULL.
*
* Returns the number of children that @iter has. As a special case, if @iter
- * is NULL, then the number of toplevel nodes is returned.
+ * is %NULL, then the number of toplevel nodes is returned.
*
* Return value: The number of children of @iter.
**/
* gtk_tree_model_iter_nth_child:
* @tree_model: A #GtkTreeModel.
* @iter: The #GtkTreeIter to set to the nth child.
- * @parent: The #GtkTreeIter to get the child from, or NULL.
+ * @parent: The #GtkTreeIter to get the child from, or %NULL.
* @n: Then index of the desired child.
*
* Sets @iter to be the child of @parent, using the given index. The first
- * index is 0. If @index is too big, or @parent has no children, @iter is set
- * to an invalid iterator and FALSE is returned. @parent will remain a valid
+ * index is 0. If @n is too big, or @parent has no children, @iter is set
+ * to an invalid iterator and %FALSE is returned. @parent will remain a valid
* node after this function has been called. As a special case, if @parent is
- * NULL, then the nth root node is set.
+ * %NULL, then the @n<!-- -->th root node is set.
*
- * Return value: TRUE, if @parent has an nth child.
+ * Return value: %TRUE, if @parent has an @n<!-- -->th child.
**/
gboolean
gtk_tree_model_iter_nth_child (GtkTreeModel *tree_model,
g_return_val_if_fail (n >= 0, FALSE);
g_return_val_if_fail (GTK_TREE_MODEL_GET_IFACE (tree_model)->iter_nth_child != NULL, FALSE);
+ INITIALIZE_TREE_ITER (iter);
+
return (* GTK_TREE_MODEL_GET_IFACE (tree_model)->iter_nth_child) (tree_model, iter, parent, n);
}
* @child: The #GtkTreeIter.
*
* Sets @iter to be the parent of @child. If @child is at the toplevel, and
- * doesn't have a parent, then @iter is set to an invalid iterator and FALSE
+ * doesn't have a parent, then @iter is set to an invalid iterator and %FALSE
* is returned. @child will remain a valid node after this function has been
* called.
*
- * Return value: TRUE, if @iter is set to the parent of @child.
+ * Return value: %TRUE, if @iter is set to the parent of @child.
**/
gboolean
gtk_tree_model_iter_parent (GtkTreeModel *tree_model,
g_return_val_if_fail (child != NULL, FALSE);
g_return_val_if_fail (GTK_TREE_MODEL_GET_IFACE (tree_model)->iter_parent != NULL, FALSE);
+ INITIALIZE_TREE_ITER (iter);
+
return (* GTK_TREE_MODEL_GET_IFACE (tree_model)->iter_parent) (tree_model, iter, child);
}
* This function is primarily meant as a way for views to let caching model know
* when nodes are being displayed (and hence, whether or not to cache that
* node.) For example, a file-system based model would not want to keep the
- * entire file-heirarchy in memory, just the sections that are currently being
+ * entire file-hierarchy in memory, just the sections that are currently being
* displayed by every current view.
*
* A model should be expected to be able to get an iter independent of it's
* implement. To be more specific, models may ignore this call as it exists
* primarily for performance reasons.
*
- * For more information on what this means, please see #gtk_tree_model_ref_node.
+ * For more information on what this means, see gtk_tree_model_ref_node().
* Please note that nodes that are deleted are not unreffed.
**/
void
* each column number followed by a place to store the value being
* retrieved. The list is terminated by a -1. For example, to get a
* value from column 0 with type %G_TYPE_STRING, you would
- * write: gtk_tree_model_set (model, iter, 0, &place_string_here, -1),
- * where place_string_here is a gchar* to be filled with the string.
+ * write: <literal>gtk_tree_model_get (model, iter, 0, &place_string_here, -1)</literal>,
+ * where <literal>place_string_here</literal> is a <type>gchar*</type> to be
+ * filled with the string.
* If appropriate, the returned values have to be freed or unreferenced.
*
**/
* gtk_tree_model_get_valist:
* @tree_model: a #GtkTreeModel
* @iter: a row in @tree_model
- * @var_args: va_list of column/return location pairs
+ * @var_args: <type>va_list</type> of column/return location pairs
*
- * See gtk_tree_model_get(), this version takes a va_list for language bindings
- * to use.
+ * See gtk_tree_model_get(), this version takes a <type>va_list</type>
+ * for language bindings to use.
**/
void
gtk_tree_model_get_valist (GtkTreeModel *tree_model,
}
}
+/**
+ * gtk_tree_model_row_changed:
+ * @tree_model: A #GtkTreeModel
+ * @path: A #GtkTreePath pointing to the changed row
+ * @iter: A valid #GtkTreeIter pointing to the changed row
+ *
+ * Emits the "row_changed" signal on @tree_model.
+ **/
void
-gtk_tree_model_range_changed (GtkTreeModel *tree_model,
- GtkTreePath *start_path,
- GtkTreeIter *start_iter,
- GtkTreePath *end_path,
- GtkTreeIter *end_iter)
+gtk_tree_model_row_changed (GtkTreeModel *tree_model,
+ GtkTreePath *path,
+ GtkTreeIter *iter)
{
- gint i;
g_return_if_fail (GTK_IS_TREE_MODEL (tree_model));
- g_return_if_fail (start_path != NULL);
- g_return_if_fail (start_iter != NULL);
- g_return_if_fail (end_path != NULL);
- g_return_if_fail (end_iter != NULL);
-
-#ifndef G_DISABLE_CHECKS
- g_return_if_fail (start_path->depth == end_path->depth);
- for (i = 0; i < start_path->depth - 1; i++)
- if (start_path->indices[i] != end_path->indices[i])
- {
- g_warning ("Concurrent paths were not passed in to gtk_tree_model_range_changed.\n");
- return;
- }
-#endif
- g_signal_emit_by_name (tree_model, "range_changed",
- start_path, start_iter,
- end_path, end_iter);
+ g_return_if_fail (path != NULL);
+ g_return_if_fail (iter != NULL);
+
+ g_signal_emit (tree_model, tree_model_signals[ROW_CHANGED], 0, path, iter);
}
+/**
+ * gtk_tree_model_row_inserted:
+ * @tree_model: A #GtkTreeModel
+ * @path: A #GtkTreePath pointing to the inserted row
+ * @iter: A valid #GtkTreeIter pointing to the inserted row
+ *
+ * Emits the "row_inserted" signal on @tree_model
+ **/
void
-gtk_tree_model_inserted (GtkTreeModel *tree_model,
- GtkTreePath *path,
- GtkTreeIter *iter)
+gtk_tree_model_row_inserted (GtkTreeModel *tree_model,
+ GtkTreePath *path,
+ GtkTreeIter *iter)
{
g_return_if_fail (GTK_IS_TREE_MODEL (tree_model));
g_return_if_fail (path != NULL);
g_return_if_fail (iter != NULL);
- g_signal_emit_by_name (tree_model, "inserted", path, iter);
+ g_signal_emit (tree_model, tree_model_signals[ROW_INSERTED], 0, path, iter);
}
+/**
+ * gtk_tree_model_row_has_child_toggled:
+ * @tree_model: A #GtkTreeModel
+ * @path: A #GtkTreePath pointing to the changed row
+ * @iter: A valid #GtkTreeIter pointing to the changed row
+ *
+ * Emits the "row_has_child_toggled" signal on @tree_model. This should be
+ * called by models after the child state of a node changes.
+ **/
void
-gtk_tree_model_has_child_toggled (GtkTreeModel *tree_model,
- GtkTreePath *path,
- GtkTreeIter *iter)
+gtk_tree_model_row_has_child_toggled (GtkTreeModel *tree_model,
+ GtkTreePath *path,
+ GtkTreeIter *iter)
{
g_return_if_fail (GTK_IS_TREE_MODEL (tree_model));
g_return_if_fail (path != NULL);
g_return_if_fail (iter != NULL);
- g_signal_emit_by_name (tree_model, "has_child_toggled", path, iter);
+ g_signal_emit (tree_model, tree_model_signals[ROW_HAS_CHILD_TOGGLED], 0, path, iter);
}
+/**
+ * gtk_tree_model_row_deleted:
+ * @tree_model: A #GtkTreeModel
+ * @path: A #GtkTreePath pointing to the previous location of the deleted row.
+ *
+ * Emits the "row_deleted" signal on @tree_model. This should be called by
+ * models after a row has been removed. The location pointed to by @path should
+ * be the location that the row previously was at. It may not be a valid
+ * location anymore.
+ **/
void
-gtk_tree_model_deleted (GtkTreeModel *tree_model,
- GtkTreePath *path)
+gtk_tree_model_row_deleted (GtkTreeModel *tree_model,
+ GtkTreePath *path)
{
g_return_if_fail (GTK_IS_TREE_MODEL (tree_model));
g_return_if_fail (path != NULL);
- g_signal_emit_by_name (tree_model, "deleted", path);
+ g_signal_emit (tree_model, tree_model_signals[ROW_DELETED], 0, path);
}
+/**
+ * gtk_tree_model_rows_reordered:
+ * @tree_model: A #GtkTreeModel
+ * @path: A #GtkTreePath pointing to the tree node whose children have been reordered
+ * @iter: A valid #GtkTreeIter pointing to the node whose children have been reordered
+ * @new_order: an array of integers containing the new indices of the children,
+ * i.e. the former child <literal>n</literal> is now at position
+ * @new_order<literal>[n]</literal>.
+ *
+ * Emits the "rows_reordered" signal on @tree_model. This should be called by
+ * models when their rows have been reordered.
+ **/
void
-gtk_tree_model_reordered (GtkTreeModel *tree_model,
- GtkTreePath *path,
- GtkTreeIter *iter,
- gint *new_order)
+gtk_tree_model_rows_reordered (GtkTreeModel *tree_model,
+ GtkTreePath *path,
+ GtkTreeIter *iter,
+ gint *new_order)
{
g_return_if_fail (GTK_IS_TREE_MODEL (tree_model));
g_return_if_fail (new_order != NULL);
- g_signal_emit_by_name (tree_model, "reordered", path, iter, new_order);
+ g_signal_emit (tree_model, tree_model_signals[ROWS_REORDERED], 0, path, iter, new_order);
}
GtkTreeModelForeachFunc func,
gpointer user_data)
{
- gtk_tree_path_append_index (path, 0);
-
do
{
GtkTreeIter child;
+ if ((* func) (model, path, iter, user_data))
+ return TRUE;
+
if (gtk_tree_model_iter_children (model, &child, iter))
{
+ gtk_tree_path_down (path);
if (gtk_tree_model_foreach_helper (model, &child, path, func, user_data))
return TRUE;
+ gtk_tree_path_up (path);
}
- if ((* func) (model, path, iter, user_data))
- return TRUE;
-
gtk_tree_path_next (path);
}
while (gtk_tree_model_iter_next (model, iter));
- gtk_tree_path_up (path);
return FALSE;
}
* @user_data: User data to passed to func.
*
* Calls func on each node in model in a depth-first fashion. If func returns
- * %TRUE, then the tree ceases to be walked, and gtk_tree_model_foreach returns.
+ * %TRUE, then the tree ceases to be walked, and gtk_tree_model_foreach() returns.
**/
void
g_return_if_fail (GTK_IS_TREE_MODEL (model));
g_return_if_fail (func != NULL);
- path = gtk_tree_path_new_root ();
+ path = gtk_tree_path_new_first ();
if (gtk_tree_model_get_iter (model, &iter, path) == FALSE)
- return;
+ {
+ gtk_tree_path_free (path);
+ return;
+ }
gtk_tree_model_foreach_helper (model, &iter, path, func, user_data);
gtk_tree_path_free (path);
* GtkTreeRowReference
*/
+static void gtk_tree_row_reference_unref_path (GtkTreePath *path,
+ GtkTreeModel *model,
+ gint depth);
+
+
+GType
+gtk_tree_row_reference_get_type (void)
+{
+ static GType our_type = 0;
+
+ if (our_type == 0)
+ our_type = g_boxed_type_register_static ("GtkTreeRowReference",
+ (GBoxedCopyFunc) gtk_tree_row_reference_copy,
+ (GBoxedFreeFunc) gtk_tree_row_reference_free);
+
+ return our_type;
+}
+
+
#define ROW_REF_DATA_STRING "gtk-tree-row-refs"
struct _GtkTreeRowReference
{
GtkTreeRowReference *reference = tmp_list->data;
- if (reference->path)
+ if (reference->path == NULL)
+ goto done;
+
+ if (reference->path->depth >= path->depth)
{
- gint depth = gtk_tree_path_get_depth (path);
- gint ref_depth = gtk_tree_path_get_depth (reference->path);
+ gint i;
+ gboolean ancestor = TRUE;
- if (ref_depth >= depth)
+ for (i = 0; i < path->depth - 1; i ++)
{
- gint *indices = gtk_tree_path_get_indices (path);
- gint *ref_indices = gtk_tree_path_get_indices (reference->path);
- gint i;
-
- /* This is the depth that might affect us. */
- i = depth - 1;
-
- if (indices[i] <= ref_indices[i])
- ref_indices[i] += 1;
+ if (path->indices[i] != reference->path->indices[i])
+ {
+ ancestor = FALSE;
+ break;
+ }
}
- }
+ if (ancestor == FALSE)
+ goto done;
+ if (path->indices[path->depth-1] <= reference->path->indices[path->depth-1])
+ reference->path->indices[path->depth-1] += 1;
+ }
+ done:
tmp_list = g_slist_next (tmp_list);
}
}
* deletion with the old path of the just-deleted row. Which means
* that the deleted path is the same now-defunct "coordinate system"
* as the path saved in the reference, which is what we want to fix.
- *
- * Note that this is different from the situation in "inserted," so
- * while you might think you can cut-and-paste between these
- * functions, it's not going to work. ;-)
*/
tmp_list = refs->list;
if (reference->path)
{
- gint depth = gtk_tree_path_get_depth (path);
- gint ref_depth = gtk_tree_path_get_depth (reference->path);
+ gint i;
- if (ref_depth >= depth)
+ if (path->depth > reference->path->depth)
+ goto next;
+ for (i = 0; i < path->depth - 1; i++)
{
- /* Need to adjust path upward */
- gint *indices = gtk_tree_path_get_indices (path);
- gint *ref_indices = gtk_tree_path_get_indices (reference->path);
- gint i;
-
- i = depth - 1;
- if (indices[i] < ref_indices[i])
- ref_indices[i] -= 1;
- else if (indices[i] == ref_indices[i])
- {
- /* the referenced node itself, or its parent, was
- * deleted, mark invalid
- */
-
- gtk_tree_path_free (reference->path);
- reference->path = NULL;
- }
+ if (path->indices[i] != reference->path->indices[i])
+ goto next;
}
+ /* We know it affects us. */
+ if (path->indices[i] == reference->path->indices[i])
+ {
+ if (reference->path->depth > path->depth)
+ /* some parent was deleted, trying to unref any node
+ * between the deleted parent and the node the reference
+ * is pointing to is bad, as those nodes are already gone.
+ */
+ gtk_tree_row_reference_unref_path (reference->path, reference->model, path->depth - 1);
+ else
+ gtk_tree_row_reference_unref_path (reference->path, reference->model, reference->path->depth - 1);
+ gtk_tree_path_free (reference->path);
+ reference->path = NULL;
+ }
+ else if (path->indices[i] < reference->path->indices[i])
+ {
+ reference->path->indices[path->depth-1]-=1;
+ }
}
+
+next:
tmp_list = g_slist_next (tmp_list);
}
}
if (new_order[i] == indices[depth])
{
indices[depth] = i;
- return;
+ break;
}
}
}
static void
connect_ref_callbacks (GtkTreeModel *model)
{
- g_signal_connect (G_OBJECT (model),
- "inserted",
- (GCallback) gtk_tree_row_ref_inserted_callback,
+ g_signal_connect (model,
+ "row_inserted",
+ G_CALLBACK (gtk_tree_row_ref_inserted_callback),
model);
- g_signal_connect (G_OBJECT (model),
- "deleted",
- (GCallback) gtk_tree_row_ref_deleted_callback,
+ g_signal_connect (model,
+ "row_deleted",
+ G_CALLBACK (gtk_tree_row_ref_deleted_callback),
model);
- g_signal_connect (G_OBJECT (model),
- "reordered",
- (GCallback) gtk_tree_row_ref_reordered_callback,
+ g_signal_connect (model,
+ "rows_reordered",
+ G_CALLBACK (gtk_tree_row_ref_reordered_callback),
model);
}
+
+/* We do this recursively so that we can unref children nodes before their parent */
+static void
+gtk_tree_row_reference_unref_path_helper (GtkTreePath *path,
+ GtkTreeModel *model,
+ GtkTreeIter *parent_iter,
+ gint depth,
+ gint current_depth)
+{
+ GtkTreeIter iter;
+
+ if (depth == current_depth)
+ return;
+
+ gtk_tree_model_iter_nth_child (model, &iter, parent_iter, path->indices[current_depth]);
+ gtk_tree_row_reference_unref_path_helper (path, model, &iter, depth, current_depth + 1);
+ gtk_tree_model_unref_node (model, &iter);
+}
+
+static void
+gtk_tree_row_reference_unref_path (GtkTreePath *path,
+ GtkTreeModel *model,
+ gint depth)
+{
+ GtkTreeIter iter;
+
+ if (depth <= 0)
+ return;
+
+ gtk_tree_model_iter_nth_child (model, &iter, NULL, path->indices[0]);
+ gtk_tree_row_reference_unref_path_helper (path, model, &iter, depth, 1);
+ gtk_tree_model_unref_node (model, &iter);
+}
+
static void
disconnect_ref_callbacks (GtkTreeModel *model)
{
- g_signal_handlers_disconnect_matched (G_OBJECT (model),
+ g_signal_handlers_disconnect_matched (model,
G_SIGNAL_MATCH_FUNC,
0, 0, NULL,
gtk_tree_row_ref_inserted_callback,
NULL);
- g_signal_handlers_disconnect_matched (G_OBJECT (model),
+ g_signal_handlers_disconnect_matched (model,
G_SIGNAL_MATCH_FUNC,
0, 0, NULL,
gtk_tree_row_ref_deleted_callback,
NULL);
- g_signal_handlers_disconnect_matched (G_OBJECT (model),
+ g_signal_handlers_disconnect_matched (model,
G_SIGNAL_MATCH_FUNC,
0, 0, NULL,
gtk_tree_row_ref_reordered_callback,
NULL);
}
+/**
+ * gtk_tree_row_reference_new:
+ * @model: A #GtkTreeModel
+ * @path: A valid #GtkTreePath to monitor
+ *
+ * Creates a row reference based on @path. This reference will keep pointing to
+ * the node pointed to by @path, so long as it exists. It listens to all
+ * signals emitted by @model, and updates it's path appropriately. If @path
+ * isn't a valid path in @model, then %NULL is returned.
+ *
+ * Return value: A newly allocated #GtkTreeRowReference, or %NULL
+ **/
GtkTreeRowReference *
gtk_tree_row_reference_new (GtkTreeModel *model,
GtkTreePath *path)
return gtk_tree_row_reference_new_proxy (G_OBJECT (model), model, path);
}
+/**
+ * gtk_tree_row_reference_new_proxy:
+ * @proxy: A proxy #GObject
+ * @model: A #GtkTreeModel
+ * @path: A valid #GtkTreePath to monitor
+ *
+ * You do not need to use this function. Creates a row reference based on
+ * @path. This reference will keep pointing to the node pointed to by @path, so
+ * long as it exists. If @path isn't a valid path in @model, then %NULL is
+ * returned. However, unlike references created with
+ * gtk_tree_row_reference_new(), it does not listen to the model for changes.
+ * The creator of the row reference must do this explicitly using
+ * gtk_tree_row_reference_inserted(), gtk_tree_row_reference_deleted(),
+ * gtk_tree_row_reference_reordered(). This must be called once per signal per
+ * proxy.
+ *
+ * This type of row reference is primarily meant by structures that need to
+ * carefully monitor exactly when a row_reference updates itself, and is not
+ * generally needed by most applications.
+ *
+ * Return value: A newly allocated #GtkTreeRowReference, or %NULL
+ **/
GtkTreeRowReference *
gtk_tree_row_reference_new_proxy (GObject *proxy,
GtkTreeModel *model,
{
GtkTreeRowReference *reference;
RowRefList *refs;
+ GtkTreeIter parent_iter;
+ gint i;
g_return_val_if_fail (G_IS_OBJECT (proxy), NULL);
g_return_val_if_fail (GTK_IS_TREE_MODEL (model), NULL);
g_return_val_if_fail (path != NULL, NULL);
+ g_return_val_if_fail (path->depth > 0, NULL);
+
+ /* check that the path is valid */
+ if (gtk_tree_model_get_iter (model, &parent_iter, path) == FALSE)
+ return NULL;
+
+ /* Now we want to ref every node */
+ gtk_tree_model_iter_nth_child (model, &parent_iter, NULL, path->indices[0]);
+ gtk_tree_model_ref_node (model, &parent_iter);
+ for (i = 1; i < path->depth; i++)
+ {
+ GtkTreeIter iter;
+ gtk_tree_model_iter_nth_child (model, &iter, &parent_iter, path->indices[i]);
+ gtk_tree_model_ref_node (model, &iter);
+ parent_iter = iter;
+ }
+
+ /* Make ther row reference */
reference = g_new (GtkTreeRowReference, 1);
g_object_ref (proxy);
* gtk_tree_row_reference_get_path:
* @reference: A #GtkTreeRowReference
*
- * Returns a path that the row reference currently points to, or NULL if the
+ * Returns a path that the row reference currently points to, or %NULL if the
* path pointed to is no longer valid.
*
- * Return value: A current path, or NULL.
+ * Return value: A current path, or %NULL.
**/
GtkTreePath *
gtk_tree_row_reference_get_path (GtkTreeRowReference *reference)
return TRUE;
}
+
+/**
+ * gtk_tree_row_reference_copy:
+ * @reference: a #GtkTreeRowReference
+ *
+ * Copies a #GtkTreeRowReference.
+ *
+ * Return value: a copy of @reference.
+ *
+ * Since: 2.2
+ **/
+GtkTreeRowReference *
+gtk_tree_row_reference_copy (GtkTreeRowReference *reference)
+{
+ return gtk_tree_row_reference_new_proxy (reference->proxy,
+ reference->model,
+ reference->path);
+}
+
/**
* gtk_tree_row_reference_free:
* @reference: A #GtkTreeRowReference, or NULL
if (refs->list == NULL)
{
- disconnect_ref_callbacks (reference->model);
+ if (G_OBJECT (reference->model) == reference->proxy)
+ disconnect_ref_callbacks (reference->model);
+
g_object_set_data (G_OBJECT (reference->proxy),
ROW_REF_DATA_STRING,
NULL);
}
- g_object_unref (reference->proxy);
- g_object_unref (reference->model);
if (reference->path)
- gtk_tree_path_free (reference->path);
+ {
+ gtk_tree_row_reference_unref_path (reference->path, reference->model, reference->path->depth);
+ gtk_tree_path_free (reference->path);
+ }
+ g_object_unref (reference->proxy);
+ g_object_unref (reference->model);
g_free (reference);
}
+/**
+ * gtk_tree_row_reference_inserted:
+ * @proxy: A #GObject
+ * @path: The row position that was inserted
+ *
+ * Lets a set of row reference created by gtk_tree_row_reference_new_proxy()
+ * know that the model emitted the "row_inserted" signal.
+ **/
void
gtk_tree_row_reference_inserted (GObject *proxy,
GtkTreePath *path)
}
+/**
+ * gtk_tree_row_reference_deleted:
+ * @proxy: A #GObject
+ * @path: The path position that was deleted
+ *
+ * Lets a set of row reference created by gtk_tree_row_reference_new_proxy()
+ * know that the model emitted the "row_deleted" signal.
+ **/
void
gtk_tree_row_reference_deleted (GObject *proxy,
GtkTreePath *path)
gtk_tree_row_ref_deleted_callback (NULL, path, proxy);
}
+/**
+ * gtk_tree_row_reference_reordered:
+ * @proxy: A #GObject
+ * @path: The parent path of the reordered signal
+ * @iter: The iter pointing to the parent of the reordered
+ * @new_order: The new order of rows
+ *
+ * Lets a set of row reference created by gtk_tree_row_reference_new_proxy()
+ * know that the model emitted the "rows_reordered" signal.
+ **/
void
gtk_tree_row_reference_reordered (GObject *proxy,
GtkTreePath *path,