1 | /* testtreeview.c |
2 | * Copyright (C) 2001 Red Hat, Inc |
3 | * Author: Jonathan Blandford |
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 <string.h> |
20 | #include <gtk/gtk.h> |
21 | #include <stdlib.h> |
22 | |
23 | /* Don't copy this bad example; inline RGB data is always a better |
24 | * idea than inline XPMs. |
25 | */ |
26 | static const char *book_closed_xpm[] = { |
27 | "16 16 6 1" , |
28 | " c None s None" , |
29 | ". c black" , |
30 | "X c red" , |
31 | "o c yellow" , |
32 | "O c #808080" , |
33 | "# c white" , |
34 | " " , |
35 | " .. " , |
36 | " ..XX. " , |
37 | " ..XXXXX. " , |
38 | " ..XXXXXXXX. " , |
39 | ".ooXXXXXXXXX. " , |
40 | "..ooXXXXXXXXX. " , |
41 | ".X.ooXXXXXXXXX. " , |
42 | ".XX.ooXXXXXX.. " , |
43 | " .XX.ooXXX..#O " , |
44 | " .XX.oo..##OO. " , |
45 | " .XX..##OO.. " , |
46 | " .X.#OO.. " , |
47 | " ..O.. " , |
48 | " .. " , |
49 | " " |
50 | }; |
51 | |
52 | static void run_automated_tests (void); |
53 | |
54 | /* This custom model is to test custom model use. */ |
55 | |
56 | #define GTK_TYPE_MODEL_TYPES (gtk_tree_model_types_get_type ()) |
57 | #define GTK_TREE_MODEL_TYPES(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), GTK_TYPE_MODEL_TYPES, GtkTreeModelTypes)) |
58 | #define GTK_TREE_MODEL_TYPES_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), GTK_TYPE_MODEL_TYPES, GtkTreeModelTypesClass)) |
59 | #define GTK_IS_TREE_MODEL_TYPES(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), GTK_TYPE_MODEL_TYPES)) |
60 | #define GTK_IS_TREE_MODEL_TYPES_GET_CLASS(klass) (G_TYPE_INSTANCE_GET_CLASS ((obj), GTK_TYPE_MODEL_TYPES)) |
61 | |
62 | typedef struct _GtkTreeModelTypes GtkTreeModelTypes; |
63 | typedef struct _GtkTreeModelTypesClass GtkTreeModelTypesClass; |
64 | |
65 | struct _GtkTreeModelTypes |
66 | { |
67 | GObject parent; |
68 | |
69 | int stamp; |
70 | }; |
71 | |
72 | struct _GtkTreeModelTypesClass |
73 | { |
74 | GObjectClass parent_class; |
75 | |
76 | guint (* get_flags) (GtkTreeModel *tree_model); |
77 | int (* get_n_columns) (GtkTreeModel *tree_model); |
78 | GType (* get_column_type) (GtkTreeModel *tree_model, |
79 | int index); |
80 | gboolean (* get_iter) (GtkTreeModel *tree_model, |
81 | GtkTreeIter *iter, |
82 | GtkTreePath *path); |
83 | GtkTreePath *(* get_path) (GtkTreeModel *tree_model, |
84 | GtkTreeIter *iter); |
85 | void (* get_value) (GtkTreeModel *tree_model, |
86 | GtkTreeIter *iter, |
87 | int column, |
88 | GValue *value); |
89 | gboolean (* iter_next) (GtkTreeModel *tree_model, |
90 | GtkTreeIter *iter); |
91 | gboolean (* iter_children) (GtkTreeModel *tree_model, |
92 | GtkTreeIter *iter, |
93 | GtkTreeIter *parent); |
94 | gboolean (* iter_has_child) (GtkTreeModel *tree_model, |
95 | GtkTreeIter *iter); |
96 | int (* iter_n_children) (GtkTreeModel *tree_model, |
97 | GtkTreeIter *iter); |
98 | gboolean (* iter_nth_child) (GtkTreeModel *tree_model, |
99 | GtkTreeIter *iter, |
100 | GtkTreeIter *parent, |
101 | int n); |
102 | gboolean (* iter_parent) (GtkTreeModel *tree_model, |
103 | GtkTreeIter *iter, |
104 | GtkTreeIter *child); |
105 | void (* ref_iter) (GtkTreeModel *tree_model, |
106 | GtkTreeIter *iter); |
107 | void (* unref_iter) (GtkTreeModel *tree_model, |
108 | GtkTreeIter *iter); |
109 | |
110 | /* These will be moved into the GtkTreeModelIface eventually */ |
111 | void (* changed) (GtkTreeModel *tree_model, |
112 | GtkTreePath *path, |
113 | GtkTreeIter *iter); |
114 | void (* inserted) (GtkTreeModel *tree_model, |
115 | GtkTreePath *path, |
116 | GtkTreeIter *iter); |
117 | void (* child_toggled) (GtkTreeModel *tree_model, |
118 | GtkTreePath *path, |
119 | GtkTreeIter *iter); |
120 | void (* deleted) (GtkTreeModel *tree_model, |
121 | GtkTreePath *path); |
122 | }; |
123 | |
124 | GType gtk_tree_model_types_get_type (void) G_GNUC_CONST; |
125 | GtkTreeModelTypes *gtk_tree_model_types_new (void); |
126 | |
127 | typedef enum |
128 | { |
129 | COLUMNS_NONE, |
130 | COLUMNS_ONE, |
131 | COLUMNS_LOTS, |
132 | COLUMNS_LAST |
133 | } ColumnsType; |
134 | |
135 | static const char *column_type_names[] = { |
136 | "No columns" , |
137 | "One column" , |
138 | "Many columns" |
139 | }; |
140 | |
141 | #define N_COLUMNS 9 |
142 | |
143 | static GType* |
144 | get_model_types (void) |
145 | { |
146 | static GType column_types[N_COLUMNS] = { 0 }; |
147 | |
148 | if (column_types[0] == 0) |
149 | { |
150 | column_types[0] = G_TYPE_STRING; |
151 | column_types[1] = G_TYPE_STRING; |
152 | column_types[2] = GDK_TYPE_PIXBUF; |
153 | column_types[3] = G_TYPE_FLOAT; |
154 | column_types[4] = G_TYPE_UINT; |
155 | column_types[5] = G_TYPE_UCHAR; |
156 | column_types[6] = G_TYPE_CHAR; |
157 | #define BOOL_COLUMN 7 |
158 | column_types[BOOL_COLUMN] = G_TYPE_BOOLEAN; |
159 | column_types[8] = G_TYPE_INT; |
160 | } |
161 | |
162 | return column_types; |
163 | } |
164 | |
165 | static void |
166 | toggled_callback (GtkCellRendererToggle *celltoggle, |
167 | char *path_string, |
168 | GtkTreeView *tree_view) |
169 | { |
170 | GtkTreeModel *model = NULL; |
171 | GtkTreeModelSort *sort_model = NULL; |
172 | GtkTreePath *path; |
173 | GtkTreeIter iter; |
174 | gboolean active = FALSE; |
175 | |
176 | g_return_if_fail (GTK_IS_TREE_VIEW (tree_view)); |
177 | |
178 | model = gtk_tree_view_get_model (tree_view); |
179 | |
180 | if (GTK_IS_TREE_MODEL_SORT (model)) |
181 | { |
182 | sort_model = GTK_TREE_MODEL_SORT (model); |
183 | model = gtk_tree_model_sort_get_model (tree_model: sort_model); |
184 | } |
185 | |
186 | if (model == NULL) |
187 | return; |
188 | |
189 | if (sort_model) |
190 | { |
191 | g_warning ("FIXME implement conversion from TreeModelSort iter to child model iter" ); |
192 | return; |
193 | } |
194 | |
195 | path = gtk_tree_path_new_from_string (path: path_string); |
196 | if (!gtk_tree_model_get_iter (tree_model: model, |
197 | iter: &iter, path)) |
198 | { |
199 | g_warning ("%s: bad path?" , G_STRLOC); |
200 | return; |
201 | } |
202 | gtk_tree_path_free (path); |
203 | |
204 | if (GTK_IS_LIST_STORE (model)) |
205 | { |
206 | gtk_tree_model_get (GTK_TREE_MODEL (model), |
207 | iter: &iter, |
208 | BOOL_COLUMN, |
209 | &active, |
210 | -1); |
211 | |
212 | gtk_list_store_set (GTK_LIST_STORE (model), |
213 | iter: &iter, |
214 | BOOL_COLUMN, |
215 | !active, |
216 | -1); |
217 | } |
218 | else if (GTK_IS_TREE_STORE (model)) |
219 | { |
220 | gtk_tree_model_get (GTK_TREE_MODEL (model), |
221 | iter: &iter, |
222 | BOOL_COLUMN, |
223 | &active, |
224 | -1); |
225 | |
226 | gtk_tree_store_set (GTK_TREE_STORE (model), |
227 | iter: &iter, |
228 | BOOL_COLUMN, |
229 | !active, |
230 | -1); |
231 | } |
232 | else |
233 | g_warning ("don't know how to actually toggle value for model type %s" , |
234 | g_type_name (G_TYPE_FROM_INSTANCE (model))); |
235 | } |
236 | |
237 | static void |
238 | edited_callback (GtkCellRendererText *renderer, |
239 | const char *path_string, |
240 | const char *new_text, |
241 | GtkTreeView *tree_view) |
242 | { |
243 | GtkTreeModel *model = NULL; |
244 | GtkTreeModelSort *sort_model = NULL; |
245 | GtkTreePath *path; |
246 | GtkTreeIter iter; |
247 | guint value = atoi (nptr: new_text); |
248 | |
249 | g_return_if_fail (GTK_IS_TREE_VIEW (tree_view)); |
250 | |
251 | model = gtk_tree_view_get_model (tree_view); |
252 | |
253 | if (GTK_IS_TREE_MODEL_SORT (model)) |
254 | { |
255 | sort_model = GTK_TREE_MODEL_SORT (model); |
256 | model = gtk_tree_model_sort_get_model (tree_model: sort_model); |
257 | } |
258 | |
259 | if (model == NULL) |
260 | return; |
261 | |
262 | if (sort_model) |
263 | { |
264 | g_warning ("FIXME implement conversion from TreeModelSort iter to child model iter" ); |
265 | return; |
266 | } |
267 | |
268 | path = gtk_tree_path_new_from_string (path: path_string); |
269 | if (!gtk_tree_model_get_iter (tree_model: model, |
270 | iter: &iter, path)) |
271 | { |
272 | g_warning ("%s: bad path?" , G_STRLOC); |
273 | return; |
274 | } |
275 | gtk_tree_path_free (path); |
276 | |
277 | if (GTK_IS_LIST_STORE (model)) |
278 | { |
279 | gtk_list_store_set (GTK_LIST_STORE (model), |
280 | iter: &iter, |
281 | 4, |
282 | value, |
283 | -1); |
284 | } |
285 | else if (GTK_IS_TREE_STORE (model)) |
286 | { |
287 | gtk_tree_store_set (GTK_TREE_STORE (model), |
288 | iter: &iter, |
289 | 4, |
290 | value, |
291 | -1); |
292 | } |
293 | else |
294 | g_warning ("don't know how to actually toggle value for model type %s" , |
295 | g_type_name (G_TYPE_FROM_INSTANCE (model))); |
296 | } |
297 | |
298 | static ColumnsType current_column_type = COLUMNS_LOTS; |
299 | |
300 | static void |
301 | set_columns_type (GtkTreeView *tree_view, ColumnsType type) |
302 | { |
303 | GtkTreeViewColumn *col; |
304 | GtkCellRenderer *rend; |
305 | GdkPixbuf *pixbuf; |
306 | GtkWidget *image; |
307 | GtkAdjustment *adjustment; |
308 | |
309 | current_column_type = type; |
310 | |
311 | col = gtk_tree_view_get_column (tree_view, n: 0); |
312 | while (col) |
313 | { |
314 | gtk_tree_view_remove_column (tree_view, column: col); |
315 | |
316 | col = gtk_tree_view_get_column (tree_view, n: 0); |
317 | } |
318 | |
319 | switch (type) |
320 | { |
321 | case COLUMNS_NONE: |
322 | break; |
323 | |
324 | case COLUMNS_LOTS: |
325 | rend = gtk_cell_renderer_text_new (); |
326 | |
327 | col = gtk_tree_view_column_new_with_attributes (title: "Column 1" , |
328 | cell: rend, |
329 | "text" , 1, |
330 | NULL); |
331 | |
332 | gtk_tree_view_append_column (GTK_TREE_VIEW (tree_view), column: col); |
333 | |
334 | col = gtk_tree_view_column_new(); |
335 | gtk_tree_view_column_set_title (tree_column: col, title: "Column 2" ); |
336 | |
337 | rend = gtk_cell_renderer_pixbuf_new (); |
338 | gtk_tree_view_column_pack_start (tree_column: col, cell: rend, FALSE); |
339 | gtk_tree_view_column_add_attribute (tree_column: col, cell_renderer: rend, attribute: "pixbuf" , column: 2); |
340 | rend = gtk_cell_renderer_text_new (); |
341 | gtk_tree_view_column_pack_start (tree_column: col, cell: rend, TRUE); |
342 | gtk_tree_view_column_add_attribute (tree_column: col, cell_renderer: rend, attribute: "text" , column: 0); |
343 | |
344 | |
345 | gtk_tree_view_append_column (GTK_TREE_VIEW (tree_view), column: col); |
346 | gtk_tree_view_set_expander_column (tree_view, column: col); |
347 | |
348 | rend = gtk_cell_renderer_toggle_new (); |
349 | |
350 | g_signal_connect (rend, "toggled" , |
351 | G_CALLBACK (toggled_callback), tree_view); |
352 | |
353 | col = gtk_tree_view_column_new_with_attributes (title: "Column 3" , |
354 | cell: rend, |
355 | "active" , BOOL_COLUMN, |
356 | NULL); |
357 | |
358 | gtk_tree_view_append_column (GTK_TREE_VIEW (tree_view), column: col); |
359 | |
360 | pixbuf = gdk_pixbuf_new_from_xpm_data (data: (const char **)book_closed_xpm); |
361 | |
362 | image = gtk_image_new_from_pixbuf (pixbuf); |
363 | |
364 | g_object_unref (object: pixbuf); |
365 | |
366 | gtk_tree_view_column_set_widget (tree_column: col, widget: image); |
367 | |
368 | rend = gtk_cell_renderer_toggle_new (); |
369 | |
370 | /* you could also set this per-row by tying it to a column |
371 | * in the model of course. |
372 | */ |
373 | g_object_set (object: rend, first_property_name: "radio" , TRUE, NULL); |
374 | |
375 | g_signal_connect (rend, "toggled" , |
376 | G_CALLBACK (toggled_callback), tree_view); |
377 | |
378 | col = gtk_tree_view_column_new_with_attributes (title: "Column 4" , |
379 | cell: rend, |
380 | "active" , BOOL_COLUMN, |
381 | NULL); |
382 | |
383 | gtk_tree_view_append_column (GTK_TREE_VIEW (tree_view), column: col); |
384 | |
385 | rend = gtk_cell_renderer_spin_new (); |
386 | |
387 | adjustment = gtk_adjustment_new (value: 0, lower: 0, upper: 10000, step_increment: 100, page_increment: 100, page_size: 100); |
388 | g_object_set (object: rend, first_property_name: "editable" , TRUE, NULL); |
389 | g_object_set (object: rend, first_property_name: "adjustment" , adjustment, NULL); |
390 | |
391 | g_signal_connect (rend, "edited" , |
392 | G_CALLBACK (edited_callback), tree_view); |
393 | |
394 | col = gtk_tree_view_column_new_with_attributes (title: "Column 5" , |
395 | cell: rend, |
396 | "text" , 4, |
397 | NULL); |
398 | |
399 | gtk_tree_view_append_column (GTK_TREE_VIEW (tree_view), column: col); |
400 | #if 0 |
401 | |
402 | rend = gtk_cell_renderer_text_new (); |
403 | |
404 | col = gtk_tree_view_column_new_with_attributes ("Column 6" , |
405 | rend, |
406 | "text" , 4, |
407 | NULL); |
408 | |
409 | gtk_tree_view_append_column (GTK_TREE_VIEW (tree_view), col); |
410 | |
411 | rend = gtk_cell_renderer_text_new (); |
412 | |
413 | col = gtk_tree_view_column_new_with_attributes ("Column 7" , |
414 | rend, |
415 | "text" , 5, |
416 | NULL); |
417 | |
418 | gtk_tree_view_append_column (GTK_TREE_VIEW (tree_view), col); |
419 | |
420 | rend = gtk_cell_renderer_text_new (); |
421 | |
422 | col = gtk_tree_view_column_new_with_attributes ("Column 8" , |
423 | rend, |
424 | "text" , 6, |
425 | NULL); |
426 | |
427 | gtk_tree_view_append_column (GTK_TREE_VIEW (tree_view), col); |
428 | |
429 | rend = gtk_cell_renderer_text_new (); |
430 | |
431 | col = gtk_tree_view_column_new_with_attributes ("Column 9" , |
432 | rend, |
433 | "text" , 7, |
434 | NULL); |
435 | |
436 | gtk_tree_view_append_column (GTK_TREE_VIEW (tree_view), col); |
437 | |
438 | rend = gtk_cell_renderer_text_new (); |
439 | |
440 | col = gtk_tree_view_column_new_with_attributes ("Column 10" , |
441 | rend, |
442 | "text" , 8, |
443 | NULL); |
444 | |
445 | gtk_tree_view_append_column (GTK_TREE_VIEW (tree_view), col); |
446 | |
447 | #endif |
448 | |
449 | G_GNUC_FALLTHROUGH; |
450 | |
451 | case COLUMNS_ONE: |
452 | rend = gtk_cell_renderer_text_new (); |
453 | |
454 | col = gtk_tree_view_column_new_with_attributes (title: "Column 0" , |
455 | cell: rend, |
456 | "text" , 0, |
457 | NULL); |
458 | |
459 | gtk_tree_view_insert_column (GTK_TREE_VIEW (tree_view), column: col, position: 0); |
460 | break; |
461 | case COLUMNS_LAST: |
462 | default: |
463 | break; |
464 | } |
465 | } |
466 | |
467 | static ColumnsType |
468 | get_columns_type (void) |
469 | { |
470 | return current_column_type; |
471 | } |
472 | |
473 | static GdkPixbuf *our_pixbuf; |
474 | |
475 | typedef enum |
476 | { |
477 | /* MODEL_TYPES, */ |
478 | MODEL_TREE, |
479 | MODEL_LIST, |
480 | MODEL_SORTED_TREE, |
481 | MODEL_SORTED_LIST, |
482 | MODEL_EMPTY_LIST, |
483 | MODEL_EMPTY_TREE, |
484 | MODEL_NULL, |
485 | MODEL_LAST |
486 | } ModelType; |
487 | |
488 | /* FIXME add a custom model to test */ |
489 | static GtkTreeModel *models[MODEL_LAST]; |
490 | static const char *model_names[MODEL_LAST] = { |
491 | "GtkTreeStore" , |
492 | "GtkListStore" , |
493 | "GtkTreeModelSort wrapping GtkTreeStore" , |
494 | "GtkTreeModelSort wrapping GtkListStore" , |
495 | "Empty GtkListStore" , |
496 | "Empty GtkTreeStore" , |
497 | "NULL (no model)" |
498 | }; |
499 | |
500 | static GtkTreeModel* |
501 | create_list_model (void) |
502 | { |
503 | GtkListStore *store; |
504 | GtkTreeIter iter; |
505 | int i; |
506 | GType *t; |
507 | |
508 | t = get_model_types (); |
509 | |
510 | store = gtk_list_store_new (N_COLUMNS, |
511 | t[0], t[1], t[2], |
512 | t[3], t[4], t[5], |
513 | t[6], t[7], t[8]); |
514 | |
515 | i = 0; |
516 | while (i < 200) |
517 | { |
518 | char *msg; |
519 | |
520 | gtk_list_store_append (list_store: store, iter: &iter); |
521 | |
522 | msg = g_strdup_printf (format: "%d" , i); |
523 | |
524 | gtk_list_store_set (list_store: store, iter: &iter, 0, msg, 1, "Foo! Foo! Foo!" , |
525 | 2, our_pixbuf, |
526 | 3, 7.0, 4, (guint) 9000, |
527 | 5, 'f', 6, 'g', |
528 | 7, TRUE, 8, 23245454, |
529 | -1); |
530 | |
531 | g_free (mem: msg); |
532 | |
533 | ++i; |
534 | } |
535 | |
536 | return GTK_TREE_MODEL (store); |
537 | } |
538 | |
539 | static void |
540 | typesystem_recurse (GType type, |
541 | GtkTreeIter *parent_iter, |
542 | GtkTreeStore *store) |
543 | { |
544 | GType* children; |
545 | guint n_children = 0; |
546 | int i; |
547 | GtkTreeIter iter; |
548 | char *str; |
549 | |
550 | gtk_tree_store_append (tree_store: store, iter: &iter, parent: parent_iter); |
551 | |
552 | str = g_strdup_printf (format: "%ld" , (glong)type); |
553 | gtk_tree_store_set (tree_store: store, iter: &iter, 0, str, 1, g_type_name (type), |
554 | 2, our_pixbuf, |
555 | 3, 7.0, 4, (guint) 9000, |
556 | 5, 'f', 6, 'g', |
557 | 7, TRUE, 8, 23245454, |
558 | -1); |
559 | g_free (mem: str); |
560 | |
561 | children = g_type_children (type, n_children: &n_children); |
562 | |
563 | i = 0; |
564 | while (i < n_children) |
565 | { |
566 | typesystem_recurse (type: children[i], parent_iter: &iter, store); |
567 | |
568 | ++i; |
569 | } |
570 | |
571 | g_free (mem: children); |
572 | } |
573 | |
574 | static GtkTreeModel* |
575 | create_tree_model (void) |
576 | { |
577 | GtkTreeStore *store; |
578 | int i; |
579 | GType *t; |
580 | |
581 | /* Make the tree more interesting */ |
582 | /* - we need this magic here so we are sure the type ends up being |
583 | * registered and gcc doesn't optimize away the code */ |
584 | g_type_class_unref (g_class: g_type_class_ref (type: gtk_scrolled_window_get_type ())); |
585 | g_type_class_unref (g_class: g_type_class_ref (type: gtk_label_get_type ())); |
586 | g_type_class_unref (g_class: g_type_class_ref (type: gtk_scrollbar_get_type ())); |
587 | g_type_class_unref (g_class: g_type_class_ref (type: pango_layout_get_type ())); |
588 | |
589 | t = get_model_types (); |
590 | |
591 | store = gtk_tree_store_new (N_COLUMNS, |
592 | t[0], t[1], t[2], |
593 | t[3], t[4], t[5], |
594 | t[6], t[7], t[8]); |
595 | |
596 | i = 0; |
597 | while (i < G_TYPE_FUNDAMENTAL_MAX) |
598 | { |
599 | typesystem_recurse (type: i, NULL, store); |
600 | |
601 | ++i; |
602 | } |
603 | |
604 | return GTK_TREE_MODEL (store); |
605 | } |
606 | |
607 | static void |
608 | model_selected (GtkComboBox *combo_box, gpointer data) |
609 | { |
610 | GtkTreeView *tree_view = GTK_TREE_VIEW (data); |
611 | int hist; |
612 | |
613 | hist = gtk_combo_box_get_active (combo_box); |
614 | |
615 | if (models[hist] != gtk_tree_view_get_model (tree_view)) |
616 | { |
617 | gtk_tree_view_set_model (tree_view, model: models[hist]); |
618 | } |
619 | } |
620 | |
621 | static void |
622 | columns_selected (GtkComboBox *combo_box, gpointer data) |
623 | { |
624 | GtkTreeView *tree_view = GTK_TREE_VIEW (data); |
625 | int hist; |
626 | |
627 | hist = gtk_combo_box_get_active (combo_box); |
628 | |
629 | if (hist != get_columns_type ()) |
630 | { |
631 | set_columns_type (tree_view, type: hist); |
632 | } |
633 | } |
634 | |
635 | static void |
636 | on_row_activated (GtkTreeView *tree_view, |
637 | GtkTreePath *path, |
638 | GtkTreeViewColumn *column, |
639 | gpointer user_data) |
640 | { |
641 | g_print (format: "Row activated\n" ); |
642 | } |
643 | |
644 | static void |
645 | quit_cb (GtkWidget *widget, |
646 | gpointer data) |
647 | { |
648 | gboolean *done = data; |
649 | |
650 | *done = TRUE; |
651 | |
652 | g_main_context_wakeup (NULL); |
653 | } |
654 | |
655 | int |
656 | main (int argc, |
657 | char **argv) |
658 | { |
659 | GtkWidget *window; |
660 | GtkWidget *sw; |
661 | GtkWidget *tv; |
662 | GtkWidget *box; |
663 | GtkWidget *combo_box; |
664 | GtkTreeModel *model; |
665 | GdkContentFormats *targets; |
666 | int i; |
667 | gboolean done = FALSE; |
668 | |
669 | gtk_init (); |
670 | |
671 | if (g_getenv (variable: "RTL" )) |
672 | gtk_widget_set_default_direction (dir: GTK_TEXT_DIR_RTL); |
673 | |
674 | our_pixbuf = gdk_pixbuf_new_from_xpm_data (data: (const char **) book_closed_xpm); |
675 | |
676 | #if 0 |
677 | models[MODEL_TYPES] = GTK_TREE_MODEL (gtk_tree_model_types_new ()); |
678 | #endif |
679 | models[MODEL_LIST] = create_list_model (); |
680 | models[MODEL_TREE] = create_tree_model (); |
681 | |
682 | model = create_list_model (); |
683 | models[MODEL_SORTED_LIST] = gtk_tree_model_sort_new_with_model (child_model: model); |
684 | g_object_unref (object: model); |
685 | |
686 | model = create_tree_model (); |
687 | models[MODEL_SORTED_TREE] = gtk_tree_model_sort_new_with_model (child_model: model); |
688 | g_object_unref (object: model); |
689 | |
690 | models[MODEL_EMPTY_LIST] = GTK_TREE_MODEL (gtk_list_store_new (1, G_TYPE_INT)); |
691 | models[MODEL_EMPTY_TREE] = GTK_TREE_MODEL (gtk_tree_store_new (1, G_TYPE_INT)); |
692 | |
693 | models[MODEL_NULL] = NULL; |
694 | |
695 | run_automated_tests (); |
696 | |
697 | window = gtk_window_new (); |
698 | g_signal_connect (window, "destroy" , G_CALLBACK (quit_cb), &done); |
699 | gtk_window_set_default_size (GTK_WINDOW (window), width: 430, height: 400); |
700 | |
701 | box = gtk_box_new (orientation: GTK_ORIENTATION_VERTICAL, spacing: 0); |
702 | |
703 | gtk_window_set_child (GTK_WINDOW (window), child: box); |
704 | |
705 | tv = gtk_tree_view_new_with_model (model: models[0]); |
706 | g_signal_connect (tv, "row-activated" , G_CALLBACK (on_row_activated), NULL); |
707 | |
708 | targets = gdk_content_formats_new_for_gtype (GTK_TYPE_TREE_ROW_DATA); |
709 | gtk_tree_view_enable_model_drag_source (GTK_TREE_VIEW (tv), |
710 | start_button_mask: GDK_BUTTON1_MASK, |
711 | formats: targets, |
712 | actions: GDK_ACTION_MOVE | GDK_ACTION_COPY); |
713 | |
714 | gtk_tree_view_enable_model_drag_dest (GTK_TREE_VIEW (tv), |
715 | formats: targets, |
716 | actions: GDK_ACTION_MOVE | GDK_ACTION_COPY); |
717 | gdk_content_formats_unref (formats: targets); |
718 | |
719 | /* Model menu */ |
720 | combo_box = gtk_combo_box_text_new (); |
721 | gtk_widget_set_halign (widget: combo_box, align: GTK_ALIGN_CENTER); |
722 | for (i = 0; i < MODEL_LAST; i++) |
723 | gtk_combo_box_text_append_text (GTK_COMBO_BOX_TEXT (combo_box), text: model_names[i]); |
724 | |
725 | gtk_box_append (GTK_BOX (box), child: combo_box); |
726 | g_signal_connect (combo_box, |
727 | "changed" , |
728 | G_CALLBACK (model_selected), |
729 | tv); |
730 | |
731 | /* Columns menu */ |
732 | combo_box = gtk_combo_box_text_new (); |
733 | gtk_widget_set_halign (widget: combo_box, align: GTK_ALIGN_CENTER); |
734 | for (i = 0; i < COLUMNS_LAST; i++) |
735 | gtk_combo_box_text_append_text (GTK_COMBO_BOX_TEXT (combo_box), text: column_type_names[i]); |
736 | |
737 | gtk_box_append (GTK_BOX (box), child: combo_box); |
738 | |
739 | set_columns_type (GTK_TREE_VIEW (tv), type: COLUMNS_LOTS); |
740 | gtk_combo_box_set_active (GTK_COMBO_BOX (combo_box), index_: COLUMNS_LOTS); |
741 | |
742 | g_signal_connect (combo_box, |
743 | "changed" , |
744 | G_CALLBACK (columns_selected), |
745 | tv); |
746 | |
747 | sw = gtk_scrolled_window_new (); |
748 | gtk_widget_set_hexpand (widget: sw, TRUE); |
749 | gtk_widget_set_vexpand (widget: sw, TRUE); |
750 | gtk_scrolled_window_set_policy (GTK_SCROLLED_WINDOW (sw), |
751 | hscrollbar_policy: GTK_POLICY_AUTOMATIC, |
752 | vscrollbar_policy: GTK_POLICY_AUTOMATIC); |
753 | |
754 | gtk_box_append (GTK_BOX (box), child: sw); |
755 | |
756 | gtk_scrolled_window_set_child (GTK_SCROLLED_WINDOW (sw), child: tv); |
757 | |
758 | gtk_widget_show (widget: window); |
759 | |
760 | while (!done) |
761 | g_main_context_iteration (NULL, TRUE); |
762 | |
763 | return 0; |
764 | } |
765 | |
766 | /* |
767 | * GtkTreeModelTypes |
768 | */ |
769 | |
770 | static void gtk_tree_model_types_init (GtkTreeModelTypes *model_types); |
771 | static void gtk_tree_model_types_tree_model_init (GtkTreeModelIface *iface); |
772 | static int gtk_real_model_types_get_n_columns (GtkTreeModel *tree_model); |
773 | static GType gtk_real_model_types_get_column_type (GtkTreeModel *tree_model, |
774 | int index); |
775 | static GtkTreePath *gtk_real_model_types_get_path (GtkTreeModel *tree_model, |
776 | GtkTreeIter *iter); |
777 | static void gtk_real_model_types_get_value (GtkTreeModel *tree_model, |
778 | GtkTreeIter *iter, |
779 | int column, |
780 | GValue *value); |
781 | static gboolean gtk_real_model_types_iter_next (GtkTreeModel *tree_model, |
782 | GtkTreeIter *iter); |
783 | static gboolean gtk_real_model_types_iter_children (GtkTreeModel *tree_model, |
784 | GtkTreeIter *iter, |
785 | GtkTreeIter *parent); |
786 | static gboolean gtk_real_model_types_iter_has_child (GtkTreeModel *tree_model, |
787 | GtkTreeIter *iter); |
788 | static int gtk_real_model_types_iter_n_children (GtkTreeModel *tree_model, |
789 | GtkTreeIter *iter); |
790 | static gboolean gtk_real_model_types_iter_nth_child (GtkTreeModel *tree_model, |
791 | GtkTreeIter *iter, |
792 | GtkTreeIter *parent, |
793 | int n); |
794 | static gboolean gtk_real_model_types_iter_parent (GtkTreeModel *tree_model, |
795 | GtkTreeIter *iter, |
796 | GtkTreeIter *child); |
797 | |
798 | |
799 | GType |
800 | gtk_tree_model_types_get_type (void) |
801 | { |
802 | static GType model_types_type = 0; |
803 | |
804 | if (!model_types_type) |
805 | { |
806 | const GTypeInfo model_types_info = |
807 | { |
808 | sizeof (GtkTreeModelTypesClass), |
809 | NULL, /* base_init */ |
810 | NULL, /* base_finalize */ |
811 | NULL, /* class_init */ |
812 | NULL, /* class_finalize */ |
813 | NULL, /* class_data */ |
814 | sizeof (GtkTreeModelTypes), |
815 | 0, |
816 | (GInstanceInitFunc) gtk_tree_model_types_init |
817 | }; |
818 | |
819 | const GInterfaceInfo tree_model_info = |
820 | { |
821 | (GInterfaceInitFunc) gtk_tree_model_types_tree_model_init, |
822 | NULL, |
823 | NULL |
824 | }; |
825 | |
826 | model_types_type = g_type_register_static (G_TYPE_OBJECT, |
827 | type_name: "GtkTreeModelTypes" , |
828 | info: &model_types_info, flags: 0); |
829 | g_type_add_interface_static (instance_type: model_types_type, |
830 | GTK_TYPE_TREE_MODEL, |
831 | info: &tree_model_info); |
832 | } |
833 | |
834 | return model_types_type; |
835 | } |
836 | |
837 | GtkTreeModelTypes * |
838 | gtk_tree_model_types_new (void) |
839 | { |
840 | GtkTreeModelTypes *retval; |
841 | |
842 | retval = g_object_new (GTK_TYPE_MODEL_TYPES, NULL); |
843 | |
844 | return retval; |
845 | } |
846 | |
847 | static void |
848 | gtk_tree_model_types_tree_model_init (GtkTreeModelIface *iface) |
849 | { |
850 | iface->get_n_columns = gtk_real_model_types_get_n_columns; |
851 | iface->get_column_type = gtk_real_model_types_get_column_type; |
852 | iface->get_path = gtk_real_model_types_get_path; |
853 | iface->get_value = gtk_real_model_types_get_value; |
854 | iface->iter_next = gtk_real_model_types_iter_next; |
855 | iface->iter_children = gtk_real_model_types_iter_children; |
856 | iface->iter_has_child = gtk_real_model_types_iter_has_child; |
857 | iface->iter_n_children = gtk_real_model_types_iter_n_children; |
858 | iface->iter_nth_child = gtk_real_model_types_iter_nth_child; |
859 | iface->iter_parent = gtk_real_model_types_iter_parent; |
860 | } |
861 | |
862 | static void |
863 | gtk_tree_model_types_init (GtkTreeModelTypes *model_types) |
864 | { |
865 | model_types->stamp = g_random_int (); |
866 | } |
867 | |
868 | static GType column_types[] = { |
869 | G_TYPE_STRING, /* GType */ |
870 | G_TYPE_STRING /* type name */ |
871 | }; |
872 | |
873 | static int |
874 | gtk_real_model_types_get_n_columns (GtkTreeModel *tree_model) |
875 | { |
876 | return G_N_ELEMENTS (column_types); |
877 | } |
878 | |
879 | static GType |
880 | gtk_real_model_types_get_column_type (GtkTreeModel *tree_model, |
881 | int index) |
882 | { |
883 | g_return_val_if_fail (index < G_N_ELEMENTS (column_types), G_TYPE_INVALID); |
884 | |
885 | return column_types[index]; |
886 | } |
887 | |
888 | #if 0 |
889 | /* Use default implementation of this */ |
890 | static gboolean |
891 | gtk_real_model_types_get_iter (GtkTreeModel *tree_model, |
892 | GtkTreeIter *iter, |
893 | GtkTreePath *path) |
894 | { |
895 | |
896 | } |
897 | #endif |
898 | |
899 | /* The toplevel nodes of the tree are the reserved types, G_TYPE_NONE through |
900 | * G_TYPE_RESERVED_FUNDAMENTAL. |
901 | */ |
902 | |
903 | static GtkTreePath * |
904 | gtk_real_model_types_get_path (GtkTreeModel *tree_model, |
905 | GtkTreeIter *iter) |
906 | { |
907 | GtkTreePath *retval; |
908 | GType type; |
909 | GType parent; |
910 | |
911 | g_return_val_if_fail (GTK_IS_TREE_MODEL_TYPES (tree_model), NULL); |
912 | g_return_val_if_fail (iter != NULL, NULL); |
913 | |
914 | type = GPOINTER_TO_INT (iter->user_data); |
915 | |
916 | retval = gtk_tree_path_new (); |
917 | |
918 | parent = g_type_parent (type); |
919 | while (parent != G_TYPE_INVALID) |
920 | { |
921 | GType* children = g_type_children (type: parent, NULL); |
922 | int i = 0; |
923 | |
924 | if (!children || children[0] == G_TYPE_INVALID) |
925 | { |
926 | g_warning ("bad iterator?" ); |
927 | return NULL; |
928 | } |
929 | |
930 | while (children[i] != type) |
931 | ++i; |
932 | |
933 | gtk_tree_path_prepend_index (path: retval, index_: i); |
934 | |
935 | g_free (mem: children); |
936 | |
937 | type = parent; |
938 | parent = g_type_parent (type: parent); |
939 | } |
940 | |
941 | /* The fundamental type itself is the index on the toplevel */ |
942 | gtk_tree_path_prepend_index (path: retval, index_: type); |
943 | |
944 | return retval; |
945 | } |
946 | |
947 | static void |
948 | gtk_real_model_types_get_value (GtkTreeModel *tree_model, |
949 | GtkTreeIter *iter, |
950 | int column, |
951 | GValue *value) |
952 | { |
953 | GType type; |
954 | |
955 | type = GPOINTER_TO_INT (iter->user_data); |
956 | |
957 | switch (column) |
958 | { |
959 | case 0: |
960 | { |
961 | char *str; |
962 | |
963 | g_value_init (value, G_TYPE_STRING); |
964 | |
965 | str = g_strdup_printf (format: "%ld" , (long int) type); |
966 | g_value_set_string (value, v_string: str); |
967 | g_free (mem: str); |
968 | } |
969 | break; |
970 | |
971 | case 1: |
972 | g_value_init (value, G_TYPE_STRING); |
973 | g_value_set_string (value, v_string: g_type_name (type)); |
974 | break; |
975 | |
976 | default: |
977 | g_warning ("Bad column %d requested" , column); |
978 | } |
979 | } |
980 | |
981 | static gboolean |
982 | gtk_real_model_types_iter_next (GtkTreeModel *tree_model, |
983 | GtkTreeIter *iter) |
984 | { |
985 | |
986 | GType parent; |
987 | GType type; |
988 | |
989 | type = GPOINTER_TO_INT (iter->user_data); |
990 | |
991 | parent = g_type_parent (type); |
992 | |
993 | if (parent == G_TYPE_INVALID) |
994 | { |
995 | /* find next _valid_ fundamental type */ |
996 | do |
997 | type++; |
998 | while (!g_type_name (type) && type <= G_TYPE_FUNDAMENTAL_MAX); |
999 | if (type <= G_TYPE_FUNDAMENTAL_MAX) |
1000 | { |
1001 | /* found one */ |
1002 | iter->user_data = GINT_TO_POINTER (type); |
1003 | return TRUE; |
1004 | } |
1005 | else |
1006 | return FALSE; |
1007 | } |
1008 | else |
1009 | { |
1010 | GType* children = g_type_children (type: parent, NULL); |
1011 | int i = 0; |
1012 | |
1013 | g_assert (children != NULL); |
1014 | |
1015 | while (children[i] != type) |
1016 | ++i; |
1017 | |
1018 | ++i; |
1019 | |
1020 | if (children[i] != G_TYPE_INVALID) |
1021 | { |
1022 | iter->user_data = GINT_TO_POINTER (children[i]); |
1023 | g_free (mem: children); |
1024 | return TRUE; |
1025 | } |
1026 | else |
1027 | { |
1028 | g_free (mem: children); |
1029 | return FALSE; |
1030 | } |
1031 | } |
1032 | } |
1033 | |
1034 | static gboolean |
1035 | gtk_real_model_types_iter_children (GtkTreeModel *tree_model, |
1036 | GtkTreeIter *iter, |
1037 | GtkTreeIter *parent) |
1038 | { |
1039 | GType type; |
1040 | GType* children; |
1041 | |
1042 | type = GPOINTER_TO_INT (parent->user_data); |
1043 | |
1044 | children = g_type_children (type, NULL); |
1045 | |
1046 | if (!children || children[0] == G_TYPE_INVALID) |
1047 | { |
1048 | g_free (mem: children); |
1049 | return FALSE; |
1050 | } |
1051 | else |
1052 | { |
1053 | iter->user_data = GINT_TO_POINTER (children[0]); |
1054 | g_free (mem: children); |
1055 | return TRUE; |
1056 | } |
1057 | } |
1058 | |
1059 | static gboolean |
1060 | gtk_real_model_types_iter_has_child (GtkTreeModel *tree_model, |
1061 | GtkTreeIter *iter) |
1062 | { |
1063 | GType type; |
1064 | GType* children; |
1065 | |
1066 | type = GPOINTER_TO_INT (iter->user_data); |
1067 | |
1068 | children = g_type_children (type, NULL); |
1069 | |
1070 | if (!children || children[0] == G_TYPE_INVALID) |
1071 | { |
1072 | g_free (mem: children); |
1073 | return FALSE; |
1074 | } |
1075 | else |
1076 | { |
1077 | g_free (mem: children); |
1078 | return TRUE; |
1079 | } |
1080 | } |
1081 | |
1082 | static int |
1083 | gtk_real_model_types_iter_n_children (GtkTreeModel *tree_model, |
1084 | GtkTreeIter *iter) |
1085 | { |
1086 | if (iter == NULL) |
1087 | { |
1088 | return G_TYPE_FUNDAMENTAL_MAX; |
1089 | } |
1090 | else |
1091 | { |
1092 | GType type; |
1093 | GType* children; |
1094 | guint n_children = 0; |
1095 | |
1096 | type = GPOINTER_TO_INT (iter->user_data); |
1097 | |
1098 | children = g_type_children (type, n_children: &n_children); |
1099 | |
1100 | g_free (mem: children); |
1101 | |
1102 | return n_children; |
1103 | } |
1104 | } |
1105 | |
1106 | static gboolean |
1107 | gtk_real_model_types_iter_nth_child (GtkTreeModel *tree_model, |
1108 | GtkTreeIter *iter, |
1109 | GtkTreeIter *parent, |
1110 | int n) |
1111 | { |
1112 | if (parent == NULL) |
1113 | { |
1114 | /* fundamental type */ |
1115 | if (n < G_TYPE_FUNDAMENTAL_MAX) |
1116 | { |
1117 | iter->user_data = GINT_TO_POINTER (n); |
1118 | return TRUE; |
1119 | } |
1120 | else |
1121 | return FALSE; |
1122 | } |
1123 | else |
1124 | { |
1125 | GType type = GPOINTER_TO_INT (parent->user_data); |
1126 | guint n_children = 0; |
1127 | GType* children = g_type_children (type, n_children: &n_children); |
1128 | |
1129 | if (n_children == 0) |
1130 | { |
1131 | g_free (mem: children); |
1132 | return FALSE; |
1133 | } |
1134 | else if (n >= n_children) |
1135 | { |
1136 | g_free (mem: children); |
1137 | return FALSE; |
1138 | } |
1139 | else |
1140 | { |
1141 | iter->user_data = GINT_TO_POINTER (children[n]); |
1142 | g_free (mem: children); |
1143 | |
1144 | return TRUE; |
1145 | } |
1146 | } |
1147 | } |
1148 | |
1149 | static gboolean |
1150 | gtk_real_model_types_iter_parent (GtkTreeModel *tree_model, |
1151 | GtkTreeIter *iter, |
1152 | GtkTreeIter *child) |
1153 | { |
1154 | GType type; |
1155 | GType parent; |
1156 | |
1157 | type = GPOINTER_TO_INT (child->user_data); |
1158 | |
1159 | parent = g_type_parent (type); |
1160 | |
1161 | if (parent == G_TYPE_INVALID) |
1162 | { |
1163 | if (type > G_TYPE_FUNDAMENTAL_MAX) |
1164 | g_warning ("no parent for %ld %s\n" , |
1165 | (long int) type, |
1166 | g_type_name (type)); |
1167 | return FALSE; |
1168 | } |
1169 | else |
1170 | { |
1171 | iter->user_data = GINT_TO_POINTER (parent); |
1172 | |
1173 | return TRUE; |
1174 | } |
1175 | } |
1176 | |
1177 | /* |
1178 | * Automated testing |
1179 | */ |
1180 | |
1181 | #if 0 |
1182 | |
1183 | static void |
1184 | treestore_torture_recurse (GtkTreeStore *store, |
1185 | GtkTreeIter *root, |
1186 | int depth) |
1187 | { |
1188 | GtkTreeModel *model; |
1189 | int i; |
1190 | GtkTreeIter iter; |
1191 | |
1192 | model = GTK_TREE_MODEL (store); |
1193 | |
1194 | if (depth > 2) |
1195 | return; |
1196 | |
1197 | ++depth; |
1198 | |
1199 | gtk_tree_store_append (store, &iter, root); |
1200 | |
1201 | gtk_tree_model_iter_children (model, &iter, root); |
1202 | |
1203 | i = 0; |
1204 | while (i < 100) |
1205 | { |
1206 | gtk_tree_store_append (store, &iter, root); |
1207 | ++i; |
1208 | } |
1209 | |
1210 | while (gtk_tree_model_iter_children (model, &iter, root)) |
1211 | gtk_tree_store_remove (store, &iter); |
1212 | |
1213 | gtk_tree_store_append (store, &iter, root); |
1214 | |
1215 | /* inserts before last node in tree */ |
1216 | i = 0; |
1217 | while (i < 100) |
1218 | { |
1219 | gtk_tree_store_insert_before (store, &iter, root, &iter); |
1220 | ++i; |
1221 | } |
1222 | |
1223 | /* inserts after the node before the last node */ |
1224 | i = 0; |
1225 | while (i < 100) |
1226 | { |
1227 | gtk_tree_store_insert_after (store, &iter, root, &iter); |
1228 | ++i; |
1229 | } |
1230 | |
1231 | /* inserts after the last node */ |
1232 | gtk_tree_store_append (store, &iter, root); |
1233 | |
1234 | i = 0; |
1235 | while (i < 100) |
1236 | { |
1237 | gtk_tree_store_insert_after (store, &iter, root, &iter); |
1238 | ++i; |
1239 | } |
1240 | |
1241 | /* remove everything again */ |
1242 | while (gtk_tree_model_iter_children (model, &iter, root)) |
1243 | gtk_tree_store_remove (store, &iter); |
1244 | |
1245 | |
1246 | /* Prepends */ |
1247 | gtk_tree_store_prepend (store, &iter, root); |
1248 | |
1249 | i = 0; |
1250 | while (i < 100) |
1251 | { |
1252 | gtk_tree_store_prepend (store, &iter, root); |
1253 | ++i; |
1254 | } |
1255 | |
1256 | /* remove everything again */ |
1257 | while (gtk_tree_model_iter_children (model, &iter, root)) |
1258 | gtk_tree_store_remove (store, &iter); |
1259 | |
1260 | gtk_tree_store_append (store, &iter, root); |
1261 | gtk_tree_store_append (store, &iter, root); |
1262 | gtk_tree_store_append (store, &iter, root); |
1263 | gtk_tree_store_append (store, &iter, root); |
1264 | |
1265 | while (gtk_tree_model_iter_children (model, &iter, root)) |
1266 | { |
1267 | treestore_torture_recurse (store, &iter, depth); |
1268 | gtk_tree_store_remove (store, &iter); |
1269 | } |
1270 | } |
1271 | |
1272 | #endif |
1273 | |
1274 | static void |
1275 | run_automated_tests (void) |
1276 | { |
1277 | g_print (format: "Running automated tests...\n" ); |
1278 | |
1279 | /* FIXME TreePath basic verification */ |
1280 | |
1281 | /* FIXME generic consistency checks on the models */ |
1282 | |
1283 | { |
1284 | /* Make sure list store mutations don't crash anything */ |
1285 | GtkListStore *store; |
1286 | GtkTreeModel *model; |
1287 | int i; |
1288 | GtkTreeIter iter; |
1289 | |
1290 | store = gtk_list_store_new (n_columns: 1, G_TYPE_INT); |
1291 | |
1292 | model = GTK_TREE_MODEL (store); |
1293 | |
1294 | i = 0; |
1295 | while (i < 100) |
1296 | { |
1297 | gtk_list_store_append (list_store: store, iter: &iter); |
1298 | ++i; |
1299 | } |
1300 | |
1301 | while (gtk_tree_model_get_iter_first (tree_model: model, iter: &iter)) |
1302 | gtk_list_store_remove (list_store: store, iter: &iter); |
1303 | |
1304 | gtk_list_store_append (list_store: store, iter: &iter); |
1305 | |
1306 | /* inserts before last node in list */ |
1307 | i = 0; |
1308 | while (i < 100) |
1309 | { |
1310 | gtk_list_store_insert_before (list_store: store, iter: &iter, sibling: &iter); |
1311 | ++i; |
1312 | } |
1313 | |
1314 | /* inserts after the node before the last node */ |
1315 | i = 0; |
1316 | while (i < 100) |
1317 | { |
1318 | gtk_list_store_insert_after (list_store: store, iter: &iter, sibling: &iter); |
1319 | ++i; |
1320 | } |
1321 | |
1322 | /* inserts after the last node */ |
1323 | gtk_list_store_append (list_store: store, iter: &iter); |
1324 | |
1325 | i = 0; |
1326 | while (i < 100) |
1327 | { |
1328 | gtk_list_store_insert_after (list_store: store, iter: &iter, sibling: &iter); |
1329 | ++i; |
1330 | } |
1331 | |
1332 | /* remove everything again */ |
1333 | while (gtk_tree_model_get_iter_first (tree_model: model, iter: &iter)) |
1334 | gtk_list_store_remove (list_store: store, iter: &iter); |
1335 | |
1336 | |
1337 | /* Prepends */ |
1338 | gtk_list_store_prepend (list_store: store, iter: &iter); |
1339 | |
1340 | i = 0; |
1341 | while (i < 100) |
1342 | { |
1343 | gtk_list_store_prepend (list_store: store, iter: &iter); |
1344 | ++i; |
1345 | } |
1346 | |
1347 | /* remove everything again */ |
1348 | while (gtk_tree_model_get_iter_first (tree_model: model, iter: &iter)) |
1349 | gtk_list_store_remove (list_store: store, iter: &iter); |
1350 | |
1351 | g_object_unref (object: store); |
1352 | } |
1353 | |
1354 | { |
1355 | /* Make sure tree store mutations don't crash anything */ |
1356 | GtkTreeStore *store; |
1357 | GtkTreeIter root; |
1358 | |
1359 | store = gtk_tree_store_new (n_columns: 1, G_TYPE_INT); |
1360 | gtk_tree_store_append (GTK_TREE_STORE (store), iter: &root, NULL); |
1361 | /* Remove test until it is rewritten to work */ |
1362 | /* treestore_torture_recurse (store, &root, 0);*/ |
1363 | |
1364 | g_object_unref (object: store); |
1365 | } |
1366 | |
1367 | g_print (format: "Passed.\n" ); |
1368 | } |
1369 | |