gem-graph-client/mes notes et liens Gtk4 (20...

352 lines
18 KiB
Plaintext
Raw Normal View History

//---------------------------------------------------------------------------------------------------------------------------
commit 'cleaned' fe7ad2488ab00f25f180e2acaeadaac2332ec3cc
//---------------------------------------------------------------------------------------------------------------------------
Linkedin thq&4s5r&CH%6pPAhJt8 jean.sirmai@orange.fr
//---------------------------------------------------------------------------------------------------------------------------
A summary from : https://docs.gtk.org/gtk4/section-list-widget.html 2024-02-02
Views or list widgets are the widgets that hold and manage the lists. Example: GtkListView
Views display data from a model. Models implement the GListModel interface and can be provided in a variety of ways:
GtkStringList is a list model implementation for strings. It can be wrapped by GtkFilterListModel or GtkSortListModel.
Developers are encouraged to create their own GListModel implementations. The interface is kept deliberately small to make this easy.
The same model can be used in multiple different views and wrapped with multiple different models at once.
The elements in a model are called items.
Every item in a model has a position which is the unsigned integer that describes where in the model the item is located. The first item in a model is at position 0. The position of an item can change as other items are added or removed from the model.
Factories are GtkListItemFactory implementations that takes care of mapping the items of the model to widgets that can be shown in the view.
Factories create a listitem for each item that is currently in use. List items are always GtkListItem instances. They are only ever created by GTK and provide information about what item they are meant to display.
Both selections and activation are supported via widget actions. This allows developers to add widgets to their lists that cause selections to change or to trigger activation via the GtkActionable interface.
The views only create a limited amount of listitems and recycle them by binding them to new items. In general, views try to keep listitems available only for the items that can actually be seen on screen. It is not possible to query a view for a listitem used for a certain position.
It is also important that developers save state they care about in the item and do not rely on the widgets they created as those widgets can be recycled for a new position at any time causing any state to be lost.
Views need to know which items are not visible so they can be recycled. Views achieve that by implementing the GtkScrollable interface and expecting to be placed directly into a GtkScrolledWindow.
GTK provides functionality to make lists look and behave like trees. This is achieved by using the GtkTreeListModel model to flatten a tree into a list. The GtkTreeExpander widget can then be used inside a listitem to allow users to expand and collapse rows and provide a similar experience to GtkTreeView.
The model allows for bulk changes via the GListModel::items-changed signal.
It is possible to refer to the contents of a row in the model directly by keeping the item. And because the items are real objects, developers can make them emit change signals causing listitems and their children to update.
GListModel, guint position, GtkTreeListRow, GObject item, GListStore, GtkTreeListModel, GtkTreeExpander, GtkSelectionModel,
GtkColumnView, GtkListView, GtkListItem, GtkSortListModel, GtkFilterListModel, GtkListItemFactory, GtkWidget
//---------------------------------------------------------------------------------------------------------------------------
https://discourse.gnome.org/t/tips-to-initialize-gtk4s-columnview-python/19028
factory = Gtk.SignalListItemFactory()
factory.connect( 'bind', bindCallback )
def bindCallback( factory, item ):
item.set_child( item.get_item().end_item )
//---------------------------------------------------------------------------------------------------------------------------
alors quune fonction normale est appelée directement,
la fonction de rappel G_CALLBACK est simplement définie au départ
et nest appelée et exécutée que lorsquun certain événement se produit.
https://www.ionos.fr/digitalguide/sites-internet/developpement-web/quest-ce-quun-callback/
Voici un exemple de callback function en C :
void A()
{
printf("Je suis une fonction A\n");
}
// La fonction callback
void B(void (*ptr)())
{
(*ptr) (); // Appel du callback à A
}
int main()
{
void (*ptr)() = &A;
// Appel de la fonction B
// La fonction A est passée en argument
B(ptr);
return 0;
}
Le résultat de ce code est donc : "Je suis une fonction A".
Comme en JavaScript, une fonction de rappel est appelée chaque fois quun certain événement se produit.
En C, ces fonctions sont utilisées pour créer diverses nouvelles bibliothèques pour des travaux de programmation ultérieurs,
et pour émettre les signaux du noyau qui sont nécessaires à la gestion des événements asynchrones.
//---------------------------------------------------------------------------------------------------------------------------
https://github.com/kriptolix/gtk4_python3_exemples/blob/main/ListView/tree_view.py
https://discourse.gnome.org/t/documentation-by-gtk-list-view-tree/18978 How to set up the tree gtklistview ?
kriptolix Diego C Sampaio answer > You will need:
1 - Gtk.ListView or Gtk.ColunmView - the widget that will display the visible content as a list.
2 - Gio.ListStore or one of its variants - the list that will contain the objects whose information will be used to create rows in the Gtk.ListView.
3 - Gtk.TreeListModel - a model that will determine how the items contained in the Gio.ListStore will be accessed/viewed.
4 - Gtk.NoSelection, Gtk.SingleSelection or Gtk.MultiSelection - will determine whether the items displayed in Gtk.ListView can be selected and how.
5 - Gtk.SignalListItemFactory or Gtk.BuildListItemFactory - a function that will build a widget to be displayed as a row in the Gtk.ListView.
This widget will be populated with the information contained in the Gio.ListStore objects.
6 - GtkTreeExpander - widget that must be included in the widget built by Gtk.SignalListItemFactory to allow row expansion.
7 - Info Object - an object that will be inserted into the Gio.ListStore and that contains the information to be displayed by the rows created by Gtk.SignalListItemFactory.
The process has a few steps, although it is possible to understand them through the documentation, there is a specific step: the Gtk.TreeListModel callback function, which I find difficult to understand without an example. Here 2 is a minimal example of implementing a tree list view in Python. https://github.com/kriptolix/gtk4_python3_exemples/blob/main/ListView/tree_view.py
import gi
gi.require_version("Gtk", "4.0")
from gi.repository import Gtk, Gio, GObject # noqa
class DataObject(GObject.GObject):
def __init__(self, txt: str, children=None):
super(DataObject, self).__init__()
self.data = txt
self.children = children
def add_tree_node(item):
if not (item):
print("no item")
return model
else:
if type(item) == Gtk.TreeListRow:
item = item.get_item()
print("converteu")
print(item)
if not item.children:
return None
store = Gio.ListStore.new(DataObject)
for child in item.children:
store.append(child)
return store
def setup(widget, item):
"""Setup the widget to show in the Gtk.Listview"""
label = Gtk.Label()
expander = Gtk.TreeExpander.new()
expander.set_child(label)
item.set_child(expander)https://discourse.gnome.org/t/tips-to-initialize-gtk4s-columnview-python/19028
def bind(widget, item):
"""bind data from the store object to the widget"""
expander = item.get_child()
label = expander.get_child()
row = item.get_item()
expander.set_list_row(row)
obj = row.get_item()
label.set_label(obj.data)
def on_activate(app):
win = Gtk.ApplicationWindow(
application=app,
title="Gtk4 is Awesome !!!",
default_height=400,
default_width=400,
)
sw = Gtk.ScrolledWindow()
list_view = Gtk.ListView()
factory = Gtk.SignalListItemFactory()
factory.connect("setup", setup)
factory.connect("bind", bind)
list_view.set_factory(factory)
selection = Gtk.SingleSelection()
store = Gio.ListStore.new(DataObject)
model = Gtk.TreeListModel.new(store, False, False, add_tree_node)
selection.set_model(model)
list_view.set_model(selection)
v1 = [DataObject("entrada 01")]
v2 = [DataObject("entrada 01", v1)]
store.append(DataObject("entrada 01", v2))
# store.append(DataObject("entrada 02"))
sw.set_child(list_view)
win.set_child(sw)
win.present()
app = Gtk.Application(application_id="org.gtk.Example")
app.connect("activate", on_activate)
app.run(None)
//--------------------------------------
https://discourse.gnome.org/t/how-can-i-get-the-expanded-collapsed-items-in-the-new-gtktreelistmodel-implementation/16824
https://github.com/kriptolix/gtk4_python3_exemples
https://github.com/kriptolix/gtk4_python3_exemples/blob/main/ListView/tree_view.py
In Gtk4, a tree list is composed of several elements:
Data Object: an object to hold the data to be displayed (a string that will be displayed like an item, for example).
List: A Gio.ListStore or other list object that will contain the data objects.
Selection: the type of Gtk.Selection that can be made in the component (none, single…), a List needs to be set as the model of the Gtk.Selection.
ItemFactory: an ItemFactory will create a widget to be displayed in the ListView (a Gtk.Label to display a string like an item, for example), and will add to it the objects information in the List (the string that goes in the Gtk.Label). The ItemFactory can do this via signals or through the Builder. Gtk.SignalListItemFactory is easier to understand and creates the widgets through a “setup” function, and connects the data object information to the widget through a “bind” function. Both are connected to ItemFactory through its “bind” and “setup” signals.
Lastly, you need Gtk.ListView to display the widget created by the ItemFactory. Once all this is created, when you insert a Data Object into the List, the ItemFactory will call the “setup” function, then the “bind” function, and the Gtk.ListView will display the widget for that item.
That said, GtkTreeListModelCreateModelFunc serves to create Models on demand to allocate the subitems of a treelist, whenever an item of the treelist is expanded or collapsed there will be a call to GtkTreeListModelCreateModelFunc. In the “bind” function, the state of the Gtk.TreeExpander must be connected to its respective Gtk.TreeListRow.
//--------------------------------------
/************************ 2024-01-06 widgets ! ************************/
/* in > 01/GTK4/tree (learning)/The_Gnome_way/demos/gtk-demo */
/* */
/* tree_store() listview_words() editable_cells() search_entry2() */
/* dnd()(= drag and drop) entry_undo() expander() textundo() */
/* scale() (= scale entries from bars) font_features() hypertext() */
/* iconview_edit() (= drag and drop icons) image_scaling() infobar() */
/* links() listbox_controls() list_store() listview_colors() */
/* listview_selections() mask(NULL) and more... */
/* */
/******************************************************************************/
/*************** The basic ideas behind list views: *******************/
/* */
/* The data for items is provided in the form of a model containing objects */
/* Widgets are created just for the viewable range of items */
/* Widgets can be recycled by binding them to different items */
/* Avoid iterating over all items in the model as much as possible, and */
/* just deal with the items in the visible range which are bound to widgets */
/* from https://blog.gtk.org/2020/06/07/scalable-lists-in-gtk-4/ */
/* */
/******************************************************************************/
// GtkListItemFactory is the object that is tasked with creating widgets
// for the items in the model.
// One implementations of this factory, GtkBuilderListItemFactory,
// is using ui files as templates for the list item widgets.
/*************** A B O U T T R E E S **************************/
/* */
/* https://docs.gtk.org/gtk4/ */
/* https://docs.gtk.org/gtk4/getting_started.html */
/* https://toshiocp.github.io/Gtk4-tutorial/sec29.html <<< TODO (tuto) */
/* Keep the "comparison chart of equivalent functionalities" (link below) */
/* https://docs.gtk.org/gtk4/section-list-widget.html */
/* https://en.wikibooks.org/wiki/GTK%2B_By_Example/Tree_View */
/* https://gnome.pages.gitlab.gnome.org/libsoup/gio/GListModel.html */
/* https://docs.gtk.org/gio/iface.ListModel.html < +++ */
/* */
/* https://docs.gtk.org/gtk4/class.TreeListModel.html (easy to find) */
/* https://developer-old.gnome.org/gtk4/stable/GtkTreeView.html (vieux...) */
/* get-path-at-pos(x,y) <> finds the path at these window coordinates. */
/* https://blog.gtk.org/2020/09/08/on-list-models/ */
/* */
/******************************************************************************/
/*..............................................................................
*
* >>> GtkStringList <<<
*
* GtkStringList is a list model that wraps an array of strings.
* The objects in the model are of type GtkStringObject
* and have a “string” property that can be used inside expressions.
* Use it where/when you would typically use a char*[], but need a list model.
*
* Every item in a model has a position (= unsigned integer)
* "factories" takes care of mapping the items of the model
* to widgets that can be shown in the view
* by creating a listitem for each item that is currently in use.
* List items are always GtkListItem instances. Widgets can be recycled.
*
* GtkStringList can only handle strings.
* It is backed by a dynamically allocated array.
* GListStore is backed by a balanced tree.
*
* GTK provides functionality to make lists look and behave like trees
* by using the GtkTreeListModel and the GtkTreeExpander widget.
*
* Widgets are styleable using GTK CSS. Use the .rich-list style class.
*
* GListModel is an interface that represents a mutable list of GObjects.
*
*............................................................................*/
https://docs.gtk.org/gio/iface.ListModel.html
Gio
ListModel
[]
Description
interface Gio.ListModel : GObject.Object
GListModel is an interface that represents a mutable list of GObject.
Its main intention is as a model for various widgets in user interfaces, such as list views,
but it can also be used as a convenient method of returning lists of data, with support for updates.
Each object in the list may also report changes in itself via some mechanism (normally the GObject::notify signal).
Taken together with the GListModel::items-changed signal, this provides for a list that can change its membership,
and in which the members can change their individual properties.
A good example would be the list of visible wireless network access points,
where each access point can report dynamic properties such as signal strength.
It is important to note that the GListModel itself does not report changes to the individual items.
It only reports changes to the list membership.
If you want to observe changes to the objects themselves then you need to connect signals to the objects that you are interested in.
All items in a GListModel are of (or derived from) the same type. g_list_model_get_item_type() returns that type.
The type may be an interface, in which case all objects in the list must implement it.
The semantics are close to that of an array: g_list_model_get_n_items() returns the number of items in the list
and g_list_model_get_item() returns an item at a (0-based) position.
In order to allow implementations to calculate the list length lazily, you can also iterate over items:
starting from 0, repeatedly call g_list_model_get_item() until it returns NULL.
An implementation may create objects lazily, but must take care to return the same object for a given position until all references to it are gone.
On the other side, a consumer is expected only to hold references on objects that are currently user visible,
in order to facilitate the maximum level of laziness in the implementation of the list and to reduce the required number of signal connections at a given time.
This interface is intended only to be used from a single thread.
The thread in which it is appropriate to use it depends on the particular implementation,
but typically it will be from the thread that owns the thread-default main context
(see g_main_context_push_thread_default()) in effect at the time that the model was created.
Over time, it has established itself as good practice for list model implementations to provide properties item-type and n-items
to ease working with them. While it is not required, it is recommended that implementations provide these two properties.
They should return the values of g_list_model_get_item_type() and g_list_model_get_n_items() respectively and be defined as such: