GtkIconView drag and drop



Hello everyone!

I'm having troubles getting drag and drop working between 2
GtkIconViews. Actually, the DND works for me most of the time, the
problems arise when one of the GtkIconViews displays an empty model.
During my testing I discovered that "drag-drop" signal doesn't get
emitted when I try to drag something on an GtkIconView with empty
model. I wrote minimalistic sample code that demonstrates the
behavior.

Does anyone knows what am I doing wrong or how can I make this work?

Thanks.

------------ CODE -------------
/*
 * icon.c - GtkIconView DnD sample (non-working) application
 *
 * For non-working example compile with:
 *   gcc -o icon icon.c $(pkg-config --cflags --libs gtk+-2.0)
 * else
 *   gcc -DNONEMPTY -o icon icon.c $(pkg-config --cflags --libs gtk+-2.0)
 *
 */

#include <gtk/gtk.h>

enum
{
    COL_TEXT = 0,
    COL_PICT,
    N_COLS
};

static GtkTreeModel *create_model( gboolean populate );

static GtkWidget *create_icon_view( gboolean populate );

static gboolean cb_drag_drop( GtkWidget      *icon,
                              GdkDragContext *context,
                              gint            x,
                              gint            y,
                              guint           time,
                              gpointer        data );

int
main( int    argc,
      char **argv )
{
    GtkWidget    *window;
    GtkWidget    *hbox;
    GtkWidget    *icon1;
    GtkWidget    *icon2;

    gtk_init( &argc, &argv );

    window = gtk_window_new( GTK_WINDOW_TOPLEVEL );
    gtk_window_set_default_size( GTK_WINDOW( window ), 400, 300 );
    gtk_container_set_border_width( GTK_CONTAINER( window ), 6 );
    g_signal_connect( G_OBJECT( window ), "destroy",
                      G_CALLBACK( gtk_main_quit ), NULL );

    hbox = gtk_hbox_new( TRUE, 6 );
    gtk_container_add( GTK_CONTAINER( window ), hbox );

    icon1 = create_icon_view( TRUE );
    gtk_widget_set_name( icon1, "Left iconview" );
    gtk_box_pack_start( GTK_BOX( hbox ), icon1, TRUE, TRUE, 0 );

    icon2 = create_icon_view( FALSE );
    gtk_widget_set_name( icon2, "Right iconview" );
    gtk_box_pack_start( GTK_BOX( hbox ), icon2, TRUE, TRUE, 0 );

    gtk_widget_show_all( window );

    gtk_main();

    return( 0 );
}

static GtkWidget *
create_icon_view( gboolean populate )
{
    GtkWidget             *icon;
    GtkTreeModel          *model;

    static GtkTargetEntry *target = NULL;

    if( ! target )
    {
        target = g_slice_new(GtkTargetEntry);
        target->target = "InternalTarget";
        target->flags  = GTK_TARGET_SAME_APP;
        target->info   = 0;
    }

    model = create_model( populate );
    icon = gtk_icon_view_new_with_model( model );
    g_object_unref( G_OBJECT( model ) );

    gtk_icon_view_set_text_column( GTK_ICON_VIEW( icon ), COL_TEXT );
    gtk_icon_view_set_pixbuf_column( GTK_ICON_VIEW( icon ), COL_PICT );

    /* DnD setup */
    gtk_icon_view_enable_model_drag_source( GTK_ICON_VIEW( icon ),
                                            GDK_BUTTON1_MASK, target, 1,
                                            GDK_ACTION_MOVE );
    gtk_icon_view_enable_model_drag_dest( GTK_ICON_VIEW( icon ), target, 1,
                                          GDK_ACTION_MOVE );

    g_signal_connect( G_OBJECT( icon ), "drag-drop",
                      G_CALLBACK( cb_drag_drop ), NULL );

    return( icon );
}

static GtkTreeModel *
create_model( gboolean populate )
{
    GtkListStore *store;
    GtkTreeIter   iter;
    GdkPixbuf    *pix;

    store = gtk_list_store_new( N_COLS, G_TYPE_STRING, GDK_TYPE_PIXBUF );

    if( ! populate )
    {
        /* This piece of code makes all the difference */
#ifdef NONEMPTY
        pix = gdk_pixbuf_new( GDK_COLORSPACE_RGB, FALSE, 8, 50, 50 );
        gdk_pixbuf_fill( pix, 0xff000000 ); /* Red */
        gtk_list_store_append( store, &iter );
        gtk_list_store_set( store, &iter, COL_TEXT, "R 4", COL_PICT, pix, -1 );
        g_object_unref( G_OBJECT( pix ) );
#endif /* NONEMPTY */
    }
    else
    {
        pix = gdk_pixbuf_new( GDK_COLORSPACE_RGB, FALSE, 8, 50, 50 );
        gdk_pixbuf_fill( pix, 0x00000000 ); /* Black */
        gtk_list_store_append( store, &iter );
        gtk_list_store_set( store, &iter, COL_TEXT, "R 1", COL_PICT, pix, -1 );
        g_object_unref( G_OBJECT( pix ) );

        pix = gdk_pixbuf_new( GDK_COLORSPACE_RGB, FALSE, 8, 50, 50 );
        gdk_pixbuf_fill( pix, 0x0000ff00 ); /* Blue */
        gtk_list_store_append( store, &iter );
        gtk_list_store_set( store, &iter, COL_TEXT, "R 2", COL_PICT, pix, -1 );
        g_object_unref( G_OBJECT( pix ) );

        pix = gdk_pixbuf_new( GDK_COLORSPACE_RGB, FALSE, 8, 50, 50 );
        gdk_pixbuf_fill( pix, 0x00ff0000 ); /* Green */
        gtk_list_store_append( store, &iter );
        gtk_list_store_set( store, &iter, COL_TEXT, "R 3", COL_PICT, pix, -1 );
        g_object_unref( G_OBJECT( pix ) );
    }

    return( GTK_TREE_MODEL( store ) );
}

static gboolean
cb_drag_drop( GtkWidget      *icon,
              GdkDragContext *context,
              gint            x,
              gint            y,
              guint           time,
              gpointer        data )
{
    GdkAtom target_type;

    g_print( "Detected drop on %s\n", gtk_widget_get_name( icon ) );

    target_type = GDK_POINTER_TO_ATOM( context->targets->data );
    gtk_drag_get_data( icon, context, target_type, time );

    return( TRUE );
}

---------- CODE --------------

-- 
Tadej Borovšak
tadeboro gmail com
tadej borovsak gmail com


[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]