summaryrefslogtreecommitdiffstats
path: root/src/nautilus-files-view-dnd.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/nautilus-files-view-dnd.c')
-rw-r--r--src/nautilus-files-view-dnd.c362
1 files changed, 362 insertions, 0 deletions
diff --git a/src/nautilus-files-view-dnd.c b/src/nautilus-files-view-dnd.c
new file mode 100644
index 0000000..96a5c82
--- /dev/null
+++ b/src/nautilus-files-view-dnd.c
@@ -0,0 +1,362 @@
+/*
+ * nautilus-view-dnd.c: DnD helpers for NautilusFilesView
+ *
+ * Copyright (C) 1999, 2000 Free Software Foundaton
+ * Copyright (C) 2000, 2001 Eazel, Inc.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation; either version 2 of the
+ * License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public
+ * License along with this program; if not, see <http://www.gnu.org/licenses/>.
+ *
+ * Authors: Ettore Perazzoli
+ * Darin Adler <darin@bentspoon.com>
+ * John Sullivan <sullivan@eazel.com>
+ * Pavel Cisler <pavel@eazel.com>
+ */
+
+#include <config.h>
+
+#include "nautilus-files-view-dnd.h"
+
+#include "nautilus-files-view.h"
+#include "nautilus-application.h"
+
+#include <eel/eel-string.h>
+#include <eel/eel-vfs-extensions.h>
+
+#include <glib/gi18n.h>
+
+#include "nautilus-clipboard.h"
+#include "nautilus-dnd.h"
+#include "nautilus-global-preferences.h"
+#include "nautilus-ui-utilities.h"
+
+#define GET_ANCESTOR(obj) \
+ GTK_WINDOW (gtk_widget_get_ancestor (GTK_WIDGET (obj), GTK_TYPE_WINDOW))
+
+void
+nautilus_files_view_handle_uri_list_drop (NautilusFilesView *view,
+ const char *item_uris,
+ const char *target_uri,
+ GdkDragAction action)
+{
+ gchar **uri_list;
+ GList *real_uri_list = NULL;
+ char *container_uri;
+ const char *real_target_uri;
+ int n_uris, i;
+
+ if (item_uris == NULL)
+ {
+ return;
+ }
+
+ container_uri = NULL;
+ if (target_uri == NULL)
+ {
+ container_uri = nautilus_files_view_get_backing_uri (view);
+ g_assert (container_uri != NULL);
+ }
+
+ if (action == GDK_ACTION_ASK)
+ {
+#if 0 && NAUTILUS_DND_NEEDS_GTK4_REIMPLEMENTATION
+ action = nautilus_drag_drop_action_ask
+ (GTK_WIDGET (view),
+ GDK_ACTION_MOVE | GDK_ACTION_COPY | GDK_ACTION_LINK);
+ if (action == 0)
+#endif
+ {
+ g_free (container_uri);
+ return;
+ }
+ }
+
+ if ((action != GDK_ACTION_COPY) &&
+ (action != GDK_ACTION_MOVE) &&
+ (action != GDK_ACTION_LINK))
+ {
+ show_dialog (_("Drag and drop is not supported."),
+ _("An invalid drag type was used."),
+ GET_ANCESTOR (view),
+ GTK_MESSAGE_WARNING);
+ g_free (container_uri);
+ return;
+ }
+
+ n_uris = 0;
+ uri_list = g_uri_list_extract_uris (item_uris);
+ for (i = 0; uri_list[i] != NULL; i++)
+ {
+ real_uri_list = g_list_append (real_uri_list, uri_list[i]);
+ n_uris++;
+ }
+ g_free (uri_list);
+
+ /* do nothing if no real uris are left */
+ if (n_uris == 0)
+ {
+ g_free (container_uri);
+ return;
+ }
+
+ real_target_uri = target_uri != NULL ? target_uri : container_uri;
+
+ nautilus_files_view_move_copy_items (view, real_uri_list,
+ real_target_uri,
+ action);
+
+ g_list_free_full (real_uri_list, g_free);
+
+ g_free (container_uri);
+}
+
+#define MAX_LEN_FILENAME 64
+#define MIN_LEN_FILENAME 8
+
+static char *
+get_drop_filename (const char *text)
+{
+ char *filename;
+ char trimmed[MAX_LEN_FILENAME];
+ int i;
+ int last_word = -1;
+ int end_sentence = -1;
+ int last_nonspace = -1;
+ int start_sentence = -1;
+ int num_attrs;
+ PangoLogAttr *attrs;
+ gchar *current_char;
+
+ num_attrs = MIN (g_utf8_strlen (text, -1), MAX_LEN_FILENAME) + 1;
+ attrs = g_new (PangoLogAttr, num_attrs);
+ g_utf8_strncpy (trimmed, text, num_attrs - 1);
+ pango_get_log_attrs (trimmed, -1, -1, pango_language_get_default (), attrs, num_attrs);
+
+ /* since the end of the text will always match a word boundary don't include it */
+ for (i = 0; (i < num_attrs - 1); i++)
+ {
+ if (attrs[i].is_sentence_start && start_sentence == -1)
+ {
+ start_sentence = i;
+ }
+ if (!attrs[i].is_white)
+ {
+ last_nonspace = i;
+ }
+ if (attrs[i].is_word_boundary)
+ {
+ last_word = last_nonspace;
+ }
+ if (attrs[i].is_sentence_end)
+ {
+ end_sentence = last_nonspace;
+ break;
+ }
+ }
+ g_free (attrs);
+
+ if (end_sentence > 0)
+ {
+ i = end_sentence;
+ }
+ else
+ {
+ i = last_word;
+ }
+
+ if (i - start_sentence > MIN_LEN_FILENAME)
+ {
+ g_autofree char *substring = g_utf8_substring (trimmed, start_sentence, i);
+ filename = g_strdup_printf ("%s.txt", substring);
+ }
+ else
+ {
+ /* Translator: This is the filename used for when you dnd text to a directory */
+ filename = g_strdup (_("Dropped Text.txt"));
+ }
+
+ /* Remove any invalid characters */
+ for (current_char = filename;
+ *current_char;
+ current_char = g_utf8_next_char (current_char))
+ {
+ if (G_IS_DIR_SEPARATOR (g_utf8_get_char (current_char)))
+ {
+ *current_char = '-';
+ }
+ }
+
+ return filename;
+}
+
+void
+nautilus_files_view_handle_text_drop (NautilusFilesView *view,
+ const char *text,
+ const char *target_uri,
+ GdkDragAction action)
+{
+ int length;
+ char *container_uri;
+ char *filename;
+
+ if (text == NULL)
+ {
+ return;
+ }
+
+ g_return_if_fail (action == GDK_ACTION_COPY);
+
+ container_uri = NULL;
+ if (target_uri == NULL)
+ {
+ container_uri = nautilus_files_view_get_backing_uri (view);
+ g_assert (container_uri != NULL);
+ }
+
+ length = strlen (text);
+
+ /* try to get text to use as a filename */
+ filename = get_drop_filename (text);
+
+ nautilus_files_view_new_file_with_initial_contents (view,
+ target_uri != NULL ? target_uri : container_uri,
+ filename,
+ text,
+ length);
+ g_free (filename);
+ g_free (container_uri);
+}
+
+void
+nautilus_files_view_handle_raw_drop (NautilusFilesView *view,
+ const char *raw_data,
+ int length,
+ const char *target_uri,
+ const char *direct_save_uri,
+ GdkDragAction action)
+{
+ char *container_uri, *filename;
+ GFile *direct_save_full;
+
+ if (raw_data == NULL)
+ {
+ return;
+ }
+
+ g_return_if_fail (action == GDK_ACTION_COPY);
+
+ container_uri = NULL;
+ if (target_uri == NULL)
+ {
+ container_uri = nautilus_files_view_get_backing_uri (view);
+ g_assert (container_uri != NULL);
+ }
+
+ filename = NULL;
+ if (direct_save_uri != NULL)
+ {
+ direct_save_full = g_file_new_for_uri (direct_save_uri);
+ filename = g_file_get_basename (direct_save_full);
+ }
+ if (filename == NULL)
+ {
+ /* Translator: This is the filename used for when you dnd raw
+ * data to a directory, if the source didn't supply a name.
+ */
+ filename = g_strdup (_("dropped data"));
+ }
+
+ nautilus_files_view_new_file_with_initial_contents (
+ view, target_uri != NULL ? target_uri : container_uri,
+ filename, raw_data, length);
+
+ g_free (container_uri);
+ g_free (filename);
+}
+
+void
+nautilus_files_view_drop_proxy_received_uris (NautilusFilesView *view,
+ const GList *source_uri_list,
+ const char *target_uri,
+ GdkDragAction action)
+{
+ g_autofree char *container_uri = NULL;
+ g_autoptr (GFile) source_location = g_file_new_for_uri (source_uri_list->data);
+ g_autoptr (GFile) target_location = g_file_new_for_uri (target_uri);
+
+ if (target_uri == NULL)
+ {
+ container_uri = nautilus_files_view_get_backing_uri (view);
+ g_assert (container_uri != NULL);
+ }
+ if (g_file_has_parent (source_location, target_location) &&
+ action & GDK_ACTION_MOVE)
+ {
+ /* By default dragging to the same directory is allowed so that
+ * users can duplicate a file using the CTRL modifier key. Prevent
+ * an accidental MOVE, by rejecting what would be an error anyways. */
+ return;
+ }
+
+ if (action == GDK_ACTION_ASK)
+ {
+#if 0 && NAUTILUS_DND_NEEDS_GTK4_REIMPLEMENTATION
+ action = nautilus_drag_drop_action_ask
+ (GTK_WIDGET (view),
+ GDK_ACTION_MOVE | GDK_ACTION_COPY | GDK_ACTION_LINK);
+ if (action == 0)
+#endif
+ {
+ return;
+ }
+ }
+
+#if 0 && NAUTILUS_DND_NEEDS_GTK4_REIMPLEMENTATION
+ nautilus_clipboard_clear_if_colliding_uris (GTK_WIDGET (view),
+ source_uri_list);
+#endif
+ nautilus_files_view_move_copy_items (view, source_uri_list,
+ target_uri != NULL ? target_uri : container_uri,
+ action);
+}
+
+void
+nautilus_files_view_handle_hover (NautilusFilesView *view,
+ const char *target_uri)
+{
+ NautilusWindowSlot *slot;
+ GFile *location;
+ GFile *current_location;
+ NautilusFile *target_file;
+ gboolean target_is_dir;
+ gboolean open_folder_on_hover;
+
+ slot = nautilus_files_view_get_nautilus_window_slot (view);
+
+ location = g_file_new_for_uri (target_uri);
+ target_file = nautilus_file_get_existing (location);
+ target_is_dir = nautilus_file_get_file_type (target_file) == G_FILE_TYPE_DIRECTORY;
+ current_location = nautilus_window_slot_get_location (slot);
+ open_folder_on_hover = g_settings_get_boolean (nautilus_preferences,
+ NAUTILUS_PREFERENCES_OPEN_FOLDER_ON_DND_HOVER);
+
+ if (target_is_dir && open_folder_on_hover &&
+ !(current_location != NULL && g_file_equal (location, current_location)))
+ {
+ nautilus_application_open_location_full (NAUTILUS_APPLICATION (g_application_get_default ()),
+ location, NAUTILUS_OPEN_FLAG_DONT_MAKE_ACTIVE,
+ NULL, NULL, slot);
+ }
+ g_object_unref (location);
+ nautilus_file_unref (target_file);
+}