mirror of
https://github.com/transmission/transmission
synced 2025-02-20 21:26:53 +00:00
(trunk gtk) rewrite the main window's drag-and-drop handler s.t. it's GTK+ 3 compliant
This commit is contained in:
parent
5182600179
commit
36064b8120
5 changed files with 65 additions and 193 deletions
165
gtk/main.c
165
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,
|
||||
|
|
|
@ -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*
|
||||
|
|
|
@ -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
|
||||
|
|
63
gtk/util.c
63
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 )
|
||||
|
|
13
gtk/util.h
13
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 );
|
||||
|
||||
/***
|
||||
****
|
||||
***/
|
||||
|
|
Loading…
Reference in a new issue