GtkColumnView general discussion


The last few days I’ve been trying to migrate from GtkTreeView to GtkColumnView, but without much luck. I have two questions that I hope you might want to answer:

  1. How do I append numbers or strings when g_list_store_append expects GObject* items?
  2. How do I retrieve the second index from within GtkSignalListItemFactory::setup or ::bind to fetch items from the GListStore without looping over GtkSignalListItemFactory pointers?


You don’t do that.

GListModel implementations do not work like GtkTreeModel ones: you don’t pack a bunch of unrelated values inside columns and display each one of them in a row.

The way the API works is that you create a GObject type that represents the whole of a row data (the “model”), using properties to store the state and notify of changes; the factory (the “controller”) creates the UI that represent that row state (the “view”).

In short:

  • inside the factory setup implementation you create widgets that represent the object state; the widgets are set as the child of the given GtkListItem
  • inside the factory bind implementation you bind properties from the state object—retrieved using gtk_list_item_get_item()—to the row widget—retrieved using gtk_list_item_get_child(); you can use g_object_bind_property() for that, but any mechanism based on signals works

Every time you need to update the view, you modify the state object; the changes in the state object will be propagated to the view.

If you have a view that can mutate the state object, then you can use a bidirectional property binding, or connect to signals and pass the state object.

Remember that list views recycle widgets; this means you should also use the factory unbind implementation to disconnect signals and unbind properties; it’s not always necessary to implement the factory teardown, because widgets are automatically unparented and collected, but if you used setup to allocate some resources bound to a widget that are not row-related, then you should free those resources inside teardown.

I have no idea what a “second index” is. Every column has its own factory, and every factory has its own view of the model, limited to the data you want to show into each cell.

The gtk4-demo demo application has multiple examples of list views, column views, and grid views that you can use.

The API reference has a section on list widgets, the high level overview, and corresponding concepts for migrating from GtkTreeView.

The way the API works is that you create a GObject type that represents the whole of a row data

I was trying to insert 1×1 dimensional objects into a r×c dimensional GListStore. You then need a second index to retrieve items from the GListStore from within the r×c calls to the GtkSignalListItemFactory::setup or ::bind signal handler.

You propose inserting 1×c dimensional objects into a r×1 dimensional GListStore. There is no need for a second index, because there are r×1 calls to the ::setup or ::bind signal, each with direct access to a 1×c dimensional object.

I see the difference.

Then the other thing:

I’ve managed to initialize any GValue with either a string or a double (G_VALUE_INIT is undocumented) and to install additional properties onto the GtkColumnViewRow, but as I allocate a new GtkColumnViewRow with g_object_new and try to assign values to the newly installed properties, it says:

../gtk/gtkcolumnviewrow.c:159: invalid property id 8 for "C00" of type 'GParamString' in 'GtkColumnViewRow'
../gtk/gtkcolumnviewrow.c:159: invalid property id 9 for "C01" of type 'GParamDouble' in 'GtkColumnViewRow'

Can exiting GObjects be adapted for storing column data or do I really need to define a new type of GObject for storing column data? Can I do that with G_DEFINE_TYPE? I see that is not that easy either.

No need to use GVariants.

Ideally you create a new custom GObject representing a row, with one property per column.

A good example is “List > Weather” in the gtk4-demo:
There is a new GObject type GtkWeatherInfo with timestamp, temperature, weather_type private properties, that are used to fill the GtkListItem in the ::bind callback.

I overlooked the example earlier, because it makes use of GtkWidget instead of GtkColumnView, but with the help of listview_ucd.c I got it to work,

using properties to store the state and notify of changes

with variables to store the state for the time being.

Thank you for your help!

1 Like

I have no idea what a “second index” is.

This is the ::bind handler of column #03:

void                gtk_signal_list_item_factory_03_on_bind           (GtkSignalListItemFactory* gtk_signal_list_item_factory_03, GObject* object, gpointer user_data)
          GtkListItem*                  gtk_list_item                         = (GtkListItem*)                          object;

          GtkTableRow*                  gtk_table_row                         = (GtkTableRow*)                          gtk_list_item_get_item                  (gtk_list_item);
          GtkLabel*                     gtk_label                             = (GtkLabel*)                             gtk_list_item_get_child                 (gtk_list_item);

          char                          gtk_label_str[sizeof("+X.XXf")];                                                sprintf                                 (gtk_label_str, "%+.2ff", gtk_table_row_get_values(gtk_table_row)[0x03]);
                                                                                                                        gtk_label_set_text                      (gtk_label, gtk_label_str);

I now have to write a ::bind handler for each column. If I had a function like:

guint*                        gtk_list_item_position                = (guint*)                                gtk_list_item_get_position              (gtk_list_item);              // solution: 2D position

or if it had returned to column number instead of the row number, that would not have been necessary.

This topic was automatically closed 14 days after the last reply. New replies are no longer allowed.