1 /* gtktreemodel.c
2 * Copyright (C) 2000 Red Hat, Inc., Jonathan Blandford <jrb@redhat.com>
3 *
4 * This library is free software; you can redistribute it and/or
5 * modify it under the terms of the GNU Library General Public
6 * License as published by the Free Software Foundation; either
7 * version 2 of the License, or (at your option) any later version.
8 *
9 * This library is distributed in the hope that it will be useful,
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
12 * Library General Public License for more details.
13 *
14 * You should have received a copy of the GNU Library General Public
15 * License along with this library. If not, see <http://www.gnu.org/licenses/>.
16 */
17
18 #include "config.h"
19 #include <stdlib.h>
20 #include <string.h>
21 #include <glib.h>
22 #include <glib/gprintf.h>
23 #include <gobject/gvaluecollector.h>
24 #include "gtktreemodel.h"
25 #include "gtktreeview.h"
26 #include "gtktreeprivate.h"
27 #include "gtkmarshalers.h"
28 #include "gtkintl.h"
29
30 /**
31 * SECTION:gtktreemodel
32 * @Title: GtkTreeModel
33 * @Short_description: The tree interface used by GtkTreeView
34 * @See_also: #GtkTreeView, #GtkTreeStore, #GtkListStore,
35 * [GtkTreeView drag-and-drop][gtk3-GtkTreeView-drag-and-drop]
36 * #GtkTreeSortable
37 *
38 * The #GtkTreeModel interface defines a generic tree interface for
39 * use by the #GtkTreeView widget. It is an abstract interface, and
40 * is designed to be usable with any appropriate data structure. The
41 * programmer just has to implement this interface on their own data
42 * type for it to be viewable by a #GtkTreeView widget.
43 *
44 * The model is represented as a hierarchical tree of strongly-typed,
45 * columned data. In other words, the model can be seen as a tree where
46 * every node has different values depending on which column is being
47 * queried. The type of data found in a column is determined by using
48 * the GType system (ie. #G_TYPE_INT, #GTK_TYPE_BUTTON, #G_TYPE_POINTER,
49 * etc). The types are homogeneous per column across all nodes. It is
50 * important to note that this interface only provides a way of examining
51 * a model and observing changes. The implementation of each individual
52 * model decides how and if changes are made.
53 *
54 * In order to make life simpler for programmers who do not need to
55 * write their own specialized model, two generic models are provided
56 * — the #GtkTreeStore and the #GtkListStore. To use these, the
57 * developer simply pushes data into these models as necessary. These
58 * models provide the data structure as well as all appropriate tree
59 * interfaces. As a result, implementing drag and drop, sorting, and
60 * storing data is trivial. For the vast majority of trees and lists,
61 * these two models are sufficient.
62 *
63 * Models are accessed on a node/column level of granularity. One can
64 * query for the value of a model at a certain node and a certain
65 * column on that node. There are two structures used to reference a
66 * particular node in a model. They are the #GtkTreePath-struct and
67 * the #GtkTreeIter-struct (“iter” is short for iterator). Most of the
68 * interface consists of operations on a #GtkTreeIter-struct.
69 *
70 * A path is essentially a potential node. It is a location on a model
71 * that may or may not actually correspond to a node on a specific
72 * model. The #GtkTreePath-struct can be converted into either an
73 * array of unsigned integers or a string. The string form is a list
74 * of numbers separated by a colon. Each number refers to the offset
75 * at that level. Thus, the path `0` refers to the root
76 * node and the path `2:4` refers to the fifth child of
77 * the third node.
78 *
79 * By contrast, a #GtkTreeIter-struct is a reference to a specific node on
80 * a specific model. It is a generic struct with an integer and three
81 * generic pointers. These are filled in by the model in a model-specific
82 * way. One can convert a path to an iterator by calling
83 * gtk_tree_model_get_iter(). These iterators are the primary way
84 * of accessing a model and are similar to the iterators used by
85 * #GtkTextBuffer. They are generally statically allocated on the
86 * stack and only used for a short time. The model interface defines
87 * a set of operations using them for navigating the model.
88 *
89 * It is expected that models fill in the iterator with private data.
90 * For example, the #GtkListStore model, which is internally a simple
91 * linked list, stores a list node in one of the pointers. The
92 * #GtkTreeModelSort stores an array and an offset in two of the
93 * pointers. Additionally, there is an integer field. This field is
94 * generally filled with a unique stamp per model. This stamp is for
95 * catching errors resulting from using invalid iterators with a model.
96 *
97 * The lifecycle of an iterator can be a little confusing at first.
98 * Iterators are expected to always be valid for as long as the model
99 * is unchanged (and doesn’t emit a signal). The model is considered
100 * to own all outstanding iterators and nothing needs to be done to
101 * free them from the user’s point of view. Additionally, some models
102 * guarantee that an iterator is valid for as long as the node it refers
103 * to is valid (most notably the #GtkTreeStore and #GtkListStore).
104 * Although generally uninteresting, as one always has to allow for
105 * the case where iterators do not persist beyond a signal, some very
106 * important performance enhancements were made in the sort model.
107 * As a result, the #GTK_TREE_MODEL_ITERS_PERSIST flag was added to
108 * indicate this behavior.
109 *
110 * To help show some common operation of a model, some examples are
111 * provided. The first example shows three ways of getting the iter at
112 * the location `3:2:5`. While the first method shown is
113 * easier, the second is much more common, as you often get paths from
114 * callbacks.
115 *
116 * ## Acquiring a #GtkTreeIter-struct
117 *
118 * |[<!-- language="C" -->
119 * // Three ways of getting the iter pointing to the location
120 * GtkTreePath *path;
121 * GtkTreeIter iter;
122 * GtkTreeIter parent_iter;
123 *
124 * // get the iterator from a string
125 * gtk_tree_model_get_iter_from_string (model,
126 * &iter,
127 * "3:2:5");
128 *
129 * // get the iterator from a path
130 * path = gtk_tree_path_new_from_string ("3:2:5");
131 * gtk_tree_model_get_iter (model, &iter, path);
132 * gtk_tree_path_free (path);
133 *
134 * // walk the tree to find the iterator
135 * gtk_tree_model_iter_nth_child (model, &iter,
136 * NULL, 3);
137 * parent_iter = iter;
138 * gtk_tree_model_iter_nth_child (model, &iter,
139 * &parent_iter, 2);
140 * parent_iter = iter;
141 * gtk_tree_model_iter_nth_child (model, &iter,
142 * &parent_iter, 5);
143 * ]|
144 *
145 * This second example shows a quick way of iterating through a list
146 * and getting a string and an integer from each row. The
147 * populate_model() function used below is not
148 * shown, as it is specific to the #GtkListStore. For information on
149 * how to write such a function, see the #GtkListStore documentation.
150 *
151 * ## Reading data from a #GtkTreeModel
152 *
153 * |[<!-- language="C" -->
154 * enum
155 * {
156 * STRING_COLUMN,
157 * INT_COLUMN,
158 * N_COLUMNS
159 * };
160 *
161 * ...
162 *
163 * GtkTreeModel *list_store;
164 * GtkTreeIter iter;
165 * gboolean valid;
166 * gint row_count = 0;
167 *
168 * // make a new list_store
169 * list_store = gtk_list_store_new (N_COLUMNS,
170 * G_TYPE_STRING,
171 * G_TYPE_INT);
172 *
173 * // Fill the list store with data
174 * populate_model (list_store);
175 *
176 * // Get the first iter in the list, check it is valid and walk
177 * // through the list, reading each row.
178 *
179 * valid = gtk_tree_model_get_iter_first (list_store,
180 * &iter);
181 * while (valid)
182 * {
183 * gchar *str_data;
184 * gint int_data;
185 *
186 * // Make sure you terminate calls to gtk_tree_model_get() with a “-1” value
187 * gtk_tree_model_get (list_store, &iter,
188 * STRING_COLUMN, &str_data,
189 * INT_COLUMN, &int_data,
190 * -1);
191 *
192 * // Do something with the data
193 * g_print ("Row %d: (%s,%d)\n",
194 * row_count, str_data, int_data);
195 * g_free (str_data);
196 *
197 * valid = gtk_tree_model_iter_next (list_store,
198 * &iter);
199 * row_count++;
200 * }
201 * ]|
202 *
203 * The #GtkTreeModel interface contains two methods for reference
204 * counting: gtk_tree_model_ref_node() and gtk_tree_model_unref_node().
205 * These two methods are optional to implement. The reference counting
206 * is meant as a way for views to let models know when nodes are being
207 * displayed. #GtkTreeView will take a reference on a node when it is
208 * visible, which means the node is either in the toplevel or expanded.
209 * Being displayed does not mean that the node is currently directly
210 * visible to the user in the viewport. Based on this reference counting
211 * scheme a caching model, for example, can decide whether or not to cache
212 * a node based on the reference count. A file-system based model would
213 * not want to keep the entire file hierarchy in memory, but just the
214 * folders that are currently expanded in every current view.
215 *
216 * When working with reference counting, the following rules must be taken
217 * into account:
218 *
219 * - Never take a reference on a node without owning a reference on its parent.
220 * This means that all parent nodes of a referenced node must be referenced
221 * as well.
222 *
223 * - Outstanding references on a deleted node are not released. This is not
224 * possible because the node has already been deleted by the time the
225 * row-deleted signal is received.
226 *
227 * - Models are not obligated to emit a signal on rows of which none of its
228 * siblings are referenced. To phrase this differently, signals are only
229 * required for levels in which nodes are referenced. For the root level
230 * however, signals must be emitted at all times (however the root level
231 * is always referenced when any view is attached).
232 */
233
234 #define INITIALIZE_TREE_ITER(Iter) \
235 G_STMT_START{ \
236 (Iter)->stamp = 0; \
237 (Iter)->user_data = NULL; \
238 (Iter)->user_data2 = NULL; \
239 (Iter)->user_data3 = NULL; \
240 }G_STMT_END
241
242 #define ROW_REF_DATA_STRING "gtk-tree-row-refs"
243
244 enum {
245 ROW_CHANGED,
246 ROW_INSERTED,
247 ROW_HAS_CHILD_TOGGLED,
248 ROW_DELETED,
249 ROWS_REORDERED,
250 LAST_SIGNAL
251 };
252
253 static guint tree_model_signals[LAST_SIGNAL] = { 0 };
254
255 struct _GtkTreePath
256 {
257 gint depth; /* Number of elements */
258 gint alloc; /* Number of allocated elements */
259 gint *indices;
260 };
261
262 typedef struct
263 {
264 GSList *list;
265 } RowRefList;
266
267 static void gtk_tree_model_base_init (gpointer g_class);
268
269 /* custom closures */
270 static void row_inserted_marshal (GClosure *closure,
271 GValue /* out */ *return_value,
272 guint n_param_value,
273 const GValue *param_values,
274 gpointer invocation_hint,
275 gpointer marshal_data);
276 static void row_deleted_marshal (GClosure *closure,
277 GValue /* out */ *return_value,
278 guint n_param_value,
279 const GValue *param_values,
280 gpointer invocation_hint,
281 gpointer marshal_data);
282 static void rows_reordered_marshal (GClosure *closure,
283 GValue /* out */ *return_value,
284 guint n_param_value,
285 const GValue *param_values,
286 gpointer invocation_hint,
287 gpointer marshal_data);
288
289 static void gtk_tree_row_ref_inserted (RowRefList *refs,
290 GtkTreePath *path,
291 GtkTreeIter *iter);
292 static void gtk_tree_row_ref_deleted (RowRefList *refs,
293 GtkTreePath *path);
294 static void gtk_tree_row_ref_reordered (RowRefList *refs,
295 GtkTreePath *path,
296 GtkTreeIter *iter,
297 gint *new_order);
298
299 GType
gtk_tree_model_get_type(void)300 gtk_tree_model_get_type (void)
301 {
302 static GType tree_model_type = 0;
303
304 if (! tree_model_type)
305 {
306 const GTypeInfo tree_model_info =
307 {
308 sizeof (GtkTreeModelIface), /* class_size */
309 gtk_tree_model_base_init, /* base_init */
310 NULL, /* base_finalize */
311 NULL,
312 NULL, /* class_finalize */
313 NULL, /* class_data */
314 0,
315 0, /* n_preallocs */
316 NULL
317 };
318
319 tree_model_type =
320 g_type_register_static (G_TYPE_INTERFACE, I_("GtkTreeModel"),
321 &tree_model_info, 0);
322
323 g_type_interface_add_prerequisite (tree_model_type, G_TYPE_OBJECT);
324 }
325
326 return tree_model_type;
327 }
328
329 static void
gtk_tree_model_base_init(gpointer g_class)330 gtk_tree_model_base_init (gpointer g_class)
331 {
332 static gboolean initialized = FALSE;
333 GClosure *closure;
334
335 if (! initialized)
336 {
337 GType row_inserted_params[2];
338 GType row_deleted_params[1];
339 GType rows_reordered_params[3];
340
341 row_inserted_params[0] = GTK_TYPE_TREE_PATH | G_SIGNAL_TYPE_STATIC_SCOPE;
342 row_inserted_params[1] = GTK_TYPE_TREE_ITER;
343
344 row_deleted_params[0] = GTK_TYPE_TREE_PATH | G_SIGNAL_TYPE_STATIC_SCOPE;
345
346 rows_reordered_params[0] = GTK_TYPE_TREE_PATH | G_SIGNAL_TYPE_STATIC_SCOPE;
347 rows_reordered_params[1] = GTK_TYPE_TREE_ITER;
348 rows_reordered_params[2] = G_TYPE_POINTER;
349
350 /**
351 * GtkTreeModel::row-changed:
352 * @tree_model: the #GtkTreeModel on which the signal is emitted
353 * @path: a #GtkTreePath-struct identifying the changed row
354 * @iter: a valid #GtkTreeIter-struct pointing to the changed row
355 *
356 * This signal is emitted when a row in the model has changed.
357 */
358 tree_model_signals[ROW_CHANGED] =
359 g_signal_new (I_("row-changed"),
360 GTK_TYPE_TREE_MODEL,
361 G_SIGNAL_RUN_LAST,
362 G_STRUCT_OFFSET (GtkTreeModelIface, row_changed),
363 NULL, NULL,
364 _gtk_marshal_VOID__BOXED_BOXED,
365 G_TYPE_NONE, 2,
366 GTK_TYPE_TREE_PATH | G_SIGNAL_TYPE_STATIC_SCOPE,
367 GTK_TYPE_TREE_ITER);
368 g_signal_set_va_marshaller (tree_model_signals[ROW_CHANGED],
369 G_TYPE_FROM_CLASS (g_class),
370 _gtk_marshal_VOID__BOXED_BOXEDv);
371
372 /* We need to get notification about structure changes
373 * to update row references., so instead of using the
374 * standard g_signal_new() with an offset into our interface
375 * structure, we use a customs closures for the class
376 * closures (default handlers) that first update row references
377 * and then calls the function from the interface structure.
378 *
379 * The reason we don't simply update the row references from
380 * the wrapper functions (gtk_tree_model_row_inserted(), etc.)
381 * is to keep proper ordering with respect to signal handlers
382 * connected normally and after.
383 */
384
385 /**
386 * GtkTreeModel::row-inserted:
387 * @tree_model: the #GtkTreeModel on which the signal is emitted
388 * @path: a #GtkTreePath-struct identifying the new row
389 * @iter: a valid #GtkTreeIter-struct pointing to the new row
390 *
391 * This signal is emitted when a new row has been inserted in
392 * the model.
393 *
394 * Note that the row may still be empty at this point, since
395 * it is a common pattern to first insert an empty row, and
396 * then fill it with the desired values.
397 */
398 closure = g_closure_new_simple (sizeof (GClosure), NULL);
399 g_closure_set_marshal (closure, row_inserted_marshal);
400 tree_model_signals[ROW_INSERTED] =
401 g_signal_newv (I_("row-inserted"),
402 GTK_TYPE_TREE_MODEL,
403 G_SIGNAL_RUN_FIRST,
404 closure,
405 NULL, NULL,
406 _gtk_marshal_VOID__BOXED_BOXED,
407 G_TYPE_NONE, 2,
408 row_inserted_params);
409 g_signal_set_va_marshaller (tree_model_signals[ROW_INSERTED],
410 G_TYPE_FROM_CLASS (g_class),
411 _gtk_marshal_VOID__BOXED_BOXEDv);
412
413 /**
414 * GtkTreeModel::row-has-child-toggled:
415 * @tree_model: the #GtkTreeModel on which the signal is emitted
416 * @path: a #GtkTreePath-struct identifying the row
417 * @iter: a valid #GtkTreeIter-struct pointing to the row
418 *
419 * This signal is emitted when a row has gotten the first child
420 * row or lost its last child row.
421 */
422 tree_model_signals[ROW_HAS_CHILD_TOGGLED] =
423 g_signal_new (I_("row-has-child-toggled"),
424 GTK_TYPE_TREE_MODEL,
425 G_SIGNAL_RUN_LAST,
426 G_STRUCT_OFFSET (GtkTreeModelIface, row_has_child_toggled),
427 NULL, NULL,
428 _gtk_marshal_VOID__BOXED_BOXED,
429 G_TYPE_NONE, 2,
430 GTK_TYPE_TREE_PATH | G_SIGNAL_TYPE_STATIC_SCOPE,
431 GTK_TYPE_TREE_ITER);
432 g_signal_set_va_marshaller (tree_model_signals[ROW_HAS_CHILD_TOGGLED],
433 G_TYPE_FROM_CLASS (g_class),
434 _gtk_marshal_VOID__BOXED_BOXEDv);
435
436 /**
437 * GtkTreeModel::row-deleted:
438 * @tree_model: the #GtkTreeModel on which the signal is emitted
439 * @path: a #GtkTreePath-struct identifying the row
440 *
441 * This signal is emitted when a row has been deleted.
442 *
443 * Note that no iterator is passed to the signal handler,
444 * since the row is already deleted.
445 *
446 * This should be called by models after a row has been removed.
447 * The location pointed to by @path should be the location that
448 * the row previously was at. It may not be a valid location anymore.
449 */
450 closure = g_closure_new_simple (sizeof (GClosure), NULL);
451 g_closure_set_marshal (closure, row_deleted_marshal);
452 tree_model_signals[ROW_DELETED] =
453 g_signal_newv (I_("row-deleted"),
454 GTK_TYPE_TREE_MODEL,
455 G_SIGNAL_RUN_FIRST,
456 closure,
457 NULL, NULL,
458 NULL,
459 G_TYPE_NONE, 1,
460 row_deleted_params);
461
462 /**
463 * GtkTreeModel::rows-reordered: (skip)
464 * @tree_model: the #GtkTreeModel on which the signal is emitted
465 * @path: a #GtkTreePath-struct identifying the tree node whose children
466 * have been reordered
467 * @iter: a valid #GtkTreeIter-struct pointing to the node whose children
468 * have been reordered, or %NULL if the depth of @path is 0
469 * @new_order: an array of integers mapping the current position
470 * of each child to its old position before the re-ordering,
471 * i.e. @new_order`[newpos] = oldpos`
472 *
473 * This signal is emitted when the children of a node in the
474 * #GtkTreeModel have been reordered.
475 *
476 * Note that this signal is not emitted
477 * when rows are reordered by DND, since this is implemented
478 * by removing and then reinserting the row.
479 */
480 closure = g_closure_new_simple (sizeof (GClosure), NULL);
481 g_closure_set_marshal (closure, rows_reordered_marshal);
482 tree_model_signals[ROWS_REORDERED] =
483 g_signal_newv (I_("rows-reordered"),
484 GTK_TYPE_TREE_MODEL,
485 G_SIGNAL_RUN_FIRST,
486 closure,
487 NULL, NULL,
488 _gtk_marshal_VOID__BOXED_BOXED_POINTER,
489 G_TYPE_NONE, 3,
490 rows_reordered_params);
491 g_signal_set_va_marshaller (tree_model_signals[ROWS_REORDERED],
492 G_TYPE_FROM_CLASS (g_class),
493 _gtk_marshal_VOID__BOXED_BOXED_POINTERv);
494 initialized = TRUE;
495 }
496 }
497
498 static void
row_inserted_marshal(GClosure * closure,GValue * return_value,guint n_param_values,const GValue * param_values,gpointer invocation_hint,gpointer marshal_data)499 row_inserted_marshal (GClosure *closure,
500 GValue /* out */ *return_value,
501 guint n_param_values,
502 const GValue *param_values,
503 gpointer invocation_hint,
504 gpointer marshal_data)
505 {
506 GtkTreeModelIface *iface;
507
508 void (* row_inserted_callback) (GtkTreeModel *tree_model,
509 GtkTreePath *path,
510 GtkTreeIter *iter) = NULL;
511
512 GObject *model = g_value_get_object (param_values + 0);
513 GtkTreePath *path = (GtkTreePath *)g_value_get_boxed (param_values + 1);
514 GtkTreeIter *iter = (GtkTreeIter *)g_value_get_boxed (param_values + 2);
515
516 /* first, we need to update internal row references */
517 gtk_tree_row_ref_inserted ((RowRefList *)g_object_get_data (model, ROW_REF_DATA_STRING),
518 path, iter);
519
520 /* fetch the interface ->row_inserted implementation */
521 iface = GTK_TREE_MODEL_GET_IFACE (model);
522 row_inserted_callback = G_STRUCT_MEMBER (gpointer, iface,
523 G_STRUCT_OFFSET (GtkTreeModelIface,
524 row_inserted));
525
526 /* Call that default signal handler, it if has been set */
527 if (row_inserted_callback)
528 row_inserted_callback (GTK_TREE_MODEL (model), path, iter);
529 }
530
531 static void
row_deleted_marshal(GClosure * closure,GValue * return_value,guint n_param_values,const GValue * param_values,gpointer invocation_hint,gpointer marshal_data)532 row_deleted_marshal (GClosure *closure,
533 GValue /* out */ *return_value,
534 guint n_param_values,
535 const GValue *param_values,
536 gpointer invocation_hint,
537 gpointer marshal_data)
538 {
539 GtkTreeModelIface *iface;
540 void (* row_deleted_callback) (GtkTreeModel *tree_model,
541 GtkTreePath *path) = NULL;
542 GObject *model = g_value_get_object (param_values + 0);
543 GtkTreePath *path = (GtkTreePath *)g_value_get_boxed (param_values + 1);
544
545 /* first, we need to update internal row references */
546 gtk_tree_row_ref_deleted ((RowRefList *)g_object_get_data (model, ROW_REF_DATA_STRING),
547 path);
548
549 /* fetch the interface ->row_deleted implementation */
550 iface = GTK_TREE_MODEL_GET_IFACE (model);
551 row_deleted_callback = G_STRUCT_MEMBER (gpointer, iface,
552 G_STRUCT_OFFSET (GtkTreeModelIface,
553 row_deleted));
554
555 /* Call that default signal handler, it if has been set */
556 if (row_deleted_callback)
557 row_deleted_callback (GTK_TREE_MODEL (model), path);
558 }
559
560 static void
rows_reordered_marshal(GClosure * closure,GValue * return_value,guint n_param_values,const GValue * param_values,gpointer invocation_hint,gpointer marshal_data)561 rows_reordered_marshal (GClosure *closure,
562 GValue /* out */ *return_value,
563 guint n_param_values,
564 const GValue *param_values,
565 gpointer invocation_hint,
566 gpointer marshal_data)
567 {
568 GtkTreeModelIface *iface;
569 void (* rows_reordered_callback) (GtkTreeModel *tree_model,
570 GtkTreePath *path,
571 GtkTreeIter *iter,
572 gint *new_order);
573
574 GObject *model = g_value_get_object (param_values + 0);
575 GtkTreePath *path = (GtkTreePath *)g_value_get_boxed (param_values + 1);
576 GtkTreeIter *iter = (GtkTreeIter *)g_value_get_boxed (param_values + 2);
577 gint *new_order = (gint *)g_value_get_pointer (param_values + 3);
578
579 /* first, we need to update internal row references */
580 gtk_tree_row_ref_reordered ((RowRefList *)g_object_get_data (model, ROW_REF_DATA_STRING),
581 path, iter, new_order);
582
583 /* fetch the interface ->rows_reordered implementation */
584 iface = GTK_TREE_MODEL_GET_IFACE (model);
585 rows_reordered_callback = G_STRUCT_MEMBER (gpointer, iface,
586 G_STRUCT_OFFSET (GtkTreeModelIface,
587 rows_reordered));
588
589 /* Call that default signal handler, it if has been set */
590 if (rows_reordered_callback)
591 rows_reordered_callback (GTK_TREE_MODEL (model), path, iter, new_order);
592 }
593
594 /**
595 * gtk_tree_path_new:
596 *
597 * Creates a new #GtkTreePath-struct.
598 * This refers to a row.
599 *
600 * Returns: A newly created #GtkTreePath-struct.
601 */
602 GtkTreePath *
gtk_tree_path_new(void)603 gtk_tree_path_new (void)
604 {
605 GtkTreePath *retval;
606 retval = g_slice_new (GtkTreePath);
607 retval->depth = 0;
608 retval->alloc = 0;
609 retval->indices = NULL;
610
611 return retval;
612 }
613
614 /**
615 * gtk_tree_path_new_from_string:
616 * @path: The string representation of a path
617 *
618 * Creates a new #GtkTreePath-struct initialized to @path.
619 *
620 * @path is expected to be a colon separated list of numbers.
621 * For example, the string “10:4:0” would create a path of depth
622 * 3 pointing to the 11th child of the root node, the 5th
623 * child of that 11th child, and the 1st child of that 5th child.
624 * If an invalid path string is passed in, %NULL is returned.
625 *
626 * Returns: A newly-created #GtkTreePath-struct, or %NULL
627 */
628 GtkTreePath *
gtk_tree_path_new_from_string(const gchar * path)629 gtk_tree_path_new_from_string (const gchar *path)
630 {
631 GtkTreePath *retval;
632 const gchar *orig_path = path;
633 gchar *ptr;
634 gint i;
635
636 g_return_val_if_fail (path != NULL, NULL);
637 g_return_val_if_fail (*path != '\000', NULL);
638
639 retval = gtk_tree_path_new ();
640
641 while (1)
642 {
643 i = strtol (path, &ptr, 10);
644 if (i < 0)
645 {
646 g_warning (G_STRLOC ": Negative numbers in path %s passed to gtk_tree_path_new_from_string", orig_path);
647 gtk_tree_path_free (retval);
648 return NULL;
649 }
650
651 gtk_tree_path_append_index (retval, i);
652
653 if (*ptr == '\000')
654 break;
655 if (ptr == path || *ptr != ':')
656 {
657 g_warning (G_STRLOC ": Invalid path %s passed to gtk_tree_path_new_from_string", orig_path);
658 gtk_tree_path_free (retval);
659 return NULL;
660 }
661 path = ptr + 1;
662 }
663
664 return retval;
665 }
666
667 /**
668 * gtk_tree_path_new_from_indices:
669 * @first_index: first integer
670 * @...: list of integers terminated by -1
671 *
672 * Creates a new path with @first_index and @varargs as indices.
673 *
674 * Returns: A newly created #GtkTreePath-struct
675 *
676 * Since: 2.2
677 */
678 GtkTreePath *
gtk_tree_path_new_from_indices(gint first_index,...)679 gtk_tree_path_new_from_indices (gint first_index,
680 ...)
681 {
682 int arg;
683 va_list args;
684 GtkTreePath *path;
685
686 path = gtk_tree_path_new ();
687
688 va_start (args, first_index);
689 arg = first_index;
690
691 while (arg != -1)
692 {
693 gtk_tree_path_append_index (path, arg);
694 arg = va_arg (args, gint);
695 }
696
697 va_end (args);
698
699 return path;
700 }
701
702 /**
703 * gtk_tree_path_new_from_indicesv: (rename-to gtk_tree_path_new_from_indices)
704 * @indices: (array length=length): array of indices
705 * @length: length of @indices array
706 *
707 * Creates a new path with the given @indices array of @length.
708 *
709 * Returns: A newly created #GtkTreePath-struct
710 *
711 * Since: 3.12
712 */
713 GtkTreePath *
gtk_tree_path_new_from_indicesv(gint * indices,gsize length)714 gtk_tree_path_new_from_indicesv (gint *indices,
715 gsize length)
716 {
717 GtkTreePath *path;
718
719 g_return_val_if_fail (indices != NULL && length != 0, NULL);
720
721 path = gtk_tree_path_new ();
722 path->alloc = length;
723 path->depth = length;
724 path->indices = g_new (gint, length);
725 memcpy (path->indices, indices, length * sizeof (gint));
726
727 return path;
728 }
729
730 /**
731 * gtk_tree_path_to_string:
732 * @path: A #GtkTreePath-struct
733 *
734 * Generates a string representation of the path.
735 *
736 * This string is a “:” separated list of numbers.
737 * For example, “4:10:0:3” would be an acceptable
738 * return value for this string.
739 *
740 * Returns: A newly-allocated string.
741 * Must be freed with g_free().
742 */
743 gchar *
gtk_tree_path_to_string(GtkTreePath * path)744 gtk_tree_path_to_string (GtkTreePath *path)
745 {
746 gchar *retval, *ptr, *end;
747 gint i, n;
748
749 g_return_val_if_fail (path != NULL, NULL);
750
751 if (path->depth == 0)
752 return NULL;
753
754 n = path->depth * 12;
755 ptr = retval = g_new0 (gchar, n);
756 end = ptr + n;
757 g_snprintf (retval, end - ptr, "%d", path->indices[0]);
758 while (*ptr != '\000')
759 ptr++;
760
761 for (i = 1; i < path->depth; i++)
762 {
763 g_snprintf (ptr, end - ptr, ":%d", path->indices[i]);
764 while (*ptr != '\000')
765 ptr++;
766 }
767
768 return retval;
769 }
770
771 /**
772 * gtk_tree_path_new_first:
773 *
774 * Creates a new #GtkTreePath-struct.
775 *
776 * The string representation of this path is “0”.
777 *
778 * Returns: A new #GtkTreePath-struct
779 */
780 GtkTreePath *
gtk_tree_path_new_first(void)781 gtk_tree_path_new_first (void)
782 {
783 GtkTreePath *retval;
784
785 retval = gtk_tree_path_new ();
786 gtk_tree_path_append_index (retval, 0);
787
788 return retval;
789 }
790
791 /**
792 * gtk_tree_path_append_index:
793 * @path: a #GtkTreePath-struct
794 * @index_: the index
795 *
796 * Appends a new index to a path.
797 *
798 * As a result, the depth of the path is increased.
799 */
800 void
gtk_tree_path_append_index(GtkTreePath * path,gint index_)801 gtk_tree_path_append_index (GtkTreePath *path,
802 gint index_)
803 {
804 g_return_if_fail (path != NULL);
805 g_return_if_fail (index_ >= 0);
806
807 if (path->depth == path->alloc)
808 {
809 gint *indices;
810 path->alloc = MAX (path->alloc * 2, 1);
811 indices = g_new (gint, path->alloc);
812 memcpy (indices, path->indices, path->depth * sizeof (gint));
813 g_free (path->indices);
814 path->indices = indices;
815 }
816
817 path->depth += 1;
818 path->indices[path->depth - 1] = index_;
819 }
820
821 /**
822 * gtk_tree_path_prepend_index:
823 * @path: a #GtkTreePath-struct
824 * @index_: the index
825 *
826 * Prepends a new index to a path.
827 *
828 * As a result, the depth of the path is increased.
829 */
830 void
gtk_tree_path_prepend_index(GtkTreePath * path,gint index)831 gtk_tree_path_prepend_index (GtkTreePath *path,
832 gint index)
833 {
834 if (path->depth == path->alloc)
835 {
836 gint *indices;
837 path->alloc = MAX (path->alloc * 2, 1);
838 indices = g_new (gint, path->alloc);
839 memcpy (indices + 1, path->indices, path->depth * sizeof (gint));
840 g_free (path->indices);
841 path->indices = indices;
842 }
843 else if (path->depth > 0)
844 memmove (path->indices + 1, path->indices, path->depth * sizeof (gint));
845
846 path->depth += 1;
847 path->indices[0] = index;
848 }
849
850 /**
851 * gtk_tree_path_get_depth:
852 * @path: a #GtkTreePath-struct
853 *
854 * Returns the current depth of @path.
855 *
856 * Returns: The depth of @path
857 */
858 gint
gtk_tree_path_get_depth(GtkTreePath * path)859 gtk_tree_path_get_depth (GtkTreePath *path)
860 {
861 g_return_val_if_fail (path != NULL, 0);
862
863 return path->depth;
864 }
865
866 /**
867 * gtk_tree_path_get_indices: (skip)
868 * @path: a #GtkTreePath-struct
869 *
870 * Returns the current indices of @path.
871 *
872 * This is an array of integers, each representing a node in a tree.
873 * This value should not be freed.
874 *
875 * The length of the array can be obtained with gtk_tree_path_get_depth().
876 *
877 * Returns: The current indices, or %NULL
878 */
879 gint *
gtk_tree_path_get_indices(GtkTreePath * path)880 gtk_tree_path_get_indices (GtkTreePath *path)
881 {
882 g_return_val_if_fail (path != NULL, NULL);
883
884 return path->indices;
885 }
886
887 /**
888 * gtk_tree_path_get_indices_with_depth: (rename-to gtk_tree_path_get_indices)
889 * @path: a #GtkTreePath-struct
890 * @depth: (out) (allow-none): return location for number of elements
891 * returned in the integer array, or %NULL
892 *
893 * Returns the current indices of @path.
894 *
895 * This is an array of integers, each representing a node in a tree.
896 * It also returns the number of elements in the array.
897 * The array should not be freed.
898 *
899 * Returns: (array length=depth) (transfer none): The current
900 * indices, or %NULL
901 *
902 * Since: 3.0
903 */
904 gint *
gtk_tree_path_get_indices_with_depth(GtkTreePath * path,gint * depth)905 gtk_tree_path_get_indices_with_depth (GtkTreePath *path,
906 gint *depth)
907 {
908 g_return_val_if_fail (path != NULL, NULL);
909
910 if (depth)
911 *depth = path->depth;
912
913 return path->indices;
914 }
915
916 /**
917 * gtk_tree_path_free:
918 * @path: (allow-none): a #GtkTreePath-struct
919 *
920 * Frees @path. If @path is %NULL, it simply returns.
921 */
922 void
gtk_tree_path_free(GtkTreePath * path)923 gtk_tree_path_free (GtkTreePath *path)
924 {
925 if (!path)
926 return;
927
928 g_free (path->indices);
929 g_slice_free (GtkTreePath, path);
930 }
931
932 /**
933 * gtk_tree_path_copy:
934 * @path: a #GtkTreePath-struct
935 *
936 * Creates a new #GtkTreePath-struct as a copy of @path.
937 *
938 * Returns: a new #GtkTreePath-struct
939 */
940 GtkTreePath *
gtk_tree_path_copy(const GtkTreePath * path)941 gtk_tree_path_copy (const GtkTreePath *path)
942 {
943 GtkTreePath *retval;
944
945 g_return_val_if_fail (path != NULL, NULL);
946
947 retval = g_slice_new (GtkTreePath);
948 retval->depth = path->depth;
949 retval->alloc = retval->depth;
950 retval->indices = g_new (gint, path->alloc);
951 memcpy (retval->indices, path->indices, path->depth * sizeof (gint));
952 return retval;
953 }
954
G_DEFINE_BOXED_TYPE(GtkTreePath,gtk_tree_path,gtk_tree_path_copy,gtk_tree_path_free)955 G_DEFINE_BOXED_TYPE (GtkTreePath, gtk_tree_path,
956 gtk_tree_path_copy,
957 gtk_tree_path_free)
958
959 /**
960 * gtk_tree_path_compare:
961 * @a: a #GtkTreePath-struct
962 * @b: a #GtkTreePath-struct to compare with
963 *
964 * Compares two paths.
965 *
966 * If @a appears before @b in a tree, then -1 is returned.
967 * If @b appears before @a, then 1 is returned.
968 * If the two nodes are equal, then 0 is returned.
969 *
970 * Returns: the relative positions of @a and @b
971 */
972 gint
973 gtk_tree_path_compare (const GtkTreePath *a,
974 const GtkTreePath *b)
975 {
976 gint p = 0, q = 0;
977
978 g_return_val_if_fail (a != NULL, 0);
979 g_return_val_if_fail (b != NULL, 0);
980 g_return_val_if_fail (a->depth > 0, 0);
981 g_return_val_if_fail (b->depth > 0, 0);
982
983 do
984 {
985 if (a->indices[p] == b->indices[q])
986 continue;
987 return (a->indices[p] < b->indices[q]?-1:1);
988 }
989 while (++p < a->depth && ++q < b->depth);
990 if (a->depth == b->depth)
991 return 0;
992 return (a->depth < b->depth?-1:1);
993 }
994
995 /**
996 * gtk_tree_path_is_ancestor:
997 * @path: a #GtkTreePath-struct
998 * @descendant: another #GtkTreePath-struct
999 *
1000 * Returns %TRUE if @descendant is a descendant of @path.
1001 *
1002 * Returns: %TRUE if @descendant is contained inside @path
1003 */
1004 gboolean
gtk_tree_path_is_ancestor(GtkTreePath * path,GtkTreePath * descendant)1005 gtk_tree_path_is_ancestor (GtkTreePath *path,
1006 GtkTreePath *descendant)
1007 {
1008 gint i;
1009
1010 g_return_val_if_fail (path != NULL, FALSE);
1011 g_return_val_if_fail (descendant != NULL, FALSE);
1012
1013 /* can't be an ancestor if we're deeper */
1014 if (path->depth >= descendant->depth)
1015 return FALSE;
1016
1017 i = 0;
1018 while (i < path->depth)
1019 {
1020 if (path->indices[i] != descendant->indices[i])
1021 return FALSE;
1022 ++i;
1023 }
1024
1025 return TRUE;
1026 }
1027
1028 /**
1029 * gtk_tree_path_is_descendant:
1030 * @path: a #GtkTreePath-struct
1031 * @ancestor: another #GtkTreePath-struct
1032 *
1033 * Returns %TRUE if @path is a descendant of @ancestor.
1034 *
1035 * Returns: %TRUE if @ancestor contains @path somewhere below it
1036 */
1037 gboolean
gtk_tree_path_is_descendant(GtkTreePath * path,GtkTreePath * ancestor)1038 gtk_tree_path_is_descendant (GtkTreePath *path,
1039 GtkTreePath *ancestor)
1040 {
1041 gint i;
1042
1043 g_return_val_if_fail (path != NULL, FALSE);
1044 g_return_val_if_fail (ancestor != NULL, FALSE);
1045
1046 /* can't be a descendant if we're shallower in the tree */
1047 if (path->depth <= ancestor->depth)
1048 return FALSE;
1049
1050 i = 0;
1051 while (i < ancestor->depth)
1052 {
1053 if (path->indices[i] != ancestor->indices[i])
1054 return FALSE;
1055 ++i;
1056 }
1057
1058 return TRUE;
1059 }
1060
1061
1062 /**
1063 * gtk_tree_path_next:
1064 * @path: a #GtkTreePath-struct
1065 *
1066 * Moves the @path to point to the next node at the current depth.
1067 */
1068 void
gtk_tree_path_next(GtkTreePath * path)1069 gtk_tree_path_next (GtkTreePath *path)
1070 {
1071 g_return_if_fail (path != NULL);
1072 g_return_if_fail (path->depth > 0);
1073
1074 path->indices[path->depth - 1] ++;
1075 }
1076
1077 /**
1078 * gtk_tree_path_prev:
1079 * @path: a #GtkTreePath-struct
1080 *
1081 * Moves the @path to point to the previous node at the
1082 * current depth, if it exists.
1083 *
1084 * Returns: %TRUE if @path has a previous node, and
1085 * the move was made
1086 */
1087 gboolean
gtk_tree_path_prev(GtkTreePath * path)1088 gtk_tree_path_prev (GtkTreePath *path)
1089 {
1090 g_return_val_if_fail (path != NULL, FALSE);
1091
1092 if (path->depth == 0)
1093 return FALSE;
1094
1095 if (path->indices[path->depth - 1] == 0)
1096 return FALSE;
1097
1098 path->indices[path->depth - 1] -= 1;
1099
1100 return TRUE;
1101 }
1102
1103 /**
1104 * gtk_tree_path_up:
1105 * @path: a #GtkTreePath-struct
1106 *
1107 * Moves the @path to point to its parent node, if it has a parent.
1108 *
1109 * Returns: %TRUE if @path has a parent, and the move was made
1110 */
1111 gboolean
gtk_tree_path_up(GtkTreePath * path)1112 gtk_tree_path_up (GtkTreePath *path)
1113 {
1114 g_return_val_if_fail (path != NULL, FALSE);
1115
1116 if (path->depth == 0)
1117 return FALSE;
1118
1119 path->depth--;
1120
1121 return TRUE;
1122 }
1123
1124 /**
1125 * gtk_tree_path_down:
1126 * @path: a #GtkTreePath-struct
1127 *
1128 * Moves @path to point to the first child of the current path.
1129 */
1130 void
gtk_tree_path_down(GtkTreePath * path)1131 gtk_tree_path_down (GtkTreePath *path)
1132 {
1133 g_return_if_fail (path != NULL);
1134
1135 gtk_tree_path_append_index (path, 0);
1136 }
1137
1138 /**
1139 * gtk_tree_iter_copy:
1140 * @iter: a #GtkTreeIter-struct
1141 *
1142 * Creates a dynamically allocated tree iterator as a copy of @iter.
1143 *
1144 * This function is not intended for use in applications,
1145 * because you can just copy the structs by value
1146 * (`GtkTreeIter new_iter = iter;`).
1147 * You must free this iter with gtk_tree_iter_free().
1148 *
1149 * Returns: a newly-allocated copy of @iter
1150 */
1151 GtkTreeIter *
gtk_tree_iter_copy(GtkTreeIter * iter)1152 gtk_tree_iter_copy (GtkTreeIter *iter)
1153 {
1154 GtkTreeIter *retval;
1155
1156 g_return_val_if_fail (iter != NULL, NULL);
1157
1158 retval = g_slice_new (GtkTreeIter);
1159 *retval = *iter;
1160
1161 return retval;
1162 }
1163
1164 /**
1165 * gtk_tree_iter_free:
1166 * @iter: a dynamically allocated tree iterator
1167 *
1168 * Frees an iterator that has been allocated by gtk_tree_iter_copy().
1169 *
1170 * This function is mainly used for language bindings.
1171 */
1172 void
gtk_tree_iter_free(GtkTreeIter * iter)1173 gtk_tree_iter_free (GtkTreeIter *iter)
1174 {
1175 g_return_if_fail (iter != NULL);
1176
1177 g_slice_free (GtkTreeIter, iter);
1178 }
1179
G_DEFINE_BOXED_TYPE(GtkTreeIter,gtk_tree_iter,gtk_tree_iter_copy,gtk_tree_iter_free)1180 G_DEFINE_BOXED_TYPE (GtkTreeIter, gtk_tree_iter,
1181 gtk_tree_iter_copy,
1182 gtk_tree_iter_free)
1183
1184 /**
1185 * gtk_tree_model_get_flags:
1186 * @tree_model: a #GtkTreeModel
1187 *
1188 * Returns a set of flags supported by this interface.
1189 *
1190 * The flags are a bitwise combination of #GtkTreeModelFlags.
1191 * The flags supported should not change during the lifetime
1192 * of the @tree_model.
1193 *
1194 * Returns: the flags supported by this interface
1195 */
1196 GtkTreeModelFlags
1197 gtk_tree_model_get_flags (GtkTreeModel *tree_model)
1198 {
1199 GtkTreeModelIface *iface;
1200
1201 g_return_val_if_fail (GTK_IS_TREE_MODEL (tree_model), 0);
1202
1203 iface = GTK_TREE_MODEL_GET_IFACE (tree_model);
1204 if (iface->get_flags)
1205 return (* iface->get_flags) (tree_model);
1206
1207 return 0;
1208 }
1209
1210 /**
1211 * gtk_tree_model_get_n_columns:
1212 * @tree_model: a #GtkTreeModel
1213 *
1214 * Returns the number of columns supported by @tree_model.
1215 *
1216 * Returns: the number of columns
1217 */
1218 gint
gtk_tree_model_get_n_columns(GtkTreeModel * tree_model)1219 gtk_tree_model_get_n_columns (GtkTreeModel *tree_model)
1220 {
1221 GtkTreeModelIface *iface;
1222 g_return_val_if_fail (GTK_IS_TREE_MODEL (tree_model), 0);
1223
1224 iface = GTK_TREE_MODEL_GET_IFACE (tree_model);
1225 g_return_val_if_fail (iface->get_n_columns != NULL, 0);
1226
1227 return (* iface->get_n_columns) (tree_model);
1228 }
1229
1230 /**
1231 * gtk_tree_model_get_column_type:
1232 * @tree_model: a #GtkTreeModel
1233 * @index_: the column index
1234 *
1235 * Returns the type of the column.
1236 *
1237 * Returns: the type of the column
1238 */
1239 GType
gtk_tree_model_get_column_type(GtkTreeModel * tree_model,gint index)1240 gtk_tree_model_get_column_type (GtkTreeModel *tree_model,
1241 gint index)
1242 {
1243 GtkTreeModelIface *iface;
1244
1245 g_return_val_if_fail (GTK_IS_TREE_MODEL (tree_model), G_TYPE_INVALID);
1246
1247 iface = GTK_TREE_MODEL_GET_IFACE (tree_model);
1248 g_return_val_if_fail (iface->get_column_type != NULL, G_TYPE_INVALID);
1249 g_return_val_if_fail (index >= 0, G_TYPE_INVALID);
1250
1251 return (* iface->get_column_type) (tree_model, index);
1252 }
1253
1254 /**
1255 * gtk_tree_model_get_iter:
1256 * @tree_model: a #GtkTreeModel
1257 * @iter: (out): the uninitialized #GtkTreeIter-struct
1258 * @path: the #GtkTreePath-struct
1259 *
1260 * Sets @iter to a valid iterator pointing to @path. If @path does
1261 * not exist, @iter is set to an invalid iterator and %FALSE is returned.
1262 *
1263 * Returns: %TRUE, if @iter was set
1264 */
1265 gboolean
gtk_tree_model_get_iter(GtkTreeModel * tree_model,GtkTreeIter * iter,GtkTreePath * path)1266 gtk_tree_model_get_iter (GtkTreeModel *tree_model,
1267 GtkTreeIter *iter,
1268 GtkTreePath *path)
1269 {
1270 GtkTreeModelIface *iface;
1271
1272 g_return_val_if_fail (GTK_IS_TREE_MODEL (tree_model), FALSE);
1273 g_return_val_if_fail (iter != NULL, FALSE);
1274 g_return_val_if_fail (path != NULL, FALSE);
1275
1276 iface = GTK_TREE_MODEL_GET_IFACE (tree_model);
1277 g_return_val_if_fail (iface->get_iter != NULL, FALSE);
1278 g_return_val_if_fail (path->depth > 0, FALSE);
1279
1280 INITIALIZE_TREE_ITER (iter);
1281
1282 return (* iface->get_iter) (tree_model, iter, path);
1283 }
1284
1285 /**
1286 * gtk_tree_model_get_iter_from_string:
1287 * @tree_model: a #GtkTreeModel
1288 * @iter: (out): an uninitialized #GtkTreeIter-struct
1289 * @path_string: a string representation of a #GtkTreePath-struct
1290 *
1291 * Sets @iter to a valid iterator pointing to @path_string, if it
1292 * exists. Otherwise, @iter is left invalid and %FALSE is returned.
1293 *
1294 * Returns: %TRUE, if @iter was set
1295 */
1296 gboolean
gtk_tree_model_get_iter_from_string(GtkTreeModel * tree_model,GtkTreeIter * iter,const gchar * path_string)1297 gtk_tree_model_get_iter_from_string (GtkTreeModel *tree_model,
1298 GtkTreeIter *iter,
1299 const gchar *path_string)
1300 {
1301 gboolean retval;
1302 GtkTreePath *path;
1303
1304 g_return_val_if_fail (GTK_IS_TREE_MODEL (tree_model), FALSE);
1305 g_return_val_if_fail (iter != NULL, FALSE);
1306 g_return_val_if_fail (path_string != NULL, FALSE);
1307
1308 path = gtk_tree_path_new_from_string (path_string);
1309
1310 g_return_val_if_fail (path != NULL, FALSE);
1311
1312 retval = gtk_tree_model_get_iter (tree_model, iter, path);
1313 gtk_tree_path_free (path);
1314
1315 return retval;
1316 }
1317
1318 /**
1319 * gtk_tree_model_get_string_from_iter:
1320 * @tree_model: a #GtkTreeModel
1321 * @iter: a #GtkTreeIter-struct
1322 *
1323 * Generates a string representation of the iter.
1324 *
1325 * This string is a “:” separated list of numbers.
1326 * For example, “4:10:0:3” would be an acceptable
1327 * return value for this string.
1328 *
1329 * Returns: a newly-allocated string.
1330 * Must be freed with g_free().
1331 *
1332 * Since: 2.2
1333 */
1334 gchar *
gtk_tree_model_get_string_from_iter(GtkTreeModel * tree_model,GtkTreeIter * iter)1335 gtk_tree_model_get_string_from_iter (GtkTreeModel *tree_model,
1336 GtkTreeIter *iter)
1337 {
1338 GtkTreePath *path;
1339 gchar *ret;
1340
1341 g_return_val_if_fail (GTK_IS_TREE_MODEL (tree_model), NULL);
1342 g_return_val_if_fail (iter != NULL, NULL);
1343
1344 path = gtk_tree_model_get_path (tree_model, iter);
1345
1346 g_return_val_if_fail (path != NULL, NULL);
1347
1348 ret = gtk_tree_path_to_string (path);
1349 gtk_tree_path_free (path);
1350
1351 return ret;
1352 }
1353
1354 /**
1355 * gtk_tree_model_get_iter_first:
1356 * @tree_model: a #GtkTreeModel
1357 * @iter: (out): the uninitialized #GtkTreeIter-struct
1358 *
1359 * Initializes @iter with the first iterator in the tree
1360 * (the one at the path "0") and returns %TRUE. Returns
1361 * %FALSE if the tree is empty.
1362 *
1363 * Returns: %TRUE, if @iter was set
1364 */
1365 gboolean
gtk_tree_model_get_iter_first(GtkTreeModel * tree_model,GtkTreeIter * iter)1366 gtk_tree_model_get_iter_first (GtkTreeModel *tree_model,
1367 GtkTreeIter *iter)
1368 {
1369 GtkTreePath *path;
1370 gboolean retval;
1371
1372 g_return_val_if_fail (GTK_IS_TREE_MODEL (tree_model), FALSE);
1373 g_return_val_if_fail (iter != NULL, FALSE);
1374
1375 path = gtk_tree_path_new_first ();
1376 retval = gtk_tree_model_get_iter (tree_model, iter, path);
1377 gtk_tree_path_free (path);
1378
1379 return retval;
1380 }
1381
1382 /**
1383 * gtk_tree_model_get_path:
1384 * @tree_model: a #GtkTreeModel
1385 * @iter: the #GtkTreeIter-struct
1386 *
1387 * Returns a newly-created #GtkTreePath-struct referenced by @iter.
1388 *
1389 * This path should be freed with gtk_tree_path_free().
1390 *
1391 * Returns: a newly-created #GtkTreePath-struct
1392 */
1393 GtkTreePath *
gtk_tree_model_get_path(GtkTreeModel * tree_model,GtkTreeIter * iter)1394 gtk_tree_model_get_path (GtkTreeModel *tree_model,
1395 GtkTreeIter *iter)
1396 {
1397 GtkTreeModelIface *iface;
1398
1399 g_return_val_if_fail (GTK_IS_TREE_MODEL (tree_model), NULL);
1400 g_return_val_if_fail (iter != NULL, NULL);
1401
1402 iface = GTK_TREE_MODEL_GET_IFACE (tree_model);
1403 g_return_val_if_fail (iface->get_path != NULL, NULL);
1404
1405 return (* iface->get_path) (tree_model, iter);
1406 }
1407
1408 /**
1409 * gtk_tree_model_get_value:
1410 * @tree_model: a #GtkTreeModel
1411 * @iter: the #GtkTreeIter-struct
1412 * @column: the column to lookup the value at
1413 * @value: (out) (transfer none): an empty #GValue to set
1414 *
1415 * Initializes and sets @value to that at @column.
1416 *
1417 * When done with @value, g_value_unset() needs to be called
1418 * to free any allocated memory.
1419 */
1420 void
gtk_tree_model_get_value(GtkTreeModel * tree_model,GtkTreeIter * iter,gint column,GValue * value)1421 gtk_tree_model_get_value (GtkTreeModel *tree_model,
1422 GtkTreeIter *iter,
1423 gint column,
1424 GValue *value)
1425 {
1426 GtkTreeModelIface *iface;
1427
1428 g_return_if_fail (GTK_IS_TREE_MODEL (tree_model));
1429 g_return_if_fail (iter != NULL);
1430 g_return_if_fail (value != NULL);
1431
1432 iface = GTK_TREE_MODEL_GET_IFACE (tree_model);
1433 g_return_if_fail (iface->get_value != NULL);
1434
1435 (* iface->get_value) (tree_model, iter, column, value);
1436 }
1437
1438 /**
1439 * gtk_tree_model_iter_next:
1440 * @tree_model: a #GtkTreeModel
1441 * @iter: (in): the #GtkTreeIter-struct
1442 *
1443 * Sets @iter to point to the node following it at the current level.
1444 *
1445 * If there is no next @iter, %FALSE is returned and @iter is set
1446 * to be invalid.
1447 *
1448 * Returns: %TRUE if @iter has been changed to the next node
1449 */
1450 gboolean
gtk_tree_model_iter_next(GtkTreeModel * tree_model,GtkTreeIter * iter)1451 gtk_tree_model_iter_next (GtkTreeModel *tree_model,
1452 GtkTreeIter *iter)
1453 {
1454 GtkTreeModelIface *iface;
1455
1456 g_return_val_if_fail (GTK_IS_TREE_MODEL (tree_model), FALSE);
1457 g_return_val_if_fail (iter != NULL, FALSE);
1458
1459 iface = GTK_TREE_MODEL_GET_IFACE (tree_model);
1460 g_return_val_if_fail (iface->iter_next != NULL, FALSE);
1461
1462 return (* iface->iter_next) (tree_model, iter);
1463 }
1464
1465 static gboolean
gtk_tree_model_iter_previous_default(GtkTreeModel * tree_model,GtkTreeIter * iter)1466 gtk_tree_model_iter_previous_default (GtkTreeModel *tree_model,
1467 GtkTreeIter *iter)
1468 {
1469 gboolean retval;
1470 GtkTreePath *path;
1471
1472 path = gtk_tree_model_get_path (tree_model, iter);
1473 if (path == NULL)
1474 return FALSE;
1475
1476 retval = gtk_tree_path_prev (path) &&
1477 gtk_tree_model_get_iter (tree_model, iter, path);
1478 if (retval == FALSE)
1479 iter->stamp = 0;
1480
1481 gtk_tree_path_free (path);
1482
1483 return retval;
1484 }
1485
1486 /**
1487 * gtk_tree_model_iter_previous:
1488 * @tree_model: a #GtkTreeModel
1489 * @iter: (in): the #GtkTreeIter-struct
1490 *
1491 * Sets @iter to point to the previous node at the current level.
1492 *
1493 * If there is no previous @iter, %FALSE is returned and @iter is
1494 * set to be invalid.
1495 *
1496 * Returns: %TRUE if @iter has been changed to the previous node
1497 *
1498 * Since: 3.0
1499 */
1500 gboolean
gtk_tree_model_iter_previous(GtkTreeModel * tree_model,GtkTreeIter * iter)1501 gtk_tree_model_iter_previous (GtkTreeModel *tree_model,
1502 GtkTreeIter *iter)
1503 {
1504 gboolean retval;
1505 GtkTreeModelIface *iface;
1506
1507 g_return_val_if_fail (GTK_IS_TREE_MODEL (tree_model), FALSE);
1508 g_return_val_if_fail (iter != NULL, FALSE);
1509
1510 iface = GTK_TREE_MODEL_GET_IFACE (tree_model);
1511
1512 if (iface->iter_previous)
1513 retval = (* iface->iter_previous) (tree_model, iter);
1514 else
1515 retval = gtk_tree_model_iter_previous_default (tree_model, iter);
1516
1517 return retval;
1518 }
1519
1520 /**
1521 * gtk_tree_model_iter_children:
1522 * @tree_model: a #GtkTreeModel
1523 * @iter: (out): the new #GtkTreeIter-struct to be set to the child
1524 * @parent: (allow-none): the #GtkTreeIter-struct, or %NULL
1525 *
1526 * Sets @iter to point to the first child of @parent.
1527 *
1528 * If @parent has no children, %FALSE is returned and @iter is
1529 * set to be invalid. @parent will remain a valid node after this
1530 * function has been called.
1531 *
1532 * If @parent is %NULL returns the first node, equivalent to
1533 * `gtk_tree_model_get_iter_first (tree_model, iter);`
1534 *
1535 * Returns: %TRUE, if @iter has been set to the first child
1536 */
1537 gboolean
gtk_tree_model_iter_children(GtkTreeModel * tree_model,GtkTreeIter * iter,GtkTreeIter * parent)1538 gtk_tree_model_iter_children (GtkTreeModel *tree_model,
1539 GtkTreeIter *iter,
1540 GtkTreeIter *parent)
1541 {
1542 GtkTreeModelIface *iface;
1543
1544 g_return_val_if_fail (GTK_IS_TREE_MODEL (tree_model), FALSE);
1545 g_return_val_if_fail (iter != NULL, FALSE);
1546
1547 iface = GTK_TREE_MODEL_GET_IFACE (tree_model);
1548 g_return_val_if_fail (iface->iter_children != NULL, FALSE);
1549
1550 INITIALIZE_TREE_ITER (iter);
1551
1552 return (* iface->iter_children) (tree_model, iter, parent);
1553 }
1554
1555 /**
1556 * gtk_tree_model_iter_has_child:
1557 * @tree_model: a #GtkTreeModel
1558 * @iter: the #GtkTreeIter-struct to test for children
1559 *
1560 * Returns %TRUE if @iter has children, %FALSE otherwise.
1561 *
1562 * Returns: %TRUE if @iter has children
1563 */
1564 gboolean
gtk_tree_model_iter_has_child(GtkTreeModel * tree_model,GtkTreeIter * iter)1565 gtk_tree_model_iter_has_child (GtkTreeModel *tree_model,
1566 GtkTreeIter *iter)
1567 {
1568 GtkTreeModelIface *iface;
1569
1570 g_return_val_if_fail (GTK_IS_TREE_MODEL (tree_model), FALSE);
1571 g_return_val_if_fail (iter != NULL, FALSE);
1572
1573 iface = GTK_TREE_MODEL_GET_IFACE (tree_model);
1574 g_return_val_if_fail (iface->iter_has_child != NULL, FALSE);
1575
1576 return (* iface->iter_has_child) (tree_model, iter);
1577 }
1578
1579 /**
1580 * gtk_tree_model_iter_n_children:
1581 * @tree_model: a #GtkTreeModel
1582 * @iter: (allow-none): the #GtkTreeIter-struct, or %NULL
1583 *
1584 * Returns the number of children that @iter has.
1585 *
1586 * As a special case, if @iter is %NULL, then the number
1587 * of toplevel nodes is returned.
1588 *
1589 * Returns: the number of children of @iter
1590 */
1591 gint
gtk_tree_model_iter_n_children(GtkTreeModel * tree_model,GtkTreeIter * iter)1592 gtk_tree_model_iter_n_children (GtkTreeModel *tree_model,
1593 GtkTreeIter *iter)
1594 {
1595 GtkTreeModelIface *iface;
1596
1597 g_return_val_if_fail (GTK_IS_TREE_MODEL (tree_model), 0);
1598
1599 iface = GTK_TREE_MODEL_GET_IFACE (tree_model);
1600 g_return_val_if_fail (iface->iter_n_children != NULL, 0);
1601
1602 return (* iface->iter_n_children) (tree_model, iter);
1603 }
1604
1605 /**
1606 * gtk_tree_model_iter_nth_child:
1607 * @tree_model: a #GtkTreeModel
1608 * @iter: (out): the #GtkTreeIter-struct to set to the nth child
1609 * @parent: (allow-none): the #GtkTreeIter-struct to get the child from, or %NULL.
1610 * @n: the index of the desired child
1611 *
1612 * Sets @iter to be the child of @parent, using the given index.
1613 *
1614 * The first index is 0. If @n is too big, or @parent has no children,
1615 * @iter is set to an invalid iterator and %FALSE is returned. @parent
1616 * will remain a valid node after this function has been called. As a
1617 * special case, if @parent is %NULL, then the @n-th root node
1618 * is set.
1619 *
1620 * Returns: %TRUE, if @parent has an @n-th child
1621 */
1622 gboolean
gtk_tree_model_iter_nth_child(GtkTreeModel * tree_model,GtkTreeIter * iter,GtkTreeIter * parent,gint n)1623 gtk_tree_model_iter_nth_child (GtkTreeModel *tree_model,
1624 GtkTreeIter *iter,
1625 GtkTreeIter *parent,
1626 gint n)
1627 {
1628 GtkTreeModelIface *iface;
1629
1630 g_return_val_if_fail (GTK_IS_TREE_MODEL (tree_model), FALSE);
1631 g_return_val_if_fail (iter != NULL, FALSE);
1632 g_return_val_if_fail (n >= 0, FALSE);
1633
1634 iface = GTK_TREE_MODEL_GET_IFACE (tree_model);
1635 g_return_val_if_fail (iface->iter_nth_child != NULL, FALSE);
1636
1637 INITIALIZE_TREE_ITER (iter);
1638
1639 return (* iface->iter_nth_child) (tree_model, iter, parent, n);
1640 }
1641
1642 /**
1643 * gtk_tree_model_iter_parent:
1644 * @tree_model: a #GtkTreeModel
1645 * @iter: (out): the new #GtkTreeIter-struct to set to the parent
1646 * @child: the #GtkTreeIter-struct
1647 *
1648 * Sets @iter to be the parent of @child.
1649 *
1650 * If @child is at the toplevel, and doesn’t have a parent, then
1651 * @iter is set to an invalid iterator and %FALSE is returned.
1652 * @child will remain a valid node after this function has been
1653 * called.
1654 *
1655 * @iter will be initialized before the lookup is performed, so @child
1656 * and @iter cannot point to the same memory location.
1657 *
1658 * Returns: %TRUE, if @iter is set to the parent of @child
1659 */
1660 gboolean
gtk_tree_model_iter_parent(GtkTreeModel * tree_model,GtkTreeIter * iter,GtkTreeIter * child)1661 gtk_tree_model_iter_parent (GtkTreeModel *tree_model,
1662 GtkTreeIter *iter,
1663 GtkTreeIter *child)
1664 {
1665 GtkTreeModelIface *iface;
1666
1667 g_return_val_if_fail (GTK_IS_TREE_MODEL (tree_model), FALSE);
1668 g_return_val_if_fail (iter != NULL, FALSE);
1669 g_return_val_if_fail (child != NULL, FALSE);
1670
1671 iface = GTK_TREE_MODEL_GET_IFACE (tree_model);
1672 g_return_val_if_fail (iface->iter_parent != NULL, FALSE);
1673
1674 INITIALIZE_TREE_ITER (iter);
1675
1676 return (* iface->iter_parent) (tree_model, iter, child);
1677 }
1678
1679 /**
1680 * gtk_tree_model_ref_node:
1681 * @tree_model: a #GtkTreeModel
1682 * @iter: the #GtkTreeIter-struct
1683 *
1684 * Lets the tree ref the node.
1685 *
1686 * This is an optional method for models to implement.
1687 * To be more specific, models may ignore this call as it exists
1688 * primarily for performance reasons.
1689 *
1690 * This function is primarily meant as a way for views to let
1691 * caching models know when nodes are being displayed (and hence,
1692 * whether or not to cache that node). Being displayed means a node
1693 * is in an expanded branch, regardless of whether the node is currently
1694 * visible in the viewport. For example, a file-system based model
1695 * would not want to keep the entire file-hierarchy in memory,
1696 * just the sections that are currently being displayed by
1697 * every current view.
1698 *
1699 * A model should be expected to be able to get an iter independent
1700 * of its reffed state.
1701 */
1702 void
gtk_tree_model_ref_node(GtkTreeModel * tree_model,GtkTreeIter * iter)1703 gtk_tree_model_ref_node (GtkTreeModel *tree_model,
1704 GtkTreeIter *iter)
1705 {
1706 GtkTreeModelIface *iface;
1707
1708 g_return_if_fail (GTK_IS_TREE_MODEL (tree_model));
1709
1710 iface = GTK_TREE_MODEL_GET_IFACE (tree_model);
1711 if (iface->ref_node)
1712 (* iface->ref_node) (tree_model, iter);
1713 }
1714
1715 /**
1716 * gtk_tree_model_unref_node:
1717 * @tree_model: a #GtkTreeModel
1718 * @iter: the #GtkTreeIter-struct
1719 *
1720 * Lets the tree unref the node.
1721 *
1722 * This is an optional method for models to implement.
1723 * To be more specific, models may ignore this call as it exists
1724 * primarily for performance reasons. For more information on what
1725 * this means, see gtk_tree_model_ref_node().
1726 *
1727 * Please note that nodes that are deleted are not unreffed.
1728 */
1729 void
gtk_tree_model_unref_node(GtkTreeModel * tree_model,GtkTreeIter * iter)1730 gtk_tree_model_unref_node (GtkTreeModel *tree_model,
1731 GtkTreeIter *iter)
1732 {
1733 GtkTreeModelIface *iface;
1734
1735 g_return_if_fail (GTK_IS_TREE_MODEL (tree_model));
1736 g_return_if_fail (iter != NULL);
1737
1738 iface = GTK_TREE_MODEL_GET_IFACE (tree_model);
1739 if (iface->unref_node)
1740 (* iface->unref_node) (tree_model, iter);
1741 }
1742
1743 /**
1744 * gtk_tree_model_get:
1745 * @tree_model: a #GtkTreeModel
1746 * @iter: a row in @tree_model
1747 * @...: pairs of column number and value return locations,
1748 * terminated by -1
1749 *
1750 * Gets the value of one or more cells in the row referenced by @iter.
1751 * The variable argument list should contain integer column numbers,
1752 * each column number followed by a place to store the value being
1753 * retrieved. The list is terminated by a -1. For example, to get a
1754 * value from column 0 with type %G_TYPE_STRING, you would
1755 * write: `gtk_tree_model_get (model, iter, 0, &place_string_here, -1)`,
1756 * where `place_string_here` is a #gchararray
1757 * to be filled with the string.
1758 *
1759 * Returned values with type %G_TYPE_OBJECT have to be unreferenced,
1760 * values with type %G_TYPE_STRING or %G_TYPE_BOXED have to be freed.
1761 * Other values are passed by value.
1762 */
1763 void
gtk_tree_model_get(GtkTreeModel * tree_model,GtkTreeIter * iter,...)1764 gtk_tree_model_get (GtkTreeModel *tree_model,
1765 GtkTreeIter *iter,
1766 ...)
1767 {
1768 va_list var_args;
1769
1770 g_return_if_fail (GTK_IS_TREE_MODEL (tree_model));
1771 g_return_if_fail (iter != NULL);
1772
1773 va_start (var_args, iter);
1774 gtk_tree_model_get_valist (tree_model, iter, var_args);
1775 va_end (var_args);
1776 }
1777
1778 /**
1779 * gtk_tree_model_get_valist:
1780 * @tree_model: a #GtkTreeModel
1781 * @iter: a row in @tree_model
1782 * @var_args: va_list of column/return location pairs
1783 *
1784 * See gtk_tree_model_get(), this version takes a va_list
1785 * for language bindings to use.
1786 */
1787 void
gtk_tree_model_get_valist(GtkTreeModel * tree_model,GtkTreeIter * iter,va_list var_args)1788 gtk_tree_model_get_valist (GtkTreeModel *tree_model,
1789 GtkTreeIter *iter,
1790 va_list var_args)
1791 {
1792 gint column;
1793
1794 g_return_if_fail (GTK_IS_TREE_MODEL (tree_model));
1795 g_return_if_fail (iter != NULL);
1796
1797 column = va_arg (var_args, gint);
1798
1799 while (column != -1)
1800 {
1801 GValue value = G_VALUE_INIT;
1802 gchar *error = NULL;
1803
1804 if (column >= gtk_tree_model_get_n_columns (tree_model))
1805 {
1806 g_warning ("%s: Invalid column number %d accessed (remember to end your list of columns with a -1)", G_STRLOC, column);
1807 break;
1808 }
1809
1810 gtk_tree_model_get_value (GTK_TREE_MODEL (tree_model), iter, column, &value);
1811
1812 G_VALUE_LCOPY (&value, var_args, 0, &error);
1813 if (error)
1814 {
1815 g_warning ("%s: %s", G_STRLOC, error);
1816 g_free (error);
1817
1818 /* we purposely leak the value here, it might not be
1819 * in a sane state if an error condition occurred
1820 */
1821 break;
1822 }
1823
1824 g_value_unset (&value);
1825
1826 column = va_arg (var_args, gint);
1827 }
1828 }
1829
1830 /**
1831 * gtk_tree_model_row_changed:
1832 * @tree_model: a #GtkTreeModel
1833 * @path: a #GtkTreePath-struct pointing to the changed row
1834 * @iter: a valid #GtkTreeIter-struct pointing to the changed row
1835 *
1836 * Emits the #GtkTreeModel::row-changed signal on @tree_model.
1837 */
1838 void
gtk_tree_model_row_changed(GtkTreeModel * tree_model,GtkTreePath * path,GtkTreeIter * iter)1839 gtk_tree_model_row_changed (GtkTreeModel *tree_model,
1840 GtkTreePath *path,
1841 GtkTreeIter *iter)
1842 {
1843 g_return_if_fail (GTK_IS_TREE_MODEL (tree_model));
1844 g_return_if_fail (path != NULL);
1845 g_return_if_fail (iter != NULL);
1846
1847 g_signal_emit (tree_model, tree_model_signals[ROW_CHANGED], 0, path, iter);
1848 }
1849
1850 /**
1851 * gtk_tree_model_row_inserted:
1852 * @tree_model: a #GtkTreeModel
1853 * @path: a #GtkTreePath-struct pointing to the inserted row
1854 * @iter: a valid #GtkTreeIter-struct pointing to the inserted row
1855 *
1856 * Emits the #GtkTreeModel::row-inserted signal on @tree_model.
1857 */
1858 void
gtk_tree_model_row_inserted(GtkTreeModel * tree_model,GtkTreePath * path,GtkTreeIter * iter)1859 gtk_tree_model_row_inserted (GtkTreeModel *tree_model,
1860 GtkTreePath *path,
1861 GtkTreeIter *iter)
1862 {
1863 g_return_if_fail (GTK_IS_TREE_MODEL (tree_model));
1864 g_return_if_fail (path != NULL);
1865 g_return_if_fail (iter != NULL);
1866
1867 g_signal_emit (tree_model, tree_model_signals[ROW_INSERTED], 0, path, iter);
1868 }
1869
1870 /**
1871 * gtk_tree_model_row_has_child_toggled:
1872 * @tree_model: a #GtkTreeModel
1873 * @path: a #GtkTreePath-struct pointing to the changed row
1874 * @iter: a valid #GtkTreeIter-struct pointing to the changed row
1875 *
1876 * Emits the #GtkTreeModel::row-has-child-toggled signal on
1877 * @tree_model. This should be called by models after the child
1878 * state of a node changes.
1879 */
1880 void
gtk_tree_model_row_has_child_toggled(GtkTreeModel * tree_model,GtkTreePath * path,GtkTreeIter * iter)1881 gtk_tree_model_row_has_child_toggled (GtkTreeModel *tree_model,
1882 GtkTreePath *path,
1883 GtkTreeIter *iter)
1884 {
1885 g_return_if_fail (GTK_IS_TREE_MODEL (tree_model));
1886 g_return_if_fail (path != NULL);
1887 g_return_if_fail (iter != NULL);
1888
1889 g_signal_emit (tree_model, tree_model_signals[ROW_HAS_CHILD_TOGGLED], 0, path, iter);
1890 }
1891
1892 /**
1893 * gtk_tree_model_row_deleted:
1894 * @tree_model: a #GtkTreeModel
1895 * @path: a #GtkTreePath-struct pointing to the previous location of
1896 * the deleted row
1897 *
1898 * Emits the #GtkTreeModel::row-deleted signal on @tree_model.
1899 *
1900 * This should be called by models after a row has been removed.
1901 * The location pointed to by @path should be the location that
1902 * the row previously was at. It may not be a valid location anymore.
1903 *
1904 * Nodes that are deleted are not unreffed, this means that any
1905 * outstanding references on the deleted node should not be released.
1906 */
1907 void
gtk_tree_model_row_deleted(GtkTreeModel * tree_model,GtkTreePath * path)1908 gtk_tree_model_row_deleted (GtkTreeModel *tree_model,
1909 GtkTreePath *path)
1910 {
1911 g_return_if_fail (GTK_IS_TREE_MODEL (tree_model));
1912 g_return_if_fail (path != NULL);
1913
1914 g_signal_emit (tree_model, tree_model_signals[ROW_DELETED], 0, path);
1915 }
1916
1917 /**
1918 * gtk_tree_model_rows_reordered: (skip)
1919 * @tree_model: a #GtkTreeModel
1920 * @path: a #GtkTreePath-struct pointing to the tree node whose children
1921 * have been reordered
1922 * @iter: a valid #GtkTreeIter-struct pointing to the node whose children
1923 * have been reordered, or %NULL if the depth of @path is 0
1924 * @new_order: an array of integers mapping the current position of
1925 * each child to its old position before the re-ordering,
1926 * i.e. @new_order`[newpos] = oldpos`
1927 *
1928 * Emits the #GtkTreeModel::rows-reordered signal on @tree_model.
1929 *
1930 * This should be called by models when their rows have been
1931 * reordered.
1932 */
1933 void
gtk_tree_model_rows_reordered(GtkTreeModel * tree_model,GtkTreePath * path,GtkTreeIter * iter,gint * new_order)1934 gtk_tree_model_rows_reordered (GtkTreeModel *tree_model,
1935 GtkTreePath *path,
1936 GtkTreeIter *iter,
1937 gint *new_order)
1938 {
1939 g_return_if_fail (GTK_IS_TREE_MODEL (tree_model));
1940 g_return_if_fail (new_order != NULL);
1941
1942 g_signal_emit (tree_model, tree_model_signals[ROWS_REORDERED], 0, path, iter, new_order);
1943 }
1944
1945 /**
1946 * gtk_tree_model_rows_reordered_with_length: (rename-to gtk_tree_model_rows_reordered)
1947 * @tree_model: a #GtkTreeModel
1948 * @path: a #GtkTreePath-struct pointing to the tree node whose children
1949 * have been reordered
1950 * @iter: (allow-none): a valid #GtkTreeIter-struct pointing to the node
1951 * whose children have been reordered, or %NULL if the depth
1952 * of @path is 0
1953 * @new_order: (array length=length): an array of integers
1954 * mapping the current position of each child to its old
1955 * position before the re-ordering,
1956 * i.e. @new_order`[newpos] = oldpos`
1957 * @length: length of @new_order array
1958 *
1959 * Emits the #GtkTreeModel::rows-reordered signal on @tree_model.
1960 *
1961 * This should be called by models when their rows have been
1962 * reordered.
1963 *
1964 * Since: 3.10
1965 */
1966 void
gtk_tree_model_rows_reordered_with_length(GtkTreeModel * tree_model,GtkTreePath * path,GtkTreeIter * iter,gint * new_order,gint length)1967 gtk_tree_model_rows_reordered_with_length (GtkTreeModel *tree_model,
1968 GtkTreePath *path,
1969 GtkTreeIter *iter,
1970 gint *new_order,
1971 gint length)
1972 {
1973 g_return_if_fail (GTK_IS_TREE_MODEL (tree_model));
1974 g_return_if_fail (new_order != NULL);
1975 g_return_if_fail (length == gtk_tree_model_iter_n_children (tree_model, iter));
1976
1977 g_signal_emit (tree_model, tree_model_signals[ROWS_REORDERED], 0, path, iter, new_order);
1978 }
1979
1980 static gboolean
gtk_tree_model_foreach_helper(GtkTreeModel * model,GtkTreeIter * iter,GtkTreePath * path,GtkTreeModelForeachFunc func,gpointer user_data)1981 gtk_tree_model_foreach_helper (GtkTreeModel *model,
1982 GtkTreeIter *iter,
1983 GtkTreePath *path,
1984 GtkTreeModelForeachFunc func,
1985 gpointer user_data)
1986 {
1987 gboolean iters_persist;
1988
1989 iters_persist = gtk_tree_model_get_flags (model) & GTK_TREE_MODEL_ITERS_PERSIST;
1990
1991 do
1992 {
1993 GtkTreeIter child;
1994
1995 if ((* func) (model, path, iter, user_data))
1996 return TRUE;
1997
1998 if (!iters_persist)
1999 {
2000 if (!gtk_tree_model_get_iter (model, iter, path))
2001 return TRUE;
2002 }
2003
2004 if (gtk_tree_model_iter_children (model, &child, iter))
2005 {
2006 gtk_tree_path_down (path);
2007 if (gtk_tree_model_foreach_helper (model, &child, path, func, user_data))
2008 return TRUE;
2009 gtk_tree_path_up (path);
2010 }
2011
2012 gtk_tree_path_next (path);
2013 }
2014 while (gtk_tree_model_iter_next (model, iter));
2015
2016 return FALSE;
2017 }
2018
2019 /**
2020 * gtk_tree_model_foreach:
2021 * @model: a #GtkTreeModel
2022 * @func: (scope call): a function to be called on each row
2023 * @user_data: user data to passed to @func
2024 *
2025 * Calls func on each node in model in a depth-first fashion.
2026 *
2027 * If @func returns %TRUE, then the tree ceases to be walked,
2028 * and gtk_tree_model_foreach() returns.
2029 */
2030 void
gtk_tree_model_foreach(GtkTreeModel * model,GtkTreeModelForeachFunc func,gpointer user_data)2031 gtk_tree_model_foreach (GtkTreeModel *model,
2032 GtkTreeModelForeachFunc func,
2033 gpointer user_data)
2034 {
2035 GtkTreePath *path;
2036 GtkTreeIter iter;
2037
2038 g_return_if_fail (GTK_IS_TREE_MODEL (model));
2039 g_return_if_fail (func != NULL);
2040
2041 path = gtk_tree_path_new_first ();
2042 if (!gtk_tree_model_get_iter (model, &iter, path))
2043 {
2044 gtk_tree_path_free (path);
2045 return;
2046 }
2047
2048 gtk_tree_model_foreach_helper (model, &iter, path, func, user_data);
2049 gtk_tree_path_free (path);
2050 }
2051
2052
2053 /*
2054 * GtkTreeRowReference
2055 */
2056
2057 static void gtk_tree_row_reference_unref_path (GtkTreePath *path,
2058 GtkTreeModel *model,
2059 gint depth);
2060
2061
2062 G_DEFINE_BOXED_TYPE (GtkTreeRowReference, gtk_tree_row_reference,
2063 gtk_tree_row_reference_copy,
2064 gtk_tree_row_reference_free)
2065
2066 struct _GtkTreeRowReference
2067 {
2068 GObject *proxy;
2069 GtkTreeModel *model;
2070 GtkTreePath *path;
2071 };
2072
2073
2074 static void
release_row_references(gpointer data)2075 release_row_references (gpointer data)
2076 {
2077 RowRefList *refs = data;
2078 GSList *tmp_list = NULL;
2079
2080 tmp_list = refs->list;
2081 while (tmp_list != NULL)
2082 {
2083 GtkTreeRowReference *reference = tmp_list->data;
2084
2085 if (reference->proxy == (GObject *)reference->model)
2086 reference->model = NULL;
2087 reference->proxy = NULL;
2088
2089 /* we don't free the reference, users are responsible for that. */
2090
2091 tmp_list = tmp_list->next;
2092 }
2093
2094 g_slist_free (refs->list);
2095 g_free (refs);
2096 }
2097
2098 static void
gtk_tree_row_ref_inserted(RowRefList * refs,GtkTreePath * path,GtkTreeIter * iter)2099 gtk_tree_row_ref_inserted (RowRefList *refs,
2100 GtkTreePath *path,
2101 GtkTreeIter *iter)
2102 {
2103 GSList *tmp_list;
2104
2105 if (refs == NULL)
2106 return;
2107
2108 /* This function corrects the path stored in the reference to
2109 * account for an insertion. Note that it's called _after_ the
2110 * insertion with the path to the newly-inserted row. Which means
2111 * that the inserted path is in a different "coordinate system" than
2112 * the old path (e.g. if the inserted path was just before the old
2113 * path, then inserted path and old path will be the same, and old
2114 * path must be moved down one).
2115 */
2116
2117 tmp_list = refs->list;
2118
2119 while (tmp_list != NULL)
2120 {
2121 GtkTreeRowReference *reference = tmp_list->data;
2122
2123 if (reference->path == NULL)
2124 goto done;
2125
2126 if (reference->path->depth >= path->depth)
2127 {
2128 gint i;
2129 gboolean ancestor = TRUE;
2130
2131 for (i = 0; i < path->depth - 1; i ++)
2132 {
2133 if (path->indices[i] != reference->path->indices[i])
2134 {
2135 ancestor = FALSE;
2136 break;
2137 }
2138 }
2139 if (ancestor == FALSE)
2140 goto done;
2141
2142 if (path->indices[path->depth-1] <= reference->path->indices[path->depth-1])
2143 reference->path->indices[path->depth-1] += 1;
2144 }
2145 done:
2146 tmp_list = tmp_list->next;
2147 }
2148 }
2149
2150 static void
gtk_tree_row_ref_deleted(RowRefList * refs,GtkTreePath * path)2151 gtk_tree_row_ref_deleted (RowRefList *refs,
2152 GtkTreePath *path)
2153 {
2154 GSList *tmp_list;
2155
2156 if (refs == NULL)
2157 return;
2158
2159 /* This function corrects the path stored in the reference to
2160 * account for an deletion. Note that it's called _after_ the
2161 * deletion with the old path of the just-deleted row. Which means
2162 * that the deleted path is the same now-defunct "coordinate system"
2163 * as the path saved in the reference, which is what we want to fix.
2164 */
2165
2166 tmp_list = refs->list;
2167
2168 while (tmp_list != NULL)
2169 {
2170 GtkTreeRowReference *reference = tmp_list->data;
2171
2172 if (reference->path)
2173 {
2174 gint i;
2175
2176 if (path->depth > reference->path->depth)
2177 goto next;
2178 for (i = 0; i < path->depth - 1; i++)
2179 {
2180 if (path->indices[i] != reference->path->indices[i])
2181 goto next;
2182 }
2183
2184 /* We know it affects us. */
2185 if (path->indices[i] == reference->path->indices[i])
2186 {
2187 if (reference->path->depth > path->depth)
2188 /* some parent was deleted, trying to unref any node
2189 * between the deleted parent and the node the reference
2190 * is pointing to is bad, as those nodes are already gone.
2191 */
2192 gtk_tree_row_reference_unref_path (reference->path, reference->model, path->depth - 1);
2193 else
2194 gtk_tree_row_reference_unref_path (reference->path, reference->model, reference->path->depth - 1);
2195 gtk_tree_path_free (reference->path);
2196 reference->path = NULL;
2197 }
2198 else if (path->indices[i] < reference->path->indices[i])
2199 {
2200 reference->path->indices[path->depth-1]-=1;
2201 }
2202 }
2203
2204 next:
2205 tmp_list = tmp_list->next;
2206 }
2207 }
2208
2209 static void
gtk_tree_row_ref_reordered(RowRefList * refs,GtkTreePath * path,GtkTreeIter * iter,gint * new_order)2210 gtk_tree_row_ref_reordered (RowRefList *refs,
2211 GtkTreePath *path,
2212 GtkTreeIter *iter,
2213 gint *new_order)
2214 {
2215 GSList *tmp_list;
2216 gint length;
2217
2218 if (refs == NULL)
2219 return;
2220
2221 tmp_list = refs->list;
2222
2223 while (tmp_list != NULL)
2224 {
2225 GtkTreeRowReference *reference = tmp_list->data;
2226
2227 length = gtk_tree_model_iter_n_children (GTK_TREE_MODEL (reference->model), iter);
2228
2229 if (length < 2)
2230 return;
2231
2232 if ((reference->path) &&
2233 (gtk_tree_path_is_ancestor (path, reference->path)))
2234 {
2235 gint ref_depth = gtk_tree_path_get_depth (reference->path);
2236 gint depth = gtk_tree_path_get_depth (path);
2237
2238 if (ref_depth > depth)
2239 {
2240 gint i;
2241 gint *indices = gtk_tree_path_get_indices (reference->path);
2242
2243 for (i = 0; i < length; i++)
2244 {
2245 if (new_order[i] == indices[depth])
2246 {
2247 indices[depth] = i;
2248 break;
2249 }
2250 }
2251 }
2252 }
2253
2254 tmp_list = tmp_list->next;
2255 }
2256 }
2257
2258 /* We do this recursively so that we can unref children nodes
2259 * before their parent
2260 */
2261 static void
gtk_tree_row_reference_unref_path_helper(GtkTreePath * path,GtkTreeModel * model,GtkTreeIter * parent_iter,gint depth,gint current_depth)2262 gtk_tree_row_reference_unref_path_helper (GtkTreePath *path,
2263 GtkTreeModel *model,
2264 GtkTreeIter *parent_iter,
2265 gint depth,
2266 gint current_depth)
2267 {
2268 GtkTreeIter iter;
2269
2270 if (depth == current_depth)
2271 return;
2272
2273 gtk_tree_model_iter_nth_child (model, &iter, parent_iter, path->indices[current_depth]);
2274 gtk_tree_row_reference_unref_path_helper (path, model, &iter, depth, current_depth + 1);
2275 gtk_tree_model_unref_node (model, &iter);
2276 }
2277
2278 static void
gtk_tree_row_reference_unref_path(GtkTreePath * path,GtkTreeModel * model,gint depth)2279 gtk_tree_row_reference_unref_path (GtkTreePath *path,
2280 GtkTreeModel *model,
2281 gint depth)
2282 {
2283 GtkTreeIter iter;
2284
2285 if (depth <= 0)
2286 return;
2287
2288 gtk_tree_model_iter_nth_child (model, &iter, NULL, path->indices[0]);
2289 gtk_tree_row_reference_unref_path_helper (path, model, &iter, depth, 1);
2290 gtk_tree_model_unref_node (model, &iter);
2291 }
2292
2293 /**
2294 * gtk_tree_row_reference_new:
2295 * @model: a #GtkTreeModel
2296 * @path: a valid #GtkTreePath-struct to monitor
2297 *
2298 * Creates a row reference based on @path.
2299 *
2300 * This reference will keep pointing to the node pointed to
2301 * by @path, so long as it exists. Any changes that occur on @model are
2302 * propagated, and the path is updated appropriately. If
2303 * @path isn’t a valid path in @model, then %NULL is returned.
2304 *
2305 * Returns: a newly allocated #GtkTreeRowReference, or %NULL
2306 */
2307 GtkTreeRowReference *
gtk_tree_row_reference_new(GtkTreeModel * model,GtkTreePath * path)2308 gtk_tree_row_reference_new (GtkTreeModel *model,
2309 GtkTreePath *path)
2310 {
2311 g_return_val_if_fail (GTK_IS_TREE_MODEL (model), NULL);
2312 g_return_val_if_fail (path != NULL, NULL);
2313
2314 /* We use the model itself as the proxy object; and call
2315 * gtk_tree_row_reference_inserted(), etc, in the
2316 * class closure (default handler) marshalers for the signal.
2317 */
2318 return gtk_tree_row_reference_new_proxy (G_OBJECT (model), model, path);
2319 }
2320
2321 /**
2322 * gtk_tree_row_reference_new_proxy:
2323 * @proxy: a proxy #GObject
2324 * @model: a #GtkTreeModel
2325 * @path: a valid #GtkTreePath-struct to monitor
2326 *
2327 * You do not need to use this function.
2328 *
2329 * Creates a row reference based on @path.
2330 *
2331 * This reference will keep pointing to the node pointed to
2332 * by @path, so long as it exists. If @path isn’t a valid
2333 * path in @model, then %NULL is returned. However, unlike
2334 * references created with gtk_tree_row_reference_new(), it
2335 * does not listen to the model for changes. The creator of
2336 * the row reference must do this explicitly using
2337 * gtk_tree_row_reference_inserted(), gtk_tree_row_reference_deleted(),
2338 * gtk_tree_row_reference_reordered().
2339 *
2340 * These functions must be called exactly once per proxy when the
2341 * corresponding signal on the model is emitted. This single call
2342 * updates all row references for that proxy. Since built-in GTK+
2343 * objects like #GtkTreeView already use this mechanism internally,
2344 * using them as the proxy object will produce unpredictable results.
2345 * Further more, passing the same object as @model and @proxy
2346 * doesn’t work for reasons of internal implementation.
2347 *
2348 * This type of row reference is primarily meant by structures that
2349 * need to carefully monitor exactly when a row reference updates
2350 * itself, and is not generally needed by most applications.
2351 *
2352 * Returns: a newly allocated #GtkTreeRowReference, or %NULL
2353 */
2354 GtkTreeRowReference *
gtk_tree_row_reference_new_proxy(GObject * proxy,GtkTreeModel * model,GtkTreePath * path)2355 gtk_tree_row_reference_new_proxy (GObject *proxy,
2356 GtkTreeModel *model,
2357 GtkTreePath *path)
2358 {
2359 GtkTreeRowReference *reference;
2360 RowRefList *refs;
2361 GtkTreeIter parent_iter;
2362 gint i;
2363
2364 g_return_val_if_fail (G_IS_OBJECT (proxy), NULL);
2365 g_return_val_if_fail (GTK_IS_TREE_MODEL (model), NULL);
2366 g_return_val_if_fail (path != NULL, NULL);
2367 g_return_val_if_fail (path->depth > 0, NULL);
2368
2369 /* check that the path is valid */
2370 if (gtk_tree_model_get_iter (model, &parent_iter, path) == FALSE)
2371 return NULL;
2372
2373 /* Now we want to ref every node */
2374 gtk_tree_model_iter_nth_child (model, &parent_iter, NULL, path->indices[0]);
2375 gtk_tree_model_ref_node (model, &parent_iter);
2376
2377 for (i = 1; i < path->depth; i++)
2378 {
2379 GtkTreeIter iter;
2380 gtk_tree_model_iter_nth_child (model, &iter, &parent_iter, path->indices[i]);
2381 gtk_tree_model_ref_node (model, &iter);
2382 parent_iter = iter;
2383 }
2384
2385 /* Make the row reference */
2386 reference = g_new (GtkTreeRowReference, 1);
2387
2388 g_object_ref (proxy);
2389 g_object_ref (model);
2390 reference->proxy = proxy;
2391 reference->model = model;
2392 reference->path = gtk_tree_path_copy (path);
2393
2394 refs = g_object_get_data (G_OBJECT (proxy), ROW_REF_DATA_STRING);
2395
2396 if (refs == NULL)
2397 {
2398 refs = g_new (RowRefList, 1);
2399 refs->list = NULL;
2400
2401 g_object_set_data_full (G_OBJECT (proxy),
2402 I_(ROW_REF_DATA_STRING),
2403 refs, release_row_references);
2404 }
2405
2406 refs->list = g_slist_prepend (refs->list, reference);
2407
2408 return reference;
2409 }
2410
2411 /**
2412 * gtk_tree_row_reference_get_path:
2413 * @reference: a #GtkTreeRowReference
2414 *
2415 * Returns a path that the row reference currently points to,
2416 * or %NULL if the path pointed to is no longer valid.
2417 *
2418 * Returns: (nullable) (transfer full): a current path, or %NULL
2419 */
2420 GtkTreePath *
gtk_tree_row_reference_get_path(GtkTreeRowReference * reference)2421 gtk_tree_row_reference_get_path (GtkTreeRowReference *reference)
2422 {
2423 g_return_val_if_fail (reference != NULL, NULL);
2424
2425 if (reference->proxy == NULL)
2426 return NULL;
2427
2428 if (reference->path == NULL)
2429 return NULL;
2430
2431 return gtk_tree_path_copy (reference->path);
2432 }
2433
2434 /**
2435 * gtk_tree_row_reference_get_model:
2436 * @reference: a #GtkTreeRowReference
2437 *
2438 * Returns the model that the row reference is monitoring.
2439 *
2440 * Returns: (transfer none): the model
2441 *
2442 * Since: 2.8
2443 */
2444 GtkTreeModel *
gtk_tree_row_reference_get_model(GtkTreeRowReference * reference)2445 gtk_tree_row_reference_get_model (GtkTreeRowReference *reference)
2446 {
2447 g_return_val_if_fail (reference != NULL, NULL);
2448
2449 return reference->model;
2450 }
2451
2452 /**
2453 * gtk_tree_row_reference_valid:
2454 * @reference: (allow-none): a #GtkTreeRowReference, or %NULL
2455 *
2456 * Returns %TRUE if the @reference is non-%NULL and refers to
2457 * a current valid path.
2458 *
2459 * Returns: %TRUE if @reference points to a valid path
2460 */
2461 gboolean
gtk_tree_row_reference_valid(GtkTreeRowReference * reference)2462 gtk_tree_row_reference_valid (GtkTreeRowReference *reference)
2463 {
2464 if (reference == NULL || reference->path == NULL)
2465 return FALSE;
2466
2467 return TRUE;
2468 }
2469
2470
2471 /**
2472 * gtk_tree_row_reference_copy:
2473 * @reference: a #GtkTreeRowReference
2474 *
2475 * Copies a #GtkTreeRowReference.
2476 *
2477 * Returns: a copy of @reference
2478 *
2479 * Since: 2.2
2480 */
2481 GtkTreeRowReference *
gtk_tree_row_reference_copy(GtkTreeRowReference * reference)2482 gtk_tree_row_reference_copy (GtkTreeRowReference *reference)
2483 {
2484 return gtk_tree_row_reference_new_proxy (reference->proxy,
2485 reference->model,
2486 reference->path);
2487 }
2488
2489 /**
2490 * gtk_tree_row_reference_free:
2491 * @reference: (allow-none): a #GtkTreeRowReference, or %NULL
2492 *
2493 * Free’s @reference. @reference may be %NULL
2494 */
2495 void
gtk_tree_row_reference_free(GtkTreeRowReference * reference)2496 gtk_tree_row_reference_free (GtkTreeRowReference *reference)
2497 {
2498 RowRefList *refs;
2499
2500 if (reference == NULL)
2501 return;
2502
2503 refs = g_object_get_data (G_OBJECT (reference->proxy), ROW_REF_DATA_STRING);
2504
2505 if (refs == NULL)
2506 {
2507 g_warning (G_STRLOC": bad row reference, proxy has no outstanding row references");
2508 return;
2509 }
2510
2511 refs->list = g_slist_remove (refs->list, reference);
2512
2513 if (refs->list == NULL)
2514 {
2515 g_object_set_data (G_OBJECT (reference->proxy),
2516 I_(ROW_REF_DATA_STRING),
2517 NULL);
2518 }
2519
2520 if (reference->path)
2521 {
2522 gtk_tree_row_reference_unref_path (reference->path, reference->model, reference->path->depth);
2523 gtk_tree_path_free (reference->path);
2524 }
2525
2526 g_object_unref (reference->proxy);
2527 g_object_unref (reference->model);
2528 g_free (reference);
2529 }
2530
2531 /**
2532 * gtk_tree_row_reference_inserted:
2533 * @proxy: a #GObject
2534 * @path: the row position that was inserted
2535 *
2536 * Lets a set of row reference created by
2537 * gtk_tree_row_reference_new_proxy() know that the
2538 * model emitted the #GtkTreeModel::row-inserted signal.
2539 */
2540 void
gtk_tree_row_reference_inserted(GObject * proxy,GtkTreePath * path)2541 gtk_tree_row_reference_inserted (GObject *proxy,
2542 GtkTreePath *path)
2543 {
2544 g_return_if_fail (G_IS_OBJECT (proxy));
2545
2546 gtk_tree_row_ref_inserted ((RowRefList *)g_object_get_data (proxy, ROW_REF_DATA_STRING), path, NULL);
2547 }
2548
2549 /**
2550 * gtk_tree_row_reference_deleted:
2551 * @proxy: a #GObject
2552 * @path: the path position that was deleted
2553 *
2554 * Lets a set of row reference created by
2555 * gtk_tree_row_reference_new_proxy() know that the
2556 * model emitted the #GtkTreeModel::row-deleted signal.
2557 */
2558 void
gtk_tree_row_reference_deleted(GObject * proxy,GtkTreePath * path)2559 gtk_tree_row_reference_deleted (GObject *proxy,
2560 GtkTreePath *path)
2561 {
2562 g_return_if_fail (G_IS_OBJECT (proxy));
2563
2564 gtk_tree_row_ref_deleted ((RowRefList *)g_object_get_data (proxy, ROW_REF_DATA_STRING), path);
2565 }
2566
2567 /**
2568 * gtk_tree_row_reference_reordered: (skip)
2569 * @proxy: a #GObject
2570 * @path: the parent path of the reordered signal
2571 * @iter: the iter pointing to the parent of the reordered
2572 * @new_order: (array): the new order of rows
2573 *
2574 * Lets a set of row reference created by
2575 * gtk_tree_row_reference_new_proxy() know that the
2576 * model emitted the #GtkTreeModel::rows-reordered signal.
2577 */
2578 void
gtk_tree_row_reference_reordered(GObject * proxy,GtkTreePath * path,GtkTreeIter * iter,gint * new_order)2579 gtk_tree_row_reference_reordered (GObject *proxy,
2580 GtkTreePath *path,
2581 GtkTreeIter *iter,
2582 gint *new_order)
2583 {
2584 g_return_if_fail (G_IS_OBJECT (proxy));
2585
2586 gtk_tree_row_ref_reordered ((RowRefList *)g_object_get_data (proxy, ROW_REF_DATA_STRING), path, iter, new_order);
2587 }
2588