New filesel DnD patch



Here is a new version of the fileselector drag and drop patch. This one 
uses the API from the patch in the mail i sent earlier today 
(Subject: Re: URIs vs. half-baked URIs [glib PATCH]).

/ Alex

Index: gtk/gtkfilesel.c
===================================================================
RCS file: /cvs/gnome/gtk+/gtk/gtkfilesel.c,v
retrieving revision 1.84
diff -u -p -r1.84 gtkfilesel.c
--- gtk/gtkfilesel.c	2001/07/18 23:39:22	1.84
+++ gtk/gtkfilesel.c	2001/08/04 00:57:50
@@ -44,6 +44,7 @@
 #ifdef HAVE_PWD_H
 #include <pwd.h>
 #endif
+#include <ctype.h>
 
 #include "fnmatch.h"
 
@@ -68,6 +69,8 @@
 #include "gtkdialog.h"
 #include "gtkmessagedialog.h"
 #include "gtkintl.h"
+#include "gtkdnd.h"
+#include "gtkeventbox.h"
 
 #if defined(G_OS_WIN32) || defined(G_WITH_CYGWIN)
 #define STRICT
@@ -588,6 +591,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 +696,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 +735,147 @@ 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 void
+filenames_dropped(GtkWidget        *widget,
+		  GdkDragContext   *context,
+		  gint              x,
+		  gint              y,
+		  GtkSelectionData *selection_data,
+		  guint             info,
+		  guint             time)
+{
+  char *uri = NULL;
+  char *filename = NULL;
+  char *hostname;
+  GError *error = NULL;
+	
+  if (!selection_data->data)
+    return;
+
+  uri = uri_list_extract_first_uri ((char *)selection_data->data);
+  
+  if (!uri)
+    return;
+
+  filename = g_filename_from_uri (uri, NULL, &error);
+  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;
+  char hostname[128];
+  int res;
+
+  file = gtk_file_selection_get_filename (filesel);
+
+  if (file)
+    {
+      res = gethostname (hostname, 128);
+      
+      uri_list = g_filename_to_uri (file, (!res)?hostname:NULL, 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 +885,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]