Gtk::TreeStore#model returns the C pointer instead of Crystal wrapper
hugopl opened this issue · comments
This may be related to the last fixes on signals, this example shows that the first signal parameter is a union type instead of a Crystal gobject wrapper.
require "gobject/gtk/autorun"
builder = Gtk::Builder.new_from_file("#{__DIR__}/../lib/gobject/samples/gtk_tree_view.glade")
builder.connect_signals
# Insert something into the model
model = Gtk::TreeStore.cast(builder["tree_model"])
root = Gtk::TreeIter.new
model.append(root, nil)
model.set(root, [0], GObject::Value.new("Root"), 1)
# view
view = Gtk::TreeView.cast(builder["tree_view"])
view.on_row_activated do |view, path, column|
model = view.model.not_nil!
puts "model type: #{typeof(model)}"
puts "path type: #{typeof(path)}"
puts "column type: #{typeof(column)}"
if model.is_a?(Gtk::TreeStore)
puts "Crystal friendly object"
elsif model.is_a?(Pointer(LibGtk::TreeModel))
puts "Got the C pointer!?"
else
abort("caos")
end
end
# Show main view.
main_window = Gtk::Window.cast(builder["main_window"])
main_window.show_all
Output here after I double click in the tree view row:
model type: (Gtk::TreeStore | Pointer(LibGtk::TreeModel))
path type: Gtk::TreePath
column type: Gtk::TreeViewColumn
Got the C pointer!?
Tested on archlinux, crystal 0.34, crystal-gobject at 4f1e6c6.
Ooops, I made a confusion... the signals seems ok, the problem is with view.model return type. sorry, should I close this bug and create another one?
It's fine, maybe just retitle it :)
Soo... returning a wrapper for interfaces, which Gtk::TreeModel
is one, simply wasn't implemented yet :D
The little bit weird typeof
result probably is a type interference bug (or maybe not since the block is captured?) caused by reusing the model
variable in the block. typeof(view.model)
showed just the pointer type and Nil
.
nice! great work!
I'm doing a pet project in Crystal/GTK, so I may submit more issues as I found.
Also... should I submit PRs "Crystalyzing" some APIs (as I need them for my pet project :-P)? Since the GTK API is too verbose due to C nature itself, and we don't need to repeat this verbosity.
Also... should I submit PRs "Crystalyzing" some APIs (as I need them for my pet project :-P)? Since the GTK API is too verbose due to C nature itself, and we don't need to repeat this verbosity.
Yes, definitely. I started this project because I wanted a libnotify binding, so for that I already did that. Just put them under src/gtk
(or whatever the respective library) for now. Eventually when they're big enough they should move into their own shard of course.
If you recognize any patterns, it's also totally a possibility to try to handle them in the generator. Like it already replaces get_foo
with just foo
and set_foo
with just the self arg and one paramater with foo=
.
cool, I'm currently doing these "crystalization" in my project itself by re-opening the classes, once I feel they are ok I submit a PR or a issue describing a pattern.
First thing I think is about to replace GValue by a Union type, I remember when I was working on PySide (Python-Qt bindings) and one of the goals was to make QVariant (Qt's GValue) transparent to users and the result was nice, however I still need to gather a bit more expertise on GTK to analyse the side effects of such suggestion.
The GValue
implementation certainly is a bit wonky still, largely because there are things I don't understand about it. Like is INT
always 32bit or platform dependent? What's the difference between INTERFACE
and OBJECT
? Can we always just use POINTER
and store an opaque one for reference types? Etc.
Alright, I spend some time improving GObejct::Value
. It now acts as union wrapper in the vein of JSON::Any
/YAML::Any
. It's still not handling 100% of the possible values, mainly because I'm pretty clueless on boxed
, variant
, param
and interface
.
I also made the generator detect a single GValue
out parameter and have it return a GObject::Value
instead. Along the way most wrapper arguments gained type restrictions.
Awesome!
I think a similar pattern could be done with Gtk::TreeIter
, it's mostly used as a out parameter. However in the case of Gtk::TreeIter
would be nice to keep the C-like versions using out parameters available just in case people want to re-use the Gtk::TreeIter
while appending hundred of rows to a model to avoid some allocations.
in my pet project I do things like:
module Gtk
class TreeView
def value(path : TreePath, column : Int32) : GObject::Value
view_model = model.not_nil!
iter = Gtk::TreeIter.new
view_model.iter(iter, path)
value = GObject::Value.new
view_model.value(iter, column, value)
value
end
end
end
to to simplify things, and a similar approach for ListStore#append
.
OTOH there's no much Gtk::TreeIter
use cases, and it's not too generic/wide used as GValue, so I would be in doubt about put such behavior in the generator or let all this be hand-made API modifications.
OTOH there's no much Gtk::TreeIter use cases, and it's not too generic/wide used as GValue, so I would be in doubt about put such behavior in the generator or let all this be hand-made API modifications.
Yes exactly. I think a handmade API would be more appropriate here, possibly using macros to iterate through the generated methods or keep the boring part down otherwise.
In other news master
cleans up the value : Enumerbale, n_values : Int
style APIs now to just compute n_values
in the wrapper. I figured out that'll be a generic enough pattern to be worth it.