Owen David
Owen David

Reputation: 1

GTK4 Problem setting image from pixbuf with a GtkDropTarget

I am testing a gtk4 widget which is GtkDropTarget. I plan on setting an image which is dragged to the window as the image of the window itself. But errors come up as soon as I drag an image file. To be clear, this is the code in vala:

int main (string[] args) {
    var app = new App();
    return app.run(args);
}

public class App : Gtk.Application {
    public App () {
    Object (
        application_id: "com.github.ea",
        flags: ApplicationFlags.FLAGS_NONE
    );
    }
    public override void activate () {
    var window = new Window (this);
    add_window (window);
    }
}

public class Window : Gtk.ApplicationWindow {
    public Window (Gtk.Application app) {
        Object (application: app);
    }

construct {
        title = "Drag";
    set_default_size (640, 480);
    var drag_source = new DragSource ();
    set_child (drag_source.self);       
    show ();
    }
}

public class DragSource {
    public Gtk.Image self;

    public DragSource () {

        self = new Gtk.Image ();
        var drag_controller = new Gtk.DropTarget (GLib.Type.INVALID,     Gdk.DragAction.COPY);

        drag_controller.set_gtypes ({typeof(File)});

        self.add_controller (drag_controller);
        drag_controller.on_drop.connect (on_drop);
    }

    private bool on_drop (GLib.Value val, double x, double y) {
        File filename = (File) val;
        var file_path = filename.get_path ();
        
        if (val.holds(typeof(File)) == true) {
        print ("The dragged object is a file.\n");

        if ("png" in file_path || "jpg" in file_path) {
                print ("The dragged object is an image.\n");
                self.set_from_pixbuf (pixbuf(file_path));
        }
            else {
                print ("The dragged object is NOT an image.\n");
        }
    }
        else {
            print ("The dragged object is NOT a file.\n");
        return false;
        }
        return true;
    }

    private Gdk.Pixbuf pixbuf (string file) {
        try {
            return new Gdk.Pixbuf.from_file (file);
        } catch (Error e) {
            error ("%s", e.message);
            }
        }
}

This compiles and runs. But as soon as I drag an image file to the window, error occurs and the image is not displayed. This are the pictures of what happens. What should happen is, when I drag a png file from my file manager, the dragged image should be the image showing in the GtkImage, which is the main widget of the window.

On my first drag of an image file from my pc, this error shows up:

The dragged object is a file.
The dragged object is an image.

(v:3891): Gtk-CRITICAL **: 08:52:28.861: gtk_image_set_from_pixbuf: assertion 'GTK_IS_IMAGE (image)' failed

On the second drag, this shows up:

(v:3891): Gdk-CRITICAL **: 08:53:33.388: gdk_drop_set_actions: assertion 'priv->state == GDK_DROP_STATE_NONE' failed
The dragged object is a file.
The dragged object is an image.

(v:3891): Gtk-CRITICAL **: 08:53:33.973: gtk_image_set_from_pixbuf: assertion 'GTK_IS_IMAGE (image)' failed

I would really appreciate a help. Thank You!

Upvotes: 0

Views: 431

Answers (2)

multia
multia

Reputation: 21

I've been looking for a solution to this too and I concluded that GTK4 is just not complete (yet?). I think chances of finding a solution to this in gtk4.0 are close to none. Even their demo apps (gtk4-demo-application and gtk4-widget-factory) produce the same warnings. Another popular application that tries to implement this in gtk4, transmission-gtk, produces these warnings too.

Upvotes: 0

aeldemery
aeldemery

Reputation: 91

This is how I would implement your intention

int main (string[] args) {
    var app = new App ();
    return app.run (args);
}

public class App : Gtk.Application {
    public App () {
        Object (
            application_id: "com.github.ea",
            flags : ApplicationFlags.FLAGS_NONE
        );
    }

    public override void activate () {
        var window = new Window (this);
        window.present ();
    }
}

public class Window : Gtk.ApplicationWindow {
    public Window (Gtk.Application app) {
        Object (application: app);
    }

    construct {
        title = "Drag an Image!";
        set_default_size (640, 480);

        var image = new Gtk.Image ();
        image.vexpand = image.hexpand = true;

        var controller = new Gtk.DropTarget (typeof (GLib.File), Gdk.DragAction.COPY);
        controller.on_drop.connect ((target, value, x, y) => {
            var file = (GLib.File) value;
            var filename = file.get_path ();
            if (GLib.ContentType.guess (filename, null, null).contains ("image")) {
                image.set_from_file (filename);
            }
        });
        image.add_controller (controller);

        set_child (image);
    }
}

Upvotes: 1

Related Questions