Open gavr123456789 opened 3 years ago
Wait, no, this is even more strange.
Label -> Widget
StringObject -> Object
Upcast of Widget to Label works with 'smart' upcast with .Label
Upcast of Object to StringObject throw exeption and works only with unsafe C 'up'cast
.
This version can compiles:
import gintro/[gtk4, gobject, gio]
import std/with
proc setup_cb(factory: gtk4.SignalListItemFactory, listitem: gtk4.ListItem) =
listitem.setChild(newLabel(""))
proc bind_cb(factory: gtk4.SignalListItemFactory, listitem: gtk4.ListItem) =
var
lb = listitem.getChild().Label
strobj = cast[StringObject](listitem.getItem())
txt = gtk4.getString(strobj)
echo txt
lb.text = txt
proc unbind_cb(factory: gtk4.SignalListItemFactory, listitem: gtk4.ListItem) =
echo "unbind"
proc teardown_cb(factory: gtk4.SignalListItemFactory, listitem: gtk4.ListItem) =
listitem.setChild (nil)
proc activate(app: gtk4.Application) =
let
window = newApplicationWindow(app)
scr = newScrolledWindow()
var
sl = gtk4.newStringList("one", "two", "three", "four")
ls = cast[ListModel](sl)
ns = gtk4.newNoSelection(ls)
factory = gtk4.newSignalListItemFactory()
lv = newListView(ns, factory)
scr.setChild lv
with factory:
connect("setup", setup_cb)
connect("bind", bind_cb)
connect("unbind", unbind_cb)
connect("teardown", teardown_cb)
with window:
title = "Nim ListView"
setChild scr
show
proc main =
let app = newApplication("org.gtk.example")
app.connect("activate", activate)
discard run(app)
main()
Thanks for reporting, I will try to investigate that issue soon.
Have you a working C code example? Starting from working C code is always the best way to debug. All the listview/treeview stuff is by far the hardest in GTK. In C code a lot of casts are performed, in Nim we should never use direct casts but provide converters or something similar. I really should read the Krause book again and all the tutorials. Well I will see if I can discover the problem.
@StefanSalewski yea, this is first example from here https://github.com/ToshioCP/Gtk4-tutorial/blob/main/gfm/sec24.md
Thanks, that will make debugging much easier.
OK, I have compiled and run his C example. But there is only a block of text displayed, really not that interesting.
I started with his C code and converted it to Nim, see below. Works, but we need two ugly casts indeed. getItem() returns a plain GObject, but we need a StringObject. And the other is StringList to StringModel. With getChild() and Label a conversion works because both are Widgets.
For fixing all this as clean as possible we have to learn the API well and then we can see if we can somehow introduce automatic conversions or give the user type safe converters. I think a few are already available. But all that is a task for maybe 6 weeks fulltime: Learning, writing documentation (the GTK4 book, I guess 50 pages), testing and providing converters when necessary. As long as we have zero users (well one with you) my motivation for that is not that large. Maybe just tell the figma guy what you did with ValaGtk and ask him how you can do that with figma. Maybe we should indeed switch to fidget? In another thread they recently promoted flutter.
Yesterday I got a request from Japan from someone who wants to translate the Nim Beginner book to Japanese, so I think I will try to add a few more pages to the book now. And I want to do some GTK programming myself again, have done nothing in the last years.
import gintro/[gtk4, gobject, gio]
proc setup_cb(factory: SignalListItemFactory; listitem: ListItem) =
let lb = newLabel()
listitem.setChild(lb)
proc bind_cb(self: SignalListItemFactory; listitem: ListItem) =
let lb: Label = Label(listItem.getChild)
let strobj: StringObject = cast[StringObject](listItem.getItem)
let text = strobj.getString
lb.setText(text)
proc unbind_cb(self: SignalListItemFactory; listitem: ListItem) =
# There's nothing to do here.
# If you does something like setting a signal in bind_cb,
# then disconnecting the signal is necessary in unbind_cb.
discard
proc teardown_cb(factory: SignalListItemFactory; listitem: ListItem) =
listitem.setChild (nil)
# When the child of listitem is set to NULL, the reference to GtkLabel will be released and lb will be destroyed.
# Therefore, g_object_unref () for the GtkLabel object doesn't need in the user code.
# ----- activate, open, startup handlers -----
proc app_activate(app: Application) =
echo "activate"
let win = newApplicationWindow(app)
win.setDefaultSize(600, 400)
let scr = newScrolledWindow()
win.setChild (scr)
let arrax = ["one", "two", "three", "four"]
let sl: gio.ListModel = cast[ListModel](newStringList(arrax)) # GtkStringList — A list model for strings
let ns: NoSElection = newNoSelection(sl) # A selection model that does not allow selecting anything
let factory: SignalListItemFactory = newSignalListItemFactory()
factory.connect("setup", setup_cb)
factory.connect("bind", bind_cb)
factory.connect("unbind", unbind_cb)
factory.connect("teardown", teardown_cb)
let lv = newListView(ns, factory)
scr.setChild (lv)
win.show
proc app_startup(app: Application) =
echo "startup"
proc main =
let app = newApplication("org.gtk.example") # "com.github.ToshioCP.list1"
app.connect("startup", app_startup)
app.connect("activate", app_activate)
let status = app.run
quit(status)
main()
Heh, looks like you got the same program with same 2 C cast.
I think this problem can be solved with new concepts https://github.com/StefanSalewski/gintro/issues/130 when they will come out
listitem.getItem()
returns ObjectStringObject is
ref object of gobject.Object
So it looks like Nim is missing UpCast? Or am I misunderstanding something.
Googling nim upcast get nothing.
Error: