[PATCH] Drag&Drop support for GnomeICU



  This patch adds some support for drag-and-drop in GnomeICU; specifically, you
can drag URLs from Netscape onto the user list and files from gmc.  There are
also a few modifications to how the (non-functional) file request code is
structured--I tried to remove the dialog display from the backend and clean it
up a little, although it's a little like trying to empty the desert of sand...

  The patch actually adds two short files, dragdrop.[ch], which I've attached
here (how do you get cvs to add new-file info to patches?).

  Daniel
-- 
  If you wish to live wisely, ignore sayings--including this one.
? dragdrop.c
? dragdrop.h
? gnomeicu
Index: Makefile.am
===================================================================
RCS file: /cvs/gnome/gnomeicu/src/Makefile.am,v
retrieving revision 1.2
diff -u -r1.2 Makefile.am
--- Makefile.am	1999/03/01 01:17:08	1.2
+++ Makefile.am	1999/03/31 18:04:40
@@ -16,6 +16,7 @@
 	changename.c	\
 	chatdlg.c	\
 	dialog.c	\
+	dragdrop.c      \
 	flash.c		\
 	gnomecfg.c	\
 	gnomeicu.c	\
Index: gnomeicu.c
===================================================================
RCS file: /cvs/gnome/gnomeicu/src/gnomeicu.c,v
retrieving revision 1.8
diff -u -r1.8 gnomeicu.c
--- gnomeicu.c	1999/03/25 23:47:13	1.8
+++ gnomeicu.c	1999/03/31 18:04:40
@@ -12,6 +12,7 @@
 #endif
 
 #include "gnomeicu.h"
+#include "dragdrop.h"
 #include "datatype.h"
 #include <stdio.h>
 #include <stdlib.h>
@@ -184,6 +185,12 @@
 int hide_ch_window( GtkWidget *widget, GdkEvent *event, GtkWidget *window );
 void Check_Endian( void );
 
+gint hide_dont_kill( GtkWidget *widget )
+{
+	gtk_widget_hide(widget);
+	return TRUE;
+}
+
 void ready_set( void )
 {
 	char *sts = NULL;
@@ -1208,12 +1215,17 @@
 	gtk_widget_realize( app );
 	gnome_app_create_menus( GNOME_APP( app ), mainmenu );
 
-	/* Changed from "delete_event" to "destroy" because it is right :) [PEL]
-	 * Now it doesn't segfault when closed by the WM */
-
-	/* EKP 3.10.99 - changed icq_quit_object to icq_quit */
-	gtk_signal_connect( GTK_OBJECT( app ), "destroy",
-	                           GTK_SIGNAL_FUNC( icq_quit ), (gpointer)&sal );
+	if( applet_toggle==FALSE ) {	
+		/* Changed from "delete_event" to "destroy" because it is right :) [PEL]
+	 	* Now it doesn't segfault when closed by the WM */
+
+		/* EKP 3.10.99 - changed icq_quit_object to icq_quit */
+		gtk_signal_connect( GTK_OBJECT( app ), "destroy",
+	                           	GTK_SIGNAL_FUNC( icq_quit ), (gpointer)&sal );
+	} else {
+		gtk_signal_connect( GTK_OBJECT( app ), "delete_event",
+					GTK_SIGNAL_FUNC( hide_dont_kill ), 0 );
+	}
 
 	gtk_widget_set_usize( app, WindowWidth, WindowHeight );
 
@@ -1247,6 +1259,8 @@
 
 	gtk_signal_connect( GTK_OBJECT( sal.lb_userwin ), "button_press_event",
 		                    GTK_SIGNAL_FUNC( icq_sendmessage_window ), &sal );
+
+	init_contact_list_drag_drop( sal.lb_userwin, &sal );
 
 	gtk_signal_connect( GTK_OBJECT( sal.lb_userwin ), "key_press_event",
 	                    GTK_SIGNAL_FUNC( icq_sendmessage_window ), &sal );
Index: gtkfunc.c
===================================================================
RCS file: /cvs/gnome/gnomeicu/src/gtkfunc.c,v
retrieving revision 1.8
diff -u -r1.8 gtkfunc.c
--- gtkfunc.c	1999/03/25 23:47:15	1.8
+++ gtkfunc.c	1999/03/31 18:04:40
@@ -414,8 +414,13 @@
 	gtk_text_thaw( GTK_TEXT( Contacts[ cx ].log_list ) );
 }
 
-void send_url_window( GtkWidget *widget, struct sokandlb *data )
+void send_url_window_default( GtkWidget *widget, struct sokandlb *data )
 {
+  send_url_window(widget, data, "");
+}
+
+void send_url_window( GtkWidget *widget, struct sokandlb *data, char *defaulturl )
+{
 	int cx;
 	GtkCList *clist = GTK_CLIST( data->lb_userwin );
 
@@ -477,6 +482,7 @@
 	
 	urlinfo->url = gtk_entry_new();
 	gtk_table_attach( GTK_TABLE( table ), urlinfo->url, 1, 2, 0, 1, 0, 0, 0, 10 );
+	gtk_entry_set_text( GTK_ENTRY( urlinfo->url ), defaulturl );
 	gtk_widget_show( urlinfo->url );
 	
 	urlinfo->desc = gtk_entry_new();
@@ -533,11 +539,60 @@
 
 	TCPSendChatRequest( Contacts[ cx ].uin, "Chat", data );
 }
+
+typedef struct
+{
+  GtkWidget *dlg;
+  GtkWidget *msg;
+  GtkWidget *file;
+  struct sokandlb *data;
+  int uin;
+} file_request_info;
+
+void send_file_request(GtkWidget *widget, file_request_info *data)
+{
+  TCPSendFileRequest( data->uin,
+		      gtk_entry_get_text(GTK_ENTRY(data->msg)),
+		      gtk_entry_get_text(GTK_ENTRY(data->file)),
+		      data->data );
+
+  gtk_widget_destroy(data->dlg);
+
+  g_free(data);
+}
+
+void file_chooser_set_retval( GtkWidget *widget, file_request_info *data)
+{
+  GtkFileSelection *filesel=GTK_FILE_SELECTION(widget->parent->parent);
+  gtk_entry_set_text(GTK_ENTRY(data->file),
+		     gtk_file_selection_get_filename(filesel));
+  gtk_widget_destroy(GTK_WIDGET(filesel));
+}
+
+void file_choose( GtkWidget *widget, file_request_info *data )
+{
+  GtkWidget *filesel;
+#ifdef TRACE_FUNCTION
+  printf( "file_choose\n" );
+#endif
+
+  filesel = gtk_file_selection_new("GnomeICU: File Transfer");
+
+  gtk_file_selection_set_filename(GTK_FILE_SELECTION(filesel),
+				  gtk_entry_get_text(GTK_ENTRY(data->file)));
+  gtk_signal_connect(GTK_OBJECT(filesel), "destroy", GTK_SIGNAL_FUNC(gtk_widget_destroy), NULL);
+  gtk_signal_connect(GTK_OBJECT(GTK_FILE_SELECTION(filesel)->ok_button), "clicked", GTK_SIGNAL_FUNC(file_chooser_set_retval), data );
+  gtk_signal_connect_object(GTK_OBJECT (GTK_FILE_SELECTION (filesel)->cancel_button), "clicked", GTK_SIGNAL_FUNC(gtk_widget_destroy), GTK_OBJECT( filesel ) );
+
+  gtk_widget_show(filesel);
+}
 
-void request_file( GtkWidget *widget, struct sokandlb *data )
+void request_file( GtkWidget *widget, struct sokandlb *data, char *defaultfile )
 {
 	int cx;
 	GtkCList *clist = GTK_CLIST( data->lb_userwin );
+	GtkWidget *button,*table,*box;
+	file_request_info *request;
 
 #ifdef TRACE_FUNCTION
 	printf( "request_file\n" );
@@ -550,7 +605,61 @@
 			break;
 	}
 
-	TCPSendFileRequest( Contacts[ cx ].uin, "foo.txt", data );
+	request=g_new(file_request_info,1);
+
+	request->dlg=gtk_dialog_new();
+	gtk_window_set_title(GTK_WINDOW(request->dlg),"Send file");
+
+	table=gtk_table_new(1,1,FALSE);
+
+	request->file=gtk_entry_new();
+	gtk_entry_set_text(GTK_ENTRY(request->file), defaultfile);
+
+	request->msg=gtk_entry_new();
+
+	gtk_table_attach_defaults(GTK_TABLE(table), gtk_label_new("Message:"), 0, 1, 0, 1);
+	gtk_table_attach_defaults(GTK_TABLE(table), request->msg, 1, 2, 0, 1);
+
+	gtk_table_attach_defaults(GTK_TABLE(table), gtk_label_new("File:"), 0, 1, 1, 2);
+
+	box=gtk_hbox_new(FALSE, 2);
+	button=gtk_button_new_with_label("Choose...");
+	gtk_signal_connect(GTK_OBJECT(button), "clicked", file_choose, request);
+
+	gtk_container_add(GTK_CONTAINER(box), request->file);
+	gtk_container_add(GTK_CONTAINER(box), button);
+
+	gtk_table_attach_defaults(GTK_TABLE(table), box, 1, 2, 1, 2);
+
+	gtk_table_set_col_spacings(GTK_TABLE(table), 4);
+	gtk_table_set_row_spacings(GTK_TABLE(table), 4);
+
+	gtk_container_set_border_width(GTK_CONTAINER(table), 4);
+
+	gtk_container_add(GTK_CONTAINER(GTK_DIALOG(request->dlg)->vbox), table);
+
+	button=gtk_button_new_with_label("Send");
+	gtk_signal_connect(GTK_OBJECT(button), "clicked", send_file_request, request);
+
+	gtk_container_add(GTK_CONTAINER(GTK_DIALOG(request->dlg)->action_area),
+			  button);
+
+	button=gtk_button_new_with_label("Cancel");
+	gtk_signal_connect_object(GTK_OBJECT(button),
+				  "clicked",
+				  GTK_SIGNAL_FUNC(gtk_widget_destroy),
+				  GTK_OBJECT(request->dlg));
+
+	gtk_container_add(GTK_CONTAINER(GTK_DIALOG(request->dlg)->action_area),
+			  button);
+
+	gtk_widget_show_all(request->dlg);
+	gtk_widget_show(request->dlg);
+}
+
+void request_file_default( GtkWidget *widget, struct sokandlb *data )
+{
+  request_file( widget, data, "" );
 }
 
 void remove_user( GtkWidget *widget, struct sokandlb *data )
@@ -1951,8 +2060,9 @@
 	if( nick == NULL )
 		return FALSE;
 
-	/* This is VERY BAD, because if you have two people with the same
-	   nick, you'll send the message to the first on the list - BAD! */
+	/* FIXME: This is VERY BAD, because if you have two people with the
+	 * same nick, you'll send the message to the first on the list - BAD!
+	 */
 
 	for( cx = 0; cx < Num_Contacts; cx ++ )
 	{
@@ -2006,7 +2116,7 @@
 			gtk_widget_show( item_box );
 			gtk_menu_append( GTK_MENU( personal_menu ), item );
 			gtk_signal_connect( GTK_OBJECT( item ), "activate",
-			                    GTK_SIGNAL_FUNC( send_url_window ),
+			                    GTK_SIGNAL_FUNC( send_url_window_default ),
 			                    data );
 			gtk_widget_show( item );
 
@@ -2038,7 +2148,7 @@
 			gtk_widget_show( item_box );
 			gtk_menu_append( GTK_MENU( personal_menu ), item );
 			gtk_signal_connect( GTK_OBJECT( item ), "activate",
-			                    GTK_SIGNAL_FUNC( request_file ),
+			                    GTK_SIGNAL_FUNC( request_file_default ),
 			                    data );
 			gtk_widget_show( item );
 
Index: gtkfunc.h
===================================================================
RCS file: /cvs/gnome/gnomeicu/src/gtkfunc.h,v
retrieving revision 1.3
diff -u -r1.3 gtkfunc.h
--- gtkfunc.h	1999/03/19 18:58:51	1.3
+++ gtkfunc.h	1999/03/31 18:04:40
@@ -1,6 +1,8 @@
 #ifndef _GTKFUNC_H
 #define _GTKFUNC_H
 
+#include "datatype.h"
+
 struct sokandlb
 {
 	int sok;
@@ -45,8 +47,13 @@
                             struct sokandlb *data );
 #endif
 void request_chat( GtkWidget *widget, struct sokandlb *data );
-void request_file( GtkWidget *widget, struct sokandlb *data );
-void send_url_window( GtkWidget *widget, struct sokandlb *data );
+
+void request_file( GtkWidget *widget, struct sokandlb *data, char *defaultfile );
+void request_file_default( GtkWidget *widget, struct sokandlb *data );
+
+void send_url_window( GtkWidget *widget, struct sokandlb *data, char *defaulturl );
+void send_url_window_default( GtkWidget *widget, struct sokandlb *data );
+
 void remove_user( GtkWidget *widget, struct sokandlb *data );
 void show_info_new( SOK_T sok, int uin );
 void retrieve_away_message( GtkWidget *widget, struct sokandlb *data );
Index: tcp.c
===================================================================
RCS file: /cvs/gnome/gnomeicu/src/tcp.c,v
retrieving revision 1.6
diff -u -r1.6 tcp.c
--- tcp.c	1999/03/25 23:47:18	1.6
+++ tcp.c	1999/03/31 18:04:41
@@ -2096,38 +2096,15 @@
 	return 1;
 }
 
-int TCPSendFileRequest( DWORD uin, char *msg, struct sokandlb *data )
+int TCPSendFileRequest( DWORD uin, char *msg, char *file, struct sokandlb *data )
 {
 #ifdef TRACE_FUNCTION
 	printf( "TCPSendChatRequest\n" );
 #endif
 
-	file_choose();
-	return 1;
-}
-
-void file_choose( void )
-{
-#ifdef TRACE_FUNCTION
-	printf( "file_choose\n" );
-#endif
-
-	filesel = gtk_file_selection_new("GnomeICU: File Transfer");
-	gtk_signal_connect(GTK_OBJECT(filesel), "destroy", GTK_SIGNAL_FUNC(gtk_widget_destroy), NULL);
-	gtk_signal_connect(GTK_OBJECT(GTK_FILE_SELECTION(filesel)->ok_button), "clicked", GTK_SIGNAL_FUNC(file_xfer_got_name), NULL );
-	gtk_signal_connect_object(GTK_OBJECT (GTK_FILE_SELECTION (filesel)->cancel_button), "clicked", GTK_SIGNAL_FUNC(gtk_widget_destroy), GTK_OBJECT( filesel ) );
-	gtk_widget_show(filesel);
-}
+	printf("About to send file: %s\n",file);
 
-void file_xfer_got_name( GtkWidget *widget, gpointer data )
-{
-#ifdef TRACE_FUNCTION
-	printf( "file_xfer_got_name\n" );
-#endif
-
-	printf( "About to send file: %s\n",
-	        gtk_file_selection_get_filename( GTK_FILE_SELECTION( filesel ) ) );
-	gtk_widget_destroy( filesel );
+	return 1;
 }
 
 void chat_save( void )
Index: tcp.h
===================================================================
RCS file: /cvs/gnome/gnomeicu/src/tcp.h,v
retrieving revision 1.3
diff -u -r1.3 tcp.h
--- tcp.h	1999/03/25 23:47:19	1.3
+++ tcp.h	1999/03/31 18:04:41
@@ -42,7 +42,7 @@
 int TCPChatSend( GtkWidget *widget, GdkEventKey *ev, int sock );
 void TCPTerminateChat( GtkWidget *widget, gpointer data );
 int TCPRetrieveAwayMessage( int cindex, struct sokandlb *data );
-int TCPSendFileRequest( DWORD uin, char *msg, struct sokandlb *data );
+int TCPSendFileRequest( DWORD uin, char *msg, char *filename, struct sokandlb *data );
 void chat_save_got_name( GtkWidget *widget, gpointer data );
 void chat_save( void );
 
/* dragdrop.c
 *
 *  GnomeICU DnD support
 *
 *  Much help from gnome-core/panel/panel.c on this one.
 */

#include "dragdrop.h"
#include <ctype.h>
#include <libgnome/libgnome.h>
#include <string.h>

enum
{
  TARGET_URL,
  TARGET_NETSCAPE_URL
};

static GtkTargetEntry contact_list_drop_types[]=
{
  { "_NETSCAPE_URL", 0, TARGET_NETSCAPE_URL },
  { "text/uri-list", 0, TARGET_URL },
  { "x-url/http", 0, TARGET_NETSCAPE_URL },
  { "x-url/ftp", 0, TARGET_NETSCAPE_URL },
  { "text/plain",0,TARGET_NETSCAPE_URL, }
  /* ??  For some reason Netscape wants to send me stuff as text/plain */
};

static gint n_contact_list_drop_types=
  sizeof(contact_list_drop_types)/sizeof(contact_list_drop_types[0]);

static void contact_list_dnd_drop(GtkWidget *widget,
				  GdkDragContext *context,
				  gint x,
				  gint y,
				  GtkSelectionData *selection_data,
				  guint info,
				  guint time,
				  struct sokandlb *data)
{
  GtkCList *list;
  int row;
  int column;

  printf("Got drop: %s\n",(char*)selection_data->data);

  g_return_if_fail(widget);
  g_return_if_fail(GTK_IS_CLIST(widget));

  list=GTK_CLIST(widget);

  gtk_clist_get_selection_info(list, x, y, &row, &column);

  gtk_clist_select_row(list, row, column);

  switch(info)
    {
    case TARGET_URL:
      // We got a bunch of file names
      {
	GList *files=gnome_uri_list_extract_filenames(selection_data->data),*tmp;

	for(tmp=files; tmp; tmp=g_list_next(tmp))
	  {
	    printf("Got URL: %s\n",(char*)tmp->data);
	    request_file(widget, data, (char *)tmp->data);
	  }

	gnome_uri_list_free_strings(files);
      }
      break;
    case TARGET_NETSCAPE_URL:
      {
	GString *type=g_string_new("");
	char *url=(char*) selection_data->data;
	char *tmp=url;
	
	printf("Got Netscape URL: %s\n",url);

	while(isalpha(*tmp))
	  type=g_string_append_c(type,*tmp++);

	printf("Type is %s\n",type->str);

	if(!strcmp(type->str,""))
	  /* Assume it's a straight filename */
	   {
	     request_file(widget, data, tmp);
	     g_string_free(type,1);
	     return;
	   }

	if(!strcmp(type->str,"file"))
	  {
	    if(*tmp++!=':')
	      {
		fprintf(stderr,"Badly formed URL: %s\n",url);
		g_string_free(type,1);
		return;
	      }
	    if(tmp[0]=='/'&&tmp[1]=='/')
	      // file://host/loationc handling.
	      // If it's of the form file://localhost/stuff, do a file transfer
	      // on stuff, otherwise continue.
	      {
		tmp+=2;
		if(strstr(tmp,"localhost")==tmp)
		  {
		    tmp+=strlen("localhost");
		    printf("Sending file request for %s\n",tmp);
		    request_file(widget, data, tmp);
		    g_string_free(type,1);
		    return;
		  }
	      }
	    else /* Of the form file:... */
	      {
		request_file(widget, data, tmp);
		g_string_free(type,1);
		return;
	      }
	  }

	printf("Sending URL request for %s\n",url);
	send_url_window( widget, data, url );
	g_string_free(type,1);
	break;
      }
    }
}

void init_contact_list_drag_drop(GtkWidget *list, struct sokandlb *data)
{
  printf("Initializing drag&drop with %i types\n",n_contact_list_drop_types);
  gtk_signal_connect(GTK_OBJECT(list),
		     "drag_data_received",
		     GTK_SIGNAL_FUNC(contact_list_dnd_drop),
		     data);
  gtk_drag_dest_set(GTK_WIDGET(list),
		    GTK_DEST_DEFAULT_MOTION |
		    GTK_DEST_DEFAULT_HIGHLIGHT |
		    GTK_DEST_DEFAULT_DROP,
		    contact_list_drop_types,
		    n_contact_list_drop_types,
		    GDK_ACTION_COPY);
}
/* dragdrop.h
 *
 *  Support for drag-and-drop in GnomeICU
 *
 *  Written with much help from gnome-core/panel/panel.c :-)
 */

#ifndef DRAGDROP_H
#define DRAGDROP_H

#include <gtk/gtk.h>
#include "gtkfunc.h"

void init_contact_list_drag_drop(GtkWidget *widget, struct sokandlb *data);

#endif


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