247 lines
13 KiB
Plaintext
247 lines
13 KiB
Plaintext
|
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/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)
|
|||
|
|
|||
|
|
|||
|
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 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.
|
|||
|
|
|||
|
//--------------------------------------
|
|||
|
|
|||
|
|
|||
|
|
|||
|
|
|||
|
|
|||
|
|
|||
|
|
|||
|
|
|||
|
|
|||
|
|
|||
|
|
|||
|
|
|||
|
|
|||
|
/************************ 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.
|
|||
|
*
|
|||
|
*............................................................................*/
|
|||
|
|
|||
|
|