1 /* gtktreestore.c
2  * Copyright (C) 2000  Red Hat, Inc.,  Jonathan Blandford <jrb@redhat.com>
3  *
4  * This library is free software; you can redistribute it and/or
5  * modify it under the terms of the GNU Library General Public
6  * License as published by the Free Software Foundation; either
7  * version 2 of the License, or (at your option) any later version.
8  *
9  * This library is distributed in the hope that it will be useful,
10  * but WITHOUT ANY WARRANTY; without even the implied warranty of
11  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
12  * Library General Public License for more details.
13  *
14  * You should have received a copy of the GNU Library General Public
15  * License along with this library. If not, see <http://www.gnu.org/licenses/>.
16  */
17 
18 #include "config.h"
19 
20 #include "gtktreemodelcssnode.h"
21 #include "gtk/gtkcsstransientnodeprivate.h"
22 
23 struct _GtkTreeModelCssNodePrivate
24 {
25   GtkTreeModelCssNodeGetFunc    get_func;
26   gint                          n_columns;
27   GType                        *column_types;
28 
29   GtkCssNode                   *root;
30 };
31 
32 static void gtk_tree_model_css_node_connect_node    (GtkTreeModelCssNode *model,
33                                                      GtkCssNode          *node,
34                                                      gboolean             emit_signal);
35 
36 static void gtk_tree_model_css_node_disconnect_node (GtkTreeModelCssNode *model,
37                                                      GtkCssNode          *node,
38                                                      gboolean             emit_signal,
39                                                      GtkCssNode          *parent,
40                                                      GtkCssNode          *previous);
41 
42 static void gtk_tree_model_css_node_tree_model_init (GtkTreeModelIface   *iface);
43 
G_DEFINE_TYPE_WITH_CODE(GtkTreeModelCssNode,gtk_tree_model_css_node,G_TYPE_OBJECT,G_ADD_PRIVATE (GtkTreeModelCssNode)G_IMPLEMENT_INTERFACE (GTK_TYPE_TREE_MODEL,gtk_tree_model_css_node_tree_model_init))44 G_DEFINE_TYPE_WITH_CODE (GtkTreeModelCssNode, gtk_tree_model_css_node, G_TYPE_OBJECT,
45                          G_ADD_PRIVATE (GtkTreeModelCssNode)
46 			 G_IMPLEMENT_INTERFACE (GTK_TYPE_TREE_MODEL,
47 						gtk_tree_model_css_node_tree_model_init))
48 
49 static GtkCssNode *
50 get_nth_child (GtkCssNode *node,
51                gint        i)
52 {
53   for (node = gtk_css_node_get_first_child (node);
54        node != NULL && i > 0;
55        node = gtk_css_node_get_next_sibling (node))
56     i--;
57 
58   return node;
59 }
60 
61 static int
get_node_index(GtkCssNode * node)62 get_node_index (GtkCssNode *node)
63 {
64   int result = 0;
65 
66   while ((node = gtk_css_node_get_previous_sibling (node)))
67     result++;
68 
69   return result;
70 }
71 
72 static GtkTreeModelFlags
gtk_tree_model_css_node_get_flags(GtkTreeModel * tree_model)73 gtk_tree_model_css_node_get_flags (GtkTreeModel *tree_model)
74 {
75   return GTK_TREE_MODEL_ITERS_PERSIST;
76 }
77 
78 static gint
gtk_tree_model_css_node_get_n_columns(GtkTreeModel * tree_model)79 gtk_tree_model_css_node_get_n_columns (GtkTreeModel *tree_model)
80 {
81   GtkTreeModelCssNode *nodemodel = GTK_TREE_MODEL_CSS_NODE (tree_model);
82   GtkTreeModelCssNodePrivate *priv = nodemodel->priv;
83 
84   return priv->n_columns;
85 }
86 
87 static GType
gtk_tree_model_css_node_get_column_type(GtkTreeModel * tree_model,gint column)88 gtk_tree_model_css_node_get_column_type (GtkTreeModel *tree_model,
89                                          gint          column)
90 {
91   GtkTreeModelCssNode *nodemodel = GTK_TREE_MODEL_CSS_NODE (tree_model);
92   GtkTreeModelCssNodePrivate *priv = nodemodel->priv;
93 
94   g_return_val_if_fail (column < priv->n_columns, G_TYPE_INVALID);
95 
96   return priv->column_types[column];
97 }
98 
99 static gboolean
gtk_tree_model_css_node_get_iter(GtkTreeModel * tree_model,GtkTreeIter * iter,GtkTreePath * path)100 gtk_tree_model_css_node_get_iter (GtkTreeModel *tree_model,
101                                   GtkTreeIter  *iter,
102                                   GtkTreePath  *path)
103 {
104   GtkTreeModelCssNode *nodemodel = GTK_TREE_MODEL_CSS_NODE (tree_model);
105   GtkTreeModelCssNodePrivate *priv = nodemodel->priv;
106   GtkCssNode *node;
107   int *indices;
108   int depth, i;
109 
110   if (priv->root == NULL)
111     return FALSE;
112 
113   indices = gtk_tree_path_get_indices (path);
114   depth = gtk_tree_path_get_depth (path);
115 
116   if (depth < 1 || indices[0] != 0)
117     return FALSE;
118 
119   node = priv->root;
120   for (i = 1; i < depth; i++)
121     {
122       node = get_nth_child (node, indices[i]);
123       if (node == NULL)
124         return FALSE;
125     }
126 
127   gtk_tree_model_css_node_get_iter_from_node (nodemodel, iter, node);
128   return TRUE;
129 }
130 
131 static GtkTreePath *
gtk_tree_model_css_node_get_path(GtkTreeModel * tree_model,GtkTreeIter * iter)132 gtk_tree_model_css_node_get_path (GtkTreeModel *tree_model,
133 			          GtkTreeIter  *iter)
134 {
135   GtkTreeModelCssNode *nodemodel = GTK_TREE_MODEL_CSS_NODE (tree_model);
136   GtkTreeModelCssNodePrivate *priv = nodemodel->priv;
137   GtkCssNode *node;
138   GtkTreePath *path;
139 
140   g_return_val_if_fail (priv->root != NULL, NULL);
141 
142   path = gtk_tree_path_new ();
143   node = gtk_tree_model_css_node_get_node_from_iter (nodemodel, iter);
144 
145   while (node != priv->root)
146     {
147       gtk_tree_path_prepend_index (path, get_node_index (node));
148       node = gtk_css_node_get_parent (node);
149     }
150 
151   gtk_tree_path_prepend_index (path, 0);
152 
153   return path;
154 }
155 
156 static void
gtk_tree_model_css_node_get_value(GtkTreeModel * tree_model,GtkTreeIter * iter,gint column,GValue * value)157 gtk_tree_model_css_node_get_value (GtkTreeModel *tree_model,
158                                    GtkTreeIter  *iter,
159                                    gint          column,
160                                    GValue       *value)
161 {
162   GtkTreeModelCssNode *nodemodel = GTK_TREE_MODEL_CSS_NODE (tree_model);
163   GtkTreeModelCssNodePrivate *priv = nodemodel->priv;
164 
165   g_value_init (value, priv->column_types[column]);
166   priv->get_func (nodemodel,
167                   gtk_tree_model_css_node_get_node_from_iter (nodemodel, iter),
168                   column,
169                   value);
170 }
171 
172 static gboolean
gtk_tree_model_css_node_iter_next(GtkTreeModel * tree_model,GtkTreeIter * iter)173 gtk_tree_model_css_node_iter_next (GtkTreeModel  *tree_model,
174 			           GtkTreeIter   *iter)
175 {
176   GtkTreeModelCssNode *nodemodel = GTK_TREE_MODEL_CSS_NODE (tree_model);
177   GtkTreeModelCssNodePrivate *priv = nodemodel->priv;
178   GtkCssNode *node;
179 
180   node = gtk_tree_model_css_node_get_node_from_iter (nodemodel, iter);
181   if (node == priv->root)
182     return FALSE;
183 
184   node = gtk_css_node_get_next_sibling (node);
185   if (node == NULL)
186     return FALSE;
187 
188   gtk_tree_model_css_node_get_iter_from_node (nodemodel, iter, node);
189   return TRUE;
190 }
191 
192 static gboolean
gtk_tree_model_css_node_iter_previous(GtkTreeModel * tree_model,GtkTreeIter * iter)193 gtk_tree_model_css_node_iter_previous (GtkTreeModel  *tree_model,
194 			               GtkTreeIter   *iter)
195 {
196   GtkTreeModelCssNode *nodemodel = GTK_TREE_MODEL_CSS_NODE (tree_model);
197   GtkTreeModelCssNodePrivate *priv = nodemodel->priv;
198   GtkCssNode *node;
199 
200   node = gtk_tree_model_css_node_get_node_from_iter (nodemodel, iter);
201   if (node == priv->root)
202     return FALSE;
203 
204   node = gtk_css_node_get_previous_sibling (node);
205   if (node == NULL)
206     return FALSE;
207 
208   gtk_tree_model_css_node_get_iter_from_node (nodemodel, iter, node);
209   return TRUE;
210 }
211 
212 static gboolean
gtk_tree_model_css_node_iter_children(GtkTreeModel * tree_model,GtkTreeIter * iter,GtkTreeIter * parent)213 gtk_tree_model_css_node_iter_children (GtkTreeModel *tree_model,
214                                        GtkTreeIter  *iter,
215                                        GtkTreeIter  *parent)
216 {
217   GtkTreeModelCssNode *nodemodel = GTK_TREE_MODEL_CSS_NODE (tree_model);
218   GtkTreeModelCssNodePrivate *priv = nodemodel->priv;
219   GtkCssNode *node;
220 
221   if (parent == NULL)
222     {
223       node = priv->root;
224     }
225   else
226     {
227       node = gtk_tree_model_css_node_get_node_from_iter (nodemodel, parent);
228       node = gtk_css_node_get_first_child (node);
229     }
230   if (node == NULL)
231     return FALSE;
232 
233   gtk_tree_model_css_node_get_iter_from_node (nodemodel, iter, node);
234   return TRUE;
235 }
236 
237 static gboolean
gtk_tree_model_css_node_iter_has_child(GtkTreeModel * tree_model,GtkTreeIter * iter)238 gtk_tree_model_css_node_iter_has_child (GtkTreeModel *tree_model,
239 			                GtkTreeIter  *iter)
240 {
241   GtkTreeModelCssNode *nodemodel = GTK_TREE_MODEL_CSS_NODE (tree_model);
242   GtkCssNode *node;
243 
244   node = gtk_tree_model_css_node_get_node_from_iter (nodemodel, iter);
245 
246   return gtk_css_node_get_first_child (node) != NULL;
247 }
248 
249 static gint
gtk_tree_model_css_node_iter_n_children(GtkTreeModel * tree_model,GtkTreeIter * iter)250 gtk_tree_model_css_node_iter_n_children (GtkTreeModel *tree_model,
251                                          GtkTreeIter  *iter)
252 {
253   GtkTreeModelCssNode *nodemodel = GTK_TREE_MODEL_CSS_NODE (tree_model);
254   GtkTreeModelCssNodePrivate *priv = nodemodel->priv;
255   GtkCssNode *node;
256 
257   if (iter == NULL)
258     return priv->root ? 1 : 0;
259 
260   node = gtk_tree_model_css_node_get_node_from_iter (nodemodel, iter);
261 
262   node = gtk_css_node_get_last_child (node);
263   if (node == NULL)
264     return 0;
265 
266   return get_node_index (node) + 1;
267 }
268 
269 static gboolean
gtk_tree_model_css_node_iter_nth_child(GtkTreeModel * tree_model,GtkTreeIter * iter,GtkTreeIter * parent,gint n)270 gtk_tree_model_css_node_iter_nth_child (GtkTreeModel *tree_model,
271                                         GtkTreeIter  *iter,
272                                         GtkTreeIter  *parent,
273                                         gint          n)
274 {
275   GtkTreeModelCssNode *nodemodel = GTK_TREE_MODEL_CSS_NODE (tree_model);
276   GtkTreeModelCssNodePrivate *priv = nodemodel->priv;
277   GtkCssNode *node;
278 
279   if (parent == NULL)
280     {
281       if (n > 0)
282         return FALSE;
283 
284       node = priv->root;
285     }
286   else
287     {
288       node = gtk_tree_model_css_node_get_node_from_iter (nodemodel, parent);
289       node = get_nth_child (node, n);
290     }
291 
292   if (node == NULL)
293     return FALSE;
294 
295   gtk_tree_model_css_node_get_iter_from_node (nodemodel, iter, node);
296   return TRUE;
297 }
298 
299 static gboolean
gtk_tree_model_css_node_iter_parent(GtkTreeModel * tree_model,GtkTreeIter * iter,GtkTreeIter * child)300 gtk_tree_model_css_node_iter_parent (GtkTreeModel *tree_model,
301                                      GtkTreeIter  *iter,
302                                      GtkTreeIter  *child)
303 {
304   GtkTreeModelCssNode *nodemodel = GTK_TREE_MODEL_CSS_NODE (tree_model);
305   GtkTreeModelCssNodePrivate *priv = nodemodel->priv;
306   GtkCssNode *node;
307 
308   node = gtk_tree_model_css_node_get_node_from_iter (nodemodel, child);
309   if (node == priv->root)
310     return FALSE;
311 
312   node = gtk_css_node_get_parent (node);
313 
314   gtk_tree_model_css_node_get_iter_from_node (nodemodel, iter, node);
315   return TRUE;
316 }
317 
318 static void
gtk_tree_model_css_node_tree_model_init(GtkTreeModelIface * iface)319 gtk_tree_model_css_node_tree_model_init (GtkTreeModelIface *iface)
320 {
321   iface->get_flags = gtk_tree_model_css_node_get_flags;
322   iface->get_n_columns = gtk_tree_model_css_node_get_n_columns;
323   iface->get_column_type = gtk_tree_model_css_node_get_column_type;
324   iface->get_iter = gtk_tree_model_css_node_get_iter;
325   iface->get_path = gtk_tree_model_css_node_get_path;
326   iface->get_value = gtk_tree_model_css_node_get_value;
327   iface->iter_next = gtk_tree_model_css_node_iter_next;
328   iface->iter_previous = gtk_tree_model_css_node_iter_previous;
329   iface->iter_children = gtk_tree_model_css_node_iter_children;
330   iface->iter_has_child = gtk_tree_model_css_node_iter_has_child;
331   iface->iter_n_children = gtk_tree_model_css_node_iter_n_children;
332   iface->iter_nth_child = gtk_tree_model_css_node_iter_nth_child;
333   iface->iter_parent = gtk_tree_model_css_node_iter_parent;
334 }
335 
336 static void
gtk_tree_model_css_node_finalize(GObject * object)337 gtk_tree_model_css_node_finalize (GObject *object)
338 {
339   GtkTreeModelCssNode *model = GTK_TREE_MODEL_CSS_NODE (object);
340   GtkTreeModelCssNodePrivate *priv = model->priv;
341 
342   if (priv->root)
343     {
344       gtk_tree_model_css_node_disconnect_node (model, priv->root, FALSE, NULL, NULL);
345       priv->root = NULL;
346     }
347 
348   G_OBJECT_CLASS (gtk_tree_model_css_node_parent_class)->finalize (object);
349 }
350 
351 static void
gtk_tree_model_css_node_class_init(GtkTreeModelCssNodeClass * class)352 gtk_tree_model_css_node_class_init (GtkTreeModelCssNodeClass *class)
353 {
354   GObjectClass *object_class = G_OBJECT_CLASS (class);
355 
356   object_class->finalize = gtk_tree_model_css_node_finalize;
357 }
358 
359 static void
gtk_tree_model_css_node_init(GtkTreeModelCssNode * nodemodel)360 gtk_tree_model_css_node_init (GtkTreeModelCssNode *nodemodel)
361 {
362   nodemodel->priv = gtk_tree_model_css_node_get_instance_private (nodemodel);
363 }
364 
365 GtkTreeModel *
gtk_tree_model_css_node_new(GtkTreeModelCssNodeGetFunc get_func,gint n_columns,...)366 gtk_tree_model_css_node_new (GtkTreeModelCssNodeGetFunc get_func,
367                              gint                       n_columns,
368 			     ...)
369 {
370   GtkTreeModel *result;
371   va_list args;
372   GType *types;
373   gint i;
374 
375   g_return_val_if_fail (get_func != NULL, NULL);
376   g_return_val_if_fail (n_columns > 0, NULL);
377 
378   types = g_new (GType, n_columns);
379   va_start (args, n_columns);
380 
381   for (i = 0; i < n_columns; i++)
382     {
383       types[i] = va_arg (args, GType);
384     }
385 
386   va_end (args);
387 
388   result = gtk_tree_model_css_node_newv (get_func, n_columns, types);
389 
390   g_free (types);
391 
392   return result;
393 }
394 
395 GtkTreeModel *
gtk_tree_model_css_node_newv(GtkTreeModelCssNodeGetFunc get_func,gint n_columns,GType * types)396 gtk_tree_model_css_node_newv (GtkTreeModelCssNodeGetFunc  get_func,
397                               gint                        n_columns,
398 			      GType                      *types)
399 {
400   GtkTreeModelCssNode *result;
401   GtkTreeModelCssNodePrivate *priv;
402 
403   g_return_val_if_fail (get_func != NULL, NULL);
404   g_return_val_if_fail (n_columns > 0, NULL);
405   g_return_val_if_fail (types != NULL, NULL);
406 
407   result = g_object_new (GTK_TYPE_TREE_MODEL_CSS_NODE, NULL);
408   priv = result->priv;
409 
410   priv->get_func = get_func;
411   priv->n_columns = n_columns;
412   priv->column_types = g_memdup (types, sizeof (GType) * n_columns);
413 
414   return GTK_TREE_MODEL (result);
415 }
416 
417 static void
child_added_cb(GtkCssNode * node,GtkCssNode * child,GtkCssNode * previous,GtkTreeModelCssNode * model)418 child_added_cb (GtkCssNode          *node,
419                 GtkCssNode          *child,
420                 GtkCssNode          *previous,
421                 GtkTreeModelCssNode *model)
422 {
423   gtk_tree_model_css_node_connect_node (model, child, TRUE);
424 }
425 
426 static void
child_removed_cb(GtkCssNode * node,GtkCssNode * child,GtkCssNode * previous,GtkTreeModelCssNode * model)427 child_removed_cb (GtkCssNode          *node,
428                   GtkCssNode          *child,
429                   GtkCssNode          *previous,
430                   GtkTreeModelCssNode *model)
431 {
432   gtk_tree_model_css_node_disconnect_node (model, child, TRUE, node, previous);
433 }
434 
435 static void
notify_cb(GtkCssNode * node,GParamSpec * pspec,GtkTreeModelCssNode * model)436 notify_cb (GtkCssNode          *node,
437            GParamSpec          *pspec,
438            GtkTreeModelCssNode *model)
439 {
440   GtkTreeIter iter;
441   GtkTreePath *path;
442 
443   gtk_tree_model_css_node_get_iter_from_node (model, &iter, node);
444   path = gtk_tree_model_css_node_get_path (GTK_TREE_MODEL (model), &iter);
445 
446   gtk_tree_model_row_changed (GTK_TREE_MODEL (model), path, &iter);
447 
448   gtk_tree_path_free (path);
449 }
450 
451 static void
style_changed_cb(GtkCssNode * node,GtkCssStyleChange * change,GtkTreeModelCssNode * model)452 style_changed_cb (GtkCssNode          *node,
453                   GtkCssStyleChange   *change,
454                   GtkTreeModelCssNode *model)
455 {
456   GtkTreeIter iter;
457   GtkTreePath *path;
458 
459   gtk_tree_model_css_node_get_iter_from_node (model, &iter, node);
460   path = gtk_tree_model_css_node_get_path (GTK_TREE_MODEL (model), &iter);
461 
462   gtk_tree_model_row_changed (GTK_TREE_MODEL (model), path, &iter);
463 
464   gtk_tree_path_free (path);
465 }
466 
467 static void
gtk_tree_model_css_node_connect_node(GtkTreeModelCssNode * model,GtkCssNode * node,gboolean emit_signal)468 gtk_tree_model_css_node_connect_node (GtkTreeModelCssNode *model,
469                                       GtkCssNode          *node,
470                                       gboolean             emit_signal)
471 {
472   GtkCssNode *child;
473 
474   if (GTK_IS_CSS_TRANSIENT_NODE (node))
475     return;
476 
477   g_object_ref (node);
478 
479   g_signal_connect_after (node, "node-added", G_CALLBACK (child_added_cb), model);
480   g_signal_connect_after (node, "node-removed", G_CALLBACK (child_removed_cb), model);
481   g_signal_connect_after (node, "notify", G_CALLBACK (notify_cb), model);
482   g_signal_connect_after (node, "style-changed", G_CALLBACK (style_changed_cb), model);
483 
484   for (child = gtk_css_node_get_first_child (node);
485        child;
486        child = gtk_css_node_get_next_sibling (child))
487     {
488       gtk_tree_model_css_node_connect_node (model, child, FALSE);
489     }
490 
491   if (emit_signal)
492     {
493       GtkTreeIter iter;
494       GtkTreePath *path;
495 
496       if (node != model->priv->root &&
497           gtk_css_node_get_previous_sibling (node) == NULL &&
498           gtk_css_node_get_next_sibling (node) == NULL)
499         {
500           /* We're the first child of the parent */
501           gtk_tree_model_css_node_get_iter_from_node (model, &iter, gtk_css_node_get_parent (node));
502           path = gtk_tree_model_css_node_get_path (GTK_TREE_MODEL (model), &iter);
503           gtk_tree_model_row_has_child_toggled (GTK_TREE_MODEL (model), path, &iter);
504           gtk_tree_path_free (path);
505         }
506 
507       gtk_tree_model_css_node_get_iter_from_node (model, &iter, node);
508       path = gtk_tree_model_css_node_get_path (GTK_TREE_MODEL (model), &iter);
509       gtk_tree_model_row_inserted (GTK_TREE_MODEL (model), path, &iter);
510       if (gtk_css_node_get_first_child (node))
511         gtk_tree_model_row_has_child_toggled (GTK_TREE_MODEL (model), path, &iter);
512 
513       gtk_tree_path_free (path);
514     }
515 }
516 
517 static void
gtk_tree_model_css_node_disconnect_node(GtkTreeModelCssNode * model,GtkCssNode * node,gboolean emit_signal,GtkCssNode * parent,GtkCssNode * previous)518 gtk_tree_model_css_node_disconnect_node (GtkTreeModelCssNode *model,
519                                          GtkCssNode          *node,
520                                          gboolean             emit_signal,
521                                          GtkCssNode          *parent,
522                                          GtkCssNode          *previous)
523 {
524   GtkCssNode *child;
525 
526   if (GTK_IS_CSS_TRANSIENT_NODE (node))
527     return;
528 
529   g_signal_handlers_disconnect_by_func (node, G_CALLBACK (child_added_cb), model);
530   g_signal_handlers_disconnect_by_func (node, G_CALLBACK (child_removed_cb), model);
531   g_signal_handlers_disconnect_by_func (node, G_CALLBACK (notify_cb), model);
532   g_signal_handlers_disconnect_by_func (node, G_CALLBACK (style_changed_cb), model);
533 
534   for (child = gtk_css_node_get_first_child (node);
535        child;
536        child = gtk_css_node_get_next_sibling (child))
537     {
538       gtk_tree_model_css_node_disconnect_node (model, child, FALSE, NULL, NULL);
539     }
540 
541   if (emit_signal)
542     {
543       GtkTreeIter iter;
544       GtkTreePath *path;
545 
546       if (parent)
547         {
548           gtk_tree_model_css_node_get_iter_from_node (model, &iter, parent);
549           path = gtk_tree_model_css_node_get_path (GTK_TREE_MODEL (model), &iter);
550         }
551       else
552         {
553           path = gtk_tree_path_new ();
554         }
555       if (previous)
556         gtk_tree_path_append_index (path, get_node_index (previous) + 1);
557       else
558         gtk_tree_path_append_index (path, 0);
559 
560       gtk_tree_model_row_deleted (GTK_TREE_MODEL (model), path);
561 
562       if (parent && gtk_css_node_get_first_child (parent) == NULL)
563         {
564           gtk_tree_path_up (path);
565           gtk_tree_model_row_has_child_toggled (GTK_TREE_MODEL (model), path, &iter);
566         }
567 
568       gtk_tree_path_free (path);
569     }
570 
571   g_object_unref (node);
572 }
573 
574 void
gtk_tree_model_css_node_set_root_node(GtkTreeModelCssNode * model,GtkCssNode * node)575 gtk_tree_model_css_node_set_root_node (GtkTreeModelCssNode *model,
576                                        GtkCssNode          *node)
577 {
578   GtkTreeModelCssNodePrivate *priv;
579 
580   g_return_if_fail (GTK_IS_TREE_MODEL_CSS_NODE (model));
581   g_return_if_fail (node == NULL || GTK_IS_CSS_NODE (node));
582 
583   priv = model->priv;
584 
585   if (priv->root == node)
586     return;
587 
588   if (priv->root)
589     {
590       gtk_tree_model_css_node_disconnect_node (model, priv->root, TRUE, NULL, NULL);
591       priv->root = NULL;
592     }
593 
594   if (node)
595     {
596       priv->root = node;
597       gtk_tree_model_css_node_connect_node (model, node, TRUE);
598     }
599 }
600 
601 GtkCssNode *
gtk_tree_model_css_node_get_root_node(GtkTreeModelCssNode * model)602 gtk_tree_model_css_node_get_root_node (GtkTreeModelCssNode *model)
603 {
604   g_return_val_if_fail (GTK_IS_TREE_MODEL_CSS_NODE (model), NULL);
605 
606   return model->priv->root;
607 }
608 
609 GtkCssNode *
gtk_tree_model_css_node_get_node_from_iter(GtkTreeModelCssNode * model,GtkTreeIter * iter)610 gtk_tree_model_css_node_get_node_from_iter (GtkTreeModelCssNode *model,
611                                             GtkTreeIter         *iter)
612 {
613   g_return_val_if_fail (GTK_IS_TREE_MODEL_CSS_NODE (model), NULL);
614   g_return_val_if_fail (iter != NULL, NULL);
615   g_return_val_if_fail (iter->user_data == model, NULL);
616   g_return_val_if_fail (GTK_IS_CSS_NODE (iter->user_data2), NULL);
617 
618   return iter->user_data2;
619 }
620 
621 void
gtk_tree_model_css_node_get_iter_from_node(GtkTreeModelCssNode * model,GtkTreeIter * iter,GtkCssNode * node)622 gtk_tree_model_css_node_get_iter_from_node (GtkTreeModelCssNode *model,
623                                             GtkTreeIter         *iter,
624                                             GtkCssNode          *node)
625 {
626   g_return_if_fail (GTK_IS_TREE_MODEL_CSS_NODE (model));
627   g_return_if_fail (iter != NULL);
628   g_return_if_fail (GTK_IS_CSS_NODE (node));
629 
630   iter->user_data = model;
631   iter->user_data2 = node;
632 }
633