Bug Summary

File:ctk/ctktreemodelfilter.c
Warning:line 1933, column 9
Assigned value is garbage or undefined

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-172619-43637-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))
51
Assuming the condition is false
52
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++)
53
Assuming the condition is false
54
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++)
55
Assuming 'i' is >= 'depth'
56
Loop condition is false. Execution continues on line 1224
1222 ctk_tree_path_append_index (retval, indices[i]);
1223
1224 return retval;
57
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
38.1
Field 'root' is non-null
)
39
Taking false branch
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,
40
Calling 'ctk_real_tree_model_filter_convert_child_path_to_path'
64
Returning from 'ctk_real_tree_model_filter_convert_child_path_to_path'
1923 c_path,
1924 FALSE(0),
1925 TRUE(!(0)));
1926
1927 if (!path)
65
Assuming 'path' is non-null
66
Taking false branch
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)
;
67
Calling 'ctk_tree_model_filter_get_iter_full'
82
Returning from 'ctk_tree_model_filter_get_iter_full'
1932
1933 level = FILTER_LEVEL (iter.user_data)((FilterLevel *)iter.user_data);
83
Assigned value is garbage or undefined
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 field 'virtual_root' is null
8
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
8.1
'c_iter' is non-null
)
9
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
9.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,
10
Calling 'ctk_real_tree_model_filter_convert_child_path_to_path'
29
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)
30
Assuming 'path' is null
31
Taking false 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 ()))))))
,
2038 &iter, path);
2039 current_state = FILTER_ELT (iter.user_data2)((FilterElt *)iter.user_data2)->visible_siter != NULL((void*)0);
2040 }
2041 else
2042 current_state = FALSE(0);
2043
2044 if (current_state
31.1
'current_state' is equal to FALSE
== FALSE(0) && requested_state == FALSE(0))
32
Assuming 'requested_state' is not equal to FALSE
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)
;
33
Assuming the condition is true
34
Taking true branch
35
Loop condition is false. Exiting loop
2091
2092 if (real_path)
36
Assuming 'real_path' is null
37
Taking false branch
2093 ctk_tree_model_filter_check_ancestors (filter, real_path);
2094
2095 ctk_tree_model_filter_emit_row_inserted_for_path (filter, c_model,
38
Calling 'ctk_tree_model_filter_emit_row_inserted_for_path'
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)
;
68
Assuming '__inst' is non-null
69
Taking false branch
70
Assuming field 'g_class' is null
71
Assuming the condition is true
72
Taking true branch
73
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)
;
74
Assuming field 'child_model' is not equal to null
75
Taking true branch
76
Loop condition is false. Exiting loop
2976
2977 indices = ctk_tree_path_get_indices (path);
2978
2979 if (filter->priv->root == NULL((void*)0))
77
Assuming field 'root' is not equal to NULL
78
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)
79
Assuming 'depth' is 0
80
Taking true branch
2985 {
2986 iter->stamp = 0;
2987 return FALSE(0);
81
Returning without writing to 'iter->user_data'
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)
;
11
Taking false branch
12
Assuming field 'g_class' is null
13
Assuming the condition is true
14
Taking true branch
15
Loop condition is false. Exiting loop
41
Taking false branch
42
Assuming the condition is true
43
Taking true branch
44
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)
;
16
Assuming field 'child_model' is not equal to null
17
Taking true branch
18
Loop condition is false. Exiting loop
45
Taking true branch
46
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)
;
19
Assuming 'child_path' is not equal to null
20
Taking true branch
21
Loop condition is false. Exiting loop
47
Taking true branch
48
Loop condition is false. Exiting loop
4043
4044 if (!filter->priv->virtual_root
48.1
Field 'virtual_root' is non-null, which participates in a condition later
)
22
Assuming field 'virtual_root' is non-null
23
Taking false branch
49
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,
50
Calling 'ctk_tree_model_filter_remove_root'
58
Returning from 'ctk_tree_model_filter_remove_root'
4048 filter->priv->virtual_root);
4049
4050 if (!real_path)
24
Assuming 'real_path' is non-null
25
Taking false branch
59
Assuming 'real_path' is non-null, which participates in a condition later
60
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
60.1
Field 'root' is not equal to NULL
== NULL((void*)0)
&& build_levels)
26
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++)
27
Assuming the condition is false
28
Loop condition is false. Execution continues on line 4114
61
Assuming the condition is false
62
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;
63
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}