Commit 45e2d19a authored by Paolo Bacchilega's avatar Paolo Bacchilega

folder tree: better drag&drop support

Allow to move a catalog into a library, and a library into
another library; show an error if the drop operation is
not possible.
parent 5fe71edb
......@@ -1445,6 +1445,64 @@ gth_file_source_catalogs_deleted_from_disk (GthFileSource *file_source,
}
static GdkDragAction
gth_file_source_catalogs_get_drop_actions (GthFileSource *file_source,
GFile *destination,
GFile *file)
{
GdkDragAction actions = 0;
char *dest_uri;
char *dest_scheme;
const char *dest_ext;
gboolean dest_is_catalog;
char *file_uri;
char *file_scheme;
const char *file_ext;
gboolean file_is_catalog;
dest_uri = g_file_get_uri (destination);
dest_scheme = _g_uri_get_scheme (dest_uri);
dest_ext = _g_uri_get_file_extension (dest_uri);
dest_is_catalog = (g_strcmp0 (dest_ext, ".catalog") == 0) || (g_strcmp0 (dest_ext, ".search") == 0);
file_uri = g_file_get_uri (file);
file_scheme = _g_uri_get_scheme (file_uri);
file_ext = _g_uri_get_file_extension (file_uri);
file_is_catalog = (g_strcmp0 (file_ext, ".catalog") == 0) || (g_strcmp0 (file_ext, ".search") == 0);
if ((g_strcmp0 (dest_scheme, "catalog://") == 0)
&& dest_is_catalog
&& (g_strcmp0 (file_scheme, "file://") == 0))
{
/* Copy files into a catalog. */
actions = GDK_ACTION_COPY;
}
else if ((g_strcmp0 (file_scheme, "catalog://") == 0)
&& file_is_catalog
&& (g_strcmp0 (dest_scheme, "catalog://") == 0)
&& ! dest_is_catalog)
{
/* Move a catalog into a library. */
actions = GDK_ACTION_MOVE;
}
else if ((g_strcmp0 (file_scheme, "catalog://") == 0)
&& ! file_is_catalog
&& (g_strcmp0 (dest_scheme, "catalog://") == 0)
&& ! dest_is_catalog)
{
/* Move a library into another library. */
actions = GDK_ACTION_MOVE;
}
g_free (file_uri);
g_free (dest_uri);
return actions;
}
static void
gth_file_source_catalogs_finalize (GObject *object)
{
......@@ -1481,6 +1539,7 @@ gth_file_source_catalogs_class_init (GthFileSourceCatalogsClass *class)
file_source_class->reorder = gth_file_source_catalogs_reorder;
file_source_class->remove = gth_file_source_catalogs_remove;
file_source_class->deleted_from_disk = gth_file_source_catalogs_deleted_from_disk;
file_source_class->get_drop_actions = gth_file_source_catalogs_get_drop_actions;
}
......
......@@ -945,86 +945,101 @@ fm__gth_browser_folder_tree_drag_data_received_cb (GthBrowser *browser,
GList *file_list,
GdkDragAction action)
{
GthFileSource *file_source;
int n_files;
GthFileSource *destination_source;
GFile *first_file;
GthFileSource *file_list_source;
gboolean move_files;
GtkWidget *dialog;
GthTask *task;
char *message;
int response;
if (destination == NULL)
return;
file_source = gth_main_get_file_source (destination->file);
if (file_source == NULL)
n_files = g_list_length (file_list);
if (n_files == 0)
return;
if ((action != GDK_ACTION_MOVE) && (action != GDK_ACTION_COPY))
return;
destination_source = gth_main_get_file_source (destination->file);
if (destination_source == NULL)
return;
first_file = G_FILE (file_list->data);
file_list_source = gth_main_get_file_source (first_file);
if (file_list_source == NULL)
return;
if (action == GDK_ACTION_MOVE)
action |= GDK_ACTION_COPY;
action = action & gth_file_source_get_drop_actions (destination_source, destination->file, first_file);
if (action == 0) {
_gtk_error_dialog_run (GTK_WINDOW (browser),
"%s",
_("Could not perform the operation"));
return;
}
move_files = (action & GDK_ACTION_MOVE) != 0;
/* ask confirmation */
response = GTK_RESPONSE_OK;
if ((action == GDK_ACTION_MOVE) || (action == GDK_ACTION_COPY)) {
int n_files;
char *message;
n_files = g_list_length (file_list);
g_return_if_fail (n_files >= 1);
if (n_files == 1) {
char *filename = _g_file_get_display_name ((GFile *) file_list->data);
if (action == GDK_ACTION_MOVE)
message = g_strdup_printf (_("Do you want to move “%s” to “%s”?"), filename, g_file_info_get_display_name (destination->info));
else
message = g_strdup_printf (_("Do you want to copy “%s” to “%s”?"), filename, g_file_info_get_display_name (destination->info));
g_free (filename);
}
else {
if (action == GDK_ACTION_MOVE)
message = g_strdup_printf (_("Do you want to move the dragged files to “%s”?"), g_file_info_get_display_name (destination->info));
else
message = g_strdup_printf (_("Do you want to copy the dragged files to “%s”?"), g_file_info_get_display_name (destination->info));
}
dialog = _gtk_message_dialog_new (GTK_WINDOW (browser),
GTK_DIALOG_MODAL,
_GTK_ICON_NAME_DIALOG_QUESTION,
message,
NULL,
_GTK_LABEL_CANCEL, GTK_RESPONSE_CANCEL,
((action == GDK_ACTION_MOVE) ? _("Move") : _("_Copy")), GTK_RESPONSE_OK,
NULL);
response = gtk_dialog_run (GTK_DIALOG (dialog));
gtk_widget_destroy (dialog);
g_free (message);
if (n_files == 1) {
GFileInfo *info;
char *filename;
info = gth_file_source_get_file_info (file_list_source, first_file, G_FILE_ATTRIBUTE_STANDARD_DISPLAY_NAME);
if (info != NULL)
filename = g_strdup (g_file_info_get_display_name (info));
else
filename = _g_file_get_display_name (first_file);
if (move_files)
message = g_strdup_printf (_("Do you want to move “%s” to “%s”?"), filename, g_file_info_get_display_name (destination->info));
else
message = g_strdup_printf (_("Do you want to copy “%s” to “%s”?"), filename, g_file_info_get_display_name (destination->info));
g_free (filename);
_g_object_unref (info);
}
else {
if (move_files)
message = g_strdup_printf (_("Do you want to move the dragged files to “%s”?"), g_file_info_get_display_name (destination->info));
else
message = g_strdup_printf (_("Do you want to copy the dragged files to “%s”?"), g_file_info_get_display_name (destination->info));
}
dialog = _gtk_message_dialog_new (GTK_WINDOW (browser),
GTK_DIALOG_MODAL,
_GTK_ICON_NAME_DIALOG_QUESTION,
message,
NULL,
_GTK_LABEL_CANCEL, GTK_RESPONSE_CANCEL,
(move_files ? _("Move") : _("_Copy")), GTK_RESPONSE_OK,
NULL);
response = gtk_dialog_run (GTK_DIALOG (dialog));
gtk_widget_destroy (dialog);
g_free (message);
if (response != GTK_RESPONSE_OK)
return;
if ((action == GDK_ACTION_MOVE) && ! gth_file_source_can_cut (file_source, (GFile *) file_list->data)) {
dialog = _gtk_message_dialog_new (GTK_WINDOW (browser),
GTK_DIALOG_MODAL,
_GTK_ICON_NAME_DIALOG_QUESTION,
_("Could not move the files"),
_("Files cannot be moved to the current location, as alternative you can choose to copy them."),
_GTK_LABEL_CANCEL, GTK_RESPONSE_CANCEL,
_GTK_LABEL_COPY, GTK_RESPONSE_OK,
NULL);
response = gtk_dialog_run (GTK_DIALOG (dialog));
gtk_widget_destroy (dialog);
if (response == GTK_RESPONSE_CANCEL)
return;
action = GDK_ACTION_COPY;
}
/* exec task */
task = gth_copy_task_new (file_source,
task = gth_copy_task_new (destination_source,
destination,
(action == GDK_ACTION_MOVE),
move_files,
file_list,
-1);
gth_browser_exec_task (browser, task, GTH_TASK_FLAGS_DEFAULT);
g_object_unref (task);
g_object_unref (file_source);
g_object_unref (destination_source);
}
......
......@@ -284,6 +284,37 @@ gth_file_source_selections_shows_extra_widget (GthFileSource *file_source)
}
static GdkDragAction
gth_file_source_selections_get_drop_actions (GthFileSource *file_source,
GFile *destination,
GFile *file)
{
GdkDragAction actions = 0;
char *dest_uri;
char *dest_scheme;
char *file_uri;
char *file_scheme;
dest_uri = g_file_get_uri (destination);
dest_scheme = _g_uri_get_scheme (dest_uri);
file_uri = g_file_get_uri (file);
file_scheme = _g_uri_get_scheme (file_uri);
if ((g_strcmp0 (dest_scheme, "selection://") == 0)
&& (g_strcmp0 (file_scheme, "file://") == 0))
{
/* Copy files into a selection. */
actions = GDK_ACTION_COPY;
}
g_free (file_uri);
g_free (dest_uri);
return actions;
}
static void
gth_file_source_selections_class_init (GthFileSourceSelectionsClass *class)
{
......@@ -304,6 +335,7 @@ gth_file_source_selections_class_init (GthFileSourceSelectionsClass *class)
file_source_class->remove = gth_file_source_selections_remove;
file_source_class->deleted_from_disk = gth_file_source_selections_deleted_from_disk;
file_source_class->shows_extra_widget = gth_file_source_selections_shows_extra_widget;
file_source_class->get_drop_actions = gth_file_source_selections_get_drop_actions;
}
......
......@@ -2661,7 +2661,6 @@ folder_tree_drag_motion_cb (GtkWidget *file_view,
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);
......@@ -2694,8 +2693,6 @@ folder_tree_drag_motion_cb (GtkWidget *file_view,
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);
......@@ -2705,52 +2702,7 @@ folder_tree_drag_motion_cb (GtkWidget *file_view,
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;
destination = gth_folder_tree_get_file (GTH_FOLDER_TREE (browser->priv->folder_tree), path);
if (destination != NULL) {
GthFileSource *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;
_g_object_unref (file_source);
}
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);
gdk_drag_status (context, GDK_ACTION_MOVE, time);
gtk_tree_path_free (path);
return TRUE;
......
......@@ -883,6 +883,24 @@ gth_file_source_vfs_remove (GthFileSource *file_source,
}
static GdkDragAction
gth_file_source_vfs_get_drop_actions (GthFileSource *file_source,
GFile *destination,
GFile *file)
{
char *dest_scheme;
char *file_scheme;
dest_scheme = g_file_get_uri_scheme(destination);
file_scheme = g_file_get_uri_scheme(file);
if ((g_strcmp0 (dest_scheme, "file") == 0) && (g_strcmp0 (file_scheme, "file") == 0))
return GDK_ACTION_COPY | GDK_ACTION_MOVE;
else
return 0;
}
static void
gth_file_source_vfs_finalize (GObject *object)
{
......@@ -926,6 +944,7 @@ gth_file_source_vfs_class_init (GthFileSourceVfsClass *class)
file_source_class->monitor_entry_points = gth_file_source_vfs_monitor_entry_points;
file_source_class->monitor_directory = gth_file_source_vfs_monitor_directory;
file_source_class->remove = gth_file_source_vfs_remove;
file_source_class->get_drop_actions = gth_file_source_vfs_get_drop_actions;
}
......
......@@ -900,6 +900,15 @@ base_shows_extra_widget (GthFileSource *file_source)
}
static GdkDragAction
base_get_drop_actions (GthFileSource *file_source,
GFile *destination,
GFile *file)
{
return 0; /* no action supported by default. */
}
static void
gth_file_source_finalize (GObject *object)
{
......@@ -938,6 +947,7 @@ gth_file_source_class_init (GthFileSourceClass *class)
class->deleted_from_disk = base_deleted_from_disk;
class->get_free_space = base_get_free_space;
class->shows_extra_widget = base_shows_extra_widget;
class->get_drop_actions = base_get_drop_actions;
}
......@@ -1436,3 +1446,12 @@ gth_file_source_shows_extra_widget (GthFileSource *file_source)
{
return GTH_FILE_SOURCE_GET_CLASS (G_OBJECT (file_source))->shows_extra_widget (file_source);
}
GdkDragAction
gth_file_source_get_drop_actions (GthFileSource *file_source,
GFile *destination,
GFile *file)
{
return GTH_FILE_SOURCE_GET_CLASS (G_OBJECT (file_source))->get_drop_actions (file_source, destination, file);
}
......@@ -139,6 +139,9 @@ struct _GthFileSourceClass
SpaceReadyCallback callback,
gpointer data);
gboolean (*shows_extra_widget) (GthFileSource *file_source);
GdkDragAction(*get_drop_actions) (GthFileSource *file_source,
GFile *destination,
GFile *file);
};
GType gth_file_source_get_type (void) G_GNUC_CONST;
......@@ -230,6 +233,9 @@ void gth_file_source_get_free_space (GthFileSource *file
SpaceReadyCallback callback,
gpointer data);
gboolean gth_file_source_shows_extra_widget (GthFileSource *file_source);
GdkDragAction gth_file_source_get_drop_actions (GthFileSource *file_source,
GFile *destination,
GFile *file);
/*< protected >*/
......
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment