New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
TreeSelection getSelected + iterNext is broken #180
Comments
Thanks for reporting, I will try to investigate that issue soon. v0.9.4 may have intraduced some changes maybe. Listview and treeview is always a bit fragile, first examples contained some casts, which is not really good. I learned about the listview stuff more than ten years ago from the book of A. Krause, but forgot most. That is the reason that my GTK4 book contains still no listview and treeview stuff, maybe I will manage to add that in the coming winter. |
Do you really think that your code has worked before: proc selectNext() =
var iter: TreeIter
var store: ListStore = listStore(list.getModel())
if not list.selection.getSelected(store, iter):
return
if store.iterNext(iter): # line 24 with crash
list.selection.selectIter(iter)
list.scrollToCell(store.getPath(iter), nil, false, 0.0, 0.0) Can iterNext() really work when iter is still uninitialled? Well, I would guess it can default to the first element of the store, but I would not rely on it, Will see if there is something like iterFirst(). Or have you seen C code where gtk_tree_model_iter_next() is used in that way? References: |
OK, that seems not to be the core bug, as store is already nil. Have to investigate further. |
proc getSelected*(self: TreeSelection; model: var (TreeModel | TreeModelSort | ListStore | TreeModelFilter | TreeStore) = cast[var TreeModel](nil);
iter: var TreeIter = cast[var TreeIter](nil)): bool =
var tmpoutgobjectarg: ptr TreeModel00
result = toBool(gtk_tree_selection_get_selected(cast[ptr TreeSelection00](self.impl), cast[var ptr TreeModel00](if addr(model) == nil: nil else: tmpoutgobjectarg), iter))
# dothemagic(model
if addr(model) != nil:
model = nil
if tmpoutgobjectarg != nil:
let argqdata = g_object_get_qdata(tmpoutgobjectarg, Quark)
if argqdata != nil:
model = cast[type(model)](argqdata)
assert(model.impl == tmpoutgobjectarg)
else:
fnew(model, gtk.finalizeGObject)
model.impl = tmpoutgobjectarg
GC_ref(model)
if g_object_is_floating(model.impl).int != 0:
discard g_object_ref_sink(model.impl)
g_object_add_toggle_ref(model.impl, toggleNotify, addr(model[]))
g_object_unref(model.impl)
assert(g_object_get_qdata(model.impl, Quark) == nil)
g_object_set_qdata(model.impl, Quark, addr(model[])) That proc is the problem, that proc has changed in the last 18 months. Sets store to nil, which maybe it should not do. Is is a complicated proc, as it has a var gobject parameter. I may have to fix it? Maybe you just use it in a wrong way, it is not that easy. https://docs.gtk.org/gtk3/method.TreeSelection.get_selected.html |
Ok, I just read the documentation. I should have do this earlier (sorry to waste your time), but didn't expect that it also sets the model/store. It's the first time a gtk function modifies it (since I'm using gtk).
I did, you're right. How to use it correctly for my case: if not list.selection.getSelected(cast[var TreeModel](nil), iter):
return
It worked before. I never touched this line for 2 years. For me it looks like it was a bug in gintro, but is solved now (I'm not sure). Thanks again for your help and keeping this project alive. |
I am not really sure. Seems that you have found a way to avoid that issue, but I will investigate that proc in more detail later. Just wrote an issue to gnome forum, new API docs are not that great: https://discourse.gnome.org/t/new-api-docs-and-gtk-tree-selection-get-selected/7667 Will investigate later... |
Regarding to this phrase in documentation:
You can set the treeview to single select or multi select (rows). If set to multiple selection, then the function cannot set the iter for the current selection, since there may be more rows selected. |
It seems that gtk_tree_selection_get_selected() call in the bindings set the passed tmpoutgobjectarg argument not to a valid value, but to nil. So it is indeed not an obvious bindings bug, but more GTK related. But from API docs I would expect that function to set tmpoutgobjectarg to a valid none nil value when return value is true. |
It is a Nim issue. The cast[var ptr TreeModel00] does not work as expected with the recent Nim compiler version. I guess I have to consult the Nim devs. |
Regarding to Nim version, I'm still on version 1.4.x, but also upgraded from 1.4.8 to 1.4.9.
|
Thanks for reporting your Nim version, I had some hope that 1.4.x versions would work at least still. Have just created a minimal example for the Nim compiler issue, see So maybe it will be fixed. If they should refuse to fix, a larger gintro modification will be necessary. |
Should be fixed now. The fix is indeed tiny:
and indeed at some locations in the gen.nim files code of that shape was used already before. But it is a bit strange still, and it is hard to remember how it has to look. Your initial program seems to compile and work now. Below is a modified version. I have added to gintro a typeCheckInstanceIsA() overload for Gobject parameter, which simplifies low level type checks. Initial parameter was only TypeInstance, which is useless. But then I found out that we do not need proc listStore() for type conversion, as Nim type test with (o of gtk.ListStore) and type conversion with gtk.ListStore(o) works. So we can use ListStore(gobject.Object(list.getModel)) Unfortunately a getSelected() with named parameters using the nil default for model does not compile, the problem may be overload resolution for that case. So we have to pass a casted nil or we have to pass an actual model. import gintro/[glib, gobject, gtk]
import gintro/gio except ListStore
const
LIST_ITEM = 0
N_COLUMNS = 1
var list: TreeView
# As the safe type conversion works in our case, we do not need this proc at all
proc listStore(o: gobject.Object): gtk.ListStore =
assert(typeCheckInstanceIsA((o), gtkListStoreGetType())) # low level gobject test
assert(typeCheckInstanceIsA((o), g_type_from_name("GtkListStore"))) # same
assert(o of gtk.ListStore) # test if the Nim proxy objects match
return gtk.ListStore(o) # in this case we can do a safe Nim type conversion
#assert(typeTest(o, "GtkListStore"))
#cast[gtk.ListStore](o)
proc selectNext() =
var iter: TreeIter
var store: ListStore = ListStore(gobject.Object(list.getModel)) # listStore(list.getModel()
#if not getSelected(self = list.getSelection, model = cast[var ListStore](nil), iter = iter): # nil default for model does not work, problem is overload resolution
if not list.selection.getSelected(store, iter):
return
if store.iterNext(iter):
list.selection.selectIter(iter)
list.scrollToCell(store.getPath(iter), nil, false, 0.0, 0.0)
proc initList(list: TreeView) =
let renderer = newCellRendererText()
let column = newTreeViewColumn()
column.title = "List Item"
column.packStart(renderer, true)
column.addAttribute(renderer, "text", LIST_ITEM)
discard list.appendColumn(column)
let gtype = gStringGetType() # typeFromName("gchararray")
let store = newListStore(N_COLUMNS, cast[ptr GType](unsafeaddr gtype)) # cast due to bug in gtk.nim, we really should fix that!
list.setModel(store)
proc activate(app: Application) =
let
window = newApplicationWindow(app)
sw = newScrolledWindow()
window.title = "List view"
window.position = WindowPosition.center
window.borderWidth = 10
window.setSizeRequest(370, 270)
list = newTreeView()
sw.add(list)
sw.setPolicy(PolicyType.automatic, PolicyType.automatic)
sw.setShadowType(ShadowType.etchedIn)
list.setHeadersVisible(false)
window.add(sw)
initList(list)
var val: Value
var iter: TreeIter
let store = ListStore(gobject.Object(list.getModel)) # listStore(getModel(list))
let gtype = gStringGetType()
discard init(val, gtype)
for idx in 0 .. 10:
setString(val, $idx)
store.append(iter)
store.setValue(iter, LIST_ITEM, val)
if idx == 0:
list.selection.selectIter(iter)
window.showAll
selectNext()
proc main =
let app = newApplication("org.gtk.example")
app.connect("activate", activate)
discard run(app)
main() |
Sorry for the late response. Thanks for the type conversion info, I'll change it in my application. Thanks for your work. |
Hi,
It looks like, the gtk (+ dependency) update broke some more, but I'm not sure, since I didn't test this for a while. In my last stable version of my software it still works (didn't recompile the old version).
In following example I used a modified version of your listview example. Adding 10 rows, selecting the first row (index 0), calling
getSelected
with TreeSelection and then callingiterNext
.Example code:
Expected behavior:
It should select the second line of treeview.
Exception:
The text was updated successfully, but these errors were encountered: