mirror of
https://github.com/transmission/transmission
synced 2025-03-04 10:38:13 +00:00
(trunk gtk) #2500 "Torrent details window should be single-instance per torrent" -- implemented for 1.80
This commit is contained in:
parent
9e9eb89784
commit
9e9d7c82c7
1 changed files with 133 additions and 36 deletions
169
gtk/main.c
169
gtk/main.c
|
@ -88,6 +88,105 @@ struct cbdata
|
||||||
GtkTreeSelection * sel;
|
GtkTreeSelection * sel;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
***
|
||||||
|
**/
|
||||||
|
|
||||||
|
static int
|
||||||
|
compareInts( const void * a, const void * b )
|
||||||
|
{
|
||||||
|
return *(int*)a - *(int*)b;
|
||||||
|
}
|
||||||
|
|
||||||
|
static char*
|
||||||
|
getDetailsDialogKey( GSList * id_list )
|
||||||
|
{
|
||||||
|
int i;
|
||||||
|
int n;
|
||||||
|
int * ids;
|
||||||
|
GSList * l;
|
||||||
|
GString * gstr = g_string_new( NULL );
|
||||||
|
|
||||||
|
n = g_slist_length( id_list );
|
||||||
|
ids = g_new( int, n );
|
||||||
|
i = 0;
|
||||||
|
for( l=id_list; l!=NULL; l=l->next )
|
||||||
|
ids[i++] = GPOINTER_TO_INT( l->data );
|
||||||
|
g_assert( i == n );
|
||||||
|
qsort( ids, n, sizeof(int), compareInts );
|
||||||
|
|
||||||
|
for( i=0; i<n; ++i )
|
||||||
|
g_string_append_printf( gstr, "%d ", ids[i] );
|
||||||
|
|
||||||
|
g_free( ids );
|
||||||
|
return g_string_free( gstr, FALSE );
|
||||||
|
}
|
||||||
|
|
||||||
|
struct DetailsDialogHandle
|
||||||
|
{
|
||||||
|
char * key;
|
||||||
|
GtkWidget * dialog;
|
||||||
|
};
|
||||||
|
|
||||||
|
static GSList*
|
||||||
|
getSelectedTorrentIds( struct cbdata * data )
|
||||||
|
{
|
||||||
|
GtkTreeSelection * s;
|
||||||
|
GtkTreeModel * model;
|
||||||
|
GSList * ids = NULL;
|
||||||
|
GList * selrows = NULL;
|
||||||
|
GList * l;
|
||||||
|
|
||||||
|
/* build a list of the selected torrents' ids */
|
||||||
|
s = tr_window_get_selection( data->wind );
|
||||||
|
for( selrows=l=gtk_tree_selection_get_selected_rows(s,&model); l; l=l->next ) {
|
||||||
|
GtkTreeIter iter;
|
||||||
|
if( gtk_tree_model_get_iter( model, &iter, l->data ) ) {
|
||||||
|
tr_torrent * tor;
|
||||||
|
gtk_tree_model_get( model, &iter, MC_TORRENT_RAW, &tor, -1 );
|
||||||
|
ids = g_slist_append( ids, GINT_TO_POINTER( tr_torrentId( tor ) ) );
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return ids;
|
||||||
|
}
|
||||||
|
|
||||||
|
static struct DetailsDialogHandle*
|
||||||
|
findDetailsDialogFromIds( struct cbdata * cbdata, GSList * ids )
|
||||||
|
{
|
||||||
|
GSList * l;
|
||||||
|
struct DetailsDialogHandle * ret = NULL;
|
||||||
|
char * key = getDetailsDialogKey( ids );
|
||||||
|
|
||||||
|
for( l=cbdata->details; l!=NULL && ret==NULL; l=l->next ) {
|
||||||
|
struct DetailsDialogHandle * h = l->data;
|
||||||
|
if( !strcmp( h->key, key ) )
|
||||||
|
ret = h;
|
||||||
|
}
|
||||||
|
|
||||||
|
g_free( key );
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
static struct DetailsDialogHandle*
|
||||||
|
findDetailsDialogFromWidget( struct cbdata * cbdata, gpointer w )
|
||||||
|
{
|
||||||
|
GSList * l;
|
||||||
|
struct DetailsDialogHandle * ret = NULL;
|
||||||
|
|
||||||
|
for( l=cbdata->details; l!=NULL && ret==NULL; l=l->next ) {
|
||||||
|
struct DetailsDialogHandle * h = l->data;
|
||||||
|
if( h->dialog == w )
|
||||||
|
ret = h;
|
||||||
|
}
|
||||||
|
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
/***
|
||||||
|
****
|
||||||
|
***/
|
||||||
|
|
||||||
static void appsetup( TrWindow * wind,
|
static void appsetup( TrWindow * wind,
|
||||||
GSList * args,
|
GSList * args,
|
||||||
struct cbdata *,
|
struct cbdata *,
|
||||||
|
@ -247,34 +346,6 @@ refreshActions( struct cbdata * data )
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static void
|
|
||||||
refreshDetailsDialog( struct cbdata * data, GtkWidget * details )
|
|
||||||
{
|
|
||||||
GtkTreeSelection * s;
|
|
||||||
GtkTreeModel * model;
|
|
||||||
GSList * ids = NULL;
|
|
||||||
GList * selrows = NULL;
|
|
||||||
GList * l;
|
|
||||||
|
|
||||||
/* build a list of the selected torrents' ids */
|
|
||||||
s = tr_window_get_selection( data->wind );
|
|
||||||
for( selrows=l=gtk_tree_selection_get_selected_rows(s,&model); l; l=l->next ) {
|
|
||||||
GtkTreeIter iter;
|
|
||||||
if( gtk_tree_model_get_iter( model, &iter, l->data ) ) {
|
|
||||||
tr_torrent * tor;
|
|
||||||
gtk_tree_model_get( model, &iter, MC_TORRENT_RAW, &tor, -1 );
|
|
||||||
ids = g_slist_append( ids, GINT_TO_POINTER( tr_torrentId( tor ) ) );
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
torrent_inspector_set_torrents( details, ids );
|
|
||||||
|
|
||||||
/* cleanup */
|
|
||||||
g_slist_free( ids );
|
|
||||||
g_list_foreach( selrows, (GFunc)gtk_tree_path_free, NULL );
|
|
||||||
g_list_free( selrows );
|
|
||||||
}
|
|
||||||
|
|
||||||
static void
|
static void
|
||||||
selectionChangedCB( GtkTreeSelection * s UNUSED, gpointer data )
|
selectionChangedCB( GtkTreeSelection * s UNUSED, gpointer data )
|
||||||
{
|
{
|
||||||
|
@ -707,10 +778,20 @@ onSessionClosed( gpointer gdata )
|
||||||
struct cbdata * cbdata = gdata;
|
struct cbdata * cbdata = gdata;
|
||||||
|
|
||||||
/* shutdown the gui */
|
/* shutdown the gui */
|
||||||
if( cbdata->details ) {
|
if( cbdata->details != NULL )
|
||||||
g_slist_foreach( cbdata->details, (GFunc)gtk_widget_destroy, NULL );
|
{
|
||||||
|
GSList * l;
|
||||||
|
for( l=cbdata->details; l!=NULL; l=l->next )
|
||||||
|
{
|
||||||
|
struct DetailsDialogHandle * h = l->data;
|
||||||
|
gtk_widget_destroy( h->dialog );
|
||||||
|
g_free( h->key );
|
||||||
|
g_free( h );
|
||||||
|
}
|
||||||
g_slist_free( cbdata->details );
|
g_slist_free( cbdata->details );
|
||||||
|
cbdata->details = NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
if( cbdata->prefs )
|
if( cbdata->prefs )
|
||||||
gtk_widget_destroy( GTK_WIDGET( cbdata->prefs ) );
|
gtk_widget_destroy( GTK_WIDGET( cbdata->prefs ) );
|
||||||
if( cbdata->wind )
|
if( cbdata->wind )
|
||||||
|
@ -1399,7 +1480,14 @@ static void
|
||||||
detailsClosed( gpointer gdata, GObject * dead )
|
detailsClosed( gpointer gdata, GObject * dead )
|
||||||
{
|
{
|
||||||
struct cbdata * data = gdata;
|
struct cbdata * data = gdata;
|
||||||
data->details = g_slist_remove( data->details, dead );
|
struct DetailsDialogHandle * h = findDetailsDialogFromWidget( data, dead );
|
||||||
|
|
||||||
|
if( h != NULL )
|
||||||
|
{
|
||||||
|
data->details = g_slist_remove( data->details, h );
|
||||||
|
g_free( h->key );
|
||||||
|
g_free( h );
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
|
@ -1488,11 +1576,20 @@ doAction( const char * action_name, gpointer user_data )
|
||||||
}
|
}
|
||||||
else if( !strcmp( action_name, "show-torrent-properties" ) )
|
else if( !strcmp( action_name, "show-torrent-properties" ) )
|
||||||
{
|
{
|
||||||
GtkWidget * w = torrent_inspector_new( GTK_WINDOW( data->wind ), data->core );
|
GtkWidget * w;
|
||||||
data->details = g_slist_prepend( data->details, w );
|
GSList * ids = getSelectedTorrentIds( data );
|
||||||
g_object_weak_ref( G_OBJECT( w ), detailsClosed, data );
|
struct DetailsDialogHandle * h = findDetailsDialogFromIds( data, ids );
|
||||||
refreshDetailsDialog( data, w );
|
if( h != NULL )
|
||||||
gtk_widget_show( w );
|
w = h->dialog;
|
||||||
|
else {
|
||||||
|
h = g_new( struct DetailsDialogHandle, 1 );
|
||||||
|
h->key = getDetailsDialogKey( ids );
|
||||||
|
h->dialog = w = torrent_inspector_new( GTK_WINDOW( data->wind ), data->core );
|
||||||
|
torrent_inspector_set_torrents( w, ids );
|
||||||
|
data->details = g_slist_append( data->details, h );
|
||||||
|
g_object_weak_ref( G_OBJECT( w ), detailsClosed, data );
|
||||||
|
}
|
||||||
|
gtk_window_present( GTK_WINDOW( w ) );
|
||||||
}
|
}
|
||||||
else if( !strcmp( action_name, "update-tracker" ) )
|
else if( !strcmp( action_name, "update-tracker" ) )
|
||||||
{
|
{
|
||||||
|
|
Loading…
Add table
Reference in a new issue