]> Pileus Git - ~andy/gtk/blob - gtk/gtktreestore.c
Re-enable the "find" dialog
[~andy/gtk] / gtk / gtktreestore.c
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, write to the
16  * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
17  * Boston, MA 02111-1307, USA.
18  */
19
20 #include "gtktreemodel.h"
21 #include "gtktreestore.h"
22 #include "gtktreedatalist.h"
23 #include "gtksignal.h"
24 #include <string.h>
25
26 #define G_NODE(node) ((GNode *)node)
27
28 enum {
29   NODE_CHANGED,
30   NODE_INSERTED,
31   NODE_CHILD_TOGGLED,
32   NODE_DELETED,
33   LAST_SIGNAL
34 };
35
36 static guint tree_store_signals[LAST_SIGNAL] = { 0 };
37
38 static void           gtk_tree_store_init            (GtkTreeStore      *tree_store);
39 static void           gtk_tree_store_class_init      (GtkTreeStoreClass *tree_store_class);
40 static void           gtk_tree_store_tree_model_init (GtkTreeModelIface *iface);
41 static gint           gtk_tree_store_get_n_columns   (GtkTreeModel      *tree_model);
42 static GtkTreeNode    gtk_tree_store_get_node        (GtkTreeModel      *tree_model,
43                                                       GtkTreePath       *path);
44 static GtkTreePath   *gtk_tree_store_get_path        (GtkTreeModel      *tree_model,
45                                                       GtkTreeNode        node);
46 static void           gtk_tree_store_node_get_value  (GtkTreeModel      *tree_model,
47                                                       GtkTreeNode        node,
48                                                       gint               column,
49                                                       GValue            *value);
50 static gboolean       gtk_tree_store_node_next       (GtkTreeModel      *tree_model,
51                                                       GtkTreeNode       *node);
52 static GtkTreeNode    gtk_tree_store_node_children   (GtkTreeModel      *tree_model,
53                                                       GtkTreeNode        node);
54 static gboolean       gtk_tree_store_node_has_child  (GtkTreeModel      *tree_model,
55                                                       GtkTreeNode        node);
56 static gint           gtk_tree_store_node_n_children (GtkTreeModel      *tree_model,
57                                                       GtkTreeNode        node);
58 static GtkTreeNode    gtk_tree_store_node_nth_child  (GtkTreeModel      *tree_model,
59                                                       GtkTreeNode        node,
60                                                       gint               n);
61 static GtkTreeNode    gtk_tree_store_node_parent     (GtkTreeModel      *tree_model,
62                                                       GtkTreeNode        node);
63
64
65
66 GtkType
67 gtk_tree_store_get_type (void)
68 {
69   static GtkType tree_store_type = 0;
70
71   if (!tree_store_type)
72     {
73       static const GTypeInfo tree_store_info =
74       {
75         sizeof (GtkTreeStoreClass),
76         NULL,           /* base_init */
77         NULL,           /* base_finalize */
78         (GClassInitFunc) gtk_tree_store_class_init,
79         NULL,           /* class_finalize */
80         NULL,           /* class_data */
81         sizeof (GtkTreeStore),
82         0,              /* n_preallocs */
83         (GInstanceInitFunc) gtk_tree_store_init
84       };
85
86       static const GInterfaceInfo tree_model_info =
87       {
88         (GInterfaceInitFunc) gtk_tree_store_tree_model_init,
89         NULL,
90         NULL
91       };
92
93       tree_store_type = g_type_register_static (GTK_TYPE_OBJECT, "GtkTreeStore", &tree_store_info);
94       g_type_add_interface_static (tree_store_type,
95                                    GTK_TYPE_TREE_MODEL,
96                                    &tree_model_info);
97     }
98
99   return tree_store_type;
100 }
101
102 static void
103 gtk_tree_store_class_init (GtkTreeStoreClass *tree_store_class)
104 {
105   GtkObjectClass *object_class;
106
107   object_class = (GtkObjectClass *) tree_store_class;
108
109   tree_store_signals[NODE_CHANGED] =
110     gtk_signal_new ("node_changed",
111                     GTK_RUN_FIRST,
112                     GTK_CLASS_TYPE (object_class),
113                     GTK_SIGNAL_OFFSET (GtkTreeStoreClass, node_changed),
114                     gtk_marshal_NONE__POINTER_POINTER,
115                     GTK_TYPE_NONE, 2,
116                     GTK_TYPE_POINTER,
117                     GTK_TYPE_POINTER);
118   tree_store_signals[NODE_INSERTED] =
119     gtk_signal_new ("node_inserted",
120                     GTK_RUN_FIRST,
121                     GTK_CLASS_TYPE (object_class),
122                     GTK_SIGNAL_OFFSET (GtkTreeStoreClass, node_inserted),
123                     gtk_marshal_NONE__POINTER_POINTER,
124                     GTK_TYPE_NONE, 2,
125                     GTK_TYPE_POINTER,
126                     GTK_TYPE_POINTER);
127   tree_store_signals[NODE_CHILD_TOGGLED] =
128     gtk_signal_new ("node_child_toggled",
129                     GTK_RUN_FIRST,
130                     GTK_CLASS_TYPE (object_class),
131                     GTK_SIGNAL_OFFSET (GtkTreeStoreClass, node_child_toggled),
132                     gtk_marshal_NONE__POINTER_POINTER,
133                     GTK_TYPE_NONE, 2,
134                     GTK_TYPE_POINTER,
135                     GTK_TYPE_POINTER);
136   tree_store_signals[NODE_DELETED] =
137     gtk_signal_new ("node_deleted",
138                     GTK_RUN_FIRST,
139                     GTK_CLASS_TYPE (object_class),
140                     GTK_SIGNAL_OFFSET (GtkTreeStoreClass, node_deleted),
141                     gtk_marshal_NONE__POINTER,
142                     GTK_TYPE_NONE, 1,
143                     GTK_TYPE_POINTER);
144
145   gtk_object_class_add_signals (object_class, tree_store_signals, LAST_SIGNAL);
146 }
147
148 static void
149 gtk_tree_store_tree_model_init (GtkTreeModelIface *iface)
150 {
151   iface->get_n_columns = gtk_tree_store_get_n_columns;
152   iface->get_node = gtk_tree_store_get_node;
153   iface->get_path = gtk_tree_store_get_path;
154   iface->node_get_value = gtk_tree_store_node_get_value;
155   iface->node_next = gtk_tree_store_node_next;
156   iface->node_children = gtk_tree_store_node_children;
157   iface->node_has_child = gtk_tree_store_node_has_child;
158   iface->node_n_children = gtk_tree_store_node_n_children;
159   iface->node_nth_child = gtk_tree_store_node_nth_child;
160   iface->node_parent = gtk_tree_store_node_parent;
161 }
162
163 static void
164 gtk_tree_store_init (GtkTreeStore *tree_store)
165 {
166   tree_store->root = gtk_tree_store_node_new ();
167 }
168
169 GtkObject *
170 gtk_tree_store_new (void)
171 {
172   return GTK_OBJECT (gtk_type_new (gtk_tree_store_get_type ()));
173 }
174
175 GtkObject *
176 gtk_tree_store_new_with_values (gint n_columns,
177                                 ...)
178 {
179   GtkObject *retval;
180   va_list args;
181   gint i;
182
183   g_return_val_if_fail (n_columns > 0, NULL);
184
185   retval = gtk_tree_store_new ();
186   gtk_tree_store_set_n_columns (GTK_TREE_STORE (retval),
187                                 n_columns);
188
189   va_start (args, n_columns);
190   for (i = 0; i < n_columns; i++)
191     gtk_tree_store_set_column_type (GTK_TREE_STORE (retval),
192                                     i, va_arg (args, GType));
193
194   va_end (args);
195
196   return retval;
197 }
198
199 void
200 gtk_tree_store_set_n_columns (GtkTreeStore *tree_store,
201                               gint          n_columns)
202 {
203   GType *new_columns;
204
205   g_return_if_fail (tree_store != NULL);
206   g_return_if_fail (GTK_IS_TREE_STORE (tree_store));
207
208   if (tree_store->n_columns == n_columns)
209     return;
210
211   new_columns = g_new0 (GType, n_columns);
212   if (tree_store->column_headers)
213     {
214       /* copy the old header orders over */
215       if (n_columns >= tree_store->n_columns)
216         memcpy (new_columns, tree_store->column_headers, tree_store->n_columns * sizeof (gchar *));
217       else
218         memcpy (new_columns, tree_store->column_headers, n_columns * sizeof (GType));
219
220       g_free (tree_store->column_headers);
221     }
222
223   tree_store->column_headers = new_columns;
224   tree_store->n_columns = n_columns;
225 }
226
227 void
228 gtk_tree_store_set_column_type (GtkTreeStore *tree_store,
229                                 gint          column,
230                                 GType         type)
231 {
232   g_return_if_fail (tree_store != NULL);
233   g_return_if_fail (GTK_IS_TREE_STORE (tree_store));
234   g_return_if_fail (column >=0 && column < tree_store->n_columns);
235
236   tree_store->column_headers[column] = type;
237 }
238
239 /* fulfill the GtkTreeModel requirements */
240 /* NOTE: GtkTreeStore::root is a GNode, that acts as the parent node.  However,
241  * it is not visible to the tree or to the user., and the path "1" refers to the
242  * first child of GtkTreeStore::root.
243  */
244 static gint
245 gtk_tree_store_get_n_columns (GtkTreeModel *tree_model)
246 {
247   g_return_val_if_fail (tree_model != NULL, 0);
248   g_return_val_if_fail (GTK_IS_TREE_STORE (tree_model), 0);
249
250   return GTK_TREE_STORE (tree_model)->n_columns;
251 }
252
253 static GtkTreeNode
254 gtk_tree_store_get_node (GtkTreeModel *tree_model,
255                          GtkTreePath  *path)
256 {
257   gint i;
258   GtkTreeNode node;
259   gint *indices = gtk_tree_path_get_indices (path);
260
261   node = GTK_TREE_STORE (tree_model)->root;
262
263   for (i = 0; i < gtk_tree_path_get_depth (path); i ++)
264     {
265       node = (GtkTreeNode) gtk_tree_store_node_nth_child (tree_model,
266                                                           (GtkTreeNode) node,
267                                                           indices[i]);
268       if (node == NULL)
269         return NULL;
270     }
271   return (GtkTreeNode) node;
272 }
273
274 static GtkTreePath *
275 gtk_tree_store_get_path (GtkTreeModel *tree_model,
276                          GtkTreeNode   node)
277 {
278   GtkTreePath *retval;
279   GNode *tmp_node;
280   gint i = 0;
281
282   g_return_val_if_fail (tree_model != NULL, NULL);
283
284   if (node == NULL)
285     return NULL;
286   if (node == G_NODE (GTK_TREE_STORE (tree_model)->root))
287     return NULL;
288
289   if (G_NODE (node)->parent == G_NODE (GTK_TREE_STORE (tree_model)->root))
290     {
291       retval = gtk_tree_path_new ();
292       tmp_node = G_NODE (GTK_TREE_STORE (tree_model)->root)->children;
293     }
294   else
295     {
296       retval = gtk_tree_store_get_path (tree_model,
297                                         G_NODE (node)->parent);
298       tmp_node = G_NODE (node)->parent->children;
299     }
300
301   if (retval == NULL)
302     return NULL;
303   if (tmp_node == NULL)
304     {
305       gtk_tree_path_free (retval);
306       return NULL;
307     }
308
309   for (; tmp_node; tmp_node = tmp_node->next)
310     {
311       if (tmp_node == G_NODE (node))
312         break;
313       i++;
314     }
315   if (tmp_node == NULL)
316     {
317       /* We couldn't find node, meaning it's prolly not ours */
318       gtk_tree_path_free (retval);
319       return NULL;
320     }
321
322   gtk_tree_path_append_index (retval, i);
323
324   return retval;
325 }
326
327
328 static void
329 gtk_tree_store_node_get_value (GtkTreeModel *tree_model,
330                                GtkTreeNode   node,
331                                gint          column,
332                                GValue       *value)
333 {
334   GtkTreeDataList *list;
335   gint tmp_column = column;
336
337   g_return_if_fail (tree_model != NULL);
338   g_return_if_fail (GTK_IS_TREE_STORE (tree_model));
339   g_return_if_fail (node != NULL);
340   g_return_if_fail (column < GTK_TREE_STORE (tree_model)->n_columns);
341
342   list = G_NODE (node)->data;
343
344   while (tmp_column-- > 0 && list)
345     list = list->next;
346
347   g_return_if_fail (list != NULL);
348
349   gtk_tree_data_list_node_to_value (list,
350                                     GTK_TREE_STORE (tree_model)->column_headers[column],
351                                     value);
352 }
353
354 static gboolean
355 gtk_tree_store_node_next (GtkTreeModel  *tree_model,
356                           GtkTreeNode   *node)
357 {
358   if (node == NULL || *node == NULL)
359     return FALSE;
360
361   *node = (GtkTreeNode) G_NODE (*node)->next;
362   return (*node != NULL);
363 }
364
365 static GtkTreeNode
366 gtk_tree_store_node_children (GtkTreeModel *tree_model,
367                               GtkTreeNode   node)
368 {
369   return (GtkTreeNode) G_NODE (node)->children;
370 }
371
372 static gboolean
373 gtk_tree_store_node_has_child (GtkTreeModel *tree_model,
374                                GtkTreeNode   node)
375 {
376   return G_NODE (node)->children != NULL;
377 }
378
379 static gint
380 gtk_tree_store_node_n_children (GtkTreeModel *tree_model,
381                                 GtkTreeNode   node)
382 {
383   gint i = 0;
384
385   node = (GtkTreeNode) G_NODE (node)->children;
386   while (node != NULL)
387     {
388       i++;
389       node = (GtkTreeNode) G_NODE (node)->next;
390     }
391
392   return i;
393 }
394
395 static GtkTreeNode
396 gtk_tree_store_node_nth_child (GtkTreeModel *tree_model,
397                                GtkTreeNode   node,
398                                gint          n)
399 {
400   g_return_val_if_fail (node != NULL, NULL);
401
402   return (GtkTreeNode) g_node_nth_child (G_NODE (node), n);
403 }
404
405 static GtkTreeNode
406 gtk_tree_store_node_parent (GtkTreeModel *tree_model,
407                             GtkTreeNode   node)
408 {
409   return (GtkTreeNode) G_NODE (node)->parent;
410 }
411
412 /* Public accessors */
413 GtkTreeNode
414 gtk_tree_store_node_new (void)
415 {
416   GtkTreeNode retval;
417
418   retval = (GtkTreeNode) g_node_new (NULL);
419   return retval;
420 }
421
422 /*
423  * This is a somewhat inelegant function that does a lot of list
424  * manipulations on it's own.
425  */
426 void
427 gtk_tree_store_node_set_cell (GtkTreeStore *tree_store,
428                               GtkTreeNode   node,
429                               gint          column,
430                               GValue       *value)
431 {
432   GtkTreeDataList *list;
433   GtkTreeDataList *prev;
434
435   g_return_if_fail (tree_store != NULL);
436   g_return_if_fail (GTK_IS_TREE_STORE (tree_store));
437   g_return_if_fail (node != NULL);
438   g_return_if_fail (column >= 0 && column < tree_store->n_columns);
439
440   prev = list = G_NODE (node)->data;
441
442   while (list != NULL)
443     {
444       if (column == 0)
445         {
446           gtk_tree_data_list_value_to_node (list, value);
447           return;
448         }
449
450       column--;
451       prev = list;
452       list = list->next;
453     }
454
455   if (G_NODE (node)->data == NULL)
456     {
457       G_NODE (node)->data = list = gtk_tree_data_list_alloc ();
458       list->next = NULL;
459     }
460   else
461     {
462       list = prev->next = gtk_tree_data_list_alloc ();
463       list->next = NULL;
464     }
465
466   while (column != 0)
467     {
468       list->next = gtk_tree_data_list_alloc ();
469       list = list->next;
470       list->next = NULL;
471       column --;
472     }
473   gtk_tree_data_list_value_to_node (list, value);
474 }
475
476 void
477 gtk_tree_store_node_remove (GtkTreeStore *model,
478                             GtkTreeNode   node)
479 {
480   GtkTreePath *path;
481   GNode *parent;
482
483   g_return_if_fail (model != NULL);
484   g_return_if_fail (GTK_IS_TREE_STORE (model));
485   g_return_if_fail (node != NULL);
486   /* FIXME: if node is NULL, do I want to free the tree? */
487
488   parent = G_NODE (node)->parent;
489
490   path = gtk_tree_store_get_path (GTK_TREE_MODEL (model), node);
491   g_node_destroy (G_NODE (node));
492   gtk_signal_emit_by_name (GTK_OBJECT (model),
493                            "node_deleted",
494                            path);
495   if (parent != G_NODE (model->root) && parent->children == NULL)
496     {
497       gtk_tree_path_up (path);
498       gtk_signal_emit_by_name (GTK_OBJECT (model),
499                                "node_child_toggled",
500                                path,
501                                parent);
502     }
503   gtk_tree_path_free (path);
504 }
505
506 GtkTreeNode
507 gtk_tree_store_node_insert (GtkTreeStore *model,
508                             GtkTreeNode   parent,
509                             gint          position,
510                             GtkTreeNode   node)
511 {
512   GtkTreePath *path;
513
514   g_return_val_if_fail (model != NULL, node);
515   g_return_val_if_fail (GTK_IS_TREE_STORE (model), node);
516   g_return_val_if_fail (node != NULL, node);
517
518   if (parent == NULL)
519     parent = model->root;
520
521   g_node_insert (G_NODE (parent), position, G_NODE (node));
522
523   path = gtk_tree_store_get_path (GTK_TREE_MODEL (model), node);
524   gtk_signal_emit_by_name (GTK_OBJECT (model),
525                            "node_inserted",
526                            path, node);
527   gtk_tree_path_free (path);
528
529   return node;
530 }
531
532 GtkTreeNode
533 gtk_tree_store_node_insert_before (GtkTreeStore *model,
534                                    GtkTreeNode   parent,
535                                    GtkTreeNode   sibling,
536                                    GtkTreeNode   node)
537 {
538   GtkTreePath *path;
539
540   g_return_val_if_fail (model != NULL, node);
541   g_return_val_if_fail (GTK_IS_TREE_STORE (model), node);
542   g_return_val_if_fail (node != NULL, node);
543
544   if (parent == NULL && sibling == NULL)
545     parent = model->root;
546
547   if (parent == NULL)
548     parent = (GtkTreeNode) G_NODE (sibling)->parent;
549
550   g_node_insert_before (G_NODE (parent), G_NODE (sibling), G_NODE (node));
551
552   path = gtk_tree_store_get_path (GTK_TREE_MODEL (model), node);
553   gtk_signal_emit_by_name (GTK_OBJECT (model),
554                            "node_inserted",
555                            path, node);
556   gtk_tree_path_free (path);
557
558   return node;
559 }
560
561 GtkTreeNode
562 gtk_tree_store_node_insert_after (GtkTreeStore *model,
563                                   GtkTreeNode   parent,
564                                   GtkTreeNode   sibling,
565                                   GtkTreeNode   node)
566 {
567   GtkTreePath *path;
568
569   g_return_val_if_fail (model != NULL, node);
570   g_return_val_if_fail (GTK_IS_TREE_STORE (model), node);
571   g_return_val_if_fail (node != NULL, node);
572
573   if (parent == NULL && sibling == NULL)
574     parent = model->root;
575
576   if (parent == NULL)
577     parent = (GtkTreeNode) G_NODE (sibling)->parent;
578
579   g_node_insert_after (G_NODE (parent), G_NODE (sibling), G_NODE (node));
580
581   path = gtk_tree_store_get_path (GTK_TREE_MODEL (model), node);
582   gtk_signal_emit_by_name (GTK_OBJECT (model),
583                            "node_inserted",
584                            path, node);
585   gtk_tree_path_free (path);
586   return node;
587 }
588
589 GtkTreeNode
590 gtk_tree_store_node_prepend (GtkTreeStore *model,
591                              GtkTreeNode   parent,
592                              GtkTreeNode   node)
593 {
594   g_return_val_if_fail (model != NULL, node);
595   g_return_val_if_fail (GTK_IS_TREE_STORE (model), node);
596   g_return_val_if_fail (node != NULL, node);
597
598   if (parent == NULL)
599     parent = model->root;
600
601   if (G_NODE (parent)->children == NULL)
602     {
603       GtkTreePath *path;
604       g_node_prepend (G_NODE (parent), G_NODE (node));
605       if (parent != model->root)
606         {
607           path = gtk_tree_store_get_path (GTK_TREE_MODEL (model), parent);
608           gtk_signal_emit_by_name (GTK_OBJECT (model),
609                                    "node_child_toggled",
610                                    path,
611                                    parent);
612           gtk_tree_path_append_index (path, 1);
613         }
614       else
615         {
616           path = gtk_tree_store_get_path (GTK_TREE_MODEL (model), G_NODE (parent)->children);
617         }
618       gtk_signal_emit_by_name (GTK_OBJECT (model),
619                                "node_inserted",
620                                path,
621                                G_NODE (parent)->children);
622       gtk_tree_path_free (path);
623     }
624   else
625     {
626       gtk_tree_store_node_insert_after (model,
627                                          parent == model->root?NULL:parent,
628                                          NULL,
629                                          node);
630     }
631   return node;
632 }
633
634 GtkTreeNode
635 gtk_tree_store_node_append (GtkTreeStore *model,
636                             GtkTreeNode   parent,
637                             GtkTreeNode   node)
638 {
639   g_return_val_if_fail (model != NULL, node);
640   g_return_val_if_fail (GTK_IS_TREE_STORE (model), node);
641   g_return_val_if_fail (node != NULL, node);
642
643   if (parent == NULL)
644     parent = model->root;
645
646   if (G_NODE (parent)->children == NULL)
647     {
648       GtkTreePath *path;
649       g_node_append (G_NODE (parent), G_NODE (node));
650       if (parent != model->root)
651         {
652           path = gtk_tree_store_get_path (GTK_TREE_MODEL (model), parent);
653           gtk_signal_emit_by_name (GTK_OBJECT (model),
654                                    "node_child_toggled",
655                                    path,
656                                    parent);
657           gtk_tree_path_append_index (path, 1);
658         }
659       else
660         {
661           path = gtk_tree_store_get_path (GTK_TREE_MODEL (model), G_NODE (parent)->children);
662         }
663       gtk_signal_emit_by_name (GTK_OBJECT (model),
664                                "node_inserted",
665                                path,
666                                G_NODE (parent)->children);
667       gtk_tree_path_free (path);
668     }
669   else
670     {
671       gtk_tree_store_node_insert_before (model,
672                                          parent == model->root?NULL:parent,
673                                          NULL,
674                                          node);
675     }
676   return node;
677 }
678
679 GtkTreeNode
680 gtk_tree_store_node_get_root (GtkTreeStore *model)
681 {
682   g_return_val_if_fail (model != NULL, NULL);
683   g_return_val_if_fail (GTK_IS_TREE_STORE (model), NULL);
684
685   return (GtkTreeNode) model->root;
686 }
687
688
689 gboolean
690 gtk_tree_store_node_is_ancestor (GtkTreeStore *model,
691                                  GtkTreeNode   node,
692                                  GtkTreeNode   descendant)
693 {
694   g_return_val_if_fail (model != NULL, FALSE);
695   g_return_val_if_fail (GTK_IS_TREE_STORE (model), FALSE);
696   g_return_val_if_fail (node != NULL, FALSE);
697   g_return_val_if_fail (descendant != NULL, FALSE);
698
699   return g_node_is_ancestor (G_NODE (node), G_NODE (descendant));
700 }
701
702
703 gint
704 gtk_tree_store_node_depth (GtkTreeStore *model,
705                            GtkTreeNode   node)
706 {
707   g_return_val_if_fail (model != NULL, 0);
708   g_return_val_if_fail (GTK_IS_TREE_STORE (model), 0);
709   g_return_val_if_fail (node != NULL, 0);
710
711   return g_node_depth (G_NODE (node));
712 }