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

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


Updating branch refs/heads/master
         to fbcfa257342a8ac84b624abc3289daf968621b2a (commit)
       from d72dfdd29ff81875b7a78e2f27517353367c5fc3 (commit)

commit fbcfa257342a8ac84b624abc3289daf968621b2a
Author: Eric Koegel <eric.koegel at gmail.com>
Date:   Fri Jan 6 21:48: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.
    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  |  157 ++++++++++++++++++++++++++++++++++++++++++++++++++++
 2 files changed, 200 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..dab29f2 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,147 @@ 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) );
+
+    /* User dropped an image, load all images in the directory
+     * and select the image.
+     */
+    if ( g_strv_length (uris) == 1)
+    {
+        file = rstto_file_new (g_file_new_for_uri (uris[n]));
+        if ( TRUE == rstto_main_window_is_valid_image (window, file))
+        {
+            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;
+        }
+
+        /* Not a valid image, but it might be a valid directory */
+        g_object_unref (file);
+    }
+
+    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))
+        {
+            /* User dropped a selection of images, load only them.
+             * On the first valid image, we reset the thumbnailbar.
+             */
+            if ( TRUE == first )
+            {
+                first = FALSE;
+                rstto_image_list_set_directory (
+                                            window->priv->image_list,
+                                            NULL,
+                                            NULL);
+            }
+
+            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