Hello, GTK4,
I’m writing a program which will display a table of data, and I’m trying to use GtkColumnView, since it’s the latest (and only non-deprecated) interface for this. I’ve been digging into the documentation, and the source code, and forums on the web, and still struggling to figure out how to implement the basic features of a table.
For starters, I want to create a context menu when the user right-clicks on a row. (With GtkTreeView in GTK3, I recall this was fairly straightforward.) I haven’t found any sample code which demonstrates this for GTK4, and I haven’t found any documentation which directly says how to do this. Some commenters in GitLab bug reports hint that it’s actually easy, without ever saying how to do it.
Idea 1: It’s possible to add a gesture listener to the entire ColumnView, but this overrides the header context menus, and there’s no way to map an (x,y) position to a row, so there’s no way to provide an appropriate menu for this context. (There’s also no way to tell the size/position of the header, so I don’t see how to avoid that case, either.) Apparently that omission is intentional, for reasons that I don’t understand: Add method get_child_at_pos for ListBase widget and ColumnView widget (#4992) · Issues · GNOME / gtk · GitLab
Idea 2: Comments in the above bug report say things like “use gestures and event controllers on the row child” and “[ListView/ColumnView/GridView] use real widgets for rows”. The only documented “row” abstraction I found for GtkColumnView is GtkColumnViewRow, which isn’t a GtkWidget, and doesn’t have any functionality related to events or menus. It’s also a new interface in GTK 4.12, which hasn’t been released yet. What exactly do they mean by “The rows are their own widgets and can react to input on their own”? What widget is this, and how do you access it to add an event listener?
Idea 3: It’s true that individual cells of a GtkColumnView are GtkWidgets, so I can add a gesture listener to each cell of a row. Unfortunately, GtkColumnView seems to put a large margin around cells, so this means there are big dead areas in each row where user right-clicks don’t do anything. Users definitely won’t expect to have to avoid clicking on certain invisible parts of a row. I don’t see any way to shrink these margins to zero, either (nor would I necessarily want to, for visual reasons).
Idea 4: I found that there is a private/undocumented row abstraction (“ListItemWidget”) in the current implementation. Unfortunately, I don’t see any way to tell when that object is instantiated. There are ‘map’/‘unmap’ signals for cells (since they’re GtkWidgets), so I think in theory it’s possible to catch when cells are built, and then walk up the hierarchy to their row widget, and add an event listener to the whole row. Then you’d need to have some sort of interlock because each cell will add an event listener to their common row, but only one handler should ever respond to an event in that row. And when rows are ‘unmapped’, you’d need to remove only the listener that it added. This seemed feasible (if rather complex), but I’ve been fighting with it for a few days and I just can’t get it to work.
I’m totally lost here. I must be missing something obvious. What’s the intended way to add a context menu to a row of a GtkColumnView? Am I even close? If one of these is the right track, I can post sample code so you can point out where I went wrong.
Thanks.