Filesel drag and drop
- From: Alex Larsson <alexl redhat com>
- To: <gtk-devel-list gnome org>
- Subject: Filesel drag and drop
- Date: Thu, 2 Aug 2001 17:33:20 -0400 (EDT)
Here is a patch that adds some drag and drop support too the file
selector. Can i commit this?
/ Alex
Index: gtkfilesel.c
===================================================================
RCS file: /cvs/gnome/gtk+/gtk/gtkfilesel.c,v
retrieving revision 1.84
diff -u -p -r1.84 gtkfilesel.c
--- gtkfilesel.c 2001/07/18 23:39:22 1.84
+++ gtkfilesel.c 2001/08/02 21:29:50
@@ -44,6 +44,7 @@
#ifdef HAVE_PWD_H
#include <pwd.h>
#endif
+#include <ctype.h>
#include "fnmatch.h"
@@ -68,6 +69,7 @@
#include "gtkdialog.h"
#include "gtkmessagedialog.h"
#include "gtkintl.h"
+#include "gtkdnd.h"
#if defined(G_OS_WIN32) || defined(G_WITH_CYGWIN)
#define STRICT
@@ -588,6 +590,7 @@ gtk_file_selection_init (GtkFileSelectio
GtkWidget *confirm_area;
GtkWidget *pulldown_hbox;
GtkWidget *scrolled_win;
+ GtkWidget *eventbox;
GtkDialog *dialog;
char *dir_title [2];
@@ -692,11 +695,14 @@ gtk_file_selection_init (GtkFileSelectio
entry_vbox = gtk_vbox_new (FALSE, 2);
gtk_box_pack_end (GTK_BOX (filesel->main_vbox), entry_vbox, FALSE, FALSE, 2);
gtk_widget_show (entry_vbox);
-
+
+ eventbox = gtk_event_box_new ();
filesel->selection_text = label = gtk_label_new ("");
gtk_misc_set_alignment (GTK_MISC (label), 0.0, 0.5);
- gtk_box_pack_start (GTK_BOX (entry_vbox), label, FALSE, FALSE, 0);
+ gtk_container_add (GTK_CONTAINER (eventbox), label);
+ gtk_box_pack_start (GTK_BOX (entry_vbox), eventbox, FALSE, FALSE, 0);
gtk_widget_show (label);
+ gtk_widget_show (eventbox);
filesel->selection_entry = gtk_entry_new ();
gtk_signal_connect (GTK_OBJECT (filesel->selection_entry), "key_press_event",
@@ -728,6 +734,172 @@ gtk_file_selection_init (GtkFileSelectio
gtk_widget_grab_focus (filesel->selection_entry);
}
+static gchar *
+uri_list_extract_first_uri (const gchar* uri_list)
+{
+ const gchar *p, *q;
+ gchar *retval;
+
+ g_return_val_if_fail (uri_list != NULL, NULL);
+
+ p = uri_list;
+ /* We don't actually try to validate the URI according to RFC
+ * 2396, or even check for allowed characters - we just ignore
+ * comments and trim whitespace off the ends. We also
+ * allow LF delimination as well as the specified CRLF.
+ */
+ while (p)
+ {
+ if (*p != '#')
+ {
+ while (isspace(*p))
+ p++;
+
+ q = p;
+ while (*q && (*q != '\n') && (*q != '\r'))
+ q++;
+
+ if (q > p)
+ {
+ q--;
+ while (q > p && isspace (*q))
+ q--;
+
+ retval = g_malloc (q - p + 2);
+ strncpy (retval, p, q - p + 1);
+ retval[q - p + 1] = '\0';
+ return retval;
+ }
+ }
+ p = strchr (p, '\n');
+ if (p)
+ p++;
+ }
+ return NULL;
+}
+
+static gchar *
+uri_extract_filename (const gchar* uri)
+{
+ /* file uri with a hostname */
+ if (strncmp(uri, "file://", strlen("file://"))==0)
+ {
+ const char *hostname = &uri[strlen("file://")];
+ char *p = strchr (hostname,'/');
+
+ /* if we can't find the '/' this uri is bad */
+ if(!p)
+ return NULL;
+
+ return g_strdup (p);
+
+ /* if the file doesn't have the //, we take it containing
+ a local path */
+ }
+ else if (strncmp (uri, "file:", strlen("file:"))==0)
+ {
+ const char *path = &uri[strlen("file:")];
+ /* if empty bad */
+ if (!*path)
+ return NULL;
+ return g_strdup (path);
+ }
+ return NULL;
+}
+
+
+static void
+filenames_dropped(GtkWidget *widget,
+ GdkDragContext *context,
+ gint x,
+ gint y,
+ GtkSelectionData *selection_data,
+ guint info,
+ guint time)
+{
+ char *uri = NULL;
+ char *filename = NULL;
+
+ if (!selection_data->data)
+ return;
+
+ uri = uri_list_extract_first_uri ((char *)selection_data->data);
+
+ if (!uri)
+ return;
+
+ filename = uri_extract_filename (uri);
+
+ g_free (uri);
+
+ if (!filename)
+ return;
+
+ gtk_file_selection_set_filename (GTK_FILE_SELECTION (widget),
+ filename);
+
+ g_free (filename);
+}
+
+static void
+filenames_drag_get (GtkWidget *widget,
+ GdkDragContext *context,
+ GtkSelectionData *selection_data,
+ guint info,
+ guint time,
+ GtkFileSelection *filesel)
+{
+ gchar *file;
+ gchar *uri_list;
+
+ file = gtk_file_selection_get_filename (filesel);
+
+ if (file) /* ignore non-file-images for now */
+ {
+ uri_list = g_strconcat ("file:", file, NULL);
+ gtk_selection_data_set (selection_data,
+ selection_data->target, 8,
+ (void *)uri_list, strlen((char *)uri_list));
+ g_free (uri_list);
+ }
+ else
+ {
+ gtk_selection_data_set (selection_data,
+ selection_data->target, 8,
+ NULL, 0);
+ }
+}
+
+
+static void
+file_selection_setup_dnd (GtkFileSelection *filesel)
+{
+ GtkWidget *eventbox;
+ static GtkTargetEntry drag_types[] = {
+ { "text/uri-list", 0, 0 }
+ };
+ static gint n_drag_types = sizeof(drag_types)/sizeof(drag_types[0]);
+
+ gtk_drag_dest_set (GTK_WIDGET (filesel),
+ GTK_DEST_DEFAULT_ALL,
+ drag_types, n_drag_types,
+ GDK_ACTION_COPY);
+
+ gtk_signal_connect (GTK_OBJECT(filesel), "drag_data_received",
+ GTK_SIGNAL_FUNC(filenames_dropped), NULL);
+
+ eventbox = gtk_widget_get_parent (filesel->selection_text);
+ gtk_drag_source_set (eventbox,
+ GDK_BUTTON1_MASK,
+ drag_types, n_drag_types,
+ GDK_ACTION_COPY);
+
+ gtk_signal_connect (GTK_OBJECT (eventbox),
+ "drag_data_get",
+ GTK_SIGNAL_FUNC (filenames_drag_get),
+ filesel);
+}
+
GtkWidget*
gtk_file_selection_new (const gchar *title)
{
@@ -737,6 +909,8 @@ gtk_file_selection_new (const gchar *tit
gtk_window_set_title (GTK_WINDOW (filesel), title);
gtk_dialog_set_has_separator (GTK_DIALOG (filesel), FALSE);
+ file_selection_setup_dnd (filesel);
+
return GTK_WIDGET (filesel);
}
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]