4 * README README README README README README README README README README
5 * README README README README README README README README README README
6 * README README README README README README README README README README
7 * README README README README README README README README README README
8 * README README README README README README README README README README
9 * README README README README README README README README README README
10 * README README README README README README README README README README
11 * README README README README README README README README README README
12 * README README README README README README README README README README
13 * README README README README README README README README README README
14 * README README README README README README README README README README
15 * README README README README README README README README README README
16 * README README README README README README README README README README
18 * DO NOT!!! I REPEAT DO NOT! EVER LOOK AT THIS CODE AS AN EXAMPLE OF WHAT YOUR
19 * CODE SHOULD LOOK LIKE.
21 * IT IS VERY CONFUSING, AND IS MEANT TO TEST A LOT OF CODE IN THE TREE. WHILE
22 * IT IS ACTUALLY CORRECT CODE, IT IS NOT USEFUL.
25 GtkWidget *left_tree_view;
26 GtkWidget *top_right_tree_view;
27 GtkWidget *bottom_right_tree_view;
28 GtkTreeModel *left_tree_model;
29 GtkTreeModel *top_right_tree_model;
30 GtkTreeModel *bottom_right_tree_model;
31 GtkWidget *sample_tree_view_top;
32 GtkWidget *sample_tree_view_bottom;
34 #define column_data "my_column_data"
38 /* Kids, don't try this at home. */
40 /* Small GtkTreeModel to model columns */
41 typedef struct _ViewColumnModel ViewColumnModel;
42 typedef struct _ViewColumnModelClass ViewColumnModelClass;
44 struct _ViewColumnModel
52 struct _ViewColumnModelClass
54 GObjectClass parent_class;
57 static void view_column_model_init (ViewColumnModel *model)
59 model->stamp = g_random_int ();
63 view_column_model_get_n_columns (GtkTreeModel *tree_model)
69 view_column_model_get_column_type (GtkTreeModel *tree_model,
77 return GTK_TYPE_TREE_VIEW_COLUMN;
79 return G_TYPE_INVALID;
84 view_column_model_get_iter (GtkTreeModel *tree_model,
89 ViewColumnModel *view_model = (ViewColumnModel *)tree_model;
93 g_return_val_if_fail (gtk_tree_path_get_depth (path) > 0, FALSE);
95 i = gtk_tree_path_get_indices (path)[0];
96 list = g_list_nth (view_model->columns, i);
101 iter->stamp = view_model->stamp;
102 iter->user_data = list;
108 view_column_model_get_path (GtkTreeModel *tree_model,
111 ViewColumnModel *view_model = (ViewColumnModel *)tree_model;
116 g_return_val_if_fail (iter->stamp == view_model->stamp, NULL);
118 for (list = view_model->columns; list; list = list->next)
120 if (list == (GList *)iter->user_data)
127 retval = gtk_tree_path_new ();
128 gtk_tree_path_append_index (retval, i);
133 view_column_model_get_value (GtkTreeModel *tree_model,
138 ViewColumnModel *view_model = (ViewColumnModel *)tree_model;
140 g_return_if_fail (column < 2);
141 g_return_if_fail (view_model->stamp == iter->stamp);
142 g_return_if_fail (iter->user_data != NULL);
146 g_value_init (value, G_TYPE_STRING);
147 g_value_set_string (value, gtk_tree_view_column_get_title (GTK_TREE_VIEW_COLUMN (((GList *)iter->user_data)->data)));
151 g_value_init (value, GTK_TYPE_TREE_VIEW_COLUMN);
152 g_value_set_object (value, ((GList *)iter->user_data)->data);
157 view_column_model_iter_next (GtkTreeModel *tree_model,
160 ViewColumnModel *view_model = (ViewColumnModel *)tree_model;
162 g_return_val_if_fail (view_model->stamp == iter->stamp, FALSE);
163 g_return_val_if_fail (iter->user_data != NULL, FALSE);
165 iter->user_data = ((GList *)iter->user_data)->next;
166 return iter->user_data != NULL;
170 view_column_model_iter_children (GtkTreeModel *tree_model,
174 ViewColumnModel *view_model = (ViewColumnModel *)tree_model;
176 /* this is a list, nodes have no children */
180 /* but if parent == NULL we return the list itself as children of the
184 if (view_model->columns)
186 iter->stamp = view_model->stamp;
187 iter->user_data = view_model->columns;
195 view_column_model_iter_has_child (GtkTreeModel *tree_model,
202 view_column_model_iter_n_children (GtkTreeModel *tree_model,
205 return g_list_length (((ViewColumnModel *)tree_model)->columns);
209 view_column_model_iter_nth_child (GtkTreeModel *tree_model,
214 ViewColumnModel *view_model = (ViewColumnModel *)tree_model;
219 iter->stamp = view_model->stamp;
220 iter->user_data = g_list_nth ((GList *)view_model->columns, n);
222 return (iter->user_data != NULL);
226 view_column_model_iter_parent (GtkTreeModel *tree_model,
234 view_column_model_tree_model_init (GtkTreeModelIface *iface)
236 iface->get_n_columns = view_column_model_get_n_columns;
237 iface->get_column_type = view_column_model_get_column_type;
238 iface->get_iter = view_column_model_get_iter;
239 iface->get_path = view_column_model_get_path;
240 iface->get_value = view_column_model_get_value;
241 iface->iter_next = view_column_model_iter_next;
242 iface->iter_children = view_column_model_iter_children;
243 iface->iter_has_child = view_column_model_iter_has_child;
244 iface->iter_n_children = view_column_model_iter_n_children;
245 iface->iter_nth_child = view_column_model_iter_nth_child;
246 iface->iter_parent = view_column_model_iter_parent;
251 view_column_model_get_type (void)
253 static GType view_column_model_type = 0;
255 if (!view_column_model_type)
257 static const GTypeInfo view_column_model_info =
259 sizeof (GtkListStoreClass),
260 NULL, /* base_init */
261 NULL, /* base_finalize */
262 NULL, /* class_init */
263 NULL, /* class_finalize */
264 NULL, /* class_data */
265 sizeof (GtkListStore),
267 (GInstanceInitFunc) view_column_model_init,
270 static const GInterfaceInfo tree_model_info =
272 (GInterfaceInitFunc) view_column_model_tree_model_init,
277 view_column_model_type = g_type_register_static (G_TYPE_OBJECT, "ViewModelColumn", &view_column_model_info, 0);
278 g_type_add_interface_static (view_column_model_type,
283 return view_column_model_type;
287 update_columns (GtkTreeView *view, ViewColumnModel *view_model)
289 GList *old_columns = view_model->columns;
290 gint old_length, length;
293 view_model->columns = gtk_tree_view_get_columns (view_model->view);
295 /* As the view tells us one change at a time, we can do this hack. */
296 length = g_list_length (view_model->columns);
297 old_length = g_list_length (old_columns);
298 if (length != old_length)
303 /* where are they different */
304 for (a = old_columns, b = view_model->columns; a && b; a = a->next, b = b->next)
306 if (a->data != b->data)
310 path = gtk_tree_path_new ();
311 gtk_tree_path_append_index (path, i);
312 if (length < old_length)
315 gtk_tree_model_row_deleted (GTK_TREE_MODEL (view_model), path);
320 iter.stamp = view_model->stamp;
322 gtk_tree_model_row_inserted (GTK_TREE_MODEL (view_model), path, &iter);
324 gtk_tree_path_free (path);
333 new_order = g_new (int, length);
334 a = old_columns; b = view_model->columns;
336 while (a->data == b->data)
345 if (a->next->data == b->data)
348 while (b->data != a->data)
353 for (i = 0; i < m; i++)
355 for (i = m; i < m+n; i++)
358 for (i = m + n +1; i < length; i++)
364 while (a->data != b->data)
369 for (i = 0; i < m; i++)
372 for (i = m+1; i < m + n+ 1; i++)
373 new_order[i] = i - 1;
374 for (i = m + n + 1; i < length; i++)
378 path = gtk_tree_path_new ();
379 gtk_tree_model_rows_reordered (GTK_TREE_MODEL (view_model),
383 gtk_tree_path_free (path);
387 g_list_free (old_columns);
390 static GtkTreeModel *
391 view_column_model_new (GtkTreeView *view)
393 GtkTreeModel *retval;
395 retval = GTK_TREE_MODEL (g_object_new (view_column_model_get_type (), NULL));
396 ((ViewColumnModel *)retval)->view = view;
397 ((ViewColumnModel *)retval)->columns = gtk_tree_view_get_columns (view);
399 gtk_signal_connect (GTK_OBJECT (view), "columns_changed", GTK_SIGNAL_FUNC (update_columns), retval);
408 add_clicked (GtkWidget *button, gpointer data)
413 GtkTreeViewColumn *column;
414 GtkTreeSelection *selection;
415 GtkCellRenderer *cell;
416 gchar *label = g_strdup_printf ("Column %d", i);
418 cell = gtk_cell_renderer_text_new ();
419 column = gtk_tree_view_column_new_with_attributes (label, cell, "text", 0, NULL);
420 g_object_set_data_full (G_OBJECT (column), column_data, label, g_free);
421 gtk_tree_view_column_set_reorderable (column, TRUE);
422 gtk_tree_view_column_set_sizing (column, GTK_TREE_VIEW_COLUMN_RESIZABLE);
423 gtk_list_store_append (GTK_LIST_STORE (left_tree_model), &iter);
424 gtk_list_store_set (GTK_LIST_STORE (left_tree_model), &iter, 0, label, 1, column, -1);
427 selection = gtk_tree_view_get_selection (GTK_TREE_VIEW (left_tree_view));
428 gtk_tree_selection_select_iter (selection, &iter);
432 get_visible (GtkTreeViewColumn *tree_column,
433 GtkCellRenderer *cell,
434 GtkTreeModel *tree_model,
438 GtkTreeViewColumn *column;
440 gtk_tree_model_get (tree_model, iter, 1, &column, -1);
443 gtk_cell_renderer_toggle_set_active (GTK_CELL_RENDERER_TOGGLE (cell),
444 gtk_tree_view_column_get_visible (column));
449 set_visible (GtkCellRendererToggle *cell,
453 GtkTreeView *tree_view = (GtkTreeView *) data;
454 GtkTreeViewColumn *column;
457 GtkTreePath *path = gtk_tree_path_new_from_string (path_str);
459 model = gtk_tree_view_get_model (tree_view);
461 gtk_tree_model_get_iter (model, &iter, path);
462 gtk_tree_model_get (model, &iter, 1, &column, -1);
466 gtk_tree_view_column_set_visible (column, ! gtk_tree_view_column_get_visible (column));
467 gtk_tree_model_row_changed (model, path, &iter);
469 gtk_tree_path_free (path);
473 add_left_clicked (GtkWidget *button,
478 GtkTreeViewColumn *column;
480 GtkTreeSelection *selection = gtk_tree_view_get_selection (GTK_TREE_VIEW (data));
482 gtk_tree_selection_get_selected (selection, NULL, &iter);
483 gtk_tree_model_get (gtk_tree_view_get_model (GTK_TREE_VIEW (data)),
484 &iter, 0, &label, 1, &column, -1);
486 if (GTK_WIDGET (data) == top_right_tree_view)
487 gtk_tree_view_remove_column (GTK_TREE_VIEW (sample_tree_view_top), column);
489 gtk_tree_view_remove_column (GTK_TREE_VIEW (sample_tree_view_bottom), column);
491 /* gtk_list_store_remove (GTK_LIST_STORE (gtk_tree_view_get_model (GTK_TREE_VIEW (data))), &iter);*/
493 /* Put it back on the left */
494 gtk_list_store_append (GTK_LIST_STORE (left_tree_model), &iter);
495 gtk_list_store_set (GTK_LIST_STORE (left_tree_model), &iter, 0, label, 1, column, -1);
496 selection = gtk_tree_view_get_selection (GTK_TREE_VIEW (left_tree_view));
497 gtk_tree_selection_select_iter (selection, &iter);
503 add_right_clicked (GtkWidget *button, gpointer data)
507 GtkTreeViewColumn *column;
509 GtkTreeSelection *selection = gtk_tree_view_get_selection (GTK_TREE_VIEW (left_tree_view));
511 gtk_tree_selection_get_selected (selection, NULL, &iter);
512 gtk_tree_model_get (GTK_TREE_MODEL (left_tree_model),
513 &iter, 0, &label, 1, &column, -1);
514 gtk_list_store_remove (GTK_LIST_STORE (left_tree_model), &iter);
516 if (GTK_WIDGET (data) == top_right_tree_view)
517 gtk_tree_view_append_column (GTK_TREE_VIEW (sample_tree_view_top), column);
519 gtk_tree_view_append_column (GTK_TREE_VIEW (sample_tree_view_bottom), column);
524 selection_changed (GtkTreeSelection *selection, GtkWidget *button)
526 if (gtk_tree_selection_get_selected (selection, NULL, NULL))
527 gtk_widget_set_sensitive (button, TRUE);
529 gtk_widget_set_sensitive (button, FALSE);
532 static GtkTargetEntry row_targets[] = {
533 { "GTK_TREE_MODEL_ROW", GTK_TARGET_SAME_APP, 0}
537 main (int argc, char *argv[])
540 GtkWidget *hbox, *vbox;
541 GtkWidget *vbox2, *bbox;
543 GtkTreeViewColumn *column;
544 GtkCellRenderer *cell;
546 GtkTreeModel *sample_model;
549 gtk_init (&argc, &argv);
551 /* First initialize all the models for signal purposes */
552 left_tree_model = (GtkTreeModel *) gtk_list_store_new (2, G_TYPE_STRING, GTK_TYPE_POINTER);
553 sample_model = (GtkTreeModel *) gtk_list_store_new (1, G_TYPE_STRING);
554 sample_tree_view_top = gtk_tree_view_new_with_model (sample_model);
555 sample_tree_view_bottom = gtk_tree_view_new_with_model (sample_model);
556 top_right_tree_model = (GtkTreeModel *) view_column_model_new (GTK_TREE_VIEW (sample_tree_view_top));
557 bottom_right_tree_model = (GtkTreeModel *) view_column_model_new (GTK_TREE_VIEW (sample_tree_view_bottom));
558 top_right_tree_view = gtk_tree_view_new_with_model (top_right_tree_model);
559 bottom_right_tree_view = gtk_tree_view_new_with_model (bottom_right_tree_model);
561 for (i = 0; i < 10; i++)
564 gchar *string = g_strdup_printf ("%d", i);
565 gtk_list_store_append (GTK_LIST_STORE (sample_model), &iter);
566 gtk_list_store_set (GTK_LIST_STORE (sample_model), &iter, 0, string, -1);
570 /* Set up the test windows. */
571 window = gtk_window_new (GTK_WINDOW_TOPLEVEL);
572 gtk_window_set_default_size (GTK_WINDOW (window), 300, 300);
573 gtk_window_set_title (GTK_WINDOW (window), "Top Window");
574 swindow = gtk_scrolled_window_new (NULL, NULL);
575 gtk_container_add (GTK_CONTAINER (window), swindow);
576 gtk_container_add (GTK_CONTAINER (swindow), sample_tree_view_top);
577 gtk_widget_show_all (window);
579 window = gtk_window_new (GTK_WINDOW_TOPLEVEL);
580 gtk_window_set_default_size (GTK_WINDOW (window), 300, 300);
581 gtk_window_set_title (GTK_WINDOW (window), "Bottom Window");
582 swindow = gtk_scrolled_window_new (NULL, NULL);
583 gtk_container_add (GTK_CONTAINER (window), swindow);
584 gtk_container_add (GTK_CONTAINER (swindow), sample_tree_view_bottom);
585 gtk_widget_show_all (window);
587 /* Set up the main window */
588 window = gtk_window_new (GTK_WINDOW_TOPLEVEL);
589 gtk_window_set_default_size (GTK_WINDOW (window), 500, 300);
590 vbox = gtk_vbox_new (FALSE, 8);
591 gtk_container_set_border_width (GTK_CONTAINER (vbox), 8);
592 gtk_container_add (GTK_CONTAINER (window), vbox);
594 hbox = gtk_hbox_new (FALSE, 8);
595 gtk_box_pack_start (GTK_BOX (vbox), hbox, TRUE, TRUE, 0);
598 cell = gtk_cell_renderer_text_new ();
600 swindow = gtk_scrolled_window_new (NULL, NULL);
601 gtk_scrolled_window_set_policy (GTK_SCROLLED_WINDOW (swindow), GTK_POLICY_AUTOMATIC, GTK_POLICY_AUTOMATIC);
602 left_tree_view = gtk_tree_view_new_with_model (left_tree_model);
603 gtk_container_add (GTK_CONTAINER (swindow), left_tree_view);
604 gtk_tree_view_insert_column_with_attributes (GTK_TREE_VIEW (left_tree_view), -1,
605 "Unattached Columns", cell, "text", 0, NULL);
606 cell = gtk_cell_renderer_toggle_new ();
607 g_signal_connect (G_OBJECT (cell), "toggled", (GCallback) set_visible, left_tree_view);
608 column = gtk_tree_view_column_new_with_attributes ("Visible", cell, NULL);
609 gtk_tree_view_append_column (GTK_TREE_VIEW (left_tree_view), column);
611 gtk_tree_view_column_set_cell_data_func (column, cell, get_visible, NULL, NULL);
612 gtk_box_pack_start (GTK_BOX (hbox), swindow, TRUE, TRUE, 0);
615 vbox2 = gtk_vbox_new (FALSE, 8);
616 gtk_box_pack_start (GTK_BOX (hbox), vbox2, FALSE, FALSE, 0);
618 bbox = gtk_vbutton_box_new ();
619 gtk_button_box_set_layout (GTK_BUTTON_BOX (bbox), GTK_BUTTONBOX_SPREAD);
620 gtk_button_box_set_child_size (GTK_BUTTON_BOX (bbox), 0, 0);
621 gtk_box_pack_start (GTK_BOX (vbox2), bbox, TRUE, TRUE, 0);
623 button = gtk_button_new_with_mnemonic ("<< (_Q)");
624 gtk_widget_set_sensitive (button, FALSE);
625 gtk_signal_connect (GTK_OBJECT (button), "clicked", GTK_SIGNAL_FUNC (add_left_clicked), top_right_tree_view);
626 g_signal_connect (G_OBJECT (gtk_tree_view_get_selection (GTK_TREE_VIEW (top_right_tree_view))),
627 "changed", GTK_SIGNAL_FUNC (selection_changed), button);
628 gtk_box_pack_start (GTK_BOX (bbox), button, FALSE, FALSE, 0);
630 button = gtk_button_new_with_mnemonic (">> (_W)");
631 gtk_widget_set_sensitive (button, FALSE);
632 gtk_signal_connect (GTK_OBJECT (button), "clicked", GTK_SIGNAL_FUNC (add_right_clicked), top_right_tree_view);
633 g_signal_connect (G_OBJECT (gtk_tree_view_get_selection (GTK_TREE_VIEW (left_tree_view))),
634 "changed", GTK_SIGNAL_FUNC (selection_changed), button);
635 gtk_box_pack_start (GTK_BOX (bbox), button, FALSE, FALSE, 0);
637 bbox = gtk_vbutton_box_new ();
638 gtk_button_box_set_layout (GTK_BUTTON_BOX (bbox), GTK_BUTTONBOX_SPREAD);
639 gtk_button_box_set_child_size (GTK_BUTTON_BOX (bbox), 0, 0);
640 gtk_box_pack_start (GTK_BOX (vbox2), bbox, TRUE, TRUE, 0);
642 button = gtk_button_new_with_mnemonic ("<< (_E)");
643 gtk_widget_set_sensitive (button, FALSE);
644 gtk_signal_connect (GTK_OBJECT (button), "clicked", GTK_SIGNAL_FUNC (add_left_clicked), bottom_right_tree_view);
645 g_signal_connect (G_OBJECT (gtk_tree_view_get_selection (GTK_TREE_VIEW (bottom_right_tree_view))),
646 "changed", GTK_SIGNAL_FUNC (selection_changed), button);
647 gtk_box_pack_start (GTK_BOX (bbox), button, FALSE, FALSE, 0);
649 button = gtk_button_new_with_mnemonic (">> (_R)");
650 gtk_widget_set_sensitive (button, FALSE);
651 gtk_signal_connect (GTK_OBJECT (button), "clicked", GTK_SIGNAL_FUNC (add_right_clicked), bottom_right_tree_view);
652 g_signal_connect (G_OBJECT (gtk_tree_view_get_selection (GTK_TREE_VIEW (left_tree_view))),
653 "changed", GTK_SIGNAL_FUNC (selection_changed), button);
654 gtk_box_pack_start (GTK_BOX (bbox), button, FALSE, FALSE, 0);
658 vbox2 = gtk_vbox_new (FALSE, 8);
659 gtk_box_pack_start (GTK_BOX (hbox), vbox2, TRUE, TRUE, 0);
661 swindow = gtk_scrolled_window_new (NULL, NULL);
662 gtk_scrolled_window_set_policy (GTK_SCROLLED_WINDOW (swindow), GTK_POLICY_AUTOMATIC, GTK_POLICY_AUTOMATIC);
663 gtk_tree_view_set_headers_visible (GTK_TREE_VIEW (top_right_tree_view), FALSE);
664 cell = gtk_cell_renderer_text_new ();
665 gtk_tree_view_insert_column_with_attributes (GTK_TREE_VIEW (top_right_tree_view), -1,
666 NULL, cell, "text", 0, NULL);
667 cell = gtk_cell_renderer_toggle_new ();
668 g_signal_connect (G_OBJECT (cell), "toggled", (GCallback) set_visible, top_right_tree_view);
669 column = gtk_tree_view_column_new_with_attributes (NULL, cell, NULL);
670 gtk_tree_view_column_set_cell_data_func (column, cell, get_visible, NULL, NULL);
671 gtk_tree_view_append_column (GTK_TREE_VIEW (top_right_tree_view), column);
673 gtk_container_add (GTK_CONTAINER (swindow), top_right_tree_view);
674 gtk_box_pack_start (GTK_BOX (vbox2), swindow, TRUE, TRUE, 0);
676 swindow = gtk_scrolled_window_new (NULL, NULL);
677 gtk_scrolled_window_set_policy (GTK_SCROLLED_WINDOW (swindow), GTK_POLICY_AUTOMATIC, GTK_POLICY_AUTOMATIC);
678 gtk_tree_view_set_headers_visible (GTK_TREE_VIEW (bottom_right_tree_view), FALSE);
679 cell = gtk_cell_renderer_text_new ();
680 gtk_tree_view_insert_column_with_attributes (GTK_TREE_VIEW (bottom_right_tree_view), -1,
681 NULL, cell, "text", 0, NULL);
682 cell = gtk_cell_renderer_toggle_new ();
683 g_signal_connect (G_OBJECT (cell), "toggled", (GCallback) set_visible, bottom_right_tree_view);
684 column = gtk_tree_view_column_new_with_attributes (NULL, cell, NULL);
685 gtk_tree_view_column_set_cell_data_func (column, cell, get_visible, NULL, NULL);
686 gtk_tree_view_append_column (GTK_TREE_VIEW (bottom_right_tree_view), column);
687 gtk_container_add (GTK_CONTAINER (swindow), bottom_right_tree_view);
688 gtk_box_pack_start (GTK_BOX (vbox2), swindow, TRUE, TRUE, 0);
692 gtk_tree_view_set_rows_drag_source (GTK_TREE_VIEW (left_tree_view),
695 G_N_ELEMENTS (row_targets),
698 gtk_tree_view_set_rows_drag_dest (GTK_TREE_VIEW (left_tree_view),
700 G_N_ELEMENTS (row_targets),
704 gtk_tree_view_set_rows_drag_source (GTK_TREE_VIEW (top_right_tree_view),
707 G_N_ELEMENTS (row_targets),
710 gtk_tree_view_set_rows_drag_dest (GTK_TREE_VIEW (top_right_tree_view),
712 G_N_ELEMENTS (row_targets),
716 gtk_tree_view_set_rows_drag_source (GTK_TREE_VIEW (bottom_right_tree_view),
719 G_N_ELEMENTS (row_targets),
722 gtk_tree_view_set_rows_drag_dest (GTK_TREE_VIEW (bottom_right_tree_view),
724 G_N_ELEMENTS (row_targets),
729 gtk_box_pack_start (GTK_BOX (vbox), gtk_hseparator_new (), FALSE, FALSE, 0);
731 hbox = gtk_hbox_new (FALSE, 8);
732 gtk_box_pack_start (GTK_BOX (vbox), hbox, FALSE, FALSE, 0);
733 button = gtk_button_new_with_mnemonic ("_Add new Column");
734 gtk_signal_connect (GTK_OBJECT (button), "clicked", GTK_SIGNAL_FUNC (add_clicked), left_tree_model);
735 gtk_box_pack_start (GTK_BOX (hbox), button, FALSE, FALSE, 0);
737 gtk_widget_show_all (window);