(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
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 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 coreerr( TrCore *, guint, const char *, struct cbdata * );
|
||||||
|
|
||||||
static void onAddTorrent( TrCore *,
|
static void onAddTorrent( TrCore *,
|
||||||
|
@ -862,10 +850,54 @@ rowChangedCB( GtkTreeModel * model UNUSED,
|
||||||
}
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
winsetup( struct cbdata * cbdata,
|
on_drag_data_received( GtkWidget * widget UNUSED,
|
||||||
TrWindow * wind )
|
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;
|
GtkTreeSelection * sel;
|
||||||
|
|
||||||
g_assert( NULL == cbdata->wind );
|
g_assert( NULL == cbdata->wind );
|
||||||
|
@ -879,7 +911,11 @@ winsetup( struct cbdata * cbdata,
|
||||||
g_signal_connect( wind, "delete-event", G_CALLBACK( winclose ), cbdata );
|
g_signal_connect( wind, "delete-event", G_CALLBACK( winclose ), cbdata );
|
||||||
refreshActions( 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
|
static gboolean
|
||||||
|
@ -995,103 +1031,6 @@ wannaquit( gpointer vdata )
|
||||||
g_thread_create( sessionCloseThreadFunc, vdata, TRUE, NULL );
|
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
|
static void
|
||||||
flushAddTorrentErrors( GtkWindow * window,
|
flushAddTorrentErrors( GtkWindow * window,
|
||||||
const char * primary,
|
const char * primary,
|
||||||
|
|
|
@ -381,14 +381,15 @@ getDefaultSavePath( void )
|
||||||
|
|
||||||
static void
|
static void
|
||||||
on_drag_data_received( GtkWidget * widget UNUSED,
|
on_drag_data_received( GtkWidget * widget UNUSED,
|
||||||
GdkDragContext * drag_context UNUSED,
|
GdkDragContext * drag_context,
|
||||||
gint x UNUSED,
|
gint x UNUSED,
|
||||||
gint y UNUSED,
|
gint y UNUSED,
|
||||||
GtkSelectionData * selection_data,
|
GtkSelectionData * selection_data,
|
||||||
guint info UNUSED,
|
guint info UNUSED,
|
||||||
guint time UNUSED,
|
guint time_,
|
||||||
gpointer user_data )
|
gpointer user_data )
|
||||||
{
|
{
|
||||||
|
gboolean success = FALSE;
|
||||||
MakeMetaUI * ui = user_data;
|
MakeMetaUI * ui = user_data;
|
||||||
char ** uris = gtk_selection_data_get_uris( selection_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... */
|
/* a directory was dragged onto the dialog... */
|
||||||
gtk_toggle_button_set_active( GTK_TOGGLE_BUTTON( ui->folder_radio ), TRUE );
|
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 );
|
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 ) )
|
else if( g_file_test( filename, G_FILE_TEST_IS_REGULAR ) )
|
||||||
{
|
{
|
||||||
/* a file was dragged on to the dialog... */
|
/* a file was dragged on to the dialog... */
|
||||||
gtk_toggle_button_set_active( GTK_TOGGLE_BUTTON( ui->file_radio ), TRUE );
|
gtk_toggle_button_set_active( GTK_TOGGLE_BUTTON( ui->file_radio ), TRUE );
|
||||||
gtk_file_chooser_set_filename( GTK_FILE_CHOOSER( ui->file_chooser ), filename );
|
gtk_file_chooser_set_filename( GTK_FILE_CHOOSER( ui->file_chooser ), filename );
|
||||||
|
success = TRUE;
|
||||||
}
|
}
|
||||||
|
|
||||||
g_free( filename );
|
g_free( filename );
|
||||||
}
|
}
|
||||||
|
|
||||||
g_strfreev( uris );
|
g_strfreev( uris );
|
||||||
|
gtk_drag_finish( drag_context, success, FALSE, time_ );
|
||||||
}
|
}
|
||||||
|
|
||||||
GtkWidget*
|
GtkWidget*
|
||||||
|
|
|
@ -1209,10 +1209,15 @@ tr_core_add_list( TrCore * core,
|
||||||
GSList * l;
|
GSList * l;
|
||||||
|
|
||||||
for( l = torrentFiles; l != NULL; l = l->next )
|
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 );
|
tr_core_torrents_added( core );
|
||||||
freestrlist( torrentFiles );
|
|
||||||
|
g_slist_free( torrentFiles );
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
|
|
63
gtk/util.c
63
gtk/util.c
|
@ -252,69 +252,6 @@ gtr_mkdir_with_parents( const char * path, int mode )
|
||||||
#endif
|
#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 */
|
/* pattern-matching text; ie, legaltorrents.com */
|
||||||
char*
|
char*
|
||||||
gtr_get_host_from_url( const char * url )
|
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 );
|
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 New Issue