/*************************************************** 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; gboolean valid = 0; char *str_data; int row_count = 0; valid = gtk_tree_model_get_iter_first (model, &iter); if (valid) gtk_tree_model_get (model, &iter, STRING_COLUMN, &str_data, -1); g_print ("first row %d: (%s)\n", row_count, str_data); valid = gtk_tree_model_iter_children (model, &iter_parent, &iter); valid = gtk_tree_model_iter_children (model, &iter, &iter_parent); //gtk_tree_model_iter_next (model, &iter); if (valid) gtk_tree_model_get (model, &iter, STRING_COLUMN, &str_data, -1); g_print ("next row %d: (%s)\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++; */ /* } */ } // Three ways of getting the iter pointing to the location https://developer-old.gnome.org/gtk4/stable/GtkTreeModel.html#gtk-tree-row-reference-new static void acquiring_a_GtkTreeIter (GtkTreeModel *my_tree_model, GtkTreePath *my_tree_path) { GtkTreeIter iter; // get the iterator from a string gtk_tree_model_get_iter_from_string (my_tree_model, &iter, gtk_tree_path_to_string (my_tree_path)); g_print ("acquiring_a_GtkTreeIter from path : [ %s ] (lines 225 & 108)\n", gtk_tree_path_to_string (my_tree_path)); my_tree_path = gtk_tree_path_new_from_string (gtk_tree_path_to_string (my_tree_path)); // get the iterator from a path gtk_tree_model_get_iter (my_tree_model, &iter, my_tree_path); gtk_tree_path_free (my_tree_path); /* GtkTreeIter parent_iter; gtk_tree_model_iter_nth_child (my_tree_model, &iter, NULL, 3); // walk the tree to find the iterator */ /* parent_iter = iter; gtk_tree_model_iter_nth_child (my_tree_model, &iter, &parent_iter, 2); */ /* parent_iter = iter; gtk_tree_model_iter_nth_child (my_tree_model, &iter, &parent_iter, 5); */ } static void /* https://developer-old.gnome.org/gtk4/stable/GtkTreeModel.html#GtkTreePath-struct and #gtk-tree-row-reference-new */ edit_a_cell (GtkTreeModel *my_tree_model, GtkCellEditable *cell_editable, GtkTreeIter *iter, GdkEvent *event, GtkTreePath *path) { GtkTreePath *any_path = gtk_tree_path_new_first (); // Creates and returns a new GtkTreePath. // The string representation of this path is “0”. const char *any_path_string = gtk_tree_path_to_string (any_path); // Generates a string representation of the path. // Path is expected to be a colon separated list of numbers. For example, the string “10:4:0”. // This string would create a path of depth 3 pointing to the 11th child of the root node, // the 5th child of that 11th child, and the 1st child of that 5th child. // If the path has depth 0, NULL is returned. any_path = gtk_tree_path_new_from_indices (10,4,0); // Creates a new path with first_index and varargs as indices. gtk_tree_model_get_iter_from_string (my_tree_model, iter, any_path_string); // Sets iter to a valid iterator pointing to path. // If path does not exist, iter is set to an invalid iterator and FALSE is returned. // gpointer *data; gboolean b = (*GtkTreeModelForeachFunc) (my_tree_model, path, iter, data); // Type of the callback passed to gtk_tree_model_foreach() to iterate over the rows in a tree model. gtk_tree_model_get (my_tree_model, 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, path); // Emits the “row-deleted” signal on tree_model . gtk_tree_model_row_inserted (my_tree_model, path, 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; edit_a_cell (my_tree_model, NULL, my_iter, NULL, my_path); /* 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; }