rhx / SwiftGdkPixbuf

A Swift wrapper around GdkPixbuf-2.x that is largely auto-generated from gobject-introspection
https://rhx.github.io/SwiftGdkPixbuf/
BSD 2-Clause "Simplified" License
0 stars 3 forks source link

How can I get the GDK_TYPE_PIXBUF constant? #2

Open jasaldivara opened 3 years ago

jasaldivara commented 3 years ago

I want to create a GtkIconView using SwiftGtk.

For the Icon View I need a ListStore in which one of the columns is of the GdkPixbuf type.

This is a C example from the official Gtk documentation:

gtk_list_store_new (3, G_TYPE_INT, G_TYPE_STRING, GDK_TYPE_PIXBUF)

Another example in Python, from the Python Gtk 3 documenation:

liststore = Gtk.ListStore(Pixbuf, str)

I couldn't find an example of GtkIconView on the SwiftGtk examples, but I find the SwiftGtkListViewDemo which does something similar, creates a ListStore with two string columns and one boolean column using the .string and .boolean values, which are members of GType:

store = ListStore(.string, .string, .boolean)

If I try to do something like that using .pixbuf, swift compiler gives me an error message:

ls = ListStore(.pixbuf, .string)
error: type 'GType' (aka 'UInt') has no member 'pixbuf'
        ls = ListStore(.pixbuf, .string)
                       ~^~~~~~

I'm importing both Gdk and GdkPixbuf in my source code:

import Gtk
import Gdk
import GdkPixbuf

If I try to use the Pixbuf class as a type value, it gives me another error message:

ls = ListStore(Pixbuf, .string)
error: cannot convert value of type 'Pixbuf.Type' to expected argument type 'GType' (aka 'UInt')
        ls = ListStore(Pixbuf, .string)
                       ^

How can I create a ListStore in which one of the columns is of the Pixbuf type?

rhx commented 3 years ago

Unfortunately, the #define GDK_TYPE_* macros are not imported by Swift, as they actually are function calls. In the case of GDK_TYPE_PIXBUF, the gdk-pixbuf-core.h include file defines this to be the gdk_pixbuf_get_type() function. While this C function isn't listed in the GIR file (and so gir2swift doesn't create a Swift wrapper for it), you can use a C function directly from Swift. So to get the GType for a Pixbuf, you need to import CGdkPixbuf, then you can use

import CGdkPixbuf
import GdkPixbuf
import Gtk

// ...
        store = ListStore(gdk_pixbuf_get_type(), .string)
// ...
rhx commented 3 years ago

I'm reopening this as it would be nice if this worked with gir2swift generated type information, rather than having to call gdk_pixbuf_get_type() directly. But for the moment, the workaround from my previous post should work fine.

jasaldivara commented 3 years ago

Thanks!

It worked ok, but I ran into another issue...

(I will put it in this same thread, since it's closely related)

How can I convert a PixbufRef into a Value (GValue) type, so I can use it as a parameter to the ListStore.append() method?

This is a code example from GtkListViewDemo, bit it only uses Strings and Boolean as values, which are converted to Value by the Swift compiler:

        store.append(asNextRow: i, "The Principle of Reason", "Martin Heidegger", false)
        store.append(asNextRow: i, "The Art of Computer Programming", "Donald E. Knuth", true)
        store.append(asNextRow: i, "Structure and Interpretation of Computer Programs", "Harold Abelson and Gerald J. Sussman", false)

If I try to append a row into a ListStore using Pixbuf as a value, the Swift compiler displays an error message saying it cannot convert PixbufRef to Value:

    var iconView: IconViewRef
    var ls: ListStore

    // ...

        ls = ListStore(gdk_pixbuf_get_type(), .string)

        // ...

        do {
            var i = TreeIter()
            let pixBufIcon = try IconTheme.getDefault().loadIcon(iconName: "image-missing", size: 64, flags: IconLookupFlags(0))

            ls.append(asNextRow: i, pixBufIcon, "Product Name")

            iconView.set(model: ls)
        } catch {
            print ("Error while loading icons")
        }
error: cannot convert value of type 'PixbufRef?' to expected argument type 'Value'
            ls.append(asNextRow: i, pixBufIcon, "Product Name")
                                    ^

How can I convert a Pixbuf into a Value (GValue type), so I can create an IconView using a ListStore as the model?

rhx commented 3 years ago

First, you need to make sure that your pixBufIcon is a non-optional, so you could do a guard let, or simply declare the type (as loadIcon() returns a force-unwrapped optional):

        let pixBufIcon: PixbufRef = try IconTheme.getDefault().loadIcon(iconName: "image-missing", size: 64, flags: IconLookupFlags(0))

Then, you can simply set it as the content in a Value container, which you can then append to your list store, e.g.:

        let pixBufValue = Value()
        pixBufValue.set(pixBufIcon)
        ls.append(asNextRow: i, pixBufValue, "Product Name")
rhx commented 3 years ago

I have just committed an update to SwiftGObject that allows initialising a Value from an optional object. So (after running ./distclean.sh or rm -rf .build) your original code should work now by simply wrapping pixbufValue in aValue in your ls.append, i.e.:

            ls.append(asNextRow: i, Value(pixBufIcon), "Product Name")
jasaldivara commented 3 years ago

Thanks!

Both solutions worked for me. Now my IconView is working ok.