Bug Summary

File:ctk/ctktreemodelfilter.c
Warning:line 2039, column 23
Access to field 'visible_siter' results in a dereference of an undefined pointer value (loaded from field 'user_data2')

Annotated Source Code

Press '?' to see keyboard shortcuts

clang -cc1 -cc1 -triple x86_64-pc-linux-gnu -analyze -disable-free -clear-ast-before-backend -disable-llvm-verifier -discard-value-names -main-file-name ctktreemodelfilter.c -analyzer-checker=core -analyzer-checker=apiModeling -analyzer-checker=unix -analyzer-checker=deadcode -analyzer-checker=security.insecureAPI.UncheckedReturn -analyzer-checker=security.insecureAPI.getpw -analyzer-checker=security.insecureAPI.gets -analyzer-checker=security.insecureAPI.mktemp -analyzer-checker=security.insecureAPI.mkstemp -analyzer-checker=security.insecureAPI.vfork -analyzer-checker=nullability.NullPassedToNonnull -analyzer-checker=nullability.NullReturnedFromNonnull -analyzer-output plist -w -setup-static-analyzer -mrelocation-model pic -pic-level 2 -fhalf-no-semantic-interposition -mframe-pointer=all -fmath-errno -ffp-contract=on -fno-rounding-math -mconstructor-aliases -funwind-tables=2 -target-cpu x86-64 -tune-cpu generic -debugger-tuning=gdb -fcoverage-compilation-dir=/rootdir/ctk -resource-dir /usr/lib/llvm-16/lib/clang/16 -D HAVE_CONFIG_H -I . -I .. -D G_LOG_DOMAIN="Ctk" -D G_LOG_USE_STRUCTURED=1 -D CTK_VERSION="3.25.5" -D CTK_BINARY_VERSION="3.0.0" -D CTK_COMPILATION -D CTK_PRINT_BACKEND_ENABLE_UNSUPPORTED -D CTK_LIBDIR="/usr/lib" -D CTK_LOCALEDIR="/usr/share/locale" -D CTK_DATADIR="/usr/share" -D CTK_DATA_PREFIX="/usr" -D CTK_SYSCONFDIR="/usr/etc" -D CTK_HOST="x86_64-pc-linux-gnu" -D CTK_PRINT_BACKENDS="file,cups" -D X11_DATA_PREFIX="/usr" -D ISO_CODES_PREFIX="" -I .. -I ../ctk -I .. -I ../cdk -I /usr/include/glib-2.0 -I /usr/lib/x86_64-linux-gnu/glib-2.0/include -I /usr/include/sysprof-6 -D G_ENABLE_DEBUG -D G_ENABLE_CONSISTENCY_CHECKS -D GLIB_MIN_REQUIRED_VERSION=GLIB_VERSION_2_66 -D GLIB_MAX_ALLOWED_VERSION=GLIB_VERSION_2_66 -I /usr/include/pango-1.0 -I /usr/include/glib-2.0 -I /usr/lib/x86_64-linux-gnu/glib-2.0/include -I /usr/include/sysprof-6 -I /usr/include/harfbuzz -I /usr/include/freetype2 -I /usr/include/libpng16 -I /usr/include/libmount -I /usr/include/blkid -I /usr/include/fribidi -I /usr/include/cairo -I /usr/include/pixman-1 -I /usr/include/atk-1.0 -I /usr/include/gdk-pixbuf-2.0 -I /usr/include/x86_64-linux-gnu -I /usr/include/webp -I /usr/include/at-spi2-atk/2.0 -I /usr/include/at-spi-2.0 -I /usr/include/dbus-1.0 -I /usr/lib/x86_64-linux-gnu/dbus-1.0/include -I /usr/include/gio-unix-2.0 -I /usr/include/harfbuzz -I /usr/include/freetype2 -I /usr/include/libpng16 -I /usr/include/glib-2.0 -I /usr/lib/x86_64-linux-gnu/glib-2.0/include -I /usr/include/sysprof-6 -I /usr/include/pango-1.0 -I /usr/include/libmount -I /usr/include/blkid -I /usr/include/fribidi -I /usr/include/cairo -I /usr/include/pixman-1 -D PIC -internal-isystem /usr/lib/llvm-16/lib/clang/16/include -internal-isystem /usr/local/include -internal-isystem /usr/lib/gcc/x86_64-linux-gnu/14/../../../../x86_64-linux-gnu/include -internal-externc-isystem /usr/include/x86_64-linux-gnu -internal-externc-isystem /include -internal-externc-isystem /usr/include -fdebug-compilation-dir=/rootdir/ctk -ferror-limit 19 -fvisibility=hidden -fgnuc-version=4.2.1 -analyzer-checker deadcode.DeadStores -analyzer-checker alpha.deadcode.UnreachableCode -analyzer-checker alpha.core.CastSize -analyzer-checker alpha.core.CastToStruct -analyzer-checker alpha.core.IdenticalExpr -analyzer-checker alpha.core.SizeofPtr -analyzer-checker alpha.security.ArrayBoundV2 -analyzer-checker alpha.security.MallocOverflow -analyzer-checker alpha.security.ReturnPtrRange -analyzer-checker alpha.unix.SimpleStream -analyzer-checker alpha.unix.cstring.BufferOverlap -analyzer-checker alpha.unix.cstring.NotNullTerminated -analyzer-checker alpha.unix.cstring.OutOfBounds -analyzer-checker alpha.core.FixedAddr -analyzer-output=html -faddrsig -D__GCC_HAVE_DWARF2_CFI_ASM=1 -o /rootdir/html-report/2024-09-19-170037-43636-1 -x c ctktreemodelfilter.c
1/* ctktreemodelfilter.c
2 * Copyright (C) 2000,2001 Red Hat, Inc., Jonathan Blandford <jrb@redhat.com>
3 * Copyright (C) 2001-2003 Kristian Rietveld <kris@gtk.org>
4 *
5 * This library is free software; you can redistribute it and/or
6 * modify it under the terms of the GNU Library General Public
7 * License as published by the Free Software Foundation; either
8 * version 2 of the License, or (at your option) any later version.
9 *
10 * This library is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13 * Library General Public License for more details.
14 *
15 * You should have received a copy of the GNU Library General Public
16 * License along with this library. If not, see <http://www.gnu.org/licenses/>.
17 */
18
19#include "config.h"
20#include "ctktreemodelfilter.h"
21#include "ctkintl.h"
22#include "ctktreednd.h"
23#include "ctkprivate.h"
24#include <string.h>
25
26
27/**
28 * SECTION:ctktreemodelfilter
29 * @Short_description: A CtkTreeModel which hides parts of an underlying tree model
30 * @Title: CtkTreeModelFilter
31 * @See_also:#CtkTreeModelSort
32 *
33 * A #CtkTreeModelFilter is a tree model which wraps another tree model,
34 * and can do the following things:
35 *
36 * - Filter specific rows, based on data from a “visible column”, a column
37 * storing booleans indicating whether the row should be filtered or not,
38 * or based on the return value of a “visible function”, which gets a
39 * model, iter and user_data and returns a boolean indicating whether the
40 * row should be filtered or not.
41 *
42 * - Modify the “appearance” of the model, using a modify function.
43 * This is extremely powerful and allows for just changing some
44 * values and also for creating a completely different model based
45 * on the given child model.
46 *
47 * - Set a different root node, also known as a “virtual root”. You can pass
48 * in a #CtkTreePath indicating the root node for the filter at construction
49 * time.
50 *
51 * The basic API is similar to #CtkTreeModelSort. For an example on its usage,
52 * see the section on #CtkTreeModelSort.
53 *
54 * When using #CtkTreeModelFilter, it is important to realize that
55 * #CtkTreeModelFilter maintains an internal cache of all nodes which are
56 * visible in its clients. The cache is likely to be a subtree of the tree
57 * exposed by the child model. #CtkTreeModelFilter will not cache the entire
58 * child model when unnecessary to not compromise the caching mechanism
59 * that is exposed by the reference counting scheme. If the child model
60 * implements reference counting, unnecessary signals may not be emitted
61 * because of reference counting rule 3, see the #CtkTreeModel
62 * documentation. (Note that e.g. #CtkTreeStore does not implement
63 * reference counting and will always emit all signals, even when
64 * the receiving node is not visible).
65 *
66 * Because of this, limitations for possible visible functions do apply.
67 * In general, visible functions should only use data or properties from
68 * the node for which the visibility state must be determined, its siblings
69 * or its parents. Usually, having a dependency on the state of any child
70 * node is not possible, unless references are taken on these explicitly.
71 * When no such reference exists, no signals may be received for these child
72 * nodes (see reference couting rule number 3 in the #CtkTreeModel section).
73 *
74 * Determining the visibility state of a given node based on the state
75 * of its child nodes is a frequently occurring use case. Therefore,
76 * #CtkTreeModelFilter explicitly supports this. For example, when a node
77 * does not have any children, you might not want the node to be visible.
78 * As soon as the first row is added to the node’s child level (or the
79 * last row removed), the node’s visibility should be updated.
80 *
81 * This introduces a dependency from the node on its child nodes. In order
82 * to accommodate this, #CtkTreeModelFilter must make sure the necessary
83 * signals are received from the child model. This is achieved by building,
84 * for all nodes which are exposed as visible nodes to #CtkTreeModelFilter's
85 * clients, the child level (if any) and take a reference on the first node
86 * in this level. Furthermore, for every row-inserted, row-changed or
87 * row-deleted signal (also these which were not handled because the node
88 * was not cached), #CtkTreeModelFilter will check if the visibility state
89 * of any parent node has changed.
90 *
91 * Beware, however, that this explicit support is limited to these two
92 * cases. For example, if you want a node to be visible only if two nodes
93 * in a child’s child level (2 levels deeper) are visible, you are on your
94 * own. In this case, either rely on #CtkTreeStore to emit all signals
95 * because it does not implement reference counting, or for models that
96 * do implement reference counting, obtain references on these child levels
97 * yourself.
98 */
99
100/* Notes on this implementation of CtkTreeModelFilter
101 * ==================================================
102 *
103 * Warnings
104 * --------
105 *
106 * In this code there is a potential for confusion as to whether an iter,
107 * path or value refers to the CtkTreeModelFilter model, or to the child
108 * model that has been set. As a convention, variables referencing the
109 * child model will have a c_ prefix before them (ie. c_iter, c_value,
110 * c_path). In case the c_ prefixed names are already in use, an f_
111 * prefix is used. Conversion of iterators and paths between
112 * CtkTreeModelFilter and the child model is done through the various
113 * ctk_tree_model_filter_convert_* functions.
114 *
115 * Even though the CtkTreeModelSort and CtkTreeModelFilter have very
116 * similar data structures, many assumptions made in the CtkTreeModelSort
117 * code do *not* apply in the CtkTreeModelFilter case. Reference counting
118 * in particular is more complicated in CtkTreeModelFilter, because
119 * we explicitly support reliance on the state of a node’s children as
120 * outlined in the public API documentation. Because of these differences,
121 * you are strongly recommended to first read through these notes before
122 * making any modification to the code.
123 *
124 * Iterator format
125 * ---------------
126 *
127 * The iterator format of iterators handed out by CtkTreeModelFilter is
128 * as follows:
129 *
130 * iter->stamp = filter->priv->stamp
131 * iter->user_data = FilterLevel
132 * iter->user_data2 = FilterElt
133 *
134 * Internal data structure
135 * -----------------------
136 *
137 * Using FilterLevel and FilterElt, CtkTreeModelFilter maintains a “cache”
138 * of the mapping from CtkTreeModelFilter nodes to nodes in the child model.
139 * This is to avoid re-creating a level each time (which involves computing
140 * visibility for each node in that level) an operation is requested on
141 * CtkTreeModelFilter, such as get iter, get path and get value.
142 *
143 * A FilterElt corresponds to a single node. The FilterElt can either be
144 * visible or invisible in the model that is exposed to the clients of this
145 * CtkTreeModelFilter. The visibility state is stored in the “visible_siter”
146 * field, which is NULL when the node is not visible. The FilterLevel keeps
147 * a reference to the parent FilterElt and its FilterLevel (if any). The
148 * FilterElt can have a “children” pointer set, which points at a child
149 * level (a sub level).
150 *
151 * In a FilterLevel, two separate GSequences are maintained. One contains
152 * all nodes of this FilterLevel, regardless of the visibility state of
153 * the node. Another contains only visible nodes. A visible FilterElt
154 * is thus present in both the full and the visible GSequence. The
155 * GSequence allows for fast access, addition and removal of nodes.
156 *
157 * It is important to recognize the two different mappings that play
158 * a part in this code:
159 * I. The mapping from the client to this model. The order in which
160 * nodes are stored in the *visible* GSequence is the order in
161 * which the nodes are exposed to clients of the CtkTreeModelFilter.
162 * II. The mapping from this model to its child model. Each FilterElt
163 * contains an “offset” field which is the offset of the
164 * corresponding node in the child model.
165 *
166 * Throughout the code, two kinds of paths relative to the CtkTreeModelFilter
167 * (those generated from the sequence positions) are used. There are paths
168 * which take non-visible nodes into account (generated from the full
169 * sequences) and paths which don’t (generated from the visible sequences).
170 * Paths which have been generated from the full sequences should only be
171 * used internally and NEVER be passed along with a signal emisson.
172 *
173 * Reference counting
174 * ------------------
175 *
176 * CtkTreeModelFilter forwards all reference and unreference operations
177 * to the corresponding node in the child model. In addition,
178 * CtkTreeModelFilter will also add references of its own. The full reference
179 * count of each node (i.e. all forwarded references and these by the
180 * filter model) is maintained internally in the “ref_count” fields in
181 * FilterElt and FilterLevel. Because there is a need to determine whether
182 * a node should be visible for the client, the reference count of only
183 * the forwarded references is maintained as well, in the “ext_ref_count”
184 * fields.
185 *
186 * In a few cases, CtkTreeModelFilter takes additional references on
187 * nodes. The first case is that a reference is taken on the parent
188 * (if any) of each level. This happens in ctk_tree_model_filter_build_level()
189 * and the reference is released again in ctk_tree_model_filter_free_level().
190 * This ensures that for all references which are taken by the filter
191 * model, all parent nodes are referenced according to reference counting
192 * rule 1 in the CtkTreeModel documentation.
193 *
194 * A second case is required to support visible functions which depend on
195 * the state of a node’s children (see the public API documentation for
196 * CtkTreeModelFilter above). We build the child level of each node that
197 * could be visible in the client (i.e. the level has an ext_ref_count > 0;
198 * not the elt, because the elt might be invisible and thus unreferenced
199 * by the client). For each node that becomes visible, due to insertion or
200 * changes in visibility state, it is checked whether node has children, if
201 * so the child level is built.
202 *
203 * A reference is taken on the first node of each level so that the child
204 * model will emit all signals for this level, due to reference counting
205 * rule 3 in the CtkTreeModel documentation. If due to changes in the level,
206 * another node becomes the first node (e.g. due to insertion or reordering),
207 * this reference is transferred from the old to the new first node.
208 *
209 * When a level has an *external* reference count of zero (which means that
210 * none of the nodes in the level is referenced by the clients), the level
211 * has a “zero ref count” on all its parents. As soon as the level reaches
212 * an *external* reference count of zero, the zero ref count value is
213 * incremented by one for all parents of this level. Due to the additional
214 * references taken by the filter model, it is important to base the
215 * zero ref count on the external reference count instead of on the full
216 * reference count of the node.
217 *
218 * The zero ref count value aids in determining which portions of the
219 * cache are possibly unused and could be removed. If a FilterElt has
220 * a zero ref count of one, then its child level is unused. However, the
221 * child level can only be removed from the cache if the FilterElt's
222 * parent level has an external ref count of zero. (Not the parent elt,
223 * because an invisible parent elt with external ref count == 0 might still
224 * become visible because of a state change in its child level!). Otherwise,
225 * monitoring this level is necessary to possibly update the visibility state
226 * of the parent. This is an important difference from CtkTreeModelSort!
227 *
228 * Signals are only required for levels with an external ref count > 0.
229 * This due to reference counting rule 3, see the CtkTreeModel
230 * documentation. In the CtkTreeModelFilter we try hard to stick to this
231 * rule and not emit redundant signals (though redundant emissions of
232 * row-has-child-toggled could appear frequently; it does happen that
233 * we simply forward the signal emitted by e.g. CtkTreeStore but also
234 * emit our own copy).
235 */
236
237
238typedef struct _FilterElt FilterElt;
239typedef struct _FilterLevel FilterLevel;
240
241struct _FilterElt
242{
243 CtkTreeIter iter;
244 FilterLevel *children;
245 gint offset;
246 gint ref_count;
247 gint ext_ref_count;
248 gint zero_ref_count;
249 GSequenceIter *visible_siter; /* iter into visible_seq */
250};
251
252struct _FilterLevel
253{
254 GSequence *seq;
255 GSequence *visible_seq;
256 gint ref_count;
257 gint ext_ref_count;
258
259 FilterElt *parent_elt;
260 FilterLevel *parent_level;
261};
262
263
264struct _CtkTreeModelFilterPrivate
265{
266 CtkTreeModel *child_model;
267 gpointer root;
268 CtkTreePath *virtual_root;
269
270 gint stamp;
271 guint child_flags;
272 gint zero_ref_count;
273 gint visible_column;
274
275 CtkTreeModelFilterVisibleFunc visible_func;
276 gpointer visible_data;
277 GDestroyNotify visible_destroy;
278
279 GType *modify_types;
280 CtkTreeModelFilterModifyFunc modify_func;
281 gpointer modify_data;
282 GDestroyNotify modify_destroy;
283 gint modify_n_columns;
284
285 guint visible_method_set : 1;
286 guint modify_func_set : 1;
287
288 guint in_row_deleted : 1;
289 guint virtual_root_deleted : 1;
290
291 /* signal ids */
292 gulong changed_id;
293 gulong inserted_id;
294 gulong has_child_toggled_id;
295 gulong deleted_id;
296 gulong reordered_id;
297};
298
299/* properties */
300enum
301{
302 PROP_0,
303 PROP_CHILD_MODEL,
304 PROP_VIRTUAL_ROOT
305};
306
307/* Set this to 0 to disable caching of child iterators. This
308 * allows for more stringent testing. It is recommended to set this
309 * to one when refactoring this code and running the unit tests to
310 * catch more errors.
311 */
312#if 1
313# define CTK_TREE_MODEL_FILTER_CACHE_CHILD_ITERS(filter)(((CtkTreeModelFilter *)filter)->priv->child_flags &
CTK_TREE_MODEL_ITERS_PERSIST)
\
314 (((CtkTreeModelFilter *)filter)->priv->child_flags & CTK_TREE_MODEL_ITERS_PERSIST)
315#else
316# define CTK_TREE_MODEL_FILTER_CACHE_CHILD_ITERS(filter)(((CtkTreeModelFilter *)filter)->priv->child_flags &
CTK_TREE_MODEL_ITERS_PERSIST)
(FALSE(0))
317#endif
318
319/* Defining this constant enables more assertions, which will be
320 * helpful when debugging the code.
321 */
322#undef MODEL_FILTER_DEBUG
323
324#define FILTER_ELT(filter_elt)((FilterElt *)filter_elt) ((FilterElt *)filter_elt)
325#define FILTER_LEVEL(filter_level)((FilterLevel *)filter_level) ((FilterLevel *)filter_level)
326#define GET_ELT(siter)((FilterElt*) (siter ? g_sequence_get (siter) : ((void*)0))) ((FilterElt*) (siter ? g_sequence_get (siter) : NULL((void*)0)))
327
328/* general code (object/interface init, properties, etc) */
329static void ctk_tree_model_filter_tree_model_init (CtkTreeModelIface *iface);
330static void ctk_tree_model_filter_drag_source_init (CtkTreeDragSourceIface *iface);
331static void ctk_tree_model_filter_finalize (GObject *object);
332static void ctk_tree_model_filter_set_property (GObject *object,
333 guint prop_id,
334 const GValue *value,
335 GParamSpec *pspec);
336static void ctk_tree_model_filter_get_property (GObject *object,
337 guint prop_id,
338 GValue *value,
339 GParamSpec *pspec);
340
341/* signal handlers */
342static void ctk_tree_model_filter_row_changed (CtkTreeModel *c_model,
343 CtkTreePath *c_path,
344 CtkTreeIter *c_iter,
345 gpointer data);
346static void ctk_tree_model_filter_row_inserted (CtkTreeModel *c_model,
347 CtkTreePath *c_path,
348 CtkTreeIter *c_iter,
349 gpointer data);
350static void ctk_tree_model_filter_row_has_child_toggled (CtkTreeModel *c_model,
351 CtkTreePath *c_path,
352 CtkTreeIter *c_iter,
353 gpointer data);
354static void ctk_tree_model_filter_row_deleted (CtkTreeModel *c_model,
355 CtkTreePath *c_path,
356 gpointer data);
357static void ctk_tree_model_filter_rows_reordered (CtkTreeModel *c_model,
358 CtkTreePath *c_path,
359 CtkTreeIter *c_iter,
360 gint *new_order,
361 gpointer data);
362
363/* CtkTreeModel interface */
364static CtkTreeModelFlags ctk_tree_model_filter_get_flags (CtkTreeModel *model);
365static gint ctk_tree_model_filter_get_n_columns (CtkTreeModel *model);
366static GType ctk_tree_model_filter_get_column_type (CtkTreeModel *model,
367 gint index);
368static gboolean ctk_tree_model_filter_get_iter_full (CtkTreeModel *model,
369 CtkTreeIter *iter,
370 CtkTreePath *path);
371static gboolean ctk_tree_model_filter_get_iter (CtkTreeModel *model,
372 CtkTreeIter *iter,
373 CtkTreePath *path);
374static CtkTreePath *ctk_tree_model_filter_get_path (CtkTreeModel *model,
375 CtkTreeIter *iter);
376static void ctk_tree_model_filter_get_value (CtkTreeModel *model,
377 CtkTreeIter *iter,
378 gint column,
379 GValue *value);
380static gboolean ctk_tree_model_filter_iter_next (CtkTreeModel *model,
381 CtkTreeIter *iter);
382static gboolean ctk_tree_model_filter_iter_previous (CtkTreeModel *model,
383 CtkTreeIter *iter);
384static gboolean ctk_tree_model_filter_iter_children (CtkTreeModel *model,
385 CtkTreeIter *iter,
386 CtkTreeIter *parent);
387static gboolean ctk_tree_model_filter_iter_has_child (CtkTreeModel *model,
388 CtkTreeIter *iter);
389static gint ctk_tree_model_filter_iter_n_children (CtkTreeModel *model,
390 CtkTreeIter *iter);
391static gboolean ctk_tree_model_filter_iter_nth_child (CtkTreeModel *model,
392 CtkTreeIter *iter,
393 CtkTreeIter *parent,
394 gint n);
395static gboolean ctk_tree_model_filter_iter_parent (CtkTreeModel *model,
396 CtkTreeIter *iter,
397 CtkTreeIter *child);
398static void ctk_tree_model_filter_ref_node (CtkTreeModel *model,
399 CtkTreeIter *iter);
400static void ctk_tree_model_filter_unref_node (CtkTreeModel *model,
401 CtkTreeIter *iter);
402
403/* TreeDragSource interface */
404static gboolean ctk_tree_model_filter_row_draggable (CtkTreeDragSource *drag_source,
405 CtkTreePath *path);
406static gboolean ctk_tree_model_filter_drag_data_get (CtkTreeDragSource *drag_source,
407 CtkTreePath *path,
408 CtkSelectionData *selection_data);
409static gboolean ctk_tree_model_filter_drag_data_delete (CtkTreeDragSource *drag_source,
410 CtkTreePath *path);
411
412/* private functions */
413static void ctk_tree_model_filter_build_level (CtkTreeModelFilter *filter,
414 FilterLevel *parent_level,
415 FilterElt *parent_elt,
416 gboolean emit_inserted);
417
418static void ctk_tree_model_filter_free_level (CtkTreeModelFilter *filter,
419 FilterLevel *filter_level,
420 gboolean unref_self,
421 gboolean unref_parent,
422 gboolean unref_external);
423
424static CtkTreePath *ctk_tree_model_filter_elt_get_path (FilterLevel *level,
425 FilterElt *elt,
426 CtkTreePath *root);
427
428static CtkTreePath *ctk_tree_model_filter_add_root (CtkTreePath *src,
429 CtkTreePath *root);
430static CtkTreePath *ctk_tree_model_filter_remove_root (CtkTreePath *src,
431 CtkTreePath *root);
432
433static void ctk_tree_model_filter_increment_stamp (CtkTreeModelFilter *filter);
434
435static void ctk_tree_model_filter_real_modify (CtkTreeModelFilter *self,
436 CtkTreeModel *child_model,
437 CtkTreeIter *iter,
438 GValue *value,
439 gint column);
440static gboolean ctk_tree_model_filter_real_visible (CtkTreeModelFilter *filter,
441 CtkTreeModel *child_model,
442 CtkTreeIter *child_iter);
443static gboolean ctk_tree_model_filter_visible (CtkTreeModelFilter *filter,
444 CtkTreeIter *child_iter);
445static void ctk_tree_model_filter_clear_cache_helper (CtkTreeModelFilter *filter,
446 FilterLevel *level);
447
448static void ctk_tree_model_filter_real_ref_node (CtkTreeModel *model,
449 CtkTreeIter *iter,
450 gboolean external);
451static void ctk_tree_model_filter_real_unref_node (CtkTreeModel *model,
452 CtkTreeIter *iter,
453 gboolean external,
454 gboolean propagate_unref);
455
456static void ctk_tree_model_filter_set_model (CtkTreeModelFilter *filter,
457 CtkTreeModel *child_model);
458static void ctk_tree_model_filter_ref_path (CtkTreeModelFilter *filter,
459 CtkTreePath *path);
460static void ctk_tree_model_filter_unref_path (CtkTreeModelFilter *filter,
461 CtkTreePath *path,
462 int depth);
463static void ctk_tree_model_filter_set_root (CtkTreeModelFilter *filter,
464 CtkTreePath *root);
465
466static CtkTreePath *ctk_real_tree_model_filter_convert_child_path_to_path (CtkTreeModelFilter *filter,
467 CtkTreePath *child_path,
468 gboolean build_levels,
469 gboolean fetch_children);
470
471static gboolean ctk_tree_model_filter_elt_is_visible_in_target (FilterLevel *level,
472 FilterElt *elt);
473
474static FilterElt *ctk_tree_model_filter_insert_elt_in_level (CtkTreeModelFilter *filter,
475 CtkTreeIter *c_iter,
476 FilterLevel *level,
477 gint offset,
478 gint *index);
479static FilterElt *ctk_tree_model_filter_fetch_child (CtkTreeModelFilter *filter,
480 FilterLevel *level,
481 gint offset,
482 gint *index);
483static void ctk_tree_model_filter_remove_elt_from_level (CtkTreeModelFilter *filter,
484 FilterLevel *level,
485 FilterElt *elt);
486static void ctk_tree_model_filter_update_children (CtkTreeModelFilter *filter,
487 FilterLevel *level,
488 FilterElt *elt);
489static void ctk_tree_model_filter_emit_row_inserted_for_path (CtkTreeModelFilter *filter,
490 CtkTreeModel *c_model,
491 CtkTreePath *c_path,
492 CtkTreeIter *c_iter);
493
494
495G_DEFINE_TYPE_WITH_CODE (CtkTreeModelFilter, ctk_tree_model_filter, G_TYPE_OBJECT,static void ctk_tree_model_filter_init (CtkTreeModelFilter *self
); static void ctk_tree_model_filter_class_init (CtkTreeModelFilterClass
*klass); static GType ctk_tree_model_filter_get_type_once (void
); static gpointer ctk_tree_model_filter_parent_class = ((void
*)0); static gint CtkTreeModelFilter_private_offset; static void
ctk_tree_model_filter_class_intern_init (gpointer klass) { ctk_tree_model_filter_parent_class
= g_type_class_peek_parent (klass); if (CtkTreeModelFilter_private_offset
!= 0) g_type_class_adjust_private_offset (klass, &CtkTreeModelFilter_private_offset
); ctk_tree_model_filter_class_init ((CtkTreeModelFilterClass
*) klass); } __attribute__ ((__unused__)) static inline gpointer
ctk_tree_model_filter_get_instance_private (CtkTreeModelFilter
*self) { return (((gpointer) ((guint8*) (self) + (glong) (CtkTreeModelFilter_private_offset
)))); } GType ctk_tree_model_filter_get_type (void) { static GType
static_g_define_type_id = 0; if ((__extension__ ({ _Static_assert
(sizeof *(&static_g_define_type_id) == sizeof (gpointer)
, "Expression evaluates to false"); (void) (0 ? (gpointer) * (
&static_g_define_type_id) : ((void*)0)); (!(__extension__
({ _Static_assert (sizeof *(&static_g_define_type_id) ==
sizeof (gpointer), "Expression evaluates to false"); __typeof__
(*(&static_g_define_type_id)) gapg_temp_newval; __typeof__
((&static_g_define_type_id)) gapg_temp_atomic = (&static_g_define_type_id
); __atomic_load (gapg_temp_atomic, &gapg_temp_newval, 5)
; gapg_temp_newval; })) && g_once_init_enter_pointer (
&static_g_define_type_id)); })) ) { GType g_define_type_id
= ctk_tree_model_filter_get_type_once (); (__extension__ ({ _Static_assert
(sizeof *(&static_g_define_type_id) == sizeof (gpointer)
, "Expression evaluates to false"); 0 ? (void) (*(&static_g_define_type_id
) = (g_define_type_id)) : (void) 0; g_once_init_leave_pointer
((&static_g_define_type_id), (gpointer) (guintptr) (g_define_type_id
)); })) ; } return static_g_define_type_id; } __attribute__ (
(__noinline__)) static GType ctk_tree_model_filter_get_type_once
(void) { GType g_define_type_id = g_type_register_static_simple
(((GType) ((20) << (2))), g_intern_static_string ("CtkTreeModelFilter"
), sizeof (CtkTreeModelFilterClass), (GClassInitFunc)(void (*
)(void)) ctk_tree_model_filter_class_intern_init, sizeof (CtkTreeModelFilter
), (GInstanceInitFunc)(void (*)(void)) ctk_tree_model_filter_init
, (GTypeFlags) 0); { {{ CtkTreeModelFilter_private_offset = g_type_add_instance_private
(g_define_type_id, sizeof (CtkTreeModelFilterPrivate)); } { const
GInterfaceInfo g_implement_interface_info = { (GInterfaceInitFunc
)(void (*)(void)) ctk_tree_model_filter_tree_model_init, ((void
*)0), ((void*)0) }; g_type_add_interface_static (g_define_type_id
, (ctk_tree_model_get_type ()), &g_implement_interface_info
); } { const GInterfaceInfo g_implement_interface_info = { (GInterfaceInitFunc
)(void (*)(void)) ctk_tree_model_filter_drag_source_init, ((void
*)0), ((void*)0) }; g_type_add_interface_static (g_define_type_id
, (ctk_tree_drag_source_get_type ()), &g_implement_interface_info
); };} } return g_define_type_id; }
496 G_ADD_PRIVATE (CtkTreeModelFilter)static void ctk_tree_model_filter_init (CtkTreeModelFilter *self
); static void ctk_tree_model_filter_class_init (CtkTreeModelFilterClass
*klass); static GType ctk_tree_model_filter_get_type_once (void
); static gpointer ctk_tree_model_filter_parent_class = ((void
*)0); static gint CtkTreeModelFilter_private_offset; static void
ctk_tree_model_filter_class_intern_init (gpointer klass) { ctk_tree_model_filter_parent_class
= g_type_class_peek_parent (klass); if (CtkTreeModelFilter_private_offset
!= 0) g_type_class_adjust_private_offset (klass, &CtkTreeModelFilter_private_offset
); ctk_tree_model_filter_class_init ((CtkTreeModelFilterClass
*) klass); } __attribute__ ((__unused__)) static inline gpointer
ctk_tree_model_filter_get_instance_private (CtkTreeModelFilter
*self) { return (((gpointer) ((guint8*) (self) + (glong) (CtkTreeModelFilter_private_offset
)))); } GType ctk_tree_model_filter_get_type (void) { static GType
static_g_define_type_id = 0; if ((__extension__ ({ _Static_assert
(sizeof *(&static_g_define_type_id) == sizeof (gpointer)
, "Expression evaluates to false"); (void) (0 ? (gpointer) * (
&static_g_define_type_id) : ((void*)0)); (!(__extension__
({ _Static_assert (sizeof *(&static_g_define_type_id) ==
sizeof (gpointer), "Expression evaluates to false"); __typeof__
(*(&static_g_define_type_id)) gapg_temp_newval; __typeof__
((&static_g_define_type_id)) gapg_temp_atomic = (&static_g_define_type_id
); __atomic_load (gapg_temp_atomic, &gapg_temp_newval, 5)
; gapg_temp_newval; })) && g_once_init_enter_pointer (
&static_g_define_type_id)); })) ) { GType g_define_type_id
= ctk_tree_model_filter_get_type_once (); (__extension__ ({ _Static_assert
(sizeof *(&static_g_define_type_id) == sizeof (gpointer)
, "Expression evaluates to false"); 0 ? (void) (*(&static_g_define_type_id
) = (g_define_type_id)) : (void) 0; g_once_init_leave_pointer
((&static_g_define_type_id), (gpointer) (guintptr) (g_define_type_id
)); })) ; } return static_g_define_type_id; } __attribute__ (
(__noinline__)) static GType ctk_tree_model_filter_get_type_once
(void) { GType g_define_type_id = g_type_register_static_simple
(((GType) ((20) << (2))), g_intern_static_string ("CtkTreeModelFilter"
), sizeof (CtkTreeModelFilterClass), (GClassInitFunc)(void (*
)(void)) ctk_tree_model_filter_class_intern_init, sizeof (CtkTreeModelFilter
), (GInstanceInitFunc)(void (*)(void)) ctk_tree_model_filter_init
, (GTypeFlags) 0); { {{ CtkTreeModelFilter_private_offset = g_type_add_instance_private
(g_define_type_id, sizeof (CtkTreeModelFilterPrivate)); } { const
GInterfaceInfo g_implement_interface_info = { (GInterfaceInitFunc
)(void (*)(void)) ctk_tree_model_filter_tree_model_init, ((void
*)0), ((void*)0) }; g_type_add_interface_static (g_define_type_id
, (ctk_tree_model_get_type ()), &g_implement_interface_info
); } { const GInterfaceInfo g_implement_interface_info = { (GInterfaceInitFunc
)(void (*)(void)) ctk_tree_model_filter_drag_source_init, ((void
*)0), ((void*)0) }; g_type_add_interface_static (g_define_type_id
, (ctk_tree_drag_source_get_type ()), &g_implement_interface_info
); };} } return g_define_type_id; }
497 G_IMPLEMENT_INTERFACE (CTK_TYPE_TREE_MODEL,static void ctk_tree_model_filter_init (CtkTreeModelFilter *self
); static void ctk_tree_model_filter_class_init (CtkTreeModelFilterClass
*klass); static GType ctk_tree_model_filter_get_type_once (void
); static gpointer ctk_tree_model_filter_parent_class = ((void
*)0); static gint CtkTreeModelFilter_private_offset; static void
ctk_tree_model_filter_class_intern_init (gpointer klass) { ctk_tree_model_filter_parent_class
= g_type_class_peek_parent (klass); if (CtkTreeModelFilter_private_offset
!= 0) g_type_class_adjust_private_offset (klass, &CtkTreeModelFilter_private_offset
); ctk_tree_model_filter_class_init ((CtkTreeModelFilterClass
*) klass); } __attribute__ ((__unused__)) static inline gpointer
ctk_tree_model_filter_get_instance_private (CtkTreeModelFilter
*self) { return (((gpointer) ((guint8*) (self) + (glong) (CtkTreeModelFilter_private_offset
)))); } GType ctk_tree_model_filter_get_type (void) { static GType
static_g_define_type_id = 0; if ((__extension__ ({ _Static_assert
(sizeof *(&static_g_define_type_id) == sizeof (gpointer)
, "Expression evaluates to false"); (void) (0 ? (gpointer) * (
&static_g_define_type_id) : ((void*)0)); (!(__extension__
({ _Static_assert (sizeof *(&static_g_define_type_id) ==
sizeof (gpointer), "Expression evaluates to false"); __typeof__
(*(&static_g_define_type_id)) gapg_temp_newval; __typeof__
((&static_g_define_type_id)) gapg_temp_atomic = (&static_g_define_type_id
); __atomic_load (gapg_temp_atomic, &gapg_temp_newval, 5)
; gapg_temp_newval; })) && g_once_init_enter_pointer (
&static_g_define_type_id)); })) ) { GType g_define_type_id
= ctk_tree_model_filter_get_type_once (); (__extension__ ({ _Static_assert
(sizeof *(&static_g_define_type_id) == sizeof (gpointer)
, "Expression evaluates to false"); 0 ? (void) (*(&static_g_define_type_id
) = (g_define_type_id)) : (void) 0; g_once_init_leave_pointer
((&static_g_define_type_id), (gpointer) (guintptr) (g_define_type_id
)); })) ; } return static_g_define_type_id; } __attribute__ (
(__noinline__)) static GType ctk_tree_model_filter_get_type_once
(void) { GType g_define_type_id = g_type_register_static_simple
(((GType) ((20) << (2))), g_intern_static_string ("CtkTreeModelFilter"
), sizeof (CtkTreeModelFilterClass), (GClassInitFunc)(void (*
)(void)) ctk_tree_model_filter_class_intern_init, sizeof (CtkTreeModelFilter
), (GInstanceInitFunc)(void (*)(void)) ctk_tree_model_filter_init
, (GTypeFlags) 0); { {{ CtkTreeModelFilter_private_offset = g_type_add_instance_private
(g_define_type_id, sizeof (CtkTreeModelFilterPrivate)); } { const
GInterfaceInfo g_implement_interface_info = { (GInterfaceInitFunc
)(void (*)(void)) ctk_tree_model_filter_tree_model_init, ((void
*)0), ((void*)0) }; g_type_add_interface_static (g_define_type_id
, (ctk_tree_model_get_type ()), &g_implement_interface_info
); } { const GInterfaceInfo g_implement_interface_info = { (GInterfaceInitFunc
)(void (*)(void)) ctk_tree_model_filter_drag_source_init, ((void
*)0), ((void*)0) }; g_type_add_interface_static (g_define_type_id
, (ctk_tree_drag_source_get_type ()), &g_implement_interface_info
); };} } return g_define_type_id; }
498 ctk_tree_model_filter_tree_model_init)static void ctk_tree_model_filter_init (CtkTreeModelFilter *self
); static void ctk_tree_model_filter_class_init (CtkTreeModelFilterClass
*klass); static GType ctk_tree_model_filter_get_type_once (void
); static gpointer ctk_tree_model_filter_parent_class = ((void
*)0); static gint CtkTreeModelFilter_private_offset; static void
ctk_tree_model_filter_class_intern_init (gpointer klass) { ctk_tree_model_filter_parent_class
= g_type_class_peek_parent (klass); if (CtkTreeModelFilter_private_offset
!= 0) g_type_class_adjust_private_offset (klass, &CtkTreeModelFilter_private_offset
); ctk_tree_model_filter_class_init ((CtkTreeModelFilterClass
*) klass); } __attribute__ ((__unused__)) static inline gpointer
ctk_tree_model_filter_get_instance_private (CtkTreeModelFilter
*self) { return (((gpointer) ((guint8*) (self) + (glong) (CtkTreeModelFilter_private_offset
)))); } GType ctk_tree_model_filter_get_type (void) { static GType
static_g_define_type_id = 0; if ((__extension__ ({ _Static_assert
(sizeof *(&static_g_define_type_id) == sizeof (gpointer)
, "Expression evaluates to false"); (void) (0 ? (gpointer) * (
&static_g_define_type_id) : ((void*)0)); (!(__extension__
({ _Static_assert (sizeof *(&static_g_define_type_id) ==
sizeof (gpointer), "Expression evaluates to false"); __typeof__
(*(&static_g_define_type_id)) gapg_temp_newval; __typeof__
((&static_g_define_type_id)) gapg_temp_atomic = (&static_g_define_type_id
); __atomic_load (gapg_temp_atomic, &gapg_temp_newval, 5)
; gapg_temp_newval; })) && g_once_init_enter_pointer (
&static_g_define_type_id)); })) ) { GType g_define_type_id
= ctk_tree_model_filter_get_type_once (); (__extension__ ({ _Static_assert
(sizeof *(&static_g_define_type_id) == sizeof (gpointer)
, "Expression evaluates to false"); 0 ? (void) (*(&static_g_define_type_id
) = (g_define_type_id)) : (void) 0; g_once_init_leave_pointer
((&static_g_define_type_id), (gpointer) (guintptr) (g_define_type_id
)); })) ; } return static_g_define_type_id; } __attribute__ (
(__noinline__)) static GType ctk_tree_model_filter_get_type_once
(void) { GType g_define_type_id = g_type_register_static_simple
(((GType) ((20) << (2))), g_intern_static_string ("CtkTreeModelFilter"
), sizeof (CtkTreeModelFilterClass), (GClassInitFunc)(void (*
)(void)) ctk_tree_model_filter_class_intern_init, sizeof (CtkTreeModelFilter
), (GInstanceInitFunc)(void (*)(void)) ctk_tree_model_filter_init
, (GTypeFlags) 0); { {{ CtkTreeModelFilter_private_offset = g_type_add_instance_private
(g_define_type_id, sizeof (CtkTreeModelFilterPrivate)); } { const
GInterfaceInfo g_implement_interface_info = { (GInterfaceInitFunc
)(void (*)(void)) ctk_tree_model_filter_tree_model_init, ((void
*)0), ((void*)0) }; g_type_add_interface_static (g_define_type_id
, (ctk_tree_model_get_type ()), &g_implement_interface_info
); } { const GInterfaceInfo g_implement_interface_info = { (GInterfaceInitFunc
)(void (*)(void)) ctk_tree_model_filter_drag_source_init, ((void
*)0), ((void*)0) }; g_type_add_interface_static (g_define_type_id
, (ctk_tree_drag_source_get_type ()), &g_implement_interface_info
); };} } return g_define_type_id; }
499 G_IMPLEMENT_INTERFACE (CTK_TYPE_TREE_DRAG_SOURCE,static void ctk_tree_model_filter_init (CtkTreeModelFilter *self
); static void ctk_tree_model_filter_class_init (CtkTreeModelFilterClass
*klass); static GType ctk_tree_model_filter_get_type_once (void
); static gpointer ctk_tree_model_filter_parent_class = ((void
*)0); static gint CtkTreeModelFilter_private_offset; static void
ctk_tree_model_filter_class_intern_init (gpointer klass) { ctk_tree_model_filter_parent_class
= g_type_class_peek_parent (klass); if (CtkTreeModelFilter_private_offset
!= 0) g_type_class_adjust_private_offset (klass, &CtkTreeModelFilter_private_offset
); ctk_tree_model_filter_class_init ((CtkTreeModelFilterClass
*) klass); } __attribute__ ((__unused__)) static inline gpointer
ctk_tree_model_filter_get_instance_private (CtkTreeModelFilter
*self) { return (((gpointer) ((guint8*) (self) + (glong) (CtkTreeModelFilter_private_offset
)))); } GType ctk_tree_model_filter_get_type (void) { static GType
static_g_define_type_id = 0; if ((__extension__ ({ _Static_assert
(sizeof *(&static_g_define_type_id) == sizeof (gpointer)
, "Expression evaluates to false"); (void) (0 ? (gpointer) * (
&static_g_define_type_id) : ((void*)0)); (!(__extension__
({ _Static_assert (sizeof *(&static_g_define_type_id) ==
sizeof (gpointer), "Expression evaluates to false"); __typeof__
(*(&static_g_define_type_id)) gapg_temp_newval; __typeof__
((&static_g_define_type_id)) gapg_temp_atomic = (&static_g_define_type_id
); __atomic_load (gapg_temp_atomic, &gapg_temp_newval, 5)
; gapg_temp_newval; })) && g_once_init_enter_pointer (
&static_g_define_type_id)); })) ) { GType g_define_type_id
= ctk_tree_model_filter_get_type_once (); (__extension__ ({ _Static_assert
(sizeof *(&static_g_define_type_id) == sizeof (gpointer)
, "Expression evaluates to false"); 0 ? (void) (*(&static_g_define_type_id
) = (g_define_type_id)) : (void) 0; g_once_init_leave_pointer
((&static_g_define_type_id), (gpointer) (guintptr) (g_define_type_id
)); })) ; } return static_g_define_type_id; } __attribute__ (
(__noinline__)) static GType ctk_tree_model_filter_get_type_once
(void) { GType g_define_type_id = g_type_register_static_simple
(((GType) ((20) << (2))), g_intern_static_string ("CtkTreeModelFilter"
), sizeof (CtkTreeModelFilterClass), (GClassInitFunc)(void (*
)(void)) ctk_tree_model_filter_class_intern_init, sizeof (CtkTreeModelFilter
), (GInstanceInitFunc)(void (*)(void)) ctk_tree_model_filter_init
, (GTypeFlags) 0); { {{ CtkTreeModelFilter_private_offset = g_type_add_instance_private
(g_define_type_id, sizeof (CtkTreeModelFilterPrivate)); } { const
GInterfaceInfo g_implement_interface_info = { (GInterfaceInitFunc
)(void (*)(void)) ctk_tree_model_filter_tree_model_init, ((void
*)0), ((void*)0) }; g_type_add_interface_static (g_define_type_id
, (ctk_tree_model_get_type ()), &g_implement_interface_info
); } { const GInterfaceInfo g_implement_interface_info = { (GInterfaceInitFunc
)(void (*)(void)) ctk_tree_model_filter_drag_source_init, ((void
*)0), ((void*)0) }; g_type_add_interface_static (g_define_type_id
, (ctk_tree_drag_source_get_type ()), &g_implement_interface_info
); };} } return g_define_type_id; }
500 ctk_tree_model_filter_drag_source_init))static void ctk_tree_model_filter_init (CtkTreeModelFilter *self
); static void ctk_tree_model_filter_class_init (CtkTreeModelFilterClass
*klass); static GType ctk_tree_model_filter_get_type_once (void
); static gpointer ctk_tree_model_filter_parent_class = ((void
*)0); static gint CtkTreeModelFilter_private_offset; static void
ctk_tree_model_filter_class_intern_init (gpointer klass) { ctk_tree_model_filter_parent_class
= g_type_class_peek_parent (klass); if (CtkTreeModelFilter_private_offset
!= 0) g_type_class_adjust_private_offset (klass, &CtkTreeModelFilter_private_offset
); ctk_tree_model_filter_class_init ((CtkTreeModelFilterClass
*) klass); } __attribute__ ((__unused__)) static inline gpointer
ctk_tree_model_filter_get_instance_private (CtkTreeModelFilter
*self) { return (((gpointer) ((guint8*) (self) + (glong) (CtkTreeModelFilter_private_offset
)))); } GType ctk_tree_model_filter_get_type (void) { static GType
static_g_define_type_id = 0; if ((__extension__ ({ _Static_assert
(sizeof *(&static_g_define_type_id) == sizeof (gpointer)
, "Expression evaluates to false"); (void) (0 ? (gpointer) * (
&static_g_define_type_id) : ((void*)0)); (!(__extension__
({ _Static_assert (sizeof *(&static_g_define_type_id) ==
sizeof (gpointer), "Expression evaluates to false"); __typeof__
(*(&static_g_define_type_id)) gapg_temp_newval; __typeof__
((&static_g_define_type_id)) gapg_temp_atomic = (&static_g_define_type_id
); __atomic_load (gapg_temp_atomic, &gapg_temp_newval, 5)
; gapg_temp_newval; })) && g_once_init_enter_pointer (
&static_g_define_type_id)); })) ) { GType g_define_type_id
= ctk_tree_model_filter_get_type_once (); (__extension__ ({ _Static_assert
(sizeof *(&static_g_define_type_id) == sizeof (gpointer)
, "Expression evaluates to false"); 0 ? (void) (*(&static_g_define_type_id
) = (g_define_type_id)) : (void) 0; g_once_init_leave_pointer
((&static_g_define_type_id), (gpointer) (guintptr) (g_define_type_id
)); })) ; } return static_g_define_type_id; } __attribute__ (
(__noinline__)) static GType ctk_tree_model_filter_get_type_once
(void) { GType g_define_type_id = g_type_register_static_simple
(((GType) ((20) << (2))), g_intern_static_string ("CtkTreeModelFilter"
), sizeof (CtkTreeModelFilterClass), (GClassInitFunc)(void (*
)(void)) ctk_tree_model_filter_class_intern_init, sizeof (CtkTreeModelFilter
), (GInstanceInitFunc)(void (*)(void)) ctk_tree_model_filter_init
, (GTypeFlags) 0); { {{ CtkTreeModelFilter_private_offset = g_type_add_instance_private
(g_define_type_id, sizeof (CtkTreeModelFilterPrivate)); } { const
GInterfaceInfo g_implement_interface_info = { (GInterfaceInitFunc
)(void (*)(void)) ctk_tree_model_filter_tree_model_init, ((void
*)0), ((void*)0) }; g_type_add_interface_static (g_define_type_id
, (ctk_tree_model_get_type ()), &g_implement_interface_info
); } { const GInterfaceInfo g_implement_interface_info = { (GInterfaceInitFunc
)(void (*)(void)) ctk_tree_model_filter_drag_source_init, ((void
*)0), ((void*)0) }; g_type_add_interface_static (g_define_type_id
, (ctk_tree_drag_source_get_type ()), &g_implement_interface_info
); };} } return g_define_type_id; }
501
502static void
503ctk_tree_model_filter_init (CtkTreeModelFilter *filter)
504{
505 filter->priv = ctk_tree_model_filter_get_instance_private (filter);
506 filter->priv->visible_column = -1;
507 filter->priv->zero_ref_count = 0;
508 filter->priv->visible_method_set = FALSE(0);
509 filter->priv->modify_func_set = FALSE(0);
510 filter->priv->in_row_deleted = FALSE(0);
511 filter->priv->virtual_root_deleted = FALSE(0);
512}
513
514static void
515ctk_tree_model_filter_class_init (CtkTreeModelFilterClass *filter_class)
516{
517 GObjectClass *object_class;
518
519 object_class = (GObjectClass *) filter_class;
520
521 object_class->set_property = ctk_tree_model_filter_set_property;
522 object_class->get_property = ctk_tree_model_filter_get_property;
523
524 object_class->finalize = ctk_tree_model_filter_finalize;
525
526 filter_class->visible = ctk_tree_model_filter_real_visible;
527 filter_class->modify = ctk_tree_model_filter_real_modify;
528
529 g_object_class_install_property (object_class,
530 PROP_CHILD_MODEL,
531 g_param_spec_object ("child-model",
532 P_("The child model")g_dgettext("ctk30" "-properties","The child model"),
533 P_("The model for the filtermodel to filter")g_dgettext("ctk30" "-properties","The model for the filtermodel to filter"
)
,
534 CTK_TYPE_TREE_MODEL(ctk_tree_model_get_type ()),
535 CTK_PARAM_READWRITEG_PARAM_READWRITE|G_PARAM_STATIC_NAME|G_PARAM_STATIC_NICK|G_PARAM_STATIC_BLURB | G_PARAM_CONSTRUCT_ONLY));
536
537 g_object_class_install_property (object_class,
538 PROP_VIRTUAL_ROOT,
539 g_param_spec_boxed ("virtual-root",
540 P_("The virtual root")g_dgettext("ctk30" "-properties","The virtual root"),
541 P_("The virtual root (relative to the child model) for this filtermodel")g_dgettext("ctk30" "-properties","The virtual root (relative to the child model) for this filtermodel"
)
,
542 CTK_TYPE_TREE_PATH(ctk_tree_path_get_type ()),
543 CTK_PARAM_READWRITEG_PARAM_READWRITE|G_PARAM_STATIC_NAME|G_PARAM_STATIC_NICK|G_PARAM_STATIC_BLURB | G_PARAM_CONSTRUCT_ONLY));
544}
545
546static void
547ctk_tree_model_filter_tree_model_init (CtkTreeModelIface *iface)
548{
549 iface->get_flags = ctk_tree_model_filter_get_flags;
550 iface->get_n_columns = ctk_tree_model_filter_get_n_columns;
551 iface->get_column_type = ctk_tree_model_filter_get_column_type;
552 iface->get_iter = ctk_tree_model_filter_get_iter;
553 iface->get_path = ctk_tree_model_filter_get_path;
554 iface->get_value = ctk_tree_model_filter_get_value;
555 iface->iter_next = ctk_tree_model_filter_iter_next;
556 iface->iter_previous = ctk_tree_model_filter_iter_previous;
557 iface->iter_children = ctk_tree_model_filter_iter_children;
558 iface->iter_has_child = ctk_tree_model_filter_iter_has_child;
559 iface->iter_n_children = ctk_tree_model_filter_iter_n_children;
560 iface->iter_nth_child = ctk_tree_model_filter_iter_nth_child;
561 iface->iter_parent = ctk_tree_model_filter_iter_parent;
562 iface->ref_node = ctk_tree_model_filter_ref_node;
563 iface->unref_node = ctk_tree_model_filter_unref_node;
564}
565
566static void
567ctk_tree_model_filter_drag_source_init (CtkTreeDragSourceIface *iface)
568{
569 iface->row_draggable = ctk_tree_model_filter_row_draggable;
570 iface->drag_data_delete = ctk_tree_model_filter_drag_data_delete;
571 iface->drag_data_get = ctk_tree_model_filter_drag_data_get;
572}
573
574
575static void
576ctk_tree_model_filter_finalize (GObject *object)
577{
578 CtkTreeModelFilter *filter = (CtkTreeModelFilter *) object;
579
580 if (filter->priv->virtual_root && !filter->priv->virtual_root_deleted)
581 {
582 ctk_tree_model_filter_unref_path (filter, filter->priv->virtual_root,
583 -1);
584 filter->priv->virtual_root_deleted = TRUE(!(0));
585 }
586
587 ctk_tree_model_filter_set_model (filter, NULL((void*)0));
588
589 if (filter->priv->virtual_root)
590 ctk_tree_path_free (filter->priv->virtual_root);
591
592 if (filter->priv->root)
593 ctk_tree_model_filter_free_level (filter, filter->priv->root, TRUE(!(0)), TRUE(!(0)), FALSE(0));
594
595 g_free (filter->priv->modify_types);
596
597 if (filter->priv->modify_destroy)
598 filter->priv->modify_destroy (filter->priv->modify_data);
599
600 if (filter->priv->visible_destroy)
601 filter->priv->visible_destroy (filter->priv->visible_data);
602
603 /* must chain up */
604 G_OBJECT_CLASS (ctk_tree_model_filter_parent_class)((((GObjectClass*) (void *) g_type_check_class_cast ((GTypeClass
*) ((ctk_tree_model_filter_parent_class)), (((GType) ((20) <<
(2))))))))
->finalize (object);
605}
606
607static void
608ctk_tree_model_filter_set_property (GObject *object,
609 guint prop_id,
610 const GValue *value,
611 GParamSpec *pspec)
612{
613 CtkTreeModelFilter *filter = CTK_TREE_MODEL_FILTER (object)((((CtkTreeModelFilter*) (void *) g_type_check_instance_cast (
(GTypeInstance*) ((object)), ((ctk_tree_model_filter_get_type
()))))))
;
614
615 switch (prop_id)
616 {
617 case PROP_CHILD_MODEL:
618 ctk_tree_model_filter_set_model (filter, g_value_get_object (value));
619 break;
620 case PROP_VIRTUAL_ROOT:
621 ctk_tree_model_filter_set_root (filter, g_value_get_boxed (value));
622 break;
623 default:
624 G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec)do { GObject *_glib__object = (GObject*) ((object)); GParamSpec
*_glib__pspec = (GParamSpec*) ((pspec)); guint _glib__property_id
= ((prop_id)); g_warning ("%s:%d: invalid %s id %u for \"%s\" of type '%s' in '%s'"
, "ctktreemodelfilter.c", 624, ("property"), _glib__property_id
, _glib__pspec->name, g_type_name ((((((GTypeClass*) (((GTypeInstance
*) (_glib__pspec))->g_class))->g_type)))), (g_type_name
((((((GTypeClass*) (((GTypeInstance*) (_glib__object))->g_class
))->g_type)))))); } while (0)
;
625 break;
626 }
627}
628
629static void
630ctk_tree_model_filter_get_property (GObject *object,
631 guint prop_id,
632 GValue *value,
633 GParamSpec *pspec)
634{
635 CtkTreeModelFilter *filter = CTK_TREE_MODEL_FILTER (object)((((CtkTreeModelFilter*) (void *) g_type_check_instance_cast (
(GTypeInstance*) ((object)), ((ctk_tree_model_filter_get_type
()))))))
;
636
637 switch (prop_id)
638 {
639 case PROP_CHILD_MODEL:
640 g_value_set_object (value, filter->priv->child_model);
641 break;
642 case PROP_VIRTUAL_ROOT:
643 g_value_set_boxed (value, filter->priv->virtual_root);
644 break;
645 default:
646 G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec)do { GObject *_glib__object = (GObject*) ((object)); GParamSpec
*_glib__pspec = (GParamSpec*) ((pspec)); guint _glib__property_id
= ((prop_id)); g_warning ("%s:%d: invalid %s id %u for \"%s\" of type '%s' in '%s'"
, "ctktreemodelfilter.c", 646, ("property"), _glib__property_id
, _glib__pspec->name, g_type_name ((((((GTypeClass*) (((GTypeInstance
*) (_glib__pspec))->g_class))->g_type)))), (g_type_name
((((((GTypeClass*) (((GTypeInstance*) (_glib__object))->g_class
))->g_type)))))); } while (0)
;
647 break;
648 }
649}
650
651/* helpers */
652
653static FilterElt *
654filter_elt_new (void)
655{
656 return g_slice_new (FilterElt)((FilterElt*) g_slice_alloc (sizeof (FilterElt)));
657}
658
659static void
660filter_elt_free (gpointer elt)
661{
662 g_slice_free (FilterElt, elt)do { if (1) g_slice_free1 (sizeof (FilterElt), (elt)); else (
void) ((FilterElt*) 0 == (elt)); } while (0)
;
663}
664
665static gint
666filter_elt_cmp (gconstpointer a,
667 gconstpointer b,
668 gpointer user_data G_GNUC_UNUSED__attribute__ ((__unused__)))
669{
670 const FilterElt *elt_a = a;
671 const FilterElt *elt_b = b;
672
673 if (elt_a->offset > elt_b->offset)
674 return +1;
675 else if (elt_a->offset < elt_b->offset)
676 return -1;
677 else
678 return 0;
679}
680
681static FilterElt *
682lookup_elt_with_offset (GSequence *seq,
683 gint offset,
684 GSequenceIter **ret_siter)
685{
686 GSequenceIter *siter;
687 FilterElt dummy;
688
689 dummy.offset = offset;
690 siter = g_sequence_lookup (seq, &dummy, filter_elt_cmp, NULL((void*)0));
691
692 if (ret_siter)
693 *ret_siter = siter;
694
695 return GET_ELT (siter)((FilterElt*) (siter ? g_sequence_get (siter) : ((void*)0)));
696}
697
698static void
699increase_offset_iter (gpointer data,
700 gpointer user_data)
701{
702 FilterElt *elt = data;
703 gint offset = GPOINTER_TO_INT (user_data)((gint) (glong) (user_data));
704
705 if (elt->offset >= offset)
706 elt->offset++;
707}
708
709static void
710decrease_offset_iter (gpointer data,
711 gpointer user_data)
712{
713 FilterElt *elt = data;
714 gint offset = GPOINTER_TO_INT (user_data)((gint) (glong) (user_data));
715
716 if (elt->offset > offset)
717 elt->offset--;
718}
719
720static void
721ctk_tree_model_filter_build_level (CtkTreeModelFilter *filter,
722 FilterLevel *parent_level,
723 FilterElt *parent_elt,
724 gboolean emit_inserted)
725{
726 CtkTreeIter iter;
727 CtkTreeIter first_node;
728 CtkTreeIter root;
729 FilterLevel *new_level;
730 FilterLevel *tmp_level;
731 FilterElt *tmp_elt;
732 CtkTreeIter f_iter;
733 gint length = 0;
734 gint i;
735 gboolean empty = TRUE(!(0));
736
737 g_assert (filter->priv->child_model != NULL)do { if (filter->priv->child_model != ((void*)0)) ; else
g_assertion_message_expr ("Ctk", "ctktreemodelfilter.c", 737
, ((const char*) (__func__)), "filter->priv->child_model != NULL"
); } while (0)
;
738
739 /* Avoid building a level that already exists */
740 if (parent_level)
741 g_assert (parent_elt->children == NULL)do { if (parent_elt->children == ((void*)0)) ; else g_assertion_message_expr
("Ctk", "ctktreemodelfilter.c", 741, ((const char*) (__func__
)), "parent_elt->children == NULL"); } while (0)
;
742 else
743 g_assert (filter->priv->root == NULL)do { if (filter->priv->root == ((void*)0)) ; else g_assertion_message_expr
("Ctk", "ctktreemodelfilter.c", 743, ((const char*) (__func__
)), "filter->priv->root == NULL"); } while (0)
;
744
745 if (filter->priv->in_row_deleted)
746 return;
747
748 if (!parent_level)
749 {
750 if (filter->priv->virtual_root)
751 {
752 if (ctk_tree_model_get_iter (filter->priv->child_model, &root, filter->priv->virtual_root) == FALSE(0))
753 return;
754 length = ctk_tree_model_iter_n_children (filter->priv->child_model, &root);
755
756 if (ctk_tree_model_iter_children (filter->priv->child_model, &iter, &root) == FALSE(0))
757 return;
758 }
759 else
760 {
761 if (!ctk_tree_model_get_iter_first (filter->priv->child_model, &iter))
762 return;
763 length = ctk_tree_model_iter_n_children (filter->priv->child_model, NULL((void*)0));
764 }
765 }
766 else
767 {
768 CtkTreeIter parent_iter;
769 CtkTreeIter child_parent_iter;
770
771 parent_iter.stamp = filter->priv->stamp;
772 parent_iter.user_data = parent_level;
773 parent_iter.user_data2 = parent_elt;
774
775 ctk_tree_model_filter_convert_iter_to_child_iter (filter,
776 &child_parent_iter,
777 &parent_iter);
778 if (ctk_tree_model_iter_children (filter->priv->child_model, &iter, &child_parent_iter) == FALSE(0))
779 return;
780
781 /* stamp may have changed */
782 ctk_tree_model_filter_convert_iter_to_child_iter (filter,
783 &child_parent_iter,
784 &parent_iter);
785 length = ctk_tree_model_iter_n_children (filter->priv->child_model, &child_parent_iter);
786
787 /* Take a reference on the parent */
788 ctk_tree_model_filter_real_ref_node (CTK_TREE_MODEL (filter)((((CtkTreeModel*) (void *) g_type_check_instance_cast ((GTypeInstance
*) ((filter)), ((ctk_tree_model_get_type ()))))))
,
789 &parent_iter, FALSE(0));
790 }
791
792 g_return_if_fail (length > 0)do { if ((length > 0)) { } else { g_return_if_fail_warning
("Ctk", ((const char*) (__func__)), "length > 0"); return
; } } while (0)
;
793
794 new_level = g_new (FilterLevel, 1)((FilterLevel *) g_malloc_n ((1), sizeof (FilterLevel)));
795 new_level->seq = g_sequence_new (filter_elt_free);
796 new_level->visible_seq = g_sequence_new (NULL((void*)0));
797 new_level->ref_count = 0;
798 new_level->ext_ref_count = 0;
799 new_level->parent_elt = parent_elt;
800 new_level->parent_level = parent_level;
801
802 if (parent_elt)
803 parent_elt->children = new_level;
804 else
805 filter->priv->root = new_level;
806
807 /* increase the count of zero ref_counts */
808 tmp_level = parent_level;
809 tmp_elt = parent_elt;
810
811 while (tmp_level)
812 {
813 tmp_elt->zero_ref_count++;
814
815 tmp_elt = tmp_level->parent_elt;
816 tmp_level = tmp_level->parent_level;
817 }
818 if (new_level != filter->priv->root)
819 filter->priv->zero_ref_count++;
820
821 i = 0;
822
823 first_node = iter;
824
825 do
826 {
827 if (ctk_tree_model_filter_visible (filter, &iter))
828 {
829 FilterElt *filter_elt;
830
831 filter_elt = filter_elt_new ();
832 filter_elt->offset = i;
833 filter_elt->zero_ref_count = 0;
834 filter_elt->ref_count = 0;
835 filter_elt->ext_ref_count = 0;
836 filter_elt->children = NULL((void*)0);
837 filter_elt->visible_siter = NULL((void*)0);
838
839 if (CTK_TREE_MODEL_FILTER_CACHE_CHILD_ITERS (filter)(((CtkTreeModelFilter *)filter)->priv->child_flags &
CTK_TREE_MODEL_ITERS_PERSIST)
)
840 filter_elt->iter = iter;
841
842 g_sequence_append (new_level->seq, filter_elt);
843 filter_elt->visible_siter = g_sequence_append (new_level->visible_seq, filter_elt);
844 empty = FALSE(0);
845
846 if (emit_inserted)
847 {
848 CtkTreePath *f_path;
849 CtkTreeIter children;
850
851 f_iter.stamp = filter->priv->stamp;
852 f_iter.user_data = new_level;
853 f_iter.user_data2 = filter_elt;
854
855 f_path = ctk_tree_model_get_path (CTK_TREE_MODEL (filter)((((CtkTreeModel*) (void *) g_type_check_instance_cast ((GTypeInstance
*) ((filter)), ((ctk_tree_model_get_type ()))))))
,
856 &f_iter);
857 ctk_tree_model_row_inserted (CTK_TREE_MODEL (filter)((((CtkTreeModel*) (void *) g_type_check_instance_cast ((GTypeInstance
*) ((filter)), ((ctk_tree_model_get_type ()))))))
,
858 f_path, &f_iter);
859 ctk_tree_path_free (f_path);
860
861 if (ctk_tree_model_iter_children (filter->priv->child_model,
862 &children, &iter))
863 ctk_tree_model_filter_update_children (filter,
864 new_level,
865 FILTER_ELT (f_iter.user_data2)((FilterElt *)f_iter.user_data2));
866 }
867 }
868 i++;
869 }
870 while (ctk_tree_model_iter_next (filter->priv->child_model, &iter));
871
872 /* The level does not contain any visible nodes. However, changes in
873 * this level might affect the parent node, which can either be visible
874 * or invisible. Therefore, this level can only be removed again,
875 * if the parent level has an external reference count of zero. That is,
876 * if this level changes state, no signals are required in the parent
877 * level.
878 */
879 if (empty &&
880 (parent_level && parent_level->ext_ref_count == 0))
881 {
882 ctk_tree_model_filter_free_level (filter, new_level, FALSE(0), TRUE(!(0)), FALSE(0));
883 return;
884 }
885
886 /* If none of the nodes are visible, we will just pull in the
887 * first node of the level.
888 */
889 if (empty)
890 {
891 FilterElt *filter_elt;
892
893 filter_elt = filter_elt_new ();
894 filter_elt->offset = 0;
895 filter_elt->zero_ref_count = 0;
896 filter_elt->ref_count = 0;
897 filter_elt->ext_ref_count = 0;
898 filter_elt->children = NULL((void*)0);
899 filter_elt->visible_siter = NULL((void*)0);
900
901 if (CTK_TREE_MODEL_FILTER_CACHE_CHILD_ITERS (filter)(((CtkTreeModelFilter *)filter)->priv->child_flags &
CTK_TREE_MODEL_ITERS_PERSIST)
)
902 filter_elt->iter = first_node;
903
904 g_sequence_append (new_level->seq, filter_elt);
905 }
906
907 /* Keep a reference on the first node of this level. We need this
908 * to make sure that we get all signals for this level.
909 */
910 f_iter.stamp = filter->priv->stamp;
911 f_iter.user_data = new_level;
912 f_iter.user_data2 = g_sequence_get (g_sequence_get_begin_iter (new_level->seq));
913
914 ctk_tree_model_filter_real_ref_node (CTK_TREE_MODEL (filter)((((CtkTreeModel*) (void *) g_type_check_instance_cast ((GTypeInstance
*) ((filter)), ((ctk_tree_model_get_type ()))))))
, &f_iter, FALSE(0));
915}
916
917static void
918ctk_tree_model_filter_free_level (CtkTreeModelFilter *filter,
919 FilterLevel *filter_level,
920 gboolean unref_self,
921 gboolean unref_parent,
922 gboolean unref_external)
923{
924 GSequenceIter *siter;
925 GSequenceIter *end_siter;
926
927 g_assert (filter_level)do { if (filter_level) ; else g_assertion_message_expr ("Ctk"
, "ctktreemodelfilter.c", 927, ((const char*) (__func__)), "filter_level"
); } while (0)
;
928
929 end_siter = g_sequence_get_end_iter (filter_level->seq);
930 for (siter = g_sequence_get_begin_iter (filter_level->seq);
931 siter != end_siter;
932 siter = g_sequence_iter_next (siter))
933 {
934 FilterElt *elt = g_sequence_get (siter);
935
936 if (elt->children)
937 {
938 /* If we recurse and unref_self == FALSE, then unref_parent
939 * must also be FALSE (otherwise a still unref a node in this
940 * level).
941 */
942 ctk_tree_model_filter_free_level (filter,
943 FILTER_LEVEL (elt->children)((FilterLevel *)elt->children),
944 unref_self,
945 unref_self == FALSE(0) ? FALSE(0) : unref_parent,
946 unref_external);
947 }
948
949 if (unref_external)
950 {
951 CtkTreeIter f_iter;
952
953 f_iter.stamp = filter->priv->stamp;
954 f_iter.user_data = filter_level;
955 f_iter.user_data2 = elt;
956
957 while (elt->ext_ref_count > 0)
958 ctk_tree_model_filter_real_unref_node (CTK_TREE_MODEL (filter)((((CtkTreeModel*) (void *) g_type_check_instance_cast ((GTypeInstance
*) ((filter)), ((ctk_tree_model_get_type ()))))))
,
959 &f_iter,
960 TRUE(!(0)), unref_self);
961 }
962 }
963
964 /* Release the reference on the first item.
965 */
966 if (unref_self)
967 {
968 CtkTreeIter f_iter;
969
970 f_iter.stamp = filter->priv->stamp;
971 f_iter.user_data = filter_level;
972 f_iter.user_data2 = g_sequence_get (g_sequence_get_begin_iter (filter_level->seq));
973
974 ctk_tree_model_filter_real_unref_node (CTK_TREE_MODEL (filter)((((CtkTreeModel*) (void *) g_type_check_instance_cast ((GTypeInstance
*) ((filter)), ((ctk_tree_model_get_type ()))))))
,
975 &f_iter, FALSE(0), TRUE(!(0)));
976 }
977
978 if (filter_level->ext_ref_count == 0)
979 {
980 FilterLevel *parent_level = filter_level->parent_level;
981 FilterElt *parent_elt = filter_level->parent_elt;
982
983 while (parent_level)
984 {
985 parent_elt->zero_ref_count--;
986
987 parent_elt = parent_level->parent_elt;
988 parent_level = parent_level->parent_level;
989 }
990
991 if (filter_level != filter->priv->root)
992 filter->priv->zero_ref_count--;
993 }
994
995#ifdef MODEL_FILTER_DEBUG
996 if (filter_level == filter->priv->root)
997 g_assert (filter->priv->zero_ref_count == 0)do { if (filter->priv->zero_ref_count == 0) ; else g_assertion_message_expr
("Ctk", "ctktreemodelfilter.c", 997, ((const char*) (__func__
)), "filter->priv->zero_ref_count == 0"); } while (0)
;
998#endif
999
1000 if (filter_level->parent_elt)
1001 {
1002 /* Release reference on parent */
1003 CtkTreeIter parent_iter;
1004
1005 parent_iter.stamp = filter->priv->stamp;
1006 parent_iter.user_data = filter_level->parent_level;
1007 parent_iter.user_data2 = filter_level->parent_elt;
1008
1009 ctk_tree_model_filter_real_unref_node (CTK_TREE_MODEL (filter)((((CtkTreeModel*) (void *) g_type_check_instance_cast ((GTypeInstance
*) ((filter)), ((ctk_tree_model_get_type ()))))))
,
1010 &parent_iter, FALSE(0), unref_parent);
1011
1012 filter_level->parent_elt->children = NULL((void*)0);
1013 }
1014 else
1015 filter->priv->root = NULL((void*)0);
1016
1017 g_sequence_free (filter_level->seq);
1018 g_sequence_free (filter_level->visible_seq);
1019 g_free (filter_level);
1020}
1021
1022/* prune_level() is like free_level(), however instead of being fully
1023 * freed, the level is pruned to a level with only the first node used
1024 * for monitoring. For now it is only being called from
1025 * ctk_tree_model_filter_remove_elt_from_level(), which is the reason
1026 * this function is lacking a “gboolean unref” argument.
1027 */
1028static void
1029ctk_tree_model_filter_prune_level (CtkTreeModelFilter *filter,
1030 FilterLevel *level)
1031{
1032 GSequenceIter *siter;
1033 GSequenceIter *end_siter;
1034 FilterElt *elt;
1035 CtkTreeIter f_iter;
1036
1037 /* This function is called when the parent of level became invisible.
1038 * All external ref counts of the children need to be dropped.
1039 * All children except the first one can be removed.
1040 */
1041
1042 /* Any child levels can be freed */
1043 end_siter = g_sequence_get_end_iter (level->seq);
1044 for (siter = g_sequence_get_begin_iter (level->seq);
1045 siter != end_siter;
1046 siter = g_sequence_iter_next (siter))
1047 {
1048 elt = g_sequence_get (siter);
1049
1050 if (elt->children)
1051 ctk_tree_model_filter_free_level (filter,
1052 FILTER_LEVEL (elt->children)((FilterLevel *)elt->children),
1053 TRUE(!(0)), TRUE(!(0)), TRUE(!(0)));
1054 }
1055
1056 /* For the first item, only drop the external references */
1057 elt = g_sequence_get (g_sequence_get_begin_iter (level->seq));
1058
1059 f_iter.stamp = filter->priv->stamp;
1060 f_iter.user_data = level;
1061 f_iter.user_data2 = elt;
1062
1063 while (elt->ext_ref_count > 0)
1064 ctk_tree_model_filter_real_unref_node (CTK_TREE_MODEL (filter)((((CtkTreeModel*) (void *) g_type_check_instance_cast ((GTypeInstance
*) ((filter)), ((ctk_tree_model_get_type ()))))))
,
1065 &f_iter, TRUE(!(0)), TRUE(!(0)));
1066
1067 if (elt->visible_siter)
1068 {
1069 g_sequence_remove (elt->visible_siter);
1070 elt->visible_siter = NULL((void*)0);
1071 }
1072
1073 /* Remove the other elts */
1074 end_siter = g_sequence_get_end_iter (level->seq);
1075 siter = g_sequence_get_begin_iter (level->seq);
1076 siter = g_sequence_iter_next (siter);
1077 for (; siter != end_siter; siter = g_sequence_iter_next (siter))
1078 {
1079 elt = g_sequence_get (siter);
1080
1081 f_iter.stamp = filter->priv->stamp;
1082 f_iter.user_data = level;
1083 f_iter.user_data2 = elt;
1084
1085 while (elt->ext_ref_count > 0)
1086 ctk_tree_model_filter_real_unref_node (CTK_TREE_MODEL (filter)((((CtkTreeModel*) (void *) g_type_check_instance_cast ((GTypeInstance
*) ((filter)), ((ctk_tree_model_get_type ()))))))
,
1087 &f_iter, TRUE(!(0)), TRUE(!(0)));
1088 /* In this case, we do remove reference counts we've added ourselves,
1089 * since the node will be removed from the data structures.
1090 */
1091 while (elt->ref_count > 0)
1092 ctk_tree_model_filter_real_unref_node (CTK_TREE_MODEL (filter)((((CtkTreeModel*) (void *) g_type_check_instance_cast ((GTypeInstance
*) ((filter)), ((ctk_tree_model_get_type ()))))))
,
1093 &f_iter, FALSE(0), TRUE(!(0)));
1094
1095 if (elt->visible_siter)
1096 {
1097 g_sequence_remove (elt->visible_siter);
1098 elt->visible_siter = NULL((void*)0);
1099 }
1100 }
1101
1102 /* Remove [begin + 1, end] */
1103 siter = g_sequence_get_begin_iter (level->seq);
1104 siter = g_sequence_iter_next (siter);
1105
1106 g_sequence_remove_range (siter, end_siter);
1107
1108 /* The level must have reached an ext ref count of zero by now, though
1109 * we only assert on this in debugging mode.
1110 */
1111#ifdef MODEL_FILTER_DEBUG
1112 g_assert (level->ext_ref_count == 0)do { if (level->ext_ref_count == 0) ; else g_assertion_message_expr
("Ctk", "ctktreemodelfilter.c", 1112, ((const char*) (__func__
)), "level->ext_ref_count == 0"); } while (0)
;
1113#endif
1114}
1115
1116static void
1117ctk_tree_model_filter_level_transfer_first_ref (CtkTreeModelFilter *filter,
1118 FilterLevel *level,
1119 GSequenceIter *from_iter,
1120 GSequenceIter *to_iter)
1121{
1122 CtkTreeIter f_iter;
1123
1124 f_iter.stamp = filter->priv->stamp;
1125 f_iter.user_data = level;
1126 f_iter.user_data2 = g_sequence_get (to_iter);
1127
1128 ctk_tree_model_filter_real_ref_node (CTK_TREE_MODEL (filter)((((CtkTreeModel*) (void *) g_type_check_instance_cast ((GTypeInstance
*) ((filter)), ((ctk_tree_model_get_type ()))))))
,
1129 &f_iter, FALSE(0));
1130
1131 f_iter.stamp = filter->priv->stamp;
1132 f_iter.user_data = level;
1133 f_iter.user_data2 = g_sequence_get (from_iter);
1134
1135 ctk_tree_model_filter_real_unref_node (CTK_TREE_MODEL (filter)((((CtkTreeModel*) (void *) g_type_check_instance_cast ((GTypeInstance
*) ((filter)), ((ctk_tree_model_get_type ()))))))
,
1136 &f_iter, FALSE(0), TRUE(!(0)));
1137}
1138
1139static void
1140ctk_tree_model_filter_level_transfer_first_ref_with_index (CtkTreeModelFilter *filter,
1141 FilterLevel *level,
1142 gint from_index,
1143 gint to_index)
1144{
1145 ctk_tree_model_filter_level_transfer_first_ref (filter, level,
1146 g_sequence_get_iter_at_pos (level->seq, from_index),
1147 g_sequence_get_iter_at_pos (level->seq, to_index));
1148}
1149
1150/* Creates paths suitable for accessing the child model. */
1151static CtkTreePath *
1152ctk_tree_model_filter_elt_get_path (FilterLevel *level,
1153 FilterElt *elt,
1154 CtkTreePath *root)
1155{
1156 FilterLevel *walker = level;
1157 FilterElt *walker2 = elt;
1158 CtkTreePath *path;
1159
1160 g_return_val_if_fail (level != NULL, NULL)do { if ((level != ((void*)0))) { } else { g_return_if_fail_warning
("Ctk", ((const char*) (__func__)), "level != NULL"); return
(((void*)0)); } } while (0)
;
1161 g_return_val_if_fail (elt != NULL, NULL)do { if ((elt != ((void*)0))) { } else { g_return_if_fail_warning
("Ctk", ((const char*) (__func__)), "elt != NULL"); return (
((void*)0)); } } while (0)
;
1162
1163 path = ctk_tree_path_new ();
1164
1165 while (walker)
1166 {
1167 ctk_tree_path_prepend_index (path, walker2->offset);
1168
1169 walker2 = walker->parent_elt;
1170 walker = walker->parent_level;
1171 }
1172
1173 if (root)
1174 {
1175 CtkTreePath *real_path;
1176
1177 real_path = ctk_tree_model_filter_add_root (path, root);
1178 ctk_tree_path_free (path);
1179 return real_path;
1180 }
1181
1182 return path;
1183}
1184
1185static CtkTreePath *
1186ctk_tree_model_filter_add_root (CtkTreePath *src,
1187 CtkTreePath *root)
1188{
1189 CtkTreePath *retval;
1190 gint i;
1191
1192 retval = ctk_tree_path_copy (root);
1193
1194 for (i = 0; i < ctk_tree_path_get_depth (src); i++)
1195 ctk_tree_path_append_index (retval, ctk_tree_path_get_indices (src)[i]);
1196
1197 return retval;
1198}
1199
1200static CtkTreePath *
1201ctk_tree_model_filter_remove_root (CtkTreePath *src,
1202 CtkTreePath *root)
1203{
1204 CtkTreePath *retval;
1205 gint i;
1206 gint depth;
1207 gint *indices;
1208
1209 if (ctk_tree_path_get_depth (src) <= ctk_tree_path_get_depth (root))
26
Assuming the condition is false
27
Taking false branch
1210 return NULL((void*)0);
1211
1212 depth = ctk_tree_path_get_depth (src);
1213 indices = ctk_tree_path_get_indices (src);
1214
1215 for (i = 0; i < ctk_tree_path_get_depth (root); i++)
28
Assuming the condition is false
29
Loop condition is false. Execution continues on line 1219
1216 if (indices[i] != ctk_tree_path_get_indices (root)[i])
1217 return NULL((void*)0);
1218
1219 retval = ctk_tree_path_new ();
1220
1221 for (; i < depth; i++)
30
Assuming 'i' is >= 'depth'
31
Loop condition is false. Execution continues on line 1224
1222 ctk_tree_path_append_index (retval, indices[i]);
1223
1224 return retval;
32
Returning pointer (loaded from 'retval'), which participates in a condition later
1225}
1226
1227static void
1228ctk_tree_model_filter_increment_stamp (CtkTreeModelFilter *filter)
1229{
1230 do
1231 {
1232 filter->priv->stamp++;
1233 }
1234 while (filter->priv->stamp == 0);
1235
1236 ctk_tree_model_filter_clear_cache (filter);
1237}
1238
1239static gboolean
1240ctk_tree_model_filter_real_visible (CtkTreeModelFilter *filter,
1241 CtkTreeModel *child_model,
1242 CtkTreeIter *child_iter)
1243{
1244 if (filter->priv->visible_func)
1245 {
1246 return filter->priv->visible_func (child_model,
1247 child_iter,
1248 filter->priv->visible_data)
1249 ? TRUE(!(0)) : FALSE(0);
1250 }
1251 else if (filter->priv->visible_column >= 0)
1252 {
1253 GValue val = G_VALUE_INIT{ 0, { { 0 } } };
1254
1255 ctk_tree_model_get_value (child_model, child_iter,
1256 filter->priv->visible_column, &val);
1257
1258 if (g_value_get_boolean (&val))
1259 {
1260 g_value_unset (&val);
1261 return TRUE(!(0));
1262 }
1263
1264 g_value_unset (&val);
1265 return FALSE(0);
1266 }
1267
1268 /* no visible function set, so always visible */
1269 return TRUE(!(0));
1270}
1271
1272static gboolean
1273ctk_tree_model_filter_visible (CtkTreeModelFilter *self,
1274 CtkTreeIter *child_iter)
1275{
1276 return CTK_TREE_MODEL_FILTER_GET_CLASS (self)((((CtkTreeModelFilterClass*) (((GTypeInstance*) ((self)))->
g_class))))
->visible (self,
1277 self->priv->child_model, child_iter);
1278}
1279
1280static void
1281ctk_tree_model_filter_clear_cache_helper_iter (gpointer data,
1282 gpointer user_data)
1283{
1284 CtkTreeModelFilter *filter = user_data;
1285 FilterElt *elt = data;
1286
1287#ifdef MODEL_FILTER_DEBUG
1288 g_assert (elt->zero_ref_count >= 0)do { if (elt->zero_ref_count >= 0) ; else g_assertion_message_expr
("Ctk", "ctktreemodelfilter.c", 1288, ((const char*) (__func__
)), "elt->zero_ref_count >= 0"); } while (0)
;
1289#endif
1290
1291 if (elt->zero_ref_count > 0)
1292 ctk_tree_model_filter_clear_cache_helper (filter, elt->children);
1293}
1294
1295static void
1296ctk_tree_model_filter_clear_cache_helper (CtkTreeModelFilter *filter,
1297 FilterLevel *level)
1298{
1299 g_assert (level)do { if (level) ; else g_assertion_message_expr ("Ctk", "ctktreemodelfilter.c"
, 1299, ((const char*) (__func__)), "level"); } while (0)
;
1300
1301 g_sequence_foreach (level->seq, ctk_tree_model_filter_clear_cache_helper_iter, filter);
1302
1303 /* If the level's ext_ref_count is zero, it means the level is not visible
1304 * and can be removed. But, since we support monitoring a child level
1305 * of a parent for changes (these might affect the parent), we will only
1306 * free the level if the parent level also has an external ref
1307 * count of zero. In that case, changes concerning our parent are
1308 * not requested.
1309 *
1310 * The root level is always visible, so an exception holds for levels
1311 * with the root level as parent level: these have to remain cached.
1312 */
1313 if (level->ext_ref_count == 0 && level != filter->priv->root &&
1314 level->parent_level && level->parent_level != filter->priv->root &&
1315 level->parent_level->ext_ref_count == 0)
1316 {
1317 ctk_tree_model_filter_free_level (filter, level, TRUE(!(0)), TRUE(!(0)), FALSE(0));
1318 return;
1319 }
1320}
1321
1322static gboolean
1323ctk_tree_model_filter_elt_is_visible_in_target (FilterLevel *level,
1324 FilterElt *elt)
1325{
1326 if (!elt->visible_siter)
1327 return FALSE(0);
1328
1329 if (!level->parent_elt)
1330 return TRUE(!(0));
1331
1332 do
1333 {
1334 elt = level->parent_elt;
1335 level = level->parent_level;
1336
1337 if (elt && !elt->visible_siter)
1338 return FALSE(0);
1339 }
1340 while (level);
1341
1342 return TRUE(!(0));
1343}
1344
1345/* If a change has occurred in path (inserted, changed or deleted),
1346 * then this function is used to check all its ancestors. An ancestor
1347 * could have changed state as a result and this needs to be propagated
1348 * to the objects monitoring the filter model.
1349 */
1350static void
1351ctk_tree_model_filter_check_ancestors (CtkTreeModelFilter *filter,
1352 CtkTreePath *path)
1353{
1354 int i = 0;
1355 int *indices = ctk_tree_path_get_indices (path);
1356 FilterElt *elt;
1357 FilterLevel *level;
1358 CtkTreeIter c_iter, tmp_iter, *root_iter;
1359
1360 level = FILTER_LEVEL (filter->priv->root)((FilterLevel *)filter->priv->root);
1361
1362 if (!level)
1363 return;
1364
1365 root_iter = NULL((void*)0);
1366 if (filter->priv->virtual_root &&
1367 ctk_tree_model_get_iter (filter->priv->child_model, &tmp_iter,
1368 filter->priv->virtual_root))
1369 root_iter = &tmp_iter;
1370 ctk_tree_model_iter_nth_child (filter->priv->child_model, &c_iter,
1371 root_iter,
1372 indices[i]);
1373
1374 while (i < ctk_tree_path_get_depth (path) - 1)
1375 {
1376 gboolean requested_state;
1377
1378 elt = lookup_elt_with_offset (level->seq,
1379 ctk_tree_path_get_indices (path)[i], NULL((void*)0));
1380
1381 requested_state = ctk_tree_model_filter_visible (filter, &c_iter);
1382
1383 if (!elt)
1384 {
1385 int index;
1386 CtkTreePath *c_path;
1387
1388 if (requested_state == FALSE(0))
1389 return;
1390
1391 /* The elt does not exist in this level (so it is not
1392 * visible), but should now be visible. We emit the
1393 * row-inserted and row-has-child-toggled signals.
1394 */
1395 elt = ctk_tree_model_filter_insert_elt_in_level (filter,
1396 &c_iter,
1397 level,
1398 indices[i],
1399 &index);
1400
1401 /* insert_elt_in_level defaults to FALSE */
1402 elt->visible_siter = g_sequence_insert_sorted (level->visible_seq,
1403 elt,
1404 filter_elt_cmp, NULL((void*)0));
1405
1406 c_path = ctk_tree_model_get_path (filter->priv->child_model,
1407 &c_iter);
1408
1409 ctk_tree_model_filter_emit_row_inserted_for_path (filter,
1410 filter->priv->child_model,
1411 c_path,
1412 &c_iter);
1413
1414 ctk_tree_path_free (c_path);
1415
1416 /* We can immediately return, because this node was not visible
1417 * before and its children will be checked for in response to
1418 * the emitted row-has-child-toggled signal.
1419 */
1420 return;
1421 }
1422 else if (elt->visible_siter)
1423 {
1424 if (!requested_state)
1425 {
1426 /* A node has turned invisible. Remove it from the level
1427 * and emit row-deleted. Since this node is being
1428 * deleted. it makes no sense to look further up the
1429 * chain.
1430 */
1431 ctk_tree_model_filter_remove_elt_from_level (filter,
1432 level, elt);
1433 return;
1434 }
1435
1436 /* Otherwise continue up the chain */
1437 }
1438 else if (!elt->visible_siter)
1439 {
1440 if (requested_state)
1441 {
1442 /* A node is already in the cache, but invisible. This
1443 * is usually a node on which a reference is kept by
1444 * the filter model, or a node fetched on the filter's
1445 * request, and thus not shown. Therefore, we will
1446 * not emit row-inserted for this node. Instead,
1447 * we signal to its parent that a change has occurred.
1448 *
1449 * Exception: root level, in this case, we must emit
1450 * row-inserted.
1451 */
1452 if (level->parent_level)
1453 {
1454 CtkTreeIter f_iter;
1455 CtkTreePath *f_path;
1456
1457 elt->visible_siter = g_sequence_insert_sorted (level->visible_seq, elt,
1458 filter_elt_cmp, NULL((void*)0));
1459
1460 f_iter.stamp = filter->priv->stamp;
1461 f_iter.user_data = level->parent_level;
1462 f_iter.user_data2 = level->parent_elt;
1463
1464 f_path = ctk_tree_model_get_path (CTK_TREE_MODEL (filter)((((CtkTreeModel*) (void *) g_type_check_instance_cast ((GTypeInstance
*) ((filter)), ((ctk_tree_model_get_type ()))))))
,
1465 &f_iter);
1466 ctk_tree_model_row_has_child_toggled (CTK_TREE_MODEL (filter)((((CtkTreeModel*) (void *) g_type_check_instance_cast ((GTypeInstance
*) ((filter)), ((ctk_tree_model_get_type ()))))))
,
1467 f_path, &f_iter);
1468 ctk_tree_path_free (f_path);
1469 }
1470 else
1471 {
1472 CtkTreePath *c_path;
1473
1474 elt->visible_siter = g_sequence_insert_sorted (level->visible_seq, elt,
1475 filter_elt_cmp, NULL((void*)0));
1476
1477 c_path = ctk_tree_model_get_path (filter->priv->child_model,
1478 &c_iter);
1479
1480 ctk_tree_model_filter_emit_row_inserted_for_path (filter,
1481 filter->priv->child_model,
1482 c_path,
1483 &c_iter);
1484
1485 ctk_tree_path_free (c_path);
1486 }
1487
1488 /* We can immediately return, because this node was not visible
1489 * before and the parent will check its children, including
1490 * this node, in response to the emitted row-has-child-toggled
1491 * signal.
1492 */
1493 return;
1494 }
1495
1496 /* Not visible, so no need to continue. */
1497 return;
1498 }
1499
1500 if (!elt->children)
1501 {
1502 /* If an elt does not have children, these are not visible.
1503 * Therefore, any signals emitted for these children will
1504 * be ignored, so we do not have to emit them.
1505 */
1506 return;
1507 }
1508
1509 level = elt->children;
1510 i++;
1511
1512 tmp_iter = c_iter;
1513 ctk_tree_model_iter_nth_child (filter->priv->child_model, &c_iter,
1514 &tmp_iter, indices[i]);
1515 }
1516}
1517
1518static FilterElt *
1519ctk_tree_model_filter_insert_elt_in_level (CtkTreeModelFilter *filter,
1520 CtkTreeIter *c_iter,
1521 FilterLevel *level,
1522 gint offset,
1523 gint *index)
1524{
1525 FilterElt *elt;
1526 GSequenceIter *siter;
1527
1528 elt = filter_elt_new ();
1529
1530 if (CTK_TREE_MODEL_FILTER_CACHE_CHILD_ITERS (filter)(((CtkTreeModelFilter *)filter)->priv->child_flags &
CTK_TREE_MODEL_ITERS_PERSIST)
)
1531 elt->iter = *c_iter;
1532
1533 elt->offset = offset;
1534 elt->zero_ref_count = 0;
1535 elt->ref_count = 0;
1536 elt->ext_ref_count = 0;
1537 elt->children = NULL((void*)0);
1538
1539 /* Because we don't emit row_inserted, the node is invisible and thus
1540 * not inserted in visible_seq
1541 */
1542 elt->visible_siter = NULL((void*)0);
1543
1544 siter = g_sequence_insert_sorted (level->seq, elt, filter_elt_cmp, NULL((void*)0));
1545 *index = g_sequence_iter_get_position (siter);
1546
1547 /* If the insert location is zero, we need to move our reference
1548 * on the old first node to the new first node.
1549 */
1550 if (*index == 0)
1551 ctk_tree_model_filter_level_transfer_first_ref_with_index (filter, level,
1552 1, 0);
1553
1554 return elt;
1555}
1556
1557static FilterElt *
1558ctk_tree_model_filter_fetch_child (CtkTreeModelFilter *filter,
1559 FilterLevel *level,
1560 gint offset,
1561 gint *index)
1562{
1563 gint len;
1564 CtkTreePath *c_path = NULL((void*)0);
1565 CtkTreeIter c_iter;
1566 CtkTreePath *c_parent_path = NULL((void*)0);
1567 CtkTreeIter c_parent_iter;
1568
1569 /* check if child exists and is visible */
1570 if (level->parent_elt)
1571 {
1572 c_parent_path =
1573 ctk_tree_model_filter_elt_get_path (level->parent_level,
1574 level->parent_elt,
1575 filter->priv->virtual_root);
1576 if (!c_parent_path)
1577 return NULL((void*)0);
1578 }
1579 else
1580 {
1581 if (filter->priv->virtual_root)
1582 c_parent_path = ctk_tree_path_copy (filter->priv->virtual_root);
1583 else
1584 c_parent_path = NULL((void*)0);
1585 }
1586
1587 if (c_parent_path)
1588 {
1589 ctk_tree_model_get_iter (filter->priv->child_model,
1590 &c_parent_iter,
1591 c_parent_path);
1592 len = ctk_tree_model_iter_n_children (filter->priv->child_model,
1593 &c_parent_iter);
1594
1595 c_path = ctk_tree_path_copy (c_parent_path);
1596 ctk_tree_path_free (c_parent_path);
1597 }
1598 else
1599 {
1600 len = ctk_tree_model_iter_n_children (filter->priv->child_model, NULL((void*)0));
1601 c_path = ctk_tree_path_new ();
1602 }
1603
1604 ctk_tree_path_append_index (c_path, offset);
1605 ctk_tree_model_get_iter (filter->priv->child_model, &c_iter, c_path);
1606 ctk_tree_path_free (c_path);
1607
1608 if (offset >= len || !ctk_tree_model_filter_visible (filter, &c_iter))
1609 return NULL((void*)0);
1610
1611 return ctk_tree_model_filter_insert_elt_in_level (filter, &c_iter,
1612 level, offset,
1613 index);
1614}
1615
1616/* Note that this function is never called from the row-deleted handler.
1617 * This means that this function is only used for removing elements
1618 * which are still present in the child model. As a result, we must
1619 * take care to properly release the references the filter model has
1620 * on the child model nodes.
1621 */
1622static void
1623ctk_tree_model_filter_remove_elt_from_level (CtkTreeModelFilter *filter,
1624 FilterLevel *level,
1625 FilterElt *elt)
1626{
1627 FilterElt *parent;
1628 FilterLevel *parent_level;
1629 gint length, orig_level_ext_ref_count;
1630 CtkTreeIter iter;
1631 CtkTreePath *path = NULL((void*)0);
1632
1633 gboolean emit_child_toggled = FALSE(0);
1634
1635 /* We need to know about the level's ext ref count before removal
1636 * of this node.
1637 */
1638 orig_level_ext_ref_count = level->ext_ref_count;
1639
1640 iter.stamp = filter->priv->stamp;
1641 iter.user_data = level;
1642 iter.user_data2 = elt;
1643
1644 parent = level->parent_elt;
1645 parent_level = level->parent_level;
1646
1647 if (!parent || orig_level_ext_ref_count > 0)
1648 path = ctk_tree_model_get_path (CTK_TREE_MODEL (filter)((((CtkTreeModel*) (void *) g_type_check_instance_cast ((GTypeInstance
*) ((filter)), ((ctk_tree_model_get_type ()))))))
, &iter);
1649 else
1650 /* If the level is not visible, the parent is potentially invisible
1651 * too. Either way, as no signal will be emitted, there is no use
1652 * for a path.
1653 */
1654 path = NULL((void*)0);
1655
1656 length = g_sequence_get_length (level->seq);
1657
1658 /* first register the node to be invisible */
1659 g_sequence_remove (elt->visible_siter);
1660 elt->visible_siter = NULL((void*)0);
1661
1662 /*
1663 * If level != root level and the number of visible nodes is 0 (ie. this
1664 * is the last node to be removed from the level), emit
1665 * row-has-child-toggled.
1666 */
1667
1668 if (level != filter->priv->root
1669 && g_sequence_get_length (level->visible_seq) == 0
1670 && parent
1671 && parent->visible_siter)
1672 emit_child_toggled = TRUE(!(0));
1673
1674 /* Distinguish:
1675 * - length > 1: in this case, the node is removed from the level
1676 * and row-deleted is emitted.
1677 * - length == 1: in this case, we need to decide whether to keep
1678 * the level or to free it.
1679 */
1680 if (length > 1)
1681 {
1682 GSequenceIter *siter;
1683
1684 /* We emit row-deleted, and remove the node from the cache.
1685 * If it has any children, these will be removed here as well.
1686 */
1687
1688 /* FIXME: I am not 100% sure it is always save to fully free the
1689 * level here. Perhaps the state of the parent level, etc. has to
1690 * be checked to make the right decision, like is done below for
1691 * the case length == 1.
1692 */
1693 if (elt->children)
1694 ctk_tree_model_filter_free_level (filter, elt->children, TRUE(!(0)), TRUE(!(0)), TRUE(!(0)));
1695
1696 /* If the first node is being removed, transfer, the reference */
1697 if (elt == g_sequence_get (g_sequence_get_begin_iter (level->seq)))
1698 {
1699 ctk_tree_model_filter_level_transfer_first_ref_with_index (filter, level,
1700 0, 1);
1701 }
1702
1703 while (elt->ext_ref_count > 0)
1704 ctk_tree_model_filter_real_unref_node (CTK_TREE_MODEL (filter)((((CtkTreeModel*) (void *) g_type_check_instance_cast ((GTypeInstance
*) ((filter)), ((ctk_tree_model_get_type ()))))))
,
1705 &iter, TRUE(!(0)), TRUE(!(0)));
1706 /* In this case, we do remove reference counts we've added ourselves,
1707 * since the node will be removed from the data structures.
1708 */
1709 while (elt->ref_count > 0)
1710 ctk_tree_model_filter_real_unref_node (CTK_TREE_MODEL (filter)((((CtkTreeModel*) (void *) g_type_check_instance_cast ((GTypeInstance
*) ((filter)), ((ctk_tree_model_get_type ()))))))
,
1711 &iter, FALSE(0), TRUE(!(0)));
1712
1713 /* remove the node */
1714 lookup_elt_with_offset (level->seq, elt->offset, &siter);
1715 g_sequence_remove (siter);
1716
1717 ctk_tree_model_filter_increment_stamp (filter);
1718
1719 /* Only if the node is in the root level (parent == NULL) or
1720 * the level is visible, a row-deleted signal is necessary.
1721 */
1722 if (!parent || orig_level_ext_ref_count > 0)
1723 ctk_tree_model_row_deleted (CTK_TREE_MODEL (filter)((((CtkTreeModel*) (void *) g_type_check_instance_cast ((GTypeInstance
*) ((filter)), ((ctk_tree_model_get_type ()))))))
, path);
1724 }
1725 else
1726 {
1727 /* There is only one node left in this level */
1728#ifdef MODEL_FILTER_DEBUG
1729 g_assert (length == 1)do { if (length == 1) ; else g_assertion_message_expr ("Ctk",
"ctktreemodelfilter.c", 1729, ((const char*) (__func__)), "length == 1"
); } while (0)
;
1730#endif
1731
1732 /* The row is signalled as deleted to the client. We have to
1733 * drop the remaining external reference count here, the client
1734 * will not do it.
1735 *
1736 * We keep the reference counts we've obtained ourselves.
1737 */
1738 while (elt->ext_ref_count > 0)
1739 ctk_tree_model_filter_real_unref_node (CTK_TREE_MODEL (filter)((((CtkTreeModel*) (void *) g_type_check_instance_cast ((GTypeInstance
*) ((filter)), ((ctk_tree_model_get_type ()))))))
,
1740 &iter, TRUE(!(0)), TRUE(!(0)));
1741
1742 /* This level is still required if:
1743 * - it is the root level
1744 * - its parent level is the root level
1745 * - its parent level has an external ref count > 0
1746 */
1747 if (! (level == filter->priv->root ||
1748 level->parent_level == filter->priv->root ||
1749 level->parent_level->ext_ref_count > 0))
1750 {
1751 /* Otherwise, the level can be removed */
1752 ctk_tree_model_filter_free_level (filter, level, TRUE(!(0)), TRUE(!(0)), TRUE(!(0)));
1753 }
1754 else
1755 {
1756 /* Level is kept, but we turn our attention to a child level.
1757 *
1758 * If level is not the root level, it is a child level with
1759 * an ext ref count that is now 0. That means that any child level
1760 * of elt can be removed.
1761 */
1762 if (level != filter->priv->root)
1763 {
1764#ifdef MODEL_FILTER_DEBUG
1765 g_assert (level->ext_ref_count == 0)do { if (level->ext_ref_count == 0) ; else g_assertion_message_expr
("Ctk", "ctktreemodelfilter.c", 1765, ((const char*) (__func__
)), "level->ext_ref_count == 0"); } while (0)
;
1766#endif
1767 if (elt->children)
1768 ctk_tree_model_filter_free_level (filter, elt->children,
1769 TRUE(!(0)), TRUE(!(0)), TRUE(!(0)));
1770 }
1771 else
1772 {
1773 /* In this case, we want to keep the level with the first
1774 * node pulled in to monitor for signals.
1775 */
1776 if (elt->children)
1777 ctk_tree_model_filter_prune_level (filter, elt->children);
1778 }
1779 }
1780
1781 if (!parent || orig_level_ext_ref_count > 0)
1782 ctk_tree_model_row_deleted (CTK_TREE_MODEL (filter)((((CtkTreeModel*) (void *) g_type_check_instance_cast ((GTypeInstance
*) ((filter)), ((ctk_tree_model_get_type ()))))))
, path);
1783 }
1784
1785 ctk_tree_path_free (path);
1786
1787 if (emit_child_toggled && parent->ext_ref_count > 0)
1788 {
1789 CtkTreeIter piter;
1790 CtkTreePath *ppath;
1791
1792 piter.stamp = filter->priv->stamp;
1793 piter.user_data = parent_level;
1794 piter.user_data2 = parent;
1795
1796 ppath = ctk_tree_model_get_path (CTK_TREE_MODEL (filter)((((CtkTreeModel*) (void *) g_type_check_instance_cast ((GTypeInstance
*) ((filter)), ((ctk_tree_model_get_type ()))))))
, &piter);
1797
1798 ctk_tree_model_row_has_child_toggled (CTK_TREE_MODEL (filter)((((CtkTreeModel*) (void *) g_type_check_instance_cast ((GTypeInstance
*) ((filter)), ((ctk_tree_model_get_type ()))))))
,
1799 ppath, &piter);
1800 ctk_tree_path_free (ppath);
1801 }
1802}
1803
1804/* This function is called after the given node has become visible.
1805 * When the node has children, we should build the level and
1806 * take a reference on the first child.
1807 */
1808static void
1809ctk_tree_model_filter_update_children (CtkTreeModelFilter *filter,
1810 FilterLevel *level,
1811 FilterElt *elt)
1812{
1813 CtkTreeIter c_iter;
1814 CtkTreeIter iter;
1815
1816 if (!elt->visible_siter)
1817 return;
1818
1819 iter.stamp = filter->priv->stamp;
1820 iter.user_data = level;
1821 iter.user_data2 = elt;
1822
1823 ctk_tree_model_filter_convert_iter_to_child_iter (filter, &c_iter, &iter);
1824
1825 if ((!level->parent_level || level->parent_level->ext_ref_count > 0) &&
1826 ctk_tree_model_iter_has_child (filter->priv->child_model, &c_iter))
1827 {
1828 if (!elt->children)
1829 ctk_tree_model_filter_build_level (filter, level, elt, FALSE(0));
1830
1831 if (elt->ext_ref_count > 0 && elt->children &&
1832 g_sequence_get_length (elt->children->seq))
1833 {
1834 CtkTreePath *path;
1835 path = ctk_tree_model_get_path (CTK_TREE_MODEL (filter)((((CtkTreeModel*) (void *) g_type_check_instance_cast ((GTypeInstance
*) ((filter)), ((ctk_tree_model_get_type ()))))))
, &iter);
1836 ctk_tree_model_row_has_child_toggled (CTK_TREE_MODEL (filter)((((CtkTreeModel*) (void *) g_type_check_instance_cast ((GTypeInstance
*) ((filter)), ((ctk_tree_model_get_type ()))))))
,
1837 path,
1838 &iter);
1839 if (path)
1840 ctk_tree_path_free (path);
1841 }
1842 }
1843}
1844
1845/* Path is relative to the child model (this is on search on elt offset)
1846 * but with the virtual root already removed if necesssary.
1847 */
1848static gboolean
1849find_elt_with_offset (CtkTreeModelFilter *filter,
1850 CtkTreePath *path,
1851 FilterLevel **level_,
1852 FilterElt **elt_)
1853{
1854 int i = 0;
1855 FilterLevel *level;
1856 FilterLevel *parent_level = NULL((void*)0);
1857 FilterElt *elt = NULL((void*)0);
1858
1859 level = FILTER_LEVEL (filter->priv->root)((FilterLevel *)filter->priv->root);
1860
1861 while (i < ctk_tree_path_get_depth (path))
1862 {
1863 if (!level)
1864 return FALSE(0);
1865
1866 elt = lookup_elt_with_offset (level->seq,
1867 ctk_tree_path_get_indices (path)[i],
1868 NULL((void*)0));
1869
1870 if (!elt)
1871 return FALSE(0);
1872
1873 parent_level = level;
1874 level = elt->children;
1875 i++;
1876 }
1877
1878 if (level_)
1879 *level_ = parent_level;
1880
1881 if (elt_)
1882 *elt_ = elt;
1883
1884 return TRUE(!(0));
1885}
1886
1887/* TreeModel signals */
1888static void
1889ctk_tree_model_filter_emit_row_inserted_for_path (CtkTreeModelFilter *filter,
1890 CtkTreeModel *c_model,
1891 CtkTreePath *c_path,
1892 CtkTreeIter *c_iter)
1893{
1894 FilterLevel *level;
1895 FilterElt *elt;
1896 CtkTreePath *path;
1897 CtkTreeIter iter, children;
1898 gboolean signals_emitted = FALSE(0);
1899
1900 if (!filter->priv->root)
1901 {
1902 /* The root level has not been exposed to the view yet, so we
1903 * need to emit signals for any node that is being inserted.
1904 */
1905 ctk_tree_model_filter_build_level (filter, NULL((void*)0), NULL((void*)0), TRUE(!(0)));
1906
1907 /* Check if the root level was built. Then child levels
1908 * that matter have also been built (due to update_children,
1909 * which triggers iter_n_children).
1910 */
1911 if (filter->priv->root &&
1912 g_sequence_get_length (FILTER_LEVEL (filter->priv->root)((FilterLevel *)filter->priv->root)->visible_seq) > 0)
1913 signals_emitted = TRUE(!(0));
1914 }
1915
1916 ctk_tree_model_filter_increment_stamp (filter);
1917
1918 /* We need to disallow to build new levels, because we are then pulling
1919 * in a child in an invisible level. We only want to find path if it
1920 * is in a visible level (and thus has a parent that is visible).
1921 */
1922 path = ctk_real_tree_model_filter_convert_child_path_to_path (filter,
1923 c_path,
1924 FALSE(0),
1925 TRUE(!(0)));
1926
1927 if (!path)
1928 /* parent is probably being filtered out */
1929 return;
1930
1931 ctk_tree_model_filter_get_iter_full (CTK_TREE_MODEL (filter)((((CtkTreeModel*) (void *) g_type_check_instance_cast ((GTypeInstance
*) ((filter)), ((ctk_tree_model_get_type ()))))))
, &iter, path);
1932
1933 level = FILTER_LEVEL (iter.user_data)((FilterLevel *)iter.user_data);
1934 elt = FILTER_ELT (iter.user_data2)((FilterElt *)iter.user_data2);
1935
1936 /* Make sure elt is visible. elt can already be visible in case
1937 * it was pulled in above, so avoid inserted it into visible_seq twice.
1938 */
1939 if (!elt->visible_siter)
1940 {
1941 elt->visible_siter = g_sequence_insert_sorted (level->visible_seq,
1942 elt, filter_elt_cmp,
1943 NULL((void*)0));
1944 }
1945
1946 /* Check whether the node and all of its parents are visible */
1947 if (ctk_tree_model_filter_elt_is_visible_in_target (level, elt))
1948 {
1949 /* visibility changed -- reget path */
1950 ctk_tree_path_free (path);
1951 path = ctk_tree_model_get_path (CTK_TREE_MODEL (filter)((((CtkTreeModel*) (void *) g_type_check_instance_cast ((GTypeInstance
*) ((filter)), ((ctk_tree_model_get_type ()))))))
, &iter);
1952
1953 if (!signals_emitted &&
1954 (!level->parent_level || level->ext_ref_count > 0))
1955 ctk_tree_model_row_inserted (CTK_TREE_MODEL (filter)((((CtkTreeModel*) (void *) g_type_check_instance_cast ((GTypeInstance
*) ((filter)), ((ctk_tree_model_get_type ()))))))
, path, &iter);
1956
1957 if (level->parent_level && level->parent_elt->ext_ref_count > 0 &&
1958 g_sequence_get_length (level->visible_seq) == 1)
1959 {
1960 /* We know that this is the first visible node in this level, so
1961 * we need to emit row-has-child-toggled on the parent. This
1962 * does not apply to the root level.
1963 */
1964
1965 ctk_tree_path_up (path);
1966 ctk_tree_model_get_iter (CTK_TREE_MODEL (filter)((((CtkTreeModel*) (void *) g_type_check_instance_cast ((GTypeInstance
*) ((filter)), ((ctk_tree_model_get_type ()))))))
, &iter, path);
1967
1968 ctk_tree_model_row_has_child_toggled (CTK_TREE_MODEL (filter)((((CtkTreeModel*) (void *) g_type_check_instance_cast ((GTypeInstance
*) ((filter)), ((ctk_tree_model_get_type ()))))))
,
1969 path,
1970 &iter);
1971 }
1972
1973 if (!signals_emitted
1974 && ctk_tree_model_iter_children (c_model, &children, c_iter))
1975 ctk_tree_model_filter_update_children (filter, level, elt);
1976 }
1977
1978 ctk_tree_path_free (path);
1979}
1980
1981static void
1982ctk_tree_model_filter_row_changed (CtkTreeModel *c_model,
1983 CtkTreePath *c_path,
1984 CtkTreeIter *c_iter,
1985 gpointer data)
1986{
1987 CtkTreeModelFilter *filter = CTK_TREE_MODEL_FILTER (data)((((CtkTreeModelFilter*) (void *) g_type_check_instance_cast (
(GTypeInstance*) ((data)), ((ctk_tree_model_filter_get_type (
)))))))
;
1988 CtkTreeIter iter;
1989 CtkTreeIter children;
1990 CtkTreeIter real_c_iter;
1991 CtkTreePath *path = NULL((void*)0);
1992 CtkTreePath *real_path = NULL((void*)0);
1993
1994 FilterElt *elt;
1995 FilterLevel *level;
1996
1997 gboolean requested_state;
1998 gboolean current_state;
1999 gboolean free_c_path = FALSE(0);
2000
2001 g_return_if_fail (c_path != NULL || c_iter != NULL)do { if ((c_path != ((void*)0) || c_iter != ((void*)0))) { } else
{ g_return_if_fail_warning ("Ctk", ((const char*) (__func__)
), "c_path != NULL || c_iter != NULL"); return; } } while (0)
;
2
Assuming 'c_path' is equal to null
3
Assuming 'c_iter' is not equal to null
4
Taking true branch
5
Loop condition is false. Exiting loop
2002
2003 if (!c_path
5.1
'c_path' is null
)
6
Taking true branch
2004 {
2005 c_path = ctk_tree_model_get_path (c_model, c_iter);
2006 free_c_path = TRUE(!(0));
2007 }
2008
2009 if (filter->priv->virtual_root)
7
Assuming pointer value is null
8
Assuming field 'virtual_root' is null
9
Taking false branch
2010 real_path = ctk_tree_model_filter_remove_root (c_path,
2011 filter->priv->virtual_root);
2012 else
2013 real_path = ctk_tree_path_copy (c_path);
2014
2015 if (c_iter
9.1
'c_iter' is non-null
)
10
Taking true branch
2016 real_c_iter = *c_iter;
2017 else
2018 ctk_tree_model_get_iter (c_model, &real_c_iter, c_path);
2019
2020 /* is this node above the virtual root? */
2021 if (filter->priv->virtual_root
10.1
Field 'virtual_root' is null
&&
2022 (ctk_tree_path_get_depth (filter->priv->virtual_root)
2023 >= ctk_tree_path_get_depth (c_path)))
2024 goto done;
2025
2026 /* what's the requested state? */
2027 requested_state = ctk_tree_model_filter_visible (filter, &real_c_iter);
2028
2029 /* now, let's see whether the item is there */
2030 path = ctk_real_tree_model_filter_convert_child_path_to_path (filter,
11
Calling 'ctk_real_tree_model_filter_convert_child_path_to_path'
40
Returning from 'ctk_real_tree_model_filter_convert_child_path_to_path'
2031 c_path,
2032 FALSE(0),
2033 FALSE(0));
2034
2035 if (path)
41
Assuming 'path' is non-null
42
Taking true branch
2036 {
2037 ctk_tree_model_filter_get_iter_full (CTK_TREE_MODEL (filter)((((CtkTreeModel*) (void *) g_type_check_instance_cast ((GTypeInstance
*) ((filter)), ((ctk_tree_model_get_type ()))))))
,
43
Calling 'ctk_tree_model_filter_get_iter_full'
58
Returning from 'ctk_tree_model_filter_get_iter_full'
2038 &iter, path);
2039 current_state = FILTER_ELT (iter.user_data2)((FilterElt *)iter.user_data2)->visible_siter != NULL((void*)0);
59
Access to field 'visible_siter' results in a dereference of an undefined pointer value (loaded from field 'user_data2')
2040 }
2041 else
2042 current_state = FALSE(0);
2043
2044 if (current_state == FALSE(0) && requested_state == FALSE(0))
2045 /* no changes required */
2046 goto done;
2047
2048 if (current_state == TRUE(!(0)) && requested_state == FALSE(0))
2049 {
2050 ctk_tree_model_filter_remove_elt_from_level (filter,
2051 FILTER_LEVEL (iter.user_data)((FilterLevel *)iter.user_data),
2052 FILTER_ELT (iter.user_data2)((FilterElt *)iter.user_data2));
2053
2054 if (real_path)
2055 ctk_tree_model_filter_check_ancestors (filter, real_path);
2056
2057 goto done;
2058 }
2059
2060 if (current_state == TRUE(!(0)) && requested_state == TRUE(!(0)))
2061 {
2062 level = FILTER_LEVEL (iter.user_data)((FilterLevel *)iter.user_data);
2063 elt = FILTER_ELT (iter.user_data2)((FilterElt *)iter.user_data2);
2064
2065 if (ctk_tree_model_filter_elt_is_visible_in_target (level, elt))
2066 {
2067 /* propagate the signal; also get a path taking only visible
2068 * nodes into account.
2069 */
2070 ctk_tree_path_free (path);
2071 path = ctk_tree_model_get_path (CTK_TREE_MODEL (filter)((((CtkTreeModel*) (void *) g_type_check_instance_cast ((GTypeInstance
*) ((filter)), ((ctk_tree_model_get_type ()))))))
, &iter);
2072
2073 if (level->ext_ref_count > 0)
2074 ctk_tree_model_row_changed (CTK_TREE_MODEL (filter)((((CtkTreeModel*) (void *) g_type_check_instance_cast ((GTypeInstance
*) ((filter)), ((ctk_tree_model_get_type ()))))))
, path, &iter);
2075
2076 /* and update the children */
2077 if (ctk_tree_model_iter_children (c_model, &children, &real_c_iter))
2078 ctk_tree_model_filter_update_children (filter, level, elt);
2079 }
2080
2081 if (real_path)
2082 ctk_tree_model_filter_check_ancestors (filter, real_path);
2083
2084 goto done;
2085 }
2086
2087 /* only current == FALSE and requested == TRUE is left,
2088 * pull in the child
2089 */
2090 g_return_if_fail (current_state == FALSE && requested_state == TRUE)do { if ((current_state == (0) && requested_state == (
!(0)))) { } else { g_return_if_fail_warning ("Ctk", ((const char
*) (__func__)), "current_state == FALSE && requested_state == TRUE"
); return; } } while (0)
;
2091
2092 if (real_path)
2093 ctk_tree_model_filter_check_ancestors (filter, real_path);
2094
2095 ctk_tree_model_filter_emit_row_inserted_for_path (filter, c_model,
2096 c_path, c_iter);
2097
2098done:
2099 if (path)
2100 ctk_tree_path_free (path);
2101
2102 if (real_path)
2103 ctk_tree_path_free (real_path);
2104
2105 if (free_c_path)
2106 ctk_tree_path_free (c_path);
2107}
2108
2109static void
2110ctk_tree_model_filter_row_inserted (CtkTreeModel *c_model,
2111 CtkTreePath *c_path,
2112 CtkTreeIter *c_iter,
2113 gpointer data)
2114{
2115 CtkTreeModelFilter *filter = CTK_TREE_MODEL_FILTER (data)((((CtkTreeModelFilter*) (void *) g_type_check_instance_cast (
(GTypeInstance*) ((data)), ((ctk_tree_model_filter_get_type (
)))))))
;
2116 CtkTreePath *real_path = NULL((void*)0);
2117
2118 CtkTreeIter real_c_iter;
2119
2120 FilterElt *elt = NULL((void*)0);
2121 FilterLevel *level = NULL((void*)0);
2122 FilterLevel *parent_level = NULL((void*)0);
2123 GSequenceIter *siter;
2124 FilterElt dummy;
2125
2126 gint i = 0, offset;
2127
2128 gboolean free_c_path = FALSE(0);
2129 gboolean emit_row_inserted = FALSE(0);
2130
2131 g_return_if_fail (c_path != NULL || c_iter != NULL)do { if ((c_path != ((void*)0) || c_iter != ((void*)0))) { } else
{ g_return_if_fail_warning ("Ctk", ((const char*) (__func__)
), "c_path != NULL || c_iter != NULL"); return; } } while (0)
;
2132
2133 if (!c_path)
2134 {
2135 c_path = ctk_tree_model_get_path (c_model, c_iter);
2136 free_c_path = TRUE(!(0));
2137 }
2138
2139 if (c_iter)
2140 real_c_iter = *c_iter;
2141 else
2142 ctk_tree_model_get_iter (c_model, &real_c_iter, c_path);
2143
2144 /* the row has already been inserted. so we need to fixup the
2145 * virtual root here first
2146 */
2147 if (filter->priv->virtual_root)
2148 {
2149 if (ctk_tree_path_get_depth (filter->priv->virtual_root) >=
2150 ctk_tree_path_get_depth (c_path))
2151 {
2152 gint depth;
2153 gint *v_indices, *c_indices;
2154 gboolean common_prefix = TRUE(!(0));
2155
2156 depth = ctk_tree_path_get_depth (c_path) - 1;
2157 v_indices = ctk_tree_path_get_indices (filter->priv->virtual_root);
2158 c_indices = ctk_tree_path_get_indices (c_path);
2159
2160 for (i = 0; i < depth; i++)
2161 if (v_indices[i] != c_indices[i])
2162 {
2163 common_prefix = FALSE(0);
2164 break;
2165 }
2166
2167 if (common_prefix && v_indices[depth] >= c_indices[depth])
2168 (v_indices[depth])++;
2169 }
2170 }
2171
2172 /* subtract virtual root if necessary */
2173 if (filter->priv->virtual_root)
2174 {
2175 real_path = ctk_tree_model_filter_remove_root (c_path,
2176 filter->priv->virtual_root);
2177 /* not our child */
2178 if (!real_path)
2179 goto done;
2180 }
2181 else
2182 real_path = ctk_tree_path_copy (c_path);
2183
2184 if (!filter->priv->root)
2185 {
2186 /* The root level has not been exposed to the view yet, so we
2187 * need to emit signals for any node that is being inserted.
2188 */
2189 ctk_tree_model_filter_build_level (filter, NULL((void*)0), NULL((void*)0), TRUE(!(0)));
2190
2191 /* Check if the root level was built. Then child levels
2192 * that matter have also been built (due to update_children,
2193 * which triggers iter_n_children).
2194 */
2195 if (filter->priv->root)
2196 {
2197 emit_row_inserted = FALSE(0);
2198 goto done;
2199 }
2200 }
2201
2202 if (ctk_tree_path_get_depth (real_path) - 1 >= 1)
2203 {
2204 gboolean found = FALSE(0);
2205 CtkTreePath *parent = ctk_tree_path_copy (real_path);
2206 ctk_tree_path_up (parent);
2207
2208 found = find_elt_with_offset (filter, parent, &parent_level, &elt);
2209
2210 ctk_tree_path_free (parent);
2211
2212 if (!found)
2213 /* Parent is not in the cache and probably being filtered out */
2214 goto done;
2215
2216 level = elt->children;
2217 }
2218 else
2219 level = FILTER_LEVEL (filter->priv->root)((FilterLevel *)filter->priv->root);
2220
2221 if (!level)
2222 {
2223 if (elt && elt->visible_siter)
2224 {
2225 /* The level in which the new node should be inserted does not
2226 * exist, but the parent, elt, does. If elt is visible, emit
2227 * row-has-child-toggled.
2228 */
2229 CtkTreePath *tmppath;
2230 CtkTreeIter tmpiter;
2231
2232 tmpiter.stamp = filter->priv->stamp;
2233 tmpiter.user_data = parent_level;
2234 tmpiter.user_data2 = elt;
2235
2236 tmppath = ctk_tree_model_get_path (CTK_TREE_MODEL (filter)((((CtkTreeModel*) (void *) g_type_check_instance_cast ((GTypeInstance
*) ((filter)), ((ctk_tree_model_get_type ()))))))
,
2237 &tmpiter);
2238
2239 if (tmppath)
2240 {
2241 ctk_tree_model_row_has_child_toggled (CTK_TREE_MODEL (filter)((((CtkTreeModel*) (void *) g_type_check_instance_cast ((GTypeInstance
*) ((filter)), ((ctk_tree_model_get_type ()))))))
,
2242 tmppath, &tmpiter);
2243 ctk_tree_path_free (tmppath);
2244 }
2245 }
2246 goto done;
2247 }
2248
2249 /* let's try to insert the value */
2250 offset = ctk_tree_path_get_indices (real_path)[ctk_tree_path_get_depth (real_path) - 1];
2251
2252 /* update the offsets, yes if we didn't insert the node above, there will
2253 * be a gap here. This will be filled with the node (via fetch_child) when
2254 * it becomes visible
2255 */
2256 dummy.offset = offset;
2257 siter = g_sequence_search (level->seq, &dummy, filter_elt_cmp, NULL((void*)0));
2258 siter = g_sequence_iter_prev (siter);
2259 g_sequence_foreach_range (siter, g_sequence_get_end_iter (level->seq),
2260 increase_offset_iter, GINT_TO_POINTER (offset)((gpointer) (glong) (offset)));
2261
2262 /* only insert when visible */
2263 if (ctk_tree_model_filter_visible (filter, &real_c_iter))
2264 {
2265 FilterElt *felt;
2266
2267 felt = ctk_tree_model_filter_insert_elt_in_level (filter,
2268 &real_c_iter,
2269 level, offset,
2270 &i);
2271
2272 /* insert_elt_in_level defaults to FALSE */
2273 felt->visible_siter = g_sequence_insert_sorted (level->visible_seq,
2274 felt,
2275 filter_elt_cmp, NULL((void*)0));
2276 emit_row_inserted = TRUE(!(0));
2277 }
2278
2279done:
2280 if (real_path)
2281 ctk_tree_model_filter_check_ancestors (filter, real_path);
2282
2283 if (emit_row_inserted)
2284 ctk_tree_model_filter_emit_row_inserted_for_path (filter, c_model,
2285 c_path, c_iter);
2286
2287 if (real_path)
2288 ctk_tree_path_free (real_path);
2289
2290 if (free_c_path)
2291 ctk_tree_path_free (c_path);
2292}
2293
2294static void
2295ctk_tree_model_filter_row_has_child_toggled (CtkTreeModel *c_model,
2296 CtkTreePath *c_path,
2297 CtkTreeIter *c_iter,
2298 gpointer data)
2299{
2300 CtkTreeModelFilter *filter = CTK_TREE_MODEL_FILTER (data)((((CtkTreeModelFilter*) (void *) g_type_check_instance_cast (
(GTypeInstance*) ((data)), ((ctk_tree_model_filter_get_type (
)))))))
;
2301 CtkTreePath *path;
2302 CtkTreeIter iter;
2303 FilterLevel *level;
2304 FilterElt *elt;
2305 gboolean requested_state;
2306
2307 g_return_if_fail (c_path != NULL && c_iter != NULL)do { if ((c_path != ((void*)0) && c_iter != ((void*)0
))) { } else { g_return_if_fail_warning ("Ctk", ((const char*
) (__func__)), "c_path != NULL && c_iter != NULL"); return
; } } while (0)
;
2308
2309 /* If we get row-has-child-toggled on the virtual root, and there is
2310 * no root level; try to build it now.
2311 */
2312 if (filter->priv->virtual_root && !filter->priv->root
2313 && !ctk_tree_path_compare (c_path, filter->priv->virtual_root))
2314 {
2315 ctk_tree_model_filter_build_level (filter, NULL((void*)0), NULL((void*)0), TRUE(!(0)));
2316 return;
2317 }
2318
2319 /* For all other levels, there is a chance that the visibility state
2320 * of the parent has changed now.
2321 */
2322
2323 path = ctk_real_tree_model_filter_convert_child_path_to_path (filter,
2324 c_path,
2325 FALSE(0),
2326 TRUE(!(0)));
2327 if (!path)
2328 return;
2329
2330 ctk_tree_model_filter_get_iter_full (CTK_TREE_MODEL (data)((((CtkTreeModel*) (void *) g_type_check_instance_cast ((GTypeInstance
*) ((data)), ((ctk_tree_model_get_type ()))))))
, &iter, path);
2331
2332 level = FILTER_LEVEL (iter.user_data)((FilterLevel *)iter.user_data);
2333 elt = FILTER_ELT (iter.user_data2)((FilterElt *)iter.user_data2);
2334
2335 ctk_tree_path_free (path);
2336
2337 requested_state = ctk_tree_model_filter_visible (filter, c_iter);
2338
2339 if (!elt->visible_siter && !requested_state)
2340 {
2341 /* The parent node currently is not visible and will not become
2342 * visible, so we will not pass on the row-has-child-toggled event.
2343 */
2344 return;
2345 }
2346 else if (elt->visible_siter && !requested_state)
2347 {
2348 /* The node is no longer visible, so it has to be removed.
2349 * _remove_elt_from_level() takes care of emitting row-has-child-toggled
2350 * when required.
2351 */
2352 ctk_tree_model_filter_remove_elt_from_level (filter, level, elt);
2353
2354 return;
2355 }
2356 else if (!elt->visible_siter && requested_state)
2357 {
2358 elt->visible_siter = g_sequence_insert_sorted (level->visible_seq,
2359 elt, filter_elt_cmp,
2360 NULL((void*)0));
2361
2362 /* Only insert if the parent is visible in the target */
2363 if (ctk_tree_model_filter_elt_is_visible_in_target (level, elt))
2364 {
2365 path = ctk_tree_model_get_path (CTK_TREE_MODEL (filter)((((CtkTreeModel*) (void *) g_type_check_instance_cast ((GTypeInstance
*) ((filter)), ((ctk_tree_model_get_type ()))))))
, &iter);
2366 ctk_tree_model_row_inserted (CTK_TREE_MODEL (filter)((((CtkTreeModel*) (void *) g_type_check_instance_cast ((GTypeInstance
*) ((filter)), ((ctk_tree_model_get_type ()))))))
, path, &iter);
2367 ctk_tree_path_free (path);
2368
2369 /* We do not update children now, because that will happen
2370 * below.
2371 */
2372 }
2373 }
2374 /* For the remaining possibility, elt->visible && requested_state
2375 * no action is required.
2376 */
2377
2378 /* If this node is referenced and has children, build the level so we
2379 * can monitor it for changes.
2380 */
2381 if (elt->ref_count > 1 && !elt->children &&
2382 ctk_tree_model_iter_has_child (c_model, c_iter))
2383 ctk_tree_model_filter_build_level (filter, level, elt, FALSE(0));
2384
2385 /* get a path taking only visible nodes into account */
2386 path = ctk_tree_model_get_path (CTK_TREE_MODEL (data)((((CtkTreeModel*) (void *) g_type_check_instance_cast ((GTypeInstance
*) ((data)), ((ctk_tree_model_get_type ()))))))
, &iter);
2387 ctk_tree_model_row_has_child_toggled (CTK_TREE_MODEL (data)((((CtkTreeModel*) (void *) g_type_check_instance_cast ((GTypeInstance
*) ((data)), ((ctk_tree_model_get_type ()))))))
, path, &iter);
2388 ctk_tree_path_free (path);
2389}
2390
2391static void
2392ctk_tree_model_filter_virtual_root_deleted (CtkTreeModelFilter *filter,
2393 CtkTreePath *c_path)
2394{
2395 gint i, nodes;
2396 CtkTreePath *path;
2397 FilterLevel *level = FILTER_LEVEL (filter->priv->root)((FilterLevel *)filter->priv->root);
2398
2399 /* The virtual root (or one of its ancestors) has been deleted. This
2400 * means that all content for our model is now gone. We deal with
2401 * this by removing everything in the filter model: we just iterate
2402 * over the root level and emit a row-deleted for each FilterElt.
2403 * (FIXME: Should we emit row-deleted for child nodes as well? This
2404 * has never been fully clear in TreeModel).
2405 */
2406
2407 /* We unref the path of the virtual root, up to and not including the
2408 * deleted node which can no longer be unreffed.
2409 */
2410 ctk_tree_model_filter_unref_path (filter, filter->priv->virtual_root,
2411 ctk_tree_path_get_depth (c_path) - 1);
2412 filter->priv->virtual_root_deleted = TRUE(!(0));
2413
2414 if (!level)
2415 return;
2416
2417 nodes = g_sequence_get_length (level->visible_seq);
2418
2419 /* We should not propagate the unref here. An unref for any of these
2420 * nodes will fail, since the respective nodes in the child model are
2421 * no longer there.
2422 */
2423 ctk_tree_model_filter_free_level (filter, filter->priv->root, FALSE(0), TRUE(!(0)), FALSE(0));
2424
2425 ctk_tree_model_filter_increment_stamp (filter);
2426
2427 path = ctk_tree_path_new ();
2428 ctk_tree_path_append_index (path, 0);
2429
2430 for (i = 0; i < nodes; i++)
2431 ctk_tree_model_row_deleted (CTK_TREE_MODEL (filter)((((CtkTreeModel*) (void *) g_type_check_instance_cast ((GTypeInstance
*) ((filter)), ((ctk_tree_model_get_type ()))))))
, path);
2432
2433 ctk_tree_path_free (path);
2434}
2435
2436static void
2437ctk_tree_model_filter_adjust_virtual_root (CtkTreeModelFilter *filter,
2438 CtkTreePath *c_path)
2439{
2440 gint i;
2441 gint level;
2442 gint *v_indices, *c_indices;
2443 gboolean common_prefix = TRUE(!(0));
2444
2445 level = ctk_tree_path_get_depth (c_path) - 1;
2446 v_indices = ctk_tree_path_get_indices (filter->priv->virtual_root);
2447 c_indices = ctk_tree_path_get_indices (c_path);
2448
2449 for (i = 0; i < level; i++)
2450 if (v_indices[i] != c_indices[i])
2451 {
2452 common_prefix = FALSE(0);
2453 break;
2454 }
2455
2456 if (common_prefix && v_indices[level] > c_indices[level])
2457 (v_indices[level])--;
2458}
2459
2460static void
2461ctk_tree_model_filter_row_deleted_invisible_node (CtkTreeModelFilter *filter,
2462 CtkTreePath *c_path)
2463{
2464 int offset;
2465 CtkTreePath *real_path;
2466 FilterLevel *level;
2467 FilterElt *elt;
2468 FilterElt dummy;
2469 GSequenceIter *siter;
2470
2471 /* The node deleted in the child model is not visible in the
2472 * filter model. We will not emit a signal, just fixup the offsets
2473 * of the other nodes.
2474 */
2475
2476 if (!filter->priv->root)
2477 return;
2478
2479 level = FILTER_LEVEL (filter->priv->root)((FilterLevel *)filter->priv->root);
2480
2481 /* subtract vroot if necessary */
2482 if (filter->priv->virtual_root)
2483 {
2484 real_path = ctk_tree_model_filter_remove_root (c_path,
2485 filter->priv->virtual_root);
2486 /* we don't handle this */
2487 if (!real_path)
2488 return;
2489 }
2490 else
2491 real_path = ctk_tree_path_copy (c_path);
2492
2493 if (ctk_tree_path_get_depth (real_path) - 1 >= 1)
2494 {
2495 gboolean found = FALSE(0);
2496 CtkTreePath *parent = ctk_tree_path_copy (real_path);
2497 ctk_tree_path_up (parent);
2498
2499 found = find_elt_with_offset (filter, parent, &level, &elt);
2500
2501 ctk_tree_path_free (parent);
2502
2503 if (!found)
2504 {
2505 /* parent is filtered out, so no level */
2506 ctk_tree_path_free (real_path);
2507 return;
2508 }
2509
2510 level = elt->children;
2511 }
2512
2513 offset = ctk_tree_path_get_indices (real_path)[ctk_tree_path_get_depth (real_path) - 1];
2514 ctk_tree_path_free (real_path);
2515
2516 if (!level)
2517 return;
2518
2519 /* decrease offset of all nodes following the deleted node */
2520 dummy.offset = offset;
2521 siter = g_sequence_search (level->seq, &dummy, filter_elt_cmp, NULL((void*)0));
2522 g_sequence_foreach_range (siter, g_sequence_get_end_iter (level->seq),
2523 decrease_offset_iter, GINT_TO_POINTER (offset)((gpointer) (glong) (offset)));
2524}
2525
2526static void
2527ctk_tree_model_filter_row_deleted (CtkTreeModel *c_model G_GNUC_UNUSED__attribute__ ((__unused__)),
2528 CtkTreePath *c_path,
2529 gpointer data)
2530{
2531 CtkTreeModelFilter *filter = CTK_TREE_MODEL_FILTER (data)((((CtkTreeModelFilter*) (void *) g_type_check_instance_cast (
(GTypeInstance*) ((data)), ((ctk_tree_model_filter_get_type (
)))))))
;
2532 CtkTreePath *path;
2533 CtkTreeIter iter;
2534 FilterElt *elt, *parent_elt = NULL((void*)0);
2535 FilterLevel *level, *parent_level = NULL((void*)0);
2536 GSequenceIter *siter;
2537 gboolean emit_child_toggled = FALSE(0);
2538 gboolean emit_row_deleted = FALSE(0);
2539 gint offset;
2540 gint orig_level_ext_ref_count;
2541
2542 g_return_if_fail (c_path != NULL)do { if ((c_path != ((void*)0))) { } else { g_return_if_fail_warning
("Ctk", ((const char*) (__func__)), "c_path != NULL"); return
; } } while (0)
;
2543
2544 /* special case the deletion of an ancestor of the virtual root */
2545 if (filter->priv->virtual_root &&
2546 (ctk_tree_path_is_ancestor (c_path, filter->priv->virtual_root) ||
2547 !ctk_tree_path_compare (c_path, filter->priv->virtual_root)))
2548 {
2549 ctk_tree_model_filter_virtual_root_deleted (filter, c_path);
2550 return;
2551 }
2552
2553 /* adjust the virtual root for the deleted row */
2554 if (filter->priv->virtual_root &&
2555 ctk_tree_path_get_depth (filter->priv->virtual_root) >=
2556 ctk_tree_path_get_depth (c_path))
2557 ctk_tree_model_filter_adjust_virtual_root (filter, c_path);
2558
2559 path = ctk_real_tree_model_filter_convert_child_path_to_path (filter,
2560 c_path,
2561 FALSE(0),
2562 FALSE(0));
2563
2564 if (!path)
2565 {
2566 ctk_tree_model_filter_row_deleted_invisible_node (filter, c_path);
2567 return;
2568 }
2569
2570 /* a node was deleted, which was in our cache */
2571 ctk_tree_model_filter_get_iter_full (CTK_TREE_MODEL (data)((((CtkTreeModel*) (void *) g_type_check_instance_cast ((GTypeInstance
*) ((data)), ((ctk_tree_model_get_type ()))))))
, &iter, path);
2572
2573 level = FILTER_LEVEL (iter.user_data)((FilterLevel *)iter.user_data);
2574 elt = FILTER_ELT (iter.user_data2)((FilterElt *)iter.user_data2);
2575 offset = elt->offset;
2576 orig_level_ext_ref_count = level->ext_ref_count;
2577
2578 if (elt->visible_siter)
2579 {
2580 /* get a path taking only visible nodes into account */
2581 ctk_tree_path_free (path);
2582 path = ctk_tree_model_get_path (CTK_TREE_MODEL (filter)((((CtkTreeModel*) (void *) g_type_check_instance_cast ((GTypeInstance
*) ((filter)), ((ctk_tree_model_get_type ()))))))
, &iter);
2583
2584 if (g_sequence_get_length (level->visible_seq) == 1)
2585 {
2586 emit_child_toggled = TRUE(!(0));
2587 parent_level = level->parent_level;
2588 parent_elt = level->parent_elt;
2589 }
2590
2591 emit_row_deleted = TRUE(!(0));
2592 }
2593
2594 /* Release the references on this node, without propagation because
2595 * the node does not exist anymore in the child model. The filter
2596 * model's references on the node in case of level->parent or use
2597 * of a virtual root are automatically destroyed by the child model.
2598 */
2599 while (elt->ext_ref_count > 0)
2600 ctk_tree_model_filter_real_unref_node (CTK_TREE_MODEL (data)((((CtkTreeModel*) (void *) g_type_check_instance_cast ((GTypeInstance
*) ((data)), ((ctk_tree_model_get_type ()))))))
, &iter,
2601 TRUE(!(0)), FALSE(0));
2602
2603 if (elt->children)
2604 /* If this last node has children, then the recursion in free_level
2605 * will release this reference.
2606 */
2607 while (elt->ref_count > 1)
2608 ctk_tree_model_filter_real_unref_node (CTK_TREE_MODEL (data)((((CtkTreeModel*) (void *) g_type_check_instance_cast ((GTypeInstance
*) ((data)), ((ctk_tree_model_get_type ()))))))
, &iter,
2609 FALSE(0), FALSE(0));
2610 else
2611 while (elt->ref_count > 0)
2612 ctk_tree_model_filter_real_unref_node (CTK_TREE_MODEL (data)((((CtkTreeModel*) (void *) g_type_check_instance_cast ((GTypeInstance
*) ((data)), ((ctk_tree_model_get_type ()))))))
, &iter,
2613 FALSE(0), FALSE(0));
2614
2615
2616 if (g_sequence_get_length (level->seq) == 1)
2617 {
2618 /* kill level */
2619 ctk_tree_model_filter_free_level (filter, level, FALSE(0), TRUE(!(0)), FALSE(0));
2620 }
2621 else
2622 {
2623 GSequenceIter *tmp;
2624 gboolean is_first;
2625
2626 lookup_elt_with_offset (level->seq, elt->offset, &siter);
2627 is_first = g_sequence_get_begin_iter (level->seq) == siter;
2628
2629 if (elt->children)
2630 ctk_tree_model_filter_free_level (filter, elt->children,
2631 FALSE(0), FALSE(0), FALSE(0));
2632
2633 /* remove the row */
2634 if (elt->visible_siter)
2635 g_sequence_remove (elt->visible_siter);
2636 tmp = g_sequence_iter_next (siter);
2637 g_sequence_remove (siter);
2638 g_sequence_foreach_range (tmp, g_sequence_get_end_iter (level->seq),
2639 decrease_offset_iter, GINT_TO_POINTER (offset)((gpointer) (glong) (offset)));
2640
2641 /* Take a reference on the new first node. The first node previously
2642 * keeping this reference has been removed above.
2643 */
2644 if (is_first)
2645 {
2646 CtkTreeIter f_iter;
2647
2648 f_iter.stamp = filter->priv->stamp;
2649 f_iter.user_data = level;
2650 f_iter.user_data2 = g_sequence_get (g_sequence_get_begin_iter (level->seq));
2651
2652 ctk_tree_model_filter_real_ref_node (CTK_TREE_MODEL (filter)((((CtkTreeModel*) (void *) g_type_check_instance_cast ((GTypeInstance
*) ((filter)), ((ctk_tree_model_get_type ()))))))
,
2653 &f_iter, FALSE(0));
2654 }
2655 }
2656
2657 if (emit_row_deleted)
2658 {
2659 /* emit row_deleted */
2660 ctk_tree_model_filter_increment_stamp (filter);
2661
2662 if (!parent_elt || orig_level_ext_ref_count > 0)
2663 ctk_tree_model_row_deleted (CTK_TREE_MODEL (data)((((CtkTreeModel*) (void *) g_type_check_instance_cast ((GTypeInstance
*) ((data)), ((ctk_tree_model_get_type ()))))))
, path);
2664 }
2665
2666 if (emit_child_toggled && parent_level)
2667 {
2668 CtkTreeIter iter2;
2669 CtkTreePath *path2;
2670
2671 iter2.stamp = filter->priv->stamp;
2672 iter2.user_data = parent_level;
2673 iter2.user_data2 = parent_elt;
2674
2675 /* We set in_row_deleted to TRUE to avoid a level build triggered
2676 * by row-has-child-toggled (parent model could call iter_has_child
2677 * for example).
2678 */
2679 filter->priv->in_row_deleted = TRUE(!(0));
2680 path2 = ctk_tree_model_get_path (CTK_TREE_MODEL (filter)((((CtkTreeModel*) (void *) g_type_check_instance_cast ((GTypeInstance
*) ((filter)), ((ctk_tree_model_get_type ()))))))
, &iter2);
2681 ctk_tree_model_row_has_child_toggled (CTK_TREE_MODEL (filter)((((CtkTreeModel*) (void *) g_type_check_instance_cast ((GTypeInstance
*) ((filter)), ((ctk_tree_model_get_type ()))))))
,
2682 path2, &iter2);
2683 ctk_tree_path_free (path2);
2684 filter->priv->in_row_deleted = FALSE(0);
2685 }
2686
2687 if (filter->priv->virtual_root)
2688 {
2689 CtkTreePath *real_path;
2690
2691 real_path = ctk_tree_model_filter_remove_root (c_path,
2692 filter->priv->virtual_root);
2693 if (real_path)
2694 {
2695 ctk_tree_model_filter_check_ancestors (filter, real_path);
2696 ctk_tree_path_free (real_path);
2697 }
2698 }
2699 else
2700 ctk_tree_model_filter_check_ancestors (filter, c_path);
2701
2702 ctk_tree_path_free (path);
2703}
2704
2705static void
2706ctk_tree_model_filter_rows_reordered (CtkTreeModel *c_model,
2707 CtkTreePath *c_path,
2708 CtkTreeIter *c_iter,
2709 gint *new_order,
2710 gpointer data)
2711{
2712 FilterElt *elt;
2713 FilterLevel *level;
2714 CtkTreeModelFilter *filter = CTK_TREE_MODEL_FILTER (data)((((CtkTreeModelFilter*) (void *) g_type_check_instance_cast (
(GTypeInstance*) ((data)), ((ctk_tree_model_filter_get_type (
)))))))
;
2715
2716 CtkTreePath *path;
2717 CtkTreeIter iter;
2718
2719 GSequence *tmp_seq;
2720 GSequenceIter *tmp_end_iter;
2721 GSequenceIter *old_first_siter = NULL((void*)0);
2722 gint *tmp_array;
2723 gint i, elt_count;
2724 gint length;
2725
2726 g_return_if_fail (new_order != NULL)do { if ((new_order != ((void*)0))) { } else { g_return_if_fail_warning
("Ctk", ((const char*) (__func__)), "new_order != NULL"); return
; } } while (0)
;
2727
2728 if (c_path == NULL((void*)0) || ctk_tree_path_get_depth (c_path) == 0)
2729 {
2730 length = ctk_tree_model_iter_n_children (c_model, NULL((void*)0));
2731
2732 if (filter->priv->virtual_root)
2733 {
2734 gint new_pos = -1;
2735
2736 /* reorder root level of path */
2737 for (i = 0; i < length; i++)
2738 if (new_order[i] == ctk_tree_path_get_indices (filter->priv->virtual_root)[0])
2739 new_pos = i;
2740
2741 if (new_pos < 0)
2742 return;
2743
2744 ctk_tree_path_get_indices (filter->priv->virtual_root)[0] = new_pos;
2745 return;
2746 }
2747
2748 path = ctk_tree_path_new ();
2749 level = FILTER_LEVEL (filter->priv->root)((FilterLevel *)filter->priv->root);
2750 }
2751 else
2752 {
2753 CtkTreeIter child_iter;
2754
2755 /* virtual root anchor reordering */
2756 if (filter->priv->virtual_root &&
2757 ctk_tree_path_is_ancestor (c_path, filter->priv->virtual_root))
2758 {
2759 gint new_pos = -1;
2760 gint len;
2761 gint depth;
2762 CtkTreeIter real_c_iter;
2763
2764 depth = ctk_tree_path_get_depth (c_path);
2765
2766 if (c_iter)
2767 real_c_iter = *c_iter;
2768 else
2769 ctk_tree_model_get_iter (c_model, &real_c_iter, c_path);
2770
2771 len = ctk_tree_model_iter_n_children (c_model, &real_c_iter);
2772
2773 for (i = 0; i < len; i++)
2774 if (new_order[i] == ctk_tree_path_get_indices (filter->priv->virtual_root)[depth])
2775 new_pos = i;
2776
2777 if (new_pos < 0)
2778 return;
2779
2780 ctk_tree_path_get_indices (filter->priv->virtual_root)[depth] = new_pos;
2781 return;
2782 }
2783
2784 path = ctk_real_tree_model_filter_convert_child_path_to_path (filter,
2785 c_path,
2786 FALSE(0),
2787 FALSE(0));
2788
2789 if (!path && filter->priv->virtual_root &&
2790 ctk_tree_path_compare (c_path, filter->priv->virtual_root))
2791 return;
2792
2793 if (!path && !filter->priv->virtual_root)
2794 return;
2795
2796 if (!path)
2797 {
2798 /* root level mode */
2799 if (!c_iter)
2800 ctk_tree_model_get_iter (c_model, c_iter, c_path);
2801 length = ctk_tree_model_iter_n_children (c_model, c_iter);
2802 path = ctk_tree_path_new ();
2803 level = FILTER_LEVEL (filter->priv->root)((FilterLevel *)filter->priv->root);
2804 }
2805 else
2806 {
2807 ctk_tree_model_filter_get_iter_full (CTK_TREE_MODEL (data)((((CtkTreeModel*) (void *) g_type_check_instance_cast ((GTypeInstance
*) ((data)), ((ctk_tree_model_get_type ()))))))
,
2808 &iter, path);
2809
2810 elt = FILTER_ELT (iter.user_data2)((FilterElt *)iter.user_data2);
2811
2812 if (!elt->children)
2813 {
2814 ctk_tree_path_free (path);
2815 return;
2816 }
2817
2818 level = elt->children;
2819
2820 ctk_tree_model_filter_convert_iter_to_child_iter (CTK_TREE_MODEL_FILTER (filter)((((CtkTreeModelFilter*) (void *) g_type_check_instance_cast (
(GTypeInstance*) ((filter)), ((ctk_tree_model_filter_get_type
()))))))
, &child_iter, &iter);
2821 length = ctk_tree_model_iter_n_children (c_model, &child_iter);
2822 }
2823 }
2824
2825 if (!level || g_sequence_get_length (level->seq) < 1)
2826 {
2827 ctk_tree_path_free (path);
2828 return;
2829 }
2830
2831 /* NOTE: we do not bail out here if level->seq->len < 2 like
2832 * CtkTreeModelSort does. This because we do some special tricky
2833 * reordering.
2834 */
2835
2836 tmp_seq = g_sequence_new (filter_elt_free);
2837 tmp_end_iter = g_sequence_get_end_iter (tmp_seq);
2838 tmp_array = g_new (gint, g_sequence_get_length (level->visible_seq))((gint *) g_malloc_n ((g_sequence_get_length (level->visible_seq
)), sizeof (gint)))
;
2839 elt_count = 0;
2840
2841 old_first_siter = g_sequence_get_iter_at_pos (level->seq, 0);
2842
2843 for (i = 0; i < length; i++)
2844 {
2845 GSequenceIter *siter;
2846
2847 elt = lookup_elt_with_offset (level->seq, new_order[i], &siter);
2848 if (elt == NULL((void*)0))
2849 continue;
2850
2851 /* Only for visible items an entry should be present in the order array
2852 * to be emitted.
2853 */
2854 if (elt->visible_siter)
2855 tmp_array[elt_count++] = g_sequence_iter_get_position (elt->visible_siter);
2856
2857 /* Steal elt from level->seq and append it to tmp_seq */
2858 g_sequence_move (siter, tmp_end_iter);
2859 elt->offset = i;
2860 }
2861
2862 g_warn_if_fail (g_sequence_get_length (level->seq) == 0)do { if (g_sequence_get_length (level->seq) == 0) ; else g_warn_message
("Ctk", "ctktreemodelfilter.c", 2862, ((const char*) (__func__
)), "g_sequence_get_length (level->seq) == 0"); } while (0
)
;
2863 g_sequence_free (level->seq);
2864 level->seq = tmp_seq;
2865 g_sequence_sort (level->visible_seq, filter_elt_cmp, NULL((void*)0));
2866
2867 /* Transfer the reference from the old item at position 0 to the
2868 * new item at position 0, unless the old item at position 0 is also
2869 * at position 0 in the new sequence.
2870 */
2871 if (g_sequence_iter_get_position (old_first_siter) != 0)
2872 ctk_tree_model_filter_level_transfer_first_ref (filter,
2873 level,
2874 old_first_siter,
2875 g_sequence_get_iter_at_pos (level->seq, 0));
2876
2877 /* emit rows_reordered */
2878 if (g_sequence_get_length (level->visible_seq) > 0)
2879 {
2880 if (!ctk_tree_path_get_indices (path))
2881 ctk_tree_model_rows_reordered (CTK_TREE_MODEL (data)((((CtkTreeModel*) (void *) g_type_check_instance_cast ((GTypeInstance
*) ((data)), ((ctk_tree_model_get_type ()))))))
, path, NULL((void*)0),
2882 tmp_array);
2883 else
2884 {
2885 /* get a path taking only visible nodes into account */
2886 ctk_tree_path_free (path);
2887 path = ctk_tree_model_get_path (CTK_TREE_MODEL (data)((((CtkTreeModel*) (void *) g_type_check_instance_cast ((GTypeInstance
*) ((data)), ((ctk_tree_model_get_type ()))))))
, &iter);
2888
2889 ctk_tree_model_rows_reordered (CTK_TREE_MODEL (data)((((CtkTreeModel*) (void *) g_type_check_instance_cast ((GTypeInstance
*) ((data)), ((ctk_tree_model_get_type ()))))))
, path, &iter,
2890 tmp_array);
2891 }
2892 }
2893
2894 /* done */
2895 g_free (tmp_array);
2896 ctk_tree_path_free (path);
2897}
2898
2899/* TreeModelIface implementation */
2900static CtkTreeModelFlags
2901ctk_tree_model_filter_get_flags (CtkTreeModel *model)
2902{
2903 CtkTreeModelFlags flags;
2904
2905 g_return_val_if_fail (CTK_IS_TREE_MODEL_FILTER (model), 0)do { if (((((__extension__ ({ GTypeInstance *__inst = (GTypeInstance
*) ((model)); GType __t = ((ctk_tree_model_filter_get_type ()
)); gboolean __r; if (!__inst) __r = (0); else if (__inst->
g_class && __inst->g_class->g_type == __t) __r =
(!(0)); else __r = g_type_check_instance_is_a (__inst, __t);
__r; })))))) { } else { g_return_if_fail_warning ("Ctk", ((const
char*) (__func__)), "CTK_IS_TREE_MODEL_FILTER (model)"); return
(0); } } while (0)
;
2906 g_return_val_if_fail (CTK_TREE_MODEL_FILTER (model)->priv->child_model != NULL, 0)do { if ((((((CtkTreeModelFilter*) (void *) g_type_check_instance_cast
((GTypeInstance*) ((model)), ((ctk_tree_model_filter_get_type
()))))))->priv->child_model != ((void*)0))) { } else {
g_return_if_fail_warning ("Ctk", ((const char*) (__func__)),
"CTK_TREE_MODEL_FILTER (model)->priv->child_model != NULL"
); return (0); } } while (0)
;
2907
2908 flags = ctk_tree_model_get_flags (CTK_TREE_MODEL_FILTER (model)((((CtkTreeModelFilter*) (void *) g_type_check_instance_cast (
(GTypeInstance*) ((model)), ((ctk_tree_model_filter_get_type (
)))))))
->priv->child_model);
2909
2910 if ((flags & CTK_TREE_MODEL_LIST_ONLY) == CTK_TREE_MODEL_LIST_ONLY)
2911 return CTK_TREE_MODEL_LIST_ONLY;
2912
2913 return 0;
2914}
2915
2916static gint
2917ctk_tree_model_filter_get_n_columns (CtkTreeModel *model)
2918{
2919 CtkTreeModelFilter *filter = (CtkTreeModelFilter *)model;
2920
2921 g_return_val_if_fail (CTK_IS_TREE_MODEL_FILTER (model), 0)do { if (((((__extension__ ({ GTypeInstance *__inst = (GTypeInstance
*) ((model)); GType __t = ((ctk_tree_model_filter_get_type ()
)); gboolean __r; if (!__inst) __r = (0); else if (__inst->
g_class && __inst->g_class->g_type == __t) __r =
(!(0)); else __r = g_type_check_instance_is_a (__inst, __t);
__r; })))))) { } else { g_return_if_fail_warning ("Ctk", ((const
char*) (__func__)), "CTK_IS_TREE_MODEL_FILTER (model)"); return
(0); } } while (0)
;
2922 g_return_val_if_fail (filter->priv->child_model != NULL, 0)do { if ((filter->priv->child_model != ((void*)0))) { }
else { g_return_if_fail_warning ("Ctk", ((const char*) (__func__
)), "filter->priv->child_model != NULL"); return (0); }
} while (0)
;
2923
2924 if (filter->priv->child_model == NULL((void*)0))
2925 return 0;
2926
2927 /* so we can't set the modify func after this ... */
2928 filter->priv->modify_func_set = TRUE(!(0));
2929
2930 if (filter->priv->modify_n_columns > 0)
2931 return filter->priv->modify_n_columns;
2932
2933 return ctk_tree_model_get_n_columns (filter->priv->child_model);
2934}
2935
2936static GType
2937ctk_tree_model_filter_get_column_type (CtkTreeModel *model,
2938 gint index)
2939{
2940 CtkTreeModelFilter *filter = (CtkTreeModelFilter *)model;
2941
2942 g_return_val_if_fail (CTK_IS_TREE_MODEL_FILTER (model), G_TYPE_INVALID)do { if (((((__extension__ ({ GTypeInstance *__inst = (GTypeInstance
*) ((model)); GType __t = ((ctk_tree_model_filter_get_type ()
)); gboolean __r; if (!__inst) __r = (0); else if (__inst->
g_class && __inst->g_class->g_type == __t) __r =
(!(0)); else __r = g_type_check_instance_is_a (__inst, __t);
__r; })))))) { } else { g_return_if_fail_warning ("Ctk", ((const
char*) (__func__)), "CTK_IS_TREE_MODEL_FILTER (model)"); return
(((GType) ((0) << (2)))); } } while (0)
;
2943 g_return_val_if_fail (filter->priv->child_model != NULL, G_TYPE_INVALID)do { if ((filter->priv->child_model != ((void*)0))) { }
else { g_return_if_fail_warning ("Ctk", ((const char*) (__func__
)), "filter->priv->child_model != NULL"); return (((GType
) ((0) << (2)))); } } while (0)
;
2944
2945 /* so we can't set the modify func after this ... */
2946 filter->priv->modify_func_set = TRUE(!(0));
2947
2948 if (filter->priv->modify_types)
2949 {
2950 g_return_val_if_fail (index < filter->priv->modify_n_columns, G_TYPE_INVALID)do { if ((index < filter->priv->modify_n_columns)) {
} else { g_return_if_fail_warning ("Ctk", ((const char*) (__func__
)), "index < filter->priv->modify_n_columns"); return
(((GType) ((0) << (2)))); } } while (0)
;
2951
2952 return filter->priv->modify_types[index];
2953 }
2954
2955 return ctk_tree_model_get_column_type (filter->priv->child_model, index);
2956}
2957
2958/* A special case of _get_iter; this function can also get iters which
2959 * are not visible. These iters should ONLY be passed internally, never
2960 * pass those along with a signal emission.
2961 */
2962static gboolean
2963ctk_tree_model_filter_get_iter_full (CtkTreeModel *model,
2964 CtkTreeIter *iter,
2965 CtkTreePath *path)
2966{
2967 CtkTreeModelFilter *filter = (CtkTreeModelFilter *)model;
2968 gint *indices;
2969 FilterLevel *level;
2970 FilterElt *elt;
2971 gint depth, i;
2972 GSequenceIter *siter;
2973
2974 g_return_val_if_fail (CTK_IS_TREE_MODEL_FILTER (model), FALSE)do { if (((((__extension__ ({ GTypeInstance *__inst = (GTypeInstance
*) ((model)); GType __t = ((ctk_tree_model_filter_get_type ()
)); gboolean __r; if (!__inst) __r = (0); else if (__inst->
g_class && __inst->g_class->g_type == __t) __r =
(!(0)); else __r = g_type_check_instance_is_a (__inst, __t);
__r; })))))) { } else { g_return_if_fail_warning ("Ctk", ((const
char*) (__func__)), "CTK_IS_TREE_MODEL_FILTER (model)"); return
((0)); } } while (0)
;
44
Assuming '__inst' is non-null
45
Taking false branch
46
Assuming field 'g_class' is null
47
Assuming the condition is true
48
Taking true branch
49
Loop condition is false. Exiting loop
2975 g_return_val_if_fail (filter->priv->child_model != NULL, FALSE)do { if ((filter->priv->child_model != ((void*)0))) { }
else { g_return_if_fail_warning ("Ctk", ((const char*) (__func__
)), "filter->priv->child_model != NULL"); return ((0));
} } while (0)
;
50
Assuming field 'child_model' is not equal to null
51
Taking true branch
52
Loop condition is false. Exiting loop
2976
2977 indices = ctk_tree_path_get_indices (path);
2978
2979 if (filter->priv->root == NULL((void*)0))
53
Assuming field 'root' is not equal to NULL
54
Taking false branch
2980 ctk_tree_model_filter_build_level (filter, NULL((void*)0), NULL((void*)0), FALSE(0));
2981 level = FILTER_LEVEL (filter->priv->root)((FilterLevel *)filter->priv->root);
2982
2983 depth = ctk_tree_path_get_depth (path);
2984 if (!depth)
55
Assuming 'depth' is 0
56
Taking true branch
2985 {
2986 iter->stamp = 0;
2987 return FALSE(0);
57
Returning without writing to 'iter->user_data2'
2988 }
2989
2990 for (i = 0; i < depth - 1; i++)
2991 {
2992 if (!level || indices[i] >= g_sequence_get_length (level->seq))
2993 {
2994 iter->stamp = 0;
2995 return FALSE(0);
2996 }
2997
2998 siter = g_sequence_get_iter_at_pos (level->seq, indices[i]);
2999 if (g_sequence_iter_is_end (siter))
3000 {
3001 iter->stamp = 0;
3002 return FALSE(0);
3003 }
3004
3005 elt = GET_ELT (siter)((FilterElt*) (siter ? g_sequence_get (siter) : ((void*)0)));
3006
3007 if (!elt->children)
3008 ctk_tree_model_filter_build_level (filter, level, elt, FALSE(0));
3009 level = elt->children;
3010 }
3011
3012 if (!level || indices[i] >= g_sequence_get_length (level->seq))
3013 {
3014 iter->stamp = 0;
3015 return FALSE(0);
3016 }
3017
3018 iter->stamp = filter->priv->stamp;
3019 iter->user_data = level;
3020
3021 siter = g_sequence_get_iter_at_pos (level->seq, indices[depth - 1]);
3022 if (g_sequence_iter_is_end (siter))
3023 {
3024 iter->stamp = 0;
3025 return FALSE(0);
3026 }
3027 iter->user_data2 = GET_ELT (siter)((FilterElt*) (siter ? g_sequence_get (siter) : ((void*)0)));
3028
3029 return TRUE(!(0));
3030}
3031
3032static gboolean
3033ctk_tree_model_filter_get_iter (CtkTreeModel *model,
3034 CtkTreeIter *iter,
3035 CtkTreePath *path)
3036{
3037 CtkTreeModelFilter *filter = (CtkTreeModelFilter *)model;
3038 gint *indices;
3039 FilterLevel *level;
3040 FilterElt *elt;
3041 GSequenceIter *siter;
3042 gint depth, i;
3043
3044 g_return_val_if_fail (CTK_IS_TREE_MODEL_FILTER (model), FALSE)do { if (((((__extension__ ({ GTypeInstance *__inst = (GTypeInstance
*) ((model)); GType __t = ((ctk_tree_model_filter_get_type ()
)); gboolean __r; if (!__inst) __r = (0); else if (__inst->
g_class && __inst->g_class->g_type == __t) __r =
(!(0)); else __r = g_type_check_instance_is_a (__inst, __t);
__r; })))))) { } else { g_return_if_fail_warning ("Ctk", ((const
char*) (__func__)), "CTK_IS_TREE_MODEL_FILTER (model)"); return
((0)); } } while (0)
;
3045 g_return_val_if_fail (filter->priv->child_model != NULL, FALSE)do { if ((filter->priv->child_model != ((void*)0))) { }
else { g_return_if_fail_warning ("Ctk", ((const char*) (__func__
)), "filter->priv->child_model != NULL"); return ((0));
} } while (0)
;
3046
3047 indices = ctk_tree_path_get_indices (path);
3048
3049 if (filter->priv->root == NULL((void*)0))
3050 ctk_tree_model_filter_build_level (filter, NULL((void*)0), NULL((void*)0), FALSE(0));
3051 level = FILTER_LEVEL (filter->priv->root)((FilterLevel *)filter->priv->root);
3052
3053 depth = ctk_tree_path_get_depth (path);
3054 if (!depth)
3055 {
3056 iter->stamp = 0;
3057 return FALSE(0);
3058 }
3059
3060 for (i = 0; i < depth - 1; i++)
3061 {
3062 if (!level || indices[i] >= g_sequence_get_length (level->visible_seq))
3063 {
3064 iter->stamp = 0;
3065 return FALSE(0);
3066 }
3067
3068 siter = g_sequence_get_iter_at_pos (level->visible_seq, indices[i]);
3069 if (g_sequence_iter_is_end (siter))
3070 {
3071 iter->stamp = 0;
3072 return FALSE(0);
3073 }
3074
3075 elt = GET_ELT (siter)((FilterElt*) (siter ? g_sequence_get (siter) : ((void*)0)));
3076 if (!elt->children)
3077 ctk_tree_model_filter_build_level (filter, level, elt, FALSE(0));
3078 level = elt->children;
3079 }
3080
3081 if (!level || indices[i] >= g_sequence_get_length (level->visible_seq))
3082 {
3083 iter->stamp = 0;
3084 return FALSE(0);
3085 }
3086
3087 iter->stamp = filter->priv->stamp;
3088 iter->user_data = level;
3089
3090 siter = g_sequence_get_iter_at_pos (level->visible_seq, indices[depth - 1]);
3091 if (g_sequence_iter_is_end (siter))
3092 {
3093 iter->stamp = 0;
3094 return FALSE(0);
3095 }
3096 iter->user_data2 = GET_ELT (siter)((FilterElt*) (siter ? g_sequence_get (siter) : ((void*)0)));
3097
3098 return TRUE(!(0));
3099}
3100
3101static CtkTreePath *
3102ctk_tree_model_filter_get_path (CtkTreeModel *model,
3103 CtkTreeIter *iter)
3104{
3105 CtkTreePath *retval;
3106 FilterLevel *level;
3107 FilterElt *elt;
3108
3109 g_return_val_if_fail (CTK_IS_TREE_MODEL_FILTER (model), NULL)do { if (((((__extension__ ({ GTypeInstance *__inst = (GTypeInstance
*) ((model)); GType __t = ((ctk_tree_model_filter_get_type ()
)); gboolean __r; if (!__inst) __r = (0); else if (__inst->
g_class && __inst->g_class->g_type == __t) __r =
(!(0)); else __r = g_type_check_instance_is_a (__inst, __t);
__r; })))))) { } else { g_return_if_fail_warning ("Ctk", ((const
char*) (__func__)), "CTK_IS_TREE_MODEL_FILTER (model)"); return
(((void*)0)); } } while (0)
;
3110 g_return_val_if_fail (CTK_TREE_MODEL_FILTER (model)->priv->child_model != NULL, NULL)do { if ((((((CtkTreeModelFilter*) (void *) g_type_check_instance_cast
((GTypeInstance*) ((model)), ((ctk_tree_model_filter_get_type
()))))))->priv->child_model != ((void*)0))) { } else {
g_return_if_fail_warning ("Ctk", ((const char*) (__func__)),
"CTK_TREE_MODEL_FILTER (model)->priv->child_model != NULL"
); return (((void*)0)); } } while (0)
;
3111 g_return_val_if_fail (CTK_TREE_MODEL_FILTER (model)->priv->stamp == iter->stamp, NULL)do { if ((((((CtkTreeModelFilter*) (void *) g_type_check_instance_cast
((GTypeInstance*) ((model)), ((ctk_tree_model_filter_get_type
()))))))->priv->stamp == iter->stamp)) { } else { g_return_if_fail_warning
("Ctk", ((const char*) (__func__)), "CTK_TREE_MODEL_FILTER (model)->priv->stamp == iter->stamp"
); return (((void*)0)); } } while (0)
;
3112
3113 level = iter->user_data;
3114 elt = iter->user_data2;
3115
3116 if (!elt->visible_siter)
3117 return NULL((void*)0);
3118
3119 retval = ctk_tree_path_new ();
3120
3121 while (level)
3122 {
3123 gint index;
3124
3125 index = g_sequence_iter_get_position (elt->visible_siter);
3126 ctk_tree_path_prepend_index (retval, index);
3127
3128 elt = level->parent_elt;
3129 level = level->parent_level;
3130 }
3131
3132 return retval;
3133}
3134
3135static void
3136ctk_tree_model_filter_real_modify (CtkTreeModelFilter *self,
3137 CtkTreeModel *child_model,
3138 CtkTreeIter *iter,
3139 GValue *value,
3140 gint column)
3141{
3142 if (self->priv->modify_func)
3143 {
3144 g_return_if_fail (column < self->priv->modify_n_columns)do { if ((column < self->priv->modify_n_columns)) { }
else { g_return_if_fail_warning ("Ctk", ((const char*) (__func__
)), "column < self->priv->modify_n_columns"); return
; } } while (0)
;
3145
3146 g_value_init (value, self->priv->modify_types[column]);
3147 self->priv->modify_func (CTK_TREE_MODEL (self)((((CtkTreeModel*) (void *) g_type_check_instance_cast ((GTypeInstance
*) ((self)), ((ctk_tree_model_get_type ()))))))
,
3148 iter, value, column,
3149 self->priv->modify_data);
3150 }
3151 else
3152 {
3153 CtkTreeIter child_iter;
3154
3155 ctk_tree_model_filter_convert_iter_to_child_iter (CTK_TREE_MODEL_FILTER (self)((((CtkTreeModelFilter*) (void *) g_type_check_instance_cast (
(GTypeInstance*) ((self)), ((ctk_tree_model_filter_get_type (
)))))))
,
3156 &child_iter, iter);
3157 ctk_tree_model_get_value (child_model, &child_iter, column, value);
3158 }
3159}
3160
3161static void
3162ctk_tree_model_filter_get_value (CtkTreeModel *model,
3163 CtkTreeIter *iter,
3164 gint column,
3165 GValue *value)
3166{
3167 CtkTreeModelFilter *filter = CTK_TREE_MODEL_FILTER (model)((((CtkTreeModelFilter*) (void *) g_type_check_instance_cast (
(GTypeInstance*) ((model)), ((ctk_tree_model_filter_get_type (
)))))))
;
3168
3169 g_return_if_fail (CTK_IS_TREE_MODEL_FILTER (model))do { if (((((__extension__ ({ GTypeInstance *__inst = (GTypeInstance
*) ((model)); GType __t = ((ctk_tree_model_filter_get_type ()
)); gboolean __r; if (!__inst) __r = (0); else if (__inst->
g_class && __inst->g_class->g_type == __t) __r =
(!(0)); else __r = g_type_check_instance_is_a (__inst, __t);
__r; })))))) { } else { g_return_if_fail_warning ("Ctk", ((const
char*) (__func__)), "CTK_IS_TREE_MODEL_FILTER (model)"); return
; } } while (0)
;
3170 g_return_if_fail (CTK_TREE_MODEL_FILTER (model)->priv->child_model != NULL)do { if ((((((CtkTreeModelFilter*) (void *) g_type_check_instance_cast
((GTypeInstance*) ((model)), ((ctk_tree_model_filter_get_type
()))))))->priv->child_model != ((void*)0))) { } else {
g_return_if_fail_warning ("Ctk", ((const char*) (__func__)),
"CTK_TREE_MODEL_FILTER (model)->priv->child_model != NULL"
); return; } } while (0)
;
3171 g_return_if_fail (CTK_TREE_MODEL_FILTER (model)->priv->stamp == iter->stamp)do { if ((((((CtkTreeModelFilter*) (void *) g_type_check_instance_cast
((GTypeInstance*) ((model)), ((ctk_tree_model_filter_get_type
()))))))->priv->stamp == iter->stamp)) { } else { g_return_if_fail_warning
("Ctk", ((const char*) (__func__)), "CTK_TREE_MODEL_FILTER (model)->priv->stamp == iter->stamp"
); return; } } while (0)
;
3172
3173 CTK_TREE_MODEL_FILTER_GET_CLASS (model)((((CtkTreeModelFilterClass*) (((GTypeInstance*) ((model)))->
g_class))))
->modify (filter,
3174 filter->priv->child_model, iter, value, column);
3175}
3176
3177static gboolean
3178ctk_tree_model_filter_iter_next (CtkTreeModel *model,
3179 CtkTreeIter *iter)
3180{
3181 FilterElt *elt;
3182 GSequenceIter *siter;
3183
3184 g_return_val_if_fail (CTK_IS_TREE_MODEL_FILTER (model), FALSE)do { if (((((__extension__ ({ GTypeInstance *__inst = (GTypeInstance
*) ((model)); GType __t = ((ctk_tree_model_filter_get_type ()
)); gboolean __r; if (!__inst) __r = (0); else if (__inst->
g_class && __inst->g_class->g_type == __t) __r =
(!(0)); else __r = g_type_check_instance_is_a (__inst, __t);
__r; })))))) { } else { g_return_if_fail_warning ("Ctk", ((const
char*) (__func__)), "CTK_IS_TREE_MODEL_FILTER (model)"); return
((0)); } } while (0)
;
3185 g_return_val_if_fail (CTK_TREE_MODEL_FILTER (model)->priv->child_model != NULL, FALSE)do { if ((((((CtkTreeModelFilter*) (void *) g_type_check_instance_cast
((GTypeInstance*) ((model)), ((ctk_tree_model_filter_get_type
()))))))->priv->child_model != ((void*)0))) { } else {
g_return_if_fail_warning ("Ctk", ((const char*) (__func__)),
"CTK_TREE_MODEL_FILTER (model)->priv->child_model != NULL"
); return ((0)); } } while (0)
;
3186 g_return_val_if_fail (CTK_TREE_MODEL_FILTER (model)->priv->stamp == iter->stamp, FALSE)do { if ((((((CtkTreeModelFilter*) (void *) g_type_check_instance_cast
((GTypeInstance*) ((model)), ((ctk_tree_model_filter_get_type
()))))))->priv->stamp == iter->stamp)) { } else { g_return_if_fail_warning
("Ctk", ((const char*) (__func__)), "CTK_TREE_MODEL_FILTER (model)->priv->stamp == iter->stamp"
); return ((0)); } } while (0)
;
3187
3188 elt = iter->user_data2;
3189
3190 siter = g_sequence_iter_next (elt->visible_siter);
3191 if (g_sequence_iter_is_end (siter))
3192 {
3193 iter->stamp = 0;
3194 return FALSE(0);
3195 }
3196
3197 iter->user_data2 = GET_ELT (siter)((FilterElt*) (siter ? g_sequence_get (siter) : ((void*)0)));
3198
3199 return TRUE(!(0));
3200}
3201
3202static gboolean
3203ctk_tree_model_filter_iter_previous (CtkTreeModel *model,
3204 CtkTreeIter *iter)
3205{
3206 FilterElt *elt;
3207 GSequenceIter *siter;
3208
3209 g_return_val_if_fail (CTK_IS_TREE_MODEL_FILTER (model), FALSE)do { if (((((__extension__ ({ GTypeInstance *__inst = (GTypeInstance
*) ((model)); GType __t = ((ctk_tree_model_filter_get_type ()
)); gboolean __r; if (!__inst) __r = (0); else if (__inst->
g_class && __inst->g_class->g_type == __t) __r =
(!(0)); else __r = g_type_check_instance_is_a (__inst, __t);
__r; })))))) { } else { g_return_if_fail_warning ("Ctk", ((const
char*) (__func__)), "CTK_IS_TREE_MODEL_FILTER (model)"); return
((0)); } } while (0)
;
3210 g_return_val_if_fail (CTK_TREE_MODEL_FILTER (model)->priv->child_model != NULL, FALSE)do { if ((((((CtkTreeModelFilter*) (void *) g_type_check_instance_cast
((GTypeInstance*) ((model)), ((ctk_tree_model_filter_get_type
()))))))->priv->child_model != ((void*)0))) { } else {
g_return_if_fail_warning ("Ctk", ((const char*) (__func__)),
"CTK_TREE_MODEL_FILTER (model)->priv->child_model != NULL"
); return ((0)); } } while (0)
;
3211 g_return_val_if_fail (CTK_TREE_MODEL_FILTER (model)->priv->stamp == iter->stamp, FALSE)do { if ((((((CtkTreeModelFilter*) (void *) g_type_check_instance_cast
((GTypeInstance*) ((model)), ((ctk_tree_model_filter_get_type
()))))))->priv->stamp == iter->stamp)) { } else { g_return_if_fail_warning
("Ctk", ((const char*) (__func__)), "CTK_TREE_MODEL_FILTER (model)->priv->stamp == iter->stamp"
); return ((0)); } } while (0)
;
3212
3213 elt = iter->user_data2;
3214
3215 if (g_sequence_iter_is_begin (elt->visible_siter))
3216 {
3217 iter->stamp = 0;
3218 return FALSE(0);
3219 }
3220 siter = g_sequence_iter_prev (elt->visible_siter);
3221
3222 iter->user_data2 = GET_ELT (siter)((FilterElt*) (siter ? g_sequence_get (siter) : ((void*)0)));
3223
3224 return TRUE(!(0));
3225}
3226
3227static gboolean
3228ctk_tree_model_filter_iter_children (CtkTreeModel *model,
3229 CtkTreeIter *iter,
3230 CtkTreeIter *parent)
3231{
3232 CtkTreeModelFilter *filter = (CtkTreeModelFilter *)model;
3233 FilterLevel *level;
3234 GSequenceIter *siter;
3235
3236 iter->stamp = 0;
3237 g_return_val_if_fail (CTK_IS_TREE_MODEL_FILTER (model), FALSE)do { if (((((__extension__ ({ GTypeInstance *__inst = (GTypeInstance
*) ((model)); GType __t = ((ctk_tree_model_filter_get_type ()
)); gboolean __r; if (!__inst) __r = (0); else if (__inst->
g_class && __inst->g_class->g_type == __t) __r =
(!(0)); else __r = g_type_check_instance_is_a (__inst, __t);
__r; })))))) { } else { g_return_if_fail_warning ("Ctk", ((const
char*) (__func__)), "CTK_IS_TREE_MODEL_FILTER (model)"); return
((0)); } } while (0)
;
3238 g_return_val_if_fail (filter->priv->child_model != NULL, FALSE)do { if ((filter->priv->child_model != ((void*)0))) { }
else { g_return_if_fail_warning ("Ctk", ((const char*) (__func__
)), "filter->priv->child_model != NULL"); return ((0));
} } while (0)
;
3239 if (parent)
3240 g_return_val_if_fail (filter->priv->stamp == parent->stamp, FALSE)do { if ((filter->priv->stamp == parent->stamp)) { }
else { g_return_if_fail_warning ("Ctk", ((const char*) (__func__
)), "filter->priv->stamp == parent->stamp"); return (
(0)); } } while (0)
;
3241
3242 if (!parent)
3243 {
3244 if (!filter->priv->root)
3245 ctk_tree_model_filter_build_level (filter, NULL((void*)0), NULL((void*)0), FALSE(0));
3246 if (!filter->priv->root)
3247 return FALSE(0);
3248
3249 level = filter->priv->root;
3250 siter = g_sequence_get_begin_iter (level->visible_seq);
3251 if (g_sequence_iter_is_end (siter))
3252 {
3253 iter->stamp = 0;
3254 return FALSE(0);
3255 }
3256
3257 iter->stamp = filter->priv->stamp;
3258 iter->user_data = level;
3259 iter->user_data2 = GET_ELT (siter)((FilterElt*) (siter ? g_sequence_get (siter) : ((void*)0)));
3260
3261 return TRUE(!(0));
3262 }
3263 else
3264 {
3265 if (FILTER_ELT (parent->user_data2)((FilterElt *)parent->user_data2)->children == NULL((void*)0))
3266 ctk_tree_model_filter_build_level (filter,
3267 FILTER_LEVEL (parent->user_data)((FilterLevel *)parent->user_data),
3268 FILTER_ELT (parent->user_data2)((FilterElt *)parent->user_data2),
3269 FALSE(0));
3270 if (FILTER_ELT (parent->user_data2)((FilterElt *)parent->user_data2)->children == NULL((void*)0))
3271 return FALSE(0);
3272
3273 level = FILTER_ELT (parent->user_data2)((FilterElt *)parent->user_data2)->children;
3274 siter = g_sequence_get_begin_iter (level->visible_seq);
3275 if (g_sequence_iter_is_end (siter))
3276 {
3277 iter->stamp = 0;
3278 return FALSE(0);
3279 }
3280
3281 iter->stamp = filter->priv->stamp;
3282 iter->user_data = level;
3283 iter->user_data2 = GET_ELT (siter)((FilterElt*) (siter ? g_sequence_get (siter) : ((void*)0)));
3284
3285 return TRUE(!(0));
3286 }
3287
3288 iter->stamp = 0;
3289 return FALSE(0);
3290}
3291
3292static gboolean
3293ctk_tree_model_filter_iter_has_child (CtkTreeModel *model,
3294 CtkTreeIter *iter)
3295{
3296 CtkTreeIter child_iter;
3297 CtkTreeModelFilter *filter = (CtkTreeModelFilter *)model;
3298 FilterElt *elt;
3299
3300 g_return_val_if_fail (CTK_IS_TREE_MODEL_FILTER (model), FALSE)do { if (((((__extension__ ({ GTypeInstance *__inst = (GTypeInstance
*) ((model)); GType __t = ((ctk_tree_model_filter_get_type ()
)); gboolean __r; if (!__inst) __r = (0); else if (__inst->
g_class && __inst->g_class->g_type == __t) __r =
(!(0)); else __r = g_type_check_instance_is_a (__inst, __t);
__r; })))))) { } else { g_return_if_fail_warning ("Ctk", ((const
char*) (__func__)), "CTK_IS_TREE_MODEL_FILTER (model)"); return
((0)); } } while (0)
;
3301 g_return_val_if_fail (filter->priv->child_model != NULL, FALSE)do { if ((filter->priv->child_model != ((void*)0))) { }
else { g_return_if_fail_warning ("Ctk", ((const char*) (__func__
)), "filter->priv->child_model != NULL"); return ((0));
} } while (0)
;
3302 g_return_val_if_fail (filter->priv->stamp == iter->stamp, FALSE)do { if ((filter->priv->stamp == iter->stamp)) { } else
{ g_return_if_fail_warning ("Ctk", ((const char*) (__func__)
), "filter->priv->stamp == iter->stamp"); return ((0
)); } } while (0)
;
3303
3304 filter = CTK_TREE_MODEL_FILTER (model)((((CtkTreeModelFilter*) (void *) g_type_check_instance_cast (
(GTypeInstance*) ((model)), ((ctk_tree_model_filter_get_type (
)))))))
;
3305
3306 ctk_tree_model_filter_convert_iter_to_child_iter (CTK_TREE_MODEL_FILTER (model)((((CtkTreeModelFilter*) (void *) g_type_check_instance_cast (
(GTypeInstance*) ((model)), ((ctk_tree_model_filter_get_type (
)))))))
, &child_iter, iter);
3307 elt = FILTER_ELT (iter->user_data2)((FilterElt *)iter->user_data2);
3308
3309 if (!elt->visible_siter)
3310 return FALSE(0);
3311
3312 /* we need to build the level to check if not all children are filtered
3313 * out
3314 */
3315 if (!elt->children
3316 && ctk_tree_model_iter_has_child (filter->priv->child_model, &child_iter))
3317 ctk_tree_model_filter_build_level (filter, FILTER_LEVEL (iter->user_data)((FilterLevel *)iter->user_data),
3318 elt, FALSE(0));
3319
3320 if (elt->children && g_sequence_get_length (elt->children->visible_seq) > 0)
3321 return TRUE(!(0));
3322
3323 return FALSE(0);
3324}
3325
3326static gint
3327ctk_tree_model_filter_iter_n_children (CtkTreeModel *model,
3328 CtkTreeIter *iter)
3329{
3330 CtkTreeIter child_iter;
3331 CtkTreeModelFilter *filter = (CtkTreeModelFilter *)model;
3332 FilterElt *elt;
3333
3334 g_return_val_if_fail (CTK_IS_TREE_MODEL_FILTER (model), 0)do { if (((((__extension__ ({ GTypeInstance *__inst = (GTypeInstance
*) ((model)); GType __t = ((ctk_tree_model_filter_get_type ()
)); gboolean __r; if (!__inst) __r = (0); else if (__inst->
g_class && __inst->g_class->g_type == __t) __r =
(!(0)); else __r = g_type_check_instance_is_a (__inst, __t);
__r; })))))) { } else { g_return_if_fail_warning ("Ctk", ((const
char*) (__func__)), "CTK_IS_TREE_MODEL_FILTER (model)"); return
(0); } } while (0)
;
3335 g_return_val_if_fail (filter->priv->child_model != NULL, 0)do { if ((filter->priv->child_model != ((void*)0))) { }
else { g_return_if_fail_warning ("Ctk", ((const char*) (__func__
)), "filter->priv->child_model != NULL"); return (0); }
} while (0)
;
3336 if (iter)
3337 g_return_val_if_fail (filter->priv->stamp == iter->stamp, 0)do { if ((filter->priv->stamp == iter->stamp)) { } else
{ g_return_if_fail_warning ("Ctk", ((const char*) (__func__)
), "filter->priv->stamp == iter->stamp"); return (0)
; } } while (0)
;
3338
3339 if (!iter)
3340 {
3341 if (!filter->priv->root)
3342 ctk_tree_model_filter_build_level (filter, NULL((void*)0), NULL((void*)0), FALSE(0));
3343
3344 if (filter->priv->root)
3345 return g_sequence_get_length (FILTER_LEVEL (filter->priv->root)((FilterLevel *)filter->priv->root)->visible_seq);
3346
3347 return 0;
3348 }
3349
3350 elt = FILTER_ELT (iter->user_data2)((FilterElt *)iter->user_data2);
3351
3352 if (!elt->visible_siter)
3353 return 0;
3354
3355 ctk_tree_model_filter_convert_iter_to_child_iter (CTK_TREE_MODEL_FILTER (model)((((CtkTreeModelFilter*) (void *) g_type_check_instance_cast (
(GTypeInstance*) ((model)), ((ctk_tree_model_filter_get_type (
)))))))
, &child_iter, iter);
3356
3357 if (!elt->children &&
3358 ctk_tree_model_iter_has_child (filter->priv->child_model, &child_iter))
3359 ctk_tree_model_filter_build_level (filter,
3360 FILTER_LEVEL (iter->user_data)((FilterLevel *)iter->user_data),
3361 elt, FALSE(0));
3362
3363 if (elt->children)
3364 return g_sequence_get_length (elt->children->visible_seq);
3365
3366 return 0;
3367}
3368
3369static gboolean
3370ctk_tree_model_filter_iter_nth_child (CtkTreeModel *model,
3371 CtkTreeIter *iter,
3372 CtkTreeIter *parent,
3373 gint n)
3374{
3375 FilterLevel *level;
3376 CtkTreeIter children;
3377 GSequenceIter *siter;
3378
3379 g_return_val_if_fail (CTK_IS_TREE_MODEL_FILTER (model), FALSE)do { if (((((__extension__ ({ GTypeInstance *__inst = (GTypeInstance
*) ((model)); GType __t = ((ctk_tree_model_filter_get_type ()
)); gboolean __r; if (!__inst) __r = (0); else if (__inst->
g_class && __inst->g_class->g_type == __t) __r =
(!(0)); else __r = g_type_check_instance_is_a (__inst, __t);
__r; })))))) { } else { g_return_if_fail_warning ("Ctk", ((const
char*) (__func__)), "CTK_IS_TREE_MODEL_FILTER (model)"); return
((0)); } } while (0)
;
3380 if (parent)
3381 g_return_val_if_fail (CTK_TREE_MODEL_FILTER (model)->priv->stamp == parent->stamp, FALSE)do { if ((((((CtkTreeModelFilter*) (void *) g_type_check_instance_cast
((GTypeInstance*) ((model)), ((ctk_tree_model_filter_get_type
()))))))->priv->stamp == parent->stamp)) { } else {
g_return_if_fail_warning ("Ctk", ((const char*) (__func__)),
"CTK_TREE_MODEL_FILTER (model)->priv->stamp == parent->stamp"
); return ((0)); } } while (0)
;
3382
3383 /* use this instead of has_child to force us to build the level, if needed */
3384 if (ctk_tree_model_filter_iter_children (model, &children, parent) == FALSE(0))
3385 {
3386 iter->stamp = 0;
3387 return FALSE(0);
3388 }
3389
3390 level = children.user_data;
3391 siter = g_sequence_get_iter_at_pos (level->visible_seq, n);
3392 if (g_sequence_iter_is_end (siter))
3393 return FALSE(0);
3394
3395 iter->stamp = CTK_TREE_MODEL_FILTER (model)((((CtkTreeModelFilter*) (void *) g_type_check_instance_cast (
(GTypeInstance*) ((model)), ((ctk_tree_model_filter_get_type (
)))))))
->priv->stamp;
3396 iter->user_data = level;
3397 iter->user_data2 = GET_ELT (siter)((FilterElt*) (siter ? g_sequence_get (siter) : ((void*)0)));
3398
3399 return TRUE(!(0));
3400}
3401
3402static gboolean
3403ctk_tree_model_filter_iter_parent (CtkTreeModel *model,
3404 CtkTreeIter *iter,
3405 CtkTreeIter *child)
3406{
3407 FilterLevel *level;
3408
3409 iter->stamp = 0;
3410 g_return_val_if_fail (CTK_IS_TREE_MODEL_FILTER (model), FALSE)do { if (((((__extension__ ({ GTypeInstance *__inst = (GTypeInstance
*) ((model)); GType __t = ((ctk_tree_model_filter_get_type ()
)); gboolean __r; if (!__inst) __r = (0); else if (__inst->
g_class && __inst->g_class->g_type == __t) __r =
(!(0)); else __r = g_type_check_instance_is_a (__inst, __t);
__r; })))))) { } else { g_return_if_fail_warning ("Ctk", ((const
char*) (__func__)), "CTK_IS_TREE_MODEL_FILTER (model)"); return
((0)); } } while (0)
;
3411 g_return_val_if_fail (CTK_TREE_MODEL_FILTER (model)->priv->child_model != NULL, FALSE)do { if ((((((CtkTreeModelFilter*) (void *) g_type_check_instance_cast
((GTypeInstance*) ((model)), ((ctk_tree_model_filter_get_type
()))))))->priv->child_model != ((void*)0))) { } else {
g_return_if_fail_warning ("Ctk", ((const char*) (__func__)),
"CTK_TREE_MODEL_FILTER (model)->priv->child_model != NULL"
); return ((0)); } } while (0)
;
3412 g_return_val_if_fail (CTK_TREE_MODEL_FILTER (model)->priv->stamp == child->stamp, FALSE)do { if ((((((CtkTreeModelFilter*) (void *) g_type_check_instance_cast
((GTypeInstance*) ((model)), ((ctk_tree_model_filter_get_type
()))))))->priv->stamp == child->stamp)) { } else { g_return_if_fail_warning
("Ctk", ((const char*) (__func__)), "CTK_TREE_MODEL_FILTER (model)->priv->stamp == child->stamp"
); return ((0)); } } while (0)
;
3413
3414 level = child->user_data;
3415
3416 if (level->parent_level)
3417 {
3418 iter->stamp = CTK_TREE_MODEL_FILTER (model)((((CtkTreeModelFilter*) (void *) g_type_check_instance_cast (
(GTypeInstance*) ((model)), ((ctk_tree_model_filter_get_type (
)))))))
->priv->stamp;
3419 iter->user_data = level->parent_level;
3420 iter->user_data2 = level->parent_elt;
3421
3422 return TRUE(!(0));
3423 }
3424
3425 return FALSE(0);
3426}
3427
3428static void
3429ctk_tree_model_filter_ref_node (CtkTreeModel *model,
3430 CtkTreeIter *iter)
3431{
3432 ctk_tree_model_filter_real_ref_node (model, iter, TRUE(!(0)));
3433}
3434
3435static void
3436ctk_tree_model_filter_real_ref_node (CtkTreeModel *model,
3437 CtkTreeIter *iter,
3438 gboolean external)
3439{
3440 CtkTreeModelFilter *filter = (CtkTreeModelFilter *)model;
3441 CtkTreeIter child_iter;
3442 FilterLevel *level;
3443 FilterElt *elt;
3444
3445 g_return_if_fail (CTK_IS_TREE_MODEL_FILTER (model))do { if (((((__extension__ ({ GTypeInstance *__inst = (GTypeInstance
*) ((model)); GType __t = ((ctk_tree_model_filter_get_type ()
)); gboolean __r; if (!__inst) __r = (0); else if (__inst->
g_class && __inst->g_class->g_type == __t) __r =
(!(0)); else __r = g_type_check_instance_is_a (__inst, __t);
__r; })))))) { } else { g_return_if_fail_warning ("Ctk", ((const
char*) (__func__)), "CTK_IS_TREE_MODEL_FILTER (model)"); return
; } } while (0)
;
3446 g_return_if_fail (CTK_TREE_MODEL_FILTER (model)->priv->child_model != NULL)do { if ((((((CtkTreeModelFilter*) (void *) g_type_check_instance_cast
((GTypeInstance*) ((model)), ((ctk_tree_model_filter_get_type
()))))))->priv->child_model != ((void*)0))) { } else {
g_return_if_fail_warning ("Ctk", ((const char*) (__func__)),
"CTK_TREE_MODEL_FILTER (model)->priv->child_model != NULL"
); return; } } while (0)
;
3447 g_return_if_fail (CTK_TREE_MODEL_FILTER (model)->priv->stamp == iter->stamp)do { if ((((((CtkTreeModelFilter*) (void *) g_type_check_instance_cast
((GTypeInstance*) ((model)), ((ctk_tree_model_filter_get_type
()))))))->priv->stamp == iter->stamp)) { } else { g_return_if_fail_warning
("Ctk", ((const char*) (__func__)), "CTK_TREE_MODEL_FILTER (model)->priv->stamp == iter->stamp"
); return; } } while (0)
;
3448
3449 ctk_tree_model_filter_convert_iter_to_child_iter (CTK_TREE_MODEL_FILTER (model)((((CtkTreeModelFilter*) (void *) g_type_check_instance_cast (
(GTypeInstance*) ((model)), ((ctk_tree_model_filter_get_type (
)))))))
, &child_iter, iter);
3450
3451 ctk_tree_model_ref_node (filter->priv->child_model, &child_iter);
3452
3453 level = iter->user_data;
3454 elt = iter->user_data2;
3455
3456 elt->ref_count++;
3457 level->ref_count++;
3458
3459 if (external)
3460 {
3461 elt->ext_ref_count++;
3462 level->ext_ref_count++;
3463
3464 if (level->ext_ref_count == 1)
3465 {
3466 FilterLevel *parent_level = level->parent_level;
3467 FilterElt *parent_elt = level->parent_elt;
3468
3469 /* we were at zero -- time to decrease the zero_ref_count val */
3470 while (parent_level)
3471 {
3472 parent_elt->zero_ref_count--;
3473
3474 parent_elt = parent_level->parent_elt;
3475 parent_level = parent_level->parent_level;
3476 }
3477
3478 if (filter->priv->root != level)
3479 filter->priv->zero_ref_count--;
3480
3481#ifdef MODEL_FILTER_DEBUG
3482 g_assert (filter->priv->zero_ref_count >= 0)do { if (filter->priv->zero_ref_count >= 0) ; else g_assertion_message_expr
("Ctk", "ctktreemodelfilter.c", 3482, ((const char*) (__func__
)), "filter->priv->zero_ref_count >= 0"); } while (0
)
;
3483 if (filter->priv->zero_ref_count > 0)
3484 g_assert (filter->priv->root != NULL)do { if (filter->priv->root != ((void*)0)) ; else g_assertion_message_expr
("Ctk", "ctktreemodelfilter.c", 3484, ((const char*) (__func__
)), "filter->priv->root != NULL"); } while (0)
;
3485#endif
3486 }
3487 }
3488
3489#ifdef MODEL_FILTER_DEBUG
3490 g_assert (elt->ref_count >= elt->ext_ref_count)do { if (elt->ref_count >= elt->ext_ref_count) ; else
g_assertion_message_expr ("Ctk", "ctktreemodelfilter.c", 3490
, ((const char*) (__func__)), "elt->ref_count >= elt->ext_ref_count"
); } while (0)
;
3491 g_assert (elt->ref_count >= 0)do { if (elt->ref_count >= 0) ; else g_assertion_message_expr
("Ctk", "ctktreemodelfilter.c", 3491, ((const char*) (__func__
)), "elt->ref_count >= 0"); } while (0)
;
3492 g_assert (elt->ext_ref_count >= 0)do { if (elt->ext_ref_count >= 0) ; else g_assertion_message_expr
("Ctk", "ctktreemodelfilter.c", 3492, ((const char*) (__func__
)), "elt->ext_ref_count >= 0"); } while (0)
;
3493#endif
3494}
3495
3496static void
3497ctk_tree_model_filter_unref_node (CtkTreeModel *model,
3498 CtkTreeIter *iter)
3499{
3500 ctk_tree_model_filter_real_unref_node (model, iter, TRUE(!(0)), TRUE(!(0)));
3501}
3502
3503static void
3504ctk_tree_model_filter_real_unref_node (CtkTreeModel *model,
3505 CtkTreeIter *iter,
3506 gboolean external,
3507 gboolean propagate_unref)
3508{
3509 CtkTreeModelFilter *filter = (CtkTreeModelFilter *)model;
3510 FilterLevel *level;
3511 FilterElt *elt;
3512
3513 g_return_if_fail (CTK_IS_TREE_MODEL_FILTER (model))do { if (((((__extension__ ({ GTypeInstance *__inst = (GTypeInstance
*) ((model)); GType __t = ((ctk_tree_model_filter_get_type ()
)); gboolean __r; if (!__inst) __r = (0); else if (__inst->
g_class && __inst->g_class->g_type == __t) __r =
(!(0)); else __r = g_type_check_instance_is_a (__inst, __t);
__r; })))))) { } else { g_return_if_fail_warning ("Ctk", ((const
char*) (__func__)), "CTK_IS_TREE_MODEL_FILTER (model)"); return
; } } while (0)
;
3514 g_return_if_fail (filter->priv->child_model != NULL)do { if ((filter->priv->child_model != ((void*)0))) { }
else { g_return_if_fail_warning ("Ctk", ((const char*) (__func__
)), "filter->priv->child_model != NULL"); return; } } while
(0)
;
3515 g_return_if_fail (filter->priv->stamp == iter->stamp)do { if ((filter->priv->stamp == iter->stamp)) { } else
{ g_return_if_fail_warning ("Ctk", ((const char*) (__func__)
), "filter->priv->stamp == iter->stamp"); return; } }
while (0)
;
3516
3517 if (propagate_unref)
3518 {
3519 CtkTreeIter child_iter;
3520 ctk_tree_model_filter_convert_iter_to_child_iter (CTK_TREE_MODEL_FILTER (model)((((CtkTreeModelFilter*) (void *) g_type_check_instance_cast (
(GTypeInstance*) ((model)), ((ctk_tree_model_filter_get_type (
)))))))
, &child_iter, iter);
3521 ctk_tree_model_unref_node (filter->priv->child_model, &child_iter);
3522 }
3523
3524 level = iter->user_data;
3525 elt = iter->user_data2;
3526
3527 g_return_if_fail (elt->ref_count > 0)do { if ((elt->ref_count > 0)) { } else { g_return_if_fail_warning
("Ctk", ((const char*) (__func__)), "elt->ref_count > 0"
); return; } } while (0)
;
3528#ifdef MODEL_FILTER_DEBUG
3529 g_assert (elt->ref_count >= elt->ext_ref_count)do { if (elt->ref_count >= elt->ext_ref_count) ; else
g_assertion_message_expr ("Ctk", "ctktreemodelfilter.c", 3529
, ((const char*) (__func__)), "elt->ref_count >= elt->ext_ref_count"
); } while (0)
;
3530 g_assert (elt->ref_count >= 0)do { if (elt->ref_count >= 0) ; else g_assertion_message_expr
("Ctk", "ctktreemodelfilter.c", 3530, ((const char*) (__func__
)), "elt->ref_count >= 0"); } while (0)
;
3531 g_assert (elt->ext_ref_count >= 0)do { if (elt->ext_ref_count >= 0) ; else g_assertion_message_expr
("Ctk", "ctktreemodelfilter.c", 3531, ((const char*) (__func__
)), "elt->ext_ref_count >= 0"); } while (0)
;
3532#endif
3533
3534 elt->ref_count--;
3535 level->ref_count--;
3536
3537 if (external)
3538 {
3539 elt->ext_ref_count--;
3540 level->ext_ref_count--;
3541
3542 if (level->ext_ref_count == 0)
3543 {
3544 FilterLevel *parent_level = level->parent_level;
3545 FilterElt *parent_elt = level->parent_elt;
3546
3547 /* we are at zero -- time to increase the zero_ref_count val */
3548 while (parent_level)
3549 {
3550 parent_elt->zero_ref_count++;
3551
3552 parent_elt = parent_level->parent_elt;
3553 parent_level = parent_level->parent_level;
3554 }
3555
3556 if (filter->priv->root != level)
3557 filter->priv->zero_ref_count++;
3558
3559#ifdef MODEL_FILTER_DEBUG
3560 g_assert (filter->priv->zero_ref_count >= 0)do { if (filter->priv->zero_ref_count >= 0) ; else g_assertion_message_expr
("Ctk", "ctktreemodelfilter.c", 3560, ((const char*) (__func__
)), "filter->priv->zero_ref_count >= 0"); } while (0
)
;
3561 if (filter->priv->zero_ref_count > 0)
3562 g_assert (filter->priv->root != NULL)do { if (filter->priv->root != ((void*)0)) ; else g_assertion_message_expr
("Ctk", "ctktreemodelfilter.c", 3562, ((const char*) (__func__
)), "filter->priv->root != NULL"); } while (0)
;
3563#endif
3564 }
3565 }
3566
3567#ifdef MODEL_FILTER_DEBUG
3568 g_assert (elt->ref_count >= elt->ext_ref_count)do { if (elt->ref_count >= elt->ext_ref_count) ; else
g_assertion_message_expr ("Ctk", "ctktreemodelfilter.c", 3568
, ((const char*) (__func__)), "elt->ref_count >= elt->ext_ref_count"
); } while (0)
;
3569 g_assert (elt->ref_count >= 0)do { if (elt->ref_count >= 0) ; else g_assertion_message_expr
("Ctk", "ctktreemodelfilter.c", 3569, ((const char*) (__func__
)), "elt->ref_count >= 0"); } while (0)
;
3570 g_assert (elt->ext_ref_count >= 0)do { if (elt->ext_ref_count >= 0) ; else g_assertion_message_expr
("Ctk", "ctktreemodelfilter.c", 3570, ((const char*) (__func__
)), "elt->ext_ref_count >= 0"); } while (0)
;
3571#endif
3572}
3573
3574/* TreeDragSource interface implementation */
3575static gboolean
3576ctk_tree_model_filter_row_draggable (CtkTreeDragSource *drag_source,
3577 CtkTreePath *path)
3578{
3579 CtkTreeModelFilter *tree_model_filter = (CtkTreeModelFilter *)drag_source;
3580 CtkTreePath *child_path;
3581 gboolean draggable;
3582
3583 g_return_val_if_fail (CTK_IS_TREE_MODEL_FILTER (drag_source), FALSE)do { if (((((__extension__ ({ GTypeInstance *__inst = (GTypeInstance
*) ((drag_source)); GType __t = ((ctk_tree_model_filter_get_type
())); gboolean __r; if (!__inst) __r = (0); else if (__inst->
g_class && __inst->g_class->g_type == __t) __r =
(!(0)); else __r = g_type_check_instance_is_a (__inst, __t);
__r; })))))) { } else { g_return_if_fail_warning ("Ctk", ((const
char*) (__func__)), "CTK_IS_TREE_MODEL_FILTER (drag_source)"
); return ((0)); } } while (0)
;
3584 g_return_val_if_fail (path != NULL, FALSE)do { if ((path != ((void*)0))) { } else { g_return_if_fail_warning
("Ctk", ((const char*) (__func__)), "path != NULL"); return (
(0)); } } while (0)
;
3585
3586 child_path = ctk_tree_model_filter_convert_path_to_child_path (tree_model_filter, path);
3587 draggable = ctk_tree_drag_source_row_draggable (CTK_TREE_DRAG_SOURCE (tree_model_filter->priv->child_model)((((CtkTreeDragSource*) (void *) g_type_check_instance_cast (
(GTypeInstance*) ((tree_model_filter->priv->child_model
)), ((ctk_tree_drag_source_get_type ()))))))
, child_path);
3588 ctk_tree_path_free (child_path);
3589
3590 return draggable;
3591}
3592
3593static gboolean
3594ctk_tree_model_filter_drag_data_get (CtkTreeDragSource *drag_source,
3595 CtkTreePath *path,
3596 CtkSelectionData *selection_data)
3597{
3598 CtkTreeModelFilter *tree_model_filter = (CtkTreeModelFilter *)drag_source;
3599 CtkTreePath *child_path;
3600 gboolean gotten;
3601
3602 g_return_val_if_fail (CTK_IS_TREE_MODEL_FILTER (drag_source), FALSE)do { if (((((__extension__ ({ GTypeInstance *__inst = (GTypeInstance
*) ((drag_source)); GType __t = ((ctk_tree_model_filter_get_type
())); gboolean __r; if (!__inst) __r = (0); else if (__inst->
g_class && __inst->g_class->g_type == __t) __r =
(!(0)); else __r = g_type_check_instance_is_a (__inst, __t);
__r; })))))) { } else { g_return_if_fail_warning ("Ctk", ((const
char*) (__func__)), "CTK_IS_TREE_MODEL_FILTER (drag_source)"
); return ((0)); } } while (0)
;
3603 g_return_val_if_fail (path != NULL, FALSE)do { if ((path != ((void*)0))) { } else { g_return_if_fail_warning
("Ctk", ((const char*) (__func__)), "path != NULL"); return (
(0)); } } while (0)
;
3604
3605 child_path = ctk_tree_model_filter_convert_path_to_child_path (tree_model_filter, path);
3606 gotten = ctk_tree_drag_source_drag_data_get (CTK_TREE_DRAG_SOURCE (tree_model_filter->priv->child_model)((((CtkTreeDragSource*) (void *) g_type_check_instance_cast (
(GTypeInstance*) ((tree_model_filter->priv->child_model
)), ((ctk_tree_drag_source_get_type ()))))))
, child_path, selection_data);
3607 ctk_tree_path_free (child_path);
3608
3609 return gotten;
3610}
3611
3612static gboolean
3613ctk_tree_model_filter_drag_data_delete (CtkTreeDragSource *drag_source,
3614 CtkTreePath *path)
3615{
3616 CtkTreeModelFilter *tree_model_filter = (CtkTreeModelFilter *)drag_source;
3617 CtkTreePath *child_path;
3618 gboolean deleted;
3619
3620 g_return_val_if_fail (CTK_IS_TREE_MODEL_FILTER (drag_source), FALSE)do { if (((((__extension__ ({ GTypeInstance *__inst = (GTypeInstance
*) ((drag_source)); GType __t = ((ctk_tree_model_filter_get_type
())); gboolean __r; if (!__inst) __r = (0); else if (__inst->
g_class && __inst->g_class->g_type == __t) __r =
(!(0)); else __r = g_type_check_instance_is_a (__inst, __t);
__r; })))))) { } else { g_return_if_fail_warning ("Ctk", ((const
char*) (__func__)), "CTK_IS_TREE_MODEL_FILTER (drag_source)"
); return ((0)); } } while (0)
;
3621 g_return_val_if_fail (path != NULL, FALSE)do { if ((path != ((void*)0))) { } else { g_return_if_fail_warning
("Ctk", ((const char*) (__func__)), "path != NULL"); return (
(0)); } } while (0)
;
3622
3623 child_path = ctk_tree_model_filter_convert_path_to_child_path (tree_model_filter, path);
3624 deleted = ctk_tree_drag_source_drag_data_delete (CTK_TREE_DRAG_SOURCE (tree_model_filter->priv->child_model)((((CtkTreeDragSource*) (void *) g_type_check_instance_cast (
(GTypeInstance*) ((tree_model_filter->priv->child_model
)), ((ctk_tree_drag_source_get_type ()))))))
, child_path);
3625 ctk_tree_path_free (child_path);
3626
3627 return deleted;
3628}
3629
3630/* bits and pieces */
3631static void
3632ctk_tree_model_filter_set_model (CtkTreeModelFilter *filter,
3633 CtkTreeModel *child_model)
3634{
3635 g_return_if_fail (CTK_IS_TREE_MODEL_FILTER (filter))do { if (((((__extension__ ({ GTypeInstance *__inst = (GTypeInstance
*) ((filter)); GType __t = ((ctk_tree_model_filter_get_type (
))); gboolean __r; if (!__inst) __r = (0); else if (__inst->
g_class && __inst->g_class->g_type == __t) __r =
(!(0)); else __r = g_type_check_instance_is_a (__inst, __t);
__r; })))))) { } else { g_return_if_fail_warning ("Ctk", ((const
char*) (__func__)), "CTK_IS_TREE_MODEL_FILTER (filter)"); return
; } } while (0)
;
3636
3637 if (filter->priv->child_model)
3638 {
3639 g_signal_handler_disconnect (filter->priv->child_model,
3640 filter->priv->changed_id);
3641 g_signal_handler_disconnect (filter->priv->child_model,
3642 filter->priv->inserted_id);
3643 g_signal_handler_disconnect (filter->priv->child_model,
3644 filter->priv->has_child_toggled_id);
3645 g_signal_handler_disconnect (filter->priv->child_model,
3646 filter->priv->deleted_id);
3647 g_signal_handler_disconnect (filter->priv->child_model,
3648 filter->priv->reordered_id);
3649
3650 /* reset our state */
3651 if (filter->priv->root)
3652 ctk_tree_model_filter_free_level (filter, filter->priv->root,
3653 TRUE(!(0)), TRUE(!(0)), FALSE(0));
3654
3655 filter->priv->root = NULL((void*)0);
3656 g_object_unref (filter->priv->child_model);
3657 filter->priv->visible_column = -1;
3658
3659 /* FIXME: do we need to destroy more here? */
3660 }
3661
3662 filter->priv->child_model = child_model;
3663
3664 if (child_model)
3665 {
3666 g_object_ref (filter->priv->child_model)((__typeof__ (filter->priv->child_model)) (g_object_ref
) (filter->priv->child_model))
;
3667 filter->priv->changed_id =
3668 g_signal_connect (child_model, "row-changed",g_signal_connect_data ((child_model), ("row-changed"), (((GCallback
) (ctk_tree_model_filter_row_changed))), (filter), ((void*)0)
, (GConnectFlags) 0)
3669 G_CALLBACK (ctk_tree_model_filter_row_changed),g_signal_connect_data ((child_model), ("row-changed"), (((GCallback
) (ctk_tree_model_filter_row_changed))), (filter), ((void*)0)
, (GConnectFlags) 0)
3670 filter)g_signal_connect_data ((child_model), ("row-changed"), (((GCallback
) (ctk_tree_model_filter_row_changed))), (filter), ((void*)0)
, (GConnectFlags) 0)
;
3671 filter->priv->inserted_id =
3672 g_signal_connect (child_model, "row-inserted",g_signal_connect_data ((child_model), ("row-inserted"), (((GCallback
) (ctk_tree_model_filter_row_inserted))), (filter), ((void*)0
), (GConnectFlags) 0)
3673 G_CALLBACK (ctk_tree_model_filter_row_inserted),g_signal_connect_data ((child_model), ("row-inserted"), (((GCallback
) (ctk_tree_model_filter_row_inserted))), (filter), ((void*)0
), (GConnectFlags) 0)
3674 filter)g_signal_connect_data ((child_model), ("row-inserted"), (((GCallback
) (ctk_tree_model_filter_row_inserted))), (filter), ((void*)0
), (GConnectFlags) 0)
;
3675 filter->priv->has_child_toggled_id =
3676 g_signal_connect (child_model, "row-has-child-toggled",g_signal_connect_data ((child_model), ("row-has-child-toggled"
), (((GCallback) (ctk_tree_model_filter_row_has_child_toggled
))), (filter), ((void*)0), (GConnectFlags) 0)
3677 G_CALLBACK (ctk_tree_model_filter_row_has_child_toggled),g_signal_connect_data ((child_model), ("row-has-child-toggled"
), (((GCallback) (ctk_tree_model_filter_row_has_child_toggled
))), (filter), ((void*)0), (GConnectFlags) 0)
3678 filter)g_signal_connect_data ((child_model), ("row-has-child-toggled"
), (((GCallback) (ctk_tree_model_filter_row_has_child_toggled
))), (filter), ((void*)0), (GConnectFlags) 0)
;
3679 filter->priv->deleted_id =
3680 g_signal_connect (child_model, "row-deleted",g_signal_connect_data ((child_model), ("row-deleted"), (((GCallback
) (ctk_tree_model_filter_row_deleted))), (filter), ((void*)0)
, (GConnectFlags) 0)
3681 G_CALLBACK (ctk_tree_model_filter_row_deleted),g_signal_connect_data ((child_model), ("row-deleted"), (((GCallback
) (ctk_tree_model_filter_row_deleted))), (filter), ((void*)0)
, (GConnectFlags) 0)
3682 filter)g_signal_connect_data ((child_model), ("row-deleted"), (((GCallback
) (ctk_tree_model_filter_row_deleted))), (filter), ((void*)0)
, (GConnectFlags) 0)
;
3683 filter->priv->reordered_id =
3684 g_signal_connect (child_model, "rows-reordered",g_signal_connect_data ((child_model), ("rows-reordered"), (((
GCallback) (ctk_tree_model_filter_rows_reordered))), (filter)
, ((void*)0), (GConnectFlags) 0)
3685 G_CALLBACK (ctk_tree_model_filter_rows_reordered),g_signal_connect_data ((child_model), ("rows-reordered"), (((
GCallback) (ctk_tree_model_filter_rows_reordered))), (filter)
, ((void*)0), (GConnectFlags) 0)
3686 filter)g_signal_connect_data ((child_model), ("rows-reordered"), (((
GCallback) (ctk_tree_model_filter_rows_reordered))), (filter)
, ((void*)0), (GConnectFlags) 0)
;
3687
3688 filter->priv->child_flags = ctk_tree_model_get_flags (child_model);
3689 filter->priv->stamp = g_random_int ();
3690 }
3691}
3692
3693static void
3694ctk_tree_model_filter_ref_path (CtkTreeModelFilter *filter,
3695 CtkTreePath *path)
3696{
3697 int len;
3698 CtkTreePath *p;
3699
3700 len = ctk_tree_path_get_depth (path);
3701 p = ctk_tree_path_copy (path);
3702 while (len--)
3703 {
3704 CtkTreeIter iter;
3705
3706 ctk_tree_model_get_iter (CTK_TREE_MODEL (filter->priv->child_model)((((CtkTreeModel*) (void *) g_type_check_instance_cast ((GTypeInstance
*) ((filter->priv->child_model)), ((ctk_tree_model_get_type
()))))))
, &iter, p);
3707 ctk_tree_model_ref_node (CTK_TREE_MODEL (filter->priv->child_model)((((CtkTreeModel*) (void *) g_type_check_instance_cast ((GTypeInstance
*) ((filter->priv->child_model)), ((ctk_tree_model_get_type
()))))))
, &iter);
3708 ctk_tree_path_up (p);
3709 }
3710
3711 ctk_tree_path_free (p);
3712}
3713
3714static void
3715ctk_tree_model_filter_unref_path (CtkTreeModelFilter *filter,
3716 CtkTreePath *path,
3717 int depth)
3718{
3719 int len;
3720 CtkTreePath *p;
3721
3722 if (depth != -1)
3723 len = depth;
3724 else
3725 len = ctk_tree_path_get_depth (path);
3726
3727 p = ctk_tree_path_copy (path);
3728 while (len--)
3729 {
3730 CtkTreeIter iter;
3731
3732 ctk_tree_model_get_iter (CTK_TREE_MODEL (filter->priv->child_model)((((CtkTreeModel*) (void *) g_type_check_instance_cast ((GTypeInstance
*) ((filter->priv->child_model)), ((ctk_tree_model_get_type
()))))))
, &iter, p);
3733 ctk_tree_model_unref_node (CTK_TREE_MODEL (filter->priv->child_model)((((CtkTreeModel*) (void *) g_type_check_instance_cast ((GTypeInstance
*) ((filter->priv->child_model)), ((ctk_tree_model_get_type
()))))))
, &iter);
3734 ctk_tree_path_up (p);
3735 }
3736
3737 ctk_tree_path_free (p);
3738}
3739
3740static void
3741ctk_tree_model_filter_set_root (CtkTreeModelFilter *filter,
3742 CtkTreePath *root)
3743{
3744 g_return_if_fail (CTK_IS_TREE_MODEL_FILTER (filter))do { if (((((__extension__ ({ GTypeInstance *__inst = (GTypeInstance
*) ((filter)); GType __t = ((ctk_tree_model_filter_get_type (
))); gboolean __r; if (!__inst) __r = (0); else if (__inst->
g_class && __inst->g_class->g_type == __t) __r =
(!(0)); else __r = g_type_check_instance_is_a (__inst, __t);
__r; })))))) { } else { g_return_if_fail_warning ("Ctk", ((const
char*) (__func__)), "CTK_IS_TREE_MODEL_FILTER (filter)"); return
; } } while (0)
;
3745
3746 if (root)
3747 {
3748 filter->priv->virtual_root = ctk_tree_path_copy (root);
3749 ctk_tree_model_filter_ref_path (filter, filter->priv->virtual_root);
3750 filter->priv->virtual_root_deleted = FALSE(0);
3751 }
3752 else
3753 filter->priv->virtual_root = NULL((void*)0);
3754}
3755
3756/* public API */
3757
3758/**
3759 * ctk_tree_model_filter_new:
3760 * @child_model: A #CtkTreeModel.
3761 * @root: (allow-none): A #CtkTreePath or %NULL.
3762 *
3763 * Creates a new #CtkTreeModel, with @child_model as the child_model
3764 * and @root as the virtual root.
3765 *
3766 * Returns: (transfer full): A new #CtkTreeModel.
3767 *
3768 * Since: 2.4
3769 */
3770CtkTreeModel *
3771ctk_tree_model_filter_new (CtkTreeModel *child_model,
3772 CtkTreePath *root)
3773{
3774 g_return_val_if_fail (CTK_IS_TREE_MODEL (child_model), NULL)do { if (((((__extension__ ({ GTypeInstance *__inst = (GTypeInstance
*) ((child_model)); GType __t = ((ctk_tree_model_get_type ())
); gboolean __r; if (!__inst) __r = (0); else if (__inst->
g_class && __inst->g_class->g_type == __t) __r =
(!(0)); else __r = g_type_check_instance_is_a (__inst, __t);
__r; })))))) { } else { g_return_if_fail_warning ("Ctk", ((const
char*) (__func__)), "CTK_IS_TREE_MODEL (child_model)"); return
(((void*)0)); } } while (0)
;
3775
3776 return g_object_new (CTK_TYPE_TREE_MODEL_FILTER(ctk_tree_model_filter_get_type ()),
3777 "child-model", child_model,
3778 "virtual-root", root,
3779 NULL((void*)0));
3780}
3781
3782/**
3783 * ctk_tree_model_filter_get_model:
3784 * @filter: A #CtkTreeModelFilter.
3785 *
3786 * Returns a pointer to the child model of @filter.
3787 *
3788 * Returns: (transfer none): A pointer to a #CtkTreeModel.
3789 *
3790 * Since: 2.4
3791 */
3792CtkTreeModel *
3793ctk_tree_model_filter_get_model (CtkTreeModelFilter *filter)
3794{
3795 g_return_val_if_fail (CTK_IS_TREE_MODEL_FILTER (filter), NULL)do { if (((((__extension__ ({ GTypeInstance *__inst = (GTypeInstance
*) ((filter)); GType __t = ((ctk_tree_model_filter_get_type (
))); gboolean __r; if (!__inst) __r = (0); else if (__inst->
g_class && __inst->g_class->g_type == __t) __r =
(!(0)); else __r = g_type_check_instance_is_a (__inst, __t);
__r; })))))) { } else { g_return_if_fail_warning ("Ctk", ((const
char*) (__func__)), "CTK_IS_TREE_MODEL_FILTER (filter)"); return
(((void*)0)); } } while (0)
;
3796
3797 return filter->priv->child_model;
3798}
3799
3800/**
3801 * ctk_tree_model_filter_set_visible_func:
3802 * @filter: A #CtkTreeModelFilter
3803 * @func: A #CtkTreeModelFilterVisibleFunc, the visible function
3804 * @data: (allow-none): User data to pass to the visible function, or %NULL
3805 * @destroy: (allow-none): Destroy notifier of @data, or %NULL
3806 *
3807 * Sets the visible function used when filtering the @filter to be @func.
3808 * The function should return %TRUE if the given row should be visible and
3809 * %FALSE otherwise.
3810 *
3811 * If the condition calculated by the function changes over time (e.g.
3812 * because it depends on some global parameters), you must call
3813 * ctk_tree_model_filter_refilter() to keep the visibility information
3814 * of the model up-to-date.
3815 *
3816 * Note that @func is called whenever a row is inserted, when it may still
3817 * be empty. The visible function should therefore take special care of empty
3818 * rows, like in the example below.
3819 *
3820 * |[<!-- language="C" -->
3821 * static gboolean
3822 * visible_func (CtkTreeModel *model,
3823 * CtkTreeIter *iter,
3824 * gpointer data)
3825 * {
3826 * // Visible if row is non-empty and first column is “HI”
3827 * gchar *str;
3828 * gboolean visible = FALSE;
3829 *
3830 * ctk_tree_model_get (model, iter, 0, &str, -1);
3831 * if (str && strcmp (str, "HI") == 0)
3832 * visible = TRUE;
3833 * g_free (str);
3834 *
3835 * return visible;
3836 * }
3837 * ]|
3838 *
3839 * Note that ctk_tree_model_filter_set_visible_func() or
3840 * ctk_tree_model_filter_set_visible_column() can only be called
3841 * once for a given filter model.
3842 *
3843 * Since: 2.4
3844 */
3845void
3846ctk_tree_model_filter_set_visible_func (CtkTreeModelFilter *filter,
3847 CtkTreeModelFilterVisibleFunc func,
3848 gpointer data,
3849 GDestroyNotify destroy)
3850{
3851 g_return_if_fail (CTK_IS_TREE_MODEL_FILTER (filter))do { if (((((__extension__ ({ GTypeInstance *__inst = (GTypeInstance
*) ((filter)); GType __t = ((ctk_tree_model_filter_get_type (
))); gboolean __r; if (!__inst) __r = (0); else if (__inst->
g_class && __inst->g_class->g_type == __t) __r =
(!(0)); else __r = g_type_check_instance_is_a (__inst, __t);
__r; })))))) { } else { g_return_if_fail_warning ("Ctk", ((const
char*) (__func__)), "CTK_IS_TREE_MODEL_FILTER (filter)"); return
; } } while (0)
;
3852 g_return_if_fail (func != NULL)do { if ((func != ((void*)0))) { } else { g_return_if_fail_warning
("Ctk", ((const char*) (__func__)), "func != NULL"); return;
} } while (0)
;
3853 g_return_if_fail (filter->priv->visible_method_set == FALSE)do { if ((filter->priv->visible_method_set == (0))) { }
else { g_return_if_fail_warning ("Ctk", ((const char*) (__func__
)), "filter->priv->visible_method_set == FALSE"); return
; } } while (0)
;
3854
3855 filter->priv->visible_func = func;
3856 filter->priv->visible_data = data;
3857 filter->priv->visible_destroy = destroy;
3858
3859 filter->priv->visible_method_set = TRUE(!(0));
3860}
3861
3862/**
3863 * ctk_tree_model_filter_set_modify_func:
3864 * @filter: A #CtkTreeModelFilter.
3865 * @n_columns: The number of columns in the filter model.
3866 * @types: (array length=n_columns): The #GTypes of the columns.
3867 * @func: A #CtkTreeModelFilterModifyFunc
3868 * @data: (allow-none): User data to pass to the modify function, or %NULL.
3869 * @destroy: (allow-none): Destroy notifier of @data, or %NULL.
3870 *
3871 * With the @n_columns and @types parameters, you give an array of column
3872 * types for this model (which will be exposed to the parent model/view).
3873 * The @func, @data and @destroy parameters are for specifying the modify
3874 * function. The modify function will get called for each
3875 * data access, the goal of the modify function is to return the data which
3876 * should be displayed at the location specified using the parameters of the
3877 * modify function.
3878 *
3879 * Note that ctk_tree_model_filter_set_modify_func()
3880 * can only be called once for a given filter model.
3881 *
3882 * Since: 2.4
3883 */
3884void
3885ctk_tree_model_filter_set_modify_func (CtkTreeModelFilter *filter,
3886 gint n_columns,
3887 GType *types,
3888 CtkTreeModelFilterModifyFunc func,
3889 gpointer data,
3890 GDestroyNotify destroy)
3891{
3892 g_return_if_fail (CTK_IS_TREE_MODEL_FILTER (filter))do { if (((((__extension__ ({ GTypeInstance *__inst = (GTypeInstance
*) ((filter)); GType __t = ((ctk_tree_model_filter_get_type (
))); gboolean __r; if (!__inst) __r = (0); else if (__inst->
g_class && __inst->g_class->g_type == __t) __r =
(!(0)); else __r = g_type_check_instance_is_a (__inst, __t);
__r; })))))) { } else { g_return_if_fail_warning ("Ctk", ((const
char*) (__func__)), "CTK_IS_TREE_MODEL_FILTER (filter)"); return
; } } while (0)
;
3893 g_return_if_fail (func != NULL)do { if ((func != ((void*)0))) { } else { g_return_if_fail_warning
("Ctk", ((const char*) (__func__)), "func != NULL"); return;
} } while (0)
;
3894 g_return_if_fail (filter->priv->modify_func_set == FALSE)do { if ((filter->priv->modify_func_set == (0))) { } else
{ g_return_if_fail_warning ("Ctk", ((const char*) (__func__)
), "filter->priv->modify_func_set == FALSE"); return; }
} while (0)
;
3895
3896 filter->priv->modify_n_columns = n_columns;
3897 filter->priv->modify_types = g_new0 (GType, n_columns)((GType *) g_malloc0_n ((n_columns), sizeof (GType)));
3898 memcpy (filter->priv->modify_types, types, sizeof (GType) * n_columns);
3899 filter->priv->modify_func = func;
3900 filter->priv->modify_data = data;
3901 filter->priv->modify_destroy = destroy;
3902
3903 filter->priv->modify_func_set = TRUE(!(0));
3904}
3905
3906/**
3907 * ctk_tree_model_filter_set_visible_column:
3908 * @filter: A #CtkTreeModelFilter
3909 * @column: A #gint which is the column containing the visible information
3910 *
3911 * Sets @column of the child_model to be the column where @filter should
3912 * look for visibility information. @columns should be a column of type
3913 * %G_TYPE_BOOLEAN, where %TRUE means that a row is visible, and %FALSE
3914 * if not.
3915 *
3916 * Note that ctk_tree_model_filter_set_visible_func() or
3917 * ctk_tree_model_filter_set_visible_column() can only be called
3918 * once for a given filter model.
3919 *
3920 * Since: 2.4
3921 */
3922void
3923ctk_tree_model_filter_set_visible_column (CtkTreeModelFilter *filter,
3924 gint column)
3925{
3926 g_return_if_fail (CTK_IS_TREE_MODEL_FILTER (filter))do { if (((((__extension__ ({ GTypeInstance *__inst = (GTypeInstance
*) ((filter)); GType __t = ((ctk_tree_model_filter_get_type (
))); gboolean __r; if (!__inst) __r = (0); else if (__inst->
g_class && __inst->g_class->g_type == __t) __r =
(!(0)); else __r = g_type_check_instance_is_a (__inst, __t);
__r; })))))) { } else { g_return_if_fail_warning ("Ctk", ((const
char*) (__func__)), "CTK_IS_TREE_MODEL_FILTER (filter)"); return
; } } while (0)
;
3927 g_return_if_fail (column >= 0)do { if ((column >= 0)) { } else { g_return_if_fail_warning
("Ctk", ((const char*) (__func__)), "column >= 0"); return
; } } while (0)
;
3928 g_return_if_fail (filter->priv->visible_method_set == FALSE)do { if ((filter->priv->visible_method_set == (0))) { }
else { g_return_if_fail_warning ("Ctk", ((const char*) (__func__
)), "filter->priv->visible_method_set == FALSE"); return
; } } while (0)
;
3929
3930 filter->priv->visible_column = column;
3931
3932 filter->priv->visible_method_set = TRUE(!(0));
3933}
3934
3935/* conversion */
3936
3937/**
3938 * ctk_tree_model_filter_convert_child_iter_to_iter:
3939 * @filter: A #CtkTreeModelFilter.
3940 * @filter_iter: (out): An uninitialized #CtkTreeIter.
3941 * @child_iter: A valid #CtkTreeIter pointing to a row on the child model.
3942 *
3943 * Sets @filter_iter to point to the row in @filter that corresponds to the
3944 * row pointed at by @child_iter. If @filter_iter was not set, %FALSE is
3945 * returned.
3946 *
3947 * Returns: %TRUE, if @filter_iter was set, i.e. if @child_iter is a
3948 * valid iterator pointing to a visible row in child model.
3949 *
3950 * Since: 2.4
3951 */
3952gboolean
3953ctk_tree_model_filter_convert_child_iter_to_iter (CtkTreeModelFilter *filter,
3954 CtkTreeIter *filter_iter,
3955 CtkTreeIter *child_iter)
3956{
3957 gboolean ret;
3958 CtkTreePath *child_path, *path;
3959
3960 g_return_val_if_fail (CTK_IS_TREE_MODEL_FILTER (filter), FALSE)do { if (((((__extension__ ({ GTypeInstance *__inst = (GTypeInstance
*) ((filter)); GType __t = ((ctk_tree_model_filter_get_type (
))); gboolean __r; if (!__inst) __r = (0); else if (__inst->
g_class && __inst->g_class->g_type == __t) __r =
(!(0)); else __r = g_type_check_instance_is_a (__inst, __t);
__r; })))))) { } else { g_return_if_fail_warning ("Ctk", ((const
char*) (__func__)), "CTK_IS_TREE_MODEL_FILTER (filter)"); return
((0)); } } while (0)
;
3961 g_return_val_if_fail (filter->priv->child_model != NULL, FALSE)do { if ((filter->priv->child_model != ((void*)0))) { }
else { g_return_if_fail_warning ("Ctk", ((const char*) (__func__
)), "filter->priv->child_model != NULL"); return ((0));
} } while (0)
;
3962 g_return_val_if_fail (filter_iter != NULL, FALSE)do { if ((filter_iter != ((void*)0))) { } else { g_return_if_fail_warning
("Ctk", ((const char*) (__func__)), "filter_iter != NULL"); return
((0)); } } while (0)
;
3963 g_return_val_if_fail (child_iter != NULL, FALSE)do { if ((child_iter != ((void*)0))) { } else { g_return_if_fail_warning
("Ctk", ((const char*) (__func__)), "child_iter != NULL"); return
((0)); } } while (0)
;
3964 g_return_val_if_fail (filter_iter != child_iter, FALSE)do { if ((filter_iter != child_iter)) { } else { g_return_if_fail_warning
("Ctk", ((const char*) (__func__)), "filter_iter != child_iter"
); return ((0)); } } while (0)
;
3965
3966 filter_iter->stamp = 0;
3967
3968 child_path = ctk_tree_model_get_path (filter->priv->child_model, child_iter);
3969 g_return_val_if_fail (child_path != NULL, FALSE)do { if ((child_path != ((void*)0))) { } else { g_return_if_fail_warning
("Ctk", ((const char*) (__func__)), "child_path != NULL"); return
((0)); } } while (0)
;
3970
3971 path = ctk_tree_model_filter_convert_child_path_to_path (filter,
3972 child_path);
3973 ctk_tree_path_free (child_path);
3974
3975 if (!path)
3976 return FALSE(0);
3977
3978 ret = ctk_tree_model_get_iter (CTK_TREE_MODEL (filter)((((CtkTreeModel*) (void *) g_type_check_instance_cast ((GTypeInstance
*) ((filter)), ((ctk_tree_model_get_type ()))))))
, filter_iter, path);
3979 ctk_tree_path_free (path);
3980
3981 return ret;
3982}
3983
3984/**
3985 * ctk_tree_model_filter_convert_iter_to_child_iter:
3986 * @filter: A #CtkTreeModelFilter.
3987 * @child_iter: (out): An uninitialized #CtkTreeIter.
3988 * @filter_iter: A valid #CtkTreeIter pointing to a row on @filter.
3989 *
3990 * Sets @child_iter to point to the row pointed to by @filter_iter.
3991 *
3992 * Since: 2.4
3993 */
3994void
3995ctk_tree_model_filter_convert_iter_to_child_iter (CtkTreeModelFilter *filter,
3996 CtkTreeIter *child_iter,
3997 CtkTreeIter *filter_iter)
3998{
3999 g_return_if_fail (CTK_IS_TREE_MODEL_FILTER (filter))do { if (((((__extension__ ({ GTypeInstance *__inst = (GTypeInstance
*) ((filter)); GType __t = ((ctk_tree_model_filter_get_type (
))); gboolean __r; if (!__inst) __r = (0); else if (__inst->
g_class && __inst->g_class->g_type == __t) __r =
(!(0)); else __r = g_type_check_instance_is_a (__inst, __t);
__r; })))))) { } else { g_return_if_fail_warning ("Ctk", ((const
char*) (__func__)), "CTK_IS_TREE_MODEL_FILTER (filter)"); return
; } } while (0)
;
4000 g_return_if_fail (filter->priv->child_model != NULL)do { if ((filter->priv->child_model != ((void*)0))) { }
else { g_return_if_fail_warning ("Ctk", ((const char*) (__func__
)), "filter->priv->child_model != NULL"); return; } } while
(0)
;
4001 g_return_if_fail (child_iter != NULL)do { if ((child_iter != ((void*)0))) { } else { g_return_if_fail_warning
("Ctk", ((const char*) (__func__)), "child_iter != NULL"); return
; } } while (0)
;
4002 g_return_if_fail (filter_iter != NULL)do { if ((filter_iter != ((void*)0))) { } else { g_return_if_fail_warning
("Ctk", ((const char*) (__func__)), "filter_iter != NULL"); return
; } } while (0)
;
4003 g_return_if_fail (filter_iter->stamp == filter->priv->stamp)do { if ((filter_iter->stamp == filter->priv->stamp)
) { } else { g_return_if_fail_warning ("Ctk", ((const char*) (
__func__)), "filter_iter->stamp == filter->priv->stamp"
); return; } } while (0)
;
4004 g_return_if_fail (filter_iter != child_iter)do { if ((filter_iter != child_iter)) { } else { g_return_if_fail_warning
("Ctk", ((const char*) (__func__)), "filter_iter != child_iter"
); return; } } while (0)
;
4005
4006 if (CTK_TREE_MODEL_FILTER_CACHE_CHILD_ITERS (filter)(((CtkTreeModelFilter *)filter)->priv->child_flags &
CTK_TREE_MODEL_ITERS_PERSIST)
)
4007 {
4008 *child_iter = FILTER_ELT (filter_iter->user_data2)((FilterElt *)filter_iter->user_data2)->iter;
4009 }
4010 else
4011 {
4012 CtkTreePath *path;
4013 gboolean valid = FALSE(0);
4014
4015 path = ctk_tree_model_filter_elt_get_path (filter_iter->user_data,
4016 filter_iter->user_data2,
4017 filter->priv->virtual_root);
4018 valid = ctk_tree_model_get_iter (filter->priv->child_model, child_iter,
4019 path);
4020 ctk_tree_path_free (path);
4021
4022 g_return_if_fail (valid == TRUE)do { if ((valid == (!(0)))) { } else { g_return_if_fail_warning
("Ctk", ((const char*) (__func__)), "valid == TRUE"); return
; } } while (0)
;
4023 }
4024}
4025
4026/* The path returned can only be used internally in the filter model. */
4027static CtkTreePath *
4028ctk_real_tree_model_filter_convert_child_path_to_path (CtkTreeModelFilter *filter,
4029 CtkTreePath *child_path,
4030 gboolean build_levels,
4031 gboolean fetch_children)
4032{
4033 gint *child_indices;
4034 CtkTreePath *retval;
4035 CtkTreePath *real_path;
4036 FilterLevel *level;
4037 FilterElt *tmp;
4038 gint i;
4039
4040 g_return_val_if_fail (CTK_IS_TREE_MODEL_FILTER (filter), NULL)do { if (((((__extension__ ({ GTypeInstance *__inst = (GTypeInstance
*) ((filter)); GType __t = ((ctk_tree_model_filter_get_type (
))); gboolean __r; if (!__inst) __r = (0); else if (__inst->
g_class && __inst->g_class->g_type == __t) __r =
(!(0)); else __r = g_type_check_instance_is_a (__inst, __t);
__r; })))))) { } else { g_return_if_fail_warning ("Ctk", ((const
char*) (__func__)), "CTK_IS_TREE_MODEL_FILTER (filter)"); return
(((void*)0)); } } while (0)
;
12
Taking false branch
13
Assuming field 'g_class' is null
14
Assuming the condition is true
15
Taking true branch
16
Loop condition is false. Exiting loop
4041 g_return_val_if_fail (filter->priv->child_model != NULL, NULL)do { if ((filter->priv->child_model != ((void*)0))) { }
else { g_return_if_fail_warning ("Ctk", ((const char*) (__func__
)), "filter->priv->child_model != NULL"); return (((void
*)0)); } } while (0)
;
17
Assuming field 'child_model' is not equal to null
18
Taking true branch
19
Loop condition is false. Exiting loop
4042 g_return_val_if_fail (child_path != NULL, NULL)do { if ((child_path != ((void*)0))) { } else { g_return_if_fail_warning
("Ctk", ((const char*) (__func__)), "child_path != NULL"); return
(((void*)0)); } } while (0)
;
20
Assuming 'child_path' is not equal to null
21
Taking true branch
22
Loop condition is false. Exiting loop
4043
4044 if (!filter->priv->virtual_root)
23
Assuming field 'virtual_root' is non-null, which participates in a condition later
24
Taking false branch
4045 real_path = ctk_tree_path_copy (child_path);
4046 else
4047 real_path = ctk_tree_model_filter_remove_root (child_path,
25
Calling 'ctk_tree_model_filter_remove_root'
33
Returning from 'ctk_tree_model_filter_remove_root'
4048 filter->priv->virtual_root);
4049
4050 if (!real_path)
34
Assuming 'real_path' is non-null, which participates in a condition later
35
Taking false branch
4051 return NULL((void*)0);
4052
4053 retval = ctk_tree_path_new ();
4054 child_indices = ctk_tree_path_get_indices (real_path);
4055
4056 if (filter->priv->root == NULL((void*)0) && build_levels)
36
Assuming field 'root' is not equal to NULL
4057 ctk_tree_model_filter_build_level (filter, NULL((void*)0), NULL((void*)0), FALSE(0));
4058 level = FILTER_LEVEL (filter->priv->root)((FilterLevel *)filter->priv->root);
4059
4060 for (i = 0; i < ctk_tree_path_get_depth (real_path); i++)
37
Assuming the condition is false
38
Loop condition is false. Execution continues on line 4114
4061 {
4062 GSequenceIter *siter;
4063 gboolean found_child = FALSE(0);
4064
4065 if (!level)
4066 {
4067 ctk_tree_path_free (real_path);
4068 ctk_tree_path_free (retval);
4069 return NULL((void*)0);
4070 }
4071
4072 tmp = lookup_elt_with_offset (level->seq, child_indices[i], &siter);
4073 if (tmp)
4074 {
4075 ctk_tree_path_append_index (retval, g_sequence_iter_get_position (siter));
4076 if (!tmp->children && build_levels)
4077 ctk_tree_model_filter_build_level (filter, level, tmp, FALSE(0));
4078 level = tmp->children;
4079 found_child = TRUE(!(0));
4080 }
4081
4082 if (!found_child && fetch_children)
4083 {
4084 int j;
4085
4086 tmp = ctk_tree_model_filter_fetch_child (filter, level,
4087 child_indices[i],
4088 &j);
4089
4090 /* didn't find the child, let's try to bring it back */
4091 if (!tmp || tmp->offset != child_indices[i])
4092 {
4093 /* not there */
4094 ctk_tree_path_free (real_path);
4095 ctk_tree_path_free (retval);
4096 return NULL((void*)0);
4097 }
4098
4099 ctk_tree_path_append_index (retval, j);
4100 if (!tmp->children && build_levels)
4101 ctk_tree_model_filter_build_level (filter, level, tmp, FALSE(0));
4102 level = tmp->children;
4103 found_child = TRUE(!(0));
4104 }
4105 else if (!found_child && !fetch_children)
4106 {
4107 /* no path */
4108 ctk_tree_path_free (real_path);
4109 ctk_tree_path_free (retval);
4110 return NULL((void*)0);
4111 }
4112 }
4113
4114 ctk_tree_path_free (real_path);
4115 return retval;
39
Returning pointer (loaded from 'retval'), which participates in a condition later
4116}
4117
4118/**
4119 * ctk_tree_model_filter_convert_child_path_to_path:
4120 * @filter: A #CtkTreeModelFilter.
4121 * @child_path: A #CtkTreePath to convert.
4122 *
4123 * Converts @child_path to a path relative to @filter. That is, @child_path
4124 * points to a path in the child model. The rerturned path will point to the
4125 * same row in the filtered model. If @child_path isn’t a valid path on the
4126 * child model or points to a row which is not visible in @filter, then %NULL
4127 * is returned.
4128 *
4129 * Returns: (nullable) (transfer full): A newly allocated #CtkTreePath, or %NULL.
4130 *
4131 * Since: 2.4
4132 */
4133CtkTreePath *
4134ctk_tree_model_filter_convert_child_path_to_path (CtkTreeModelFilter *filter,
4135 CtkTreePath *child_path)
4136{
4137 CtkTreeIter iter;
4138 CtkTreePath *path;
4139
4140 /* this function does the sanity checks */
4141 path = ctk_real_tree_model_filter_convert_child_path_to_path (filter,
4142 child_path,
4143 TRUE(!(0)),
4144 TRUE(!(0)));
4145
4146 if (!path)
4147 return NULL((void*)0);
4148
4149 /* get a new path which only takes visible nodes into account.
4150 * -- if this gives any performance issues, we can write a special
4151 * version of convert_child_path_to_path immediately returning
4152 * a visible-nodes-only path.
4153 */
4154 ctk_tree_model_filter_get_iter_full (CTK_TREE_MODEL (filter)((((CtkTreeModel*) (void *) g_type_check_instance_cast ((GTypeInstance
*) ((filter)), ((ctk_tree_model_get_type ()))))))
, &iter, path);
4155
4156 ctk_tree_path_free (path);
4157 path = ctk_tree_model_get_path (CTK_TREE_MODEL (filter)((((CtkTreeModel*) (void *) g_type_check_instance_cast ((GTypeInstance
*) ((filter)), ((ctk_tree_model_get_type ()))))))
, &iter);
4158
4159 return path;
4160}
4161
4162/**
4163 * ctk_tree_model_filter_convert_path_to_child_path:
4164 * @filter: A #CtkTreeModelFilter.
4165 * @filter_path: A #CtkTreePath to convert.
4166 *
4167 * Converts @filter_path to a path on the child model of @filter. That is,
4168 * @filter_path points to a location in @filter. The returned path will
4169 * point to the same location in the model not being filtered. If @filter_path
4170 * does not point to a location in the child model, %NULL is returned.
4171 *
4172 * Returns: (nullable) (transfer full): A newly allocated #CtkTreePath, or %NULL.
4173 *
4174 * Since: 2.4
4175 */
4176CtkTreePath *
4177ctk_tree_model_filter_convert_path_to_child_path (CtkTreeModelFilter *filter,
4178 CtkTreePath *filter_path)
4179{
4180 gint *filter_indices;
4181 CtkTreePath *retval;
4182 FilterLevel *level;
4183 gint i;
4184
4185 g_return_val_if_fail (CTK_IS_TREE_MODEL_FILTER (filter), NULL)do { if (((((__extension__ ({ GTypeInstance *__inst = (GTypeInstance
*) ((filter)); GType __t = ((ctk_tree_model_filter_get_type (
))); gboolean __r; if (!__inst) __r = (0); else if (__inst->
g_class && __inst->g_class->g_type == __t) __r =
(!(0)); else __r = g_type_check_instance_is_a (__inst, __t);
__r; })))))) { } else { g_return_if_fail_warning ("Ctk", ((const
char*) (__func__)), "CTK_IS_TREE_MODEL_FILTER (filter)"); return
(((void*)0)); } } while (0)
;
4186 g_return_val_if_fail (filter->priv->child_model != NULL, NULL)do { if ((filter->priv->child_model != ((void*)0))) { }
else { g_return_if_fail_warning ("Ctk", ((const char*) (__func__
)), "filter->priv->child_model != NULL"); return (((void
*)0)); } } while (0)
;
4187 g_return_val_if_fail (filter_path != NULL, NULL)do { if ((filter_path != ((void*)0))) { } else { g_return_if_fail_warning
("Ctk", ((const char*) (__func__)), "filter_path != NULL"); return
(((void*)0)); } } while (0)
;
4188
4189 /* convert path */
4190 retval = ctk_tree_path_new ();
4191 filter_indices = ctk_tree_path_get_indices (filter_path);
4192 if (!filter->priv->root)
4193 ctk_tree_model_filter_build_level (filter, NULL((void*)0), NULL((void*)0), FALSE(0));
4194 level = FILTER_LEVEL (filter->priv->root)((FilterLevel *)filter->priv->root);
4195
4196 for (i = 0; i < ctk_tree_path_get_depth (filter_path); i++)
4197 {
4198 FilterElt *elt;
4199 GSequenceIter *siter;
4200
4201 if (!level)
4202 {
4203 ctk_tree_path_free (retval);
4204 return NULL((void*)0);
4205 }
4206
4207 siter = g_sequence_get_iter_at_pos (level->visible_seq, filter_indices[i]);
4208 if (g_sequence_iter_is_end (siter))
4209 {
4210 ctk_tree_path_free (retval);
4211 return NULL((void*)0);
4212 }
4213
4214 elt = GET_ELT (siter)((FilterElt*) (siter ? g_sequence_get (siter) : ((void*)0)));
4215 if (elt->children == NULL((void*)0))
4216 ctk_tree_model_filter_build_level (filter, level, elt, FALSE(0));
4217
4218 ctk_tree_path_append_index (retval, elt->offset);
4219 level = elt->children;
4220 }
4221
4222 /* apply vroot */
4223
4224 if (filter->priv->virtual_root)
4225 {
4226 CtkTreePath *real_retval;
4227
4228 real_retval = ctk_tree_model_filter_add_root (retval,
4229 filter->priv->virtual_root);
4230 ctk_tree_path_free (retval);
4231
4232 return real_retval;
4233 }
4234
4235 return retval;
4236}
4237
4238static gboolean
4239ctk_tree_model_filter_refilter_helper (CtkTreeModel *model,
4240 CtkTreePath *path,
4241 CtkTreeIter *iter,
4242 gpointer data)
4243{
4244 /* evil, don't try this at home, but certainly speeds things up */
4245 ctk_tree_model_filter_row_changed (model, path, iter, data);
1
Calling 'ctk_tree_model_filter_row_changed'
4246
4247 return FALSE(0);
4248}
4249
4250/**
4251 * ctk_tree_model_filter_refilter:
4252 * @filter: A #CtkTreeModelFilter.
4253 *
4254 * Emits ::row_changed for each row in the child model, which causes
4255 * the filter to re-evaluate whether a row is visible or not.
4256 *
4257 * Since: 2.4
4258 */
4259void
4260ctk_tree_model_filter_refilter (CtkTreeModelFilter *filter)
4261{
4262 g_return_if_fail (CTK_IS_TREE_MODEL_FILTER (filter))do { if (((((__extension__ ({ GTypeInstance *__inst = (GTypeInstance
*) ((filter)); GType __t = ((ctk_tree_model_filter_get_type (
))); gboolean __r; if (!__inst) __r = (0); else if (__inst->
g_class && __inst->g_class->g_type == __t) __r =
(!(0)); else __r = g_type_check_instance_is_a (__inst, __t);
__r; })))))) { } else { g_return_if_fail_warning ("Ctk", ((const
char*) (__func__)), "CTK_IS_TREE_MODEL_FILTER (filter)"); return
; } } while (0)
;
4263
4264 /* S L O W */
4265 ctk_tree_model_foreach (filter->priv->child_model,
4266 ctk_tree_model_filter_refilter_helper,
4267 filter);
4268}
4269
4270/**
4271 * ctk_tree_model_filter_clear_cache:
4272 * @filter: A #CtkTreeModelFilter.
4273 *
4274 * This function should almost never be called. It clears the @filter
4275 * of any cached iterators that haven’t been reffed with
4276 * ctk_tree_model_ref_node(). This might be useful if the child model
4277 * being filtered is static (and doesn’t change often) and there has been
4278 * a lot of unreffed access to nodes. As a side effect of this function,
4279 * all unreffed iters will be invalid.
4280 *
4281 * Since: 2.4
4282 */
4283void
4284ctk_tree_model_filter_clear_cache (CtkTreeModelFilter *filter)
4285{
4286 g_return_if_fail (CTK_IS_TREE_MODEL_FILTER (filter))do { if (((((__extension__ ({ GTypeInstance *__inst = (GTypeInstance
*) ((filter)); GType __t = ((ctk_tree_model_filter_get_type (
))); gboolean __r; if (!__inst) __r = (0); else if (__inst->
g_class && __inst->g_class->g_type == __t) __r =
(!(0)); else __r = g_type_check_instance_is_a (__inst, __t);
__r; })))))) { } else { g_return_if_fail_warning ("Ctk", ((const
char*) (__func__)), "CTK_IS_TREE_MODEL_FILTER (filter)"); return
; } } while (0)
;
4287
4288 if (filter->priv->zero_ref_count > 0)
4289 ctk_tree_model_filter_clear_cache_helper (filter,
4290 FILTER_LEVEL (filter->priv->root)((FilterLevel *)filter->priv->root));
4291}