gotk4 icon indicating copy to clipboard operation
gotk4 copied to clipboard

How to use GTK 4 GridView with gio.ListStore and gtk.BuilderListItemFactory

Open coderkun opened this issue 1 year ago • 2 comments

I want to use the GTK 4 GridView with a gio.ListStore and a BuilderListItemFactory but cannot figure out how to add an item.

This is my test code:

package main

import (
	"os"

	coreglib "github.com/diamondburned/gotk4/pkg/core/glib"
	"github.com/diamondburned/gotk4/pkg/gio/v2"
	"github.com/diamondburned/gotk4/pkg/glib/v2"
	"github.com/diamondburned/gotk4/pkg/gtk/v4"
)

var factoryXML = `<?xml version='1.0' encoding='UTF-8'?>
<interface>
    <template class="GtkListItem">
        <property name="child">
            <object class="GtkLabel">
                <property name="xalign">0</property>
                <property name="label">Test</property>
                <binding name="label">
                    <lookup name="label">
                        <lookup name="item">GtkListItem</lookup>
                    </lookup>
                </binding>
            </object>
        </property>
    </template>
</interface>`

type Item struct {
	*coreglib.Object
	Label string
}

func main() {
	app := gtk.NewApplication("test.test", gio.ApplicationFlagsNone)
	app.ConnectActivate(func() { activate(app) })

	if code := app.Run(os.Args); code > 0 {
		os.Exit(int(code))
	}
}

func activate(app *gtk.Application) {
	store := gio.NewListStore(coreglib.TypeObject)
	selection := gtk.NewMultiSelection(store)
	factory := &gtk.NewBuilderListItemFactoryFromBytes(gtk.NewBuilderCScope(), glib.NewBytes([]byte(factoryXML))).ListItemFactory
	gridview := gtk.NewGridView(selection, factory)

	item := &Item{
		Label: "Test 1",
	}
	store.Append(item.Object)

	window := gtk.NewWindow()
	window.SetTitle("GridView Test")
	window.SetChild(gridview)
	app.AddWindow(window)
	window.Show()
}

This code panics. I guess I am creating the item incorrectly. Or do I have to define my own coreglib.Type like in the GTK C demo?

Any help would be much appreciated. If we can make this work, I will submit a PR to add an example for the GridView. Thanks a lot.

coderkun avatar Nov 12 '23 12:11 coderkun

This isn't really an answer, because I'm only currently working with strings, but I'm going through a similar process of trying to get model binding working with the dynamic GTK4 gridviews. In case it's helpful, I've got a version of your code working using a backing gtk.StringList, rather than the gio.ListStore:

Rather than calling gio.NewListStore and then appending an item to it, I create a StringList with:

store := gtk.NewStringList([]string{"Test 1", "Test 2"})

and then the only other relevant change is the data binding, so replacing <lookup name="label"> with <lookup name="string" type="GtkStringObject">.

After that, I get a view that shows two text labels as expected ("Test 1" and "Test 2").

I'll also need to build a more complex / custom data model, so I'll keep working on this, too.

nsw42 avatar Feb 24 '24 17:02 nsw42

You can't create an object like that. gotk4 unfortunately doesn't support subclassing.

You could try to use gioutil.ListModel[T].

diamondburned avatar Feb 25 '24 01:02 diamondburned