[Xfce4-commits] <ristretto:master> Drag and drop for images.

Stephan Arts noreply at xfce.org
Sat Jan 7 09:46:04 CET 2012


Updating branch refs/heads/master
         to a2a5d9ffed39f05edda04e0120de02db021b94fd (commit)
       from 6e4f29ce317a6f0379ba3a4fae7b7347ed9cfa1a (commit)

commit a2a5d9ffed39f05edda04e0120de02db021b94fd
Author: Eric Koegel <eric.koegel at gmail.com>
Date:   Sat Jan 7 05:15:08 2012 +0300

    Drag and drop for images.
    
    Adds support to open image files into ristretto as well as all the
    images in that same directory depending on what files were dropped,
    i.e. dropping one image will load all images in the directory while
    dropping a selection will reset the thumbnail bar and only load the
    selected images.
    Optionally, the user can just drop a single folder and ristretto
    will load all the images in there. For bug 3688.
    
    Signed-off-by: Stephan Arts <stephan at xfce.org>

 src/image_viewer.c |   46 +++++++++++++++-
 src/main_window.c  |  149 ++++++++++++++++++++++++++++++++++++++++++++++++++++
 2 files changed, 192 insertions(+), 3 deletions(-)

diff --git a/src/image_viewer.c b/src/image_viewer.c
index 557e1e3..5aa7d64 100644
--- a/src/image_viewer.c
+++ b/src/image_viewer.c
@@ -188,6 +188,9 @@ static void
 cb_rstto_image_loader_closed (GdkPixbufLoader *loader, RsttoImageViewerTransaction *transaction);
 static gboolean
 cb_rstto_image_viewer_update_pixbuf (RsttoImageViewer *viewer);
+static void
+cb_rstto_image_viewer_dnd (GtkWidget *widget, GdkDragContext *context, gint x, gint y, GtkSelectionData *data,
+                           guint info, guint time_, RsttoImageViewer *viewer);
 
 static gboolean
 rstto_scroll_event (
@@ -307,6 +310,11 @@ rstto_image_viewer_init ( GObject *object )
             "notify::revert-zoom-direction",
             G_CALLBACK (cb_rstto_zoom_direction_changed),
             viewer);
+    g_signal_connect (
+            G_OBJECT(viewer),
+            "drag-data-received",
+            G_CALLBACK (cb_rstto_image_viewer_dnd),
+            viewer);
 
     gtk_widget_set_events (GTK_WIDGET(viewer),
                            GDK_BUTTON_PRESS_MASK |
@@ -315,10 +323,11 @@ rstto_image_viewer_init ( GObject *object )
                            GDK_ENTER_NOTIFY_MASK |
                            GDK_POINTER_MOTION_MASK);
 
-    /*
-    gtk_drag_dest_set(GTK_WIDGET(viewer), 0, drop_targets, G_N_ELEMENTS(drop_targets),
+
+    gtk_drag_dest_set(GTK_WIDGET(viewer), GTK_DEST_DEFAULT_ALL, NULL, 0,
                       GDK_ACTION_COPY | GDK_ACTION_LINK | GDK_ACTION_MOVE | GDK_ACTION_PRIVATE);
-    */
+    gtk_drag_dest_add_uri_targets (GTK_WIDGET(viewer));
+
 }
 
 /**
@@ -378,6 +387,14 @@ rstto_image_viewer_class_init(RsttoImageViewerClass *viewer_class)
             NULL, NULL,
             g_cclosure_marshal_VOID__VOID,
             G_TYPE_NONE, 0);
+    g_signal_new ("files-dnd",
+            G_TYPE_FROM_CLASS (object_class),
+            G_SIGNAL_RUN_FIRST,
+            0,
+            NULL, NULL,
+            g_cclosure_marshal_VOID__POINTER,
+            G_TYPE_NONE, 1,
+            G_TYPE_POINTER);
 }
 
 /**
@@ -2488,3 +2505,26 @@ rstto_popup_menu (
     }
     return FALSE;
 }
+
+static void
+cb_rstto_image_viewer_dnd (GtkWidget *widget, GdkDragContext *context, gint x, gint y, GtkSelectionData *data,
+              guint info, guint time_, RsttoImageViewer *viewer)
+{
+    g_return_if_fail ( RSTTO_IS_IMAGE_VIEWER(viewer) );
+
+    if ((data->length >= 0) && (data->format == 8))
+    {
+        gchar **uris;
+
+        uris = g_uri_list_extract_uris ((const gchar*)data->data);
+
+        g_signal_emit_by_name (viewer, "files-dnd", uris);
+
+        gtk_drag_finish (context, TRUE, FALSE, time_);
+        g_strfreev (uris);
+    }
+    else
+    {
+        gtk_drag_finish (context, FALSE, FALSE, time_);
+    }
+}
diff --git a/src/main_window.c b/src/main_window.c
index cb13fd4..2e26e14 100644
--- a/src/main_window.c
+++ b/src/main_window.c
@@ -117,6 +117,8 @@ struct _RsttoMainWindowPriv
 
     gboolean playing;
     gint play_timeout_id;
+
+    GtkFileFilter *filter;
 };
 
 enum
@@ -192,6 +194,8 @@ static void
 cb_rstto_main_window_save_copy (GtkWidget *widget, RsttoMainWindow *window);
 static void
 cb_rstto_main_window_delete (GtkWidget *widget, RsttoMainWindow *window);
+static void
+cb_rstto_main_window_dnd_files (GtkWidget *widget, gchar **uris, RsttoMainWindow *window);
 
 static void
 cb_rstto_main_window_set_as_wallpaper (GtkWidget *widget, RsttoMainWindow *window);
@@ -452,6 +456,11 @@ rstto_main_window_init (RsttoMainWindow *window)
     window->priv->recent_manager = gtk_recent_manager_get_default();
     window->priv->settings_manager = rstto_settings_new();
 
+    /* Setup the image filter list for drag and drop */
+    window->priv->filter = gtk_file_filter_new ();
+    g_object_ref_sink (window->priv->filter);
+    gtk_file_filter_add_pixbuf_formats (window->priv->filter);
+
     /* D-Bus stuff */
 
     window->priv->connection = dbus_g_bus_get(DBUS_BUS_SESSION, NULL);
@@ -768,6 +777,7 @@ rstto_main_window_init (RsttoMainWindow *window)
     g_signal_connect(G_OBJECT(window->priv->thumbnailbar), "button-press-event", G_CALLBACK(cb_rstto_main_window_navigationtoolbar_button_press_event), window);
     g_signal_connect(G_OBJECT(window->priv->image_viewer), "size-ready", G_CALLBACK(cb_rstto_main_window_update_statusbar), window);
     g_signal_connect(G_OBJECT(window->priv->image_viewer), "scale-changed", G_CALLBACK(cb_rstto_main_window_update_statusbar), window);
+    g_signal_connect(G_OBJECT(window->priv->image_viewer), "files-dnd", G_CALLBACK(cb_rstto_main_window_dnd_files), window);
 
     if ( TRUE == rstto_settings_get_boolean_property (window->priv->settings_manager, "merge-toolbars"))
     {
@@ -869,6 +879,12 @@ rstto_main_window_dispose(GObject *object)
             g_object_unref (window->priv->image_list);
             window->priv->image_list = NULL;
         }
+
+        if (window->priv->filter)
+        {
+            g_object_unref (window->priv->filter);
+            window->priv->filter= NULL;
+        }
         g_free (window->priv);
         window->priv = NULL;
     }
@@ -3112,6 +3128,139 @@ cb_rstto_main_window_delete (
     g_object_unref (file);
 }
 
+static gboolean
+rstto_main_window_is_valid_image (RsttoMainWindow *window,
+                                  RsttoFile *file)
+{
+    GtkFileFilterInfo filter_info;
+
+    filter_info.contains =  GTK_FILE_FILTER_MIME_TYPE | GTK_FILE_FILTER_URI;
+    filter_info.uri = rstto_file_get_uri (file);
+    filter_info.mime_type = rstto_file_get_content_type (file);
+
+    return gtk_file_filter_filter (window->priv->filter, &filter_info);
+}
+
+/**
+ * cb_rstto_main_window_dnd_files:
+ * @widget:
+ * @uris:
+ * @window:
+ *
+ */
+static void
+cb_rstto_main_window_dnd_files (GtkWidget *widget,
+                                gchar **uris,
+                                RsttoMainWindow *window)
+{
+    RsttoFile *file;
+    guint n;
+    gboolean first = TRUE;
+
+    g_return_if_fail ( RSTTO_IS_MAIN_WINDOW(window) );
+
+    for (n = 0; n < g_strv_length (uris); n++)
+    {
+        file = rstto_file_new (g_file_new_for_uri (uris[n]));
+
+        if ( TRUE == rstto_main_window_is_valid_image (window, file))
+        {
+            if ( TRUE == first )
+            {
+                first = FALSE;
+
+                /* On the first valid image, we reset the thumbnailbar. */
+                rstto_image_list_set_directory (
+                                            window->priv->image_list,
+                                            NULL,
+                                            NULL);
+
+                /* User dropped a single image, load all images in the
+                 * directory and select the image.
+                 */
+                if (n + 1 == g_strv_length (uris))
+                {
+                    GFile *p_file;
+                    p_file = g_file_get_parent (rstto_file_get_file (file));
+                    rstto_image_list_set_directory (window->priv->image_list,
+                                                    p_file,
+                                                    NULL );
+                    rstto_image_list_iter_find_file (window->priv->iter,
+                                                     file );
+
+                    return;
+                }
+            }
+
+            /* User dropped a selection of images, load only them. */
+            rstto_image_list_add_file ( window->priv->image_list, file, NULL);
+            rstto_image_list_iter_find_file ( window->priv->iter,
+                                              file );
+        }
+        else if ( g_file_query_file_type ( rstto_file_get_file (file),
+                                           G_FILE_QUERY_INFO_NONE,
+                                           NULL) == G_FILE_TYPE_DIRECTORY)
+        {
+            GFileEnumerator *enumerator;
+
+            /* User dropped in a directory, get the files in it */
+            enumerator = g_file_enumerate_children (
+                            rstto_file_get_file (file),
+                            "standard::name,access::can-read",
+                            G_FILE_QUERY_INFO_NONE,
+                            NULL,
+                            NULL);
+
+            if (enumerator)
+            {
+                GFileInfo *f_info;
+                RsttoFile *child;
+
+                /* Check all the files for a valid image */
+                for (f_info = g_file_enumerator_next_file (enumerator, NULL, NULL);
+                     f_info != NULL;
+                     f_info = g_file_enumerator_next_file (enumerator, NULL, NULL))
+                {
+                    gchar *path = g_strdup_printf ("%s/%s",
+                                                   rstto_file_get_path (file),
+                                                   g_file_info_get_name (f_info));
+
+                    child = rstto_file_new (g_file_new_for_path (path));
+
+                    g_object_unref (f_info);
+                    g_free (path);
+
+                    if ( TRUE == rstto_main_window_is_valid_image (
+                                                                window,
+                                                                child))
+                    {
+                        /* Found a valid image, use the directory
+                         * and select the first image in the dir */
+                        rstto_image_list_set_directory (
+                                            window->priv->image_list,
+                                            rstto_file_get_file (file),
+                                            NULL );
+                        rstto_image_list_iter_find_file (
+                                                    window->priv->iter,
+                                                    child );
+
+                        break;
+                    }
+                    /* Not a valid image file */
+                    g_object_unref (child);
+                }
+                g_file_enumerator_close (enumerator, NULL, NULL);
+                g_object_unref (enumerator);
+            }
+        }
+        else
+        {
+            /* Not an image file or directory */
+            g_object_unref (file);
+        }
+    }
+}
+
 /**********************/
 /* PRINTING CALLBACKS */
 /**********************/


More information about the Xfce4-commits mailing list