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.
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"""
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 object’s 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.
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: