rasmus91
rasmus91

Reputation: 3214

Implementing ListModel with Gee.ArrayList

So I thought I'd be clever one of the more generic and easy to use classes, namely Gee.ArrayList for the data for a ListBox. Turns out that ListBox will take a ListModel, and I figured, since I was using ArrayList, that I might as well just make a class that is both a Gee.ArrayList and a ListModel:

public class ObservableArrayList<T> : ListModel, Gee.ArrayList<T>{

    //Implement ListModel
    public Object? get_item(uint position){
        if((int)position > size){
            return null;
        }

        return (Object?) this.get((int)position);
    }

    public Type get_item_type(){
        return element_type;
    }

    public uint get_n_items(){
        return (uint)size;
    }

    public new Object? get_object(uint position){
        if((int)position > size){
            return null;
        }
        return (Object) this.get((int)position);
    }

}

This, however gives me a strange compile message:

/home/rasmus/Projects/Vala/Test/ObservableList.vala.c: In function ‘observable_array_list_g_list_model_interface_init’:
/home/rasmus/Projects/Vala/Test/ObservableList.vala.c:189:18: warning: assignment from incompatible pointer type [-Wincompatible-pointer-types]
  iface->get_item = (GObject* (*) (GListModel*, guint)) observable_array_list_real_get_item;

And while the compilation succeeds, the class is very much unusable as a ListModel:

using Gtk;

public class TestApp : Gtk.Application{

    public TestApp () {
        Object (
            application_id: "TestApp",
            flags: ApplicationFlags.FLAGS_NONE
        );
    }

    protected override void activate(){
        var main_window = new Gtk.ApplicationWindow (this);
            main_window.default_height = 400;
            main_window.default_width = 600;
            main_window.title = "test";

        ListModel t = new ObservableArrayList<int>();

        var list_box = new Gtk.ListBox();

        list_box.bind_model(t, null);

        main_window.add(list_box);

        main_window.show_all ();

    }

    public static int main (string[] args) {
        Gtk.init (ref args);

        var app = new TestApp ();

        return app.run(args);
    }
}   

The output of which, when trying to run a compiled program is:

segmentationfault

Is there a good way to resolve this, or have i been trying something that was wrong from the outset?

Upvotes: 1

Views: 654

Answers (1)

Zander Brown
Zander Brown

Reputation: 637

An important thing to remember is that Vala actually compiles to C which is then fed into GCC to build an executable, your compiler warning is actually comping from gcc not valac

On my machine the message is formatted slightly differently

warning: assignment to ‘void * (*)(GListModel *, guint)’ {aka ‘void * (*)(struct _GListModel *, unsigned int)’} from incompatible pointer type ‘GObject * (*)(GListModel *, guint)’ {aka ‘struct _GObject * (*)(struct _GListModel *, unsigned int)’}

Which can be simplified to

assignment to ‘void * (*)(GListModel *, guint)’ from incompatible type ‘GObject * (*)(GListModel *, guint)’

Which is basically saying that GLib expects get_item to return void * instead of a GObject, this is a bug in the bindings so can be ignored

The run comes with the runtime warnings

(list:4511): GLib-GIO-CRITICAL **: 21:44:24.003: g_application_set_application_id: assertion 'application_id == NULL || g_application_id_is_valid (application_id)' failed

(list:4511): Gtk-CRITICAL **: 21:44:24.008: gtk_list_box_bind_model: assertion 'model == NULL || create_widget_func != NULL' failed

So you have 2 problems

  1. Your application id is wrong. Take a look at HowDoI/ChooseApplicationID to help decide what to use instead of "TestApp", generally something like com.githost.me.App
  2. You haven't actually set a method to bind the model with so Gtk is rejecting it, make sure you actually pass a function there

However neither of those tell us why your getting SEGV

The answer lies in that your GListModel contains elements of type int whereas GtkListBox is expecting a collection of Object

Upvotes: 2

Related Questions