/*************************************************** R E M E M B E R ! *******************************************************/ /* */ /* jean@Project:~/Gem-Graph/gem-graph-client/tree (learning)/The_Gnome_way/gtk$ guix shell -m manifest.scm --check */ /* guix shell: vérification des variables d'environnement visibles depuis le shell « /gnu/store/ --- (a commit) --- /bin/bash »… */ /* guix shell: Tout va bien ! Le shell a les bonnes variables d'environnement. */ /* jean@Project:~/Gem-Graph/gem-graph-client/tree (learning)/The_Gnome_way/gtk [env] $ cd builddir/ */ /* jean@Project:~/Gem-Graph/gem-graph-client/tree...way/gtk/builddir [env] $ clear && meson compile && demos/gtk-demo/gtk4-demo */ /* */ /* -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- A Session -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- */ /* */ /* jean@Project:~/Gem-Graph/gem-graph-client/tree (learning)/The_Gnome_way/gtk/builddir [env] $ ctrl D (avant de fermer builder) */ /* */ /****************************************************************************************************************************************/ /************************************************** W I D G E T S ********************************************************/ /* _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ */ /* _ _ _ _ _ _ _ _ _ _ _ _ _ E D I T A B L E _ _ _ _ _ _ _ _ _ _ _ _ _ _ */ /* */ /* https://developer-old.gnome.org/gtk4/stable/ch03s02.html Which widget should I use ?... */ /* https://developer-old.gnome.org/gtk4/stable/GtkCellEditable.html#GtkCellEditable-struct */ /* The GtkCellEditable interface must be implemented for widgets to be usable to edit the contents of a GtkTreeView cell. */ /* It provides a way to specify how temporary widgets should be configured for editing, get the new value, etc. */ /* _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ */ /* _ _ _ _ _ _ _ _ _ _ _ _ _ _ T R E E _ _ _ _ _ _ _ _ _ _ _ _ _ _ */ /* */ /* https://developer-old.gnome.org/gtk4/stable/GtkTreeView.html */ /* https://en.wikibooks.org/wiki/GTK%2B_By_Example/Tree_View/Custom_Models */ /* https://developer-old.gnome.org/gtk4/stable/GtkTreeSelection.html#GtkTreeSelection-struct */ /* https://developer-old.gnome.org/gtk4/stable/GtkTreeView.html#gtk-tree-view-get-path-at-pos << get-path-at-pos */ /* Finds the path at the point (x , y ), relative to bin_window coordinates. Use gtk_tree_view_convert_widget_to_bin_window_coords(). */ /* https://www.gnu.org/software/guile-gnome/docs/gtk/html/GtkCellRenderer.html */ /* GtkTreeSelection, GtkTreeView drag-and-drop, GtkTreeSortable, GtkTreeModelSort, GtkCellEditable, GtkCellRendererText,... */ /* gtk_tree_view_get_search_entry (treeview) */ /* */ /****************************************************************************************************************************************/ #include #include #include "config.h" #include "custom-list.h" G_GNUC_BEGIN_IGNORE_DEPRECATIONS enum { STRING_COLUMN, NUM_COLUMNS }; static GObjectClass *parent_class = NULL; /* GObject stuff - nothing to worry about */ static void custom_list_finalize (GObject *object); static void custom_list_class_init (CustomListClass *klass) { GObjectClass *object_class; parent_class = (GObjectClass*) g_type_class_peek_parent (klass); object_class = (GObjectClass*) klass; object_class->finalize = custom_list_finalize; } static void custom_list_tree_model_init (GtkTreeModelIface *iface) { /* Here we override the GtkTreeModel * interface functions that we implement */ iface->get_flags = NULL; // custom_list_get_flags; iface->get_n_columns = NULL; // custom_list_get_n_columns; iface->get_column_type = NULL; // custom_list_get_column_type; iface->get_iter = NULL; // custom_list_get_iter; iface->get_path = NULL; // custom_list_get_path; iface->get_value = NULL; // custom_list_get_value; iface->iter_next = NULL; // custom_list_iter_next; iface->iter_children = NULL; // custom_list_iter_children; iface->iter_has_child = NULL; // custom_list_iter_has_child; iface->iter_n_children = NULL; // custom_list_iter_n_children; iface->iter_nth_child = NULL; // custom_list_iter_nth_child; iface->iter_parent = NULL; // custom_list_iter_parent; } // gtk_tree_model_foreach (model, TRUE, my_user_data); https://developer-old.gnome.org/gtk4/stable/GtkTreeModel.html#GtkTreeModelForeachFunc static void iterating_a_model_in_a_depth_first_fashion (GtkTreeModel *model) { // gboolean (*GtkTreeModelForeachFunc) (GtkTreeModel *model, GtkTreePath *path, GtkTreeIter *iter, gpointer data); GtkTreeIter iter, iter_parent; char *str_data; int row_count = 0; gtk_tree_model_get_iter_first (model, &iter); gtk_tree_model_get (model, &iter, STRING_COLUMN, &str_data, -1); g_print ("first row %d: (%s)\n", row_count, str_data); gtk_tree_model_iter_children (model, &iter_parent, &iter); gtk_tree_model_iter_children (model, &iter, &iter_parent); // Sets iter to point to the first child of parent. //gtk_tree_model_iter_next (model, &iter); gtk_tree_model_get (model, &iter, STRING_COLUMN, &str_data, -1); g_print ("next row %d: (%s) < False (should be 'A' <-- line 104)\n", row_count, str_data); /* while (valid) first row 0: (ROOT) next row 0: (D)*/ /* { */ /* char *str_data; */ /* // Make sure you terminate calls to gtk_tree_model_get() with a “-1” value */ /* gtk_tree_model_get (model, &iter, STRING_COLUMN, &str_data, -1); */ /* g_print ("Row %d: (%s) <> gtk_tree_model_get_iter_first (model, &iter) &iter = [%s] (line 67) ", row_count, str_data, "xxx");//&iter); */ /* g_free (str_data); */ /* valid = gtk_tree_model_iter_next (model, &iter); */ /* // valid = gtk_tree_model_iter_children (model, &iter, parent); << how to get the parent ?? */ /* g_print ("valid = %d = gtk_tree_model_iter_next (model, &iter) %s (line 69)\n",\ */ /* valid, gtk_tree_model_get_string_from_iter (model, &iter)); */ /* row_count++; */ /* } */ } static void /* https://developer-old.gnome.org/gtk4/stable/GtkTreeModel.html#GtkTreePath-struct and #gtk-tree-row-reference-new */ gtk_tree_model_get_data_from_iter (GtkTreeModel *my_tree_model, GtkCellEditable *cell_editable, GtkTreeIter *my_iter, GdkEvent *event, GtkTreePath *my_path) { char *str_data; gtk_tree_model_get_iter (my_tree_model, &my_iter, my_path); gtk_tree_model_get (my_tree_model, &my_iter, STRING_COLUMN, &str_data, -1); g_print ("row from iter at [ %s ] = '%s'\n",\ gtk_tree_model_get_string_from_iter(my_tree_model, &my_iter), str_data); gtk_tree_path_free (my_path); } static void /* https://developer-old.gnome.org/gtk4/stable/GtkTreeModel.html#GtkTreePath-struct and #gtk-tree-row-reference-new */ gtk_tree_model_edit_a_cell (GtkTreeModel *my_tree_model, GtkCellEditable *cell_editable, GtkTreeIter *my_iter, GdkEvent *event, GtkTreePath *my_path) { gtk_tree_model_get (my_tree_model, my_iter); // Gets the value of one or more cells in the row referenced by iter gtk_cell_editable_start_editing (cell_editable, event); // Begins editing on a cell_editable . gtk_cell_editable_editing_done (cell_editable); // Emits the “editing-done” signal. gtk_tree_model_row_deleted (my_tree_model, my_path); // Emits the “row-deleted” signal on tree_model . gtk_tree_model_row_inserted (my_tree_model, my_path, my_iter); // Emits the “row-inserted” signal on tree_model . } /* TreeItem structure */ typedef struct _TreeItem TreeItem; struct _TreeItem { const char *label; TreeItem *children; }; /* tree data */ static TreeItem E[] = {NULL}, F[] = {NULL}, G[] = {NULL}, H[] = {NULL}; static TreeItem I[] = {NULL}, K[] = {NULL}, N[] = {NULL}, M[] = {NULL}; static TreeItem L[] = {{"M", M}, {"N", N}, {NULL }}, J[] = {{"L", L}, {NULL}}; static TreeItem D[] = {{"I", I}, {"J", J}, {"K", K}, {NULL}}; static TreeItem C[] = {{"F", F}, {"G", G}, {"H", H}, {NULL}}; static TreeItem A[] = {{"D", D}, {NULL}}, B[] = {{"E", E}, {NULL}}; static TreeItem R[] = {{"A", A}, {"B", B}, {"C", C}, {NULL}}; static TreeItem O[] = {{"ROOT", R}, {NULL}}; // Artefact added for symmetry static GtkTreeModel *create_node_recursive (GtkTreeStore *model, TreeItem *current_item, GtkTreeIter *iter_parent, int depth) { GtkTreeIter iter; if (model == NULL) model = gtk_tree_store_new (NUM_COLUMNS, G_TYPE_STRING); while (current_item->label) { if (0) printf("[%d] Current label : %s\n", depth, current_item->label); gtk_tree_store_append (model, &iter, iter_parent); gtk_tree_store_set (model, &iter, STRING_COLUMN, current_item->label, -1); if (current_item->children) create_node_recursive (model, current_item->children, &iter, depth + 1); else break; current_item++; } if (depth == 0) return GTK_TREE_MODEL(model); // cast from GtkTreeModel to GtkTreeStore else return NULL; } GtkWidget * do_tree_store (GtkWidget *do_widget) { static GtkWidget *my_window = NULL; if (! my_window) { GtkWidget *vbox; GtkWidget *sw; // sw : 'scrolled_window' GtkWidget *treeview; GtkTreeModel *my_tree_model; GtkTreeStore *my_tree_store = NULL; // The GtkTreeStore is used to store data in tree form, // to be used later on by a GtkTreeView to display it. /* create window, etc */ my_window = gtk_window_new (); gtk_window_set_title (GTK_WINDOW (my_window), "Tree Store"); g_object_add_weak_pointer (G_OBJECT (my_window), (gpointer *)&my_window); vbox = gtk_box_new (GTK_ORIENTATION_VERTICAL, 8); gtk_widget_set_margin_start (vbox, 8); gtk_widget_set_margin_end (vbox, 8); gtk_widget_set_margin_top (vbox, 8); gtk_widget_set_margin_bottom (vbox, 8); gtk_window_set_child (GTK_WINDOW (my_window), vbox); gtk_box_append (GTK_BOX (vbox), gtk_label_new ("Learning GTK trees")); sw = gtk_scrolled_window_new (); gtk_scrolled_window_set_has_frame (GTK_SCROLLED_WINDOW (sw), TRUE); gtk_scrolled_window_set_policy (GTK_SCROLLED_WINDOW (sw), GTK_POLICY_AUTOMATIC, GTK_POLICY_AUTOMATIC); gtk_box_append (GTK_BOX (vbox), sw); /* create tree_model */ my_tree_model = create_node_recursive (my_tree_store, O, NULL, 0); iterating_a_model_in_a_depth_first_fashion (my_tree_model); // GtkTreePath *my_path = gtk_tree_path_new_from_string ("0:0:1:0:1"); // acquiring_a_GtkTreeIter (my_tree_model, my_path); GtkTreeIter *my_iter; gtk_tree_model_get_data_from_iter (my_tree_model, NULL, my_iter, NULL, gtk_tree_path_new_from_string ("0:0:0:1:0:1")); /* create tree view */ treeview = gtk_tree_view_new_with_model (my_tree_model); gtk_tree_view_set_headers_visible (GTK_TREE_VIEW (treeview), FALSE); gtk_tree_view_set_enable_tree_lines (GTK_TREE_VIEW (treeview), TRUE); gtk_widget_set_vexpand (treeview, TRUE); gtk_tree_selection_set_mode (gtk_tree_view_get_selection (GTK_TREE_VIEW (treeview)), GTK_SELECTION_MULTIPLE); gtk_tree_view_set_reorderable (GTK_TREE_VIEW (treeview), TRUE); g_object_unref (my_tree_model); GtkCellRenderer *renderer; renderer = gtk_cell_renderer_text_new (); g_object_set (renderer, "xalign", 0.0, NULL); gtk_tree_view_insert_column_with_attributes (GTK_TREE_VIEW (treeview), -1, "Col 0", renderer, "text", STRING_COLUMN, NULL); gtk_scrolled_window_set_child (GTK_SCROLLED_WINDOW (sw), treeview); /* expand all rows after the treeview widget has been realized */ g_signal_connect (treeview, "realize", G_CALLBACK (gtk_tree_view_expand_all), NULL); gtk_window_set_default_size (GTK_WINDOW (my_window), 200, 400); } if (!gtk_widget_get_visible (my_window)) gtk_widget_set_visible (my_window, TRUE); else gtk_window_destroy (GTK_WINDOW (my_window)); return my_window; }