Skip to content
New issue

Have a question about this project? # for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “#”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? # to your account

Need same cast helper as stringObject() for FileInfo #135

Open
gavr123456789 opened this issue Jun 4, 2021 · 8 comments
Open

Need same cast helper as stringObject() for FileInfo #135

gavr123456789 opened this issue Jun 4, 2021 · 8 comments

Comments

@gavr123456789
Copy link

gavr123456789 commented Jun 4, 2021

import gintro/[gtk4, gobject, gio]
import std/with

proc getFileName(info: gio.FileInfo): string =
  return info.getName()  

proc setup_cb(factory: gtk4.SignalListItemFactory, listitem: gtk4.ListItem) =
  listitem.setChild(newLabel(""))
  
proc bind_cb(factory: gtk4.SignalListItemFactory, listitem: gtk4.ListItem) =
  let 
    lb = listitem.getChild().Label
    strobj = cast[FileInfo](listitem.getItem())

  lb.text = strobj.getFileName()

proc unbind_cb(factory: gtk4.SignalListItemFactory, listitem: gtk4.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. 
  echo "unbind"

proc teardown_cb(factory: gtk4.SignalListItemFactory, listitem: gtk4.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. 

proc activate(app: gtk4.Application) =
  let
    window = newApplicationWindow(app)
    scr = newScrolledWindow()
    file = gio.newGFileForPath(".")
    sl = gtk4.newDirectoryList("standard::name", file)
    ls = 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:
    defaultSize = (600, 400)
    title = "Nim ListView"
    setChild scr
    show

proc main =
  let app = newApplication("org.gtk.example")
  app.connect("activate", activate)
  discard run(app)

main()
@StefanSalewski
Copy link
Owner

I was just going to add your requested converter proc, but I noticed that your example code crash when compiled with --gc:arc.

Does it crash for you also, and do you have an idea about the reason already?

Yesterday I discovered another bug myself, see #137

So I think I will call the current version at github 0.90 for now and then try to fix bug #137.

In the last week I spent a lot of time with the listview_clocks example requested by aeldemery.

That example is really low level and too hard for pure Nim currently, but mixing C and Nim code works not that bad, so I got it working. But while playing with it I noticed another issue for the "transfer full" case of proc arguments. An example is

  expression = gtk_property_expression_new (GTK_TYPE_CLOCK,
                                            gtk_expression_ref (clock_expression),
                                            "location");

from listview_clocks.c.

Here the clock expression is a "transfer full" parameter, which is used later in the proc again. So detaching it from the Nim GC with .ignoreFinalizer = true is not the best solution here, we should better call gtk_expression_ref() on the gtk object. I will try that for version 0.91 then.

Another interesting problem is

discard gtk4.bind(expression, location_label, "label", location_label)

Would compile fine without the gtk4. prefix, just using Nim's own bind keyword. But is not working then of course. Took me nearly a full day to find that. I regard that a Nim bug, but I guess reporting to Nim's issue tracker will not help, they will tell us that we should know what we are doing.

@gavr123456789
Copy link
Author

Does it crash for you also, and do you have an idea about the reason already?

Yes, I think this is exactly #137

Traceback (most recent call last)
/home/gavr/Projects/Nim/gintro/examples/gtk4/directory_list.nim(59) directory_list
/home/gavr/Projects/Nim/gintro/examples/gtk4/directory_list.nim(57) main
/home/gavr/.nimble/pkgs/gintro-#head/gintro/gio.nim(31021) run
/usr/lib/nim/core/macros.nim(565) connect_for_signal_cdecl_bind2
/home/gavr/Projects/Nim/gintro/examples/gtk4/directory_list.nim(13) bind_cb
/home/gavr/.nimble/pkgs/gintro-#head/gintro/gtk4.nim(49244) getItem
/usr/lib/nim/system/arc.nim(84) nimNewObj
/usr/lib/nim/system/alloc.nim(958) alloc0
SIGSEGV: Illegal storage access. (Attempt to read from nil?)
Error: execution of an external program failed: '/home/gavr/Projects/Nim/gintro/examples/gtk4/directory_list 

@StefanSalewski
Copy link
Owner

OK, following the discussion from

https://discourse.gnome.org/t/get-ref-function-for-none-gobject-classes-like-gtkexpression/6696

with nimble install gintro@#head

your example above should work now. We have also added the fileInfo() converter proc.

  strobj = fileInfo(listitem.getItem())

The existing examples seems to compile still and at least some work, but I have not tested all yet. The Gtk4 fontchooser example fails currently, but that may be due to a change in GTK4 itself.

The listview_clock example works now also, I have split it in a low level C part and a Nim part. That splitting works not bad. I will ship the code soon.

@gavr123456789
Copy link
Author

@StefanSalewski With new version I have error:
/home/gavr/.nimble/pkgs/gintro-#head/gintro/adw.nim(1796, 43) Error: undeclared identifier: 'gtk_expression_ref'
When compile any adwaita example with any GC.

@StefanSalewski
Copy link
Owner

We missed that because we have currently no working adwaita example.

proc getExpression*(self: ComboRow): gtk4.Expression =
  let impl0 = adw_combo_row_get_expression(cast[ptr ComboRow00](self.impl))
  if impl0.isNil:
    return nil
  fnew(result, generic_gtk_expression_unref)
  result.impl = cast[typeof(result.impl)](gtk_expression_ref(impl0))

proc expression*(self: ComboRow): gtk4.Expression =
  let impl0 = adw_combo_row_get_expression(cast[ptr ComboRow00](self.impl))
  if impl0.isNil:
    return nil
  fnew(result, generic_gtk_expression_unref)
  result.impl = cast[typeof(result.impl)](gtk_expression_ref(impl0))

We intentionally do not export gtk_expression_ref() because people shall not use it directly. But as adw.nim needs it we have to export it. So add an export marker to

grep "proc gtk_expression_ref" ~/.nimble/pkgs/gintro-#head/gintro/gtk4.nim 
proc gtk_expression_ref(self: ptr Expression00): ptr Expression00 {.

manually for now. I will fix that soon.

@gavr123456789
Copy link
Author

I have Adwaita examples in my PR

@StefanSalewski
Copy link
Owner

Sorry, please stop further testing for now, we have stupid bugs like

proc getFontDesc*(self: FontChooser | FontChooserWidget | FontChooserDialog | FontButton): pango.FontDescription =
  let impl0 = gtk_font_chooser_get_font_desc(cast[ptr FontChooser00](self.impl))
  if impl0.isNil:
    return nil
  fnew(result, gBoxedFreePangoFontDescription)

Will try to fix it soon, should be easy.

@StefanSalewski
Copy link
Owner

Should be fixed. Fontchooser works, and all including adw.nim compiles. Will do more serious tests soon.

# for free to join this conversation on GitHub. Already have an account? # to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants