guile-gi
guile-gi copied to clipboard
Support (Gtk) tree-store:*
It would be nice if GtkTreeStore worked.
Current situation:
(use-modules (system foreign))
(load-by-name "Gtk" "TreeStore")
(tree-store:new 1 long)
(process:32652): GuileGI-ERROR **: 10:35:18.655: unhandled argument type 'pointer to GArray of type GBoxed' src/gig_argument.c:555
Gtk+ version is gtk+ 3.24.20.
gir is:
<class name="TreeStore"
c:symbol-prefix="tree_store"
c:type="GtkTreeStore"
parent="GObject.Object"
glib:type-name="GtkTreeStore"
glib:get-type="gtk_tree_store_get_type"
glib:type-struct="TreeStoreClass">
<source-position filename="gtktreestore.h" line="61"/>
<implements name="Buildable"/>
<implements name="TreeDragDest"/>
<implements name="TreeDragSource"/>
<implements name="TreeModel"/>
<implements name="TreeSortable"/>
<constructor name="new"
c:identifier="gtk_tree_store_new"
shadowed-by="newv"
introspectable="0">
...
</constructor>
<constructor name="newv"
c:identifier="gtk_tree_store_newv"
shadows="new">
<source-position filename="gtktreestore.h" line="70"/>
<return-value transfer-ownership="full">
<doc xml:space="preserve"
filename="gtktreestore.c"
line="355">a new #GtkTreeStore</doc>
<type name="TreeStore" c:type="GtkTreeStore*"/>
</return-value>
<parameters>
<parameter name="n_columns" transfer-ownership="none">
<doc xml:space="preserve"
filename="gtktreestore.c"
line="350">number of columns in the tree store</doc>
<type name="gint" c:type="gint"/>
</parameter>
<parameter name="types" transfer-ownership="none">
<doc xml:space="preserve"
filename="gtktreestore.c"
line="351">an array of #GType types for the columns, from first to last</doc>
<array length="0" zero-terminated="0" c:type="GType*">
<type name="GType" c:type="GType"/>
</array>
</parameter>
</parameters>
</constructor>
<method name="append" c:identifier="gtk_tree_store_append">
<source-position filename="gtktreestore.h" line="135"/>
<return-value transfer-ownership="none">
<type name="none" c:type="void"/>
</return-value>
<parameters>
<instance-parameter name="tree_store" transfer-ownership="none">
<doc xml:space="preserve"
filename="gtktreestore.c"
line="1718">A #GtkTreeStore</doc>
<type name="TreeStore" c:type="GtkTreeStore*"/>
</instance-parameter>
<parameter name="iter"
direction="out"
caller-allocates="1"
transfer-ownership="none">
<doc xml:space="preserve"
filename="gtktreestore.c"
line="1719">An unset #GtkTreeIter to set to the appended row</doc>
<type name="TreeIter" c:type="GtkTreeIter*"/>
</parameter>
<parameter name="parent"
transfer-ownership="none"
nullable="1"
allow-none="1">
<doc xml:space="preserve"
filename="gtktreestore.c"
line="1720">A valid #GtkTreeIter, or %NULL</doc>
<type name="TreeIter" c:type="GtkTreeIter*"/>
</parameter>
</parameters>
</method>
[...]
</class>
Thanks for the report. I'll see what I can do.
Added pull request.
In order to test:
(tree-store:new (vector G_TYPE_LONG))
btw: I'm pretty sure that GI said that this function requires two arguments--but it doesn't work if I put two arguments.
Not saying that I want to explicitly specify the number of elements, but it's just something notable.
After that, tree-store:append!
needs an (possibly) uninitialized allocated GtkTreeIter
. How do I get one? I found tree-iter:copy
and tree-iter:free
(the latter has no exclamation mark O_o), but both don't help me here...
What does exist: (make <GtkTreeIter>)
, and it does something.
But when I do (tree-view:set-model tree-view tree-store)
, I get:
(tree1.scm:16667): GuileGI-ERROR **: 19:28:45.219: unhandled argument type 'pointer to GtkTreeModel of type GInterface or NULL' src/gig_argument.c:250
That's because scm_to_c_interface
is not implemented yet.
It should do something like arg->v_pointer = g_type_check_instance_cast((GTypeInstance*)gig_type_peek_object(object), meta->gtype)
.
I added it to my pull request.
Even though the following functions should have the following prototypes, actually using them as one would in C does not work (oop/goops.scm:1585:2: No applicable method for #<<generic> tree-store:set (1)> in call (tree-store:set #<<GtkTreeStore> 7ffff2d705f0> #<<GtkTreeIter> 7ffff2d704b0> #(0 1) #(42 24) 2)
).
set-value GtkTreeIter, int32, GValue
3 parameters! Second one is passed as GBoxed by the library, and is_raw_array is set.
set GtkTreeIter, ARRAY of int32, ARRAY of GValue, INT32
4 parameters!
iter
columns
values
n_values
I think that might be because the implicit conversion into GValue is not done? If it was done, it would be done using gig_value_from_scm
.
The workaround (define value (make <GValue>))
does not really work. Using (tree-store:set tree-store iter (vector 0 1) (vector value value))
I get: bytevector expected
, because scm_to_c_native_immediate_array always expects bytevector, even for int32 vectors.
Using tree-store:set-value
, I try (define v (make <GValue>)) (set! (value v) 42)
and get In procedure %set: Wrong type argument in position 2: 42
.
For setting values of integer type, perhaps (set! (value G_TYPE_INT) 42)
might work better.
For making typed bytevectors, core Guile provides the family of functions u32vector
as in (u32vector 100 100)
. And also list->u32vector
and friends.
For vectors from C types that may vary between 32-bit and 64-bit platforms (gi util)
provides list->int-vector
and friends.
For tree-store:set
, it is a documentation error that there is a 4th argument n_values
. It should be just iter
, columns
, values
. The n_values
in the C API is computed from the length of the 3rd argument.
Ohhh! Thanks!
The following indeed does work:
(define iter (make <GtkTreeIter>))
(tree-store:append! tree-store iter #f)
(define value (make <GValue>))
(set! (value G_TYPE_INT) 42)
(tree-store:set tree-store iter (u32vector 0 1) (vector value value))
The following doesn't work and doesn't give an error:
(define iter (make <GtkTreeIter>))
(define value (make <GValue> #:type G_TYPE_INT #:value 42))
(tree-store:set tree-store iter (u32vector 0 1) (vector value value))
And I can't for the life of me successfully call tree-store:set-value
, though. Not that important, but ehhh.
Also, G_TYPE_STRING is missing.
Added G_TYPE_STRING
in 3929243ed52c217a23a473d012300e85f414aceb , but I would imagine that @LordYuuma would say that <string>
is more appropriate.
tree-store:set-value
does work; however, in Scheme the API is a bit torturous. See ad02cd82f9ef0677f1365752ea2c97b6a67b5c40
tree-store:set
does also appear to work; however, the Scheme API is also torturous. See c8908fd92e1eaab5959772bfdfd98db299ae0c23
guile-gi
definitely needs more flexible handling of GArray
. Requiring bytevectors is inflexible.
Added
G_TYPE_STRING
in 3929243 , but I would imagine that @LordYuuma would say that<string>
is more appropriate.
Thanks! <string> does indeed work and is nicer! Is there something else in Guile for G_TYPE_INT
, too? I tried (system foreign)'s int, but I guess those are different integers, so that won't work I guess.
There sadly is no scheme equivalent to G_TYPE_INT
, you'll have to use the GLib constants. There is no direct equivalence between numeric C types and the Scheme number tower, see https://github.com/spk121/guile-gi/blob/c8908fd92e1eaab5959772bfdfd98db299ae0c23/src/gig_type.c#L823-L832
Also doesn't work as it should:
(define (install-tree-view-tooltip-handler! tree-view)
(set! (has-tooltip tree-view) #t)
(connect tree-view query-tooltip
(lambda (tree-view x y keyboard-tip tooltip)
(let* ((iter (make <GtkTreeIter>))
(value (make <GValue>)))
(let-values (((on-row? x y model path iter)
(tree-view:get-tooltip-context! tree-view x y keyboard-tip iter)))
(write (tree-model:get-value! model iter 1 value)) ; error message here
(tooltip:set-text tooltip "XXX")
; (tree-view-set-tooltip-row tree-view tooltip path)
on-row?)))))
The model used is a GtkTreeModelSort
.
Error message (when hovering over a row):
ice-9/boot-9.scm:1669:16: In procedure raise-exception:
No applicable method for #<<generic> tree-model:get-value! (1)> in call (tree-model:get-value! #<<GtkTreeModel> 7fc66bb830c0> #<<GtkTreeIter> 7fc66bb83040> 1 #<<GValue> 7fc66bb87100>)
I suspect that's because the returned GtkTreeModel
's actual class is not checked? Or what happens here?
Also, that might be a guile thing, but wouldn't it be possible to, on error messages like "No applicable method", to list all those methods of that generic that are present? I mean it knows those, right? That would help a lot.
You can [roughly] inspect GOOPS methods by doing the following:
(use-modules (ice-9 pretty-print)
(oop goops)
(srfi srfi-1))
(let* ((methods (generic-function-methods YOUR-FUNCTION))
(formals (map method-formals methods))
(specializers (map method-specializers methods)))
(pretty-print (map (lambda (a b) (if (pair? a) (zip a b) (list a b))) formals specializers)))
You might encounter a few issues with improper lists, e.g. (a b . rest)
, but Guile-GI should not produce methods with such specializers anyway.
As for the specific issue with tree-model:get-value!
, please try the following and report the result:
(apply peek 'expected (method-specializers (car (generic-function-methods tree-model:get-value!)))
(apply peek 'actual (map class-of (list model iter 1 value)))
Thanks!
;;; (expected #<<class> <GtkTreeModel> 7f6874446980> #<<class> <GtkTreeIter> 7f6874446080> #<<class> <integer> 7f687631f200> #<<class> <GValue> 7f687445ee00>)
#<<class> <GValue> 7f687445ee00>
;;; (actual #<<class> <GtkTreeModel> 7f6874446980> #<<class> <GtkTreeIter> 7f6874446080> #<<class> <integer> 7f687631f200> #<<applicable-struct-with-setter-class> <GValue> 7f6874396f80>)
#<<applicable-struct-with-setter-class> <GValue> 7f6874396f80>
So maybe that's because I'm mixing high-level and low-level constructs?
I've been trying to use low-level constructs everywhere--but didn't find the one to make a GtkTreeIter
, and neither the one to make a GValue
so far.
Nah, you're not doing anything wrong here. The model iter 1
part of your call matches the expectation. The difference lies in the GValue
parameter. Guile-GI sets up G_TYPE_VALUE
to be an applicable struct with setter, but somehow there exists a separate GValue
class, that is created when the introspection is loaded. I have no idea at all what happens here.
For the record, this is a type of behaviour, that for some weird reason I've only been able to observe in Guix environments. I'm hesitant to call it Guix-specific, but something inside Guix seems to exacerbate it. See https://github.com/spk121/guile-gi/blob/89babf64759be7b700477f9b7fb3a84c5c4731d7/test/marshall.scm#L751-L767
This would probably deserve its own issue somewhere, but I have yet to find out, who is at fault here (us, GI, GLib itself, Guix...)
For what it's worth, the tree-store:set
tests pass inside guix environment
on dev-defer-types, but I have not yet fixed all bugs with that.
tree-model:iter-previous!
and tree-model:iter-next!
seem to be missing, too. Although tree-model:iter-n-children
and tree-model:iter-children!
are present.
How come?
They're iter-previous?
and iter-next?
, see #87.
You should really just peek into the output from load
and load-by-name
from time to time. ;)
tree-model:get!
is missing.
(I'd like to have a method to get the entire tree row at once; get-value!
for each cell does work but is slow)
There is sadly little to be done on our front. get!
is not introspectable (being varargs as you'd expect), and they don't seem to have get-values!
, but that'd be little more than a loop around get-value!
anyway.
It's fine--but I thought I should ask.
GtkTreeView is badly supported in gobject-introspection, which is worrying because you basically need it any time you show a list. I've fixed so many bugs in upstream gtk+ regarding introspection hints by now. (I wonder whether gtk-rs trusts those hints for lifetime tracking, though O_O)
Still, the usual enterprise distros won't have those fixes for years, because they hardly ever update gtk...
Compared to the other stuff, missing get!
is not a bad thing at all :)
Oh well. Thanks for having a look, though!
My personal experience with Gtk/Vala tells me that introspection hints (and vapis) are serious business, so I'd assume some of those bugs make it into Rust. Not that I have too high expectations for Rust anyway.
From what I gather from the developer blogs, list views and models and associated classes are quite different in Gtk4. Perhaps they will be better supported
Sorry to necro up this issue, but I need to ask the state of afairs with this. I want to create an application, which critically relies on GtkTreeView
and I think for that I will have to work with a tree-store and all the other things like columns, column renderers, model and whatnot. In my example I need to only display some strings (utf-8 though) and perhaps numbers, but I think not.
Is there a way to make TreeView work and dynamically add and remove things shown in it using guile-gi? To me this issue reads like there are issues with it and that it does not work yet (?).
Well, I can take another look, but, the core problem is that guile-gi only provides functionality that the introspection library provides, and it doesn't provide any exceptional work-arounds except for Cairo. The introspection that Gtk-3.0 provides for GtkTreeView looks clunky and very verbose in guile-gi. It sort of works, though, depending on what you need.
I made a quick example. See this attachment --> gtk-tree-store.scm.txt
Thank you a lot for making an example. I will try and understand and try to use for my use-case.
@spk121 Where would be the best place to ask questions about some of the things in that example code? Here in this topic? Or rather a new issue? Or e-mail?
@ZelphirKaltstahl Email is perfectly fine by me, but if you want to do it on a web site, i enabled the discussions tab in GitHub. I've never used it tho, so I don't know if it is any good