Learning_GTK4_tree/demos/gtk-demo/tree_store.c

306 lines
16 KiB
C
Raw Normal View History

/*************************************************** 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://docs.gtk.org/gtk4/ */
/* https://docs.gtk.org/gtk4/section-tree-widget.html */
/* https://docs.gtk.org/gtk4/section-list-widget.html << (see below the "quick comparison chart of equivalent functionalities") */
/* https://docs.gtk.org/gtk4/class.TreeListModel.html */
/* */
/* */
/* 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) */
/* */
/****************************************************************************************************************************************/
2023-12-12 11:36:42 +01:00
/* ... Finally heres a quick comparison chart of equivalent functionalitqy
to look for when transitioning code:
Old New
..................................................................
GtkTreeModel GListModel
GtkTreePath guint position, GtkTreeListRow
GtkTreeIter guint position
GtkTreeRowReference GObject item
GtkListStore GListStore
GtkTreeStore GtkTreeListModel, GtkTreeExpander
GtkTreeSelection GtkSelectionModel
GtkTreeViewColumn GtkColumnView
GtkTreeView GtkListView, GtkColumnView
GtkCellView GtkListItem
GtkComboBox GtkDropDown
GtkIconView GtkGridView
GtkTreeSortable GtkColumnView
GtkTreeModelSort GtkSortListModel
GtkTreeModelFilter GtkFilterListModel
GtkCellLayout GtkListItemFactory
GtkCellArea GtkWidget
GtkCellRenderer GtkWidget
..............................................................................*/
2023-12-12 11:36:42 +01:00
#include <gtk/gtk.h>
#include <stdio.h>
#include "config.h"
#include "custom-list.h"
2023-12-12 11:36:42 +01:00
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;
2023-12-22 12:46:00 +01:00
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 .
}
2023-12-12 11:36:42 +01:00
/* TreeItem structure */
typedef struct _TreeItem TreeItem;
struct _TreeItem
{
const char *label;
TreeItem *children;
};
/* tree data */
2023-12-18 18:48:14 +01:00
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
2023-12-12 11:36:42 +01:00
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;
}
2023-12-12 11:36:42 +01:00
GtkWidget *
do_tree_store (GtkWidget *do_widget)
{
static GtkWidget *my_window = NULL;
2023-12-12 11:36:42 +01:00
if (! my_window)
2023-12-12 11:36:42 +01:00
{
GtkWidget *vbox;
GtkWidget *sw; // sw : 'scrolled_window'
2023-12-12 11:36:42 +01:00
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.
2023-12-12 11:36:42 +01:00
/* 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);
2023-12-12 11:36:42 +01:00
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);
2023-12-12 11:36:42 +01:00
2023-12-15 10:12:13 +01:00
gtk_box_append (GTK_BOX (vbox), gtk_label_new ("Learning GTK trees"));
2023-12-12 11:36:42 +01:00
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"));
2023-12-12 11:36:42 +01:00
/* create tree view */
treeview = gtk_tree_view_new_with_model (my_tree_model);
2023-12-18 18:48:14 +01:00
gtk_tree_view_set_headers_visible (GTK_TREE_VIEW (treeview), FALSE);
gtk_tree_view_set_enable_tree_lines (GTK_TREE_VIEW (treeview), TRUE);
2023-12-12 11:36:42 +01:00
gtk_widget_set_vexpand (treeview, TRUE);
gtk_tree_selection_set_mode (gtk_tree_view_get_selection (GTK_TREE_VIEW (treeview)),
GTK_SELECTION_MULTIPLE);
2023-12-18 18:48:14 +01:00
gtk_tree_view_set_reorderable (GTK_TREE_VIEW (treeview), TRUE);
g_object_unref (my_tree_model);
2023-12-12 11:36:42 +01:00
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);
2023-12-12 11:36:42 +01:00
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);
2023-12-12 11:36:42 +01:00
}
if (!gtk_widget_get_visible (my_window))
gtk_widget_set_visible (my_window, TRUE);
2023-12-12 11:36:42 +01:00
else
gtk_window_destroy (GTK_WINDOW (my_window));
return my_window;
2023-12-12 11:36:42 +01:00
}