]> Pileus Git - ~andy/gtk/blob - demos/gtk-demo/tree_store.c
Use gtk_box_new() instead gtk_[v|h]box_new()
[~andy/gtk] / demos / gtk-demo / tree_store.c
1 /* Tree View/Tree Store
2  *
3  * The GtkTreeStore is used to store data in tree form, to be
4  * used later on by a GtkTreeView to display it. This demo builds
5  * a simple GtkTreeStore and displays it. If you're new to the
6  * GtkTreeView widgets and associates, look into the GtkListStore
7  * example first.
8  *
9  */
10
11 #include <gtk/gtk.h>
12
13 static GtkWidget *window = NULL;
14
15 /* TreeItem structure */
16 typedef struct _TreeItem TreeItem;
17 struct _TreeItem
18 {
19   const gchar    *label;
20   gboolean        alex;
21   gboolean        havoc;
22   gboolean        tim;
23   gboolean        owen;
24   gboolean        dave;
25   gboolean        world_holiday; /* shared by the European hackers */
26   TreeItem       *children;
27 };
28
29 /* columns */
30 enum
31 {
32   HOLIDAY_NAME_COLUMN = 0,
33   ALEX_COLUMN,
34   HAVOC_COLUMN,
35   TIM_COLUMN,
36   OWEN_COLUMN,
37   DAVE_COLUMN,
38
39   VISIBLE_COLUMN,
40   WORLD_COLUMN,
41   NUM_COLUMNS
42 };
43
44 /* tree data */
45 static TreeItem january[] =
46 {
47   {"New Years Day", TRUE, TRUE, TRUE, TRUE, FALSE, TRUE, NULL },
48   {"Presidential Inauguration", FALSE, TRUE, FALSE, TRUE, FALSE, FALSE, NULL },
49   {"Martin Luther King Jr. day", FALSE, TRUE, FALSE, TRUE, FALSE, FALSE, NULL },
50   { NULL }
51 };
52
53 static TreeItem february[] =
54 {
55   { "Presidents' Day", FALSE, TRUE, FALSE, TRUE, FALSE, FALSE, NULL },
56   { "Groundhog Day", FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, NULL },
57   { "Valentine's Day", FALSE, FALSE, FALSE, FALSE, TRUE, TRUE, NULL },
58   { NULL }
59 };
60
61 static TreeItem march[] =
62 {
63   { "National Tree Planting Day", FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, NULL },
64   { "St Patrick's Day", FALSE, FALSE, FALSE, FALSE, FALSE, TRUE, NULL },
65   { NULL }
66 };
67 static TreeItem april[] =
68 {
69   { "April Fools' Day", FALSE, FALSE, FALSE, FALSE, FALSE, TRUE, NULL },
70   { "Army Day", FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, NULL },
71   { "Earth Day", FALSE, FALSE, FALSE, FALSE, FALSE, TRUE, NULL },
72   { "Administrative Professionals' Day", FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, NULL },
73   { NULL }
74 };
75
76 static TreeItem may[] =
77 {
78   { "Nurses' Day", FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, NULL },
79   { "National Day of Prayer", FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, NULL },
80   { "Mothers' Day", FALSE, FALSE, FALSE, FALSE, FALSE, TRUE, NULL },
81   { "Armed Forces Day", FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, NULL },
82   { "Memorial Day", TRUE, TRUE, TRUE, TRUE, FALSE, TRUE, NULL },
83   { NULL }
84 };
85
86 static TreeItem june[] =
87 {
88   { "June Fathers' Day", FALSE, FALSE, FALSE, FALSE, FALSE, TRUE, NULL },
89   { "Juneteenth (Liberation of Slaves)", FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, NULL },
90   { "Flag Day", FALSE, TRUE, FALSE, TRUE, FALSE, FALSE, NULL },
91   { NULL }
92 };
93
94 static TreeItem july[] =
95 {
96   { "Parents' Day", FALSE, FALSE, FALSE, FALSE, FALSE, TRUE, NULL },
97   { "Independence Day", FALSE, TRUE, FALSE, TRUE, FALSE, FALSE, NULL },
98   { NULL }
99 };
100
101 static TreeItem august[] =
102 {
103   { "Air Force Day", FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, NULL },
104   { "Coast Guard Day", FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, NULL },
105   { "Friendship Day", FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, NULL },
106   { NULL }
107 };
108
109 static TreeItem september[] =
110 {
111   { "Grandparents' Day", FALSE, FALSE, FALSE, FALSE, FALSE, TRUE, NULL },
112   { "Citizenship Day or Constitution Day", FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, NULL },
113   { "Labor Day", TRUE, TRUE, TRUE, TRUE, FALSE, TRUE, NULL },
114   { NULL }
115 };
116
117 static TreeItem october[] =
118 {
119   { "National Children's Day", FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, NULL },
120   { "Bosses' Day", FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, NULL },
121   { "Sweetest Day", FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, NULL },
122   { "Mother-in-Law's Day", FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, NULL },
123   { "Navy Day", FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, NULL },
124   { "Columbus Day", FALSE, TRUE, FALSE, TRUE, FALSE, FALSE, NULL },
125   { "Halloween", FALSE, FALSE, FALSE, FALSE, FALSE, TRUE, NULL },
126   { NULL }
127 };
128
129 static TreeItem november[] =
130 {
131   { "Marine Corps Day", FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, NULL },
132   { "Veterans' Day", TRUE, TRUE, TRUE, TRUE, FALSE, TRUE, NULL },
133   { "Thanksgiving", FALSE, TRUE, FALSE, TRUE, FALSE, FALSE, NULL },
134   { NULL }
135 };
136
137 static TreeItem december[] =
138 {
139   { "Pearl Harbor Remembrance Day", FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, NULL },
140   { "Christmas", TRUE, TRUE, TRUE, TRUE, FALSE, TRUE, NULL },
141   { "Kwanzaa", FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, NULL },
142   { NULL }
143 };
144
145
146 static TreeItem toplevel[] =
147 {
148   {"January", FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, january},
149   {"February", FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, february},
150   {"March", FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, march},
151   {"April", FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, april},
152   {"May", FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, may},
153   {"June", FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, june},
154   {"July", FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, july},
155   {"August", FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, august},
156   {"September", FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, september},
157   {"October", FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, october},
158   {"November", FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, november},
159   {"December", FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, december},
160   {NULL}
161 };
162
163
164 static GtkTreeModel *
165 create_model (void)
166 {
167   GtkTreeStore *model;
168   GtkTreeIter iter;
169   TreeItem *month = toplevel;
170
171   /* create tree store */
172   model = gtk_tree_store_new (NUM_COLUMNS,
173                               G_TYPE_STRING,
174                               G_TYPE_BOOLEAN,
175                               G_TYPE_BOOLEAN,
176                               G_TYPE_BOOLEAN,
177                               G_TYPE_BOOLEAN,
178                               G_TYPE_BOOLEAN,
179                               G_TYPE_BOOLEAN,
180                               G_TYPE_BOOLEAN);
181
182   /* add data to the tree store */
183   while (month->label)
184     {
185       TreeItem *holiday = month->children;
186
187       gtk_tree_store_append (model, &iter, NULL);
188       gtk_tree_store_set (model, &iter,
189                           HOLIDAY_NAME_COLUMN, month->label,
190                           ALEX_COLUMN, FALSE,
191                           HAVOC_COLUMN, FALSE,
192                           TIM_COLUMN, FALSE,
193                           OWEN_COLUMN, FALSE,
194                           DAVE_COLUMN, FALSE,
195                           VISIBLE_COLUMN, FALSE,
196                           WORLD_COLUMN, FALSE,
197                           -1);
198
199       /* add children */
200       while (holiday->label)
201         {
202           GtkTreeIter child_iter;
203
204           gtk_tree_store_append (model, &child_iter, &iter);
205           gtk_tree_store_set (model, &child_iter,
206                               HOLIDAY_NAME_COLUMN, holiday->label,
207                               ALEX_COLUMN, holiday->alex,
208                               HAVOC_COLUMN, holiday->havoc,
209                               TIM_COLUMN, holiday->tim,
210                               OWEN_COLUMN, holiday->owen,
211                               DAVE_COLUMN, holiday->dave,
212                               VISIBLE_COLUMN, TRUE,
213                               WORLD_COLUMN, holiday->world_holiday,
214                               -1);
215
216           holiday++;
217         }
218
219       month++;
220     }
221
222   return GTK_TREE_MODEL (model);
223 }
224
225 static void
226 item_toggled (GtkCellRendererToggle *cell,
227               gchar                 *path_str,
228               gpointer               data)
229 {
230   GtkTreeModel *model = (GtkTreeModel *)data;
231   GtkTreePath *path = gtk_tree_path_new_from_string (path_str);
232   GtkTreeIter iter;
233   gboolean toggle_item;
234
235   gint *column;
236
237   column = g_object_get_data (G_OBJECT (cell), "column");
238
239   /* get toggled iter */
240   gtk_tree_model_get_iter (model, &iter, path);
241   gtk_tree_model_get (model, &iter, column, &toggle_item, -1);
242
243   /* do something with the value */
244   toggle_item ^= 1;
245
246   /* set new value */
247   gtk_tree_store_set (GTK_TREE_STORE (model), &iter, column,
248                       toggle_item, -1);
249
250   /* clean up */
251   gtk_tree_path_free (path);
252 }
253
254 static void
255 add_columns (GtkTreeView *treeview)
256 {
257   gint col_offset;
258   GtkCellRenderer *renderer;
259   GtkTreeViewColumn *column;
260   GtkTreeModel *model = gtk_tree_view_get_model (treeview);
261
262   /* column for holiday names */
263   renderer = gtk_cell_renderer_text_new ();
264   g_object_set (renderer, "xalign", 0.0, NULL);
265
266   col_offset = gtk_tree_view_insert_column_with_attributes (GTK_TREE_VIEW (treeview),
267                                                             -1, "Holiday",
268                                                             renderer, "text",
269                                                             HOLIDAY_NAME_COLUMN,
270                                                             NULL);
271   column = gtk_tree_view_get_column (GTK_TREE_VIEW (treeview), col_offset - 1);
272   gtk_tree_view_column_set_clickable (GTK_TREE_VIEW_COLUMN (column), TRUE);
273
274   /* alex column */
275   renderer = gtk_cell_renderer_toggle_new ();
276   g_object_set (renderer, "xalign", 0.0, NULL);
277   g_object_set_data (G_OBJECT (renderer), "column", (gint *)ALEX_COLUMN);
278
279   g_signal_connect (renderer, "toggled", G_CALLBACK (item_toggled), model);
280
281   col_offset = gtk_tree_view_insert_column_with_attributes (GTK_TREE_VIEW (treeview),
282                                                             -1, "Alex",
283                                                             renderer,
284                                                             "active",
285                                                             ALEX_COLUMN,
286                                                             "visible",
287                                                             VISIBLE_COLUMN,
288                                                             "activatable",
289                                                             WORLD_COLUMN, NULL);
290
291   column = gtk_tree_view_get_column (GTK_TREE_VIEW (treeview), col_offset - 1);
292   gtk_tree_view_column_set_sizing (GTK_TREE_VIEW_COLUMN (column),
293                                    GTK_TREE_VIEW_COLUMN_FIXED);
294   gtk_tree_view_column_set_fixed_width (GTK_TREE_VIEW_COLUMN (column), 50);
295   gtk_tree_view_column_set_clickable (GTK_TREE_VIEW_COLUMN (column), TRUE);
296
297   /* havoc column */
298   renderer = gtk_cell_renderer_toggle_new ();
299   g_object_set (renderer, "xalign", 0.0, NULL);
300   g_object_set_data (G_OBJECT (renderer), "column", (gint *)HAVOC_COLUMN);
301
302   g_signal_connect (renderer, "toggled", G_CALLBACK (item_toggled), model);
303
304   col_offset = gtk_tree_view_insert_column_with_attributes (GTK_TREE_VIEW (treeview),
305                                                             -1, "Havoc",
306                                                             renderer,
307                                                             "active",
308                                                             HAVOC_COLUMN,
309                                                             "visible",
310                                                             VISIBLE_COLUMN,
311                                                             NULL);
312
313   column = gtk_tree_view_get_column (GTK_TREE_VIEW (treeview), col_offset - 1);
314   gtk_tree_view_column_set_sizing (GTK_TREE_VIEW_COLUMN (column),
315                                    GTK_TREE_VIEW_COLUMN_FIXED);
316   gtk_tree_view_column_set_fixed_width (GTK_TREE_VIEW_COLUMN (column), 50);
317   gtk_tree_view_column_set_clickable (GTK_TREE_VIEW_COLUMN (column), TRUE);
318
319   /* tim column */
320   renderer = gtk_cell_renderer_toggle_new ();
321   g_object_set (renderer, "xalign", 0.0, NULL);
322   g_object_set_data (G_OBJECT (renderer), "column", (gint *)TIM_COLUMN);
323
324   g_signal_connect (renderer, "toggled", G_CALLBACK (item_toggled), model);
325
326   col_offset = gtk_tree_view_insert_column_with_attributes (GTK_TREE_VIEW (treeview),
327                                                             -1, "Tim",
328                                                             renderer,
329                                                             "active",
330                                                             TIM_COLUMN,
331                                                             "visible",
332                                                             VISIBLE_COLUMN,
333                                                             "activatable",
334                                                             WORLD_COLUMN, NULL);
335
336   column = gtk_tree_view_get_column (GTK_TREE_VIEW (treeview), col_offset - 1);
337   gtk_tree_view_column_set_sizing (GTK_TREE_VIEW_COLUMN (column),
338                                    GTK_TREE_VIEW_COLUMN_FIXED);
339   gtk_tree_view_column_set_fixed_width (GTK_TREE_VIEW_COLUMN (column), 50);
340   gtk_tree_view_column_set_clickable (GTK_TREE_VIEW_COLUMN (column), TRUE);
341
342   /* owen column */
343   renderer = gtk_cell_renderer_toggle_new ();
344   g_object_set (renderer, "xalign", 0.0, NULL);
345   g_object_set_data (G_OBJECT (renderer), "column", (gint *)OWEN_COLUMN);
346
347   g_signal_connect (renderer, "toggled", G_CALLBACK (item_toggled), model);
348
349   col_offset = gtk_tree_view_insert_column_with_attributes (GTK_TREE_VIEW (treeview),
350                                                             -1, "Owen",
351                                                             renderer,
352                                                             "active",
353                                                             OWEN_COLUMN,
354                                                             "visible",
355                                                             VISIBLE_COLUMN,
356                                                             NULL);
357
358   column = gtk_tree_view_get_column (GTK_TREE_VIEW (treeview), col_offset - 1);
359   gtk_tree_view_column_set_sizing (GTK_TREE_VIEW_COLUMN (column),
360                                    GTK_TREE_VIEW_COLUMN_FIXED);
361   gtk_tree_view_column_set_fixed_width (GTK_TREE_VIEW_COLUMN (column), 50);
362   gtk_tree_view_column_set_clickable (GTK_TREE_VIEW_COLUMN (column), TRUE);
363
364   /* dave column */
365   renderer = gtk_cell_renderer_toggle_new ();
366   g_object_set (renderer, "xalign", 0.0, NULL);
367   g_object_set_data (G_OBJECT (renderer), "column", (gint *)DAVE_COLUMN);
368
369   g_signal_connect (renderer, "toggled", G_CALLBACK (item_toggled), model);
370
371   col_offset = gtk_tree_view_insert_column_with_attributes (GTK_TREE_VIEW (treeview),
372                                                             -1, "Dave",
373                                                             renderer,
374                                                             "active",
375                                                             DAVE_COLUMN,
376                                                             "visible",
377                                                             VISIBLE_COLUMN,
378                                                             NULL);
379
380   column = gtk_tree_view_get_column (GTK_TREE_VIEW (treeview), col_offset - 1);
381   gtk_tree_view_column_set_sizing (GTK_TREE_VIEW_COLUMN (column),
382                                    GTK_TREE_VIEW_COLUMN_FIXED);
383   gtk_tree_view_column_set_fixed_width (GTK_TREE_VIEW_COLUMN (column), 50);
384   gtk_tree_view_column_set_clickable (GTK_TREE_VIEW_COLUMN (column), TRUE);
385 }
386
387 GtkWidget *
388 do_tree_store (GtkWidget *do_widget)
389 {
390   if (!window)
391     {
392       GtkWidget *vbox;
393       GtkWidget *sw;
394       GtkWidget *treeview;
395       GtkTreeModel *model;
396
397       /* create window, etc */
398       window = gtk_window_new (GTK_WINDOW_TOPLEVEL);
399       gtk_window_set_screen (GTK_WINDOW (window),
400                              gtk_widget_get_screen (do_widget));
401       gtk_window_set_title (GTK_WINDOW (window), "Card planning sheet");
402       g_signal_connect (window, "destroy",
403                         G_CALLBACK (gtk_widget_destroyed), &window);
404
405       vbox = gtk_box_new (GTK_ORIENTATION_VERTICAL, FALSE, 8);
406       gtk_container_set_border_width (GTK_CONTAINER (vbox), 8);
407       gtk_container_add (GTK_CONTAINER (window), vbox);
408
409       gtk_box_pack_start (GTK_BOX (vbox),
410                           gtk_label_new ("Jonathan's Holiday Card Planning Sheet"),
411                           FALSE, FALSE, 0);
412
413       sw = gtk_scrolled_window_new (NULL, NULL);
414       gtk_scrolled_window_set_shadow_type (GTK_SCROLLED_WINDOW (sw),
415                                            GTK_SHADOW_ETCHED_IN);
416       gtk_scrolled_window_set_policy (GTK_SCROLLED_WINDOW (sw),
417                                       GTK_POLICY_AUTOMATIC,
418                                       GTK_POLICY_AUTOMATIC);
419       gtk_box_pack_start (GTK_BOX (vbox), sw, TRUE, TRUE, 0);
420
421       /* create model */
422       model = create_model ();
423
424       /* create tree view */
425       treeview = gtk_tree_view_new_with_model (model);
426       g_object_unref (model);
427       gtk_tree_view_set_rules_hint (GTK_TREE_VIEW (treeview), TRUE);
428       gtk_tree_selection_set_mode (gtk_tree_view_get_selection (GTK_TREE_VIEW (treeview)),
429                                    GTK_SELECTION_MULTIPLE);
430
431       add_columns (GTK_TREE_VIEW (treeview));
432
433       gtk_container_add (GTK_CONTAINER (sw), treeview);
434
435       /* expand all rows after the treeview widget has been realized */
436       g_signal_connect (treeview, "realize",
437                         G_CALLBACK (gtk_tree_view_expand_all), NULL);
438       gtk_window_set_default_size (GTK_WINDOW (window), 650, 400);
439     }
440
441   if (!gtk_widget_get_visible (window))
442     gtk_widget_show_all (window);
443   else
444     {
445       gtk_widget_destroy (window);
446       window = NULL;
447     }
448
449   return window;
450 }