[gthumb] drag&drop: move files by default



commit 318da5793e151eca463454854206b2951d7216f7
Author: Paolo Bacchilega <paobac src gnome org>
Date:   Sun Mar 15 14:45:54 2015 +0100

    drag&drop: move files by default

 extensions/file_manager/callbacks.c |   86 +++++++++++++++++----
 gthumb/gth-browser.c                |  143 ++++++++++++++++++++++++++++++++++-
 gthumb/gth-file-list.c              |   59 +++++++++------
 gthumb/gth-file-list.h              |    5 +
 4 files changed, 251 insertions(+), 42 deletions(-)
---
diff --git a/extensions/file_manager/callbacks.c b/extensions/file_manager/callbacks.c
index 5b3936e..5f200d0 100644
--- a/extensions/file_manager/callbacks.c
+++ b/extensions/file_manager/callbacks.c
@@ -34,6 +34,7 @@
 #define BROWSER_DATA_KEY             "file-manager-browser-data"
 #define URI_LIST_ATOM                (gdk_atom_intern_static_string ("text/uri-list"))
 #define XDND_ACTION_DIRECT_SAVE_ATOM (gdk_atom_intern_static_string ("XdndDirectSave0"))
+#define GTHUMB_REORDERABLE_LIST_ATOM (gdk_atom_intern_static_string ("gthumb/reorderable-list"))
 #define TEXT_PLAIN_ATOM              (gdk_atom_intern_static_string ("text/plain"))
 #define SCROLL_TIMEOUT               30 /* autoscroll timeout in milliseconds */
 
@@ -125,7 +126,13 @@ static const GthAccelerator accelerators[] = {
 
 static GtkTargetEntry reorderable_drag_dest_targets[] = {
         { "text/uri-list", 0, 0 },
-        { "text/uri-list", GTK_TARGET_SAME_WIDGET, 0 }
+        { "text/uri-list", GTK_TARGET_SAME_WIDGET, 0 },
+       { "gthumb/reorderable-list", 0, 0 }
+};
+
+
+static GtkTargetEntry reorderable_drag_source_targets[] = {
+       { "gthumb/reorderable-list", 0, 0 }
 };
 
 
@@ -175,8 +182,6 @@ gth_file_list_drag_data_received (GtkWidget        *file_view,
        GList          *selected_files;
        GdkDragAction   action;
 
-       g_signal_stop_emission_by_name (file_view, "drag-data-received");
-
        action = gdk_drag_context_get_suggested_action (context);
        if (action == GDK_ACTION_COPY || action == GDK_ACTION_MOVE) {
                success = TRUE;
@@ -435,10 +440,27 @@ gth_file_list_drag_motion (GtkWidget      *file_view,
                        data->scroll_event = 0;
                }
        }
-       else if (gdk_drag_context_get_suggested_action (context) == GDK_ACTION_ASK)
+       else if (gdk_drag_context_get_suggested_action (context) == GDK_ACTION_ASK) {
                gdk_drag_status (context, GDK_ACTION_ASK, time);
-       else
-               gdk_drag_status (context, GDK_ACTION_COPY, time);
+       }
+       else {
+               gboolean  source_is_reorderable = FALSE;
+               GList    *targets = gdk_drag_context_list_targets (context);
+               GList    *scan;
+
+               /* use COPY when dragging a file from a catalog to a directory */
+
+               for (scan = targets; scan; scan = scan->next) {
+                       GdkAtom target = scan->data;
+
+                       if (target == GTHUMB_REORDERABLE_LIST_ATOM) {
+                               source_is_reorderable = TRUE;
+                               break;
+                       }
+               }
+
+               gdk_drag_status (context, source_is_reorderable ? GDK_ACTION_COPY : GDK_ACTION_MOVE, time);
+       }
 
        return TRUE;
 }
@@ -596,8 +618,13 @@ fm__gth_browser_load_location_after_cb (GthBrowser   *browser,
                                        GthFileData  *location_data,
                                        const GError *error)
 {
-       BrowserData *data;
-       GtkWidget   *file_view;
+       BrowserData    *data;
+       GtkWidget      *file_list;
+       GtkWidget      *file_view;
+       GtkTargetList  *source_target_list;
+       GtkTargetEntry *source_targets;
+       int             n_source_targets;
+       GdkDragAction   source_actions;
 
        if ((location_data == NULL) || (error != NULL))
                return;
@@ -605,38 +632,65 @@ fm__gth_browser_load_location_after_cb (GthBrowser   *browser,
        data = g_object_get_data (G_OBJECT (browser), BROWSER_DATA_KEY);
        file_manager_update_ui (data, browser);
 
+       source_target_list = gtk_target_list_new (NULL, 0);
+       gtk_target_list_add_uri_targets (source_target_list, 0);
+       gtk_target_list_add_text_targets (source_target_list, 0);
+       source_actions = GDK_ACTION_PRIVATE;
+
+       file_list = gth_browser_get_file_list (browser);
        if (! g_file_info_get_attribute_boolean (location_data->info, G_FILE_ATTRIBUTE_ACCESS_CAN_WRITE)) {
-               file_view = gth_file_list_get_view (GTH_FILE_LIST (gth_browser_get_file_list (browser)));
+               file_view = gth_file_list_get_view (GTH_FILE_LIST (file_list));
                gth_file_view_unset_drag_dest (GTH_FILE_VIEW (file_view));
-               file_view = gth_file_list_get_empty_view (GTH_FILE_LIST (gth_browser_get_file_list 
(browser)));
+               file_view = gth_file_list_get_empty_view (GTH_FILE_LIST (file_list));
                gtk_drag_dest_unset (file_view);
+
+               source_actions = GDK_ACTION_COPY;
        }
        else if (gth_file_source_is_reorderable (gth_browser_get_location_source (browser))) {
-               file_view = gth_file_list_get_view (GTH_FILE_LIST (gth_browser_get_file_list (browser)));
+               file_view = gth_file_list_get_view (GTH_FILE_LIST (file_list));
                gth_file_view_enable_drag_dest (GTH_FILE_VIEW (file_view),
                                                reorderable_drag_dest_targets,
                                                G_N_ELEMENTS (reorderable_drag_dest_targets),
                                                GDK_ACTION_COPY | GDK_ACTION_MOVE);
-               file_view = gth_file_list_get_empty_view (GTH_FILE_LIST (gth_browser_get_file_list 
(browser)));
+               file_view = gth_file_list_get_empty_view (GTH_FILE_LIST (file_list));
                gtk_drag_dest_set (file_view,
                                   0,
                                   reorderable_drag_dest_targets,
                                   G_N_ELEMENTS (reorderable_drag_dest_targets),
                                   GDK_ACTION_COPY | GDK_ACTION_MOVE);
+
+               gtk_target_list_add_table (source_target_list,
+                                          reorderable_drag_source_targets,
+                                          G_N_ELEMENTS (reorderable_drag_source_targets));
+               source_actions = GDK_ACTION_COPY | GDK_ACTION_MOVE;
        }
        else {
-               file_view = gth_file_list_get_view (GTH_FILE_LIST (gth_browser_get_file_list (browser)));
+               file_view = gth_file_list_get_view (GTH_FILE_LIST (file_list));
                gth_file_view_enable_drag_dest (GTH_FILE_VIEW (file_view),
                                                non_reorderable_drag_dest_targets,
                                                G_N_ELEMENTS (non_reorderable_drag_dest_targets),
-                                               GDK_ACTION_COPY);
-               file_view = gth_file_list_get_empty_view (GTH_FILE_LIST (gth_browser_get_file_list 
(browser)));
+                                               GDK_ACTION_COPY | GDK_ACTION_MOVE);
+               file_view = gth_file_list_get_empty_view (GTH_FILE_LIST (file_list));
                gtk_drag_dest_set (file_view,
                                   0,
                                   non_reorderable_drag_dest_targets,
                                   G_N_ELEMENTS (non_reorderable_drag_dest_targets),
-                                  GDK_ACTION_COPY);
+                                  GDK_ACTION_COPY | GDK_ACTION_MOVE);
+
+               source_actions = GDK_ACTION_MOVE | GDK_ACTION_ASK;
        }
+
+       /* set the drag source targets */
+
+       source_targets = gtk_target_table_new_from_list (source_target_list, &n_source_targets);
+       gth_file_view_enable_drag_source (GTH_FILE_VIEW (gth_file_list_get_view (GTH_FILE_LIST (file_list))),
+                                         GDK_BUTTON1_MASK | GDK_BUTTON2_MASK,
+                                         source_targets,
+                                         n_source_targets,
+                                         source_actions);
+
+       gtk_target_list_unref (source_target_list);
+       gtk_target_table_free (source_targets, n_source_targets);
 }
 
 
diff --git a/gthumb/gth-browser.c b/gthumb/gth-browser.c
index 386bcef..307ac6f 100644
--- a/gthumb/gth-browser.c
+++ b/gthumb/gth-browser.c
@@ -73,11 +73,10 @@
 #define MIN_SIDEBAR_SIZE 100
 #define MIN_VIEWER_SIZE 256
 #define STATUSBAR_SEPARATOR "  ยท  "
-#define SHIRNK_WRAP_WIDTH_OFFSET 100
-#define SHIRNK_WRAP_HEIGHT_OFFSET 125
 #define FILE_PROPERTIES_MINIMUM_HEIGHT 100
 #define HISTORY_FILE "history.xbel"
 #define OVERLAY_MARGIN 10
+#define AUTO_OPEN_FOLDER_DELAY 500
 
 
 G_DEFINE_TYPE (GthBrowser, gth_browser, GTH_TYPE_WINDOW)
@@ -182,6 +181,8 @@ struct _GthBrowserPrivate {
        GthSidebarState    viewer_sidebar;
        BrowserState       state;
        GthICCProfile      screen_profile;
+       GtkTreePath       *folder_tree_last_dest_row; /* used to open a folder during D&D */
+       guint              folder_tree_open_folder_id;
 
        /* settings */
 
@@ -2172,6 +2173,11 @@ _gth_browser_real_close (GthBrowser *browser)
                browser->priv->selection_changed_event = 0;
        }
 
+       if (browser->priv->folder_tree_open_folder_id != 0) {
+               g_source_remove (browser->priv->folder_tree_open_folder_id);
+               browser->priv->folder_tree_open_folder_id = 0;
+       }
+
        /* cancel async operations */
 
        _gth_browser_cancel (browser, _gth_browser_close_step3, browser);
@@ -2602,6 +2608,7 @@ gth_browser_finalize (GObject *object)
        _g_object_unref (browser->priv->folder_popup_file_data);
        _g_object_unref (browser->priv->history_menu);
        gth_icc_profile_free (browser->priv->screen_profile);
+       gtk_tree_path_free (browser->priv->folder_tree_last_dest_row);
 
        G_OBJECT_CLASS (gth_browser_parent_class)->finalize (object);
 }
@@ -2672,6 +2679,130 @@ viewer_container_get_child_position_cb (GtkOverlay   *overlay,
 }
 
 
+static gboolean
+folder_tree_open_folder_cb (gpointer user_data)
+{
+       GthBrowser *browser = user_data;
+
+       if (browser->priv->folder_tree_open_folder_id != 0) {
+               g_source_remove (browser->priv->folder_tree_open_folder_id);
+               browser->priv->folder_tree_open_folder_id = 0;
+       }
+
+       gtk_tree_view_expand_row (GTK_TREE_VIEW (browser->priv->folder_tree),
+                                 browser->priv->folder_tree_last_dest_row,
+                                 FALSE);
+
+       return FALSE;
+}
+
+
+static gboolean
+folder_tree_drag_motion_cb (GtkWidget      *file_view,
+                           GdkDragContext *context,
+                           gint            x,
+                           gint            y,
+                           guint           time,
+                           gpointer        user_data)
+{
+       GthBrowser              *browser = user_data;
+       GtkTreePath             *path;
+       GtkTreeViewDropPosition  pos;
+       GdkDragAction            action;
+
+       if (gdk_drag_context_get_suggested_action (context) == GDK_ACTION_ASK) {
+               gdk_drag_status (context, GDK_ACTION_ASK, time);
+               return FALSE;
+       }
+
+       if (! gtk_tree_view_get_dest_row_at_pos (GTK_TREE_VIEW (file_view),
+                                                x,
+                                                y,
+                                                &path,
+                                                &pos))
+       {
+               gtk_tree_path_free (browser->priv->folder_tree_last_dest_row);
+               browser->priv->folder_tree_last_dest_row = NULL;
+
+               if (browser->priv->folder_tree_open_folder_id != 0) {
+                       g_source_remove (browser->priv->folder_tree_open_folder_id);
+                       browser->priv->folder_tree_open_folder_id = 0;
+               }
+
+               gtk_tree_view_set_drag_dest_row (GTK_TREE_VIEW (file_view), NULL, 0);
+               gdk_drag_status (context, 0, time);
+               return TRUE;
+       }
+
+       if (pos == GTK_TREE_VIEW_DROP_BEFORE)
+               pos = GTK_TREE_VIEW_DROP_INTO_OR_BEFORE;
+       if (pos == GTK_TREE_VIEW_DROP_AFTER)
+               pos = GTK_TREE_VIEW_DROP_INTO_OR_AFTER;
+
+       gtk_tree_view_set_drag_dest_row (GTK_TREE_VIEW (file_view), path, pos);
+
+       action = GDK_ACTION_MOVE;
+
+       if ((browser->priv->folder_tree_last_dest_row == NULL) || gtk_tree_path_compare (path, 
browser->priv->folder_tree_last_dest_row) != 0) {
+               gtk_tree_path_free (browser->priv->folder_tree_last_dest_row);
+               browser->priv->folder_tree_last_dest_row = gtk_tree_path_copy (path);
+
+               if (browser->priv->folder_tree_open_folder_id != 0)
+                       g_source_remove (browser->priv->folder_tree_open_folder_id);
+               browser->priv->folder_tree_open_folder_id = g_timeout_add (AUTO_OPEN_FOLDER_DELAY, 
folder_tree_open_folder_cb, browser);
+       }
+
+       /* use COPY if dropping a file in a catalog */
+
+       if (action == GDK_ACTION_MOVE) {
+               GthFileData   *destination;
+               GthFileSource *file_source;
+
+               destination = gth_folder_tree_get_file (GTH_FOLDER_TREE (browser->priv->folder_tree), path);
+               if (destination != NULL) {
+                       file_source = gth_main_get_file_source (destination->file);
+                       _g_object_unref (destination);
+
+                       if (file_source != NULL) {
+                               if (gth_file_source_is_reorderable (file_source))
+                                       action = GDK_ACTION_COPY;
+                       }
+                       else
+                               action = 0;
+               }
+               else
+                       action = 0;
+       }
+
+       /* use COPY when dragging a file from a catalog to a directory */
+
+       if (action == GDK_ACTION_MOVE) {
+               gboolean  source_is_reorderable;
+               GList    *targets;
+               GList    *scan;
+
+               source_is_reorderable = FALSE;
+               targets = gdk_drag_context_list_targets (context);
+               for (scan = targets; scan; scan = scan->next) {
+                       GdkAtom target = scan->data;
+
+                       if (target == gdk_atom_intern_static_string ("gthumb/reorderable-list")) {
+                               source_is_reorderable = TRUE;
+                               break;
+                       }
+               }
+
+               if (source_is_reorderable)
+                       action = GDK_ACTION_COPY;
+       }
+
+       gdk_drag_status (context, action, time);
+       gtk_tree_path_free (path);
+
+       return TRUE;
+}
+
+
 static void
 folder_tree_drag_data_received (GtkWidget        *tree_view,
                                GdkDragContext   *context,
@@ -2757,7 +2888,7 @@ folder_tree_drag_data_get_cb (GtkWidget        *widget,
        if (file_source == NULL)
                return;
 
-       if (gdk_drag_context_get_actions (drag_context) && GDK_ACTION_MOVE) {
+       if (gdk_drag_context_get_actions (drag_context) & GDK_ACTION_MOVE) {
                GdkDragAction action =
                        gth_file_source_can_cut (file_source, file_data->file) ?
                        GDK_ACTION_MOVE : GDK_ACTION_COPY;
@@ -4131,6 +4262,8 @@ gth_browser_init (GthBrowser *browser)
        browser->priv->file_properties_on_the_right = g_settings_get_boolean 
(browser->priv->browser_settings, PREF_BROWSER_PROPERTIES_ON_THE_RIGHT);
        browser->priv->menu_managers = g_hash_table_new_full (g_str_hash, g_str_equal, g_free, 
g_object_unref);
        browser->priv->screen_profile = NULL;
+       browser->priv->folder_tree_last_dest_row = NULL;
+       browser->priv->folder_tree_open_folder_id = 0;
 
        browser_state_init (&browser->priv->state);
 
@@ -4547,6 +4680,10 @@ gth_browser_init (GthBrowser *browser)
                                                    n_targets,
                                                    GDK_ACTION_MOVE | GDK_ACTION_COPY);
                g_signal_connect (browser->priv->folder_tree,
+                                 "drag_motion",
+                                 G_CALLBACK (folder_tree_drag_motion_cb),
+                                 browser);
+               g_signal_connect (browser->priv->folder_tree,
                                  "drag-data-received",
                                  G_CALLBACK (folder_tree_drag_data_received),
                                  browser);
diff --git a/gthumb/gth-file-list.c b/gthumb/gth-file-list.c
index 299b814..1457d1a 100644
--- a/gthumb/gth-file-list.c
+++ b/gthumb/gth-file-list.c
@@ -660,30 +660,13 @@ gth_file_list_construct (GthFileList     *file_list,
                          "rows-reordered",
                          G_CALLBACK (file_store_rows_reordered_cb),
                          file_list);
+       g_signal_connect (G_OBJECT (file_list->priv->view),
+                         "drag-data-get",
+                         G_CALLBACK (file_view_drag_data_get_cb),
+                         file_list);
 
-       if (enable_drag_drop) {
-               GtkTargetList  *target_list;
-               GtkTargetEntry *targets;
-               int             n_targets;
-
-               target_list = gtk_target_list_new (NULL, 0);
-               gtk_target_list_add_uri_targets (target_list, 0);
-               gtk_target_list_add_text_targets (target_list, 0);
-               targets = gtk_target_table_new_from_list (target_list, &n_targets);
-               gth_file_view_enable_drag_source (GTH_FILE_VIEW (file_list->priv->view),
-                                                 GDK_BUTTON1_MASK | GDK_BUTTON2_MASK,
-                                                 targets,
-                                                 n_targets,
-                                                 GDK_ACTION_COPY | GDK_ACTION_MOVE | GDK_ACTION_ASK);
-
-               gtk_target_list_unref (target_list);
-               gtk_target_table_free (targets, n_targets);
-
-               g_signal_connect (G_OBJECT (file_list->priv->view),
-                                 "drag-data-get",
-                                 G_CALLBACK (file_view_drag_data_get_cb),
-                                 file_list);
-       }
+       if (enable_drag_drop)
+               gth_file_list_enable_drag_source (file_list, GDK_ACTION_COPY | GDK_ACTION_MOVE | 
GDK_ACTION_ASK);
 
        gth_file_list_set_mode (file_list, list_type);
 
@@ -2150,3 +2133,33 @@ gth_file_list_prev_file (GthFileList *file_list,
 
        return (scan != NULL) ? pos : -1;
 }
+
+
+void
+gth_file_list_enable_drag_source (GthFileList     *file_list,
+                                 GdkDragAction    actions)
+{
+       GtkTargetList  *target_list;
+       GtkTargetEntry *targets;
+       int             n_targets;
+
+       target_list = gtk_target_list_new (NULL, 0);
+       gtk_target_list_add_uri_targets (target_list, 0);
+       gtk_target_list_add_text_targets (target_list, 0);
+       targets = gtk_target_table_new_from_list (target_list, &n_targets);
+       gth_file_view_enable_drag_source (GTH_FILE_VIEW (file_list->priv->view),
+                                         GDK_BUTTON1_MASK | GDK_BUTTON2_MASK,
+                                         targets,
+                                         n_targets,
+                                         actions);
+
+       gtk_target_list_unref (target_list);
+       gtk_target_table_free (targets, n_targets);
+}
+
+
+void
+gth_file_list_unset_drag_source (GthFileList *file_list)
+{
+       gth_file_view_unset_drag_source (GTH_FILE_VIEW (file_list->priv->view));
+}
diff --git a/gthumb/gth-file-list.h b/gthumb/gth-file-list.h
index 18c68af..02962de 100644
--- a/gthumb/gth-file-list.h
+++ b/gthumb/gth-file-list.h
@@ -128,6 +128,11 @@ int               gth_file_list_prev_file         (GthFileList          *file_li
                                                   gboolean              only_selected,
                                                   gboolean              wrap);
 
+void              gth_file_list_enable_drag_source (GthFileList         *file_list,
+                                                   GdkDragAction        actions);
+void              gth_file_list_unset_drag_source  (GthFileList         *file_list);
+
+
 G_END_DECLS
 
 #endif /* GTH_FILE_LIST_H */


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