From 36064b81202f2caf19a9e176f35606a124efb841 Mon Sep 17 00:00:00 2001 From: Charles Kerr Date: Mon, 2 Aug 2010 22:31:31 +0000 Subject: [PATCH] (trunk gtk) rewrite the main window's drag-and-drop handler s.t. it's GTK+ 3 compliant --- gtk/main.c | 165 +++++++++++++++------------------------------- gtk/makemeta-ui.c | 8 ++- gtk/tr-core.c | 9 ++- gtk/util.c | 63 ------------------ gtk/util.h | 13 ---- 5 files changed, 65 insertions(+), 193 deletions(-) diff --git a/gtk/main.c b/gtk/main.c index e93308f95..23d531e7a 100644 --- a/gtk/main.c +++ b/gtk/main.c @@ -200,18 +200,6 @@ static void winsetup( struct cbdata * cbdata, static void wannaquit( gpointer vdata ); -static void setupdrag( GtkWidget * widget, - struct cbdata *data ); - -static void gotdrag( GtkWidget * widget, - GdkDragContext * dc, - gint x, - gint y, - GtkSelectionData *sel, - guint info, - guint time, - gpointer gdata ); - static void coreerr( TrCore *, guint, const char *, struct cbdata * ); static void onAddTorrent( TrCore *, @@ -862,10 +850,54 @@ rowChangedCB( GtkTreeModel * model UNUSED, } static void -winsetup( struct cbdata * cbdata, - TrWindow * wind ) +on_drag_data_received( GtkWidget * widget UNUSED, + GdkDragContext * drag_context, + gint x UNUSED, + gint y UNUSED, + GtkSelectionData * selection_data, + guint info UNUSED, + guint time_, + gpointer gdata ) { - GtkTreeModel * model; + int i; + gboolean success = FALSE; + GSList * filenames = NULL; + struct cbdata * data = gdata; + char ** uris = gtk_selection_data_get_uris( selection_data ); + + /* try to add the filename URIs... */ + for( i=0; uris && uris[i]; ++i ) + { + const char * uri = uris[i]; + char * filename = g_filename_from_uri( uri, NULL, NULL ); + + if( filename && g_file_test( filename, G_FILE_TEST_EXISTS ) ) + { + filenames = g_slist_append( filenames, g_strdup( filename ) ); + success = TRUE; + } + else if( tr_urlIsValid( uri ) ) + { + tr_core_add_from_url( data->core, uri ); + success = TRUE; + } + } + + if( filenames ) + tr_core_add_list_defaults( data->core, g_slist_reverse( filenames ), TRUE ); + + tr_core_torrents_added( data->core ); + gtk_drag_finish( drag_context, success, FALSE, time_ ); + + /* cleanup */ + g_strfreev( uris ); +} + +static void +winsetup( struct cbdata * cbdata, TrWindow * wind ) +{ + GtkWidget * w; + GtkTreeModel * model; GtkTreeSelection * sel; g_assert( NULL == cbdata->wind ); @@ -879,7 +911,11 @@ winsetup( struct cbdata * cbdata, g_signal_connect( wind, "delete-event", G_CALLBACK( winclose ), cbdata ); refreshActions( cbdata ); - setupdrag( GTK_WIDGET( wind ), cbdata ); + /* register to handle URIs that get dragged onto our main window */ + w = GTK_WIDGET( wind ); + gtk_drag_dest_set( w, GTK_DEST_DEFAULT_ALL, NULL, 0, GDK_ACTION_COPY ); + gtk_drag_dest_add_uri_targets( w ); + g_signal_connect( w, "drag-data-received", G_CALLBACK(on_drag_data_received), cbdata ); } static gboolean @@ -995,103 +1031,6 @@ wannaquit( gpointer vdata ) g_thread_create( sessionCloseThreadFunc, vdata, TRUE, NULL ); } -static void -gotdrag( GtkWidget * widget UNUSED, - GdkDragContext * dc, - gint x UNUSED, - gint y UNUSED, - GtkSelectionData * sel, - guint info UNUSED, - guint time, - gpointer gdata ) -{ - struct cbdata * data = gdata; - GSList * paths = NULL; - GSList * freeme = NULL; - -#if 0 - int i; - char * sele = gdk_atom_name( sel->selection ); - char * targ = gdk_atom_name( sel->target ); - char * type = gdk_atom_name( sel->type ); - - g_message( "dropped file: sel=%s targ=%s type=%s fmt=%i len=%i", - sele, targ, type, sel->format, sel->length ); - g_free( sele ); - g_free( targ ); - g_free( type ); - if( sel->format == 8 ) - { - for( i = 0; i < sel->length; ++i ) - fprintf( stderr, "%02X ", sel->data[i] ); - fprintf( stderr, "\n" ); - } -#endif - - if( ( sel->format == 8 ) - && ( sel->selection == gdk_atom_intern( "XdndSelection", FALSE ) ) ) - { - int i; - char * str = g_strndup( (char*)sel->data, sel->length ); - gchar ** files = g_strsplit_set( str, "\r\n", -1 ); - for( i = 0; files && files[i]; ++i ) - { - char * filename; - if( !*files[i] ) /* empty filename... */ - continue; - - /* decode the filename */ - filename = decode_uri( files[i] ); - freeme = g_slist_prepend( freeme, filename ); - if( !g_utf8_validate( filename, -1, NULL ) ) - continue; - - /* walk past "file://", if present */ - if( g_str_has_prefix( filename, "file:" ) ) { - filename += 5; - while( g_str_has_prefix( filename, "//" ) ) - ++filename; - } - - if( g_file_test( filename, G_FILE_TEST_EXISTS ) ) - paths = g_slist_prepend( paths, g_strdup( filename ) ); - else - tr_core_add_from_url( data->core, filename ); - } - - /* try to add any torrents we found */ - if( paths ) - { - paths = g_slist_reverse( paths ); - tr_core_add_list_defaults( data->core, paths, TRUE ); - tr_core_torrents_added( data->core ); - } - - freestrlist( freeme ); - g_strfreev( files ); - g_free( str ); - } - - gtk_drag_finish( dc, ( NULL != paths ), FALSE, time ); -} - -static void -setupdrag( GtkWidget * widget, - struct cbdata *data ) -{ - GtkTargetEntry targets[] = { - { (char*)"STRING", 0, 0 }, - { (char*)"text/plain", 0, 0 }, - { (char*)"text/uri-list", 0, 0 }, - }; - - g_signal_connect( widget, "drag_data_received", G_CALLBACK( - gotdrag ), data ); - - gtk_drag_dest_set( widget, GTK_DEST_DEFAULT_ALL, targets, - G_N_ELEMENTS( targets ), GDK_ACTION_COPY | GDK_ACTION_MOVE ); -} - static void flushAddTorrentErrors( GtkWindow * window, const char * primary, diff --git a/gtk/makemeta-ui.c b/gtk/makemeta-ui.c index 76afd05ec..2d1620e35 100644 --- a/gtk/makemeta-ui.c +++ b/gtk/makemeta-ui.c @@ -381,14 +381,15 @@ getDefaultSavePath( void ) static void on_drag_data_received( GtkWidget * widget UNUSED, - GdkDragContext * drag_context UNUSED, + GdkDragContext * drag_context, gint x UNUSED, gint y UNUSED, GtkSelectionData * selection_data, guint info UNUSED, - guint time UNUSED, + guint time_, gpointer user_data ) { + gboolean success = FALSE; MakeMetaUI * ui = user_data; char ** uris = gtk_selection_data_get_uris( selection_data ); @@ -402,18 +403,21 @@ on_drag_data_received( GtkWidget * widget UNUSED, /* a directory was dragged onto the dialog... */ gtk_toggle_button_set_active( GTK_TOGGLE_BUTTON( ui->folder_radio ), TRUE ); gtk_file_chooser_set_current_folder( GTK_FILE_CHOOSER( ui->folder_chooser ), filename ); + success = TRUE; } else if( g_file_test( filename, G_FILE_TEST_IS_REGULAR ) ) { /* a file was dragged on to the dialog... */ gtk_toggle_button_set_active( GTK_TOGGLE_BUTTON( ui->file_radio ), TRUE ); gtk_file_chooser_set_filename( GTK_FILE_CHOOSER( ui->file_chooser ), filename ); + success = TRUE; } g_free( filename ); } g_strfreev( uris ); + gtk_drag_finish( drag_context, success, FALSE, time_ ); } GtkWidget* diff --git a/gtk/tr-core.c b/gtk/tr-core.c index 35ccb97a2..ef1f5a94b 100644 --- a/gtk/tr-core.c +++ b/gtk/tr-core.c @@ -1209,10 +1209,15 @@ tr_core_add_list( TrCore * core, GSList * l; for( l = torrentFiles; l != NULL; l = l->next ) - add_filename( core, l->data, doStart, doPrompt, doNotify ); + { + char * filename = l->data; + add_filename( core, filename, doStart, doPrompt, doNotify ); + g_free( filename ); + } tr_core_torrents_added( core ); - freestrlist( torrentFiles ); + + g_slist_free( torrentFiles ); } void diff --git a/gtk/util.c b/gtk/util.c index b039ce6cb..bceeee409 100644 --- a/gtk/util.c +++ b/gtk/util.c @@ -252,69 +252,6 @@ gtr_mkdir_with_parents( const char * path, int mode ) #endif } -GSList * -dupstrlist( GSList * l ) -{ - GSList * ret = NULL; - - for( ; l != NULL; l = l->next ) - ret = g_slist_prepend( ret, g_strdup( l->data ) ); - return g_slist_reverse( ret ); -} - -char * -joinstrlist( GSList *list, - char * sep ) -{ - GSList * l; - GString *gstr = g_string_new ( NULL ); - - for( l = list; l != NULL; l = l->next ) - { - g_string_append ( gstr, (char*)l->data ); - if( l->next != NULL ) - g_string_append ( gstr, ( sep ) ); - } - return g_string_free ( gstr, FALSE ); -} - -void -freestrlist( GSList *list ) -{ - g_slist_foreach ( list, (GFunc)g_free, NULL ); - g_slist_free ( list ); -} - -char * -decode_uri( const char * uri ) -{ - gboolean in_query = FALSE; - char * ret = g_new( char, strlen( uri ) + 1 ); - char * out = ret; - - for( ; uri && *uri; ) - { - char ch = *uri; - if( ch == '?' ) - in_query = TRUE; - else if( ch == '+' && in_query ) - ch = ' '; - else if( ch == '%' && isxdigit( (unsigned char)uri[1] ) - && isxdigit( (unsigned char)uri[2] ) ) - { - char buf[3] = { uri[1], uri[2], '\0' }; - ch = (char) g_ascii_strtoull( buf, NULL, 16 ); - uri += 2; - } - - ++uri; - *out++ = ch; - } - - *out = '\0'; - return ret; -} - /* pattern-matching text; ie, legaltorrents.com */ char* gtr_get_host_from_url( const char * url ) diff --git a/gtk/util.h b/gtk/util.h index e92f2fa6b..995d9a5bc 100644 --- a/gtk/util.h +++ b/gtk/util.h @@ -91,19 +91,6 @@ gboolean gtr_is_magnet_link( const char * str ); gboolean gtr_is_hex_hashcode( const char * str ); - -/* create a copy of a GSList of strings, this dups the actual strings too */ -GSList * dupstrlist( GSList * list ); - -/* joins a GSList of strings into one string using an optional separator */ -char * joinstrlist( GSList *list, char * sep ); - -/* free a GSList of strings */ -void freestrlist( GSList *list ); - -/* decodes a string that has been urlencoded */ -char * decode_uri( const char * uri ); - /*** **** ***/