1/* testtreecolumns.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 "config.h"
20#include <gtk/gtk.h>
21
22/*
23 * README README README README README README README README README README
24 * README README README README README README README README README README
25 * README README README README README README README README README README
26 * README README README README README README README README README README
27 * README README README README README README README README README README
28 * README README README README README README README README README README
29 * README README README README README README README README README README
30 * README README README README README README README README README README
31 * README README README README README README README README README README
32 * README README README README README README README README README README
33 * README README README README README README README README README README
34 * README README README README README README README README README README
35 * README README README README README README README README README README
36 *
37 * DO NOT!!! I REPEAT DO NOT! EVER LOOK AT THIS CODE AS AN EXAMPLE OF WHAT YOUR
38 * CODE SHOULD LOOK LIKE.
39 *
40 * IT IS VERY CONFUSING, AND IS MEANT TO TEST A LOT OF CODE IN THE TREE. WHILE
41 * IT IS ACTUALLY CORRECT CODE, IT IS NOT USEFUL.
42 */
43
44GtkWidget *left_tree_view;
45GtkWidget *top_right_tree_view;
46GtkWidget *bottom_right_tree_view;
47GtkTreeModel *left_tree_model;
48GtkTreeModel *top_right_tree_model;
49GtkTreeModel *bottom_right_tree_model;
50GtkWidget *sample_tree_view_top;
51GtkWidget *sample_tree_view_bottom;
52
53#define column_data "my_column_data"
54
55static void move_row (GtkTreeModel *src,
56 GtkTreeIter *src_iter,
57 GtkTreeModel *dest,
58 GtkTreeIter *dest_iter);
59
60/* Kids, don't try this at home. */
61
62/* Small GtkTreeModel to model columns */
63typedef struct _ViewColumnModel ViewColumnModel;
64typedef struct _ViewColumnModelClass ViewColumnModelClass;
65
66struct _ViewColumnModel
67{
68 GtkListStore parent;
69 GtkTreeView *view;
70 GList *columns;
71 int stamp;
72};
73
74struct _ViewColumnModelClass
75{
76 GtkListStoreClass parent_class;
77};
78
79static void view_column_model_tree_model_init (GtkTreeModelIface *iface);
80static void view_column_model_drag_source_init (GtkTreeDragSourceIface *iface);
81static void view_column_model_drag_dest_init (GtkTreeDragDestIface *iface);
82
83
84static GType view_column_model_get_type (void);
85G_DEFINE_TYPE_WITH_CODE (ViewColumnModel, view_column_model, GTK_TYPE_LIST_STORE,
86 G_IMPLEMENT_INTERFACE (GTK_TYPE_TREE_MODEL, view_column_model_tree_model_init)
87 G_IMPLEMENT_INTERFACE (GTK_TYPE_TREE_DRAG_SOURCE, view_column_model_drag_source_init)
88 G_IMPLEMENT_INTERFACE (GTK_TYPE_TREE_DRAG_DEST, view_column_model_drag_dest_init))
89
90
91
92static void view_column_model_init (ViewColumnModel *model)
93{
94 model->stamp = g_random_int ();
95}
96
97static int
98view_column_model_get_n_columns (GtkTreeModel *tree_model)
99{
100 return 2;
101}
102
103static GType
104view_column_model_get_column_type (GtkTreeModel *tree_model,
105 int index)
106{
107 switch (index)
108 {
109 case 0:
110 return G_TYPE_STRING;
111 case 1:
112 return GTK_TYPE_TREE_VIEW_COLUMN;
113 default:
114 return G_TYPE_INVALID;
115 }
116}
117
118static gboolean
119view_column_model_get_iter (GtkTreeModel *tree_model,
120 GtkTreeIter *iter,
121 GtkTreePath *path)
122
123{
124 ViewColumnModel *view_model = (ViewColumnModel *)tree_model;
125 GList *list;
126 int i;
127
128 g_return_val_if_fail (gtk_tree_path_get_depth (path) > 0, FALSE);
129
130 i = gtk_tree_path_get_indices (path)[0];
131 list = g_list_nth (list: view_model->columns, n: i);
132
133 if (list == NULL)
134 return FALSE;
135
136 iter->stamp = view_model->stamp;
137 iter->user_data = list;
138
139 return TRUE;
140}
141
142static GtkTreePath *
143view_column_model_get_path (GtkTreeModel *tree_model,
144 GtkTreeIter *iter)
145{
146 ViewColumnModel *view_model = (ViewColumnModel *)tree_model;
147 GtkTreePath *retval;
148 GList *list;
149 int i = 0;
150
151 g_return_val_if_fail (iter->stamp == view_model->stamp, NULL);
152
153 for (list = view_model->columns; list; list = list->next)
154 {
155 if (list == (GList *)iter->user_data)
156 break;
157 i++;
158 }
159 if (list == NULL)
160 return NULL;
161
162 retval = gtk_tree_path_new ();
163 gtk_tree_path_append_index (path: retval, index_: i);
164 return retval;
165}
166
167static void
168view_column_model_get_value (GtkTreeModel *tree_model,
169 GtkTreeIter *iter,
170 int column,
171 GValue *value)
172{
173#ifndef G_DISABLE_CHECKS
174 ViewColumnModel *view_model = (ViewColumnModel *)tree_model;
175
176 g_return_if_fail (column < 2);
177 g_return_if_fail (view_model->stamp == iter->stamp);
178 g_return_if_fail (iter->user_data != NULL);
179#endif
180
181 if (column == 0)
182 {
183 g_value_init (value, G_TYPE_STRING);
184 g_value_set_string (value, v_string: gtk_tree_view_column_get_title (GTK_TREE_VIEW_COLUMN (((GList *)iter->user_data)->data)));
185 }
186 else
187 {
188 g_value_init (value, GTK_TYPE_TREE_VIEW_COLUMN);
189 g_value_set_object (value, v_object: ((GList *)iter->user_data)->data);
190 }
191}
192
193static gboolean
194view_column_model_iter_next (GtkTreeModel *tree_model,
195 GtkTreeIter *iter)
196{
197#ifndef G_DISABLE_CHECKS
198 ViewColumnModel *view_model = (ViewColumnModel *)tree_model;
199
200 g_return_val_if_fail (view_model->stamp == iter->stamp, FALSE);
201 g_return_val_if_fail (iter->user_data != NULL, FALSE);
202#endif
203
204 iter->user_data = ((GList *)iter->user_data)->next;
205 return iter->user_data != NULL;
206}
207
208static gboolean
209view_column_model_iter_children (GtkTreeModel *tree_model,
210 GtkTreeIter *iter,
211 GtkTreeIter *parent)
212{
213 ViewColumnModel *view_model = (ViewColumnModel *)tree_model;
214
215 /* this is a list, nodes have no children */
216 if (parent)
217 return FALSE;
218
219 /* but if parent == NULL we return the list itself as children of the
220 * "root"
221 */
222
223 if (view_model->columns)
224 {
225 iter->stamp = view_model->stamp;
226 iter->user_data = view_model->columns;
227 return TRUE;
228 }
229 else
230 return FALSE;
231}
232
233static gboolean
234view_column_model_iter_has_child (GtkTreeModel *tree_model,
235 GtkTreeIter *iter)
236{
237 return FALSE;
238}
239
240static int
241view_column_model_iter_n_children (GtkTreeModel *tree_model,
242 GtkTreeIter *iter)
243{
244 return g_list_length (list: ((ViewColumnModel *)tree_model)->columns);
245}
246
247static int
248view_column_model_iter_nth_child (GtkTreeModel *tree_model,
249 GtkTreeIter *iter,
250 GtkTreeIter *parent,
251 int n)
252{
253 ViewColumnModel *view_model = (ViewColumnModel *)tree_model;
254
255 if (parent)
256 return FALSE;
257
258 iter->stamp = view_model->stamp;
259 iter->user_data = g_list_nth (list: (GList *)view_model->columns, n);
260
261 return (iter->user_data != NULL);
262}
263
264static gboolean
265view_column_model_iter_parent (GtkTreeModel *tree_model,
266 GtkTreeIter *iter,
267 GtkTreeIter *child)
268{
269 return FALSE;
270}
271
272static void
273view_column_model_tree_model_init (GtkTreeModelIface *iface)
274{
275 iface->get_n_columns = view_column_model_get_n_columns;
276 iface->get_column_type = view_column_model_get_column_type;
277 iface->get_iter = view_column_model_get_iter;
278 iface->get_path = view_column_model_get_path;
279 iface->get_value = view_column_model_get_value;
280 iface->iter_next = view_column_model_iter_next;
281 iface->iter_children = view_column_model_iter_children;
282 iface->iter_has_child = view_column_model_iter_has_child;
283 iface->iter_n_children = view_column_model_iter_n_children;
284 iface->iter_nth_child = view_column_model_iter_nth_child;
285 iface->iter_parent = view_column_model_iter_parent;
286}
287
288static GdkContentProvider *
289view_column_model_drag_data_get (GtkTreeDragSource *drag_source,
290 GtkTreePath *path)
291{
292 return gtk_tree_create_row_drag_content (GTK_TREE_MODEL (drag_source), path);
293}
294
295static gboolean
296view_column_model_drag_data_delete (GtkTreeDragSource *drag_source,
297 GtkTreePath *path)
298{
299 /* Nothing -- we handle moves on the dest side */
300
301 return TRUE;
302}
303
304static gboolean
305view_column_model_row_drop_possible (GtkTreeDragDest *drag_dest,
306 GtkTreePath *dest_path,
307 const GValue *value)
308{
309 GtkTreeModel *src_model;
310
311 if (gtk_tree_get_row_drag_data (value,
312 tree_model: &src_model,
313 NULL))
314 {
315 if (src_model == left_tree_model ||
316 src_model == top_right_tree_model ||
317 src_model == bottom_right_tree_model)
318 return TRUE;
319 }
320
321 return FALSE;
322}
323
324static gboolean
325view_column_model_drag_data_received (GtkTreeDragDest *drag_dest,
326 GtkTreePath *dest,
327 const GValue *value)
328{
329 GtkTreeModel *src_model;
330 GtkTreePath *src_path = NULL;
331 gboolean retval = FALSE;
332
333 if (gtk_tree_get_row_drag_data (value,
334 tree_model: &src_model,
335 path: &src_path))
336 {
337 GtkTreeIter src_iter;
338 GtkTreeIter dest_iter;
339 gboolean have_dest;
340
341 /* We are a little lazy here, and assume if we can't convert dest
342 * to an iter, we need to append. See gtkliststore.c for a more
343 * careful handling of this.
344 */
345 have_dest = gtk_tree_model_get_iter (GTK_TREE_MODEL (drag_dest), iter: &dest_iter, path: dest);
346
347 if (gtk_tree_model_get_iter (tree_model: src_model, iter: &src_iter, path: src_path))
348 {
349 if (src_model == left_tree_model ||
350 src_model == top_right_tree_model ||
351 src_model == bottom_right_tree_model)
352 {
353 move_row (src: src_model, src_iter: &src_iter, GTK_TREE_MODEL (drag_dest),
354 dest_iter: have_dest ? &dest_iter : NULL);
355 retval = TRUE;
356 }
357 }
358
359 gtk_tree_path_free (path: src_path);
360 }
361
362 return retval;
363}
364
365static void
366view_column_model_drag_source_init (GtkTreeDragSourceIface *iface)
367{
368 iface->drag_data_get = view_column_model_drag_data_get;
369 iface->drag_data_delete = view_column_model_drag_data_delete;
370}
371
372static void
373view_column_model_drag_dest_init (GtkTreeDragDestIface *iface)
374{
375 iface->drag_data_received = view_column_model_drag_data_received;
376 iface->row_drop_possible = view_column_model_row_drop_possible;
377}
378
379static void
380view_column_model_class_init (ViewColumnModelClass *klass)
381{
382}
383
384static void
385update_columns (GtkTreeView *view, ViewColumnModel *view_model)
386{
387 GList *old_columns = view_model->columns;
388 int old_length, length;
389 GList *a, *b;
390
391 view_model->columns = gtk_tree_view_get_columns (tree_view: view_model->view);
392
393 /* As the view tells us one change at a time, we can do this hack. */
394 length = g_list_length (list: view_model->columns);
395 old_length = g_list_length (list: old_columns);
396 if (length != old_length)
397 {
398 GtkTreePath *path;
399 int i = 0;
400
401 /* where are they different */
402 for (a = old_columns, b = view_model->columns; a && b; a = a->next, b = b->next)
403 {
404 if (a->data != b->data)
405 break;
406 i++;
407 }
408 path = gtk_tree_path_new ();
409 gtk_tree_path_append_index (path, index_: i);
410 if (length < old_length)
411 {
412 view_model->stamp++;
413 gtk_tree_model_row_deleted (GTK_TREE_MODEL (view_model), path);
414 }
415 else
416 {
417 GtkTreeIter iter;
418 iter.stamp = view_model->stamp;
419 iter.user_data = b;
420 gtk_tree_model_row_inserted (GTK_TREE_MODEL (view_model), path, iter: &iter);
421 }
422 gtk_tree_path_free (path);
423 }
424 else
425 {
426 int i;
427 int m = 0, n = 1;
428 int *new_order;
429 GtkTreePath *path;
430
431 new_order = g_new (int, length);
432 a = old_columns; b = view_model->columns;
433
434 while (a->data == b->data)
435 {
436 a = a->next;
437 b = b->next;
438 if (a == NULL)
439 return;
440 m++;
441 }
442
443 if (a->next->data == b->data)
444 {
445 b = b->next;
446 while (b->data != a->data)
447 {
448 b = b->next;
449 n++;
450 }
451 for (i = 0; i < m; i++)
452 new_order[i] = i;
453 for (i = m; i < m+n; i++)
454 new_order[i] = i+1;
455 new_order[i] = m;
456 for (i = m + n +1; i < length; i++)
457 new_order[i] = i;
458 }
459 else
460 {
461 a = a->next;
462 while (a->data != b->data)
463 {
464 a = a->next;
465 n++;
466 }
467 for (i = 0; i < m; i++)
468 new_order[i] = i;
469 new_order[m] = m+n;
470 for (i = m+1; i < m + n+ 1; i++)
471 new_order[i] = i - 1;
472 for (i = m + n + 1; i < length; i++)
473 new_order[i] = i;
474 }
475
476 path = gtk_tree_path_new ();
477 gtk_tree_model_rows_reordered (GTK_TREE_MODEL (view_model),
478 path,
479 NULL,
480 new_order);
481 gtk_tree_path_free (path);
482 g_free (mem: new_order);
483 }
484 if (old_columns)
485 g_list_free (list: old_columns);
486}
487
488static GtkTreeModel *
489view_column_model_new (GtkTreeView *view)
490{
491 GtkTreeModel *retval;
492
493 retval = g_object_new (object_type: view_column_model_get_type (), NULL);
494 ((ViewColumnModel *)retval)->view = view;
495 ((ViewColumnModel *)retval)->columns = gtk_tree_view_get_columns (tree_view: view);
496
497 g_signal_connect (view, "columns_changed", G_CALLBACK (update_columns), retval);
498
499 return retval;
500}
501
502/* Back to sanity.
503 */
504
505static void
506add_clicked (GtkWidget *button, gpointer data)
507{
508 static int i = 0;
509
510 GtkTreeIter iter;
511 GtkTreeViewColumn *column;
512 GtkTreeSelection *selection;
513 GtkCellRenderer *cell;
514 char *label = g_strdup_printf (format: "Column %d", i);
515
516 cell = gtk_cell_renderer_text_new ();
517 column = gtk_tree_view_column_new_with_attributes (title: label, cell, "text", 0, NULL);
518 g_object_set_data_full (G_OBJECT (column), column_data, data: label, destroy: g_free);
519 gtk_tree_view_column_set_reorderable (tree_column: column, TRUE);
520 gtk_tree_view_column_set_sizing (tree_column: column, type: GTK_TREE_VIEW_COLUMN_GROW_ONLY);
521 gtk_tree_view_column_set_resizable (tree_column: column, TRUE);
522 gtk_list_store_append (GTK_LIST_STORE (left_tree_model), iter: &iter);
523 gtk_list_store_set (GTK_LIST_STORE (left_tree_model), iter: &iter, 0, label, 1, column, -1);
524 i++;
525
526 selection = gtk_tree_view_get_selection (GTK_TREE_VIEW (left_tree_view));
527 gtk_tree_selection_select_iter (selection, iter: &iter);
528}
529
530static void
531get_visible (GtkTreeViewColumn *tree_column,
532 GtkCellRenderer *cell,
533 GtkTreeModel *tree_model,
534 GtkTreeIter *iter,
535 gpointer data)
536{
537 GtkTreeViewColumn *column;
538
539 gtk_tree_model_get (tree_model, iter, 1, &column, -1);
540 if (column)
541 {
542 gtk_cell_renderer_toggle_set_active (GTK_CELL_RENDERER_TOGGLE (cell),
543 setting: gtk_tree_view_column_get_visible (tree_column: column));
544 }
545}
546
547static void
548set_visible (GtkCellRendererToggle *cell,
549 char *path_str,
550 gpointer data)
551{
552 GtkTreeView *tree_view = (GtkTreeView *) data;
553 GtkTreeViewColumn *column;
554 GtkTreeModel *model;
555 GtkTreeIter iter;
556 GtkTreePath *path = gtk_tree_path_new_from_string (path: path_str);
557
558 model = gtk_tree_view_get_model (tree_view);
559
560 gtk_tree_model_get_iter (tree_model: model, iter: &iter, path);
561 gtk_tree_model_get (tree_model: model, iter: &iter, 1, &column, -1);
562
563 if (column)
564 {
565 gtk_tree_view_column_set_visible (tree_column: column, visible: ! gtk_tree_view_column_get_visible (tree_column: column));
566 gtk_tree_model_row_changed (tree_model: model, path, iter: &iter);
567 }
568 gtk_tree_path_free (path);
569}
570
571static void
572move_to_left (GtkTreeModel *src,
573 GtkTreeIter *src_iter,
574 GtkTreeIter *dest_iter)
575{
576 GtkTreeIter iter;
577 GtkTreeViewColumn *column;
578 GtkTreeSelection *selection;
579 char *label;
580
581 gtk_tree_model_get (tree_model: src, iter: src_iter, 0, &label, 1, &column, -1);
582
583 if (src == top_right_tree_model)
584 gtk_tree_view_remove_column (GTK_TREE_VIEW (sample_tree_view_top), column);
585 else
586 gtk_tree_view_remove_column (GTK_TREE_VIEW (sample_tree_view_bottom), column);
587
588 /* gtk_list_store_remove (GTK_LIST_STORE (gtk_tree_view_get_model (GTK_TREE_VIEW (data))), &iter);*/
589
590 /* Put it back on the left */
591 if (dest_iter)
592 gtk_list_store_insert_before (GTK_LIST_STORE (left_tree_model),
593 iter: &iter, sibling: dest_iter);
594 else
595 gtk_list_store_append (GTK_LIST_STORE (left_tree_model), iter: &iter);
596
597 gtk_list_store_set (GTK_LIST_STORE (left_tree_model), iter: &iter, 0, label, 1, column, -1);
598 selection = gtk_tree_view_get_selection (GTK_TREE_VIEW (left_tree_view));
599 gtk_tree_selection_select_iter (selection, iter: &iter);
600
601 g_free (mem: label);
602}
603
604static void
605move_to_right (GtkTreeIter *src_iter,
606 GtkTreeModel *dest,
607 GtkTreeIter *dest_iter)
608{
609 char *label;
610 GtkTreeViewColumn *column;
611 int before = -1;
612
613 gtk_tree_model_get (GTK_TREE_MODEL (left_tree_model),
614 iter: src_iter, 0, &label, 1, &column, -1);
615 gtk_list_store_remove (GTK_LIST_STORE (left_tree_model), iter: src_iter);
616
617 if (dest_iter)
618 {
619 GtkTreePath *path = gtk_tree_model_get_path (tree_model: dest, iter: dest_iter);
620 before = (gtk_tree_path_get_indices (path))[0];
621 gtk_tree_path_free (path);
622 }
623
624 if (dest == top_right_tree_model)
625 gtk_tree_view_insert_column (GTK_TREE_VIEW (sample_tree_view_top), column, position: before);
626 else
627 gtk_tree_view_insert_column (GTK_TREE_VIEW (sample_tree_view_bottom), column, position: before);
628
629 g_free (mem: label);
630}
631
632static void
633move_up_or_down (GtkTreeModel *src,
634 GtkTreeIter *src_iter,
635 GtkTreeModel *dest,
636 GtkTreeIter *dest_iter)
637{
638 GtkTreeViewColumn *column;
639 char *label;
640 int before = -1;
641
642 gtk_tree_model_get (tree_model: src, iter: src_iter, 0, &label, 1, &column, -1);
643
644 if (dest_iter)
645 {
646 GtkTreePath *path = gtk_tree_model_get_path (tree_model: dest, iter: dest_iter);
647 before = (gtk_tree_path_get_indices (path))[0];
648 gtk_tree_path_free (path);
649 }
650
651 if (src == top_right_tree_model)
652 gtk_tree_view_remove_column (GTK_TREE_VIEW (sample_tree_view_top), column);
653 else
654 gtk_tree_view_remove_column (GTK_TREE_VIEW (sample_tree_view_bottom), column);
655
656 if (dest == top_right_tree_model)
657 gtk_tree_view_insert_column (GTK_TREE_VIEW (sample_tree_view_top), column, position: before);
658 else
659 gtk_tree_view_insert_column (GTK_TREE_VIEW (sample_tree_view_bottom), column, position: before);
660
661 g_free (mem: label);
662}
663
664static void
665move_row (GtkTreeModel *src,
666 GtkTreeIter *src_iter,
667 GtkTreeModel *dest,
668 GtkTreeIter *dest_iter)
669{
670 if (src == left_tree_model)
671 move_to_right (src_iter, dest, dest_iter);
672 else if (dest == left_tree_model)
673 move_to_left (src, src_iter, dest_iter);
674 else
675 move_up_or_down (src, src_iter, dest, dest_iter);
676}
677
678static void
679add_left_clicked (GtkWidget *button,
680 gpointer data)
681{
682 GtkTreeIter iter;
683
684 GtkTreeSelection *selection = gtk_tree_view_get_selection (GTK_TREE_VIEW (data));
685
686 gtk_tree_selection_get_selected (selection, NULL, iter: &iter);
687
688 move_to_left (src: gtk_tree_view_get_model (GTK_TREE_VIEW (data)), src_iter: &iter, NULL);
689}
690
691static void
692add_right_clicked (GtkWidget *button, gpointer data)
693{
694 GtkTreeIter iter;
695
696 GtkTreeSelection *selection = gtk_tree_view_get_selection (GTK_TREE_VIEW (left_tree_view));
697
698 gtk_tree_selection_get_selected (selection, NULL, iter: &iter);
699
700 move_to_right (src_iter: &iter, dest: gtk_tree_view_get_model (GTK_TREE_VIEW (data)), NULL);
701}
702
703static void
704selection_changed (GtkTreeSelection *selection, GtkWidget *button)
705{
706 if (gtk_tree_selection_get_selected (selection, NULL, NULL))
707 gtk_widget_set_sensitive (widget: button, TRUE);
708 else
709 gtk_widget_set_sensitive (widget: button, FALSE);
710}
711
712static void
713quit_cb (GtkWidget *widget,
714 gpointer data)
715{
716 gboolean *done = data;
717
718 *done = TRUE;
719
720 g_main_context_wakeup (NULL);
721}
722
723int
724main (int argc, char *argv[])
725{
726 GtkWidget *window;
727 GtkWidget *hbox, *vbox;
728 GtkWidget *vbox2, *bbox;
729 GtkWidget *button;
730 GtkTreeViewColumn *column;
731 GtkCellRenderer *cell;
732 GtkWidget *swindow;
733 GtkTreeModel *sample_model;
734 GdkContentFormats *targets;
735 int i;
736 gboolean done = FALSE;
737
738 gtk_init ();
739
740 /* First initialize all the models for signal purposes */
741 left_tree_model = (GtkTreeModel *) gtk_list_store_new (n_columns: 2, G_TYPE_STRING, G_TYPE_POINTER);
742 sample_model = (GtkTreeModel *) gtk_list_store_new (n_columns: 1, G_TYPE_STRING);
743 sample_tree_view_top = gtk_tree_view_new_with_model (model: sample_model);
744 sample_tree_view_bottom = gtk_tree_view_new_with_model (model: sample_model);
745 top_right_tree_model = (GtkTreeModel *) view_column_model_new (GTK_TREE_VIEW (sample_tree_view_top));
746 bottom_right_tree_model = (GtkTreeModel *) view_column_model_new (GTK_TREE_VIEW (sample_tree_view_bottom));
747 top_right_tree_view = gtk_tree_view_new_with_model (model: top_right_tree_model);
748 bottom_right_tree_view = gtk_tree_view_new_with_model (model: bottom_right_tree_model);
749
750 for (i = 0; i < 10; i++)
751 {
752 GtkTreeIter iter;
753 char *string = g_strdup_printf (format: "%d", i);
754 gtk_list_store_append (GTK_LIST_STORE (sample_model), iter: &iter);
755 gtk_list_store_set (GTK_LIST_STORE (sample_model), iter: &iter, 0, string, -1);
756 g_free (mem: string);
757 }
758
759 /* Set up the test windows. */
760 window = gtk_window_new ();
761 g_signal_connect (window, "destroy", G_CALLBACK (quit_cb), &done);
762 gtk_window_set_default_size (GTK_WINDOW (window), width: 300, height: 300);
763 gtk_window_set_title (GTK_WINDOW (window), title: "Top Window");
764 swindow = gtk_scrolled_window_new ();
765 gtk_window_set_child (GTK_WINDOW (window), child: swindow);
766 gtk_scrolled_window_set_child (GTK_SCROLLED_WINDOW (swindow), child: sample_tree_view_top);
767 gtk_widget_show (widget: window);
768
769 window = gtk_window_new ();
770 g_signal_connect (window, "destroy", G_CALLBACK (quit_cb), &done);
771 gtk_window_set_default_size (GTK_WINDOW (window), width: 300, height: 300);
772 gtk_window_set_title (GTK_WINDOW (window), title: "Bottom Window");
773 swindow = gtk_scrolled_window_new ();
774 gtk_window_set_child (GTK_WINDOW (window), child: swindow);
775 gtk_scrolled_window_set_child (GTK_SCROLLED_WINDOW (swindow), child: sample_tree_view_bottom);
776 gtk_widget_show (widget: window);
777
778 /* Set up the main window */
779 window = gtk_window_new ();
780 g_signal_connect (window, "destroy", G_CALLBACK (quit_cb), &done);
781 gtk_window_set_default_size (GTK_WINDOW (window), width: 500, height: 300);
782 vbox = gtk_box_new (orientation: GTK_ORIENTATION_VERTICAL, spacing: 8);
783 gtk_window_set_child (GTK_WINDOW (window), child: vbox);
784
785 hbox = gtk_box_new (orientation: GTK_ORIENTATION_HORIZONTAL, spacing: 8);
786 gtk_box_append (GTK_BOX (vbox), child: hbox);
787
788 /* Left Pane */
789 cell = gtk_cell_renderer_text_new ();
790
791 swindow = gtk_scrolled_window_new ();
792 gtk_scrolled_window_set_policy (GTK_SCROLLED_WINDOW (swindow), hscrollbar_policy: GTK_POLICY_AUTOMATIC, vscrollbar_policy: GTK_POLICY_AUTOMATIC);
793 left_tree_view = gtk_tree_view_new_with_model (model: left_tree_model);
794 gtk_scrolled_window_set_child (GTK_SCROLLED_WINDOW (swindow), child: left_tree_view);
795 gtk_tree_view_insert_column_with_attributes (GTK_TREE_VIEW (left_tree_view), position: -1,
796 title: "Unattached Columns", cell, "text", 0, NULL);
797 cell = gtk_cell_renderer_toggle_new ();
798 g_signal_connect (cell, "toggled", G_CALLBACK (set_visible), left_tree_view);
799 column = gtk_tree_view_column_new_with_attributes (title: "Visible", cell, NULL);
800 gtk_tree_view_append_column (GTK_TREE_VIEW (left_tree_view), column);
801
802 gtk_tree_view_column_set_cell_data_func (tree_column: column, cell_renderer: cell, func: get_visible, NULL, NULL);
803 gtk_box_append (GTK_BOX (hbox), child: swindow);
804
805 /* Middle Pane */
806 vbox2 = gtk_box_new (orientation: GTK_ORIENTATION_VERTICAL, spacing: 8);
807 gtk_box_append (GTK_BOX (hbox), child: vbox2);
808
809 bbox = gtk_box_new (orientation: GTK_ORIENTATION_VERTICAL, spacing: 0);
810 gtk_box_append (GTK_BOX (vbox2), child: bbox);
811
812 button = gtk_button_new_with_mnemonic (label: "<< (_Q)");
813 gtk_widget_set_sensitive (widget: button, FALSE);
814 g_signal_connect (button, "clicked", G_CALLBACK (add_left_clicked), top_right_tree_view);
815 g_signal_connect (gtk_tree_view_get_selection (GTK_TREE_VIEW (top_right_tree_view)),
816 "changed", G_CALLBACK (selection_changed), button);
817 gtk_box_append (GTK_BOX (bbox), child: button);
818
819 button = gtk_button_new_with_mnemonic (label: ">> (_W)");
820 gtk_widget_set_sensitive (widget: button, FALSE);
821 g_signal_connect (button, "clicked", G_CALLBACK (add_right_clicked), top_right_tree_view);
822 g_signal_connect (gtk_tree_view_get_selection (GTK_TREE_VIEW (left_tree_view)),
823 "changed", G_CALLBACK (selection_changed), button);
824 gtk_box_append (GTK_BOX (bbox), child: button);
825
826 bbox = gtk_box_new (orientation: GTK_ORIENTATION_VERTICAL, spacing: 0);
827 gtk_box_append (GTK_BOX (vbox2), child: bbox);
828
829 button = gtk_button_new_with_mnemonic (label: "<< (_E)");
830 gtk_widget_set_sensitive (widget: button, FALSE);
831 g_signal_connect (button, "clicked", G_CALLBACK (add_left_clicked), bottom_right_tree_view);
832 g_signal_connect (gtk_tree_view_get_selection (GTK_TREE_VIEW (bottom_right_tree_view)),
833 "changed", G_CALLBACK (selection_changed), button);
834 gtk_box_append (GTK_BOX (bbox), child: button);
835
836 button = gtk_button_new_with_mnemonic (label: ">> (_R)");
837 gtk_widget_set_sensitive (widget: button, FALSE);
838 g_signal_connect (button, "clicked", G_CALLBACK (add_right_clicked), bottom_right_tree_view);
839 g_signal_connect (gtk_tree_view_get_selection (GTK_TREE_VIEW (left_tree_view)),
840 "changed", G_CALLBACK (selection_changed), button);
841 gtk_box_append (GTK_BOX (bbox), child: button);
842
843
844 /* Right Pane */
845 vbox2 = gtk_box_new (orientation: GTK_ORIENTATION_VERTICAL, spacing: 8);
846 gtk_box_append (GTK_BOX (hbox), child: vbox2);
847
848 swindow = gtk_scrolled_window_new ();
849 gtk_scrolled_window_set_policy (GTK_SCROLLED_WINDOW (swindow), hscrollbar_policy: GTK_POLICY_AUTOMATIC, vscrollbar_policy: GTK_POLICY_AUTOMATIC);
850 gtk_tree_view_set_headers_visible (GTK_TREE_VIEW (top_right_tree_view), FALSE);
851 cell = gtk_cell_renderer_text_new ();
852 gtk_tree_view_insert_column_with_attributes (GTK_TREE_VIEW (top_right_tree_view), position: -1,
853 NULL, cell, "text", 0, NULL);
854 cell = gtk_cell_renderer_toggle_new ();
855 g_signal_connect (cell, "toggled", G_CALLBACK (set_visible), top_right_tree_view);
856 column = gtk_tree_view_column_new_with_attributes (NULL, cell, NULL);
857 gtk_tree_view_column_set_cell_data_func (tree_column: column, cell_renderer: cell, func: get_visible, NULL, NULL);
858 gtk_tree_view_append_column (GTK_TREE_VIEW (top_right_tree_view), column);
859
860 gtk_scrolled_window_set_child (GTK_SCROLLED_WINDOW (swindow), child: top_right_tree_view);
861 gtk_box_append (GTK_BOX (vbox2), child: swindow);
862
863 swindow = gtk_scrolled_window_new ();
864 gtk_scrolled_window_set_policy (GTK_SCROLLED_WINDOW (swindow), hscrollbar_policy: GTK_POLICY_AUTOMATIC, vscrollbar_policy: GTK_POLICY_AUTOMATIC);
865 gtk_tree_view_set_headers_visible (GTK_TREE_VIEW (bottom_right_tree_view), FALSE);
866 cell = gtk_cell_renderer_text_new ();
867 gtk_tree_view_insert_column_with_attributes (GTK_TREE_VIEW (bottom_right_tree_view), position: -1,
868 NULL, cell, "text", 0, NULL);
869 cell = gtk_cell_renderer_toggle_new ();
870 g_signal_connect (cell, "toggled", G_CALLBACK (set_visible), bottom_right_tree_view);
871 column = gtk_tree_view_column_new_with_attributes (NULL, cell, NULL);
872 gtk_tree_view_column_set_cell_data_func (tree_column: column, cell_renderer: cell, func: get_visible, NULL, NULL);
873 gtk_tree_view_append_column (GTK_TREE_VIEW (bottom_right_tree_view), column);
874 gtk_scrolled_window_set_child (GTK_SCROLLED_WINDOW (swindow), child: bottom_right_tree_view);
875 gtk_box_append (GTK_BOX (vbox2), child: swindow);
876
877
878 /* Drag and Drop */
879 targets = gdk_content_formats_new_for_gtype (GTK_TYPE_TREE_ROW_DATA);
880 gtk_tree_view_enable_model_drag_source (GTK_TREE_VIEW (left_tree_view),
881 start_button_mask: GDK_BUTTON1_MASK,
882 formats: targets,
883 actions: GDK_ACTION_MOVE);
884 gtk_tree_view_enable_model_drag_dest (GTK_TREE_VIEW (left_tree_view),
885 formats: targets,
886 actions: GDK_ACTION_MOVE);
887
888 gtk_tree_view_enable_model_drag_source (GTK_TREE_VIEW (top_right_tree_view),
889 start_button_mask: GDK_BUTTON1_MASK,
890 formats: targets,
891 actions: GDK_ACTION_MOVE);
892 gtk_tree_view_enable_model_drag_dest (GTK_TREE_VIEW (top_right_tree_view),
893 formats: targets,
894 actions: GDK_ACTION_MOVE);
895
896 gtk_tree_view_enable_model_drag_source (GTK_TREE_VIEW (bottom_right_tree_view),
897 start_button_mask: GDK_BUTTON1_MASK,
898 formats: targets,
899 actions: GDK_ACTION_MOVE);
900 gtk_tree_view_enable_model_drag_dest (GTK_TREE_VIEW (bottom_right_tree_view),
901 formats: targets,
902 actions: GDK_ACTION_MOVE);
903 gdk_content_formats_unref (formats: targets);
904
905 gtk_box_append (GTK_BOX (vbox), child: gtk_separator_new (orientation: GTK_ORIENTATION_HORIZONTAL));
906
907 hbox = gtk_box_new (orientation: GTK_ORIENTATION_HORIZONTAL, spacing: 8);
908 gtk_box_append (GTK_BOX (vbox), child: hbox);
909 button = gtk_button_new_with_mnemonic (label: "_Add new Column");
910 g_signal_connect (button, "clicked", G_CALLBACK (add_clicked), left_tree_model);
911 gtk_box_append (GTK_BOX (hbox), child: button);
912
913 gtk_widget_show (widget: window);
914
915 while (!done)
916 g_main_context_iteration (NULL, TRUE);
917
918 return 0;
919}
920

source code of gtk/tests/testtreecolumns.c